add store closed day in event record calendar
This commit is contained in:
@@ -36,12 +36,15 @@
|
|||||||
v-for="item in calendarDayList"
|
v-for="item in calendarDayList"
|
||||||
:key="item.key"
|
:key="item.key"
|
||||||
class="day-cell"
|
class="day-cell"
|
||||||
:class="{muted: !item.inMonth, today: item.isToday, marked: 0 < item.records.length}"
|
:class="{muted: !item.inMonth, today: item.isToday, marked: 0 < item.records.length, 'rest-day': item.isRestDay}"
|
||||||
type="button"
|
type="button"
|
||||||
:disabled="!item.records.length"
|
:disabled="!item.records.length"
|
||||||
@click="openDayRecords(item)"
|
@click="openDayRecords(item)"
|
||||||
>
|
>
|
||||||
<span class="date" v-text="item.day" />
|
<span class="date">
|
||||||
|
<span v-text="item.day" />
|
||||||
|
<span v-if="item.isRestDay" class="rest">休</span>
|
||||||
|
</span>
|
||||||
<span v-if="item.records.length" class="count" v-text="`${item.records.length} 条`" />
|
<span v-if="item.records.length" class="count" v-text="`${item.records.length} 条`" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -104,8 +107,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import StoreAPI from "@/api/StoreAPI";
|
||||||
import type {EventItem} from "@/types/EventItem";
|
import type {EventItem} from "@/types/EventItem";
|
||||||
import type {EventRecord} from "@/types/EventRecord";
|
import type {EventRecord} from "@/types/EventRecord";
|
||||||
|
import type {StoreBusinessDay} from "@/types/Store";
|
||||||
|
import {getCurrentStoreId} from "@/utils/store";
|
||||||
import {Time} from "timi-web";
|
import {Time} from "timi-web";
|
||||||
|
|
||||||
interface CalendarDay {
|
interface CalendarDay {
|
||||||
@@ -114,6 +120,7 @@ interface CalendarDay {
|
|||||||
dateText: string;
|
dateText: string;
|
||||||
inMonth: boolean;
|
inMonth: boolean;
|
||||||
isToday: boolean;
|
isToday: boolean;
|
||||||
|
isRestDay: boolean;
|
||||||
records: EventRecord[];
|
records: EventRecord[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,11 +138,13 @@ const props = withDefaults(defineProps<{
|
|||||||
records: EventRecord[];
|
records: EventRecord[];
|
||||||
selectedEventIdList: string[];
|
selectedEventIdList: string[];
|
||||||
showEventFilter?: boolean;
|
showEventFilter?: boolean;
|
||||||
|
storeId?: string;
|
||||||
}>(), {
|
}>(), {
|
||||||
customerName: "",
|
customerName: "",
|
||||||
emptyText: "当前月份暂无匹配登记",
|
emptyText: "当前月份暂无匹配登记",
|
||||||
loading: false,
|
loading: false,
|
||||||
showEventFilter: true
|
showEventFilter: true,
|
||||||
|
storeId: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -151,6 +160,8 @@ const dayRecordVisible = ref(false);
|
|||||||
const eventFilterVisible = ref(false);
|
const eventFilterVisible = ref(false);
|
||||||
const selectedDayTitle = ref("");
|
const selectedDayTitle = ref("");
|
||||||
const selectedDayRecords = ref<EventRecord[]>([]);
|
const selectedDayRecords = ref<EventRecord[]>([]);
|
||||||
|
const businessDayList = ref<StoreBusinessDay[]>([]);
|
||||||
|
let businessDayRequestId = 0;
|
||||||
|
|
||||||
const selectedEventIdListProxy = computed({
|
const selectedEventIdListProxy = computed({
|
||||||
get: () => props.selectedEventIdList,
|
get: () => props.selectedEventIdList,
|
||||||
@@ -166,6 +177,12 @@ const eventNameMap = computed(() => {
|
|||||||
return map;
|
return map;
|
||||||
});
|
});
|
||||||
const selectedEventIdSet = computed(() => new Set(props.selectedEventIdList));
|
const selectedEventIdSet = computed(() => new Set(props.selectedEventIdList));
|
||||||
|
const resolvedStoreId = computed(() => props.storeId || getCurrentStoreId());
|
||||||
|
const restDaySet = computed(() => new Set(
|
||||||
|
businessDayList.value
|
||||||
|
.filter(item => item.status === "CLOSED" && item.dateValue)
|
||||||
|
.map(item => item.dateValue as number)
|
||||||
|
));
|
||||||
const filteredRecords = computed(() => {
|
const filteredRecords = computed(() => {
|
||||||
if (!props.showEventFilter || !props.selectedEventIdList.length) {
|
if (!props.showEventFilter || !props.selectedEventIdList.length) {
|
||||||
return props.records;
|
return props.records;
|
||||||
@@ -188,12 +205,42 @@ const calendarDayList = computed<CalendarDay[]>(() => {
|
|||||||
dateText,
|
dateText,
|
||||||
inMonth: date.getMonth() === props.modelValue.getMonth(),
|
inMonth: date.getMonth() === props.modelValue.getMonth(),
|
||||||
isToday: dateText === todayText,
|
isToday: dateText === todayText,
|
||||||
|
isRestDay: restDaySet.value.has(toDateValue(date)),
|
||||||
records: filteredRecords.value.filter(item => getRecordDateText(item) === dateText)
|
records: filteredRecords.value.filter(item => getRecordDateText(item) === dateText)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch([() => props.modelValue, resolvedStoreId], async () => {
|
||||||
|
await loadBusinessDays();
|
||||||
|
}, {
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadBusinessDays(): Promise<void> {
|
||||||
|
const storeId = resolvedStoreId.value;
|
||||||
|
if (!storeId) {
|
||||||
|
businessDayList.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestId = ++businessDayRequestId;
|
||||||
|
const beginDate = getCalendarBeginDate(props.modelValue);
|
||||||
|
const endDate = addDays(beginDate, 41);
|
||||||
|
try {
|
||||||
|
const result = await StoreAPI.businessDayCalendar(storeId, toDateValue(beginDate), toDateValue(endDate));
|
||||||
|
if (requestId === businessDayRequestId) {
|
||||||
|
businessDayList.value = result || [];
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
if (requestId === businessDayRequestId) {
|
||||||
|
businessDayList.value = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function shiftMonth(offset: number): void {
|
function shiftMonth(offset: number): void {
|
||||||
emit("update:modelValue", addMonths(props.modelValue, offset));
|
emit("update:modelValue", addMonths(props.modelValue, offset));
|
||||||
}
|
}
|
||||||
@@ -286,6 +333,10 @@ function addMonths(date: Date, months: number): Date {
|
|||||||
return new Date(date.getFullYear(), date.getMonth() + months, 1, 0, 0, 0, 0);
|
return new Date(date.getFullYear(), date.getMonth() + months, 1, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toDateValue(date: Date): number {
|
||||||
|
return Number(Time.formatDate(date).replaceAll("-", ""));
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
@@ -353,13 +404,22 @@ function addMonths(date: Date, months: number): Date {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
|
display: flex;
|
||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rest {
|
||||||
|
color: #dc2626;
|
||||||
|
margin-left: .125rem;
|
||||||
|
font-size: .625rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
.count {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: #2563eb;
|
color: var(--td-brand-color);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-size: .625rem;
|
font-size: .625rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -373,11 +433,15 @@ function addMonths(date: Date, months: number): Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.today {
|
&.today {
|
||||||
border-color: #2563eb;
|
color: var(--td-brand-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.marked {
|
&.marked {
|
||||||
background: #eff6ff;
|
background: var(--td-brand-color-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.rest-day {
|
||||||
|
background: #fef2f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
@@ -479,6 +543,10 @@ function addMonths(date: Date, months: number): Date {
|
|||||||
&.marked {
|
&.marked {
|
||||||
background: rgba(37, 99, 235, .2);
|
background: rgba(37, 99, 235, .2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.rest-day {
|
||||||
|
background: rgba(220, 38, 38, .12);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
v-model:selected-event-id-list="selectedEventIdList"
|
v-model:selected-event-id-list="selectedEventIdList"
|
||||||
:customer-id="selectedCustomer.id || ''"
|
:customer-id="selectedCustomer.id || ''"
|
||||||
:customer-name="selectedCustomer.name"
|
:customer-name="selectedCustomer.name"
|
||||||
|
:store-id="selectedCustomer.storeId"
|
||||||
@list="toEventRecordList"
|
@list="toEventRecordList"
|
||||||
/>
|
/>
|
||||||
<customer-record-trend-chart
|
<customer-record-trend-chart
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
class="calendar-section"
|
class="calendar-section"
|
||||||
:event-list="eventList"
|
:event-list="eventList"
|
||||||
:customer-name="customerName"
|
:customer-name="customerName"
|
||||||
|
:store-id="storeId"
|
||||||
:loading="isCalendarLoading"
|
:loading="isCalendarLoading"
|
||||||
:records="records"
|
:records="records"
|
||||||
@list="value => emit('list', value)"
|
@list="value => emit('list', value)"
|
||||||
@@ -23,6 +24,7 @@ import type { StoreEventRecordCalendarView } from "@/types/Store";
|
|||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
customerId: string;
|
customerId: string;
|
||||||
customerName?: string;
|
customerName?: string;
|
||||||
|
storeId?: string;
|
||||||
modelValue: Date;
|
modelValue: Date;
|
||||||
selectedEventIdList: string[];
|
selectedEventIdList: string[];
|
||||||
}>();
|
}>();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
empty-text="当前月份暂无登记事件记录"
|
empty-text="当前月份暂无登记事件记录"
|
||||||
:loading="isCalendarLoading"
|
:loading="isCalendarLoading"
|
||||||
:records="monthRecords"
|
:records="monthRecords"
|
||||||
|
:store-id="storeId"
|
||||||
@list="value => emit('list', value)"
|
@list="value => emit('list', value)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -17,6 +18,7 @@ import EventRecordCalendar, { type EventRecordCalendarListPayload } from "@/comp
|
|||||||
import type { EventItem } from "@/types/EventItem";
|
import type { EventItem } from "@/types/EventItem";
|
||||||
import type { EventRecord } from "@/types/EventRecord";
|
import type { EventRecord } from "@/types/EventRecord";
|
||||||
import type { StoreEventRecordCalendarView } from "@/types/Store";
|
import type { StoreEventRecordCalendarView } from "@/types/Store";
|
||||||
|
import { useCurrentStoreStore } from "@/store/currentStoreStore";
|
||||||
import { Time } from "timi-web";
|
import { Time } from "timi-web";
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -28,6 +30,8 @@ const selectedEventIdList = ref<string[]>([]);
|
|||||||
const monthRecords = ref<EventRecord[]>([]);
|
const monthRecords = ref<EventRecord[]>([]);
|
||||||
const isCalendarLoading = ref(false);
|
const isCalendarLoading = ref(false);
|
||||||
const monthCursor = ref(getMonthStart(new Date()));
|
const monthCursor = ref(getMonthStart(new Date()));
|
||||||
|
const currentStoreStore = useCurrentStoreStore();
|
||||||
|
const storeId = computed(() => currentStoreStore.currentStoreId);
|
||||||
let calendarRequestId = 0;
|
let calendarRequestId = 0;
|
||||||
|
|
||||||
watch(monthCursor, async () => {
|
watch(monthCursor, async () => {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
* @param backgroundColor 头像背景色
|
* @param backgroundColor 头像背景色
|
||||||
*/
|
*/
|
||||||
export function buildFallbackAvatar(name?: string, backgroundColor = "#2563eb"): string {
|
export function buildFallbackAvatar(name?: string, backgroundColor = "#2563eb"): string {
|
||||||
const text = encodeURIComponent((name?.trim() || "用户").slice(0, 2));
|
const text = encodeURIComponent((name?.trim() || "用户").slice(0, 1));
|
||||||
const fill = encodeURIComponent(backgroundColor);
|
const fill = encodeURIComponent(backgroundColor);
|
||||||
return [
|
return [
|
||||||
"data:image/svg+xml;charset=UTF-8,",
|
"data:image/svg+xml;charset=UTF-8,",
|
||||||
|
|||||||
Reference in New Issue
Block a user