功能概述 商品更新记录功能用于跟踪小象买菜系统中商品信息的变更历史,包括价格调整、库存变化、商品上下架等操作,便于管理员审计和问题追溯。 数据库设计 商品更新记录表(product_update_log) ```sql CREATETABLE`product_upd
功能概述
商品更新记录功能用于跟踪小象买菜系统中商品信息的变更历史,包括价格调整、库存变化、商品上下架等操作,便于管理员审计和问题追溯。
数据库设计
商品更新记录表(product_update_log)
```sql
CREATE TABLE `product_update_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID,
`product_id` bigint(20) NOT NULL COMMENT 商品ID,
`update_type` varchar(20) NOT NULL COMMENT 更新类型(price/stock/status/info),
`old_value` text COMMENT 旧值(JSON格式),
`new_value` text NOT NULL COMMENT 新值(JSON格式),
`operator_id` bigint(20) DEFAULT NULL COMMENT 操作人ID,
`operator_name` varchar(50) DEFAULT NULL COMMENT 操作人姓名,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 更新时间,
`ip_address` varchar(50) DEFAULT NULL COMMENT 操作IP,
`remark` varchar(255) DEFAULT NULL COMMENT 备注,
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`),
KEY `idx_update_time` (`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=商品更新记录表;
```
后端实现
1. 创建更新记录实体类
```java
@Data
public class ProductUpdateLog {
private Long id;
private Long productId;
private String updateType; // price/stock/status/info
private String oldValue; // JSON格式
private String newValue; // JSON格式
private Long operatorId;
private String operatorName;
private LocalDateTime updateTime;
private String ipAddress;
private String remark;
}
```
2. 创建更新记录Mapper接口
```java
@Mapper
public interface ProductUpdateLogMapper {
int insert(ProductUpdateLog log);
List
selectByProductId(@Param("productId") Long productId);
List selectByTimeRange(@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
}
```
3. 创建更新记录服务类
```java
@Service
public class ProductUpdateLogService {
@Autowired
private ProductUpdateLogMapper logMapper;
/
* 记录商品更新
*/
public void recordUpdate(Long productId, String updateType,
String oldValue, String newValue,
Long operatorId, String operatorName,
String ipAddress, String remark) {
ProductUpdateLog log = new ProductUpdateLog();
log.setProductId(productId);
log.setUpdateType(updateType);
log.setOldValue(oldValue);
log.setNewValue(newValue);
log.setOperatorId(operatorId);
log.setOperatorName(operatorName);
log.setIpAddress(ipAddress);
log.setRemark(remark);
logMapper.insert(log);
}
/
* 查询商品更新记录
*/
public List getUpdateLogs(Long productId) {
return logMapper.selectByProductId(productId);
}
/
* 查询时间范围内的更新记录
*/
public List getUpdateLogsByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
return logMapper.selectByTimeRange(startTime, endTime);
}
}
```
4. 在商品服务中集成更新记录
```java
@Service
public class ProductService {
@Autowired
private ProductUpdateLogService logService;
// 更新商品价格示例
@Transactional
public boolean updatePrice(Long productId, BigDecimal newPrice,
Long operatorId, String operatorName, String ip) {
// 1. 获取旧价格
Product product = productMapper.selectById(productId);
BigDecimal oldPrice = product.getPrice();
// 2. 更新价格
product.setPrice(newPrice);
int result = productMapper.updateById(product);
// 3. 记录更新日志
if (result > 0) {
JSONObject oldValue = new JSONObject();
oldValue.put("price", oldPrice);
JSONObject newValue = new JSONObject();
newValue.put("price", newPrice);
logService.recordUpdate(productId, "price",
oldValue.toJSONString(),
newValue.toJSONString(),
operatorId, operatorName, ip, "价格调整");
}
return result > 0;
}
// 其他更新操作类似...
}
```
前端实现
1. 商品更新记录列表页面
```vue
商品更新记录
旧价格: {{ getPriceFromJson(scope.row.oldValue) }}
新价格: {{ getPriceFromJson(scope.row.newValue) }}
旧库存: {{ getStockFromJson(scope.row.oldValue) }}
新库存: {{ getStockFromJson(scope.row.newValue) }}
变更详情: {{ scope.row.newValue }}
<script>
export default {
data() {
return {
updateLogs: []
}
},
created() {
this.fetchUpdateLogs();
},
methods: {
fetchUpdateLogs() {
const productId = this.$route.params.productId;
this.$api.get(`/product/update-logs/${productId}`).then(response => {
this.updateLogs = response.data;
});
},
getPriceFromJson(jsonStr) {
try {
const obj = JSON.parse(jsonStr);
return obj.price;
} catch (e) {
return jsonStr;
}
},
getStockFromJson(jsonStr) {
try {
const obj = JSON.parse(jsonStr);
return obj.stock;
} catch (e) {
return jsonStr;
}
}
}
}
```
2. 商品详情页添加更新记录入口
```vue
操作记录
查看更新记录
<script>
export default {
methods: {
viewUpdateLogs() {
this.$router.push({
name: ProductUpdateLogs,
params: { productId: this.product.id }
});
}
}
}
```
高级功能扩展
1. 更新记录对比视图
可以开发一个对比视图,直观展示变更前后的差异:
```vue
变更对比
变更前
{{ formattedOldValue }} 变更后
{{ formattedNewValue }}
<script>
export default {
props: {
oldValue: String,
newValue: String
},
computed: {
formattedOldValue() {
return this.formatJson(this.oldValue);
},
formattedNewValue() {
return this.formatJson(this.newValue);
}
},
methods: {
formatJson(jsonStr) {
try {
const obj = JSON.parse(jsonStr);
return JSON.stringify(obj, null, 2);
} catch (e) {
return jsonStr;
}
}
}
}
<style scoped>
.diff-container {
display: flex;
gap: 20px;
}
.diff-section {
flex: 1;
border: 1px solid eee;
padding: 10px;
border-radius: 4px;
}
pre {
background: f5f5f5;
padding: 10px;
border-radius: 4px;
overflow-x: auto;
}
```
2. 更新记录导出功能
```java
@RestController
@RequestMapping("/product/update-logs")
public class ProductUpdateLogController {
@Autowired
private ProductUpdateLogService logService;
@GetMapping("/export/{productId}")
public void exportUpdateLogs(@PathVariable Long productId, HttpServletResponse response) {
List logs = logService.getUpdateLogs(productId);
// 设置响应头
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("商品更新记录", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8" + fileName + ".xlsx");
// 创建Excel工作簿
try (XSSFWorkbook workbook = new XSSFWorkbook()) {
XSSFSheet sheet = workbook.createSheet("更新记录");
// 创建表头
Row headerRow = sheet.createRow(0);
String[] headers = {"更新时间", "更新类型", "操作人", "操作IP", "变更前", "变更后", "备注"};
for (int i = 0; i < headers.length; i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(headers[i]);
}
// 填充数据
for (int i = 0; i < logs.size(); i++) {
ProductUpdateLog log = logs.get(i);
Row row = sheet.createRow(i + 1);
row.createCell(0).setCellValue(log.getUpdateTime().toString());
row.createCell(1).setCellValue(log.getUpdateType());
row.createCell(2).setCellValue(log.getOperatorName());
row.createCell(3).setCellValue(log.getIpAddress());
row.createCell(4).setCellValue(log.getOldValue());
row.createCell(5).setCellValue(log.getNewValue());
row.createCell(6).setCellValue(log.getRemark());
}
// 写入响应流
try (OutputStream out = response.getOutputStream()) {
workbook.write(out);
}
} catch (IOException e) {
throw new RuntimeException("导出失败", e);
}
}
}
```
注意事项
1. 性能考虑:对于高频更新的商品,更新记录可能会快速增长,考虑定期归档或分表存储
2. 数据安全:敏感信息如成本价等不应记录在更新日志中
3. 存储优化:对于频繁变更的字段,可以考虑只记录变更部分而非整个对象
4. 审计要求:根据业务需求,可能需要保留更新记录一定年限
5. 并发控制:在高并发场景下,确保更新记录的原子性
通过以上实现,小象买菜系统可以完整记录商品信息的变更历史,为运营分析和问题排查提供有力支持。