- 添加类型定义文件和类型引用 - 删除废弃的页面模块和导出文件 - 新增聚合管理模块和插件系统 - 修复类型错误和潜在运行时问题 - 更新API基础URL和配置 - 优化组件类型定义和事件处理 - 重构数据源接口和实现 - 完善文档和开发进度记录
37 KiB
商品中心与价格系统深度分析报告
文档目的: 基于ChatGPT对话内容,结合项目现有文档和代码实现,系统梳理商品管理、价格策略、组织权限的核心架构,识别差距并提出最优解决方案。
创建日期: 2026-03-22
参考来源:
chatgpt-vs-2026-03-22T03-06-04-110Z.md
目录
1. 核心概念梳理
1.1 商品映射 vs 商品刊登
| 维度 | 商品映射(Mapping) | 商品刊登(Listing/Publish) |
|---|---|---|
| 本质 | 关系绑定 | 创建商品 + 发布到平台 |
| 动作 | 不创建新商品 | 创建新Listing |
| 方向 | 双向绑定 | 单向(系统→平台) |
| 触发时机 | 已有商品需要统一管理 | 新品上架、批量铺货 |
| 结果 | 系统知道"平台SKU = 主SKU" | 平台新增商品 |
| 用途 | 统一库存、利润分析、AI调价 | 上新、自动铺货、跨平台分发 |
核心判断公式:
这个动作有没有在平台创建新商品?
- 有 → 刊登
- 没有 → 映射
业务流程对比:
场景1:已有店铺商品 → 用「映射」
平台已有商品 → 抓取 → 绑定到系统SKU → 完成映射
用途:统一管理库存、做利润分析、AI调价
场景2:要卖新产品 → 用「刊登」
选品 → AI生成内容 → 发布到平台 → 创建Listing
用途:上新、自动铺货、跨平台分发
1.2 价格归属问题
核心结论:
❌ 价格绝对不属于商品(SKU)本身 ✅ 价格属于:"渠道 + 场景 + Listing"
价格多场景示例:
场景1:跨平台价格不同
同一个SKU:
- Amazon:$19.99
- TikTok:$17.99
- Shopify:$21.99
原因:手续费不同、流量成本不同、用户价格敏感度不同
场景2:同平台同店铺价格不同(AB测试/不同引流)
同一个SKU,在同一个TikTok店铺:
- Listing A:$19.99(自然流量)
- Listing B:$15.99(广告引流)
- Listing C:$12.99(清库存)
原因:AB测试、不同标题/人群、不同投放策略、不同活动入口
1.3 三层价格体系
┌─────────────────────────────────────────┐
│ 1️⃣ 基准价层(Base Price Layer) │
│ SKU.base_price = 99 │
│ SKU.cost_price = 40 │
│ 用途:统一锚点、人工理解 │
└──────────────┬──────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ 2️⃣ 策略层(Strategy Layer) │
│ PriceStrategy: │
│ - scope: 平台/店铺/Listing │
│ - type: multiplier/fixed/dynamic │
│ - value: 1.1 │
│ 用途:规则定义、批量控制 │
└──────────────┬──────────────────────────┘
│
↓
┌─────────────────────────────────────────┐
│ 3️⃣ Listing层(Final Price Layer) │
│ PlatformListing: │
│ - price(最终成交价) │
│ - strategy_id │
│ - override_price(手动覆盖) │
│ 用途:真正赚钱的地方 │
└─────────────────────────────────────────┘
最终价格计算公式:
最终价格 = override_price || strategy计算结果 || AI计算结果
三层价格体系示例:
主SKU: SKU-001(蓝牙耳机)
├── TikTok主店(东南亚) → 基准价 $99 → 策略: × 1.0 = $99
├── TikTok美国店(美国) → 基准价 $99 → 策略: × 1.1 = $109
├── Shopee旗舰店(马来) → 基准价 $99 → 策略: × 0.9 = $89
├── Shopify独立站(全球) → 基准价 $99 → 策略: × 1.15 = $114
└── B2B批发(国内) → 基准价 $99 → 策略: × 0.5 = $50
1.4 组织权限模型
核心原则:
❗ 权限 = 能做什么(Permission) ❗ 数据范围 = 能操作谁的数据(Scope) 👉 两者必须同时存在
多租户层级结构:
平台(Platform)
↓
商户/公司(Tenant/Organization)
↓
组织结构(Org Tree)
├── 部门A(主管)
│ ├── 组A1(组长)
│ │ ├── 员工1
│ │ └── 员工2
│ └── 组A2(组长)
│ └── 员工3
└── 部门B(主管)
└── ...
Scope(数据范围)定义:
type DataScope =
| 'SELF' // 只看自己
| 'TEAM' // 看自己组
| 'DEPT' // 看自己部门
| 'ORG' // 看整个公司
| 'ALL'; // 全平台(超管)
角色权限设计:
| 角色 | 描述 | 权限范围 |
|---|---|---|
| owner | 拥有者 | 删除店铺、管理授权、管理成员、所有权限 |
| admin | 管理员 | 管理商品、管理价格、管理订单、不可删除店铺 |
| operator | 运营 | 刊登、改价、查看数据 |
| viewer | 只读 | 查看数据、不可操作 |
1.5 授权模型
核心原则:
❗ 授权属于店铺,不属于用户 ❗ 店铺属于主体(Owner),用户只是被授权使用
店铺授权结构:
Organization(公司)
↓
Shop(店铺)
↓
Auth(授权)
↑
User(使用者)
授权类型:
| 类型 | 适用平台 | 存储内容 |
|---|---|---|
| API授权 | Shopify、Amazon | access_token, refresh_token, expire_time |
| Agent授权 | TikTok、Shopee | cookies, proxy, device_id, user_agent |
授权状态机:
INIT → AUTHORIZED → EXPIRED → INVALID → ERROR
1.6 商品三层模型
SPU(产品层)
↓
SKU(库存单元层)
↓
Listing(平台商品层)
SPU(产品层):
Product (SPU) {
id: string;
name: string; // 蓝牙耳机
brand: string;
category_id: string;
attributes: JSON; // 通用属性
}
SKU(库存单元):
ProductSKU {
id: string;
spu_id: string;
sku_code: string;
attributes: JSON; // {"color": "red", "size": "XL"}
cost_price: number; // 成本价
base_price: number; // 基准价(参考用)
weight: number;
}
PlatformListing(平台商品层):
PlatformListing {
id: string;
sku_id: string;
shop_id: string;
platform: string;
platform_listing_id: string;
title: string;
price: number; // 最终销售价
stock: number;
status: string;
}
2. 现有架构分析
2.1 项目现有数据模型
基于 docs/01_Architecture/03_Domain_Model.md:
| 实体 | 现有字段 | 缺失关键点 |
|---|---|---|
| Product | id, merchant_id, store_id, name, sku, price, stock | ❌ 无SPU/SKU分层、❌ 价格不应在SKU层 |
| Store | id, merchant_id, name, platform, platform_shop_id | ✅ 基本完整,⚠️ 缺少org_id归属 |
| User | id, merchant_id, role, status | ❌ 无Team归属、❌ 无Scope |
| Order | id, user_id, merchant_id, total_amount, status | ⚠️ 缺少shop_id关联 |
| Inventory | id, product_id, merchant_id, warehouse_id, quantity | ⚠️ 缺少SKU级别库存 |
2.2 项目现有权限设计
基于 docs/02_Backend/07_RBAC_Design.md:
| 维度 | 现有实现 | 评估 |
|---|---|---|
| 角色定义 | ADMIN/MANAGER/OPERATOR/FINANCE/SOURCING/LOGISTICS/ANALYST | ✅ 完整 |
| 权限定义 | CREATE/READ/UPDATE/DELETE/APPROVE/EXPORT/IMPORT | ✅ 完整 |
| 租户隔离 | tenantId字段过滤 | ✅ 已实现 |
| 店铺隔离 | shopId字段过滤 | ⚠️ 部分实现 |
| 组织层级 | ❌ 无Team/Department结构 | 🔴 缺失 |
| 数据范围 | ❌ 无Scope概念 | 🔴 缺失 |
| 层级继承 | ❌ 无parent_id树结构 | 🔴 缺失 |
2.3 项目现有商品闭环
基于 docs/00_Business/Business_ClosedLoops/01_Product.md:
| 闭环 | 状态 | 缺失点 |
|---|---|---|
| 数据采集与清洗 | ✅ 已定义 | - |
| 商品刊登 | ✅ 已定义 | ⚠️ 缺少Listing实体 |
| SKU变体与结构 | ✅ 已定义 | ⚠️ 缺少映射表 |
| 多平台商品管理 | ✅ 已定义 | ⚠️ 缺少价格策略层 |
| 商品主数据 | ✅ 已定义 | ⚠️ 缺少属性标准化 |
2.4 项目现有服务编排
基于 docs/01_Architecture/04_Service_Map.md:
| 服务闭环 | 状态 | 评估 |
|---|---|---|
| 权限校验闭环 | ✅ 已定义 | ⚠️ 缺少Scope校验 |
| 商户管理闭环 | ✅ 已定义 | ✅ 完整 |
| 店铺管理闭环 | ✅ 已定义 | ⚠️ 缺少授权管理 |
| 多租户数据隔离 | ✅ 已定义 | ⚠️ 缺少组织层级 |
2.5 项目现有状态机
基于 docs/01_Architecture/06_State_Machine.md:
| 实体 | 状态定义 | 评估 |
|---|---|---|
| Product | DRAFT → PENDING_APPROVAL → ACTIVE → INACTIVE → DISCONTINUED | ⚠️ 缺少Listing状态 |
| Store | PENDING → ACTIVE → INACTIVE → SUSPENDED | ✅ 完整 |
| Order | PENDING → PAID → SPLIT → PROCESSING → SHIPPED → COMPLETED → REFUNDED → CANCELLED | ✅ 完整 |
3. 差距识别与问题诊断
3.1 🔴 严重问题(必须修复)
问题1:价格存储在SKU层
现状:
Product.price = 99 // ❌ 错误设计
后果:
- 一改价格 → 全平台全乱
- 无法做AB测试
- 无法做利润分析
- AI无法决策
影响范围:商品管理、价格策略、利润计算、AI调价
问题2:缺少SPU/SKU分层
现状:
// 只有Product,无SPU/SKU区分
Product { id, name, sku, price }
后果:
- 无法管理变体(颜色/尺寸)
- 跨平台SKU映射困难
- 库存管理混乱
影响范围:商品管理、库存管理、订单归集
问题3:缺少Listing实体
现状:无PlatformListing表
后果:
- 无法支持"一个SKU → 多个Listing"
- 无法实现同店铺多价格
- 无法做AB测试
影响范围:多平台管理、价格策略、刊登系统
问题4:缺少组织层级
现状:
User { merchant_id, role } // 无team_id
后果:
- 组长看不到下属数据
- 无法实现部门管理
- 无法支持代运营场景
影响范围:权限系统、数据隔离、团队协作
3.2 🟡 中等问题(建议修复)
问题5:缺少价格策略表
现状:前端有UI,后端无表
后果:
- 策略无法持久化
- 无法批量调价
- AI调价无基础
影响范围:价格管理、AI调价
问题6:缺少SKU映射表
现状:前端有UI,后端无表
后果:
- 映射关系无法存储
- 订单无法归集
- 库存无法统一
影响范围:多平台管理、库存同步
问题7:缺少操作归因
现状:有OperationLog但无target_user_id
后果:
- 无法追踪"谁帮谁操作"
- 无法做绩效分析
- 审计不完整
影响范围:审计系统、绩效分析
问题8:缺少属性标准化体系
现状:无Attribute表
后果:
- 不同平台类目不同
- AI生成依赖结构化数据
- 映射会失败
影响范围:商品管理、AI生成、跨平台刊登
3.3 🟢 轻微问题(可后续优化)
- 缺少类目映射系统
- 缺少单位/货币统一管理
- 缺少数据快照/回滚能力
- 缺少并发控制机制
- 缺少幂等性保证
4. 最优解决方案
4.1 数据模型重构方案
4.1.1 商品三层模型
-- SPU(产品层)
CREATE TABLE cf_spu (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
brand VARCHAR(100),
category_id VARCHAR(36),
description TEXT,
main_image VARCHAR(500),
status ENUM('draft', 'active', 'inactive', 'archived') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_tenant (tenant_id),
INDEX idx_category (category_id)
);
-- SKU(库存单元层)
CREATE TABLE cf_sku (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
spu_id VARCHAR(36) NOT NULL,
sku_code VARCHAR(100) NOT NULL,
name VARCHAR(255),
attributes JSON, -- {"color": "red", "size": "XL"}
cost_price DECIMAL(10,2) NOT NULL, -- 成本价
base_price DECIMAL(10,2), -- 基准价(参考用)
weight DECIMAL(10,3),
status ENUM('draft', 'active', 'inactive', 'archived') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_tenant_sku (tenant_id, sku_code),
INDEX idx_spu (spu_id),
INDEX idx_tenant (tenant_id)
);
-- PlatformListing(平台商品层)
CREATE TABLE cf_platform_listing (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
sku_id VARCHAR(36) NOT NULL,
shop_id VARCHAR(36) NOT NULL,
platform ENUM('tiktok', 'shopee', 'lazada', 'shopify', 'woocommerce', 'b2b', 'custom') NOT NULL,
platform_listing_id VARCHAR(100), -- 平台商品ID
platform_sku VARCHAR(100), -- 平台SKU
title VARCHAR(500),
price DECIMAL(10,2) NOT NULL, -- 最终销售价
original_price DECIMAL(10,2),
currency VARCHAR(10) DEFAULT 'USD',
stock INT DEFAULT 0,
status ENUM('draft', 'pending', 'active', 'inactive', 'error') DEFAULT 'draft',
sync_status ENUM('synced', 'syncing', 'error', 'never') DEFAULT 'never',
last_sync_at TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_sku (sku_id),
INDEX idx_shop (shop_id),
INDEX idx_platform_listing (platform, platform_listing_id),
INDEX idx_tenant (tenant_id)
);
4.1.2 价格策略模型
-- 价格策略表
CREATE TABLE cf_price_strategy (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
name VARCHAR(100) NOT NULL,
scope ENUM('global', 'platform', 'shop', 'listing') NOT NULL,
target_id VARCHAR(36), -- 平台ID/店铺ID/ListingID
strategy_type ENUM('multiplier', 'fixed', 'dynamic', 'range') NOT NULL,
strategy_value DECIMAL(10,4), -- 倍率或固定值
min_price DECIMAL(10,2),
max_price DECIMAL(10,2),
profit_rate_min DECIMAL(5,4), -- 最低利润率
is_active BOOLEAN DEFAULT TRUE,
priority INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_tenant (tenant_id),
INDEX idx_scope_target (scope, target_id)
);
-- 价格变更日志
CREATE TABLE cf_price_change_log (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
listing_id VARCHAR(36) NOT NULL,
old_price DECIMAL(10,2),
new_price DECIMAL(10,2),
change_type ENUM('manual', 'strategy', 'ai', 'sync') NOT NULL,
strategy_id VARCHAR(36),
reason VARCHAR(500),
operator_id VARCHAR(36),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_listing (listing_id),
INDEX idx_tenant (tenant_id),
INDEX idx_created (created_at)
);
4.1.3 SKU映射模型
-- SKU映射表
CREATE TABLE cf_sku_mapping (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
master_sku_id VARCHAR(36) NOT NULL, -- 主SKU
listing_id VARCHAR(36) NOT NULL, -- 平台Listing
mapping_type ENUM('auto', 'manual') DEFAULT 'manual',
confidence DECIMAL(5,4), -- 自动映射置信度
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_sku_listing (master_sku_id, listing_id),
INDEX idx_tenant (tenant_id)
);
4.1.4 组织层级模型
-- 组织/公司表
CREATE TABLE cf_organization (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
name VARCHAR(255) NOT NULL,
type ENUM('company', 'department', 'team') NOT NULL,
parent_id VARCHAR(36), -- 支持层级
level INT DEFAULT 0, -- 层级深度
path VARCHAR(500), -- 路径:/org1/org2/org3
manager_id VARCHAR(36), -- 负责人
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_tenant (tenant_id),
INDEX idx_parent (parent_id),
INDEX idx_path (path)
);
-- 用户组织关系
CREATE TABLE cf_user_organization (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
user_id VARCHAR(36) NOT NULL,
org_id VARCHAR(36) NOT NULL,
role ENUM('manager', 'member') DEFAULT 'member',
data_scope ENUM('self', 'team', 'dept', 'org', 'all') DEFAULT 'self',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_org (user_id, org_id),
INDEX idx_tenant (tenant_id),
INDEX idx_org (org_id)
);
-- 店铺归属(挂到组织)
ALTER TABLE cf_store ADD COLUMN org_id VARCHAR(36);
ALTER TABLE cf_store ADD INDEX idx_org (org_id);
4.1.5 授权模型
-- 店铺授权表
CREATE TABLE cf_shop_auth (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
shop_id VARCHAR(36) NOT NULL,
auth_type ENUM('api', 'agent') NOT NULL,
-- API类
access_token TEXT,
refresh_token TEXT,
expire_time TIMESTAMP,
-- Agent类
cookies JSON,
proxy VARCHAR(255),
device_id VARCHAR(100),
user_agent VARCHAR(500),
-- 通用
status ENUM('init', 'authorized', 'expired', 'invalid', 'error') DEFAULT 'init',
last_refresh_at TIMESTAMP,
raw_data JSON, -- 原始返回(兼容)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_shop (shop_id),
INDEX idx_tenant (tenant_id)
);
-- 用户店铺关系
CREATE TABLE cf_user_shop (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
user_id VARCHAR(36) NOT NULL,
shop_id VARCHAR(36) NOT NULL,
role ENUM('owner', 'admin', 'operator', 'viewer') DEFAULT 'operator',
permissions JSON, -- 细粒度权限
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_user_shop (user_id, shop_id),
INDEX idx_tenant (tenant_id),
INDEX idx_shop (shop_id)
);
4.1.6 属性标准化模型
-- 属性定义表
CREATE TABLE cf_attribute (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
name VARCHAR(100) NOT NULL, -- 颜色 / 尺寸 / 材质
code VARCHAR(50) NOT NULL, -- color / size
type ENUM('enum', 'string', 'number') NOT NULL,
is_required BOOLEAN DEFAULT FALSE,
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_tenant_code (tenant_id, code),
INDEX idx_tenant (tenant_id)
);
-- 属性值表
CREATE TABLE cf_attribute_value (
id VARCHAR(36) PRIMARY KEY,
attribute_id VARCHAR(36) NOT NULL,
value VARCHAR(100) NOT NULL, -- 红 / 蓝 / XL
sort_order INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_attribute (attribute_id)
);
-- SKU属性绑定
CREATE TABLE cf_sku_attribute (
id VARCHAR(36) PRIMARY KEY,
sku_id VARCHAR(36) NOT NULL,
attribute_id VARCHAR(36) NOT NULL,
value VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_sku_attr (sku_id, attribute_id),
INDEX idx_sku (sku_id)
);
-- 类目映射表
CREATE TABLE cf_category_mapping (
id VARCHAR(36) PRIMARY KEY,
tenant_id VARCHAR(36) NOT NULL,
platform ENUM('tiktok', 'shopee', 'lazada', 'shopify', 'woocommerce', 'amazon') NOT NULL,
platform_category_id VARCHAR(100) NOT NULL,
platform_category_name VARCHAR(255),
internal_category_id VARCHAR(36) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY uk_platform_category (platform, platform_category_id),
INDEX idx_tenant (tenant_id)
);
4.2 服务层设计
4.2.1 价格服务(PricingService)
/**
* 价格服务 - 所有价格计算必须通过此服务
* 禁止在Controller或前端直接计算价格
*/
interface PricingService {
calculatePrice(skuId: string, shopId: string): Promise<number>;
applyStrategy(listingId: string, strategyId: string): Promise<void>;
overridePrice(listingId: string, price: number, reason: string): Promise<void>;
getPriceHistory(listingId: string, period: DateRange): Promise<PriceChangeLog[]>;
suggestPrice(skuId: string, platform: Platform): Promise<PriceSuggestion>;
batchApplyStrategy(skuIds: string[], strategyId: string): Promise<BatchResult>;
}
interface PriceSuggestion {
suggestedPrice: number;
confidence: number;
factors: {
cost: number;
competitorPrice?: number;
demandLevel: 'low' | 'medium' | 'high';
profitRate: number;
};
}
interface BatchResult {
success: number;
failed: number;
errors: Array<{ id: string; reason: string }>;
}
4.2.2 映射服务(MappingService)
/**
* SKU映射服务 - 管理主SKU与平台Listing的映射关系
*/
interface MappingService {
createMapping(masterSkuId: string, listingId: string, type: 'auto' | 'manual'): Promise<SkuMapping>;
autoMap(skuId: string, platform: Platform): Promise<SkuMapping[]>;
validateMapping(mappingId: string): Promise<boolean>;
getMappingByListing(listingId: string): Promise<SkuMapping | null>;
getMappingsBySku(skuId: string): Promise<SkuMapping[]>;
batchMap(mappings: Array<{ skuId: string; listingId: string }>): Promise<BatchResult>;
}
4.2.3 数据范围服务(DataScopeService)
/**
* 数据范围服务 - 所有数据访问必须通过此服务校验
*/
interface DataScopeService {
getUserScope(userId: string): Promise<DataScope>;
getAccessibleShopIds(userId: string): Promise<string[]>;
getAccessibleUserIds(userId: string): Promise<string[]>;
checkDataAccess(userId: string, targetShopId: string): Promise<boolean>;
getOrgTree(orgId: string): Promise<OrganizationNode[]>;
buildScopeQuery(userId: string, baseQuery: QueryBuilder): Promise<QueryBuilder>;
}
interface DataScope {
scope: 'self' | 'team' | 'dept' | 'org' | 'all';
orgIds: string[];
shopIds: string[];
userIds: string[];
}
4.2.4 刊登服务(ListingService)
/**
* 刊登服务 - 管理商品到平台的刊登流程
*/
interface ListingService {
createDraft(skuId: string, shopId: string, data: ListingDraftData): Promise<PlatformListing>;
publishDraft(draftId: string): Promise<PublishResult>;
syncToListing(listingId: string): Promise<SyncResult>;
batchPublish(draftIds: string[]): Promise<BatchResult>;
getListingStatus(listingId: string): Promise<ListingStatus>;
}
interface PublishResult {
success: boolean;
platformListingId?: string;
error?: string;
}
4.3 API设计
4.3.1 商品API
# SPU管理
GET /api/v1/spu # SPU列表
POST /api/v1/spu # 创建SPU
GET /api/v1/spu/:id # SPU详情
PUT /api/v1/spu/:id # 更新SPU
DELETE /api/v1/spu/:id # 删除SPU
# SKU管理
GET /api/v1/spu/:spuId/sku # SKU列表
POST /api/v1/spu/:spuId/sku # 创建SKU
GET /api/v1/sku/:id # SKU详情
PUT /api/v1/sku/:id # 更新SKU
DELETE /api/v1/sku/:id # 删除SKU
# Listing管理
GET /api/v1/listing # Listing列表(支持多筛选)
POST /api/v1/listing # 创建Listing(刊登)
GET /api/v1/listing/:id # Listing详情
PUT /api/v1/listing/:id # 更新Listing
DELETE /api/v1/listing/:id # 删除Listing
POST /api/v1/listing/:id/sync # 同步到平台
POST /api/v1/listing/batch # 批量操作
4.3.2 价格API
# 价格策略
GET /api/v1/price-strategy # 策略列表
POST /api/v1/price-strategy # 创建策略
PUT /api/v1/price-strategy/:id # 更新策略
DELETE /api/v1/price-strategy/:id # 删除策略
POST /api/v1/price-strategy/:id/apply # 应用策略
# 价格操作
GET /api/v1/listing/:id/price # 获取价格
PUT /api/v1/listing/:id/price # 修改价格
GET /api/v1/listing/:id/price/history # 价格历史
POST /api/v1/listing/:id/price/suggest # AI建议价
4.3.3 映射API
GET /api/v1/sku-mapping # 映射列表
POST /api/v1/sku-mapping # 创建映射
DELETE /api/v1/sku-mapping/:id # 删除映射
POST /api/v1/sku-mapping/auto # 自动映射
POST /api/v1/sku-mapping/validate # 验证映射
4.3.4 组织API
# 组织管理
GET /api/v1/organization # 组织列表
POST /api/v1/organization # 创建组织
GET /api/v1/organization/:id # 组织详情
PUT /api/v1/organization/:id # 更新组织
DELETE /api/v1/organization/:id # 删除组织
GET /api/v1/organization/:id/tree # 组织树
# 用户组织关系
GET /api/v1/user-organization # 用户组织关系
POST /api/v1/user-organization # 分配用户到组织
PUT /api/v1/user-organization/:id # 更新关系
DELETE /api/v1/user-organization/:id # 移除关系
# 数据范围
GET /api/v1/data-scope # 获取当前用户数据范围
GET /api/v1/data-scope/shops # 可访问店铺
GET /api/v1/data-scope/users # 可管理用户
4.3.5 授权API
# 店铺授权
GET /api/v1/shop-auth # 授权列表
POST /api/v1/shop-auth # 创建授权
GET /api/v1/shop-auth/:id # 授权详情
DELETE /api/v1/shop-auth/:id # 删除授权
POST /api/v1/shop-auth/:id/refresh # 刷新授权
# OAuth流程
GET /api/v1/auth/:platform/start # 开始OAuth
GET /api/v1/auth/:platform/callback # OAuth回调
# Agent授权
POST /api/v1/auth/agent/login # Agent登录
POST /api/v1/auth/agent/cookie # 上传Cookie
4.4 前端改造方案
4.4.1 页面结构调整
商品中心(新一级菜单)
├── 商品管理(SPU/SKU)
│ ├── SPU列表
│ ├── SKU列表
│ └── 商品详情
├── 平台商品(Listing)
│ ├── Listing列表
│ ├── 刊登管理
│ └── 同步状态
├── 价格策略
│ ├── 策略列表
│ ├── 策略配置
│ └── 价格历史
└── SKU映射
├── 映射列表
└── 自动映射
组织管理(新一级菜单)
├── 组织架构
│ ├── 组织树
│ └── 成员管理
├── 店铺管理
│ ├── 店铺列表
│ └── 授权管理
└── 权限配置
├── 角色管理
└── 数据范围
4.4.2 关键组件设计
interface ProductListPage {
filters: {
platform?: Platform[];
shopIds?: string[];
status?: ProductStatus;
category?: string;
search?: string;
};
view: 'spu' | 'sku' | 'listing';
actions: {
batchEdit: () => void;
batchSync: () => void;
export: () => void;
};
}
interface PriceStrategyEditor {
basePrice: number;
strategies: PriceStrategy[];
calculatedPrices: Map<string, number>;
onStrategyChange: (strategy: PriceStrategy) => void;
onApply: () => void;
}
interface DataScopeSelector {
currentScope: DataScope;
orgTree: OrganizationNode[];
onScopeChange: (scope: DataScope) => void;
}
interface ListingPriceEditor {
listingId: string;
currentPrice: number;
basePrice: number;
strategyPrice: number;
onPriceChange: (price: number, reason: string) => void;
}
4.4.3 操作日志增强
interface OperationLog {
id: string;
tenant_id: string;
user_id: string;
shop_id: string;
action: string;
target_id: string;
target_user_id?: string; // 新增:操作归属用户
before: JSON;
after: JSON;
ip: string;
device: string;
created_at: Timestamp;
}
5. 实施步骤
5.1 阶段一:数据模型迁移(预计3天)
任务清单
| 任务ID | 任务描述 | 优先级 | 预计时间 |
|---|---|---|---|
| DB-001 | 创建cf_spu表 | P0 | 0.5天 |
| DB-002 | 创建cf_sku表 | P0 | 0.5天 |
| DB-003 | 创建cf_platform_listing表 | P0 | 0.5天 |
| DB-004 | 创建cf_price_strategy表 | P0 | 0.5天 |
| DB-005 | 创建cf_sku_mapping表 | P1 | 0.5天 |
| DB-006 | 创建cf_organization表 | P1 | 0.5天 |
| DB-007 | 创建cf_user_organization表 | P1 | 0.5天 |
| DB-008 | 创建cf_shop_auth表 | P1 | 0.5天 |
| DB-009 | 创建cf_user_shop表 | P1 | 0.5天 |
| DB-010 | 创建cf_attribute表 | P2 | 0.5天 |
| DB-011 | 创建cf_attribute_value表 | P2 | 0.5天 |
| DB-012 | 创建cf_sku_attribute表 | P2 | 0.5天 |
| DB-013 | 创建cf_category_mapping表 | P2 | 0.5天 |
| DB-014 | 数据迁移脚本(Product→SPU/SKU/Listing) | P0 | 1天 |
数据迁移策略
-- Step 1: 迁移现有Product到SPU
INSERT INTO cf_spu (id, tenant_id, name, status, created_at)
SELECT id, merchant_id, name, status, created_at
FROM cf_product;
-- Step 2: 创建默认SKU(每个SPU一个)
INSERT INTO cf_sku (id, tenant_id, spu_id, sku_code, name, cost_price, base_price, status, created_at)
SELECT
UUID() as id,
merchant_id as tenant_id,
id as spu_id,
sku as sku_code,
name,
price * 0.4 as cost_price, -- 假设成本为售价40%
price as base_price,
status,
created_at
FROM cf_product;
-- Step 3: 创建默认Listing(关联到店铺)
INSERT INTO cf_platform_listing (id, tenant_id, sku_id, shop_id, platform, price, stock, status, created_at)
SELECT
UUID() as id,
p.merchant_id as tenant_id,
s.id as sku_id,
p.store_id as shop_id,
st.platform,
p.price,
p.stock,
p.status,
p.created_at
FROM cf_product p
JOIN cf_sku s ON s.spu_id = p.id
JOIN cf_store st ON st.id = p.store_id;
-- Step 4: 创建默认价格策略
INSERT INTO cf_price_strategy (id, tenant_id, name, scope, strategy_type, strategy_value, is_active)
SELECT
UUID() as id,
merchant_id as tenant_id,
'默认策略' as name,
'global' as scope,
'multiplier' as strategy_type,
1.0 as strategy_value,
TRUE as is_active
FROM cf_merchant;
5.2 阶段二:服务层实现(预计5天)
任务清单
| 任务ID | 任务描述 | 优先级 | 预计时间 |
|---|---|---|---|
| SVC-001 | PricingService实现 | P0 | 1天 |
| SVC-002 | MappingService实现 | P0 | 1天 |
| SVC-003 | DataScopeService实现 | P0 | 1天 |
| SVC-004 | ListingService实现 | P1 | 1天 |
| SVC-005 | OrganizationService实现 | P1 | 0.5天 |
| SVC-006 | AuthService实现 | P1 | 0.5天 |
服务层实现原则
- 所有业务逻辑必须在Service层
- Controller只负责请求/响应和权限校验
- 禁止跨Domain直接操作数据库
- 所有状态变更必须通过STATE_MACHINE
5.3 阶段三:API层实现(预计3天)
任务清单
| 任务ID | 任务描述 | 优先级 | 预计时间 |
|---|---|---|---|
| API-001 | 商品API实现 | P0 | 1天 |
| API-002 | 价格API实现 | P0 | 1天 |
| API-003 | 映射API实现 | P1 | 0.5天 |
| API-004 | 组织API实现 | P1 | 0.5天 |
5.4 阶段四:前端改造(预计5天)
任务清单
| 任务ID | 任务描述 | 优先级 | 预计时间 |
|---|---|---|---|
| FE-001 | 商品管理页面重构 | P0 | 1天 |
| FE-002 | Listing管理页面 | P0 | 1天 |
| FE-003 | 价格策略页面 | P0 | 1天 |
| FE-004 | 组织架构页面 | P1 | 1天 |
| FE-005 | 授权管理页面 | P1 | 0.5天 |
| FE-006 | 数据范围选择器组件 | P1 | 0.5天 |
5.5 阶段五:测试与验证(预计2天)
任务清单
| 任务ID | 任务描述 | 优先级 | 预计时间 |
|---|---|---|---|
| TEST-001 | 单元测试编写 | P0 | 0.5天 |
| TEST-002 | 集成测试编写 | P0 | 0.5天 |
| TEST-003 | 数据迁移验证 | P0 | 0.5天 |
| TEST-004 | 权限系统验证 | P0 | 0.5天 |
5.6 总体进度安排
阶段一:数据模型迁移 ████████░░░░░░░░░░░░ Day 1-3
阶段二:服务层实现 ░░░░░░░░████████░░░░ Day 4-8
阶段三:API层实现 ░░░░░░░░░░░░░░██████ Day 9-11
阶段四:前端改造 ░░░░████████░░░░░░░░ Day 12-16
阶段五:测试与验证 ░░░░░░░░░░░░░░░░████ Day 17-18
预计总工期:18天(可并行压缩至12天)
6. 风险评估与应对
6.1 技术风险
风险1:数据迁移数据丢失
风险等级:🔴 高
影响:历史商品数据丢失,影响业务连续性
应对措施:
- 迁移前完整备份现有数据
- 编写迁移验证脚本,对比迁移前后数据量
- 保留原Product表6个月,设置只读
- 分批迁移,每批验证后再进行下一批
回滚方案:
-- 回滚脚本示例
DROP TABLE IF EXISTS cf_spu, cf_sku, cf_platform_listing;
RESTORE TABLE cf_product FROM backup;
风险2:权限系统重构影响现有用户
风险等级:🟡 中
影响:现有用户权限丢失或混乱
应对措施:
- 为现有用户自动创建默认组织关系
- 保留原有role字段作为fallback
- 灰度发布,先在测试环境验证
- 提供权限迁移工具,支持手动调整
风险3:价格计算逻辑变更导致价格错误
风险等级:🔴 高
影响:商品价格错误,影响销售和利润
应对措施:
- 所有价格变更记录日志
- 价格计算服务增加单元测试覆盖
- 上线前进行价格对比验证
- 提供价格回滚功能
6.2 业务风险
风险4:用户不适应新操作流程
风险等级:🟡 中
影响:用户投诉,使用效率下降
应对措施:
- 提供详细的操作文档和视频教程
- 保留旧版入口1个月过渡期
- 收集用户反馈,快速迭代优化
- 提供在线客服支持
风险5:多平台同步延迟
风险等级:🟡 中
影响:数据不一致,影响运营决策
应对措施:
- 增加同步状态监控和告警
- 提供手动同步入口
- 记录同步日志,便于排查
- 设置合理的同步频率和重试机制
6.3 性能风险
风险6:组织层级查询性能问题
风险等级:🟡 中
影响:权限校验慢,影响系统响应
应对措施:
- 使用path字段优化层级查询
- 缓存用户Scope信息
- 定期更新层级缓存
- 限制组织层级深度(建议不超过5层)
// Scope缓存示例
const userScopeCache = new Map<string, DataScope>();
async function getUserScope(userId: string): Promise<DataScope> {
if (userScopeCache.has(userId)) {
return userScopeCache.get(userId)!;
}
const scope = await calculateUserScope(userId);
userScopeCache.set(userId, scope);
return scope;
}
6.4 风险矩阵
| 风险 | 等级 | 概率 | 影响 | 应对优先级 |
|---|---|---|---|---|
| 数据迁移丢失 | 🔴 高 | 低 | 极高 | P0 |
| 价格计算错误 | 🔴 高 | 中 | 极高 | P0 |
| 权限系统混乱 | 🟡 中 | 中 | 高 | P1 |
| 用户不适应 | 🟡 中 | 高 | 中 | P2 |
| 同步延迟 | 🟡 中 | 中 | 中 | P2 |
| 性能问题 | 🟡 中 | 低 | 中 | P3 |
7. 附录
7.1 术语对照表
| 术语 | 英文 | 说明 |
|---|---|---|
| 商品映射 | Product Mapping | 绑定系统SKU与平台商品的关系 |
| 商品刊登 | Product Listing | 创建新商品并发布到平台 |
| 基准价 | Base Price | SKU层的参考价格锚点 |
| 策略层 | Strategy Layer | 价格规则定义层 |
| Listing层 | Listing Layer | 最终销售价格层 |
| 数据范围 | Data Scope | 用户可访问的数据边界 |
| 组织层级 | Organization Hierarchy | 公司/部门/团队的树形结构 |
7.2 参考文档
7.3 变更记录
| 日期 | 版本 | 变更内容 | 作者 |
|---|---|---|---|
| 2026-03-22 | 1.0 | 初始版本,完整分析报告 | AI |
本报告基于ChatGPT对话内容和项目现有文档综合分析生成,如有疑问请参考原始文档。