hsy
2026-08-28 36fa58c0de255ad56f50a565cbe7a5d93604dd88
feat(quality): 新增质量管理-报告管理模块

- 数据库:新增 `qms_inspection_report` 质检报告表及配套 SQL 脚本。
- 后端:新增报告管理的实体类、Mapper、Service 及 Controller,实现列表查询、新增、修改与状态注销(软删除)接口,查询按到期时间正序排列。
- 前端:在报告分析下新增“报告管理”页面 (`inspectionReport`)。
- 采用 PIMTable 规范构建列表页,新增“到期前30天预警”的数据标红高亮功能。
- 新增表单弹窗,实现填写“报告日期”和“有效期(月)”后自动通过 dayjs 推算“到期时间”的联动逻辑。
- 接入标准多文件上传组件,规范化核心资产报告的管理流程。
已添加7个文件
已修改1个文件
266 ■■■■■ 文件已修改
sql/qms_inspection_report.sql 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/quality/report/controller/InspectionReportController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/quality/report/domain/InspectionReport.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/quality/report/mapper/InspectionReportMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/quality/report/service/IInspectionReportService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/quality/report/service/impl/InspectionReportServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/InspectionReportMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/qms_inspection_report.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
CREATE TABLE `qms_inspection_report` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `product_name` varchar(100) NOT NULL COMMENT '产品名称',
  `product_model` varchar(100) DEFAULT NULL COMMENT '产品型号',
  `report_no` varchar(100) NOT NULL COMMENT '报告编号',
  `report_date` date NOT NULL COMMENT '报告日期',
  `validity_period` int(11) NOT NULL COMMENT '有效期(月)',
  `expiration_time` date NOT NULL COMMENT '到期时间',
  `testing_agency` varchar(100) DEFAULT NULL COMMENT '检测单位',
  `report_type` varchar(50) DEFAULT NULL COMMENT '报告类型(字典项)',
  `attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件上传(多URL逗号分隔)',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  `status` varchar(20) DEFAULT 'NORMAL' COMMENT '状态(NORMAL:正常, CANCELLED:注销)',
  `create_user` bigint(20) DEFAULT NULL COMMENT '创建人ID',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_user` bigint(20) DEFAULT NULL COMMENT '更新人ID',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `tenant_id` bigint(20) DEFAULT NULL COMMENT '租户ID',
  `dept_id` bigint(20) DEFAULT NULL COMMENT '部门ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='检测报告管理表';
src/main/java/com/ruoyi/ai/config/EmbeddingStoreConfig.java
@@ -45,7 +45,7 @@
                .createIndex(PineconeServerlessIndexConfig.builder()
                        .cloud("AWS")
                        .region("us-east-1")
                        .dimension(embeddingModel.dimension()) // ä¸´æ—¶å†™æ­»ç»´åº¦(qwen一般是1536),避免项目启动时调用API导致欠费报错
                        .dimension(1536) // ä¸´æ—¶å†™æ­»ç»´åº¦(qwen一般是1536),避免项目启动时调用API导致欠费报错
                        .build())
                .build();
    }
src/main/java/com/ruoyi/project/quality/report/controller/InspectionReportController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
package com.ruoyi.project.quality.report.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.quality.report.domain.InspectionReport;
import com.ruoyi.project.quality.report.service.IInspectionReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
/**
 * æ£€æµ‹æŠ¥å‘Š Controller
 */
@RestController
@RequestMapping("/quality/inspectionReport")
public class InspectionReportController {
    @Autowired
    private IInspectionReportService inspectionReportService;
    /**
     * æŸ¥è¯¢æ£€æµ‹æŠ¥å‘Šåˆ—表
     */
    @GetMapping("/listPage")
    public AjaxResult listPage(Page<InspectionReport> page, InspectionReport report) {
        IPage<InspectionReport> iPage = inspectionReportService.listPage(page, report);
        return AjaxResult.success(iPage);
    }
    /**
     * èŽ·å–æ£€æµ‹æŠ¥å‘Šè¯¦ç»†ä¿¡æ¯
     */
    @GetMapping("/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(inspectionReportService.getById(id));
    }
    /**
     * æ–°å¢žæ£€æµ‹æŠ¥å‘Š
     */
    @PostMapping
    public AjaxResult add(@RequestBody InspectionReport report) {
        // é»˜è®¤çŠ¶æ€ä¸ºæ­£å¸¸
        if (report.getStatus() == null) {
            report.setStatus("NORMAL");
        }
        return AjaxResult.success(inspectionReportService.save(report));
    }
    /**
     * ä¿®æ”¹æ£€æµ‹æŠ¥å‘Š
     */
    @PutMapping
    public AjaxResult edit(@RequestBody InspectionReport report) {
        return AjaxResult.success(inspectionReportService.updateById(report));
    }
    /**
     * æ³¨é”€(软删除)检测报告
     */
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        for (Long id : ids) {
            InspectionReport report = new InspectionReport();
            report.setId(id);
            report.setStatus("CANCELLED");
            inspectionReportService.updateById(report);
        }
        return AjaxResult.success();
    }
}
src/main/java/com/ruoyi/project/quality/report/domain/InspectionReport.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.ruoyi.project.quality.report.domain;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * æ£€æµ‹æŠ¥å‘Šå¯¹è±¡ qms_inspection_report
 */
@Data
@TableName("qms_inspection_report")
public class InspectionReport implements Serializable {
    private static final long serialVersionUID = 1L;
    /** ä¸»é”®ID */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /** äº§å“åç§° */
    private String productName;
    /** äº§å“åž‹å· */
    private String productModel;
    /** æŠ¥å‘Šç¼–号 */
    private String reportNo;
    /** æŠ¥å‘Šæ—¥æœŸ */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date reportDate;
    /** æœ‰æ•ˆæœŸ(月) */
    private Integer validityPeriod;
    /** åˆ°æœŸæ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date expirationTime;
    /** æ£€æµ‹å•位 */
    private String testingAgency;
    /** æŠ¥å‘Šç±»åž‹ */
    private String reportType;
    /** é™„件上传(多URL逗号分隔) */
    private String attachmentUrls;
    /** å¤‡æ³¨ */
    private String remark;
    /** çŠ¶æ€(NORMAL:正常, CANCELLED:注销) */
    private String status;
    /** åˆ›å»ºäºº */
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    /** åˆ›å»ºæ—¶é—´ */
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** æ›´æ–°äºº */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
    /** æ›´æ–°æ—¶é—´ */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /** ç§Ÿæˆ·ID */
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    /** éƒ¨é—¨ID */
    @TableField(fill = FieldFill.INSERT)
    private Long deptId;
}
src/main/java/com/ruoyi/project/quality/report/mapper/InspectionReportMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.ruoyi.project.quality.report.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.project.quality.report.domain.InspectionReport;
import org.apache.ibatis.annotations.Mapper;
/**
 * æ£€æµ‹æŠ¥å‘ŠMapper接口
 */
@Mapper
public interface InspectionReportMapper extends BaseMapper<InspectionReport> {
}
src/main/java/com/ruoyi/project/quality/report/service/IInspectionReportService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.ruoyi.project.quality.report.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.project.quality.report.domain.InspectionReport;
/**
 * æ£€æµ‹æŠ¥å‘ŠService接口
 */
public interface IInspectionReportService extends IService<InspectionReport> {
    /**
     * åˆ†é¡µæŸ¥è¯¢
     */
    IPage<InspectionReport> listPage(Page<InspectionReport> page, InspectionReport report);
}
src/main/java/com/ruoyi/project/quality/report/service/impl/InspectionReportServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.project.quality.report.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.project.quality.report.domain.InspectionReport;
import com.ruoyi.project.quality.report.mapper.InspectionReportMapper;
import com.ruoyi.project.quality.report.service.IInspectionReportService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
/**
 * æ£€æµ‹æŠ¥å‘ŠService业务层处理
 */
@Service
public class InspectionReportServiceImpl extends ServiceImpl<InspectionReportMapper, InspectionReport> implements IInspectionReportService {
    @Override
    public IPage<InspectionReport> listPage(Page<InspectionReport> page, InspectionReport report) {
        LambdaQueryWrapper<InspectionReport> lqw = Wrappers.lambdaQuery();
        if (report != null) {
            if (StringUtils.isNotBlank(report.getProductName())) {
                lqw.like(InspectionReport::getProductName, report.getProductName());
            }
            if (StringUtils.isNotBlank(report.getProductModel())) {
                lqw.like(InspectionReport::getProductModel, report.getProductModel());
            }
            if (StringUtils.isNotBlank(report.getReportNo())) {
                lqw.like(InspectionReport::getReportNo, report.getReportNo());
            }
            if (StringUtils.isNotBlank(report.getReportType())) {
                lqw.eq(InspectionReport::getReportType, report.getReportType());
            }
            if (StringUtils.isNotBlank(report.getStatus())) {
                lqw.eq(InspectionReport::getStatus, report.getStatus());
            } else {
                // é»˜è®¤æŸ¥è¯¢æ­£å¸¸çš„
                lqw.ne(InspectionReport::getStatus, "CANCELLED");
            }
        } else {
            lqw.ne(InspectionReport::getStatus, "CANCELLED");
        }
        // æŒ‰ç…§åˆ°æœŸæ—¶é—´æ­£åºï¼Œè¶Šè¿‘到期排在越前
        lqw.orderByAsc(InspectionReport::getExpirationTime);
        return baseMapper.selectPage(page, lqw);
    }
}
src/main/resources/mapper/quality/InspectionReportMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.project.quality.report.mapper.InspectionReportMapper">
</mapper>