From 6f90e7110190d146fde06cf1f5b2272fd49b53d6 Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期一, 19 十月 2026 17:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
src/components/Table/lims-table.vue | 10
src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue | 788 +++++++++++++++++++-------------
src/api/cnas/process/ensureResults/qualityMonitor.js | 32 +
src/utils/inspectionValueFormat.js | 58 ++
src/components/Excel/luckysheet.vue | 7
src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue | 25
src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue | 13
src/api/cnas/process/method/methodVerification.js | 9
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue | 233 +++++++++
src/views/business/inspectionTask/inspection.vue | 31 +
src/views/business/inspectionTask/index.vue | 73 ++
src/views/standard/model/index.vue | 14
package.json | 1
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue | 136 ++++
14 files changed, 1,073 insertions(+), 357 deletions(-)
diff --git a/package.json b/package.json
index ca6f270..2605259 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"html2canvas": "^1.4.1",
"js-beautify": "1.15.4",
"js-cookie": "3.0.5",
+ "jsbarcode": "^3.12.3",
"jsencrypt": "3.3.2",
"jspdf": "^2.5.2",
"mammoth": "^1.13.0",
diff --git a/src/api/cnas/process/ensureResults/qualityMonitor.js b/src/api/cnas/process/ensureResults/qualityMonitor.js
index 55bb995..73883b6 100644
--- a/src/api/cnas/process/ensureResults/qualityMonitor.js
+++ b/src/api/cnas/process/ensureResults/qualityMonitor.js
@@ -1,6 +1,38 @@
// 璐ㄩ噺鐩戞帶璁″垝椤甸潰鐩稿叧鎺ュ彛
import request from '@/utils/request'
+export function createAnnualPlan(data) {
+ return request({ url: '/qualityMonitor/createAnnualPlan', method: 'post', data })
+}
+
+export function getAnnualPlan(params) {
+ return request({ url: '/qualityMonitor/getAnnualPlan', method: 'get', params })
+}
+
+export function submitAnnualPlan(qualityMonitorId) {
+ return request({ url: '/qualityMonitor/submitAnnualPlan', method: 'post', data: { qualityMonitorId } })
+}
+
+export function dispatchInspectionTask(qualityMonitorDetailsId) {
+ return request({ url: '/qualityMonitor/dispatchInspectionTask', method: 'post', data: { qualityMonitorDetailsId } })
+}
+
+export function cancelInspectionTask(qualityMonitorDetailsId) {
+ return request({ url: '/qualityMonitor/cancelInspectionTask', method: 'post', data: { qualityMonitorDetailsId } })
+}
+
+export function getInspectionEvaluation(qualityMonitorDetailsId) {
+ return request({ url: '/qualityMonitor/getInspectionEvaluation', method: 'get', params: { qualityMonitorDetailsId } })
+}
+
+export function submitInspectionEvaluation(data) {
+ return request({ url: '/qualityMonitor/submitInspectionEvaluation', method: 'post', data })
+}
+
+export function approveInspectionEvaluation(data) {
+ return request({ url: '/qualityMonitor/approveInspectionEvaluation', method: 'post', data })
+}
+
// 鐩戞帶骞村害璁″垝鍒楄〃
export function pageQualityMonitor(query) {
return request({
diff --git a/src/api/cnas/process/method/methodVerification.js b/src/api/cnas/process/method/methodVerification.js
index 582953e..e0658e8 100644
--- a/src/api/cnas/process/method/methodVerification.js
+++ b/src/api/cnas/process/method/methodVerification.js
@@ -47,6 +47,15 @@
})
}
+// 鎸夊綋鍓嶆墍閫夎澶囧疄鏃惰鍙栨牎鍑嗚瘉涔�
+export function getCurrentCalibrationFiles(query) {
+ return request({
+ url: '/processMethodVerify/getCurrentCalibrationFiles',
+ method: 'get',
+ params: query,
+ })
+}
+
// 淇敼鏍囧噯鏂规硶楠岃瘉
export function updateMethodVerify(data) {
return request({
diff --git a/src/components/Excel/luckysheet.vue b/src/components/Excel/luckysheet.vue
index bf779ad..204b6eb 100644
--- a/src/components/Excel/luckysheet.vue
+++ b/src/components/Excel/luckysheet.vue
@@ -51,6 +51,13 @@
mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1024 1024'%3E%3Cpath d='M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896m0 192a58.43 58.43 0 0 0-58.24 63.744l23.36 256.384a35.072 35.072 0 0 0 69.76 0l23.296-256.384A58.43 58.43 0 0 0 512 256m0 512a51.2 51.2 0 1 0 0-102.4 51.2 51.2 0 0 0 0 102.4'/%3E%3C/svg%3E") center/contain no-repeat;
}
+/* Luckysheet 鐨勫伐鍏锋爮涓嬫媺鑿滃崟锛堟壒娉ㄣ�佸瓧浣撻鑹茬瓑锛夋槸鎸傚湪 body 涓婄殑锛�
+ 榛樿 z-index 鍙湁 1004锛涗笂闈� #luckysheet 鎶埌浜� 99999锛屼細鎶婅繖浜涜彍鍗曟暣涓洊浣忥紝
+ 琛ㄧ幇涓衡�滅偣鎵规敞娌″弽搴斺�濄�傛妸 body 绾ц彍鍗曟姮鍒板鍣ㄤ箣涓娿�� */
+.luckysheet-cols-menu {
+ z-index: 100001 !important;
+}
+
#luckysheet .save:hover {
opacity: 0.8;
}
diff --git a/src/components/Table/lims-table.vue b/src/components/Table/lims-table.vue
index 8b7a584..70539e5 100644
--- a/src/components/Table/lims-table.vue
+++ b/src/components/Table/lims-table.vue
@@ -35,7 +35,7 @@
:label="item.label"
:prop="item.prop"
:show-overflow-tooltip="item.dataType === 'action' || item.dataType === 'slot' ? false : true"
- :min-width="columnWidth(item)"
+ :min-width="columnMinWidth(item)"
:sortable="item.sortable ? true : false"
:type="item.type"
:width="columnWidth(item)"
@@ -214,6 +214,14 @@
})
function columnWidth(item) {
+ if (item.minWidth) return undefined
+ return item.dataType === 'action' ? actionColumnWidth.value : item.width
+}
+
+// 閰嶇疆 minWidth 鏃跺彧绾︽潫鏈�灏忓搴︼紝鎶婂墿浣欑┖闂翠氦缁� Element Plus 鑷姩鍒嗛厤銆�
+// 鏈厤缃� minWidth 鐨勬棫椤甸潰缁х画娌跨敤鍘熸湁鍥哄畾 width 琛屼负銆�
+function columnMinWidth(item) {
+ if (item.minWidth) return item.minWidth
return item.dataType === 'action' ? actionColumnWidth.value : item.width
}
diff --git a/src/utils/inspectionValueFormat.js b/src/utils/inspectionValueFormat.js
new file mode 100644
index 0000000..f0f536a
--- /dev/null
+++ b/src/utils/inspectionValueFormat.js
@@ -0,0 +1,58 @@
+/**
+ * 瑙f瀽鍘熷璁板綍妯℃澘涓殑妫�楠屽�兼壒娉ㄣ��
+ * 鍏煎鏃ф牸寮忊�滄楠屽�尖�濓紝骞舵敮鎸侊細妫�楠屽�硷紝2銆佹楠屽�硷紝2锛岀瀛﹁鏁版硶銆�
+ */
+export function parseInspectionValueAnnotation(annotation) {
+ if (typeof annotation !== 'string' || !annotation.includes('妫�楠屽��')) return null;
+ // 鎵规敞鍏佽涓枃閫楀彿銆佽嫳鏂囬�楀彿浠ュ強鈥滃拰鈥濊繛鎺ユ牸寮忓弬鏁般��
+ const parts = annotation
+ .replace(/锛�/g, ',')
+ .replace(/\s+/g, '')
+ .replace(/鍜�/g, ',')
+ .split(',')
+ .map(item => item.trim())
+ .filter(Boolean);
+ const decimalPlaces = parts[1] === '' || parts[1] == null ? null : Number(parts[1]);
+ if (decimalPlaces != null && (!Number.isInteger(decimalPlaces) || decimalPlaces < 0 || decimalPlaces > 15)) {
+ return { error: '灏忔暟浣嶆暟蹇呴』鏄� 0 鍒� 15 鐨勬暣鏁�' };
+ }
+ const displayMode = parts.slice(2).includes('绉戝璁℃暟娉�') ? 'SCIENTIFIC' : 'NORMAL';
+ const roundingNames = {
+ '鍥涜垗浜斿叆': 'HALF_UP',
+ '鍥涜垗鍏叆': 'HALF_UP_6',
+ '鍚戜笂鑸嶅叆': 'CEILING',
+ '鍚戜笅鑸嶅叆': 'FLOOR',
+ '鎴柇': 'DOWN'
+ };
+ const roundingPart = parts.slice(2).find(item => Object.prototype.hasOwnProperty.call(roundingNames, item));
+ const unsupported = parts.slice(2).filter(item => item && item !== '绉戝璁℃暟娉�' && !roundingNames[item]);
+ if (unsupported.length || parts.length > 4) {
+ return { error: '妫�楠屽�兼壒娉ㄦ牸寮忓簲涓猴細妫�楠屽�硷紝2锛屽洓鑸嶄簲鍏� 鎴� 妫�楠屽�硷紝2锛岀瀛﹁鏁版硶锛屽洓鑸嶄簲鍏�' };
+ }
+ return { decimalPlaces, displayMode, roundingMode: roundingPart ? roundingNames[roundingPart] : 'HALF_UP' };
+}
+
+export function formatInspectionValue(value, config) {
+ if (!config || config.error || config.decimalPlaces == null || value === '' || value == null) return value;
+ const number = Number(value);
+ if (!Number.isFinite(number)) return value;
+ const factor = 10 ** config.decimalPlaces;
+ let rounded;
+ if (config.roundingMode === 'CEILING') rounded = Math.ceil(number * factor) / factor;
+ else if (config.roundingMode === 'FLOOR') rounded = Math.floor(number * factor) / factor;
+ else if (config.roundingMode === 'DOWN') rounded = (number < 0 ? Math.ceil(number * factor) : Math.floor(number * factor)) / factor;
+ else if (config.roundingMode === 'HALF_UP_6') {
+ const absolute = Math.abs(number) * factor;
+ const base = Math.floor(absolute);
+ const fraction = absolute - base;
+ rounded = (number < 0 ? -1 : 1) * ((fraction >= 0.6 ? base + 1 : base) / factor);
+ } else rounded = Math.round((number + (number >= 0 ? Number.EPSILON : -Number.EPSILON)) * factor) / factor;
+ return config.displayMode === 'SCIENTIFIC'
+ ? rounded.toExponential(config.decimalPlaces)
+ : rounded.toFixed(config.decimalPlaces);
+}
+
+export function validateInspectionValueAnnotation(annotation) {
+ const config = parseInspectionValueAnnotation(annotation);
+ return config && config.error ? config.error : null;
+}
diff --git a/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue b/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue
index 62415a7..6341f59 100644
--- a/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue
+++ b/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue
@@ -1,45 +1,73 @@
<template>
<div>
- <el-dialog title="缂栬緫" v-model="formDia"
+ <el-dialog :title="operationType === 'add' ? '鏂板璐ㄦ帶椤圭洰' : '缂栬緫璐ㄦ帶椤圭洰'" v-model="formDia"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="80%" @close="closeDia">
<el-form :model="form" :rules="rules" ref="form" label-width="140px">
<el-col :span="12">
- <el-form-item label="鐩戞帶鐩殑" prop="monitorPurpose">
- <el-input v-model="form.monitorPurpose" size="small" clearable></el-input>
+ <el-form-item label="搴忓彿" prop="sortNo">
+ <el-input-number v-model="form.sortNo" :min="1" style="width:100%" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="璁″垝寮�灞曟椂闂�" prop="plannedTime">
- <el-input v-model="form.plannedTime" size="small" clearable></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="鐩戞帶椤圭洰" prop="monitorProject">
+ <el-form-item label="璐ㄦ帶椤圭洰" prop="monitorProject">
<el-input v-model="form.monitorProject" size="small" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鍙傚姞鍗曚綅锛堜汉鍛橈級" prop="participant">
- <el-input v-model="form.participant" size="small" clearable></el-input>
+ <el-form-item label="鎶�鏈爣鍑�" prop="technicalStandardText">
+ <el-input v-model="form.technicalStandardText" size="small" clearable placeholder="鏍囧噯缂栧彿鍙婂悕绉帮紱闈炴娴嬬被鍙~鍐欑▼搴忔枃浠舵垨/" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="棰勭畻锛堝厓锛�" prop="budget">
- <el-input v-model="form.budget" size="small" clearable></el-input>
+ <el-form-item label="璐ㄦ帶鏂瑰紡" prop="monitorWay">
+ <el-input v-model="form.monitorWay" size="small" clearable placeholder="濡傜洸鏍锋娴嬨�佷汉鍛樻瘮瀵广�佺洃鐫f鏌�" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="缁勭粐浜哄憳" prop="organization">
- <el-input v-model="form.organization" size="small" clearable></el-input>
+ <el-form-item label="瀹屾垚鏃堕檺" prop="completionMonth">
+ <el-date-picker v-model="form.completionMonth" type="month" value-format="YYYY-MM" format="YYYY.MM" style="width:100%" />
</el-form-item>
</el-col>
<el-col :span="12">
- <el-form-item label="鐩戞帶鏂瑰紡" prop="monitorWay">
- <el-input v-model="form.monitorWay" size="small" clearable></el-input>
+ <el-form-item label="璐熻矗浜�" prop="responsibleUserId">
+ <el-select v-model="form.responsibleUserId" filterable style="width:100%">
+ <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
+ </el-select>
</el-form-item>
</el-col>
+ <el-col :span="12">
+ <el-form-item label="浜嬮」绫诲埆" prop="itemKind">
+ <el-select v-model="form.itemKind" style="width: 100%">
+ <el-option label="闈炴娴嬬被" value="OTHER" />
+ <el-option label="妫�娴嬬被" value="INSPECTION" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <template v-if="form.itemKind === 'INSPECTION'">
+ <el-col :span="12"><el-form-item label="妫�娴嬫爣鍑�" prop="standardMethodId">
+ <el-select v-model="form.standardMethodId" filterable style="width: 100%" placeholder="璇烽�夋嫨妫�娴嬫爣鍑�" @change="handleStandardChange">
+ <el-option v-for="item in standardOptions" :key="item.id" :value="item.id" :label="`${item.code || ''} ${item.name || ''}`" />
+ </el-select>
+ </el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="鍘熷璁板綍妯℃澘" prop="templateIds">
+ <el-select v-model="form.templateIds" multiple collapse-tags filterable style="width: 100%" placeholder="鍙�夋嫨澶氫釜妯℃澘">
+ <el-option v-for="item in templateOptions" :key="item.id" :value="item.id" :label="item.name" />
+ </el-select>
+ </el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="鏍峰搧鍚嶇О"><el-input v-model="form.sampleName" /></el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="鏍峰搧瑙勬牸"><el-input v-model="form.sampleSpec" /></el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="妫�娴嬪憳"><el-select v-model="form.inspectorUserId" filterable style="width: 100%">
+ <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
+ </el-select></el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="璇勪环浜�"><el-select v-model="form.evaluatorUserId" filterable style="width: 100%">
+ <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
+ </el-select></el-form-item></el-col>
+ <el-col :span="12"><el-form-item label="浠诲姟鎴鏃�">
+ <el-date-picker v-model="form.dueDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
+ </el-form-item></el-col>
+ </template>
</el-form>
<template #footer><span class="dialog-footer">
<el-button @click="closeDia">鍙� 娑�</el-button>
@@ -54,6 +82,9 @@
addQualityMonitorDetail,
updateQualityMonitorDetail
} from "@/api/cnas/process/ensureResults/qualityMonitor";
+import { selectStandardMethodList } from '@/api/cnas/process/method/standardMethod';
+import { selectStandardTemplatePageList } from '@/api/standard/model';
+import { selectUserCondition } from '@/api/performance/class';
export default {
name: 'detailFormDialog',
@@ -66,6 +97,10 @@
formDia: false,
form: {
qualityMonitorDetailsId: '',
+ sortNo: null,
+ technicalStandardText: '',
+ completionMonth: '',
+ responsibleUserId: null,
monitorPurpose: '',
plannedTime: '',
monitorProject: '',
@@ -73,10 +108,26 @@
budget: '',
organization: '',
monitorWay: '',
+ itemKind: 'OTHER',
+ standardMethodId: null,
+ templateId: null,
+ templateIds: [],
+ sampleName: '',
+ sampleSpec: '',
+ inspectorUserId: null,
+ evaluatorUserId: null,
+ dueDate: null,
},
+ standardOptions: [],
+ templateOptions: [],
+ userOptions: [],
rules: {
- monitorPurpose: [{ required: true, message: '璇疯緭鍏ョ洃鎺х洰鐨�', trigger: 'blur' }],
- monitorProject: [{ required: true, message: '璇疯緭鍏ョ洃鎺ч」鐩�', trigger: 'blur' }],
+ monitorProject: [{ required: true, message: '璇疯緭鍏ヨ川鎺ч」鐩�', trigger: 'blur' }],
+ technicalStandardText: [{ required: true, message: '璇疯緭鍏ユ妧鏈爣鍑�', trigger: 'blur' }],
+ monitorWay: [{ required: true, message: '璇疯緭鍏ヨ川鎺ф柟寮�', trigger: 'blur' }],
+ completionMonth: [{ required: true, message: '璇烽�夋嫨瀹屾垚鏃堕檺', trigger: 'change' }],
+ responsibleUserId: [{ required: true, message: '璇烽�夋嫨璐熻矗浜�', trigger: 'change' }],
+ templateIds: [{ required: true, type: 'array', min: 1, message: '璇疯嚦灏戦�夋嫨涓�涓師濮嬭褰曟ā鏉�', trigger: 'change' }],
},
upLoad: false,
operationType: '',
@@ -86,18 +137,59 @@
methods: {
openDia(type, row) {
this.formDia = true
+ selectStandardMethodList({ current: 1, size: 1000 }).then(res => { this.standardOptions = res.data?.records || res.data || [] })
+ selectStandardTemplatePageList({ current: 1, size: 1000 }).then(res => { this.templateOptions = res.data?.records || res.data || [] })
+ selectUserCondition({ type: 1 }).then(res => { this.userOptions = res.data || [] })
this.operationType = type
if (type === 'edit') {
this.searchInfo(row)
}
},
searchInfo (row) {
- this.form = {...row}
+ const templateIds = row.templateIds
+ ? String(row.templateIds).split(',').filter(Boolean).map(id => Number(id))
+ : (row.templateId ? [Number(row.templateId)] : [])
+ this.form = {...row, itemKind: row.itemKind || 'OTHER', templateIds}
+ },
+ handleStandardChange(id) {
+ const standard = this.standardOptions.find(item => Number(item.id) === Number(id))
+ if (standard) this.form.technicalStandardText = `${standard.code || ''} ${standard.name || ''}`.trim()
+ this.form.templateIds = []
+ this.form.templateId = null
+ },
+ buildEntity () {
+ const entity = this.HaveJson(this.form)
+ const templateIds = Array.isArray(this.form.templateIds)
+ ? this.form.templateIds.map(id => Number(id)).filter(id => Number.isInteger(id) && id > 0)
+ : []
+ entity.templateIds = templateIds.join(',') || null
+ entity.templateId = templateIds.length ? templateIds[0] : null
+ entity.reviewerUserId = null
+ return entity
},
// 鎻愪氦琛ㄥ崟
submitForm () {
this.$refs['form'].validate((valid) => {
if (valid) {
+ if (this.form.itemKind === 'INSPECTION') {
+ const required = ['standardMethodId','sampleName','inspectorUserId','evaluatorUserId','dueDate']
+ if (required.some(key => !this.form[key])) {
+ this.$message.warning('璇疯ˉ榻愭娴嬫爣鍑嗐�佹ā鏉裤�佹牱鍝併�佹娴嬪憳銆佽瘎浠蜂汉鍜屼换鍔℃埅姝㈡棩')
+ return
+ }
+ if (!Array.isArray(this.form.templateIds) || !this.form.templateIds.length) {
+ this.$message.warning('璇疯嚦灏戦�夋嫨涓�涓師濮嬭褰曟ā鏉�')
+ return
+ }
+ if (this.form.inspectorUserId === this.form.evaluatorUserId) {
+ this.$message.warning('妫�娴嬪憳涓嶈兘鍚屾椂鎷呬换璇勪环浜�')
+ return
+ }
+ if (this.form.dueDate.slice(0, 7) > this.form.completionMonth) {
+ this.$message.warning('浠诲姟鎴鏃ヤ笉鑳芥櫄浜庤鍒掑畬鎴愭湀浠�')
+ return
+ }
+ }
if (this.operationType === 'add') {
this.handleAdd()
} else {
@@ -108,7 +200,7 @@
},
// 鎻愪氦鏂板
handleAdd () {
- let entity = this.HaveJson(this.form)
+ let entity = this.buildEntity()
entity.qualityMonitorId = this.qualityMonitorId
this.upLoad = true
addQualityMonitorDetail(entity).then(res => {
@@ -122,7 +214,7 @@
},
// 鎻愪氦淇敼
handleEdit () {
- const entity = this.HaveJson(this.form)
+ const entity = this.buildEntity()
this.upLoad = true
updateQualityMonitorDetail(entity).then(res => {
this.upLoad = false
diff --git a/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue b/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue
new file mode 100644
index 0000000..110092e
--- /dev/null
+++ b/src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue
@@ -0,0 +1,233 @@
+<template>
+ <el-dialog v-model="visible" title="璐ㄩ噺鎺у埗璇勪环璁板綍" width="min(960px, 94vw)" @closed="$emit('close')">
+ <div class="record-code">璁板綍缂栧彿锛歀MSY-CX30-JL03</div>
+ <el-alert v-if="row"
+ :title="`鐩戞帶浠诲姟 ${row.inspectionTaskCode || row.entrustCode || ''} 路 ${row.monitorProject || ''}`"
+ type="info"
+ :closable="false"/>
+ <el-alert v-if="!canEdit" :title="editNotice" :type="loaded ? 'warning' : 'info'"
+ :closable="false" style="margin-top:8px"/>
+ <el-form :model="form" label-width="110px" style="margin-top: 16px">
+ <el-row :gutter="12">
+ <el-col :span="12">
+ <el-form-item label="妫�娴嬮」鐩�">
+ <el-input :model-value="row?.monitorProject" disabled/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="妫�娴嬫椂闂�">
+ <el-input :model-value="inspectionDateDisplay" readonly placeholder="鍘熷璁板綍澶嶆牳鍚庤嚜鍔ㄥ甫鍏�"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="妫�娴嬫牱鍝�">
+ <el-input :model-value="row?.sampleName || row?.sample" disabled/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鎵�鐢ㄨ澶�">
+ <el-input :model-value="form.rawEquipmentDescription || ''" type="textarea"
+ :autosize="{ minRows: 1, maxRows: 6 }" readonly placeholder="鍘熷璁板綍澶嶆牳鍚庤嚜鍔ㄥ甫鍏�"/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁惧瑙勬牸">
+ <el-input :model-value="form.rawEquipmentSpec || ''" type="textarea" :autosize="{ minRows: 1, maxRows: 6 }"
+ readonly/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="璁惧缂栧彿">
+ <el-input :model-value="form.rawEquipmentCode || ''" type="textarea" :autosize="{ minRows: 1, maxRows: 6 }"
+ readonly/>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐩戠潱鍛�">
+ <el-select v-model="form.supervisorUserId" filterable style="width: 100%" :disabled="!canEdit">
+ <el-option v-for="person in supervisorOptions" :key="person.id" :value="person.id" :label="person.name"/>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="琚洃鐫d汉鍛�">
+ <el-input :model-value="supervisedPersonName" disabled/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="妫�娴嬫儏鍐靛強璇勪环">
+ <el-input v-model="form.evaluationConclusion" type="textarea" :rows="4" :disabled="!canEdit"/>
+ </el-form-item>
+ <el-table :data="form.resultRows" border style="width:100%">
+ <el-table-column label="浜哄憳濮撳悕" min-width="120">
+ <template #default>{{ supervisedPersonName }}</template>
+ </el-table-column>
+ <el-table-column label="褰撴棩妫�娴嬫暟鎹�" min-width="180">
+ <template #default="{ row: item }"><span :title="item.itemName || ''">{{
+ item.measuredValue
+ }} {{ item.unit === '/' ? '' : item.unit }}</span></template>
+ </el-table-column>
+ <el-table-column label="鐩叉牱鍊�" min-width="180">
+ <template #default="{ row: item }">
+ <el-input v-model="item.referenceValue" :disabled="!canEdit" placeholder="璇勪环浜哄~鍐�"/>
+ </template>
+ </el-table-column>
+ </el-table>
+ <el-checkbox v-if="canEdit" v-model="form.measurementConfirmed" style="margin:12px 0">
+ 宸叉牳瀵瑰綋鏃ユ娴嬫暟鎹笌宸插鏍稿師濮嬭褰曚竴鑷�
+ </el-checkbox>
+ <el-form-item label="璇勪环浜哄憳绛惧瓧">
+ <el-input
+ :model-value="form.reviewUser ? `${form.reviewUser} ${form.reviewTime || ''}` : '鎻愪氦鍚庤褰曡瘎浠蜂汉鍙婃棩鏈�'"
+ disabled/>
+ </el-form-item>
+ <el-form-item label="绾犳鎺柦鍙婇闃叉帾鏂�">
+ <el-input v-model="form.correctiveAction" type="textarea" :rows="2" :disabled="!canEdit"/>
+ </el-form-item>
+ <el-row :gutter="12">
+ <el-col :span="12">
+ <el-form-item label="绾犳璐d换浜�">
+ <el-select v-model="form.correctiveResponsibleUserId" filterable clearable style="width:100%"
+ :disabled="!canEdit">
+ <el-option v-for="person in people" :key="person.id" :value="person.id" :label="person.name"/>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀹屾垚鏃ユ湡">
+ <el-date-picker v-model="form.correctiveDueDate" type="date" value-format="YYYY-MM-DD" style="width:100%"
+ :disabled="!canEdit"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="楠岃瘉鎯呭喌">
+ <el-input v-model="form.verificationResult" type="textarea" :rows="2" :disabled="!canEdit"/>
+ </el-form-item>
+ <el-row :gutter="12">
+ <el-col :span="12">
+ <el-form-item label="楠岃瘉璐d换浜�">
+ <el-select v-model="form.verificationResponsibleUserId" filterable clearable style="width:100%"
+ :disabled="!canEdit">
+ <el-option v-for="person in people" :key="person.id" :value="person.id" :label="person.name"/>
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="楠岃瘉鏃ユ湡">
+ <el-date-picker v-model="form.verificationDate" type="date" value-format="YYYY-MM-DD" style="width:100%"
+ :disabled="!canEdit"/>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item v-if="form.ratifyOpinion" label="鎵瑰噯鎰忚">
+ <el-input :model-value="form.ratifyOpinion" disabled/>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button @click="visible = false">鍏抽棴</el-button>
+ <el-button v-if="canEdit" type="primary" :loading="loading" @click="save">鎻愪氦璇勪环</el-button>
+ <template v-if="canApprove">
+ <el-button :loading="loading" @click="approve(false)">閫�鍥炶瘎浠�</el-button>
+ <el-button type="primary" :loading="loading" @click="approve(true)">鎵瑰噯褰掓。</el-button>
+ </template>
+ </template>
+ </el-dialog>
+</template>
+
+<script>
+import {mapGetters} from '@/utils/store-compat';
+import {selectUserCondition} from '@/api/performance/class';
+import {
+ getInspectionEvaluation,
+ submitInspectionEvaluation,
+ approveInspectionEvaluation
+} from '@/api/cnas/process/ensureResults/qualityMonitor';
+
+export default {
+ name: 'InspectionEvaluationDialog',
+ emits: ['close'],
+ data() {
+ return {visible: false, loading: false, loaded: false, loadError: '', row: null, people: [], form: {resultRows: []}}
+ },
+ computed: {
+ ...mapGetters(['userId']),
+ canEdit() {
+ return this.loaded && this.form.evaluationEditable === true
+ },
+ inspectionDateDisplay() {
+ const dates = this.form.rawInspectionDates || []
+ if (!dates.length) return ''
+ return dates.length === 1 ? dates[0] : `${dates[0]} 锝� ${dates[dates.length - 1]}`
+ },
+ editNotice() {
+ if (!this.loaded) return '姝e湪璇诲彇璇勪环璁板綍鍜岀紪杈戞潈闄愨��'
+ return this.loadError || this.form.evaluationEditReason || '褰撳墠璐﹀彿鍙兘鏌ョ湅璇勪环璁板綍'
+ },
+ canApprove() {
+ return !!this.form.detailsEvaluateId && this.form.isFinish !== 1 && Number(this.userId) === Number(this.row?.planRatifyUserId)
+ },
+ supervisedPersonName() {
+ const id = this.form.inspectorUserId || this.row?.inspectorUserId
+ return this.people.find(person => Number(person.id) === Number(id))?.name || ''
+ },
+ supervisorOptions() {
+ const inspectorId = Number(this.form.inspectorUserId || this.row?.inspectorUserId)
+ const evaluatorId = Number(this.row?.evaluatorUserId)
+ return this.people.filter(person => Number(person.id) !== inspectorId && Number(person.id) !== evaluatorId)
+ }
+ },
+ methods: {
+ open(row) {
+ this.row = row
+ this.loaded = false
+ this.loadError = ''
+ this.form = {
+ qualityMonitorDetailsId: row.qualityMonitorDetailsId,
+ inspectorUserId: row.inspectorUserId,
+ resultRows: [],
+ measurementConfirmed: false
+ }
+ this.visible = true
+ selectUserCondition({type: 1}).then(res => {
+ this.people = res.data || []
+ })
+ getInspectionEvaluation(row.qualityMonitorDetailsId).then(res => {
+ if (res.data) this.form = {...res.data, resultRows: res.data.resultRows || [], measurementConfirmed: false}
+ }).catch(() => {
+ this.loadError = '璇勪环璁板綍璇诲彇澶辫触锛岃鍒锋柊鍚庨噸璇�'
+ }).finally(() => {
+ this.loaded = true
+ })
+ },
+ save() {
+ if (!this.form.supervisorUserId || !this.form.evaluationConclusion?.trim() || !this.form.resultRows?.length || this.form.resultRows.some(item => !item.measuredValue || !item.referenceValue?.trim()) || !this.form.measurementConfirmed) {
+ this.$message.warning('璇烽�夋嫨鐩戠潱鍛橈紝濉啓妫�娴嬫儏鍐靛強璇勪环銆佺洸鏍峰�硷紝骞舵牳瀵瑰師濮嬭褰曟娴嬫暟鎹�')
+ return
+ }
+ this.loading = true
+ submitInspectionEvaluation(this.form).then(() => {
+ this.$message.success('璇勪环宸叉彁浜�')
+ this.visible = false
+ }).finally(() => {
+ this.loading = false
+ })
+ },
+ approve(approved) {
+ this.$prompt('璇疯緭鍏ユ壒鍑嗘垨閫�鍥炴剰瑙�', approved ? '鎵瑰噯璇勪环' : '閫�鍥炶瘎浠�', {inputValue: this.form.ratifyOpinion || ''}).then(({value}) => {
+ this.loading = true
+ approveInspectionEvaluation({
+ qualityMonitorDetailsId: this.row.qualityMonitorDetailsId,
+ approved,
+ opinion: value
+ }).then(() => {
+ this.$message.success(approved ? '璇勪环宸插綊妗�' : '璇勪环宸查��鍥�')
+ this.visible = false
+ }).finally(() => {
+ this.loading = false
+ })
+ }).catch(() => {
+ })
+ }
+ }
+}
+</script>
diff --git a/src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue b/src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue
index 4589e7b..224c51e 100644
--- a/src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue
+++ b/src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue
@@ -1,38 +1,80 @@
<template>
<!-- 7.7璐ㄩ噺鐩戞帶璁″垝-->
<div class="app-container">
- <div class="table-card">
- <div style="display: flex;justify-content: space-between">
- <div style="display: flex;">
- <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
- <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">璁″垝鍚嶇О</span>
- <el-input size="small" placeholder="璇疯緭鍏�" clearable v-model="yearForm.monitorName"
- @keyup.enter="getYearPlanList"></el-input>
- </div>
- <div style="line-height: 30px;">
- <el-button type="primary" size="small" @click="getYearPlanList">鏌ヨ</el-button>
- <el-button size="small" @click="clearYear">閲嶇疆</el-button>
- </div>
+ <section v-if="pageMode === 'list'" class="plan-list-card">
+ <div class="plan-list-toolbar">
+ <div class="plan-list-filters">
+ <span class="annual-plan-label">璁″垝骞村害</span>
+ <el-date-picker v-model="selectedYear" type="year" value-format="YYYY" format="YYYY骞�" :clearable="false"
+ size="small" style="width: 130px" @change="handleYearChange" />
+ <span class="filter-label">璁″垝鍚嶇О</span>
+ <el-input v-model="yearForm.monitorName" clearable placeholder="璇疯緭鍏�" size="small" style="width: 220px"
+ @keyup.enter="getYearPlanList" />
+ <el-button type="primary" size="small" @click="getYearPlanList">鏌ヨ</el-button>
+ <el-button size="small" @click="clearYear">閲嶇疆</el-button>
</div>
- <div style="line-height: 30px;">
- <el-button size="small" type="primary" @click="leadInto">瀵煎叆</el-button>
+ <div class="plan-list-actions">
+ <el-button size="small" @click="leadInto">瀵煎叆</el-button>
+ <el-button type="primary" size="small" @click="openCreatePlan">鏂板缓骞村害璁″垝</el-button>
</div>
</div>
- <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage" :tableLoading="yearLoading"
- :height="'calc(100vh - 34em)'" @pagination="pagination" :rowClick="rowClick" key="yearTableData"></lims-table>
+ <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage"
+ :tableLoading="yearLoading" :height="'calc(100vh - 11em)'" @pagination="pagination" key="yearTableData">
+ <template #planActions="{ row }">
+ <div class="detail-actions">
+ <el-button link type="primary" size="small" @click="openPlan(row)">鏌ョ湅璁″垝</el-button>
+ <el-button v-if="canReviewRow(row)" link type="primary" size="small" @click="examinePlan(row)">瀹℃牳</el-button>
+ <el-button v-if="canApproveRow(row)" link type="primary" size="small" @click="approvalPlan(row)">鎵瑰噯</el-button>
+ <el-dropdown trigger="click" @command="command => handlePlanCommand(command, row)">
+ <el-button link type="primary" size="small">鏇村鈱�</el-button>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item command="export" :disabled="row.ratifyStatus !== 1">瀵煎嚭骞村害璁″垝</el-dropdown-item>
+ <el-dropdown-item command="delete" divided :disabled="!canDeleteRow(row)">鍒犻櫎</el-dropdown-item>
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
+ </div>
+ </template>
+ </lims-table>
+ </section>
+
+ <template v-else>
+ <div class="annual-plan-header">
+ <div class="annual-plan-main">
+ <el-button link type="primary" size="small" @click="backToPlanList">鈫� 杩斿洖骞村害璁″垝</el-button>
+ <span class="annual-plan-label">{{ selectedYear }}骞村害</span>
+ <template v-if="currentPlan">
+ <strong>{{ currentPlan.monitorName }}</strong>
+ <el-tag :type="planStatusType">{{ planStatusText }}</el-tag>
+ <span>缂栧埗锛歿{ currentPlan.writeName || '-' }} {{ formatDate(currentPlan.writeTime) }}</span>
+ <span>瀹℃牳锛歿{ currentPlan.examineName || '-' }}</span>
+ <span>鎵瑰噯锛歿{ currentPlan.ratifyName || '-' }}</span>
+ </template>
+ <el-tag v-else type="info">璇ュ勾搴﹀皻鏈缓绔嬭鍒�</el-tag>
+ </div>
+ <div class="annual-plan-actions">
+ <el-button v-if="canEditPlan" type="primary" size="small" @click="submitPlan">鎻愪氦瀹℃牳</el-button>
+ <el-button v-if="canReviewPlan" type="primary" size="small" @click="examinePlan(currentPlan)">瀹℃牳</el-button>
+ <el-button v-if="canApprovePlan" type="primary" size="small" @click="approvalPlan(currentPlan)">鎵瑰噯</el-button>
+ <el-button size="small" @click="leadInto">瀵煎叆</el-button>
+ <el-button v-if="currentPlan" size="small" :disabled="currentPlan.ratifyStatus !== 1" @click="handleDown(currentPlan)">瀵煎嚭骞村害璁″垝</el-button>
+ </div>
</div>
- <div style="margin-top: 20px">
- <div style="display: flex;justify-content: space-between">
+ <div class="plan-detail-card">
+ <div class="plan-detail-toolbar">
<div style="display: flex;">
+ <span class="section-title">璐ㄦ帶椤圭洰</span>
<div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
- <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">鐩戞帶鐩殑</span>
- <el-input v-model="yearDetailForm.monitorPurpose" placeholder="璇疯緭鍏�" size="small"
+ <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">璐ㄦ帶椤圭洰</span>
+ <el-input v-model="yearDetailForm.monitorProject" placeholder="璇疯緭鍏�" size="small"
@keyup.enter="getYearDetailPlanList"></el-input>
</div>
<div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
- <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">鐩戞帶椤圭洰</span>
- <el-input v-model="yearDetailForm.monitorProject" placeholder="璇疯緭鍏�" size="small"
- @keyup.enter="getYearDetailPlanList"></el-input>
+ <span style="width: 70px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">璐熻矗浜�</span>
+ <el-select v-model="yearDetailForm.responsibleUserId" clearable filterable size="small" style="width: 160px">
+ <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" />
+ </el-select>
</div>
<div style="line-height: 30px;">
<el-button type="primary" size="small" @click="getYearDetailPlanList">鏌ヨ</el-button>
@@ -40,14 +82,65 @@
</div>
</div>
<div style="line-height: 30px;">
- <el-button size="small" type="primary" @click="exportSignatureTemplate">瀵煎嚭绛惧悕妯℃澘</el-button>
- <el-button size="small" type="primary" @click="showDialog('add')">鏂板</el-button>
+<!-- <el-button size="small" type="primary" @click="exportSignatureTemplate">瀵煎嚭绛惧悕妯℃澘</el-button>-->
+ <el-button size="small" type="primary" :disabled="!canEditPlan" @click="showDialog('add')">鏂板璐ㄦ帶椤圭洰</el-button>
</div>
</div>
<lims-table :tableData="yearDetailTableData" :column="yearDetailColumnData" :page="yearDetailPage"
- :tableLoading="yearDetailLoading" :height="'calc(100vh - 34em)'" @pagination="pagination1" ref="yearDetailTableData"
- key="yearDetailTableData"></lims-table>
+ :tableLoading="yearDetailLoading" :height="'calc(100vh - 15em)'" @pagination="pagination1" ref="yearDetailTableData"
+ key="yearDetailTableData">
+ <template #detailActions="{ row }">
+ <div class="detail-actions">
+ <el-button link type="primary" size="small" :disabled="!canEditPlan || !!row.inspectionTaskId"
+ @click="showDialog('edit', row)">缂栬緫</el-button>
+
+ <el-button v-if="row.itemKind !== 'INSPECTION'" link type="primary" size="small"
+ @click="carryOut(row)">瀹炴柦</el-button>
+ <el-button v-else-if="!row.inspectionTaskId" link type="primary" size="small"
+ :disabled="row.planRatifyStatus !== 1" @click="dispatchTask(row)">涓嬪彂浠诲姟</el-button>
+ <el-button v-else link type="primary" size="small" @click="evaluate(row)">
+ {{ row.inspectionTaskState === 5 ? '璇勪环璁板綍' : '璇勪环瑕佹眰' }}
+ </el-button>
+
+ <el-dropdown trigger="click" @command="command => handleDetailCommand(command, row)">
+ <el-button link type="primary" size="small">鏇村鈱�</el-button>
+ <template #dropdown>
+ <el-dropdown-menu>
+ <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="complete">瀹屾垚鎶ュ憡</el-dropdown-item>
+ <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="evaluate">璇勪环</el-dropdown-item>
+ <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && !row.inspectionTaskId" command="requirement">璇勪环瑕佹眰</el-dropdown-item>
+ <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && row.inspectionTaskId" command="cancel"
+ :disabled="row.inspectionTaskOrderState !== 1 || row.inspectionTaskState !== 0">鍙栨秷浠诲姟</el-dropdown-item>
+ <el-dropdown-item command="attachment">闄勪欢涓婁紶</el-dropdown-item>
+ <el-dropdown-item command="export">瀵煎嚭</el-dropdown-item>
+ <el-dropdown-item command="delete" divided
+ :disabled="!canEditPlan || !!row.inspectionTaskId">鍒犻櫎</el-dropdown-item>
+ </el-dropdown-menu>
+ </template>
+ </el-dropdown>
+ </div>
+ </template>
+ </lims-table>
</div>
+ </template>
+ <el-dialog v-model="createPlanDialog" title="鏂板缓骞村害璐ㄩ噺鎺у埗璁″垝" width="520px">
+ <el-form :model="planForm" label-width="90px">
+ <el-form-item label="骞村害">
+ <el-date-picker v-model="planForm.monitorYear" type="year" value-format="YYYY" format="YYYY骞�"
+ :clearable="false" style="width: 100%" placeholder="璇烽�夋嫨骞村害" />
+ </el-form-item>
+ <el-form-item label="璁″垝鍚嶇О"><el-input v-model="planForm.monitorName" /></el-form-item>
+ <el-form-item label="瀹℃牳浜�">
+ <el-select v-model="planForm.examineUserId" filterable style="width:100%">
+ <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" />
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <el-button @click="createPlanDialog=false">鍙栨秷</el-button>
+ <el-button type="primary" :loading="createPlanLoading" @click="createPlan">纭畾</el-button>
+ </template>
+ </el-dialog>
<!--鏂板淇敼寮规-->
<detail-form-dialog v-if="formDia" ref="formDia" :qualityMonitorId="qualityMonitorId"
@closeDia="closeDia"></detail-form-dialog>
@@ -56,6 +149,8 @@
@closeCarryOutDia="closeCarryOutDia"></carry-out-dialog>
<!--璇勪环娴佺▼寮规-->
<evaluate-dialog v-if="evaluateDialog" ref="evaluateDialog" @closeEvaDia="closeEvaDia"></evaluate-dialog>
+ <inspection-evaluation-dialog v-if="inspectionEvaluateDialog" ref="inspectionEvaluateDialog"
+ @close="closeInspectionEvaluateDialog" />
<el-dialog v-model="examineDialog" title="瀹℃牳" width="30%" @close="closeExamineDia">
<span>
瀹℃牳澶囨敞锛�
@@ -170,17 +265,20 @@
<script>
import DetailFormDialog from './components/detailFormDialog.vue';
+import InspectionEvaluationDialog from './components/inspectionEvaluationDialog.vue';
import CarryOutDialog from './components/carryOutDialog.vue';
import EvaluateDialog from './components/evaluateDialog.vue';
import filePreview from "@/components/Preview/filePreview.vue";
import limsTable from "@/components/Table/lims-table.vue";
import {
+ createAnnualPlan, getAnnualPlan, submitAnnualPlan,
delQualityMonitorDetail,
delQualitySupervise,
examineQualityMonitor, exportQualityMonitorDetail, exportQualityMonitorEvaluate, exportQualityMonitorRatify,
pageQualityMonitor, pageQualityMonitorDetail, ratifyFinishReport,
ratifyQualityMonitor
} from "@/api/cnas/process/ensureResults/qualityMonitor";
+import { dispatchInspectionTask, cancelInspectionTask } from "@/api/cnas/process/ensureResults/qualityMonitor";
import { selectUserCondition } from "@/api/performance/class";
import { mapGetters } from "@/utils/store-compat";
import ViewRecord from "./components/ViewRecord.vue";
@@ -188,11 +286,19 @@
export default {
name: 'EnsureResultsValidity',
// import 寮曞叆鐨勭粍浠堕渶瑕佹敞鍏ュ埌瀵硅薄涓墠鑳戒娇鐢�
- components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog },
+ components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog, InspectionEvaluationDialog },
data() {
// 杩欓噷瀛樻斁鏁版嵁
return {
ViewRecord: false,
+ inspectionEvaluateDialog: false,
+ pageMode: 'list',
+ selectedYear: String(new Date().getFullYear()),
+ currentPlan: null,
+ selectedPlanId: null,
+ createPlanDialog: false,
+ createPlanLoading: false,
+ planForm: { monitorYear: String(new Date().getFullYear()), monitorName: '', examineUserId: null },
examineUserId: '',
responsibleOptions: [],
yearForm: {
@@ -207,247 +313,92 @@
{
label: '璁″垝鍚嶇О',
prop: 'monitorName',
- width: '150px'
+ minWidth: '220px'
+ }, {
+ label: '璁″垝骞村害',
+ prop: 'monitorYear',
+ width: '100px'
+ }, {
+ dataType: 'tag',
+ label: '璁″垝鐘舵��',
+ prop: 'workflowStatus',
+ width: '110px',
+ formatData: (value, row) => this.planWorkflowText(value),
+ formatType: value => this.planWorkflowType(value)
}, {
label: '缂栧埗浜�',
prop: 'writeName',
- width: '100'
+ minWidth: '100px'
}, {
label: '缂栧埗鏃ユ湡',
prop: 'writeTime',
- width: '160'
- }, {
- dataType: 'tag',
- label: '瀹℃牳鐘舵��',
- prop: 'examineStatus',
- width: '100',
- formatData: (params) => {
- if (params === 0) {
- return '涓嶉�氳繃';
- } else if (params === 1) {
- return '閫氳繃';
- } else {
- return null;
- }
- },
- formatType: (params) => {
- if (params === 0) {
- return 'danger';
- } else if (params === 1) {
- return 'success';
- } else {
- return null;
- }
- }
- }, {
- label: '瀹℃牳鍐呭',
- prop: 'examineRemark',
- width: '100'
+ minWidth: '150px',
+ formatData: value => this.formatDate(value)
}, {
label: '瀹℃牳浜�',
prop: 'examineName',
- width: '100'
+ minWidth: '100px'
}, {
label: '瀹℃牳鏃ユ湡',
prop: 'examineTime',
- width: '160'
- }, {
- dataType: 'tag',
- label: '鎵瑰噯鐘舵��',
- prop: 'ratifyStatus',
- width: '100',
- formatData: (params) => {
- if (params === 0) {
- return '涓嶆壒鍑�';
- } else if (params === 1) {
- return '鎵瑰噯';
- } else {
- return null;
- }
- },
- formatType: (params) => {
- if (params === 0) {
- return 'danger';
- } else if (params === 1) {
- return 'success';
- } else {
- return null;
- }
- }
- }, {
- label: '鎵瑰噯鍐呭',
- prop: 'ratifyRemark',
- width: '100'
+ minWidth: '150px',
+ formatData: value => this.formatDate(value)
}, {
label: '鎵瑰噯浜�',
prop: 'ratifyName',
- width: '100'
+ minWidth: '100px'
}, {
label: '鎵瑰噯鏃ユ湡',
prop: 'ratifyTime',
- width: '160'
+ minWidth: '150px',
+ formatData: value => this.formatDate(value)
}, {
- dataType: 'action',
+ dataType: 'slot',
+ slot: 'planActions',
label: '鎿嶄綔',
fixed: 'right',
- operation: [
- {
- name: '瀹℃牳',
- type: 'text',
- disabled: (row) => {
- if (row.examineStatus === 1 || this.userId != row.examineUserId) {
- return true
- } else {
- return false
- }
- },
- clickFun: (row) => {
- this.examinePlan(row)
- }
- },
- {
- name: '鎵瑰噯',
- type: 'text',
- disabled: (row) => {
- if (row.ratifyStatus === 1 || row.examineStatus !== 1 || this.userId != row.ratifyUserId) {
- return true
- } else {
- return false
- }
- },
- clickFun: (row) => {
- this.approvalPlan(row)
- }
- },
- {
- name: '瀵煎嚭',
- type: 'text',
- clickFun: (row) => {
- this.handleDown(row)
- },
- disabled: (row) => {
- if (row.ratifyStatus !== 1) {
- return true
- } else {
- return false
- }
- },
- },
- {
- name: '鍒犻櫎',
- type: 'text',
- color: 'var(--el-color-danger)',
- clickFun: (row) => {
- this.delPlan(row)
- },
- disabled: (row) => {
- if (row.examineStatus === 1) {
- return true;
- } else {
- return false;
- }
- },
- }
- ]
+ width: '220px'
}],
yearTableData: [], // 骞磋〃
yearLoading: false,
yearDetailForm: {
- monitorPurpose: '',
monitorProject: '',
+ responsibleUserId: null,
},
yearDetailColumnData: [
{
- label: '鐩戞帶鐩殑',
- prop: 'monitorPurpose',
- width: '150px',
- showOverflowTooltip: true,
- }, {
- label: '璁″垝寮�灞曟椂闂�',
- prop: 'plannedTime',
- width: '150px'
- }, {
- label: '鐩戞帶椤圭洰',
+ label: '璐ㄦ帶椤圭洰',
prop: 'monitorProject',
- width: '150px'
+ minWidth: '140px'
}, {
- label: '鍙傚姞鍗曚綅锛堜汉鍛橈級',
- prop: 'participant',
- width: '190px'
+ label: '鎶�鏈爣鍑�',
+ prop: 'technicalStandardText',
+ minWidth: '220px'
}, {
- label: '棰勭畻锛堝厓锛�',
- prop: 'budget',
- width: '150px'
- }, {
- label: '缁勭粐浜哄憳',
- prop: 'organization',
- width: '150px'
- }, {
- label: '鐩戞帶鏂瑰紡',
+ label: '璐ㄦ帶鏂瑰紡',
prop: 'monitorWay',
- width: '150px'
- },{
- dataType: 'tag',
- label: '瀹炴柦鐘舵��',
- prop: 'detailsRatifyStatus',
- width: '100',
- formatData: (params) => {
- if (params === 0) {
- return '鏈紑濮�';
- } else if (params === 1) {
- return '寰呰瘎浠�';
- } else if (params === 2) {
- return '涓嶆壒鍑�';
- } else if (params === 3) {
- return '宸叉壒鍑�';
- } else {
- return null;
- }
- },
- formatType: (params) => {
- if (params === 0) {
- return '';
- } else if (params === 1) {
- return 'warning';
- } else if (params === 2) {
- return 'danger';
- } else if (params === 3) {
- return 'success';
- } else {
- return null;
- }
- }
- },{
- dataType: 'tag',
- label: '鎶ュ憡鐘舵��',
- prop: 'reportStatus',
- width: '100',
- formatData: (params) => {
- if (params === 0) {
- return '鏈紑濮�';
- } else if (params === 1) {
- return '寰呰瘎浠�';
- } else if (params === 2) {
- return '涓嶆壒鍑�';
- } else if (params === 3) {
- return '宸叉壒鍑�';
- } else {
- return null;
- }
- },
- formatType: (params) => {
- if (params === 0) {
- return '';
- } else if (params === 1) {
- return 'warning';
- } else if (params === 2) {
- return 'danger';
- } else if (params === 3) {
- return 'success';
- } else {
- return null;
- }
- }
+ minWidth: '120px'
+ }, {
+ label: '瀹屾垚鏃堕檺',
+ prop: 'completionMonth',
+ width: '110px',
+ formatData: value => value ? value.replace('-', '.') : ''
+ }, {
+ label: '璐熻矗浜�',
+ prop: 'responsibleName',
+ minWidth: '100px'
+ }, {
+ label: '璇勪环浜�',
+ prop: 'evaluatorName',
+ minWidth: '100px'
+ }, {
+ label: '浜嬮」绫诲埆', prop: 'itemKind', width: '100px',
+ formatData: value => value === 'INSPECTION' ? '妫�娴嬬被' : '闈炴娴嬬被'
+ }, {
+ label: '鐩戞帶浠诲姟缂栧彿', prop: 'inspectionTaskCode', minWidth: '150px'
+ }, {
+ label: '浠诲姟鐘舵��', prop: 'inspectionTaskState', width: '100px',
+ formatData: value => this.inspectionTaskStatus(value)
},{
dataType: 'tag',
label: '璇勪环鐘舵��',
@@ -480,61 +431,11 @@
}
}
}, {
- dataType: 'action',
+ dataType: 'slot',
+ slot: 'detailActions',
label: '鎿嶄綔',
fixed: 'right',
- operation: [
- {
- name: '缂栬緫',
- type: 'text',
- clickFun: (row) => {
- this.showDialog('edit', row)
- }
- },
- {
- name: '瀹炴柦',
- type: 'text',
- clickFun: (row) => {
- this.carryOut(row)
- }
- },
- {
- name: '瀹屾垚鎶ュ憡',
- type: 'text',
- clickFun: (row) => {
- this.record(row)
- },
- },
- {
- name: '璇勪环',
- type: 'text',
- clickFun: (row) => {
- this.evaluate(row)
- }
- },
- {
- name: '闄勪欢涓婁紶',
- type: 'text',
- clickFun: (row) => {
- this.viewTestRecord(row)
- }
- },
- {
- name: '瀵煎嚭',
- type: 'text',
- clickFun: (row) => {
- this.downLoadPost(row);
- },
- },
- {
- name: '鍒犻櫎',
- type: 'text',
- color: 'var(--el-color-danger)',
- clickFun: (row) => {
- this.delYearPlanDetail(row)
- }
- }
- ]
+ width: '220px'
}
],
yearDetailTableData: [], // 骞存槑缁嗚〃
@@ -574,31 +475,91 @@
};
},
mounted() {
+ this.getUserList()
this.getYearPlanList()
},
// 鏂规硶闆嗗悎
methods: {
// 鏌ヨ骞村害璁″垝琛�
getYearPlanList() {
- const entity = {
- monitorName: this.yearForm.monitorName,
- }
- const page = this.yearPage
this.yearLoading = true
- pageQualityMonitor({ ...entity, ...page }).then(res => {
- this.yearLoading = false
- this.yearTableData = res.data.records
- this.yearPage.total = res.data.total
- if (this.yearTableData.length > 0) {
- this.rowClick(this.yearTableData[0])
- }
- }).catch(err => {
- console.log('err---', err);
+ const entity = {
+ monitorYear: this.selectedYear,
+ monitorName: this.yearForm.monitorName
+ }
+ return pageQualityMonitor({ ...entity, ...this.yearPage }).then(res => {
+ this.yearTableData = res.data?.records || []
+ this.yearPage.total = res.data?.total || 0
+ }).finally(() => {
this.yearLoading = false
})
},
+ loadAnnualPlan() {
+ if (!this.selectedPlanId) return Promise.resolve()
+ return this.loadPlanVersion()
+ },
+ loadPlanVersion() {
+ if (!this.selectedPlanId) return Promise.resolve()
+ return getAnnualPlan({ monitorYear: this.selectedYear, qualityMonitorId: this.selectedPlanId }).then(res => {
+ this.currentPlan = res.data || null
+ this.qualityMonitorId = this.currentPlan?.qualityMonitorId || ''
+ this.yearDetailPage.current = 1
+ return this.getYearDetailPlanList()
+ })
+ },
+ openPlan(row, addFirstDetail = false) {
+ this.selectedYear = String(row.monitorYear || this.selectedYear)
+ this.selectedPlanId = row.qualityMonitorId
+ this.pageMode = 'detail'
+ return this.loadPlanVersion().then(() => {
+ if (addFirstDetail) this.showDialog('add')
+ })
+ },
+ backToPlanList() {
+ this.pageMode = 'list'
+ this.currentPlan = null
+ this.qualityMonitorId = ''
+ this.yearDetailForm = { monitorProject: '', responsibleUserId: null }
+ this.getYearPlanList()
+ },
+ handleYearChange() {
+ this.yearPage.current = 1
+ this.getYearPlanList()
+ },
+ openCreatePlan() {
+ this.planForm = {
+ monitorYear: String(new Date().getFullYear()),
+ monitorName: '',
+ examineUserId: null
+ }
+ this.createPlanDialog = true
+ },
+ createPlan() {
+ if (!this.planForm.monitorYear || !this.planForm.monitorName || !this.planForm.examineUserId) {
+ this.$message.warning('璇烽�夋嫨骞村害銆佸~鍐欒鍒掑悕绉板苟閫夋嫨瀹℃牳浜�')
+ return
+ }
+ this.createPlanLoading = true
+ createAnnualPlan({ ...this.planForm }).then(res => {
+ this.createPlanDialog = false
+ this.selectedYear = String(res.data.monitorYear)
+ this.yearPage.current = 1
+ this.$message.success('骞村害璁″垝宸插垱寤猴紝璇峰~鍐欑涓�涓川鎺ч」鐩�')
+ return this.getYearPlanList().then(() => this.openPlan(res.data, true))
+ }).finally(() => { this.createPlanLoading = false })
+ },
+ submitPlan() {
+ this.$confirm('鎻愪氦鍚庤川鎺ч」鐩皢閿佸畾锛岀‘璁ゆ彁浜ゅ鏍革紵', '鎻愪氦瀹℃牳').then(() => {
+ submitAnnualPlan(this.qualityMonitorId).then(() => {
+ this.$message.success('宸叉彁浜ゅ鏍�')
+ this.loadPlanVersion()
+ this.getYearPlanList()
+ })
+ }).catch(() => {})
+ },
clearYear() {
this.yearForm.monitorName = ''
+ this.yearPage.current = 1
this.getYearPlanList()
},
pagination({ page, limit }) {
@@ -609,10 +570,11 @@
pagination1({ page, limit }) {
this.yearDetailPage.current = page;
this.yearDetailPage.size = limit;
- this.getYearPlanList();
+ this.getYearDetailPlanList();
},
leadInto() {
this.uploadDia = true
+ this.planYear = this.selectedYear
this.getUserList()
},
// 瀵煎叆娴佺▼
@@ -636,7 +598,7 @@
this.timer = setTimeout(() => {
this.uploadDia = false
this.fileList = []
- this.planYear = ''
+ this.planYear = this.selectedYear
this.examineUserId = ''
this.getYearPlanList()
}, 1000)
@@ -650,7 +612,7 @@
return;
}
if (!this.examineUserId) {
- this.$message.warning('璇烽�夋嫨鎵瑰噯浜�')
+ this.$message.warning('璇烽�夋嫨瀹℃牳浜�')
return;
}
this.$refs.upload.submit();
@@ -678,7 +640,7 @@
closeExamineDia() {
this.examineDialog = false
this.examineInfo.examineRemark = ''
- this.getYearPlanList()
+ this.refreshPlanData()
},
// 鎵瑰噯
approvalPlan(row) {
@@ -701,7 +663,14 @@
closeRatifyDia() {
this.ratifyDialog = false
this.ratifyInfo.ratifyRemark = ''
- this.getYearPlanList()
+ this.refreshPlanData()
+ },
+ refreshPlanData() {
+ return this.getYearPlanList().then(() => {
+ if (this.pageMode === 'detail' && this.selectedPlanId) {
+ return this.loadPlanVersion()
+ }
+ })
},
// 鎵瑰噯鎶ュ憡
handleApproval(status) {
@@ -762,8 +731,8 @@
getYearDetailPlanList() {
const entity = {
qualityMonitorId: this.qualityMonitorId,
- monitorPurpose: this.yearDetailForm.monitorPurpose,
monitorProject: this.yearDetailForm.monitorProject,
+ responsibleUserId: this.yearDetailForm.responsibleUserId,
}
const page = this.yearDetailPage
this.yearDetailLoading = true
@@ -771,7 +740,7 @@
this.yearDetailLoading = false
this.yearDetailTableData = res.data.records
this.yearDetailPage.total = res.data.total
- this.$refs.yearDetailTableData.$refs.multipleTable.doLayout()
+ this.$nextTick(() => this.$refs.yearDetailTableData?.$refs?.multipleTable?.doLayout())
}).catch(err => {
console.log('err---', err);
this.yearDetailLoading = false
@@ -780,8 +749,8 @@
// 閲嶇疆鏄庣粏琛�
clearDetail() {
this.yearDetailForm = {
- monitorPurpose: '',
- monitorProject: ''
+ monitorProject: '',
+ responsibleUserId: null
}
this.getYearDetailPlanList()
},
@@ -862,6 +831,11 @@
// end
// 鎵撳紑璇勪环寮规
evaluate(row) {
+ if (row.itemKind === 'INSPECTION') {
+ this.inspectionEvaluateDialog = true
+ this.$nextTick(() => this.$refs.inspectionEvaluateDialog.open(row))
+ return
+ }
this.evaluateDialog = true
this.$nextTick(() => {
this.$refs.evaluateDialog.openDia(row)
@@ -870,6 +844,26 @@
closeEvaDia() {
this.evaluateDialog = false
this.getYearDetailPlanList()
+ },
+ closeInspectionEvaluateDialog() {
+ this.inspectionEvaluateDialog = false
+ this.getYearDetailPlanList()
+ },
+ dispatchTask(row) {
+ this.$confirm(`纭涓嬪彂鈥�${row.monitorProject}鈥濈殑璐ㄩ噺鐩戞帶妫�楠屼换鍔★紵`, '涓嬪彂浠诲姟').then(() => {
+ dispatchInspectionTask(row.qualityMonitorDetailsId).then(res => {
+ this.$message.success(`宸蹭笅鍙戠洃鎺т换鍔★細${res.data.entrustCode}`)
+ this.getYearDetailPlanList()
+ })
+ }).catch(() => {})
+ },
+ cancelTask(row) {
+ this.$confirm(`纭鍙栨秷鐩戞帶浠诲姟鈥�${row.inspectionTaskCode}鈥濓紵宸插彇娑堜换鍔′細淇濈暀鍘嗗彶璁板綍銆俙, '鍙栨秷浠诲姟').then(() => {
+ cancelInspectionTask(row.qualityMonitorDetailsId).then(() => {
+ this.$message.success('浠诲姟宸插彇娑�')
+ this.getYearDetailPlanList()
+ })
+ }).catch(() => {})
},
// 闄勪欢涓婁紶
viewTestRecord (row) {
@@ -885,6 +879,14 @@
},
// 鎵撳紑骞村害鏄庣粏鏂板銆佷慨鏀瑰脊妗�
showDialog(type, row) {
+ if (!this.qualityMonitorId) {
+ this.$message.warning('璇峰厛鏂板缓骞村害璐ㄩ噺鎺у埗璁″垝')
+ return
+ }
+ if (!this.canEditPlan) {
+ this.$message.warning('褰撳墠璁″垝鐘舵�佷笉鑳界淮鎶よ川鎺ч」鐩�')
+ return
+ }
this.formDia = true
this.$nextTick(() => {
this.$refs.formDia.openDia(type, row)
@@ -949,11 +951,93 @@
link.target = '_blank';
document.body.appendChild(link);
link.click();
+ },
+ formatDate(value) {
+ return value ? String(value).slice(0, 10) : '-'
+ },
+ planWorkflowText(value) {
+ return ({
+ DRAFT: '鑽夌',
+ PENDING_REVIEW: '寰呭鏍�',
+ REVIEW_REJECTED: '瀹℃牳閫�鍥�',
+ PENDING_APPROVAL: '寰呮壒鍑�',
+ APPROVAL_REJECTED: '鎵瑰噯閫�鍥�',
+ APPROVED: '宸叉壒鍑�'
+ })[value] || '鍘嗗彶璁″垝'
+ },
+ planWorkflowType(value) {
+ return ({
+ DRAFT: 'info',
+ PENDING_REVIEW: 'warning',
+ REVIEW_REJECTED: 'danger',
+ PENDING_APPROVAL: 'warning',
+ APPROVAL_REJECTED: 'danger',
+ APPROVED: 'success'
+ })[value] || 'info'
+ },
+ canReviewRow(row) {
+ return row.workflowStatus === 'PENDING_REVIEW'
+ && Number(this.userId) === Number(row.examineUserId)
+ },
+ canApproveRow(row) {
+ return row.workflowStatus === 'PENDING_APPROVAL'
+ && Number(this.userId) === Number(row.ratifyUserId)
+ },
+ canDeleteRow(row) {
+ return Number(this.userId) === Number(row.writeUserId)
+ && ['DRAFT', 'REVIEW_REJECTED', 'APPROVAL_REJECTED'].includes(row.workflowStatus || 'DRAFT')
+ },
+ handlePlanCommand(command, row) {
+ if (command === 'export') this.handleDown(row)
+ if (command === 'delete') this.delPlan(row)
+ },
+ inspectionTaskStatus(value) {
+ const map = { 0: '寰呮娴�', 1: '妫�娴嬩腑', 2: '妫�娴嬩腑', 3: '寰呭鏍�', 4: '澶嶆牳閫�鍥�', 5: '寰呰瘎浠�' }
+ return value === null || value === undefined ? '鏈笅鍙�' : (map[value] || '澶勭悊涓�')
+ },
+ handleDetailCommand(command, row) {
+ const handlers = {
+ complete: () => this.record(row),
+ evaluate: () => this.evaluate(row),
+ requirement: () => this.evaluate(row),
+ cancel: () => this.cancelTask(row),
+ attachment: () => this.viewTestRecord(row),
+ export: () => this.downLoadPost(row),
+ delete: () => this.delYearPlanDetail(row)
+ }
+ handlers[command]?.()
}
},
// 鐢ㄤ簬涓婁紶鏂囦欢鐨勪俊鎭�
computed: {
...mapGetters(["userId", "nickName"]),
+ effectivePlanStatus() {
+ if (!this.currentPlan) return ''
+ if (this.currentPlan.workflowStatus) return this.currentPlan.workflowStatus
+ if (this.currentPlan.ratifyStatus === 1) return 'APPROVED'
+ if (this.currentPlan.ratifyStatus === 0) return 'APPROVAL_REJECTED'
+ if (this.currentPlan.examineStatus === 1) return 'PENDING_APPROVAL'
+ if (this.currentPlan.examineStatus === 0) return 'REVIEW_REJECTED'
+ return 'DRAFT'
+ },
+ planStatusText() {
+ return ({DRAFT:'鑽夌',PENDING_REVIEW:'寰呭鏍�',REVIEW_REJECTED:'瀹℃牳閫�鍥�',PENDING_APPROVAL:'寰呮壒鍑�',APPROVAL_REJECTED:'鎵瑰噯閫�鍥�',APPROVED:'宸叉壒鍑�'})[this.effectivePlanStatus] || '鍘嗗彶璁″垝'
+ },
+ planStatusType() {
+ return ({DRAFT:'info',PENDING_REVIEW:'warning',REVIEW_REJECTED:'danger',PENDING_APPROVAL:'warning',APPROVAL_REJECTED:'danger',APPROVED:'success'})[this.effectivePlanStatus] || 'info'
+ },
+ canEditPlan() {
+ return !!this.currentPlan && Number(this.userId) === Number(this.currentPlan.writeUserId)
+ && ['DRAFT','REVIEW_REJECTED','APPROVAL_REJECTED'].includes(this.effectivePlanStatus)
+ },
+ canReviewPlan() {
+ return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_REVIEW'
+ && Number(this.userId) === Number(this.currentPlan.examineUserId)
+ },
+ canApprovePlan() {
+ return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_APPROVAL'
+ && Number(this.userId) === Number(this.currentPlan.ratifyUserId)
+ },
action() {
return this.javaApi + '/qualityMonitor/importQualityMonitor'
},
@@ -967,4 +1051,84 @@
};
</script>
-<style scoped></style>
+<style scoped>
+.plan-list-card {
+ min-width: 0;
+ padding: 14px 16px;
+ background: var(--lims-card-bg, var(--el-bg-color));
+ border: 1px solid var(--el-border-color-light);
+ border-radius: 4px;
+}
+.plan-list-toolbar,
+.plan-list-filters,
+.plan-list-actions {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.plan-list-toolbar {
+ justify-content: space-between;
+ margin-bottom: 14px;
+}
+.filter-label {
+ margin-left: 8px;
+ font-size: 14px;
+ font-weight: 700;
+ color: var(--lims-text-2);
+ white-space: nowrap;
+}
+.annual-plan-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ padding: 14px 16px;
+ margin-bottom: 16px;
+ background: var(--lims-card-bg, var(--el-bg-color));
+ border: 1px solid var(--el-border-color-light);
+ border-radius: 4px;
+}
+.annual-plan-main, .annual-plan-actions {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.annual-plan-label { font-weight: 700; color: var(--lims-text-2); }
+.plan-detail-card {
+ min-width: 0;
+ background: var(--lims-card-bg, var(--el-bg-color));
+}
+.plan-detail-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+.section-title {
+ display: inline-flex;
+ align-items: center;
+ margin-right: 18px;
+ font-size: 15px;
+ font-weight: 700;
+ color: var(--lims-text-1, var(--el-text-color-primary));
+ white-space: nowrap;
+}
+.detail-actions {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ white-space: nowrap;
+}
+@media (max-width: 1200px) {
+ .annual-plan-header {
+ align-items: flex-start;
+ flex-direction: column;
+ }
+ .annual-plan-actions {
+ width: 100%;
+ }
+}
+</style>
diff --git a/src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue b/src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue
index cccee81..04ca9c0 100644
--- a/src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue
+++ b/src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue
@@ -2,6 +2,8 @@
<div>
<el-dialog v-model="filesDialogVisible" title="鏌ョ湅鏍″噯璇佷功" width="80%" @closed="closeFilesLook">
<div>
+ <el-alert v-if="!tableLoading && tableData.length === 0" type="info" :closable="false"
+ title="鎵�閫夎澶囨殏鏃犳牎鍑嗚瘉涔�"/>
<limsTable
ref="yearTable"
:column="columnData"
@@ -18,7 +20,7 @@
fullscreen
title="鏌ョ湅闄勪欢" top="5vh" width="800px">
<filePreview v-if="lookDialogVisible" :currentFile="{}"
- :fileUrl="javaApi+'/img/'+currentInfo.fileUrl" style="max-height: 90vh;overflow-y: auto;"/>
+ :fileUrl="fileUrl(currentInfo)" style="max-height: 90vh;overflow-y: auto;"/>
</el-dialog>
</div>
</template>
@@ -27,6 +29,7 @@
import filePreview from '@/components/Preview/filePreview.vue';
import limsTable from '@/components/Table/lims-table.vue'
import file from '@/utils/file';
+import { getCurrentCalibrationFiles } from '@/api/cnas/process/method/methodVerification'
export default {
name: 'calibrationsFileDia',
@@ -88,10 +91,24 @@
},
// 鏂规硶闆嗗悎
methods: {
- openDia(row) {
+ fileUrl(row) {
+ const image = /\.(png|jpe?g|gif|bmp|webp)$/i.test(row.fileUrl || '')
+ return this.javaApi + (image ? '/img/' : '/word/') + row.fileUrl
+ },
+ openDia(row = {}) {
this.filesDialogVisible = true
this.info = row
- this.tableData = this.info.calibrationsFileList
+ this.tableData = row.calibrationsFileList || []
+ if (row.useCurrentDevices) {
+ const deviceIds = [...new Set((row.machineAttachmentList || []).map(device => device.deviceId).filter(Boolean))]
+ if (!deviceIds.length) return
+ this.tableLoading = true
+ getCurrentCalibrationFiles({deviceIds: deviceIds.join(',')}).then(res => {
+ if (res.code === 200) this.tableData = res.data || []
+ }).finally(() => {
+ this.tableLoading = false
+ })
+ }
},
closeFilesLook () {
this.filesDialogVisible = false
@@ -104,7 +121,7 @@
// 涓嬭浇
upload (row) {
let url = '';
- if(row.type==1){
+ if (/\.(png|jpe?g|gif|bmp|webp)$/i.test(row.fileUrl || '')) {
url = this.javaApi+'/img/'+row.fileUrl
file.downloadIamge(url,row.fileName)
}else{
diff --git a/src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue b/src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue
index 21df974..9fa3579 100644
--- a/src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue
+++ b/src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue
@@ -57,11 +57,11 @@
<el-select v-model="form.confirmUser" multiple :multiple-limit="5" placeholder="璇烽�夋嫨妫�娴嬩汉鍛�" :disabled="isView">
<el-option v-for="user in userList" :key="user.id" :label="user.name" :value="user.id"/>
</el-select>
- <el-link v-if="operationType !== 'add'" type="primary" @click="viewWorkPermit">鏌ョ湅涓婂矖璇�</el-link>
+ <el-link type="primary" @click="viewWorkPermit">鏌ョ湅涓婂矖璇�</el-link>
</div>
<div v-if="item.key === 'equipment'" class="row-extra">
<el-link type="primary" @click="viewDevice">鏌ョ湅璁惧</el-link>
- <el-link v-if="operationType !== 'add'" type="primary" @click="viewCalibrationsFileDia">鏌ョ湅鏍″噯璇佷功
+ <el-link type="primary" @click="viewCalibrationsFileDia">鏌ョ湅鏍″噯璇佷功
</el-link>
</div>
</td>
@@ -237,7 +237,14 @@
this.openChild('deviceVisible', 'device', this.form)
},
viewCalibrationsFileDia() {
- this.openChild('calibrationVisible', 'calibration', this.form)
+ if (this.operationType === 'add' && !(this.form.machineAttachmentList || []).some(device => device.deviceId)) {
+ this.$message.warning('璇峰厛閫夋嫨璁惧')
+ return
+ }
+ this.openChild('calibrationVisible', 'calibration', {
+ ...this.form,
+ useCurrentDevices: this.operationType === 'add'
+ })
},
viewTestRecord() {
this.openChild('recordVisible', 'record', this.info)
diff --git a/src/views/business/inspectionTask/index.vue b/src/views/business/inspectionTask/index.vue
index 0e712b9..9131551 100644
--- a/src/views/business/inspectionTask/index.vue
+++ b/src/views/business/inspectionTask/index.vue
@@ -3,7 +3,7 @@
<div style="height: 100%">
<div class="search">
<el-form :model="queryParams" ref="queryParams" size="small" :inline="true">
- <el-form-item label="濮旀墭缂栧彿" prop="entrustCode">
+ <el-form-item :label="taskSource === 'QUALITY_MONITOR' ? '鐩戞帶浠诲姟缂栧彿' : '濮旀墭缂栧彿'" prop="entrustCode">
<el-input v-model="queryParams.entrustCode" clearable placeholder="璇疯緭鍏�" size="small"
@keyup.enter="refreshTable()"></el-input>
</el-form-item>
@@ -29,7 +29,7 @@
<div class="center" v-loading="tableLoading">
<div class="center-options">
<div style="display: flex; align-items: center">
- <span style="font-size: 14px">璇曢獙瀹�:</span>
+ <span style="font-size: 14px">浠诲姟鏉ユ簮:</span>
<ul class="tab">
<li v-for="(m, i) in tabList" :key="i" :class="{ active: i == tabIndex }" @click="handleTab(m, i)">
{{ m.label.replace("璇曢獙瀹�", "") }}
@@ -45,7 +45,7 @@
<span>{{ page.total }}</span>
</div>
</div>
- <lims-table :tableData="tableData" :column="column" :page="page"
+ <lims-table :tableData="tableData" :column="displayColumns" :page="page"
:rowClassName="rowClassName" :height="'calc(100vh - 300px)'" @pagination="pagination"
key="tableData0">
<template #action="scope"><div>
@@ -56,7 +56,7 @@
(scope.row.userName && !scope.row.userName.includes(nickName))
)"
@click="handleInspection(scope.row)">妫�楠�</el-button>
- <el-button link type="primary" size="small" :disabled="(
+ <el-button v-if="scope.row.taskSource !== 'QUALITY_MONITOR'" link type="primary" size="small" :disabled="(
scope.row.userName == null ||
scope.row.insState == 5 ||
scope.row.insState == 3 ||
@@ -64,12 +64,13 @@
)"
@click="handleConnect(scope.row)">浜ゆ帴</el-button>
<el-button link type="primary" size="small" @click="viewInspectInfo(scope.row)">鍘熷璁板綍</el-button>
- <el-popover placement="bottom" trigger="hover" style="margin-left: 6px" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||(scope.row.userName && !scope.row.userName.includes(nickName)))">
+ <el-button v-if="scope.row.taskSource === 'QUALITY_MONITOR'" link type="primary" size="small" @click="showMonitorRequirement(scope.row)">{{ Number(scope.row.insState) === 5 ? '璇勪环璁板綍' : '璇勪环瑕佹眰' }}</el-button>
+ <el-popover v-if="scope.row.taskSource !== 'QUALITY_MONITOR'" placement="bottom" trigger="hover" style="margin-left: 6px" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||(scope.row.userName && !scope.row.userName.includes(nickName)))">
<template #reference>
- <el-button link type="primary" size="small" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
+ <el-button link type="primary" size="small" :disabled="(scope.row.taskSource === 'QUALITY_MONITOR' || scope.row.insState != 3 || scope.row.userName == null ||
(scope.row.userName && !scope.row.userName.includes(nickName)))">鏇村</el-button>
</template>
- <div>
+ <div v-if="scope.row.taskSource !== 'QUALITY_MONITOR'">
<el-button :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
(scope.row.userName && !scope.row.userName.includes(nickName)))" style="margin-left: 10px" link type="primary" size="small" @click="download(scope.row)">涓嬭浇鎶ュ憡</el-button>
<el-button :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
@@ -80,6 +81,23 @@
</lims-table>
</div>
</div>
+ <el-dialog v-model="monitorRequirementVisible" title="璐ㄩ噺鐩戞帶璇勪环瑕佹眰" width="560px">
+ <el-descriptions :column="1" border>
+ <el-descriptions-item label="鐩戞帶浠诲姟缂栧彿">{{ monitorRequirement.entrustCode }}</el-descriptions-item>
+ <el-descriptions-item label="鐩戞帶椤圭洰">{{ monitorRequirement.monitorProject }}</el-descriptions-item>
+ <el-descriptions-item label="鐩戞帶鐩殑">{{ monitorRequirement.monitorPurpose }}</el-descriptions-item>
+ <el-descriptions-item label="鐩戞帶鏂瑰紡">{{ monitorRequirement.monitorWay }}</el-descriptions-item>
+ <el-descriptions-item label="妫�娴嬫爣鍑�">{{ monitorRequirement.standardCode }}</el-descriptions-item>
+ <el-descriptions-item label="鏍峰搧鍙婅鏍�">{{ monitorRequirement.sample }} {{ monitorRequirement.sampleSpec }}</el-descriptions-item>
+ <el-descriptions-item label="瀹屾垚鏈熼檺">{{ monitorRequirement.dueDate }}</el-descriptions-item>
+ </el-descriptions>
+ <p>璇峰湪鈥滃師濮嬭褰曗�濅腑濉啓妫�娴嬫暟鎹紝澶嶆牳閫氳繃鍚庣敱璇勪环浜哄憳濉啓璐ㄩ噺鎺у埗璇勪环璁板綍銆�</p>
+ <template #footer>
+ <el-button @click="monitorRequirementVisible=false">鍏抽棴</el-button>
+ <el-button v-if="Number(monitorRequirement.insState) === 5" type="primary" @click="openMonitorEvaluation">鎵撳紑璇勪环璁板綍</el-button>
+ </template>
+ </el-dialog>
+ <inspection-evaluation-dialog v-if="inspectionEvaluateDialog" ref="inspectionEvaluateDialog" @close="inspectionEvaluateDialog=false" />
<el-dialog v-model="claimVisible" title="鎻愮ず" width="400px">
鏄惁璁ら濮旀墭缂栧彿<span style="color: #33c130">{{
sampleUserForm.entrustCode
@@ -210,10 +228,11 @@
import {getRetestResult} from "@/api/business/rawMaterialOrder";
import onlyoffice from "@/components/Onlyoffice/onlyoffice.vue";
import filePreview from "@/components/Preview/filePreview.vue";
+import InspectionEvaluationDialog from "@/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue";
export default {
name: 'InspectionTask',
components: {
- filePreview, onlyoffice,
+ filePreview, onlyoffice, InspectionEvaluationDialog,
limsTable,
viewManHourDia,
UnPassRetestResult
@@ -221,10 +240,18 @@
dicts: ["urgency_level", "inspection_task_state","material_prop_type"],
computed: {
...mapGetters(["nickName", "userId"]),
+ displayColumns() {
+ return this.column.filter(item => this.taskSource === 'QUALITY_MONITOR'
+ ? !['typeSource', 'orderType'].includes(item.prop)
+ : !['monitorProject', 'dueDate'].includes(item.prop))
+ },
},
data() {
return {
issuedVisible: false,
+ monitorRequirementVisible: false,
+ monitorRequirement: {},
+ inspectionEvaluateDialog: false,
fullscreen: false,
lookDialogVisible: false,
option: null,
@@ -245,7 +272,8 @@
},
claimVisible: false,
tabList: [
- { label: "濮旀墭", value: -1 },
+ { label: "濮旀墭", value: "ENTRUSTED" },
+ { label: "璐ㄩ噺鐩戞帶", value: "QUALITY_MONITOR" },
// { label: "鍘熸潗鏂�", value: 1 },
// { label: "澶栬喘", value: 0 },
],
@@ -255,6 +283,7 @@
insStateList: [],
state: 0, // 0:鍙拌处椤碉紝1锛氭楠岄〉闈�,2妫�楠岄〉闈�(澶嶆牳)锛岄粯璁や负0,3鏁版嵁鏌ョ湅
typeSource: -1, // 0:澶栬喘鎴愬搧涓嬪崟锛�1锛氬師鏉愭枡涓嬪崟
+ taskSource: 'ENTRUSTED',
sonLaboratory: null, // 0:濮旀墭锛�1锛氬師鏉愭枡
activeFace: 0, // 1锛氫笅鍗曪紝2锛氭煡鐪嬶紝3锛氬鏍革紝榛樿涓�0
currentId: null,
@@ -328,12 +357,14 @@
tableData: [],
column: [
{
- label: "濮旀墭缂栧彿",
+ label: "浠诲姟缂栧彿",
prop: "entrustCode",
width: "160px",
dataType: "link",
linkMethod: "selectAllByOne",
},
+ { label: "鐩戞帶椤圭洰", prop: "monitorProject", width: "150px" },
+ { label: "璁″垝鏈熼檺", prop: "dueDate", width: "120px" },
{ label: "鏍峰搧鍚嶇О", prop: "sample", width: "160px" },
{
label: "涓嬪崟绫诲埆",
@@ -445,6 +476,7 @@
this.getAuthorizedPerson();
this.queryParams.userId = this.userId;
this.queryParams.typeSource = this.typeSource
+ this.queryParams.taskSource = this.taskSource
this.currentTime = getYearAndMonthAndDays();
this.getDicts("urgency_level").then((response) => {
this.urgencyLevel = this.dictToValue(response.data);
@@ -464,9 +496,19 @@
this.inspectionTaskState = this.dictToValue(response.data);
});
this.queryParams.typeSource = this.typeSource
+ this.queryParams.taskSource = this.taskSource
this.refreshTable();
},
methods: {
+ showMonitorRequirement(row) {
+ this.monitorRequirement = row
+ this.monitorRequirementVisible = true
+ },
+ openMonitorEvaluation() {
+ this.monitorRequirementVisible = false
+ this.inspectionEvaluateDialog = true
+ this.$nextTick(() => this.$refs.inspectionEvaluateDialog.open(this.monitorRequirement))
+ },
getList() {
this.tableLoading = true;
let param = { ...this.queryParams, ...this.page };
@@ -505,7 +547,8 @@
refreshTable(e) {
this.page.current = 1;
this.queryParams.tabLabel = this.tabLabel;
- this.queryParams.typeSource = this.typeSource;
+ this.queryParams.taskSource = this.taskSource;
+ this.queryParams.typeSource = this.taskSource === 'ENTRUSTED' ? -1 : null;
this.getList();
},
// 涓嬭浇鎶ュ憡
@@ -576,11 +619,15 @@
},
handleTab(m, i) {
this.tabIndex = i;
- this.typeSource =m.value;
+ this.taskSource = m.value;
this.queryParams.sonLaboratory = "";
this.refreshTable();
},
selectAllByOne(row) {
+ if (row.taskSource === 'QUALITY_MONITOR') {
+ this.viewInspectInfo(row)
+ return
+ }
this.isCopper = row.isCopper;
this.customsInspection = row;
this.activeFace = 2;
@@ -647,6 +694,7 @@
sonLaboratory: this.sonLaboratory,
state: this.state,
typeSource: this.typeSource,
+ taskSource: row.taskSource,
orderId: this.orderId
},
});
@@ -673,6 +721,7 @@
sonLaboratory: this.sonLaboratory,
state: this.state,
typeSource: this.typeSource,
+ taskSource: row.taskSource,
orderId: this.orderId,
},
});
diff --git a/src/views/business/inspectionTask/inspection.vue b/src/views/business/inspectionTask/inspection.vue
index bc31b8c..1031214 100644
--- a/src/views/business/inspectionTask/inspection.vue
+++ b/src/views/business/inspectionTask/inspection.vue
@@ -396,7 +396,7 @@
</div>
<div class="search_input" style="width: 100%">
<el-select v-model="verifyUser" clearable filterable placeholder="璇烽�夋嫨" size="small" style="width: 100%">
- <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
+ <el-option v-for="(item, i) in reviewerOptions" :key="i" :label="item.label" :value="item.value">
</el-option>
</el-select>
</div>
@@ -521,6 +521,7 @@
import { mapGetters } from "@/utils/store-compat";
import viewManHourDia from "@/views/business/inspectionTask/components/viewManHourDia.vue";
import {getDicts} from "@/api/system/dict/data";
+import { parseInspectionValueAnnotation, formatInspectionValue } from "@/utils/inspectionValueFormat";
export default {
name: 'Inspection',
components: {
@@ -553,6 +554,7 @@
state: null,
inspectorList: null,
typeSource: null,
+ taskSource: null,
sagData: [],
sagForm: {
sampleCode: null,
@@ -726,6 +728,11 @@
// 鐢ㄤ簬涓婁紶鏂囦欢鐨勪俊鎭�
computed: {
...mapGetters(["userId"]),
+ reviewerOptions() {
+ return this.taskSource === 'QUALITY_MONITOR'
+ ? this.personList.filter(item => Number(item.value) !== Number(this.userId))
+ : this.personList;
+ },
action() {
return this.javaApi + "/insOrderPlan/uploadFile";
},
@@ -830,14 +837,16 @@
},
methods: {
syncRouteContext() {
- const { sonLaboratory, orderId, state, inspectorList, typeSource } = this.$route.query;
+ const { sonLaboratory, orderId, state, inspectorList, typeSource, taskSource } = this.$route.query;
const orderChanged = this.id !== orderId;
this.sonLaboratory = sonLaboratory;
this.orderId = orderId;
this.state = state;
this.inspectorList = inspectorList;
this.typeSource = typeSource;
+ this.taskSource = taskSource;
if (orderChanged) {
+ if (taskSource === 'QUALITY_MONITOR') this.verifyUser = null;
this.tableLists = [];
this.tableList = [];
this.sampleProduct = [];
@@ -999,6 +1008,7 @@
laboratory: this.sonLaboratory,
}).then(async (res) => {
this.insOrder = res.data.insOrder;
+ this.taskSource = this.insOrder.taskSource || this.taskSource;
if(res.data.insOrder.ifsOrderType==='02wg'){
//鏌ヨ闆朵欢灞炴��
this.getPartProps(res.data.insOrder.ifsInventoryId)
@@ -1575,6 +1585,17 @@
// 妫�楠屽�艰緭鍏ュ悗瑙﹀彂鐨勫嚱鏁�
changeInput(m, code, n) {
if (n) {
+ const config = parseInspectionValueAnnotation(n.v && n.v.ps && n.v.ps.value);
+ if (config && !config.error && config.decimalPlaces != null && typeof n.v.v === 'string') {
+ const numericPattern = config.displayMode === 'SCIENTIFIC'
+ ? /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/
+ : /^[+-]?\d*\.?\d+$/;
+ if (n.v.v.trim() && !numericPattern.test(n.v.v.trim())) {
+ this.$message.warning('璇ユ楠屽�煎繀椤诲~鍐欐暟瀛�');
+ return;
+ }
+ n.v.v = formatInspectionValue(n.v.v, config);
+ }
// 瀹氫箟涓�涓嚱鏁版潵楠岃瘉鍒嗘暟鏄惁鏈夋晥
if (typeof n.v.v == "string") {
function isValidFraction(fraction) {
@@ -1705,7 +1726,7 @@
const v = n.v.v;
// 鑳藉姏鑼冨洿宸插簾寮�,妫�楠屽�肩被鍨嬩笉鍐嶄綔涓哄垽鏂緷鎹�傛暣涓插彧鐢辩畻寮忓瓧绗︾粍鎴愭椂鎵嶈鑼冨寲鏍煎紡,
// 鍑虹幇涓枃绛夊叾瀹冨瓧绗﹀嵆鎸夋枃鏈鐞嗗師鏍蜂繚鐣�,鍚﹀垯鏂囧瓧浼氳閫愬瓧鍒犳帀
- if (typeof v !== "string" || /[^\d.^e>锛炩墺鈮�<锛滄柇瑁傝剢鍖朶-/+]/.test(v)) {
+ if (typeof v !== "string" || /[^\d.^eE>锛炩墺鈮�<锛滄柇瑁傝剢鍖朶-/+]/.test(v)) {
return;
}
n.v.v = v
@@ -1747,6 +1768,10 @@
}
},
openAddCheck() {
+ if (this.taskSource === 'QUALITY_MONITOR') {
+ this.upInsReview(1);
+ return;
+ }
this.addCheck = true;
},
// 鏀堕泦妯℃澘绾ф娴嬫潯浠剁殑缂哄け椤癸紙姣忎釜妯℃澘閮借濉叏锛�
diff --git a/src/views/standard/model/index.vue b/src/views/standard/model/index.vue
index 9821820..d4e0274 100644
--- a/src/views/standard/model/index.vue
+++ b/src/views/standard/model/index.vue
@@ -64,6 +64,7 @@
delStandardTemplate,
getEditTemplatePreparation,
} from "@/api/standard/model";
+import { validateInspectionValueAnnotation } from "@/utils/inspectionValueFormat";
export default {
name: 'Model',
components: {
@@ -349,7 +350,12 @@
}
}
}
+ let annotationError = null;
data.data[0].celldata.forEach((a) => {
+ if (a.v && a.v.ps && typeof a.v.ps.value === "string") {
+ const error = validateInspectionValueAnnotation(a.v.ps.value);
+ if (!annotationError && error) annotationError = `鍗曞厓鏍�(${a.r + 1}琛�${a.c + 1}鍒�)锛�${error}`;
+ }
if (
a.v.ps != undefined &&
(a.v.ps.value === "妫�楠屽��" ||
@@ -362,6 +368,11 @@
}
}
});
+ if (annotationError) {
+ this.loading = false;
+ this.$message.error(annotationError);
+ return;
+ }
upStandardTemplate({
id: this.row.id,
thing: JSON.stringify(data),
@@ -370,6 +381,9 @@
this.loading = false;
this.$message.success("宸蹭繚瀛�");
this.isShow = false;
+ }).catch((error) => {
+ this.loading = false;
+ this.$message.error(error.message || "妯℃澘淇濆瓨澶辫触");
});
},
isClose(done) {
--
Gitblit v1.9.3