feat(project): restore product labels page and split modules

This commit is contained in:
2026-02-21 10:17:58 +08:00
parent 83ea84bf11
commit a53db5f0a4
17 changed files with 1341 additions and 434 deletions

View File

@@ -79,10 +79,9 @@ interface AddonGroupRecord {
interface LabelRecord {
color: string;
description: string;
id: string;
name: string;
productIds: string[];
productCount: number;
sort: number;
status: ProductSwitchStatus;
updatedAt: string;
@@ -289,9 +288,6 @@ function cleanupRelationIds(state: ProductExtensionStoreState) {
for (const group of state.addonGroups) {
group.productIds = group.productIds.filter((item) => idSet.has(item));
}
for (const label of state.labels) {
label.productIds = label.productIds.filter((item) => idSet.has(item));
}
for (const schedule of state.schedules) {
schedule.productIds = schedule.productIds.filter((item) => idSet.has(item));
}
@@ -386,18 +382,14 @@ function toAddonGroupItem(
};
}
function toLabelItem(state: ProductExtensionStoreState, item: LabelRecord) {
const idSet = new Set(state.products.map((product) => product.id));
const productIds = item.productIds.filter((id) => idSet.has(id));
function toLabelItem(item: LabelRecord) {
return {
id: item.id,
name: item.name,
color: item.color,
description: item.description,
sort: item.sort,
status: item.status,
productIds,
productCount: productIds.length,
productCount: item.productCount,
updatedAt: item.updatedAt,
};
}
@@ -540,20 +532,18 @@ function createDefaultState(storeId: string): ProductExtensionStoreState {
id: createId('label', storeId),
name: '招牌',
color: '#cf1322',
description: '店铺主推商品',
sort: 1,
status: 'enabled',
productIds: products.slice(0, 6).map((item) => item.id),
productCount: 6,
updatedAt: toDateTimeText(new Date()),
},
{
id: createId('label', storeId),
name: '新品',
color: '#2f54eb',
description: '近 30 天上新',
sort: 2,
status: 'enabled',
productIds: products.slice(6, 12).map((item) => item.id),
productCount: 6,
updatedAt: toDateTimeText(new Date()),
},
];
@@ -1220,12 +1210,9 @@ Mock.mock(
.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) => toLabelItem(state, item));
.map((item) => toLabelItem(item));
return { code: 200, data: list };
},
@@ -1244,9 +1231,6 @@ Mock.mock(/\/product\/label\/save/, 'post', (options: MockRequestOptions) => {
const existingIndex = state.labels.findIndex((item) => item.id === id);
const fallbackSort =
state.labels.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 next: LabelRecord =
existingIndex === -1
@@ -1254,26 +1238,20 @@ Mock.mock(/\/product\/label\/save/, 'post', (options: MockRequestOptions) => {
id: createId('label', storeId),
name,
color: normalizeText(body.color, '#1677ff'),
description: normalizeText(body.description),
sort: normalizeInt(body.sort, fallbackSort, 1),
status: normalizeSwitchStatus(body.status, 'enabled'),
productIds,
productCount: 0,
updatedAt: toDateTimeText(new Date()),
}
: {
...state.labels[existingIndex],
name,
color: normalizeText(body.color, state.labels[existingIndex].color),
description: normalizeText(
body.description,
state.labels[existingIndex].description,
),
sort: normalizeInt(body.sort, state.labels[existingIndex].sort, 1),
status: normalizeSwitchStatus(
body.status,
state.labels[existingIndex].status,
),
productIds,
updatedAt: toDateTimeText(new Date()),
};
@@ -1283,7 +1261,7 @@ Mock.mock(/\/product\/label\/save/, 'post', (options: MockRequestOptions) => {
state.labels.splice(existingIndex, 1, next);
}
return { code: 200, data: toLabelItem(state, next) };
return { code: 200, data: toLabelItem(next) };
});
Mock.mock(/\/product\/label\/delete/, 'post', (options: MockRequestOptions) => {
@@ -1308,7 +1286,7 @@ Mock.mock(/\/product\/label\/status/, 'post', (options: MockRequestOptions) => {
if (!target) return { code: 404, data: null, message: '标签不存在' };
target.status = normalizeSwitchStatus(body.status, target.status);
target.updatedAt = toDateTimeText(new Date());
return { code: 200, data: toLabelItem(state, target) };
return { code: 200, data: toLabelItem(target) };
});
Mock.mock(