From 6c324a234060820d031014ea657af5aa0b0d478e Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 五月 2026 13:29:20 +0800
Subject: [PATCH] 审批模板
---
src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js | 263 ++++++++++++++++++++++++++++++++-------------------
1 files changed, 164 insertions(+), 99 deletions(-)
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
index c56d055..8489e13 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -1,24 +1,49 @@
-import { Search } from "@element-plus/icons-vue";
-import dayjs from "dayjs";
-import { ElMessageBox } from "element-plus";
-import { computed, reactive, ref, watch } from "vue";
import {
+ addApprovalTemplate,
+ deleteApprovalTemplate,
+ getApprovalTemplateDetail,
+ listApprovalTemplate,
+ listApprovalTemplatePage,
+ TEMPLATE_TYPE_BUILTIN,
+ TEMPLATE_TYPE_CUSTOM,
+ TEMPLATE_TYPE_OPTIONS,
+ 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 {
+ buildApprovalTemplateListParams,
createEmptyTemplateForm,
- createInitialMockTemplates,
flowNodesSummary,
- getBuiltinTemplates,
- loadStoredTemplates,
+ mapBuiltinCardFromApi,
+ mapTemplateFromApi,
+ mapTemplateToApi,
nodeSignModeLabel,
- saveStoredTemplates,
+ templateTypeLabel,
+ unwrapTemplateList,
+ formatDisplayTime,
+ unwrapTemplateDetail,
validateTemplateForm,
} from "./approveTemplateConstants.js";
+import { parseFormConfigToData } from "./formConfigUtils.js";
+
+const LEGACY_STORAGE_KEY = "oa_approve_template_custom_v1";
+
+function clearLegacyStorage() {
+ try {
+ localStorage.removeItem(LEGACY_STORAGE_KEY);
+ } catch {
+ /* ignore */
+ }
+}
export function useApproveTemplate() {
- const stored = loadStoredTemplates();
- const allTemplates = ref(stored?.length ? stored : createInitialMockTemplates());
+ clearLegacyStorage();
const activeTab = ref("custom");
- const builtinTemplates = getBuiltinTemplates();
+ const builtinTemplates = ref([]);
+ const builtinLoading = ref(false);
const searchForm = reactive({
keyword: "",
@@ -27,6 +52,7 @@
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());
@@ -34,44 +60,22 @@
const detailDialog = reactive({ visible: false });
const detailRow = ref({});
-
- const filteredList = computed(() => {
- let list = [...allTemplates.value];
- const kw = (searchForm.keyword || "").trim().toLowerCase();
- if (kw) {
- list = list.filter((r) => {
- const name = (r.templateName || "").toLowerCase();
- const desc = (r.description || "").toLowerCase();
- return name.includes(kw) || desc.includes(kw);
- });
- }
- if (searchForm.enabledOnly) {
- list = list.filter((r) => r.enabled !== false);
- }
- return list.sort((a, b) => (String(a.updateTime) < String(b.updateTime) ? 1 : -1));
- });
-
- watch(
- filteredList,
- (list) => {
- page.total = list.length;
- const maxPage = Math.max(1, Math.ceil(list.length / page.size) || 1);
- if (page.current > maxPage) page.current = maxPage;
- },
- { immediate: true }
- );
-
- const tableData = computed(() => {
- const start = (page.current - 1) * page.size;
- return filteredList.value.slice(start, start + page.size);
- });
+ const detailLoading = ref(false);
const formRules = {
templateName: [{ required: true, message: "璇疯緭鍏ユā鏉垮悕绉�", trigger: "blur" }],
+ templateType: [{ required: true, message: "璇烽�夋嫨妯℃澘绫诲瀷", trigger: "change" }],
};
const tableColumn = ref([
{ label: "妯℃澘鍚嶇О", prop: "templateName", minWidth: 140 },
+ {
+ label: "妯℃澘绫诲瀷",
+ prop: "templateType",
+ width: 100,
+ align: "center",
+ formatData: (v) => templateTypeLabel(v),
+ },
{ label: "璇存槑", prop: "description", minWidth: 160, showOverflowTooltip: true },
{
label: "鑺傜偣鏁�",
@@ -96,31 +100,72 @@
formatData: (v) => (v !== false ? "鍚敤" : "鍋滅敤"),
formatType: (v) => (v !== false ? "success" : "info"),
},
- { label: "鏇存柊鏃堕棿", prop: "updateTime", width: 170 },
+ {
+ 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: 200,
+ width: 220,
operation: [
{ name: "璇︽儏", type: "text", clickFun: (row) => openDetail(row) },
{ name: "缂栬緫", type: "text", clickFun: (row) => openFormDialog("edit", row) },
- { name: "鍒犻櫎", type: "text", clickFun: (row) => removeTemplate(row) },
+ {
+ name: "鍒犻櫎",
+ type: "danger",
+ link: true,
+ clickFun: (row) => removeTemplate(row),
+ },
],
},
]);
- function persist() {
- saveStoredTemplates(allTemplates.value);
+ async function loadBuiltinTemplates() {
+ builtinLoading.value = true;
+ try {
+ const res = await listApprovalTemplate(TEMPLATE_TYPE_BUILTIN);
+ builtinTemplates.value = unwrapTemplateList(res).map(mapBuiltinCardFromApi);
+ } catch {
+ builtinTemplates.value = [];
+ ElMessage.warning("绯荤粺甯哥敤瀹℃壒鍔犺浇澶辫触");
+ } finally {
+ builtinLoading.value = false;
+ }
+ }
+
+ 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() {
- tableLoading.value = true;
page.current = 1;
- setTimeout(() => {
- tableLoading.value = false;
- }, 150);
+ fetchTemplateList();
}
function resetSearch() {
@@ -132,6 +177,7 @@
function pagination({ page: p, limit }) {
page.current = p;
page.size = limit;
+ fetchTemplateList();
}
function resetForm(row) {
@@ -145,6 +191,11 @@
id: row.id,
templateName: row.templateName || "",
description: row.description || "",
+ templateType: row.templateType ?? TEMPLATE_TYPE_CUSTOM,
+ formConfig: row.formConfig || "",
+ formConfigData: JSON.parse(
+ JSON.stringify(row.formConfigData || parseFormConfigToData(row.formConfig))
+ ),
enabled: row.enabled !== false,
flowNodes: JSON.parse(JSON.stringify(row.flowNodes || [base.flowNodes[0]])),
});
@@ -152,19 +203,27 @@
function openFormDialog(mode, row) {
formDialog.mode = mode;
- formDialog.title = mode === "add" ? "鏂板缓鑷畾涔夊鎵规ā鏉�" : "缂栬緫鑷畾涔夊鎵规ā鏉�";
+ formDialog.title = mode === "add" ? "鏂板缓瀹℃壒妯℃澘" : "缂栬緫瀹℃壒妯℃澘";
resetForm(mode === "edit" ? row : null);
formDialog.visible = true;
}
- function openDetail(row) {
- detailRow.value = { ...row };
+ async function openDetail(row) {
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鏌ョ湅璇︽儏锛氱己灏戞ā鏉� ID");
+ return;
+ }
detailDialog.visible = true;
- }
-
- function isNameDuplicate(name, excludeId) {
- const n = (name || "").trim();
- return allTemplates.value.some((t) => t.templateName?.trim() === n && t.id !== excludeId);
+ 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() {
@@ -178,64 +237,70 @@
if (!validated.ok) {
return { message: validated.message };
}
- if (isNameDuplicate(validated.name, form.id)) {
- return { message: "妯℃澘鍚嶇О宸插瓨鍦紝璇锋洿鎹㈠悕绉�" };
+ if (formDialog.mode === "edit" && !form.id) {
+ return { message: "缂哄皯妯℃澘 ID锛屾棤娉曚繚瀛樹慨鏀�" };
}
- const now = dayjs().format("YYYY-MM-DD HH:mm:ss");
- if (formDialog.mode === "add") {
- allTemplates.value.unshift({
- id: `tpl_${Date.now()}`,
- templateName: validated.name,
- description: (form.description || "").trim(),
- enabled: form.enabled !== false,
- createTime: now,
- updateTime: now,
- flowNodes: validated.nodes,
- });
- } else {
- const hit = allTemplates.value.find((t) => t.id === form.id);
- if (!hit) return { message: "妯℃澘涓嶅瓨鍦ㄦ垨宸插垹闄�" };
- hit.templateName = validated.name;
- hit.description = (form.description || "").trim();
- hit.enabled = form.enabled !== false;
- hit.flowNodes = validated.nodes;
- hit.updateTime = now;
+ const dto = mapTemplateToApi(form);
+ try {
+ if (formDialog.mode === "add") {
+ await addApprovalTemplate(dto);
+ } else {
+ await updateApprovalTemplate(dto);
+ }
+ } catch {
+ return false;
}
- persist();
formDialog.visible = false;
page.current = 1;
+ await fetchTemplateList();
+ if (dto.templateType === TEMPLATE_TYPE_BUILTIN) {
+ await loadBuiltinTemplates();
+ }
return { ok: true };
}
async function removeTemplate(row) {
+ if (row?.id == null || row.id === "") {
+ ElMessage.warning("鏃犳硶鍒犻櫎锛氱己灏戞ā鏉� ID");
+ return;
+ }
+ const name = row.templateName || "鏈懡鍚嶆ā鏉�";
try {
- await ElMessageBox.confirm(`纭畾鍒犻櫎妯℃澘銆�${row.templateName}銆嶅悧锛焋, "鎻愮ず", {
- type: "warning",
- confirmButtonText: "鍒犻櫎",
- cancelButtonText: "鍙栨秷",
- });
+ await ElMessageBox.confirm(
+ `纭畾瑕佸垹闄ゅ鎵规ā鏉裤��${name}銆嶅悧锛熷垹闄ゅ悗涓嶅彲鎭㈠銆俙,
+ "鍒犻櫎纭",
+ {
+ type: "warning",
+ confirmButtonText: "纭畾鍒犻櫎",
+ cancelButtonText: "鍙栨秷",
+ distinguishCancelAndClose: true,
+ autofocus: false,
+ }
+ );
} catch {
return;
}
- const idx = allTemplates.value.findIndex((t) => t.id === row.id);
- if (idx >= 0) {
- allTemplates.value.splice(idx, 1);
- persist();
+ try {
+ await deleteApprovalTemplate([row.id]);
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ await fetchTemplateList();
+ if (row.templateType === TEMPLATE_TYPE_BUILTIN) {
+ await loadBuiltinTemplates();
+ }
+ } catch {
+ /* 閿欒鐢辨嫤鎴櫒鎻愮ず */
}
- }
-
- function toggleEnabled(row) {
- const hit = allTemplates.value.find((t) => t.id === row.id);
- if (!hit) return;
- hit.enabled = !hit.enabled;
- hit.updateTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
- persist();
}
return {
Search,
+ TEMPLATE_TYPE_OPTIONS,
+ templateTypeLabel,
activeTab,
builtinTemplates,
+ builtinLoading,
+ loadBuiltinTemplates,
+ fetchTemplateList,
nodeSignModeLabel,
flowNodesSummary,
searchForm,
@@ -249,12 +314,12 @@
formRules,
detailDialog,
detailRow,
+ detailLoading,
handleQuery,
resetSearch,
pagination,
openFormDialog,
openDetail,
submitForm,
- toggleEnabled,
};
}
--
Gitblit v1.9.3