From 6164c340e703d4a52227a2b6df5b22bdad112245 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期日, 11 十月 2026 21:21:01 +0800
Subject: [PATCH] fix: 修复 1.导入提示修改

---
 src/utils/index.ts                                      |    1 
 src/views/system/user/modules/import-form.vue           |   22 +++-
 src/views/crm/customer/modules/import-form.vue          |   22 +++-
 src/utils/import-result.ts                              |   90 ++++++++++++++++++
 src/views/system/post/modules/import-form.vue           |   22 +++-
 src/api/system/post/index.ts                            |   18 ++
 src/views/hrm/attendance/record/modules/import-form.vue |    3 
 src/api/crm/customer/index.ts                           |   12 ++
 src/views/mes/md/item/modules/import-form.vue           |   33 +++---
 src/api/system/user/index.ts                            |   18 ++
 src/views/mes/dv/machinery/modules/import-form.vue      |   24 +++-
 11 files changed, 212 insertions(+), 53 deletions(-)

diff --git a/src/api/crm/customer/index.ts b/src/api/crm/customer/index.ts
index 4c17fde..a8a03ae 100644
--- a/src/api/crm/customer/index.ts
+++ b/src/api/crm/customer/index.ts
@@ -44,6 +44,13 @@
     file: File;
     updateSupport: boolean;
   }
+
+  /** 瀹㈡埛瀵煎叆缁撴灉 */
+  export interface CustomerImportRespVO {
+    createCustomerNames?: string[]; // 鏂板鎴愬姛鐨勫鎴峰悕
+    updateCustomerNames?: string[]; // 鏇存柊鎴愬姛鐨勫鎴峰悕
+    failureCustomerNames?: Record<string, string>; // 瀵煎叆澶辫触鐨勫鎴峰悕鍙婂師鍥�
+  }
 }
 
 /** 鏌ヨ瀹㈡埛鍒楄〃 */
@@ -88,7 +95,10 @@
 
 /** 瀵煎叆瀹㈡埛 */
 export function importCustomer(data: CrmCustomerApi.CustomerImportReqVO) {
-  return requestClient.upload('/crm/customer/import', data);
+  return requestClient.upload<CrmCustomerApi.CustomerImportRespVO>(
+    '/crm/customer/import',
+    data,
+  );
 }
 
 /** 鑾峰彇瀹㈡埛绮剧畝淇℃伅鍒楄〃 */
diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts
index 3032a56..ca7c381 100644
--- a/src/api/system/post/index.ts
+++ b/src/api/system/post/index.ts
@@ -13,6 +13,13 @@
     remark: string;
     createTime?: Date;
   }
+
+  /** 宀椾綅瀵煎叆缁撴灉 */
+  export interface PostImportRespVO {
+    createPostNames?: string[]; // 鏂板鎴愬姛鐨勫矖浣嶅悕
+    updatePostNames?: string[]; // 鏇存柊鎴愬姛鐨勫矖浣嶅悕
+    failurePostNames?: Record<string, string>; // 瀵煎叆澶辫触鐨勫矖浣嶅悕鍙婂師鍥�
+  }
 }
 
 /** 鏌ヨ宀椾綅鍒楄〃 */
@@ -69,8 +76,11 @@
 
 /** 瀵煎叆宀椾綅 */
 export function importPost(file: File, updateSupport: boolean) {
-  return requestClient.upload('/system/post/import', {
-    file,
-    updateSupport,
-  });
+  return requestClient.upload<SystemPostApi.PostImportRespVO>(
+    '/system/post/import',
+    {
+      file,
+      updateSupport,
+    },
+  );
 }
diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts
index 208d4b9..7491b84 100644
--- a/src/api/system/user/index.ts
+++ b/src/api/system/user/index.ts
@@ -26,6 +26,13 @@
   export interface UserSimple extends User {
     id: number;
   }
+
+  /** 鐢ㄦ埛瀵煎叆缁撴灉 */
+  export interface UserImportRespVO {
+    createUsernames?: string[]; // 鏂板鎴愬姛鐨勭敤鎴峰悕
+    updateUsernames?: string[]; // 鏇存柊鎴愬姛鐨勭敤鎴峰悕
+    failureUsernames?: Record<string, string>; // 瀵煎叆澶辫触鐨勭敤鎴峰悕鍙婂師鍥�
+  }
 }
 
 /** 鏌ヨ鐢ㄦ埛绠$悊鍒楄〃 */
@@ -80,10 +87,13 @@
 
 /** 瀵煎叆鐢ㄦ埛 */
 export function importUser(file: File, updateSupport: boolean) {
-  return requestClient.upload('/system/user/import', {
-    file,
-    updateSupport,
-  });
+  return requestClient.upload<SystemUserApi.UserImportRespVO>(
+    '/system/user/import',
+    {
+      file,
+      updateSupport,
+    },
+  );
 }
 
 /** 鐢ㄦ埛瀵嗙爜閲嶇疆 */
diff --git a/src/utils/import-result.ts b/src/utils/import-result.ts
new file mode 100644
index 0000000..ca78840
--- /dev/null
+++ b/src/utils/import-result.ts
@@ -0,0 +1,90 @@
+import type { VNodeChild } from 'vue';
+
+import { h } from 'vue';
+
+import { message, notification } from 'ant-design-vue';
+
+export interface ImportResultNotifyOptions {
+  /** 涓氬姟涓讳綋锛岀敤浜庢嫾鏍囬涓庡缓璁紝濡傘�岃澶囥�嶃�屽鎴枫�� */
+  subject: string;
+  /** 鏂板鎴愬姛鐨勬潯鏁� */
+  createCount?: number;
+  /** 鏇存柊鎴愬姛鐨勬潯鏁� */
+  updateCount?: number;
+  /** 澶辫触鏄庣粏锛歬ey 涓虹紪鐮�/鍚嶇О锛寁alue 涓哄悗绔け璐ュ師鍥� */
+  failures?: null | Record<string, string>;
+  /** 銆屼笉瀛樺湪銆嶇被澶辫触鐨勮惤鐐规彁绀猴紝濡傘�屻�愯澶囩被鍨嬨�戙�愯溅闂淬�戙�愬伐浣滅珯銆戜腑鐨勫搴旂紪鐮併�� */
+  masterDataHint?: string;
+}
+
+/**
+ * 缁熶竴灞曠ず Excel 瀵煎叆缁撴灉銆�
+ *
+ * 鍙鍚庣杩斿洖浜嗗け璐ユ槑缁嗭紝灏辩粷涓嶈兘鍐嶆彁绀恒�屾搷浣滄垚鍔熴�嶁�斺�旀敼涓哄父椹婚�氱煡閫愯鍒楀嚭澶辫触鍘熷洜锛�
+ * 骞舵寜澶辫触鍘熷洜缁欏嚭涓嬩竴姝ュ姩浣滐紱鍏ㄩ儴鎴愬姛鏃舵墠鎻愮ず鎴愬姛銆�
+ *
+ * @returns 瀹為檯鍐欏叆鐨勬潯鏁帮紙鏂板 + 鏇存柊锛夛紝渚涜皟鐢ㄦ柟鍐冲畾鏄惁闇�瑕佸埛鏂板垪琛�
+ */
+export function notifyImportResult(
+  options: ImportResultNotifyOptions,
+): number {
+  const {
+    subject,
+    createCount = 0,
+    updateCount = 0,
+    failures,
+    masterDataHint,
+  } = options;
+  const failureEntries = Object.entries(failures ?? {});
+  const importedCount = createCount + updateCount;
+
+  if (failureEntries.length === 0) {
+    message.success(`瀵煎叆鎴愬姛锛氭柊澧� ${createCount} 鏉★紝鏇存柊 ${updateCount} 鏉);
+    return importedCount;
+  }
+
+  const nodes: VNodeChild[] = [
+    h(
+      'div',
+      `鏂板鎴愬姛 ${createCount} 鏉★紝鏇存柊鎴愬姛 ${updateCount} 鏉★紝澶辫触 ${failureEntries.length} 鏉★細`,
+    ),
+    ...failureEntries.map(([name, reason]) => h('div', `${name}锛�${reason}`)),
+    ...buildFailureHints(failureEntries.map(([, reason]) => reason), {
+      subject,
+      masterDataHint,
+    }).map((hint) => h('div', { class: 'mt-2 text-red-500' }, hint)),
+  ];
+
+  const notify = importedCount === 0 ? notification.error : notification.warning;
+  notify({
+    message:
+      importedCount === 0
+        ? `${subject}瀵煎叆澶辫触锛�${failureEntries.length} 琛屽叏閮ㄦ湭瀵煎叆`
+        : `瀵煎叆瀹屾垚锛岄儴鍒�${subject}瀵煎叆澶辫触锛堟垚鍔� ${importedCount} 鏉� / 澶辫触 ${failureEntries.length} 鏉★級`,
+    description: () => h('div', nodes),
+    duration: null,
+  });
+  return importedCount;
+}
+
+/** 鎸夊け璐ュ師鍥犲綊绾充笅涓�姝ュ姩浣滐紝閬垮厤鐢ㄦ埛鍙湅鍒般�屽け璐ャ�嶅嵈涓嶇煡閬撴敼鍝噷 */
+function buildFailureHints(
+  reasons: string[],
+  { subject, masterDataHint }: Pick<ImportResultNotifyOptions, 'masterDataHint' | 'subject'>,
+): string[] {
+  const hints = new Set<string>();
+  for (const reason of reasons) {
+    if (reason.includes('涓嶅瓨鍦�')) {
+      hints.add(
+        `鎻愮ず銆屼笉瀛樺湪銆嶇殑锛氳鍏堢淮鎶ゅソ${masterDataHint ?? '瀵瑰簲涓绘暟鎹�'}锛屾垨鎶� Excel 涓殑鍊兼敼鎴愬凡瀛樺湪鐨勶紝鍐嶉噸鏂板鍏ャ�俙,
+      );
+    } else if (reason.includes('宸茬粡瀛樺湪') || reason.includes('宸插瓨鍦�')) {
+      hints.add(
+        `鎻愮ず銆屽凡瀛樺湪銆嶇殑锛氳淇敼 Excel 涓殑${subject}鍚嶇О鎴栫紪鐮侊紝鎴栧嬀閫夈�屾敮鎸佹洿鏂般�嶅悗閲嶆柊瀵煎叆浠ヨ鐩栧凡鏈夋暟鎹�俙,
+      );
+    } else if (reason.includes('涓嶈兘涓虹┖') || reason.includes('涓虹┖')) {
+      hints.add('鎻愮ず銆屼笉鑳戒负绌恒�嶇殑锛氳琛ラ綈 Excel 涓搴斿垪鐨勫唴瀹瑰悗閲嶆柊瀵煎叆銆�');
+    }
+  }
+  return [...hints];
+}
diff --git a/src/utils/index.ts b/src/utils/index.ts
index cdedaf7..f1778e7 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,5 +1,6 @@
 import type { Recordable } from '@vben/types';
 
+export * from './import-result';
 export * from './rangePickerProps';
 export * from './routerHelper';
 
diff --git a/src/views/crm/customer/modules/import-form.vue b/src/views/crm/customer/modules/import-form.vue
index a943b4b..e23dd06 100644
--- a/src/views/crm/customer/modules/import-form.vue
+++ b/src/views/crm/customer/modules/import-form.vue
@@ -4,11 +4,11 @@
 import { useVbenModal } from '@vben/common-ui';
 import { downloadFileFromBlobPart } from '@vben/utils';
 
-import { Button, message, Upload } from 'ant-design-vue';
+import { Button, Upload } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { importCustomer, importCustomerTemplate } from '#/api/crm/customer';
-import { $t } from '#/locales';
+import { notifyImportResult } from '#/utils';
 
 import { useImportFormSchema } from '../data';
 
@@ -34,15 +34,25 @@
     // 鎻愪氦琛ㄥ崟
     const data = await formApi.getValues();
     try {
-      await importCustomer({
+      const importData = await importCustomer({
         ownerUserId: data.ownerUserId,
         file: data.file,
         updateSupport: data.updateSupport,
       });
-      // 鍏抽棴骞舵彁绀�
+      const createCount = importData.createCustomerNames?.length || 0;
+      const updateCount = importData.updateCustomerNames?.length || 0;
+
+      // 鍏抽棴骞舵寜瀵煎叆缁撴灉鎻愮ず锛氫粎鍦ㄧ‘鏈夋暟鎹啓鍏ユ椂閫氱煡鍒楄〃鍒锋柊
       await modalApi.close();
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
+      if (createCount + updateCount > 0) {
+        emit('success');
+      }
+      notifyImportResult({
+        subject: '瀹㈡埛',
+        createCount,
+        updateCount,
+        failures: importData.failureCustomerNames,
+      });
     } finally {
       modalApi.unlock();
     }
diff --git a/src/views/hrm/attendance/record/modules/import-form.vue b/src/views/hrm/attendance/record/modules/import-form.vue
index ccc0e50..e20e2cb 100644
--- a/src/views/hrm/attendance/record/modules/import-form.vue
+++ b/src/views/hrm/attendance/record/modules/import-form.vue
@@ -31,7 +31,8 @@
       emit('success');
       // 鍚庣杩斿洖瀵煎叆缁撴灉锛堝惈澶辫触鍘熷洜锛屼緥濡傗�滀互涓嬪憳宸ヤ笉瀛樺湪...锛涢渶琛ュ厖鎵嬫満鍙�...鈥濓級
       if (res && res.length > 0) {
-        message[res.includes('鏈�') || res.includes('涓嶅畬鏁�') ? 'warning' : 'success'](res);
+        // 澶辫触鏃跺悗绔細鎷间笂銆屾湭鑳藉鍏ワ細銆嶆槑缁嗘锛岀敤瀹冨垽瀹氾紝閬垮厤鎴愬姛鏂囨閲屽嚭鐜般�屾湭銆嶅氨璇姤璀﹀憡
+        message[res.includes('鏈兘瀵煎叆') ? 'warning' : 'success'](res);
       } else {
         message.success('瀵煎叆鎴愬姛');
       }
diff --git a/src/views/mes/dv/machinery/modules/import-form.vue b/src/views/mes/dv/machinery/modules/import-form.vue
index b4cd717..eb6a01d 100644
--- a/src/views/mes/dv/machinery/modules/import-form.vue
+++ b/src/views/mes/dv/machinery/modules/import-form.vue
@@ -6,7 +6,7 @@
 import { useVbenModal } from '@vben/common-ui';
 import { downloadFileFromBlobPart } from '@vben/utils';
 
-import { Button, message, Upload } from 'ant-design-vue';
+import { Button, Upload } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import {
@@ -14,6 +14,7 @@
   importMachineryTemplate,
 } from '#/api/mes/dv/machinery';
 import { $t } from '#/locales';
+import { notifyImportResult } from '#/utils';
 
 import { useImportFormSchema } from '../data';
 
@@ -44,14 +45,21 @@
     try {
       const result = await importMachinery(data.file, data.updateSupport);
       const importData = result as MesDvMachineryApi.MachineryImportRespVO;
-      let text = `涓婁紶鎴愬姛鏁伴噺锛�${importData.createCodes?.length || 0}锛沗;
-      text += `鏇存柊鎴愬姛鏁伴噺锛�${importData.updateCodes?.length || 0}锛沗;
-      text += `鏇存柊澶辫触鏁伴噺锛�${Object.keys(importData.failureCodes || {}).length}锛沗;
-      message.info(text);
-      // 鍏抽棴骞舵彁绀�
+      const createCount = importData.createCodes?.length || 0;
+      const updateCount = importData.updateCodes?.length || 0;
+
+      // 鍏抽棴骞舵寜瀵煎叆缁撴灉鎻愮ず锛氫粎鍦ㄧ‘鏈夋暟鎹啓鍏ユ椂閫氱煡鍒楄〃鍒锋柊
       await modalApi.close();
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
+      if (createCount + updateCount > 0) {
+        emit('success');
+      }
+      notifyImportResult({
+        subject: '璁惧',
+        createCount,
+        updateCount,
+        failures: importData.failureCodes,
+        masterDataHint: '銆愯澶囩被鍨嬨�戙�愯溅闂淬�戙�愬伐浣滅珯銆戜腑鐨勫搴旂紪鐮�',
+      });
     } finally {
       modalApi.unlock();
     }
diff --git a/src/views/mes/md/item/modules/import-form.vue b/src/views/mes/md/item/modules/import-form.vue
index ff4718b..da0b0fc 100644
--- a/src/views/mes/md/item/modules/import-form.vue
+++ b/src/views/mes/md/item/modules/import-form.vue
@@ -6,11 +6,12 @@
 import { useVbenModal } from '@vben/common-ui';
 import { downloadFileFromBlobPart } from '@vben/utils';
 
-import { Button, message, Upload } from 'ant-design-vue';
+import { Button, Upload } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { importItem, importItemTemplate } from '#/api/mes/md/item';
 import { $t } from '#/locales';
+import { notifyImportResult } from '#/utils';
 
 import { useImportFormSchema } from '../data';
 
@@ -41,23 +42,21 @@
     try {
       const result = await importItem(data.file, data.updateSupport);
       const importData = result as MesMdItemApi.ItemImportRespVO;
-      let text = `涓婁紶鎴愬姛鏁伴噺锛�${importData.createCodes?.length || 0};`;
-      for (const code of importData.createCodes || []) {
-        text += `< ${code} >`;
-      }
-      text += `鏇存柊鎴愬姛鏁伴噺锛�${importData.updateCodes?.length || 0};`;
-      for (const code of importData.updateCodes || []) {
-        text += `< ${code} >`;
-      }
-      text += `鏇存柊澶辫触鏁伴噺锛�${Object.keys(importData.failureCodes || {}).length};`;
-      for (const code in importData.failureCodes || {}) {
-        text += `< ${code}: ${importData.failureCodes?.[code]} >`;
-      }
-      message.info(text);
-      // 鍏抽棴骞舵彁绀�
+      const createCount = importData.createCodes?.length || 0;
+      const updateCount = importData.updateCodes?.length || 0;
+
+      // 鍏抽棴骞舵寜瀵煎叆缁撴灉鎻愮ず锛氫粎鍦ㄧ‘鏈夋暟鎹啓鍏ユ椂閫氱煡鍒楄〃鍒锋柊
       await modalApi.close();
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
+      if (createCount + updateCount > 0) {
+        emit('success');
+      }
+      notifyImportResult({
+        subject: '鐗╂枡',
+        createCount,
+        updateCount,
+        failures: importData.failureCodes,
+        masterDataHint: '銆愮墿鏂欏垎绫汇�戜腑鐨勫搴旂紪鐮�',
+      });
     } finally {
       modalApi.unlock();
     }
diff --git a/src/views/system/post/modules/import-form.vue b/src/views/system/post/modules/import-form.vue
index ba6b9ca..5a465a6 100644
--- a/src/views/system/post/modules/import-form.vue
+++ b/src/views/system/post/modules/import-form.vue
@@ -4,11 +4,11 @@
 import { useVbenModal } from '@vben/common-ui';
 import { downloadFileFromBlobPart } from '@vben/utils';
 
-import { Button, message, Upload } from 'ant-design-vue';
+import { Button, Upload } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { importPost, importPostTemplate } from '#/api/system/post';
-import { $t } from '#/locales';
+import { notifyImportResult } from '#/utils';
 
 import { useImportFormSchema } from '../data';
 
@@ -34,11 +34,21 @@
     // 鎻愪氦琛ㄥ崟
     const data = await formApi.getValues();
     try {
-      await importPost(data.file, data.updateSupport);
-      // 鍏抽棴骞舵彁绀�
+      const importData = await importPost(data.file, data.updateSupport);
+      const createCount = importData.createPostNames?.length || 0;
+      const updateCount = importData.updatePostNames?.length || 0;
+
+      // 鍏抽棴骞舵寜瀵煎叆缁撴灉鎻愮ず锛氫粎鍦ㄧ‘鏈夋暟鎹啓鍏ユ椂閫氱煡鍒楄〃鍒锋柊
       await modalApi.close();
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
+      if (createCount + updateCount > 0) {
+        emit('success');
+      }
+      notifyImportResult({
+        subject: '宀椾綅',
+        createCount,
+        updateCount,
+        failures: importData.failurePostNames,
+      });
     } finally {
       modalApi.unlock();
     }
diff --git a/src/views/system/user/modules/import-form.vue b/src/views/system/user/modules/import-form.vue
index f3fad2d..5585c26 100644
--- a/src/views/system/user/modules/import-form.vue
+++ b/src/views/system/user/modules/import-form.vue
@@ -4,11 +4,11 @@
 import { useVbenModal } from '@vben/common-ui';
 import { downloadFileFromBlobPart } from '@vben/utils';
 
-import { Button, message, Upload } from 'ant-design-vue';
+import { Button, Upload } from 'ant-design-vue';
 
 import { useVbenForm } from '#/adapter/form';
 import { importUser, importUserTemplate } from '#/api/system/user';
-import { $t } from '#/locales';
+import { notifyImportResult } from '#/utils';
 
 import { useImportFormSchema } from '../data';
 
@@ -34,11 +34,21 @@
     // 鎻愪氦琛ㄥ崟
     const data = await formApi.getValues();
     try {
-      await importUser(data.file, data.updateSupport);
-      // 鍏抽棴骞舵彁绀�
+      const importData = await importUser(data.file, data.updateSupport);
+      const createCount = importData.createUsernames?.length || 0;
+      const updateCount = importData.updateUsernames?.length || 0;
+
+      // 鍏抽棴骞舵寜瀵煎叆缁撴灉鎻愮ず锛氫粎鍦ㄧ‘鏈夋暟鎹啓鍏ユ椂閫氱煡鍒楄〃鍒锋柊
       await modalApi.close();
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
+      if (createCount + updateCount > 0) {
+        emit('success');
+      }
+      notifyImportResult({
+        subject: '鐢ㄦ埛',
+        createCount,
+        updateCount,
+        failures: importData.failureUsernames,
+      });
     } finally {
       modalApi.unlock();
     }

--
Gitblit v1.9.3