From d21d7dd23f15a0ca395a4c9d1b3bb31330ff56c0 Mon Sep 17 00:00:00 2001
From: yxh <172933527@qq.com>
Date: 星期三, 30 九月 2026 11:27:37 +0800
Subject: [PATCH] 专家费校验

---
 src/views/project/fund/performancedetails/index.vue                |  394 +++++++++++++---
 src/views/project/fund/applyDetail/index.vue                       |  598 +++++++++++++++++--------
 src/views/project/fund/expertFeeApply/index.vue                    |   47 +
 vue.config.js                                                      |    2 
 src/views/project/travelexpenseapply/travelexpensedetail/index.vue |   89 +++
 package.json                                                       |    2 
 src/views/project/fundcheck/expertFeeCheck/index.vue               |   31 +
 src/views/project/externalperson/index.vue                         |   86 +++
 src/views/project/documentfiles/index.vue                          |  100 +++
 src/api/project/fund.js                                            |   10 
 10 files changed, 1,006 insertions(+), 353 deletions(-)

diff --git a/package.json b/package.json
index 761dd72..015116b 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
   "author": "娴欐睙浜ュ皵鏃朵俊鎭鎶�鏈夐檺鍏徃",
   "license": "MIT",
   "scripts": {
-    "dev": "vue-cli-service serve",
+    "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
     "build:stage": "vue-cli-service build --mode staging",
     "preview": "node build/index.js --preview",
diff --git a/src/api/project/fund.js b/src/api/project/fund.js
index 92f64cc..3608fb9 100644
--- a/src/api/project/fund.js
+++ b/src/api/project/fund.js
@@ -160,6 +160,16 @@
   })
 }
 
+// 涓撳鍔冲姟璐癸細淇濆瓨鍓嶇殑璐圭敤鎺у埗鏍¢獙锛堝共璺戯紝涓嶈惤搴擄級
+// 杩斿洖 { errors: [闃绘柇鎬т俊鎭痌, warnings: [鎻愮ず淇℃伅], blocked: 鏄惁闃绘柇 }
+export function validateExpertFee(data) {
+  return request({
+    url: '/project/fund/validateExpertFee',
+    method: 'post',
+    data: data
+  })
+}
+
 // 浼︾悊涓撳璐规墦鍗�
 export function getdownloadLL(id) {
   return request({
diff --git a/src/views/project/documentfiles/index.vue b/src/views/project/documentfiles/index.vue
index 64bf2be..591306b 100644
--- a/src/views/project/documentfiles/index.vue
+++ b/src/views/project/documentfiles/index.vue
@@ -659,34 +659,100 @@
     download() {
       let list = this.fileList;
       if (list.length > 0) {
-        let downUrl = list[0].url;
-        const link = document.createElement("a");
-        link.href = this.baseUrl + downUrl;
-        link.setAttribute("download", this.getFileName(list[0].name));
-        document.body.appendChild(link);
-        link.click();
+        this.saveFile(list[0].url, this.getFileName(list[0].name, list[0].url));
       } else {
         this.$modal.msgWarning("鏈幏鍙栧埌鏂囦欢鍦板潃锛岃纭");
       }
     },
     handleDownload(row) {
       if (row.fileurl != "" && row.fileurl != null) {
-        const link = document.createElement("a");
-        link.href = this.baseUrl + row.fileurl;
-        link.setAttribute("download", this.getFileName(row.fileurl));
-        document.body.appendChild(link);
-        link.click();
+        this.saveFile(
+          row.fileurl,
+          this.getFileName(row.filename, row.fileurl, row.filename)
+        );
       } else {
         this.$modal.msgWarning("鏈幏鍙栧埌鏂囦欢鍦板潃锛岃纭");
       }
     },
-    // 鑾峰彇鏂囦欢鍚嶇О
-    getFileName(name) {
-      if (name.lastIndexOf("/") > -1) {
-        return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
-      } else {
-        return "";
+
+    /**
+     * 涓嬭浇鏂囦欢锛堝繀椤诲甫閴存潈锛夈��
+     *
+     * 鑳屾櫙锛�/profile/** 闈欐�佽祫婧愭湭鍦� SecurityConfig 涓斁琛岋紙anyRequest().authenticated()锛夛紝
+     * 鑰屽悗绔� TokenService 鍙粠璇锋眰澶� Authorization 鍙� token銆�
+     * 鍥犳鐢� <a href> 鐩存帴璺宠浆涓嬭浇涓嶄細鎼哄甫 token锛屾湇鍔$杩斿洖 401锛岃〃鐜颁负鈥滅偣涓嬭浇娌″弽搴�/涓嬩笉鍒版枃浠垛�濄��
+     * 杩欓噷鏀逛负 fetch 甯� Authorization 澶村彇鍥炴枃浠舵祦锛屽啀鐢� blob 鏈湴鍙﹀瓨銆�
+     *
+     * @param {string} fileUrl 鏂囦欢鍦板潃锛堝簱涓瓨鐨勬槸 /profile/upload/... 鐩稿璺緞锛�
+     * @param {string} fileName 鍙﹀瓨涓虹殑鏂囦欢鍚�
+     */
+    saveFile(fileUrl, fileName) {
+      if (!fileUrl) {
+        this.$modal.msgWarning("鏈幏鍙栧埌鏂囦欢鍦板潃锛岃纭");
+        return;
       }
+      // 鍏煎鍘嗗彶鏁版嵁涓凡鏄粷瀵瑰湴鍧�鐨勬儏鍐碉紝閬垮厤閲嶅鎷兼帴
+      const isAbsolute = /^https?:\/\//i.test(fileUrl);
+      const url = isAbsolute ? fileUrl : this.baseUrl + fileUrl;
+
+      this.$modal.loading("姝e湪涓嬭浇鏂囦欢锛岃鑰愬績绛夊緟锛�");
+      fetch(url, {
+        method: "get",
+        headers: { Authorization: "Bearer " + getToken() },
+      })
+        .then((response) => {
+          if (!response.ok) {
+            // 401/403/404 蹇呴』鏄惧紡鎻愮ず锛屽惁鍒欎細涓嬪埌涓�涓唴瀹逛负閿欒椤电殑鏂囦欢
+            throw new Error("HTTP " + response.status);
+          }
+          return response.blob();
+        })
+        .then((blob) => {
+          const blobUrl = window.URL.createObjectURL(blob);
+          const link = document.createElement("a");
+          link.href = blobUrl;
+          link.setAttribute("download", fileName || "涓嬭浇鏂囦欢");
+          document.body.appendChild(link);
+          link.click();
+          document.body.removeChild(link);
+          window.URL.revokeObjectURL(blobUrl);
+        })
+        .catch((err) => {
+          console.error("鏂囦欢涓嬭浇澶辫触锛�" + url, err);
+          this.$modal.msgError("鏂囦欢涓嬭浇澶辫触锛岃纭鏂囦欢鏄惁瀛樺湪鎴栫櫥褰曟槸鍚﹁繃鏈�");
+        })
+        .finally(() => {
+          this.$modal.closeLoading();
+        });
+    },
+
+    /**
+     * 鑾峰彇鍙﹀瓨涓虹殑鏂囦欢鍚嶃��
+     *
+     * 浼樺厛绾э細甯︽墿灞曞悕鐨勫師濮嬫枃浠跺悕 > 鏂囦欢鍦板潃鏈 > 鏂囨。鏍囬銆�
+     * 涔嬫墍浠ヤ笉鐩存帴鐢� form.filename锛氳瀛楁鍦ㄨ〃鍗曚腑鍙墜宸ョ紪杈戯紙濡傗�滀汉浣撳櫒瀹樼Щ妞嶆潯渚嬧�濓級锛�
+     * 涓嶅甫鎵╁睍鍚嶏紝鐩存帴鐢ㄤ綔鍙﹀瓨鍚嶄細瀵艰嚧绯荤粺鏃犳硶璇嗗埆鎵撳紑鏂瑰紡銆�
+     *
+     * @param {string} storedName 鍘熷鏂囦欢鍚嶏紙濡� form.filename 涓瓨鐨� xxx.docx锛�
+     * @param {string} fileUrl 鏂囦欢鍦板潃
+     * @param {string} title 澶囩敤鍚嶇О锛堟枃妗f爣棰橈級
+     */
+    getFileName(storedName, fileUrl, title) {
+      const hasExt = (name) => !!name && name.lastIndexOf(".") > -1;
+
+      if (hasExt(storedName)) {
+        return storedName;
+      }
+
+      const source = fileUrl || "";
+      if (source.lastIndexOf("/") > -1) {
+        const fromUrl = source.slice(source.lastIndexOf("/") + 1);
+        if (fromUrl) {
+          return fromUrl;
+        }
+      }
+
+      return title || storedName || "涓嬭浇鏂囦欢";
     },
 
     //鏂囦欢涓婁紶鎴愬姛鍥炶皟
diff --git a/src/views/project/externalperson/index.vue b/src/views/project/externalperson/index.vue
index 0741472..af8db6b 100644
--- a/src/views/project/externalperson/index.vue
+++ b/src/views/project/externalperson/index.vue
@@ -47,9 +47,10 @@
 
     <el-table v-loading="loading" :data="externalpersonList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
-      <el-table-column label="璐﹀彿绫诲埆" align="center" prop="usertype">
+      <el-table-column label="璐﹀彿绫诲埆" align="center" prop="usertype" width="220">
         <template slot-scope="scope">
-          <dict-tag :options="dict.type.sys_UserType" :value="scope.row.usertype" />
+          <dict-tag v-for="t in splitUserType(scope.row.usertype)" :key="t"
+            :options="dict.type.sys_UserType" :value="t" />
         </template>
       </el-table-column>
       <el-table-column label="璐﹀彿缂栧彿" align="center" prop="userno" />
@@ -90,7 +91,7 @@
       <el-form ref="form" :model="form" :rules="rules" label-width="120px">
         <el-row>
           <el-col :span="12"><el-form-item label="璐﹀彿绫诲埆" prop="usertype">
-              <el-select v-model="form.usertype" placeholder="璇烽�夋嫨璐﹀彿绫诲埆">
+              <el-select v-model="form.usertype" multiple collapse-tags placeholder="璇烽�夋嫨璐﹀彿绫诲埆锛堝彲澶氶�夛級">
                 <el-option v-for="dict in dict.type.sys_UserType" :key="dict.value" :label="dict.label"
                   :value="dict.value"></el-option>
               </el-select>
@@ -118,14 +119,14 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row v-if="form.usertype != 'org'">
+        <el-row v-if="!isUnitForm">
           <el-col :span="24">
             <el-form-item label="韬唤璇佸彿" prop="idcardno">
               <el-input v-model="form.idcardno" placeholder="璇疯緭鍏ヨ韩浠借瘉鍙�" />
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row v-if="form.usertype != 'org'"><el-col :span="12">
+        <el-row v-if="!isUnitForm"><el-col :span="12">
             <el-form-item label="鎬у埆" prop="sex">
               <el-select v-model="form.sex" placeholder="璇烽�夋嫨鎬у埆">
                 <el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label"
@@ -140,7 +141,7 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row v-if="form.usertype != 'org'">
+        <el-row v-if="!isUnitForm">
           <el-col :span="12">
             <el-form-item label="鎵�鍦ㄥ崟浣�" prop="unitname">
               <el-select v-model="form.unitno" placeholder="鎵�鍦ㄥ崟浣�" clearable filterable allow-create style="width: 100%">
@@ -272,7 +273,19 @@
           { required: true, message: "璇疯緭鍏ヨ处鎴峰悕绉�", trigger: "blur" }
         ],
         idcardno: [
-          { required: true, message: "璇疯緭鍏ヨ韩浠借瘉鍙风爜", trigger: "blur" }
+          {
+            //璐﹀彿绫诲埆涓�"鍗曚綅鏈烘瀯"鏃舵棤闇�韬唤璇佸彿
+            validator: (rule, value, callback) => {
+              if (this.hasUserType(this.form.usertype, "org")) {
+                return callback();
+              }
+              if (!value || !String(value).trim()) {
+                return callback(new Error("璇疯緭鍏ヨ韩浠借瘉鍙风爜"));
+              }
+              return callback();
+            },
+            trigger: "blur"
+          }
         ],
         bankcardno: [
           { required: true, message: "璇疯緭鍏ラ摱琛岃处鍙�", trigger: "blur" }
@@ -282,6 +295,12 @@
         ]
       },      
     };
+  },
+  computed: {
+    /** 琛ㄥ崟鏄惁閫夋嫨浜�"鍗曚綅鏈烘瀯"锛堣处鍙风被鍒负澶氬�硷紝鍚� org 鍗充负鍗曚綅锛� */
+    isUnitForm() {
+      return this.hasUserType(this.form.usertype, "org");
+    }
   },
   created() {
     this.getUserProfile();
@@ -296,6 +315,28 @@
         const managerList = ["admin", "048", "047"];
         this.ismanager = managerList.includes(res.data.userName);
       });
+    },
+
+    /** 浜哄憳绫诲瀷锛堝鍊硷紝閫楀彿鍒嗛殧锛夎浆鏁扮粍 */
+    splitUserType(usertype) {
+      if (!usertype) {
+        return [];
+      }
+      if (Array.isArray(usertype)) {
+        return usertype;
+      }
+      return String(usertype)
+        .split(",")
+        .map(t => t.trim())
+        .filter(t => t);
+    },
+    /** 浜哄憳绫诲瀷鏁扮粍杞�楀彿鍒嗛殧瀛楃涓� */
+    joinUserType(usertype) {
+      return Array.isArray(usertype) ? usertype.join(",") : usertype;
+    },
+    /** 浜哄憳绫诲瀷鏄惁鍖呭惈鎸囧畾绫诲瀷锛堝 org = 鍗曚綅鏈烘瀯锛� */
+    hasUserType(usertype, code) {
+      return this.splitUserType(usertype).indexOf(code) > -1;
     },
 
     /** 鏌ヨ鍗曚綅銆佷汉鍛樿处鍙峰垪琛� */
@@ -331,7 +372,7 @@
         userno: null,
         username: null,
         userstatus: 0,
-        usertype: null,
+        usertype: [],
         personnelunitno: null,
         delFlag: null,
         createBy: null,
@@ -383,6 +424,8 @@
       const id = row.id || this.ids;
       getExternalperson(id).then(response => {
         this.form = response.data;
+        //璐﹀彿绫诲埆涓哄鍊硷紙閫楀彿鍒嗛殧锛夛紝琛ㄥ崟鐢ㄦ暟缁勫洖鏄�
+        this.form.usertype = this.splitUserType(response.data.usertype);
         this.open = true;
         this.title = "浜哄憳/鍗曚綅璐﹀彿淇℃伅淇敼";
       });
@@ -396,6 +439,8 @@
             if (res.organizationid == this.form.unitno)
               this.form.unitname = res.organizationname;
           });
+          //璐﹀彿绫诲埆涓哄鍊硷細鎻愪氦鍓嶈浆鍥為�楀彿鍒嗛殧鐨勫瓧绗︿覆
+          this.form.usertype = this.joinUserType(this.form.usertype);
           console.log(this.form);
           if (this.form.id != null) {
             updateExternalperson(this.form).then(response => {
@@ -405,15 +450,8 @@
               this.getList();
             });
           } else {
-            //妫�鏌ヨ韩浠借瘉鍞竴
-            getInfoByIDCardNo(this.form.idcardno).then(res => {
-              if (res.data.length > 1) {
-                this.$modal.msgWarning("韬唤璇佸彿淇℃伅宸茶鐧昏锛岃妫�鏌ヨ韩浠借瘉鍙凤紒"
-                );
-                return;
-              }
-
-              //淇濆瓨淇℃伅
+            //淇濆瓨淇℃伅锛堝崟浣嶈处鍙锋病鏈夎韩浠借瘉鍙凤紝璺宠繃韬唤璇佹煡閲嶏級
+            const saveNew = () => {
               getOnlyCode(this.seqnoParams).then(res => {
                 this.form.userno = res.data.currentvalue;
 
@@ -424,7 +462,21 @@
                   this.getList();
                 });
               });
+            };
 
+            if (!this.form.idcardno || !String(this.form.idcardno).trim()) {
+              saveNew();
+              return;
+            }
+
+            //妫�鏌ヨ韩浠借瘉鍞竴
+            getInfoByIDCardNo(this.form.idcardno).then(res => {
+              if (res.data.length > 1) {
+                this.$modal.msgWarning("韬唤璇佸彿淇℃伅宸茶鐧昏锛岃妫�鏌ヨ韩浠借瘉鍙凤紒"
+                );
+                return;
+              }
+              saveNew();
             });
           }
         }
diff --git a/src/views/project/fund/applyDetail/index.vue b/src/views/project/fund/applyDetail/index.vue
index 8f7e001..89b17e7 100644
--- a/src/views/project/fund/applyDetail/index.vue
+++ b/src/views/project/fund/applyDetail/index.vue
@@ -229,8 +229,9 @@
               v-if="businessType == '1' || businessType == '2'">
               <template slot-scope="scope">
                 <el-form-item label-width="0">
-                  <el-input :disabled="userprofile.nickName != '闄堟厱鍗�'" v-model.number="scope.row.idcardno"
-                    @input="tableParValueChange1(scope.row)" placeholder="韬唤璇佸彿" />
+                  <el-input :disabled="userprofile.nickName != '闄堟厱鍗�' || scope.row.isunit == 1"
+                    :placeholder="scope.row.isunit == 1 ? '鍗曚綅鏃犻渶濉啓' : '韬唤璇佸彿'"
+                    v-model.number="scope.row.idcardno" @input="tableParValueChange1(scope.row)" />
                 </el-form-item>
               </template>
             </el-table-column>
@@ -690,13 +691,19 @@
     </el-dialog>
 
     <!-- 鎵归噺閫夊彇 -->
-    <el-dialog title="鎵归噺鐢熸垚鏄庣粏淇℃伅" :visible.sync="batchdialogVisible" width="30%">
+    <el-dialog title="鎵归噺鐢熸垚鏄庣粏淇℃伅" :visible.sync="batchdialogVisible" width="35%">
+      <div style="margin-bottom: 12px">
+        <el-input v-model="personKeyword" clearable size="small" prefix-icon="el-icon-search"
+          placeholder="杈撳叆 濮撳悕 / 鍗曚綅 / 宸ュ彿 / 韬唤璇佸悗4浣� 绛涙煡" style="width: 330px" />
+        <span style="margin-left: 10px; color: #909399; font-size: 12px">鍏� {{ filteredCityOptions.length }} 浜�</span>
+      </div>
       <div style="max-height: 300px; overflow-y: auto">
-        <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">鍏ㄩ��</el-checkbox>
+        <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">鍏ㄩ�夛紙褰撳墠绛涙煡缁撴灉锛�</el-checkbox>
         <div style="margin: 15px 0;"></div>
         <el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
-          <el-checkbox border v-for="city in cityOptions" :label="city" :key="city.reportNo">{{ city.reportName
-          }}</el-checkbox>
+          <el-checkbox border v-for="city in filteredCityOptions" :label="city"
+            :key="city.reportNo + '_' + city.reportName">{{ city.reportName
+            }}{{ city.unitname ? " 路 " + city.unitname : "" }}</el-checkbox>
         </el-checkbox-group>
       </div>
 
@@ -736,6 +743,7 @@
   addorupdateFund,
   ManualCalculation,
   getdetailsByItemId,
+  validateExpertFee,
   listbypower
 } from "@/api/project/fund";
 
@@ -882,6 +890,8 @@
       // 缃戠粶璇锋眰澶�
       Networkheader: null,
       batchdialogVisible: false,
+      //鎵归噺褰曞叆寮规鐨勭瓫鏌ュ叧閿瓧
+      personKeyword: "",
       itemlist: [],
       cityOptions: [],
       checkAll: false,
@@ -964,7 +974,19 @@
         ],
         unitTaxNo: [{ required: true, message: "璇疯緭鍏ョ◣鍙�", trigger: "blur" }],
         idcardno: [
-          { required: true, message: '璇疯緭鍏ヨ韩浠借瘉鍙�', trigger: 'blur' },
+          {
+            // 璐︽埛绫诲瀷閫夋嫨"鍗曚綅鏈烘瀯"鏃朵笉闇�瑕佽韩浠借瘉鍙�
+            validator: (rule, value, callback) => {
+              if (this.hasUserType(this.accountselectform.usertype, "org")) {
+                return callback();
+              }
+              if (!value || !String(value).trim()) {
+                return callback(new Error("璇疯緭鍏ヨ韩浠借瘉鍙�"));
+              }
+              return callback();
+            },
+            trigger: "blur"
+          },
           // 娣诲姞鑷畾涔夋牎楠岃鍒�
           { validator: validateIdCard, trigger: 'blur' }
         ],
@@ -1126,7 +1148,16 @@
   },
 
   //鐩戝惉灞炴�� 绫讳技浜巇ata姒傚康
-  computed: {},
+  computed: {
+    //鎵归噺褰曞叆寮规锛氭寜鍏抽敭瀛楋紙濮撳悕/鍗曚綅/宸ュ彿/韬唤璇佸悗4浣嶏級绛涙煡鍚庣殑鍊欓�変汉
+    filteredCityOptions() {
+      const kw = (this.personKeyword || "").trim().toLowerCase();
+      if (!kw) {
+        return this.cityOptions;
+      }
+      return this.cityOptions.filter(item => this.personMatchKeyword(item, kw));
+    }
+  },
   //鐩戞帶data涓殑鏁版嵁鍙樺寲
   watch: {},
   //鏂规硶闆嗗悎
@@ -1539,6 +1570,31 @@
         if (valid) {
           this.formData = this.form;
 
+          // 涓撳鍔冲姟璐逛笓鐢細9 鏉¤垂鐢ㄦ帶鍒惰鍒欐牎楠岋紙鏍¢獙涓嶉�氳繃涓嶅厑璁镐繚瀛橈級
+          if (this.businessType == "1") {
+            this.$modal.loading("姝e湪鏍¢獙涓撳鍔冲姟璐圭敤锛岃绋嶅�欙紒");
+            this.checkExpertFeeRules("淇濆瓨").then((allowed) => {
+              this.$modal.closeLoading();
+              if (allowed) {
+                this.doSubmitForm();
+              }
+            });
+            return;
+          }
+
+          this.doSubmitForm();
+        }
+      });
+    }, 500),
+
+    /**
+     * 淇濆瓨鐢宠鍗曠殑瀹為檯钀藉簱閫昏緫銆�
+     *
+     * 浠� submitForm 涓媶鍑猴紝渚夸簬鍦ㄤ笓瀹跺姵鍔¤垂瑙勫垯鏍¢獙閫氳繃鍚庡啀鎵ц锛�
+     * 鍏朵粬涓氬姟绫诲瀷鐢� submitForm 鐩存帴璋冪敤锛岃涓轰笌鎷嗗垎鍓嶄竴鑷淬��
+     */
+    doSubmitForm() {
+
           //淇濆瓨鍓嶆牎楠屾暟鎹�
           for (let k = 0; k < this.rbDetails.length; k++) {
             let tempDetail = this.rbDetails[k];
@@ -1736,9 +1792,84 @@
           //鍏抽棴绐楀彛
           this.loading = false;
           // this.getfundList();
-        }
+    },
+
+    /**
+     * 涓撳鍔冲姟璐� 9 鏉¤垂鐢ㄦ帶鍒惰鍒欐牎楠岋紙鎻愪氦鍓嶆嫤鎴級銆�
+     *
+     * 閫傜敤鑼冨洿锛歜usinessType === '1'锛堜笓瀹跺姵鍔¤垂鐢宠鍗曪級锛屼笌鍚庣 applytype === '1' 瀵瑰簲銆�
+     * 鍏朵粬涓氬姟绫诲瀷锛堜鸡鐞嗕笓瀹惰垂銆佸尰瀛︽垚鏈�佸姙鍏垂鐢級涓嶆牎楠岋紝鐩存帴鏀捐銆�
+     *
+     * 鏍¢獙鍙e緞锛堝悓涓�鎹愮尞妗堜緥 infoid 涓嬬疮璁★級鐢卞悗绔粺涓�瀹炵幇锛�
+     *   errors   闃绘柇鍨嬶細鎻愮ず杩濆弽鐨勫叿浣撹鍒欙紝涓嶅厑璁哥户缁繚瀛�/瀹℃牳
+     *   warnings 鎻愮ず鍨嬶細浠呮彁閱掔粡鍔炰汉澶勭悊锛堣鍒� 5銆�6锛夛紝闇�浜屾纭鍚庢墠缁х画
+     *
+     * @param {string} action 褰撳墠鍔ㄤ綔锛岀敤浜庢嫾鎺ユ彁绀烘枃妗堬紙濡傗�滀繚瀛樷�濃�滄彁浜ゅ鏍糕�濓級
+     * @returns {Promise<boolean>} true 鍏佽缁х画锛宖alse 闃绘缁х画
+     */
+    checkExpertFeeRules(action) {
+      if (this.businessType != "1") {
+        return Promise.resolve(true);
+      }
+      // 鍚庣鎸夈�屾渚嬪唴宸叉湁鍗曟嵁 + 鏈鎻愪氦鏄庣粏銆嶅悎骞惰绠楋紝纭繚灏氭湭钀藉簱鐨勬槑缁嗕篃鍙備笌鏍¢獙
+      const payload = Object.assign({}, this.form, {
+        applytype: this.form.applytype || "1",
+        serviceFunddetails: this.rbDetails,
       });
-    }, 500),
+      // 鎺掓煡鐢細鑳界洿鎺ヤ粠鎺у埗鍙扮湅鍒板埌搴曢�佷簡浠�涔堬紝浠ュ強鍚庣鍒ゅ畾浜嗕粈涔�
+      console.log("[涓撳璐规牎楠宂 鎻愪氦鏍¢獙", action, {
+        businessType: this.businessType,
+        applytype: payload.applytype,
+        infoid: payload.infoid,
+        fundId: payload.id,
+        鏄庣粏: (this.rbDetails || []).map((d) => ({
+          itemid: d.itemid,
+          amount: d.amount,
+          taxedamount: d.taxedamount,
+          鍦烘櫙: d.servicesscopename,
+        })),
+      });
+         
+      return validateExpertFee(payload)
+        .then((res) => {
+          const errors = (res && res.errors) || [];
+          const warnings = (res && res.warnings) || [];
+          console.log("[涓撳璐规牎楠宂 鍚庣杩斿洖", { errors, warnings });
+
+          // 1) 闃绘柇鍨嬶細鍒楀嚭杩濆弽鐨勫叿浣撹鍒欙紝涓嶅厑璁哥户缁�
+          //    鐢ㄥ脊绐楄�岄潪杞绘彁绀猴細閿欒鍙兘鏈夊鏉★紝杞绘彁绀轰細鎸ゆ垚涓�琛屼笖寰堝揩娑堝け
+          if (errors.length > 0) {
+            this.$modal.alertError(
+              "涓撳鍔冲姟璐圭敤涓嶇鍚堜互涓嬭瀹氾紝鏃犳硶" +
+                action +
+                "锛歕n\n" +
+                errors.map((msg, i) => i + 1 + ". " + msg).join("\n\n")
+            );
+            return false;
+          }
+
+          // 2) 鎻愮ず鍨嬶細闇�缁忓姙浜虹‘璁ゅ悗鎵嶈兘缁х画锛堝綋鍓嶈鍒� 5銆�6 宸叉敼涓虹‖鎷︽埅锛屾鍒嗘敮淇濈暀澶囩敤锛�
+          if (warnings.length > 0) {
+            const confirmText =
+              "涓撳鍔冲姟璐圭敤瀛樺湪浠ヤ笅闂锛岃纭鏄惁缁х画" +
+              action +
+              "锛焅n\n" +
+              warnings.map((msg, i) => i + 1 + ". " + msg).join("\n\n");
+            return this.$modal
+              .confirm(confirmText)
+              .then(() => true)
+              .catch(() => false);
+          }
+
+          return true;
+        })
+        .catch((err) => {
+          // 鎺ュ彛寮傚父鏃舵寜鈥滀笉闃绘柇鈥濆鐞嗭紝閬垮厤鏍¢獙鏈嶅姟涓嶅彲鐢ㄥ鑷村畬鍏ㄦ棤娉曟姤閿�锛�
+          // 鍚庣 addOrUpdateNew / checkFund 浠嶆湁鍚屾牱鐨勭‖鎷︽埅鍏滃簳銆�
+          console.error("涓撳鍔冲姟璐硅鍒欐牎楠屾帴鍙h皟鐢ㄥけ璐�", err);
+          return true;
+        });
+    },
 
     checksubmit() {
       //妫�鏌ユ槸鍚︽敹鍒扮焊璐ㄦ潗鏂�
@@ -1770,8 +1901,19 @@
         return;
       }
 
-      this.Savenow();
-      console.log("淇濆瓨骞跺鎵�");
+      // 涓撳鍔冲姟璐逛笓鐢細9 鏉¤垂鐢ㄦ帶鍒惰鍒欐牎楠岋紙浠呭鏍搁�氳繃鏃舵嫤鎴級
+      const needExpertFeeCheck = this.checkObj.flowlevelone == 1;
+      const expertFeePromise = needExpertFeeCheck
+        ? this.checkExpertFeeRules("鎻愪氦瀹℃牳")
+        : Promise.resolve(true);
+
+      expertFeePromise.then((allowed) => {
+        if (!allowed) {
+          return;
+        }
+        this.Savenow();
+        console.log("淇濆瓨骞跺鎵�");
+      });
     },
 
     // 杩炵画瀹℃壒锛氳幏鍙栧綋鍓嶄笟鍔$被鍨嬩笅鐨勫緟瀹℃壒鍒楄〃
@@ -1880,6 +2022,19 @@
       });
     },
 
+    /** 浜哄憳绫诲瀷锛堝鍊硷紝閫楀彿鍒嗛殧锛夋槸鍚﹀寘鍚寚瀹氱被鍨嬶紱org = 鍗曚綅鏈烘瀯 */
+    hasUserType(usertype, code) {
+      if (!usertype) {
+        return false;
+      }
+      return (
+        String(usertype)
+          .split(",")
+          .map(t => t.trim())
+          .indexOf(code) > -1
+      );
+    },
+    /** 鍙楃泭浜�/璐︽埛鏄惁涓�"鍗曚綅"锛堜汉鍛樼被鍨嬪惈 org锛� */
     //鑾峰彇涓撳銆佸崟浣嶆満鏋勭殑璐︽埛鍒楄〃
     getAccountList() {
       listExternalperson().then(res => {
@@ -1888,7 +2043,7 @@
         for (let j = 0; j < res.rows.length; j++) {
           //鍗曚綅璐﹀彿鍒楄〃
           if (res.rows[j].userstatus == "1") {
-            if (res.rows[j].usertype == "org") {
+            if (this.hasUserType(res.rows[j].usertype, "org")) {
               this.accountlist.push({
                 id: res.rows[j].id,
                 userno: res.rows[j].userno,
@@ -1899,6 +2054,7 @@
                 bankcardno: res.rows[j].bankcardno,
                 unitno: res.rows[j].unitno,
                 unitname: res.rows[j].unitname,
+                usertype: res.rows[j].usertype,
                 userid:
                   res.rows[j].username + "锛�" + res.rows[j].bankcardno + "锛�"
               });
@@ -1913,6 +2069,7 @@
                 bankcardno: res.rows[j].bankcardno,
                 unitno: res.rows[j].unitno,
                 unitname: res.rows[j].unitname,
+                usertype: res.rows[j].usertype,
                 userid:
                   res.rows[j].username + "锛�" + res.rows[j].idcardno + "锛�"
               });
@@ -2193,192 +2350,202 @@
       this.Savereminder = false;
       this.Reminderquantity = 0;
       this.totalquantity = 0;
-      this.$refs["form"].validate(valid => {
-        if (valid) {
-          this.formData = this.form;
 
-          //淇濆瓨鍓嶆牎楠屾暟鎹�
-          for (let k = 0; k < this.rbDetails.length; k++) {
-            let tempDetail = this.rbDetails[k];
-            if (tempDetail.itemid == null) {
-              this.$modal.msgWarning(
-                "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                (k + 1).toString() +
-                "琛岀殑鏈嶅姟椤圭洰鏈�夋嫨锛岃鍏堥�夋嫨鏈嶅姟椤圭洰鍚庡啀鎻愪氦淇濆瓨锛�"
-              );
-              return;
-            }
-
-            if (this.businessType == "1") {
-              if (tempDetail.servicesscope == null) {
-                this.$modal.msgWarning(
-                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                  (k + 1).toString() +
-                  "琛岀殑璐圭敤璇存槑鏈�夋嫨,璇烽�夋嫨璐圭敤璇存槑鍚庡啀鎻愪氦淇濆瓨锛�"
-                );
-                return;
-              }
-
-              if (tempDetail.beneficiaryno == null) {
-                this.$modal.msgWarning(
-                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                  (k + 1).toString() +
-                  "琛岀殑浜哄憳濮撳悕涓虹┖,璇烽�夋嫨浜哄憳鍚庡啀鎻愪氦淇濆瓨锛�"
-                );
-                return;
-              }
-              if (tempDetail.unitname == null) {
-                this.$modal.msgWarning(
-                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                  (k + 1).toString() +
-                  "琛岀殑涓撳鍗曚綅涓虹┖,璇烽�夋嫨鍗曚綅鍚庡啀鎻愪氦淇濆瓨锛�"
-                );
-                return;
-              }
-            }
-          }
-
-          //澶勭悊鏄庣粏
-          for (let i = 0; i < this.rbDetails.length; i++) {
-            let tempDetail = this.rbDetails[i];
-            //鑾峰彇鏈嶅姟椤圭洰鏄庣粏
-            let tempitemlist = tempDetail.itemlist;
-            let itemIndex = tempitemlist.findIndex(
-              item => tempDetail.itemid == item.id
-            );
-            if (itemIndex > -1) {
-              tempDetail.itemname = tempitemlist[itemIndex].itemName;
-              tempDetail.itemid = tempitemlist[itemIndex].id;
-            }
-
-            //鑾峰彇applytypename銆佹湇鍔¤垂鐢ㄥぇ绫�
-            let applytypeIndex = this.rowfeeItemTypes.findIndex(
-              item => tempDetail.applytype == item.value
-            );
-            if (applytypeIndex > -1) {
-              tempDetail.applytypename = this.rowfeeItemTypes[
-                applytypeIndex
-              ].label;
-              tempDetail.subjecttype = this.rowfeeItemTypes[
-                applytypeIndex
-              ].subjecttype;
-              tempDetail.subjecttypename = this.rowfeeItemTypes[
-                applytypeIndex
-              ].subjecttypename;
-            }
-            this.rbDetails[i] = tempDetail;
-          }
-          //璁$畻褰撳墠琛屾姤閿�鍐呭璐圭敤鍚堣锛岀◣鍓嶉噾棰濓紙amount锛夈�佹墸绋庨噾棰濓紙taxamount锛夈�佺◣鍚庨噾棰濓紙taxedamount锛�
-          if (this.businessType == "2") {
-            for (let j = 0; j < this.rbDetails.length; j++) {
-              let tempDetail = this.rbDetails[j];
-              if (
-                isNaN(parseFloat(tempDetail.amount)) ||
-                moneyRound(tempDetail.amount) == 0
-              ) {
-                this.$modal.msgWarning(
-                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                  (j + 1).toString() +
-                  "琛岀殑閲戦鏈緭鍏ワ紝璇峰厛杈撳叆閲戦鍚庡啀鎻愪氦淇濆瓨锛�"
-                );
-                return;
-              }
-            }
-          } else if (this.businessType == "3" || this.businessType == "4") {
-            for (let j = 0; j < this.rbDetails.length; j++) {
-              let tempDetail = this.rbDetails[j];
-              if (
-                isNaN(parseFloat(tempDetail.amount)) ||
-                moneyRound(tempDetail.amount) == 0
-              ) {
-                this.$modal.msgWarning(
-                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
-                  (j + 1).toString() +
-                  "琛岀殑閲戦鏈緭鍏ワ紝璇峰厛杈撳叆閲戦鍚庡啀鎻愪氦淇濆瓨锛�"
-                );
-                return;
-              }
-              if (
-                isNaN(parseFloat(tempDetail.taxamount)) ||
-                moneyRound(tempDetail.taxamount) == 0
-              ) {
-                tempDetail.taxedamount = parseFloat(tempDetail.amount);
-              } else {
-                tempDetail.taxedamount =
-                  parseFloat(tempDetail.amount) +
-                  parseFloat(tempDetail.taxamount);
-              }
-            }
-          }
-
-          //淇濆瓨鏁版嵁
-          this.loading = true;
-          this.form.serviceFunddetails = 0;
-          this.rbDetails.map(item => {
-            this.form.serviceFunddetails += item.amount;
-          });
-          this.form.serviceFunddetails = this.rbDetails;
-
-          if (this.form.id != null) {
-          } else {
-            this.form.recordstatus = -1;
-          }
-
-          addorupdateFund(this.form).then(response => {
-            if (response.code === 200) {
-              this.$modal.msgSuccess("鐢宠鍗曚繚瀛樻垚鍔燂紒");
-              // 闈炴彁閱掔姸鎬佷笅鎵ц瀹℃壒瑙e喅寮傛璋冪敤寤惰繜闂
-              if (!this.Savereminder) {
-                let checkFundObj = {
-                  // fundid: this.checkObj.fundid,
-                  fundid: this.curId,
-                  flowconclusion: this.checkObj.flowlevelone,
-                  flowcontent: this.checkObj.flowconclusion
-                };
-                this.$modal.loading("姝e湪鎻愪氦瀹℃牳锛岃绋嶅�欙紒");
-                checkfund(checkFundObj).then(res => {
-                  if (res.code == 200) {
-                    //鍏抽棴绐楀彛
-                    this.$modal.closeLoading();
-                    this.$modal.msgSuccess("瀹℃牳瀹屾垚!");
-                    // 杩炵画瀹℃壒锛氳闂槸鍚︾户缁鎵逛笅涓�鍗�
-                    this.continueOrExit();
-                  } else {
-                    this.$modal.closeLoading();
-
-                    if (res.msg) {
-                      this.$modal.msgError("鎿嶄綔澶辫");
-                    } else {
-                      this.$modal.msgError(res.msg);
-                    }
-                  }
-                });
-              }
-              this.Getnetworkheader();
-              this.getroute();
-              this.getAccountList();
-              this.getUserList();
-              this.getUserProfile();
-            } else {
-              this.$modal.msgError("鐢宠鍗曚繚瀛樺け璐ワ細" + response.msg);
-            }
-          });
-
-          //鍏抽棴绐楀彛
-          this.loading = false;
-          // this.getfundList();
+      // 涓撳鍔冲姟璐逛笓鐢細9 鏉¤垂鐢ㄦ帶鍒惰鍒欐牎楠岋紙鏍¢獙涓嶉�氳繃涓嶅厑璁歌惤搴擄級
+      this.checkExpertFeeRules("淇濆瓨").then((allowed) => {
+        if (!allowed) {
+          return;
         }
+
+        this.$refs["form"].validate(valid => {
+          if (valid) {
+            this.formData = this.form;
+
+            //淇濆瓨鍓嶆牎楠屾暟鎹�
+            for (let k = 0; k < this.rbDetails.length; k++) {
+              let tempDetail = this.rbDetails[k];
+              if (tempDetail.itemid == null) {
+                this.$modal.msgWarning(
+                  "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                  (k + 1).toString() +
+                  "琛岀殑鏈嶅姟椤圭洰鏈�夋嫨锛岃鍏堥�夋嫨鏈嶅姟椤圭洰鍚庡啀鎻愪氦淇濆瓨锛�"
+                );
+                return;
+              }
+
+              if (this.businessType == "1") {
+                if (tempDetail.servicesscope == null) {
+                  this.$modal.msgWarning(
+                    "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                    (k + 1).toString() +
+                    "琛岀殑璐圭敤璇存槑鏈�夋嫨,璇烽�夋嫨璐圭敤璇存槑鍚庡啀鎻愪氦淇濆瓨锛�"
+                  );
+                  return;
+                }
+
+                if (tempDetail.beneficiaryno == null) {
+                  this.$modal.msgWarning(
+                    "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                    (k + 1).toString() +
+                    "琛岀殑浜哄憳濮撳悕涓虹┖,璇烽�夋嫨浜哄憳鍚庡啀鎻愪氦淇濆瓨锛�"
+                  );
+                  return;
+                }
+                if (tempDetail.unitname == null) {
+                  this.$modal.msgWarning(
+                    "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                    (k + 1).toString() +
+                    "琛岀殑涓撳鍗曚綅涓虹┖,璇烽�夋嫨鍗曚綅鍚庡啀鎻愪氦淇濆瓨锛�"
+                  );
+                  return;
+                }
+              }
+            }
+
+            //澶勭悊鏄庣粏
+            for (let i = 0; i < this.rbDetails.length; i++) {
+              let tempDetail = this.rbDetails[i];
+              //鑾峰彇鏈嶅姟椤圭洰鏄庣粏
+              let tempitemlist = tempDetail.itemlist;
+              let itemIndex = tempitemlist.findIndex(
+                item => tempDetail.itemid == item.id
+              );
+              if (itemIndex > -1) {
+                tempDetail.itemname = tempitemlist[itemIndex].itemName;
+                tempDetail.itemid = tempitemlist[itemIndex].id;
+              }
+
+              //鑾峰彇applytypename銆佹湇鍔¤垂鐢ㄥぇ绫�
+              let applytypeIndex = this.rowfeeItemTypes.findIndex(
+                item => tempDetail.applytype == item.value
+              );
+              if (applytypeIndex > -1) {
+                tempDetail.applytypename = this.rowfeeItemTypes[
+                  applytypeIndex
+                ].label;
+                tempDetail.subjecttype = this.rowfeeItemTypes[
+                  applytypeIndex
+                ].subjecttype;
+                tempDetail.subjecttypename = this.rowfeeItemTypes[
+                  applytypeIndex
+                ].subjecttypename;
+              }
+              this.rbDetails[i] = tempDetail;
+            }
+            //璁$畻褰撳墠琛屾姤閿�鍐呭璐圭敤鍚堣锛岀◣鍓嶉噾棰濓紙amount锛夈�佹墸绋庨噾棰濓紙taxamount锛夈�佺◣鍚庨噾棰濓紙taxedamount锛�
+            if (this.businessType == "2") {
+              for (let j = 0; j < this.rbDetails.length; j++) {
+                let tempDetail = this.rbDetails[j];
+                if (
+                  isNaN(parseFloat(tempDetail.amount)) ||
+                  moneyRound(tempDetail.amount) == 0
+                ) {
+                  this.$modal.msgWarning(
+                    "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                    (j + 1).toString() +
+                    "琛岀殑閲戦鏈緭鍏ワ紝璇峰厛杈撳叆閲戦鍚庡啀鎻愪氦淇濆瓨锛�"
+                  );
+                  return;
+                }
+              }
+            } else if (this.businessType == "3" || this.businessType == "4") {
+              for (let j = 0; j < this.rbDetails.length; j++) {
+                let tempDetail = this.rbDetails[j];
+                if (
+                  isNaN(parseFloat(tempDetail.amount)) ||
+                  moneyRound(tempDetail.amount) == 0
+                ) {
+                  this.$modal.msgWarning(
+                    "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
+                    (j + 1).toString() +
+                    "琛岀殑閲戦鏈緭鍏ワ紝璇峰厛杈撳叆閲戦鍚庡啀鎻愪氦淇濆瓨锛�"
+                  );
+                  return;
+                }
+                if (
+                  isNaN(parseFloat(tempDetail.taxamount)) ||
+                  moneyRound(tempDetail.taxamount) == 0
+                ) {
+                  tempDetail.taxedamount = parseFloat(tempDetail.amount);
+                } else {
+                  tempDetail.taxedamount =
+                    parseFloat(tempDetail.amount) +
+                    parseFloat(tempDetail.taxamount);
+                }
+              }
+            }
+
+            //淇濆瓨鏁版嵁
+            this.loading = true;
+            this.form.serviceFunddetails = 0;
+            this.rbDetails.map(item => {
+              this.form.serviceFunddetails += item.amount;
+            });
+            this.form.serviceFunddetails = this.rbDetails;
+
+            if (this.form.id != null) {
+            } else {
+              this.form.recordstatus = -1;
+            }
+
+            addorupdateFund(this.form).then(response => {
+              if (response.code === 200) {
+                this.$modal.msgSuccess("鐢宠鍗曚繚瀛樻垚鍔燂紒");
+                // 闈炴彁閱掔姸鎬佷笅鎵ц瀹℃壒瑙e喅寮傛璋冪敤寤惰繜闂
+                if (!this.Savereminder) {
+                  let checkFundObj = {
+                    // fundid: this.checkObj.fundid,
+                    fundid: this.curId,
+                    flowconclusion: this.checkObj.flowlevelone,
+                    flowcontent: this.checkObj.flowconclusion
+                  };
+                  this.$modal.loading("姝e湪鎻愪氦瀹℃牳锛岃绋嶅�欙紒");
+                  checkfund(checkFundObj).then(res => {
+                    if (res.code == 200) {
+                      //鍏抽棴绐楀彛
+                      this.$modal.closeLoading();
+                      this.$modal.msgSuccess("瀹℃牳瀹屾垚!");
+                      // 杩炵画瀹℃壒锛氳闂槸鍚︾户缁鎵逛笅涓�鍗�
+                      this.continueOrExit();
+                    } else {
+                      this.$modal.closeLoading();
+
+                      if (res.msg) {
+                        this.$modal.msgError("鎿嶄綔澶辫");
+                      } else {
+                        this.$modal.msgError(res.msg);
+                      }
+                    }
+                  });
+                }
+                this.Getnetworkheader();
+                this.getroute();
+                this.getAccountList();
+                this.getUserList();
+                this.getUserProfile();
+              } else {
+                this.$modal.msgError("鐢宠鍗曚繚瀛樺け璐ワ細" + response.msg);
+              }
+            });
+
+            //鍏抽棴绐楀彛
+            this.loading = false;
+            // this.getfundList();
+          }
+        });
       });
     },
     handleCheckAllChange(val) {
-      this.checkedCities = val ? this.cityOptions : [];
+      this.checkedCities = val ? this.filteredCityOptions.slice() : [];
       this.isIndeterminate = false;
     },
     handleCheckedCitiesChange(value) {
       let checkedCount = value.length;
-      this.checkAll = checkedCount === this.cityOptions.length;
+      this.checkAll =
+        this.filteredCityOptions.length > 0 &&
+        checkedCount === this.filteredCityOptions.length;
       this.isIndeterminate =
-        checkedCount > 0 && checkedCount < this.cityOptions.length;
+        checkedCount > 0 && checkedCount < this.filteredCityOptions.length;
     },
     // 鎵嬪姩璁$畻
     Manualcalculationfn() {
@@ -2414,19 +2581,57 @@
     // 鎵归噺褰曞叆鐐瑰嚮
     Batchentry() {
       // ethical
+      this.personKeyword = "";
+      this.checkedCities = [];
+      this.checkAll = false;
+      this.isIndeterminate = false;
       listReportname("ethical").then(res => {
         this.cityOptions = res.data;
       });
       this.batchdialogVisible = true;
     },
+    /** 鎵归噺褰曞叆寮规锛氬鍚�/鍗曚綅/宸ュ彿/韬唤璇佸悗4浣� 鍛戒腑鍒ゆ柇 */
+    personMatchKeyword(item, kw) {
+      const idcard = String(item.idcrad || "");
+      return (
+        String(item.reportName || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        String(item.unitname || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        String(item.reportNo || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        (idcard.length >= 4 && idcard.slice(-4).indexOf(kw) > -1)
+      );
+    },
     // 纭褰曞叆
     BatchentryFn() {
+      // 鏄庣粏涓凡鏈夌殑浜哄憳濮撳悕锛岀敤浜庨噸澶嶆彁閱�
+      const existed = {};
+      this.rbDetails.forEach(row => {
+        if (row.beneficiaryname) {
+          existed[String(row.beneficiaryname).trim()] = true;
+        }
+      });
+
+      const duplicated = [];
       this.checkedCities.forEach(item => {
+        const nameKey = String(item.reportName || "").trim();
+        if (nameKey && existed[nameKey]) {
+          duplicated.push(item.reportName);
+          return;
+        }
+        if (nameKey) {
+          existed[nameKey] = true;
+        }
         let rowData = {
           orderno: null,
           fundid: null,
           beneficiaryname: item.reportName,
           beneficiaryno: item.reportNo,
+          isunit: 0,
           unitname: item.unitname,
           unitno: null,
           uintuserno: null,
@@ -2471,11 +2676,17 @@
 
         this.rbDetails.push(rowData);
       });
-      for (let i = 0; i < this.checkedCities.length + 1; i++) {
+      for (let i = 0; i < this.rbDetails.length; i++) {
         this.rbDetails[i].orderno = i + 1;
       }
       this.calculateTax();
       this.batchdialogVisible = false;
+      this.checkedCities = [];
+      if (duplicated.length) {
+        this.$modal.msgWarning(
+          "浠ヤ笅浜哄憳鍦ㄦ槑缁嗕腑宸插瓨鍦紝宸茶烦杩囬噸澶嶆坊鍔狅細" + duplicated.join("銆�")
+        );
+      }
     },
     //鏂板涓�琛�
     addRow(rowIndex) {
@@ -2485,6 +2696,7 @@
         fundid: null,
         beneficiaryname: null,
         beneficiaryno: null,
+        isunit: 0,
         unitname: null,
         itemdescribe: null,
         unitno: null,
@@ -3121,11 +3333,13 @@
                   this.rbDetails[tempIndex].phone = res.telephone;
 
                   if (res.usertype == "org") {
+                    this.$set(this.rbDetails[tempIndex], "isunit", 1);
                     this.rbDetails[tempIndex].idcardno = "";
                     this.rbDetails[tempIndex].title = "";
                     this.rbDetails[tempIndex].unitno = "";
                     this.rbDetails[tempIndex].unitname = "";
                   } else {
+                    this.$set(this.rbDetails[tempIndex], "isunit", 0);
                     this.rbDetails[tempIndex].idcardno = res.idcardno;
                     this.rbDetails[tempIndex].title = res.title;
                     this.rbDetails[tempIndex].unitno = parseInt(res.unitno);
@@ -3231,12 +3445,14 @@
                       this.rbDetails[tempIndex].bankcardno = res.bankcardno;
                       this.rbDetails[tempIndex].phone = res.telephone;
 
-                      if (res.usertype == "org") {
+                      if (this.hasUserType(res.usertype, "org")) {
+                        this.$set(this.rbDetails[tempIndex], "isunit", 1);
                         this.rbDetails[tempIndex].idcardno = "";
                         this.rbDetails[tempIndex].title = "";
                         this.rbDetails[tempIndex].unitno = "";
                         this.rbDetails[tempIndex].unitname = "";
                       } else {
+                        this.$set(this.rbDetails[tempIndex], "isunit", 0);
                         this.rbDetails[tempIndex].idcardno = res.idcardno;
                         this.rbDetails[tempIndex].title = res.title;
                         this.rbDetails[tempIndex].unitno = parseInt(res.unitno);
diff --git a/src/views/project/fund/expertFeeApply/index.vue b/src/views/project/fund/expertFeeApply/index.vue
index 4f61c94..d68ed78 100644
--- a/src/views/project/fund/expertFeeApply/index.vue
+++ b/src/views/project/fund/expertFeeApply/index.vue
@@ -1112,7 +1112,8 @@
   getdownloadYX,
   getdownloadBX,
   addorupdateFund,
-  getdetailsByItemId
+  getdetailsByItemId,
+  validateExpertFee
 } from "@/api/project/fund";
 
 import {
@@ -1825,21 +1826,37 @@
             // });
           }
 
-          addorupdateFund(this.form).then(response => {
-            if (response.code === 200) {
-              this.selectDonotor(this.curCase);
-              this.$modal.msgSuccess("涓撳鍔冲姟璐逛繚瀛樻垚鍔燂紒");
-            } else {
-              this.$modal.msgError("涓撳鍔冲姟璐逛繚瀛樺け璐ワ細" + response.msg);
-            }
-          });
+          // 淇濆瓨鍓嶅厛鍋氫笓瀹跺姵鍔¤垂 9 鏉¤垂鐢ㄦ帶鍒舵牎楠岋紙鍚屼竴妗堜緥绱锛�
+          validateExpertFee(this.form).then(valid => {
+            const errors = (valid && valid.errors) || [];
+            const warnings = (valid && valid.warnings) || [];
 
-          //鍏抽棴绐楀彛
-          this.loading = false;
-          this.dialogOpen = false;
-          // this.getfundList();
-          this.getList();
-          this.selectDonotor(this.curCase);
+            // warnings锛堣鍒� 5銆�6锛変粎鎻愮ず锛屼笉闃绘柇淇濆瓨
+            if (warnings.length > 0) {
+              this.$modal.msgWarning(warnings.join("锛�"));
+            }
+
+            // errors 闃绘柇淇濆瓨锛屼繚鐣欑獥鍙h缁忓姙浜哄厛淇
+            if (errors.length > 0) {
+              this.$modal.msgError(errors.join("锛�"));
+              this.loading = false;
+              return;
+            }
+
+            addorupdateFund(this.form).then(response => {
+              if (response.code === 200) {
+                //鍏抽棴绐楀彛
+                this.loading = false;
+                this.dialogOpen = false;
+                this.selectDonotor(this.curCase);
+                this.$modal.msgSuccess("涓撳鍔冲姟璐逛繚瀛樻垚鍔燂紒");
+                this.getList();
+              } else {
+                this.$modal.msgError("涓撳鍔冲姟璐逛繚瀛樺け璐ワ細" + response.msg);
+                this.loading = false;
+              }
+            });
+          });
         }
       });
     },
diff --git a/src/views/project/fund/performancedetails/index.vue b/src/views/project/fund/performancedetails/index.vue
index aabeffc..6cfb93d 100644
--- a/src/views/project/fund/performancedetails/index.vue
+++ b/src/views/project/fund/performancedetails/index.vue
@@ -115,7 +115,7 @@
                 icon="el-icon-download"
                 size="small"
                 @click="Batchentry"
-                >鎵归噺褰曞叆浜哄憳</el-button
+                >鎵归噺瀵煎叆缁╂晥浜哄憳</el-button
               >
             </div>
           </el-col>
@@ -266,7 +266,7 @@
             <el-table-column
               prop="beneficiaryname"
               align="center"
-              label="缁╂晥浜哄憳鎴栧崟浣�"
+              label="缁╂晥浜哄憳/鍗曚綅"
               width="250"
             >
               <template slot-scope="scope">
@@ -283,13 +283,33 @@
               </template>
             </el-table-column>
             <el-table-column
+              prop="isunit"
+              align="center"
+              label="浜哄憳绫诲埆"
+              width="100"
+            >
+              <template slot-scope="scope">
+                <el-tag
+                  :type="scope.row.isunit == 1 ? 'warning' : 'success'"
+                  size="mini"
+                  >{{ scope.row.isunit == 1 ? "鍗曚綅" : "涓汉" }}</el-tag
+                >
+              </template>
+            </el-table-column>
+            <el-table-column
               prop="idcardno"
               align="center"
               label="韬唤璇佸彿"
               width="200"
             >
               <template slot-scope="scope">
-                <el-input v-model="scope.row.idcardno" placeholder="韬唤璇佸彿" />
+                <el-input
+                  v-model="scope.row.idcardno"
+                  :disabled="scope.row.isunit == 1"
+                  :placeholder="
+                    scope.row.isunit == 1 ? '鍗曚綅鏃犻渶濉啓' : '韬唤璇佸彿'
+                  "
+                />
               </template>
             </el-table-column>
 
@@ -470,34 +490,43 @@
       :visible.sync="showSelectionDialog"
       :close-on-click-modal="false"
       :title="'缁╂晥浜哄憳锛堝惈鎵�鍦ㄥ崟浣嶏級璐﹀彿閫夋嫨'"
-      width="500px"
+      width="560px"
       style="text-align: center"
       v-loading="loading"
     >
       <el-form ref="funddetailForm" :model="funddetailForm">
         <el-row>
-          <el-form-item label="璇疯緭鍏ラ�夋嫨锛�" prop="unitno" label-width="120px">
+          <el-form-item label="绛涙煡浜哄憳锛�" prop="userKey" label-width="120px">
             <el-select
-              v-model="funddetailForm.userName"
+              v-model="funddetailForm.userKey"
               filterable
-              remote
-              reserve-keyword
+              clearable
               allow-create
               default-first-option
-              placeholder="璇疯緭鍏ュ鍚嶆垨鍗曚綅鍚嶇О"
-              :remote-method="remoteMethod"
-              :loading="loadingperformance"
+              :filter-method="filterPersonOption"
+              placeholder="杈撳叆 濮撳悕 / 鍗曚綅 / 宸ュ彿 / 韬唤璇佸悗4浣� 绛涙煡锛屼篃鍙洿鎺ヨ緭鍏ュ鍚�"
               style="width: 100%"
             >
               <el-option
                 v-for="item in optionsperformance"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
+                :key="item.id"
+                :label="personOptionLabel(item)"
+                :value="item.id"
               >
+                <span style="float: left">{{ item.username }}</span>
+                <span style="float: right; color: #8492a6; font-size: 13px">
+                  {{
+                    item.isUnitPerson ? "鍗曚綅" : "宸ュ彿 " + (item.userno || "-")
+                  }}{{ item.unitname ? " 路 " + item.unitname : "" }}
+                </span>
               </el-option>
             </el-select>
           </el-form-item>
+        </el-row>
+        <el-row style="text-align: left; padding-left: 120px">
+          <span style="color: #909399; font-size: 12px">
+            鍊欓�変负浜哄憳绫诲瀷鍚�屽弬涓庣哗鏁堛�嶇殑浜哄憳锛涢�変腑鍚庤韩浠借瘉鍙枫�侀摱琛岃处鍙风瓑鑷姩甯﹀嚭锛屽崟浣嶄负鍗曚綅鐨勮涓嶆牎楠岃韩浠借瘉鍙枫��
+          </span>
         </el-row>
       </el-form>
       <span slot="footer" class="dialog-footer">
@@ -798,12 +827,25 @@
           <el-radio-button :label="70">骞村害缁╂晥</el-radio-button>
         </el-radio-group>
       </div>
+      <div style="margin-bottom: 12px; margin-left: 10px;">
+        <el-input
+          v-model="personKeyword"
+          clearable
+          size="small"
+          prefix-icon="el-icon-search"
+          placeholder="杈撳叆 濮撳悕 / 鍗曚綅 / 宸ュ彿 / 韬唤璇佸悗4浣� 绛涙煡"
+          style="width: 330px"
+        />
+        <span style="margin-left: 10px; color: #909399; font-size: 12px">
+          鍏� {{ filteredCityOptions.length }} 浜�
+        </span>
+      </div>
       <div style="max-height: 330px; overflow-y: auto">
         <el-checkbox
           :indeterminate="isIndeterminate"
           v-model="checkAll"
           @change="handleCheckAllChange"
-          >鍏ㄩ��</el-checkbox
+          >鍏ㄩ�夛紙褰撳墠绛涙煡缁撴灉锛�</el-checkbox
         >
         <div style="margin: 15px 0;"></div>
         <el-checkbox-group
@@ -812,10 +854,11 @@
         >
           <el-checkbox
             border
-            v-for="city in cityOptions"
+            v-for="city in filteredCityOptions"
             :label="city"
-            :key="city.userNo"
-            >{{ city.userName }}</el-checkbox
+            :key="city.id"
+            >{{ city.username }}{{ city.isUnitPerson ? "锛堝崟浣嶏級" : ""
+            }}{{ city.unitname ? " 路 " + city.unitname : "" }}</el-checkbox
           >
         </el-checkbox-group>
       </div>
@@ -859,7 +902,6 @@
   listOrganization,
   getOrganization,
   listReportname,
-  listperformance,
   listUser
 } from "@/api/project/organization";
 
@@ -931,7 +973,10 @@
       feeUnitList: [],
       batchdialogVisible: false,
       itemlist: [],
+      //缁╂晥浜哄憳鍊欓�夛紙浜哄憳绫诲瀷鍚�屽弬涓庣哗鏁堛�嶇殑浜哄憳锛屾潵鑷� service_externalperson锛�
       cityOptions: [],
+      //鎵归噺褰曞叆寮规鐨勭瓫鏌ュ叧閿瓧
+      personKeyword: "",
       checkAll: false,
       checkedCities: [],
       Personnelforname: null,
@@ -1064,6 +1109,7 @@
 
       funddetailForm: {
         index: null,
+        userKey: null,
         userName: null,
         beneficiaryname: null,
         beneficiaryno: null,
@@ -1199,7 +1245,16 @@
   },
 
   //鐩戝惉灞炴�� 绫讳技浜巇ata姒傚康
-  computed: {},
+  computed: {
+    //鎵归噺褰曞叆寮规锛氭寜鍏抽敭瀛楋紙濮撳悕/鍗曚綅/宸ュ彿/韬唤璇佸悗4浣嶏級绛涙煡鍚庣殑鍊欓�変汉
+    filteredCityOptions() {
+      const kw = (this.personKeyword || "").trim().toLowerCase();
+      if (!kw) {
+        return this.cityOptions;
+      }
+      return this.cityOptions.filter(item => this.personMatchKeyword(item, kw));
+    }
+  },
   //鐩戞帶data涓殑鏁版嵁鍙樺寲
   watch: {},
   //鏂规硶闆嗗悎
@@ -1625,7 +1680,12 @@
               );
               return;
             }
-            if (tempDetail.idcardno == null) {
+            // 鍗曚綅琛岋紙isunit=1锛変笉闇�瑕佽韩浠借瘉鍙�
+            if (
+              tempDetail.isunit != 1 &&
+              (tempDetail.idcardno == null ||
+                String(tempDetail.idcardno).trim() === "")
+            ) {
               this.$modal.msgWarning(
                 "鏈嶅姟椤圭洰琛ㄤ腑锛岀" +
                   (k + 1).toString() +
@@ -1653,6 +1713,22 @@
                 return;
               }
             }
+          }
+
+          //鏄庣粏閲嶅鏍¢獙锛氬悓涓�浜哄憳/鍗曚綅涓嶅厑璁稿嚭鐜板琛�
+          const detailNameMap = {};
+          for (let k = 0; k < this.rbDetails.length; k++) {
+            const nm = String(this.rbDetails[k].beneficiaryname || "").trim();
+            if (!nm) {
+              continue;
+            }
+            if (detailNameMap[nm]) {
+              this.$modal.msgWarning(
+                "鏈嶅姟椤圭洰琛ㄤ腑锛屼汉鍛樺悕绉帮細" + nm + " 閲嶅锛岃鏍稿鍚庡啀鎻愪氦淇濆瓨锛�"
+              );
+              return;
+            }
+            detailNameMap[nm] = true;
           }
 
           //澶勭悊鏄庣粏
@@ -1866,7 +1942,7 @@
         this.personlist = res.rows;
         for (let j = 0; j < this.personlist.length; j++) {
           //鑾峰彇璐圭敤鎶ラ攢鏈烘瀯鍒楄〃
-          if (this.personlist[j].usertype == "org") {
+          if (this.hasUserType(this.personlist[j].usertype, "org")) {
             this.feeUnitList.push({
               id: this.personlist[j].id,
               reportNo: this.personlist[j].userno,
@@ -1877,7 +1953,7 @@
             });
           }
           //涓撳浜哄憳鍒楄〃
-          else if (res.rows[j].usertype == "expert") {
+          else if (this.hasUserType(res.rows[j].usertype, "expert")) {
             this.expertlist.push({
               expertNo: this.personlist[j].id,
               exportName: this.personlist[j].username
@@ -2153,6 +2229,22 @@
             }
           }
 
+          //鏄庣粏閲嶅鏍¢獙锛氬悓涓�浜哄憳/鍗曚綅涓嶅厑璁稿嚭鐜板琛�
+          const detailNameMap = {};
+          for (let k = 0; k < this.rbDetails.length; k++) {
+            const nm = String(this.rbDetails[k].beneficiaryname || "").trim();
+            if (!nm) {
+              continue;
+            }
+            if (detailNameMap[nm]) {
+              this.$modal.msgWarning(
+                "鏈嶅姟椤圭洰琛ㄤ腑锛屼汉鍛樺悕绉帮細" + nm + " 閲嶅锛岃鏍稿鍚庡啀鎻愪氦淇濆瓨锛�"
+              );
+              return;
+            }
+            detailNameMap[nm] = true;
+          }
+
           //澶勭悊鏄庣粏
           for (let i = 0; i < this.rbDetails.length; i++) {
             let tempDetail = this.rbDetails[i];
@@ -2239,16 +2331,18 @@
         }
       });
     },
-    // 鍏ㄩ��
+    // 鍏ㄩ�夛紙鎸夊綋鍓嶇瓫鏌ョ粨鏋滐級
     handleCheckAllChange(val) {
-      this.checkedCities = val ? this.cityOptions : [];
+      this.checkedCities = val ? this.filteredCityOptions.slice() : [];
       this.isIndeterminate = false;
     },
     handleCheckedCitiesChange(value) {
       let checkedCount = value.length;
-      this.checkAll = checkedCount === this.cityOptions.length;
+      this.checkAll =
+        this.filteredCityOptions.length > 0 &&
+        checkedCount === this.filteredCityOptions.length;
       this.isIndeterminate =
-        checkedCount > 0 && checkedCount < this.cityOptions.length;
+        checkedCount > 0 && checkedCount < this.filteredCityOptions.length;
     },
     // 鎵嬪姩璁$畻
     Manualcalculationfn() {
@@ -2273,18 +2367,107 @@
     },
     // 鎵归噺褰曞叆鐐瑰嚮
     Batchentry() {
-      // ethical
-      this.listperformance();
+      this.personKeyword = "";
+      this.checkedCities = [];
+      this.checkAll = false;
+      this.isIndeterminate = false;
       this.batchdialogVisible = true;
     },
+    /**
+     * 杞藉叆缁╂晥浜哄憳鍊欓�夈��
+     * 鏀归�犲墠鍙栬嚜浜哄憳鍒嗙粍琛紙service_externalperson_group锛実roup_id=1锛夛紱
+     * 2026-09-27 璧锋敼涓恒�屼汉鍛樼被鍨嬶紙UserType锛屽彲澶氶�夛級鍚� 鍙備笌缁╂晥銆嶇殑澶栧洿浜哄憳璐︽埛锛�
+     * 涓嶅啀渚濊禆鍒嗙粍琛ㄣ��
+     */
     listperformance() {
-      listperformance(1).then(res => {
-        this.cityOptions = res.data;
-        this.listperformancea = [];
-        this.listperformancea = this.cityOptions.map(item => {
-          return { value: item.userName, label: item.userName };
-        });
+      listExternalperson({
+        usertype: "performance",
+        pageNum: 1,
+        pageSize: 10000
+      }).then(res => {
+        const rows = res.rows || [];
+        this.cityOptions = rows
+          //鍙繚鐣欏惎鐢ㄨ处鍙凤紙涓庢敼閫犲墠鍒嗙粍琛ㄦ帴鍙g殑 userstatus=1 鍙e緞涓�鑷达級銆�
+          //娉ㄦ剰锛歋erviceExternalperson 瀹炰綋娌℃湁 del_flag 瀛楁锛屾帴鍙d笉杩斿洖璇ュ瓧娈碉紝
+          //涓嶈兘鐢ㄥ畠鍋氳繃婊わ紝鍚﹀垯 undefined == 0 浼氭妸鍏ㄩ儴鍊欓�変汉婊ょ┖銆�
+          .filter(
+            item =>
+              item.userstatus === undefined ||
+              item.userstatus === null ||
+              item.userstatus == 1
+          )
+          .map(item => {
+            return Object.assign({}, item, {
+              isUnitPerson: this.hasUserType(item.usertype, "org")
+            });
+          });
       });
+    },
+    /** 浜哄憳绫诲瀷锛堝鍊硷紝閫楀彿鍒嗛殧锛夋槸鍚﹀寘鍚寚瀹氱被鍨� */
+    hasUserType(usertype, code) {
+      if (!usertype) {
+        return false;
+      }
+      return (
+        String(usertype)
+          .split(",")
+          .map(t => t.trim())
+          .indexOf(code) > -1
+      );
+    },
+    /** 鍏抽敭瀛楀懡涓垽鏂細濮撳悕 / 鍗曚綅 / 宸ュ彿 / 韬唤璇佸悗4浣� */
+    personMatchKeyword(item, kw) {
+      const idcard = String(item.idcardno || "");
+      return (
+        String(item.username || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        String(item.unitname || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        String(item.userno || "")
+          .toLowerCase()
+          .indexOf(kw) > -1 ||
+        (idcard.length >= 4 && idcard.slice(-4).indexOf(kw) > -1)
+      );
+    },
+    /** 璇嗗埆浜哄憳绫诲埆锛氬崟浣嶏紙浜哄憳绫诲瀷鍚� org锛夎繕鏄釜浜� */
+    isUnitPerson(item) {
+      return !!(item && this.hasUserType(item.usertype, "org"));
+    },
+    /** 閫夋嫨妗嗕笅鎷夐」鏂囨锛氬鍚嶏紙鍗曚綅锛� */
+    personOptionLabel(item) {
+      return (
+        (item.username || "") +
+        (item.unitname ? "锛�" + item.unitname + "锛�" : "") +
+        (item.isUnitPerson ? " - 鍗曚綅" : "")
+      );
+    },
+    /** 閫夋嫨妗嗗�欓�夛細绌哄叧閿瓧杩斿洖鍏ㄩ儴锛屽惁鍒欐寜鍏抽敭瀛楃瓫鏌� */
+    filterPersonCandidates(kw) {
+      if (!kw) {
+        return this.cityOptions.slice();
+      }
+      return this.cityOptions.filter(item => this.personMatchKeyword(item, kw));
+    },
+    /** 閫夋嫨妗嗘湰鍦扮瓫鏌ワ紙濮撳悕/鍗曚綅/宸ュ彿/韬唤璇佸悗4浣嶏級 */
+    filterPersonOption(query) {
+      const kw = (query || "").trim().toLowerCase();
+      this.optionsperformance = this.filterPersonCandidates(kw);
+      // 宸查�変腑椤硅淇濈暀鍦ㄤ笅鎷夐噷锛屽惁鍒欏洖鏄句細绌虹櫧
+      const picked = this.getPickedPerson(this.funddetailForm.userKey);
+      if (picked && this.optionsperformance.indexOf(picked) === -1) {
+        this.optionsperformance = [picked].concat(this.optionsperformance);
+      }
+    },
+    /** 鎸夊敮涓�閿紙浜哄憳 ID锛夊彇鍊欓�夛紱鎵嬪伐杈撳叆鐨勫鍚嶈繑鍥� null */
+    getPickedPerson(key) {
+      if (key === null || key === undefined || key === "") {
+        return null;
+      }
+      return (
+        this.cityOptions.find(item => String(item.id) === String(key)) || null
+      );
     },
     // 纭褰曞叆
     BatchentryFn() {
@@ -2292,23 +2475,42 @@
       if (!this.rbDetails[0].applytype) {
         this.rbDetails = [];
       }
+      // 鏄庣粏涓凡鏈夌殑浜哄憳濮撳悕锛岀敤浜庨噸澶嶆彁閱掞紙涓庝鸡鐞嗕笓瀹惰垂椤电殑鍒ら噸鍙e緞涓�鑷达級
+      const existed = {};
+      this.rbDetails.forEach(row => {
+        if (row.beneficiaryname) {
+          existed[String(row.beneficiaryname).trim()] = true;
+        }
+      });
+
+      const duplicated = [];
       this.checkedCities.forEach(item => {
+        const nameKey = String(item.username || "").trim();
+        if (nameKey && existed[nameKey]) {
+          duplicated.push(item.username);
+          return;
+        }
+        if (nameKey) {
+          existed[nameKey] = true;
+        }
+        const isunit = this.isUnitPerson(item);
         let rowData = {
           orderno: null,
           fundid: null,
-          beneficiaryname: item.userName,
-          beneficiaryno: item.usertNo,
+          beneficiaryname: item.username,
+          beneficiaryno: item.userno,
+          isunit: isunit ? 1 : 0,
           unitname: item.unitname,
-          unitno: null,
+          unitno: item.unitno,
           uintuserno: null,
           title: item.title,
           idcardtype: null,
-          idcardno: item.idcrad,
+          idcardno: isunit ? "" : item.idcardno,
           sex: null,
           familyrelations: null,
-          phone: null,
-          depositbank: item.depositBank,
-          bankcardno: item.bankCardNo,
+          phone: item.telephone,
+          depositbank: item.depositbank,
+          bankcardno: item.bankcardno,
           branchbankname: item.branchbankname,
           annexbankcard: null,
           annexregistform: null,
@@ -2351,6 +2553,11 @@
       this.calculateTax();
       this.batchdialogVisible = false;
       this.checkedCities = [];
+      if (duplicated.length) {
+        this.$modal.msgWarning(
+          "浠ヤ笅浜哄憳鍦ㄦ槑缁嗕腑宸插瓨鍦紝宸茶烦杩囬噸澶嶆坊鍔狅細" + duplicated.join("銆�")
+        );
+      }
       console.log(this.rowfeeItemTypes);
     },
     //鏂板涓�琛�
@@ -2361,6 +2568,7 @@
         fundid: null,
         beneficiaryname: null,
         beneficiaryno: null,
+        isunit: 0,
         unitname: null,
         unitno: null,
         uintuserno: null,
@@ -2460,64 +2668,78 @@
         });
       //鍏ㄩ儴鍒犻櫎鍚庢坊鍔犱竴鏉℃柊琛�
     },
-    //涓撳/鍖荤枟鏈烘瀯/璐圭敤鎶ラ攢鏈烘瀯閫夋嫨
+    //缁╂晥浜哄憳/鍗曚綅閫夋嫨锛氭墦寮�鏃堕濉綋鍓嶈宸查�変汉鍛橈紝閬垮厤"鐩存帴纭畾"鎶婂凡鏈夊鍚嶆竻绌�
     ShowDetailDialog(spoce, showType) {
       this.spocewl = spoce;
       this.selectionType = showType;
-      this.selectionType = this.experthear;
-      this.expertfrom = "1";
       this.funddetailForm.index = spoce.$index;
       this.funddetailForm.beneficiaryno = spoce.row.beneficiaryno;
       this.funddetailForm.beneficiaryname = spoce.row.beneficiaryname;
       this.funddetailForm.unitno = spoce.row.unitno;
       this.funddetailForm.unitname = spoce.row.unitname;
-      this.funddetailForm.expertname = "";
-      this.funddetailForm.expertidcardno = "";
-      this.funddetailForm.expertunitno = "";
-      this.funddetailForm.expertunitname = "";
-      this.funddetailForm.experttitle = "";
-      this.funddetailForm.expertdepositbank = "";
-      this.funddetailForm.expertbankcardno = "";
+      //褰撳墠琛屽凡閫変汉鍛樼殑鍥炲~锛氬厛鎸変汉鍛樼紪鍙峰尮閰嶏紝鍖归厤涓嶅埌鍐嶆寜濮撳悕鍖归厤
+      let cur =
+        this.cityOptions.find(
+          item => String(item.userno) === String(spoce.row.beneficiaryno)
+        ) || null;
+      if (!cur && spoce.row.beneficiaryname) {
+        cur =
+          this.cityOptions.find(
+            item => item.username === spoce.row.beneficiaryname
+          ) || null;
+      }
+      this.funddetailForm.userKey = cur
+        ? cur.id
+        : spoce.row.beneficiaryname || null;
+      this.funddetailForm.userName = spoce.row.beneficiaryname || null;
+      //鎵撳紑鏃跺睍绀哄叏閲忓�欓�夛紝渚夸簬鐩存帴娴忚绛涙煡
+      this.optionsperformance = this.cityOptions.slice();
       this.showSelectionDialog = true;
     },
 
-    //涓撳/鍖荤枟鏈烘瀯/璐圭敤鎶ラ攢鏈烘瀯閫夋嫨
+    /**
+     * 纭畾閫夋嫨锛氭寜鍞竴閿紙浜哄憳 ID锛夊尮閰嶅�欓�夛紝
+     * 鑷姩甯﹀嚭韬唤璇佸彿銆侀摱琛岃处鍙枫�佸紑鎴烽摱琛屻�佺數璇濄�佽亴绉般�佷汉鍛樼紪鍙枫�佸崟浣嶏紱
+     * 鍗曚綅锛堜汉鍛樼被鍨嬪惈 org锛変笉鍐欒韩浠借瘉鍙凤紱鎵嬪伐杈撳叆鐨勫鍚嶄笉鍋氬甫鍑恒��
+     */
     ConfirmDetailDialog() {
-      let tempIndex = this.funddetailForm.index;
-      let tempExpertName = this.funddetailForm.userName;
-      let singleDetail = this.rbDetails[tempIndex];
+      const tempIndex = this.funddetailForm.index;
+      const singleDetail = this.rbDetails[tempIndex];
+      const key = this.funddetailForm.userKey;
 
-      //浠庝笓瀹跺垪琛ㄨ幏鍙栦俊鎭�
-      this.cityOptions.map(res => {
-        if (tempExpertName == res.userName) {
-          singleDetail.beneficiaryno = res.userno;
-          singleDetail.bankcardno = res.bankCardNo;
-          singleDetail.branchbankname = res.branchbankname;
-          singleDetail.depositbank = res.depositBank;
-          singleDetail.idcardno = res.idcardNo;
-          singleDetail.phone = res.telephone;
-          singleDetail.title = res.title;
-          singleDetail.unitname = res.unitname;
-          singleDetail.unitno = parseInt(res.unitno);
-        }
-      });
-      singleDetail.beneficiaryname = tempExpertName;
-      this.rbDetails[tempIndex] = singleDetail;
-      this.showSelectionDialog = false;
-    },
-    remoteMethod(query) {
-      console.log(this.listperformancea);
-      if (query !== "") {
-        this.loadingperformance = true;
-        setTimeout(() => {
-          this.loadingperformance = false;
-          this.optionsperformance = this.listperformancea.filter(item => {
-            return item.label.toLowerCase().indexOf(query.toLowerCase()) > -1;
-          });
-        }, 200);
-      } else {
-        this.optionsperformance = [];
+      if (key === null || key === undefined || key === "") {
+        this.$modal.msgWarning("璇峰厛绛涙煡骞堕�夋嫨缁╂晥浜哄憳锛屾垨鐩存帴杈撳叆浜哄憳濮撳悕锛�");
+        return;
       }
+
+      const person = this.getPickedPerson(key);
+      if (person) {
+        // 鍛戒腑浜哄憳搴擄細鑷姩甯﹀嚭鍏ㄩ儴淇℃伅
+        const isunit = this.isUnitPerson(person);
+        singleDetail.beneficiaryname = person.username;
+        singleDetail.beneficiaryno = person.userno;
+        singleDetail.isunit = isunit ? 1 : 0;
+        singleDetail.idcardno = isunit ? "" : person.idcardno;
+        singleDetail.bankcardno = person.bankcardno;
+        singleDetail.branchbankname = person.branchbankname;
+        singleDetail.depositbank = person.depositbank;
+        singleDetail.phone = person.telephone;
+        singleDetail.title = person.title;
+        singleDetail.unitname = person.unitname;
+        singleDetail.unitno = person.unitno;
+      } else {
+        // 鎵嬪伐杈撳叆鐨勪汉鍛橈細鍙啓濮撳悕锛岃韩浠借瘉鍙�/閾惰璐﹀彿鐢辩粡鍔炰汉濉啓
+        singleDetail.beneficiaryname = String(key);
+        singleDetail.isunit = 0;
+        this.$modal.msgWarning(
+          "浜哄憳搴撲腑鏈壘鍒般��" +
+            key +
+            "銆嶏紝宸叉寜鎵嬪伐褰曞叆澶勭悊锛岃鑷濉啓韬唤璇佸彿銆侀摱琛岃处鍙风瓑淇℃伅銆�"
+        );
+      }
+
+      this.$set(this.rbDetails, tempIndex, singleDetail);
+      this.showSelectionDialog = false;
     },
     handleUploadError() {},
     remove(file, fileList) {
diff --git a/src/views/project/fundcheck/expertFeeCheck/index.vue b/src/views/project/fundcheck/expertFeeCheck/index.vue
index a25bc43..3382991 100644
--- a/src/views/project/fundcheck/expertFeeCheck/index.vue
+++ b/src/views/project/fundcheck/expertFeeCheck/index.vue
@@ -421,7 +421,8 @@
   checkfund,
   listbypower,
   addFundSharedInfo,
-  TotalcalculationFn
+  TotalcalculationFn,
+  validateExpertFee
 } from "@/api/project/fund";
 import {
   onelistFunds,
@@ -738,6 +739,27 @@
         this.$modal.msgError("璇烽�夋嫨瀹℃牳缁撹!");
         return;
       }
+
+      // 瀹℃牳鈥滈�氳繃鈥濆墠锛氬厛鍋氫笓瀹跺姵鍔¤垂 9 鏉¤垂鐢ㄦ帶鍒舵牎楠岋紙涓庡悗绔嫤鎴悓鍙e緞锛�
+      if (checkfundobj.flowconclusion == 1) {
+        validateExpertFee({ id: this.form.id }).then(valid => {
+          const errors = (valid && valid.errors) || [];
+          const warnings = (valid && valid.warnings) || [];
+          if (warnings.length > 0) {
+            this.$modal.msgWarning(warnings.join("锛�"));
+          }
+          if (errors.length > 0) {
+            this.$modal.msgError("涓嶈兘瀹℃牳閫氳繃锛�" + errors.join("锛�"));
+            return;
+          }
+          this.doCheckfund(checkfundobj);
+        });
+        return;
+      }
+      // 涓嶉�氳繃锛氭棤闇�鏍¢獙闄愰
+      this.doCheckfund(checkfundobj);
+    },
+    doCheckfund(checkfundobj) {
       checkfund(checkfundobj).then(res => {
         if (res.code == 200) {
           this.reset();
@@ -745,11 +767,8 @@
           this.getlistbypower();
           this.dialogOpen = false;
         } else {
-          if (res.msg) {
-            this.$modal.msgError("鎿嶄綔澶辫");
-          } else {
-            this.$modal.msgError(res.msg);
-          }
+          // 鍚庣杩斿洖鐨勫叿浣撳師鍥狅紙濡傝秴闄愰锛変紭鍏堝睍绀�
+          this.$modal.msgError(res.msg || "鎿嶄綔澶辫");
         }
       });
     },
diff --git a/src/views/project/travelexpenseapply/travelexpensedetail/index.vue b/src/views/project/travelexpenseapply/travelexpensedetail/index.vue
index 410ebbc..bd4b966 100644
--- a/src/views/project/travelexpenseapply/travelexpensedetail/index.vue
+++ b/src/views/project/travelexpenseapply/travelexpensedetail/index.vue
@@ -2538,7 +2538,7 @@
             .map(item => ({ url: item, name: item }))
           : [];
         //瀹℃牳鐘舵��
-        this.form.recordstatus = response.data.recordstatus + "";
+        this.form.recordstatus = this.toStatusText(response.data.recordstatus, "-1");
         let ids = response.data.id;
         let listFundflowparams = {
           fundid: ids,
@@ -2549,14 +2549,19 @@
         });
 
         //鎶ラ攢鏄庣粏
-        getReimbursementdetaillist(ids).then(res => {
-          this.rbDetails = res.data;
-          //鍚堣璐圭敤
-          // if (this.rbDetails.length > 0) this.sumTotalFee();
-          for (let i = 0; i < this.rbDetails.length; i++) {
-            this.sumRowFee(this.rbDetails[i]);
-          }
-        });
+        getReimbursementdetaillist(ids)
+          .then(res => {
+            this.rbDetails = this.normalizeDetailList(res);
+            //鍚堣璐圭敤
+            // if (this.rbDetails.length > 0) this.sumTotalFee();
+            for (let i = 0; i < this.rbDetails.length; i++) {
+              this.sumRowFee(this.rbDetails[i]);
+            }
+          })
+          .catch(err => {
+            this.rbDetails = [];
+            console.error("鑾峰彇鎶ラ攢鏄庣粏澶辫触,id=" + ids, err);
+          });
 
         //浠樻淇℃伅
         this.queryParamsPayee.rbid = ids;
@@ -2592,7 +2597,8 @@
       getReimbursement(id).then(response => {
         this.form = response.data;
         console.log(this.form.checkstatus, "checkstatus");
-        this.form.checkstatus = this.form.checkstatus.toString();
+        // checkstatus 鍦ㄥ簱涓彲涓虹┖锛堥瀹$姸鎬佸皻鏈骇鐢熸椂锛夛紝鐩存帴 toString 浼氭姏 TypeError 涓柇鍚庣画鍙栨暟
+        this.form.checkstatus = this.toStatusText(this.form.checkstatus, "-1");
 
         //绁ㄦ嵁
         this.fileListto = this.form.annexfiles
@@ -2619,16 +2625,22 @@
         });
 
         //鎶ラ攢鏄庣粏
-        getReimbursementdetaillist(ids).then(res => {
-          this.rbDetails = res.data;
-          console.log(this.rbDetails);
+        getReimbursementdetaillist(ids)
+          .then(res => {
+            this.rbDetails = this.normalizeDetailList(res);
+            console.log("鎶ラ攢鏄庣粏琛屾暟锛�", this.rbDetails.length, this.rbDetails);
 
-          //鍚堣璐圭敤
-          // if (this.rbDetails.length > 0) this.sumTotalFee();
-          for (let i = 0; i < this.rbDetails.length; i++) {
-            this.sumRowFee(this.rbDetails[i]);
-          }
-        });
+            //鍚堣璐圭敤
+            // if (this.rbDetails.length > 0) this.sumTotalFee();
+            for (let i = 0; i < this.rbDetails.length; i++) {
+              this.sumRowFee(this.rbDetails[i]);
+            }
+          })
+          .catch(err => {
+            // 鍙栨暟澶辫触鏃朵笉鍐嶉潤榛橈細缃┖骞舵墦鍑哄師鍥狅紝閬垮厤鈥滄帴鍙f湁鏁版嵁浣嗛〉闈㈢┖鐧解�濇棤浠庢帓鏌�
+            this.rbDetails = [];
+            console.error("鑾峰彇鎶ラ攢鏄庣粏澶辫触,id=" + ids, err);
+          });
 
         //浠樻淇℃伅
         this.queryParamsPayee.rbid = ids;
@@ -3251,6 +3263,45 @@
         });
     },
 
+    /**
+     * 鐘舵�佺被瀛楁杞瓧绗︿覆锛堟帴鍙e彲鑳借繑鍥� null锛夈��
+     *
+     * 鑳屾櫙锛歝heckstatus銆乺ecordstatus 绛夊湪搴撲腑鍙┖锛屾棭鏈熺洿鎺ヨ皟鐢� .toString()
+     * 浼氭姏 TypeError 骞朵腑鏂叾鍚庣殑鍙栨暟閫昏緫锛岃〃鐜颁负鈥滄帴鍙e凡鏈夋暟鎹絾鏄庣粏鍖虹┖鐧解�濄��
+     *
+     * @param {*} value 鍘熷鐘舵�佸��
+     * @param {string} fallback 涓虹┖鏃剁殑鍏滃簳鍊�
+     * @returns {string}
+     */
+    toStatusText(value, fallback) {
+      if (value === null || value === undefined || value === "") {
+        return fallback;
+      }
+      return String(value);
+    },
+
+    /**
+     * 缁熶竴浠庢槑缁嗘帴鍙e搷搴斾腑鍙栧嚭鏁扮粍銆�
+     *
+     * 姝e父涓� AjaxResult 鐨� data 鏁扮粍锛涜嫢鍚庣鏀逛负鍒嗛〉缁撴瀯锛坱otal + rows锛夛紝
+     * res.data 灏嗕笉鏄暟缁勶紝鐩存帴缁戝畾鍒� el-table 浼氬鑷粹�滄湁鏁版嵁浣嗕笉鏄剧ず鈥濄��
+     *
+     * @param {Object} res 鎺ュ彛鍘熷鍝嶅簲
+     * @returns {Array} 鏄庣粏鏁扮粍锛堝紓甯告椂涓虹┖鏁扮粍锛屼笉浼氳琛ㄦ牸鎷垮埌闈炴暟缁勶級
+     */
+    normalizeDetailList(res) {
+      if (!res) {
+        return [];
+      }
+      if (Array.isArray(res.data)) {
+        return res.data;
+      }
+      if (Array.isArray(res.rows)) {
+        return res.rows;
+      }
+      return [];
+    },
+
     //璁$畻涓�琛屽悎璁�
     //璁$畻褰撳墠琛屾姤閿�鍐呭璐圭敤鍚堣锛堥噾棰濅竴寰嬭蛋绮剧‘杩愮畻锛�
     sumRowFee(row) {
diff --git a/vue.config.js b/vue.config.js
index d5c694b..1c1ae17 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -34,7 +34,7 @@
       // detail: https://cli.vuejs.org/config/#devserver-proxy
       [process.env.VUE_APP_BASE_API]: {
         target:`http://localhost:8080`,
-        // target:`http://192.168.100.10:8081`,
+        // target:`http://192.168.100.110:8080`,
         // target:`http://192.168.100.137:8080`,
         // target: `https://slb.hospitalstar.com:9093`,
         changeOrigin: true,

--
Gitblit v1.9.3