mirror of
https://gitee.com/cai_xiao_feng/lowflow-design.git
synced 2025-12-08 00:58:23 +08:00
执行监听器
This commit is contained in:
parent
a0c7db739a
commit
d65509f2eb
140
src/typings/auto-imports.d.ts
vendored
140
src/typings/auto-imports.d.ts
vendored
@ -5,73 +5,85 @@
|
|||||||
// Generated by unplugin-auto-import
|
// Generated by unplugin-auto-import
|
||||||
export {}
|
export {}
|
||||||
declare global {
|
declare global {
|
||||||
const EffectScope: typeof import('vue')['EffectScope']
|
const EffectScope: (typeof import('vue'))['EffectScope']
|
||||||
const ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
const ElCheckbox: (typeof import('element-plus/es'))['ElCheckbox']
|
||||||
const ElDivider: typeof import('element-plus/es')['ElDivider']
|
const ElDivider: (typeof import('element-plus/es'))['ElDivider']
|
||||||
const ElInput: typeof import('element-plus/es')['ElInput']
|
const ElInput: (typeof import('element-plus/es'))['ElInput']
|
||||||
const ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
const ElInputNumber: (typeof import('element-plus/es'))['ElInputNumber']
|
||||||
const ElRadio: typeof import('element-plus/es')['ElRadio']
|
const ElRadio: (typeof import('element-plus/es'))['ElRadio']
|
||||||
const ElSelect: typeof import('element-plus/es')['ElSelect']
|
const ElSelect: (typeof import('element-plus/es'))['ElSelect']
|
||||||
const computed: typeof import('vue')['computed']
|
const computed: (typeof import('vue'))['computed']
|
||||||
const createApp: typeof import('vue')['createApp']
|
const createApp: (typeof import('vue'))['createApp']
|
||||||
const customRef: typeof import('vue')['customRef']
|
const customRef: (typeof import('vue'))['customRef']
|
||||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent']
|
||||||
const defineComponent: typeof import('vue')['defineComponent']
|
const defineComponent: (typeof import('vue'))['defineComponent']
|
||||||
const effectScope: typeof import('vue')['effectScope']
|
const effectScope: (typeof import('vue'))['effectScope']
|
||||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
const getCurrentInstance: (typeof import('vue'))['getCurrentInstance']
|
||||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
const getCurrentScope: (typeof import('vue'))['getCurrentScope']
|
||||||
const h: typeof import('vue')['h']
|
const h: (typeof import('vue'))['h']
|
||||||
const inject: typeof import('vue')['inject']
|
const inject: (typeof import('vue'))['inject']
|
||||||
const isProxy: typeof import('vue')['isProxy']
|
const isProxy: (typeof import('vue'))['isProxy']
|
||||||
const isReactive: typeof import('vue')['isReactive']
|
const isReactive: (typeof import('vue'))['isReactive']
|
||||||
const isReadonly: typeof import('vue')['isReadonly']
|
const isReadonly: (typeof import('vue'))['isReadonly']
|
||||||
const isRef: typeof import('vue')['isRef']
|
const isRef: (typeof import('vue'))['isRef']
|
||||||
const markRaw: typeof import('vue')['markRaw']
|
const markRaw: (typeof import('vue'))['markRaw']
|
||||||
const nextTick: typeof import('vue')['nextTick']
|
const nextTick: (typeof import('vue'))['nextTick']
|
||||||
const onActivated: typeof import('vue')['onActivated']
|
const onActivated: (typeof import('vue'))['onActivated']
|
||||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
const onBeforeMount: (typeof import('vue'))['onBeforeMount']
|
||||||
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
|
const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave']
|
||||||
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
|
const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate']
|
||||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount']
|
||||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate']
|
||||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
const onDeactivated: (typeof import('vue'))['onDeactivated']
|
||||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
const onErrorCaptured: (typeof import('vue'))['onErrorCaptured']
|
||||||
const onMounted: typeof import('vue')['onMounted']
|
const onMounted: (typeof import('vue'))['onMounted']
|
||||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
const onRenderTracked: (typeof import('vue'))['onRenderTracked']
|
||||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
const onRenderTriggered: (typeof import('vue'))['onRenderTriggered']
|
||||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
const onScopeDispose: (typeof import('vue'))['onScopeDispose']
|
||||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
const onServerPrefetch: (typeof import('vue'))['onServerPrefetch']
|
||||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
const onUnmounted: (typeof import('vue'))['onUnmounted']
|
||||||
const onUpdated: typeof import('vue')['onUpdated']
|
const onUpdated: (typeof import('vue'))['onUpdated']
|
||||||
const provide: typeof import('vue')['provide']
|
const provide: (typeof import('vue'))['provide']
|
||||||
const reactive: typeof import('vue')['reactive']
|
const reactive: (typeof import('vue'))['reactive']
|
||||||
const readonly: typeof import('vue')['readonly']
|
const readonly: (typeof import('vue'))['readonly']
|
||||||
const ref: typeof import('vue')['ref']
|
const ref: (typeof import('vue'))['ref']
|
||||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
const resolveComponent: (typeof import('vue'))['resolveComponent']
|
||||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
const shallowReactive: (typeof import('vue'))['shallowReactive']
|
||||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
const shallowReadonly: (typeof import('vue'))['shallowReadonly']
|
||||||
const shallowRef: typeof import('vue')['shallowRef']
|
const shallowRef: (typeof import('vue'))['shallowRef']
|
||||||
const toRaw: typeof import('vue')['toRaw']
|
const toRaw: (typeof import('vue'))['toRaw']
|
||||||
const toRef: typeof import('vue')['toRef']
|
const toRef: (typeof import('vue'))['toRef']
|
||||||
const toRefs: typeof import('vue')['toRefs']
|
const toRefs: (typeof import('vue'))['toRefs']
|
||||||
const toValue: typeof import('vue')['toValue']
|
const toValue: (typeof import('vue'))['toValue']
|
||||||
const triggerRef: typeof import('vue')['triggerRef']
|
const triggerRef: (typeof import('vue'))['triggerRef']
|
||||||
const unref: typeof import('vue')['unref']
|
const unref: (typeof import('vue'))['unref']
|
||||||
const useAttrs: typeof import('vue')['useAttrs']
|
const useAttrs: (typeof import('vue'))['useAttrs']
|
||||||
const useCssModule: typeof import('vue')['useCssModule']
|
const useCssModule: (typeof import('vue'))['useCssModule']
|
||||||
const useCssVars: typeof import('vue')['useCssVars']
|
const useCssVars: (typeof import('vue'))['useCssVars']
|
||||||
const useLink: typeof import('vue-router')['useLink']
|
const useLink: (typeof import('vue-router'))['useLink']
|
||||||
const useRoute: typeof import('vue-router')['useRoute']
|
const useRoute: (typeof import('vue-router'))['useRoute']
|
||||||
const useRouter: typeof import('vue-router')['useRouter']
|
const useRouter: (typeof import('vue-router'))['useRouter']
|
||||||
const useSlots: typeof import('vue')['useSlots']
|
const useSlots: (typeof import('vue'))['useSlots']
|
||||||
const watch: typeof import('vue')['watch']
|
const watch: (typeof import('vue'))['watch']
|
||||||
const watchEffect: typeof import('vue')['watchEffect']
|
const watchEffect: (typeof import('vue'))['watchEffect']
|
||||||
const watchPostEffect: typeof import('vue')['watchPostEffect']
|
const watchPostEffect: (typeof import('vue'))['watchPostEffect']
|
||||||
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
|
const watchSyncEffect: (typeof import('vue'))['watchSyncEffect']
|
||||||
}
|
}
|
||||||
// for type re-export
|
// for type re-export
|
||||||
declare global {
|
declare global {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
|
export type {
|
||||||
|
Component,
|
||||||
|
ComponentPublicInstance,
|
||||||
|
ComputedRef,
|
||||||
|
ExtractDefaultPropTypes,
|
||||||
|
ExtractPropTypes,
|
||||||
|
ExtractPublicPropTypes,
|
||||||
|
InjectionKey,
|
||||||
|
PropType,
|
||||||
|
Ref,
|
||||||
|
VNode,
|
||||||
|
WritableComputedRef
|
||||||
|
} from 'vue'
|
||||||
import('vue')
|
import('vue')
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/typings/components.d.ts
vendored
1
src/typings/components.d.ts
vendored
@ -9,6 +9,7 @@ declare module 'vue' {
|
|||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
AdvancedFilter: typeof import('./../components/AdvancedFilter/index.vue')['default']
|
AdvancedFilter: typeof import('./../components/AdvancedFilter/index.vue')['default']
|
||||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||||
|
ElBadge: typeof import('element-plus/es')['ElBadge']
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
|
ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
|
|||||||
@ -203,6 +203,7 @@ const addApproval = (node: FlowNode) => {
|
|||||||
pid: node.id,
|
pid: node.id,
|
||||||
type: 'approval',
|
type: 'approval',
|
||||||
name: '审批人',
|
name: '审批人',
|
||||||
|
executionListeners: [],
|
||||||
child: child,
|
child: child,
|
||||||
// 属性
|
// 属性
|
||||||
assigneeType: 'user',
|
assigneeType: 'user',
|
||||||
|
|||||||
@ -1,22 +1,62 @@
|
|||||||
<script setup lang="ts"></script>
|
<script setup lang="ts">
|
||||||
|
import type { FlowNode } from '@/views/flowDesign/nodes/type'
|
||||||
|
import type { Ref } from 'vue'
|
||||||
|
|
||||||
|
const _inject = inject<{
|
||||||
|
readOnly?: Ref<boolean>
|
||||||
|
}>('flowDesign', { readOnly: ref(false) })
|
||||||
|
const $emits = defineEmits<{
|
||||||
|
(e: 'activeNode', node: FlowNode): void
|
||||||
|
}>()
|
||||||
|
const $props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
node: FlowNode
|
||||||
|
readOnly?: boolean
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
readOnly: false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const _readOnly = computed(() => _inject.readOnly?.value || $props.readOnly)
|
||||||
|
const activeNode = () => {
|
||||||
|
if (_readOnly.value) return
|
||||||
|
$emits('activeNode', $props.node)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="end-node">
|
<div class="node-box">
|
||||||
<div class="end-node-circle" />
|
<div class="end-node-circle"></div>
|
||||||
<el-text>流程结束</el-text>
|
<div class="end-node" @click="activeNode">
|
||||||
|
<el-text>{{ node.name }}</el-text>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.end-node {
|
.node-box {
|
||||||
padding: 0 0 30px;
|
position: relative;
|
||||||
|
|
||||||
.end-node-circle {
|
.end-node-circle {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: var(--el-border-color);
|
background-color: var(--el-border-color);
|
||||||
margin: auto;
|
margin: auto auto 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.end-node {
|
||||||
|
position: relative;
|
||||||
|
background: var(--el-border-color-lighter);
|
||||||
|
padding: 7px 24px;
|
||||||
|
border-radius: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: visible;
|
||||||
|
z-index: 10;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 5px 0 var(--el-color-primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -15,9 +15,16 @@ export interface FlowNode {
|
|||||||
pid?: string
|
pid?: string
|
||||||
name: string
|
name: string
|
||||||
type: NodeType
|
type: NodeType
|
||||||
|
executionListeners?: NodeListener[]
|
||||||
child?: FlowNode
|
child?: FlowNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NodeListener {
|
||||||
|
event: string
|
||||||
|
implementationType: 'class' | 'expression' | 'delegateExpression'
|
||||||
|
implementation: string
|
||||||
|
}
|
||||||
|
|
||||||
export interface StartNode extends FlowNode {
|
export interface StartNode extends FlowNode {
|
||||||
formProperties: FormProperty[]
|
formProperties: FormProperty[]
|
||||||
}
|
}
|
||||||
@ -77,6 +84,8 @@ export interface ApprovalNode extends AssigneeNode {
|
|||||||
formProperties: FormProperty[]
|
formProperties: FormProperty[]
|
||||||
// 操作权限
|
// 操作权限
|
||||||
operations: OperationPermissions
|
operations: OperationPermissions
|
||||||
|
// 任务监听器
|
||||||
|
taskListeners?: NodeListener[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TimerNode extends FlowNode {
|
export interface TimerNode extends FlowNode {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import type { Field } from '@/components/Render/type'
|
|||||||
import UserSelector from '@/components/UserSelector/index.vue'
|
import UserSelector from '@/components/UserSelector/index.vue'
|
||||||
import AssigneePanel from './AssigneePanel.vue'
|
import AssigneePanel from './AssigneePanel.vue'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
|
import TaskListeners from './TaskListeners.vue'
|
||||||
|
|
||||||
const { fields } = inject<{ fields: Ref<Field[]>; admin: string[] }>('flowDesign', {
|
const { fields } = inject<{ fields: Ref<Field[]>; admin: string[] }>('flowDesign', {
|
||||||
fields: ref([]),
|
fields: ref([]),
|
||||||
@ -133,6 +134,9 @@ watchEffect(() => {
|
|||||||
placeholder="指定人员"
|
placeholder="指定人员"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="taskListeners" label="任务监听器">
|
||||||
|
<TaskListeners :node="activeData" />
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="表单权限" name="formPermissions">
|
<el-tab-pane label="表单权限" name="formPermissions">
|
||||||
|
|||||||
18
src/views/flowDesign/panels/EndPanel.vue
Normal file
18
src/views/flowDesign/panels/EndPanel.vue
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { EndNode } from '../nodes/type'
|
||||||
|
import ExecutionListeners from './ExecutionListeners.vue'
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
activeData: EndNode
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-form label-position="top" label-width="90px">
|
||||||
|
<el-form-item prop="executionListeners" label="执行监听器">
|
||||||
|
<ExecutionListeners :node="activeData" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
107
src/views/flowDesign/panels/ExecutionListeners.vue
Normal file
107
src/views/flowDesign/panels/ExecutionListeners.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { FlowNode } from '@/views/flowDesign/nodes/type'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
node: FlowNode
|
||||||
|
}>()
|
||||||
|
const drawer = ref(false)
|
||||||
|
const addListener = () => {
|
||||||
|
if (!props.node.executionListeners) {
|
||||||
|
props.node.executionListeners = []
|
||||||
|
}
|
||||||
|
props.node.executionListeners?.push({
|
||||||
|
event: 'start',
|
||||||
|
implementationType: 'delegateExpression',
|
||||||
|
implementation: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const delListener = (index: number) => {
|
||||||
|
props.node.executionListeners?.splice(index, 1)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot>
|
||||||
|
<el-badge :value="node.executionListeners?.length || 0" class="item" type="primary">
|
||||||
|
<el-button icon="Setting" @click="drawer = true"> 配置</el-button>
|
||||||
|
</el-badge>
|
||||||
|
</slot>
|
||||||
|
<el-drawer v-model="drawer" title="执行监听器">
|
||||||
|
<div class="flex-col">
|
||||||
|
<el-button @click="addListener" type="primary" icon="Plus">添加监听器</el-button>
|
||||||
|
<div v-for="(item, index) in node.executionListeners" :key="index" class="listener-box">
|
||||||
|
<el-button
|
||||||
|
class="listener-close"
|
||||||
|
@click="delListener(index)"
|
||||||
|
plain
|
||||||
|
circle
|
||||||
|
icon="CircleClose"
|
||||||
|
size="small"
|
||||||
|
type="danger"
|
||||||
|
/>
|
||||||
|
<el-form-item label="事件" :prop="`executionListeners.${index}.event`">
|
||||||
|
<el-radio-group v-model="item.event">
|
||||||
|
<el-radio-button label="开始" value="start" />
|
||||||
|
<el-radio-button label="结束" value="end" />
|
||||||
|
<el-radio-button label="迁移" value="take" />
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类型" :prop="`executionListeners.${index}.implementationType`">
|
||||||
|
<el-radio-group v-model="item.implementationType">
|
||||||
|
<el-radio-button label="委托表达式" value="delegateExpression" />
|
||||||
|
<el-radio-button label="java类" value="class" />
|
||||||
|
<el-radio-button label="表达式" value="expression" />
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="监听器" :prop="`executionListeners.${index}.implementation`">
|
||||||
|
<template #label>
|
||||||
|
<div class="flex-items-center gap3px">
|
||||||
|
<span>监听器</span>
|
||||||
|
<el-tooltip placement="top-start">
|
||||||
|
<template #content>
|
||||||
|
实现 ExecutionListener 接口 <br />
|
||||||
|
委托表达式:${myExecutionListener} <br />
|
||||||
|
表达式: ${myExecutionListener.notify(execution)} <br />
|
||||||
|
java类:${com.example.listener.MyExecutionListener}
|
||||||
|
</template>
|
||||||
|
<el-icon>
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-input v-model="item.implementation" placeholder="请输入监听器" clearable>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.listener-box {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: var(--el-border-radius-base);
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
|
||||||
|
.listener-close {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.listener-close {
|
||||||
|
position: absolute;
|
||||||
|
top: -7px;
|
||||||
|
right: -7px;
|
||||||
|
z-index: 1;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -2,11 +2,13 @@
|
|||||||
import type { FormProperty, StartNode } from '../nodes/type'
|
import type { FormProperty, StartNode } from '../nodes/type'
|
||||||
import type { Field } from '@/components/Render/type'
|
import type { Field } from '@/components/Render/type'
|
||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
|
import ExecutionListeners from './ExecutionListeners.vue'
|
||||||
|
|
||||||
const { fields } = inject<{ fields: Ref<Field[]> }>('flowDesign', { fields: ref([]) })
|
const { fields } = inject<{ fields: Ref<Field[]> }>('flowDesign', { fields: ref([]) })
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
activeData: StartNode
|
activeData: StartNode
|
||||||
}>()
|
}>()
|
||||||
|
const activeName = ref('basicSettings')
|
||||||
const allReadonly = computed({
|
const allReadonly = computed({
|
||||||
get() {
|
get() {
|
||||||
return props.activeData.formProperties.every((e) => e.readonly)
|
return props.activeData.formProperties.every((e) => e.readonly)
|
||||||
@ -84,33 +86,46 @@ watchEffect(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-table :data="activeData.formProperties">
|
<el-tabs v-model="activeName" stretch class="el-segmented">
|
||||||
<el-table-column prop="name" label="字段" />
|
<el-tab-pane label="基础设置" name="basicSettings">
|
||||||
<el-table-column prop="readonly">
|
<el-form label-position="top" label-width="90px">
|
||||||
<template #header>
|
<el-form-item prop="executionListeners" label="执行监听器">
|
||||||
<el-checkbox v-model="allReadonly" label="只读" />
|
<ExecutionListeners :node="activeData" />
|
||||||
</template>
|
</el-form-item>
|
||||||
<template #default="{ row }">
|
</el-form>
|
||||||
<el-checkbox v-model="row.readonly" @change="changeReadonly(row)" />
|
</el-tab-pane>
|
||||||
</template>
|
<el-tab-pane label="表单权限" name="formPermissions">
|
||||||
</el-table-column>
|
<el-table :data="activeData.formProperties">
|
||||||
<el-table-column prop="required">
|
<el-table-column prop="name" label="字段" />
|
||||||
<template #header>
|
<el-table-column prop="readonly">
|
||||||
<el-checkbox v-model="allRequired" label="必填" />
|
<template #header>
|
||||||
</template>
|
<el-checkbox v-model="allReadonly" label="只读" />
|
||||||
<template #default="{ row }">
|
</template>
|
||||||
<el-checkbox v-model="row.required" @change="changeRequired(row)" />
|
<template #default="{ row }">
|
||||||
</template>
|
<el-checkbox v-model="row.readonly" @change="changeReadonly(row)" />
|
||||||
</el-table-column>
|
</template>
|
||||||
<el-table-column prop="hidden">
|
</el-table-column>
|
||||||
<template #header>
|
<el-table-column prop="required">
|
||||||
<el-checkbox v-model="allHidden" label="隐藏" />
|
<template #header>
|
||||||
</template>
|
<el-checkbox v-model="allRequired" label="必填" />
|
||||||
<template #default="{ row }">
|
</template>
|
||||||
<el-checkbox v-model="row.hidden" @change="changeHidden(row)" />
|
<template #default="{ row }">
|
||||||
</template>
|
<el-checkbox v-model="row.required" @change="changeRequired(row)" />
|
||||||
</el-table-column>
|
</template>
|
||||||
</el-table>
|
</el-table-column>
|
||||||
|
<el-table-column prop="hidden">
|
||||||
|
<template #header>
|
||||||
|
<el-checkbox v-model="allHidden" label="隐藏" />
|
||||||
|
</template>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-checkbox v-model="row.hidden" @change="changeHidden(row)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss"></style>
|
<style scoped lang="scss">
|
||||||
|
@import '@/styles/el-segmented.scss';
|
||||||
|
</style>
|
||||||
|
|||||||
107
src/views/flowDesign/panels/TaskListeners.vue
Normal file
107
src/views/flowDesign/panels/TaskListeners.vue
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { ApprovalNode } from '@/views/flowDesign/nodes/type'
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
node: ApprovalNode
|
||||||
|
}>()
|
||||||
|
const drawer = ref(false)
|
||||||
|
const addListener = () => {
|
||||||
|
if (!props.node.taskListeners) {
|
||||||
|
props.node.taskListeners = []
|
||||||
|
}
|
||||||
|
props.node.taskListeners?.push({
|
||||||
|
event: 'create',
|
||||||
|
implementationType: 'delegateExpression',
|
||||||
|
implementation: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const delListener = (index: number) => {
|
||||||
|
props.node.taskListeners?.splice(index, 1)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<slot>
|
||||||
|
<el-badge :value="node.taskListeners?.length || 0" class="item" type="primary">
|
||||||
|
<el-button icon="Setting" @click="drawer = true"> 配置</el-button>
|
||||||
|
</el-badge>
|
||||||
|
</slot>
|
||||||
|
<el-drawer v-model="drawer" title="任务监听器">
|
||||||
|
<div class="flex-col">
|
||||||
|
<el-button @click="addListener" type="primary" icon="Plus">添加监听器</el-button>
|
||||||
|
<div v-for="(item, index) in node.taskListeners" :key="index" class="listener-box">
|
||||||
|
<el-button
|
||||||
|
class="listener-close"
|
||||||
|
@click="delListener(index)"
|
||||||
|
plain
|
||||||
|
circle
|
||||||
|
icon="CircleClose"
|
||||||
|
size="small"
|
||||||
|
type="danger"
|
||||||
|
/>
|
||||||
|
<el-form-item label="事件" :prop="`taskListeners.${index}.event`">
|
||||||
|
<el-radio-group v-model="item.event">
|
||||||
|
<el-radio-button label="创建" value="create" />
|
||||||
|
<el-radio-button label="指派" value="assignment" />
|
||||||
|
<el-radio-button label="完成" value="complete" />
|
||||||
|
<el-radio-button label="删除" value="delete" />
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="类型" :prop="`taskListeners.${index}.implementationType`">
|
||||||
|
<el-radio-group v-model="item.implementationType">
|
||||||
|
<el-radio-button label="委托表达式" value="delegateExpression" />
|
||||||
|
<el-radio-button label="java类" value="class" />
|
||||||
|
<el-radio-button label="表达式" value="expression" />
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="监听器" :prop="`taskListeners.${index}.implementation`">
|
||||||
|
<template #label>
|
||||||
|
<div class="flex-items-center gap3px">
|
||||||
|
<span>监听器</span>
|
||||||
|
<el-tooltip placement="top-start">
|
||||||
|
<template #content>
|
||||||
|
委托表达式:${myCreateTaskListener} <br />
|
||||||
|
表达式: ${myCreateTaskListener.notify(execution)} <br />
|
||||||
|
java类:${com.example.listener.MyCreateTaskListener}
|
||||||
|
</template>
|
||||||
|
<el-icon>
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-input v-model="item.implementation" placeholder="请输入监听器" clearable>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.listener-box {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: var(--el-border-radius-base);
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 7px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
|
||||||
|
.listener-close {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.listener-close {
|
||||||
|
position: absolute;
|
||||||
|
top: -7px;
|
||||||
|
right: -7px;
|
||||||
|
z-index: 1;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -7,6 +7,7 @@ import Cc from './CcPanel.vue'
|
|||||||
import Timer from './TimerPanel.vue'
|
import Timer from './TimerPanel.vue'
|
||||||
import Notify from './NotifyPanel.vue'
|
import Notify from './NotifyPanel.vue'
|
||||||
import Condition from './ConditionPanel.vue'
|
import Condition from './ConditionPanel.vue'
|
||||||
|
import End from './EndPanel.vue'
|
||||||
import type { FlowNode } from '../nodes/type'
|
import type { FlowNode } from '../nodes/type'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@ -19,7 +20,8 @@ const panels: Recordable<Component> = {
|
|||||||
cc: Cc,
|
cc: Cc,
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
notify: Notify,
|
notify: Notify,
|
||||||
condition: Condition
|
condition: Condition,
|
||||||
|
end: End
|
||||||
}
|
}
|
||||||
const showInput = ref(false)
|
const showInput = ref(false)
|
||||||
const onClickOutside = () => {
|
const onClickOutside = () => {
|
||||||
|
|||||||
@ -10,12 +10,14 @@ const process = ref<FlowNode>({
|
|||||||
pid: undefined,
|
pid: undefined,
|
||||||
type: 'start',
|
type: 'start',
|
||||||
name: '发起人',
|
name: '发起人',
|
||||||
|
executionListeners: [],
|
||||||
formProperties: [],
|
formProperties: [],
|
||||||
child: {
|
child: {
|
||||||
id: 'end',
|
id: 'end',
|
||||||
pid: 'root',
|
pid: 'root',
|
||||||
type: 'end',
|
type: 'end',
|
||||||
name: '结束',
|
name: '流程结束',
|
||||||
|
executionListeners: [],
|
||||||
child: undefined
|
child: undefined
|
||||||
} as EndNode
|
} as EndNode
|
||||||
} as StartNode)
|
} as StartNode)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user