main
commit
a1fab2bf8a
|
|
@ -184,5 +184,8 @@
|
|||
".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*"
|
||||
},
|
||||
"terminal.integrated.scrollback": 10000,
|
||||
"nuxt.isNuxtApp": false
|
||||
"nuxt.isNuxtApp": false,
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,17 +79,23 @@
|
|||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
"ant-design-vue": "^4.0.8",
|
||||
"axios": "^1.6.4",
|
||||
"bpmn-js": "^17.0.2",
|
||||
"bpmn-js-properties-panel": "^5.13.0",
|
||||
"bpmn-js-token-simulation": "^0.33.1",
|
||||
"codemirror": "^5.65.16",
|
||||
"cropperjs": "^1.6.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"diagram-js": "^14.1.0",
|
||||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.4.3",
|
||||
"exceljs": "^4.4.0",
|
||||
"highlight.js": "^11.9.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mars3d": "^3.7.0",
|
||||
"mars3d-cesium": "^1.113.0",
|
||||
"min-dash": "^4.2.1",
|
||||
"mockjs": "^1.1.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"path-to-regexp": "^6.2.1",
|
||||
|
|
@ -118,7 +124,8 @@
|
|||
"xe-utils": "^3.5.14",
|
||||
"xlsx": "^0.18.5",
|
||||
"kml-geojson": "^1.2.2",
|
||||
"localforage": "^1.10.0"
|
||||
"localforage": "^1.10.0",
|
||||
"xml-js": "^1.6.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.4.4",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-02-05 16:06:58
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\api\sys\user.ts
|
||||
* @Description:
|
||||
*/
|
||||
import { defHttp } from '@/utils/http/axios';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-01 15:55:24
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-02 16:08:00
|
||||
* @Description:
|
||||
*/
|
||||
import { withInstall } from '@/utils';
|
||||
|
||||
import bWflowViewer from './src/bWflowViewer.vue'
|
||||
|
||||
export const BWflowViewer = withInstall(bWflowViewer);
|
||||
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<a-button class="ml-2" title="撤销" :icon="h(RedoOutlined)" @click="handleUndo"> </a-button>
|
||||
<a-button title="复原" :icon="h(UndoOutlined)" @click="handleRedo"> </a-button>
|
||||
<a-button class="ml-2" title=" 重做" :icon="h(StopOutlined)"> </a-button>
|
||||
<a-button title="放大" :icon="h(PlusCircleOutlined)"> </a-button>
|
||||
<a-button title="缩小" :icon="h(MinusCircleOutlined)"> </a-button>
|
||||
<a-button title="下载" :icon="h(SearchOutlined)" @click="handleDownload"> </a-button>
|
||||
|
||||
<div id="container"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { h, ref, onMounted, reactive } from 'vue';
|
||||
import { RedoOutlined, UndoOutlined, StopOutlined, PlusCircleOutlined, MinusCircleOutlined, SearchOutlined } from '@ant-design/icons-vue';
|
||||
import { Button } from 'ant-design-vue';
|
||||
|
||||
import BpmnModeler from 'bpmn-js/lib/Modeler';
|
||||
import camundaExtension from './js/camunda.json'; //定义各个元素拥有的属性配置
|
||||
import customTranslate from "./js/customTranslate.js";//汉化
|
||||
import EventEmitter from './utils/EventEmitter'
|
||||
const state = reactive({
|
||||
containerEl: null,
|
||||
bpmnModeler: null,
|
||||
fileList: [],
|
||||
});
|
||||
EventEmitter.instance.on('modeler-init', (modeler) => {
|
||||
modeler.on('element.click', (element) => {
|
||||
console.log(element)
|
||||
currentElement.value = element
|
||||
})
|
||||
})
|
||||
function create() {
|
||||
state.bpmnModeler.createDiagram(() => {
|
||||
state.bpmnModeler.get('canvas').zoom('fit-viewport');
|
||||
});
|
||||
}
|
||||
function handleRemove(file) {
|
||||
for (let i = 0; i < state.fileList.length; i++) {
|
||||
if (file.name === state.fileList[i].name) {
|
||||
state.fileList.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
function beforeRemove(file) {
|
||||
return this.$confirm(`确定移除 ${file.name}?`);
|
||||
}
|
||||
// 后退
|
||||
function handleUndo() {
|
||||
state.bpmnModeler.get('commandStack').undo();
|
||||
}
|
||||
// 前进
|
||||
function handleRedo() {
|
||||
state.bpmnModeler.get('commandStack').redo();
|
||||
}
|
||||
function handleDownload() {
|
||||
console.log(state.bpmnModeler)
|
||||
|
||||
state.bpmnModeler.saveXML({ format: true }, (err, data) => {
|
||||
console.log(data)
|
||||
// const dataTrack = 'bpmn';
|
||||
// const a = document.createElement('a');
|
||||
// const name = `diagram.${dataTrack}`;
|
||||
// a.setAttribute(
|
||||
// 'href',
|
||||
// `data:application/bpmn20-xml;charset=UTF-8,${encodeURIComponent(data)}`
|
||||
// );
|
||||
// a.setAttribute('target', '_blank');
|
||||
// a.setAttribute('dataTrack', `diagram:download-${dataTrack}`);
|
||||
// a.setAttribute('download', name);
|
||||
// document.body.appendChild(a);
|
||||
// a.click();
|
||||
// document.body.removeChild(a);
|
||||
});
|
||||
}
|
||||
function handleOnchangeFile(file) {
|
||||
const reader = new FileReader();
|
||||
let data = '';
|
||||
reader.readAsText(file.raw);
|
||||
reader.onload = (event) => {
|
||||
data = event.target.result;
|
||||
state.bpmnModeler.importXML(data, (err) => {
|
||||
if (err) {
|
||||
this.$message.info('导入失败');
|
||||
} else {
|
||||
this.$message.success('导入成功');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
let customTranslateModule = {
|
||||
translate: ["value", customTranslate]
|
||||
};
|
||||
state.containerEl = document.querySelector('#container');
|
||||
state.bpmnModeler = new BpmnModeler({
|
||||
container: state.containerEl,
|
||||
moddleExtensions: { camunda: camundaExtension },
|
||||
additionalModules: [
|
||||
// 汉化
|
||||
customTranslateModule,
|
||||
],
|
||||
});
|
||||
create();
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#container {
|
||||
height: calc(100% - 50px);
|
||||
background-size: 20px 20px, 20px 20px, 10px 10px, 10px 10px;
|
||||
background-image: linear-gradient(to right, #dfdfdf 1px, transparent 1px), linear-gradient(to bottom, #dfdfdf 1px, transparent 1px), linear-gradient(to right, #f1f1f1 1px, transparent 1px), linear-gradient(to bottom, #f1f1f1 1px, transparent 1px);
|
||||
background-position: left -1px top -1px, left -1px top -1px, left -1px top -1px, left -1px top -1px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,14 @@
|
|||
import translations from './translations';
|
||||
|
||||
|
||||
export default function customTranslate(template, replacements) {
|
||||
replacements = replacements || {};
|
||||
|
||||
// Translate
|
||||
template = translations[template] || template;
|
||||
|
||||
// Replace
|
||||
return template.replace(/{([^}]+)}/g, function(_, key) {
|
||||
return replacements[key] || '{' + key + '}';
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
export default {
|
||||
// hong
|
||||
// Labels
|
||||
'Activate the global connect tool' : '激活全局连接工具',
|
||||
'Append {type}': '追加 {type}',
|
||||
'Append EndEvent': '追加 结束事件 ',
|
||||
'Append Task':'追加 任务',
|
||||
'Append Gateway':'追加 网关',
|
||||
'Append Intermediate/Boundary Event':'追加 中间/边界 事件',
|
||||
'Add Lane above': '在上面添加道',
|
||||
'Divide into two Lanes': '分割成两个道',
|
||||
'Divide into three Lanes': '分割成三个道',
|
||||
'Add Lane below': '在下面添加道',
|
||||
'Append compensation activity': '追加补偿活动',
|
||||
'Change type': '修改类型',
|
||||
'Connect using Association': '使用关联连接',
|
||||
'Connect using Sequence/MessageFlow or Association': '使用顺序/消息流或者关联连接',
|
||||
'Connect using DataInputAssociation': '使用数据输入关联连接',
|
||||
'Remove': '移除',
|
||||
'Activate the hand tool': '激活抓手工具',
|
||||
'Activate the lasso tool': '激活套索工具',
|
||||
'Activate the create/remove space tool': '激活创建/删除空间工具',
|
||||
'Create expanded SubProcess': '创建扩展子过程',
|
||||
'Create IntermediateThrowEvent/BoundaryEvent' : '创建中间抛出事件/边界事件',
|
||||
'Create Pool/Participant': '创建池/参与者',
|
||||
'Parallel Multi Instance': '并行多重事件',
|
||||
'Sequential Multi Instance': '时序多重事件',
|
||||
'DataObjectReference':'数据对象参考',
|
||||
'DataStoreReference':'数据存储参考',
|
||||
'Loop': '循环',
|
||||
'Ad-hoc': '即席',
|
||||
'Create {type}': '创建 {type}',
|
||||
'Create Task':'创建任务',
|
||||
'Create StartEvent':'创建开始事件',
|
||||
'Create EndEvent':'创建结束事件',
|
||||
'Create Group':'创建组',
|
||||
'Task': '任务',
|
||||
'Send Task': '发送任务',
|
||||
'Receive Task': '接收任务',
|
||||
'User Task': '用户任务',
|
||||
'Manual Task': '手工任务',
|
||||
'Business Rule Task': '业务规则任务',
|
||||
'Service Task': '服务任务',
|
||||
'Script Task': '脚本任务',
|
||||
'Call Activity': '调用活动',
|
||||
'Sub Process (collapsed)': '子流程(折叠的)',
|
||||
'Sub Process (expanded)': '子流程(展开的)',
|
||||
'Start Event': '开始事件',
|
||||
'StartEvent': '开始事件',
|
||||
'Intermediate Throw Event': '中间事件',
|
||||
'End Event': '结束事件',
|
||||
'EndEvent': '结束事件',
|
||||
'Create Gateway': '创建网关',
|
||||
'GateWay':'网关',
|
||||
'Create Intermediate/Boundary Event': '创建中间/边界事件',
|
||||
'Message Start Event': '消息开始事件',
|
||||
'Timer Start Event': '定时开始事件',
|
||||
'Conditional Start Event': '条件开始事件',
|
||||
'Signal Start Event': '信号开始事件',
|
||||
'Error Start Event': '错误开始事件',
|
||||
'Escalation Start Event': '升级开始事件',
|
||||
'Compensation Start Event': '补偿开始事件',
|
||||
'Message Start Event (non-interrupting)': '消息开始事件(非中断)',
|
||||
'Timer Start Event (non-interrupting)': '定时开始事件(非中断)',
|
||||
'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)',
|
||||
'Signal Start Event (non-interrupting)': '信号开始事件(非中断)',
|
||||
'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)',
|
||||
'Message Intermediate Catch Event': '消息中间捕获事件',
|
||||
'Message Intermediate Throw Event': '消息中间抛出事件',
|
||||
'Timer Intermediate Catch Event': '定时中间捕获事件',
|
||||
'Escalation Intermediate Throw Event': '升级中间抛出事件',
|
||||
'Conditional Intermediate Catch Event': '条件中间捕获事件',
|
||||
'Link Intermediate Catch Event': '链接中间捕获事件',
|
||||
'Link Intermediate Throw Event': '链接中间抛出事件',
|
||||
'Compensation Intermediate Throw Event': '补偿中间抛出事件',
|
||||
'Signal Intermediate Catch Event': '信号中间捕获事件',
|
||||
'Signal Intermediate Throw Event': '信号中间抛出事件',
|
||||
'Message End Event': '消息结束事件',
|
||||
'Escalation End Event': '定时结束事件',
|
||||
'Error End Event': '错误结束事件',
|
||||
'Cancel End Event': '取消结束事件',
|
||||
'Compensation End Event': '补偿结束事件',
|
||||
'Signal End Event': '信号结束事件',
|
||||
'Terminate End Event': '终止结束事件',
|
||||
'Message Boundary Event': '消息边界事件',
|
||||
'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)',
|
||||
'Timer Boundary Event': '定时边界事件',
|
||||
'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)',
|
||||
'Escalation Boundary Event': '升级边界事件',
|
||||
'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)',
|
||||
'Conditional Boundary Event': '条件边界事件',
|
||||
'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)',
|
||||
'Error Boundary Event': '错误边界事件',
|
||||
'Cancel Boundary Event': '取消边界事件',
|
||||
'Signal Boundary Event': '信号边界事件',
|
||||
'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)',
|
||||
'Compensation Boundary Event': '补偿边界事件',
|
||||
'Exclusive Gateway': '互斥网关',
|
||||
'Parallel Gateway': '并行网关',
|
||||
'Inclusive Gateway': '相容网关',
|
||||
'Complex Gateway': '复杂网关',
|
||||
'Event based Gateway': '事件网关',
|
||||
'Transaction': '转运',
|
||||
'Sub Process': '子流程',
|
||||
'Event Sub Process': '事件子流程',
|
||||
'Collapsed Pool': '折叠池',
|
||||
'Expanded Pool': '展开池',
|
||||
// Errors
|
||||
'no parent for {element} in {parent}': '在{parent}里,{element}没有父类',
|
||||
'no shape type specified': '没有指定的形状类型',
|
||||
'flow elements must be children of pools/participants': '流元素必须是池/参与者的子类',
|
||||
'out of bounds release': 'out of bounds release',
|
||||
'more than {count} child lanes': '子道大于{count} ',
|
||||
'element required': '元素不能为空',
|
||||
'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范',
|
||||
'no diagram to display': '没有可展示的流程图',
|
||||
'no process or collaboration to display': '没有可展示的流程/协作',
|
||||
'element {element} referenced by {referenced}#{property} not yet drawn': '由{referenced}#{property}引用的{element}元素仍未绘制',
|
||||
'already rendered {element}': '{element} 已被渲染',
|
||||
'failed to import {element}': '导入{element}失败',
|
||||
//属性面板的参数
|
||||
'Id':'编号',
|
||||
'Name':'名称',
|
||||
'General':'常规',
|
||||
'Details':'详情',
|
||||
'Message Name':'消息名称',
|
||||
'Message':'消息',
|
||||
'Initiator':'创建者',
|
||||
'Asynchronous Continuations':'持续异步',
|
||||
'Asynchronous Before':'异步前',
|
||||
'Asynchronous After':'异步后',
|
||||
'Job Configuration':'工作配置',
|
||||
'Exclusive':'排除',
|
||||
'Job Priority':'工作优先级',
|
||||
'Retry Time Cycle':'重试时间周期',
|
||||
'Documentation':'文档',
|
||||
'Element Documentation':'元素文档',
|
||||
'History Configuration':'历史配置',
|
||||
'History Time To Live':'历史的生存时间',
|
||||
'Forms':'表单',
|
||||
'Form Key':'表单key',
|
||||
'Form Fields':'表单字段',
|
||||
'Business Key':'业务key',
|
||||
'Form Field':'表单字段',
|
||||
'ID':'编号',
|
||||
'Type':'类型',
|
||||
'Label':'名称',
|
||||
'Default Value':'默认值',
|
||||
'Validation':'校验',
|
||||
'Add Constraint':'添加约束',
|
||||
'Config':'配置',
|
||||
'Properties':'属性',
|
||||
'Add Property':'添加属性',
|
||||
'Value':'值',
|
||||
'Add':'添加',
|
||||
'Values':'值',
|
||||
'Add Value':'添加值',
|
||||
'Listeners':'监听器',
|
||||
'Execution Listener':'执行监听',
|
||||
'Event Type':'事件类型',
|
||||
'Listener Type':'监听器类型',
|
||||
'Java Class':'Java类',
|
||||
'Expression':'表达式',
|
||||
'Must provide a value':'必须提供一个值',
|
||||
'Delegate Expression':'代理表达式',
|
||||
'Script':'脚本',
|
||||
'Script Format':'脚本格式',
|
||||
'Script Type':'脚本类型',
|
||||
'Inline Script':'内联脚本',
|
||||
'External Script':'外部脚本',
|
||||
'Resource':'资源',
|
||||
'Field Injection':'字段注入',
|
||||
'Extensions':'扩展',
|
||||
'Input/Output':'输入/输出',
|
||||
'Input Parameters':'输入参数',
|
||||
'Output Parameters':'输出参数',
|
||||
'Parameters':'参数',
|
||||
'Output Parameter':'输出参数',
|
||||
'Timer Definition Type':'定时器定义类型',
|
||||
'Timer Definition':'定时器定义',
|
||||
'Date':'日期',
|
||||
'Duration':'持续',
|
||||
'Cycle':'循环',
|
||||
'Signal':'信号',
|
||||
'Signal Name':'信号名称',
|
||||
'Escalation':'升级',
|
||||
'Error':'错误',
|
||||
'Link Name':'链接名称',
|
||||
'Condition':'条件名称',
|
||||
'Variable Name':'变量名称',
|
||||
'Variable Event':'变量事件',
|
||||
'Specify more than one variable change event as a comma separated list.':'多个变量事件以逗号隔开',
|
||||
'Wait for Completion':'等待完成',
|
||||
'Activity Ref':'活动参考',
|
||||
'Version Tag':'版本标签',
|
||||
'Executable':'可执行文件',
|
||||
'External Task Configuration':'扩展任务配置',
|
||||
'Task Priority':'任务优先级',
|
||||
'External':'外部',
|
||||
'Connector':'连接器',
|
||||
'Must configure Connector':'必须配置连接器',
|
||||
'Connector Id':'连接器编号',
|
||||
'Implementation':'实现方式',
|
||||
'Field Injections':'字段注入',
|
||||
'Fields':'字段',
|
||||
'Result Variable':'结果变量',
|
||||
'Topic':'主题',
|
||||
'Configure Connector':'配置连接器',
|
||||
'Input Parameter':'输入参数',
|
||||
'Assignee':'代理人',
|
||||
'Candidate Users':'候选用户',
|
||||
'Candidate Groups':'候选组',
|
||||
'Due Date':'到期时间',
|
||||
'Follow Up Date':'跟踪日期',
|
||||
'Priority':'优先级',
|
||||
'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)':'跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
|
||||
'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)':'跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
|
||||
'Variables':'变量',
|
||||
'Candidate Starter Configuration':'候选开始配置',
|
||||
'Task Listener':'任务监听器',
|
||||
'Candidate Starter Groups':'候选开始组',
|
||||
'Candidate Starter Users':'候选开始用户',
|
||||
'Tasklist Configuration':'任务列表配置',
|
||||
'Startable':'启动',
|
||||
'Specify more than one group as a comma separated list.':'指定多个组,用逗号分隔',
|
||||
'Specify more than one user as a comma separated list.':'指定多个用户,用逗号分隔',
|
||||
'This maps to the process definition key.':'这会映射为流程定义的键',
|
||||
'CallActivity Type':'调用活动类型',
|
||||
'Condition Type':'条件类型',
|
||||
'Create UserTask':'创建用户任务',
|
||||
'Create CallActivity':'创建调用活动',
|
||||
'Called Element':'调用元素',
|
||||
'Create DataObjectReference':'创建数据对象引用',
|
||||
'Create DataStoreReference':'创建数据存储引用',
|
||||
'Multi Instance':'多实例',
|
||||
'Loop Cardinality':'实例数量',
|
||||
'Collection':'任务参与人列表',
|
||||
'Element Variable':'元素变量',
|
||||
'Completion Condition':'完成条件'
|
||||
};
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
declare class EventEmitter {
|
||||
private _events;
|
||||
private static _instance;
|
||||
static instance(): EventEmitter;
|
||||
constructor();
|
||||
private _addListener;
|
||||
addListener(type: string, fn: any, context?: any): this;
|
||||
on(type: string, fn: any, context?: any): this;
|
||||
once(type: string, fn: any, context?: any): this;
|
||||
emit(type: any, ...rest: any[]): boolean;
|
||||
removeListener(type: any, fn: any): this;
|
||||
removeAllListeners(type: any): this;
|
||||
listeners(type: any): Function[];
|
||||
listenerCount(type: any): number;
|
||||
eventNames(): string[];
|
||||
}
|
||||
declare const _default: {
|
||||
EventEmitter: typeof EventEmitter;
|
||||
instance: EventEmitter;
|
||||
};
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
import { getRawType, notNull } from './tools';
|
||||
const isArray = (obj) => getRawType(obj) === 'array';
|
||||
const isNullOrUndefined = (obj) => !notNull(obj);
|
||||
class EventEmitter {
|
||||
_events = {};
|
||||
static _instance = null;
|
||||
static instance() {
|
||||
// 单例模式
|
||||
if (!this._instance) {
|
||||
this._instance = new EventEmitter();
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
constructor() {
|
||||
if (this._events === undefined) {
|
||||
this._events = Object.create(null);
|
||||
}
|
||||
}
|
||||
_addListener(type, fn, context, once) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('fn must be a function');
|
||||
}
|
||||
fn.context = context;
|
||||
fn.once = !!once;
|
||||
const event = this._events[type];
|
||||
// only one, let `this._events[type]` to be a function
|
||||
if (isNullOrUndefined(event)) {
|
||||
this._events[type] = fn;
|
||||
}
|
||||
else if (typeof event === 'function') {
|
||||
// already has one function, `this._events[type]` must be a function before
|
||||
this._events[type] = [event, fn];
|
||||
}
|
||||
else if (isArray(event)) {
|
||||
// already has more than one function, just push
|
||||
this._events[type].push(fn);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
addListener(type, fn, context) {
|
||||
return this._addListener(type, fn, context);
|
||||
}
|
||||
on(type, fn, context) {
|
||||
return this.addListener(type, fn, context);
|
||||
}
|
||||
once(type, fn, context) {
|
||||
return this._addListener(type, fn, context, true);
|
||||
}
|
||||
emit(type, ...rest) {
|
||||
if (isNullOrUndefined(type)) {
|
||||
throw new Error('emit must receive at lease one argument');
|
||||
}
|
||||
const event = this._events[type];
|
||||
if (isNullOrUndefined(event))
|
||||
return false;
|
||||
if (typeof event === 'function') {
|
||||
event.call(event.context || null, ...rest);
|
||||
if (event.once) {
|
||||
this.removeListener(type, event);
|
||||
}
|
||||
}
|
||||
else if (isArray(event)) {
|
||||
event.map((e) => {
|
||||
e.call(e.context || null, ...rest);
|
||||
if (e.once) {
|
||||
this.removeListener(type, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
removeListener(type, fn) {
|
||||
if (isNullOrUndefined(this._events))
|
||||
return this;
|
||||
// if type is undefined or null, nothing to do, just return this
|
||||
if (isNullOrUndefined(type))
|
||||
return this;
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error('fn must be a function');
|
||||
}
|
||||
const events = this._events[type];
|
||||
if (typeof events === 'function') {
|
||||
events === fn && delete this._events[type];
|
||||
}
|
||||
else {
|
||||
const findIndex = events.findIndex((e) => e === fn);
|
||||
if (findIndex === -1)
|
||||
return this;
|
||||
// match the first one, shift faster than splice
|
||||
if (findIndex === 0) {
|
||||
events.shift();
|
||||
}
|
||||
else {
|
||||
events.splice(findIndex, 1);
|
||||
}
|
||||
// just left one listener, change Array to Function
|
||||
if (events.length === 1) {
|
||||
// @ts-ignore
|
||||
this._events[type] = events[0];
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
removeAllListeners(type) {
|
||||
if (isNullOrUndefined(this._events))
|
||||
return this;
|
||||
// if not provide type, remove all
|
||||
if (isNullOrUndefined(type))
|
||||
this._events = Object.create(null);
|
||||
const events = this._events[type];
|
||||
if (!isNullOrUndefined(events)) {
|
||||
// check if `type` is the last one
|
||||
if (Object.keys(this._events).length === 1) {
|
||||
this._events = Object.create(null);
|
||||
}
|
||||
else {
|
||||
delete this._events[type];
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
listeners(type) {
|
||||
if (isNullOrUndefined(this._events))
|
||||
return [];
|
||||
const events = this._events[type];
|
||||
// use `map` because we need to return a new array
|
||||
return isNullOrUndefined(events) ? [] : typeof events === 'function' ? [events] : events.map((o) => o);
|
||||
}
|
||||
listenerCount(type) {
|
||||
if (isNullOrUndefined(this._events))
|
||||
return 0;
|
||||
const events = this._events[type];
|
||||
return isNullOrUndefined(events) ? 0 : typeof events === 'function' ? 1 : events.length;
|
||||
}
|
||||
eventNames() {
|
||||
if (isNullOrUndefined(this._events))
|
||||
return [];
|
||||
return Object.keys(this._events);
|
||||
}
|
||||
}
|
||||
export default { EventEmitter, instance: EventEmitter.instance() };
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
import { getRawType, notNull } from './tools'
|
||||
|
||||
const isArray = (obj) => getRawType(obj) === 'array'
|
||||
const isNullOrUndefined = (obj) => !notNull(obj)
|
||||
|
||||
class EventEmitter {
|
||||
private _events: { [key: string]: Function[] } = {}
|
||||
private static _instance: null | EventEmitter = null
|
||||
|
||||
static instance(): EventEmitter {
|
||||
// 单例模式
|
||||
if (!this._instance) {
|
||||
this._instance = new EventEmitter()
|
||||
}
|
||||
return this._instance
|
||||
}
|
||||
|
||||
constructor() {
|
||||
if (this._events === undefined) {
|
||||
this._events = Object.create(null)
|
||||
}
|
||||
}
|
||||
|
||||
private _addListener(type: string, fn: any, context?: any, once?) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('fn must be a function')
|
||||
}
|
||||
|
||||
fn.context = context
|
||||
fn.once = !!once
|
||||
|
||||
const event = this._events[type]
|
||||
// only one, let `this._events[type]` to be a function
|
||||
if (isNullOrUndefined(event)) {
|
||||
this._events[type] = fn
|
||||
} else if (typeof event === 'function') {
|
||||
// already has one function, `this._events[type]` must be a function before
|
||||
this._events[type] = [event, fn]
|
||||
} else if (isArray(event)) {
|
||||
// already has more than one function, just push
|
||||
this._events[type].push(fn)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
addListener(type: string, fn: any, context?: any) {
|
||||
return this._addListener(type, fn, context)
|
||||
}
|
||||
|
||||
on(type: string, fn: any, context?: any) {
|
||||
return this.addListener(type, fn, context)
|
||||
}
|
||||
|
||||
once(type: string, fn: any, context?: any) {
|
||||
return this._addListener(type, fn, context, true)
|
||||
}
|
||||
|
||||
emit(type, ...rest) {
|
||||
if (isNullOrUndefined(type)) {
|
||||
throw new Error('emit must receive at lease one argument')
|
||||
}
|
||||
|
||||
const event: any = this._events[type]
|
||||
|
||||
if (isNullOrUndefined(event)) return false
|
||||
|
||||
if (typeof event === 'function') {
|
||||
event.call(event.context || null, ...rest)
|
||||
if (event.once) {
|
||||
this.removeListener(type, event)
|
||||
}
|
||||
} else if (isArray(event)) {
|
||||
event.map((e) => {
|
||||
e.call(e.context || null, ...rest)
|
||||
if (e.once) {
|
||||
this.removeListener(type, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
removeListener(type, fn) {
|
||||
if (isNullOrUndefined(this._events)) return this
|
||||
|
||||
// if type is undefined or null, nothing to do, just return this
|
||||
if (isNullOrUndefined(type)) return this
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new Error('fn must be a function')
|
||||
}
|
||||
|
||||
const events = this._events[type]
|
||||
|
||||
if (typeof events === 'function') {
|
||||
events === fn && delete this._events[type]
|
||||
} else {
|
||||
const findIndex = events.findIndex((e) => e === fn)
|
||||
|
||||
if (findIndex === -1) return this
|
||||
|
||||
// match the first one, shift faster than splice
|
||||
if (findIndex === 0) {
|
||||
events.shift()
|
||||
} else {
|
||||
events.splice(findIndex, 1)
|
||||
}
|
||||
|
||||
// just left one listener, change Array to Function
|
||||
if (events.length === 1) {
|
||||
// @ts-ignore
|
||||
this._events[type] = events[0]
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
removeAllListeners(type) {
|
||||
if (isNullOrUndefined(this._events)) return this
|
||||
|
||||
// if not provide type, remove all
|
||||
if (isNullOrUndefined(type)) this._events = Object.create(null)
|
||||
|
||||
const events = this._events[type]
|
||||
if (!isNullOrUndefined(events)) {
|
||||
// check if `type` is the last one
|
||||
if (Object.keys(this._events).length === 1) {
|
||||
this._events = Object.create(null)
|
||||
} else {
|
||||
delete this._events[type]
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
listeners(type) {
|
||||
if (isNullOrUndefined(this._events)) return []
|
||||
|
||||
const events = this._events[type]
|
||||
// use `map` because we need to return a new array
|
||||
return isNullOrUndefined(events) ? [] : typeof events === 'function' ? [events] : events.map((o) => o)
|
||||
}
|
||||
|
||||
listenerCount(type) {
|
||||
if (isNullOrUndefined(this._events)) return 0
|
||||
|
||||
const events = this._events[type]
|
||||
|
||||
return isNullOrUndefined(events) ? 0 : typeof events === 'function' ? 1 : events.length
|
||||
}
|
||||
|
||||
eventNames() {
|
||||
if (isNullOrUndefined(this._events)) return []
|
||||
|
||||
return Object.keys(this._events)
|
||||
}
|
||||
}
|
||||
|
||||
export default { EventEmitter, instance: EventEmitter.instance() }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
declare const _default: (key: string, name: string, type?: string | undefined) => string;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
export default (key, name, type) => {
|
||||
if (!type)
|
||||
type = 'camunda';
|
||||
const TYPE_TARGET = {
|
||||
activiti: 'http://activiti.org/bpmn',
|
||||
camunda: 'http://bpmn.io/schema/bpmn',
|
||||
flowable: 'http://flowable.org/bpmn'
|
||||
};
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn2:definitions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
||||
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
|
||||
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
|
||||
id="diagram_${key}"
|
||||
targetNamespace="${TYPE_TARGET[type]}">
|
||||
<bpmn2:process id="${key}" name="${name}" isExecutable="true">
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${key}">
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>`;
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
export default (key: string, name: string, type?: string): string => {
|
||||
if (!type) type = 'camunda'
|
||||
const TYPE_TARGET = {
|
||||
activiti: 'http://activiti.org/bpmn',
|
||||
camunda: 'http://bpmn.io/schema/bpmn',
|
||||
flowable: 'http://flowable.org/bpmn'
|
||||
}
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn2:definitions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
||||
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
|
||||
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
|
||||
id="diagram_${key}"
|
||||
targetNamespace="${TYPE_TARGET[type]}">
|
||||
<bpmn2:process id="${key}" name="${name}" isExecutable="true">
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${key}">
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>`
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
declare function setLocal(key: string, value: any): void;
|
||||
declare function getLocal(key: string): any;
|
||||
declare const _default: {
|
||||
setLocal: typeof setLocal;
|
||||
getLocal: typeof getLocal;
|
||||
};
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
function setLocal(key, value) {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
function getLocal(key) {
|
||||
return JSON.parse(localStorage.getItem(key) || '');
|
||||
}
|
||||
export default {
|
||||
setLocal,
|
||||
getLocal
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
function setLocal(key: string, value: any) {
|
||||
localStorage.setItem(key, JSON.stringify(value))
|
||||
}
|
||||
|
||||
function getLocal(key: string) {
|
||||
return JSON.parse(localStorage.getItem(key) || '')
|
||||
}
|
||||
|
||||
export default {
|
||||
setLocal,
|
||||
getLocal
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
export declare function noop(): void;
|
||||
/**
|
||||
* 校验非空
|
||||
* @param {*} val
|
||||
* @return boolean
|
||||
*/
|
||||
export declare function notEmpty(val: any): any;
|
||||
export declare function notNull(val: any): boolean;
|
||||
/**
|
||||
* 返回数据原始类型
|
||||
* @param value
|
||||
* @return { 'string' | 'array' | 'boolean' | 'number' | 'object' | 'function' } type
|
||||
*/
|
||||
export declare function getRawType(value: any): string;
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* 空函数 */
|
||||
export function noop() { }
|
||||
/**
|
||||
* 校验非空
|
||||
* @param {*} val
|
||||
* @return boolean
|
||||
*/
|
||||
export function notEmpty(val) {
|
||||
if (!notNull(val)) {
|
||||
return false;
|
||||
}
|
||||
if (getRawType(val) === 'array') {
|
||||
return val.length;
|
||||
}
|
||||
if (getRawType(val) === 'object') {
|
||||
return Reflect.ownKeys(val).length;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
export function notNull(val) {
|
||||
return val !== undefined && val !== null;
|
||||
}
|
||||
/**
|
||||
* 返回数据原始类型
|
||||
* @param value
|
||||
* @return { 'string' | 'array' | 'boolean' | 'number' | 'object' | 'function' } type
|
||||
*/
|
||||
export function getRawType(value) {
|
||||
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/* 空函数 */
|
||||
export function noop() {}
|
||||
|
||||
/**
|
||||
* 校验非空
|
||||
* @param {*} val
|
||||
* @return boolean
|
||||
*/
|
||||
export function notEmpty(val) {
|
||||
if (!notNull(val)) {
|
||||
return false
|
||||
}
|
||||
if (getRawType(val) === 'array') {
|
||||
return val.length
|
||||
}
|
||||
if (getRawType(val) === 'object') {
|
||||
return Reflect.ownKeys(val).length
|
||||
}
|
||||
return true
|
||||
}
|
||||
export function notNull(val) {
|
||||
return val !== undefined && val !== null
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回数据原始类型
|
||||
* @param value
|
||||
* @return { 'string' | 'array' | 'boolean' | 'number' | 'object' | 'function' } type
|
||||
*/
|
||||
export function getRawType(value) {
|
||||
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-25 10:05:50
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-26 09:52:37
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\components\PermissionBtn\index.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
@ -18,7 +17,6 @@
|
|||
import { router } from '@/router';
|
||||
import { defineEmits } from 'vue'
|
||||
const btnList = router.currentRoute.value.meta.elements ?router.currentRoute.value.meta.elements :[]
|
||||
console.log(btnList)
|
||||
btnList.sort((a, b) => {
|
||||
return (a.sort || 0) - (b.sort || 0);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<div class="process-design" :style="'display: flex; height:' + data.height">
|
||||
<bpmn-process-designer v-model="data.xmlString" v-bind="data.controlForm" keyboard ref="processDesigner" :events="[
|
||||
'element.click',
|
||||
'connection.added',
|
||||
'connection.removed',
|
||||
'connection.changed'
|
||||
]" @element-click="elementClick" @init-finished="initModeler" @event="handlerEvent" @save="onSaveProcess" />
|
||||
<!-- 属性面板 -->
|
||||
<bmpn-process-penal :element="data.element" :bpmn-modeler="data.modeler" :prefix="data.controlForm.prefix" class="process-panel" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { h, reactive, onMounted, defineProps, computed, defineEmits } from 'vue';
|
||||
import './package/theme/index.scss';
|
||||
// 流程面板和属性面板
|
||||
import { BpmnProcessDesigner, BmpnProcessPenal } from './package/index';
|
||||
import 'highlight.js/styles/atom-one-dark-reasonable.css';
|
||||
const emit = defineEmits(['save']);
|
||||
|
||||
// Vue.use(vuePlugin);
|
||||
const props = defineProps({
|
||||
bpmnXml: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
designerForm: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
const data = reactive({
|
||||
height: document.documentElement.clientHeight - 94.5 + "px;",
|
||||
xmlString: props.bpmnXml,
|
||||
modeler: null,
|
||||
controlForm: {
|
||||
processId: props.designerForm.processKey || '',
|
||||
processName: props.designerForm.processName || '',
|
||||
simulation: false,
|
||||
labelEditing: false,
|
||||
labelVisible: false,
|
||||
prefix: 'flowable',
|
||||
headerButtonSize: 'small',
|
||||
// additionalModel: [CustomContentPadProvider, CustomPaletteProvider]
|
||||
},
|
||||
element:null,
|
||||
})
|
||||
function elementClick(element) {
|
||||
data.element = element;
|
||||
}
|
||||
function initModeler(modeler) {
|
||||
setTimeout(() => {
|
||||
data.modeler = modeler;
|
||||
}, 10);
|
||||
}
|
||||
function handlerEvent(eventName, element) {
|
||||
}
|
||||
function onSaveProcess(saveData) {
|
||||
emit('save', saveData);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
body {
|
||||
overflow: auto !important;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body,
|
||||
body * {
|
||||
|
||||
/* 滚动条 */
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background-color: #fff;
|
||||
/*滚动条的背景颜色*/
|
||||
-webkit-border-radius: 0;
|
||||
/*滚动条的圆角宽度*/
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
/*滚动条的宽度*/
|
||||
height: 8px;
|
||||
/*滚动条的高度*/
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:vertical {
|
||||
/*垂直滚动条的样式*/
|
||||
height: 50px;
|
||||
background-color: rgba(153, 153, 153, 0.5);
|
||||
-webkit-border-radius: 4px;
|
||||
outline: 2px solid #fff;
|
||||
outline-offset: -2px;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
/*滚动条的hover样式*/
|
||||
background-color: rgba(159, 159, 159, 0.3);
|
||||
-webkit-border-radius: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
/*滚动条的hover样式*/
|
||||
background-color: rgba(159, 159, 159, 0.5);
|
||||
-webkit-border-radius: 4px;
|
||||
}
|
||||
}
|
||||
.process-panel{
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
<template>
|
||||
<div class="my-process-designer">
|
||||
<div class="my-process-designer__header">
|
||||
<slot name="control-header"></slot>
|
||||
<template v-if="!$slots['control-header']">
|
||||
|
||||
<div slot="content">
|
||||
<a-button :type="headerButtonType" :icon="h(SaveOutlined)" @click="onSave" class="ml-2">保存流程
|
||||
</a-button>
|
||||
<a-button :type="headerButtonType" @click="previewProcessXML" class="ml-2">预览XML</a-button>
|
||||
<a-button :type="headerButtonType" @click="previewProcessJson" class="ml-2">预览JSON</a-button>
|
||||
<a-space>
|
||||
<a-tooltip placement="bottom" class="ml-2" title="缩小视图">
|
||||
<a-button :disabled="defaultZoom <= 0.3" :icon="h(ZoomOutOutlined)" @click="processZoomOut()"></a-button>
|
||||
</a-tooltip>
|
||||
<a-button>{{ Math.floor(process.defaultZoom * 10 * 10) + "%" }}</a-button>
|
||||
<a-tooltip placement="bottom" title="放大视图">
|
||||
<a-button :disabled="defaultZoom >= 3.9" :icon="h(ZoomInOutlined)" @click="processZoomIn()"></a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom" title="撤销" class="ml-2">
|
||||
<a-button :icon="h(RotateLeftOutlined)" @click="processUndo()"></a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom" title="恢复">
|
||||
<a-button :icon="h(RotateRightOutlined)" @click="processRedo()"></a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip placement="bottom" title="重新绘制">
|
||||
<a-button :icon="h(ClearOutlined)" @click="processRestart()"></a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-process-designer__container">
|
||||
<div class="my-process-designer__canvas" ref="bpmn-canvas" id="bpmn-canvas"></div>
|
||||
</div>
|
||||
<a-modal v-model:open="process.previewModelVisible" width="60%" title="预览">
|
||||
<highlightjs :language="process.previewType" :code="process.previewResult" style="height: 60vh" />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { h,provide, reactive, onMounted, defineProps, computed, defineEmits } from 'vue';
|
||||
import { SaveOutlined, ZoomOutOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
|
||||
// 生产环境时优化
|
||||
import BpmnModeler from "bpmn-js/lib/Modeler";
|
||||
import DefaultEmptyXML from "./plugins/defaultEmpty.ts";
|
||||
// 翻译方法(汉化)
|
||||
import customTranslate from "./plugins/translate/customTranslate.ts";
|
||||
|
||||
import MoveModule from 'diagram-js/lib/features/move'
|
||||
import ModelingModule from 'bpmn-js/lib/features/modeling'
|
||||
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'
|
||||
|
||||
const emit = defineEmits(['init-finished', 'event', 'commandStack-changed', 'input', 'change', 'canvas-viewbox-changed', 'destroy', 'save', 'element-click', 'connection-added', 'connection-removed', 'connection-changed']);
|
||||
|
||||
// 引入json转换与高亮
|
||||
import convert from "xml-js";
|
||||
const process = reactive({
|
||||
defaultZoom: 1,
|
||||
previewModelVisible: false,
|
||||
simulationStatus: false,
|
||||
previewResult: "",
|
||||
previewType: "xml",
|
||||
recoverable: false,
|
||||
revocable: false,
|
||||
bpmnModeler: null
|
||||
})
|
||||
const props = defineProps({
|
||||
value: String, // xml 字符串
|
||||
processId: String,
|
||||
processName: String,
|
||||
translations: Object, // 自定义的翻译文件
|
||||
additionalModel: [Object, Array], // 自定义model
|
||||
moddleExtension: Object, // 自定义moddle
|
||||
onlyCustomizeAddi: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
onlyCustomizeModdle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
simulation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
keyboard: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
prefix: {
|
||||
type: String,
|
||||
default: "flowable"
|
||||
},
|
||||
events: {
|
||||
type: Array,
|
||||
default: () => ["element.click"]
|
||||
},
|
||||
headerButtonSize: {
|
||||
type: String,
|
||||
default: "small",
|
||||
validator: value => ["default", "medium", "small", "mini"].indexOf(value) !== -1
|
||||
},
|
||||
headerButtonType: {
|
||||
type: String,
|
||||
default: "primary",
|
||||
validator: value => ["default", "primary", "success", "warning", "danger", "info"].indexOf(value) !== -1
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
initBpmnModeler();
|
||||
console.log(props.value)
|
||||
createNewDiagram(props.value);
|
||||
})
|
||||
function onSave() {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(process.bpmnModeler)
|
||||
if (process.bpmnModeler == null) {
|
||||
reject();
|
||||
}
|
||||
process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
|
||||
emit('save', xml);
|
||||
resolve(xml);
|
||||
});
|
||||
})
|
||||
}
|
||||
function initBpmnModeler() {
|
||||
if (process.bpmnModeler) return;
|
||||
const containerEl = document.querySelector('#bpmn-canvas');
|
||||
process.bpmnModeler = new BpmnModeler({
|
||||
container: '#bpmn-canvas',
|
||||
additionalModules: [
|
||||
{
|
||||
translate: ['value', customTranslate]
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log(process.bpmnModeler)
|
||||
emit("init-finished", process.bpmnModeler);
|
||||
initModelListeners();
|
||||
}
|
||||
function initModelListeners() {
|
||||
const EventBus = process.bpmnModeler.get("eventBus");
|
||||
const that = this;
|
||||
// 注册需要的监听事件, 将. 替换为 - , 避免解析异常
|
||||
props.events.forEach(event => {
|
||||
EventBus.on(event, function (eventObj) {
|
||||
console.log(eventObj)
|
||||
provide('wfdesign',eventObj)
|
||||
let eventName = event.replace(/\./g, "-");
|
||||
let element = eventObj ? eventObj.element : null;
|
||||
emit(eventName, element, eventObj);
|
||||
emit('event', eventName, element, eventObj);
|
||||
});
|
||||
});
|
||||
// 监听图形改变返回xml
|
||||
EventBus.on("commandStack.changed", async event => {
|
||||
try {
|
||||
process.recoverable = process.bpmnModeler.get("commandStack").canRedo();
|
||||
process.revocable = process.bpmnModeler.get("commandStack").canUndo();
|
||||
let { xml } = await process.bpmnModeler.saveXML({ format: true });
|
||||
emit("commandStack-changed", event);
|
||||
emit("input", xml);
|
||||
emit("change", xml);
|
||||
} catch (e) {
|
||||
console.error(`[Process Designer Warn]: ${e.message || e}`);
|
||||
}
|
||||
});
|
||||
// 监听视图缩放变化
|
||||
process.bpmnModeler.on("canvas.viewbox.changed", ({ viewbox }) => {
|
||||
emit("canvas-viewbox-changed", { viewbox });
|
||||
const { scale } = viewbox;
|
||||
process.defaultZoom = Math.floor(scale * 100) / 100;
|
||||
});
|
||||
}
|
||||
/* 创建新的流程图 */
|
||||
async function createNewDiagram(xml) {
|
||||
// 将字符串转换成图显示出来
|
||||
let newId = props.processId || `Process_${new Date().getTime()}`;
|
||||
let newName = props.processName || `业务流程_${new Date().getTime()}`;
|
||||
let xmlString = xml || DefaultEmptyXML(newId, newName, props.prefix);
|
||||
try {
|
||||
let { warnings } = await process.bpmnModeler.importXML(xmlString);
|
||||
if (warnings && warnings.length) {
|
||||
warnings.forEach(warn => console.warn(warn));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`[Process Designer Warn]: ${e.message || e}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 下载流程图到本地
|
||||
async function downloadProcess(type, name) {
|
||||
try {
|
||||
const _this = this;
|
||||
// 按需要类型创建文件并下载
|
||||
if (type === "xml" || type === "bpmn") {
|
||||
const { err, xml } = await process.bpmnModeler.saveXML();
|
||||
// 读取异常时抛出异常
|
||||
if (err) {
|
||||
console.error(`[Process Designer Warn ]: ${err.message || err}`);
|
||||
}
|
||||
let { href, filename } = setEncoded(type.toUpperCase(), name, xml);
|
||||
downloadFunc(href, filename);
|
||||
} else {
|
||||
const { err, svg } = await process.bpmnModeler.saveSVG();
|
||||
// 读取异常时抛出异常
|
||||
if (err) {
|
||||
return console.error(err);
|
||||
}
|
||||
let { href, filename } = setEncoded("SVG", name, svg);
|
||||
downloadFunc(href, filename);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`[Process Designer Warn ]: ${e.message || e}`);
|
||||
}
|
||||
// 文件下载方法
|
||||
function downloadFunc(href, filename) {
|
||||
if (href && filename) {
|
||||
let a = document.createElement("a");
|
||||
a.download = filename; //指定下载的文件名
|
||||
a.href = href; // URL对象
|
||||
a.click(); // 模拟点击
|
||||
URL.revokeObjectURL(a.href); // 释放URL 对象
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 根据所需类型进行转码并返回下载地址
|
||||
function setEncoded(type, filename = "diagram", data) {
|
||||
const encodedData = encodeURIComponent(data);
|
||||
return {
|
||||
filename: `${filename}.${type}`,
|
||||
href: `data:application/${type === "svg" ? "text/xml" : "bpmn20-xml"};charset=UTF-8,${encodedData}`,
|
||||
data: data
|
||||
};
|
||||
}
|
||||
|
||||
// 加载本地文件
|
||||
function importLocalFile() {
|
||||
const that = this;
|
||||
const file = this.$refs.refFile.files[0];
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file);
|
||||
reader.onload = function () {
|
||||
let xmlStr = this.result;
|
||||
createNewDiagram(xmlStr);
|
||||
};
|
||||
}
|
||||
/* ------------------------------------------------ refs methods ------------------------------------------------------ */
|
||||
function downloadProcessAsXml() {
|
||||
downloadProcess("xml");
|
||||
}
|
||||
function downloadProcessAsBpmn() {
|
||||
downloadProcess("bpmn");
|
||||
}
|
||||
function downloadProcessAsSvg() {
|
||||
downloadProcess("svg");
|
||||
}
|
||||
function processSimulation() {
|
||||
process.simulationStatus = !process.simulationStatus;
|
||||
props.simulation && process.bpmnModeler.get("toggleMode").toggleMode();
|
||||
}
|
||||
function processRedo() {
|
||||
process.bpmnModeler.get("commandStack").redo();
|
||||
}
|
||||
function processUndo() {
|
||||
process.bpmnModeler.get("commandStack").undo();
|
||||
}
|
||||
function processZoomIn(zoomStep = 0.1) {
|
||||
let newZoom = Math.floor(process.defaultZoom * 100 + zoomStep * 100) / 100;
|
||||
if (newZoom > 4) {
|
||||
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be greater than 4");
|
||||
}
|
||||
process.defaultZoom = newZoom;
|
||||
process.bpmnModeler.get("canvas").zoom(process.defaultZoom);
|
||||
}
|
||||
function processZoomOut(zoomStep = 0.1) {
|
||||
let newZoom = Math.floor(process.defaultZoom * 100 - zoomStep * 100) / 100;
|
||||
if (newZoom < 0.2) {
|
||||
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be less than 0.2");
|
||||
}
|
||||
process.defaultZoom = newZoom;
|
||||
process.bpmnModeler.get("canvas").zoom(process.defaultZoom);
|
||||
}
|
||||
function processZoomTo(newZoom = 1) {
|
||||
if (newZoom < 0.2) {
|
||||
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be less than 0.2");
|
||||
}
|
||||
if (newZoom > 4) {
|
||||
throw new Error("[Process Designer Warn ]: The zoom ratio cannot be greater than 4");
|
||||
}
|
||||
process.defaultZoom = newZoom;
|
||||
process.bpmnModeler.get("canvas").zoom(newZoom);
|
||||
}
|
||||
function processReZoom() {
|
||||
process.defaultZoom = 1;
|
||||
process.bpmnModeler.get("canvas").zoom("fit-viewport", "auto");
|
||||
}
|
||||
function processRestart() {
|
||||
process.recoverable = false;
|
||||
process.revocable = false;
|
||||
createNewDiagram(null).then(() => process.bpmnModeler.get("canvas").zoom(1, "auto"));
|
||||
}
|
||||
function elementsAlign(align) {
|
||||
const Align = process.bpmnModeler.get("alignElements");
|
||||
const Selection = process.bpmnModeler.get("selection");
|
||||
const SelectedElements = Selection.get();
|
||||
if (!SelectedElements || SelectedElements.length <= 1) {
|
||||
this.$message.warning("请按住 Ctrl 键选择多个元素对齐");
|
||||
return;
|
||||
}
|
||||
this.$confirm("自动对齐可能造成图形变形,是否继续?", "警告", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => Align.trigger(SelectedElements, align));
|
||||
}
|
||||
/*----------------------------- 方法结束 ---------------------------------*/
|
||||
function previewProcessXML() {
|
||||
process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
|
||||
process.previewResult = xml;
|
||||
process.previewType = "xml";
|
||||
process.previewModelVisible = true;
|
||||
});
|
||||
}
|
||||
function previewProcessJson() {
|
||||
process.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
|
||||
console.log(convert.xml2json(xml, { spaces: 2 }))
|
||||
process.previewResult = convert.xml2json(xml, { spaces: 2 });
|
||||
process.previewType = "json";
|
||||
process.previewModelVisible = true;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import BpmnProcessDesigner from "./ProcessDesigner.vue";
|
||||
|
||||
BpmnProcessDesigner.install = function(Vue) {
|
||||
Vue.component(BpmnProcessDesigner.name, BpmnProcessDesigner);
|
||||
};
|
||||
|
||||
export default BpmnProcessDesigner;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
export default (key, name, type) => {
|
||||
if (!type) type = "camunda";
|
||||
const TYPE_TARGET = {
|
||||
activiti: "http://activiti.org/bpmn",
|
||||
camunda: "http://bpmn.io/schema/bpmn",
|
||||
flowable: "http://flowable.org/bpmn"
|
||||
};
|
||||
return `
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<bpmn2:definitions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
||||
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
||||
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
|
||||
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
|
||||
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd"
|
||||
id="diagram_${key}"
|
||||
targetNamespace="${TYPE_TARGET[type]}">
|
||||
<bpmn2:process id="${key}" name="${name}" isExecutable="true">
|
||||
</bpmn2:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="${key}">
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn2:definitions>
|
||||
`;
|
||||
};
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import translations from './zh.ts'
|
||||
|
||||
export default function customTranslate(template, replacements) {
|
||||
replacements = replacements || {}
|
||||
template = translations[template] || template
|
||||
return template.replace(/{([^}]+)}/g, function (_, key) {
|
||||
return replacements[key] || '{' + key + '}'
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
export default {
|
||||
"Activate hand tool": "激活抓手工具",
|
||||
"Activate lasso tool": "激活套索工具",
|
||||
"Activate create/remove space tool": "激活创建/删除空间工具",
|
||||
"Activate global connect tool": "激活全局连接工具",
|
||||
"Create start event": "创建开始事件",
|
||||
"Create end event": "创建结束事件",
|
||||
"Create task": "创建任务",
|
||||
"Create user task": "创建用户任务",
|
||||
"Create gateway": "创建网关",
|
||||
"Create data object reference": "创建数据对象",
|
||||
"Create data store reference": "创建数据存储",
|
||||
"Create group": "创建分组",
|
||||
"Create intermediate/boundary event": "创建中间/边界事件",
|
||||
"Create expanded sub-process": "创建扩展子过程",
|
||||
"Create pool/participant": "创建池/参与者",
|
||||
"Change element": "修改类型",
|
||||
"Delete": "移除",
|
||||
"Append end event": "追加结束事件",
|
||||
"Append gateway": "追加网关",
|
||||
"Append task": "追加任务",
|
||||
"Append intermediate/boundary event": "追加中间抛出事件/边界事件",
|
||||
"Add text annotation": "添加 text annotation",
|
||||
"Connect using association": "使用关联连接",
|
||||
"Connect to other element": "消息关联",
|
||||
"Start event": "开始事件",
|
||||
"End event": "结束事件",
|
||||
"Message intermediate catch event": "消息中间捕获事件",
|
||||
"Message intermediate throw event": "消息中间抛出事件",
|
||||
"Timer intermediate catch event": "定时中间捕获事件",
|
||||
"Escalation intermediate throw event": "升级中间抛出事件",
|
||||
"Conditional intermediate catch event": "条件中间捕获事件",
|
||||
"Link intermediate catch event": "链接中间捕获事件",
|
||||
"Link intermediate throw event": "链接中间抛出事件",
|
||||
"Compensation intermediate throw event": "补偿中间抛出事件",
|
||||
"Signal intermediate catch event": "信号中间捕获事件",
|
||||
"Signal intermediate throw event": "信号中间抛出事件",
|
||||
"User task": "用户任务",
|
||||
"Service task": "服务任务",
|
||||
"Send task": "发送任务",
|
||||
"Receive task": "、接收任务",
|
||||
"Manual task": "手动任务",
|
||||
"Business rule task": "业务规则任务",
|
||||
"Script task": "脚本任务",
|
||||
"Call activity": "调用活动",
|
||||
"Sub-process (collapsed)": "子流程(已折叠)",
|
||||
"Sub-process (expanded)": "子流程(扩大)",
|
||||
"Intermediate throw event": "中间抛出事件",
|
||||
"Message start event": "消息开始事件",
|
||||
"Timer start event": "定时开始事件",
|
||||
"Conditional start event": "条件开始事件",
|
||||
"Signal start event": "信号开始事件",
|
||||
"Parallel gateway":"并行网关",
|
||||
"Inclusive gateway":"包容网关",
|
||||
"Complex gateway":"复杂网关",
|
||||
"Event-based gateway":"事件网关",
|
||||
"Message end event":"消息结束事件",
|
||||
"Escalation end event":"升级结束事件",
|
||||
"Error end event":"错误结束事件",
|
||||
"Compensation end event":"补偿结束事件",
|
||||
"Signal end event":"信号结束事件",
|
||||
"Terminate end event":"终止结束事件",
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
"Process": "业务流程",
|
||||
"Append EndEvent": "追加结束事件",
|
||||
"Append Gateway": "追加网关",
|
||||
"Append Task": "追加任务",
|
||||
"Append Intermediate/Boundary Event": "追加中间抛出事件/边界事件",
|
||||
"Activate the global connect tool": "激活全局连接工具",
|
||||
"Append {type}": "添加 {type}",
|
||||
"Add Lane above": "在上面添加道",
|
||||
"Divide into two Lanes": "分割成两个道",
|
||||
"Divide into three Lanes": "分割成三个道",
|
||||
"Add Lane below": "在下面添加道",
|
||||
"Append compensation activity": "追加补偿活动",
|
||||
"Change type": "修改类型",
|
||||
"Connect using Association": "使用关联连接",
|
||||
"Connect using Sequence/MessageFlow or Association": "使用顺序/消息流或者关联连接",
|
||||
"Connect using DataInputAssociation": "使用数据输入关联连接",
|
||||
"Remove": "移除",
|
||||
"Activate the hand tool": "激活抓手工具",
|
||||
"Activate the lasso tool": "激活套索工具",
|
||||
"Activate the create/remove space tool": "激活创建/删除空间工具",
|
||||
"Create expanded SubProcess": "创建扩展子过程",
|
||||
"Create IntermediateThrowEvent/BoundaryEvent": "创建中间抛出事件/边界事件",
|
||||
"Create Pool/Participant": "创建池/参与者",
|
||||
"Parallel Multi Instance": "并行多重事件",
|
||||
"Sequential Multi Instance": "时序多重事件",
|
||||
"DataObjectReference": "数据对象参考",
|
||||
"DataStoreReference": "数据存储参考",
|
||||
"Loop": "循环",
|
||||
"Ad-hoc": "即席",
|
||||
"Create {type}": "创建 {type}",
|
||||
"Create StartEvent": "创建开始事件",
|
||||
"Create EndEvent": "创建结束事件",
|
||||
"Create Task": "创建任务",
|
||||
"Create User Task": "创建用户任务",
|
||||
"Create Gateway": "创建网关",
|
||||
"Create DataObjectReference": "创建数据对象",
|
||||
"Create DataStoreReference": "创建数据存储",
|
||||
"Create Group": "创建分组",
|
||||
"Create Intermediate/Boundary Event": "创建中间/边界事件",
|
||||
"Message Start Event": "消息开始事件",
|
||||
"Timer Start Event": "定时开始事件",
|
||||
"Conditional Start Event": "条件开始事件",
|
||||
"Signal Start Event": "信号开始事件",
|
||||
"Error Start Event": "错误开始事件",
|
||||
"Escalation Start Event": "升级开始事件",
|
||||
"Compensation Start Event": "补偿开始事件",
|
||||
"Message Start Event (non-interrupting)": "消息开始事件(非中断)",
|
||||
"Timer Start Event (non-interrupting)": "定时开始事件(非中断)",
|
||||
"Conditional Start Event (non-interrupting)": "条件开始事件(非中断)",
|
||||
"Signal Start Event (non-interrupting)": "信号开始事件(非中断)",
|
||||
"Escalation Start Event (non-interrupting)": "升级开始事件(非中断)",
|
||||
"Message Intermediate Catch Event": "消息中间捕获事件",
|
||||
"Message Intermediate Throw Event": "消息中间抛出事件",
|
||||
"Timer Intermediate Catch Event": "定时中间捕获事件",
|
||||
"Escalation Intermediate Throw Event": "升级中间抛出事件",
|
||||
"Conditional Intermediate Catch Event": "条件中间捕获事件",
|
||||
"Link Intermediate Catch Event": "链接中间捕获事件",
|
||||
"Link Intermediate Throw Event": "链接中间抛出事件",
|
||||
"Compensation Intermediate Throw Event": "补偿中间抛出事件",
|
||||
"Signal Intermediate Catch Event": "信号中间捕获事件",
|
||||
"Signal Intermediate Throw Event": "信号中间抛出事件",
|
||||
"Collapsed Pool": "折叠池",
|
||||
"Expanded Pool": "展开池",
|
||||
"no parent for {element} in {parent}": "在{parent}里,{element}没有父类",
|
||||
"no shape type specified": "没有指定的形状类型",
|
||||
"flow elements must be children of pools/participants": "流元素必须是池/参与者的子类",
|
||||
"out of bounds release": "out of bounds release",
|
||||
"more than {count} child lanes": "子道大于{count} ",
|
||||
"element required": "元素不能为空",
|
||||
"diagram not part of bpmn:Definitions": "流程图不符合bpmn规范",
|
||||
"no diagram to display": "没有可展示的流程图",
|
||||
"no process or collaboration to display": "没有可展示的流程/协作",
|
||||
"element {element} referenced by {referenced}#{property} not yet drawn":
|
||||
"由{referenced}#{property}引用的{element}元素仍未绘制",
|
||||
"already rendered {element}": "{element} 已被渲染",
|
||||
"failed to import {element}": "导入{element}失败",
|
||||
"Id": "编号",
|
||||
"Name": "名称",
|
||||
"General": "常规",
|
||||
"Details": "详情",
|
||||
"Message Name": "消息名称",
|
||||
"Message": "消息",
|
||||
"Initiator": "创建者",
|
||||
"Asynchronous Continuations": "持续异步",
|
||||
"Asynchronous Before": "异步前",
|
||||
"Asynchronous After": "异步后",
|
||||
"Job Configuration": "工作配置",
|
||||
"Exclusive": "排除",
|
||||
"Job Priority": "工作优先级",
|
||||
"Retry Time Cycle": "重试时间周期",
|
||||
"Documentation": "文档",
|
||||
"Element Documentation": "元素文档",
|
||||
"History Configuration": "历史配置",
|
||||
"History Time To Live": "历史的生存时间",
|
||||
"Forms": "表单",
|
||||
"Form Key": "表单key",
|
||||
"Form Fields": "表单字段",
|
||||
"Business Key": "业务key",
|
||||
"Form Field": "表单字段",
|
||||
"ID": "编号",
|
||||
"Type": "类型",
|
||||
"Label": "名称",
|
||||
"Default Value": "默认值",
|
||||
"Default Flow": "默认流转路径",
|
||||
"Conditional Flow": "条件流转路径",
|
||||
"Sequence Flow": "普通流转路径",
|
||||
"Validation": "校验",
|
||||
"Add Constraint": "添加约束",
|
||||
"Config": "配置",
|
||||
"Properties": "属性",
|
||||
"Add Property": "添加属性",
|
||||
"Value": "值",
|
||||
"Listeners": "监听器",
|
||||
"Execution Listener": "执行监听",
|
||||
"Event Type": "事件类型",
|
||||
"Listener Type": "监听器类型",
|
||||
"Java Class": "Java类",
|
||||
"Expression": "表达式",
|
||||
"Must provide a value": "必须提供一个值",
|
||||
"Delegate Expression": "代理表达式",
|
||||
"Script": "脚本",
|
||||
"Script Format": "脚本格式",
|
||||
"Script Type": "脚本类型",
|
||||
"Inline Script": "内联脚本",
|
||||
"External Script": "外部脚本",
|
||||
"Resource": "资源",
|
||||
"Field Injection": "字段注入",
|
||||
"Extensions": "扩展",
|
||||
"Input/Output": "输入/输出",
|
||||
"Input Parameters": "输入参数",
|
||||
"Output Parameters": "输出参数",
|
||||
"Parameters": "参数",
|
||||
"Output Parameter": "输出参数",
|
||||
"Timer Definition Type": "定时器定义类型",
|
||||
"Timer Definition": "定时器定义",
|
||||
"Date": "日期",
|
||||
"Duration": "持续",
|
||||
"Cycle": "循环",
|
||||
"Signal": "信号",
|
||||
"Signal Name": "信号名称",
|
||||
"Escalation": "升级",
|
||||
"Error": "错误",
|
||||
"Link Name": "链接名称",
|
||||
"Condition": "条件名称",
|
||||
"Variable Name": "变量名称",
|
||||
"Variable Event": "变量事件",
|
||||
"Specify more than one variable change event as a comma separated list.": "多个变量事件以逗号隔开",
|
||||
"Wait for Completion": "等待完成",
|
||||
"Activity Ref": "活动参考",
|
||||
"Version Tag": "版本标签",
|
||||
"Executable": "可执行文件",
|
||||
"External Task Configuration": "扩展任务配置",
|
||||
"Task Priority": "任务优先级",
|
||||
"External": "外部",
|
||||
"Connector": "连接器",
|
||||
"Must configure Connector": "必须配置连接器",
|
||||
"Connector Id": "连接器编号",
|
||||
"Implementation": "实现方式",
|
||||
"Field Injections": "字段注入",
|
||||
"Fields": "字段",
|
||||
"Result Variable": "结果变量",
|
||||
"Topic": "主题",
|
||||
"Configure Connector": "配置连接器",
|
||||
"Input Parameter": "输入参数",
|
||||
"Assignee": "代理人",
|
||||
"Candidate Users": "候选用户",
|
||||
"Candidate Groups": "候选组",
|
||||
"Due Date": "到期时间",
|
||||
"Follow Up Date": "跟踪日期",
|
||||
"Priority": "优先级",
|
||||
"The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)":
|
||||
"跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00",
|
||||
"The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)":
|
||||
"跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00",
|
||||
"Variables": "变量",
|
||||
"Candidate Starter Configuration": "候选人起动器配置",
|
||||
"Candidate Starter Groups": "候选人起动器组",
|
||||
"This maps to the process definition key.": "这映射到流程定义键。",
|
||||
"Candidate Starter Users": "候选人起动器的用户",
|
||||
"Specify more than one user as a comma separated list.": "指定多个用户作为逗号分隔的列表。",
|
||||
"Tasklist Configuration": "Tasklist配置",
|
||||
"Startable": "启动",
|
||||
"Specify more than one group as a comma separated list.": "指定多个组作为逗号分隔的列表。",
|
||||
"Execution listeners": "执行监听器"
|
||||
};
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-04 13:39:52
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-05 16:07:51
|
||||
* @Description:
|
||||
*/
|
||||
const hljs = require("highlight.js/lib/core");
|
||||
hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml"));
|
||||
hljs.registerLanguage("json", require("highlight.js/lib/languages/json"));
|
||||
|
||||
export default hljs;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import BpmnProcessDesigner from "./designer/index.ts";
|
||||
import BmpnProcessPenal from "./penal";
|
||||
|
||||
export {
|
||||
BpmnProcessDesigner,
|
||||
BmpnProcessPenal
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-05 17:09:44
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 14:52:13
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div :class="prefixCls" :style="{ width: `${props.width}px` }">
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="流程属性">
|
||||
<shcemeinfo-config ref="shcemeinfo" :disabled="true"></shcemeinfo-config>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="发起权限" force-render>
|
||||
<auth-config ref="auth"></auth-config>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="开始节点">
|
||||
<start-event-option ref="start" :element="data.elementData"></start-event-option>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="4" tab="审核节点">
|
||||
<user-task-option ref="task"></user-task-option>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<!-- <el-tabs v-model="configActiveName" :stretch="true">
|
||||
<el-tab-pane :label="$t(wfNodeName[currentWfNode.type])" name="tab01" v-if="currentWfNode != undefined">
|
||||
<component :disabled="true" ref="wfcongfig" :is="`${currentWfNode.type}Option`"></component>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="流程属性" name="tab02">
|
||||
<shcemeinfo-config ref="shcemeinfo" :disabled="true"></shcemeinfo-config>
|
||||
</el-tab-pane>
|
||||
</el-tabs> -->
|
||||
<!-- <Tabs v-model:activeKey="configActiveName">
|
||||
<Tabs.TabPane :label="$t(wfNodeName[currentWfNode.type])" name="tab01" v-if="currentWfNode != undefined">
|
||||
<component :disabled="true" ref="wfcongfig" :is="`${currentWfNode.type}Option`"></component>
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane label="流程属性" name="tab02">
|
||||
<shcemeinfo-config ref="shcemeinfo" :disabled="true"></shcemeinfo-config>
|
||||
</Tabs.TabPane>
|
||||
</Tabs> -->
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { h, reactive, onMounted, defineProps, computed, defineEmits, provide, watch, ref } from 'vue';
|
||||
import { SaveOutlined, ZoomOutOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
|
||||
import { Tabs } from 'ant-design-vue';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import { useDesign } from '@/hooks/web/useDesign';
|
||||
const { prefixCls } = useDesign('process-property');
|
||||
|
||||
|
||||
// 流程属性
|
||||
import shcemeinfoConfig from './shcemeInfo/index.vue'
|
||||
// 发起权限
|
||||
import authConfig from './auth/index.vue'
|
||||
// 开始节点
|
||||
import startEventOption from './startEvent/index.vue'
|
||||
// 审核节点
|
||||
import userTaskOption from './userTask/index.vue'
|
||||
// 结束节点
|
||||
import endEventOption from './config/endEvent.vue'
|
||||
import gatewayAndOption from './config/gatewayAnd.vue'
|
||||
import gatewayInclusiveOption from './config/gatewayInclusive.vue'
|
||||
import gatewayXorOption from './config/gatewayXor.vue'
|
||||
import scriptTaskOption from './config/scriptTask.vue'
|
||||
import subprocessOption from './config/subprocess.vue'
|
||||
import mylineOption from './config/myline.vue'
|
||||
/**
|
||||
* 侧边栏
|
||||
* @Author MiyueFE
|
||||
* @Home https://github.com/miyuesc
|
||||
* @Date 2021年3月31日18:57:51
|
||||
*/
|
||||
const props = defineProps({
|
||||
bpmnModeler: Object,
|
||||
prefix: {
|
||||
type: String,
|
||||
default: "camunda"
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 520
|
||||
},
|
||||
idEditDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
element: Object
|
||||
})
|
||||
|
||||
provide('prefix', props.prefix)
|
||||
provide('width', props.width)
|
||||
const activeKey = ref("4")
|
||||
const data = reactive({
|
||||
configActiveName: 'tab02',
|
||||
currentWfNode: undefined,
|
||||
wfNodeName: {
|
||||
startEvent: '开始节点',
|
||||
endEvent: '结束节点',
|
||||
gatewayAnd: '并行网关',
|
||||
gatewayInclusive: '包含网关',
|
||||
gatewayXor: '排他网关',
|
||||
scriptTask: '脚本节点',
|
||||
userTask: '审核节点',
|
||||
subprocess: '子流程',
|
||||
myline: '线条'
|
||||
},
|
||||
elementData:{}
|
||||
})
|
||||
watch(
|
||||
() => props.element,
|
||||
(newVal, oldVal) => {
|
||||
data.elementData = newVal
|
||||
}
|
||||
)
|
||||
const achieveList = ref([
|
||||
{
|
||||
key: '1',
|
||||
name: '文章',
|
||||
component: 'startEventOption',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
name: '应用',
|
||||
component: 'startEventOption',
|
||||
},
|
||||
])
|
||||
const tabs = {
|
||||
startEventOption,
|
||||
startEventOption,
|
||||
};
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@prefix-cls: ~'@{namespace}-process-property';
|
||||
|
||||
.@{prefix-cls} {
|
||||
background-color: @component-background;
|
||||
}
|
||||
|
||||
::v-deep .ant-tabs {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
padding: 0 20px;
|
||||
|
||||
}
|
||||
|
||||
::v-deep .ant-tabs-content-holder {
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-05 17:09:44
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 15:37:16
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div class="auth-config">
|
||||
<a-tabs v-model:activeKey="f_AuthType" type="card" size="small">
|
||||
<a-tab-pane key="1" tab="所有成员">
|
||||
<a-alert message="权限说明" description="所有人员指不限制流程模版的发起人员,表示每个人都能发起该流程模版。" type="info" show-icon />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="指定成员">
|
||||
<a-space>
|
||||
<a-radio-group>
|
||||
<a-radio-button value="1" @click="handlePostClick">岗位</a-radio-button>
|
||||
<a-radio-button value="2" @click="handleRoleClick">角色</a-radio-button>
|
||||
<a-radio-button value="3" @click="handleAccountClick">用户</a-radio-button>
|
||||
</a-radio-group>
|
||||
<a-button danger :size="size">清空</a-button>
|
||||
</a-space>
|
||||
<a-table size="small" :columns="columns" :data-source="dataSource" bordered :pagination="false">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['name', 'type'].includes(column.dataIndex)">
|
||||
<div>
|
||||
{{ text }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<a-popconfirm v-if="dataSource.length" title="Sure to delete?"
|
||||
@confirm="onDelete(record.key)">
|
||||
<a>Delete</a>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<a-modal width="60%" v-model:open="data.postOpen" title="添加岗位" @ok="postHandleOk">
|
||||
<SelectPos ref="posRef"></SelectPos>
|
||||
</a-modal>
|
||||
<a-modal width="60%" v-model:open="data.roleOpen" title="添加角色" @ok="roleHandleOk">
|
||||
<SelectRole ref="roleRef"></SelectRole>
|
||||
</a-modal>
|
||||
<a-modal width="60%" v-model:open="data.accountOpen" title="添加角色" @ok="accountHandleOk">
|
||||
<SelectAccount ref="accountRef"></SelectAccount>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, nextTick, unref } from 'vue';
|
||||
const f_AuthType = ref("1")
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import type { UnwrapRef } from 'vue';
|
||||
import SelectPos from '@/components/SelectPos/index.vue';
|
||||
import SelectRole from '@/components/SelectRole/index.vue';
|
||||
import SelectAccount from '@/components/SelectAccount/index.vue';
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
},
|
||||
|
||||
];
|
||||
const dataSource = [
|
||||
{
|
||||
id: 0,
|
||||
name: "王五",
|
||||
type: "管理员",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "王五",
|
||||
type: "管理员",
|
||||
},
|
||||
]
|
||||
const data = reactive({
|
||||
postOpen: false,
|
||||
roleOpen: false,
|
||||
accountOpen: false,
|
||||
})
|
||||
// 岗位
|
||||
const posRef = ref < any > ()
|
||||
|
||||
function handlePostClick() {
|
||||
data.postOpen = true;
|
||||
}
|
||||
function postHandleOk() {
|
||||
console.log(roleRef.value.getRow())
|
||||
}
|
||||
// 角色
|
||||
const roleRef = ref < any > ()
|
||||
|
||||
function handleRoleClick() {
|
||||
data.roleOpen = true;
|
||||
}
|
||||
function roleHandleOk() {
|
||||
console.log(roleRef.value.getRow())
|
||||
}
|
||||
// 用户
|
||||
const accountRef = ref < any > ()
|
||||
|
||||
function handleAccountClick() {
|
||||
data.accountOpen = true;
|
||||
}
|
||||
function accountHandleOk() {
|
||||
console.log(accountRef.value.getRow())
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.site-space-compact-wrapper {
|
||||
width: 100%;
|
||||
|
||||
.ant-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ant-tabs {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .ant-table-content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
<template>
|
||||
<div class="l-from-body" >
|
||||
<el-form :model="formData" :rules="rules" size="mini" ref="form" label-width="120px" >
|
||||
<el-col :span="24">
|
||||
<el-form-item label="条件名称" prop="name">
|
||||
<el-input v-model="formData.name" >
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据库" prop="dbCode">
|
||||
<el-select v-model="formData.dbCode" placeholder="请选择">
|
||||
<el-option-group
|
||||
v-for="group in lr_dblinkTree"
|
||||
:key="group.id"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="item in group.children"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据表" prop="table">
|
||||
<l-codetable-select
|
||||
@change="handleTableChange"
|
||||
:dbCode="formData.dbCode"
|
||||
v-model="formData.table"></l-codetable-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="关联流程字段" prop="rfield">
|
||||
<l-select :options="formData.columns" valueKey="name" labelKey="coment" v-model="formData.rfield" >
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="比较字段" prop="cfield">
|
||||
<l-select :options="formData.columns" valueKey="name" labelKey="coment" v-model="formData.cfield" >
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="比较类型" prop="compareType">
|
||||
<l-select :options="options" v-model="formData.compareType" >
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据值" prop="value">
|
||||
<el-input v-model="formData.value" >
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'condition-formula',
|
||||
props:{
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
formData:{
|
||||
dbCode:'',
|
||||
table:'',
|
||||
columns:[],
|
||||
rfield:'',
|
||||
cfield:'',
|
||||
compareType:'',
|
||||
value:'',
|
||||
name:''
|
||||
},
|
||||
rules: {
|
||||
dbCode: [
|
||||
{ required: true, message: '请选择数据库' }
|
||||
],
|
||||
table: [
|
||||
{ required: true, message: '请选择数据表' }
|
||||
],
|
||||
rfield: [
|
||||
{ required: true, message: '请选择关联字段' }
|
||||
],
|
||||
cfield: [
|
||||
{ required: true, message: '请选择比较字段' }
|
||||
],
|
||||
compareType: [
|
||||
{ required: true, message: '请选择比较类型' }
|
||||
],
|
||||
value: [
|
||||
{ required: true, message: '请填写值' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请填写条件名称' }
|
||||
]
|
||||
},
|
||||
options:[
|
||||
{ value: '1', label: '等于' },
|
||||
{ value: '2', label: '不等于' },
|
||||
{ value: '3', label: '大于' },
|
||||
{ value: '4', label: '大于等于' },
|
||||
{ value: '5', label: '小于' },
|
||||
{ value: '6', label: '小于等于' },
|
||||
{ value: '7', label: '包含' },
|
||||
{ value: '8', label: '不包含' },
|
||||
{ value: '9', label: '包含于' },
|
||||
{ value: '10', label: '不包含于' }]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods:{
|
||||
handleTableChange(table){
|
||||
this.formData.columns = table.columns;
|
||||
console.log(table);
|
||||
},
|
||||
resetForm(){
|
||||
this.formData.columns = [];
|
||||
this.$refs.form && this.$refs.form.resetFields();
|
||||
},
|
||||
// 校验表单
|
||||
validateForm(callback){
|
||||
this.$refs.form.validate((valid) => {
|
||||
if(valid){
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
setForm(data){
|
||||
this.formData = this.$deepClone(data);
|
||||
},
|
||||
getForm(){
|
||||
let formData = this.$deepClone(this.formData);
|
||||
return formData;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<template>
|
||||
<div class="l-from-body" >
|
||||
<el-form :model="formData" :rules="rules" size="mini" ref="form" label-width="120px" >
|
||||
<el-col :span="24">
|
||||
<el-form-item label="条件名称" prop="name">
|
||||
<el-input v-model="formData.name" >
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据库" prop="dbCode">
|
||||
<el-select v-model="formData.dbCode" placeholder="请选择">
|
||||
<el-option-group
|
||||
v-for="group in lr_dblinkTree"
|
||||
:key="group.id"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="item in group.children"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<div style="padding:0 0 16px 120px;">
|
||||
<el-alert
|
||||
title="sql语句说明"
|
||||
type="warning"
|
||||
description="请在开发人员指导下进行配置SQL语句({processId}流程发起实例主键{userId}流程发起用户Id{userAccount}流程发起用户账号{companyId}流程发起用户公司{departmentId}流程发起用户部门)!"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="SQL语句" prop="sql">
|
||||
<el-input v-model="formData.sql" type="textarea"
|
||||
:autosize="{ minRows: 8}" >
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'condition-sql',
|
||||
props:{
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
formData:{
|
||||
dbCode:'',
|
||||
sql:'',
|
||||
name:''
|
||||
},
|
||||
rules: {
|
||||
dbCode: [
|
||||
{ required: true, message: '请选择数据库' }
|
||||
],
|
||||
sql: [
|
||||
{ required: true, message: '请填写sql语句' }
|
||||
],
|
||||
name: [
|
||||
{ required: true, message: '请填写条件名称' }
|
||||
]
|
||||
},
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods:{
|
||||
resetForm(){
|
||||
this.$refs.form && this.$refs.form.resetFields();
|
||||
},
|
||||
// 校验表单
|
||||
validateForm(callback){
|
||||
this.$refs.form.validate((valid) => {
|
||||
if(valid){
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
setForm(data){
|
||||
this.formData = this.$deepClone(data);
|
||||
},
|
||||
getForm(){
|
||||
let formData = this.$deepClone(this.formData);
|
||||
return formData;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'end-event-option',
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<div style="padding:0 16px;">
|
||||
<el-alert
|
||||
title="并行网关说明"
|
||||
type="info"
|
||||
description="并行网关会等待所有分支汇入才往下执行,所有出口分支都会被执行"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'gateway-and-option',
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
<template>
|
||||
<l-layout :top="180" >
|
||||
<template #top>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<div style="padding:0 16px;">
|
||||
<el-alert
|
||||
title="包容网关说明"
|
||||
type="info"
|
||||
description="包容网关会等待所有分支汇入才往下执行,出口分支能执行多条(条件为true)"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<l-layout :top="40">
|
||||
<template #top v-if="!disabled">
|
||||
<div style="padding-left:8px;float:left;" >
|
||||
<el-button-group>
|
||||
<el-button size="mini" icon="el-icon-plus" @click="handleFormulaClick">{{$t('公式')}}</el-button>
|
||||
<el-button size="mini" icon="el-icon-plus" @click="handleSQlClick">{{$t('sql语句')}}</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<div style="padding-right:8px;float:right;">
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="handleClearClick">{{$t('清空')}}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<l-table :columns="columns" :dataSource="node.conditions" >
|
||||
<template v-slot:type="scope" >
|
||||
{{typeFormat(scope.row.type)}}
|
||||
</template>
|
||||
<l-table-btns v-if="!disabled" :btns="tableBtns" @click="handleTableBtnClick" ></l-table-btns>
|
||||
</l-table>
|
||||
</l-layout>
|
||||
|
||||
|
||||
<l-dialog
|
||||
:title="$t('添加公式条件')"
|
||||
:visible.sync="formulaVisible"
|
||||
:height="480"
|
||||
|
||||
@ok="handleFormulaOk"
|
||||
@closed="handleFormulaClosed"
|
||||
@opened="handleFormulaOpened"
|
||||
>
|
||||
<condition-formula ref="conditionFormula" ></condition-formula>
|
||||
</l-dialog>
|
||||
|
||||
<l-dialog
|
||||
:title="$t('添加sql条件')"
|
||||
:visible.sync="sqlVisible"
|
||||
:height="480"
|
||||
|
||||
@ok="handleSqlOk"
|
||||
@closed="handleSqlClosed"
|
||||
@opened="handleSqlOpened"
|
||||
>
|
||||
<condition-sql ref="conditionSql" ></condition-sql>
|
||||
</l-dialog>
|
||||
|
||||
|
||||
</l-layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import conditionFormula from './conditionFormula.vue'
|
||||
import conditionSql from './conditionSql.vue'
|
||||
|
||||
export default {
|
||||
name:'gateway-inclusive-option',
|
||||
props:{
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
conditionFormula,
|
||||
conditionSql
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tableBtns:[
|
||||
{prop:'Edit',label:'编辑'},
|
||||
{prop:'Delete',label:'删除'}
|
||||
],
|
||||
columns:[
|
||||
{label:'类型',prop:'type',width:'80', align: 'center'},
|
||||
{label:'名称',prop:'name',minWidth:'100'},
|
||||
],
|
||||
tableData:[],
|
||||
|
||||
formulaVisible:false,
|
||||
sqlVisible:false,
|
||||
|
||||
editRow:null,
|
||||
isEdit:false,
|
||||
rowIndex:0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"],
|
||||
methods:{
|
||||
typeFormat(type){
|
||||
switch(type){
|
||||
case '1':
|
||||
return '表达式'
|
||||
case '2':
|
||||
return 'sql语句'
|
||||
}
|
||||
},
|
||||
handleTableBtnClick(btn){
|
||||
switch(btn.type){
|
||||
case 'Edit':
|
||||
this.isEdit = true;
|
||||
this.editRow = btn.row;
|
||||
this.rowIndex = btn.rowIndex;
|
||||
if(this.editRow.type == '1'){
|
||||
this.formulaVisible = true;
|
||||
}
|
||||
else{
|
||||
this.sqlVisible = true;
|
||||
}
|
||||
break;
|
||||
case 'Delete':
|
||||
this.node.conditions.splice(btn.rowIndex,1);
|
||||
break;
|
||||
}
|
||||
console.log(btn);
|
||||
//this.tableData.splice(btn.rowIndex,1);
|
||||
},
|
||||
handleFormulaClick(){
|
||||
this.isEdit = false;
|
||||
this.formulaVisible = true;
|
||||
},
|
||||
handleSQlClick(){
|
||||
this.isEdit = false;
|
||||
this.sqlVisible = true;
|
||||
},
|
||||
handleClearClick(){
|
||||
this.node.conditions = [];
|
||||
},
|
||||
handleFormulaOk(){
|
||||
this.$refs.conditionFormula.validateForm(()=>{
|
||||
let formData = this.$refs.conditionFormula.getForm();
|
||||
formData.type = '1';
|
||||
|
||||
if(this.isEdit){
|
||||
this.node.conditions[this.rowIndex] = formData;
|
||||
}
|
||||
else{
|
||||
formData.code = this.$uuid();
|
||||
this.node.conditions.push(formData);
|
||||
}
|
||||
|
||||
|
||||
this.formulaVisible = false;
|
||||
})
|
||||
},
|
||||
handleFormulaOpened(){
|
||||
if(this.isEdit){
|
||||
this.$refs.conditionFormula.setForm(this.editRow);
|
||||
}
|
||||
|
||||
},
|
||||
handleFormulaClosed(){
|
||||
this.$refs.conditionFormula.resetForm();
|
||||
},
|
||||
handleSqlOk(){
|
||||
this.$refs.conditionSql.validateForm(()=>{
|
||||
let formData = this.$refs.conditionSql.getForm();
|
||||
formData.type = '2';
|
||||
|
||||
if(this.isEdit){
|
||||
this.node.conditions[this.rowIndex] = formData;
|
||||
}
|
||||
else{
|
||||
formData.code = this.$uuid();
|
||||
this.node.conditions.push(formData);
|
||||
}
|
||||
|
||||
this.sqlVisible = false;
|
||||
})
|
||||
},
|
||||
handleSqlOpened(){
|
||||
if(this.isEdit){
|
||||
this.$refs.conditionSql.setForm(this.editRow);
|
||||
}
|
||||
},
|
||||
handleSqlClosed(){
|
||||
this.$refs.conditionSql.resetForm();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<l-layout :top="180" >
|
||||
<template #top>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<div style="padding:0 16px;">
|
||||
<el-alert
|
||||
title="排他网关说明"
|
||||
type="info"
|
||||
description="排他网关不会等待所有分支汇入才往下执行,只要有分支汇入就会往下执行,出口分支只会执行一条(条件为true,如果多条出口分支条件为true也执行一条)"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<l-layout :top="40">
|
||||
<template #top v-if="!disabled">
|
||||
<div style="padding-left:8px;float:left;" >
|
||||
<el-button-group>
|
||||
<el-button size="mini" icon="el-icon-plus" @click="handleFormulaClick">{{$t('公式')}}</el-button>
|
||||
<el-button size="mini" icon="el-icon-plus" @click="handleSQlClick">{{$t('sql语句')}}</el-button>
|
||||
</el-button-group>
|
||||
</div>
|
||||
<div style="padding-right:8px;float:right;">
|
||||
<el-button size="mini" type="danger" icon="el-icon-delete" @click="handleClearClick">{{$t('清空')}}</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<l-table :columns="columns" :dataSource="node.conditions" >
|
||||
<template v-slot:type="scope" >
|
||||
{{typeFormat(scope.row.type)}}
|
||||
</template>
|
||||
<l-table-btns v-if="!disabled" :btns="tableBtns" @click="handleTableBtnClick" ></l-table-btns>
|
||||
</l-table>
|
||||
</l-layout>
|
||||
|
||||
|
||||
<l-dialog
|
||||
:title="$t('添加公式条件')"
|
||||
:visible.sync="formulaVisible"
|
||||
:height="480"
|
||||
|
||||
@ok="handleFormulaOk"
|
||||
@closed="handleFormulaClosed"
|
||||
@opened="handleFormulaOpened"
|
||||
>
|
||||
<condition-formula ref="conditionFormula" ></condition-formula>
|
||||
</l-dialog>
|
||||
|
||||
<l-dialog
|
||||
:title="$t('添加sql条件')"
|
||||
:visible.sync="sqlVisible"
|
||||
:height="480"
|
||||
|
||||
@ok="handleSqlOk"
|
||||
@closed="handleSqlClosed"
|
||||
@opened="handleSqlOpened"
|
||||
>
|
||||
<condition-sql ref="conditionSql" ></condition-sql>
|
||||
</l-dialog>
|
||||
|
||||
|
||||
</l-layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import conditionFormula from './conditionFormula.vue'
|
||||
import conditionSql from './conditionSql.vue'
|
||||
|
||||
export default {
|
||||
name:'gateway-xor-option',
|
||||
props:{
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
conditionFormula,
|
||||
conditionSql
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tableBtns:[
|
||||
{prop:'Edit',label:'编辑'},
|
||||
{prop:'Delete',label:'删除'}
|
||||
],
|
||||
columns:[
|
||||
{label:'类型',prop:'type',width:'80', align: 'center'},
|
||||
{label:'名称',prop:'name',minWidth:'100'},
|
||||
],
|
||||
tableData:[],
|
||||
|
||||
formulaVisible:false,
|
||||
sqlVisible:false,
|
||||
|
||||
editRow:null,
|
||||
isEdit:false,
|
||||
rowIndex:0,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"],
|
||||
methods:{
|
||||
typeFormat(type){
|
||||
switch(type){
|
||||
case '1':
|
||||
return '表达式'
|
||||
case '2':
|
||||
return 'sql语句'
|
||||
}
|
||||
},
|
||||
handleTableBtnClick(btn){
|
||||
switch(btn.type){
|
||||
case 'Edit':
|
||||
this.isEdit = true;
|
||||
this.editRow = btn.row;
|
||||
this.rowIndex = btn.rowIndex;
|
||||
if(this.editRow.type == '1'){
|
||||
this.formulaVisible = true;
|
||||
}
|
||||
else{
|
||||
this.sqlVisible = true;
|
||||
}
|
||||
break;
|
||||
case 'Delete':
|
||||
this.node.conditions.splice(btn.rowIndex,1);
|
||||
break;
|
||||
}
|
||||
console.log(btn);
|
||||
//this.tableData.splice(btn.rowIndex,1);
|
||||
},
|
||||
handleFormulaClick(){
|
||||
this.isEdit = false;
|
||||
this.formulaVisible = true;
|
||||
},
|
||||
handleSQlClick(){
|
||||
this.isEdit = false;
|
||||
this.sqlVisible = true;
|
||||
},
|
||||
handleClearClick(){
|
||||
this.node.conditions = [];
|
||||
},
|
||||
handleFormulaOk(){
|
||||
this.$refs.conditionFormula.validateForm(()=>{
|
||||
let formData = this.$refs.conditionFormula.getForm();
|
||||
formData.type = '1';
|
||||
|
||||
if(this.isEdit){
|
||||
this.node.conditions[this.rowIndex] = formData;
|
||||
}
|
||||
else{
|
||||
formData.code = this.$uuid();
|
||||
this.node.conditions.push(formData);
|
||||
}
|
||||
|
||||
|
||||
this.formulaVisible = false;
|
||||
})
|
||||
},
|
||||
handleFormulaOpened(){
|
||||
if(this.isEdit){
|
||||
this.$refs.conditionFormula.setForm(this.editRow);
|
||||
}
|
||||
|
||||
},
|
||||
handleFormulaClosed(){
|
||||
this.$refs.conditionFormula.resetForm();
|
||||
},
|
||||
handleSqlOk(){
|
||||
this.$refs.conditionSql.validateForm(()=>{
|
||||
let formData = this.$refs.conditionSql.getForm();
|
||||
formData.type = '2';
|
||||
|
||||
if(this.isEdit){
|
||||
this.node.conditions[this.rowIndex] = formData;
|
||||
}
|
||||
else{
|
||||
formData.code = this.$uuid();
|
||||
this.node.conditions.push(formData);
|
||||
}
|
||||
|
||||
this.sqlVisible = false;
|
||||
})
|
||||
},
|
||||
handleSqlOpened(){
|
||||
if(this.isEdit){
|
||||
this.$refs.conditionSql.setForm(this.editRow);
|
||||
}
|
||||
},
|
||||
handleSqlClosed(){
|
||||
this.$refs.conditionSql.resetForm();
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini">
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="conditionsOptions && conditionsOptions.length >0" label="流转条件">
|
||||
<l-select
|
||||
:disabled="disabled"
|
||||
|
||||
v-model="value"
|
||||
:options="conditionsOptions"
|
||||
|
||||
labelKey="name"
|
||||
valueKey="code"
|
||||
:multiple="true"
|
||||
placeholder="不选择,默认流转条件为true"
|
||||
></l-select>
|
||||
</el-form-item>
|
||||
|
||||
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'line-option',
|
||||
props:{
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
conditionsOptions:[],
|
||||
value2:''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
},
|
||||
value:{
|
||||
get(){
|
||||
return this.value2;
|
||||
},
|
||||
set(val){
|
||||
this.value2 = val;
|
||||
this.node.lineConditions = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"],
|
||||
created(){
|
||||
this.getConditions()
|
||||
},
|
||||
methods:{
|
||||
getConditions(){
|
||||
let wfdata = this.wfdesign.handleGetWFData();
|
||||
let fromNode = wfdata.find(t=>t.id == this.node.from);
|
||||
/**
|
||||
* startEvent:'开始节点',
|
||||
endEvent:'结束节点',
|
||||
gatewayAnd:'并行网关',
|
||||
gatewayInclusive:'包含网关',
|
||||
gatewayXor:'排他网关',
|
||||
scriptTask:'脚本节点',
|
||||
userTask:'审核节点',
|
||||
subprocess:'子流程',
|
||||
*/
|
||||
switch(fromNode.type){
|
||||
case 'startEvent':
|
||||
case 'endEvent':
|
||||
case 'gatewayAnd':
|
||||
case 'scriptTask':
|
||||
case 'subprocess':
|
||||
this.node.lineConditions = ''
|
||||
this.conditionsOptions = []
|
||||
break
|
||||
case 'gatewayInclusive':
|
||||
case 'gatewayXor':
|
||||
this.conditionsOptions = fromNode.conditions
|
||||
// 过滤掉没有的值
|
||||
this.filterValue()
|
||||
break
|
||||
case 'userTask':
|
||||
this.conditionsOptions = fromNode.btnlist.filter(t=>!t.hidden)
|
||||
|
||||
|
||||
|
||||
// 过滤掉没有的值
|
||||
this.filterValue()
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
|
||||
this.value2 = this.node.lineConditions
|
||||
},
|
||||
filterValue(){
|
||||
const vlist = this.node.lineConditions.split(',')
|
||||
const res = []
|
||||
vlist.forEach(item => {
|
||||
if(this.conditionsOptions.findIndex(t=>t.code == item) != -1){
|
||||
res.push(item)
|
||||
}
|
||||
})
|
||||
this.node.lineConditions = String(res)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini">
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<el-divider>执行操作</el-divider>
|
||||
<div style="text-align: center;margin-bottom:16px;" >
|
||||
<el-radio-group v-model="node.executeType" size="mini" :disabled="disabled">
|
||||
<el-radio-button label="1">执行SQL</el-radio-button>
|
||||
<el-radio-button label="2">.NET方法</el-radio-button>
|
||||
<el-radio-button label="3">第三方接口</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<template v-if="node.executeType == '1'" >
|
||||
<div style="padding:0 0 16px 0;">
|
||||
<el-alert
|
||||
title="sql参数说明"
|
||||
type="info"
|
||||
description="参数有 @processId流程进程主键 @code上一步执行码 @userId流程发起人Id @userAccount流程发起人账号 @companyId流程发起人公司 @departmentId流程发起人部门;
|
||||
@userId2上一步审核人Id @userAccount2上一步审核人账号 @companyId2上一步审核人公司 @departmentId2上一步审核人部门;
|
||||
"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
<el-form-item label-width="0">
|
||||
<el-select v-model="node.sqlDb" placeholder="请选择执行SQL数据库" :disabled="disabled">
|
||||
<el-option-group
|
||||
v-for="group in lr_dblinkTree"
|
||||
:key="group.id"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="item in group.children"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.sqlStr" rows="8" placeholder="请填写SQL语句" ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.sqlStrRevoke" rows="8" placeholder="请填写SQL语句(撤销)" ></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="node.executeType == '2'" >
|
||||
<div style="padding:0 0 16px 0;">
|
||||
<el-alert
|
||||
title="IOC说明"
|
||||
type="info"
|
||||
description="注意:编写一个继承IWorkFlowMethod的类
|
||||
"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.ioc" rows="4" placeholder="ioc名称" ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.iocRevoke" rows="4" placeholder="ioc名称(撤销)" ></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="node.executeType == '3'" >
|
||||
<div style="padding:0 0 16px 0;">
|
||||
<el-alert
|
||||
title="接口参数说明"
|
||||
type="info"
|
||||
description="注意:配置支持Post方法的接口,json数据格式。{
|
||||
processId:'流程发起实例主键',userId:'流程发起人Id',userAccount:'流程发起人账号',companyId:'流程发起人公司',departmentId:'流程发起人部门',code:'上一步执行码',
|
||||
userId2:'上一步审核人Id',userAccount2:'上一步审核人账号',companyId2:'上一步审核人公司',departmentId2:'上一步审核人部门'
|
||||
}
|
||||
"
|
||||
show-icon
|
||||
:closable="false"
|
||||
>
|
||||
</el-alert>
|
||||
</div>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.apiUrl" rows="4" placeholder="接口地址" ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0">
|
||||
<el-input :readonly="disabled" type="textarea" v-model="node.apiUrlRevoke" rows="4" placeholder="接口地址(撤销)" ></el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
|
||||
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'script-task-option',
|
||||
props:{
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-02-29 13:56:45
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-02-29 14:34:53
|
||||
* @Description:
|
||||
-->
|
||||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form
|
||||
class="l-form-config"
|
||||
label-width="88px"
|
||||
label-position="left"
|
||||
size="mini">
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly ></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否异步">
|
||||
<el-switch :disabled="disabled" v-model="node.isAsync">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程模版">
|
||||
<l-select :disabled="disabled" v-model="node.wfschemeId" :options="list">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="流程版本">
|
||||
<l-select :disabled="disabled" v-model="node.wfVersionId" :options="verisons">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// const api = window.$api.workflow.scheme
|
||||
|
||||
export default {
|
||||
name:'subprocess-option',
|
||||
props:{
|
||||
disabled:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
asyncComputed:{
|
||||
list:{
|
||||
async get(){
|
||||
const data = []
|
||||
// const data = await this.$awaitWraper(api.getList())
|
||||
const res = data || []
|
||||
return res.filter(t=>t.f_Id != this.wfdesign.schemeinfoId).map(t=>{return {label:t.f_Name,value:t.f_Id}})
|
||||
}
|
||||
},
|
||||
verisons:{
|
||||
async get(){
|
||||
let res = []
|
||||
if(!this.$validatenull(this.node.wfschemeId)){
|
||||
// res = await this.$awaitWraper(api.getHistoryList(this.node.wfschemeId))
|
||||
}
|
||||
return (res || []).map(t=>{return { label:this.lr_dateFormat(t.f_CreateDate),value:t.f_Id }})
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node(){
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import BpmnPropertiesPanel from "./PropertiesPanel.vue";
|
||||
|
||||
BpmnPropertiesPanel.install = function(Vue) {
|
||||
Vue.component(BpmnPropertiesPanel.name, BpmnPropertiesPanel);
|
||||
};
|
||||
|
||||
export default BpmnPropertiesPanel;
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
<template>
|
||||
<div class="shceme-info">
|
||||
<a-form ref="formRef" :rules="rules" :model="formState" labelAlign="left" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-form-item label="模板编号" name="f_Code">
|
||||
<a-input v-model:value="formState.f_Code" placeholder="请输入" />
|
||||
</a-form-item>
|
||||
<a-form-item label="模板名称" name="f_Name">
|
||||
<a-input v-model:value="formState.f_Name" placeholder="请输入" />
|
||||
</a-form-item>
|
||||
<a-form-item label="模板图标" name="f_Icon">
|
||||
<IconPicker :value="formState.f_Icon" />
|
||||
</a-form-item>
|
||||
<a-form-item label="图标颜色" name="f_Color">
|
||||
<a-input type="color" v-model="formState.f_Color" placeholder="请输入"></a-input>
|
||||
</a-form-item>
|
||||
<a-form-item label="模板分类" name="f_Category">
|
||||
<a-select v-model:value="formState.f_Category" placeholder="please select your zone">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="我的任务创建">
|
||||
<a-radio-group v-model:value="formState.f_Mark" name="radioGroup">
|
||||
<a-radio v-for="item in data.optionsNotOrOk" :value="item.value">{{item.label}}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="移动端创建">
|
||||
<a-radio-group v-model:value="formState.f_IsInApp" name="radioGroup">
|
||||
<a-radio v-for="item in data.optionsNotOrOk" :value="item.value">{{item.label}}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-textarea v-model:value="formState.f_Description" placeholder="请填写备注"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
|
||||
|
||||
<a-divider plain="true">撤销操作</a-divider>
|
||||
<a-tabs v-model:activeKey="formState.undoType" type="card" size="small" centered="true">
|
||||
<a-tab-pane key="1" tab="执行SQL">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-select v-model:value="formState.undoDbCode" placeholder="请选择执行SQL数据库">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-space-compact>
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.undoDbSQL"
|
||||
placeholder="请填写SQL语句,参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab=".NET方法">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.undoIOCName" placeholder="请填写.NET方法IOC别名"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="第三方接口">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.undoUrl"
|
||||
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<a-divider plain="true">作废操作</a-divider>
|
||||
<a-tabs v-model:activeKey="formState.deleteType" type="card" size="small" centered="true">
|
||||
<a-tab-pane key="1" tab="执行SQL">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-select v-model:value="formState.deleteDbCode" placeholder="请选择执行SQL数据库">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-space-compact>
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.deleteDbSQL"
|
||||
placeholder="请填写SQL语句,参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab=".NET方法">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.deleteIOCName" placeholder="请填写.NET方法IOC别名"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="第三方接口">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.undoUrl"
|
||||
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<a-divider plain="true">删除草稿</a-divider>
|
||||
<a-tabs v-model:activeKey="formState.deleteDraftType" type="card" size="small" centered="true">
|
||||
<a-tab-pane key="1" tab="执行SQL">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-select v-model:value="formState.deleteDraftDbCode" placeholder="请选择执行SQL数据库">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-space-compact>
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.deleteDraftDbSQL"
|
||||
placeholder="请填写SQL语句,参数有 @processId流程进程主键 @userId用户Id @userAccount用户账号 @companyId用户公司 @departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab=".NET方法">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.deleteDraftIOCName" placeholder="请填写.NET方法IOC别名"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="第三方接口">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-textarea v-model:value="formState.undoUrl"
|
||||
placeholder="请填写第三方接口地址(POST),JSON 格式,参数有 userId用户Id,userAccount用户账号,companyId用户公司,departmentId用户部门"
|
||||
:auto-size="{ minRows: 5, maxRows: 8 }" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Dayjs } from 'dayjs';
|
||||
import { reactive, ref, toRaw } from 'vue';
|
||||
import type { UnwrapRef } from 'vue';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import { IconPicker } from '/@/components/Icon';
|
||||
const formRef = ref();
|
||||
const labelCol = { span: 7 };
|
||||
const wrapperCol = { span: 17 };
|
||||
const activeKey = ref('1')
|
||||
const data = reactive({
|
||||
optionsNotOrOk: [{ label: '允许', value: 1 }, { label: '不允许', value: 2 }],
|
||||
|
||||
})
|
||||
const formState = reactive({
|
||||
f_Code: '',
|
||||
f_Name: '',
|
||||
f_Category: '',
|
||||
f_Mark: 1,
|
||||
f_IsInApp: 2,
|
||||
f_Description: '',
|
||||
|
||||
titleRules: '',
|
||||
|
||||
undoType: "1",
|
||||
undoDbCode: '',
|
||||
undoDbSQL: '',
|
||||
undoIOCName: '',
|
||||
undoUrl: '',
|
||||
|
||||
deleteType: "1",
|
||||
deleteDbCode: '',
|
||||
deleteDbSQL: '',
|
||||
deleteIOCName: '',
|
||||
deleteUrl: '',
|
||||
|
||||
deleteDraftType: "1",
|
||||
deleteDraftDbCode: '',
|
||||
deleteDraftDbSQL: '',
|
||||
deleteDraftIOCName: '',
|
||||
deleteDraftUrl: '',
|
||||
f_Icon: '',
|
||||
f_Color: '#409EFF',
|
||||
});
|
||||
const rules: Record<string, Rule[]> = {
|
||||
f_Code: [
|
||||
{ required: true, message: '请输入模板编号' },
|
||||
// { validator: lr_existDbFiled, keyValue: () => { return data.formData.f_Id }, tableName: 'lr_wf_schemeinfo', keyName: 'f_Id', trigger: 'blur' }
|
||||
],
|
||||
f_Name: [
|
||||
{ required: true, message: '请输入模板名称' }
|
||||
],
|
||||
f_Category: [
|
||||
{ required: true, message: '请选择模板分类' }
|
||||
],
|
||||
f_Icon: [
|
||||
{ required: true, message: '请选择图标' }
|
||||
],
|
||||
f_Color: [
|
||||
{ required: true, message: '请选择颜色' }
|
||||
],
|
||||
};
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.site-space-compact-wrapper {
|
||||
width: 100%;
|
||||
.ant-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
::v-deep .ant-tabs {
|
||||
padding: 0!important;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<div class="start-event">
|
||||
|
||||
<a-form ref="formRef" :rules="rules" :model="node" labelAlign="left" :label-col="labelCol"
|
||||
:wrapper-col="wrapperCol">
|
||||
<a-form-item label="节点标识">
|
||||
<a-input v-model:value="node.id" placeholder="请输入" readonly />
|
||||
</a-form-item>
|
||||
<a-form-item label="下一审核人">
|
||||
<a-switch v-model:checked="node.isNextAuditor" />
|
||||
</a-form-item>
|
||||
<a-form-item label="自定义标题">
|
||||
<a-switch v-model:checked="node.isCustmerTitle" />
|
||||
</a-form-item>
|
||||
<a-form-item label="通知策略" name="f_Color">
|
||||
<a-checkbox-group v-model:value="node.messageType" name="checkboxgroup"
|
||||
:options="[{value:'1',label:'短信'},{value:'2',label:'邮箱'},{value:'3',label:'微信'},{value:'4',label:'站内消息'}]" />
|
||||
</a-form-item>
|
||||
|
||||
<a-divider plain="true">表单添加</a-divider>
|
||||
<a-tabs v-model:activeKey="node.formType" type="card" size="small" centered="true">
|
||||
<a-tab-pane key="1" tab="自定义表单">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-select v-model:value="node.formVerison" placeholder="请选择表单版本">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-space-compact>
|
||||
<a-space-compact block>
|
||||
<a-select v-model:value="node.formRelationId" placeholder="请选择流程关联字段">
|
||||
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||
<a-select-option value="beijing">Zone two</a-select-option>
|
||||
</a-select>
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="系统表单">
|
||||
<a-space direction="vertical" size="middle" class="site-space-compact-wrapper">
|
||||
<a-space-compact block>
|
||||
<a-input v-model:value="node.formUrl" placeholder="请输入PC端表单地址" />
|
||||
</a-space-compact>
|
||||
<a-space-compact block>
|
||||
<a-input v-model:value="node.formAppUrl" placeholder="请输入APP端表单地址" />
|
||||
</a-space-compact>
|
||||
</a-space>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
<a-divider plain="true">表单字段权限</a-divider>
|
||||
<a-table :columns="data.columns" :data-source="node.authFields" bordered :pagination="false"
|
||||
v-if="node.formType == 1">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['label', 'field'].includes(column.dataIndex)">
|
||||
<div>
|
||||
{{ text }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="['required', 'isEdit','isLook'].includes(column.dataIndex)">
|
||||
<div>
|
||||
<a-switch v-model:checked="record[column.dataIndex]" />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
<a-table :columns="data.columns" :data-source="node.authFields" bordered :pagination="false" v-else>
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['label', 'field'].includes(column.dataIndex)">
|
||||
<div>
|
||||
{{ text }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="['required', 'isEdit','isLook'].includes(column.dataIndex)">
|
||||
<div>
|
||||
<a-switch v-model:checked="record[column.dataIndex]" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<delete-outlined two-tone-color='#eb2f96' @click='handleDeleteAuthField(record.field)' />
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<a-divider plain="true"></a-divider>
|
||||
<a-space v-if="node.formType!=1">
|
||||
<a-button @click="handleAddAuthField" width="100%" type="dashed" danger :icon="h(PlusOutlined)">添加字段</a-button>
|
||||
</a-space>
|
||||
<!-- <a-table :columns="data.columns" :data-source="node.authField" bordered :pagination="false">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['name', 'type'].includes(column.dataIndex)">
|
||||
<div>
|
||||
<a-input
|
||||
v-model:value="text"
|
||||
style="margin: -5px 0"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<a>删除</a>
|
||||
</template>
|
||||
</template>
|
||||
</a-table> -->
|
||||
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, defineProps, computed, inject, ref, watch, h } from 'vue'
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons-vue'
|
||||
const labelCol = { span: 7 };
|
||||
const wrapperCol = { span: 17 };
|
||||
const props = defineProps({
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
element: Object
|
||||
})
|
||||
const data = reactive({
|
||||
columns: [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'label',
|
||||
},
|
||||
{
|
||||
title: '字段',
|
||||
dataIndex: 'field',
|
||||
},
|
||||
{
|
||||
title: '必填',
|
||||
dataIndex: 'required',
|
||||
},
|
||||
{
|
||||
title: '编辑',
|
||||
dataIndex: 'isEdit',
|
||||
},
|
||||
{
|
||||
title: '查看',
|
||||
dataIndex: 'isLook',
|
||||
},
|
||||
|
||||
|
||||
],
|
||||
formRelations: [],
|
||||
elementData: props.element
|
||||
})
|
||||
const node = reactive({
|
||||
id: data.elementData.id,
|
||||
type: data.elementData.type,
|
||||
isNextAuditor: false,
|
||||
isCustmerTitle: false,
|
||||
formRelations: [],
|
||||
formType: "1",
|
||||
formCode: "",
|
||||
formVerison: "",
|
||||
formRelationId: "",
|
||||
formUrl: "",
|
||||
formAppUrl: "",
|
||||
authFields: [
|
||||
{
|
||||
label: '测试',
|
||||
field: 'ceshi',
|
||||
required: true,
|
||||
isEdit: true,
|
||||
isLook: true,
|
||||
}
|
||||
],
|
||||
messageType: "",
|
||||
isInit: true
|
||||
})
|
||||
watch(
|
||||
() => props.element,
|
||||
(newVal, oldVal) => {
|
||||
data.elementData = newVal
|
||||
node.id = data.elementData.id
|
||||
node.type = data.elementData.type
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => node.formType,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal == 1) {
|
||||
data.columns = data.columns.filter(item => item.dataIndex !== 'operation');
|
||||
} else {
|
||||
data.columns.push({
|
||||
title: '',
|
||||
dataIndex: 'operation',
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async function custmerformChange(val) {
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
if (val == null) {
|
||||
this.node.authFields = [];
|
||||
this.node.formVerison = ''
|
||||
return;
|
||||
}
|
||||
if (this.$validatenull(this.wfdesign.custmerformSchemes[val.f_SchemeId])) {
|
||||
// const {f_SchemeInfoId,f_Scheme,f_Id} = (await this.$awaitWraper(apiForm.getHistory(val.f_SchemeId))) || {}
|
||||
this.wfdesign.custmerformSchemes[f_Id] = { f_Scheme }
|
||||
if (this.node.formCode == f_SchemeInfoId) {
|
||||
this.loadFormScheme(f_Scheme)
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.loadFormScheme(this.wfdesign.custmerformSchemes[val.f_SchemeId].f_Scheme);
|
||||
}
|
||||
this.node.formVerison = val.f_SchemeId
|
||||
}
|
||||
async function custmerformVerisonChange(val) {
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
if (this.$validatenull(val)) {
|
||||
this.node.authFields = []
|
||||
return
|
||||
}
|
||||
if (this.$validatenull(this.wfdesign.custmerformSchemes[val.value])) {
|
||||
// const {f_Scheme,f_Id} = (await this.$awaitWraper(apiForm.getHistory(val.value))) || {}
|
||||
this.wfdesign.custmerformSchemes[f_Id] = { f_Scheme }
|
||||
if (this.node.formVerison == f_Id) {
|
||||
|
||||
this.loadFormScheme(f_Scheme)
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.loadFormScheme(this.wfdesign.custmerformSchemes[val.value].f_Scheme);
|
||||
}
|
||||
}
|
||||
function loadFormScheme(strScheme) {
|
||||
const scheme = JSON.parse(strScheme)
|
||||
const fields = []
|
||||
const rfields = []
|
||||
scheme.formInfo.tabList.forEach(tab => {
|
||||
tab.components.forEach(component => {
|
||||
if (['guid'].includes(component.type)) {
|
||||
rfields.push({ label: component.label, value: component.prop })
|
||||
}
|
||||
|
||||
if (!['gridtable', 'divider'].includes(component.type) && component.display) {
|
||||
fields.push({
|
||||
prop: component.prop,
|
||||
field: component.field,
|
||||
label: component.label,
|
||||
table: component.table,
|
||||
required: component.required,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
})
|
||||
}
|
||||
else if (['gridtable'].includes(component.type)) {
|
||||
fields.push({
|
||||
prop: `${component.prop}_add`,
|
||||
label: `${component.label || '表格'}-添加按钮`,
|
||||
required: false,
|
||||
isEdit: true,
|
||||
isLook: false,
|
||||
type: 'grid'
|
||||
})
|
||||
fields.push({
|
||||
prop: `${component.prop}_remove`,
|
||||
label: `${component.label || '表格'}-删除按钮`,
|
||||
required: false,
|
||||
isEdit: true,
|
||||
isLook: false,
|
||||
type: 'grid'
|
||||
})
|
||||
|
||||
fields.push({
|
||||
prop: `${component.prop}_required`,
|
||||
label: `${component.label || '表格'}-数据`,
|
||||
required: component.required,
|
||||
isEdit: false,
|
||||
isLook: false,
|
||||
type: 'gridrequired'
|
||||
})
|
||||
fields.push(...component.children.filter(t => t.display).map(t => {
|
||||
return {
|
||||
gridprop: component.prop,
|
||||
prop: t.prop,
|
||||
field: t.field,
|
||||
label: `${component.label || '表格'}-${t.label}`,
|
||||
table: component.table,
|
||||
required: t.required,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
this.node.formRelations = rfields
|
||||
this.node.authFields = fields
|
||||
|
||||
}
|
||||
function handleFormTypeChange() {
|
||||
this.node.formCode = ''
|
||||
this.node.formUrl = ''
|
||||
this.node.formAppUrl = ''
|
||||
this.node.authFields = []
|
||||
this.node.formRelations = []
|
||||
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
|
||||
}
|
||||
function handleAddAuthField() {
|
||||
node.authFields.push({
|
||||
field: '',
|
||||
label: '',
|
||||
required: true,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
})
|
||||
}
|
||||
function handleDeleteAuthField(key) {
|
||||
node.authFields = node.authFields.filter(item => item.field !== key);
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.site-space-compact-wrapper {
|
||||
width: 100%;
|
||||
|
||||
.ant-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ant-tabs {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .ant-space {
|
||||
width: 90%;
|
||||
margin-left: 5%;
|
||||
|
||||
.ant-space-item {
|
||||
width: 100%;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<el-form label-width="96px" label-position="left" size="mini">
|
||||
<el-collapse v-model="activeNames" accordion>
|
||||
<el-collapse-item :title="$t('基础配置')" name="1">
|
||||
<div style="padding:0 16px;">
|
||||
<el-form-item label="节点标识">
|
||||
<el-input v-model="node.id" readonly></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="继承表单">
|
||||
<el-switch :disabled="disabled" v-model="node.isInherit">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许加签">
|
||||
<el-switch :disabled="disabled" v-model="node.isAddSign">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许转移">
|
||||
<el-switch :disabled="disabled" v-model="node.isTransfer">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="允许批量审核">
|
||||
<el-switch :disabled="disabled" v-model="node.isBatchAudit">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="自动同意规则">
|
||||
<l-select multiple :disabled="disabled" v-model="node.autoAgree" :options="atuoAgreeOptions">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="无对应处理人">
|
||||
<l-select :disabled="disabled" v-model="node.noAuditor" :options="noAuditorOptions">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="驳回策略">
|
||||
<l-radio :disabled="disabled" v-model="node.rejectType"
|
||||
:options="[{value:'1',label:'驳回节点固定'},{value:'2',label:'能驳回到任何执行过节点'}]">
|
||||
</l-radio>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="通知策略">
|
||||
<l-checkbox :disabled="disabled" v-model="node.messageType"
|
||||
:options="[{value:'1',label:'短信'},{value:'2',label:'邮箱'},{value:'3',label:'微信'},{value:'4',label:'站内消息'}]">
|
||||
</l-checkbox>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('审核人员设置')" name="2">
|
||||
<el-button-group style="padding:0 0 8px 8px" v-if="!disabled">
|
||||
<el-button size="mini" @click="handlePostClick(false)">{{$t('岗位')}}</el-button>
|
||||
<el-button size="mini" @click="handleRoleClick(false)">{{$t('角色')}}</el-button>
|
||||
<el-button size="mini" @click="handleUserClick(false)">{{$t('用户')}}</el-button>
|
||||
<el-button size="mini" @click="handleLevelClick(false)">{{$t('上下级')}}</el-button>
|
||||
<el-button size="mini" @click="handleNodeAuditorClick(false)">{{$t('节点执行人')}}</el-button>
|
||||
<el-button size="mini" @click="handleAuditorSqlClick(false)">{{$t('表字段')}}</el-button>
|
||||
</el-button-group>
|
||||
<l-table height="notset" :isShowNum="false" :columns="userColumns" :dataSource="node.auditUsers">
|
||||
<template v-slot:type="scope">
|
||||
{{typeFormat(scope.row.type)}}
|
||||
</template>
|
||||
<template v-slot:condition="scope">
|
||||
<l-select :disabled="disabled" size="mini" v-if="scope.row.type == '2'"
|
||||
:options="conditionOptions" v-model="scope.row.condition"></l-select>
|
||||
</template>
|
||||
<l-table-btns v-if="!disabled" :isFixed="false" :btns="tableBtns" @click="handleTableBtnClick">
|
||||
</l-table-btns>
|
||||
</l-table>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('传阅人员设置')" name="3">
|
||||
<el-button-group style="padding:0 0 8px 8px" v-if="!disabled">
|
||||
<el-button size="mini" @click="handlePostClick(true)">{{$t('岗位')}}</el-button>
|
||||
<el-button size="mini" @click="handleRoleClick(true)">{{$t('角色')}}</el-button>
|
||||
<el-button size="mini" @click="handleUserClick(true)">{{$t('用户')}}</el-button>
|
||||
<el-button size="mini" @click="handleLevelClick(true)">{{$t('上下级')}}</el-button>
|
||||
<el-button size="mini" @click="handleNodeAuditorClick(true)">{{$t('节点执行人')}}</el-button>
|
||||
<el-button size="mini" @click="handleAuditorSqlClick(true)">{{$t('表字段')}}</el-button>
|
||||
</el-button-group>
|
||||
<l-table height="notset" :isShowNum="false" :columns="userColumns" :dataSource="node.lookUsers">
|
||||
<template v-slot:type="scope">
|
||||
{{typeFormat(scope.row.type)}}
|
||||
</template>
|
||||
<template v-slot:condition="scope">
|
||||
<l-select :disabled="disabled" size="mini" v-if="scope.row.type == '2'"
|
||||
:options="conditionOptions" v-model="scope.row.condition"></l-select>
|
||||
</template>
|
||||
<l-table-btns v-if="!disabled" :isFixed="false" :btns="tableBtns" @click="handleTableBtnClick2">
|
||||
</l-table-btns>
|
||||
</l-table>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item v-if="!node.isInherit" :title="$t('表单设置')" name="4">
|
||||
<div style="padding:0 16px;">
|
||||
<div style="text-align: center;margin-bottom:16px;">
|
||||
<el-radio-group :disabled="disabled" v-model="node.formType" size="mini"
|
||||
@change="handleFormTypeChange">
|
||||
<el-radio-button label="1">自定义表单</el-radio-button>
|
||||
<el-radio-button label="2">系统表单</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-show="node.formType === '1'">
|
||||
<el-form-item label-width="0px">
|
||||
<l-custmerform-select v-model="node.formCode" @change="custmerformChange"
|
||||
:disabled="disabled">
|
||||
</l-custmerform-select>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<l-select v-model="node.formVerison" :disabled="disabled" :options="formVerisons"
|
||||
@change="custmerformVerisonChange" placeholder="请选择表单版本">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<l-select v-model="node.formRelationId" :disabled="disabled" :options="node.formRelations"
|
||||
placeholder="请选择流程关联字段">
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
|
||||
</div>
|
||||
<div v-show="node.formType === '2'">
|
||||
<el-form-item label-width="0px">
|
||||
<el-input v-model="node.formUrl" placeholder="请输入PC端表单地址" :readonly="disabled">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<el-input v-model="node.formAppUrl" placeholder="请输入APP端表单地址" :readonly="disabled">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-divider>表单字段权限</el-divider>
|
||||
<template v-if="node.formType === '1'">
|
||||
<l-table height="notset" :isShowNum="false" :columns="columns" :dataSource="node.authFields"
|
||||
ref="authField">
|
||||
<template v-slot:required="scope">
|
||||
<el-switch v-model="scope.row.required"
|
||||
:disabled="disabled || scope.row.type == 'grid'">
|
||||
</el-switch>
|
||||
</template>
|
||||
<template v-slot:isEdit="scope">
|
||||
<el-switch v-model="scope.row.isEdit"
|
||||
:disabled="disabled || scope.row.type == 'gridrequired'">
|
||||
</el-switch>
|
||||
</template>
|
||||
<template v-slot:isLook="scope">
|
||||
<el-switch v-model="scope.row.isLook"
|
||||
:disabled="disabled || scope.row.type == 'grid' || scope.row.type == 'gridrequired'">
|
||||
</el-switch>
|
||||
</template>
|
||||
</l-table>
|
||||
</template>
|
||||
<template v-else>
|
||||
<l-edit-table addBtnText="添加字段" :dataSource="node.authFields" :isShowNum="false"
|
||||
:isAddBtn="!disabled" :isRemoveBtn="!disabled" @addRow="handleAddAuthField"
|
||||
@deleteRow="handleDeleteAuthField">
|
||||
<el-table-column prop="label" label="名称" minWidth="100">
|
||||
<template slot-scope="scope">
|
||||
<el-input :readonly="disabled" size="mini" v-model="scope.row.label"
|
||||
placeholder="请输入名称"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="field" label="字段" minWidth="100">
|
||||
<template slot-scope="scope">
|
||||
<el-input :readonly="disabled" size="mini" v-model="scope.row.field"
|
||||
placeholder="请输入字段"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="required" label="必填" width="64">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.required" :disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isEdit" label="编辑" width="64">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isEdit" :disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="isLook" label="查看" width="64">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isLook" :disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</l-edit-table>
|
||||
</template>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('按钮设置')" name="5">
|
||||
<l-edit-table addBtnText="添加按钮" :dataSource="node.btnlist" :isShowNum="false"
|
||||
:hasDeleteBtn="hasBtnsDeleteBtn" :isAddBtn="!disabled" :isRemoveBtn="!disabled"
|
||||
@addRow="handleAddBtns" @deleteRow="handleDeleteBtns">
|
||||
<el-table-column prop="name" label="名称" minWidth="100">
|
||||
<template slot-scope="scope">
|
||||
<el-input :readonly="disabled" v-if="!scope.row.isSys" size="mini" v-model="scope.row.name"
|
||||
placeholder="请输入名称"></el-input>
|
||||
<span v-else>{{scope.row.name}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="code" label="编码" minWidth="100">
|
||||
<template slot-scope="scope">
|
||||
<el-input :readonly="disabled" v-if="!scope.row.isSys" size="mini" v-model="scope.row.code"
|
||||
placeholder="请输入编码"></el-input>
|
||||
<span v-else>{{scope.row.code}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="hidden" label="隐藏" width="64">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.hidden" :disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="isSign" label="签章" width="64">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.isSign" :disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="isNextAuditor" label="下一审核人" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-if="scope.row.code != 'disagree'" v-model="scope.row.isNextAuditor"
|
||||
:disabled="disabled">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</l-edit-table>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('会签设置')" name="6">
|
||||
<div style="padding:0 16px">
|
||||
<el-form-item label="是否会签">
|
||||
<el-switch v-model="node.isCountersign" :disabled="disabled">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<template v-if="node.isCountersign">
|
||||
<el-form-item label="审核方式">
|
||||
<l-radio :disabled="disabled" v-model="node.countersignType"
|
||||
:options="[{value:'1',label:'并行'},{value:'2',label:'串行'}]">
|
||||
</l-radio>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="node.countersignType == '1'" label="是否等待">
|
||||
<!--并行才有这个设置-->
|
||||
<el-switch v-model="node.isCountersignAll" :disabled="disabled">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="node.countersignType == '1'" label="通过百分比">
|
||||
<el-input-number :disabled="disabled" :min="1" :max="100" v-model="node.countersignAllType">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="再次审核">
|
||||
<l-radio :disabled="disabled" v-model="node.countersignAgian"
|
||||
:options="[{value:'1',label:'已同意不需要审核'},{value:'2',label:'已同意需要审核'}]">
|
||||
</l-radio>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('超时设置')" name="7">
|
||||
<div style="padding:0 16px">
|
||||
<el-form-item label="超时通知">
|
||||
<el-switch :disabled="disabled" v-model="node.isOvertimeMessage">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
<template v-if="node.isOvertimeMessage">
|
||||
|
||||
<el-form-item label="第一次通知(时)">
|
||||
<el-input-number :disabled="disabled" :min="1" v-model="node.overtimeMessageStart">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="通知间隔(时)">
|
||||
<el-input-number :disabled="disabled" :min="1" v-model="node.overtimeMessageInterval">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="超时流转时间(时)">
|
||||
<el-input-number :disabled="disabled" :min="1" v-model="node.overtimeGo">
|
||||
</el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="超时通知策略">
|
||||
<l-checkbox :disabled="disabled" v-model="node.overtimeMessageType"
|
||||
:options="[{value:'1',label:'短信'},{value:'2',label:'邮箱'},{value:'3',label:'微信'},{value:'4',label:'站内消息'}]">
|
||||
</l-checkbox>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
|
||||
|
||||
<l-dialog :title="$t('添加岗位')" :visible.sync="selectPostVisible" :height="480" width="1024px"
|
||||
@ok="handlePostSelectOk" @closed="handlePostSelectClosed">
|
||||
<l-post-select-panel ref="postSelectPanel"></l-post-select-panel>
|
||||
</l-dialog>
|
||||
|
||||
<l-dialog :title="$t('添加角色')" :visible.sync="selectRoleVisible" :height="480" width="800px"
|
||||
@ok="handleRoleSelectOk" @closed="handleRoleSelectClosed">
|
||||
<l-role-select-panel ref="roleSelectPanel"></l-role-select-panel>
|
||||
</l-dialog>
|
||||
|
||||
|
||||
<l-dialog :title="$t('添加用户')" :visible.sync="selectUserVisible" :height="480" width="1024px"
|
||||
@ok="handleUserSelectOk" @closed="handleUserSelectClosed">
|
||||
<l-user-select-panel ref="userSelectPanel"></l-user-select-panel>
|
||||
</l-dialog>
|
||||
|
||||
<!--上下级选择-->
|
||||
<l-dialog :title="$t('上下级选择')" :visible.sync="levelVisible" :height="200" width="500px" @ok="handleLevelOk"
|
||||
@closed="handleLevelClosed">
|
||||
<!-- <auditor-level-form ref="auditorLevelForm"></auditor-level-form> -->
|
||||
</l-dialog>
|
||||
|
||||
<!--流程节点选择-->
|
||||
<l-dialog :title="$t('流程节点选择')" :visible.sync="nodeAuditorVisible" :height="200" width="500px"
|
||||
@ok="handleNodeAuditorOk" @closed="handleNodeAuditorClosed" @opened="handleNodeAuditorOpened">
|
||||
<!-- <node-auditor-form ref="nodeAuditorForm"></node-auditor-form> -->
|
||||
</l-dialog>
|
||||
|
||||
<!--流程节点选择-->
|
||||
<l-dialog :title="$t('数据表字段选择')" :visible.sync="auditorSqlVisible" width="500px" :height="300"
|
||||
@ok="handleAuditorSqlOk" @closed="handleAuditorSqlClosed">
|
||||
<!-- <auditor-sql-form ref="auditorSqlForm"></auditor-sql-form> -->
|
||||
</l-dialog>
|
||||
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
// const apiForm = window.$api.custmerForm.scheme
|
||||
|
||||
// import auditorLevelForm from './auditorLevel.vue'
|
||||
// import nodeAuditorForm from './auditorNode.vue'
|
||||
// import auditorSqlForm from './auditorSql.vue'
|
||||
|
||||
export default {
|
||||
name: 'user-task-option',
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
components: {
|
||||
// auditorLevelForm,
|
||||
// nodeAuditorForm,
|
||||
// auditorSqlForm
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeNames: ['1'],
|
||||
columns: [
|
||||
{ label: '名称', prop: 'label', minWidth: '100' },
|
||||
{ label: '字段', prop: 'field', minWidth: '100' },
|
||||
{ label: '必填', prop: 'required', width: '64', align: 'center' },
|
||||
{ label: '编辑', prop: 'isEdit', width: '64', align: 'center' },
|
||||
{ label: '查看', prop: 'isLook', width: '64', align: 'center' },
|
||||
],
|
||||
tableBtns: [
|
||||
{ prop: 'Delete', label: '删除' }
|
||||
],
|
||||
atuoAgreeOptions: [{ value: '1', label: '处理人就是提交人' }, { value: '2', label: '处理人和上一步的处理人相同' }, { value: '3', label: '处理人审批过' }],
|
||||
noAuditorOptions: [{ value: '1', label: '超级管理员处理' }, { value: '2', label: '跳过此步骤' }, { value: '3', label: '不能提交' }],
|
||||
userColumns: [
|
||||
{ label: '类型', prop: 'type', width: '64' },
|
||||
{ label: '名称', prop: 'name', minWidth: '100' },
|
||||
{ label: '附加条件', prop: 'condition', minWidth: '100' }
|
||||
],
|
||||
|
||||
conditionOptions: [{ value: '1', label: '同一个部门' }, { value: '2', label: '同一个公司' }, { value: '3', label: '发起人上级' }, { value: '4', label: '发起人下级' }],
|
||||
|
||||
selectPostVisible: false,
|
||||
selectRoleVisible: false,
|
||||
selectUserVisible: false,
|
||||
levelVisible: false,
|
||||
nodeAuditorVisible: false,
|
||||
auditorSqlVisible: false,
|
||||
|
||||
isLooker: false,
|
||||
|
||||
}
|
||||
},
|
||||
asyncComputed: {
|
||||
formVerisons: {
|
||||
async get() {
|
||||
let res = []
|
||||
if (!this.$validatenull(this.node.formCode) && this.node.formType == '1') {
|
||||
// res = await this.$awaitWraper(apiForm.getHistoryList(this.node.formCode))
|
||||
}
|
||||
return (res || []).map(t => { return { label: this.lr_dateFormat(t.f_CreateDate), value: t.f_Id } })
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
node() {
|
||||
return this.wfdesign.currentWfNode;
|
||||
}
|
||||
},
|
||||
inject: ["wfdesign"],
|
||||
methods: {
|
||||
async custmerformChange(val) {
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
if (val == null) {
|
||||
this.node.authFields = [];
|
||||
this.node.formVerison = ''
|
||||
return;
|
||||
}
|
||||
if (this.$validatenull(this.wfdesign.custmerformSchemes[val.f_SchemeId])) {
|
||||
// const {f_SchemeInfoId,f_Scheme,f_Id} = (await this.$awaitWraper(apiForm.getHistory(val.f_SchemeId))) || {}
|
||||
const { f_SchemeInfoId, f_Scheme, f_Id } = {}
|
||||
this.wfdesign.custmerformSchemes[f_Id] = { f_Scheme }
|
||||
if (this.node.formCode == f_SchemeInfoId) {
|
||||
this.loadFormScheme(f_Scheme)
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.loadFormScheme(this.wfdesign.custmerformSchemes[val.f_SchemeId].f_Scheme);
|
||||
}
|
||||
this.node.formVerison = val.f_SchemeId
|
||||
},
|
||||
async custmerformVerisonChange(val) {
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
if (this.$validatenull(val)) {
|
||||
this.node.authFields = []
|
||||
return
|
||||
}
|
||||
if (this.$validatenull(this.wfdesign.custmerformSchemes[val.value])) {
|
||||
// const {f_Scheme,f_Id} = (await this.$awaitWraper(apiForm.getHistory(val.value))) || {}
|
||||
const { f_Scheme, f_Id } = {}
|
||||
this.wfdesign.custmerformSchemes[f_Id] = { f_Scheme }
|
||||
if (this.node.formVerison == f_Id) {
|
||||
this.loadFormScheme(f_Scheme)
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.loadFormScheme(this.wfdesign.custmerformSchemes[val.value].f_Scheme);
|
||||
}
|
||||
},
|
||||
loadFormScheme(strScheme) {
|
||||
const scheme = JSON.parse(strScheme)
|
||||
const fields = []
|
||||
const rfields = []
|
||||
scheme.formInfo.tabList.forEach(tab => {
|
||||
tab.components.forEach(component => {
|
||||
if (['guid'].includes(component.type)) {
|
||||
rfields.push({ label: component.label, value: component.prop })
|
||||
}
|
||||
|
||||
if (!['gridtable', 'divider'].includes(component.type) && component.display) {
|
||||
fields.push({
|
||||
prop: component.prop,
|
||||
field: component.field,
|
||||
label: component.label,
|
||||
table: component.table,
|
||||
required: component.required,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
})
|
||||
}
|
||||
else if (['gridtable'].includes(component.type)) {
|
||||
fields.push({
|
||||
prop: `${component.prop}_add`,
|
||||
label: `${component.label || '表格'}-添加按钮`,
|
||||
required: false,
|
||||
isEdit: true,
|
||||
isLook: false,
|
||||
type: 'grid'
|
||||
})
|
||||
fields.push({
|
||||
prop: `${component.prop}_remove`,
|
||||
label: `${component.label || '表格'}-删除按钮`,
|
||||
required: false,
|
||||
isEdit: true,
|
||||
isLook: false,
|
||||
type: 'grid'
|
||||
})
|
||||
|
||||
fields.push({
|
||||
prop: `${component.prop}_required`,
|
||||
label: `${component.label || '表格'}-数据`,
|
||||
required: component.required,
|
||||
isEdit: false,
|
||||
isLook: false,
|
||||
type: 'gridrequired'
|
||||
})
|
||||
fields.push(...component.children.filter(t => t.display).map(t => {
|
||||
return {
|
||||
gridprop: component.prop,
|
||||
prop: t.prop,
|
||||
field: t.field,
|
||||
label: `${component.label || '表格'}-${t.label}`,
|
||||
table: component.table,
|
||||
required: t.required,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
})
|
||||
this.node.formRelations = rfields
|
||||
this.node.authFields = fields
|
||||
|
||||
},
|
||||
handleFormTypeChange() {
|
||||
this.node.formCode = ''
|
||||
this.node.formUrl = ''
|
||||
this.node.formAppUrl = ''
|
||||
this.node.authFields = []
|
||||
this.node.formRelations = []
|
||||
|
||||
this.$set(this.node, 'formRelationId', '')
|
||||
|
||||
},
|
||||
handleAddAuthField() {
|
||||
this.node.authFields.push({
|
||||
field: '',
|
||||
label: '',
|
||||
required: true,
|
||||
isEdit: true,
|
||||
isLook: true
|
||||
})
|
||||
},
|
||||
handleDeleteAuthField(row) {
|
||||
this.node.authFields.splice(row.index, 1);
|
||||
},
|
||||
|
||||
handleTableBtnClick(btn) {
|
||||
this.node.auditUsers.splice(btn.rowIndex, 1);
|
||||
},
|
||||
handleTableBtnClick2(btn) {
|
||||
this.node.lookUsers.splice(btn.rowIndex, 1);
|
||||
},
|
||||
|
||||
typeFormat(type) {
|
||||
switch (type) {
|
||||
case '1':
|
||||
return '岗位'
|
||||
case '2':
|
||||
return '角色'
|
||||
case '3':
|
||||
return '用户'
|
||||
case '4':
|
||||
return '上下级'
|
||||
case '5':
|
||||
return '节点'
|
||||
case '6':
|
||||
return '表字段'
|
||||
}
|
||||
},
|
||||
addTableData(selectData) {
|
||||
if (this.isLooker) {
|
||||
let addData2 = selectData.filter(t => this.node.lookUsers.findIndex(t2 => t2.id == t.id && t2.type == t.type) == -1);
|
||||
this.node.lookUsers = this.node.lookUsers.concat(addData2);
|
||||
}
|
||||
else {
|
||||
let addData = selectData.filter(t => this.node.auditUsers.findIndex(t2 => t2.id == t.id && t2.type == t.type) == -1);
|
||||
this.node.auditUsers = this.node.auditUsers.concat(addData);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
handlePostClick(isLooker) {
|
||||
this.selectPostVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handlePostSelectClosed() {
|
||||
this.$refs.postSelectPanel.resetForm();
|
||||
},
|
||||
handlePostSelectOk() {
|
||||
let selectData = this.$refs.postSelectPanel.getForm().map(t => { return { type: '1', id: t.f_PostId, name: t.name } });
|
||||
this.addTableData(selectData);
|
||||
this.selectPostVisible = false;
|
||||
},
|
||||
|
||||
handleRoleClick(isLooker) {
|
||||
this.selectRoleVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handleRoleSelectClosed() {
|
||||
this.$refs.roleSelectPanel.resetForm();
|
||||
},
|
||||
handleRoleSelectOk() {
|
||||
let selectData = this.$refs.roleSelectPanel.getForm().map(t => { return { type: '2', id: t.f_RoleId, name: t.f_FullName, condition: '' } });
|
||||
this.addTableData(selectData);
|
||||
this.selectRoleVisible = false;
|
||||
},
|
||||
|
||||
handleUserClick(isLooker) {
|
||||
this.selectUserVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handleUserSelectClosed() {
|
||||
this.$refs.userSelectPanel.resetForm();
|
||||
},
|
||||
handleUserSelectOk() {
|
||||
let selectData = this.$refs.userSelectPanel.getForm().map(t => { return { type: '3', id: t.f_UserId, name: t.name } });
|
||||
this.addTableData(selectData);
|
||||
this.selectUserVisible = false;
|
||||
},
|
||||
|
||||
|
||||
handleLevelClick(isLooker) {
|
||||
this.levelVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handleLevelClosed() {
|
||||
this.$refs.auditorLevelForm.resetForm();
|
||||
},
|
||||
handleLevelOk() {
|
||||
this.$refs.auditorLevelForm.validateForm(() => {
|
||||
let data = this.$refs.auditorLevelForm.getForm();
|
||||
this.addTableData([data]);
|
||||
this.levelVisible = false;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
handleNodeAuditorClick(isLooker) {
|
||||
this.nodeAuditorVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handleNodeAuditorOk() {
|
||||
this.$refs.nodeAuditorForm.validateForm(() => {
|
||||
let data = this.$refs.nodeAuditorForm.getForm();
|
||||
this.addTableData([data]);
|
||||
this.nodeAuditorVisible = false;
|
||||
});
|
||||
},
|
||||
handleNodeAuditorClosed() {
|
||||
this.$refs.nodeAuditorForm.resetForm();
|
||||
},
|
||||
handleNodeAuditorOpened() {
|
||||
let wfdata = this.wfdesign.handleGetWFData();
|
||||
this.$refs.nodeAuditorForm.setForm(wfdata.filter(t => t.type = 'userTask' && t.id != this.node.id));
|
||||
},
|
||||
|
||||
|
||||
handleAuditorSqlClick(isLooker) {
|
||||
this.auditorSqlVisible = true;
|
||||
this.isLooker = isLooker;
|
||||
},
|
||||
handleAuditorSqlOk() {
|
||||
this.$refs.auditorSqlForm.validateForm(() => {
|
||||
let data = this.$refs.auditorSqlForm.getForm();
|
||||
data.name = `${data.table}【${data.auditorField}】`
|
||||
this.addTableData([data]);
|
||||
this.auditorSqlVisible = false;
|
||||
});
|
||||
},
|
||||
handleAuditorSqlClosed() {
|
||||
this.$refs.auditorSqlForm.resetForm();
|
||||
},
|
||||
|
||||
hasBtnsDeleteBtn(row) {
|
||||
if (row.isSys) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
handleAddBtns() {
|
||||
this.node.btnlist.push({ code: '', name: '', hidden: false, isNextAuditor: false, isSign: false })
|
||||
},
|
||||
handleDeleteBtns(row) {
|
||||
this.node.btnlist.splice(row.index, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
|
@ -0,0 +1,275 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-05 17:09:44
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 16:14:52
|
||||
* @Description:
|
||||
-->
|
||||
<!-- 开始节点配置 -->
|
||||
<template>
|
||||
<div class="user-task">
|
||||
<a-form ref="formRef" :rules="rules" :model="formState" labelAlign="left" :label-col="labelCol"
|
||||
:wrapper-col="wrapperCol">
|
||||
<a-collapse v-model:activeKey="activeKey" accordion ghost>
|
||||
<a-collapse-panel key="1" header="基础配置">
|
||||
<a-form-item label="节点标识">
|
||||
<a-input v-model:value="node.id" placeholder="请输入" readonly />
|
||||
</a-form-item>
|
||||
<a-form-item label="继承表单">
|
||||
<a-switch v-model:checked="node.isInherit" />
|
||||
</a-form-item>
|
||||
<a-form-item label="允许加签">
|
||||
<a-switch v-model:checked="node.isAddSign" />
|
||||
</a-form-item>
|
||||
<a-form-item label="允许转移">
|
||||
<a-switch v-model:checked="node.isBatchAudit" />
|
||||
</a-form-item>
|
||||
<a-form-item label="允许批量审核">
|
||||
<a-switch v-model:checked="node.isBatchAudit" />
|
||||
</a-form-item>
|
||||
<a-form-item label="自动同意规则">
|
||||
<a-select v-model:value="node.autoAgree" :options="data.atuoAgreeOptions">
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="无对应处理人">
|
||||
<a-select v-model:value="node.rejectType"
|
||||
:options="[{value:'1',label:'驳回节点固定'},{value:'2',label:'能驳回到任何执行过节点'}]">
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="驳回策略">
|
||||
<a-radio-group v-model:value="node.rejectType" name="checkboxgroup"
|
||||
:options="[{value:'1',label:'驳回节点固定'},{value:'2',label:'能驳回到任何执行过节点'}]" />
|
||||
</a-form-item>
|
||||
<a-form-item label="通知策略">
|
||||
<a-checkbox-group v-model:value="node.messageType" name="checkboxgroup"
|
||||
:options="[{value:'1',label:'短信'},{value:'2',label:'邮箱'},{value:'3',label:'微信'},{value:'4',label:'站内消息'}]" />
|
||||
</a-form-item>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel key="2" header="审核人员设置">
|
||||
<a-space>
|
||||
<a-radio-group size="small">
|
||||
<a-radio-button value="1" @click="handlePostClick">岗位</a-radio-button>
|
||||
<a-radio-button value="2" @click="handleRoleClick">角色</a-radio-button>
|
||||
<a-radio-button value="3" @click="handleAccountClick">用户</a-radio-button>
|
||||
<a-radio-button value="3" @click="handleLevelClick">上下级</a-radio-button>
|
||||
<a-radio-button value="3" @click="handleNodeAuditorClick">节点执行人</a-radio-button>
|
||||
<a-radio-button value="3" @click="handleAuditorSqlClick">表字段</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-space>
|
||||
<a-table size="small" :columns="columns" :data-source="dataSource" bordered :pagination="false">
|
||||
<template #bodyCell="{ column, text, record }">
|
||||
<template v-if="['name', 'type'].includes(column.dataIndex)">
|
||||
<div>
|
||||
{{ text }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="column.dataIndex === 'operation'">
|
||||
<a-popconfirm v-if="dataSource.length" title="Sure to delete?"
|
||||
@confirm="onDelete(record.key)">
|
||||
<a>Delete</a>
|
||||
</a-popconfirm>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel key="3" header="This is panel header 3">
|
||||
<p>{{ text }}</p>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel key="4" header="This is panel header 3">
|
||||
<p>{{ text }}</p>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel key="5" header="This is panel header 3">
|
||||
<p>{{ text }}</p>
|
||||
</a-collapse-panel>
|
||||
<a-collapse-panel key="6" header="This is panel header 3">
|
||||
<p>{{ text }}</p>
|
||||
</a-collapse-panel>
|
||||
</a-collapse>
|
||||
|
||||
</a-form>
|
||||
<a-modal width="60%" v-model:open="data.postOpen" title="添加岗位" @ok="postHandleOk">
|
||||
<SelectPos ref="posRef"></SelectPos>
|
||||
</a-modal>
|
||||
<a-modal width="60%" v-model:open="data.roleOpen" title="添加角色" @ok="roleHandleOk">
|
||||
<SelectRole ref="roleRef"></SelectRole>
|
||||
</a-modal>
|
||||
<a-modal width="60%" v-model:open="data.accountOpen" title="添加角色" @ok="accountHandleOk">
|
||||
<SelectAccount ref="accountRef"></SelectAccount>
|
||||
</a-modal>
|
||||
<a-modal width="60%" v-model:open="data.levelOpen" title="添加角色" @ok="accountHandleOk">
|
||||
<AuditorLevel ref="levelRef"></AuditorLevel>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, nextTick, unref } from 'vue';
|
||||
import { BasicTree, TreeItem } from '@/components/Tree';
|
||||
import SelectPos from '@/components/SelectPos/index.vue';
|
||||
import SelectRole from '@/components/SelectRole/index.vue';
|
||||
import SelectAccount from '@/components/SelectAccount/index.vue';
|
||||
import AuditorLevel from './src/auditorLevel.vue'
|
||||
import { getOrgPositonTree, userOrgs } from '@/api/demo/system';
|
||||
const labelCol = { span: 7 };
|
||||
const wrapperCol = { span: 17 };
|
||||
const data = reactive({
|
||||
activeKey: '1',
|
||||
atuoAgreeOptions: [{ value: '1', label: '处理人就是提交人' }, { value: '2', label: '处理人和上一步的处理人相同' }, { value: '3', label: '处理人审批过' }],
|
||||
postOpen: false,
|
||||
roleOpen: false,
|
||||
accountOpen: false,
|
||||
levelOpen:false,
|
||||
|
||||
})
|
||||
const node = reactive({
|
||||
id: "edb713be-7a25-44a2-8048-1f9abc638680",
|
||||
type: "userTask",
|
||||
isAddSign: false,
|
||||
isTransfer: false,
|
||||
isBatchAudit: false,
|
||||
autoAgree: "",
|
||||
noAuditor: "1",
|
||||
rejectType: "1",
|
||||
messageType: "",
|
||||
auditUsers: [],
|
||||
lookUsers: [],
|
||||
formRelations: [],
|
||||
formType: "1",
|
||||
formCode: "",
|
||||
formVerison: "",
|
||||
formRelationId: "",
|
||||
formUrl: "",
|
||||
formAppUrl: "",
|
||||
authFields: [],
|
||||
name: "审核节点",
|
||||
btnlist: [
|
||||
{
|
||||
code: "agree",
|
||||
name: "同意",
|
||||
hidden: false,
|
||||
isNextAuditor: false,
|
||||
isSign: false,
|
||||
isSys: true
|
||||
},
|
||||
{
|
||||
code: "disagree",
|
||||
name: "驳回",
|
||||
hidden: false,
|
||||
isNextAuditor: false,
|
||||
isSign: false,
|
||||
isSys: true
|
||||
}
|
||||
],
|
||||
isCountersign: false,
|
||||
isCountersignAll: false,
|
||||
countersignAgian: "1",
|
||||
countersignType: "1",
|
||||
countersignAllType: 100,
|
||||
isOvertimeMessage: false,
|
||||
overtimeMessageType: "",
|
||||
overtimeMessageStart: 1,
|
||||
overtimeMessageInterval: 1,
|
||||
overtimeGo: 12,
|
||||
isInherit: true,
|
||||
isInit: true
|
||||
})
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
},
|
||||
|
||||
];
|
||||
const dataSource = [
|
||||
{
|
||||
id: 0,
|
||||
name: "王五",
|
||||
type: "管理员",
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "王五",
|
||||
type: "管理员",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
// 岗位
|
||||
const posRef = ref < any > ()
|
||||
|
||||
function handlePostClick() {
|
||||
data.postOpen = true;
|
||||
}
|
||||
function postHandleOk() {
|
||||
console.log(posRef.value.getRow())
|
||||
|
||||
}
|
||||
// 角色
|
||||
const roleRef = ref < any > ()
|
||||
|
||||
function handleRoleClick() {
|
||||
data.roleOpen = true;
|
||||
}
|
||||
function roleHandleOk() {
|
||||
console.log(roleRef.value.getRow())
|
||||
}
|
||||
// 用户
|
||||
const accountRef = ref < any > ()
|
||||
|
||||
function handleAccountClick() {
|
||||
data.accountOpen = true;
|
||||
}
|
||||
function accountHandleOk() {
|
||||
console.log(accountRef.value.getRow())
|
||||
}
|
||||
// 上下级
|
||||
const levelRef = ref < any > ()
|
||||
function handleLevelClick() {
|
||||
data.levelOpen = true;
|
||||
}
|
||||
function levelHandleOk() {
|
||||
console.log(levelRef.value.getRow())
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.site-space-compact-wrapper {
|
||||
width: 100%;
|
||||
|
||||
.ant-select {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ant-tabs {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
::v-deep .ant-space {
|
||||
width: 90%;
|
||||
margin-left: 5%;
|
||||
|
||||
.ant-space-item {
|
||||
width: 100%;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .ant-table-content {
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
<div class="l-from-body">
|
||||
<a-form ref="formRef" :rules="data.rules" :model="data.formData" labelAlign="left" :label-col="labelCol"
|
||||
:wrapper-col="wrapperCol">
|
||||
<a-form-item label="上下级" name="id">
|
||||
<a-select v-model:value="data.formData.id" placeholder="请选择上下级" :options="data.options">
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import {reactive} from 'vue'
|
||||
const data = reactive({
|
||||
formData: {
|
||||
name: '',
|
||||
type: '4',
|
||||
id: '',
|
||||
},
|
||||
rules: {
|
||||
id: [
|
||||
{ required: true, message: '请选择上下级' }
|
||||
]
|
||||
},
|
||||
options: [
|
||||
{ value: '1', label: '上一级' },
|
||||
{ value: '2', label: '上二级' },
|
||||
{ value: '3', label: '上三级' },
|
||||
{ value: '4', label: '上四级' },
|
||||
{ value: '5', label: '上五级' },
|
||||
{ value: '6', label: '下一级' },
|
||||
{ value: '7', label: '下二级' },
|
||||
{ value: '8', label: '下三级' },
|
||||
{ value: '9', label: '下四级' },
|
||||
{ value: '10', label: '下五级' }
|
||||
]
|
||||
})
|
||||
function getRow() {
|
||||
let rows = data.value.formData
|
||||
return rows
|
||||
}
|
||||
defineExpose({
|
||||
getRow
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.l-from-body{
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div class="l-from-body" >
|
||||
<el-form :model="formData" :rules="rules" size="mini" ref="form" label-width="80px" >
|
||||
<el-col :span="24">
|
||||
<el-form-item label="节点" prop="id">
|
||||
<l-select v-model="formData.id" placeholder="请选择节点" valueKey="id" labelKey="name" :options="options" @change="handleChange" ></l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'node-auditor-form',
|
||||
data(){
|
||||
return {
|
||||
formData:{
|
||||
name:'',
|
||||
type:'5',
|
||||
id:'',
|
||||
},
|
||||
rules: {
|
||||
id: [
|
||||
{ required: true, message: '请选择节点' }
|
||||
]
|
||||
},
|
||||
options: []
|
||||
};
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods:{
|
||||
resetForm(){
|
||||
this.$refs.form && this.$refs.form.resetFields();
|
||||
},
|
||||
// 校验表单
|
||||
validateForm(callback){
|
||||
this.$refs.form.validate((valid) => {
|
||||
if(valid){
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
setForm(wfdata){
|
||||
//console.log(wfdata,'节点选择')
|
||||
this.options = wfdata.filter(t=>t.name);
|
||||
},
|
||||
getForm(){
|
||||
return this.$deepClone(this.formData);
|
||||
},
|
||||
handleChange(val){
|
||||
this.formData.name = this.options.find(t=>t.id == val).name;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<template>
|
||||
<div class="l-from-body" >
|
||||
<el-form :model="formData" :rules="rules" size="mini" ref="form" label-width="120px" >
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据库" prop="dbCode">
|
||||
<el-select v-model="formData.dbCode" placeholder="请选择">
|
||||
<el-option-group
|
||||
v-for="group in lr_dblinkTree"
|
||||
:key="group.id"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="item in group.children"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="数据表" prop="table">
|
||||
<l-codetable-select
|
||||
@change="handleTableChange"
|
||||
:dbCode="formData.dbCode"
|
||||
v-model="formData.table"></l-codetable-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="关联流程字段" prop="rfield">
|
||||
<l-select :options="columns" valueKey="name" labelKey="coment" v-model="formData.rfield" >
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="审核人字段" prop="auditorField">
|
||||
<l-select :options="columns" valueKey="name" labelKey="coment" v-model="formData.auditorField" >
|
||||
</l-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'auditor-sql-form',
|
||||
props:{
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
formData:{
|
||||
dbCode:'',
|
||||
table:'',
|
||||
rfield:'',
|
||||
auditorField:'',
|
||||
type:'6'
|
||||
},
|
||||
rules: {
|
||||
dbCode: [
|
||||
{ required: true, message: '请选择数据库' }
|
||||
],
|
||||
table: [
|
||||
{ required: true, message: '请选择数据表' }
|
||||
],
|
||||
rfield: [
|
||||
{ required: true, message: '请选择关联字段' }
|
||||
],
|
||||
auditorField: [
|
||||
{ required: true, message: '请选择审核人字段' }
|
||||
]
|
||||
},
|
||||
columns:[],
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods:{
|
||||
handleTableChange(table){
|
||||
this.columns = table.columns
|
||||
},
|
||||
resetForm(){
|
||||
this.columns = [];
|
||||
this.$refs.form && this.$refs.form.resetFields()
|
||||
},
|
||||
// 校验表单
|
||||
validateForm(callback){
|
||||
this.$refs.form.validate((valid) => {
|
||||
if(valid){
|
||||
callback()
|
||||
}
|
||||
});
|
||||
},
|
||||
setForm(data){
|
||||
this.formData = this.$deepClone(data)
|
||||
},
|
||||
getForm(){
|
||||
let formData = this.$deepClone(this.formData)
|
||||
return formData
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* 改变主题色变量 */
|
||||
// $--color-primary: #1890ff;
|
||||
// $--color-danger: #ff4d4f;
|
||||
|
||||
/* 改变 icon 字体路径变量,必需 */
|
||||
|
||||
.process-drawer .el-drawer__header {
|
||||
padding: 16px 16px 8px 16px;
|
||||
margin: 0;
|
||||
line-height: 24px;
|
||||
font-size: 18px;
|
||||
color: #303133;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
div[class^="el-drawer"]:focus,
|
||||
span:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.process-drawer .el-drawer__body {
|
||||
box-sizing: border-box;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.process-design {
|
||||
.el-table td,
|
||||
.el-table th {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.el-dialog__header {
|
||||
padding: 16px 16px 8px 16px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding: 16px;
|
||||
max-height: 80vh;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.el-dialog__footer {
|
||||
padding: 16px;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
}
|
||||
.el-dialog__close {
|
||||
font-weight: 600;
|
||||
}
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
.el-divider:not(.el-divider--horizontal) {
|
||||
margin: 0 8px ;
|
||||
}
|
||||
.el-divider.el-divider--horizontal {
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
@import "./flow-element-variables.scss";
|
||||
@import "bpmn-js-token-simulation/assets/css/bpmn-js-token-simulation.css";
|
||||
// @import "bpmn-js-token-simulation/assets/css/font-awesome.min.css";
|
||||
// @import "bpmn-js-token-simulation/assets/css/normalize.css";
|
||||
@import "bpmn-js/dist/assets/diagram-js.css";
|
||||
@import "bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
|
||||
@import "bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
|
||||
@import "./process-designer.scss";
|
||||
@import "./process-panel.scss";
|
||||
|
||||
$success-color: #4eb819;
|
||||
$primary-color: #409EFF;
|
||||
$warning-color: #E6A23C;
|
||||
$danger-color: #F56C6C;
|
||||
$cancel-color: #909399;
|
||||
|
||||
.process-viewer {
|
||||
position: relative;
|
||||
border: 1px solid #EFEFEF;
|
||||
background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+') repeat!important;
|
||||
|
||||
.success-arrow {
|
||||
fill: $success-color;
|
||||
stroke: $success-color;
|
||||
}
|
||||
|
||||
.success-conditional {
|
||||
fill: white;
|
||||
stroke: $success-color;
|
||||
}
|
||||
|
||||
.fail-arrow {
|
||||
fill: $warning-color;
|
||||
stroke: $warning-color;
|
||||
}
|
||||
|
||||
.fail-conditional {
|
||||
fill: white;
|
||||
stroke: $warning-color;
|
||||
}
|
||||
|
||||
.success.djs-connection {
|
||||
.djs-visual path {
|
||||
stroke: $success-color!important;
|
||||
marker-end: url(#sequenceflow-end-white-success)!important;
|
||||
}
|
||||
}
|
||||
|
||||
.success.djs-connection.condition-expression {
|
||||
.djs-visual path {
|
||||
marker-start: url(#conditional-flow-marker-white-success)!important;
|
||||
}
|
||||
}
|
||||
|
||||
.success.djs-shape {
|
||||
.djs-visual rect {
|
||||
stroke: $success-color!important;
|
||||
fill: $success-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
|
||||
.djs-visual polygon {
|
||||
stroke: $success-color!important;
|
||||
}
|
||||
|
||||
.djs-visual path:nth-child(2) {
|
||||
stroke: $success-color!important;
|
||||
fill: $success-color!important;
|
||||
}
|
||||
|
||||
.djs-visual circle {
|
||||
stroke: $success-color!important;
|
||||
fill: $success-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
}
|
||||
|
||||
.primary.djs-shape {
|
||||
.djs-visual rect {
|
||||
stroke: $primary-color!important;
|
||||
fill: $primary-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
|
||||
.djs-visual polygon {
|
||||
stroke: $primary-color!important;
|
||||
}
|
||||
|
||||
.djs-visual circle {
|
||||
stroke: $primary-color!important;
|
||||
fill: $primary-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
}
|
||||
|
||||
.warning.djs-connection {
|
||||
.djs-visual path {
|
||||
stroke: $warning-color!important;
|
||||
marker-end: url(#sequenceflow-end-white-fail)!important;
|
||||
}
|
||||
}
|
||||
|
||||
.warning.djs-connection.condition-expression {
|
||||
.djs-visual path {
|
||||
marker-start: url(#conditional-flow-marker-white-fail)!important;
|
||||
}
|
||||
}
|
||||
|
||||
.warning.djs-shape {
|
||||
.djs-visual rect {
|
||||
stroke: $warning-color!important;
|
||||
fill: $warning-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
|
||||
.djs-visual polygon {
|
||||
stroke: $warning-color!important;
|
||||
}
|
||||
|
||||
.djs-visual path:nth-child(2) {
|
||||
stroke: $warning-color!important;
|
||||
fill: $warning-color!important;
|
||||
}
|
||||
|
||||
.djs-visual circle {
|
||||
stroke: $warning-color!important;
|
||||
fill: $warning-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
}
|
||||
|
||||
.danger.djs-shape {
|
||||
.djs-visual rect {
|
||||
stroke: $danger-color!important;
|
||||
fill: $danger-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
|
||||
.djs-visual polygon {
|
||||
stroke: $danger-color!important;
|
||||
}
|
||||
|
||||
.djs-visual circle {
|
||||
stroke: $danger-color!important;
|
||||
fill: $danger-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel.djs-shape {
|
||||
.djs-visual rect {
|
||||
stroke: $cancel-color!important;
|
||||
fill: $cancel-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
|
||||
.djs-visual polygon {
|
||||
stroke: $cancel-color!important;
|
||||
}
|
||||
|
||||
.djs-visual circle {
|
||||
stroke: $cancel-color!important;
|
||||
fill: $cancel-color!important;
|
||||
fill-opacity: 0.15!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.process-viewer .djs-tooltip-container, .process-viewer .djs-overlay-container, .process-viewer .djs-palette {
|
||||
display: none;
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
// 边框被 token-simulation 样式覆盖了
|
||||
.djs-palette {
|
||||
background: var(--palette-background-color);
|
||||
border: solid 1px var(--palette-border-color) !important;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.my-process-designer {
|
||||
padding: 5px 0 10px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 70%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
.my-process-designer__header {
|
||||
width: 100%;
|
||||
min-height: 36px;
|
||||
.el-button {
|
||||
text-align: center;
|
||||
}
|
||||
.el-button-group {
|
||||
margin: 4px;
|
||||
}
|
||||
.el-tooltip__popper {
|
||||
.el-button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
.el-button:hover {
|
||||
background: rgba(64, 158, 255, 0.8);
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
.align {
|
||||
position: relative;
|
||||
i {
|
||||
&:after {
|
||||
content: "|";
|
||||
position: absolute;
|
||||
transform: rotate(90deg) translate(200%, 60%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.align.align-left i {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.align.align-right i {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.align.align-top i {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.align.align-bottom i {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.align.align-center i {
|
||||
transform: rotate(90deg);
|
||||
&:after {
|
||||
transform: rotate(90deg) translate(0, 60%);
|
||||
}
|
||||
}
|
||||
.align.align-middle i {
|
||||
transform: rotate(0deg);
|
||||
&:after {
|
||||
transform: rotate(90deg) translate(0, 60%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.my-process-designer__container {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
.my-process-designer__canvas {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+")
|
||||
repeat !important;
|
||||
div.toggle-mode {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.my-process-designer__property-panel {
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//侧边栏配置
|
||||
.djs-palette.open {
|
||||
.djs-palette-entries {
|
||||
div[class^="bpmn-icon-"]:before,
|
||||
div[class*="bpmn-icon-"]:before {
|
||||
line-height: unset;
|
||||
}
|
||||
div.entry {
|
||||
position: relative;
|
||||
}
|
||||
div.entry:hover {
|
||||
&::after {
|
||||
width: max-content;
|
||||
content: attr(title);
|
||||
vertical-align: text-bottom;
|
||||
position: absolute;
|
||||
right: -10px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
transform: translateX(100%);
|
||||
font-size: 0.5em;
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
background: #fafafa;
|
||||
box-shadow: 0 0 6px #eeeeee;
|
||||
border: 1px solid #cccccc;
|
||||
box-sizing: border-box;
|
||||
padding: 0 16px;
|
||||
border-radius: 4px;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
max-height: calc(80vh - 32px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.hljs {
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.hljs * {
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
.process-design {
|
||||
.process-panel__container {
|
||||
box-sizing: border-box;
|
||||
padding: 0 8px;
|
||||
border-left: 1px solid #eeeeee;
|
||||
box-shadow: 0 0 8px #cccccc;
|
||||
max-height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.panel-tab__title {
|
||||
font-weight: 600;
|
||||
padding: 0 8px;
|
||||
font-size: 1.1em;
|
||||
line-height: 1.2em;
|
||||
i {
|
||||
margin-right: 8px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
.panel-tab__content {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border-top: 1px solid #eeeeee;
|
||||
padding: 8px 16px;
|
||||
.panel-tab__content--title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 8px;
|
||||
span {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-property {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin: 8px 0;
|
||||
.element-property__label {
|
||||
display: block;
|
||||
width: 90px;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
padding-right: 12px;
|
||||
line-height: 32px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.element-property__value {
|
||||
flex: 1;
|
||||
line-height: 32px;
|
||||
}
|
||||
.el-form-item {
|
||||
width: 100%;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
}
|
||||
.list-property {
|
||||
flex-direction: column;
|
||||
.element-listener-item {
|
||||
width: 100%;
|
||||
display: inline-grid;
|
||||
grid-template-columns: 16px auto 32px 32px;
|
||||
grid-column-gap: 8px;
|
||||
}
|
||||
.element-listener-item + .element-listener-item {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
.listener-filed__title {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 0;
|
||||
span {
|
||||
width: 200px;
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
}
|
||||
i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
.element-drawer__button {
|
||||
margin-top: 8px;
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.element-drawer__button > .el-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-collapse-item__content {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.el-input.is-disabled .el-input__inner {
|
||||
color: #999999;
|
||||
}
|
||||
.el-form-item.el-form-item--mini {
|
||||
margin-bottom: 0;
|
||||
& + .el-form-item {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
// 创建监听器实例
|
||||
export function createListenerObject(options, isTask, prefix) {
|
||||
const listenerObj = Object.create(null);
|
||||
listenerObj.event = options.event;
|
||||
// isTask && (listenerObj.id = options.id); // 任务监听器特有的 id 字段
|
||||
switch (options.listenerType) {
|
||||
case "scriptListener":
|
||||
listenerObj.script = createScriptObject(options, prefix);
|
||||
break;
|
||||
case "expressionListener":
|
||||
listenerObj.expression = options.expression;
|
||||
break;
|
||||
case "delegateExpressionListener":
|
||||
listenerObj.delegateExpression = options.delegateExpression;
|
||||
break;
|
||||
default:
|
||||
listenerObj.class = options.class;
|
||||
}
|
||||
// 注入字段
|
||||
if (options.fields) {
|
||||
listenerObj.fields = options.fields.map(field => {
|
||||
return createFieldObject(field, prefix);
|
||||
});
|
||||
}
|
||||
// 任务监听器的 定时器 设置
|
||||
if (isTask && options.event === "timeout" && !!options.eventDefinitionType) {
|
||||
const timeDefinition = window.bpmnInstances.moddle.create("bpmn:FormalExpression", { body: options.eventTimeDefinitions });
|
||||
const TimerEventDefinition = window.bpmnInstances.moddle.create("bpmn:TimerEventDefinition", {
|
||||
id: `TimerEventDefinition_${uuid(8)}`,
|
||||
[`time${options.eventDefinitionType.replace(/^\S/, s => s.toUpperCase())}`]: timeDefinition
|
||||
});
|
||||
listenerObj.eventDefinitions = [TimerEventDefinition];
|
||||
}
|
||||
return window.bpmnInstances.moddle.create(`${prefix}:${isTask ? "TaskListener" : "ExecutionListener"}`, listenerObj);
|
||||
}
|
||||
|
||||
// 创建 监听器的注入字段 实例
|
||||
export function createFieldObject(option, prefix) {
|
||||
const { name, fieldType, string, expression } = option;
|
||||
const fieldConfig = fieldType === "string" ? { name, string } : { name, expression };
|
||||
return window.bpmnInstances.moddle.create(`${prefix}:Field`, fieldConfig);
|
||||
}
|
||||
|
||||
// 创建脚本实例
|
||||
export function createScriptObject(options, prefix) {
|
||||
const { scriptType, scriptFormat, value, resource } = options;
|
||||
const scriptConfig = scriptType === "inlineScript" ? { scriptFormat, value } : { scriptFormat, resource };
|
||||
return window.bpmnInstances.moddle.create(`${prefix}:Script`, scriptConfig);
|
||||
}
|
||||
|
||||
// 更新元素扩展属性
|
||||
export function updateElementExtensions(element, extensionList) {
|
||||
const extensions = window.bpmnInstances.moddle.create("bpmn:ExtensionElements", {
|
||||
values: extensionList
|
||||
});
|
||||
window.bpmnInstances.modeling.updateProperties(element, {
|
||||
extensionElements: extensions
|
||||
});
|
||||
}
|
||||
|
||||
// 创建一个id
|
||||
export function uuid(length = 8, chars) {
|
||||
let result = "";
|
||||
let charsString = chars || "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
for (let i = length; i > 0; --i) {
|
||||
result += charsString[Math.floor(Math.random() * charsString.length)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-07 10:43:34
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 10:49:15
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div class="m-4 mr-0 overflow-hidden bg-white">
|
||||
<BasicTree title="部门列表" toolbar treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData
|
||||
:clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
|
||||
@select="handleSelect" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
import { BasicTree, TreeItem } from '@/components/Tree';
|
||||
import { getDeptList } from '@/api/demo/system';
|
||||
|
||||
defineOptions({ name: 'DeptTree' });
|
||||
|
||||
const emit = defineEmits(['select']);
|
||||
|
||||
const treeData = ref < TreeItem[] > ([]);
|
||||
|
||||
async function fetch() {
|
||||
treeData.value = (await getDeptList()) as unknown as TreeItem[];
|
||||
}
|
||||
|
||||
function handleSelect(keys) {
|
||||
emit('select', keys[0]);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-07 10:43:34
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 10:48:39
|
||||
* @Description:
|
||||
*/
|
||||
import { getAllRoleList, isAccountExist } from '@/api/demo/system';
|
||||
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||
|
||||
/**
|
||||
* transform mock data
|
||||
* {
|
||||
* 0: '华东分部',
|
||||
* '0-0': '华东分部-研发部'
|
||||
* '0-1': '华东分部-市场部',
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'account',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '昵称',
|
||||
dataIndex: 'name',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '所属部门',
|
||||
dataIndex: 'organizations',
|
||||
// customRender: ({ value }) => {
|
||||
// return deptMap[value];
|
||||
// },
|
||||
},
|
||||
];
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'account',
|
||||
label: '用户名',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
{
|
||||
field: 'nickname',
|
||||
label: '昵称',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-07 10:43:34
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 10:56:46
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<!-- <PageWrapper dense contentFullHeight fixedHeight contentClass="flex"> -->
|
||||
<div class="select-account">
|
||||
<DeptTree class="w-1/4 xl:w-1/5" @select="handleSelect" />
|
||||
<BasicTable @register="registerTable" class="w-3/4 xl:w-4/5" :searchInfo="searchInfo"> </BasicTable>
|
||||
</div>
|
||||
<!-- </PageWrapper> -->
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
|
||||
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||
import { getAccountList, deleteAccount } from '@/api/demo/system';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import DeptTree from './DeptTree.vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
|
||||
|
||||
import { columns, searchFormSchema } from './account.data';
|
||||
|
||||
defineOptions({ name: 'AccountManagement' });
|
||||
|
||||
const searchInfo = reactive < Recordable > ({});
|
||||
const [registerTable, { reload, updateTableDataRecord, getSelectRows, clearSelectedRowKeys }] = useTable({
|
||||
title: '账号列表',
|
||||
api: getAccountList,
|
||||
rowKey: 'id',
|
||||
columns,
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
},
|
||||
rowSelection: {//多选框
|
||||
type: 'checkbox',
|
||||
},
|
||||
useSearchForm: true,
|
||||
showTableSetting: false,
|
||||
bordered: true,
|
||||
tableSetting: { fullScreen: true },
|
||||
isCanResizeParent: true,
|
||||
handleSearchInfoFn(info) {
|
||||
console.log('handleSearchInfoFn', info);
|
||||
return info;
|
||||
},
|
||||
});
|
||||
function getRow() {
|
||||
let rows = getSelectRows();
|
||||
return rows
|
||||
}
|
||||
defineExpose({
|
||||
getRow
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.select-account{
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-07 10:00:26
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 15:37:30
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<BasicTree ref="asyncExpandTreeRef" title="部门和职级列表" toolbar treeWrapperClassName="h-[calc(100%-35px)] overflow-auto"
|
||||
loadData :clickRowToExpand="false" :treeData="treeData"
|
||||
:fieldNames="{ key: 'id', title: 'name' ,disabled:'disabled'}" :defaultExpandAll="true" :checkable="true"
|
||||
:checkStrictly="true" @check="handleSelect" />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref, onMounted, nextTick, unref } from 'vue';
|
||||
|
||||
import { BasicTree, TreeItem } from '@/components/Tree';
|
||||
|
||||
import { getOrgPositonTree, userOrgs } from '@/api/demo/system';
|
||||
|
||||
defineOptions({ name: 'RoleManagement' });
|
||||
const treeData = ref < TreeItem[] > ([]);
|
||||
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
|
||||
const posData = ref([])
|
||||
function treeIterator(tree) {
|
||||
tree.forEach((node) => {
|
||||
if (node.key == 0) {
|
||||
node.name = "部门--" + node.name
|
||||
node.disableCheckbox = true
|
||||
} else {
|
||||
node.name = "职级--" + node.name
|
||||
// 需要拼接parentName
|
||||
posData.value.push(node)
|
||||
}
|
||||
node.children && treeIterator(node.children)
|
||||
})
|
||||
}
|
||||
async function fetch() {
|
||||
const data = (await getOrgPositonTree()) as unknown as TreeItem[];
|
||||
treeIterator(data)
|
||||
treeData.value = await data
|
||||
// 展开全部
|
||||
nextTick(() => {
|
||||
unref(asyncExpandTreeRef)?.expandAll(true);
|
||||
});
|
||||
}
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
});
|
||||
let orgList = ref([])
|
||||
let posList = ref([])
|
||||
function handleSelect(checkedKeys, e: { checked: bool, checkedNodes, node, event }) {
|
||||
const list = e.checkedNodes
|
||||
console.log(e.node)
|
||||
console.log(checkedKeys)
|
||||
orgList.value = []
|
||||
posList.value = []
|
||||
list.forEach(element => {
|
||||
if (element.key > 0) {
|
||||
posList.value.push({
|
||||
orgId: Number(element.tag),
|
||||
posId: element.id,
|
||||
})
|
||||
} else {
|
||||
orgList.value.push({
|
||||
orgId: element.id,
|
||||
posId: 0,
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
function getRow() {
|
||||
let rows = getSelectRows();
|
||||
return rows
|
||||
}
|
||||
defineExpose({
|
||||
getRow
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-07 10:00:26
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-07 10:50:39
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<BasicTable @register="registerTable" :searchInfo="searchInfo"> </BasicTable>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, } from 'vue';
|
||||
|
||||
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||
import { getRoleListByPage, deleteRole } from '@/api/demo/system';
|
||||
|
||||
defineOptions({ name: 'RoleManagement' });
|
||||
|
||||
const searchInfo = reactive < Recordable > ({});
|
||||
|
||||
const [registerTable, { reload, getSelectRows, clearSelectedRowKeys }] = useTable({
|
||||
// 表格名称
|
||||
title: '角色列表',
|
||||
// 获取数据的接口
|
||||
api: getRoleListByPage,
|
||||
// 表单列信息 BasicColumn[]
|
||||
columns: [
|
||||
{
|
||||
title: '角色名称',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
width: 180,
|
||||
},
|
||||
],
|
||||
rowKey: 'id',
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: [{
|
||||
field: 'key',
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
}],
|
||||
},
|
||||
// 使用搜索表单
|
||||
useSearchForm: true,
|
||||
// 显示表格设置工具
|
||||
showTableSetting: false,
|
||||
// 是否显示表格边框
|
||||
bordered: true,
|
||||
// 序号列
|
||||
showIndexColumn: false,
|
||||
// 勾选列
|
||||
rowSelection: {//多选框
|
||||
type: 'checkbox',
|
||||
},
|
||||
tableSetting: { fullScreen: true },
|
||||
isCanResizeParent: true,
|
||||
// 搜索
|
||||
handleSearchInfoFn(info) {
|
||||
return info;
|
||||
},
|
||||
});
|
||||
|
||||
function getRow() {
|
||||
let rows = getSelectRows();
|
||||
return rows
|
||||
}
|
||||
defineExpose({
|
||||
getRow
|
||||
})
|
||||
|
||||
</script>
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-19 14:50:22
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\enums\httpEnum.ts
|
||||
* @Description:
|
||||
*/
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -176,5 +176,8 @@
|
|||
"authColumn": "权限列",
|
||||
"resizeParentHeightTable": "继承父元素高度",
|
||||
"vxeTable": "VxeTable"
|
||||
},
|
||||
"workflow":{
|
||||
"scheme_preview":"流程模板设计"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
12
src/main.ts
12
src/main.ts
|
|
@ -2,8 +2,7 @@
|
|||
* @Author: 刘妍
|
||||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-25 13:24:08
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\main.ts
|
||||
* @LastEditTime: 2024-03-06 10:56:44
|
||||
* @Description:
|
||||
*/
|
||||
import 'uno.css';
|
||||
|
|
@ -34,16 +33,25 @@ import App from './App.vue';
|
|||
import "mars3d-cesium/Build/Cesium/Widgets/widgets.css"
|
||||
import "mars3d/dist/mars3d.css"
|
||||
|
||||
|
||||
import MarsUIInstall from "@/mars/components/mars-ui"
|
||||
import "@/mars/components/mars-ui/common"
|
||||
|
||||
|
||||
|
||||
import 'bpmn-js/dist/assets/diagram-js.css';
|
||||
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
|
||||
|
||||
import Antd from "ant-design-vue"
|
||||
|
||||
async function bootstrap() {
|
||||
const app = createApp(App);
|
||||
app.use(Antd)
|
||||
|
||||
// Configure store
|
||||
// 配置 store
|
||||
setupStore(app);
|
||||
|
||||
// Initialize internal system configuration
|
||||
// 初始化内部系统配置
|
||||
initAppConfigStore();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-17 15:24:04
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-18 08:41:32
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\mars\components\mars-work\main-view.vue
|
||||
* @Description:
|
||||
-->
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-17 15:24:04
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-18 08:40:39
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\mars\views\index.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-25 09:30:23
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\router\routes\index.ts
|
||||
* @Description:
|
||||
*/
|
||||
import type { AppRouteRecordRaw, AppRouteModule } from '@/router/types';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,10 @@
|
|||
/*
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-01 14:24:28
|
||||
* @Description:
|
||||
*/
|
||||
import type { AppRouteModule } from '@/router/types';
|
||||
|
||||
import { LAYOUT } from '@/router/constant';
|
||||
|
|
@ -23,6 +30,18 @@ const dashboard: AppRouteModule = {
|
|||
title: t('routes.dashboard.analysis'),
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'scheme_preview/:id',
|
||||
name: 'AccountDetail',
|
||||
meta: {
|
||||
hideMenu: true,
|
||||
title: t('routes.demo.workflow.scheme_preview'),
|
||||
ignoreKeepAlive: true,
|
||||
showMenu: false,
|
||||
currentActiveMenu: '/workflow/scheme',
|
||||
},
|
||||
component: () => import('@/views/demo/workflow/scheme/preview.vue'),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-22 08:55:09
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\utils\http\axios\helper.ts
|
||||
* @Description:
|
||||
*/
|
||||
import { isObject, isString } from '@/utils/is';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-16 13:48:53
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-17 16:53:26
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\views\demo\charts\mars3d\index.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-27 10:58:29
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-27 14:15:31
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\views\demo\system\account\AssignRoleModal.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-29 08:58:01
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-30 08:44:07
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\views\demo\system\account\OrgPositonModal.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="50%" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, unref } from 'vue';
|
||||
import { BasicForm, useForm } from '@/components/Form';
|
||||
import { formSchema } from './menu.data';
|
||||
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
|
||||
|
||||
import { getMenuList, addMenu, editMenu, addButton, editButton } from '@/api/demo/system';
|
||||
|
||||
defineOptions({ name: 'MenuDrawer' });
|
||||
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
|
||||
const isUpdate = ref(true);
|
||||
|
||||
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
|
||||
labelWidth: 100,
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: { lg: 12, md: 24 },
|
||||
});
|
||||
|
||||
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
|
||||
resetFields();
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
|
||||
if (unref(isUpdate)) {
|
||||
setFieldsValue({
|
||||
...data.record,
|
||||
});
|
||||
}
|
||||
const treeData = await getMenuList();
|
||||
updateSchema({
|
||||
field: 'parentId',
|
||||
componentProps: { treeData },
|
||||
});
|
||||
updateSchema({
|
||||
field: 'moduleId',
|
||||
componentProps: { treeData },
|
||||
});
|
||||
});
|
||||
|
||||
const getTitle = computed(() => (!unref(isUpdate) ? '新增菜单' : '编辑菜单'));
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const values = await validate();
|
||||
setDrawerProps({ confirmLoading: true });
|
||||
// TODO custom api
|
||||
console.log(values)
|
||||
if (values.type == '1') {
|
||||
console.log("新增菜单")
|
||||
delete values.type
|
||||
// 新增菜单
|
||||
if (!unref(isUpdate)) {
|
||||
const data = await addMenu(values);
|
||||
} else {
|
||||
const data = await editMenu(values);
|
||||
}
|
||||
closeDrawer();
|
||||
emit('success');
|
||||
} else {
|
||||
console.log("新增按钮")
|
||||
// 新增按钮
|
||||
delete values.type
|
||||
if (!unref(isUpdate)) {
|
||||
const data = await addButton(values);
|
||||
} else {
|
||||
const data = await editButton(values);
|
||||
}
|
||||
closeDrawer();
|
||||
emit('success');
|
||||
}
|
||||
|
||||
} finally {
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<div class="m-4 mr-0 overflow-hidden bg-white">
|
||||
<BasicTree ref="asyncExpandTreeRef" title="菜单列表" toolbar search
|
||||
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
|
||||
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
|
||||
:defaultExpandAll="true" @select="handleSelect" />
|
||||
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
|
||||
确认要删除菜单吗?
|
||||
</BasicModal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, h, nextTick, unref } from 'vue';
|
||||
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
|
||||
import { getMenuList, deleteMenu } from '@/api/demo/system';
|
||||
import { FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||
import { BasicModal, useModal } from '@/components/Modal';
|
||||
import { router } from '@/router';
|
||||
const [register, { closeModal, openModal }] = useModal();
|
||||
defineOptions({ name: 'DeptTree' });
|
||||
|
||||
const emit = defineEmits(['select', 'edit']);
|
||||
|
||||
const treeData = ref < TreeItem[] > ([]);
|
||||
let selectItemId = ref('')
|
||||
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
|
||||
|
||||
async function handleSubmit() {
|
||||
var query = [selectItemId.value]
|
||||
const data = await deleteMenu(query);
|
||||
closeModal();
|
||||
|
||||
}
|
||||
|
||||
async function fetch() {
|
||||
treeData.value = (await getMenuList()) as unknown as TreeItem[];
|
||||
// 展开全部
|
||||
nextTick(() => {
|
||||
unref(asyncExpandTreeRef)?.expandAll(true);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSelect(keys) {
|
||||
emit('select', keys[0]);
|
||||
}
|
||||
const btnList = router.currentRoute.value.meta.elements
|
||||
const actionList: TreeActionItem[] = []
|
||||
btnList.forEach(element => {
|
||||
if (element.domId == 'btnEdit') {
|
||||
actionList.push({
|
||||
render: (node) => {
|
||||
return h(FormOutlined, {
|
||||
class: 'ml-2',
|
||||
onClick: () => {
|
||||
emit('edit', node);
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
} else if (element.domId == 'btnDelete') {
|
||||
actionList.push({
|
||||
render: (node) => {
|
||||
return h(DeleteOutlined, {
|
||||
class: 'ml-2',
|
||||
onClick: () => {
|
||||
selectItemId.value = node.id
|
||||
openModal(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function createIcon({ level }) {
|
||||
if (level === 1) {
|
||||
return 'ion:git-compare-outline';
|
||||
}
|
||||
if (level === 2) {
|
||||
return 'ion:home';
|
||||
}
|
||||
if (level === 3) {
|
||||
return 'ion:airplane';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
});
|
||||
defineExpose({
|
||||
fetch
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<template>
|
||||
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
||||
<MenuTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="editMenu" />
|
||||
<BasicTable class="w-3/4 xl:w-4/5" @register="registerTable" @fetch-success="onFetchSuccess"
|
||||
:searchInfo="searchInfo">
|
||||
<template #toolbar>
|
||||
<!-- <a-button type="primary" @click="handleCreate"> 新增 </a-button> -->
|
||||
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
|
||||
</template>
|
||||
</BasicTable>
|
||||
<MenuDrawer @register="registerDrawer" @success="handleSuccess" />
|
||||
</PageWrapper>
|
||||
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, nextTick, ref } from 'vue';
|
||||
|
||||
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||
import { getMenuList, getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import MenuTree from './MenuTree.vue';
|
||||
|
||||
import { useDrawer } from '@/components/Drawer';
|
||||
import MenuDrawer from './MenuDrawer.vue';
|
||||
|
||||
import { columns, searchFormSchema } from './menu.data';
|
||||
import PermissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createConfirm,createMessage } = useMessage();
|
||||
defineOptions({ name: 'MenuManagement' });
|
||||
const searchInfo = reactive < Recordable > ({});
|
||||
|
||||
const [registerDrawer, { openDrawer }] = useDrawer();
|
||||
const [registerTable, { reload, expandAll, getSelectRows,clearSelectedRowKeys }] = useTable({
|
||||
title: '按钮列表',
|
||||
api: getButtonList,
|
||||
columns,
|
||||
rowKey:'id',
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
isTreeTable: true,
|
||||
striped: false,
|
||||
useSearchForm: true,
|
||||
showTableSetting: true,
|
||||
bordered: true,
|
||||
showIndexColumn: false,
|
||||
rowSelection: {//多选框
|
||||
// type: 'checkbox',
|
||||
type: 'radio',
|
||||
},
|
||||
handleSearchInfoFn(info) {
|
||||
return info;
|
||||
},
|
||||
});
|
||||
const childRef = ref < any > ()
|
||||
function handleCreate() {
|
||||
openDrawer(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
}
|
||||
|
||||
function handleEdit() {
|
||||
let rows = getSelectRows();
|
||||
if(rows.length == 0){
|
||||
return createMessage.warn('请选择一个按钮进行编辑');
|
||||
}
|
||||
const record = rows[0]
|
||||
record.type = '2'
|
||||
openDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
async function editMenu(node: Recordable) {
|
||||
var query = {
|
||||
id: node.id
|
||||
}
|
||||
const record = await getMenuDetail(query);
|
||||
record.type = '1'
|
||||
openDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
function handleSelect(ModuleId = '') {
|
||||
searchInfo.ModuleId = ModuleId;
|
||||
clearSelectedRowKeys()
|
||||
reload();
|
||||
}
|
||||
async function handleDelete(record: Recordable) {
|
||||
let rows = getSelectRows();
|
||||
if(rows.length == 0){
|
||||
return createMessage.warn('请选择一个按钮进行删除');
|
||||
}
|
||||
const query = [rows[0].id]
|
||||
createConfirm({
|
||||
iconType: 'info',
|
||||
title: '删除',
|
||||
content: '确定要删除当前按钮吗',
|
||||
onOk: async () => {
|
||||
const data = await deleteButton(query);
|
||||
reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleSuccess() {
|
||||
childRef.value.fetch();
|
||||
clearSelectedRowKeys()
|
||||
reload();
|
||||
}
|
||||
|
||||
function onFetchSuccess() {
|
||||
// 演示默认展开所有表项
|
||||
nextTick(expandAll);
|
||||
}
|
||||
function onBtnClicked(domId) {
|
||||
console.log(domId)
|
||||
switch (domId) {
|
||||
case 'btnAdd':
|
||||
handleCreate()
|
||||
break;
|
||||
case 'btnEdit':
|
||||
handleEdit()
|
||||
break;
|
||||
case 'btnDelete':
|
||||
handleDelete()
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||
import { h } from 'vue';
|
||||
import { Tag } from 'ant-design-vue';
|
||||
import Icon from '@/components/Icon/Icon.vue';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '按钮名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: 'DOMID',
|
||||
dataIndex: 'domId',
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sort',
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
const isDir = (type: string) => type === '0';
|
||||
const isMenu = (type: string) => type === '1';
|
||||
const isButton = (type: string) => type === '2';
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'key',
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
];
|
||||
|
||||
export const formSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'type',
|
||||
label: '类型',
|
||||
component: 'RadioButtonGroup',
|
||||
defaultValue: '1',
|
||||
componentProps: {
|
||||
options: [
|
||||
// { label: '目录', value: '0' },
|
||||
{ label: '菜单', value: '1' },
|
||||
{ label: '按钮', value: '2' },
|
||||
],
|
||||
},
|
||||
colProps: { lg: 24, md: 24 },
|
||||
},
|
||||
{
|
||||
field: 'id',
|
||||
label: '名称',
|
||||
component: 'Input',
|
||||
ifShow:false
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
label: '名称',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
|
||||
{
|
||||
field: 'parentId',
|
||||
label: '上级',
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
fieldNames: {
|
||||
label: 'name',
|
||||
key: 'id',
|
||||
value: 'id',
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'moduleId',
|
||||
label: '菜单',
|
||||
component: 'TreeSelect',
|
||||
componentProps: {
|
||||
fieldNames: {
|
||||
label: 'name',
|
||||
key: 'id',
|
||||
value: 'id',
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
ifShow: ({ values }) => isButton(values.type),
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'domId',
|
||||
label: 'DMOID',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
ifShow: ({ values }) => isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'sortNo',
|
||||
label: '排序',
|
||||
component: 'InputNumber',
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'sort',
|
||||
label: '排序',
|
||||
component: 'InputNumber',
|
||||
ifShow: ({ values }) => isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'class',
|
||||
helpMessage: ['参考参数值', 'success、warning、error'],
|
||||
label: '样式',
|
||||
component: 'Input',
|
||||
ifShow: ({ values }) => isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'iconName',
|
||||
label: '图标',
|
||||
component: 'IconPicker',
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
|
||||
{
|
||||
field: 'url',
|
||||
label: '路由地址',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
// {
|
||||
// field: 'component',
|
||||
// label: '组件路径',
|
||||
// component: 'Input',
|
||||
// ifShow: ({ values }) => isMenu(values.type),
|
||||
// },
|
||||
{
|
||||
field: 'code',
|
||||
label: '权限标识',
|
||||
component: 'Input',
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
label: '是否系统',
|
||||
component: 'RadioButtonGroup',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '是', value: 0 },
|
||||
{ label: '否', value: 1 },
|
||||
],
|
||||
},
|
||||
ifShow: ({ values }) => !isButton(values.type),
|
||||
},
|
||||
// {
|
||||
// field: 'isExt',
|
||||
// label: '是否外链',
|
||||
// component: 'RadioButtonGroup',
|
||||
// defaultValue: '0',
|
||||
// componentProps: {
|
||||
// options: [
|
||||
// { label: '否', value: '0' },
|
||||
// { label: '是', value: '1' },
|
||||
// ],
|
||||
// },
|
||||
// ifShow: ({ values }) => !isButton(values.type),
|
||||
// },
|
||||
|
||||
// {
|
||||
// field: 'keepalive',
|
||||
// label: '是否缓存',
|
||||
// component: 'RadioButtonGroup',
|
||||
// defaultValue: '0',
|
||||
// componentProps: {
|
||||
// options: [
|
||||
// { label: '否', value: '0' },
|
||||
// { label: '是', value: '1' },
|
||||
// ],
|
||||
// },
|
||||
// ifShow: ({ values }) => isMenu(values.type),
|
||||
// },
|
||||
|
||||
// {
|
||||
// field: 'show',
|
||||
// label: '是否显示',
|
||||
// component: 'RadioButtonGroup',
|
||||
// defaultValue: '0',
|
||||
// componentProps: {
|
||||
// options: [
|
||||
// { label: '是', value: '0' },
|
||||
// { label: '否', value: '1' },
|
||||
// ],
|
||||
// },
|
||||
// ifShow: ({ values }) => !isButton(values.type),
|
||||
// },
|
||||
];
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-02-01 09:07:48
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-02-01 16:55:15
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\views\demo\system\role\AccountModal.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
* @Date: 2024-01-29 08:58:01
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-01-30 13:39:08
|
||||
* @FilePath: \费县天空地大屏正式代码e:\新架构\vue-vben-admin\src\views\demo\system\role\ModulesModal.vue
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-02-26 13:22:28
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-02-26 13:23:09
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
流程发起
|
||||
</template>
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-02-27 09:06:43
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-02-27 10:49:01
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="500px" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicDrawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, unref } from 'vue';
|
||||
import { BasicForm, useForm } from '@/components/Form';
|
||||
import { formSchema } from './scheme.data';
|
||||
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
|
||||
|
||||
import { getMenuList, addMenu, editMenu, addButton, editButton } from '@/api/demo/system';
|
||||
|
||||
defineOptions({ name: 'SchemeDrawer' });
|
||||
|
||||
const emit = defineEmits(['success', 'register']);
|
||||
|
||||
const isUpdate = ref(true);
|
||||
|
||||
const [registerForm, { resetFields, setFieldsValue, updateSchema, validate }] = useForm({
|
||||
labelWidth: 90,
|
||||
baseColProps: { span: 24 },
|
||||
schemas: formSchema,
|
||||
showActionButtonGroup: false,
|
||||
});
|
||||
|
||||
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
|
||||
resetFields();
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
|
||||
if (unref(isUpdate)) {
|
||||
setFieldsValue({
|
||||
...data.record,
|
||||
});
|
||||
}
|
||||
const treeData = await getMenuList();
|
||||
updateSchema({
|
||||
field: 'parentId',
|
||||
componentProps: { treeData },
|
||||
});
|
||||
updateSchema({
|
||||
field: 'moduleId',
|
||||
componentProps: { treeData },
|
||||
});
|
||||
});
|
||||
|
||||
const getTitle = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const values = await validate();
|
||||
setDrawerProps({ confirmLoading: true });
|
||||
// TODO custom api
|
||||
console.log(values)
|
||||
if (values.type == '1') {
|
||||
console.log("新增菜单")
|
||||
delete values.type
|
||||
// 新增菜单
|
||||
if (!unref(isUpdate)) {
|
||||
const data = await addMenu(values);
|
||||
} else {
|
||||
const data = await editMenu(values);
|
||||
}
|
||||
closeDrawer();
|
||||
emit('success');
|
||||
} else {
|
||||
console.log("新增按钮")
|
||||
// 新增按钮
|
||||
delete values.type
|
||||
if (!unref(isUpdate)) {
|
||||
const data = await addButton(values);
|
||||
} else {
|
||||
const data = await editButton(values);
|
||||
}
|
||||
closeDrawer();
|
||||
emit('success');
|
||||
}
|
||||
|
||||
} finally {
|
||||
setDrawerProps({ confirmLoading: false });
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-02-27 09:06:43
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-05 16:00:45
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<div class="m-4 mr-0 overflow-hidden bg-white">
|
||||
<BasicTree ref="asyncExpandTreeRef" title="流程分类" toolbar search
|
||||
treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" loadData :actionList="actionList"
|
||||
:renderIcon="createIcon" :clickRowToExpand="false" :treeData="treeData" :fieldNames="{ key: 'id', title: 'name' }"
|
||||
:defaultExpandAll="true" @select="handleSelect" />
|
||||
<BasicModal @register="register" title="删除" :helpMessage="['提示1', '提示2']" @ok="handleSubmit">
|
||||
确认要删除流程分类吗?
|
||||
</BasicModal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, ref, h, nextTick, unref } from 'vue';
|
||||
import { BasicTree, TreeItem, TreeActionItem } from '@/components/Tree';
|
||||
import { getMenuList, deleteMenu } from '@/api/demo/system';
|
||||
import { PlusOutlined, FormOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||
import { Card, Row, Col, Spin } from 'ant-design-vue';
|
||||
import { BasicModal, useModal } from '@/components/Modal';
|
||||
import { router } from '@/router';
|
||||
const [register, { closeModal, openModal }] = useModal();
|
||||
defineOptions({ name: 'DeptTree' });
|
||||
|
||||
const emit = defineEmits(['select', 'edit']);
|
||||
|
||||
const treeData = ref < TreeItem[] > ([]);
|
||||
let selectItemId = ref('')
|
||||
const asyncExpandTreeRef = ref < Nullable < TreeActionType >> (null);
|
||||
const treeLoading = ref(false);
|
||||
async function handleSubmit() {
|
||||
var query = [selectItemId.value]
|
||||
const data = await deleteMenu(query);
|
||||
closeModal();
|
||||
|
||||
}
|
||||
|
||||
async function fetch() {
|
||||
treeLoading.value = true;
|
||||
treeData.value = (await getMenuList()) as unknown as TreeItem[];
|
||||
// 展开全部
|
||||
nextTick(() => {
|
||||
treeLoading.value = false;
|
||||
unref(asyncExpandTreeRef)?.expandAll(true);
|
||||
});
|
||||
}
|
||||
|
||||
function handleSelect(keys) {
|
||||
emit('select', keys[0]);
|
||||
}
|
||||
const btnList = router.currentRoute.value.meta.elements
|
||||
const actionList: TreeActionItem[] = []
|
||||
btnList.forEach(element => {
|
||||
if(element.domId=='btnAdd'){
|
||||
actionList.push({
|
||||
render: (node) => {
|
||||
return h(PlusOutlined, {
|
||||
class: 'ml-2',
|
||||
onClick: () => {
|
||||
emit('add', node);
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
}else if (element.domId == 'btnEdit') {
|
||||
actionList.push({
|
||||
render: (node) => {
|
||||
return h(FormOutlined, {
|
||||
class: 'ml-2',
|
||||
onClick: () => {
|
||||
emit('edit', node);
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
} else if (element.domId == 'btnDelete') {
|
||||
actionList.push({
|
||||
render: (node) => {
|
||||
return h(DeleteOutlined, {
|
||||
class: 'ml-2',
|
||||
onClick: () => {
|
||||
selectItemId.value = node.id
|
||||
openModal(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
function createIcon({ level }) {
|
||||
if (level === 1) {
|
||||
return 'ion:git-compare-outline';
|
||||
}
|
||||
if (level === 2) {
|
||||
return 'ion:home';
|
||||
}
|
||||
if (level === 3) {
|
||||
return 'ion:airplane';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
onMounted(() => {
|
||||
fetch();
|
||||
});
|
||||
defineExpose({
|
||||
fetch
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
<template>
|
||||
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
|
||||
<SchemeTree ref="childRef" class="w-1/4 xl:w-1/5" @select="handleSelect" @edit="editMenu" @add='handleCreate'/>
|
||||
<BasicTable class="w-3/4 xl:w-4/5" @register="registerTable" @fetch-success="onFetchSuccess"
|
||||
:searchInfo="searchInfo">
|
||||
<template #toolbar>
|
||||
<!-- <a-button type="primary" @click="handleCreate"> 新增 </a-button> -->
|
||||
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'action'">
|
||||
<TableAction
|
||||
:actions="[
|
||||
{
|
||||
icon: 'clarity:info-standard-line',
|
||||
tooltip: '查看历史记录',
|
||||
onClick: handleView.bind(null, record),
|
||||
}
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
</BasicTable>
|
||||
<SchemeDrawer @register="registerDrawer" @success="handleSuccess" />
|
||||
</PageWrapper>
|
||||
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, nextTick, ref } from 'vue';
|
||||
|
||||
import { BasicTable, useTable, TableAction } from '@/components/Table';
|
||||
import { getMenuList, getButtonList, getMenuDetail, deleteButton } from '@/api/demo/system';
|
||||
import { PageWrapper } from '@/components/Page';
|
||||
import SchemeTree from './SchemeTree.vue';
|
||||
|
||||
import { useDrawer } from '@/components/Drawer';
|
||||
import SchemeDrawer from './SchemeDrawer.vue';
|
||||
|
||||
import { columns, searchFormSchema } from './scheme.data';
|
||||
import PermissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
const { createConfirm,createMessage } = useMessage();
|
||||
|
||||
import { useGo } from '@/hooks/web/usePage';
|
||||
const go = useGo();
|
||||
|
||||
defineOptions({ name: 'SchemeManagement' });
|
||||
const searchInfo = reactive < Recordable > ({});
|
||||
|
||||
const [registerDrawer, { openDrawer }] = useDrawer();
|
||||
const [registerTable, { reload, expandAll, getSelectRows,clearSelectedRowKeys }] = useTable({
|
||||
title: '模板列表',
|
||||
api: getButtonList,
|
||||
columns,
|
||||
rowKey:'id',
|
||||
formConfig: {
|
||||
labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
},
|
||||
isTreeTable: true,
|
||||
striped: false,
|
||||
useSearchForm: true,
|
||||
showTableSetting: true,
|
||||
bordered: true,
|
||||
showIndexColumn: false,
|
||||
rowSelection: {//多选框
|
||||
// type: 'checkbox',
|
||||
type: 'radio',
|
||||
},
|
||||
handleSearchInfoFn(info) {
|
||||
return info;
|
||||
},
|
||||
actionColumn: {
|
||||
width: 100,
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
// slots: { customRender: 'action' },
|
||||
},
|
||||
});
|
||||
const childRef = ref < any > ()
|
||||
function handleCreate() {
|
||||
openDrawer(true, {
|
||||
isUpdate: false,
|
||||
});
|
||||
}
|
||||
function handleView(record: Recordable) {
|
||||
go('/dashboard/scheme_preview/' + record.id);
|
||||
}
|
||||
function handleEdit() {
|
||||
let rows = getSelectRows();
|
||||
if(rows.length == 0){
|
||||
return createMessage.warn('请选择一个按钮进行编辑');
|
||||
}
|
||||
const record = rows[0]
|
||||
record.type = '2'
|
||||
openDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
async function editMenu(node: Recordable) {
|
||||
var query = {
|
||||
id: node.id
|
||||
}
|
||||
const record = await getMenuDetail(query);
|
||||
record.type = '1'
|
||||
openDrawer(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
});
|
||||
}
|
||||
function handleSelect(ModuleId = '') {
|
||||
searchInfo.ModuleId = ModuleId;
|
||||
clearSelectedRowKeys()
|
||||
reload();
|
||||
}
|
||||
async function handleDelete(record: Recordable) {
|
||||
let rows = getSelectRows();
|
||||
if(rows.length == 0){
|
||||
return createMessage.warn('请选择一个按钮进行删除');
|
||||
}
|
||||
const query = [rows[0].id]
|
||||
createConfirm({
|
||||
iconType: 'info',
|
||||
title: '删除',
|
||||
content: '确定要删除当前按钮吗',
|
||||
onOk: async () => {
|
||||
const data = await deleteButton(query);
|
||||
reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function handleSuccess() {
|
||||
childRef.value.fetch();
|
||||
clearSelectedRowKeys()
|
||||
reload();
|
||||
}
|
||||
|
||||
function onFetchSuccess() {
|
||||
// 演示默认展开所有表项
|
||||
nextTick(expandAll);
|
||||
}
|
||||
function onBtnClicked(domId) {
|
||||
console.log(domId)
|
||||
switch (domId) {
|
||||
case 'btnAdd':
|
||||
go('/dashboard/scheme_preview/add');
|
||||
break;
|
||||
case 'btnEdit':
|
||||
handleEdit()
|
||||
break;
|
||||
case 'btnDelete':
|
||||
handleDelete()
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-03-01 14:18:39
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-05 10:18:49
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
<!-- <process-viewer :key="`designer-${processView.index}`" :xml="processView.xmlData" :style="{height: '400px'}" /> -->
|
||||
<process-designer :key="designerOpen" style="border:1px solid rgba(0, 0, 0, 0.1);" ref="modelDesigner"
|
||||
v-loading="designerData.loading" :bpmnXml="designerData.bpmnXml" :designerForm="designerData.form"
|
||||
@save="onSaveDesigner" />
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProcessDesigner from '@/components/ProcessDesigner/index.vue';
|
||||
// import ProcessViewer from '@/components/ProcessViewer/index.vue'
|
||||
|
||||
export default {
|
||||
name: "Model",
|
||||
components: {
|
||||
ProcessDesigner,
|
||||
// ProcessViewer,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
designerOpen: false,
|
||||
designerData: {
|
||||
loading: false,
|
||||
bpmnXml: '',
|
||||
modelId: null,
|
||||
form: {
|
||||
processName: null,
|
||||
processKey: null
|
||||
}
|
||||
},
|
||||
designerModelId: null,
|
||||
processView: {
|
||||
title: '',
|
||||
open: false,
|
||||
index: undefined,
|
||||
xmlData: "",
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
/** 查看流程图 */
|
||||
handleProcessView(row) {
|
||||
let modelId = row.modelId;
|
||||
this.processView.title = "流程图";
|
||||
this.processView.index = modelId;
|
||||
// 发送请求,获取xml
|
||||
getBpmnXml(modelId).then(response => {
|
||||
this.processView.xmlData = response.data;
|
||||
})
|
||||
this.processView.open = true;
|
||||
},
|
||||
/** 设计按钮操作 */
|
||||
handleDesigner(row) {
|
||||
this.designerData.bpmnXml = '';
|
||||
this.designerData.title = "流程设计 - " + row.modelName;
|
||||
// this.designerData.modelId = row.modelId;
|
||||
// this.designerData.form = {
|
||||
// processName: row.modelName,
|
||||
// processKey: row.modelKey
|
||||
// }
|
||||
// if (row.modelId) {
|
||||
// this.designerData.loading = true;
|
||||
// getBpmnXml(row.modelId).then(response => {
|
||||
// this.designerData.bpmnXml = response.data || '';
|
||||
// this.designerData.loading = false;
|
||||
// this.designerOpen = true;
|
||||
// })
|
||||
// }
|
||||
},
|
||||
onSaveDesigner(bpmnXml) {
|
||||
console.log(bpmnXml)
|
||||
// this.bpmnXml = bpmnXml;
|
||||
// let dataBody = {
|
||||
// modelId: this.designerData.modelId,
|
||||
// bpmnXml: this.bpmnXml
|
||||
// }
|
||||
// this.$confirm("是否将此模型保存为新版本?", "提示", {
|
||||
// distinguishCancelAndClose: true,
|
||||
// confirmButtonText: '是',
|
||||
// cancelButtonText: '否'
|
||||
// }).then(() => {
|
||||
// this.confirmSave(dataBody, true)
|
||||
// }).catch(action => {
|
||||
// if (action === 'cancel') {
|
||||
// this.confirmSave(dataBody, false)
|
||||
// }
|
||||
// })
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import { BasicColumn, FormSchema } from '@/components/Table';
|
||||
import { h } from 'vue';
|
||||
import { Tag } from 'ant-design-vue';
|
||||
import Icon from '@/components/Icon/Icon.vue';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '编号',
|
||||
dataIndex: 'domId',
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
dataIndex: 'name',
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sort',
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
const isDir = (type: string) => type === '0';
|
||||
const isMenu = (type: string) => type === '1';
|
||||
const isButton = (type: string) => type === '2';
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'key',
|
||||
label: '关键字',
|
||||
component: 'Input',
|
||||
colProps: { span: 8 },
|
||||
},
|
||||
];
|
||||
|
||||
export const formSchema: FormSchema[] = [
|
||||
{
|
||||
field: 'id',
|
||||
label: '名称',
|
||||
component: 'Input',
|
||||
ifShow:false
|
||||
},
|
||||
{
|
||||
field: 'name',
|
||||
label: '名称',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'value',
|
||||
label: '值',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'sortNo',
|
||||
label: '排序',
|
||||
component: 'InputNumber',
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
label: '是否有效',
|
||||
component: 'RadioButtonGroup',
|
||||
defaultValue: 1,
|
||||
componentProps: {
|
||||
options: [
|
||||
{ label: '是', value: 0 },
|
||||
{ label: '否', value: 1 },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'remark',
|
||||
label: '备注',
|
||||
component: 'InputTextArea',
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<!--
|
||||
* @Author: 刘妍
|
||||
* @Date: 2024-02-26 13:22:28
|
||||
* @LastEditors: Do not edit
|
||||
* @LastEditTime: 2024-03-05 15:59:12
|
||||
* @Description:
|
||||
-->
|
||||
<template>
|
||||
流程任务
|
||||
</template>
|
||||
|
|
@ -2,7 +2,11 @@
|
|||
* @Author: 刘妍
|
||||
* @Date: 2024-01-13 13:04:15
|
||||
* @LastEditors: Do not edit
|
||||
<<<<<<< HEAD
|
||||
* @LastEditTime: 2024-03-08 09:17:00
|
||||
=======
|
||||
* @LastEditTime: 2024-03-05 15:57:29
|
||||
>>>>>>> ly
|
||||
* @Description:
|
||||
*/
|
||||
import { defineApplicationConfig } from '@vben/vite-config';
|
||||
|
|
|
|||
Loading…
Reference in New Issue