From e97b55310155a2dd691bd698a10295a4d867f60c Mon Sep 17 00:00:00 2001
From: baoshiwei <baoshiwei@shlanbao.cn>
Date: 星期五, 17 四月 2026 15:55:51 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmJudgeDetails.java | 8
ruoyi-plus-soybean/src/router/elegant/routes.ts | 27
ruoyi-plus-soybean/src/views/qm/batch/modules/batch-operate-drawer.vue | 280 -
ruoyi-plus-soybean/src/service/api/qm/judge-details.ts | 10
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatTypeVo.java | 106 +
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java | 11
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports | 2
ruoyi-plus-soybean/src/typings/api/md.mat-type.api.d.ts | 76
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/mapper/QmMatcheckMapper.java | 38
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeServiceImpl.java | 61
ruoyi-plus-soybean/src/views/md/mat-type/index.vue | 241 ++
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmBatchVo.java | 15
ruoyi-plus-soybean/src/views/qm/judge/modules/judge-operate-drawer.vue | 59
ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-operate-drawer.vue | 70
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeDetailsVo.java | 54
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatServiceImpl.java | 147 +
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/MatNameTranslationImpl.java | 28
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/MatService.java | 13
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatController.java | 105
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/qm/QmMatcheckMapper.xml | 67
ruoyi-plus-soybean/src/views/qm/judge/modules/judge-search.vue | 54
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/JudgeNameTranslationImpl.java | 26
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmMatcheckService.java | 85
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/JudgeService.java | 13
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMatType.java | 87
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatBo.java | 97
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmMatcheckBo.java | 183 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatMapper.java | 15
ruoyi-plus-soybean/src/typings/elegant-router.d.ts | 6
ruoyi-plus-soybean/src/views/qm/matcheck/index.vue | 268 ++
ruoyi-plus-soybean/src/service/api/qm/matcheck.ts | 57
ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-search.vue | 93
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMat.java | 97
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmMatcheckController.java | 122 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeDetailsServiceImpl.java | 45
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatTypeService.java | 68
ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-operate-drawer.vue | 266 ++
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/test | 0
ruoyi-plus-soybean/src/router/elegant/transform.ts | 3
ruoyi-plus-soybean/src/typings/api/qm.judge-details.api.d.ts | 40
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmJudgeDetailsBo.java | 8
ruoyi-plus-soybean/src/views/qm/judge/index.vue | 103
ruoyi-plus-soybean/src/typings/api/qm.batch.api.d.ts | 4
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmMatcheck.java | 184 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatVo.java | 118 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatTypeMapper.java | 15
ruoyi-plus-soybean/src/service/api/md/mat.ts | 35
ruoyi-plus-soybean/src/views/md/mat/modules/mat-operate-drawer.vue | 184 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmMatcheckVo.java | 255 ++
ruoyi-plus-soybean/src/views/md/mat/index.vue | 283 ++
ruoyi-plus-soybean/src/typings/api/md.mat.api.d.ts | 83
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeVo.java | 1
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatTypeBo.java | 87
ruoyi-plus-soybean/src/views/qm/batch/index.vue | 231 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmJudgeDetailsController.java | 10
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatMapper.xml | 6
ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-operate-drawer.vue | 171 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatTypeMapper.xml | 6
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmMatcheckServiceImpl.java | 154 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatTypeServiceImpl.java | 138 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmJudgeDetailsService.java | 8
ruoyi-plus-soybean/src/typings/api/qm.matcheck.api.d.ts | 165 +
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatTypeController.java | 105
ruoyi-plus-soybean/src/router/elegant/imports.ts | 3
ruoyi-plus-soybean/src/views/md/mat/modules/mat-search.vue | 119 +
ruoyi-plus-soybean/src/views/qm/batch/modules/batch-search.vue | 166
ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-sub-table.vue | 414 +++
ruoyi-plus-soybean/src/service/api/md/mat-type.ts | 35
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/test | 0
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatService.java | 68
ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-search.vue | 99
71 files changed, 5,838 insertions(+), 463 deletions(-)
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/JudgeService.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/JudgeService.java
new file mode 100644
index 0000000..36c1903
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/JudgeService.java
@@ -0,0 +1,13 @@
+package org.dromara.common.core.service;
+
+/**
+ * 鍒ゅ畾渚濇嵁
+ */
+public interface JudgeService {
+ /**
+ * 鍒ゅ畾渚濇嵁code杞琻ame
+ * @param judgeCode
+ * @return
+ */
+ String selectJudgeNameByCode(String judgeCode);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/MatService.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/MatService.java
new file mode 100644
index 0000000..283acda
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/service/MatService.java
@@ -0,0 +1,13 @@
+package org.dromara.common.core.service;
+
+/**
+ * 鐗╂枡
+ */
+public interface MatService {
+ /**
+ * 鐗╂枡code杞琻ame
+ * @param matCode
+ * @return
+ */
+ String selectMatNameByCode(String matCode);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
index c084ea1..254b13c 100755
--- a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
@@ -32,4 +32,15 @@
*/
String OSS_ID_TO_URL = "oss_id_to_url";
+
+ /**
+ * 鐗╂枡code杞琻ame
+ */
+ String MAT_CODE_TO_NAME = "mat_code_to_name";
+
+ /**
+ * 鍒ゅ畾渚濇嵁code杞琻ame
+ */
+ String JUDGE_CODE_TO_NAME = "judge_code_to_name";
+
}
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/JudgeNameTranslationImpl.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/JudgeNameTranslationImpl.java
new file mode 100755
index 0000000..9234fd2
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/JudgeNameTranslationImpl.java
@@ -0,0 +1,26 @@
+package org.dromara.common.translation.core.impl;
+
+import lombok.AllArgsConstructor;
+import org.dromara.common.core.service.JudgeService;
+import org.dromara.common.core.service.MatService;
+import org.dromara.common.translation.annotation.TranslationType;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.common.translation.core.TranslationInterface;
+
+/**
+ * judgeName缈昏瘧瀹炵幇
+ *
+ * @author zhuguifei
+ */
+@AllArgsConstructor
+@TranslationType(type = TransConstant.JUDGE_CODE_TO_NAME)
+public class JudgeNameTranslationImpl implements TranslationInterface<String> {
+
+ private final JudgeService judgeService;
+
+ @Override
+ public String translation(Object key, String other) {
+ if(key == null) return "";
+ return judgeService.selectJudgeNameByCode(key.toString());
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/MatNameTranslationImpl.java b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/MatNameTranslationImpl.java
new file mode 100755
index 0000000..39d48cf
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/MatNameTranslationImpl.java
@@ -0,0 +1,28 @@
+package org.dromara.common.translation.core.impl;
+
+import cn.hutool.core.convert.Convert;
+import lombok.AllArgsConstructor;
+import org.dromara.common.core.service.MatService;
+import org.dromara.common.core.service.UserService;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.translation.annotation.TranslationType;
+import org.dromara.common.translation.constant.TransConstant;
+import org.dromara.common.translation.core.TranslationInterface;
+
+/**
+ * matName缈昏瘧瀹炵幇
+ *
+ * @author zhuguifei
+ */
+@AllArgsConstructor
+@TranslationType(type = TransConstant.MAT_CODE_TO_NAME)
+public class MatNameTranslationImpl implements TranslationInterface<String> {
+
+ private final MatService matService;
+
+ @Override
+ public String translation(Object key, String other) {
+ if(key == null) return "";
+ return matService.selectMatNameByCode(key.toString());
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index ad40205..88a1ea3 100755
--- a/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -4,3 +4,5 @@
org.dromara.common.translation.core.impl.OssUrlTranslationImpl
org.dromara.common.translation.core.impl.UserNameTranslationImpl
org.dromara.common.translation.core.impl.NicknameTranslationImpl
+org.dromara.common.translation.core.impl.MatNameTranslationImpl
+org.dromara.common.translation.core.impl.JudgeNameTranslationImpl
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmJudgeDetailsController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmJudgeDetailsController.java
index c58d4d6..20b4367 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmJudgeDetailsController.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmJudgeDetailsController.java
@@ -46,6 +46,16 @@
}
/**
+ * 鏌ヨ鍒ゅ畾妯℃澘鏄庣粏鏍戝舰缁撴瀯鍒楄〃
+ */
+ @SaCheckPermission("qm:judgeDetails:list")
+ @GetMapping("/tree")
+ public TableDataInfo<QmJudgeDetailsVo> tree(@RequestParam @NotBlank(message = "judgeId涓嶈兘涓虹┖") String judgeId) {
+ List<QmJudgeDetailsVo> list = qmJudgeDetailsService.queryTreeListByJudgeId(judgeId);
+ return TableDataInfo.build(list);
+ }
+
+ /**
* 瀵煎嚭鍒ゅ畾妯℃澘鏄庣粏鍒楄〃
*/
@SaCheckPermission("qm:judgeDetails:export")
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmMatcheckController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmMatcheckController.java
new file mode 100644
index 0000000..5bf78c1
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/controller/QmMatcheckController.java
@@ -0,0 +1,122 @@
+package org.dromara.qa.qm.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.qa.qm.domain.vo.QmMatcheckVo;
+import org.dromara.qa.qm.domain.bo.QmMatcheckBo;
+import org.dromara.qa.qm.service.IQmMatcheckService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁�
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/qm/matcheck")
+public class QmMatcheckController extends BaseController {
+
+ private final IQmMatcheckService qmMatcheckService;
+
+ /**
+ * 鏌ヨ鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ @SaCheckPermission("qm:matcheck:list")
+ @GetMapping("/list")
+ public TableDataInfo<QmMatcheckVo> list(QmMatcheckBo bo, PageQuery pageQuery) {
+ return qmMatcheckService.queryPageList(bo, pageQuery);
+ }
+
+
+ @SaCheckPermission("qm:matcheck:list")
+ @GetMapping("/listCheckItem")
+ public R<List<Map<String, Object>>> listCheckItem(@RequestParam String judgeId) {
+ return R.ok(qmMatcheckService.getQmCheckItem(judgeId));
+ }
+
+ /**
+ * 鎸夋壒娆″拰鐗屽彿鏌ヨ鏉愭枡妫�楠岀粺璁�(澶氳〃)
+ */
+ @SaCheckPermission("qm:matcheck:list")
+ @GetMapping("/listQmMatcheck")
+ public TableDataInfo<QmMatcheckVo> listQmMatcheck(QmMatcheckBo bo, PageQuery pageQuery) {
+ return TableDataInfo.build(qmMatcheckService.listQmMatcheck(bo), pageQuery.build());
+ }
+
+ /**
+ * 瀵煎嚭鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ @SaCheckPermission("qm:matcheck:export")
+ @Log(title = "鏉愭枡妫�楠岀粺璁�", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(QmMatcheckBo bo, HttpServletResponse response) {
+ List<QmMatcheckVo> list = qmMatcheckService.queryList(bo);
+ ExcelUtil.exportExcel(list, "鏉愭枡妫�楠岀粺璁�", QmMatcheckVo.class, response);
+ }
+
+ /**
+ * 鑾峰彇鏉愭枡妫�楠岀粺璁¤缁嗕俊鎭�
+ *
+ * @param id 涓婚敭
+ */
+ @SaCheckPermission("qm:matcheck:query")
+ @GetMapping("/{id}")
+ public R<QmMatcheckVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String id) {
+ return R.ok(qmMatcheckService.queryById(id));
+ }
+
+ /**
+ * 鏂板鏉愭枡妫�楠岀粺璁�
+ */
+ @SaCheckPermission("qm:matcheck:add")
+ @Log(title = "鏉愭枡妫�楠岀粺璁�", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R<Void> add(@Validated(AddGroup.class) @RequestBody QmMatcheckBo bo) {
+ return toAjax(qmMatcheckService.insertByBo(bo));
+ }
+
+ /**
+ * 淇敼鏉愭枡妫�楠岀粺璁�
+ */
+ @SaCheckPermission("qm:matcheck:edit")
+ @Log(title = "鏉愭枡妫�楠岀粺璁�", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R<Void> edit(@Validated(EditGroup.class) @RequestBody QmMatcheckBo bo) {
+ return toAjax(qmMatcheckService.updateByBo(bo));
+ }
+
+ /**
+ * 鍒犻櫎鏉愭枡妫�楠岀粺璁�
+ *
+ * @param ids 涓婚敭涓�
+ */
+ @SaCheckPermission("qm:matcheck:remove")
+ @Log(title = "鏉愭枡妫�楠岀粺璁�", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String[] ids) {
+ return toAjax(qmMatcheckService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmJudgeDetails.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmJudgeDetails.java
index 1b07cdf..a7b227e 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmJudgeDetails.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmJudgeDetails.java
@@ -44,17 +44,17 @@
/**
* 鏍囧噯鍊�
*/
- private Long value3;
+ private Double value3;
/**
* 鍒ゅ畾鍊�1
*/
- private Long value1;
+ private Double value1;
/**
* 鍒ゅ畾鍊�2
*/
- private Long value2;
+ private Double value2;
/**
* 缂洪櫡浣嶇疆
@@ -69,7 +69,7 @@
/**
* 鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�
*/
- private Long stdscore;
+ private Double stdscore;
/**
* 鏍囪姝ら」鏄惁涓哄悎鎴愰」鐩紝姣斿澶栬锛屽疄闄呬笂鍏宠仈浜嗗緢澶氬瓙椤圭洰
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmMatcheck.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmMatcheck.java
new file mode 100644
index 0000000..e3f73e4
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/QmMatcheck.java
@@ -0,0 +1,184 @@
+package org.dromara.qa.qm.domain;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+
+import java.io.Serial;
+import java.util.Date;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁″璞� qm_matcheck
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+@Data
+@TableName("qm_matcheck")
+public class QmMatcheck {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "id")
+ private String id;
+
+ /**
+ * 姹囨�昏〃ID
+ */
+ private String pid;
+
+ /**
+ * 妫�楠屾壒娆�
+ */
+ private String batchCode;
+
+ /**
+ * 鐗屽彿
+ */
+ private String matCode;
+
+ /**
+ * 浠櫒缂栧彿
+ */
+ private String instrumentCode;
+
+ /**
+ * 鎶�鏈姹�
+ */
+ private String techReq;
+
+ /**
+ * 妫�楠屼緷鎹�
+ */
+ private String checkStd;
+
+ /**
+ * 娴嬭瘯鐜
+ */
+ private String testEnv;
+
+ /**
+ * 妫�楠岄」鐩瓹OD
+ */
+ private String itemCode;
+
+ /**
+ * 鐩樺彿
+ */
+ private String subBatchCode;
+
+ /**
+ * 姣忕洏妫�楠屾暟閲�
+ */
+ private Long sampleNumber;
+
+ /**
+ * 鍙栨牱绫诲瀷
+ */
+ private Long sampleType;
+
+ /**
+ * 妫�楠屽憳
+ */
+ private String checkName;
+
+ /**
+ * 妫�楠屾椂闂�
+ */
+ private Date checkTime;
+
+ /**
+ * 澶嶆牳鍛�
+ */
+ private String reviewName;
+
+ /**
+ * 澶嶆牳鏃堕棿
+ */
+ private Date reviewTime;
+
+ /**
+ * 鏈�澶у��
+ */
+ private Double maxval;
+
+ /**
+ * 鏈�灏忓��
+ */
+ private Double minval;
+
+ /**
+ * 骞冲潎鍊�
+ */
+ private Double avgval;
+
+ /**
+ * SD鍊�
+ */
+ private Double sdval;
+
+ /**
+ * CV鍊�
+ */
+ private Double cvval;
+
+ /**
+ * CPK鍊�
+ */
+ private Double cpkval;
+
+ /**
+ * 瓒呮爣鏁�
+ */
+ private Double badval;
+
+ /**
+ * 鍒ゅ畾
+ */
+ private String judge;
+
+ /**
+ * 鍗曢」鍒ゅ畾
+ */
+ private String singlejudge;
+
+ /**
+ * 鐗堟湰鍚嶇О
+ */
+ private String verName;
+
+ /**
+ * 鐗堟湰缂栧彿
+ */
+ private String verCode;
+
+ /**
+ * 淇濆瓨鏈�
+ */
+ private String archDate;
+
+ /**
+ * 鍒犻櫎鏍囧織
+ */
+ private Long del;
+
+ /**
+ * 0-鏈笂浼爉es 1-宸蹭笂浼�
+ */
+ private String flag;
+
+ /**
+ * 涓婁紶mes鏃堕棿
+ */
+ private Date toMesTime;
+
+ /**
+ * 澶囨敞
+ */
+ private String chkDes;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmJudgeDetailsBo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmJudgeDetailsBo.java
index 9fd1f63..e5aa98d 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmJudgeDetailsBo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmJudgeDetailsBo.java
@@ -43,17 +43,17 @@
/**
* 鏍囧噯鍊�
*/
- private Long value3;
+ private Double value3;
/**
* 鍒ゅ畾鍊�1
*/
- private Long value1;
+ private Double value1;
/**
* 鍒ゅ畾鍊�2
*/
- private Long value2;
+ private Double value2;
/**
* 缂洪櫡浣嶇疆
@@ -68,7 +68,7 @@
/**
* 鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�
*/
- private Long stdscore;
+ private Double stdscore;
/**
* 鏍囪姝ら」鏄惁涓哄悎鎴愰」鐩紝姣斿澶栬锛屽疄闄呬笂鍏宠仈浜嗗緢澶氬瓙椤圭洰
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmMatcheckBo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmMatcheckBo.java
new file mode 100644
index 0000000..98378e5
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/bo/QmMatcheckBo.java
@@ -0,0 +1,183 @@
+package org.dromara.qa.qm.domain.bo;
+
+import org.dromara.qa.qm.domain.QmMatcheck;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁′笟鍔″璞� qm_matcheck
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = QmMatcheck.class, reverseConvertGenerate = false)
+public class QmMatcheckBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ private String id;
+
+ /**
+ * 姹囨�昏〃ID
+ */
+ private String pid;
+
+ /**
+ * 妫�楠屾壒娆�
+ */
+ private String batchCode;
+
+ /**
+ * 鐗屽彿
+ */
+ private String matCode;
+
+ /**
+ * 浠櫒缂栧彿
+ */
+ private String instrumentCode;
+
+ /**
+ * 鎶�鏈姹�
+ */
+ private String techReq;
+
+ /**
+ * 妫�楠屼緷鎹�
+ */
+ private String checkStd;
+
+ /**
+ * 娴嬭瘯鐜
+ */
+ private String testEnv;
+
+ /**
+ * 妫�楠岄」鐩瓹OD
+ */
+ private String itemCode;
+
+ /**
+ * 鐩樺彿
+ */
+ private String subBatchCode;
+
+ /**
+ * 姣忕洏妫�楠屾暟閲�
+ */
+ private Long sampleNumber;
+
+ /**
+ * 鍙栨牱绫诲瀷
+ */
+ private Long sampleType;
+
+ /**
+ * 妫�楠屽憳
+ */
+ private String checkName;
+
+ /**
+ * 妫�楠屾椂闂�
+ */
+ private Date checkTime;
+
+ /**
+ * 澶嶆牳鍛�
+ */
+ private String reviewName;
+
+ /**
+ * 澶嶆牳鏃堕棿
+ */
+ private Date reviewTime;
+
+ /**
+ * 鏈�澶у��
+ */
+ private Double maxval;
+
+ /**
+ * 鏈�灏忓��
+ */
+ private Double minval;
+
+ /**
+ * 骞冲潎鍊�
+ */
+ private Double avgval;
+
+ /**
+ * SD鍊�
+ */
+ private Double sdval;
+
+ /**
+ * CV鍊�
+ */
+ private Double cvval;
+
+ /**
+ * CPK鍊�
+ */
+ private Double cpkval;
+
+ /**
+ * 瓒呮爣鏁�
+ */
+ private Double badval;
+
+ /**
+ * 鍒ゅ畾
+ */
+ private String judge;
+
+ /**
+ * 鍗曢」鍒ゅ畾
+ */
+ private String singlejudge;
+
+ /**
+ * 鐗堟湰鍚嶇О
+ */
+ private String verName;
+
+ /**
+ * 鐗堟湰缂栧彿
+ */
+ private String verCode;
+
+ /**
+ * 淇濆瓨鏈�
+ */
+ private String archDate;
+
+ /**
+ * 鍒犻櫎鏍囧織
+ */
+ private Long del;
+
+ /**
+ * 0-鏈笂浼爉es 1-宸蹭笂浼�
+ */
+ private String flag;
+
+ /**
+ * 涓婁紶mes鏃堕棿
+ */
+ private Date toMesTime;
+
+ /**
+ * 澶囨敞
+ */
+ private String chkDes;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmBatchVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmBatchVo.java
index 4d3132f..ce8136f 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmBatchVo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmBatchVo.java
@@ -2,6 +2,8 @@
import java.util.Date;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
import org.dromara.qa.qm.domain.QmBatch;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
@@ -59,8 +61,15 @@
/**
* 鐗屽彿
*/
- @ExcelProperty(value = "鐗屽彿")
+ @ExcelProperty(value = "鐗屽彿code")
private String matCode;
+
+ /**
+ * 鐗屽彿
+ */
+ @ExcelProperty(value = "鐗屽彿")
+ @Translation(type = TransConstant.MAT_CODE_TO_NAME, mapper = "matCode")
+ private String matName;
/**
* 鍒ゅ畾渚濇嵁浠g爜
@@ -68,6 +77,10 @@
@ExcelProperty(value = "鍒ゅ畾渚濇嵁浠g爜")
private String judgeCode;
+ @ExcelProperty(value = "鍒ゅ畾渚濇嵁")
+ @Translation(type = TransConstant.JUDGE_CODE_TO_NAME, mapper = "judgeCode")
+ private String judgeName;
+
/**
* 鎵规鐢熸垚鏃ユ湡
*/
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeDetailsVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeDetailsVo.java
index f005ed1..9829c65 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeDetailsVo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeDetailsVo.java
@@ -11,7 +11,7 @@
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
-
+import java.util.List;
/**
@@ -27,6 +27,8 @@
@Serial
private static final long serialVersionUID = 1L;
+
+ private String id;
/**
* 鍒ゅ畾涓绘爣璇�
@@ -50,19 +52,19 @@
* 鏍囧噯鍊�
*/
@ExcelProperty(value = "鏍囧噯鍊�")
- private Long value3;
+ private Double value3;
/**
* 鍒ゅ畾鍊�1
*/
@ExcelProperty(value = "鍒ゅ畾鍊�1")
- private Long value1;
+ private Double value1;
/**
* 鍒ゅ畾鍊�2
*/
@ExcelProperty(value = "鍒ゅ畾鍊�2")
- private Long value2;
+ private Double value2;
/**
* 缂洪櫡浣嶇疆
@@ -80,7 +82,7 @@
* 鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�
*/
@ExcelProperty(value = "鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�")
- private Long stdscore;
+ private Double stdscore;
/**
* 鏍囪姝ら」鏄惁涓哄悎鎴愰」鐩紝姣斿澶栬锛屽疄闄呬笂鍏宠仈浜嗗緢澶氬瓙椤圭洰
@@ -113,4 +115,46 @@
private String updateUser;
+ /**
+ * 瀛愭壒娆$爜
+ */
+ @ExcelProperty(value = "瀛愭壒娆$爜")
+ private String subBatchCode;
+
+ /**
+ * 涓嶈壇鍊�
+ */
+ @ExcelProperty(value = "涓嶈壇鍊�")
+ private Long badVal;
+
+ /**
+ * 鎵规鐮�
+ */
+ @ExcelProperty(value = "鎵规鐮�")
+ private String batchCode;
+
+ /**
+ * 鐗╂枡鐮�
+ */
+ @ExcelProperty(value = "鐗╂枡鐮�")
+ private String matCode;
+
+ /**
+ * 璁惧
+ */
+ @ExcelProperty(value = "璁惧")
+ private String eqp;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @ExcelProperty(value = "鏇存柊鏃堕棿")
+ private Date updateTime;
+
+ /**
+ * 瀛愰」鍒楄〃锛堢敤浜庢爲褰㈢粨鏋勶級
+ */
+ private List<QmJudgeDetailsVo> children;
+
+
}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeVo.java
index e0fd2d8..66fd9a8 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeVo.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmJudgeVo.java
@@ -48,6 +48,7 @@
* 鐗╂枡鐗屽彿
*/
@ExcelProperty(value = "鐗╂枡鐗屽彿")
+ @Translation(type = TransConstant.MAT_CODE_TO_NAME, mapper = "matCode")
private String matName;
/**
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmMatcheckVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmMatcheckVo.java
new file mode 100644
index 0000000..30a2376
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/domain/vo/QmMatcheckVo.java
@@ -0,0 +1,255 @@
+package org.dromara.qa.qm.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.qa.qm.domain.QmMatcheck;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 鏉愭枡妫�楠岀粺璁¤鍥惧璞� qm_matcheck
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = QmMatcheck.class)
+public class QmMatcheckVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private String id;
+
+ /**
+ * 姹囨�昏〃ID
+ */
+ @ExcelProperty(value = "姹囨�昏〃ID")
+ private String pid;
+
+ /**
+ * 妫�楠屾壒娆�
+ */
+ @ExcelProperty(value = "妫�楠屾壒娆�")
+ private String batchCode;
+
+ /**
+ * 鐗屽彿
+ */
+ @ExcelProperty(value = "鐗屽彿")
+ private String matCode;
+
+ /**
+ * 浠櫒缂栧彿
+ */
+ @ExcelProperty(value = "浠櫒缂栧彿")
+ private String instrumentCode;
+
+ /**
+ * 鎶�鏈姹�
+ */
+ @ExcelProperty(value = "鎶�鏈姹�")
+ private String techReq;
+
+ /**
+ * 妫�楠屼緷鎹�
+ */
+ @ExcelProperty(value = "妫�楠屼緷鎹�")
+ private String checkStd;
+
+ /**
+ * 娴嬭瘯鐜
+ */
+ @ExcelProperty(value = "娴嬭瘯鐜")
+ private String testEnv;
+
+ /**
+ * 妫�楠岄」鐩瓹OD
+ */
+ @ExcelProperty(value = "妫�楠岄」鐩瓹OD")
+ private String itemCode;
+
+ /**
+ * 妫�楠岄」鐩悕绉�
+ */
+ private String itemName;
+
+ /**
+ * 璁惧
+ */
+ private String eqp;
+
+ /**
+ * 鐩樺彿
+ */
+ @ExcelProperty(value = "鐩樺彿")
+ private String subBatchCode;
+
+ /**
+ * 姣忕洏妫�楠屾暟閲�
+ */
+ @ExcelProperty(value = "姣忕洏妫�楠屾暟閲�")
+ private Long sampleNumber;
+
+ /**
+ * 鍙栨牱绫诲瀷
+ */
+ @ExcelProperty(value = "鍙栨牱绫诲瀷")
+ private Long sampleType;
+
+ /**
+ * 妫�楠屽憳
+ */
+ @ExcelProperty(value = "妫�楠屽憳")
+ private String checkName;
+
+ /**
+ * 妫�楠屾椂闂�
+ */
+ @ExcelProperty(value = "妫�楠屾椂闂�")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private Date checkTime;
+
+ /**
+ * 澶嶆牳鍛�
+ */
+ @ExcelProperty(value = "澶嶆牳鍛�")
+ private String reviewName;
+
+ /**
+ * 澶嶆牳鏃堕棿
+ */
+ @ExcelProperty(value = "澶嶆牳鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private Date reviewTime;
+
+ /**
+ * 鏈�澶у��
+ */
+ @ExcelProperty(value = "鏈�澶у��")
+ private Double maxval;
+
+ /**
+ * 鏈�灏忓��
+ */
+ @ExcelProperty(value = "鏈�灏忓��")
+ private Double minval;
+
+ /**
+ * 骞冲潎鍊�
+ */
+ @ExcelProperty(value = "骞冲潎鍊�")
+ private Double avgval;
+
+ /**
+ * SD鍊�
+ */
+ @ExcelProperty(value = "SD鍊�")
+ private Double sdval;
+
+ /**
+ * CV鍊�
+ */
+ @ExcelProperty(value = "CV鍊�")
+ private Double cvval;
+
+ /**
+ * CPK鍊�
+ */
+ @ExcelProperty(value = "CPK鍊�")
+ private Double cpkval;
+
+ /**
+ * 瓒呮爣鏁�
+ */
+ @ExcelProperty(value = "瓒呮爣鏁�")
+ private Double badval;
+
+ /**
+ * 鍒ゅ畾
+ */
+ @ExcelProperty(value = "鍒ゅ畾")
+ private String judge;
+
+ /**
+ * 鍗曢」鍒ゅ畾
+ */
+ @ExcelProperty(value = "鍗曢」鍒ゅ畾")
+ private String singlejudge;
+
+ /**
+ * 鐗堟湰鍚嶇О
+ */
+ @ExcelProperty(value = "鐗堟湰鍚嶇О")
+ private String verName;
+
+ /**
+ * 鐗堟湰缂栧彿
+ */
+ @ExcelProperty(value = "鐗堟湰缂栧彿")
+ private String verCode;
+
+ /**
+ * 淇濆瓨鏈�
+ */
+ @ExcelProperty(value = "淇濆瓨鏈�")
+ private String archDate;
+
+ /**
+ * 鍒犻櫎鏍囧織
+ */
+ @ExcelProperty(value = "鍒犻櫎鏍囧織")
+ private Long del;
+
+ /**
+ * 0-鏈笂浼爉es 1-宸蹭笂浼�
+ */
+ @ExcelProperty(value = "0-鏈笂浼爉es 1-宸蹭笂浼�")
+ private String flag;
+
+ /**
+ * 涓婁紶mes鏃堕棿
+ */
+ @ExcelProperty(value = "涓婁紶mes鏃堕棿")
+ private Date toMesTime;
+
+ /**
+ * 澶囨敞
+ */
+ @ExcelProperty(value = "澶囨敞")
+ private String chkDes;
+
+ /**
+ * 妫�楠屼汉灞曠ず鍚�
+ */
+ private String checker;
+
+ /**
+ * 鍒ゅ畾瑙勭▼code(闈炴暟鎹簱瀛楁)
+ */
+ private String judgeCode;
+
+ /**
+ * 鏄惁鐢熸垚30鏀儫鏄庣粏(闈炴暟鎹簱瀛楁)
+ */
+ private String generateDetails;
+
+ /**
+ * 妫�娴嬬被鍨�(闈炴暟鎹簱瀛楁)
+ */
+ private String checkType;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/mapper/QmMatcheckMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/mapper/QmMatcheckMapper.java
new file mode 100644
index 0000000..6c6fbaa
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/mapper/QmMatcheckMapper.java
@@ -0,0 +1,38 @@
+package org.dromara.qa.qm.mapper;
+
+import org.apache.ibatis.annotations.Result;
+import org.apache.ibatis.annotations.Results;
+import org.dromara.qa.qm.domain.bo.QmMatcheckBo;
+import org.dromara.qa.qm.domain.QmMatcheck;
+import org.dromara.qa.qm.domain.vo.QmMatcheckVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁apper鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+public interface QmMatcheckMapper extends BaseMapperPlus<QmMatcheck, QmMatcheckVo> {
+ @Results(id = "qmCheckItemMap", value = {
+ @Result(property = "itemCode", column = "item_code"),
+ @Result(property = "itemName", column = "item_name")
+ })
+ @Select("SELECT b.item_code, a.item_name FROM QM_JUDGE_DETAILS a " +
+ "JOIN QM_CHECKITEM b ON a.item_cod = b.id " +
+ "WHERE a.judge_id = #{judgeId} AND a.rid IS NULL AND a.category IN (0)")
+ List<Map<String, Object>> getQmCheckItem(@Param("judgeId") String judgeId);
+
+ /**
+ * 鎸夋壒娆″拰鐗屽彿鏌ヨ鏉愭枡妫�楠岀粺璁�(澶氳〃)
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ List<QmMatcheckVo> listQmMatcheck(@Param("bo") QmMatcheckBo bo);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmJudgeDetailsService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmJudgeDetailsService.java
index d6506ed..ad2a804 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmJudgeDetailsService.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmJudgeDetailsService.java
@@ -42,6 +42,14 @@
List<QmJudgeDetailsVo> queryList(QmJudgeDetailsBo bo);
/**
+ * 鏌ヨ鏍戝舰缁撴瀯鏁版嵁
+ *
+ * @param judgeId 鍒ゅ畾涓绘爣璇�
+ * @return 鏍戝舰缁撴瀯鍒楄〃
+ */
+ List<QmJudgeDetailsVo> queryTreeListByJudgeId(String judgeId);
+
+ /**
* 鏂板鍒ゅ畾妯℃澘鏄庣粏
*
* @param bo 鍒ゅ畾妯℃澘鏄庣粏
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmMatcheckService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmMatcheckService.java
new file mode 100644
index 0000000..6f7f7da
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/IQmMatcheckService.java
@@ -0,0 +1,85 @@
+package org.dromara.qa.qm.service;
+
+import org.dromara.qa.qm.domain.vo.QmMatcheckVo;
+import org.dromara.qa.qm.domain.bo.QmMatcheckBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁ervice鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+public interface IQmMatcheckService {
+
+ /**
+ * 鏌ヨ鏉愭枡妫�楠岀粺璁�
+ *
+ * @param id 涓婚敭
+ * @return 鏉愭枡妫�楠岀粺璁�
+ */
+ QmMatcheckVo queryById(String id);
+
+ /**
+ * 鍒嗛〉鏌ヨ鏉愭枡妫�楠岀粺璁″垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鏉愭枡妫�楠岀粺璁″垎椤靛垪琛�
+ */
+ TableDataInfo<QmMatcheckVo> queryPageList(QmMatcheckBo bo, PageQuery pageQuery);
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勬潗鏂欐楠岀粺璁″垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ List<QmMatcheckVo> queryList(QmMatcheckBo bo);
+
+ /**
+ * 鏂板鏉愭枡妫�楠岀粺璁�
+ *
+ * @param bo 鏉愭枡妫�楠岀粺璁�
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ Boolean insertByBo(QmMatcheckBo bo);
+
+ /**
+ * 淇敼鏉愭枡妫�楠岀粺璁�
+ *
+ * @param bo 鏉愭枡妫�楠岀粺璁�
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ Boolean updateByBo(QmMatcheckBo bo);
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ゆ潗鏂欐楠岀粺璁′俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
+
+ /**
+ * 鑾峰彇妫�楠岄」鐩�
+ *
+ * @param judgeId 鍒ゅ畾ID
+ * @return 妫�楠岄」鐩垪琛�
+ */
+ List<Map<String, Object>> getQmCheckItem(String judgeId);
+
+ /**
+ * 鎸夋壒娆″拰鐗屽彿鏌ヨ鏉愭枡妫�楠岀粺璁�(澶氳〃)
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ List<QmMatcheckVo> listQmMatcheck(QmMatcheckBo bo);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeDetailsServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeDetailsServiceImpl.java
index ccfb91d..c76b09c 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeDetailsServiceImpl.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeDetailsServiceImpl.java
@@ -70,6 +70,51 @@
return baseMapper.selectVoList(lqw);
}
+ /**
+ * 鏌ヨ鏍戝舰缁撴瀯鏁版嵁
+ *
+ * @param judgeId 鍒ゅ畾涓绘爣璇�
+ * @return 鏍戝舰缁撴瀯鍒楄〃
+ */
+ @Override
+ public List<QmJudgeDetailsVo> queryTreeListByJudgeId(String judgeId) {
+ if (StringUtils.isBlank(judgeId)) {
+ return new java.util.ArrayList<>();
+ }
+ // 1. 鏌ヨ鏍硅妭鐐� (rid is null)
+ List<QmJudgeDetailsVo> roots = selectTreeNodes(judgeId, null);
+ for (QmJudgeDetailsVo root : roots) {
+ // 2. 鏌ヨ绗竴绾у瓙鑺傜偣 (rid = root.itemCod)
+ List<QmJudgeDetailsVo> children = selectTreeNodes(judgeId, root.getItemCod());
+ for (QmJudgeDetailsVo child : children) {
+ // 3. 鏌ヨ绗簩绾у瓙鑺傜偣 (rid = child.itemCod)
+ List<QmJudgeDetailsVo> grandchildren = selectTreeNodes(judgeId, child.getItemCod());
+ child.setChildren(grandchildren);
+ }
+ root.setChildren(children);
+ }
+ return roots;
+ }
+
+ /**
+ * 鏌ヨ鏍戣妭鐐�
+ *
+ * @param judgeId 鍒ゅ畾涓绘爣璇�
+ * @param rid 鍏宠仈椤笽D
+ * @return 鑺傜偣鍒楄〃
+ */
+ private List<QmJudgeDetailsVo> selectTreeNodes(String judgeId, String rid) {
+ LambdaQueryWrapper<QmJudgeDetails> lqw = Wrappers.lambdaQuery();
+ lqw.eq(QmJudgeDetails::getJudgeId, judgeId);
+ if (rid == null) {
+ lqw.isNull(QmJudgeDetails::getRid);
+ } else {
+ lqw.eq(QmJudgeDetails::getRid, rid);
+ }
+ lqw.orderByAsc(QmJudgeDetails::getId);
+ return baseMapper.selectVoList(lqw);
+ }
+
private LambdaQueryWrapper<QmJudgeDetails> buildQueryWrapper(QmJudgeDetailsBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<QmJudgeDetails> lqw = Wrappers.lambdaQuery();
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeServiceImpl.java
index 55b949c..e6edd0e 100644
--- a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeServiceImpl.java
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmJudgeServiceImpl.java
@@ -1,5 +1,6 @@
package org.dromara.qa.qm.service.impl;
+import org.dromara.common.core.service.JudgeService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
@@ -19,6 +20,13 @@
import org.dromara.qa.qm.service.IQmStdService;
import org.dromara.qa.qm.mapper.QmStdMapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import org.dromara.qa.qm.domain.QmCheckitem;
+import org.dromara.qa.qm.domain.QmJudgeDetails;
+import org.dromara.qa.qm.mapper.QmCheckitemMapper;
+import org.dromara.qa.qm.mapper.QmJudgeDetailsMapper;
+import org.springframework.transaction.annotation.Transactional;
+
import java.util.List;
import java.util.Map;
import java.util.Collection;
@@ -35,10 +43,12 @@
@Slf4j
@RequiredArgsConstructor
@Service
-public class QmJudgeServiceImpl implements IQmJudgeService {
+public class QmJudgeServiceImpl implements IQmJudgeService, JudgeService {
private final QmJudgeMapper baseMapper;
private final QmStdMapper qmStdMapper;
+ private final QmCheckitemMapper qmCheckitemMapper;
+ private final QmJudgeDetailsMapper qmJudgeDetailsMapper;
/**
* 鏌ヨ鍒ゅ畾渚濇嵁
@@ -127,12 +137,52 @@
* @return 鏄惁鏂板鎴愬姛
*/
@Override
+ @Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(QmJudgeBo bo) {
QmJudge add = MapstructUtils.convert(bo, QmJudge.class);
+ if (add.getCdate() == null) {
+ add.setCdate(new java.util.Date());
+ }
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
if (flag) {
bo.setId(add.getId());
+
+ // 1. 鏍规嵁 stdCod 鏌ヨ鍚敤鐨勮绋嬫楠岄」鐩�
+ LambdaQueryWrapper<QmCheckitem> itemLqw = Wrappers.lambdaQuery();
+ itemLqw.eq(QmCheckitem::getStdCode, bo.getStdCod());
+ itemLqw.eq(QmCheckitem::getEnable, 1L);
+ itemLqw.ne(QmCheckitem::getDel, 1L);
+ List<QmCheckitem> checkitems = qmCheckitemMapper.selectList(itemLqw);
+
+ if (!checkitems.isEmpty()) {
+ List<QmJudgeDetails> detailsList = checkitems.stream().map(item -> {
+ QmJudgeDetails detail = new QmJudgeDetails();
+ detail.setJudgeId(add.getId());
+ detail.setItemCod(item.getId());
+ detail.setItemName(item.getItemName());
+ detail.setValue3(0.0);
+ detail.setValue1(0.0);
+ detail.setValue2(0.0);
+ detail.setLocation(item.getLocation());
+ detail.setCls(item.getCheckLevel());
+ detail.setStdscore(item.getScore() != null ? item.getScore() : 0.0);
+ detail.setIsmix(item.getIsmix() != null ? item.getIsmix() : 0L);
+ detail.setRid(item.getRid());
+ detail.setCategory(item.getCategory());
+ detail.setDecisionDes(item.getItemDes());
+ return detail;
+ }).collect(Collectors.toList());
+ qmJudgeDetailsMapper.insertBatch(detailsList);
+ }
+
+ // 2. 灏嗗師鏉ュ瓨鍦ㄧ殑鐩稿悓鐗╂枡鐗屽彿鍜岀被鍨嬬殑渚濇嵁璁剧疆涓虹鐢�
+ LambdaUpdateWrapper<QmJudge> updateWrapper = Wrappers.lambdaUpdate();
+ updateWrapper.set(QmJudge::getStatus, 0L)
+ .eq(QmJudge::getMatCode, bo.getMatCode())
+ .eq(QmJudge::getCategory, bo.getCategory())
+ .ne(QmJudge::getId, add.getId());
+ baseMapper.update(null, updateWrapper);
}
return flag;
}
@@ -171,4 +221,13 @@
}
return baseMapper.deleteByIds(ids) > 0;
}
+
+ @Override
+ public String selectJudgeNameByCode(String judgeCode) {
+ QmJudgeVo qmJudgeVo = baseMapper.selectVoById(judgeCode);
+ if(qmJudgeVo!=null){
+ return qmJudgeVo.getJudgeName();
+ }
+ return null;
+ }
}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmMatcheckServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmMatcheckServiceImpl.java
new file mode 100644
index 0000000..721519d
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/qm/service/impl/QmMatcheckServiceImpl.java
@@ -0,0 +1,154 @@
+package org.dromara.qa.qm.service.impl;
+
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.qa.qm.domain.bo.QmMatcheckBo;
+import org.dromara.qa.qm.domain.vo.QmMatcheckVo;
+import org.dromara.qa.qm.domain.QmMatcheck;
+import org.dromara.qa.qm.mapper.QmMatcheckMapper;
+import org.dromara.qa.qm.service.IQmMatcheckService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 鏉愭枡妫�楠岀粺璁ervice涓氬姟灞傚鐞�
+ *
+ * @author zhuguifei
+ * @date 2026-04-15
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class QmMatcheckServiceImpl implements IQmMatcheckService {
+
+ private final QmMatcheckMapper baseMapper;
+
+ /**
+ * 鏌ヨ鏉愭枡妫�楠岀粺璁�
+ *
+ * @param id 涓婚敭
+ * @return 鏉愭枡妫�楠岀粺璁�
+ */
+ @Override
+ public QmMatcheckVo queryById(String id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 鍒嗛〉鏌ヨ鏉愭枡妫�楠岀粺璁″垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鏉愭枡妫�楠岀粺璁″垎椤靛垪琛�
+ */
+ @Override
+ public TableDataInfo<QmMatcheckVo> queryPageList(QmMatcheckBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper<QmMatcheck> lqw = buildQueryWrapper(bo);
+ Page<QmMatcheckVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勬潗鏂欐楠岀粺璁″垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ @Override
+ public List<QmMatcheckVo> queryList(QmMatcheckBo bo) {
+ LambdaQueryWrapper<QmMatcheck> lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper<QmMatcheck> buildQueryWrapper(QmMatcheckBo bo) {
+ LambdaQueryWrapper<QmMatcheck> lqw = Wrappers.lambdaQuery();
+ lqw.like(StringUtils.isNotBlank(bo.getBatchCode()), QmMatcheck::getBatchCode, bo.getBatchCode());
+ lqw.eq(StringUtils.isNotBlank(bo.getMatCode()), QmMatcheck::getMatCode, bo.getMatCode());
+ lqw.like(StringUtils.isNotBlank(bo.getCheckName()), QmMatcheck::getCheckName, bo.getCheckName());
+ return lqw;
+ }
+
+ /**
+ * 鏂板鏉愭枡妫�楠岀粺璁�
+ *
+ * @param bo 鏉愭枡妫�楠岀粺璁�
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ @Override
+ public Boolean insertByBo(QmMatcheckBo bo) {
+ QmMatcheck add = MapstructUtils.convert(bo, QmMatcheck.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 淇敼鏉愭枡妫�楠岀粺璁�
+ *
+ * @param bo 鏉愭枡妫�楠岀粺璁�
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ @Override
+ public Boolean updateByBo(QmMatcheckBo bo) {
+ QmMatcheck update = MapstructUtils.convert(bo, QmMatcheck.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+ */
+ private void validEntityBeforeSave(QmMatcheck entity){
+ //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+ }
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ゆ潗鏂欐楠岀粺璁′俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
+ if(isValid){
+ //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+
+ /**
+ * 鑾峰彇妫�楠岄」鐩�
+ *
+ * @param judgeId 鍒ゅ畾ID
+ * @return 妫�楠岄」鐩垪琛�
+ */
+ @Override
+ public List<Map<String, Object>> getQmCheckItem(String judgeId) {
+ return baseMapper.getQmCheckItem(judgeId);
+ }
+
+ /**
+ * 鎸夋壒娆″拰鐗屽彿鏌ヨ鏉愭枡妫�楠岀粺璁�(澶氳〃)
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鏉愭枡妫�楠岀粺璁″垪琛�
+ */
+ @Override
+ public List<QmMatcheckVo> listQmMatcheck(QmMatcheckBo bo) {
+ return baseMapper.listQmMatcheck(bo);
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatController.java
new file mode 100644
index 0000000..038b934
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatController.java
@@ -0,0 +1,105 @@
+package org.dromara.sc.md.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.sc.md.domain.vo.MdMatVo;
+import org.dromara.sc.md.domain.bo.MdMatBo;
+import org.dromara.sc.md.service.IMdMatService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 鐗╂枡
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/md/mat")
+public class MdMatController extends BaseController {
+
+ private final IMdMatService mdMatService;
+
+ /**
+ * 鏌ヨ鐗╂枡鍒楄〃
+ */
+ @SaCheckPermission("md:mat:list")
+ @GetMapping("/list")
+ public TableDataInfo<MdMatVo> list(MdMatBo bo, PageQuery pageQuery) {
+ return mdMatService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 瀵煎嚭鐗╂枡鍒楄〃
+ */
+ @SaCheckPermission("md:mat:export")
+ @Log(title = "鐗╂枡", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(MdMatBo bo, HttpServletResponse response) {
+ List<MdMatVo> list = mdMatService.queryList(bo);
+ ExcelUtil.exportExcel(list, "鐗╂枡", MdMatVo.class, response);
+ }
+
+ /**
+ * 鑾峰彇鐗╂枡璇︾粏淇℃伅
+ *
+ * @param id 涓婚敭
+ */
+ @SaCheckPermission("md:mat:query")
+ @GetMapping("/{id}")
+ public R<MdMatVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String id) {
+ return R.ok(mdMatService.queryById(id));
+ }
+
+ /**
+ * 鏂板鐗╂枡
+ */
+ @SaCheckPermission("md:mat:add")
+ @Log(title = "鐗╂枡", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R<Void> add(@Validated(AddGroup.class) @RequestBody MdMatBo bo) {
+ return toAjax(mdMatService.insertByBo(bo));
+ }
+
+ /**
+ * 淇敼鐗╂枡
+ */
+ @SaCheckPermission("md:mat:edit")
+ @Log(title = "鐗╂枡", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R<Void> edit(@Validated(EditGroup.class) @RequestBody MdMatBo bo) {
+ return toAjax(mdMatService.updateByBo(bo));
+ }
+
+ /**
+ * 鍒犻櫎鐗╂枡
+ *
+ * @param ids 涓婚敭涓�
+ */
+ @SaCheckPermission("md:mat:remove")
+ @Log(title = "鐗╂枡", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String[] ids) {
+ return toAjax(mdMatService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatTypeController.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatTypeController.java
new file mode 100644
index 0000000..2729d63
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/controller/MdMatTypeController.java
@@ -0,0 +1,105 @@
+package org.dromara.sc.md.controller;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.sc.md.domain.vo.MdMatTypeVo;
+import org.dromara.sc.md.domain.bo.MdMatTypeBo;
+import org.dromara.sc.md.service.IMdMatTypeService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 鐗╂枡绫诲瀷
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/md/matType")
+public class MdMatTypeController extends BaseController {
+
+ private final IMdMatTypeService mdMatTypeService;
+
+ /**
+ * 鏌ヨ鐗╂枡绫诲瀷鍒楄〃
+ */
+ @SaCheckPermission("md:matType:list")
+ @GetMapping("/list")
+ public TableDataInfo<MdMatTypeVo> list(MdMatTypeBo bo, PageQuery pageQuery) {
+ return mdMatTypeService.queryPageList(bo, pageQuery);
+ }
+
+ /**
+ * 瀵煎嚭鐗╂枡绫诲瀷鍒楄〃
+ */
+ @SaCheckPermission("md:matType:export")
+ @Log(title = "鐗╂枡绫诲瀷", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(MdMatTypeBo bo, HttpServletResponse response) {
+ List<MdMatTypeVo> list = mdMatTypeService.queryList(bo);
+ ExcelUtil.exportExcel(list, "鐗╂枡绫诲瀷", MdMatTypeVo.class, response);
+ }
+
+ /**
+ * 鑾峰彇鐗╂枡绫诲瀷璇︾粏淇℃伅
+ *
+ * @param id 涓婚敭
+ */
+ @SaCheckPermission("md:matType:query")
+ @GetMapping("/{id}")
+ public R<MdMatTypeVo> getInfo(@NotNull(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String id) {
+ return R.ok(mdMatTypeService.queryById(id));
+ }
+
+ /**
+ * 鏂板鐗╂枡绫诲瀷
+ */
+ @SaCheckPermission("md:matType:add")
+ @Log(title = "鐗╂枡绫诲瀷", businessType = BusinessType.INSERT)
+ @RepeatSubmit()
+ @PostMapping()
+ public R<Void> add(@Validated(AddGroup.class) @RequestBody MdMatTypeBo bo) {
+ return toAjax(mdMatTypeService.insertByBo(bo));
+ }
+
+ /**
+ * 淇敼鐗╂枡绫诲瀷
+ */
+ @SaCheckPermission("md:matType:edit")
+ @Log(title = "鐗╂枡绫诲瀷", businessType = BusinessType.UPDATE)
+ @RepeatSubmit()
+ @PutMapping()
+ public R<Void> edit(@Validated(EditGroup.class) @RequestBody MdMatTypeBo bo) {
+ return toAjax(mdMatTypeService.updateByBo(bo));
+ }
+
+ /**
+ * 鍒犻櫎鐗╂枡绫诲瀷
+ *
+ * @param ids 涓婚敭涓�
+ */
+ @SaCheckPermission("md:matType:remove")
+ @Log(title = "鐗╂枡绫诲瀷", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public R<Void> remove(@NotEmpty(message = "涓婚敭涓嶈兘涓虹┖")
+ @PathVariable String[] ids) {
+ return toAjax(mdMatTypeService.deleteWithValidByIds(List.of(ids), true));
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMat.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMat.java
new file mode 100644
index 0000000..389590c
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMat.java
@@ -0,0 +1,97 @@
+package org.dromara.sc.md.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 鐗╂枡瀵硅薄 MD_MAT
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@TableName("MD_MAT")
+public class MdMat {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "ID")
+ private String id;
+
+ /**
+ * 鐗╂枡浠g爜
+ */
+ private String code;
+
+ /**
+ * 鍏ㄧО
+ */
+ private String name;
+
+ /**
+ * 绠�绉�
+ */
+ private String simpleName;
+
+ /**
+ * 鎻忚堪
+ */
+ private String des;
+
+ /**
+ * 鍗曚綅
+ */
+ private String uid;
+
+ /**
+ * 鏈�鍚庢洿鏂版椂闂�
+ */
+ private Date lastUpdateTime;
+
+ /**
+ * 鍚敤
+ */
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ private String del;
+
+ /**
+ * 鐗╂枡绫诲瀷
+ */
+ private String tid;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMatType.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMatType.java
new file mode 100644
index 0000000..273e37f
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/MdMatType.java
@@ -0,0 +1,87 @@
+package org.dromara.sc.md.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.io.Serial;
+
+/**
+ * 鐗╂枡绫诲瀷瀵硅薄 MD_MAT_TYPE
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@TableName("MD_MAT_TYPE")
+public class MdMatType {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @TableId(value = "ID")
+ private String id;
+
+ /**
+ * 鐗╂枡缁勫閿�
+ */
+ private String gid;
+
+ /**
+ * 缂栫爜
+ */
+ private String code;
+
+ /**
+ * 鍚嶇О
+ */
+ private String name;
+
+ /**
+ * 鎻忚堪
+ */
+ private String des;
+
+ /**
+ * 鍚敤
+ */
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ private String del;
+
+ /**
+ * mes缂栫爜
+ */
+ private String mesCode;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatBo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatBo.java
new file mode 100644
index 0000000..8937469
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatBo.java
@@ -0,0 +1,97 @@
+package org.dromara.sc.md.domain.bo;
+
+import org.dromara.sc.md.domain.MdMat;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 鐗╂枡涓氬姟瀵硅薄 MD_MAT
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MdMat.class, reverseConvertGenerate = false)
+public class MdMatBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ @NotBlank(message = "id涓嶈兘涓虹┖", groups = { EditGroup.class })
+ private String id;
+
+ /**
+ * 鐗╂枡浠g爜
+ */
+ private String code;
+
+ /**
+ * 鍏ㄧО
+ */
+ private String name;
+
+ /**
+ * 绠�绉�
+ */
+ private String simpleName;
+
+ /**
+ * 鎻忚堪
+ */
+ private String des;
+
+ /**
+ * 鍗曚綅
+ */
+ private String uid;
+
+ /**
+ * 鏈�鍚庢洿鏂版椂闂�
+ */
+ private Date lastUpdateTime;
+
+ /**
+ * 鍚敤
+ */
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ private String del;
+
+ /**
+ * 鐗╂枡绫诲瀷
+ */
+ private String tid;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatTypeBo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatTypeBo.java
new file mode 100644
index 0000000..570defe
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/bo/MdMatTypeBo.java
@@ -0,0 +1,87 @@
+package org.dromara.sc.md.domain.bo;
+
+import org.dromara.sc.md.domain.MdMatType;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+/**
+ * 鐗╂枡绫诲瀷涓氬姟瀵硅薄 MD_MAT_TYPE
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MdMatType.class, reverseConvertGenerate = false)
+public class MdMatTypeBo extends BaseEntity {
+
+ /**
+ * id
+ */
+ @NotBlank(message = "id涓嶈兘涓虹┖", groups = { EditGroup.class })
+ private String id;
+
+ /**
+ * 鐗╂枡缁勫閿�
+ */
+ private String gid;
+
+ /**
+ * 缂栫爜
+ */
+ private String code;
+
+ /**
+ * 鍚嶇О
+ */
+ private String name;
+
+ /**
+ * 鎻忚堪
+ */
+ private String des;
+
+ /**
+ * 鍚敤
+ */
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ private String del;
+
+ /**
+ * mes缂栫爜
+ */
+ private String mesCode;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatTypeVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatTypeVo.java
new file mode 100644
index 0000000..e84d889
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatTypeVo.java
@@ -0,0 +1,106 @@
+package org.dromara.sc.md.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.sc.md.domain.MdMatType;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 鐗╂枡绫诲瀷瑙嗗浘瀵硅薄 MD_MAT_TYPE
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = MdMatType.class)
+public class MdMatTypeVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private String id;
+
+ /**
+ * 鐗╂枡缁勫閿�
+ */
+ @ExcelProperty(value = "鐗╂枡缁勫閿�")
+ private String gid;
+
+ /**
+ * 缂栫爜
+ */
+ @ExcelProperty(value = "缂栫爜")
+ private String code;
+
+ /**
+ * 鍚嶇О
+ */
+ @ExcelProperty(value = "鍚嶇О")
+ private String name;
+
+ /**
+ * 鎻忚堪
+ */
+ @ExcelProperty(value = "鎻忚堪")
+ private String des;
+
+ /**
+ * 鍚敤
+ */
+ @ExcelProperty(value = "鍚敤")
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ @ExcelProperty(value = "鍒犻櫎")
+ private String del;
+
+ /**
+ * mes缂栫爜
+ */
+ @ExcelProperty(value = "mes缂栫爜")
+ private String mesCode;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ExcelProperty(value = "鍒涘缓浜�")
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ExcelProperty(value = "鍒涘缓鏃堕棿")
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @ExcelProperty(value = "鏇存柊浜�")
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @ExcelProperty(value = "鏇存柊鏃堕棿")
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatVo.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatVo.java
new file mode 100644
index 0000000..56be849
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/domain/vo/MdMatVo.java
@@ -0,0 +1,118 @@
+package org.dromara.sc.md.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.sc.md.domain.MdMat;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 鐗╂枡瑙嗗浘瀵硅薄 MD_MAT
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = MdMat.class)
+public class MdMatVo implements Serializable {
+
+ @Serial
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * id
+ */
+ @ExcelProperty(value = "id")
+ private String id;
+
+ /**
+ * 鐗╂枡浠g爜
+ */
+ @ExcelProperty(value = "鐗╂枡浠g爜")
+ private String code;
+
+ /**
+ * 鍏ㄧО
+ */
+ @ExcelProperty(value = "鍏ㄧО")
+ private String name;
+
+ /**
+ * 绠�绉�
+ */
+ @ExcelProperty(value = "绠�绉�")
+ private String simpleName;
+
+ /**
+ * 鎻忚堪
+ */
+ @ExcelProperty(value = "鎻忚堪")
+ private String des;
+
+ /**
+ * 鍗曚綅
+ */
+ @ExcelProperty(value = "鍗曚綅")
+ private String uid;
+
+ /**
+ * 鏈�鍚庢洿鏂版椂闂�
+ */
+ @ExcelProperty(value = "鏈�鍚庢洿鏂版椂闂�")
+ private Date lastUpdateTime;
+
+ /**
+ * 鍚敤
+ */
+ @ExcelProperty(value = "鍚敤")
+ private Long enable;
+
+ /**
+ * 鍒犻櫎
+ */
+ @ExcelProperty(value = "鍒犻櫎")
+ private String del;
+
+ /**
+ * 鐗╂枡绫诲瀷
+ */
+ @ExcelProperty(value = "鐗╂枡绫诲瀷")
+ private String tid;
+
+ /**
+ * 鍒涘缓浜�
+ */
+ @ExcelProperty(value = "鍒涘缓浜�")
+ private String createUserName;
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ @ExcelProperty(value = "鍒涘缓鏃堕棿")
+ private Date createUserTime;
+
+ /**
+ * 鏇存柊浜�
+ */
+ @ExcelProperty(value = "鏇存柊浜�")
+ private String updateUserName;
+
+ /**
+ * 鏇存柊鏃堕棿
+ */
+ @ExcelProperty(value = "鏇存柊鏃堕棿")
+ private Date updateUserTime;
+
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatMapper.java
new file mode 100644
index 0000000..0c41b40
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.sc.md.mapper;
+
+import org.dromara.sc.md.domain.MdMat;
+import org.dromara.sc.md.domain.vo.MdMatVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 鐗╂枡Mapper鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+public interface MdMatMapper extends BaseMapperPlus<MdMat, MdMatVo> {
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatTypeMapper.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatTypeMapper.java
new file mode 100644
index 0000000..2e962df
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/mapper/MdMatTypeMapper.java
@@ -0,0 +1,15 @@
+package org.dromara.sc.md.mapper;
+
+import org.dromara.sc.md.domain.MdMatType;
+import org.dromara.sc.md.domain.vo.MdMatTypeVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 鐗╂枡绫诲瀷Mapper鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+public interface MdMatTypeMapper extends BaseMapperPlus<MdMatType, MdMatTypeVo> {
+
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatService.java
new file mode 100644
index 0000000..0b9c397
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatService.java
@@ -0,0 +1,68 @@
+package org.dromara.sc.md.service;
+
+import org.dromara.sc.md.domain.vo.MdMatVo;
+import org.dromara.sc.md.domain.bo.MdMatBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 鐗╂枡Service鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+public interface IMdMatService {
+
+ /**
+ * 鏌ヨ鐗╂枡
+ *
+ * @param id 涓婚敭
+ * @return 鐗╂枡
+ */
+ MdMatVo queryById(String id);
+
+ /**
+ * 鍒嗛〉鏌ヨ鐗╂枡鍒楄〃
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鐗╂枡鍒嗛〉鍒楄〃
+ */
+ TableDataInfo<MdMatVo> queryPageList(MdMatBo bo, PageQuery pageQuery);
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勭墿鏂欏垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鐗╂枡鍒楄〃
+ */
+ List<MdMatVo> queryList(MdMatBo bo);
+
+ /**
+ * 鏂板鐗╂枡
+ *
+ * @param bo 鐗╂枡
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ Boolean insertByBo(MdMatBo bo);
+
+ /**
+ * 淇敼鐗╂枡
+ *
+ * @param bo 鐗╂枡
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ Boolean updateByBo(MdMatBo bo);
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ょ墿鏂欎俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatTypeService.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatTypeService.java
new file mode 100644
index 0000000..ac89e41
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/IMdMatTypeService.java
@@ -0,0 +1,68 @@
+package org.dromara.sc.md.service;
+
+import org.dromara.sc.md.domain.vo.MdMatTypeVo;
+import org.dromara.sc.md.domain.bo.MdMatTypeBo;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 鐗╂枡绫诲瀷Service鎺ュ彛
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+public interface IMdMatTypeService {
+
+ /**
+ * 鏌ヨ鐗╂枡绫诲瀷
+ *
+ * @param id 涓婚敭
+ * @return 鐗╂枡绫诲瀷
+ */
+ MdMatTypeVo queryById(String id);
+
+ /**
+ * 鍒嗛〉鏌ヨ鐗╂枡绫诲瀷鍒楄〃
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鐗╂枡绫诲瀷鍒嗛〉鍒楄〃
+ */
+ TableDataInfo<MdMatTypeVo> queryPageList(MdMatTypeBo bo, PageQuery pageQuery);
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勭墿鏂欑被鍨嬪垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鐗╂枡绫诲瀷鍒楄〃
+ */
+ List<MdMatTypeVo> queryList(MdMatTypeBo bo);
+
+ /**
+ * 鏂板鐗╂枡绫诲瀷
+ *
+ * @param bo 鐗╂枡绫诲瀷
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ Boolean insertByBo(MdMatTypeBo bo);
+
+ /**
+ * 淇敼鐗╂枡绫诲瀷
+ *
+ * @param bo 鐗╂枡绫诲瀷
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ Boolean updateByBo(MdMatTypeBo bo);
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ょ墿鏂欑被鍨嬩俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatServiceImpl.java
new file mode 100644
index 0000000..1575845
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatServiceImpl.java
@@ -0,0 +1,147 @@
+package org.dromara.sc.md.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import org.dromara.common.core.service.MatService;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.sc.md.domain.bo.MdMatBo;
+import org.dromara.sc.md.domain.vo.MdMatVo;
+import org.dromara.sc.md.domain.MdMat;
+import org.dromara.sc.md.mapper.MdMatMapper;
+import org.dromara.sc.md.service.IMdMatService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 鐗╂枡Service涓氬姟灞傚鐞�
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@DS("oracle_sc")
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MdMatServiceImpl implements IMdMatService, MatService {
+
+ private final MdMatMapper baseMapper;
+
+ /**
+ * 鏌ヨ鐗╂枡
+ *
+ * @param id 涓婚敭
+ * @return 鐗╂枡
+ */
+ @Override
+ public MdMatVo queryById(String id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 鍒嗛〉鏌ヨ鐗╂枡鍒楄〃
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鐗╂枡鍒嗛〉鍒楄〃
+ */
+ @Override
+ public TableDataInfo<MdMatVo> queryPageList(MdMatBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper<MdMat> lqw = buildQueryWrapper(bo);
+ Page<MdMatVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勭墿鏂欏垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鐗╂枡鍒楄〃
+ */
+ @Override
+ public List<MdMatVo> queryList(MdMatBo bo) {
+ LambdaQueryWrapper<MdMat> lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper<MdMat> buildQueryWrapper(MdMatBo bo) {
+ Map<String, Object> params = bo.getParams();
+ LambdaQueryWrapper<MdMat> lqw = Wrappers.lambdaQuery();
+ lqw.orderByAsc(MdMat::getId);
+ lqw.eq(StringUtils.isNotBlank(bo.getCode()), MdMat::getCode, bo.getCode());
+ lqw.like(StringUtils.isNotBlank(bo.getName()), MdMat::getName, bo.getName());
+ lqw.like(StringUtils.isNotBlank(bo.getSimpleName()), MdMat::getSimpleName, bo.getSimpleName());
+ lqw.eq(bo.getEnable() != null, MdMat::getEnable, bo.getEnable());
+ lqw.eq(StringUtils.isNotBlank(bo.getTid()), MdMat::getTid, bo.getTid());
+ return lqw;
+ }
+
+ /**
+ * 鏂板鐗╂枡
+ *
+ * @param bo 鐗╂枡
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ @Override
+ public Boolean insertByBo(MdMatBo bo) {
+ MdMat add = MapstructUtils.convert(bo, MdMat.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 淇敼鐗╂枡
+ *
+ * @param bo 鐗╂枡
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ @Override
+ public Boolean updateByBo(MdMatBo bo) {
+ MdMat update = MapstructUtils.convert(bo, MdMat.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+ */
+ private void validEntityBeforeSave(MdMat entity){
+ //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+ }
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ょ墿鏂欎俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
+ if(isValid){
+ //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+
+ @Override
+ public String selectMatNameByCode(String matCode) {
+ LambdaQueryWrapper<MdMat> lqw = Wrappers.lambdaQuery();
+ lqw.eq(MdMat::getCode,matCode);
+ MdMatVo mdMatVo = baseMapper.selectVoOne(lqw);
+ return mdMatVo.getName();
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatTypeServiceImpl.java b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatTypeServiceImpl.java
new file mode 100644
index 0000000..8a43315
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/md/service/impl/MdMatTypeServiceImpl.java
@@ -0,0 +1,138 @@
+package org.dromara.sc.md.service.impl;
+
+import com.baomidou.dynamic.datasource.annotation.DS;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.dromara.sc.md.domain.bo.MdMatTypeBo;
+import org.dromara.sc.md.domain.vo.MdMatTypeVo;
+import org.dromara.sc.md.domain.MdMatType;
+import org.dromara.sc.md.mapper.MdMatTypeMapper;
+import org.dromara.sc.md.service.IMdMatTypeService;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Collection;
+
+/**
+ * 鐗╂枡绫诲瀷Service涓氬姟灞傚鐞�
+ *
+ * @author zhuguifei
+ * @date 2026-04-13
+ */
+@DS("oracle_sc")
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class MdMatTypeServiceImpl implements IMdMatTypeService {
+
+ private final MdMatTypeMapper baseMapper;
+
+ /**
+ * 鏌ヨ鐗╂枡绫诲瀷
+ *
+ * @param id 涓婚敭
+ * @return 鐗╂枡绫诲瀷
+ */
+ @Override
+ public MdMatTypeVo queryById(String id){
+ return baseMapper.selectVoById(id);
+ }
+
+ /**
+ * 鍒嗛〉鏌ヨ鐗╂枡绫诲瀷鍒楄〃
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @param pageQuery 鍒嗛〉鍙傛暟
+ * @return 鐗╂枡绫诲瀷鍒嗛〉鍒楄〃
+ */
+ @Override
+ public TableDataInfo<MdMatTypeVo> queryPageList(MdMatTypeBo bo, PageQuery pageQuery) {
+ LambdaQueryWrapper<MdMatType> lqw = buildQueryWrapper(bo);
+ Page<MdMatTypeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+ return TableDataInfo.build(result);
+ }
+
+ /**
+ * 鏌ヨ绗﹀悎鏉′欢鐨勭墿鏂欑被鍨嬪垪琛�
+ *
+ * @param bo 鏌ヨ鏉′欢
+ * @return 鐗╂枡绫诲瀷鍒楄〃
+ */
+ @Override
+ public List<MdMatTypeVo> queryList(MdMatTypeBo bo) {
+ LambdaQueryWrapper<MdMatType> lqw = buildQueryWrapper(bo);
+ return baseMapper.selectVoList(lqw);
+ }
+
+ private LambdaQueryWrapper<MdMatType> buildQueryWrapper(MdMatTypeBo bo) {
+ Map<String, Object> params = bo.getParams();
+ LambdaQueryWrapper<MdMatType> lqw = Wrappers.lambdaQuery();
+ lqw.orderByAsc(MdMatType::getId);
+ lqw.like(StringUtils.isNotBlank(bo.getCode()), MdMatType::getCode, bo.getCode());
+ lqw.like(StringUtils.isNotBlank(bo.getName()), MdMatType::getName, bo.getName());
+ lqw.eq(bo.getEnable() != null, MdMatType::getEnable, bo.getEnable());
+ lqw.eq(StringUtils.isNotBlank(bo.getDel()), MdMatType::getDel, bo.getDel());
+ lqw.like(StringUtils.isNotBlank(bo.getMesCode()), MdMatType::getMesCode, bo.getMesCode());
+ return lqw;
+ }
+
+ /**
+ * 鏂板鐗╂枡绫诲瀷
+ *
+ * @param bo 鐗╂枡绫诲瀷
+ * @return 鏄惁鏂板鎴愬姛
+ */
+ @Override
+ public Boolean insertByBo(MdMatTypeBo bo) {
+ MdMatType add = MapstructUtils.convert(bo, MdMatType.class);
+ validEntityBeforeSave(add);
+ boolean flag = baseMapper.insert(add) > 0;
+ if (flag) {
+ bo.setId(add.getId());
+ }
+ return flag;
+ }
+
+ /**
+ * 淇敼鐗╂枡绫诲瀷
+ *
+ * @param bo 鐗╂枡绫诲瀷
+ * @return 鏄惁淇敼鎴愬姛
+ */
+ @Override
+ public Boolean updateByBo(MdMatTypeBo bo) {
+ MdMatType update = MapstructUtils.convert(bo, MdMatType.class);
+ validEntityBeforeSave(update);
+ return baseMapper.updateById(update) > 0;
+ }
+
+ /**
+ * 淇濆瓨鍓嶇殑鏁版嵁鏍¢獙
+ */
+ private void validEntityBeforeSave(MdMatType entity){
+ //TODO 鍋氫竴浜涙暟鎹牎楠�,濡傚敮涓�绾︽潫
+ }
+
+ /**
+ * 鏍¢獙骞舵壒閲忓垹闄ょ墿鏂欑被鍨嬩俊鎭�
+ *
+ * @param ids 寰呭垹闄ょ殑涓婚敭闆嗗悎
+ * @param isValid 鏄惁杩涜鏈夋晥鎬ф牎楠�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ @Override
+ public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
+ if(isValid){
+ //TODO 鍋氫竴浜涗笟鍔′笂鐨勬牎楠�,鍒ゆ柇鏄惁闇�瑕佹牎楠�
+ }
+ return baseMapper.deleteByIds(ids) > 0;
+ }
+}
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/test b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/sc/test
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/qm/QmMatcheckMapper.xml b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/qm/QmMatcheckMapper.xml
new file mode 100644
index 0000000..180a1a7
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/qm/QmMatcheckMapper.xml
@@ -0,0 +1,67 @@
+<?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="org.dromara.qa.qm.mapper.QmMatcheckMapper">
+
+ <select id="listQmMatcheck" resultType="org.dromara.qa.qm.domain.vo.QmMatcheckVo">
+ SELECT
+ a.ID AS id,
+ a.PID AS pid,
+ a.BATCH_CODE AS batchCode,
+ a.MAT_CODE AS matCode,
+ a.INSTRUMENT_CODE AS instrumentCode,
+ a.TECH_REQ AS techReq,
+ a.CHECK_STD AS checkStd,
+ a.TEST_ENV AS testEnv,
+ a.ITEM_CODE AS itemCode,
+ d.ITEM_NAME AS itemName,
+ CAST(NULL AS VARCHAR(100)) AS eqp,
+ a.SUB_BATCH_CODE AS subBatchCode,
+ a.SAMPLE_NUMBER AS sampleNumber,
+ a.SAMPLE_TYPE AS sampleType,
+ a.CHECK_NAME AS checkName,
+ a.CHECK_TIME AS checkTime,
+ a.REVIEW_NAME AS reviewName,
+ a.REVIEW_TIME AS reviewTime,
+ a.MAXVAL AS maxval,
+ a.MINVAL AS minval,
+ a.AVGVAL AS avgval,
+ a.SDVAL AS sdval,
+ a.CVVAL AS cvval,
+ a.CPKVAL AS cpkval,
+ a.BADVAL AS badval,
+ a.JUDGE AS judge,
+ a.SINGLEJUDGE AS singlejudge,
+ a.VER_NAME AS verName,
+ a.VER_CODE AS verCode,
+ a.ARCH_DATE AS archDate,
+ a.DEL AS del,
+ a.FLAG AS flag,
+ a.TO_MES_TIME AS toMesTime,
+ a.CHK_DES AS chkDes,
+ CAST(NULL AS VARCHAR(200)) AS checker,
+ b.JUDGE_CODE AS judgeCode,
+ CAST(NULL AS VARCHAR(10)) AS generateDetails,
+ CAST(NULL AS VARCHAR(10)) AS checkType
+ FROM QM_MATCHECK a
+ JOIN QM_BATCH b ON b.BATCH_CODE = a.BATCH_CODE
+ AND b.MAT_CODE = a.MAT_CODE
+ JOIN QM_JUDGE c ON b.JUDGE_CODE = c.ID
+ JOIN QM_CHECKITEM d ON d.STD_CODE = c.STD_COD
+ AND d.ITEM_CODE = a.ITEM_CODE
+ AND d.RID IS NULL
+ AND d.DEL != 1
+ <where>
+ <if test="bo.batchCode != null and bo.batchCode != ''">
+ AND a.BATCH_CODE = #{bo.batchCode}
+ </if>
+ <if test="bo.matCode != null and bo.matCode != ''">
+ AND a.MAT_CODE = #{bo.matCode}
+ </if>
+ AND (a.DEL = 0 OR a.DEL IS NULL)
+ AND b.DELETED != '1'
+ </where>
+ ORDER BY a.ITEM_CODE, a.SUB_BATCH_CODE
+ </select>
+</mapper>
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatMapper.xml b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatMapper.xml
new file mode 100644
index 0000000..afb20ab
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatMapper.xml
@@ -0,0 +1,6 @@
+<?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="org.dromara.sc.md.mapper.MdMatMapper">
+</mapper>
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatTypeMapper.xml b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatTypeMapper.xml
new file mode 100644
index 0000000..5659381
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/md/MdMatTypeMapper.xml
@@ -0,0 +1,6 @@
+<?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="org.dromara.sc.md.mapper.MdMatTypeMapper">
+</mapper>
diff --git a/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/test b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/sc/test
diff --git a/ruoyi-plus-soybean/src/router/elegant/imports.ts b/ruoyi-plus-soybean/src/router/elegant/imports.ts
index 4639592..6e4b3ff 100755
--- a/ruoyi-plus-soybean/src/router/elegant/imports.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/imports.ts
@@ -33,6 +33,8 @@
demo_tree: () => import("@/views/demo/tree/index.vue"),
home: () => import("@/views/home/index.vue"),
md_instrument: () => import("@/views/md/instrument/index.vue"),
+ "md_mat-type": () => import("@/views/md/mat-type/index.vue"),
+ md_mat: () => import("@/views/md/mat/index.vue"),
md_shift: () => import("@/views/md/shift/index.vue"),
"md_weighing-box": () => import("@/views/md/weighing-box/index.vue"),
monitor_cache: () => import("@/views/monitor/cache/index.vue"),
@@ -42,6 +44,7 @@
qm_batch: () => import("@/views/qm/batch/index.vue"),
"qm_judge-details": () => import("@/views/qm/judge-details/index.vue"),
qm_judge: () => import("@/views/qm/judge/index.vue"),
+ qm_matcheck: () => import("@/views/qm/matcheck/index.vue"),
qm_std: () => import("@/views/qm/std/index.vue"),
report_demo: () => import("@/views/report/demo/index.vue"),
"report_silk-storage-output": () => import("@/views/report/silk-storage-output/index.vue"),
diff --git a/ruoyi-plus-soybean/src/router/elegant/routes.ts b/ruoyi-plus-soybean/src/router/elegant/routes.ts
index 2fadf2c..0d1d1ce 100755
--- a/ruoyi-plus-soybean/src/router/elegant/routes.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/routes.ts
@@ -199,6 +199,24 @@
}
},
{
+ name: 'md_mat',
+ path: '/md/mat',
+ component: 'view.md_mat',
+ meta: {
+ title: 'md_mat',
+ i18nKey: 'route.md_mat'
+ }
+ },
+ {
+ name: 'md_mat-type',
+ path: '/md/mat-type',
+ component: 'view.md_mat-type',
+ meta: {
+ title: 'md_mat-type',
+ i18nKey: 'route.md_mat-type'
+ }
+ },
+ {
name: 'md_shift',
path: '/md/shift',
component: 'view.md_shift',
@@ -302,6 +320,15 @@
}
},
{
+ name: 'qm_matcheck',
+ path: '/qm/matcheck',
+ component: 'view.qm_matcheck',
+ meta: {
+ title: 'qm_matcheck',
+ i18nKey: 'route.qm_matcheck'
+ }
+ },
+ {
name: 'qm_std',
path: '/qm/std',
component: 'view.qm_std',
diff --git a/ruoyi-plus-soybean/src/router/elegant/transform.ts b/ruoyi-plus-soybean/src/router/elegant/transform.ts
index 4d6dcc9..d2cbbfa 100755
--- a/ruoyi-plus-soybean/src/router/elegant/transform.ts
+++ b/ruoyi-plus-soybean/src/router/elegant/transform.ts
@@ -186,6 +186,8 @@
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
"md": "/md",
"md_instrument": "/md/instrument",
+ "md_mat": "/md/mat",
+ "md_mat-type": "/md/mat-type",
"md_shift": "/md/shift",
"md_weighing-box": "/md/weighing-box",
"monitor": "/monitor",
@@ -197,6 +199,7 @@
"qm_batch": "/qm/batch",
"qm_judge": "/qm/judge",
"qm_judge-details": "/qm/judge-details",
+ "qm_matcheck": "/qm/matcheck",
"qm_std": "/qm/std",
"report": "/report",
"report_demo": "/report/demo",
diff --git a/ruoyi-plus-soybean/src/service/api/md/mat-type.ts b/ruoyi-plus-soybean/src/service/api/md/mat-type.ts
new file mode 100644
index 0000000..da2cdd3
--- /dev/null
+++ b/ruoyi-plus-soybean/src/service/api/md/mat-type.ts
@@ -0,0 +1,35 @@
+import { request } from '@/service/request';
+
+/** 鑾峰彇鐗╂枡绫诲瀷鍒楄〃 */
+export function fetchGetMatTypeList (params?: Api.Md.MatTypeSearchParams) {
+ return request<Api.Md.MatTypeList>({
+ url: '/md/matType/list',
+ method: 'get',
+ params
+ });
+}
+/** 鏂板鐗╂枡绫诲瀷 */
+export function fetchCreateMatType (data: Api.Md.MatTypeOperateParams) {
+ return request<boolean>({
+ url: '/md/matType',
+ method: 'post',
+ data
+ });
+}
+
+/** 淇敼鐗╂枡绫诲瀷 */
+export function fetchUpdateMatType (data: Api.Md.MatTypeOperateParams) {
+ return request<boolean>({
+ url: '/md/matType',
+ method: 'put',
+ data
+ });
+}
+
+/** 鎵归噺鍒犻櫎鐗╂枡绫诲瀷 */
+export function fetchBatchDeleteMatType (ids: CommonType.IdType[]) {
+ return request<boolean>({
+ url: `/md/matType/${ids.join(',')}`,
+ method: 'delete'
+ });
+}
diff --git a/ruoyi-plus-soybean/src/service/api/md/mat.ts b/ruoyi-plus-soybean/src/service/api/md/mat.ts
new file mode 100644
index 0000000..dcd6389
--- /dev/null
+++ b/ruoyi-plus-soybean/src/service/api/md/mat.ts
@@ -0,0 +1,35 @@
+import { request } from '@/service/request';
+
+/** 鑾峰彇鐗╂枡鍒楄〃 */
+export function fetchGetMatList (params?: Api.Md.MatSearchParams) {
+ return request<Api.Md.MatList>({
+ url: '/md/mat/list',
+ method: 'get',
+ params
+ });
+}
+/** 鏂板鐗╂枡 */
+export function fetchCreateMat (data: Api.Md.MatOperateParams) {
+ return request<boolean>({
+ url: '/md/mat',
+ method: 'post',
+ data
+ });
+}
+
+/** 淇敼鐗╂枡 */
+export function fetchUpdateMat (data: Api.Md.MatOperateParams) {
+ return request<boolean>({
+ url: '/md/mat',
+ method: 'put',
+ data
+ });
+}
+
+/** 鎵归噺鍒犻櫎鐗╂枡 */
+export function fetchBatchDeleteMat (ids: CommonType.IdType[]) {
+ return request<boolean>({
+ url: `/md/mat/${ids.join(',')}`,
+ method: 'delete'
+ });
+}
diff --git a/ruoyi-plus-soybean/src/service/api/qm/judge-details.ts b/ruoyi-plus-soybean/src/service/api/qm/judge-details.ts
index 3f180f9..971f037 100644
--- a/ruoyi-plus-soybean/src/service/api/qm/judge-details.ts
+++ b/ruoyi-plus-soybean/src/service/api/qm/judge-details.ts
@@ -8,6 +8,16 @@
params
});
}
+/** 鑾峰彇鍒ゅ畾妯℃澘鏄庣粏鏍戝舰鍒楄〃 */
+export function fetchGetJudgeDetailsTree(params?: Api.Qm.JudgeDetailsSearchParams) {
+ return request<Api.Qm.JudgeDetailsList>({
+ url: '/qm/judgeDetails/tree',
+ method: 'get',
+ params
+ });
+}
+
+
/** 鏂板鍒ゅ畾妯℃澘鏄庣粏 */
export function fetchCreateJudgeDetails(data: Api.Qm.JudgeDetailsOperateParams) {
return request<boolean>({
diff --git a/ruoyi-plus-soybean/src/service/api/qm/matcheck.ts b/ruoyi-plus-soybean/src/service/api/qm/matcheck.ts
new file mode 100644
index 0000000..8353c54
--- /dev/null
+++ b/ruoyi-plus-soybean/src/service/api/qm/matcheck.ts
@@ -0,0 +1,57 @@
+import { request } from '@/service/request';
+
+/** 鑾峰彇鏉愭枡妫�楠岀粺璁″垪琛� */
+export function fetchGetMatcheckList (params?: Api.Qm.MatcheckSearchParams) {
+ return request<Api.Qm.MatcheckList>({
+ url: '/qm/matcheck/list',
+ method: 'get',
+ params
+ });
+}
+
+export function fetchCheckItemList (params?: Api.Qm.MatcheckSearchParams) {
+ return request<Api.Qm.MatcheckCustomItem[]>({
+ url: '/qm/matcheck/listCheckItem',
+ method: 'get',
+ params
+ });
+}
+
+
+/**
+ * 澶氳〃鏌ヨ
+ * @param params
+ */
+export function fetchGetQmMatcheckList (params?: Api.Qm.MatcheckSearchParams) {
+ return request<Api.Qm.MatcheckList[]>({
+ url: '/qm/matcheck/listQmMatcheck',
+ method: 'get',
+ params
+ });
+}
+
+/** 鏂板鏉愭枡妫�楠岀粺璁� */
+export function fetchCreateMatcheck (data: Api.Qm.MatcheckOperateParams) {
+ return request<boolean>({
+ url: '/qm/matcheck',
+ method: 'post',
+ data
+ });
+}
+
+/** 淇敼鏉愭枡妫�楠岀粺璁� */
+export function fetchUpdateMatcheck (data: Api.Qm.MatcheckOperateParams) {
+ return request<boolean>({
+ url: '/qm/matcheck',
+ method: 'put',
+ data
+ });
+}
+
+/** 鎵归噺鍒犻櫎鏉愭枡妫�楠岀粺璁� */
+export function fetchBatchDeleteMatcheck (ids: CommonType.IdType[]) {
+ return request<boolean>({
+ url: `/qm/matcheck/${ids.join(',')}`,
+ method: 'delete'
+ });
+}
diff --git a/ruoyi-plus-soybean/src/typings/api/md.mat-type.api.d.ts b/ruoyi-plus-soybean/src/typings/api/md.mat-type.api.d.ts
new file mode 100644
index 0000000..aa4ccc5
--- /dev/null
+++ b/ruoyi-plus-soybean/src/typings/api/md.mat-type.api.d.ts
@@ -0,0 +1,76 @@
+/**
+ * Namespace Api
+ *
+ * All backend api type
+ */
+declare namespace Api {
+ /**
+ * namespace Md
+ *
+ * backend api module: "Md"
+ */
+ namespace Md {
+ /** mat type */
+ type MatType = Common.CommonRecord<{
+ /** id */
+ id: CommonType.IdType;
+ /** 鐗╂枡缁勫閿� */
+ gid: CommonType.IdType;
+ /** 缂栫爜 */
+ code: string;
+ /** 鍚嶇О */
+ name: string;
+ /** 鎻忚堪 */
+ des: string;
+ /** 鍚敤 */
+ enable: number;
+ /** 鍒犻櫎 */
+ del: string;
+ /** mes缂栫爜 */
+ mesCode: string;
+ /** 鍒涘缓浜� */
+ createUserName: string;
+ /** 鍒涘缓鏃堕棿 */
+ createUserTime: string;
+ /** 鏇存柊浜� */
+ updateUserName: string;
+ /** 鏇存柊鏃堕棿 */
+ updateUserTime: string;
+ }>;
+
+ /** mat type search params */
+ type MatTypeSearchParams = CommonType.RecordNullable<
+ Pick<
+ Api.Md.MatType,
+ | 'code'
+ | 'name'
+ | 'enable'
+ | 'del'
+ | 'mesCode'
+ > &
+ Api.Common.CommonSearchParams
+ >;
+
+ /** mat type operate params */
+ type MatTypeOperateParams = CommonType.RecordNullable<
+ Pick<
+ Api.Md.MatType,
+ | 'id'
+ | 'gid'
+ | 'code'
+ | 'name'
+ | 'des'
+ | 'enable'
+ | 'del'
+ | 'mesCode'
+ | 'createUserName'
+ | 'createUserTime'
+ | 'updateUserName'
+ | 'updateUserTime'
+ >
+ >;
+
+ /** mat type list */
+ type MatTypeList = Api.Common.PaginatingQueryRecord<MatType>;
+ }
+}
diff --git a/ruoyi-plus-soybean/src/typings/api/md.mat.api.d.ts b/ruoyi-plus-soybean/src/typings/api/md.mat.api.d.ts
new file mode 100644
index 0000000..5ed69f4
--- /dev/null
+++ b/ruoyi-plus-soybean/src/typings/api/md.mat.api.d.ts
@@ -0,0 +1,83 @@
+/**
+ * Namespace Api
+ *
+ * All backend api type
+ */
+declare namespace Api {
+ /**
+ * namespace Md
+ *
+ * backend api module: "Md"
+ */
+ namespace Md {
+ /** mat */
+ type Mat = Common.CommonRecord<{
+ /** id */
+ id: CommonType.IdType;
+ /** 鐗╂枡浠g爜 */
+ code: string;
+ /** 鍏ㄧО */
+ name: string;
+ /** 绠�绉� */
+ simpleName: string;
+ /** 鎻忚堪 */
+ des: string;
+ /** 鍗曚綅 */
+ uid: CommonType.IdType;
+ /** 鏈�鍚庢洿鏂版椂闂� */
+ lastUpdateTime: string;
+ /** 鍚敤 */
+ enable: number;
+ /** 鍒犻櫎 */
+ del: string;
+ /** 鐗╂枡绫诲瀷 */
+ tid: CommonType.IdType;
+ /** 鍒涘缓浜� */
+ createUserName: string;
+ /** 鍒涘缓鏃堕棿 */
+ createUserTime: string;
+ /** 鏇存柊浜� */
+ updateUserName: string;
+ /** 鏇存柊鏃堕棿 */
+ updateUserTime: string;
+ }>;
+
+ /** mat search params */
+ type MatSearchParams = CommonType.RecordNullable<
+ Pick<
+ Api.Md.Mat,
+ | 'code'
+ | 'name'
+ | 'simpleName'
+ | 'enable'
+ | 'del'
+ | 'tid'
+ > &
+ Api.Common.CommonSearchParams
+ >;
+
+ /** mat operate params */
+ type MatOperateParams = CommonType.RecordNullable<
+ Pick<
+ Api.Md.Mat,
+ | 'id'
+ | 'code'
+ | 'name'
+ | 'simpleName'
+ | 'des'
+ | 'uid'
+ | 'lastUpdateTime'
+ | 'enable'
+ | 'del'
+ | 'tid'
+ | 'createUserName'
+ | 'createUserTime'
+ | 'updateUserName'
+ | 'updateUserTime'
+ >
+ >;
+
+ /** mat list */
+ type MatList = Api.Common.PaginatingQueryRecord<Mat>;
+ }
+}
diff --git a/ruoyi-plus-soybean/src/typings/api/qm.batch.api.d.ts b/ruoyi-plus-soybean/src/typings/api/qm.batch.api.d.ts
index bdb8333..97572b6 100755
--- a/ruoyi-plus-soybean/src/typings/api/qm.batch.api.d.ts
+++ b/ruoyi-plus-soybean/src/typings/api/qm.batch.api.d.ts
@@ -24,6 +24,8 @@
eqpCode: string;
/** 鐗屽彿 */
matCode: string;
+ /** 鐗屽彿 */
+ matName: string;
/** 鍒ゅ畾渚濇嵁浠g爜 */
judgeCode: string;
/** 鎵规鐢熸垚鏃ユ湡 */
@@ -113,6 +115,7 @@
Pick<
Api.Qm.Batch,
| 'batchCode'
+ | 'isflag'
| 'typ'
| 'eqpCode'
| 'matCode'
@@ -120,6 +123,7 @@
| 'flag'
| 'toMesDate'
| 'fromMesDate'
+ | 'enabled'
| 'deleted'
| 'category'
| 'state'
diff --git a/ruoyi-plus-soybean/src/typings/api/qm.judge-details.api.d.ts b/ruoyi-plus-soybean/src/typings/api/qm.judge-details.api.d.ts
index 681ce8f..f4e3cbc 100644
--- a/ruoyi-plus-soybean/src/typings/api/qm.judge-details.api.d.ts
+++ b/ruoyi-plus-soybean/src/typings/api/qm.judge-details.api.d.ts
@@ -16,32 +16,54 @@
id: CommonType.IdType;
/** 鍒ゅ畾涓绘爣璇� */
judgeId: CommonType.IdType;
- /** 鍒ゅ畾椤笽TEM */
+ /** 妫�楠岄」鐩唬鐮� */
+ itemCode: string;
+ /** 鍒ゅ畾椤笽TEM (鍏煎鏃у瓧娈�) */
itemCod: string;
- /** 鍒ゅ畾椤筃AME */
+ /** 妫�楠岄」鐩悕绉� */
itemName: string;
+ /** 鍗曚綅 */
+ unit: string;
+ /** 鍚敤 */
+ enable: number;
+ /** 鍒犻櫎 */
+ del: number;
+ /** 妫�楠岄」鎻忚堪 */
+ itemDes: string;
+ /** 瑙勭▼浠g爜 */
+ stdCode: string;
+ /** 浠櫒鎻忚堪 */
+ instrumentDes: string;
/** 鏍囧噯鍊� */
value3: number;
/** 鍒ゅ畾鍊�1 */
value1: number;
/** 鍒ゅ畾鍊�2 */
value2: number;
- /** 缂洪櫡浣嶇疆 */
+ /** 缂洪櫡浣嶇疆-澶栬鐢� */
location: string;
- /** 鍒ゅ畾绾у埆 (A,B,C,D) */
+ /** 鍒咥,B,C,D鍥涗釜绾у埆 */
+ checkLevel: string;
+ /** 鍒ゅ畾绾у埆 (A,B,C,D) (鍏煎鏃у瓧娈�) */
cls: string;
- /** 鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒� */
+ /** 鍒嗗�� */
+ score: number;
+ /** 鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�) (鍏煎鏃у瓧娈�) */
stdscore: number;
- /** 鏍囪姝ら」鏄惁涓哄悎鎴愰」鐩紝姣斿澶栬锛屽疄闄呬笂鍏宠仈浜嗗緢澶氬瓙椤圭洰 */
+ /** 鏄惁鍚堟垚椤� */
ismix: number;
- /** 鑻ユ瀛楁鏈塙UID鍊硷紝琛ㄦ槑瀹冨彲鑳戒负鍏朵粬椤圭洰鐨勫瓙椤癸紝姣斿鈥滅┖澶粹��,瀹冧负鐑熸敮澶栬椤圭洰鐨勫瓙椤� */
+ /** 鍏宠仈椤笽D */
rid: CommonType.IdType;
- /** 鑼冨洿-澶囩敤 */
+ /** 绫诲埆 0:鎴愬搧 1杈呮枡 */
category: number;
- /** 澶囨敞 */
+ /** 浠櫒缂栫爜 */
+ instrumentCode: string;
+ /** 澶囨敞 (鍏煎鏃у瓧娈�) */
decisionDes: string;
/** 淇敼浜� */
updateUser: string;
+ /** 瀛愯妭鐐� */
+ children?: Api.Qm.JudgeDetails[];
}>;
/** judge details search params */
diff --git a/ruoyi-plus-soybean/src/typings/api/qm.matcheck.api.d.ts b/ruoyi-plus-soybean/src/typings/api/qm.matcheck.api.d.ts
new file mode 100644
index 0000000..c340104
--- /dev/null
+++ b/ruoyi-plus-soybean/src/typings/api/qm.matcheck.api.d.ts
@@ -0,0 +1,165 @@
+/**
+ * Namespace Api
+ *
+ * All backend api type
+ */
+declare namespace Api {
+ /**
+ * namespace Qm
+ *
+ * backend api module: "Qm"
+ */
+ namespace Qm {
+ /** matcheck */
+ type Matcheck = Common.CommonRecord<{
+ /** id */
+ id: CommonType.IdType;
+ /** 姹囨�昏〃ID */
+ pid: CommonType.IdType;
+ /** 妫�楠屾壒娆� */
+ batchCode: string;
+ /** 鐗屽彿 */
+ matCode: string;
+ /** 浠櫒缂栧彿 */
+ instrumentCode: string;
+ /** 鎶�鏈姹� */
+ techReq: string;
+ /** 妫�楠屼緷鎹� */
+ checkStd: string;
+ /** 娴嬭瘯鐜 */
+ testEnv: string;
+ /** 妫�楠岄」鐩瓹OD */
+ itemCode: string;
+ /** 妫�楠岄」鐩悕绉� */
+ itemName: string;
+ /** 璁惧 */
+ eqp: string;
+ /** 鐩樺彿 */
+ subBatchCode: string;
+ /** 姣忕洏妫�楠屾暟閲� */
+ sampleNumber: number;
+ /** 鍙栨牱绫诲瀷 */
+ sampleType: number;
+ /** 妫�楠屽憳 */
+ checkName: string;
+ /** 妫�楠屾椂闂� */
+ checkTime: string;
+ /** 澶嶆牳鍛� */
+ reviewName: string;
+ /** 澶嶆牳鏃堕棿 */
+ reviewTime: string;
+ /** 鏈�澶у�� */
+ maxval: number;
+ /** 鏈�灏忓�� */
+ minval: number;
+ /** 骞冲潎鍊� */
+ avgval: number;
+ /** SD鍊� */
+ sdval: number;
+ /** CV鍊� */
+ cvval: number;
+ /** CPK鍊� */
+ cpkval: number;
+ /** 瓒呮爣鏁� */
+ badval: number;
+ /** 鍒ゅ畾 */
+ judge: string;
+ /** 鍗曢」鍒ゅ畾 */
+ singlejudge: string;
+ /** 鐗堟湰鍚嶇О */
+ verName: string;
+ /** 鐗堟湰缂栧彿 */
+ verCode: string;
+ /** 淇濆瓨鏈� */
+ archDate: string;
+ /** 鍒犻櫎鏍囧織 */
+ del: number;
+ /** 0-鏈笂浼爉es 1-宸蹭笂浼� */
+ flag: string;
+ /** 涓婁紶MES鏃堕棿 */
+ toMesTime: string;
+ /** 澶囨敞 */
+ chkDes: string;
+ /** 妫�楠屼汉灞曠ず鍚� */
+ checker: string;
+ /** 鍒ゅ畾瑙勭▼ code锛堥潪鏁版嵁搴撳瓧娈碉級 */
+ judgeCode: string;
+ /** 鏄惁鐢熸垚 30 鏀儫鏄庣粏锛堥潪鏁版嵁搴撳瓧娈碉級 */
+ generateDetails: string;
+ /** 妫�娴嬬被鍨嬶紙闈炴暟鎹簱瀛楁锛� */
+ checkType: string;
+ }>;
+
+ /** matcheck search params */
+ type MatcheckSearchParams = CommonType.RecordNullable<
+ Pick<
+ Api.Qm.Matcheck,
+ | 'batchCode'
+ | 'judgeCode'
+ | 'matCode'
+ | 'checkName'
+ | 'checkTime'
+ | 'reviewName'
+ | 'reviewTime'
+ > &
+ Api.Common.CommonSearchParams & {
+ /** 妫�楠岄」涓嬫媺绛夋帴鍙d娇鐢ㄧ殑鍒ゅ畾瑙勭▼ id */
+ judgeId?: string;
+ }
+ >;
+
+ /** matcheck operate params */
+ type MatcheckOperateParams = CommonType.RecordNullable<
+ Pick<
+ Api.Qm.Matcheck,
+ | 'id'
+ | 'pid'
+ | 'batchCode'
+ | 'matCode'
+ | 'instrumentCode'
+ | 'techReq'
+ | 'checkStd'
+ | 'testEnv'
+ | 'itemCode'
+ | 'itemName'
+ | 'eqp'
+ | 'subBatchCode'
+ | 'sampleNumber'
+ | 'sampleType'
+ | 'checkName'
+ | 'checkTime'
+ | 'reviewName'
+ | 'reviewTime'
+ | 'maxval'
+ | 'minval'
+ | 'avgval'
+ | 'sdval'
+ | 'cvval'
+ | 'cpkval'
+ | 'badval'
+ | 'judge'
+ | 'singlejudge'
+ | 'verName'
+ | 'verCode'
+ | 'archDate'
+ | 'del'
+ | 'flag'
+ | 'toMesTime'
+ | 'chkDes'
+ | 'checker'
+ | 'judgeCode'
+ | 'generateDetails'
+ | 'checkType'
+ >
+ >;
+
+ /** matcheck list */
+ type MatcheckList = Api.Common.PaginatingQueryRecord<Matcheck>;
+
+ /** custom matcheck item */
+ type MatcheckCustomItem = {
+ itemCode: string;
+ itemName: string;
+ };
+ }
+}
diff --git a/ruoyi-plus-soybean/src/typings/elegant-router.d.ts b/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
index 42fe324..c2dc49e 100755
--- a/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
+++ b/ruoyi-plus-soybean/src/typings/elegant-router.d.ts
@@ -40,6 +40,8 @@
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
"md": "/md";
"md_instrument": "/md/instrument";
+ "md_mat": "/md/mat";
+ "md_mat-type": "/md/mat-type";
"md_shift": "/md/shift";
"md_weighing-box": "/md/weighing-box";
"monitor": "/monitor";
@@ -51,6 +53,7 @@
"qm_batch": "/qm/batch";
"qm_judge": "/qm/judge";
"qm_judge-details": "/qm/judge-details";
+ "qm_matcheck": "/qm/matcheck";
"qm_std": "/qm/std";
"report": "/report";
"report_demo": "/report/demo";
@@ -161,6 +164,8 @@
| "demo_tree"
| "home"
| "md_instrument"
+ | "md_mat-type"
+ | "md_mat"
| "md_shift"
| "md_weighing-box"
| "monitor_cache"
@@ -170,6 +175,7 @@
| "qm_batch"
| "qm_judge-details"
| "qm_judge"
+ | "qm_matcheck"
| "qm_std"
| "report_demo"
| "report_silk-storage-output"
diff --git a/ruoyi-plus-soybean/src/views/md/mat-type/index.vue b/ruoyi-plus-soybean/src/views/md/mat-type/index.vue
new file mode 100644
index 0000000..c3fdd16
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat-type/index.vue
@@ -0,0 +1,241 @@
+<script setup lang="tsx">
+import { ref } from 'vue';
+import { NDivider } from 'naive-ui';
+import { fetchBatchDeleteMatType, fetchGetMatTypeList } from '@/service/api/md/mat-type';
+import { useAppStore } from '@/store/modules/app';
+import { useAuth } from '@/hooks/business/auth';
+import { useDownload } from '@/hooks/business/download';
+import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import ButtonIcon from '@/components/custom/button-icon.vue';
+import MatTypeOperateDrawer from './modules/mat-type-operate-drawer.vue';
+import MatTypeSearch from './modules/mat-type-search.vue';
+
+defineOptions({
+ name: 'MatTypeList'
+});
+
+
+const appStore = useAppStore();
+const { download } = useDownload();
+const { hasAuth } = useAuth();
+
+const searchParams = ref<Api.Md.MatTypeSearchParams>({
+ pageNum: 1,
+ pageSize: 10,
+ code: null,
+ name: null,
+ enable: 1,
+ del: '0',
+ mesCode: null,
+ params: {}
+});
+
+const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
+ useNaivePaginatedTable({
+ api: () => fetchGetMatTypeList(searchParams.value),
+ transform: response => defaultTransform(response),
+ onPaginationParamsChange: params => {
+ searchParams.value.pageNum = params.page;
+ searchParams.value.pageSize = params.pageSize;
+ },
+ columns: () => [
+ {
+ type: 'selection',
+ align: 'center',
+ width: 48
+ },
+ {
+ key: 'index',
+ title: $t('common.index'),
+ align: 'center',
+ width: 64,
+ render: (_, index) => index + 1
+ },
+ {
+ key: 'code',
+ title: '缂栫爜',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'name',
+ title: '鍚嶇О',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'des',
+ title: '鎻忚堪',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'enable',
+ title: '鍚敤',
+ align: 'center',
+ minWidth: 120,
+ render: row => (row.enable == 1 ? '鏄�' : '鍚�')
+ },
+ {
+ key: 'del',
+ title: '鍒犻櫎',
+ align: 'center',
+ minWidth: 120,
+ render: row => (row.del == 1 ? '鏄�' : '鍚�')
+ },
+ {
+ key: 'mesCode',
+ title: 'mes缂栫爜',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'createUserName',
+ title: '鍒涘缓浜�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'createUserTime',
+ title: '鍒涘缓鏃堕棿',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'updateUserName',
+ title: '鏇存柊浜�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'updateUserTime',
+ title: '鏇存柊鏃堕棿',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'operate',
+ title: $t('common.operate'),
+ align: 'center',
+ fixed: 'right',
+ width: 130,
+ render: row => {
+ const divider = () => {
+ if (!hasAuth('md:matType:edit') || !hasAuth('md:matType:remove')) {
+ return null;
+ }
+ return <NDivider vertical />;
+ };
+
+ const editBtn = () => {
+ if (!hasAuth('md:matType:edit')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="primary"
+ icon="material-symbols:drive-file-rename-outline-outline"
+ tooltipContent={$t('common.edit')}
+ onClick={() => edit(row.id)}
+ />
+ );
+ };
+
+ const deleteBtn = () => {
+ if (!hasAuth('md:matType:remove')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="error"
+ icon="material-symbols:delete-outline"
+ tooltipContent={$t('common.delete')}
+ popconfirmContent={$t('common.confirmDelete')}
+ onPositiveClick={() => handleDelete(row.id)}
+ />
+ );
+ };
+
+ return (
+ <div class="flex-center gap-8px">
+ {editBtn()}
+ {divider()}
+ {deleteBtn()}
+ </div>
+ );
+ }
+ }
+ ]
+});
+
+const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
+ useTableOperate(data, 'id', getData);
+
+async function handleBatchDelete() {
+ // request
+ const { error } = await fetchBatchDeleteMatType(checkedRowKeys.value);
+ if (error) return;
+ onBatchDeleted();
+}
+
+async function handleDelete(id: CommonType.IdType) {
+ // request
+ const { error } = await fetchBatchDeleteMatType([id]);
+ if (error) return;
+ onDeleted();
+}
+
+function edit(id: CommonType.IdType) {
+ handleEdit(id);
+}
+
+function handleExport() {
+ download('/md/matType/export', searchParams.value, `鐗╂枡绫诲瀷_${new Date().getTime()}.xlsx`);
+}
+</script>
+
+<template>
+ <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
+ <MatTypeSearch v-model:model="searchParams" @search="getDataByPage" />
+ <NCard title="鐗╂枡绫诲瀷鍒楄〃" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
+ <template #header-extra>
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('md:matType:add')"
+ :show-delete="hasAuth('md:matType:remove')"
+ :show-export="hasAuth('md:matType:export')"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @export="handleExport"
+ @refresh="getData"
+ />
+ </template>
+ <NDataTable
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="data"
+ size="small"
+ :flex-height="!appStore.isMobile"
+ :scroll-x="scrollX"
+ :loading="loading"
+ remote
+ :row-key="row => row.id"
+ :pagination="mobilePagination"
+ class="sm:h-full"
+ />
+ <MatTypeOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ @submitted="getDataByPage"
+ />
+ </NCard>
+ </div>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-operate-drawer.vue b/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-operate-drawer.vue
new file mode 100644
index 0000000..c46a545
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-operate-drawer.vue
@@ -0,0 +1,171 @@
+<script setup lang="ts">
+import { computed, ref, watch } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { fetchCreateMatType, fetchUpdateMatType } from '@/service/api/md/mat-type';
+import { useFormRules, useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+
+defineOptions({
+ name: 'MatTypeOperateDrawer'
+});
+
+interface Props {
+ /** the type of operation */
+ operateType: NaiveUI.TableOperateType;
+ /** the edit row data */
+ rowData?: Api.Md.MatType | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+ (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+ default: false
+});
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+const { createRequiredRule } = useFormRules();
+
+const title = computed(() => {
+ const titles: Record<NaiveUI.TableOperateType, string> = {
+ add: '鏂板鐗╂枡绫诲瀷',
+ edit: '缂栬緫鐗╂枡绫诲瀷'
+ };
+ return titles[props.operateType];
+});
+
+type Model = Api.Md.MatTypeOperateParams;
+
+const model = ref<Model>(createDefaultModel());
+
+function createDefaultModel(): Model {
+ return {
+ id: '',
+ gid: '',
+ code: '',
+ name: '',
+ des: '',
+ enable: null,
+ del: '',
+ mesCode: '',
+ createUserName: '',
+ createUserTime: null,
+ updateUserName: '',
+ updateUserTime: null
+ };
+}
+
+type RuleKey = Extract<
+ keyof Model,
+ | 'id'
+>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+ id: createRequiredRule('id涓嶈兘涓虹┖'),
+};
+
+function handleUpdateModelWhenEdit() {
+ model.value = createDefaultModel();
+
+ if (props.operateType === 'edit' && props.rowData) {
+ Object.assign(model.value, jsonClone(props.rowData));
+ }
+}
+
+function closeDrawer() {
+ visible.value = false;
+}
+
+async function handleSubmit() {
+ await validate();
+
+ const { id, gid, code, name, des, enable, del, mesCode, createUserName, createUserTime, updateUserName, updateUserTime } = model.value;
+
+ // request
+ if (props.operateType === 'add') {
+ const { error } = await fetchCreateMatType({ gid, code, name, des, enable, del, mesCode, createUserName, createUserTime, updateUserName, updateUserTime });
+ if (error) return;
+ }
+
+ if (props.operateType === 'edit') {
+ const { error } = await fetchUpdateMatType({ id, gid, code, name, des, enable, del, mesCode, createUserName, createUserTime, updateUserName, updateUserTime });
+ if (error) return;
+ }
+
+ window.$message?.success($t('common.updateSuccess'));
+ closeDrawer();
+ emit('submitted');
+}
+
+watch(visible, () => {
+ if (visible.value) {
+ handleUpdateModelWhenEdit();
+ restoreValidation();
+ }
+});
+</script>
+
+<template>
+ <NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
+ <NDrawerContent :title="title" :native-scrollbar="false" closable>
+ <NForm ref="formRef" :model="model" :rules="rules">
+ <NFormItem label="鐗╂枡缁勫閿�" path="gid">
+ <NInput v-model:value="model.gid" placeholder="璇疯緭鍏ョ墿鏂欑粍澶栭敭" />
+ </NFormItem>
+ <NFormItem label="缂栫爜" path="code">
+ <NInput v-model:value="model.code" placeholder="璇疯緭鍏ョ紪鐮�" />
+ </NFormItem>
+ <NFormItem label="鍚嶇О" path="name">
+ <NInput v-model:value="model.name" placeholder="璇疯緭鍏ュ悕绉�" />
+ </NFormItem>
+ <NFormItem label="鎻忚堪" path="des">
+ <NInput v-model:value="model.des" placeholder="璇疯緭鍏ユ弿杩�" />
+ </NFormItem>
+ <NFormItem label="鍚敤" path="enable">
+ <NInput v-model:value="model.enable" placeholder="璇疯緭鍏ュ惎鐢�" />
+ </NFormItem>
+ <NFormItem label="鍒犻櫎" path="del">
+ <NInput v-model:value="model.del" placeholder="璇疯緭鍏ュ垹闄�" />
+ </NFormItem>
+ <NFormItem label="mes缂栫爜" path="mesCode">
+ <NInput v-model:value="model.mesCode" placeholder="璇疯緭鍏es缂栫爜" />
+ </NFormItem>
+ <NFormItem label="鍒涘缓浜�" path="createUserName">
+ <NInput v-model:value="model.createUserName" placeholder="璇疯緭鍏ュ垱寤轰汉" />
+ </NFormItem>
+ <NFormItem label="鍒涘缓鏃堕棿" path="createUserTime">
+ <NDatePicker
+ v-model:formatted-value="model.createUserTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItem>
+ <NFormItem label="鏇存柊浜�" path="updateUserName">
+ <NInput v-model:value="model.updateUserName" placeholder="璇疯緭鍏ユ洿鏂颁汉" />
+ </NFormItem>
+ <NFormItem label="鏇存柊鏃堕棿" path="updateUserTime">
+ <NDatePicker
+ v-model:formatted-value="model.updateUserTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItem>
+ </NForm>
+ <template #footer>
+ <NSpace :size="16">
+ <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
+ <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
+ </NSpace>
+ </template>
+ </NDrawerContent>
+ </NDrawer>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-search.vue b/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-search.vue
new file mode 100644
index 0000000..a55c423
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat-type/modules/mat-type-search.vue
@@ -0,0 +1,99 @@
+<script setup lang="ts">
+import { toRaw } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+
+defineOptions({
+ name: 'MatTypeSearch'
+});
+
+interface Emits {
+ (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+
+const model = defineModel<Api.Md.MatTypeSearchParams>('model', { required: true });
+
+const defaultModel = jsonClone(toRaw(model.value));
+
+function resetModel() {
+ Object.assign(model.value, defaultModel);
+}
+
+async function reset() {
+ await restoreValidation();
+ resetModel();
+ emit('search');
+}
+
+async function search() {
+ await validate();
+ emit('search');
+}
+</script>
+
+<template>
+ <NCard :bordered="false" size="small" class="card-wrapper">
+ <NCollapse>
+ <NCollapseItem :title="$t('common.search')" name="md-mat-type-search">
+ <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
+ <NGrid responsive="screen" item-responsive>
+ <NFormItemGi span="24 s:12 m:6" label="缂栫爜" label-width="auto" path="code" class="pr-24px">
+ <NInput v-model:value="model.code" placeholder="璇疯緭鍏ョ紪鐮�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍚嶇О" label-width="auto" path="name" class="pr-24px">
+ <NInput v-model:value="model.name" placeholder="璇疯緭鍏ュ悕绉�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍚敤" label-width="auto" path="enable" class="pr-24px">
+ <NSelect
+ v-model:value="model.enable"
+ placeholder="璇烽�夋嫨鍚敤"
+ :options="[
+ { label: '鏄�', value: 1 },
+ { label: '鍚�', value: 0 }
+ ]"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍒犻櫎" label-width="auto" path="del" class="pr-24px">
+ <NSelect
+ v-model:value="model.del"
+ placeholder="璇烽�夋嫨鍒犻櫎"
+ :options="[
+ { label: '鏄�', value: '1' },
+ { label: '鍚�', value: '0' }
+ ]"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="mes缂栫爜" label-width="auto" path="mesCode" class="pr-24px">
+ <NInput v-model:value="model.mesCode" placeholder="璇疯緭鍏es缂栫爜" />
+ </NFormItemGi>
+ <NFormItemGi :show-feedback="false" span="24" class="pr-24px">
+ <NSpace class="w-full" justify="end">
+ <NButton @click="reset">
+ <template #icon>
+ <icon-ic-round-refresh class="text-icon" />
+ </template>
+ {{ $t('common.reset') }}
+ </NButton>
+ <NButton type="primary" ghost @click="search">
+ <template #icon>
+ <icon-ic-round-search class="text-icon" />
+ </template>
+ {{ $t('common.search') }}
+ </NButton>
+ </NSpace>
+ </NFormItemGi>
+ </NGrid>
+ </NForm>
+ </NCollapseItem>
+ </NCollapse>
+ </NCard>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/md/mat/index.vue b/ruoyi-plus-soybean/src/views/md/mat/index.vue
new file mode 100644
index 0000000..b292a2e
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat/index.vue
@@ -0,0 +1,283 @@
+<script setup lang="tsx">
+import { onMounted, ref } from 'vue';
+import { NDivider } from 'naive-ui';
+import { fetchBatchDeleteMat, fetchGetMatList } from '@/service/api/md/mat';
+import { fetchGetMatTypeList } from '@/service/api/md/mat-type';
+import { useAppStore } from '@/store/modules/app';
+import { useAuth } from '@/hooks/business/auth';
+import { useDownload } from '@/hooks/business/download';
+import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import ButtonIcon from '@/components/custom/button-icon.vue';
+import MatOperateDrawer from './modules/mat-operate-drawer.vue';
+import MatSearch from './modules/mat-search.vue';
+
+defineOptions({
+ name: 'MatList'
+});
+
+
+const appStore = useAppStore();
+const { download } = useDownload();
+const { hasAuth } = useAuth();
+
+const matTypeOptions = ref<CommonType.Option[]>([]);
+
+async function getMatTypeOptions() {
+ const { data: typeData } = await fetchGetMatTypeList();
+ if (typeData) {
+ matTypeOptions.value = typeData.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
+
+onMounted(() => {
+ getMatTypeOptions();
+});
+
+const searchParams = ref<Api.Md.MatSearchParams>({
+ pageNum: 1,
+ pageSize: 10,
+ code: null,
+ name: null,
+ simpleName: null,
+ enable: 1,
+ del: '0',
+ tid: null,
+ params: {}
+});
+
+const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
+ useNaivePaginatedTable({
+ api: () => fetchGetMatList(searchParams.value),
+ transform: response => defaultTransform(response),
+ onPaginationParamsChange: params => {
+ searchParams.value.pageNum = params.page;
+ searchParams.value.pageSize = params.pageSize;
+ },
+ columns: () => [
+ {
+ type: 'selection',
+ align: 'center',
+ width: 48
+ },
+ {
+ key: 'index',
+ title: $t('common.index'),
+ align: 'center',
+ width: 64,
+ render: (_, index) => index + 1
+ },
+ {
+ key: 'code',
+ title: '鐗╂枡浠g爜',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'name',
+ title: '鍏ㄧО',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'simpleName',
+ title: '绠�绉�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'des',
+ title: '鎻忚堪',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'uid',
+ title: '鍗曚綅',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'lastUpdateTime',
+ title: '鏈�鍚庢洿鏂版椂闂�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'enable',
+ title: '鍚敤',
+ align: 'center',
+ minWidth: 120,
+ render: row => (row.enable === 1 ? '鏄�' : '鍚�')
+ },
+ {
+ key: 'del',
+ title: '鍒犻櫎',
+ align: 'center',
+ minWidth: 120,
+ render: row => (row.del === '1' ? '鏄�' : '鍚�')
+ },
+ {
+ key: 'tid',
+ title: '鐗╂枡绫诲瀷',
+ align: 'center',
+ minWidth: 120,
+ render: row => {
+ if (row.tid) {
+ return matTypeOptions.value.find(item => String(item.value) === String(row.tid))?.label || row.tid;
+ }
+ return '';
+ }
+ },
+ {
+ key: 'createUserName',
+ title: '鍒涘缓浜�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'createUserTime',
+ title: '鍒涘缓鏃堕棿',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'updateUserName',
+ title: '鏇存柊浜�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'updateUserTime',
+ title: '鏇存柊鏃堕棿',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'operate',
+ title: $t('common.operate'),
+ align: 'center',
+ fixed: 'right',
+ width: 130,
+ render: row => {
+ const divider = () => {
+ if (!hasAuth('md:mat:edit') || !hasAuth('md:mat:remove')) {
+ return null;
+ }
+ return <NDivider vertical />;
+ };
+
+ const editBtn = () => {
+ if (!hasAuth('md:mat:edit')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="primary"
+ icon="material-symbols:drive-file-rename-outline-outline"
+ tooltipContent={$t('common.edit')}
+ onClick={() => edit(row.id)}
+ />
+ );
+ };
+
+ const deleteBtn = () => {
+ if (!hasAuth('md:mat:remove')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="error"
+ icon="material-symbols:delete-outline"
+ tooltipContent={$t('common.delete')}
+ popconfirmContent={$t('common.confirmDelete')}
+ onPositiveClick={() => handleDelete(row.id)}
+ />
+ );
+ };
+
+ return (
+ <div class="flex-center gap-8px">
+ {editBtn()}
+ {divider()}
+ {deleteBtn()}
+ </div>
+ );
+ }
+ }
+ ]
+});
+
+const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
+ useTableOperate(data, 'id', getData);
+
+async function handleBatchDelete() {
+ // request
+ const { error } = await fetchBatchDeleteMat(checkedRowKeys.value);
+ if (error) return;
+ onBatchDeleted();
+}
+
+async function handleDelete(id: CommonType.IdType) {
+ // request
+ const { error } = await fetchBatchDeleteMat([id]);
+ if (error) return;
+ onDeleted();
+}
+
+function edit(id: CommonType.IdType) {
+ handleEdit(id);
+}
+
+function handleExport() {
+ download('/md/mat/export', searchParams.value, `鐗╂枡_${new Date().getTime()}.xlsx`);
+}
+</script>
+
+<template>
+ <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
+ <MatSearch v-model:model="searchParams" @search="getDataByPage" />
+ <NCard title="鐗╂枡鍒楄〃" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
+ <template #header-extra>
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('md:mat:add')"
+ :show-delete="hasAuth('md:mat:remove')"
+ :show-export="hasAuth('md:mat:export')"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @export="handleExport"
+ @refresh="getData"
+ />
+ </template>
+ <NDataTable
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="data"
+ size="small"
+ :flex-height="!appStore.isMobile"
+ :scroll-x="scrollX"
+ :loading="loading"
+ remote
+ :row-key="row => row.id"
+ :pagination="mobilePagination"
+ class="sm:h-full"
+ />
+ <MatOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ @submitted="getDataByPage"
+ />
+ </NCard>
+ </div>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/md/mat/modules/mat-operate-drawer.vue b/ruoyi-plus-soybean/src/views/md/mat/modules/mat-operate-drawer.vue
new file mode 100644
index 0000000..4977e2b
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat/modules/mat-operate-drawer.vue
@@ -0,0 +1,184 @@
+<script setup lang="ts">
+import { computed, ref, watch } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { fetchCreateMat, fetchUpdateMat } from '@/service/api/md/mat';
+import { useFormRules, useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+
+defineOptions({
+ name: 'MatOperateDrawer'
+});
+
+interface Props {
+ /** the type of operation */
+ operateType: NaiveUI.TableOperateType;
+ /** the edit row data */
+ rowData?: Api.Md.Mat | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+ (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+ default: false
+});
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+const { createRequiredRule } = useFormRules();
+
+const title = computed(() => {
+ const titles: Record<NaiveUI.TableOperateType, string> = {
+ add: '鏂板鐗╂枡',
+ edit: '缂栬緫鐗╂枡'
+ };
+ return titles[props.operateType];
+});
+
+type Model = Api.Md.MatOperateParams;
+
+const model = ref<Model>(createDefaultModel());
+
+function createDefaultModel(): Model {
+ return {
+ id: '',
+ code: '',
+ name: '',
+ simpleName: '',
+ des: '',
+ uid: '',
+ lastUpdateTime: null,
+ enable: null,
+ del: '',
+ tid: '',
+ createUserName: '',
+ createUserTime: null,
+ updateUserName: '',
+ updateUserTime: null
+ };
+}
+
+type RuleKey = Extract<
+ keyof Model,
+ | 'id'
+>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+ id: createRequiredRule('id涓嶈兘涓虹┖'),
+};
+
+function handleUpdateModelWhenEdit() {
+ model.value = createDefaultModel();
+
+ if (props.operateType === 'edit' && props.rowData) {
+ Object.assign(model.value, jsonClone(props.rowData));
+ }
+}
+
+function closeDrawer() {
+ visible.value = false;
+}
+
+async function handleSubmit() {
+ await validate();
+
+ const { id, code, name, simpleName, des, uid, lastUpdateTime, enable, del, tid, createUserName, createUserTime, updateUserName, updateUserTime } = model.value;
+
+ // request
+ if (props.operateType === 'add') {
+ const { error } = await fetchCreateMat({ code, name, simpleName, des, uid, lastUpdateTime, enable, del, tid, createUserName, createUserTime, updateUserName, updateUserTime });
+ if (error) return;
+ }
+
+ if (props.operateType === 'edit') {
+ const { error } = await fetchUpdateMat({ id, code, name, simpleName, des, uid, lastUpdateTime, enable, del, tid, createUserName, createUserTime, updateUserName, updateUserTime });
+ if (error) return;
+ }
+
+ window.$message?.success($t('common.updateSuccess'));
+ closeDrawer();
+ emit('submitted');
+}
+
+watch(visible, () => {
+ if (visible.value) {
+ handleUpdateModelWhenEdit();
+ restoreValidation();
+ }
+});
+</script>
+
+<template>
+ <NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
+ <NDrawerContent :title="title" :native-scrollbar="false" closable>
+ <NForm ref="formRef" :model="model" :rules="rules">
+ <NFormItem label="鐗╂枡浠g爜" path="code">
+ <NInput v-model:value="model.code" placeholder="璇疯緭鍏ョ墿鏂欎唬鐮�" />
+ </NFormItem>
+ <NFormItem label="鍏ㄧО" path="name">
+ <NInput v-model:value="model.name" placeholder="璇疯緭鍏ュ叏绉�" />
+ </NFormItem>
+ <NFormItem label="绠�绉�" path="simpleName">
+ <NInput v-model:value="model.simpleName" placeholder="璇疯緭鍏ョ畝绉�" />
+ </NFormItem>
+ <NFormItem label="鎻忚堪" path="des">
+ <NInput v-model:value="model.des" placeholder="璇疯緭鍏ユ弿杩�" />
+ </NFormItem>
+ <NFormItem label="鍗曚綅" path="uid">
+ <NInput v-model:value="model.uid" placeholder="璇疯緭鍏ュ崟浣�" />
+ </NFormItem>
+ <NFormItem label="鏈�鍚庢洿鏂版椂闂�" path="lastUpdateTime">
+ <NDatePicker
+ v-model:formatted-value="model.lastUpdateTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItem>
+ <NFormItem label="鍚敤" path="enable">
+ <NInput v-model:value="model.enable" placeholder="璇疯緭鍏ュ惎鐢�" />
+ </NFormItem>
+ <NFormItem label="鍒犻櫎" path="del">
+ <NInput v-model:value="model.del" placeholder="璇疯緭鍏ュ垹闄�" />
+ </NFormItem>
+ <NFormItem label="鐗╂枡绫诲瀷" path="tid">
+ <NInput v-model:value="model.tid" placeholder="璇疯緭鍏ョ墿鏂欑被鍨�" />
+ </NFormItem>
+ <NFormItem label="鍒涘缓浜�" path="createUserName">
+ <NInput v-model:value="model.createUserName" placeholder="璇疯緭鍏ュ垱寤轰汉" />
+ </NFormItem>
+ <NFormItem label="鍒涘缓鏃堕棿" path="createUserTime">
+ <NDatePicker
+ v-model:formatted-value="model.createUserTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItem>
+ <NFormItem label="鏇存柊浜�" path="updateUserName">
+ <NInput v-model:value="model.updateUserName" placeholder="璇疯緭鍏ユ洿鏂颁汉" />
+ </NFormItem>
+ <NFormItem label="鏇存柊鏃堕棿" path="updateUserTime">
+ <NDatePicker
+ v-model:formatted-value="model.updateUserTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItem>
+ </NForm>
+ <template #footer>
+ <NSpace :size="16">
+ <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
+ <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
+ </NSpace>
+ </template>
+ </NDrawerContent>
+ </NDrawer>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/md/mat/modules/mat-search.vue b/ruoyi-plus-soybean/src/views/md/mat/modules/mat-search.vue
new file mode 100644
index 0000000..36f9d22
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/md/mat/modules/mat-search.vue
@@ -0,0 +1,119 @@
+<script setup lang="ts">
+import { onMounted, ref, toRaw } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { fetchGetMatTypeList } from '@/service/api/md/mat-type';
+import { useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+
+defineOptions({
+ name: 'MatSearch'
+});
+
+interface Emits {
+ (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+
+const model = defineModel<Api.Md.MatSearchParams>('model', { required: true });
+
+const defaultModel = jsonClone(toRaw(model.value));
+
+const matTypeOptions = ref<CommonType.Option[]>([]);
+
+async function getMatTypeOptions() {
+ const { data } = await fetchGetMatTypeList();
+ if (data) {
+ matTypeOptions.value = data.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
+
+onMounted(() => {
+ getMatTypeOptions();
+});
+
+function resetModel() {
+ Object.assign(model.value, defaultModel);
+}
+
+async function reset() {
+ await restoreValidation();
+ resetModel();
+ emit('search');
+}
+
+async function search() {
+ await validate();
+ emit('search');
+}
+</script>
+
+<template>
+ <NCard :bordered="false" size="small" class="card-wrapper">
+ <NCollapse>
+ <NCollapseItem :title="$t('common.search')" name="md-mat-search">
+ <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
+ <NGrid responsive="screen" item-responsive>
+ <NFormItemGi span="24 s:12 m:6" label="鐗╂枡浠g爜" label-width="auto" path="code" class="pr-24px">
+ <NInput v-model:value="model.code" placeholder="璇疯緭鍏ョ墿鏂欎唬鐮�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍏ㄧО" label-width="auto" path="name" class="pr-24px">
+ <NInput v-model:value="model.name" placeholder="璇疯緭鍏ュ叏绉�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="绠�绉�" label-width="auto" path="simpleName" class="pr-24px">
+ <NInput v-model:value="model.simpleName" placeholder="璇疯緭鍏ョ畝绉�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍚敤" label-width="auto" path="enable" class="pr-24px">
+ <NSelect
+ v-model:value="model.enable"
+ placeholder="璇烽�夋嫨鍚敤"
+ :options="[
+ { label: '鏄�', value: 1 },
+ { label: '鍚�', value: 0 }
+ ]"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鍒犻櫎" label-width="auto" path="del" class="pr-24px">
+ <NSelect
+ v-model:value="model.del"
+ placeholder="璇烽�夋嫨鍒犻櫎"
+ :options="[
+ { label: '鏄�', value: '1' },
+ { label: '鍚�', value: '0' }
+ ]"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="鐗╂枡绫诲瀷" label-width="auto" path="tid" class="pr-24px">
+ <NSelect v-model:value="model.tid" placeholder="璇烽�夋嫨鐗╂枡绫诲瀷" :options="matTypeOptions" clearable />
+ </NFormItemGi>
+ <NFormItemGi :show-feedback="false" span="24" class="pr-24px">
+ <NSpace class="w-full" justify="end">
+ <NButton @click="reset">
+ <template #icon>
+ <icon-ic-round-refresh class="text-icon" />
+ </template>
+ {{ $t('common.reset') }}
+ </NButton>
+ <NButton type="primary" ghost @click="search">
+ <template #icon>
+ <icon-ic-round-search class="text-icon" />
+ </template>
+ {{ $t('common.search') }}
+ </NButton>
+ </NSpace>
+ </NFormItemGi>
+ </NGrid>
+ </NForm>
+ </NCollapseItem>
+ </NCollapse>
+ </NCard>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/qm/batch/index.vue b/ruoyi-plus-soybean/src/views/qm/batch/index.vue
index 96d7c52..e25ab9c 100755
--- a/ruoyi-plus-soybean/src/views/qm/batch/index.vue
+++ b/ruoyi-plus-soybean/src/views/qm/batch/index.vue
@@ -1,12 +1,14 @@
<script setup lang="tsx">
-import { ref } from 'vue';
-import { NDivider } from 'naive-ui';
-import { fetchBatchDeleteBatch, fetchGetBatchList } from '@/service/api/qm/batch';
-import { useAppStore } from '@/store/modules/app';
-import { useAuth } from '@/hooks/business/auth';
-import { useDownload } from '@/hooks/business/download';
-import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
-import { $t } from '@/locales';
+import {nextTick, ref} from 'vue';
+import {useRouter} from 'vue-router';
+import {NDivider, NDropdown} from 'naive-ui';
+import {fetchBatchDeleteBatch, fetchGetBatchList} from '@/service/api/qm/batch';
+import {useAppStore} from '@/store/modules/app';
+import {useAuth} from '@/hooks/business/auth';
+import {useDownload} from '@/hooks/business/download';
+import {useSvgIcon} from '@/hooks/common/icon';
+import {defaultTransform, useNaivePaginatedTable, useTableOperate} from '@/hooks/common/table';
+import {$t} from '@/locales';
import ButtonIcon from '@/components/custom/button-icon.vue';
import BatchOperateDrawer from './modules/batch-operate-drawer.vue';
import BatchSearch from './modules/batch-search.vue';
@@ -16,18 +18,145 @@
});
const appStore = useAppStore();
-const { download } = useDownload();
-const { hasAuth } = useAuth();
+const router = useRouter();
+const {download} = useDownload();
+const {hasAuth} = useAuth();
+const {SvgIconVNode} = useSvgIcon();
+
+// 鍙抽敭鑿滃崟鐩稿叧
+const showDropdown = ref(false);
+const x = ref(0);
+const y = ref(0);
+const currentRow = ref<Api.Qm.Batch | null>(null);
+
+const dropdownOptions = [
+ {
+ label: '鍘熷鏁版嵁缁存姢',
+ key: 'raw-data-maintenance',
+ icon: SvgIconVNode({icon: 'mdi:database-edit-outline', fontSize: 18})
+ },
+ {
+ label: '缁煎悎娴嬭瘯鍙版暟鎹淮鎶�',
+ key: 'test-bench-maintenance',
+ icon: SvgIconVNode({icon: 'mdi:monitor-dashboard', fontSize: 18})
+ },
+ {
+ label: '鏂板缓澶嶆鎵规',
+ key: 'new-recheck-batch',
+ icon: SvgIconVNode({icon: 'mdi:plus-circle-outline', fontSize: 18})
+ },
+ {
+ type: 'divider',
+ key: 'd1'
+ },
+ {
+ label: '鍗峰寘鍗峰埗妫�楠岀粨鏋滄姤鍛�',
+ key: 'report-rolling',
+ icon: SvgIconVNode({icon: 'mdi:file-document-outline', fontSize: 18})
+ },
+ {
+ label: '鍖呰鏍囪瘑妫�楠屽師濮嬭褰�',
+ key: 'record-packaging',
+ icon: SvgIconVNode({icon: 'mdi:barcode-scan', fontSize: 18})
+ },
+ {
+ label: '鐔勭伀銆佸惈姘寸巼銆佸惈鏈巼鍘熷璁板綍',
+ key: 'record-quality',
+ icon: SvgIconVNode({icon: 'mdi:water-percent', fontSize: 18})
+ },
+ {
+ label: '绔儴钀戒笣鍘熷璁板綍',
+ key: 'record-silk',
+ icon: SvgIconVNode({icon: 'mdi:format-list-bulleted-type', fontSize: 18})
+ },
+ {
+ label: '缁煎悎娴嬭瘯鍙板師濮嬭褰�',
+ key: 'record-bench',
+ icon: SvgIconVNode({icon: 'mdi:chart-line', fontSize: 18})
+ },
+ {
+ label: '澶栬妫�楠屽師濮嬭褰�',
+ key: 'record-appearance',
+ icon: SvgIconVNode({icon: 'mdi:eye-outline', fontSize: 18})
+ },
+ {
+ type: 'divider',
+ key: 'd2'
+ },
+ {
+ label: $t('common.edit'),
+ key: 'edit',
+ icon: SvgIconVNode({icon: 'material-symbols:drive-file-rename-outline-outline', fontSize: 18}),
+ show: hasAuth('qm:batch:edit')
+ },
+ {
+ label: $t('common.delete'),
+ key: 'delete',
+ icon: SvgIconVNode({icon: 'material-symbols:delete-outline', fontSize: 18}),
+ show: hasAuth('qm:batch:remove')
+ }
+];
+
+function handleSelect(key: string) {
+ showDropdown.value = false;
+ if (!currentRow.value) return;
+
+ if (key === 'edit') {
+ edit(currentRow.value.id);
+ } else if (key === 'delete') {
+ window.$dialog?.error({
+ title: $t('common.confirmDelete'),
+ content: $t('common.confirmDelete'),
+ positiveText: $t('common.confirm'),
+ negativeText: $t('common.cancel'),
+ onPositiveClick: () => {
+ handleDelete(currentRow.value!.id);
+ }
+ });
+ } else if (key === 'raw-data-maintenance') {
+ // 璺宠浆鍒� matcheck 椤甸潰
+ if (!currentRow.value.judgeCode) {
+ window.$message?.warning('璇ユ壒娆℃病鏈夊垽瀹氫緷鎹�');
+ return;
+ }
+ router.push({
+ path: '/qm/matcheck',
+ query: {
+ judgeCode: currentRow.value.judgeCode,
+ batchCode: currentRow.value.batchCode,
+ matCode: currentRow.value.matCode
+ }
+ });
+ } else {
+ // 澶勭悊鍏朵粬涓氬姟鎿嶄綔
+ window.$message?.info(`鐐瑰嚮浜�: ${key}`);
+ }
+}
+
+function handleRowProps(row: Api.Qm.Batch) {
+ return {
+ onContextmenu: (e: MouseEvent) => {
+ e.preventDefault();
+ showDropdown.value = false;
+ nextTick().then(() => {
+ currentRow.value = row;
+ x.value = e.clientX;
+ y.value = e.clientY;
+ showDropdown.value = true;
+ });
+ }
+ };
+}
// 绫诲瀷/鍙嶉MES/绫诲埆鐨� value->label 鏄犲皠锛堢敤浜庤〃鏍兼樉绀猴級
-const TYP_MAP: Record<string, string> = { A: '鍒朵笣', B: '鎴愬瀷', C: '鍗峰寘', D: '灏佺', E: '绯栭鏂�' };
-const FLAG_MAP: Record<string, string> = { '0': '鏈笂浼爉es', '1': '宸蹭笂浼�', '3': '浠嶮ES涓嬭浇' };
-const CATEGORY_MAP: Record<string, string> = { '0': '鎴愬搧', '1': '杈呮潗' };
+const FLAG_MAP: Record<string, string> = {'0': '鏈笂浼爉es', '1': '宸蹭笂浼�', '3': '浠嶮ES涓嬭浇'};
+const CATEGORY_MAP: Record<string, string> = {'0': '鎴愬搧', '1': '杈呮潗'};
const searchParams = ref<Api.Qm.BatchSearchParams>({
pageNum: 1,
pageSize: 10,
batchCode: null,
+ isflag: '1',
typ: null,
eqpCode: null,
matCode: null,
@@ -35,13 +164,17 @@
flag: null,
toMesDate: null,
fromMesDate: null,
- deleted: null,
- category: null,
+ enabled: '1',
+ deleted: 0,
+ category: '0',
state: null,
- params: {}
+ params: {
+ beginBatchDate: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')} 00:00:00`,
+ endBatchDate: `${new Date().getFullYear()}-${String(new Date().getMonth() + 1).padStart(2, '0')}-${String(new Date().getDate()).padStart(2, '0')} 23:59:59`
+ }
});
-const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
+const {columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX} =
useNaivePaginatedTable({
api: () => fetchGetBatchList(searchParams.value),
transform: response => defaultTransform(response),
@@ -63,45 +196,20 @@
render: (_, index) => index + 1
},
{
- key: 'id',
- title: '缂栫爜',
- align: 'center',
- minWidth: 120
- },
- {
key: 'batchCode',
- title: '鎵规浠g爜',
+ title: '鎵规鍙�',
align: 'center',
minWidth: 120
},
{
- key: 'batchName',
- title: '鎵规鍚嶇О',
- align: 'center',
- minWidth: 120
- },
- {
- key: 'typ',
- title: '绫诲瀷',
- align: 'center',
- minWidth: 120,
- render: row => TYP_MAP[row.typ] ?? row.typ
- },
- {
- key: 'eqpCode',
- title: '鏈哄彴浠g爜',
- align: 'center',
- minWidth: 120
- },
- {
- key: 'matCode',
+ key: 'matName',
title: '鐗屽彿',
align: 'center',
minWidth: 120
},
{
- key: 'judgeCode',
- title: '鍒ゅ畾渚濇嵁浠g爜',
+ key: 'judgeName',
+ title: '鍒ゅ畾渚濇嵁',
align: 'center',
minWidth: 120
},
@@ -115,13 +223,15 @@
key: 'isflag',
title: '浣跨敤鏍囧織',
align: 'center',
- minWidth: 120
+ minWidth: 120,
+ render: row => (row.isflag == '1' ? '鏄�' : '鍚�')
},
{
key: 'enabled',
title: '鍚敤鏍囧織',
align: 'center',
- minWidth: 120
+ minWidth: 120,
+ render: row => (row.enabled == '1' ? '鏄�' : '鍚�')
},
{
key: 'totalNum',
@@ -200,7 +310,8 @@
key: 'deleted',
title: '鍒犻櫎鏍囧織',
align: 'center',
- minWidth: 120
+ minWidth: 120,
+ render: row => (row.deleted == 1 ? '鏄�' : '鍚�')
},
{
key: 'batchDes',
@@ -350,6 +461,7 @@
{
key: 'operate',
title: $t('common.operate'),
+ fixed: 'right',
align: 'center',
width: 130,
render: row => {
@@ -357,7 +469,7 @@
if (!hasAuth('qm:batch:edit') || !hasAuth('qm:batch:remove')) {
return null;
}
- return <NDivider vertical />;
+ return <NDivider vertical/>;
};
const editBtn = () => {
@@ -403,19 +515,19 @@
]
});
-const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
+const {drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted} =
useTableOperate(data, 'id', getData);
async function handleBatchDelete() {
// request
- const { error } = await fetchBatchDeleteBatch(checkedRowKeys.value);
+ const {error} = await fetchBatchDeleteBatch(checkedRowKeys.value);
if (error) return;
onBatchDeleted();
}
async function handleDelete(id: CommonType.IdType) {
// request
- const { error } = await fetchBatchDeleteBatch([id]);
+ const {error} = await fetchBatchDeleteBatch([id]);
if (error) return;
onDeleted();
}
@@ -431,7 +543,7 @@
<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
- <BatchSearch v-model:model="searchParams" @search="getDataByPage" />
+ <BatchSearch v-model:model="searchParams" @search="getDataByPage"/>
<NCard title="妫�楠屾壒娆″垪琛�" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
<template #header-extra>
<TableHeaderOperation
@@ -458,8 +570,19 @@
remote
:row-key="row => row.id"
:pagination="mobilePagination"
+ :row-props="handleRowProps"
class="sm:h-full"
/>
+ <NDropdown
+ placement="bottom-start"
+ trigger="manual"
+ :x="x"
+ :y="y"
+ :options="dropdownOptions"
+ :show="showDropdown"
+ :on-clickoutside="() => (showDropdown = false)"
+ @select="handleSelect"
+ />
<BatchOperateDrawer
v-model:visible="drawerVisible"
:operate-type="operateType"
diff --git a/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-operate-drawer.vue b/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-operate-drawer.vue
index bccc726..2af78f4 100755
--- a/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-operate-drawer.vue
+++ b/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-operate-drawer.vue
@@ -1,7 +1,9 @@
<script setup lang="ts">
-import { computed, ref, watch } from 'vue';
+import { computed, onMounted, ref, watch } from 'vue';
import { jsonClone } from '@sa/utils';
import { fetchCreateBatch, fetchUpdateBatch } from '@/service/api/qm/batch';
+import { fetchGetMatList } from '@/service/api/md/mat';
+import { fetchGetJudgeList } from '@/service/api/qm/judge';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
@@ -31,27 +33,41 @@
const { formRef, validate, restoreValidation } = useNaiveForm();
const { createRequiredRule } = useFormRules();
-// 绫诲瀷閫夐」锛欰-鍒朵笣 B-鎴愬瀷 C-鍗峰寘 D-灏佺 E-绯栭鏂�
-const typOptions = [
- { label: '鍒朵笣', value: 'A' },
- { label: '鎴愬瀷', value: 'B' },
- { label: '鍗峰寘', value: 'C' },
- { label: '灏佺', value: 'D' },
- { label: '绯栭鏂�', value: 'E' }
+const matOptions = ref<CommonType.Option[]>([]);
+const judgeOptions = ref<CommonType.Option[]>([]);
+const stateOptions = [
+ { label: '姝e父', value: '0' },
+ { label: '鍋滅敤', value: '1' }
];
-// 鍙嶉MES閫夐」锛�0-鏈笂浼爉es 1-宸蹭笂浼� 3-浠嶮ES涓嬭浇
-const flagOptions = [
- { label: '鏈笂浼爉es', value: '0' },
- { label: '宸蹭笂浼�', value: '1' },
- { label: '浠嶮ES涓嬭浇', value: '3' }
-];
+async function getMatOptions() {
+ const { data, error } = await fetchGetMatList({ tid: '1' as any, pageSize: 1000 });
+ if (!error) {
+ matOptions.value = data.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
-// 绫诲埆閫夐」锛�0-鎴愬搧 1-杈呮潗
-const categoryOptions = [
- { label: '鎴愬搧', value: '0' },
- { label: '杈呮潗', value: '1' }
-];
+async function getJudgeOptions(matCode?: string | null) {
+ if (!matCode) {
+ judgeOptions.value = [];
+ return;
+ }
+ const params: Api.Qm.JudgeSearchParams = { category: 0, pageSize: 1000, matCode };
+ const { data, error } = await fetchGetJudgeList(params);
+ if (!error) {
+ judgeOptions.value = data.rows.map(item => ({
+ label: item.judgeName,
+ value: String(item.id)
+ })) as CommonType.Option[];
+ }
+}
+
+onMounted(() => {
+ getMatOptions();
+});
const title = computed(() => {
const titles: Record<NaiveUI.TableOperateType, string> = {
@@ -70,13 +86,13 @@
id: '',
batchCode: '',
batchName: '',
- typ: '',
+ typ: '0',
eqpCode: '',
- matCode: '',
+ matCode: null,
judgeCode: '',
batchDate: null,
- isflag: '',
- enabled: '',
+ isflag: '0',
+ enabled: '1',
totalNum: null,
results: '',
approver: '',
@@ -86,19 +102,19 @@
verName: '',
verCode: '',
archDate: '',
- flag: '',
+ flag: '0',
toMesDate: null,
fromMesDate: null,
- deleted: null,
+ deleted: 0,
batchDes: '',
- category: '',
+ category: '0',
makeno: '',
shifteqpno: '',
boxno: '',
pid: '',
reviewer: '',
rvcount: null,
- state: '',
+ state: '0',
reviewTime: null,
auditTime: null,
spec: '',
@@ -117,10 +133,11 @@
};
}
-type RuleKey = Extract<keyof Model, 'id'>;
+type RuleKey = Extract<keyof Model, 'batchCode' | 'matCode'>;
const rules: Record<RuleKey, App.Global.FormRule> = {
- id: createRequiredRule('缂栫爜涓嶈兘涓虹┖')
+ batchCode: createRequiredRule('鎵规鍙蜂笉鑳戒负绌�'),
+ matCode: createRequiredRule('鐗屽彿涓嶈兘涓虹┖')
};
function handleUpdateModelWhenEdit() {
@@ -303,201 +320,54 @@
if (visible.value) {
handleUpdateModelWhenEdit();
restoreValidation();
+ getJudgeOptions(model.value.matCode);
}
});
+
+watch(
+ () => model.value.matCode,
+ newVal => {
+ if (visible.value) {
+ model.value.judgeCode = '';
+ getJudgeOptions(newVal);
+ }
+ }
+);
</script>
<template>
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
<NDrawerContent :title="title" :native-scrollbar="false" closable>
- <NForm ref="formRef" :model="model" :rules="rules">
- <NFormItem label="鎵规浠g爜" path="batchCode">
- <NInput v-model:value="model.batchCode" placeholder="璇疯緭鍏ユ壒娆′唬鐮�" />
- </NFormItem>
- <NFormItem label="鎵规鍚嶇О" path="batchName">
- <NInput v-model:value="model.batchName" placeholder="璇疯緭鍏ユ壒娆″悕绉�" />
- </NFormItem>
- <NFormItem label="绫诲瀷" path="typ">
- <NSelect v-model:value="model.typ" :options="typOptions" placeholder="璇烽�夋嫨绫诲瀷" clearable />
- </NFormItem>
- <NFormItem label="鏈哄彴浠g爜" path="eqpCode">
- <NInput v-model:value="model.eqpCode" placeholder="璇疯緭鍏ユ満鍙颁唬鐮�" />
+ <NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="100">
+ <NFormItem label="鎵规鍙�" path="batchCode">
+ <NInput v-model:value="model.batchCode" placeholder="璇疯緭鍏ユ壒娆″彿" />
</NFormItem>
<NFormItem label="鐗屽彿" path="matCode">
- <NInput v-model:value="model.matCode" placeholder="璇疯緭鍏ョ墝鍙�" />
+ <NSelect v-model:value="model.matCode" :options="matOptions" placeholder="璇烽�夋嫨鐗屽彿" clearable filterable />
</NFormItem>
- <NFormItem label="鍒ゅ畾渚濇嵁浠g爜" path="judgeCode">
- <NInput v-model:value="model.judgeCode" placeholder="璇疯緭鍏ュ垽瀹氫緷鎹唬鐮�" />
- </NFormItem>
- <NFormItem label="鎵规鐢熸垚鏃ユ湡" path="batchDate">
- <NDatePicker
- v-model:formatted-value="model.batchDate"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
+ <NFormItem label="鍒ゅ畾渚濇嵁" path="judgeCode">
+ <NSelect
+ v-model:value="model.judgeCode"
+ :options="judgeOptions"
+ placeholder="璇烽�夋嫨鍒ゅ畾渚濇嵁"
clearable
- />
- </NFormItem>
- <NFormItem label="浣跨敤鏍囧織" path="isflag">
- <NInput v-model:value="model.isflag" placeholder="璇疯緭鍏ヤ娇鐢ㄦ爣蹇�" />
- </NFormItem>
- <NFormItem label="鍚敤鏍囧織" path="enabled">
- <NInput v-model:value="model.enabled" placeholder="璇疯緭鍏ュ惎鐢ㄦ爣蹇�" />
- </NFormItem>
- <NFormItem label="鍒拌揣鎬婚噺" path="totalNum">
- <NInputNumber v-model:value="model.totalNum" placeholder="璇疯緭鍏ュ埌璐ф�婚噺" class="w-full" />
- </NFormItem>
- <NFormItem label="缁煎悎鍒ゅ畾" path="results">
- <NInput v-model:value="model.results" placeholder="璇疯緭鍏ョ患鍚堝垽瀹�" />
- </NFormItem>
- <NFormItem label="鎵瑰噯浜�" path="approver">
- <NInput v-model:value="model.approver" placeholder="璇疯緭鍏ユ壒鍑嗕汉" />
- </NFormItem>
- <NFormItem label="瀹℃牳浜�" path="auditor">
- <NInput v-model:value="model.auditor" placeholder="璇疯緭鍏ュ鏍镐汉" />
- </NFormItem>
- <NFormItem label="鍒涘缓浜�" path="creater">
- <NInput v-model:value="model.creater" placeholder="璇疯緭鍏ュ垱寤轰汉" />
- </NFormItem>
- <NFormItem label="鍒惰〃鏃ユ湡" path="tabDate">
- <NDatePicker
- v-model:formatted-value="model.tabDate"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="鐗堟湰鍚嶇О" path="verName">
- <NInput v-model:value="model.verName" placeholder="璇疯緭鍏ョ増鏈悕绉�" />
- </NFormItem>
- <NFormItem label="鐗堟湰缂栧彿" path="verCode">
- <NInput v-model:value="model.verCode" placeholder="璇疯緭鍏ョ増鏈紪鍙�" />
- </NFormItem>
- <NFormItem label="淇濆瓨鏈�" path="archDate">
- <NInput v-model:value="model.archDate" placeholder="璇疯緭鍏ヤ繚瀛樻湡" />
- </NFormItem>
- <NFormItem label="鍙嶉MES" path="flag">
- <NSelect v-model:value="model.flag" :options="flagOptions" placeholder="璇烽�夋嫨鍙嶉MES" clearable />
- </NFormItem>
- <NFormItem label="涓婁紶MES鏃堕棿" path="toMesDate">
- <NDatePicker
- v-model:formatted-value="model.toMesDate"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="浠嶮ES鏃堕棿涓嬭浇" path="fromMesDate">
- <NDatePicker
- v-model:formatted-value="model.fromMesDate"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="鍒犻櫎鏍囧織" path="deleted">
- <NInputNumber v-model:value="model.deleted" placeholder="璇疯緭鍏ュ垹闄ゆ爣蹇�" class="w-full" />
- </NFormItem>
- <NFormItem label="鎵规鎻忚堪" path="batchDes">
- <NInput v-model:value="model.batchDes" placeholder="璇疯緭鍏ユ壒娆℃弿杩�" />
- </NFormItem>
- <NFormItem label="绫诲埆" path="category">
- <NSelect v-model:value="model.category" :options="categoryOptions" placeholder="璇烽�夋嫨绫诲埆" clearable />
- </NFormItem>
- <NFormItem label="鍗峰埗宸ュ彿" path="makeno">
- <NInput v-model:value="model.makeno" placeholder="璇疯緭鍏ュ嵎鍒跺伐鍙�" />
- </NFormItem>
- <NFormItem label="鐝鏈哄彿" path="shifteqpno">
- <NInput v-model:value="model.shifteqpno" placeholder="璇疯緭鍏ョ彮娆℃満鍙�" />
- </NFormItem>
- <NFormItem label="瑁呯鍙�" path="boxno">
- <NInput v-model:value="model.boxno" placeholder="璇疯緭鍏ヨ绠卞彿" />
- </NFormItem>
- <NFormItem label="鐖舵壒娆″彿" path="pid">
- <NInput v-model:value="model.pid as any" placeholder="璇疯緭鍏ョ埗鎵规鍙�" />
- </NFormItem>
- <NFormItem label="澶嶆牳浜�" path="reviewer">
- <NInput v-model:value="model.reviewer" placeholder="璇疯緭鍏ュ鏍镐汉" />
- </NFormItem>
- <NFormItem label="澶嶆娆℃暟" path="rvcount">
- <NInputNumber v-model:value="model.rvcount" placeholder="璇疯緭鍏ュ妫�娆℃暟" class="w-full" />
- </NFormItem>
- <NFormItem label="鎵规鐘舵��" path="state">
- <NInput v-model:value="model.state" placeholder="璇疯緭鍏ユ壒娆$姸鎬�" />
- </NFormItem>
- <NFormItem label="澶嶆牳鏃ユ湡" path="reviewTime">
- <NDatePicker
- v-model:formatted-value="model.reviewTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="瀹℃牳鏃ユ湡" path="auditTime">
- <NDatePicker
- v-model:formatted-value="model.auditTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
+ filterable
/>
</NFormItem>
<NFormItem label="瑙勬牸" path="spec">
<NInput v-model:value="model.spec" placeholder="璇疯緭鍏ヨ鏍�" />
</NFormItem>
- <NFormItem label="鎵瑰噯鏃堕棿" path="approveTime">
- <NDatePicker
- v-model:formatted-value="model.approveTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
+ <NFormItem label="瑁呯鍙�" path="boxno">
+ <NInput v-model:value="model.boxno" placeholder="璇疯緭鍏ヨ绠卞彿" />
</NFormItem>
- <NFormItem label="鍒拌揣鍗曚綅" path="unit">
- <NInput v-model:value="model.unit" placeholder="璇疯緭鍏ュ埌璐у崟浣�" />
+ <NFormItem label="鐝鏈哄彿" path="shifteqpno">
+ <NInput v-model:value="model.shifteqpno" placeholder="璇疯緭鍏ョ彮娆℃満鍙�" />
</NFormItem>
- <NFormItem label="鍒拌揣鏃ユ湡" path="arrivalTime">
- <NDatePicker
- v-model:formatted-value="model.arrivalTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
+ <NFormItem label="鎻忚堪" path="batchDes">
+ <NInput v-model:value="model.batchDes" placeholder="璇疯緭鍏ユ弿杩�" />
</NFormItem>
- <NFormItem label="瀛樻斁鍦扮偣" path="storagePlace">
- <NInput v-model:value="model.storagePlace" placeholder="璇疯緭鍏ュ瓨鏀惧湴鐐�" />
- </NFormItem>
- <NFormItem label="妫�楠屽憳" path="checker">
- <NInput v-model:value="model.checker" placeholder="璇疯緭鍏ユ楠屽憳" />
- </NFormItem>
- <NFormItem label="鎺ュ崟鏃ユ湡" path="receiveTime">
- <NDatePicker
- v-model:formatted-value="model.receiveTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="鎶ユ鏃ユ湡" path="inspTime">
- <NDatePicker
- v-model:formatted-value="model.inspTime"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItem>
- <NFormItem label="浠撳簱淇濈鍛�" path="storer">
- <NInput v-model:value="model.storer" placeholder="璇疯緭鍏ヤ粨搴撲繚绠″憳" />
- </NFormItem>
- <NFormItem label="鏄惁楠岃瘉" path="isverify">
- <NInput v-model:value="model.isverify" placeholder="璇疯緭鍏ユ槸鍚﹂獙璇�" />
- </NFormItem>
- <NFormItem label="鏄惁妫�楠�" path="ischk">
- <NInput v-model:value="model.ischk" placeholder="璇疯緭鍏ユ槸鍚︽楠�" />
- </NFormItem>
- <NFormItem label="澶囩敤1" path="bak1">
- <NInput v-model:value="model.bak1" placeholder="璇疯緭鍏ュ鐢�1" />
- </NFormItem>
- <NFormItem label="澶囩敤2" path="bak2">
- <NInput v-model:value="model.bak2" placeholder="璇疯緭鍏ュ鐢�2" />
+ <NFormItem label="鐘舵��" path="state">
+ <NSelect v-model:value="model.state" :options="stateOptions" placeholder="璇烽�夋嫨鐘舵��" clearable />
</NFormItem>
</NForm>
<template #footer>
diff --git a/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-search.vue b/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-search.vue
index 77400be..3397bf9 100755
--- a/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-search.vue
+++ b/ruoyi-plus-soybean/src/views/qm/batch/modules/batch-search.vue
@@ -1,6 +1,7 @@
<script setup lang="ts">
-import { ref, toRaw } from 'vue';
+import { onMounted, ref, toRaw, watch } from 'vue';
import { jsonClone } from '@sa/utils';
+import { fetchGetMatList } from '@/service/api/md/mat';
import { useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
@@ -16,38 +17,53 @@
const { formRef, validate, restoreValidation } = useNaiveForm();
-const dateRangeToMesDate = ref<[string, string] | null>(null);
-const dateRangeFromMesDate = ref<[string, string] | null>(null);
const model = defineModel<Api.Qm.BatchSearchParams>('model', { required: true });
+
+const dateRangeBatchDate = ref<[string, string] | null>(null);
+
+const matOptions = ref<CommonType.Option[]>([]);
+
+async function getMatOptions() {
+ const { data } = await fetchGetMatList({ tid: '1' as any, pageSize: 1000 });
+ if (data) {
+ matOptions.value = data.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
+
+onMounted(() => {
+ getMatOptions();
+});
+
+// sync model params to dateRangeBatchDate
+watch(
+ () => model.value.params,
+ val => {
+ if (val?.beginBatchDate && val?.endBatchDate) {
+ dateRangeBatchDate.value = [val.beginBatchDate, val.endBatchDate];
+ } else {
+ dateRangeBatchDate.value = null;
+ }
+ },
+ { immediate: true, deep: true }
+);
const defaultModel = jsonClone(toRaw(model.value));
-// 绫诲瀷閫夐」锛欰-鍒朵笣 B-鎴愬瀷 C-鍗峰寘 D-灏佺 E-绯栭鏂�
-const typOptions = [
- { label: '鍒朵笣', value: 'A' },
- { label: '鎴愬瀷', value: 'B' },
- { label: '鍗峰寘', value: 'C' },
- { label: '灏佺', value: 'D' },
- { label: '绯栭鏂�', value: 'E' }
-];
-
-// 鍙嶉MES閫夐」锛�0-鏈笂浼爉es 1-宸蹭笂浼� 3-浠嶮ES涓嬭浇
-const flagOptions = [
- { label: '鏈笂浼爉es', value: '0' },
- { label: '宸蹭笂浼�', value: '1' },
- { label: '浠嶮ES涓嬭浇', value: '3' }
-];
-
-// 绫诲埆閫夐」锛�0-鎴愬搧 1-杈呮潗
-const categoryOptions = [
- { label: '鎴愬搧', value: '0' },
- { label: '杈呮潗', value: '1' }
-];
+function onDateRangeBatchDateUpdate(value: [string, string] | null) {
+ if (value && value.length === 2) {
+ model.value.params!.beginBatchDate = value[0];
+ model.value.params!.endBatchDate = value[1];
+ } else {
+ model.value.params!.beginBatchDate = undefined;
+ model.value.params!.endBatchDate = undefined;
+ }
+}
function resetModel() {
- dateRangeToMesDate.value = null;
- dateRangeFromMesDate.value = null;
- Object.assign(model.value, defaultModel);
+ Object.assign(model.value, jsonClone(defaultModel));
}
async function reset() {
@@ -58,14 +74,6 @@
async function search() {
await validate();
- if (dateRangeToMesDate.value?.length) {
- model.value.params!.beginToMesDate = dateRangeToMesDate.value[0];
- model.value.params!.endToMesDate = dateRangeToMesDate.value[1];
- }
- if (dateRangeFromMesDate.value?.length) {
- model.value.params!.beginFromMesDate = dateRangeFromMesDate.value[0];
- model.value.params!.endFromMesDate = dateRangeFromMesDate.value[1];
- }
emit('search');
}
</script>
@@ -74,70 +82,68 @@
<NCard :bordered="false" size="small" class="card-wrapper">
<NCollapse>
<NCollapseItem :title="$t('common.search')" name="qm-batch-search">
- <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
+ <NForm ref="formRef" :model="model" label-placement="left" :label-width="110">
<NGrid responsive="screen" item-responsive>
- <NFormItemGi span="24 s:12 m:8" label="鎵规浠g爜" label-width="auto" path="batchCode" class="pr-24px">
- <NInput v-model:value="model.batchCode" placeholder="璇疯緭鍏ユ壒娆′唬鐮�" />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="绫诲瀷" label-width="auto" path="typ" class="pr-24px">
- <NSelect v-model:value="model.typ" :options="typOptions" placeholder="璇烽�夋嫨绫诲瀷" clearable />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="鏈哄彴浠g爜" label-width="auto" path="eqpCode" class="pr-24px">
- <NInput v-model:value="model.eqpCode" placeholder="璇疯緭鍏ユ満鍙颁唬鐮�" />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="鐗屽彿" label-width="auto" path="matCode" class="pr-24px">
- <NInput v-model:value="model.matCode" placeholder="璇疯緭鍏ョ墝鍙�" />
- </NFormItemGi>
<NFormItemGi span="24 s:12 m:8" label="鎵规鐢熸垚鏃ユ湡" label-width="auto" path="batchDate" class="pr-24px">
<NDatePicker
- v-model:formatted-value="model.batchDate"
- type="datetime"
- value-format="yyyy-MM-dd HH:mm:ss"
- clearable
- />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="鍙嶉MES" label-width="auto" path="flag" class="pr-24px">
- <NSelect v-model:value="model.flag" :options="flagOptions" placeholder="璇烽�夋嫨鍙嶉MES" clearable />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="涓婁紶MES鏃堕棿" label-width="auto" path="toMesDate" class="pr-24px">
- <NDatePicker
- v-model:formatted-value="dateRangeToMesDate"
+ v-model:formatted-value="dateRangeBatchDate"
type="datetimerange"
value-format="yyyy-MM-dd HH:mm:ss"
clearable
+ :default-time="['00:00:00', '23:59:59']"
+ @update:formatted-value="onDateRangeBatchDateUpdate"
/>
</NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="浠嶮ES鏃堕棿涓嬭浇" label-width="auto" path="fromMesDate" class="pr-24px">
- <NDatePicker
- v-model:formatted-value="dateRangeFromMesDate"
- type="datetimerange"
- value-format="yyyy-MM-dd HH:mm:ss"
+ <NFormItemGi span="24 s:12 m:8" label="鐗屽彿" label-width="auto" path="matCode" class="pr-24px">
+ <NSelect v-model:value="model.matCode" placeholder="璇烽�夋嫨鐗屽彿" :options="matOptions" clearable />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:8" label="浣跨敤鏍囧織" label-width="auto" path="isflag" class="pr-24px">
+ <NSelect
+ v-model:value="model.isflag"
+ placeholder="璇烽�夋嫨浣跨敤鏍囧織"
+ :options="[
+ { label: '鏄�', value: '1' },
+ { label: '鍚�', value: '0' }
+ ]"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:8" label="鍚敤鏍囧織" label-width="auto" path="enabled" class="pr-24px">
+ <NSelect
+ v-model:value="model.enabled"
+ placeholder="璇烽�夋嫨鍚敤鏍囧織"
+ :options="[
+ { label: '鏄�', value: '1' },
+ { label: '鍚�', value: '0' }
+ ]"
clearable
/>
</NFormItemGi>
<NFormItemGi span="24 s:12 m:8" label="鍒犻櫎鏍囧織" label-width="auto" path="deleted" class="pr-24px">
- <NInputNumber v-model:value="model.deleted" placeholder="璇疯緭鍏ュ垹闄ゆ爣蹇�" class="w-full" />
+ <NSelect
+ v-model:value="model.deleted"
+ placeholder="璇烽�夋嫨鍒犻櫎鏍囧織"
+ :options="[
+ { label: '鏄�', value: 1 },
+ { label: '鍚�', value: 0 }
+ ]"
+ clearable
+ />
</NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="绫诲埆" label-width="auto" path="category" class="pr-24px">
- <NSelect v-model:value="model.category" :options="categoryOptions" placeholder="璇烽�夋嫨绫诲埆" clearable />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:8" label="鎵规鐘舵��" label-width="auto" path="state" class="pr-24px">
- <NInput v-model:value="model.state" placeholder="璇疯緭鍏ユ壒娆$姸鎬�" />
- </NFormItemGi>
- <NFormItemGi :show-feedback="false" span="24" class="pr-24px">
- <NSpace class="w-full" justify="end">
- <NButton @click="reset">
- <template #icon>
- <icon-ic-round-refresh class="text-icon" />
- </template>
- {{ $t('common.reset') }}
- </NButton>
+ <NFormItemGi :show-feedback="false" span="24 s:12 m:8" class="pr-24px">
+ <NSpace class="w-full" justify="start">
<NButton type="primary" ghost @click="search">
<template #icon>
<icon-ic-round-search class="text-icon" />
</template>
{{ $t('common.search') }}
</NButton>
+ <NButton @click="reset">
+ <template #icon>
+ <icon-ic-round-refresh class="text-icon" />
+ </template>
+ {{ $t('common.reset') }}
+ </NButton>
</NSpace>
</NFormItemGi>
</NGrid>
diff --git a/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-operate-drawer.vue b/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-operate-drawer.vue
index f573bb8..55fcf0d 100644
--- a/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-operate-drawer.vue
+++ b/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-operate-drawer.vue
@@ -39,6 +39,13 @@
return titles[props.operateType];
});
+const clsOptions = [
+ { label: 'A', value: 'A' },
+ { label: 'B', value: 'B' },
+ { label: 'C', value: 'C' },
+ { label: 'D', value: 'D' }
+];
+
type Model = Api.Qm.JudgeDetailsOperateParams;
const model = ref<Model>(createDefaultModel());
@@ -65,12 +72,14 @@
type RuleKey = Extract<keyof Model, 'id'>;
-const rules: Record<RuleKey, App.Global.FormRule> = {};
+const rules: Record<RuleKey, App.Global.FormRule | App.Global.FormRule[]> = {
+ id: createRequiredRule('璇疯緭鍏ョ紪鐮�')
+};
function handleUpdateModelWhenEdit() {
model.value = createDefaultModel();
- if (props.operateType === 'edit' && props.rowData) {
+ if (props.rowData) {
Object.assign(model.value, jsonClone(props.rowData));
}
}
@@ -160,59 +169,26 @@
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
<NDrawerContent :title="title" :native-scrollbar="false" closable>
<NForm ref="formRef" :model="model" :rules="rules">
- <NFormItem label="缂栫爜" path="id">
- <NInput v-model:value="model.id" placeholder="璇疯緭鍏ョ紪鐮�" />
- </NFormItem>
- <NFormItem label="鍒ゅ畾涓绘爣璇�" path="judgeId">
- <NInput v-model:value="model.judgeId" placeholder="璇疯緭鍏ュ垽瀹氫富鏍囪瘑" />
- </NFormItem>
- <NFormItem label="鍒ゅ畾椤笽TEM" path="itemCod">
- <NInput v-model:value="model.itemCod" placeholder="璇疯緭鍏ュ垽瀹氶」ITEM" />
- </NFormItem>
- <NFormItem label="鍒ゅ畾椤筃AME" path="itemName">
- <NInput v-model:value="model.itemName" placeholder="璇疯緭鍏ュ垽瀹氶」NAME" />
+ <NFormItem label="鍒ゅ畾椤�" path="itemName">
+ <NInput v-model:value="(model.itemName as any)" placeholder="璇疯緭鍏ュ垽瀹氶」" :disabled="operateType === 'edit'" />
</NFormItem>
<NFormItem label="鏍囧噯鍊�" path="value3">
- <NInput v-model:value="model.value3" placeholder="璇疯緭鍏ユ爣鍑嗗��" />
+ <NInputNumber v-model:value="(model.value3 as any)" placeholder="璇疯緭鍏ユ爣鍑嗗��" class="w-full" />
</NFormItem>
- <NFormItem label="鍒ゅ畾鍊�1" path="value1">
- <NInput v-model:value="model.value1" placeholder="璇疯緭鍏ュ垽瀹氬��1" />
+ <NFormItem label="涓嬮檺鍊�" path="value1">
+ <NInputNumber v-model:value="(model.value1 as any)" placeholder="璇疯緭鍏ヤ笅闄愬��" class="w-full" />
</NFormItem>
- <NFormItem label="鍒ゅ畾鍊�2" path="value2">
- <NInput v-model:value="model.value2" placeholder="璇疯緭鍏ュ垽瀹氬��2" />
+ <NFormItem label="涓婇檺鍊�" path="value2">
+ <NInputNumber v-model:value="(model.value2 as any)" placeholder="璇疯緭鍏ヤ笂闄愬��" class="w-full" />
</NFormItem>
- <NFormItem label="缂洪櫡浣嶇疆" path="location">
- <NInput v-model:value="model.location" placeholder="璇疯緭鍏ョ己闄蜂綅缃�" />
+ <NFormItem label="鍒嗗��" path="stdscore">
+ <NInputNumber v-model:value="(model.stdscore as any)" placeholder="璇疯緭鍏ュ垎鍊�" class="w-full" />
</NFormItem>
- <NFormItem label="鍒ゅ畾绾у埆 (A,B,C,D)" path="cls">
- <NInput v-model:value="model.cls" placeholder="璇疯緭鍏ュ垽瀹氱骇鍒� (A,B,C,D)" />
- </NFormItem>
- <NFormItem label="鍒嗗�兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�" path="stdscore">
- <NInput
- v-model:value="model.stdscore"
- placeholder="璇疯緭鍏ュ垎鍊兼爣鍑� (鎵e垎鏍囧噯锛屽緱鍒嗘爣鍑�),姣斿涓嶅悎鏍间竴娆℃墸澶氬皯鍒�"
- />
- </NFormItem>
- <NFormItem label="鏍囪姝ら」鏄惁涓哄悎鎴愰」鐩紝姣斿澶栬锛屽疄闄呬笂鍏宠仈浜嗗緢澶氬瓙椤圭洰" path="ismix">
- <NInput
- v-model:value="model.ismix"
- placeholder="璇疯緭鍏ユ爣璁版椤规槸鍚︿负鍚堟垚椤圭洰锛屾瘮濡傚瑙傦紝瀹為檯涓婂叧鑱斾簡寰堝瀛愰」鐩�"
- />
- </NFormItem>
- <NFormItem label="鑻ユ瀛楁鏈塙UID鍊硷紝琛ㄦ槑瀹冨彲鑳戒负鍏朵粬椤圭洰鐨勫瓙椤癸紝姣斿鈥滅┖澶粹��,瀹冧负鐑熸敮澶栬椤圭洰鐨勫瓙椤�" path="rid">
- <NInput
- v-model:value="model.rid"
- placeholder="璇疯緭鍏ヨ嫢姝ゅ瓧娈垫湁UUID鍊硷紝琛ㄦ槑瀹冨彲鑳戒负鍏朵粬椤圭洰鐨勫瓙椤癸紝姣斿鈥滅┖澶粹��,瀹冧负鐑熸敮澶栬椤圭洰鐨勫瓙椤�"
- />
- </NFormItem>
- <NFormItem label="鑼冨洿-澶囩敤" path="category">
- <NInput v-model:value="model.category" placeholder="璇疯緭鍏ヨ寖鍥�-澶囩敤" />
+ <NFormItem label="鍒ゅ畾绾у埆" path="cls">
+ <NSelect v-model:value="(model.cls as any)" :options="clsOptions" placeholder="璇烽�夋嫨鍒ゅ畾绾у埆" />
</NFormItem>
<NFormItem label="澶囨敞" path="decisionDes">
- <NInput v-model:value="model.decisionDes" placeholder="璇疯緭鍏ュ娉�" />
- </NFormItem>
- <NFormItem label="淇敼浜�" path="updateUser">
- <NInput v-model:value="model.updateUser" placeholder="璇疯緭鍏ヤ慨鏀逛汉" />
+ <NInput v-model:value="(model.decisionDes as any)" type="textarea" placeholder="璇疯緭鍏ュ娉�" />
</NFormItem>
</NForm>
<template #footer>
diff --git a/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-sub-table.vue b/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-sub-table.vue
new file mode 100644
index 0000000..67101a2
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/qm/judge-details/modules/judge-details-sub-table.vue
@@ -0,0 +1,414 @@
+<script setup lang="tsx">
+import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
+import type { DataTableRowKey } from 'naive-ui';
+import { NDivider } from 'naive-ui';
+import { jsonClone } from '@sa/utils';
+import { fetchBatchDeleteJudgeDetails, fetchGetJudgeDetailsTree } from '@/service/api/qm/judge-details';
+import { useAuth } from '@/hooks/business/auth';
+import { useNaiveTable } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import ButtonIcon from '@/components/custom/button-icon.vue';
+import JudgeDetailsOperateDrawer from './judge-details-operate-drawer.vue';
+
+defineOptions({
+ name: 'JudgeDetailsSubTable'
+});
+
+interface Props {
+ judgeId?: CommonType.IdType | null;
+}
+
+const props = withDefaults(defineProps<Props>(), {
+ judgeId: null
+});
+
+interface JudgeDetailsSubRow extends Api.Qm.JudgeDetails {
+ children?: JudgeDetailsSubRow[];
+}
+
+const { hasAuth } = useAuth();
+
+const checkedRowKeys = ref<CommonType.IdType[]>([]);
+const drawerVisible = ref(false);
+const operateType = ref<NaiveUI.TableOperateType>('add');
+const editingData = ref<Api.Qm.JudgeDetails | null>(null);
+const showFullscreen = ref(false);
+const fullscreenStyle = ref<Record<string, string>>({});
+
+function handleAdd() {
+ if (!props.judgeId) {
+ window.$message?.warning('璇峰厛閫夋嫨鍒ゅ畾渚濇嵁');
+ return;
+ }
+ operateType.value = 'add';
+ editingData.value = { judgeId: props.judgeId } as any;
+ drawerVisible.value = true;
+}
+
+function handleEdit(row: JudgeDetailsSubRow) {
+ operateType.value = 'edit';
+ editingData.value = jsonClone(row);
+ drawerVisible.value = true;
+}
+
+async function handleBatchDelete() {
+ if (checkedRowKeys.value.length === 0) return;
+ const { error } = await fetchBatchDeleteJudgeDetails(checkedRowKeys.value);
+ if (error) return;
+ window.$message?.success($t('common.deleteSuccess'));
+ checkedRowKeys.value = [];
+ await getData();
+}
+
+async function handleDelete(id: CommonType.IdType) {
+ const { error } = await fetchBatchDeleteJudgeDetails([id]);
+ if (error) return;
+ window.$message?.success($t('common.deleteSuccess'));
+ await getData();
+}
+
+const {
+ columns,
+ columnChecks,
+ data: rows,
+ loading,
+ getData,
+ scrollX
+} = useNaiveTable<Api.Common.PaginatingQueryRecord<Api.Qm.JudgeDetails>, Api.Qm.JudgeDetails>({
+ api: async () => {
+ if (!props.judgeId) return { rows: [], total: 0, pageNum: 1 } as any;
+ const { data } = await fetchGetJudgeDetailsTree({
+ pageNum: 1,
+ pageSize: 9999,
+ judgeId: props.judgeId
+ });
+ return data;
+ },
+ columns: () => [
+ {
+ type: 'selection',
+ align: 'center',
+ width: 48
+ },
+ {
+ key: 'index',
+ title: $t('common.index'),
+ align: 'center',
+ width: 56,
+ render: (_: any, index: number) => index + 1
+ },
+ {
+ key: 'itemName',
+ title: '鍒ゅ畾椤�',
+ align: 'left',
+ width: 250,
+ tree: true
+ } as any,
+ {
+ key: 'value3',
+ title: '鏍囧噯鍊�',
+ align: 'center',
+ width: 100
+ },
+ {
+ key: 'value1',
+ title: '涓嬮檺鍊�',
+ align: 'center',
+ width: 100
+ },
+ {
+ key: 'value2',
+ title: '涓婇檺鍊�',
+ align: 'center',
+ width: 100
+ },
+ {
+ key: 'cls',
+ title: '绾у埆',
+ align: 'center',
+ width: 80
+ },
+ {
+ key: 'stdscore',
+ title: '鍒嗗��',
+ align: 'center',
+ minWidth: 150
+ },
+ {
+ key: 'decisionDes',
+ title: '澶囨敞',
+ align: 'center',
+ minWidth: 150
+ },
+ {
+ key: 'updateUser',
+ title: '淇敼浜�',
+ align: 'center',
+ minWidth: 150
+ },
+ {
+ key: 'operate',
+ title: $t('common.operate'),
+ fixed: 'right',
+ align: 'center',
+ width: 130,
+ render: (row: any) => {
+ const divider = () => {
+ if (!hasAuth('qm:judgeDetails:edit') || !hasAuth('qm:judgeDetails:remove')) {
+ return null;
+ }
+ return <NDivider vertical />;
+ };
+
+ const editBtn = () => {
+ if (!hasAuth('qm:judgeDetails:edit')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="primary"
+ icon="material-symbols:drive-file-rename-outline-outline"
+ tooltipContent={$t('common.edit')}
+ onClick={() => handleEdit(row)}
+ />
+ );
+ };
+
+ const deleteBtn = () => {
+ if (!hasAuth('qm:judgeDetails:remove')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="error"
+ icon="material-symbols:delete-outline"
+ tooltipContent={$t('common.delete')}
+ popconfirmContent={$t('common.confirmDelete')}
+ onPositiveClick={() => handleDelete(row.id)}
+ />
+ );
+ };
+
+ return (
+ <div class="flex-center gap-8px">
+ {editBtn()}
+ {divider()}
+ {deleteBtn()}
+ </div>
+ );
+ }
+ }
+ ],
+ transform: response => {
+ return response?.rows || [];
+ }
+});
+
+const onFullscreenKeydown = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ showFullscreen.value = false;
+ }
+};
+
+const cardTitle = computed(() => `鍒ゅ畾鏄庣粏缁存姢`);
+
+watch(
+ () => props.judgeId,
+ async () => {
+ checkedRowKeys.value = [];
+ await getData();
+ },
+ { immediate: true }
+);
+
+watch(
+ showFullscreen,
+ visible => {
+ if (visible) {
+ updateFullscreenStyle();
+ window.addEventListener('keydown', onFullscreenKeydown);
+ window.addEventListener('resize', updateFullscreenStyle);
+ window.addEventListener('scroll', updateFullscreenStyle, true);
+ return;
+ }
+ window.removeEventListener('keydown', onFullscreenKeydown);
+ window.removeEventListener('resize', updateFullscreenStyle);
+ window.removeEventListener('scroll', updateFullscreenStyle, true);
+ },
+ { immediate: true }
+);
+
+onBeforeUnmount(() => {
+ window.removeEventListener('keydown', onFullscreenKeydown);
+ window.removeEventListener('resize', updateFullscreenStyle);
+ window.removeEventListener('scroll', updateFullscreenStyle, true);
+});
+
+onMounted(() => {
+ updateFullscreenStyle();
+});
+
+function updateFullscreenStyle() {
+ const container = document.querySelector<HTMLElement>('.judge-content-area');
+ if (!container) {
+ fullscreenStyle.value = {
+ position: 'fixed',
+ inset: '0',
+ zIndex: '20'
+ };
+ return;
+ }
+ const rect = container.getBoundingClientRect();
+ fullscreenStyle.value = {
+ position: 'fixed',
+ left: `${rect.left}px`,
+ top: `${rect.top}px`,
+ width: `${rect.width}px`,
+ height: `${rect.height}px`,
+ zIndex: '20'
+ };
+}
+
+function rowKey(row: JudgeDetailsSubRow): DataTableRowKey {
+ return String(row.id);
+}
+</script>
+
+<template>
+ <div class="flex-col-stretch">
+ <NCard
+ :title="cardTitle"
+ :bordered="false"
+ size="small"
+ class="flex-col-stretch card-wrapper flex-1-hidden"
+ :content-style="{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }"
+ >
+ <template #header-extra>
+ <NSpace align="center">
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:judgeDetails:add')"
+ :show-delete="hasAuth('qm:judgeDetails:remove')"
+ :show-export="false"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @refresh="getData"
+ />
+ <NButton size="small" @click="showFullscreen = true">
+ <template #icon>
+ <icon-mdi-fullscreen class="text-icon" />
+ </template>
+ 鍏ㄥ睆
+ </NButton>
+ </NSpace>
+ </template>
+
+ <NSpin :show="loading" class="h-full" content-class="h-full flex-col-stretch flex-1-hidden">
+ <div v-if="!props.judgeId" class="h-full flex-center text-gray-400">璇风偣鍑讳笂鏂硅〃鏍艰鏌ョ湅鏄庣粏</div>
+ <NDataTable
+ v-else
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="rows"
+ size="small"
+ flex-height
+ children-key="children"
+ :row-key="rowKey"
+ default-expand-all
+ striped
+ class="flex-1-hidden"
+ />
+ </NSpin>
+ </NCard>
+
+ <Teleport to="body">
+ <div v-if="showFullscreen" class="fullscreen-mask" :style="fullscreenStyle" @click.self="showFullscreen = false">
+ <NCard
+ :title="cardTitle"
+ :bordered="false"
+ size="small"
+ class="fullscreen-card flex-col-stretch"
+ :content-style="{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }"
+ >
+ <template #header-extra>
+ <NSpace align="center">
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:judgeDetails:add')"
+ :show-delete="hasAuth('qm:judgeDetails:remove')"
+ :show-export="false"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @refresh="getData"
+ />
+ <NButton size="small" ghost type="error" @click="showFullscreen = false">
+ <template #icon>
+ <icon-mdi-close class="text-icon" />
+ </template>
+ 鍏抽棴
+ </NButton>
+ </NSpace>
+ </template>
+
+ <NSpin :show="loading" class="h-full" content-class="h-full">
+ <div v-if="!props.judgeId" class="h-full flex-center text-gray-400">璇风偣鍑讳笂鏂硅〃鏍艰鏌ョ湅鏄庣粏</div>
+ <NDataTable
+ v-else
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="rows"
+ size="small"
+ flex-height
+ children-key="children"
+ :row-key="rowKey"
+ striped
+ class="fullscreen-table"
+ />
+ </NSpin>
+ </NCard>
+ </div>
+ </Teleport>
+
+ <JudgeDetailsOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ @submitted="getData"
+ />
+ </div>
+</template>
+
+<style scoped>
+:deep(.n-card__content) {
+ padding: 8px 12px;
+}
+
+:deep(.n-data-table-th),
+:deep(.n-data-table-td) {
+ padding: 4px 6px;
+}
+
+.fullscreen-mask {
+ position: absolute;
+ inset: 0;
+ z-index: 20;
+ background: #fff;
+ padding: 0;
+ display: flex;
+}
+
+.fullscreen-card {
+ width: 100%;
+ height: 100%;
+}
+
+.fullscreen-table {
+ height: 100%;
+}
+</style>
diff --git a/ruoyi-plus-soybean/src/views/qm/judge/index.vue b/ruoyi-plus-soybean/src/views/qm/judge/index.vue
index 84b5e37..13fe5c0 100644
--- a/ruoyi-plus-soybean/src/views/qm/judge/index.vue
+++ b/ruoyi-plus-soybean/src/views/qm/judge/index.vue
@@ -10,6 +10,8 @@
import ButtonIcon from '@/components/custom/button-icon.vue';
import JudgeOperateDrawer from './modules/judge-operate-drawer.vue';
import JudgeSearch from './modules/judge-search.vue';
+import JudgeDetailsSubTable from '../judge-details/modules/judge-details-sub-table.vue';
+import StdSubTable from "@/views/qm/std/modules/std-sub-table.vue";
defineOptions({
name: 'JudgeList'
@@ -19,6 +21,8 @@
const { download } = useDownload();
const { hasAuth } = useAuth();
+const selectedJudgeId = ref<CommonType.IdType | null>(null);
+
const searchParams = ref<Api.Qm.JudgeSearchParams>({
pageNum: 1,
pageSize: 10,
@@ -26,7 +30,7 @@
matName: null,
judgeName: null,
category: 0, // 榛樿閫夋嫨鎴愬搧
- status: -1, // 榛樿閫夋嫨鍏ㄩ儴
+ status: 1, // 榛樿鏌ヨ鍚敤
params: {}
});
@@ -276,47 +280,74 @@
function handleExport() {
download('/qm/judge/export', searchParams.value, `鍒ゅ畾渚濇嵁_${new Date().getTime()}.xlsx`);
}
+
+function handleRowClick(row: any) {
+ return {
+ onClick: (e: MouseEvent) => {
+ const target = e.target as HTMLElement | null;
+ if (target?.closest('.n-checkbox') || target?.closest('.n-button') || target?.closest('a')) return;
+ selectedJudgeId.value = row.id;
+ },
+ style: 'cursor: pointer;'
+ };
+}
</script>
<template>
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
<JudgeSearch v-model:model="searchParams" @search="getDataByPage" />
- <NCard title="鍒ゅ畾渚濇嵁鍒楄〃" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
- <template #header-extra>
- <TableHeaderOperation
- v-model:columns="columnChecks"
- :disabled-delete="checkedRowKeys.length === 0"
- :loading="loading"
- :show-add="hasAuth('qm:judge:add')"
- :show-delete="hasAuth('qm:judge:remove')"
- :show-export="hasAuth('qm:judge:export')"
- @add="handleAdd"
- @delete="handleBatchDelete"
- @export="handleExport"
- @refresh="getData"
- />
- </template>
- <NDataTable
- v-model:checked-row-keys="checkedRowKeys"
- :columns="columns"
- :data="data"
+ <div class="judge-content-area relative flex-col-stretch gap-16px sm:flex-1-hidden">
+ <NCard
+ title="鍒ゅ畾渚濇嵁鍒楄〃"
+ :bordered="false"
size="small"
- :flex-height="!appStore.isMobile"
- :scroll-x="scrollX"
- :loading="loading"
- remote
- :row-key="row => row.id"
- :pagination="mobilePagination"
- class="sm:h-full"
- />
- <JudgeOperateDrawer
- v-model:visible="drawerVisible"
- :operate-type="operateType"
- :row-data="editingData"
- @submitted="getDataByPage"
- />
- </NCard>
+ class="flex-col-stretch card-wrapper sm:flex-1-hidden"
+ :content-style="{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }"
+ >
+ <template #header-extra>
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:judge:add')"
+ :show-delete="hasAuth('qm:judge:remove')"
+ :show-export="hasAuth('qm:judge:export')"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @export="handleExport"
+ @refresh="getData"
+ />
+ </template>
+ <NDataTable
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="data"
+ size="small"
+ :flex-height="!appStore.isMobile"
+ :scroll-x="scrollX"
+ :loading="loading"
+ remote
+ :row-key="row => row.id"
+ :pagination="mobilePagination"
+ :row-props="handleRowClick"
+ class="flex-1-hidden"
+ />
+ <JudgeOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ @submitted="getDataByPage"
+ />
+ </NCard>
+ <JudgeDetailsSubTable :judge-id="selectedJudgeId" class="sm:flex-1-hidden" />
+ </div>
</div>
</template>
-<style scoped></style>
+<style scoped>
+:deep(.n-data-table-th),
+:deep(.n-data-table-td) {
+ padding: 4px 6px;
+ overflow: hidden;
+}
+</style>
diff --git a/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-operate-drawer.vue b/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-operate-drawer.vue
index 82a891e..28bfabd 100644
--- a/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-operate-drawer.vue
+++ b/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-operate-drawer.vue
@@ -1,10 +1,11 @@
<script setup lang="ts">
-import { computed, onMounted, ref, watch } from 'vue';
+import { computed, ref, watch } from 'vue';
import type { SelectOption } from 'naive-ui';
import { NSelect } from 'naive-ui';
import { jsonClone } from '@sa/utils';
import { fetchCreateJudge, fetchUpdateJudge } from '@/service/api/qm/judge';
import { fetchGetStdList } from '@/service/api/qm/std';
+import { fetchGetMatList } from '@/service/api/md/mat';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
@@ -53,6 +54,7 @@
];
const stdOptions = ref<SelectOption[]>([]);
+const matOptions = ref<SelectOption[]>([]);
type Model = Api.Qm.JudgeOperateParams;
@@ -102,6 +104,20 @@
}
}
+async function fetchMatOptions() {
+ if (model.value.category === 1) {
+ matOptions.value = [];
+ return;
+ }
+ const { data } = await fetchGetMatList({ tid: 1, pageSize: 1000 });
+ if (data) {
+ matOptions.value = data.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
+
async function handleSubmit() {
await validate();
@@ -147,20 +163,39 @@
emit('submitted');
}
-watch(visible, () => {
+watch(visible, async () => {
if (visible.value) {
handleUpdateModelWhenEdit();
restoreValidation();
- // Fetch stdOptions when the drawer becomes visible
- fetchStdOptions();
+ await fetchStdOptions();
+ await fetchMatOptions();
}
});
watch(
() => model.value.category,
- () => {
+ async () => {
fetchStdOptions();
+ model.value.matName = '';
+ model.value.matCode = '';
+ await fetchMatOptions();
+ }
+);
+
+watch(
+ () => model.value.matCode,
+ val => {
+ if (val) {
+ const selectedOption = matOptions.value.find(opt => opt.value === val);
+ if (selectedOption && typeof selectedOption.label === 'string') {
+ const name = selectedOption.label as string;
+ model.value.matName = name;
+ model.value.judgeName = name;
+ }
+ } else {
+ model.value.matName = '';
+ }
}
);
</script>
@@ -172,15 +207,17 @@
<NFormItem label="鍒ゅ畾鍚嶇О" path="judgeName">
<NInput v-model:value="model.judgeName" placeholder="璇疯緭鍏ュ垽瀹氬悕绉�" />
</NFormItem>
- <NFormItem label="鐗╂枡鐗屽彿浠g爜" path="matCode">
- <NInput v-model:value="model.matCode" placeholder="璇疯緭鍏ョ墿鏂欑墝鍙蜂唬鐮�" />
- </NFormItem>
- <NFormItem label="鐗╂枡鐗屽彿" path="matName">
- <NInput v-model:value="model.matName" placeholder="璇疯緭鍏ョ墿鏂欑墝鍙�" />
- </NFormItem>
<NFormItem label="鐗╂枡绫诲瀷" path="category">
<NSelect v-model:value="model.category" :options="categoryOptions" placeholder="璇烽�夋嫨鐗╂枡绫诲瀷" />
</NFormItem>
+ <NFormItem label="鐗╂枡鐗屽彿" path="matName">
+ <NSelect
+ v-model:value="model.matCode"
+ :options="matOptions"
+ placeholder="璇烽�夋嫨鐗╂枡鐗屽彿"
+ :disabled="model.category === 1"
+ />
+ </NFormItem>
<NFormItem label="鐘舵��" path="status">
<NSelect v-model:value="model.status" :options="statusOptions" placeholder="璇烽�夋嫨鐘舵��" />
</NFormItem>
diff --git a/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-search.vue b/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-search.vue
index 235b8a3..ba7c5dd 100644
--- a/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-search.vue
+++ b/ruoyi-plus-soybean/src/views/qm/judge/modules/judge-search.vue
@@ -1,6 +1,7 @@
<script setup lang="ts">
-import { toRaw } from 'vue';
+import { onMounted, ref, toRaw, watch } from 'vue';
import { jsonClone } from '@sa/utils';
+import { fetchGetMatList } from '@/service/api/md/mat';
import { useNaiveForm } from '@/hooks/common/form';
import { $t } from '@/locales';
@@ -19,6 +20,43 @@
const model = defineModel<Api.Qm.JudgeSearchParams>('model', { required: true });
const defaultModel = jsonClone(toRaw(model.value));
+
+const matOptions = ref<CommonType.Option[]>([]);
+
+async function getMatOptions() {
+ if (model.value.category !== 0) {
+ matOptions.value = [];
+ model.value.matName = null;
+ model.value.matCode = null;
+ return;
+ }
+ const { data } = await fetchGetMatList({ tid: 1, pageSize: 1000 });
+ if (data) {
+ matOptions.value = data.rows.map(item => ({
+ label: item.name,
+ value: item.code
+ }));
+ }
+}
+
+watch(
+ () => model.value.category,
+ newVal => {
+ if (newVal === 0) {
+ getMatOptions();
+ } else {
+ matOptions.value = [];
+ model.value.matName = null;
+ model.value.matCode = null;
+ }
+ }
+);
+
+onMounted(() => {
+ if (model.value.category === 0) {
+ getMatOptions();
+ }
+});
function resetModel() {
Object.assign(model.value, defaultModel);
@@ -53,11 +91,15 @@
/>
</NFormItemGi>
- <NFormItemGi span="24 s:12 m:6" label="鐗╂枡鐗屽彿浠g爜" label-width="auto" path="matCode" class="pr-24px">
- <NInput v-model:value="model.matCode" placeholder="璇疯緭鍏ョ墿鏂欑墝鍙蜂唬鐮�" />
- </NFormItemGi>
- <NFormItemGi span="24 s:12 m:6" label="鐗╂枡鐗屽彿" label-width="auto" path="matName" class="pr-24px">
- <NInput v-model:value="model.matName" placeholder="璇疯緭鍏ョ墿鏂欑墝鍙�" />
+ <NFormItemGi span="24 s:12 m:6" label="鐗╂枡鐗屽彿" label-width="auto" path="matCode" class="pr-24px">
+ <NSelect
+ v-model:value="model.matCode"
+ :options="matOptions"
+ placeholder="璇烽�夋嫨鐗╂枡鐗屽彿"
+ :disabled="model.category !== 0"
+ clearable
+ filterable
+ />
</NFormItemGi>
<NFormItemGi span="24 s:12 m:6" label="鍒ゅ畾鍚嶇О" label-width="auto" path="judgeName" class="pr-24px">
<NInput v-model:value="model.judgeName" placeholder="璇疯緭鍏ュ垽瀹氬悕绉�" />
diff --git a/ruoyi-plus-soybean/src/views/qm/matcheck/index.vue b/ruoyi-plus-soybean/src/views/qm/matcheck/index.vue
new file mode 100644
index 0000000..6203c03
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/qm/matcheck/index.vue
@@ -0,0 +1,268 @@
+<script setup lang="tsx">
+import { ref } from 'vue';
+import { NDivider } from 'naive-ui';
+import { fetchBatchDeleteMatcheck, fetchGetQmMatcheckList } from '@/service/api/qm/matcheck';
+import { useAppStore } from '@/store/modules/app';
+import { useAuth } from '@/hooks/business/auth';
+import { useDownload } from '@/hooks/business/download';
+import { defaultTransform, useNaivePaginatedTable, useTableOperate } from '@/hooks/common/table';
+import { $t } from '@/locales';
+import ButtonIcon from '@/components/custom/button-icon.vue';
+import MatcheckOperateDrawer from './modules/matcheck-operate-drawer.vue';
+import { useRoute } from 'vue-router';
+
+defineOptions({
+ name: 'MatcheckList'
+});
+
+
+const appStore = useAppStore();
+const { download } = useDownload();
+const { hasAuth } = useAuth();
+
+const route = useRoute();
+function getSingleQueryValue(query: string | string[] | null | undefined) {
+ if (Array.isArray(query)) return query[0] || '';
+ return query || '';
+}
+
+const judgeCode = getSingleQueryValue(route.query.judgeCode);
+const batchCode = getSingleQueryValue(route.query.batchCode);
+const matCode = getSingleQueryValue(route.query.matCode);
+
+const searchParams = ref<Api.Qm.MatcheckSearchParams>({
+ pageNum: 1,
+ pageSize: 10,
+ batchCode,
+ judgeCode,
+ matCode,
+ checkName: null,
+ checkTime: null,
+ reviewName: null,
+ reviewTiem: null,
+ params: {}
+});
+
+const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } =
+ useNaivePaginatedTable({
+ api: () => fetchGetQmMatcheckList(searchParams.value),
+ transform: response => defaultTransform(response),
+ onPaginationParamsChange: params => {
+ searchParams.value.pageNum = params.page;
+ searchParams.value.pageSize = params.pageSize;
+ },
+ columns: () => [
+ {
+ type: 'selection',
+ align: 'center',
+ width: 48
+ },
+ {
+ key: 'index',
+ title: $t('common.index'),
+ align: 'center',
+ width: 64,
+ render: (_, index) => index + 1
+ },
+ {
+ key: 'itemName',
+ title: '妫�楠岄」',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'maxval',
+ title: '鏈�澶у��/鐑熶笣璐ㄩ噺(鍚湯鐜�)',
+ align: 'center',
+ minWidth: 170
+ },
+ {
+ key: 'minval',
+ title: '鏈�灏忓��/鐑熸湯璐ㄩ噺(鍚湯鐜�)',
+ align: 'center',
+ minWidth: 170
+ },
+ {
+ key: 'avgval',
+ title: '骞冲潎鍊�/鍚湯鐜�',
+ align: 'center',
+ minWidth: 130
+ },
+ {
+ key: 'sdval',
+ title: 'SD鍊�',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'cvval',
+ title: 'CV鍊�',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'cpkval',
+ title: 'CPK鍊�',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'badval',
+ title: '瓒呮爣鏁�',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'checker',
+ title: '妫�楠屽憳',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'checkTime',
+ title: '妫�楠屾椂闂�',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'reviewName',
+ title: '澶嶆鍛�',
+ align: 'center',
+ minWidth: 100
+ },
+ {
+ key: 'reviewTime',
+ title: '澶嶆鏃堕棿',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'chkDes',
+ title: '鎻忚堪',
+ align: 'center',
+ minWidth: 120
+ },
+ {
+ key: 'operate',
+ title: $t('common.operate'),
+ align: 'center',
+ fixed: 'right',
+ width: 130,
+ render: row => {
+ const divider = () => {
+ if (!hasAuth('qm:matcheck:edit') || !hasAuth('qm:matcheck:remove')) {
+ return null;
+ }
+ return <NDivider vertical />;
+ };
+
+ const editBtn = () => {
+ if (!hasAuth('qm:matcheck:edit')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="primary"
+ icon="material-symbols:drive-file-rename-outline-outline"
+ tooltipContent={$t('common.edit')}
+ onClick={() => edit(row.id)}
+ />
+ );
+ };
+
+ const deleteBtn = () => {
+ if (!hasAuth('qm:matcheck:remove')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="error"
+ icon="material-symbols:delete-outline"
+ tooltipContent={$t('common.delete')}
+ popconfirmContent={$t('common.confirmDelete')}
+ onPositiveClick={() => handleDelete(row.id)}
+ />
+ );
+ };
+
+ return (
+ <div class="flex-center gap-8px">
+ {editBtn()}
+ {divider()}
+ {deleteBtn()}
+ </div>
+ );
+ }
+ }
+ ]
+});
+
+const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } =
+ useTableOperate(data, 'id', getData);
+
+async function handleBatchDelete() {
+ // request
+ const { error } = await fetchBatchDeleteMatcheck(checkedRowKeys.value);
+ if (error) return;
+ onBatchDeleted();
+}
+
+async function handleDelete(id: CommonType.IdType) {
+ // request
+ const { error } = await fetchBatchDeleteMatcheck([id]);
+ if (error) return;
+ onDeleted();
+}
+
+function edit(id: CommonType.IdType) {
+ handleEdit(id);
+}
+
+function handleExport() {
+ download('/qm/matcheck/export', searchParams.value, `鏉愭枡妫�楠岀粺璁${new Date().getTime()}.xlsx`);
+}
+</script>
+
+<template>
+ <div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
+ <NCard title="鏉愭枡妫�楠岀粺璁″垪琛�" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
+ <template #header-extra>
+ <TableHeaderOperation
+ v-model:columns="columnChecks"
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:matcheck:add')"
+ :show-delete="hasAuth('qm:matcheck:remove')"
+ :show-export="hasAuth('qm:matcheck:export')"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @export="handleExport"
+ @refresh="getData"
+ />
+ </template>
+ <NDataTable
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns"
+ :data="data"
+ size="small"
+ :flex-height="!appStore.isMobile"
+ :scroll-x="scrollX"
+ :loading="loading"
+ remote
+ :row-key="row => row.id"
+ :pagination="mobilePagination"
+ class="sm:h-full"
+ />
+ <MatcheckOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ @submitted="getDataByPage"
+ />
+ </NCard>
+ </div>
+</template>
+
+<style scoped></style>
diff --git a/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-operate-drawer.vue b/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-operate-drawer.vue
new file mode 100644
index 0000000..8115cdf
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-operate-drawer.vue
@@ -0,0 +1,266 @@
+<script setup lang="ts">
+import { computed, onMounted, ref, watch } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { fetchCreateMatcheck, fetchUpdateMatcheck, fetchCheckItemList } from '@/service/api/qm/matcheck';
+import { useFormRules, useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+import { useRoute } from 'vue-router';
+
+defineOptions({
+ name: 'MatcheckOperateDrawer'
+});
+
+interface Props {
+ /** the type of operation */
+ operateType: NaiveUI.TableOperateType;
+ /** the edit row data */
+ rowData?: Api.Qm.Matcheck | null;
+}
+
+const props = defineProps<Props>();
+
+interface Emits {
+ (e: 'submitted'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const visible = defineModel<boolean>('visible', {
+ default: false
+});
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+const { createRequiredRule } = useFormRules();
+const route = useRoute();
+
+// 妫�楠岄」閫夐」
+const checkItemOptions = ref<CommonType.Option[]>([]);
+
+// 鑾峰彇妫�楠岄」閫夐」
+async function getCheckItemOptions() {
+ const judgeCode = Array.isArray(route.query.judgeCode) ? route.query.judgeCode[0] : route.query.judgeCode;
+ if (!judgeCode) {
+ checkItemOptions.value = [];
+ return;
+ }
+
+ const { data, error } = await fetchCheckItemList({ judgeId: judgeCode });
+ if (!error && data) {
+ checkItemOptions.value = data.map(item => ({
+ label: item.itemName, // 鎺ュ彛杩斿洖鐨勫瓧娈垫槸 item_name
+ value: item.itemCode // 鎺ュ彛杩斿洖鐨勫瓧娈垫槸 item_code
+ }));
+ }
+}
+
+const title = computed(() => {
+ const titles: Record<NaiveUI.TableOperateType, string> = {
+ add: '鏂板鏉愭枡妫�楠岀粺璁�',
+ edit: '缂栬緫鏉愭枡妫�楠岀粺璁�'
+ };
+ return titles[props.operateType];
+});
+
+type Model = Api.Qm.MatcheckOperateParams;
+
+const model = ref<Model>(createDefaultModel());
+
+const generateDetailsChecked = computed<string | number | boolean | undefined>({
+ get() {
+ return model.value.generateDetails ?? '0';
+ },
+ set(value) {
+ model.value.generateDetails = String(value ?? '0');
+ }
+});
+
+
+function createDefaultModel(): Model {
+ // 鑾峰彇褰撳墠鏃ユ湡锛屾牸寮忎负 yyyy-MM-dd
+ const today = new Date().toISOString().split('T')[0];
+ const matCode = (route.query.matCode as string) || '';
+
+ return {
+ id: '',
+ pid: '',
+ batchCode: route.query.batchCode as string || '',
+ matCode,
+ instrumentCode: '',
+ techReq: '',
+ checkStd: '',
+ testEnv: '',
+ itemCode: '',
+ subBatchCode: '',
+ sampleNumber: null,
+ sampleType: null,
+ checkName: '',
+ checkTime: today,
+ reviewName: '',
+ reviewTime: null,
+ maxval: null,
+ minval: null,
+ avgval: null,
+ sdval: null,
+ cvval: null,
+ cpkval: null,
+ badval: null,
+ judge: '',
+ singlejudge: '',
+ verName: '',
+ verCode: '',
+ archDate: '',
+ del: null,
+ flag: '',
+ toMesTime: null,
+ chkDes: '',
+ generateDetails: '0'
+ };
+}
+
+type RuleKey = Extract<
+ keyof Model,
+ | 'id'
+>;
+
+const rules: Record<RuleKey, App.Global.FormRule> = {
+ id: createRequiredRule('涓婚敭锛岀紪鐮佷笉鑳戒负绌�'),
+};
+
+function handleUpdateModelWhenEdit() {
+ model.value = createDefaultModel();
+
+ if (props.operateType === 'edit' && props.rowData) {
+ Object.assign(model.value, jsonClone(props.rowData));
+ model.value.generateDetails = model.value.generateDetails ?? '0';
+ }
+}
+
+function closeDrawer() {
+ visible.value = false;
+}
+
+async function handleSubmit() {
+ await validate();
+
+ const { id, pid, batchCode, matCode, instrumentCode, techReq, checkStd, testEnv, itemCode, subBatchCode, sampleNumber, sampleType, checkName, checkTime, reviewName, reviewTime, maxval, minval, avgval, sdval, cvval, cpkval, badval, judge, singlejudge, verName, verCode, archDate, del, flag, toMesTime, chkDes, generateDetails } = model.value;
+
+ // request
+ if (props.operateType === 'add') {
+ const { error } = await fetchCreateMatcheck({ id, pid, batchCode, matCode, instrumentCode, techReq, checkStd, testEnv, itemCode, subBatchCode, sampleNumber, sampleType, checkName, checkTime, reviewName, reviewTime, maxval, minval, avgval, sdval, cvval, cpkval, badval, judge, singlejudge, verName, verCode, archDate, del, flag, toMesTime, chkDes, generateDetails });
+ if (error) return;
+ }
+
+ if (props.operateType === 'edit') {
+ const { error } = await fetchUpdateMatcheck({ id, pid, batchCode, matCode, instrumentCode, techReq, checkStd, testEnv, itemCode, subBatchCode, sampleNumber, sampleType, checkName, checkTime, reviewName, reviewTime, maxval, minval, avgval, sdval, cvval, cpkval, badval, judge, singlejudge, verName, verCode, archDate, del, flag, toMesTime, chkDes, generateDetails });
+ if (error) return;
+ }
+
+ window.$message?.success($t('common.updateSuccess'));
+ closeDrawer();
+ emit('submitted');
+}
+
+onMounted(() => {
+ getCheckItemOptions();
+});
+
+watch(visible, () => {
+ if (visible.value) {
+ handleUpdateModelWhenEdit();
+ restoreValidation();
+ getCheckItemOptions();
+ }
+});
+</script>
+
+<template>
+ <NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
+ <NDrawerContent :title="title" :native-scrollbar="false" closable>
+ <NForm ref="formRef" :model="model" :rules="rules" label-placement="left" :label-width="180">
+ <NFormItem label="鎵规鍙�" path="batchCode">
+ <NInput v-model:value="model.batchCode" placeholder="鎵规鍙�" :disabled="true" />
+ </NFormItem>
+ <NFormItem label="妫�楠岄」" path="itemCode">
+ <NSelect
+ v-model:value="model.itemCode"
+ placeholder="璇烽�夋嫨妫�楠岄」"
+ :options="checkItemOptions"
+ clearable
+ filterable
+ />
+ </NFormItem>
+ <NFormItem label="鐩樺彿" path="subBatchCode">
+ <NInput v-model:value="model.subBatchCode" placeholder="璇疯緭鍏ョ洏鍙�" />
+ </NFormItem>
+ <NFormItem path="maxval">
+ <template #label>
+ 鏈�澶у��/<br>
+ 鐑熶笣璐ㄩ噺/<br>
+ (鍚湯鐜�)
+ </template>
+ <NInputNumber v-model:value="model.maxval" placeholder="璇疯緭鍏ユ渶澶у��" class="w-full" />
+ </NFormItem>
+ <NFormItem path="minval">
+ <template #label>
+ 鏈�灏忓��/<br>
+ 鐑熸湯璐ㄩ噺/<br>
+ (鍚湯鐜�)
+ </template>
+ <NInputNumber v-model:value="model.minval" placeholder="璇疯緭鍏ユ渶灏忓��" class="w-full" />
+ </NFormItem>
+ <NFormItem path="avgval">
+ <template #label>
+ 骞冲潎鍊�/<br>
+ 鍚湯鐜�
+ </template>
+ <NInputNumber v-model:value="model.avgval" placeholder="璇疯緭鍏ュ钩鍧囧��" class="w-full" />
+ </NFormItem>
+ <NFormItem label="SD鍊�" path="sdval">
+ <NInputNumber v-model:value="model.sdval" placeholder="璇疯緭鍏D鍊�" class="w-full" />
+ </NFormItem>
+ <NFormItem label="CV鍊�" path="cvval">
+ <NInputNumber v-model:value="model.cvval" placeholder="璇疯緭鍏V鍊�" class="w-full" />
+ </NFormItem>
+ <NFormItem label="CPK鍊�" path="cpkval">
+ <NInputNumber v-model:value="model.cpkval" placeholder="璇疯緭鍏PK鍊�" class="w-full" />
+ </NFormItem>
+ <NFormItem label="瓒呮爣鏁�" path="badval">
+ <NInputNumber v-model:value="model.badval" placeholder="璇疯緭鍏ヨ秴鏍囨暟" class="w-full" />
+ </NFormItem>
+ <NFormItem label="妫�楠屾棩鏈�" path="checkTime">
+ <NDatePicker
+ v-model:formatted-value="model.checkTime"
+ type="date"
+ value-format="yyyy-MM-dd"
+ clearable
+ />
+ </NFormItem>
+ <NFormItem label="鍒ゅ畾" path="judge">
+ <NInput v-model:value="model.judge" placeholder="璇疯緭鍏ュ垽瀹�" />
+ </NFormItem>
+ <NFormItem label="鍗曢」鍒ゅ畾" path="singlejudge">
+ <NInput v-model:value="model.singlejudge" placeholder="璇疯緭鍏ュ崟椤瑰垽瀹�" />
+ </NFormItem>
+ <NFormItem label="鎻忚堪" path="chkDes">
+ <NInput v-model:value="model.chkDes" placeholder="璇疯緭鍏ユ弿杩�" />
+ </NFormItem>
+ <NFormItem label="鐢熸垚鏄庣粏" path="generateDetails">
+ <NCheckbox v-model:checked="generateDetailsChecked" checked-value="1" unchecked-value="0" />
+ </NFormItem>
+ </NForm>
+ <template #footer>
+ <NSpace :size="16">
+ <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
+ <NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
+ </NSpace>
+ </template>
+ </NDrawerContent>
+ </NDrawer>
+</template>
+
+<style scoped>
+.n-form-item-label {
+ white-space: pre-line;
+ line-height: 1.4;
+}
+</style>
diff --git a/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-search.vue b/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-search.vue
new file mode 100644
index 0000000..bc73db1
--- /dev/null
+++ b/ruoyi-plus-soybean/src/views/qm/matcheck/modules/matcheck-search.vue
@@ -0,0 +1,93 @@
+<script setup lang="ts">
+import { toRaw } from 'vue';
+import { jsonClone } from '@sa/utils';
+import { useNaiveForm } from '@/hooks/common/form';
+import { $t } from '@/locales';
+
+defineOptions({
+ name: 'MatcheckSearch'
+});
+
+interface Emits {
+ (e: 'search'): void;
+}
+
+const emit = defineEmits<Emits>();
+
+const { formRef, validate, restoreValidation } = useNaiveForm();
+
+const model = defineModel<Api.Qm.MatcheckSearchParams>('model', { required: true });
+
+const defaultModel = jsonClone(toRaw(model.value));
+
+function resetModel() {
+ Object.assign(model.value, defaultModel);
+}
+
+async function reset() {
+ await restoreValidation();
+ resetModel();
+ emit('search');
+}
+
+async function search() {
+ await validate();
+ emit('search');
+}
+</script>
+
+<template>
+ <NCard :bordered="false" size="small" class="card-wrapper">
+ <NCollapse>
+ <NCollapseItem :title="$t('common.search')" name="qm-matcheck-search">
+ <NForm ref="formRef" :model="model" label-placement="left" :label-width="80">
+ <NGrid responsive="screen" item-responsive>
+ <NFormItemGi span="24 s:12 m:6" label="鐗屽彿" label-width="auto" path="matCode" class="pr-24px">
+ <NInput v-model:value="model.matCode" placeholder="璇疯緭鍏ョ墝鍙�" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="妫�楠屽憳" label-width="auto" path="checkName" class="pr-24px">
+ <NInput v-model:value="model.checkName" placeholder="璇疯緭鍏ユ楠屽憳" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="妫�楠屾椂闂�" label-width="auto" path="checkTime" class="pr-24px">
+ <NDatePicker
+ v-model:formatted-value="model.checkTime"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="澶嶆牳鍛�" label-width="auto" path="reviewName" class="pr-24px">
+ <NInput v-model:value="model.reviewName" placeholder="璇疯緭鍏ュ鏍稿憳" />
+ </NFormItemGi>
+ <NFormItemGi span="24 s:12 m:6" label="澶嶆牳鏃堕棿" label-width="auto" path="reviewTiem" class="pr-24px">
+ <NDatePicker
+ v-model:formatted-value="model.reviewTiem"
+ type="datetime"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ clearable
+ />
+ </NFormItemGi>
+ <NFormItemGi :show-feedback="false" span="24" class="pr-24px">
+ <NSpace class="w-full" justify="end">
+ <NButton @click="reset">
+ <template #icon>
+ <icon-ic-round-refresh class="text-icon" />
+ </template>
+ {{ $t('common.reset') }}
+ </NButton>
+ <NButton type="primary" ghost @click="search">
+ <template #icon>
+ <icon-ic-round-search class="text-icon" />
+ </template>
+ {{ $t('common.search') }}
+ </NButton>
+ </NSpace>
+ </NFormItemGi>
+ </NGrid>
+ </NForm>
+ </NCollapseItem>
+ </NCollapse>
+ </NCard>
+</template>
+
+<style scoped></style>
--
Gitblit v1.9.3