add store closed day in event record calendar

This commit is contained in:
Timi
2026-08-13 14:50:35 +08:00
parent fa1f5f1f2d
commit e43ba9db8d
5 changed files with 82 additions and 7 deletions
+74 -6
View File
@@ -36,12 +36,15 @@
v-for="item in calendarDayList"
:key="item.key"
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"
:disabled="!item.records.length"
@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} 条`" />
</button>
</div>
@@ -104,8 +107,11 @@
</template>
<script setup lang="ts">
import StoreAPI from "@/api/StoreAPI";
import type {EventItem} from "@/types/EventItem";
import type {EventRecord} from "@/types/EventRecord";
import type {StoreBusinessDay} from "@/types/Store";
import {getCurrentStoreId} from "@/utils/store";
import {Time} from "timi-web";
interface CalendarDay {
@@ -114,6 +120,7 @@ interface CalendarDay {
dateText: string;
inMonth: boolean;
isToday: boolean;
isRestDay: boolean;
records: EventRecord[];
}
@@ -131,11 +138,13 @@ const props = withDefaults(defineProps<{
records: EventRecord[];
selectedEventIdList: string[];
showEventFilter?: boolean;
storeId?: string;
}>(), {
customerName: "",
emptyText: "当前月份暂无匹配登记",
loading: false,
showEventFilter: true
showEventFilter: true,
storeId: ""
});
const emit = defineEmits<{
@@ -151,6 +160,8 @@ const dayRecordVisible = ref(false);
const eventFilterVisible = ref(false);
const selectedDayTitle = ref("");
const selectedDayRecords = ref<EventRecord[]>([]);
const businessDayList = ref<StoreBusinessDay[]>([]);
let businessDayRequestId = 0;
const selectedEventIdListProxy = computed({
get: () => props.selectedEventIdList,
@@ -166,6 +177,12 @@ const eventNameMap = computed(() => {
return map;
});
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(() => {
if (!props.showEventFilter || !props.selectedEventIdList.length) {
return props.records;
@@ -188,12 +205,42 @@ const calendarDayList = computed<CalendarDay[]>(() => {
dateText,
inMonth: date.getMonth() === props.modelValue.getMonth(),
isToday: dateText === todayText,
isRestDay: restDaySet.value.has(toDateValue(date)),
records: filteredRecords.value.filter(item => getRecordDateText(item) === dateText)
});
}
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 {
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);
}
function toDateValue(date: Date): number {
return Number(Time.formatDate(date).replaceAll("-", ""));
}
</script>
<style scoped lang="less">
@@ -353,13 +404,22 @@ function addMonths(date: Date, months: number): Date {
flex-direction: column;
.date {
display: flex;
font-size: .875rem;
align-items: center;
font-weight: 700;
}
.rest {
color: #dc2626;
margin-left: .125rem;
font-size: .625rem;
font-weight: 700;
}
.count {
width: 100%;
color: #2563eb;
color: var(--td-brand-color);
overflow: hidden;
font-size: .625rem;
font-weight: 700;
@@ -373,11 +433,15 @@ function addMonths(date: Date, months: number): Date {
}
&.today {
border-color: #2563eb;
color: var(--td-brand-color);
}
&.marked {
background: #eff6ff;
background: var(--td-brand-color-1);
}
&.rest-day {
background: #fef2f2;
}
&:disabled {
@@ -479,6 +543,10 @@ function addMonths(date: Date, months: number): Date {
&.marked {
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"
:customer-id="selectedCustomer.id || ''"
:customer-name="selectedCustomer.name"
:store-id="selectedCustomer.storeId"
@list="toEventRecordList"
/>
<customer-record-trend-chart
@@ -5,6 +5,7 @@
class="calendar-section"
:event-list="eventList"
:customer-name="customerName"
:store-id="storeId"
:loading="isCalendarLoading"
:records="records"
@list="value => emit('list', value)"
@@ -23,6 +24,7 @@ import type { StoreEventRecordCalendarView } from "@/types/Store";
const props = defineProps<{
customerId: string;
customerName?: string;
storeId?: string;
modelValue: Date;
selectedEventIdList: string[];
}>();
@@ -6,6 +6,7 @@
empty-text="当前月份暂无登记事件记录"
:loading="isCalendarLoading"
:records="monthRecords"
:store-id="storeId"
@list="value => emit('list', value)"
/>
</template>
@@ -17,6 +18,7 @@ import EventRecordCalendar, { type EventRecordCalendarListPayload } from "@/comp
import type { EventItem } from "@/types/EventItem";
import type { EventRecord } from "@/types/EventRecord";
import type { StoreEventRecordCalendarView } from "@/types/Store";
import { useCurrentStoreStore } from "@/store/currentStoreStore";
import { Time } from "timi-web";
const emit = defineEmits<{
@@ -28,6 +30,8 @@ const selectedEventIdList = ref<string[]>([]);
const monthRecords = ref<EventRecord[]>([]);
const isCalendarLoading = ref(false);
const monthCursor = ref(getMonthStart(new Date()));
const currentStoreStore = useCurrentStoreStore();
const storeId = computed(() => currentStoreStore.currentStoreId);
let calendarRequestId = 0;
watch(monthCursor, async () => {
+1 -1
View File
@@ -5,7 +5,7 @@
* @param backgroundColor 头像背景色
*/
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);
return [
"data:image/svg+xml;charset=UTF-8,",