From dc082351978a1e9f75d7a1471a0ca7ebeac552a5 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期一, 01 六月 2026 11:07:50 +0800
Subject: [PATCH] opo维护
---
src/views/business/ethicalReview/ethicalReviewInfo.vue | 724 +++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 620 insertions(+), 104 deletions(-)
diff --git a/src/views/business/ethicalReview/ethicalReviewInfo.vue b/src/views/business/ethicalReview/ethicalReviewInfo.vue
index c783e46..8e56dfa 100644
--- a/src/views/business/ethicalReview/ethicalReviewInfo.vue
+++ b/src/views/business/ethicalReview/ethicalReviewInfo.vue
@@ -55,7 +55,7 @@
<el-input v-model="form.initiatePerson" />
</el-form-item>
</el-col>
- <el-col :span="8">
+ <!-- <el-col :span="8">
<el-form-item label="瀹℃煡鐘舵��" prop="status">
<el-select v-model="form.status" style="width: 100%">
<el-option
@@ -66,7 +66,7 @@
/>
</el-select>
</el-form-item>
- </el-col>
+ </el-col> -->
</el-row>
<!-- 涓撳鐩稿叧淇℃伅 -->
@@ -215,6 +215,14 @@
<div slot="header" class="clearfix">
<span class="detail-title">涓撳瀹℃煡鎯呭喌</span>
<div style="float: right;">
+ <el-button
+ type="warning"
+ size="mini"
+ @click="handleRefresh"
+ icon="el-icon-refresh"
+ >
+ 鍒锋柊
+ </el-button>
<el-button size="mini" type="primary" @click="handleAddExpert">
娣诲姞涓撳
</el-button>
@@ -350,7 +358,27 @@
<span v-else class="no-data">-</span>
</template>
</el-table-column>
-
+ <!-- 鍦�"瀹℃煡鏃堕棿"鍒楀悗闈㈡坊鍔�"鎵嬬闄勪欢"鍒� -->
+ <el-table-column label="鎵嬬闄勪欢" width="120" align="center">
+ <template slot-scope="scope">
+ <template v-if="scope.row.sigin">
+ <!-- 鏈夌鍚嶏紝鏄剧ず鍙偣鍑婚瑙堢殑鍥剧墖 -->
+ <el-button
+ type="text"
+ size="mini"
+ @click="handlePreviewSignature(scope.row.sigin)"
+ class="signature-preview-btn"
+ >
+ <i class="el-icon-picture" style="margin-right: 4px;"></i>
+ 鏌ョ湅绛惧悕
+ </el-button>
+ </template>
+ <template v-else>
+ <!-- 鏃犵鍚嶏紝鏄剧ず鏂滄潬 -->
+ <span class="no-signature">/</span>
+ </template>
+ </template>
+ </el-table-column>
<el-table-column label="瀹℃煡鎰忚" min-width="200" show-overflow-tooltip>
<template slot-scope="scope">
<span :class="{ 'expert-opinion': scope.row.expertopinion }">
@@ -435,7 +463,7 @@
<el-dialog
title="娣诲姞涓撳"
:visible.sync="expertDialogVisible"
- width="800px"
+ width="900px"
@close="handleExpertDialogClose"
>
<div style="margin-bottom: 20px;">
@@ -469,7 +497,7 @@
:data="filteredExpertList"
v-loading="expertListLoading"
style="width: 100%"
- max-height="400"
+ max-height="600"
@selection-change="handleExpertSelectionChange"
>
<el-table-column type="selection" width="55"></el-table-column>
@@ -505,7 +533,7 @@
></el-table-column>
<el-table-column
label="鑱旂郴鐢佃瘽"
- prop="telephone"
+ prop="donorno"
width="120"
></el-table-column>
</el-table>
@@ -572,7 +600,7 @@
placeholder="璇烽�夋嫨鎴鏃堕棿"
value-format="yyyy-MM-dd HH:mm:ss"
style="width: 100%"
- :disabled="sendForm.expertType === 'chief'"
+ :disabled="sendForm.expertType == 'chief'"
/>
<div v-if="sendForm.expertType !== 'chief'" style="margin-top: 5px;">
<el-button-group>
@@ -585,7 +613,7 @@
</el-button-group>
</div>
<div
- v-if="sendForm.expertType === 'chief'"
+ v-if="sendForm.expertType == 'chief'"
style="font-size: 12px; color: #999; margin-top: 5px;"
>
涓诲涓撳鏃犻渶璁剧疆鎴鏃堕棿
@@ -627,12 +655,35 @@
</el-form>
<div slot="footer">
<el-button @click="sendDialogVisible = false">鍙栨秷</el-button>
- <el-button type="primary" @click="handleSendConfirm" :loading="sending"
- >纭鍙戦��</el-button
+ <el-button
+ type="primary"
+ @click="handleSendConfirm"
+ :loading="sendingAll"
+ :disabled="sendingAll"
>
+ {{
+ sendingAll
+ ? `鍙戦�佷腑 (${sendingProgress}/${sendingTotal})`
+ : "纭鍙戦��"
+ }}
+ </el-button>
</div>
</el-dialog>
-
+ <!-- 鎴栬�呭湪椤甸潰涓坊鍔犺繘搴︽潯 -->
+ <div v-if="sendingAll" class="send-progress-container">
+ <el-progress
+ :percentage="Math.round((sendingProgress / sendingTotal) * 100)"
+ :text-inside="true"
+ :stroke-width="20"
+ status="success"
+ >
+ <span>宸插彂閫� {{ sendingProgress }} / {{ sendingTotal }}</span>
+ </el-progress>
+ <div class="send-stats">
+ <span class="stat-item success">鎴愬姛: {{ sendingSuccessCount }}</span>
+ <span class="stat-item fail">澶辫触: {{ sendingFailCount }}</span>
+ </div>
+ </div>
<!-- 涓撳鍘嗗彶瀹℃壒鎯呭喌瀵硅瘽妗� -->
<el-dialog
title="涓撳鍘嗗彶瀹℃壒鎯呭喌"
@@ -764,7 +815,8 @@
ethicalreviewadd,
ethicalreviewInfo,
ethicalreExpertTotal,
- sendNotification
+ sendNotification,
+ sendcall
} from "@/api/businessApi";
import { listExternalperson } from "@/api/project/externalperson";
import CaseBasicInfo from "@/components/CaseBasicInfo";
@@ -859,7 +911,17 @@
{ max: 500, message: "闀垮害涓嶈兘瓒呰繃 500 涓瓧绗�", trigger: "blur" }
]
},
-
+ sending: false, // 鍗曚釜鍙戦�佺姸鎬�
+ sendingAll: false, // 鍏ㄥ眬鍙戦�佺姸鎬�
+ sendingProgress: 0, // 鍙戦�佽繘搴�
+ sendingTotal: 0, // 鎬诲彂閫佹暟
+ sendingSuccessCount: 0, // 鎴愬姛鏁�
+ sendingFailCount: 0, // 澶辫触鏁�
+ sendingResults: [], // 鍙戦�佺粨鏋滃垪琛�
+ originalFormData: null, // 鍘熷琛ㄥ崟鏁版嵁
+ originalExpertList: null, // 鍘熷涓撳鍒楄〃
+ originalAttachments: null, // 鍘熷闄勪欢鍒楄〃
+ isDataLoaded: false, // 鏁版嵁鏄惁宸插姞杞�
// 淇濆瓨鍔犺浇鐘舵��
saveLoading: false,
completeLoading: false,
@@ -924,14 +986,14 @@
// 璁$畻灞炴�э細鏅�氫笓瀹舵暟閲�
normalExpertsCount() {
return this.ethicalreviewopinionsList.filter(
- expert => expert.expertType === "0"
+ expert => expert.expertType == "0"
).length;
},
// 璁$畻灞炴�э細涓诲涓撳鏁伴噺
chiefExpertsCount() {
return this.ethicalreviewopinionsList.filter(
- expert => expert.expertType === "1"
+ expert => expert.expertType == "1"
).length;
},
@@ -943,7 +1005,7 @@
// 璁$畻灞炴�э細宸插悓鎰忎笓瀹舵暟閲�
approvedExpertsCount() {
return this.ethicalreviewopinionsList.filter(
- expert => expert.expertconclusion === "1"
+ expert => expert.expertconclusion == "1"
).length;
},
@@ -952,7 +1014,7 @@
const total = this.totalExpertsCount;
const approved = this.approvedExpertsCount;
- if (total === 0) return "鏈鏌�";
+ if (total == 0) return "鏈鏌�";
if (approved >= Math.ceil(total * 0.7)) {
// 瓒呰繃70%鍚屾剰
return "閫氳繃";
@@ -968,7 +1030,7 @@
const total = this.totalExpertsCount;
const approved = this.approvedExpertsCount;
- if (total === 0) return "info";
+ if (total == 0) return "info";
if (approved >= Math.ceil(total * 0.7)) {
return "success";
} else if (approved >= Math.ceil(total * 0.5)) {
@@ -982,10 +1044,10 @@
availableNormalExperts() {
return this.ethicalreviewopinionsList.filter(
expert =>
- expert.expertType === "0" &&
+ expert.expertType == "0" &&
(!expert.receiveStatus ||
- expert.receiveStatus === "0" ||
- expert.receiveStatus === "1")
+ expert.receiveStatus == "0" ||
+ expert.receiveStatus == "1")
);
},
@@ -993,10 +1055,10 @@
availableChiefExperts() {
return this.ethicalreviewopinionsList.filter(
expert =>
- expert.expertType === "1" &&
+ expert.expertType == "1" &&
(!expert.receiveStatus ||
- expert.receiveStatus === "0" ||
- expert.receiveStatus === "1")
+ expert.receiveStatus == "0" ||
+ expert.receiveStatus == "1")
);
},
@@ -1008,7 +1070,7 @@
// 鏄惁鍙互鍙戦�佺粰涓诲涓撳锛堥渶瑕佽嚦灏�12涓櫘閫氫笓瀹跺悓鎰忥級
canSendToChiefExpert() {
const normalApprovedCount = this.ethicalreviewopinionsList.filter(
- expert => expert.expertType === "0" && expert.expertconclusion === "1"
+ expert => expert.expertType == "0" && expert.expertconclusion == "1"
).length;
return this.availableChiefExperts.length > 0 && normalApprovedCount >= 12;
},
@@ -1059,9 +1121,9 @@
// 鍙戦�佸璇濇鏍囬
sendDialogTitle() {
- if (this.sendForm.expertType === "chief") {
+ if (this.sendForm.expertType == "chief") {
return "鍙戦�佷富濮斾笓瀹跺鏌�";
- } else if (this.sendForm.expertType === "normal") {
+ } else if (this.sendForm.expertType == "normal") {
return "鍙戦�佹櫘閫氫笓瀹跺鏌�";
} else {
return "鍙戦�佷笓瀹跺鏌�";
@@ -1082,6 +1144,12 @@
this.id = this.$route.query.id;
this.caseId = this.$route.query.infoid;
this.getDetail(this.infoid, this.id);
+ // 鐩戝惉璺敱鍙樺寲锛岄槻姝㈢敤鎴风寮�椤甸潰
+ window.addEventListener("beforeunload", this.beforeUnloadHandler);
+ },
+ beforeDestroy() {
+ // 绉婚櫎浜嬩欢鐩戝惉鍣�
+ window.removeEventListener("beforeunload", this.beforeUnloadHandler);
},
methods: {
// 鍒濆鍖栨柊澧炴暟鎹�
@@ -1107,7 +1175,7 @@
response = await reviewinitiateBaseInfoList({ infoid: infoid });
}
- if (response.code === 200) {
+ if (response.code == 200) {
let detailData = {};
if (response.data && id) {
@@ -1116,24 +1184,24 @@
this.parseFilePatch(this.form.filePatch);
this.initAttachmentFileList();
- // 濡傛灉涓撳瀹℃煡鎰忚鍒楄〃涓嶅瓨鍦紝鍒濆鍖栦负绌烘暟缁�
if (!this.form.ethicalreviewopinionsList) {
this.$set(this.form, "ethicalreviewopinionsList", []);
}
} else if (response.data && infoid) {
this.form = response.data[0];
- // 瑙f瀽 filePatch 瀛楁
this.parseFilePatch(this.form.filePatch);
this.initAttachmentFileList();
- // 濡傛灉涓撳瀹℃煡鎰忚鍒楄〃涓嶅瓨鍦紝鍒濆鍖栦负绌烘暟缁�
if (!this.form.ethicalreviewopinionsList) {
this.$set(this.form, "ethicalreviewopinionsList", []);
}
}
- // 璁剧疆 expertReviews 鐢ㄤ簬琛ㄦ牸鏄剧ず
+ // 淇濆瓨鍘熷鏁版嵁鐢ㄤ簬姣旇緝
+ this.saveOriginalData();
+
this.expertReviews = this.form.ethicalreviewopinionsList;
+ this.isDataLoaded = true;
this.$message.success("鏁版嵁鍔犺浇鎴愬姛");
} else {
@@ -1145,6 +1213,22 @@
} finally {
this.expertLoading = false;
}
+ },
+
+ // 淇濆瓨鍘熷鏁版嵁
+ saveOriginalData() {
+ // 娣辨嫹璐濊〃鍗曟暟鎹�
+ this.originalFormData = JSON.parse(JSON.stringify(this.form));
+
+ // 娣辨嫹璐濅笓瀹跺垪琛�
+ this.originalExpertList = this.form.ethicalreviewopinionsList
+ ? JSON.parse(JSON.stringify(this.form.ethicalreviewopinionsList))
+ : [];
+
+ // 娣辨嫹璐濋檮浠跺垪琛�
+ this.originalAttachments = this.form.annexfilesList
+ ? JSON.parse(JSON.stringify(this.form.annexfilesList))
+ : [];
},
// 瑙f瀽 filePatch 瀛楁
@@ -1182,7 +1266,7 @@
// 鏋勫缓 filePatch 瀛楁
buildFilePatch() {
- if (!this.form.annexfilesList || this.form.annexfilesList.length === 0) {
+ if (!this.form.annexfilesList || this.form.annexfilesList.length == 0) {
return "";
}
return JSON.stringify(this.form.annexfilesList);
@@ -1197,7 +1281,7 @@
handleAttachmentRemove(file) {
if (file.url) {
const index = this.form.annexfilesList.findIndex(
- item => item.path === file.url || item.fileUrl === file.url
+ item => item.path == file.url || item.fileUrl == file.url
);
if (index > -1) {
this.form.annexfilesList.splice(index, 1);
@@ -1214,7 +1298,7 @@
// 涓婁紶鎴愬姛澶勭悊
handleUploadSuccess({ file, fileList, response }) {
- if (response.code === 200) {
+ if (response.code == 200) {
const attachmentObj = {
fileName: file.name,
path: response.data || file.url,
@@ -1238,10 +1322,23 @@
// 鏂囦欢棰勮
handlePreview(file) {
+ console.log(file, "file");
+
this.currentPreviewFile = {
fileName: file.fileName,
fileUrl: file.path || file.fileUrl,
fileType: this.getFileType(file.fileName)
+ };
+ this.previewVisible = true;
+ },
+ // 鏂囦欢棰勮
+ handlePreviewSignature(file) {
+ console.log(file, "file");
+
+ this.currentPreviewFile = {
+ fileName: file,
+ fileUrl: file,
+ fileType: "png"
};
this.previewVisible = true;
},
@@ -1317,13 +1414,13 @@
// 鑱岀О鍖呭惈"涓讳换濮斿憳"鎴栬�卐xpertType涓�"1"
return (
(expert.title && expert.title.includes("涓讳换濮斿憳")) ||
- expert.expertType === "1"
+ expert.expertType == "1"
);
},
// 涓撳绫诲瀷鏂囨湰杞崲
getExpertTypeText(type) {
- return type === "1" ? "涓诲涓撳" : "鏅�氫笓瀹�";
+ return type == "1" ? "涓诲涓撳" : "鏅�氫笓瀹�";
},
// 瀹℃煡鐘舵�佽繃婊ゅ櫒
@@ -1372,7 +1469,7 @@
// 涓撳琛屾牱寮�
getExpertRowClassName({ row }) {
- return row.expertType === "1" ? "chief-expert-row" : "normal-expert-row";
+ return row.expertType == "1" ? "chief-expert-row" : "normal-expert-row";
},
// 鑾峰彇涓撳鍞竴鏍囪瘑
@@ -1382,7 +1479,7 @@
// 涓撳绫诲瀷鍙樻洿澶勭悊
handleExpertTypeChange() {
- if (this.sendForm.expertType === "chief") {
+ if (this.sendForm.expertType == "chief") {
// 涓诲涓撳鏃犻渶璁剧疆鎴鏃堕棿
this.sendForm.endTime = "";
} else {
@@ -1407,9 +1504,9 @@
if (valid) {
this.saveLoading = true;
// 淇濆瓨娓呯┖id渚夸簬鍚庣鏁翠綋鍒犻櫎鏂板
- this.form.ethicalreviewopinionsList.forEach(item=>{
- item.id=null
- })
+ this.form.ethicalreviewopinionsList.forEach(item => {
+ item.id = null;
+ });
try {
const submitData = {
...this.form,
@@ -1428,8 +1525,10 @@
response = await ethicalreviewadd(submitData);
}
- if (response.code === 200) {
+ if (response.code == 200) {
this.$message.success("淇濆瓨鎴愬姛");
+ // 淇濆瓨鎴愬姛鍚庢洿鏂板師濮嬫暟鎹�
+ this.saveOriginalData();
this.isEdit = false;
if (!this.form.id && response.data && response.data.id) {
this.form.id = response.data.id;
@@ -1471,7 +1570,7 @@
const response = await ethicalreviewedit(updateData);
- if (response.code === 200) {
+ if (response.code == 200) {
this.$message.success("瀹℃煡鐘舵�佸凡鏇存柊涓哄畬鎴�");
this.form.status = "3";
this.form.endTime = updateData.endTime;
@@ -1523,7 +1622,7 @@
const response = await ethicalreviewedit(updateData);
- if (response.code === 200) {
+ if (response.code == 200) {
this.$message.success("瀹℃煡宸蹭腑姝紝鎵�鏈変笓瀹剁姸鎬佸凡鏇存柊");
this.form.status = "2";
} else {
@@ -1555,7 +1654,7 @@
try {
const updateData = {
...this.form,
- status: "2", // 瀹℃煡涓
+ status: "4", // 瀹℃煡涓
endTime: new Date()
.toISOString()
.replace("T", " ")
@@ -1564,9 +1663,9 @@
const response = await ethicalreviewedit(updateData);
- if (response.code === 200) {
+ if (response.code == 200) {
this.$message.success("瀹℃煡宸茬粨鏉�");
- this.form.status = "2";
+ this.form.status = "4";
this.form.endTime = updateData.endTime;
} else {
this.$message.error("鎿嶄綔澶辫触锛�" + (response.msg || "鏈煡閿欒"));
@@ -1586,13 +1685,255 @@
this.expertDialogVisible = true;
this.loadExperts();
},
+ /**
+ * 鍒锋柊椤甸潰鏁版嵁
+ */
+ async refreshPageData() {
+ try {
+ // 閲嶇疆鏁版嵁鐘舵��
+ this.isDataLoaded = false;
+ // 娓呯┖褰撳墠鏁版嵁
+ this.form = {
+ id: undefined,
+ infoid: undefined,
+ caseNo: "",
+ initiateTheme: "",
+ initiatePerson: "",
+ status: "0",
+ startTime: "",
+ cutOffTime: "",
+ endTime: "",
+ expertName: "",
+ expertNo: "",
+ expertType: "0",
+ expertConclusion: "",
+ expertOpinion: "",
+ expertTime: "",
+ orderNo: 1,
+ remark: "",
+ annexfilesList: [],
+ filePatch: "",
+ ethicalreviewopinionsList: [],
+ createBy: "",
+ createTime: "",
+ updateBy: "",
+ updateTime: "",
+ delFlag: "0"
+ };
+
+ this.attachmentFileList = [];
+ this.originalFormData = null;
+ this.originalExpertList = null;
+ this.originalAttachments = null;
+
+ // 閲嶆柊鑾峰彇鏁版嵁
+ if (this.id) {
+ await this.getDetail(this.infoid, this.id);
+ } else if (this.infoid) {
+ await this.getDetail(this.infoid, null);
+ } else {
+ this.$message.warning("鏃犳硶鍒锋柊锛岀己灏戝繀瑕佺殑鍙傛暟");
+ }
+
+ this.$message.success("鏁版嵁鍒锋柊鎴愬姛");
+ } catch (error) {
+ console.error("鍒锋柊鏁版嵁澶辫触:", error);
+ this.$message.error("鍒锋柊鏁版嵁澶辫触锛岃閲嶈瘯");
+ }
+ },
+
+ /**
+ * 澶勭悊椤甸潰鍒锋柊
+ * 妫�鏌ユ槸鍚︽湁鏈繚瀛樻暟鎹紝纭鍚庡埛鏂伴〉闈�
+ */
+ handleRefresh() {
+ // 妫�鏌ユ槸鍚︽湁鏈繚瀛樼殑缂栬緫
+ if (this.hasUnsavedChanges()) {
+ this.$confirm(
+ "褰撳墠鏈夋湭淇濆瓨鐨勬暟鎹紝鍒锋柊椤甸潰灏嗕涪澶辫繖浜涙洿鏀广�傛槸鍚︾户缁埛鏂帮紵",
+ "璀﹀憡",
+ {
+ confirmButtonText: "缁х画鍒锋柊",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ distinguishCancelAndClose: true,
+ beforeClose: (action, instance, done) => {
+ if (action === "confirm") {
+ instance.confirmButtonLoading = true;
+ instance.confirmButtonText = "鍒锋柊涓�...";
+
+ // 寤惰繜鎵ц浠ョ‘淇漊I鏇存柊
+ setTimeout(() => {
+ done();
+ instance.confirmButtonLoading = false;
+
+ // 鐢ㄦ埛纭鍒锋柊
+ this.refreshPageData();
+ }, 300);
+ } else {
+ this.$message({
+ type: "info",
+ message: "宸插彇娑堝埛鏂�"
+ });
+ done();
+ }
+ }
+ }
+ ).catch(action => {
+ if (action === "cancel") {
+ this.$message({
+ type: "info",
+ message: "宸插彇娑堝埛鏂�"
+ });
+ }
+ });
+ } else {
+ // 娌℃湁鏈繚瀛樼殑缂栬緫锛岀洿鎺ュ埛鏂�
+ this.refreshPageData();
+ }
+ },
+ // 妫�鏌ユ槸鍚︽湁鏈繚瀛樼殑鏁版嵁鍙樺寲
+ hasUnsavedChanges() {
+ if (!this.isDataLoaded) {
+ return false; // 鏁版嵁鏈姞杞斤紝鏃犻渶妫�娴�
+ }
+
+ // 1. 妫�鏌ヨ〃鍗曞瓧娈靛彉鍖�
+ const formFieldsChanged = this.checkFormFieldsChanged();
+
+ // 2. 妫�鏌ヤ笓瀹跺垪琛ㄥ彉鍖�
+ const expertListChanged = this.checkExpertListChanged();
+
+ // 3. 妫�鏌ラ檮浠跺垪琛ㄥ彉鍖�
+ const attachmentsChanged = this.checkAttachmentsChanged();
+
+ return formFieldsChanged || expertListChanged || attachmentsChanged;
+ },
+
+ // 妫�鏌ヨ〃鍗曞瓧娈垫槸鍚︽湁鍙樺寲
+ checkFormFieldsChanged() {
+ if (!this.originalFormData) return false;
+
+ const formKeys = [
+ "initiateTheme",
+ "initiatePerson",
+ "status",
+ "expertConclusion",
+ "expertOpinion",
+ "expertTime",
+ "remark"
+ ];
+
+ for (const key of formKeys) {
+ if (this.form[key] !== this.originalFormData[key]) {
+ console.log(
+ `琛ㄥ崟瀛楁鍙樺寲: ${key}`,
+ this.form[key],
+ this.originalFormData[key]
+ );
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ // 妫�鏌ヤ笓瀹跺垪琛ㄥ彉鍖�
+ checkExpertListChanged() {
+ if (!this.originalExpertList || !this.form.ethicalreviewopinionsList) {
+ return false;
+ }
+
+ const original = this.originalExpertList;
+ const current = this.form.ethicalreviewopinionsList;
+
+ // 1. 妫�鏌ユ暟閲忓彉鍖�
+ if (original.length !== current.length) {
+ console.log("涓撳鏁伴噺鍙樺寲:", original.length, "->", current.length);
+ return true;
+ }
+
+ // 2. 妫�鏌ユ瘡涓笓瀹剁殑鍙樺寲
+ for (let i = 0; i < original.length; i++) {
+ const origExpert = original[i];
+ const currExpert = current[i];
+
+ // 妫�鏌ュ叧閿瓧娈靛彉鍖�
+ const fieldsToCheck = [
+ "expertconclusion",
+ "expertopinion",
+ "receiveStatus",
+ "conclusiontime",
+ "startTime",
+ "endTime",
+ "sendType"
+ ];
+
+ for (const field of fieldsToCheck) {
+ if (origExpert[field] !== currExpert[field]) {
+ console.log(
+ `涓撳${i}鐨�${field}瀛楁鍙樺寲:`,
+ origExpert[field],
+ "->",
+ currExpert[field]
+ );
+ return true;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ // 妫�鏌ラ檮浠跺垪琛ㄥ彉鍖�
+ checkAttachmentsChanged() {
+ if (!this.originalAttachments || !this.form.annexfilesList) {
+ return false;
+ }
+
+ const original = this.originalAttachments;
+ const current = this.form.annexfilesList;
+
+ // 妫�鏌ユ暟閲忓彉鍖�
+ if (original.length !== current.length) {
+ console.log("闄勪欢鏁伴噺鍙樺寲:", original.length, "->", current.length);
+ return true;
+ }
+
+ // 妫�鏌ユ枃浠跺悕鍙樺寲锛堥�氬父闄勪欢涓嶄細淇敼锛屽彧澧炲垹锛�
+ const originalFileNames = original.map(f => f.fileName || f.name).sort();
+ const currentFileNames = current.map(f => f.fileName || f.name).sort();
+
+ for (let i = 0; i < originalFileNames.length; i++) {
+ if (originalFileNames[i] !== currentFileNames[i]) {
+ console.log(
+ "闄勪欢鏂囦欢鍚嶅彉鍖�:",
+ originalFileNames[i],
+ "->",
+ currentFileNames[i]
+ );
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ // 娴忚鍣ㄧ寮�椤甸潰妫�娴�
+ beforeUnloadHandler(event) {
+ if (this.hasUnsavedChanges()) {
+ const message = "鎮ㄦ湁鏈繚瀛樼殑鏇存敼锛岀‘瀹氳绂诲紑鍚楋紵";
+ event.returnValue = message; // 鏍囧噯鏂瑰紡
+ return message; // 鏌愪簺娴忚鍣ㄩ渶瑕佽繑鍥炲瓧绗︿覆
+ }
+ },
// 鍔犺浇涓撳鍒楄〃
async loadExperts() {
try {
this.expertListLoading = true;
const params = {
- usertype: "浼︾悊涓撳", // 浼︾悊涓撳
+ usertype: "ethical", // 浼︾悊涓撳
pageNum: this.expertPage.pageNum,
pageSize: this.expertPage.pageSize
};
@@ -1602,7 +1943,7 @@
}
const response = await listExternalperson(params);
- if (response.code === 200) {
+ if (response.code == 200) {
this.expertList = response.rows || [];
this.expertTotal = response.total || 0;
} else {
@@ -1639,7 +1980,7 @@
// 纭娣诲姞涓撳
handleConfirmAddExpert() {
- if (this.selectedExperts.length === 0) {
+ if (this.selectedExperts.length == 0) {
this.$message.warning("璇烽�夋嫨瑕佹坊鍔犵殑涓撳");
return;
}
@@ -1664,7 +2005,7 @@
expertType: isChief ? "1" : "0", // 涓讳换濮斿憳璁剧疆涓轰富濮斾笓瀹�
deptName: expert.unitname || "",
title: expert.title || "",
- deptname: expert.telephone || "",
+ donorno: expert.telephone || "",
receiveStatus: "0", // 寰呮帴鏀�
expertconclusion: "",
expertopinion: "",
@@ -1736,8 +2077,8 @@
// 鍙戦�佺粰鍗曚釜涓撳
handleSendToExpert(expert) {
this.currentSendExperts = [expert];
- this.sendForm.expertType = expert.expertType === "1" ? "chief" : "normal";
- this.sendForm.endTime = expert.expertType === "1" ? "" : ""; // 涓诲涓撳鏃犻渶鎴鏃堕棿
+ this.sendForm.expertType = expert.expertType == "1" ? "chief" : "normal";
+ this.sendForm.endTime = expert.expertType == "1" ? "" : ""; // 涓诲涓撳鏃犻渶鎴鏃堕棿
this.sendDialogVisible = true;
},
@@ -1784,40 +2125,52 @@
return;
}
- if (this.currentSendExperts.length === 0) {
+ if (this.currentSendExperts.length == 0) {
this.$message.warning("娌℃湁鎵惧埌鍙彂閫佺殑涓撳");
return;
}
- this.sending = true;
+ // 鍒濆鍖栧彂閫佺姸鎬�
+ this.sendingAll = true;
+ this.sendingProgress = 0;
+ this.sendingTotal = this.currentSendExperts.length;
+ this.sendingSuccessCount = 0;
+ this.sendingFailCount = 0;
+ this.sendingResults = [];
+
+ // 鍒涘缓涓�涓繘搴﹀璇濇
+ const progressDialog = this.$message({
+ type: "info",
+ message: `姝e湪鍙戦�侀�氱煡锛岃绋嶅��... (0/${this.sendingTotal})`,
+ duration: 0, // 涓嶄細鑷姩鍏抽棴
+ showClose: true
+ });
+
try {
- // 鍙戦�佺粰姣忎釜涓撳
- const sendPromises = this.currentSendExperts.map(async expert => {
+ // 浣跨敤Promise鏁扮粍鏉ラ『搴忔墽琛屽彂閫�
+ for (let i = 0; i < this.currentSendExperts.length; i++) {
+ const expert = this.currentSendExperts[i];
+
+ // 鏇存柊杩涘害
+ this.sendingProgress = i;
+ progressDialog.message = `姝e湪鍙戦�侀�氱煡锛岃绋嶅��... (${i}/${this.sendingTotal})`;
+
try {
- // 鏋勫缓鍙戦�佹暟鎹�
- const sendData = {
- number: expert.deptname || "", // 鐢ㄦ埛鎵嬫満鍙�
- title: this.sendForm.title,
- url: this.sendForm.url || "",
+ // 鍙戦�佸崟涓笓瀹堕�氱煡
+ const result = await this.sendSingleExpert(expert, i);
+ this.sendingResults.push(result);
- createTime: new Date()
- .toISOString()
- .replace("T", " ")
- .substring(0, 19)
- };
+ if (result.success) {
+ this.sendingSuccessCount++;
- // 璋冪敤鍙戦�侀�氱煡鎺ュ彛
- const response = await sendNotification(sendData);
-
- if (response.code === 200) {
// 鏇存柊涓撳鐘舵��
const index = this.form.ethicalreviewopinionsList.findIndex(
e =>
- e.expertNo === expert.expertNo ||
- e.expertname === expert.expertname
+ e.expertNo == expert.expertNo ||
+ e.expertname == expert.expertname
);
- if (index !== -1) {
+ if (index != -1) {
this.form.ethicalreviewopinionsList[index].receiveStatus = "1"; // 宸叉帴鏀�
this.form.ethicalreviewopinionsList[
index
@@ -1842,42 +2195,49 @@
this.form.ethicalreviewopinionsList[index]
);
}
-
- return { success: true, expert: expert.expertname };
} else {
- return {
- success: false,
- expert: expert.expertname,
- error: response.msg
- };
+ this.sendingFailCount++;
}
} catch (error) {
console.error(`鍙戦�佺粰涓撳 ${expert.expertname} 澶辫触:`, error);
- return {
+ this.sendingResults.push({
success: false,
expert: expert.expertname,
error: error.message
- };
+ });
+ this.sendingFailCount++;
}
- });
- // 绛夊緟鎵�鏈夊彂閫佸畬鎴�
- const results = await Promise.all(sendPromises);
-
- // 缁熻鍙戦�佺粨鏋�
- const successCount = results.filter(r => r.success).length;
- const failCount = results.filter(r => !r.success).length;
-
- if (failCount === 0) {
- this.$message.success(`鎴愬姛鍙戦�佺粰 ${successCount} 浣嶄笓瀹禶);
- } else if (successCount > 0) {
- this.$message.warning(
- `鎴愬姛鍙戦�佺粰 ${successCount} 浣嶄笓瀹讹紝澶辫触 ${failCount} 浣峘
- );
- } else {
- this.$message.error("鍙戦�佸け璐ワ紝璇风◢鍚庨噸璇�");
+ // 濡傛灉涓嶆槸鏈�鍚庝竴涓紝绛夊緟100ms鍐嶅彂閫佷笅涓�涓�
+ if (i < this.currentSendExperts.length - 1) {
+ await this.sleep(100);
+ }
}
+ // 瀹屾垚杩涘害
+ this.sendingProgress = this.sendingTotal;
+ progressDialog.message = `鍙戦�佸畬鎴愶紝鎴愬姛 ${this.sendingSuccessCount} 涓紝澶辫触 ${this.sendingFailCount} 涓猔;
+
+ // 寤惰繜1绉掑悗鍏抽棴杩涘害瀵硅瘽妗�
+ await this.sleep(1000);
+ progressDialog.close();
+
+ // 鏄剧ず鏈�缁堢粨鏋�
+ if (this.sendingFailCount == 0) {
+ this.$message.success(
+ `鎴愬姛鍙戦�佺粰 ${this.sendingSuccessCount} 浣嶄笓瀹禶
+ );
+ } else if (this.sendingSuccessCount > 0) {
+ this.$message.warning(
+ `鎴愬姛鍙戦�佺粰 ${this.sendingSuccessCount} 浣嶄笓瀹讹紝澶辫触 ${this.sendingFailCount} 浣峘
+ );
+ // 濡傛灉鏈夊け璐ワ紝鍙互鏄剧ず璇︾粏澶辫触淇℃伅
+ this.showFailedDetails();
+ } else {
+ this.$message.error("鍏ㄩ儴鍙戦�佸け璐ワ紝璇风◢鍚庨噸璇�");
+ }
+
+ // 鍏抽棴鍙戦�佸璇濇
this.sendDialogVisible = false;
this.sendForm = {
expertType: "normal",
@@ -1890,14 +2250,99 @@
url: ""
};
this.currentSendExperts = [];
+ // 淇濆瓨鏁翠釜鍗曟嵁
+ this.handleSave();
} catch (error) {
- console.error("鍙戦�佸け璐�:", error);
- this.$message.error("鍙戦�佸け璐ワ紝璇烽噸璇�");
+ console.error("鍙戦�佽繃绋嬩腑鍙戠敓閿欒:", error);
+ progressDialog.close();
+ this.$message.error("鍙戦�佽繃绋嬩腑鍙戠敓閿欒锛岃閲嶈瘯");
} finally {
- this.sending = false;
+ this.sendingAll = false;
+ }
+ },
+ // 鍙戦�佸崟涓笓瀹剁殑鏂规硶
+ async sendSingleExpert(expert, index) {
+ try {
+ // 鏋勫缓鍙戦�佹暟鎹�
+ const sendData = {
+ number: expert.deptname || "", // 鐢ㄦ埛鎵嬫満鍙�
+ title: this.sendForm.title,
+ url: this.sendForm.url || "",
+ createTime: new Date()
+ .toISOString()
+ .replace("T", " ")
+ .substring(0, 19)
+ };
+
+ console.log(`姝e湪鍙戦�佺 ${index + 1} 涓笓瀹�: ${expert.expertname}`);
+
+ // 璋冪敤鍙戦�侀�氱煡鎺ュ彛
+ // const response = await sendNotification(sendData);
+ const response = await sendcall({
+ tel: expert.donorno ? expert.donorno : 13634195431, // 杩欓噷搴旇鏄� expert.deptname 鎴� expert.phone
+ messageContent:
+ "闈掑矝澶у闄勫睘鍖婚櫌涓婃姤娼滃湪鎹愮尞妗堜緥锛岃鐧诲綍OPO绯荤粺鏌ョ湅璇︾粏淇℃伅锛屽強鏃惰繘琛屽鎺ャ�傜櫥褰曢摼鎺�:https://brdeddd.qduhosos.cn/dklejdj/deljf/index"
+ });
+
+ if (response.code == 200) {
+ return {
+ success: true,
+ expert: expert.expertname,
+ index: index
+ };
+ } else {
+ return {
+ success: false,
+ expert: expert.expertname,
+ index: index,
+ error: response.msg
+ };
+ }
+ } catch (error) {
+ console.error(`鍙戦�佺粰涓撳 ${expert.expertname} 澶辫触:`, error);
+ return {
+ success: false,
+ expert: expert.expertname,
+ index: index,
+ error: error.message
+ };
}
},
+ // 鏄剧ず澶辫触璇︽儏鐨勬柟娉�
+ showFailedDetails() {
+ const failedExperts = this.sendingResults.filter(r => !r.success);
+ if (failedExperts.length > 0) {
+ this.$confirm(
+ `鏈� ${failedExperts.length} 浣嶄笓瀹跺彂閫佸け璐ワ紝鏄惁鏌ョ湅澶辫触璇︽儏锛焋,
+ "鍙戦�佺粨鏋�",
+ {
+ confirmButtonText: "鏌ョ湅璇︽儏",
+ cancelButtonText: "鍏抽棴",
+ type: "warning"
+ }
+ )
+ .then(() => {
+ let detailMessage = "鍙戦�佸け璐ョ殑涓撳锛歕n\n";
+ failedExperts.forEach((expert, index) => {
+ detailMessage += `${index + 1}. ${expert.expert}: ${
+ expert.error
+ }\n`;
+ });
+
+ this.$alert(detailMessage, "鍙戦�佸け璐ヨ鎯�", {
+ confirmButtonText: "纭畾",
+ customClass: "failed-details-dialog"
+ });
+ })
+ .catch(() => {});
+ }
+ },
+
+ // 鐫$湢鍑芥暟锛岀敤浜庨棿闅�
+ sleep(ms) {
+ return new Promise(resolve => setTimeout(resolve, ms));
+ },
// 鍒犻櫎涓撳瀹℃煡
handleDeleteExpertReview(expert, index) {
this.$confirm("纭畾瑕佸垹闄よ涓撳鐨勫鏌ヨ褰曞悧锛�", "鎻愮ず", {
@@ -1931,7 +2376,7 @@
const response = await ethicalreExpertTotal(params);
- if (response && response.code === 200) {
+ if (response && response.code == 200) {
this.expertHistoryData = response.data || response[0] || null;
} else {
this.$message.error(
@@ -2171,11 +2616,82 @@
.selected-case-info {
margin-bottom: 20px;
}
+/* 鍙戦�佽繘搴︽牱寮� */
+.send-progress-container {
+ margin: 20px 0;
+ padding: 20px;
+ background: #f5f7fa;
+ border-radius: 8px;
+}
+.send-stats {
+ display: flex;
+ justify-content: center;
+ gap: 30px;
+ margin-top: 10px;
+}
+
+.stat-item {
+ font-size: 14px;
+ font-weight: 500;
+ padding: 4px 12px;
+ border-radius: 4px;
+}
+
+.stat-item.success {
+ color: #67c23a;
+ background: #f0f9eb;
+}
+
+.stat-item.fail {
+ color: #f56c6c;
+ background: #fef0f0;
+}
+
+/* 澶辫触璇︽儏瀵硅瘽妗� */
+.failed-details-dialog {
+ min-width: 400px;
+ max-width: 600px;
+}
+
+.failed-details-dialog .el-message-box__content {
+ max-height: 400px;
+ overflow-y: auto;
+ white-space: pre-wrap;
+ word-break: break-word;
+}
.case-info-card {
border-left: 4px solid #67c23a;
}
+/* 鍦–SS涓坊鍔� */
+:deep(.el-message-box) {
+ max-width: 500px;
+}
+/* 娣诲姞鏈繚瀛樼姸鎬佹牱寮� */
+.unsaved-hint {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ background: #e6a23c;
+ color: white;
+ padding: 4px 8px;
+ border-radius: 4px;
+ font-size: 12px;
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0% {
+ opacity: 0.8;
+ }
+ 50% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0.8;
+ }
+}
/* 鍝嶅簲寮忚璁� */
@media (max-width: 768px) {
.ethics-review-detail {
--
Gitblit v1.9.3