src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -3,27 +3,27 @@
  deleteApprovalTemplate,
  getApprovalTemplateDetail,
  listApprovalTemplatePage,
  TEMPLATE_TYPE_CUSTOM,
  TEMPLATE_TYPE_BUILTIN,
  updateApprovalTemplate,
} from "@/api/officeProcessAutomation/approvalTemplate.js";
import { Search } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { reactive, ref } from "vue";
import { computed, reactive, ref } from "vue";
import {
  buildApprovalTemplateListParams,
  createEmptyTemplateForm,
  fetchBusinessTypeOptions,
  flowNodesSummary,
  isBuiltinTemplate,
  mapTemplateFromApi,
  mapTemplateToApi,
  nodeDisplayName,
  nodeSignModeLabel,
  formatDisplayTime,
  unwrapTemplateDetail,
  validateTemplateForm,
} from "./approveTemplateConstants.js";
import { parseFormConfigToData } from "./formConfigUtils.js";
const LEGACY_STORAGE_KEY = "oa_approve_template_custom_v1";
const FALLBACK_TEMPLATE_TYPE_OPTIONS = [
  { value: 0, label: "系统内置" },
@@ -37,17 +37,7 @@
  );
}
function clearLegacyStorage() {
  try {
    localStorage.removeItem(LEGACY_STORAGE_KEY);
  } catch {
    /* ignore */
  }
}
export function useApproveTemplate() {
  clearLegacyStorage();
  const templateTypeOptions = ref([...FALLBACK_TEMPLATE_TYPE_OPTIONS]);
  function templateTypeLabel(type) {
@@ -70,6 +60,10 @@
  const formDialog = reactive({ visible: false, title: "", mode: "add" });
  const form = reactive(createEmptyTemplateForm());
  const formRef = ref();
  const isEditingBuiltin = computed(
    () => formDialog.mode === "edit" && Number(form.templateType) === TEMPLATE_TYPE_BUILTIN
  );
  async function loadTemplateTypeOptions() {
    try {
@@ -111,10 +105,9 @@
    },
    {
      label: "流程概要",
      prop: "flowNodes",
      prop: "flowSummary",
      minWidth: 220,
      showOverflowTooltip: true,
      formatData: (v) => flowNodesSummary(v),
    },
    {
      label: "状态",
@@ -132,13 +125,13 @@
      showOverflowTooltip: true,
      formatData: (v) => formatDisplayTime(v),
    },
    {
      label: "更新时间",
      prop: "updatedTime",
      width: 170,
      showOverflowTooltip: true,
      formatData: (v) => formatDisplayTime(v),
    },
    // {
    //   label: "更新时间",
    //   prop: "updatedTime",
    //   width: 170,
    //   showOverflowTooltip: true,
    //   formatData: (v) => formatDisplayTime(v),
    // },
    {
      dataType: "action",
      label: "操作",
@@ -152,6 +145,7 @@
          name: "删除",
          type: "danger",
          link: true,
          disabled: (row) => isBuiltinTemplate(row),
          clickFun: (row) => removeTemplate(row),
        },
      ],
@@ -165,7 +159,11 @@
        buildApprovalTemplateListParams({ page, searchForm })
      );
      const data = res?.data || {};
      tableData.value = (data.records || []).map(mapTemplateFromApi);
      // 流程概要按「审批类型·层级」展示,需要把模板名带进文案里
      tableData.value = (data.records || []).map(mapTemplateFromApi).map((row) => ({
        ...row,
        flowSummary: flowNodesSummary(row.flowNodes, row.templateName),
      }));
      page.total = Number(data.total || 0);
    } catch {
      tableData.value = [];
@@ -198,25 +196,43 @@
      Object.assign(form, base);
      return;
    }
    const formConfigData = JSON.parse(
      JSON.stringify(row.formConfigData || parseFormConfigToData(row.formConfig))
    );
    const builtin = isBuiltinTemplate(row);
    Object.assign(form, {
      ...base,
      id: row.id,
      templateName: row.templateName || "",
      description: row.description || "",
      templateType: row.templateType != null ? Number(row.templateType) : base.templateType,
      businessType: row.businessType ?? "",
      formConfig: row.formConfig || "",
      formConfigData: JSON.parse(
        JSON.stringify(row.formConfigData || parseFormConfigToData(row.formConfig))
      ),
      formConfigData,
      lockedFormFieldUids: builtin
        ? (formConfigData.fields || []).map((f) => f._uid).filter(Boolean)
        : [],
      enabled: row.enabled !== false,
      flowNodes: JSON.parse(JSON.stringify(row.flowNodes || [base.flowNodes[0]])),
      storageBlobDTOs: JSON.parse(JSON.stringify(row.storageBlobDTOs || [])),
    });
  }
  function openFormDialog(mode, row) {
  async function openFormDialog(mode, row) {
    formDialog.mode = mode;
    formDialog.title = mode === "add" ? "新建审批模板" : "编辑审批模板";
    resetForm(mode === "edit" ? row : null);
    if (mode === "edit" && row?.id) {
      // 编辑时先查询详情获取完整数据(包含附件)
      try {
        const res = await getApprovalTemplateDetail(row.id);
        const detailData = mapTemplateFromApi(unwrapTemplateDetail(res));
        resetForm(detailData);
      } catch {
        resetForm(row);
      }
    } else {
      resetForm(mode === "edit" ? row : null);
    }
    formDialog.visible = true;
  }
@@ -269,6 +285,10 @@
  }
  async function removeTemplate(row) {
    if (isBuiltinTemplate(row)) {
      ElMessage.warning("系统内置模板不允许删除");
      return;
    }
    if (row?.id == null || row.id === "") {
      ElMessage.warning("无法删除:缺少模板 ID");
      return;
@@ -305,6 +325,7 @@
    templateTypeLabel,
    fetchTemplateList,
    nodeSignModeLabel,
    nodeDisplayName,
    flowNodesSummary,
    searchForm,
    tableLoading,
@@ -315,6 +336,7 @@
    form,
    formRef,
    formRules,
    isEditingBuiltin,
    detailDialog,
    detailRow,
    detailLoading,