From bbd7e52e708ee4760863b9071ad9d2c97b37d39e Mon Sep 17 00:00:00 2001 From: jacy <18049821889@163.com> Date: Sun, 16 Aug 2026 12:09:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E5=A5=97=E9=A4=90=E5=8F=98?= =?UTF-8?q?=E6=9B=B4=E5=AF=B9=E6=AF=94=E9=80=90=E5=AD=97=E6=AE=B5=E5=88=97?= =?UTF-8?q?=E5=87=BA=E5=8F=98=E5=8A=A8=E6=98=8E=E7=BB=86(v3.4.18)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/StorePackageAuditsPage.tsx | 83 ++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/apps/admin-web/src/pages/StorePackageAuditsPage.tsx b/apps/admin-web/src/pages/StorePackageAuditsPage.tsx index f728ce1..ecdcd9f 100644 --- a/apps/admin-web/src/pages/StorePackageAuditsPage.tsx +++ b/apps/admin-web/src/pages/StorePackageAuditsPage.tsx @@ -42,6 +42,31 @@ function imageSignature(pkg: StorePackageItemDto | StorePackageViewDto) { return normalizeStorePackageImageUrls(pkg).join('|'); } +type FieldChange = { label: string; old: string; now: string }; + +/** 逐字段比较套餐内容,返回发生变化的字段明细(用于“变动的地方详细列出”) */ +function fieldChanges( + live: StorePackageItemDto | StorePackageViewDto, + proposed: StorePackageItemDto | StorePackageViewDto, +): FieldChange[] { + const changes: FieldChange[] = []; + const text = (v: string | number | null | undefined) => (v ?? '').toString().trim(); + const pushIf = (label: string, oldV: string, newV: string) => { + if (oldV !== newV) changes.push({ label, old: oldV || '(空)', now: newV || '(空)' }); + }; + pushIf('价格', `¥${text(live.price)}`, `¥${text(proposed.price)}`); + pushIf('套餐名称', text(live.name), text(proposed.name)); + pushIf('菜品内容', text(live.dishes), text(proposed.dishes)); + pushIf('可用时间', text(live.usableTime), text(proposed.usableTime)); + pushIf('其他说明', text(live.otherNotes), text(proposed.otherNotes)); + const liveImgs = normalizeStorePackageImageUrls(live); + const proposedImgs = normalizeStorePackageImageUrls(proposed); + if (imageSignature(live) !== imageSignature(proposed)) { + changes.push({ label: '图片', old: `${liveImgs.length} 张`, now: `${proposedImgs.length} 张` }); + } + return changes; +} + function diffPackages(live: StorePackageViewDto[], proposed: StorePackageItemDto[]) { const liveMap = new Map(live.map((p, i) => [packageKey(p, i), p])); const proposedMap = new Map(proposed.map((p, i) => [packageKey(p, i), p])); @@ -51,6 +76,7 @@ function diffPackages(live: StorePackageViewDto[], proposed: StorePackageItemDto change: 'added' | 'removed' | 'changed' | 'unchanged'; live?: StorePackageViewDto; proposed?: StorePackageItemDto; + changes?: FieldChange[]; }> = []; for (const key of keys) { @@ -67,7 +93,13 @@ function diffPackages(live: StorePackageViewDto[], proposed: StorePackageItemDto (l.usableTime ?? '') !== (p.usableTime ?? '') || (l.otherNotes ?? '') !== (p.otherNotes ?? '') || imageSignature(l) !== imageSignature(p); - rows.push({ key, change: changed ? 'changed' : 'unchanged', live: l, proposed: p }); + rows.push({ + key, + change: changed ? 'changed' : 'unchanged', + live: l, + proposed: p, + changes: changed ? fieldChanges(l, p) : undefined, + }); } } return rows; @@ -84,10 +116,12 @@ function PackageDetailCard({ title, pkg, change, + changes, }: { title?: string; pkg: StorePackageItemDto | StorePackageViewDto; change?: keyof typeof CHANGE_LABELS; + changes?: FieldChange[]; }) { const images = normalizeStorePackageImageUrls(pkg); const meta = change ? CHANGE_LABELS[change] : null; @@ -149,6 +183,33 @@ function PackageDetailCard({ ) : ( 无套餐图片 )} + {changes && changes.length ? ( +
+ + 变更明细 + + +
+ ) : null} ); } @@ -236,6 +297,11 @@ export default function StorePackageAuditsPage() { const diffRows = detail ? diffPackages(detail.livePackages ?? [], detail.packages ?? []) : []; const changeByKey = new Map(diffRows.map((row) => [row.key, row.change])); + const changesByKey = new Map(diffRows.map((row) => [row.key, row.changes])); + const addedCount = diffRows.filter((r) => r.change === 'added').length; + const removedCount = diffRows.filter((r) => r.change === 'removed').length; + const changedCount = diffRows.filter((r) => r.change === 'changed').length; + const unchangedCount = diffRows.filter((r) => r.change === 'unchanged').length; const columns: ColumnsType = [ { title: '门店', dataIndex: 'storeName', render: (_, row) => row.storeName || row.storeId }, @@ -354,9 +420,17 @@ export default function StorePackageAuditsPage() { {detail.rejectReason ? ( 驳回原因:{detail.rejectReason} ) : null} - - 线上已审核 {detail.livePackages?.length ?? 0} 条 · 待审核 {detail.packages?.length ?? 0} 条 - + + + 线上已审核 {detail.livePackages?.length ?? 0} 条 · 待审核 {detail.packages?.length ?? 0} 条 + + + 新增 {addedCount} + 删除 {removedCount} + 变更 {changedCount} + {unchangedCount ? 未变 {unchangedCount} : null} + +
@@ -386,6 +460,7 @@ export default function StorePackageAuditsPage() { title={`套餐 ${index + 1}`} pkg={pkg} change={changeByKey.get(packageKey(pkg, index))} + changes={changesByKey.get(packageKey(pkg, index))} /> )) ) : (