gaoluyang
8 天以前 caddfd7efaabf86eb2348ae33d9b7a2281a2b167
src/utils/import-result.ts
@@ -2,7 +2,7 @@
import { h } from 'vue';
import { message, notification } from 'ant-design-vue';
import { message, Modal } from 'ant-design-vue';
export interface ImportResultNotifyOptions {
  /** 业务主体,用于拼标题与建议,如「设备」「客户」 */
@@ -20,8 +20,10 @@
/**
 * 统一展示 Excel 导入结果。
 *
 * 只要后端返回了失败明细,就绝不能再提示「操作成功」——改为常驻通知逐行列出失败原因,
 * 只要后端返回了失败明细,就绝不能再提示「操作成功」——改为弹窗逐行列出失败原因,
 * 并按失败原因给出下一步动作;全部成功时才提示成功。
 *
 * 失败明细可能上百行,所以用弹窗(弹窗内列表可滚动),避免长消息糊满屏幕。
 *
 * @returns 实际写入的条数(新增 + 更新),供调用方决定是否需要刷新列表
 */
@@ -43,26 +45,41 @@
    return importedCount;
  }
  const nodes: VNodeChild[] = [
  const hints = buildFailureHints(
    failureEntries.map(([, reason]) => reason),
    { subject, masterDataHint },
  );
  const content: VNodeChild = h('div', [
    h(
      'div',
      `新增成功 ${createCount} 条,更新成功 ${updateCount} 条,失败 ${failureEntries.length} 条:`,
      `新增成功 ${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)),
  ];
    h(
      'div',
      {
        class:
          'mt-2 max-h-72 overflow-y-auto rounded border border-solid border-gray-200 px-3 py-2 text-sm leading-6',
      },
      failureEntries.map(([name, reason]) =>
        h('div', { class: 'py-0.5' }, `${name}:${reason}`),
      ),
    ),
    ...hints.map((hint) =>
      h('div', { class: 'mt-2 text-red-500' }, hint),
    ),
  ]);
  const notify = importedCount === 0 ? notification.error : notification.warning;
  notify({
    message:
  const openModal = importedCount === 0 ? Modal.error : Modal.warning;
  openModal({
    title:
      importedCount === 0
        ? `${subject}导入失败:${failureEntries.length} 行全部未导入`
        : `导入完成,部分${subject}导入失败(成功 ${importedCount} 条 / 失败 ${failureEntries.length} 条)`,
    description: () => h('div', nodes),
    duration: null,
        : `导入完成:成功 ${importedCount} 条,失败 ${failureEntries.length} 条`,
    content,
    width: 680,
    centered: true,
    okText: '知道了',
  });
  return importedCount;
}
@@ -70,7 +87,10 @@
/** 按失败原因归纳下一步动作,避免用户只看到「失败」却不知道改哪里 */
function buildFailureHints(
  reasons: string[],
  { subject, masterDataHint }: Pick<ImportResultNotifyOptions, 'masterDataHint' | 'subject'>,
  {
    subject,
    masterDataHint,
  }: Pick<ImportResultNotifyOptions, 'masterDataHint' | 'subject'>,
): string[] {
  const hints = new Set<string>();
  for (const reason of reasons) {