!306 Merge remote-tracking branch 'yudao/dev' into dev

Merge pull request !306 from Jason/dev
This commit is contained in:
芋道源码
2025-12-20 07:10:35 +00:00
committed by Gitee
13 changed files with 274 additions and 51 deletions

View File

@@ -16,7 +16,7 @@ import {
} from 'element-plus'; } from 'element-plus';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
// import ProcessListenerSelectModal from '#/views/bpm/processListener/components/process-listener-select-modal.vue'; import { ProcessListenerSelectModal } from '#/views/bpm/processListener/components';
import { createListenerObject, updateElementExtensions } from '../../utils'; import { createListenerObject, updateElementExtensions } from '../../utils';
import ListenerFieldModal from './ListenerFieldModal.vue'; import ListenerFieldModal from './ListenerFieldModal.vue';
@@ -268,15 +268,15 @@ const [FieldModal, fieldModalApi] = useVbenModal({
}); });
// 配置选择监听器 Modal // 配置选择监听器 Modal
// const [ProcessListenerSelectModalComp, processListenerSelectModalApi] = const [ProcessListenerSelectModalComp, processListenerSelectModalApi] =
// useVbenModal({ useVbenModal({
// connectedComponent: ProcessListenerSelectModal, connectedComponent: ProcessListenerSelectModal,
// destroyOnClose: true, destroyOnClose: true,
// }); });
// 打开监听器弹窗 // 打开监听器弹窗
const openProcessListenerDialog = async () => { const openProcessListenerDialog = async () => {
// processListenerSelectModalApi.setData({ type: 'execution' }).open(); processListenerSelectModalApi.setData({ type: 'execution' }).open();
}; };
const selectProcessListener = (listener: any) => { const selectProcessListener = (listener: any) => {
const instances = bpmnInstances(); const instances = bpmnInstances();

View File

@@ -16,7 +16,7 @@ import {
} from 'element-plus'; } from 'element-plus';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
// import ProcessListenerSelectModal from '#/views/bpm/processListener/components/process-listener-select-modal.vue'; import { ProcessListenerSelectModal } from '#/views/bpm/processListener/components';
import { createListenerObject, updateElementExtensions } from '../../utils'; import { createListenerObject, updateElementExtensions } from '../../utils';
import ListenerFieldModal from './ListenerFieldModal.vue'; import ListenerFieldModal from './ListenerFieldModal.vue';
@@ -220,7 +220,7 @@ const removeListenerField = (_: any, index: number) => {
}; };
const openProcessListenerDialog = async () => { const openProcessListenerDialog = async () => {
// processListenerSelectModalApi.setData({ type: 'task' }).open(); processListenerSelectModalApi.setData({ type: 'task' }).open();
}; };
const selectProcessListener = (listener: any) => { const selectProcessListener = (listener: any) => {
const instances = bpmnInstances(); const instances = bpmnInstances();
@@ -253,11 +253,11 @@ const [FieldModal, fieldModalApi] = useVbenModal({
connectedComponent: ListenerFieldModal, connectedComponent: ListenerFieldModal,
}); });
// const [ProcessListenerSelectModalComp, processListenerSelectModalApi] = const [ProcessListenerSelectModalComp, processListenerSelectModalApi] =
// useVbenModal({ useVbenModal({
// connectedComponent: ProcessListenerSelectModal, connectedComponent: ProcessListenerSelectModal,
// destroyOnClose: true, destroyOnClose: true,
// }); });
const [FieldsGrid, fieldsGridApi] = useVbenVxeGrid({ const [FieldsGrid, fieldsGridApi] = useVbenVxeGrid({
gridOptions: { gridOptions: {

View File

@@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { BpmProcessExpressionApi } from '#/api/bpm/processExpression';
import type { BpmUserGroupApi } from '#/api/bpm/userGroup'; import type { BpmUserGroupApi } from '#/api/bpm/userGroup';
import type { SystemPostApi } from '#/api/system/post'; import type { SystemPostApi } from '#/api/system/post';
import type { SystemRoleApi } from '#/api/system/role'; import type { SystemRoleApi } from '#/api/system/role';
@@ -16,6 +17,7 @@ import {
watch, watch,
} from 'vue'; } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { SelectOutlined } from '@vben/icons'; import { SelectOutlined } from '@vben/icons';
import { handleTree } from '@vben/utils'; import { handleTree } from '@vben/utils';
@@ -41,7 +43,7 @@ import {
MULTI_LEVEL_DEPT, MULTI_LEVEL_DEPT,
} from '#/views/bpm/components/simple-process-design/consts'; } from '#/views/bpm/components/simple-process-design/consts';
import { useFormFieldsPermission } from '#/views/bpm/components/simple-process-design/helpers'; import { useFormFieldsPermission } from '#/views/bpm/components/simple-process-design/helpers';
// import ProcessExpressionSelectModal from '#/views/bpm/processExpression/components/process-expression-select-modal.vue'; import { ProcessExpressionSelectModal } from '#/views/bpm/processExpression/components';
defineOptions({ name: 'UserTask' }); defineOptions({ name: 'UserTask' });
const props = defineProps({ const props = defineProps({
@@ -290,21 +292,21 @@ const updateSkipExpression = () => {
}; };
// 打开监听器弹窗 // 打开监听器弹窗
// const [ProcessExpressionSelectModalComp, ProcessExpressionSelectModalApi] = const [ProcessExpressionSelectModalComp, ProcessExpressionSelectModalApi] =
// useVbenModal({ useVbenModal({
// connectedComponent: ProcessExpressionSelectModal, connectedComponent: ProcessExpressionSelectModal,
// destroyOnClose: true, destroyOnClose: true,
// }); });
const openProcessExpressionDialog = async () => { const openProcessExpressionDialog = async () => {
// ProcessExpressionSelectModalApi.open(); ProcessExpressionSelectModalApi.open();
};
const selectProcessExpression = (
expression: BpmProcessExpressionApi.ProcessExpression,
) => {
// @ts-ignore
userTaskForm.value.candidateParam = [expression.expression];
updateElementTask();
}; };
// const selectProcessExpression = (
// expression: BpmProcessExpressionApi.ProcessExpression,
// ) => {
// // @ts-ignore
// userTaskForm.value.candidateParam = [expression.expression];
// updateElementTask();
// };
const handleFormUserChange = (e: any) => { const handleFormUserChange = (e: any) => {
if (e === 'PROCESS_START_USER_ID') { if (e === 'PROCESS_START_USER_ID') {
@@ -551,9 +553,8 @@ onBeforeUnmount(() => {
选择表达式 选择表达式
</ElButton> </ElButton>
</div> </div>
<!-- 选择弹窗 <!-- 选择弹窗 -->
<ProcessExpressionSelectModalComp @select="selectProcessExpression" /> <ProcessExpressionSelectModalComp @select="selectProcessExpression" />
-->
</ElFormItem> </ElFormItem>
<ElFormItem label="跳过表达式" prop="skipExpression"> <ElFormItem label="跳过表达式" prop="skipExpression">

View File

@@ -211,7 +211,7 @@ watch(
<ElInput <ElInput
v-model="cronStr" v-model="cronStr"
readonly readonly
class="w-[400px] font-bold" class="!w-[400px] font-bold"
key="cronStr" key="cronStr"
/> />
</div> </div>
@@ -273,7 +273,7 @@ watch(
:min="f.min" :min="f.min"
:max="f.max" :max="f.max"
size="small" size="small"
class="w-[60px]" class="!w-[100px]"
:key="`range0-${f.key}`" :key="`range0-${f.key}`"
/> />
@@ -282,7 +282,7 @@ watch(
:min="f.min" :min="f.min"
:max="f.max" :max="f.max"
size="small" size="small"
class="w-[60px]" class="!w-[100px]"
:key="`range1-${f.key}`" :key="`range1-${f.key}`"
/> />
之间每{{ f.label }} 之间每{{ f.label }}
@@ -294,7 +294,7 @@ watch(
:min="f.min" :min="f.min"
:max="f.max" :max="f.max"
size="small" size="small"
class="w-[60px]" class="!w-[100px]"
:key="`step0-${f.key}`" :key="`step0-${f.key}`"
/> />
开始每 开始每
@@ -303,7 +303,7 @@ watch(
:min="1" :min="1"
:max="f.max" :max="f.max"
size="small" size="small"
class="w-[60px]" class="!w-[100px]"
:key="`step1-${f.key}`" :key="`step1-${f.key}`"
/> />
{{ f.label }} {{ f.label }}
@@ -342,7 +342,7 @@ watch(
循环次数<ElInputNumber 循环次数<ElInputNumber
v-model="repeat" v-model="repeat"
:min="1" :min="1"
class="w-[100px]" class="!w-[100px]"
key="repeat" key="repeat"
/> />
</div> </div>
@@ -351,7 +351,7 @@ watch(
v-model="isoDate" v-model="isoDate"
type="datetime" type="datetime"
placeholder="选择开始时间" placeholder="选择开始时间"
class="w-[200px]" class="!w-[200px]"
key="isoDate" key="isoDate"
/> />
</div> </div>
@@ -360,7 +360,7 @@ watch(
v-model="isoDuration" v-model="isoDuration"
readonly readonly
placeholder="如P3DT30M30S" placeholder="如P3DT30M30S"
class="w-[200px]" class="!w-[200px]"
key="isoDuration" key="isoDuration"
/> />
</div> </div>
@@ -380,7 +380,7 @@ watch(
<ElInput <ElInput
v-model="durationCustom[unit.key]" v-model="durationCustom[unit.key]"
size="small" size="small"
class="ml-2 w-[60px]" class="ml-2 !w-[60px]"
placeholder="自定义" placeholder="自定义"
@change="setDuration(unit.key, durationCustom[unit.key])" @change="setDuration(unit.key, durationCustom[unit.key])"
/> />

View File

@@ -69,7 +69,7 @@ watch(
<template> <template>
<div> <div>
<div class="mb-2.5"> <div class="mb-2.5">
当前选择<ElInput v-model="isoString" readonly class="w-[300px]" /> 当前选择<ElInput v-model="isoString" readonly class="!w-[300px]" />
</div> </div>
<div v-for="unit in units" :key="unit.key" class="mb-2"> <div v-for="unit in units" :key="unit.key" class="mb-2">
<span>{{ unit.label }}</span> <span>{{ unit.label }}</span>
@@ -86,7 +86,7 @@ watch(
<ElInput <ElInput
v-model="custom[unit.key]" v-model="custom[unit.key]"
size="small" size="small"
class="ml-2 w-[60px]" class="ml-2 !w-[60px]"
placeholder="自定义" placeholder="自定义"
@change="setUnit(unit.key, custom[unit.key])" @change="setUnit(unit.key, custom[unit.key])"
/> />

View File

@@ -1,6 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Dayjs } from 'dayjs';
import type { Ref } from 'vue'; import type { Ref } from 'vue';
import { computed, nextTick, onMounted, ref, toRaw, watch } from 'vue'; import { computed, nextTick, onMounted, ref, toRaw, watch } from 'vue';
@@ -30,7 +28,7 @@ const bpmnInstances = () => (window as any).bpmnInstances;
const type: Ref<string> = ref('time'); const type: Ref<string> = ref('time');
const condition: Ref<string> = ref(''); const condition: Ref<string> = ref('');
const valid: Ref<boolean> = ref(false); const valid: Ref<boolean> = ref(false);
const dateValue = ref<Dayjs>(); const dateValue = ref();
const placeholder = computed<string>(() => { const placeholder = computed<string>(() => {
if (type.value === 'time') return '请输入时间'; if (type.value === 'time') return '请输入时间';
@@ -108,7 +106,6 @@ function validate(): boolean {
// 选择时间 Modal // 选择时间 Modal
const [DateModal, dateModalApi] = useVbenModal({ const [DateModal, dateModalApi] = useVbenModal({
title: '选择时间', title: '选择时间',
class: 'w-[400px]',
onConfirm: onDateConfirm, onConfirm: onDateConfirm,
}); });
@@ -126,7 +123,6 @@ function onDateConfirm(): void {
// 持续时长 Modal // 持续时长 Modal
const [DurationModal, durationModalApi] = useVbenModal({ const [DurationModal, durationModalApi] = useVbenModal({
title: '时间配置', title: '时间配置',
class: 'w-[600px]',
onConfirm: onDurationConfirm, onConfirm: onDurationConfirm,
}); });
@@ -141,7 +137,6 @@ function onDurationConfirm(): void {
// 循环配置 Modal // 循环配置 Modal
const [CycleModal, cycleModalApi] = useVbenModal({ const [CycleModal, cycleModalApi] = useVbenModal({
title: '时间配置', title: '时间配置',
class: 'w-[800px]',
onConfirm: onCycleConfirm, onConfirm: onCycleConfirm,
}); });
@@ -338,7 +333,7 @@ watch(
v-model="dateValue" v-model="dateValue"
type="datetime" type="datetime"
placeholder="选择日期时间" placeholder="选择日期时间"
class="w-full" class="!w-full"
@change="onDateChange" @change="onDateChange"
/> />
</DateModal> </DateModal>
@@ -349,7 +344,7 @@ watch(
</DurationModal> </DurationModal>
<!-- 循环配置器 --> <!-- 循环配置器 -->
<CycleModal> <CycleModal class="w-2/3">
<CycleConfig :value="condition" @change="onCycleChange" /> <CycleConfig :value="condition" @change="onCycleChange" />
</CycleModal> </CycleModal>

View File

@@ -289,7 +289,7 @@ defineExpose({ validate });
</ElFormItem> </ElFormItem>
<ElFormItem label="流程图标"> <ElFormItem label="流程图标">
<ImageUpload <ImageUpload
v-model:value="modelData.icon" v-model="modelData.icon"
:show-description="false" :show-description="false"
width="120px" width="120px"
height="120px" height="120px"

View File

@@ -0,0 +1 @@
export { default as ProcessExpressionSelectModal } from './select-modal.vue';

View File

@@ -0,0 +1,92 @@
<script lang="ts" setup>
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type { BpmProcessExpressionApi } from '#/api/bpm/processExpression';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { CommonStatusEnum } from '@vben/constants';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getProcessExpressionPage } from '#/api/bpm/processExpression';
defineOptions({ name: 'ProcessExpressionSelectModal' });
const emit = defineEmits<{
select: [expression: BpmProcessExpressionApi.ProcessExpression];
}>();
// 查询参数
const queryParams = ref({
status: CommonStatusEnum.ENABLE,
});
// 配置 VxeGrid
const [Grid] = useVbenVxeGrid({
gridOptions: {
columns: [
{ field: 'name', title: '名字', minWidth: 160 },
{ field: 'expression', title: '表达式', minWidth: 260 },
{
field: 'action',
title: '操作',
width: 120,
slots: { default: 'action' },
},
],
showOverflow: true,
minHeight: 300,
proxyConfig: {
ajax: {
// 查询表达式列表
query: async ({ page }) => {
return await getProcessExpressionPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
status: queryParams.value.status,
});
},
},
} as VxeGridPropTypes.ProxyConfig,
rowConfig: {
keyField: 'id',
isHover: true,
},
toolbarConfig: {
enabled: false,
},
},
});
// 配置 Modal
const [Modal, modalApi] = useVbenModal({
showConfirmButton: false,
destroyOnClose: true,
});
// 选择表达式
function handleSelect(row: BpmProcessExpressionApi.ProcessExpression) {
emit('select', row);
modalApi.close();
}
</script>
<template>
<Modal class="w-4/5" title="请选择表达式">
<Grid>
<template #action="{ row }">
<TableAction
:actions="[
{
label: '选择',
type: 'primary',
link: true,
icon: 'lucide:pointer',
onClick: handleSelect.bind(null, row),
},
]"
/>
</template>
</Grid>
</Modal>
</template>

View File

@@ -0,0 +1,36 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import { DICT_TYPE } from '@vben/constants';
/** 选择监听器弹窗的列表字段 */
export function useGridColumns(): VxeTableGridOptions['columns'] {
return [
{ field: 'name', title: '名字', minWidth: 120 },
{
field: 'type',
title: '类型',
minWidth: 200,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_TYPE },
},
},
{ field: 'event', title: '事件', minWidth: 200 },
{
field: 'valueType',
title: '值类型',
minWidth: 200,
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE },
},
},
{ field: 'value', title: '值', minWidth: 150 },
{
title: '操作',
width: 100,
slots: { default: 'action' },
fixed: 'right',
},
];
}

View File

@@ -0,0 +1 @@
export { default as ProcessListenerSelectModal } from './select-modal.vue';

View File

@@ -0,0 +1,96 @@
<script lang="ts" setup>
import type { VxeGridPropTypes } from '#/adapter/vxe-table';
import type { BpmProcessListenerApi } from '#/api/bpm/processListener';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { CommonStatusEnum } from '@vben/constants';
import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getProcessListenerPage } from '#/api/bpm/processListener';
import { useGridColumns } from './data';
defineOptions({ name: 'ProcessListenerSelectModal' });
const emit = defineEmits<{
select: [listener: BpmProcessListenerApi.ProcessListener];
}>();
// 查询参数
const queryParams = ref({
type: '',
status: CommonStatusEnum.ENABLE,
});
// 配置 VxeGrid
const [Grid] = useVbenVxeGrid({
gridOptions: {
columns: useGridColumns(),
showOverflow: true,
minHeight: 300,
proxyConfig: {
ajax: {
query: async ({ page }) => {
return await getProcessListenerPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
type: queryParams.value.type,
status: queryParams.value.status,
});
},
},
} as VxeGridPropTypes.ProxyConfig,
rowConfig: {
keyField: 'id',
isHover: true,
},
toolbarConfig: {
enabled: false,
},
},
});
// 配置 Modal
const [Modal, modalApi] = useVbenModal({
showConfirmButton: false,
onOpenChange: async (isOpen: boolean) => {
if (!isOpen) {
queryParams.value.type = '';
return;
}
const data = modalApi.getData<{ type: string }>();
if (data?.type) {
queryParams.value.type = data.type;
}
},
destroyOnClose: true,
});
// 选择监听器
function handleSelect(row: BpmProcessListenerApi.ProcessListener) {
emit('select', row);
modalApi.close();
}
</script>
<template>
<Modal class="w-4/5" title="请选择监听器">
<Grid>
<template #action="{ row }">
<TableAction
:actions="[
{
label: '选择',
type: 'primary',
link: true,
icon: 'lucide:pointer',
onClick: handleSelect.bind(null, row),
},
]"
/>
</template>
</Grid>
</Modal>
</template>

View File

@@ -5,7 +5,8 @@
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"#/*": ["./src/*"] "#/*": ["./src/*"]
} },
"allowJs": true
}, },
"references": [{ "path": "./tsconfig.node.json" }], "references": [{ "path": "./tsconfig.node.json" }],
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"] "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"]