From 0a40c5890d13d9f2de5c3ab663876afecbfbefbe Mon Sep 17 00:00:00 2001
From: 吴羡 <16976746+Xian-TT3@user.noreply.gitee.com>
Date: 星期三, 28 十月 2026 17:57:46 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
src/api/structural/laboratory.js | 29 +++++
src/views/CNAS/process/method/standardMethod/index.vue | 29 -----
src/views/structural/capabilityAndLaboratory/laboratory/index.vue | 222 +++++++++++++++++++++++++++++++++++---------
3 files changed, 205 insertions(+), 75 deletions(-)
diff --git a/src/api/structural/laboratory.js b/src/api/structural/laboratory.js
index 1e2f9b0..8499174 100644
--- a/src/api/structural/laboratory.js
+++ b/src/api/structural/laboratory.js
@@ -8,6 +8,16 @@
params: query
})
}
+
+// 鎸塈D鏌ヨ璧勮川璇︽儏
+export function getCertificationById(id) {
+ return request({
+ url: '/certification/getCertificationById',
+ method: 'get',
+ params: { id }
+ })
+}
+
// 娣诲姞璧勮川鏄庣粏鍒楄〃
export function addCertificationDetail(query) {
return request({
@@ -16,6 +26,25 @@
data: query
})
}
+
+// 鏇存柊璧勮川璧勬枡
+export function updateCertificationDetail(data) {
+ return request({
+ url: '/certification/updateCertificationDetail',
+ method: 'put',
+ data
+ })
+}
+
+// 鏇存柊璧勮川鍥剧墖
+export function updateCertificationImage(data) {
+ return request({
+ url: '/certification/updateCertificationImage',
+ method: 'put',
+ data
+ })
+}
+
// 鍒犻櫎璧勮川鏄庣粏鍒楄〃
export function delCertificationDetail(query) {
return request({
diff --git a/src/views/CNAS/process/method/standardMethod/index.vue b/src/views/CNAS/process/method/standardMethod/index.vue
index b141bf1..c611153 100644
--- a/src/views/CNAS/process/method/standardMethod/index.vue
+++ b/src/views/CNAS/process/method/standardMethod/index.vue
@@ -65,12 +65,6 @@
</el-option>
</el-select>
</el-form-item>
- <el-form-item label="鏄惁浜у搧鏍囧噯" prop="isProduct">
- <el-select v-model="addForm.isProduct" size="small" clearable placeholder="璇烽�夋嫨" style="width: 100%">
- <el-option label="鍚�" :value="0"></el-option>
- <el-option label="鏄�" :value="1"></el-option>
- </el-select>
- </el-form-item>
<el-form-item label="鏄惁鍚敤" prop="isUse">
<el-select v-model="addForm.isUse" size="small" clearable placeholder="璇烽�夋嫨" style="width: 100%">
<el-option label="鍚�" :value="0"></el-option>
@@ -150,26 +144,6 @@
{label: "鏍囧噯鎻忚堪", prop: "name", width: "100px"},
{label: "澶囨敞", prop: "remark"},
{
- label: "鏄惁浜у搧鏍囧噯",
- prop: "isProduct",
- width: "100px",
- dataType: "tag",
- formatData: (params) => {
- if (params == 0) {
- return "鍚�";
- } else {
- return "鏄�";
- }
- },
- formatType: (params) => {
- if (params == 0) {
- return "danger";
- } else {
- return "primary";
- }
- },
- },
- {
label: "鏄惁鍚敤",
prop: "isUse",
formatData: (params) => {
@@ -246,9 +220,6 @@
addRules: {
code: [{required: true, message: "璇疯緭鍏ユ爣鍑嗙紪鍙�", trigger: "blur"}],
name: [{required: true, message: "璇疯緭鍏ユ爣鍑嗘弿杩�", trigger: "blur"}],
- isProduct: [
- {required: true, message: "璇烽�夋嫨鏄惁浜у搧鏍囧噯", trigger: "change"},
- ],
isUse: [
{required: true, message: "璇烽�夋嫨鏄惁鍚敤", trigger: "change"},
],
diff --git a/src/views/structural/capabilityAndLaboratory/laboratory/index.vue b/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
index c05a6fe..7dde2e5 100644
--- a/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
+++ b/src/views/structural/capabilityAndLaboratory/laboratory/index.vue
@@ -3,7 +3,7 @@
<div>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
<el-form-item label="璧勮川鍚嶇О" prop="name">
- <el-select v-model="queryParams.name" placeholder="閫夋嫨璧勮川鍚嶇О" size="small" @change="refreshTable(), list = []">
+ <el-select v-model="queryParams.name" placeholder="閫夋嫨璧勮川鍚嶇О" size="small" @change="handleQuery">
<el-option v-for="dict in dict.type.cnas_method_qualification" :key="dict.value" :label="dict.label"
:value="dict.value">
{{ dict.label }}
@@ -11,7 +11,7 @@
</el-select>
</el-form-item>
<el-form-item>
- <el-button type="primary" size="small" @click="refreshTable">鏌ヨ</el-button>
+ <el-button type="primary" size="small" @click="handleQuery">鏌ヨ</el-button>
<el-button size="small" @click="refresh">閲嶇疆</el-button>
</el-form-item>
</el-form>
@@ -25,7 +25,7 @@
</el-radio-group>
</el-col>
<el-col :span="12" style="text-align: right" v-if="radio === 0">
- <el-button size="small" type="primary" @click="openAdd">璧勮川鏇存柊</el-button>
+ <el-button size="small" type="primary" @click="openAdd">璧勮川鏂板</el-button>
<el-button size="small" :icon="$icon('el-icon-delete')" @click="handleDel">鍒犻櫎</el-button>
</el-col>
</el-row>
@@ -37,7 +37,7 @@
</div>
<div class="table" v-if="radio === 1" v-loading="pageLoading" @scroll="scrollFn">
<el-row :gutter="16">
- <el-col :span="8" v-for="(m, i) in list" :key="i" :xs="24" :sm="12" :md="8" :lg="8" :xl="6"
+ <el-col :span="8" v-for="m in list" :key="m.id" :xs="24" :sm="12" :md="8" :lg="8" :xl="6"
style="margin-bottom: 16px">
<div class="table-item">
<el-image style="
@@ -45,7 +45,7 @@
height: 102px;
margin-right: 20px;
border-radius: 16px;
- " :src="javaApi + '/img/' + m.imageUrl">
+ " :src="getImageUrl(m.imageUrl)">
<template #error><div class="image-error" style="
width: 100px;
height: 100px;
@@ -69,6 +69,15 @@
<el-tag :type="m.state === 0 ? 'danger' : 'success'" size="small">{{ m.state === 0 ? "澶辨晥" : "鏈夋晥"
}}</el-tag>
</p>
+ <el-upload :action="uploadAction" :headers="headers" :show-file-list="false"
+ :disabled="!!overviewUploading[m.id]"
+ accept="image/jpg,image/jpeg,image/png" :before-upload="file => beforeOverviewImageUpload(file, m)"
+ :on-success="response => handleOverviewImageSuccess(response, m)"
+ :on-error="() => handleOverviewImageError(m.id)">
+ <el-button link type="primary" size="small" :loading="!!overviewUploading[m.id]">
+ {{ m.imageUrl ? "鏇存崲鍥剧墖" : "涓婁紶鍥剧墖" }}
+ </el-button>
+ </el-upload>
</div>
</div>
</el-col>
@@ -89,7 +98,7 @@
style="display: flex; margin: 0 auto; color: var(--lims-text-3)">宸茬粡娌℃湁鏇村鍟</el-button>
</div>
</div>
- <el-dialog title="璧勮川鏇存柊" v-model="qualificationsConnectVisible" width="400px">
+ <el-dialog :title="dialogTitle" v-model="qualificationsConnectVisible" width="400px" @closed="resetDialog">
<el-form ref="formDataRef" :model="formData" label-position="right" :rules="formDataRules" label-width="78px">
<el-form-item label="璧勮川鍚嶇О" prop="name">
<el-select v-model="formData.name" placeholder="璇烽�夋嫨" style="width: 100%" size="small" clearable>
@@ -121,21 +130,26 @@
<el-form-item label="璧勮川鍥剧墖">
<el-upload ref="upload" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'imageUrl')"
accept="image/jpg,image/jpeg,image/png" :multiple="false" :limit="1" :headers="headers"
- :on-change="beforeUpload" :on-error="onError">
+ :show-file-list="false" :before-upload="beforeFormImageUpload" :on-error="() => onError('imageUrl')">
<template #trigger><el-button size="small" type="primary">閫夊彇鍥剧墖</el-button></template>
</el-upload>
+ <el-image v-if="formData.imageUrl" class="qualification-preview" :src="getImageUrl(formData.imageUrl)" fit="cover" />
</el-form-item>
<el-form-item label="璧勮川闄勪欢">
<el-upload ref="upload1" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'fileUrl')"
accept="image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx" :headers="headers" :multiple="false"
- :limit="1" :on-change="beforeUpload1" :on-error="onError1">
+ :limit="1" :show-file-list="false" :before-upload="beforeFormFileUpload" :on-error="() => onError('fileUrl')">
<template #trigger><el-button size="small" type="primary">閫夊彇鏂囦欢</el-button></template>
</el-upload>
+ <el-button v-if="formData.fileUrl" link type="primary" size="small" @click="handleDownLoad(formData)">
+ 宸叉湁闄勪欢锛歿{ getFileName(formData.fileUrl) }}
+ </el-button>
</el-form-item>
</el-form>
<template #footer><span class="dialog-footer">
<el-button @click="qualificationsConnectVisible = false">鍙� 娑�</el-button>
- <el-button type="primary" @click="confirmQualifications" :loading="loading">纭� 瀹�</el-button>
+ <el-button type="primary" @click="confirmQualifications" :loading="loading"
+ :disabled="imageUploading || fileUploading">纭� 瀹�</el-button>
</span></template>
</el-dialog>
</div>
@@ -146,7 +160,10 @@
import {
addCertificationDetail,
delCertificationDetail,
+ getCertificationById,
getCertificationDetail,
+ updateCertificationDetail,
+ updateCertificationImage,
} from "@/api/structural/laboratory";
import { getToken } from "@/utils/auth";
@@ -177,6 +194,13 @@
label: "鎿嶄綔",
operation: [
{
+ name: "璧勮川鏇存柊",
+ type: "text",
+ clickFun: (row) => {
+ this.openEdit(row);
+ },
+ },
+ {
name: "闄勪欢涓嬭浇",
type: "text",
clickFun: (row) => {
@@ -194,6 +218,7 @@
tableLoading: false,
qualificationsList: [],
qualificationsConnectVisible: false,
+ dialogTitle: "璧勮川鏂板",
formData: {},
formDataRules: {
name: [
@@ -211,6 +236,10 @@
],
},
loading: false,
+ imageUploading: false,
+ fileUploading: false,
+ overviewUploading: {},
+ scrollHandler: null,
pageLoading: false,
isLoding: false, // 鍔犺浇涓紝loading鍥炬爣,榛樿涓簍rue
finishLoding: false, // 鍔犺浇瀹屾垚锛屾樉绀哄凡缁忔病鏈夋洿澶氫簡
@@ -223,14 +252,32 @@
};
},
mounted() {
+ this.scrollHandler = this.throttle(this.scrollFn.bind(this), 200);
+ window.addEventListener("scroll", this.scrollHandler);
this.refreshTable();
},
methods: {
selectorSwitch(radio) {
if (radio === 1) {
- this.list = [];
+ this.reloadOverview();
+ } else {
+ this.page.current = 1;
this.refreshTable();
}
+ },
+ handleQuery() {
+ if (this.radio === 0) {
+ this.page.current = 1;
+ this.refreshTable();
+ } else {
+ this.reloadOverview();
+ }
+ },
+ reloadOverview() {
+ this.currentPage = 1;
+ this.list = [];
+ this.finishLoding = false;
+ this.refreshTable();
},
refreshTable() {
if (this.radio === 0) {
@@ -251,12 +298,6 @@
this.isLoding = true;
} else {
this.pageLoading = true;
- }
- if (this.list.length === 0) {
- window.addEventListener(
- "scroll",
- this.throttle(this.scrollFn, 20000)
- );
}
getCertificationDetail({
current: this.currentPage,
@@ -290,16 +331,13 @@
},
// 閲嶇疆
refresh() {
+ this.queryParams.name = "";
if (this.radio === 0) {
- this.queryParams.name = "";
this.page.size = 10;
this.page.current = 1;
this.refreshTable();
} else {
- this.finishLoding = false;
- this.currentPage = 1;
- this.list = [];
- this.refreshTable();
+ this.reloadOverview();
}
},
// 琛ㄦ牸澶氶��
@@ -307,6 +345,7 @@
this.selection = selection;
},
pagination(page) {
+ this.page.current = page.page;
this.page.size = page.limit;
this.refreshTable();
},
@@ -335,57 +374,140 @@
this.$download.saveAs(row.fileUrl, row.fileUrl);
},
openAdd() {
- this.qualificationsConnectVisible = true;
- this.$nextTick(() => {
- this.$refs.upload.clearFiles();
- this.$refs.upload1.clearFiles();
- });
+ this.dialogTitle = "璧勮川鏂板";
this.formData = {};
+ this.qualificationsConnectVisible = true;
+ this.clearUploadFiles();
+ },
+ openEdit(row) {
+ this.dialogTitle = "璧勮川鏇存柊";
+ this.loading = true;
+ getCertificationById(row.id).then((res) => {
+ if (res.code !== 200 || !res.data) return;
+ this.formData = { ...res.data };
+ this.qualificationsConnectVisible = true;
+ this.clearUploadFiles();
+ }).finally(() => {
+ this.loading = false;
+ });
+ },
+ resetDialog() {
+ this.formData = {};
+ this.dialogTitle = "璧勮川鏂板";
+ this.imageUploading = false;
+ this.fileUploading = false;
+ this.clearUploadFiles();
+ this.$refs.formDataRef?.clearValidate();
+ },
+ clearUploadFiles() {
+ this.$nextTick(() => {
+ this.$refs.upload?.clearFiles();
+ this.$refs.upload1?.clearFiles();
+ });
},
handleSuccessUpImg(response, name) {
- if (response.code === 200) {
+ this.setFormUploadState(name, false);
+ if (response && response.code === 200 && response.data && response.data.url) {
this.formData[name] = response.data.url;
+ this.$message.success(name === 'imageUrl' ? "鍥剧墖涓婁紶鎴愬姛" : "闄勪欢涓婁紶鎴愬姛");
+ this.clearUploadFiles();
+ } else {
+ this.$message.error("涓婁紶澶辫触");
}
},
- beforeUpload(file) {
+ validateImage(file) {
+ const allowed = ["image/jpeg", "image/png"];
+ if (!allowed.includes(file.type)) {
+ this.$message.error("浠呮敮鎸丣PG銆丣PEG銆丳NG鍥剧墖");
+ return false;
+ }
if (file.size > 1024 * 1024 * 10) {
this.$message.error("涓婁紶鏂囦欢涓嶈秴杩�10M");
- this.$refs.upload.clearFiles();
return false;
- } else {
- return true;
}
+ return true;
},
- onError(err, file, fileList) {
- this.$message.error("涓婁紶澶辫触");
- this.$refs.upload.clearFiles();
+ beforeFormImageUpload(file) {
+ const valid = this.validateImage(file);
+ this.imageUploading = valid;
+ return valid;
},
- beforeUpload1(file) {
+ beforeFormFileUpload(file) {
+ const extension = (file.name.split('.').pop() || '').toLowerCase();
+ const allowed = ["jpg", "jpeg", "png", "pdf", "doc", "docx"];
+ if (!allowed.includes(extension)) {
+ this.$message.error("浠呮敮鎸丣PG銆丣PEG銆丳NG銆丳DF銆丏OC銆丏OCX鏂囦欢");
+ return false;
+ }
if (file.size > 1024 * 1024 * 10) {
this.$message.error("涓婁紶鏂囦欢涓嶈秴杩�10M");
- this.$refs.upload1.clearFiles();
return false;
- } else {
- return true;
}
+ this.fileUploading = true;
+ return true;
},
- onError1(err, file, fileList) {
+ setFormUploadState(name, value) {
+ if (name === 'imageUrl') this.imageUploading = value;
+ if (name === 'fileUrl') this.fileUploading = value;
+ },
+ onError(name) {
+ this.setFormUploadState(name, false);
this.$message.error("涓婁紶澶辫触");
- this.$refs.upload1.clearFiles();
+ this.clearUploadFiles();
+ },
+ beforeOverviewImageUpload(file, row) {
+ const valid = this.validateImage(file);
+ if (valid) this.overviewUploading[row.id] = true;
+ return valid;
+ },
+ handleOverviewImageSuccess(response, row) {
+ if (!response || response.code !== 200 || !response.data || !response.data.url) {
+ this.overviewUploading[row.id] = false;
+ this.$message.error("鍥剧墖涓婁紶澶辫触");
+ return;
+ }
+ const imageUrl = response.data.url;
+ updateCertificationImage({ id: row.id, imageUrl }).then((res) => {
+ if (res.code !== 200) return;
+ row.imageUrl = imageUrl;
+ this.$message.success("鍥剧墖鏇存柊鎴愬姛");
+ }).finally(() => {
+ this.overviewUploading[row.id] = false;
+ });
+ },
+ handleOverviewImageError(id) {
+ this.overviewUploading[id] = false;
+ this.$message.error("鍥剧墖涓婁紶澶辫触");
+ },
+ getImageUrl(imageUrl) {
+ if (!imageUrl) return "";
+ if (/^https?:\/\//i.test(imageUrl)) return imageUrl;
+ if (imageUrl.startsWith('/')) return this.javaApi + imageUrl;
+ return this.javaApi + '/img/' + imageUrl;
+ },
+ getFileName(fileUrl) {
+ if (!fileUrl) return "";
+ return fileUrl.split(/[\\/]/).pop();
},
confirmQualifications() {
+ if (this.imageUploading || this.fileUploading) {
+ this.$message.warning("璇风瓑寰呮枃浠朵笂浼犲畬鎴�");
+ return;
+ }
this.$refs["formDataRef"].validate((valid) => {
if (valid) {
this.loading = true;
- addCertificationDetail({ ...this.formData })
+ const submit = this.dialogTitle === "璧勮川鏂板"
+ ? addCertificationDetail
+ : updateCertificationDetail;
+ submit({ ...this.formData })
.then((res) => {
- this.loading = false;
+ if (res.code !== 200) return;
this.$message.success("宸叉彁浜�");
- this.refreshTable();
- this.resetForm("formDataRef");
this.qualificationsConnectVisible = false;
+ this.handleQuery();
})
- .catch((err) => {
+ .finally(() => {
this.loading = false;
});
}
@@ -428,7 +550,7 @@
},
},
unmounted() {
- window.removeEventListener("scroll", this.throttle(), false);
+ if (this.scrollHandler) window.removeEventListener("scroll", this.scrollHandler);
},
};
</script>
@@ -450,4 +572,12 @@
align-items: center;
justify-content: space-between;
}
+
+.qualification-preview {
+ width: 72px;
+ height: 72px;
+ margin-left: 10px;
+ border-radius: 8px;
+ vertical-align: middle;
+}
</style>
--
Gitblit v1.9.3