From b725cca0ff60728be04ef2ddb4cde5fcdf80bf8e Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 14 九月 2026 16:15:24 +0800
Subject: [PATCH] feat(bpm): 流程模型列表新增「免审批」开关与全局总开关
---
src/api/bpm/model/index.ts | 2
src/api/bpm/autoApprove/index.ts | 59 ++++++++++++++
src/views/bpm/model/index.vue | 87 ++++++++++++++++++++-
src/views/bpm/model/modules/category-draggable-model.vue | 55 +++++++++++++
src/views/bpm/model/data.ts | 6 +
5 files changed, 205 insertions(+), 4 deletions(-)
diff --git a/src/api/bpm/autoApprove/index.ts b/src/api/bpm/autoApprove/index.ts
new file mode 100644
index 0000000..def749a
--- /dev/null
+++ b/src/api/bpm/autoApprove/index.ts
@@ -0,0 +1,59 @@
+import { requestClient } from '#/api/request';
+
+export namespace BpmAutoApproveApi {
+ /** 娴佺▼鍏嶅鎵归厤缃� */
+ export interface AutoApproveConfig {
+ id: number;
+ /** 娴佺▼瀹氫箟鐨� Key */
+ processDefinitionKey: string;
+ /** 鏄惁鍏嶅鎵癸細true-鎻愪氦鍚庣郴缁熻嚜鍔ㄩ�氳繃锛宖alse-姝e父浜哄伐瀹℃壒 */
+ autoApprove: boolean;
+ /** 澶囨敞 */
+ remark?: string;
+ createTime: string;
+ }
+}
+
+/** 鑾峰彇鍏ㄩ儴娴佺▼鍏嶅鎵归厤缃� */
+export async function getAutoApproveList() {
+ return requestClient.get<BpmAutoApproveApi.AutoApproveConfig[]>(
+ '/bpm/process-auto-approve/list',
+ );
+}
+
+/** 鑾峰緱鍏ㄥ眬鍏嶅鎵规�诲紑鍏崇姸鎬� */
+export async function getGlobalAutoApprove() {
+ return requestClient.get<boolean>('/bpm/process-auto-approve/global');
+}
+
+/** 璁剧疆鍏ㄥ眬鍏嶅鎵规�诲紑鍏筹細寮�鍚悗鎵�鏈夋祦绋嬩竴寰嬪厤瀹℃壒 */
+export async function updateGlobalAutoApprove(
+ autoApprove: boolean,
+ remark?: string,
+) {
+ const params = new URLSearchParams({ autoApprove: String(autoApprove) });
+ if (remark) {
+ params.append('remark', remark);
+ }
+ return requestClient.put<boolean>(
+ `/bpm/process-auto-approve/update-global?${params.toString()}`,
+ );
+}
+
+/** 鎸夋祦绋嬪畾涔夌殑 Key 璁剧疆鍏嶅鎵瑰紑鍏筹紙涓嶅瓨鍦ㄥ垯鏂板銆佸瓨鍦ㄥ垯鏇存柊锛� */
+export async function updateAutoApproveByKey(
+ processDefinitionKey: string,
+ autoApprove: boolean,
+ remark?: string,
+) {
+ const params = new URLSearchParams({
+ processDefinitionKey,
+ autoApprove: String(autoApprove),
+ });
+ if (remark) {
+ params.append('remark', remark);
+ }
+ return requestClient.put<boolean>(
+ `/bpm/process-auto-approve/update-by-key?${params.toString()}`,
+ );
+}
diff --git a/src/api/bpm/model/index.ts b/src/api/bpm/model/index.ts
index e0c033a..8c83a1c 100644
--- a/src/api/bpm/model/index.ts
+++ b/src/api/bpm/model/index.ts
@@ -20,6 +20,8 @@
createTime: string;
bpmnXml: string;
startUsers?: UserInfo[];
+ /** 鏄惁鍏嶅鎵癸紙鐢遍〉闈㈡牴鎹祦绋嬪厤瀹℃壒閰嶇疆鍚堝苟锛岄潪鍚庣杩斿洖瀛楁锛� */
+ autoApprove?: boolean;
}
/** 娴佺▼瀹氫箟 */
diff --git a/src/views/bpm/model/data.ts b/src/views/bpm/model/data.ts
index 59405e7..c1be1bb 100644
--- a/src/views/bpm/model/data.ts
+++ b/src/views/bpm/model/data.ts
@@ -40,6 +40,12 @@
slots: { default: 'deploymentTime' },
},
{
+ field: 'autoApprove',
+ title: '鍏嶅鎵�',
+ minWidth: 110,
+ slots: { default: 'autoApprove' },
+ },
+ {
title: '鎿嶄綔',
width: 150,
fixed: 'right',
diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue
index d7b2b7d..2ed2171 100644
--- a/src/views/bpm/model/index.vue
+++ b/src/views/bpm/model/index.vue
@@ -1,15 +1,37 @@
<script lang="ts" setup>
import type { ModelCategoryInfo } from '#/api/bpm/model';
-import { onActivated, onMounted, reactive, ref, useTemplateRef, watch } from 'vue';
+import {
+ computed,
+ onActivated,
+ onMounted,
+ reactive,
+ ref,
+ useTemplateRef,
+ watch,
+} from 'vue';
+import { useAccess } from '@vben/access';
import { Page, useVbenModal } from '@vben/common-ui';
import { IconifyIcon } from '@vben/icons';
import { cloneDeep } from '@vben/utils';
import { useSortable } from '@vueuse/integrations/useSortable';
-import { Button, Card, Dropdown, Input, Menu, message } from 'ant-design-vue';
+import {
+ Button,
+ Card,
+ Dropdown,
+ Input,
+ Menu,
+ message,
+ Switch,
+ Tooltip,
+} from 'ant-design-vue';
+import {
+ getAutoApproveList,
+ updateGlobalAutoApprove,
+} from '#/api/bpm/autoApprove';
import {
getCategorySimpleList,
updateCategorySortBatch,
@@ -26,6 +48,17 @@
});
const modelListSpinning = ref(false); // 妯″瀷鍒楄〃鍔犺浇鐘舵��
+
+/** 鍏ㄥ眬鍏嶅鎵规�诲紑鍏冲崰鐢ㄧ殑娴佺▼ Key锛堜笌鍚庣 BpmProcessAutoApproveService.GLOBAL_KEY 淇濇寔涓�鑷达級 */
+const GLOBAL_AUTO_APPROVE_KEY = '*';
+const globalAutoApprove = ref(false); // 鍏ㄥ眬鍏嶅鎵规�诲紑鍏�
+const globalAutoApproveLoading = ref(false); // 鎬诲紑鍏虫彁浜ょ姸鎬�
+
+const { hasAccessByCodes } = useAccess();
+/** 鍏嶅鎵瑰紑鍏崇殑鏉冮檺锛氭棤鏉冮檺鏃跺紑鍏崇疆鐏帮紝閬垮厤鐐逛簡鎵嶆姤閿� */
+const hasPermiAutoApprove = computed(() => {
+ return hasAccessByCodes(['bpm:process-auto-approve:update']);
+});
const saveSortLoading = ref(false); // 淇濆瓨鎺掑簭鐘舵��
const categoryGroup = ref<ModelCategoryInfo[]>([]); // 鎸夌収 category 鍒嗙粍鐨勬暟鎹�
@@ -59,8 +92,22 @@
async function getList() {
modelListSpinning.value = true;
try {
- const modelList = await getModelList(queryParams.name);
- const categoryList = await getCategorySimpleList();
+ const [modelList, categoryList, autoApproveList] = await Promise.all([
+ getModelList(queryParams.name),
+ getCategorySimpleList(),
+ getAutoApproveList(),
+ ]);
+ // 鍏嶅鎵归厤缃寜銆屾祦绋� Key銆嶅缓绔嬫槧灏勶紝鍚堝苟鍒版ā鍨嬭鏁版嵁涓婏紝渚涘垪琛ㄥ唴鐨勫厤瀹℃壒寮�鍏冲垪鐩存帴璇诲彇
+ const autoApproveMap = new Map<string, boolean>();
+ autoApproveList.forEach((config) => {
+ autoApproveMap.set(config.processDefinitionKey, config.autoApprove);
+ });
+ modelList.forEach((model: any) => {
+ model.autoApprove = autoApproveMap.get(model.key) ?? false;
+ });
+ // 鍏ㄥ眬鎬诲紑鍏充互鐗规畩 Key 瀛樻斁鍦ㄥ悓涓�鏉¢厤缃噷
+ globalAutoApprove.value =
+ autoApproveMap.get(GLOBAL_AUTO_APPROVE_KEY) ?? false;
// 鎸夌収 category 鑱氬悎
categoryGroup.value = categoryList.map((category: any) => ({
...category,
@@ -142,6 +189,28 @@
sortableInstance.value.option('disabled', true);
}
}
+
+/** 鍒囨崲鍏ㄥ眬鍏嶅鎵规�诲紑鍏筹細寮�鍚悗鎵�鏈夋祦绋嬩竴寰嬪厤瀹℃壒 */
+async function handleGlobalAutoApproveChange(checked: boolean) {
+ globalAutoApprove.value = checked;
+ globalAutoApproveLoading.value = true;
+ try {
+ await updateGlobalAutoApprove(checked);
+ message.success(
+ checked
+ ? '宸插紑鍚叏灞�鍏嶅鎵癸細鎵�鏈夋祦绋嬫彁浜ゅ悗灏嗙洿鎺ラ�氳繃'
+ : '宸插叧闂叏灞�鍏嶅鎵癸細鎭㈠涓烘寜鍚勬祦绋嬪紑鍏冲垽瀹�',
+ );
+ // 閲嶆柊鎷夊彇鍒楄〃锛屽悓姝ュ悇娴佺▼寮�鍏崇殑灞曠ず
+ await getList();
+ } catch (error) {
+ // 澶辫触鍥炴粴
+ globalAutoApprove.value = !checked;
+ console.error('璁剧疆鍏ㄥ眬鍏嶅鎵瑰紑鍏冲け璐�', error);
+ } finally {
+ globalAutoApproveLoading.value = false;
+ }
+}
</script>
<template>
@@ -156,6 +225,16 @@
>
<template #extra>
<div v-if="!isCategorySorting">
+ <Tooltip title="寮�鍚悗鎵�鏈夋祦绋嬩竴寰嬪厤瀹℃壒锛堜紭鍏堜簬鍚勬祦绋嬭嚜宸辩殑寮�鍏筹級">
+ <span class="mr-1">鍏ㄩ儴鍏嶅鎵�</span>
+ </Tooltip>
+ <Switch
+ :checked="globalAutoApprove"
+ :loading="globalAutoApproveLoading"
+ :disabled="!hasPermiAutoApprove"
+ class="mr-3"
+ @change="(checked: any) => handleGlobalAutoApproveChange(checked)"
+ />
<Input
v-model:value="queryParams.name"
placeholder="鎼滅储娴佺▼"
diff --git a/src/views/bpm/model/modules/category-draggable-model.vue b/src/views/bpm/model/modules/category-draggable-model.vue
index 4071c1e..4950b9c 100644
--- a/src/views/bpm/model/modules/category-draggable-model.vue
+++ b/src/views/bpm/model/modules/category-draggable-model.vue
@@ -21,11 +21,13 @@
Dropdown,
Menu,
message,
+ Switch,
Tag,
Tooltip,
} from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
+import { updateAutoApproveByKey } from '#/api/bpm/autoApprove';
import { deleteCategory } from '#/api/bpm/category';
import {
cleanModel,
@@ -64,6 +66,7 @@
const isModelSorting = ref(false);
const originalData = ref<BpmModelApi.Model[]>([]);
const modelList = ref<BpmModelApi.Model[]>([]);
+const autoApproveLoadingId = ref<null | number>(null); // 鍏嶅鎵瑰紑鍏筹細姝e湪鎻愪氦鐨勬ā鍨嬬紪鍙�
// TODO @jason锛氬彲浠ュ叏閮ㄥ睍寮�涔堬紵 @鑺嬭壙 涓婃璁ㄨ銆傚ソ鍍忔槸鍥犱负鎬ц兘闂鎵嶅彧灞曞紑绗竴涓垎绫�
const isExpand = ref(props.isFirst); // 鏍规嵁鏄惁涓虹涓�涓垎绫�, 鏉ヨ缃垵濮嬪睍寮�鐘舵��
@@ -81,6 +84,10 @@
});
const hasPermiDeploy = computed(() => {
return hasAccessByCodes(['bpm:model:deploy']);
+});
+/** 鍏嶅鎵瑰紑鍏崇殑鏉冮檺锛氭棤鏉冮檺鏃跺紑鍏崇疆鐏帮紝閬垮厤鐐逛簡鎵嶆姤閿� */
+const hasPermiAutoApprove = computed(() => {
+ return hasAccessByCodes(['bpm:process-auto-approve:update']);
});
const [Grid, gridApi] = useVbenVxeGrid({
@@ -287,6 +294,32 @@
message.success(`鍙戝竷[${row.name}]娴佺▼鎴愬姛`);
// 鍒锋柊鍒楄〃
emit('success');
+}
+
+/** 鍒囨崲鍏嶅鎵瑰紑鍏筹細寮�鍚悗璇ユ祦绋嬫彁浜ゆ椂涓嶅啀杩涘叆浜哄伐瀹℃壒锛岀敱绯荤粺鑷姩閫氳繃 */
+async function handleAutoApproveChange(checked: boolean, row: any) {
+ const oldValue = row.autoApprove;
+ // 涔愯鏇存柊锛岄伩鍏嶇瓑寰呮帴鍙f湡闂村紑鍏崇姸鎬佸洖璺�
+ row.autoApprove = checked;
+ gridApi.setGridOptions({ data: modelList.value });
+ autoApproveLoadingId.value = row.id;
+ try {
+ await updateAutoApproveByKey(row.key, checked);
+ message.success(
+ checked
+ ? `宸插紑鍚痆${row.name}]鍏嶅鎵癸細璇ユ祦绋嬫彁浜ゅ悗灏嗙敱绯荤粺鑷姩閫氳繃`
+ : `宸插叧闂璠${row.name}]鍏嶅鎵癸細鎭㈠涓烘甯镐汉宸ュ鎵筦,
+ );
+ // 閲嶆柊鎷夊彇鍒楄〃锛屼繚璇佸墠绔姸鎬佷笌鍚庣涓�鑷�
+ emit('success');
+ } catch (error) {
+ // 澶辫触鍥炴粴
+ row.autoApprove = oldValue;
+ gridApi.setGridOptions({ data: modelList.value });
+ console.error('璁剧疆鍏嶅鎵瑰紑鍏冲け璐�', error);
+ } finally {
+ autoApproveLoadingId.value = null;
+ }
}
/** '鏇村'鎿嶄綔鎸夐挳 */
@@ -661,6 +694,28 @@
</Tag>
</div>
</template>
+ <template #autoApprove="{ row }">
+ <div class="flex items-center gap-1">
+ <Switch
+ :checked="row.autoApprove"
+ :loading="autoApproveLoadingId === row.id"
+ :disabled="!hasPermiAutoApprove"
+ size="small"
+ @change="
+ (checked: any) => handleAutoApproveChange(checked, row)
+ "
+ />
+ <Tooltip
+ v-if="!row.processDefinition"
+ title="娴佺▼灏氭湭鍙戝竷锛屽厤瀹℃壒寮�鍏充笉浼氱敓鏁堬紝璇峰厛鍙戝竷娴佺▼"
+ >
+ <IconifyIcon
+ icon="lucide:alert-circle"
+ class="text-base text-orange-400"
+ />
+ </Tooltip>
+ </div>
+ </template>
<template #actions="{ row }">
<div class="flex items-center space-x-0">
<Button
--
Gitblit v1.9.3