From 6689bfb1c2f0638e8493adfa058d57d86e473eac Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 19 五月 2026 17:21:10 +0800
Subject: [PATCH] 审批列表得提交审批根据模板类型区分
---
src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js | 74 +++++++++++++++---
src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js | 36 +++++++++
src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue | 55 +++++++++++++
src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js | 7 +
src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js | 1
src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js | 31 -------
6 files changed, 158 insertions(+), 46 deletions(-)
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js b/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
index 80af992..8974cf4 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
@@ -50,10 +50,16 @@
return {
id: row?.id,
key: String(row?.id ?? ""),
+ businessType: row?.businessType ?? cfg.approvalType ?? row?.approvalType ?? "",
approvalType: cfg.approvalType || row?.approvalType || "",
label: row?.templateName || "鈥�",
summaryPlaceholder: (row?.description || "").trim() || cfg.summaryPlaceholder || "鐐瑰嚮濉啓骞舵彁浜�",
};
+}
+
+export function matchBusinessTypeValue(a, b) {
+ if (a == null || a === "" || b == null || b === "") return false;
+ return a === b || a === Number(b) || Number(a) === b || String(a) === String(b);
}
/** 瀹℃壒璁板綍 approveAction 鈫� 椤甸潰 result */
@@ -275,6 +281,7 @@
const dto = {
templateId,
templateName: submitForm?.templateName || tpl.label || "",
+ businessType: tpl.businessType ?? submitForm?.businessType ?? "",
title,
formConfig: buildInstanceFormConfigJson({ ...tpl, fields: tpl.fields || submitForm?.formFieldDefs }, payload),
tasks: taskList,
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue b/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
index cdae763..5fce871 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/index.vue
@@ -77,7 +77,34 @@
@closed="resetSubmitDialogState"
>
<template v-if="submitDialog.step === 1 && !isSubmitEdit">
- <p class="template-hint">璇烽�夋嫨宸插惎鐢ㄧ殑瀹℃壒妯℃澘锛岀郴缁熷皢鎸夋ā鏉块厤缃紩瀵煎~鎶ャ��</p>
+ <p class="template-hint">璇峰厛閫夋嫨妯℃澘绫诲瀷锛屽啀閫夋嫨璇ョ被鍨嬩笅宸插惎鐢ㄧ殑瀹℃壒妯℃澘銆�</p>
+ <div v-loading="submitTemplatesLoading" class="template-grid">
+ <div
+ v-for="opt in submitBusinessTypeOptions"
+ :key="`biz-type-${opt.value}`"
+ class="template-card"
+ :class="{ 'is-disabled': !countTemplatesByBusinessType(opt.value) }"
+ @click="onBusinessTypePick(opt.value)"
+ >
+ <span class="template-card-type">{{ opt.label }}</span>
+ <span class="template-card-desc">
+ {{ countTemplatesByBusinessType(opt.value) }} 涓彲鐢ㄦā鏉�
+ </span>
+ </div>
+ <el-empty
+ v-if="!submitTemplatesLoading && !submitBusinessTypeOptions.length"
+ description="鏆傛棤妯℃澘绫诲瀷"
+ :image-size="80"
+ class="template-empty"
+ />
+ </div>
+ </template>
+
+ <template v-else-if="submitDialog.step === 2 && !isSubmitEdit">
+ <p class="template-hint">
+ 褰撳墠绫诲瀷锛歿{ selectedBusinessTypeLabel || "鈥�" }}锛岃閫夋嫨鍏蜂綋瀹℃壒妯℃澘銆�
+ <el-button type="primary" link class="ml8" @click="backToBusinessTypePick">鏇存崲绫诲瀷</el-button>
+ </p>
<div v-loading="submitTemplatesLoading" class="template-grid">
<div
v-for="card in submitTemplateCards"
@@ -92,7 +119,7 @@
</div>
<el-empty
v-if="!submitTemplatesLoading && !submitTemplateCards.length"
- description="鏆傛棤鍙敤瀹℃壒妯℃澘"
+ description="璇ョ被鍨嬩笅鏆傛棤鍙敤瀹℃壒妯℃澘"
:image-size="80"
class="template-empty"
/>
@@ -132,12 +159,18 @@
<template #footer>
<el-button
- v-if="submitDialog.step === 2 || isSubmitEdit"
+ v-if="submitDialog.step === 3 || isSubmitEdit"
type="primary"
:loading="submitSaving"
@click="onSubmitInstance"
>
{{ isSubmitEdit ? "淇� 瀛�" : "鎻� 浜�" }}
+ </el-button>
+ <el-button
+ v-if="submitDialog.step === 2 && !isSubmitEdit"
+ @click="backToBusinessTypePick"
+ >
+ 涓婁竴姝�
</el-button>
<el-button @click="submitDialog.visible = false">
{{ submitDialog.step === 1 && !isSubmitEdit ? "鍙� 娑�" : "鍏� 闂�" }}
@@ -274,8 +307,13 @@
const {
Search,
APPROVAL_TYPE_OPTIONS,
+ submitBusinessTypeOptions,
submitTemplateCards,
+ selectedBusinessTypeLabel,
+ countTemplatesByBusinessType,
submitTemplatesLoading,
+ onBusinessTypePick,
+ backToBusinessTypePick,
approvalTypeLabel,
approvalActionLabel,
searchForm,
@@ -434,6 +472,17 @@
border-color: var(--el-color-primary);
box-shadow: var(--shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.06));
}
+.template-card.is-disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+.template-card.is-disabled:hover {
+ border-color: var(--el-border-color-lighter);
+ box-shadow: none;
+}
+.ml8 {
+ margin-left: 8px;
+}
.template-card-type {
display: inline-block;
padding: 2px 8px;
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js b/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
index 337b00d..4b8510a 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-list/useApproveList.js
@@ -1,7 +1,6 @@
import {
getApprovalTemplateDetail,
listApprovalTemplate,
- TEMPLATE_TYPE_BUILTIN,
TEMPLATE_TYPE_CUSTOM,
} from "@/api/officeProcessAutomation/approvalTemplate.js";
import {
@@ -16,6 +15,7 @@
import { ElMessage, ElMessageBox } from "element-plus";
import { computed, reactive, ref } from "vue";
import {
+ fetchBusinessTypeOptions,
formatDisplayTime,
mapEnabledFromApi,
mapTemplateFromApi,
@@ -36,6 +36,7 @@
createEmptySubmitForm,
mapInstanceFromApi,
mapSubmitTemplateCard,
+ matchBusinessTypeValue,
validateSubmitFlowNodes,
unwrapInstancePage,
} from "./approveListConstants.js";
@@ -45,8 +46,17 @@
const userStore = useUserStore();
const tableData = ref([]);
- const submitTemplateCards = ref([]);
+ const submitBusinessTypeOptions = ref([]);
+ const allSubmitTemplates = ref([]);
+ const selectedBusinessType = ref("");
const submitTemplatesLoading = ref(false);
+
+ const submitTemplateCards = computed(() => {
+ if (selectedBusinessType.value == null || selectedBusinessType.value === "") return [];
+ return allSubmitTemplates.value.filter((card) =>
+ matchBusinessTypeValue(card.businessType, selectedBusinessType.value)
+ );
+ });
const searchForm = reactive({
approvalType: "",
@@ -75,9 +85,22 @@
if (submitDialog.mode === "edit") {
return `淇敼${activeTemplate.value?.label || submitForm.templateName || "瀹℃壒"}`;
}
- if (submitDialog.step === 1) return "閫夋嫨瀹℃壒妯℃澘";
+ if (submitDialog.step === 1) return "閫夋嫨妯℃澘绫诲瀷";
+ if (submitDialog.step === 2) return `閫夋嫨瀹℃壒妯℃澘${businessTypeLabel(selectedBusinessType.value) ? `锛�${businessTypeLabel(selectedBusinessType.value)}锛塦 : ""}`;
return `鎻愪氦${activeTemplate.value?.label || "瀹℃壒"}`;
});
+
+ const selectedBusinessTypeLabel = computed(() => businessTypeLabel(selectedBusinessType.value));
+
+ function businessTypeLabel(type) {
+ if (type == null || type === "") return "";
+ const hit = submitBusinessTypeOptions.value.find((x) => matchBusinessTypeValue(x.value, type));
+ return hit?.label || "";
+ }
+
+ function countTemplatesByBusinessType(type) {
+ return allSubmitTemplates.value.filter((card) => matchBusinessTypeValue(card.businessType, type)).length;
+ }
const activeTemplate = computed(() => submitForm.templateSnapshot || null);
@@ -187,17 +210,17 @@
async function loadSubmitTemplates() {
submitTemplatesLoading.value = true;
try {
- const [builtinRes, customRes] = await Promise.all([
- listApprovalTemplate(TEMPLATE_TYPE_BUILTIN),
+ const [typeOptions, customRes] = await Promise.all([
+ fetchBusinessTypeOptions(),
listApprovalTemplate(TEMPLATE_TYPE_CUSTOM),
]);
- const merged = [
- ...unwrapTemplateList(builtinRes),
- ...unwrapTemplateList(customRes),
- ].filter((row) => mapEnabledFromApi(row.enabled));
- submitTemplateCards.value = merged.map(mapSubmitTemplateCard);
+ submitBusinessTypeOptions.value = typeOptions;
+ allSubmitTemplates.value = unwrapTemplateList(customRes)
+ .filter((row) => mapEnabledFromApi(row.enabled))
+ .map(mapSubmitTemplateCard);
} catch {
- submitTemplateCards.value = [];
+ submitBusinessTypeOptions.value = [];
+ allSubmitTemplates.value = [];
ElMessage.error("鍔犺浇瀹℃壒妯℃澘澶辫触");
} finally {
submitTemplatesLoading.value = false;
@@ -236,6 +259,7 @@
function resetSubmitDialogState() {
submitDialog.mode = "add";
submitDialog.step = 1;
+ selectedBusinessType.value = "";
submitEditRow.value = null;
Object.assign(submitForm, createEmptySubmitForm(""));
}
@@ -256,7 +280,7 @@
return;
}
submitDialog.mode = "edit";
- submitDialog.step = 2;
+ submitDialog.step = 3;
submitEditRow.value = { ...row };
Object.assign(submitForm, buildEditFormFromInstanceRow(row));
submitDialog.visible = true;
@@ -276,10 +300,11 @@
Object.assign(submitForm, {
...base,
templateName: mapped.templateName || tpl.label || "",
+ businessType: mapped.businessType ?? card.businessType ?? selectedBusinessType.value,
templateSnapshot: tpl,
formFieldDefs: tpl.fields || [],
});
- submitDialog.step = 2;
+ submitDialog.step = 3;
} catch {
ElMessage.error("鍔犺浇妯℃澘璇︽儏澶辫触");
} finally {
@@ -287,8 +312,22 @@
}
}
- function backToTemplatePick() {
+ function onBusinessTypePick(type) {
+ if (!countTemplatesByBusinessType(type)) {
+ ElMessage.warning("璇ョ被鍨嬩笅鏆傛棤鍙敤瀹℃壒妯℃澘");
+ return;
+ }
+ selectedBusinessType.value = type;
+ submitDialog.step = 2;
+ }
+
+ function backToBusinessTypePick() {
+ selectedBusinessType.value = "";
submitDialog.step = 1;
+ }
+
+ function backToTemplatePick() {
+ submitDialog.step = 2;
}
async function submitInstanceForm() {
@@ -474,7 +513,12 @@
activeTemplate,
submitFormFields,
submitFormRules,
+ submitBusinessTypeOptions,
submitTemplateCards,
+ selectedBusinessType,
+ selectedBusinessTypeLabel,
+ businessTypeLabel,
+ countTemplatesByBusinessType,
submitTemplatesLoading,
handleQuery,
resetSearch,
@@ -482,7 +526,9 @@
resetSubmitDialogState,
openSubmitDialog,
openEditDialog,
+ onBusinessTypePick,
onTemplatePick,
+ backToBusinessTypePick,
backToTemplatePick,
submitInstanceForm,
submitNewApproval,
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
index 3b5fb21..517e01c 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/approveTemplateConstants.js
@@ -1,4 +1,5 @@
import dayjs from "dayjs";
+import { getTypeEnums } from "@/api/basicData/enum.js";
import { TEMPLATE_TYPE_CUSTOM } from "@/api/officeProcessAutomation/approvalTemplate.js";
import { APPROVAL_TYPE_OPTIONS } from "../approve-list/approveListConstants.js";
import {
@@ -8,6 +9,41 @@
validateFormConfigData,
} from "./formConfigUtils.js";
+export function unwrapEnumList(data) {
+ if (Array.isArray(data)) return data;
+ if (!data || typeof data !== "object") return [];
+ if (Array.isArray(data.TypeEnums)) return data.TypeEnums;
+ if (Array.isArray(data.typeEnums)) return data.typeEnums;
+ const nested = Object.values(data).find((v) => Array.isArray(v));
+ return nested || [];
+}
+
+export function normalizeBusinessTypeOptions(data) {
+ return unwrapEnumList(data)
+ .map((item) => {
+ const rawValue = item?.value ?? item?.code ?? item?.businessType ?? item?.dictValue ?? item?.key;
+ if (rawValue == null || rawValue === "") return null;
+ const num = Number(rawValue);
+ const value =
+ typeof rawValue === "number" || (Number.isFinite(num) && String(rawValue).trim() !== "")
+ ? num
+ : rawValue;
+ const label =
+ item?.label ?? item?.name ?? item?.desc ?? item?.dictLabel ?? item?.text ?? String(value);
+ return { label, value };
+ })
+ .filter(Boolean);
+}
+
+export async function fetchBusinessTypeOptions() {
+ try {
+ const res = await getTypeEnums();
+ return normalizeBusinessTypeOptions(res?.data);
+ } catch {
+ return [];
+ }
+}
+
/** 鑺傜偣鍐呭鎵规柟寮忥細浼氱 / 鎴栫 */
export const NODE_SIGN_MODE_OPTIONS = [
{ value: "countersign", label: "浼氱", desc: "鏈妭鐐规墍鏈夊鎵逛汉鍧囬渶閫氳繃" },
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js
index 0cb20ea..733f463 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/formConfigUtils.js
@@ -264,6 +264,7 @@
}));
return {
label: row?.templateName || "瀹℃壒",
+ businessType: row?.businessType ?? cfg.approvalType ?? "",
approvalType: cfg.approvalType || "",
summaryPlaceholder: cfg.summaryPlaceholder || "",
approvalMode: cfg.approvalMode || "parallel",
diff --git a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
index 3e27afb..95eac7b 100644
--- a/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
+++ b/src/views/officeProcessAutomation/ApproveManage/approve-template/useApproveTemplate.js
@@ -6,13 +6,13 @@
TEMPLATE_TYPE_CUSTOM,
updateApprovalTemplate,
} from "@/api/officeProcessAutomation/approvalTemplate.js";
-import { getTypeEnums } from "@/api/basicData/enum.js";
import { Search } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { reactive, ref } from "vue";
import {
buildApprovalTemplateListParams,
createEmptyTemplateForm,
+ fetchBusinessTypeOptions,
flowNodesSummary,
mapTemplateFromApi,
mapTemplateToApi,
@@ -29,32 +29,6 @@
{ value: 0, label: "绯荤粺鍐呯疆" },
{ value: 1, label: "鑷畾涔�" },
];
-
-function unwrapEnumList(data) {
- if (Array.isArray(data)) return data;
- if (!data || typeof data !== "object") return [];
- if (Array.isArray(data.TypeEnums)) return data.TypeEnums;
- if (Array.isArray(data.typeEnums)) return data.typeEnums;
- const nested = Object.values(data).find((v) => Array.isArray(v));
- return nested || [];
-}
-
-function normalizeTypeEnumOptions(data) {
- return unwrapEnumList(data)
- .map((item) => {
- const rawValue = item?.value ?? item?.code ?? item?.businessType ?? item?.dictValue ?? item?.key;
- if (rawValue == null || rawValue === "") return null;
- const num = Number(rawValue);
- const value =
- typeof rawValue === "number" || (Number.isFinite(num) && String(rawValue).trim() !== "")
- ? num
- : rawValue;
- const label =
- item?.label ?? item?.name ?? item?.desc ?? item?.dictLabel ?? item?.text ?? String(value);
- return { label, value };
- })
- .filter(Boolean);
-}
function matchTemplateTypeValue(options, type) {
if (type == null || type === "") return false;
@@ -99,8 +73,7 @@
async function loadTemplateTypeOptions() {
try {
- const res = await getTypeEnums();
- const list = normalizeTypeEnumOptions(res?.data);
+ const list = await fetchBusinessTypeOptions();
templateTypeOptions.value = list.length ? list : [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
} catch {
templateTypeOptions.value = [...FALLBACK_TEMPLATE_TYPE_OPTIONS];
--
Gitblit v1.9.3