功能概述 商品更新记录功能用于跟踪小象买菜系统中商品的变更历史,包括价格调整、库存变化、商品信息修改等操作。这有助于: -审计追踪 -问题排查 -数据分析 -业务决策支持 数据库设计 商品更新记录表(product_update_log) ```sql CR
功能概述
商品更新记录功能用于跟踪小象买菜系统中商品的变更历史,包括价格调整、库存变化、商品信息修改等操作。这有助于:
- 审计追踪
- 问题排查
- 数据分析
- 业务决策支持
数据库设计
商品更新记录表(product_update_log)
```sql
CREATE TABLE product_update_log (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 记录ID,
product_id BIGINT NOT NULL COMMENT 商品ID,
update_type VARCHAR(50) NOT NULL COMMENT 更新类型(price/stock/info),
old_value TEXT COMMENT 旧值(JSON格式),
new_value TEXT COMMENT 新值(JSON格式),
update_by BIGINT COMMENT 操作者ID,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 更新时间,
remark VARCHAR(255) COMMENT 备注,
INDEX idx_product_id (product_id),
INDEX idx_update_time (update_time)
) ENGINE=InnoDB COMMENT=商品更新记录表;
```
后端实现
1. 使用AOP实现自动记录
```java
@Aspect
@Component
public class ProductUpdateLogAspect {
@Autowired
private ProductUpdateLogService logService;
// 拦截商品服务中的更新方法
@AfterReturning(pointcut = "execution(* com.xiaoxiang.service.ProductService.update*(..))",
returning = "result")
public void afterProductUpdate(JoinPoint joinPoint, Object result) {
Object[] args = joinPoint.getArgs();
if (args == null || args.length < 1) return;
// 获取商品ID和更新类型(通过方法名判断)
String methodName = joinPoint.getSignature().getName();
String updateType = determineUpdateType(methodName);
// 获取商品旧数据(通常需要从数据库查询)
Long productId = (Long) args[0]; // 假设第一个参数是productId
Product oldProduct = productService.getProductById(productId);
// 创建更新记录
ProductUpdateLog log = new ProductUpdateLog();
log.setProductId(productId);
log.setUpdateType(updateType);
log.setOldValue(JSON.toJSONString(oldProduct));
log.setNewValue(JSON.toJSONString(args[1])); // 假设新数据在第二个参数
log.setUpdateBy(getCurrentUserId()); // 获取当前操作者ID
logService.save(log);
}
private String determineUpdateType(String methodName) {
if (methodName.contains("Price")) return "price";
if (methodName.contains("Stock")) return "stock";
return "info";
}
}
```
2. 手动记录方式
对于不适合AOP拦截的场景,可以手动记录:
```java
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductUpdateLogService logService;
@Override
public boolean updateProductPrice(Long productId, BigDecimal newPrice) {
// 获取旧价格
Product product = productRepository.findById(productId).orElseThrow();
BigDecimal oldPrice = product.getPrice();
// 更新价格
boolean success = productRepository.updatePrice(productId, newPrice);
if (success) {
// 记录更新日志
ProductUpdateLog log = new ProductUpdateLog();
log.setProductId(productId);
log.setUpdateType("price");
log.setOldValue(oldPrice.toString());
log.setNewValue(newPrice.toString());
log.setUpdateBy(getCurrentUserId());
logService.save(log);
}
return success;
}
}
```
前端实现
商品更新记录列表页面
```javascript
// React示例
function ProductUpdateHistory({ productId }) {
const [logs, setLogs] = useState([]);
useEffect(() => {
fetch(`/api/products/${productId}/update-logs`)
.then(res => res.json())
.then(data => setLogs(data));
}, [productId]);
return (
商品更新记录
更新时间 |
更新类型 |
变更内容 |
操作人 |
|---|
{logs.map(log => (
{formatDate(log.updateTime)} |
{log.updateType} |
|
{log.operatorName} |
))}
);
}
```
变更对比组件
```javascript
function ChangeDiff({ oldValue, newValue }) {
// 简单实现,实际项目中可以使用专门的diff库
if (typeof oldValue === object && typeof newValue === object) {
// 对象对比
return (
旧值: {JSON.stringify(oldValue)}
新值: {JSON.stringify(newValue)}
);
}
return (
旧值: {oldValue}
新值: {newValue}
);
}
```
API接口设计
获取商品更新记录
```
GET /api/products/{productId}/update-logs
参数:
- page: 页码 (可选)
- size: 每页数量 (可选)
- type: 更新类型 (可选)
响应:
{
"code": 200,
"data": {
"list": [
{
"id": 123,
"productId": 456,
"updateType": "price",
"oldValue": "19.99",
"newValue": "24.99",
"updateTime": "2023-05-15T10:30:00",
"operatorId": 789,
"operatorName": "张三"
}
// 更多记录...
],
"total": 15
}
}
```
高级功能扩展
1. 变更可视化:使用diff算法高亮显示变更部分
2. 批量导出:支持导出Excel或CSV格式的历史记录
3. 时间线视图:以时间轴形式展示商品变更历史
4. 变更回滚:支持基于历史记录回滚到特定版本
5. 变更通知:当关键字段变更时发送通知
性能优化建议
1. 对商品更新记录表进行分区(按时间或商品ID)
2. 实现异步日志记录,避免阻塞主业务流程
3. 定期归档旧数据到历史表
4. 使用缓存存储热门商品的更新记录
安全考虑
1. 记录操作人信息(ID、IP等)
2. 对敏感字段(如成本价)进行脱敏处理
3. 实现细粒度的权限控制,限制查看和导出权限
以上实现方案可根据小象买菜系统的具体需求和技术栈进行调整和扩展。