From 1678465c039ce6255105c1fcdb3ace56860f44f9 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期一, 08 六月 2026 17:29:25 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro

---
 src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js |  345 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 345 insertions(+), 0 deletions(-)

diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
new file mode 100644
index 0000000..79e96bc
--- /dev/null
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -0,0 +1,345 @@
+import {
+  addApprovalTemplate,
+  deleteApprovalTemplate,
+  getApprovalTemplateDetail,
+  listApprovalTemplatePage,
+  TEMPLATE_TYPE_BUILTIN,
+  updateApprovalTemplate,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { Search } from "@element-plus/icons-vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { computed, reactive, ref } from "vue";
+import {
+  buildApprovalTemplateListParams,
+  createEmptyTemplateForm,
+  fetchBusinessTypeOptions,
+  flowNodesSummary,
+  isBuiltinTemplate,
+  mapTemplateFromApi,
+  mapTemplateToApi,
+  nodeSignModeLabel,
+  formatDisplayTime,
+  unwrapTemplateDetail,
+  validateTemplateForm,
+} from "./approveTemplateConstants.js";
+import { parseFormConfigToData } from "./formConfigUtils.js";
+
+const FALLBACK_TEMPLATE_TYPE_OPTIONS = [
+  { value: 0, label: "绯荤粺鍐呯疆" },
+  { value: 1, label: "鑷畾涔�" },
+];
+
+function matchTemplateTypeValue(options, type) {
+  if (type == null || type === "") return false;
+  return options.some(
+    (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
+  );
+}
+
+export function useApproveTemplate() {
+  const templateTypeOptions = ref([...FALLBACK_TEMPLATE_TYPE_OPTIONS]);
+
+  function templateTypeLabel(type) {
+    if (type == null || type === "") return "鈥�";
+    const hit = templateTypeOptions.value.find(
+      (x) => x.value === type || x.value === Number(type) || String(x.value) === String(type)
+    );
+    return hit?.label || "鈥�";
+  }
+
+  const searchForm = reactive({
+    keyword: "",
+    enabledOnly: false,
+  });
+
+  const tableLoading = ref(false);
+  const page = reactive({ current: 1, size: 10, total: 0 });
+  const tableData = ref([]);
+
+  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 {
+      const list = await fetchBusinessTypeOptions();
+      templateTypeOptions.value = list.length ? list : [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
+    } catch {
+      templateTypeOptions.value = [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
+    }
+    if (!matchTemplateTypeValue(templateTypeOptions.value, form.businessType)) {
+      form.businessType = templateTypeOptions.value[0]?.value ?? "";
+    }
+  }
+
+  const detailDialog = reactive({ visible: false });
+  const detailRow = ref({});
+  const detailLoading = ref(false);
+
+  const formRules = {
+    templateName: [{ required: true, message: "璇疯緭鍏ユā鏉垮悕绉�", trigger: "blur" }],
+    businessType: [{ required: true, message: "璇烽�夋嫨妯℃澘绫诲瀷", trigger: "change" }],
+  };
+
+  const tableColumn = ref([
+    { label: "妯℃澘鍚嶇О", prop: "templateName", minWidth: 140 },
+    {
+      label: "妯℃澘绫诲瀷",
+      prop: "businessType",
+      width: 100,
+      align: "center",
+      formatData: (v) => templateTypeLabel(v),
+    },
+    { label: "璇存槑", prop: "description", minWidth: 160, showOverflowTooltip: true },
+    {
+      label: "鑺傜偣鏁�",
+      prop: "flowNodes",
+      width: 80,
+      align: "center",
+      formatData: (v) => (Array.isArray(v) ? v.length : 0),
+    },
+    {
+      label: "娴佺▼姒傝",
+      prop: "flowNodes",
+      minWidth: 220,
+      showOverflowTooltip: true,
+      formatData: (v) => flowNodesSummary(v),
+    },
+    {
+      label: "鐘舵��",
+      prop: "enabled",
+      width: 90,
+      align: "center",
+      dataType: "tag",
+      formatData: (v) => (v !== false ? "鍚敤" : "鍋滅敤"),
+      formatType: (v) => (v !== false ? "success" : "info"),
+    },
+    {
+      label: "鍒涘缓鏃堕棿",
+      prop: "createdTime",
+      width: 170,
+      showOverflowTooltip: true,
+      formatData: (v) => formatDisplayTime(v),
+    },
+    {
+      label: "鏇存柊鏃堕棿",
+      prop: "updatedTime",
+      width: 170,
+      showOverflowTooltip: true,
+      formatData: (v) => formatDisplayTime(v),
+    },
+    {
+      dataType: "action",
+      label: "鎿嶄綔",
+      align: "center",
+      fixed: "right",
+      width: 220,
+      operation: [
+        { name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
+        { name: "缂栬緫", type: "text", clickFun: (row) => openFormDialog("edit", row) },
+        {
+          name: "鍒犻櫎",
+          type: "danger",
+          link: true,
+          disabled: (row) => isBuiltinTemplate(row),
+          clickFun: (row) => removeTemplate(row),
+        },
+      ],
+    },
+  ]);
+
+  async function fetchTemplateList() {
+    tableLoading.value = true;
+    try {
+      const res = await listApprovalTemplatePage(
+        buildApprovalTemplateListParams({ page, searchForm })
+      );
+      const data = res?.data || {};
+      tableData.value = (data.records || []).map(mapTemplateFromApi);
+      page.total = Number(data.total || 0);
+    } catch {
+      tableData.value = [];
+      page.total = 0;
+    } finally {
+      tableLoading.value = false;
+    }
+  }
+
+  function handleQuery() {
+    page.current = 1;
+    fetchTemplateList();
+  }
+
+  function resetSearch() {
+    searchForm.keyword = "";
+    searchForm.enabledOnly = false;
+    handleQuery();
+  }
+
+  function pagination({ page: p, limit }) {
+    page.current = p;
+    page.size = limit;
+    fetchTemplateList();
+  }
+
+  function resetForm(row) {
+    const base = createEmptyTemplateForm();
+    if (!row) {
+      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,
+      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 || [])),
+    });
+  }
+
+  async function openFormDialog(mode, row) {
+    formDialog.mode = mode;
+    formDialog.title = mode === "add" ? "鏂板缓瀹℃壒妯℃澘" : "缂栬緫瀹℃壒妯℃澘";
+    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;
+  }
+
+  async function openDetail(row) {
+    if (row?.id == null || row.id === "") {
+      ElMessage.warning("鏃犳硶鏌ョ湅璇︽儏锛氱己灏戞ā鏉� ID");
+      return;
+    }
+    detailDialog.visible = true;
+    detailLoading.value = true;
+    detailRow.value = {};
+    try {
+      const res = await getApprovalTemplateDetail(row.id);
+      detailRow.value = mapTemplateFromApi(unwrapTemplateDetail(res));
+    } catch {
+      detailDialog.visible = false;
+    } finally {
+      detailLoading.value = false;
+    }
+  }
+
+  async function submitForm() {
+    if (!formRef.value) return false;
+    try {
+      await formRef.value.validate();
+    } catch {
+      return false;
+    }
+    const validated = validateTemplateForm(form);
+    if (!validated.ok) {
+      return { message: validated.message };
+    }
+    if (formDialog.mode === "edit" && !form.id) {
+      return { message: "缂哄皯妯℃澘 ID锛屾棤娉曚繚瀛樹慨鏀�" };
+    }
+    const dto = mapTemplateToApi(form);
+    try {
+      if (formDialog.mode === "add") {
+        await addApprovalTemplate(dto);
+      } else {
+        await updateApprovalTemplate(dto);
+      }
+    } catch {
+      return false;
+    }
+    formDialog.visible = false;
+    page.current = 1;
+    await fetchTemplateList();
+    return { ok: true };
+  }
+
+  async function removeTemplate(row) {
+    if (isBuiltinTemplate(row)) {
+      ElMessage.warning("绯荤粺鍐呯疆妯℃澘涓嶅厑璁稿垹闄�");
+      return;
+    }
+    if (row?.id == null || row.id === "") {
+      ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戞ā鏉� ID");
+      return;
+    }
+    const name = row.templateName || "鏈懡鍚嶆ā鏉�";
+    try {
+      await ElMessageBox.confirm(
+        `纭畾瑕佸垹闄ゅ鎵规ā鏉裤��${name}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+        "鍒犻櫎纭",
+        {
+          type: "warning",
+          confirmButtonText: "纭畾鍒犻櫎",
+          cancelButtonText: "鍙栨秷",
+          distinguishCancelAndClose: true,
+          autofocus: false,
+        }
+      );
+    } catch {
+      return;
+    }
+    try {
+      await deleteApprovalTemplate([row.id]);
+      ElMessage.success("鍒犻櫎鎴愬姛");
+      await fetchTemplateList();
+    } catch {
+      /* 閿欒鐢辨嫤鎴櫒鎻愮ず */
+    }
+  }
+
+  return {
+    Search,
+    templateTypeOptions,
+    loadTemplateTypeOptions,
+    templateTypeLabel,
+    fetchTemplateList,
+    nodeSignModeLabel,
+    flowNodesSummary,
+    searchForm,
+    tableLoading,
+    page,
+    tableData,
+    tableColumn,
+    formDialog,
+    form,
+    formRef,
+    formRules,
+    isEditingBuiltin,
+    detailDialog,
+    detailRow,
+    detailLoading,
+    handleQuery,
+    resetSearch,
+    pagination,
+    openFormDialog,
+    openDetail,
+    submitForm,
+  };
+}

--
Gitblit v1.9.3