一、系统设计目标 1.实现商品信息的全生命周期管理 2.记录商品每次变更的详细信息 3.支持商品版本回溯和对比 4.提供商品变更的审计追踪功能 5.确保数据一致性和可追溯性 二、核心功能模块 1.商品基础信息管理 -商品ID、名称、分类、条码等基础信息 -商品状
一、系统设计目标
1. 实现商品信息的全生命周期管理
2. 记录商品每次变更的详细信息
3. 支持商品版本回溯和对比
4. 提供商品变更的审计追踪功能
5. 确保数据一致性和可追溯性
二、核心功能模块
1. 商品基础信息管理
- 商品ID、名称、分类、条码等基础信息
- 商品状态管理(上架/下架/预售等)
- 商品生命周期管理
2. 商品迭代记录模块
- 变更类型:新增、修改、删除、状态变更等
- 变更字段:记录具体修改的字段和旧值/新值
- 变更时间:精确到秒的变更时间戳
- 操作人:记录执行变更的操作员或系统
- 变更原因:可选的变更说明或备注
3. 版本管理模块
- 自动生成商品版本号(如V1.0, V1.1等)
- 支持版本回滚功能
- 版本对比工具(可比较两个版本的差异)
4. 审批流程模块
- 商品变更审批工作流
- 多级审批机制(根据变更类型)
- 审批状态跟踪
三、数据库设计
商品主表(product_main)
```sql
CREATE TABLE product_main (
product_id VARCHAR(32) PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
category_id VARCHAR(32) NOT NULL,
barcode VARCHAR(50),
status TINYINT DEFAULT 1 COMMENT 1-上架 2-下架 3-预售,
create_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
current_version VARCHAR(20) NOT NULL
);
```
商品迭代记录表(product_history)
```sql
CREATE TABLE product_history (
history_id BIGINT AUTO_INCREMENT PRIMARY KEY,
product_id VARCHAR(32) NOT NULL,
version VARCHAR(20) NOT NULL,
change_type TINYINT NOT NULL COMMENT 1-新增 2-修改 3-删除 4-状态变更,
change_fields JSON NOT NULL COMMENT 变更字段JSON {field: {old_value, new_value}},
operator VARCHAR(50) NOT NULL COMMENT 操作人,
operator_type TINYINT COMMENT 1-人工 2-系统,
change_reason VARCHAR(500),
change_time DATETIME NOT NULL,
approval_status TINYINT DEFAULT 0 COMMENT 0-待审批 1-已通过 2-已拒绝,
approval_time DATETIME,
approval_operator VARCHAR(50),
FOREIGN KEY (product_id) REFERENCES product_main(product_id)
);
```
四、关键实现逻辑
1. 商品变更拦截器
```java
@Aspect
@Component
public class ProductChangeAspect {
@Autowired
private ProductHistoryService historyService;
@AfterReturning(pointcut = "execution(* com.dingdong.service.ProductService.update*(..)) && args(productDTO)", returning = "result")
public void afterProductUpdate(JoinPoint joinPoint, ProductDTO productDTO, Boolean result) {
if (result) {
// 获取变更前后对比数据
Map
changes = compareChanges(productDTO); // 记录变更历史 ProductHistory history = new ProductHistory(); history.setProductId(productDTO.getProductId()); history.setChangeType(ChangeType.UPDATE.getCode()); history.setChangeFields(changes); history.setOperator(getCurrentOperator()); // 其他字段设置... historyService.save(history); } } private Map compareChanges(ProductDTO newProduct) { // 从数据库获取旧数据 Product oldProduct = productRepository.findById(newProduct.getProductId()); Map changes = new HashMap<>(); // 比较每个字段的变化 if (!Objects.equals(oldProduct.getName(), newProduct.getName())) { changes.put("name", new FieldChange(oldProduct.getName(), newProduct.getName())); } // 其他字段比较... return changes; } } ``` 2. 版本生成策略 ```java public class VersionGenerator { public static String generateNextVersion(String currentVersion) { if (currentVersion == null || currentVersion.isEmpty()) { return "V1.0"; } try { String[] parts = currentVersion.substring(1).split("\\."); int major = Integer.parseInt(parts[0]); int minor = parts.length > 1 ? Integer.parseInt(parts[1]) : 0; // 简单策略:每次修改minor版本+1 return String.format("V%d.%d", major, minor + 1); } catch (Exception e) { return "V1.0"; // 默认版本 } } } ``` 3. 版本回滚实现 ```java @Service public class ProductRollbackService { @Autowired private ProductRepository productRepository; @Autowired private ProductHistoryRepository historyRepository; @Transactional public boolean rollbackToVersion(String productId, String targetVersion) { // 1. 获取目标版本的历史记录 ProductHistory targetHistory = historyRepository.findByProductIdAndVersion(productId, targetVersion) .orElseThrow(() -> new RuntimeException("目标版本不存在")); // 2. 验证审批状态 if (targetHistory.getApprovalStatus() != ApprovalStatus.APPROVED.getCode()) { throw new RuntimeException("目标版本未通过审批,不能回滚"); } // 3. 获取当前商品数据 Product currentProduct = productRepository.findById(productId); // 4. 创建新的历史记录(记录回滚操作) ProductHistory rollbackHistory = new ProductHistory(); rollbackHistory.setProductId(productId); rollbackHistory.setChangeType(ChangeType.ROLLBACK.getCode()); // 设置回滚相关字段... // 5. 更新商品数据(根据目标版本还原) Map changes = new ObjectMapper().readValue( targetHistory.getChangeFields().toString(), Map.class); // 还原字段(示例) if (changes.containsKey("name")) { Map nameChange = (Map) changes.get("name"); currentProduct.setName(nameChange.get("old_value")); // 实际应使用目标版本的值 } // 其他字段还原... productRepository.save(currentProduct); historyRepository.save(rollbackHistory); return true; } } ``` 五、前端展示方案 1. 商品变更历史列表 ```javascript // 示例React组件 function ProductHistoryList({ productId }) { const [histories, setHistories] = useState([]); useEffect(() => { fetch(`/api/products/${productId}/histories`) .then(res => res.json()) .then(data => setHistories(data)); }, [productId]); return ( 商品变更历史 版本 变更类型 操作人 变更时间 操作 {histories.map(history => ( {history.version} {getChangeTypeLabel(history.changeType)} {history.operator} {formatDate(history.changeTime)} viewDetails(history)}>查看详情 ))}
); } ``` 2. 变更详情对比视图 ```javascript function HistoryDetailModal({ history, onClose }) { const [changes, setChanges] = useState([]); useEffect(() => { const changeEntries = Object.entries(history.changeFields || {}); setChanges(changeEntries.map(([field, value]) => ({ field, oldValue: value.old_value, newValue: value.new_value }))); }, [history]); return ( 变更详情 - {history.version} 字段 旧值 新值 {changes.map((change, index) => ( {change.field} {change.oldValue || -} {change.newValue || -} ))}
关闭 ); } ``` 六、扩展功能建议 1. 变更通知系统:当重要商品信息变更时,自动通知相关人员(如采购、运营) 2. 变更影响分析:分析商品变更对库存、订单、促销等活动的影响 3. 数据导出功能:支持导出商品变更历史为Excel或PDF格式 4. 变更统计报表:生成商品变更频率、变更类型分布等统计报表 5. 与SCM系统集成:将商品变更同步到供应链管理系统 七、实施注意事项 1. 性能考虑:对于高频变更的商品,考虑异步记录历史或批量写入 2. 数据安全:确保历史数据不可篡改,可采用区块链技术增强可信度 3. 存储优化:对于大量历史数据,考虑分区表或冷热数据分离策略 4. 权限控制:不同角色对历史数据的查看和操作权限应严格控制 此方案可根据叮咚买菜实际业务需求和技术栈进行调整和扩展,核心思想是通过完善的变更记录机制实现商品信息的可追溯性和审计能力。