一、需求分析
随机抽检管理是小象买菜系统中的重要质量控制环节,主要功能包括:
1. 从订单或商品中随机抽取样本进行质量检查
2. 记录抽检结果并生成报告
3. 跟踪问题商品的处理流程
4. 提供抽检数据统计分析
二、系统设计
1. 数据库设计
```sql
-- 抽检任务表
CREATE TABLE inspection_tasks (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
task_name VARCHAR(100) NOT NULL,
task_type ENUM(order, product, supplier) NOT NULL,
sample_size INT NOT NULL,
status ENUM(pending, in_progress, completed, cancelled) DEFAULT pending,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
complete_time DATETIME,
creator_id BIGINT NOT NULL,
remark TEXT
);
-- 抽检样本表
CREATE TABLE inspection_samples (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
task_id BIGINT NOT NULL,
sample_type ENUM(order, product, batch) NOT NULL,
sample_id VARCHAR(50) NOT NULL, -- 订单号或商品ID
sample_name VARCHAR(100) NOT NULL,
is_selected BOOLEAN DEFAULT FALSE,
FOREIGN KEY (task_id) REFERENCES inspection_tasks(id)
);
-- 抽检结果表
CREATE TABLE inspection_results (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
task_id BIGINT NOT NULL,
sample_id BIGINT NOT NULL, -- 对应inspection_samples的ID
inspector_id BIGINT NOT NULL,
inspection_time DATETIME DEFAULT CURRENT_TIMESTAMP,
result ENUM(pass, fail, warning) NOT NULL,
problem_description TEXT,
handling_measures TEXT,
handling_status ENUM(pending, processing, completed) DEFAULT pending,
FOREIGN KEY (task_id) REFERENCES inspection_tasks(id),
FOREIGN KEY (sample_id) REFERENCES inspection_samples(id)
);
```
2. 随机抽检算法实现
```java
// Java示例:从订单列表中随机抽取样本
public List
randomSelectOrders(List allOrders, int sampleSize) {
if (sampleSize <= 0 || allOrders.isEmpty() || sampleSize > allOrders.size()) {
return Collections.emptyList();
}
// 打乱列表顺序
Collections.shuffle(allOrders);
// 返回前sampleSize个元素
return allOrders.subList(0, sampleSize);
}
// 更高效的随机抽样算法(适用于大数据量)
public List reservoirSampling(List allOrders, int sampleSize) {
List result = new ArrayList<>(sampleSize);
Random random = new Random();
for (int i = 0; i < allOrders.size(); i++) {
if (i < sampleSize) {
result.add(allOrders.get(i));
} else {
int j = random.nextInt(i + 1);
if (j < sampleSize) {
result.set(j, allOrders.get(i));
}
}
}
return result;
}
```
3. 核心功能模块
抽检任务创建
```java
public InspectionTask createInspectionTask(String taskName, String taskType,
int sampleSize, Long creatorId, String remark) {
InspectionTask task = new InspectionTask();
task.setTaskName(taskName);
task.setTaskType(taskType);
task.setSampleSize(sampleSize);
task.setStatus("pending");
task.setCreatorId(creatorId);
task.setRemark(remark);
// 保存到数据库
inspectionTaskRepository.save(task);
// 根据类型获取候选样本
List<?> candidates;
switch (taskType) {
case "order":
candidates = orderService.getRecentOrders();
break;
case "product":
candidates = productService.getActiveProducts();
break;
case "supplier":
candidates = supplierService.getActiveSuppliers();
break;
default:
throw new IllegalArgumentException("Invalid task type");
}
// 随机选择样本
List<?> selectedSamples = randomSelect(candidates, sampleSize);
// 保存样本到数据库
for (Object sample : selectedSamples) {
InspectionSample inspectionSample = new InspectionSample();
inspectionSample.setTaskId(task.getId());
// 设置其他样本属性...
inspectionSampleRepository.save(inspectionSample);
}
return task;
}
```
抽检结果记录
```java
public InspectionResult recordInspectionResult(Long taskId, Long sampleId,
Long inspectorId, String result, String problemDesc, String handlingMeasures) {
InspectionSample sample = inspectionSampleRepository.findById(sampleId)
.orElseThrow(() -> new RuntimeException("Sample not found"));
InspectionResult inspectionResult = new InspectionResult();
inspectionResult.setTaskId(taskId);
inspectionResult.setSampleId(sampleId);
inspectionResult.setInspectorId(inspectorId);
inspectionResult.setResult(result);
inspectionResult.setProblemDescription(problemDesc);
inspectionResult.setHandlingMeasures(handlingMeasures);
// 更新任务状态
Optional taskOpt = inspectionTaskRepository.findById(taskId);
taskOpt.ifPresent(task -> {
if (task.getStatus().equals("pending") || task.getStatus().equals("in_progress")) {
// 检查是否所有样本都已抽检
long completedCount = inspectionResultRepository.countByTaskIdAndResultIsNotNull(taskId);
long totalSamples = inspectionSampleRepository.countByTaskId(taskId);
if (completedCount >= totalSamples) {
task.setStatus("completed");
} else {
task.setStatus("in_progress");
}
inspectionTaskRepository.save(task);
}
});
return inspectionResultRepository.save(inspectionResult);
}
```
三、前端实现要点
1. 抽检任务创建页面:
- 表单包含任务名称、类型、样本数量等字段
- 类型选择影响后续样本来源
2. 抽检任务列表页面:
- 展示所有抽检任务及其状态
- 提供筛选和排序功能
- 支持按状态、时间范围等条件查询
3. 抽检执行页面:
- 显示当前任务的样本列表
- 提供抽检结果录入表单
- 支持上传检测报告或图片
4. 统计分析页面:
- 抽检合格率趋势图
- 问题商品分类统计
- 供应商质量排名
四、高级功能实现
1. 智能抽检策略
```java
public class SmartSamplingStrategy {
// 基于风险的抽检策略
public List riskBasedSampling(List allProducts) {
// 1. 获取各商品的历史问题记录
Map productRiskScores = getProductRiskScores(allProducts);
// 2. 按风险评分排序
allProducts.sort((p1, p2) -> {
int score1 = productRiskScores.getOrDefault(p1.getId(), 0);
int score2 = productRiskScores.getOrDefault(p2.getId(), 0);
return Integer.compare(score2, score1); // 降序
});
// 3. 高风险商品优先抽检
// 这里可以应用更复杂的算法,如根据风险分数分配抽检概率
return allProducts.stream()
.filter(p -> Math.random() < getSamplingProbability(p, productRiskScores))
.limit(calculateSampleSize(allProducts.size()))
.collect(Collectors.toList());
}
private double getSamplingProbability(Product product, Map riskScores) {
int riskScore = riskScores.getOrDefault(product.getId(), 0);
// 风险越高,抽检概率越大
return 0.1 + (riskScore * 0.05); // 示例公式
}
private int calculateSampleSize(int populationSize) {
// 根据总体大小计算合适的样本量
// 这里可以使用统计公式或预设规则
return Math.min(100, Math.max(5, (int)(populationSize * 0.1)));
}
}
```
2. 抽检结果预警
```java
public class InspectionAlertService {
@Autowired
private InspectionResultRepository inspectionResultRepository;
@Autowired
private AlertService alertService;
// 检查是否需要触发预警
public void checkForAlerts() {
// 1. 查询最近24小时内的抽检结果
LocalDateTime startTime = LocalDateTime.now().minusHours(24);
List recentResults = inspectionResultRepository
.findByInspectionTimeAfter(startTime);
// 2. 统计各供应商的不合格率
Map supplierFailureRates = calculateSupplierFailureRates(recentResults);
// 3. 触发预警条件
supplierFailureRates.forEach((supplierId, failureRate) -> {
if (failureRate > 0.1) { // 不合格率超过10%触发预警
Supplier supplier = supplierService.getSupplierById(supplierId);
String message = String.format(
"预警:供应商%s的商品抽检不合格率达到%.2f%%",
supplier.getName(), failureRate * 100);
alertService.sendAlert(message, AlertLevel.HIGH);
}
});
}
private Map calculateSupplierFailureRates(List results) {
Map totalInspections = new HashMap<>();
Map failedInspections = new HashMap<>();
for (InspectionResult result : results) {
Long supplierId = getSupplierIdFromSample(result.getSampleId());
totalInspections.merge(supplierId, 1, Integer::sum);
if ("fail".equals(result.getResult())) {
failedInspections.merge(supplierId, 1, Integer::sum);
}
}
Map failureRates = new HashMap<>();
totalInspections.forEach((supplierId, total) -> {
int failed = failedInspections.getOrDefault(supplierId, 0);
failureRates.put(supplierId, (double)failed / total);
});
return failureRates;
}
}
```
五、系统集成与部署
1. 与现有系统集成:
- 订单系统:获取待抽检订单
- 商品系统:获取商品信息和库存状态
- 供应商系统:获取供应商信息和历史记录
- 通知系统:发送抽检任务提醒和结果通知
2. 部署方案:
- 微服务架构:将抽检管理作为独立服务部署
- 定时任务:设置每日/每周自动抽检任务
- 监控告警:对抽检系统本身进行监控
3. 权限控制:
- 抽检任务创建:质量管理部门
- 抽检执行:质检人员
- 结果查看:管理层和相关供应商
- 系统配置:系统管理员
六、测试与优化
1. 测试用例:
- 正常流程测试:创建任务→执行抽检→记录结果→生成报告
- 边界条件测试:样本量为0或大于总数的情况
- 异常情况测试:网络中断、数据不一致等
2. 性能优化:
- 大数据量抽检时使用分页查询
- 异步处理抽检结果通知
- 缓存常用查询结果
3. 持续改进:
- 收集用户反馈优化界面
- 根据抽检数据调整抽检策略
- 定期审查抽检规则的有效性
通过以上设计和实现,小象买菜系统的随机抽检管理模块将能够有效提升商品质量控制水平,确保食品安全和客户满意度。