package com.kaidi.oa.seed; import com.kaidi.oa.domain.LabElnAccessLog; import com.kaidi.oa.repository.LabElnAccessLogRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import java.time.Instant; import java.time.temporal.ChronoUnit; /** * 实验室 ELN / 报告读取访问日志演示数据(质量管理与合规 §6 审计追踪)。 * * 覆盖全部动作类型(登录/ELN查看/ELN导出/报告查看/报告导出/原始数据查看/原始数据导出/审批查看), * 涉及多名实验人员、多时间段,让 eln-audit.vue 活体展示完整审计轨迹。 * * @Order(205) 在所有主数据 Seeder 之后、幂等(count > 0 则跳过)。 */ @DemoSeed @Order(205) public class LabElnAccessLogSeeder implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(LabElnAccessLogSeeder.class); private final LabElnAccessLogRepository repo; public LabElnAccessLogSeeder(LabElnAccessLogRepository repo) { this.repo = repo; } @Override public void run(String... args) { if (repo.count() > 0) { return; } log.info("Seeding LabElnAccessLog demo data..."); Instant base = Instant.now().minus(7, ChronoUnit.DAYS); // Day -7:登录审计 seed(null, null, "登录", "李化验", "质量检测部", "192.168.1.45", "用户登录实验室系统", base); seed(null, null, "登录", "王化验", "质量检测部", "192.168.1.47", "用户登录实验室系统", base.plus(10, ChronoUnit.MINUTES)); seed(null, null, "登录", "陈检测", "质量检测部", "192.168.1.52", "用户登录实验室系统", base.plus(25, ChronoUnit.MINUTES)); // Day -7:ELN 查看 seed(1L, "ELN-001 COD分析实验记录", "ELN查看", "李化验", "质量检测部", "192.168.1.45", "查看 ELN-001 COD分析实验记录", base.plus(30, ChronoUnit.MINUTES)); seed(2L, "ELN-002 氨氮检测实验记录", "ELN查看", "王化验", "质量检测部", "192.168.1.47", "查看 ELN-002 氨氮检测实验记录", base.plus(35, ChronoUnit.MINUTES)); // Day -6:ELN 导出 seed(1L, "ELN-001 COD分析实验记录", "ELN导出", "李化验", "质量检测部", "192.168.1.45", "导出 ELN-001 PDF,用于报告附件", base.plus(1, ChronoUnit.DAYS)); seed(3L, "ELN-003 总磷TP检测记录", "ELN导出", "陈检测", "质量检测部", "192.168.1.52", "导出 ELN-003 Excel,用于数据汇总", base.plus(1, ChronoUnit.DAYS).plus(2, ChronoUnit.HOURS)); // Day -5:报告查看 seed(null, "检测报告 JC-2026-05-001", "报告查看", "张主任", "质量管理部", "192.168.1.60", "查看检测报告 JC-2026-05-001(COD/氨氮汇总)", base.plus(2, ChronoUnit.DAYS)); seed(null, "检测报告 JC-2026-05-002", "报告查看", "王化验", "质量检测部", "192.168.1.47", "查看检测报告 JC-2026-05-002(总磷/总氮)", base.plus(2, ChronoUnit.DAYS).plus(1, ChronoUnit.HOURS)); // Day -4:报告导出 seed(null, "检测报告 JC-2026-05-001", "报告导出", "张主任", "质量管理部", "192.168.1.60", "导出报告 JC-2026-05-001 PDF(送客户)", base.plus(3, ChronoUnit.DAYS)); seed(null, "检测报告 JC-2026-05-003", "报告导出", "李化验", "质量检测部", "192.168.1.45", "导出报告 JC-2026-05-003 PDF(归档)", base.plus(3, ChronoUnit.DAYS).plus(3, ChronoUnit.HOURS)); // Day -3:原始数据查看 seed(2L, "ELN-002 氨氮检测实验记录", "原始数据查看", "陈检测", "质量检测部", "192.168.1.52", "查看 ELN-002 原始色谱数据", base.plus(4, ChronoUnit.DAYS)); seed(4L, "ELN-004 pH值检测记录", "原始数据查看", "李化验", "质量检测部", "192.168.1.45", "查看 ELN-004 原始pH计读数", base.plus(4, ChronoUnit.DAYS).plus(2, ChronoUnit.HOURS)); // Day -2:原始数据导出 seed(2L, "ELN-002 氨氮检测实验记录", "原始数据导出", "陈检测", "质量检测部", "192.168.1.52", "导出 ELN-002 原始数据CSV(归档备查)", base.plus(5, ChronoUnit.DAYS)); seed(5L, "ELN-005 悬浮物SS检测记录", "原始数据导出", "王化验", "质量检测部", "192.168.1.47", "导出 ELN-005 原始数据Excel(OOS偏差调查)", base.plus(5, ChronoUnit.DAYS).plus(1, ChronoUnit.HOURS)); // Day -1:审批查看 seed(null, "审批流 RPT-APR-2026-06", "审批查看", "张主任", "质量管理部", "192.168.1.60", "查看报告审批进度(检测人→复核人→批准人)", base.plus(6, ChronoUnit.DAYS)); seed(null, "审批流 RPT-APR-2026-07", "审批查看", "李主任", "质量管理部", "192.168.1.62", "查看报告审批进度(已批准待签发)", base.plus(6, ChronoUnit.DAYS).plus(2, ChronoUnit.HOURS)); // 今日:各类操作 seed(null, null, "登录", "李化验", "质量检测部", "192.168.1.45", "用户登录实验室系统", Instant.now().minus(2, ChronoUnit.HOURS)); seed(6L, "ELN-006 总氮TN检测记录", "ELN查看", "李化验", "质量检测部", "192.168.1.45", "查看 ELN-006 总氮TN检测记录", Instant.now().minus(90, ChronoUnit.MINUTES)); seed(6L, "ELN-006 总氮TN检测记录", "ELN导出", "李化验", "质量检测部", "192.168.1.45", "导出 ELN-006 PDF附于检测报告", Instant.now().minus(60, ChronoUnit.MINUTES)); log.info("LabElnAccessLog demo data seeded: {} records.", repo.count()); } private void seed(Long elnId, String elnRef, String action, String operator, String dept, String ip, String detail, Instant occurredInstant) { LabElnAccessLog r = new LabElnAccessLog(); r.setElnId(elnId); r.setElnRef(elnRef); r.setAction(action); r.setOperator(operator); r.setOperatorDept(dept); r.setIp(ip); r.setDetail(detail); // 格式化操作时间字符串 java.time.LocalDateTime ldt = java.time.LocalDateTime.ofInstant(occurredInstant, java.time.ZoneId.systemDefault()); r.setOccurredAt(ldt.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); r.setCreatedAt(occurredInstant); repo.save(r); } }