feat(project): rebuild schedule supply module with split structure

This commit is contained in:
2026-02-21 11:52:09 +08:00
parent a53db5f0a4
commit 270c51de59
21 changed files with 2368 additions and 617 deletions

View File

@@ -87,22 +87,15 @@ interface LabelRecord {
updatedAt: string;
}
interface ScheduleSlotRecord {
endTime: string;
id: string;
startTime: string;
weekDays: number[];
}
interface ScheduleRecord {
description: string;
endTime: string;
id: string;
name: string;
productIds: string[];
slots: ScheduleSlotRecord[];
sort: number;
startTime: string;
status: ProductSwitchStatus;
updatedAt: string;
weekDays: number[];
}
interface ProductExtensionStoreState {
@@ -403,18 +396,13 @@ function toScheduleItem(
return {
id: item.id,
name: item.name,
description: item.description,
sort: item.sort,
startTime: item.startTime,
endTime: item.endTime,
weekDays: [...item.weekDays],
status: item.status,
productIds,
productCount: productIds.length,
updatedAt: item.updatedAt,
slots: item.slots.map((slot) => ({
id: slot.id,
weekDays: [...slot.weekDays],
startTime: slot.startTime,
endTime: slot.endTime,
})),
};
}
@@ -552,19 +540,12 @@ function createDefaultState(storeId: string): ProductExtensionStoreState {
{
id: createId('schedule', storeId),
name: '午市供应',
description: '适用于午餐时段',
sort: 1,
startTime: '10:30',
endTime: '14:00',
weekDays: [1, 2, 3, 4, 5, 6, 7],
status: 'enabled',
productIds: products.slice(0, 8).map((item) => item.id),
updatedAt: toDateTimeText(new Date()),
slots: [
{
id: createId('slot', storeId),
weekDays: [1, 2, 3, 4, 5, 6, 7],
startTime: '10:30',
endTime: '14:00',
},
],
},
];
@@ -1300,14 +1281,11 @@ Mock.mock(
const state = ensureStoreState(storeId);
const list = state.schedules
.toSorted((a, b) => a.sort - b.sort)
.toSorted((a, b) => a.name.localeCompare(b.name))
.filter((item) => {
if (status && item.status !== status) return false;
if (!keyword) return true;
return (
item.name.toLowerCase().includes(keyword) ||
item.description.toLowerCase().includes(keyword)
);
return item.name.toLowerCase().includes(keyword);
})
.map((item) => toScheduleItem(state, item));
@@ -1329,29 +1307,14 @@ Mock.mock(
const state = ensureStoreState(storeId);
const existingIndex = state.schedules.findIndex((item) => item.id === id);
const fallbackSort =
state.schedules.reduce((max, item) => Math.max(max, item.sort), 0) + 1;
const productIds = normalizeIdList(body.productIds).filter((productId) =>
state.products.some((item) => item.id === productId),
);
const slotListRaw = Array.isArray(body.slots) ? body.slots : [];
const slots: ScheduleSlotRecord[] = slotListRaw
.map((slot) => {
if (!slot || typeof slot !== 'object') return null;
const current = slot as Record<string, unknown>;
return {
id: normalizeText(current.id, createId('slot', storeId)),
weekDays: normalizeWeekDays(current.weekDays),
startTime: normalizeTimeText(current.startTime, '09:00'),
endTime: normalizeTimeText(current.endTime, '21:00'),
};
})
.filter((item): item is ScheduleSlotRecord => item !== null)
.toSorted((a, b) => a.startTime.localeCompare(b.startTime));
if (slots.length === 0) {
return { code: 400, data: null, message: '至少保留一个时段' };
const startTime = normalizeTimeText(body.startTime, '09:00');
const endTime = normalizeTimeText(body.endTime, '21:00');
const weekDays = normalizeWeekDays(body.weekDays);
if (productIds.length === 0) {
return { code: 400, data: null, message: '请至少关联一个商品' };
}
const next: ScheduleRecord =
@@ -1359,31 +1322,24 @@ Mock.mock(
? {
id: createId('schedule', storeId),
name,
description: normalizeText(body.description),
sort: normalizeInt(body.sort, fallbackSort, 1),
startTime,
endTime,
weekDays,
status: normalizeSwitchStatus(body.status, 'enabled'),
productIds,
slots,
updatedAt: toDateTimeText(new Date()),
}
: {
...state.schedules[existingIndex],
name,
description: normalizeText(
body.description,
state.schedules[existingIndex].description,
),
sort: normalizeInt(
body.sort,
state.schedules[existingIndex].sort,
1,
),
startTime,
endTime,
weekDays,
status: normalizeSwitchStatus(
body.status,
state.schedules[existingIndex].status,
),
productIds,
slots,
updatedAt: toDateTimeText(new Date()),
};