# CFC 电商原生扩展设计方案 > **版本:** v1.0 > **日期:** 2026-06-24 > **优先级:** P0+P1 ## 1. 决策背景 原计划将 DanShop(`dan/danshop/`)作为独立 Spring Boot 模块部署在 9081 端口,与 cfc-backend(9082)通过 Feign 跨服务通信。经评估: | 方案 | 优势 | 劣势 | |------|------|------| | **独立模块 (DanShop)** | 代码隔离、独立部署 | 双 JVM 运维、Feign 网络开销、共享 DB 仍耦合、重复认证逻辑 | | **CFC 原生扩展** | 单 JVM 运维、直接服务调用、统一认证、统一事务 | 单体代码量增加 | **决策:** 所有电商功能直接构建在 `cfc-backend`,使用 `shop/` 子包隔离,表使用 `shop_` 前缀。 --- ## 2. 架构概览 ``` ┌──────────────────────────────────────────────────────────────┐ │ cfc-frontend (uni-app) │ │ pages/shop/* → /api/product/*, /api/cart/* 等 CFC 原生 API │ └──────────────────────┬───────────────────────────────────────┘ │ JWT + POST Mapping ┌──────────────────────▼───────────────────────────────────────┐ │ cfc-backend (9082) │ ├──────────────────────────────────────────────────────────────┤ │ controller/ │ │ ├── product/ ← 现有: Product/ProductOrder │ │ ├── cart/ ← 新增: 购物车 │ │ ├── shop/ ← 新增: 类目/售后/折扣 │ │ ├── admin/ ← 新增: 销售体系/折扣管理 │ │ └── payment/ ← 增强: PaymentService (真实微信支付) │ ├──────────────────────────────────────────────────────────────┤ │ service/ + entity/ + mapper/ ← 按模块组织 │ └──────────────────────┬───────────────────────────────────────┘ │ 单数据源 ┌──────────────────────▼───────────────────────────────────────┐ │ MySQL 8.0 (zxyj) │ │ 表: products, product_orders, cart_items, shop_categories, │ │ shop_discount_rules, distribution_systems, │ │ distribution_relations, after_sales_requests ... │ └──────────────────────────────────────────────────────────────┘ ``` ### 2.1 模块位置 ``` cfc-backend/src/main/java/com/etotem/cfc/ ├── controller/ │ ├── product/ProductController.java ← 现有,增强 │ ├── product/ProductOrderController.java ← 现有,增强 │ ├── cart/CartController.java ← 新增:购物车 │ ├── payment/PaymentController.java ← 新增:支付 │ ├── shop/ │ │ ├── ProductCategoryController.java ← 新增:商品类目(小程序) │ │ ├── AfterSalesController.java ← 新增:售后 │ │ └── RegionController.java ← 现有地址区域接口 │ └── admin/ │ ├── AdminCategoryController.java ← 新增:类目管理 │ ├── AdminDistributionController.java ← 新增:销售体系管理 │ └── AdminDiscountController.java ← 新增:折扣管理 ├── entity/ │ ├── Product.java ← 增强(categoryId, distributionSystemId, images) │ ├── ProductOrder.java ← 增强(discountAmount, couponId, cancelAt, items) │ ├── CartItem.java ← 新增 │ ├── ProductCategory.java ← 新增 │ ├── DiscountRule.java ← 新增 │ ├── DistributionSystem.java ← 新增 │ ├── DistributionRelation.java ← 新增 │ └── AfterSalesRequest.java ← 新增 ├── service/ │ ├── ProductService.java ← 现有,增强 │ ├── ProductOrderService.java ← 现有,增强 │ ├── CartService.java ← 新增 │ ├── PaymentService.java ← 重写(真实微信支付) │ ├── ProductCategoryService.java ← 新增 │ ├── DiscountService.java ← 新增 │ ├── DistributionService.java ← 新增 │ └── AfterSalesService.java ← 新增 └── mapper/ ← 每个实体对应 Mapper ``` --- ## 3. 模块设计 ### 3.1 [P0] 支付统一(PaymentService 重构) **现状:** `PaymentService` 目前为桩代码,返回 mock 数据。`PackageOrder` 使用,`ProductOrder` 下单后直接调 `pay()` 改状态。 **改造目标:** ```java @Service public class PaymentService { // 微信支付预下单 - 统一下单API public Map createWechatPrepay(String orderNo, String description, Integer totalFee); // 处理微信支付回调通知 public String handleWechatNotify(String requestBody, String signatureHeader); // 处理支付宝回调 public boolean handleAlipayNotify(Map params); // 统一支付结果查询 public PaymentStatus queryPaymentStatus(String orderNo); // 退款 public boolean refund(String orderNo, Integer amount, String reason); } ``` **配置:** ```yaml payment: wechat: app-id: wx5ba8038ef16fb245 mch-id: ${WX_MCH_ID} api-v3-key: ${WX_API_V3_KEY} private-key-path: ${WX_PRIVATE_KEY_PATH} notify-url: https://cfc.etotem.com.cn/api/payment/wechat/notify cert-path: ${WX_CERT_PATH} ``` ### 3.2 [P0] 购物车 **数据模型:** MySQL 持久化(`cart_items` 表) ```java @TableName("cart_items") public class CartItem { Long id; Long userId; Long productId; Integer quantity; Boolean selected; // 是否选中 Date createdAt; Date updatedAt; } ``` **API:** | 端点 | 说明 | |------|------| | `POST /api/cart/list` | 我的购物车(返回商品实时信息 + 价格同步) | | `POST /api/cart/add` | 加入购物车(已有则增加数量) | | `POST /api/cart/update` | 修改数量 (`productId` + `quantity`) | | `POST /api/cart/remove` | 移除商品(支持批量) | | `POST /api/cart/toggle` | 切换选中状态 | **校验:** - 加入时校验商品存在且 `on_shelf` - list 时检查库存和价格同步 - 下架/删除商品标记失效(仍显示但不允许勾选结算) ### 3.3 [P0] 结算 + 待支付 **当前 ProductOrder 增强:** ```java @TableName("product_orders") public class ProductOrder { // 现有字段保留 Long id; String orderNo; Long productId; String productName; String productType; Long buyerId; Long familyId; Integer quantity; Integer unitPrice; Integer totalAmount; String status; String paymentMethod; String remark; Date paidAt; Date createdAt; Date updatedAt; // 新增字段 String coverImage; // 商品封面(快照) Integer discountAmount; // 优惠金额(分) Long couponId; // 使用的优惠券/折扣ID Date cancelAt; // 自动取消时间(createdAt+30min) String transactionId; // 支付平台交易号 String addressSnapshot; // 收货地址快照(JSON) String logisticsNo; // 物流单号 String logisticsCompany; // 物流公司 } ``` **前端改造:** 订单列表按状态 tab(全部/待支付/已完成/已取消),待支付订单显示支付倒计时和「去支付」按钮。 ### 3.4 [P0] 售后(人工客服版) ```java @TableName("after_sales_requests") public class AfterSalesRequest { Long id; Long orderId; String orderNo; Long userId; String type; // REFUND(仅退款) / RETURN_REFUND(退货退款) String reason; String description; String images; // 凭证图片(JSON数组) Integer refundAmount; // 退款金额(分) String status; // pending(待审核)/approved(已通过)/rejected(驳回)/completed(已完成) String rejectReason; String handledBy; // 处理人ID Date handledAt; Date createdAt; } ``` **流程:** 买家提交 → 管理员审核 → 线下退款 → 标记完成。无自动退款。 **API:** | 端点 | 端 | 说明 | |------|----|------| | `POST /api/shop/after-sales/create` | 小程序 | 提交售后申请 | | `POST /api/shop/after-sales/list` | 小程序 | 我的售后记录 | | `POST /api/shop/after-sales/detail` | 小程序 | 售后详情 | | `POST /api/admin/shop/after-sales/list` | Web | 售后列表(管理端) | | `POST /api/admin/shop/after-sales/review` | Web | 审核售后申请 | ### 3.5 [P1] 商品类目(多维度 + 多种类) ```java @TableName("shop_categories") public class ProductCategory { Long id; String name; Long parentId; // 0=根节点 Integer level; // 0/1/2/3 Integer sort; String image; Boolean enabled; String dimensionCodes; // "body,mind,heart" 多维度关联 String productTypes; // "PHYSICAL,COURSE,ASSESSMENT,VIRTUAL" Date createdAt; Date updatedAt; } ``` **Product 增加字段:** - `Long categoryId` — 所属类目 - `Long distributionSystemId` — 销售体系归属 **维度继承:** ``` 类目(维度=身,智) → 子类目(继承维度=身,智, 可追加指定) → 商品(继承类目维度) ``` **API:** | 端点 | 端 | 说明 | |------|----|------| | `POST /api/admin/shop/category/create` | Web | 创建类目 | | `POST /api/admin/shop/category/update` | Web | 更新类目 | | `POST /api/admin/shop/category/delete` | Web | 删除类目 | | `POST /api/admin/shop/category/tree` | Web | 管理端树形 | | `POST /api/shop/category/tree` | 小程序 | 商城端类目树 | | `POST /api/shop/category/products` | 小程序 | 类目下商品列表 | ### 3.6 [P1] 商品相册 **Product.images 增强:** - `coverImage` 作为主图(封面) - `images` 存储 JSON 数组 `["url1","url2","url3"]` - 管理端商品编辑支持多图上传/排序/删除 **前端展示:** - 详情页轮播图(coverImage + images) - 列表页使用 coverImage ### 3.7 [P1] 多销售体系 ```java @TableName("distribution_systems") public class DistributionSystem { Long id; String name; String description; Long ownerId; // 创建者 Integer profitRate; // 平台利润率(千分比),仅管理员可修改 Boolean enabled; Date createdAt; Date updatedAt; } @TableName("distribution_relations") public class DistributionRelation { Long id; Long systemId; Long userId; Long parentId; // 上级(null=根) Integer depth; Date createdAt; } ``` **业务规则:** - `profitRate` 管理员在 Web 端设置,合作商不可修改 - 每个销售体系有自己的上下级关系树 - 商品归属一个销售体系(`product.distributionSystemId`) - 下单时通过用户 → 销售关系链查找上级,按体系规则返利 - 平台只记录外部销售关系(external),不计算外部利润 **API(Web 管理端):** | 端点 | 说明 | |------|------| | `POST /api/admin/distribution/system/create` | 创建销售体系 | | `POST /api/admin/distribution/system/update` | 更新(含 profitRate 设置) | | `POST /api/admin/distribution/system/list` | 体系列表 | | `POST /api/admin/distribution/system/toggle` | 启用/禁用 | | `POST /api/admin/distribution/relation/list` | 查看某体系的关系树 | | `POST /api/admin/distribution/relation/add` | 手动添加关系 | | `POST /api/admin/distribution/relation/remove` | 移除关系 | ### 3.8 [P1] 折扣管理 ```java @TableName("shop_discount_rules") public class DiscountRule { Long id; String name; String type; // PERCENT(打折) / FIXED(减额) / THRESHOLD(满减) Integer value; // PERCENT: 打折值(如10=9折); FIXED/THRESHOLD: 金额(分) Integer thresholdAmount; // 满减门槛(分), THRESHOLD时使用 Long categoryId; // 适用类目(null=全部) Long distributionSystemId;// 适用体系(null=全部) String productIds; // 适用商品(逗号分隔, null=全部) Date startTime; Date endTime; Integer maxUses; // 最大使用次数(0=不限) Integer usedCount; Boolean enabled; Date createdAt; Date updatedAt; } ``` **API(Web 管理端):** | 端点 | 说明 | |------|------| | `POST /api/admin/shop/discount/create` | 创建折扣规则 | | `POST /api/admin/shop/discount/update` | 更新 | | `POST /api/admin/shop/discount/list` | 规则列表 | | `POST /api/admin/shop/discount/toggle` | 启用/禁用 | **结算页集成:** 下单时 `DiscountService.calculateBestDiscount()` 自动计算可享最优折扣,返回优惠信息。 --- ## 4. 前端改造(小程序 cfc-frontend) ### 4.1 API 切换 所有 `config.danshop(...)` → `config.baseUrl(...)` / CFC 原生 API: | 文件 | 当前 | 改造后 | |------|------|--------| | `pages/shop/cart/cart.vue` | `danshop/cart/list` → `danshop/cart/remove` | `/api/cart/list` → `/api/cart/remove` | | `pages/shop/checkout/checkout.vue` | `danshop/address/list` → `danshop/order/create` | `/api/user/address/list` → `/api/product/order/create` | | `pages/shop/payment/payment.vue` | `danshop/payment/precreate` → `danshop/order/cancel` | `/api/product/order/pay` → `/api/product/order/cancel` | | `pages/shop/address/address.vue` | `danshop/address/list/delete/setDefault` | `/api/user/address/*` (已有 CFC API) | | `pages/shop/address-edit/address-edit.vue` | `danshop/address/get/save` + `danshop/region/*` | `/api/user/address/*` + `/api/region/*` | | `pages/shop/logistics/logistics.vue` | `danshop/logistics/query` | `/api/shop/logistics/query` | | `pages/shop/order-list/order-list.vue` | 可能 mock | `/api/product/order/list` | | `pages/shop/order-detail/order-detail.vue` | 可能 mock | `/api/product/order/detail` | | `pages/shop/detail/detail.vue` | — | 增加「加入购物车」按钮 | ### 4.2 新增/增强功能 - **detail.vue**:增加「加入购物车」按钮、数量选择 - **order-list.vue**:按状态 tab 分组(全部/待付款/已付款/已完成/已取消),待付款显示倒计时和「去支付」 - **cart.vue**:商品失效标记、直接从 CFC API 获取 - **checkout.vue**:优惠信息展示(后续对接折扣系统) --- ## 5. 实施顺序 | 阶段 | 模块 | 后端 | 前端 | Web | 依赖 | |:----:|------|:----:|:----:|:---:|:----:| | 1 | 购物车 CartItem + CartService + CartController | ✅ | ✅ | — | 无 | | 2 | PaymentService 重构(真实微信支付) | ✅ | — | — | 无 | | 3 | 结算 + 待支付(ProductOrder 增强) | ✅ | ✅ | — | 阶段1,2 | | 4 | 售后(人工审核) | ✅ | ✅ | ✅ | 阶段3 | | 5 | 商品类目(多维度+多种类) | ✅ | ✅ | ✅ | 无 | | 6 | 商品相册(多图支持) | ✅ | — | ✅ | 阶段5 | | 7 | 多销售体系 | ✅ | — | ✅ | 无 | | 8 | 折扣管理 | ✅ | — | ✅ | 阶段5 | --- ## 6. 数据库表变更总览 | 表名 | 操作 | 说明 | |------|------|------| | `products` | 增强 | 加 `category_id`, `distribution_system_id`, `images` JSON 格式 | | `product_orders` | 增强 | 加 `discount_amount`, `coupon_id`, `cancel_at`, `transaction_id`, 地址快照等 | | `cart_items` | 新建 | 购物车 | | `shop_categories` | 新建 | 商品类目(树形) | | `shop_discount_rules` | 新建 | 折扣规则 | | `distribution_systems` | 新建 | 销售体系 | | `distribution_relations` | 新建 | 销售关系 | | `after_sales_requests` | 新建 | 售后申请 | | `user_address` | 已有 | CFC 现有地址表(复用) | --- ## 7. 关键约定 - 所有新接口使用 `@PostMapping`,遵循 CFC 项目规范 - 新实体使用 `@TableName` + `@TableId(type = IdType.AUTO)` - 统一返回 `Result` 包装 - JWT 认证:`@RequestAttribute("userId")` 获取当前用户 - 金额统一使用 **分(Integer)** 存储 - 状态字段使用字符串(可读性) - 新 Controller/Service 名避免与其他包 Bean Name 冲突