From a567edf28abb00581c93b27405ed9657b63a8bd7 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 五月 2026 13:32:17 +0800
Subject: [PATCH] 模板类型设置

---
 src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js |  311 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 226 insertions(+), 85 deletions(-)

diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
index 81884a1..3325e55 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
@@ -1,5 +1,23 @@
 import dayjs from "dayjs";
-import { APPROVAL_TYPE_OPTIONS, SUBMIT_TEMPLATES } from "../approve-list/approveListConstants.js";
+import {
+  TEMPLATE_TYPE_CUSTOM,
+  TEMPLATE_TYPE_OPTIONS,
+} from "@/api/officeProcessAutomation/approvalTemplate.js";
+import { APPROVAL_TYPE_OPTIONS } from "../approve-list/approveListConstants.js";
+import {
+  buildFormConfigJson,
+  createEmptyFormConfigData,
+  parseFormConfigToData,
+  validateFormConfigData,
+} from "./formConfigUtils.js";
+
+export { TEMPLATE_TYPE_OPTIONS };
+
+export function templateTypeLabel(type) {
+  if (type == null || type === "") return "鈥�";
+  const n = Number(type);
+  return TEMPLATE_TYPE_OPTIONS.find((x) => x.value === n)?.label || "鈥�";
+}
 
 /** 鑺傜偣鍐呭鎵规柟寮忥細浼氱 / 鎴栫 */
 export const NODE_SIGN_MODE_OPTIONS = [
@@ -7,18 +25,205 @@
   { value: "or_sign", label: "鎴栫", desc: "鏈妭鐐逛换涓�瀹℃壒浜洪�氳繃鍗冲彲" },
 ];
 
-export const STORAGE_KEY = "oa_approve_template_custom_v1";
+function parseFormConfig(formConfig) {
+  if (!formConfig) return {};
+  if (typeof formConfig === "object") return formConfig;
+  try {
+    return JSON.parse(formConfig);
+  } catch {
+    return {};
+  }
+}
 
-/** 绯荤粺鍐呯疆甯哥敤瀹℃壒锛堝彧璇诲睍绀猴紝鏉ユ簮浜庡鎵瑰垪琛ㄦ彁浜ゆā鏉匡級 */
-export function getBuiltinTemplates() {
-  return Object.entries(SUBMIT_TEMPLATES).map(([key, tpl]) => ({
-    key,
-    approvalType: tpl.approvalType,
-    label: tpl.label,
-    summary: tpl.summaryPlaceholder || "绯荤粺棰勭疆濉姤瀛楁",
-    fieldCount: (tpl.fields || []).length,
-    defaultMode: tpl.approvalMode,
+function resolveDefaultMode(row, cfg, nodes) {
+  let mode = cfg.approvalMode || cfg.defaultMode;
+  if (!mode && nodes.length) {
+    const t = String(nodes[0]?.approveType || "").toUpperCase();
+    mode = t === "OR" ? "or_sign" : "parallel";
+  }
+  const m = String(mode || "").toLowerCase();
+  if (m === "or" || m === "or_sign") return "or_sign";
+  return "parallel";
+}
+
+/** 灏嗘帴鍙h繑鍥炵殑妯℃澘杞负銆岀郴缁熷父鐢ㄥ鎵广�嶅崱鐗囨暟鎹� */
+export function mapBuiltinCardFromApi(row) {
+  const cfg = parseFormConfig(row?.formConfig);
+  const fields = cfg.fields || cfg.formFields || [];
+  const nodes = row?.nodes || row?.flowNodes || [];
+  return {
+    key: String(row?.id ?? row?.templateName ?? ""),
+    id: row?.id,
+    approvalType: cfg.approvalType || row?.approvalType || "",
+    label: row?.templateName || row?.name || "鈥�",
+    summary: (row?.description || "").trim() || cfg.summaryPlaceholder || "绯荤粺棰勭疆濉姤瀛楁",
+    fieldCount: fields.length,
+    defaultMode: resolveDefaultMode(row, cfg, nodes),
+  };
+}
+
+export function unwrapTemplateList(payload) {
+  const data = payload?.data ?? payload;
+  if (Array.isArray(data)) return data;
+  if (Array.isArray(data?.records)) return data.records;
+  if (Array.isArray(data?.list)) return data.list;
+  return [];
+}
+
+/** 鍚庣 approveType 鈫� 椤甸潰 signMode */
+export function mapSignModeFromApi(approveType) {
+  const t = String(approveType || "").toUpperCase();
+  return t === "OR" ? "or_sign" : "countersign";
+}
+
+/** 椤甸潰 signMode 鈫� 鍚庣 approveType */
+export function mapSignModeToApi(signMode) {
+  return signMode === "or_sign" ? "OR" : "AND";
+}
+
+/** 椤甸潰 enabled 鈫� 鍚庣 enabled锛�1 鍚敤锛�0 鍋滅敤锛� */
+export function mapEnabledToApi(enabled) {
+  return enabled !== false ? "1" : "0";
+}
+
+/** 鍚庣 nodes 鈫� 椤甸潰 flowNodes锛堜繚鐣� id 渚涗慨鏀规彁浜わ級 */
+export function mapNodesFromApi(nodes) {
+  const list = Array.isArray(nodes) ? nodes : [];
+  return list.map((n, i) => ({
+    id: n.id,
+    templateId: n.templateId,
+    nodeOrder: n.levelNo ?? i + 1,
+    signMode: mapSignModeFromApi(n.approveType ?? n.signMode),
+    approvers: (n.approvers || [])
+      .filter((a) => a?.approverId != null && a.approverId !== "")
+      .map((a) => ({
+        id: a.id,
+        nodeId: a.nodeId,
+        templateId: a.templateId,
+        approverId: a.approverId,
+        approverName: a.approverName || "",
+      })),
   }));
+}
+
+/** enabled锛�1 鍚敤锛�0 鍋滅敤 */
+export function mapEnabledFromApi(enabled) {
+  return enabled === "1" || enabled === 1 || enabled === true;
+}
+
+/** 鍏煎澶氱鍚庣鏃堕棿瀛楁鍚嶅苟鏍煎紡鍖栧睍绀� */
+export function pickTemplateTimes(row) {
+  const rawCreated =
+    row?.createdTime ?? row?.createTime ?? row?.gmtCreate ?? row?.created_at ?? "";
+  const rawUpdated =
+    row?.updatedTime ?? row?.updateTime ?? row?.gmtModified ?? row?.modifyTime ?? row?.updated_at ?? "";
+  const createdTime = normalizeTimeValue(rawCreated);
+  const updatedTime = normalizeTimeValue(rawUpdated);
+  return { createdTime, updatedTime, createTime: createdTime, updateTime: updatedTime };
+}
+
+function normalizeTimeValue(val) {
+  if (val == null || val === "") return "";
+  if (Array.isArray(val) && val.length >= 3) {
+    const [y, m, d, h = 0, min = 0, s = 0] = val;
+    return dayjs(new Date(y, m - 1, d, h, min, s)).format("YYYY-MM-DD HH:mm:ss");
+  }
+  if (typeof val === "number") {
+    const d = val > 1e12 ? dayjs(val) : dayjs.unix(val);
+    return d.isValid() ? d.format("YYYY-MM-DD HH:mm:ss") : "";
+  }
+  const s = String(val).trim();
+  if (!s) return "";
+  const parsed = dayjs(s.includes("T") ? s : s.replace(/-/g, "/"));
+  return parsed.isValid() ? parsed.format("YYYY-MM-DD HH:mm:ss") : s;
+}
+
+export function formatDisplayTime(val) {
+  const t = normalizeTimeValue(val);
+  return t || "鈥�";
+}
+
+/** 璇︽儏鎺ュ彛 data 瑙e寘 */
+export function unwrapTemplateDetail(res) {
+  const data = res?.data ?? res;
+  if (!data || typeof data !== "object") return {};
+  if (data.templateName != null || data.id != null) return data;
+  if (data.approvalTemplateVo) return data.approvalTemplateVo;
+  if (data.records && data.records[0]) return data.records[0];
+  return data;
+}
+
+/** 鍒嗛〉鍒楄〃椤� 鈫� 椤甸潰琛屾暟鎹紙涓昏〃 + 鑺傜偣锛� */
+export function mapTemplateFromApi(row) {
+  if (!row) return {};
+  const flowNodes = mapNodesFromApi(row.nodes || row.flowNodes);
+  const times = pickTemplateTimes(row);
+  return {
+    id: row.id,
+    templateName: row.templateName || "",
+    description: row.description || "",
+    enabled: mapEnabledFromApi(row.enabled),
+    enabledRaw: row.enabled,
+    templateType: row.templateType != null ? Number(row.templateType) : undefined,
+    formConfig: row.formConfig,
+    formConfigData: parseFormConfigToData(row.formConfig),
+    createdUser: row.createdUser,
+    createdUserName: row.createdUserName,
+    ...times,
+    flowNodes,
+    nodes: row.nodes || row.flowNodes,
+  };
+}
+
+/** 琛ㄥ崟鏁版嵁 鈫� 鎻愪氦 DTO锛圓pprovalTemplateDto锛� */
+export function mapTemplateToApi(form) {
+  const nodes = normalizeFlowNodes(form.flowNodes);
+  const templateId = form.id || null;
+  const dto = {
+    templateName: (form.templateName || "").trim(),
+    description: (form.description || "").trim(),
+    enabled: mapEnabledToApi(form.enabled),
+    templateType: form.templateType ?? TEMPLATE_TYPE_CUSTOM,
+    formConfig: buildFormConfigJson(form.formConfigData),
+    nodes: nodes.map((n, i) => {
+      const node = {
+        levelNo: n.nodeOrder ?? i + 1,
+        approveType: mapSignModeToApi(n.signMode),
+        approvers: n.approvers.map((a, idx) => {
+          const approver = {
+            approverId: a.approverId,
+            approverName: a.approverName || "",
+            sortNo: idx + 1,
+          };
+          if (a.id != null) approver.id = a.id;
+          if (a.nodeId != null) approver.nodeId = a.nodeId;
+          if (a.templateId != null) approver.templateId = a.templateId;
+          else if (templateId) approver.templateId = templateId;
+          return approver;
+        }),
+      };
+      if (n.id != null) node.id = n.id;
+      if (n.templateId != null) node.templateId = n.templateId;
+      else if (templateId) node.templateId = templateId;
+      return node;
+    }),
+  };
+  if (templateId) dto.id = templateId;
+  return dto;
+}
+
+export function buildApprovalTemplateListParams({ page, searchForm, templateType = TEMPLATE_TYPE_CUSTOM }) {
+  const params = {
+    current: page.current,
+    size: page.size,
+    templateType: searchForm?.templateType != null && searchForm.templateType !== ""
+      ? searchForm.templateType
+      : templateType,
+  };
+  const kw = (searchForm?.keyword || "").trim();
+  if (kw) params.templateName = kw;
+  if (searchForm?.enabledOnly) params.enabled = "1";
+  return params;
 }
 
 export function nodeSignModeLabel(mode) {
@@ -42,6 +247,9 @@
     id: "",
     templateName: "",
     description: "",
+    templateType: TEMPLATE_TYPE_CUSTOM,
+    formConfig: "",
+    formConfigData: createEmptyFormConfigData(),
     enabled: true,
     flowNodes: [createEmptyNode(1)],
   };
@@ -50,11 +258,16 @@
 export function normalizeFlowNodes(nodes) {
   const list = Array.isArray(nodes) ? nodes : [];
   return list.map((n, i) => ({
+    id: n.id,
+    templateId: n.templateId,
     nodeOrder: i + 1,
     signMode: n.signMode === "or_sign" ? "or_sign" : "countersign",
     approvers: (n.approvers || [])
       .filter((a) => a?.approverId != null && a.approverId !== "")
       .map((a) => ({
+        id: a.id,
+        nodeId: a.nodeId,
+        templateId: a.templateId,
         approverId: a.approverId,
         approverName: a.approverName || "",
       })),
@@ -71,6 +284,8 @@
       return { ok: false, message: `璇蜂负绗� ${i + 1} 涓妭鐐归�夋嫨鑷冲皯涓�鍚嶅鎵逛汉` };
     }
   }
+  const cfgCheck = validateFormConfigData(form.formConfigData);
+  if (!cfgCheck.ok) return cfgCheck;
   return { ok: true, nodes, name };
 }
 
@@ -83,78 +298,4 @@
       return `鑺傜偣${i + 1}(${nodeSignModeLabel(n.signMode)}:${names})`;
     })
     .join(" 鈫� ");
-}
-
-export function createInitialMockTemplates() {
-  const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
-  return [
-    {
-      id: "tpl_demo_1",
-      templateName: "椤圭洰绔嬮」瀹℃壒",
-      description: "璺ㄩ儴闂ㄩ」鐩珛椤癸紝闇�鎶�鏈�佽储鍔′緷娆′細绛�",
-      enabled: true,
-      createTime: dayjs().subtract(5, "day").format("YYYY-MM-DD HH:mm:ss"),
-      updateTime: now,
-      flowNodes: [
-        {
-          nodeOrder: 1,
-          signMode: "countersign",
-          approvers: [
-            { approverId: "mock_tech_lead", approverName: "鎶�鏈礋璐d汉" },
-            { approverId: "mock_pm", approverName: "椤圭洰缁忕悊" },
-          ],
-        },
-        {
-          nodeOrder: 2,
-          signMode: "or_sign",
-          approvers: [
-            { approverId: "mock_finance", approverName: "璐㈠姟涓荤" },
-            { approverId: "mock_cfo", approverName: "璐㈠姟鎬荤洃" },
-          ],
-        },
-      ],
-    },
-    {
-      id: "tpl_demo_2",
-      templateName: "鍚堝悓鐢ㄥ嵃鐢宠",
-      description: "娉曞姟涓庤鏀挎垨绛惧悗锛屾�荤粡鐞嗙粓瀹�",
-      enabled: true,
-      createTime: dayjs().subtract(12, "day").format("YYYY-MM-DD HH:mm:ss"),
-      updateTime: dayjs().subtract(2, "day").format("YYYY-MM-DD HH:mm:ss"),
-      flowNodes: [
-        {
-          nodeOrder: 1,
-          signMode: "or_sign",
-          approvers: [
-            { approverId: "mock_legal", approverName: "娉曞姟涓撳憳" },
-            { approverId: "mock_admin", approverName: "琛屾斂涓荤" },
-          ],
-        },
-        {
-          nodeOrder: 2,
-          signMode: "countersign",
-          approvers: [{ approverId: "mock_ceo", approverName: "鎬荤粡鐞�" }],
-        },
-      ],
-    },
-  ];
-}
-
-export function loadStoredTemplates() {
-  try {
-    const raw = localStorage.getItem(STORAGE_KEY);
-    if (!raw) return null;
-    const parsed = JSON.parse(raw);
-    return Array.isArray(parsed) ? parsed : null;
-  } catch {
-    return null;
-  }
-}
-
-export function saveStoredTemplates(rows) {
-  try {
-    localStorage.setItem(STORAGE_KEY, JSON.stringify(rows));
-  } catch {
-    /* ignore */
-  }
 }

--
Gitblit v1.9.3