diff --git a/apps/admin-web/src/pages/ProductsPage.tsx b/apps/admin-web/src/pages/ProductsPage.tsx
index e02bcff..9062a8c 100644
--- a/apps/admin-web/src/pages/ProductsPage.tsx
+++ b/apps/admin-web/src/pages/ProductsPage.tsx
@@ -21,6 +21,22 @@ type ProductDetailContentDto = {
features?: Array<{ icon: string; title: string; desc: string }>;
};
+type SkuListRow = {
+ id: string;
+ skuCode: string;
+ barcode69: string;
+ specText: string;
+ price: number;
+ benefitAmount: number;
+ status: string;
+ isDefault?: boolean;
+ allowOnSitePickup?: boolean;
+ allowOnlinePurchase?: boolean;
+ allowCrossCityDelivery?: boolean;
+ soldBottles?: number;
+ virtual?: boolean;
+};
+
type Row = {
id: string;
skuCode: string;
@@ -30,9 +46,15 @@ type Row = {
aromaType: string;
spec: string;
price: number;
+ priceMin?: number;
+ priceMax?: number;
+ soldBottles?: number;
benefitAmount: number;
status: string;
sortOrder: number;
+ skuCount?: number;
+ specEnabled?: boolean;
+ skus?: SkuListRow[];
allowOnSitePickup?: boolean;
allowOnlinePurchase?: boolean;
allowCrossCityDelivery?: boolean;
@@ -214,7 +236,33 @@ function VisibilityWhitelistFields({ form }: { form: FormInstance }) {
);
}
-function BaseInfoFields({ mode, form }: { mode: 'create' | 'edit'; form: FormInstance }) {
+function FulfillmentTags(row: {
+ allowOnlinePurchase?: boolean;
+ allowCrossCityDelivery?: boolean;
+ allowOnSitePickup?: boolean;
+}) {
+ return (
+
+ {row.allowOnlinePurchase !== false ? 线上 : null}
+ {row.allowOnlinePurchase !== false && row.allowCrossCityDelivery !== false ? (
+ 跨城
+ ) : null}
+ {row.allowOnSitePickup ? 现场 : null}
+ {row.allowOnlinePurchase === false && !row.allowOnSitePickup ? 无 : null}
+
+ );
+}
+
+function BaseInfoFields({
+ mode,
+ form,
+ hideFulfillment,
+}: {
+ mode: 'create' | 'edit';
+ form: FormInstance;
+ /** 多规格商品:履约只在规格 SKU 上编辑 */
+ hideFulfillment?: boolean;
+}) {
return (
<>
{mode === 'create' && (
@@ -256,39 +304,47 @@ function BaseInfoFields({ mode, form }: { mode: 'create' | 'edit'; form: FormIns
-
- {
- if (!checked) form.setFieldsValue({ allowCrossCityDelivery: false });
- }}
- />
-
- prev.allowOnlinePurchase !== cur.allowOnlinePurchase}>
- {() => (
+ {hideFulfillment ? (
+
+ 该商品有多种规格,履约(线上 / 跨城 / 现场)请到「规格与 SKU」中按规格设置。
+
+ ) : (
+ <>
{
+ if (!checked) form.setFieldsValue({ allowCrossCityDelivery: false });
+ }}
/>
- )}
-
-
-
-
+ prev.allowOnlinePurchase !== cur.allowOnlinePurchase}>
+ {() => (
+
+
+
+ )}
+
+
+
+
+ >
+ )}
@@ -332,12 +388,35 @@ export default function ProductsPage() {
}
const columns: ColumnsType = useMemo(() => [
- { title: 'SKU', dataIndex: 'skuCode', width: 90 },
- { title: '商品名', dataIndex: 'name', width: 180, ellipsis: true },
{ title: '香型', dataIndex: 'aromaType', width: 80, render: (v) => AROMA_TYPE_LABELS[v] || v },
- { title: '规格', dataIndex: 'spec', width: 120, ellipsis: true },
- { title: '售价', dataIndex: 'price', width: 80, render: (v) => `¥${v}` },
- { title: '权益额', dataIndex: 'benefitAmount', width: 80, render: (v) => `¥${v}` },
+ { title: '品名', dataIndex: 'name', width: 200, ellipsis: true },
+ {
+ title: '累计销售',
+ dataIndex: 'soldBottles',
+ width: 110,
+ render: (v: number | undefined) => `累计 ${v ?? 0} 瓶`,
+ },
+ {
+ title: '售价',
+ key: 'priceRange',
+ width: 120,
+ render: (_, row) => {
+ const min = row.priceMin ?? row.price;
+ const max = row.priceMax ?? row.price;
+ if (min === max) return `¥${min}`;
+ return `¥${min} ~ ¥${max}`;
+ },
+ },
+ {
+ title: '规格数',
+ dataIndex: 'skuCount',
+ width: 80,
+ render: (v: number | undefined, row) => {
+ const real = v ?? 0;
+ if (real > 0) return real;
+ return row.skus?.some((s) => s.virtual) ? 1 : 0;
+ },
+ },
{ title: '状态', dataIndex: 'status', width: 80, render: (s) => (
{PRODUCT_STATUS_LABELS[s] || s}
) },
@@ -348,23 +427,7 @@ export default function ProductsPage() {
render: (v: boolean) =>
v ? 限测 : 公开,
},
- {
- title: '履约',
- key: 'fulfillment',
- width: 160,
- render: (_, row) => (
-
- {row.allowOnlinePurchase !== false ? 线上 : null}
- {row.allowOnlinePurchase !== false && row.allowCrossCityDelivery !== false ? (
- 跨城
- ) : null}
- {row.allowOnSitePickup ? 现场 : null}
- {row.allowOnlinePurchase === false && !row.allowOnSitePickup ? 无 : null}
-
- ),
- },
{ title: '排序', dataIndex: 'sortOrder', width: 60 },
- { title: '创建', dataIndex: 'createdAt', width: 160, render: fmtTime },
{
title: '操作', width: 120,
render: (_, row) => (
@@ -377,7 +440,7 @@ export default function ProductsPage() {
}}>编辑
= useMemo(() => [
+ {
+ title: '规格',
+ dataIndex: 'specText',
+ width: 140,
+ ellipsis: true,
+ render: (v: string, row) => (
+
+ {v || '默认'}
+ {row.isDefault ? 默认 : null}
+ {row.virtual ? 未建SKU : null}
+
+ ),
+ },
+ { title: 'SKU', dataIndex: 'skuCode', width: 110 },
+ { title: '69码', dataIndex: 'barcode69', width: 160, ellipsis: true },
+ { title: '售价', dataIndex: 'price', width: 90, render: (v) => `¥${v}` },
+ { title: '权益额', dataIndex: 'benefitAmount', width: 90, render: (v) => `¥${v}` },
+ {
+ title: '累计销售',
+ dataIndex: 'soldBottles',
+ width: 100,
+ render: (v: number | undefined) => `${v ?? 0} 瓶`,
+ },
+ {
+ title: '履约',
+ key: 'fulfillment',
+ width: 160,
+ render: (_, row) => ,
+ },
+ {
+ title: '状态',
+ dataIndex: 'status',
+ width: 90,
+ render: (s) => (
+ {PRODUCT_STATUS_LABELS[s] || s}
+ ),
+ },
+ ], []);
+
return (
@@ -397,7 +500,9 @@ export default function ProductsPage() {
+
+
+
@@ -406,17 +511,46 @@ export default function ProductsPage() {
-
{ setPage(p); setPageSize(ps); } }} />
+ true,
+ expandedRowRender: (row) => (
+
+ ),
+ }}
+ pagination={{ current: page, pageSize, total: data?.total ?? 0, showSizeChanger: true, onChange: (p, ps) => { setPage(p); setPageSize(ps); } }}
+ />
setDrawerOpen(false)}
extra={detail && (