init
This commit is contained in:
138
src/flow/designer/components/flow-area-view.vue
Normal file
138
src/flow/designer/components/flow-area-view.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<template>
|
||||
<div id="jfDragWrapPaper">
|
||||
<div
|
||||
id="jfWrapPaper"
|
||||
class="jf-wrap-paper"
|
||||
>
|
||||
<div id="jsonflowMainPaper"></div>
|
||||
</div>
|
||||
<div id="minimapPaperView" class="jsonflow-navigator"></div>
|
||||
<div class="container-scale">
|
||||
<el-button icon="ZoomIn" circle size="small" type="default" @click="methods.enlargePaper"></el-button>
|
||||
<span>{{ data.container.scaleShow }}% </span>
|
||||
<el-button icon="ZoomOut" circle size="small" type="default" @click="methods.narrowPaper"></el-button>
|
||||
</div>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.nodeContMenuData"
|
||||
>
|
||||
</vue-context-menu>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.linkContMenuData"
|
||||
>
|
||||
</vue-context-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowAreaView">
|
||||
import {flowConfig} from "../config/flow-config";
|
||||
import {utils} from "../utils/common";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {hideVueContextmenuName} from "/@/flow/utils";
|
||||
|
||||
// 引入组件
|
||||
const VueContextMenu = defineAsyncComponent(() => import('../../components/contextmenu/index.vue'));
|
||||
const {t} = useI18n();
|
||||
const $emit = defineEmits(["initJsonFlowView"]);
|
||||
const props = defineProps({
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: {},
|
||||
}
|
||||
});
|
||||
const data = reactive({
|
||||
container: {
|
||||
scaleShow: utils.mul(flowConfig.defaultStyle.containerScale.init, 100)
|
||||
},
|
||||
linkContMenuData: deepClone(flowConfig.contextMenu.linkView),
|
||||
nodeContMenuData: deepClone(flowConfig.contextMenu.nodeView)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
// 画布放大
|
||||
enlargePaper() {
|
||||
data.container.scaleShow = window._jfOperate.zoomOut();
|
||||
},
|
||||
// 画布缩小
|
||||
narrowPaper() {
|
||||
let zoomIn = window._jfOperate.zoomIn();
|
||||
data.container.scaleShow = parseInt(zoomIn)
|
||||
},
|
||||
// 节点click事件
|
||||
showNodeClickMenu(currSelect, e) {
|
||||
// TODO 业务侧替换其他内容
|
||||
methods.showNodeContMenu(currSelect, e)
|
||||
},
|
||||
// 节点hover事件
|
||||
showNodeContMenu(currSelect, e) {
|
||||
if (validateNull(currSelect)) {
|
||||
currSelect = props.currSelect
|
||||
}
|
||||
if (Object.keys(currSelect).length === 0) return
|
||||
// 计算节点信息
|
||||
methods.updateNodeContMenuData(currSelect)
|
||||
let event = window.event || e;
|
||||
event.preventDefault();
|
||||
hideVueContextmenuName()
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.nodeContMenuData.axis = {x, y};
|
||||
},
|
||||
updateNodeContMenuData(currSelect) {
|
||||
let nodeNameBtnName = flowConfig.contextMenu.nodeView.menulists[0].btnName;
|
||||
let text;
|
||||
if (!currSelect.attributes.attrs.label) text = currSelect.attrs.label.text
|
||||
else text = currSelect.attributes.attrs.label.text
|
||||
data.nodeContMenuData.menulists[0].btnName = nodeNameBtnName + text
|
||||
data.nodeContMenuData.menulists[1].btnName = currSelect.attributes.startTime
|
||||
data.nodeContMenuData.menulists[2].btnName = currSelect.attributes.userRoleName
|
||||
data.nodeContMenuData.menulists[3].btnName = currSelect.attributes.userName
|
||||
data.nodeContMenuData.menulists[4].btnName = currSelect.attributes.remark
|
||||
},
|
||||
// 连接click事件
|
||||
showLinkClickMenu(currSelect, e) {
|
||||
// TODO 业务侧替换其他内容
|
||||
methods.showLinkContMenu(currSelect, e)
|
||||
},
|
||||
// 连接线hover事件
|
||||
showLinkContMenu(currSelect, e) {
|
||||
if (validateNull(currSelect)) {
|
||||
currSelect = props.currSelect
|
||||
}
|
||||
if (Object.keys(currSelect).length === 0) return
|
||||
// 计算连线条件
|
||||
let varKeyVal = currSelect.attributes.attrs.cdata.attrs.varKeyVal;
|
||||
hideVueContextmenuName()
|
||||
if (!varKeyVal) return
|
||||
let btnName = flowConfig.contextMenu.linkView.menulists[0].btnName;
|
||||
data.linkContMenuData.menulists[0].btnName = btnName + varKeyVal
|
||||
|
||||
let event = window.event || e;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.linkContMenuData.axis = {x, y};
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
$emit("initJsonFlowView");
|
||||
})
|
||||
});
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
showNodeContMenu: methods.showNodeContMenu,
|
||||
showNodeClickMenu: methods.showNodeClickMenu,
|
||||
showLinkContMenu: methods.showLinkContMenu,
|
||||
showLinkClickMenu: methods.showLinkClickMenu,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/style/flow-area.scss";
|
||||
@import "../assets/style/flow-paper.css";
|
||||
</style>
|
||||
384
src/flow/designer/components/flow-area.vue
Normal file
384
src/flow/designer/components/flow-area.vue
Normal file
@@ -0,0 +1,384 @@
|
||||
<template>
|
||||
<div id="jfDragWrapPaper">
|
||||
<div id="jfWrapPaper"
|
||||
class="jf-wrap-paper"
|
||||
>
|
||||
<div id="jsonflowMainPaper" @dragover="methods.allowDrop" @drop="methods.drop"></div>
|
||||
<div class="horizontal-line-x"></div>
|
||||
<div class="vertical-line-y"></div>
|
||||
</div>
|
||||
<div id="minimapPaperView" class="jsonflow-navigator"></div>
|
||||
<div class="container-scale">
|
||||
<el-button icon="ZoomIn" circle size="small" type="default"
|
||||
@click="methods.enlargePaper"></el-button>
|
||||
<span>{{ data.container.scaleShow }}% </span>
|
||||
<el-button icon="ZoomOut" circle size="small" type="default"
|
||||
@click="methods.narrowPaper"></el-button>
|
||||
</div>
|
||||
<!-- 选择连接的节点 -->
|
||||
<el-dialog
|
||||
v-model="data.showSetConnectNode" v-if="data.showSetConnectNode"
|
||||
top="20px"
|
||||
width="50%"
|
||||
title="请选择连接到的节点"
|
||||
append-to-body>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="170px">
|
||||
<el-form-item label="连接到的节点">
|
||||
<el-select class="input-attr" placeholder="请选择连接到的节点" style="width: 80%!important;"
|
||||
@change="methods.doConnectNode"
|
||||
v-model="data.toFlowNodeId"
|
||||
filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.flowNodeIds"
|
||||
:key="item.id"
|
||||
:label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>从当前节点连接到目标节点</template>
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 选择连线的起始节点 -->
|
||||
<el-dialog
|
||||
v-model="data.showLinkFlowNodeIds" v-if="data.showLinkFlowNodeIds"
|
||||
top="20px"
|
||||
width="50%"
|
||||
:title="'请选择连接到的' + (data.modifyPointType === '0' ? '起点' : '终点')"
|
||||
append-to-body>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="170px">
|
||||
<el-form-item label="起始节点(可修改)" v-if="data.modifyPointType ==='0'">
|
||||
<el-select class="input-attr" style="width: 80%!important;"
|
||||
v-model="data.fromFlowNodeId"
|
||||
@change="methods.changeLinkFlowNodeIds('0')"
|
||||
filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.fromFlowNodeIds"
|
||||
:key="item.id"
|
||||
:label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标节点(可修改)" v-if="data.modifyPointType ==='1'">
|
||||
<el-select class="input-attr" style="width: 80%!important;"
|
||||
v-model="data.toFlowNodeId"
|
||||
@change="methods.changeLinkFlowNodeIds('1')"
|
||||
filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.toFlowNodeIds"
|
||||
:key="item.id"
|
||||
:label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.paperContMenuData"
|
||||
@flowInfo="methods.flowInfo"
|
||||
@paste="methods.paste"
|
||||
>
|
||||
</vue-context-menu>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.nodeContMenuData"
|
||||
@setNodeAttr="methods.setNodeAttr('0')"
|
||||
@copyNode="methods.copyNode"
|
||||
@deleteNode="methods.deleteNode"
|
||||
@setConnectNode="methods.setConnectNode"
|
||||
>
|
||||
</vue-context-menu>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.nodeConnectMenuData"
|
||||
@setSerialNode="methods.setSerialNode"
|
||||
@setSerialGate="methods.setSerialGate"
|
||||
@setParallelNode="methods.setParallelNode"
|
||||
@setParallelGate="methods.setParallelGate"
|
||||
@setConnectNode="methods.setConnectNode"
|
||||
>
|
||||
</vue-context-menu>
|
||||
<vue-context-menu
|
||||
:contextMenuData="data.linkContMenuData"
|
||||
@deleteLink="methods.deleteLink"
|
||||
@setLinkAttr="methods.setNodeAttr('1')"
|
||||
@modifySourceNode="methods.handleLinkFlowNodeIds('0')"
|
||||
@modifyTargetNode="methods.handleLinkFlowNodeIds('1')"
|
||||
>
|
||||
</vue-context-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowArea">
|
||||
import {flowConfig} from "../config/flow-config";
|
||||
import {utils} from "../utils/common";
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage, useMessageBox} from "/@/hooks/message";
|
||||
import {notifyLeft} from "/@/flow";
|
||||
import {CommonNodeType, HighNodeType} from "../config/type";
|
||||
import {hideVueContextmenuName} from "/@/flow/utils";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {changeLinkFlowNodeIds, handleLinkFlowNodeIds, validateNodeType} from "./index";
|
||||
|
||||
// 引入组件
|
||||
const VueContextMenu = defineAsyncComponent(() => import('../../components/contextmenu/index.vue'));
|
||||
|
||||
const {t} = useI18n();
|
||||
const {proxy} = getCurrentInstance();
|
||||
const $message = useMessage();
|
||||
const $emit = defineEmits(["removeEleTools", "showAttrConfig", "initJsonFlow"]);
|
||||
const props = defineProps({
|
||||
dragInfo: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: {},
|
||||
}
|
||||
});
|
||||
const data = reactive({
|
||||
container: {
|
||||
scaleShow: utils.mul(flowConfig.defaultStyle.containerScale.init, 100)
|
||||
},
|
||||
paperContMenuData: flowConfig.contextMenu.container,
|
||||
nodeContMenuData: flowConfig.contextMenu.node,
|
||||
nodeConnectMenuData: flowConfig.contextMenu.nodeConnect,
|
||||
linkContMenuData: flowConfig.contextMenu.link,
|
||||
clipboard: {},
|
||||
showSetConnectNode: false,
|
||||
showLinkFlowNodeIds: false,
|
||||
toFlowNodeId: null,
|
||||
flowNodeIds: [],
|
||||
modifyPointType: null,
|
||||
fromFlowNodeId: null,
|
||||
fromFlowNodeIds: [],
|
||||
toFlowNodeIds: []
|
||||
})
|
||||
const methods = {
|
||||
allowDrop(e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
drop(e) {
|
||||
// 增加节点
|
||||
window._jfOperate.dropNewNode(e, props.dragInfo, true);
|
||||
},
|
||||
// 画布放大
|
||||
enlargePaper() {
|
||||
data.container.scaleShow = window._jfOperate.zoomOut();
|
||||
},
|
||||
// 画布缩小
|
||||
narrowPaper() {
|
||||
let zoomIn = window._jfOperate.zoomIn();
|
||||
data.container.scaleShow = parseInt(zoomIn)
|
||||
},
|
||||
// 画布右健
|
||||
showPaperContMenu(e) {
|
||||
let event = window.event || e;
|
||||
|
||||
event.preventDefault();
|
||||
hideVueContextmenuName()
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.paperContMenuData.axis = {x, y};
|
||||
},
|
||||
// 流程图信息
|
||||
flowInfo() {
|
||||
$message.info(
|
||||
"当前流程图中有 " +
|
||||
window._jfGraph.getElements().length +
|
||||
" 个节点,有 " +
|
||||
window._jfGraph.getLinks().length +
|
||||
" 条连线。"
|
||||
);
|
||||
},
|
||||
handleFlowNodeIds() {
|
||||
data.flowNodeIds = []
|
||||
let models = window._jfGraph.getElements();
|
||||
if (validateNull(models)) return
|
||||
models.forEach(each => {
|
||||
if (!validateNodeType(each)) return
|
||||
if (props.currSelect.id !== each.id) {
|
||||
let id = each.id
|
||||
let nodeName = each.attributes.attrs.label.text + "(ID:" + id + ")"
|
||||
data.flowNodeIds.push({id, nodeName})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 粘贴
|
||||
paste() {
|
||||
let e = window.event;
|
||||
let b = Object.keys(data.clipboard).length === 0;
|
||||
if (b) {
|
||||
$message.info("请将鼠标放节点上, 右键菜单复制节点");
|
||||
hideVueContextmenuName()
|
||||
return
|
||||
}
|
||||
let newNode = data.clipboard.clone()
|
||||
window._jfOperate.pasteNode(newNode, e);
|
||||
data.clipboard = {}
|
||||
hideVueContextmenuName()
|
||||
},
|
||||
// 节点右键
|
||||
showNodeContMenu(e) {
|
||||
let event = window.event || e;
|
||||
|
||||
event.preventDefault();
|
||||
hideVueContextmenuName()
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.nodeContMenuData.axis = {x, y};
|
||||
},
|
||||
// 复制节点
|
||||
copyNode() {
|
||||
data.clipboard = {};
|
||||
if (methods.validateCurrSelect("0")) {
|
||||
return
|
||||
}
|
||||
data.clipboard = props.currSelect;
|
||||
hideVueContextmenuName()
|
||||
},
|
||||
// 删除节点
|
||||
deleteNode() {
|
||||
if (methods.validateCurrSelect("0")) {
|
||||
return
|
||||
}
|
||||
props.currSelect.remove()
|
||||
$emit("removeEleTools");
|
||||
},
|
||||
setNodeAttr(type) {
|
||||
if (methods.validateCurrSelect(type)) {
|
||||
return
|
||||
}
|
||||
$emit("showAttrConfig", true);
|
||||
},
|
||||
// 连接线右键
|
||||
showLinkContMenu(e) {
|
||||
let event = window.event || e;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
hideVueContextmenuName()
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.linkContMenuData.axis = {x, y};
|
||||
},
|
||||
// 删除线
|
||||
deleteLink() {
|
||||
if (methods.validateCurrSelect("1")) {
|
||||
return
|
||||
}
|
||||
props.currSelect.remove()
|
||||
$emit("removeEleTools");
|
||||
},
|
||||
validateCurrSelect(type) {
|
||||
let b = Object.keys(props.currSelect).length === 0;
|
||||
if (b !== true) return false
|
||||
if (type === '0') {
|
||||
notifyLeft('请先选择节点', 'warning')
|
||||
} else {
|
||||
notifyLeft('请先移动到连线上方', 'warning')
|
||||
}
|
||||
return true
|
||||
},
|
||||
// 节点连接右键
|
||||
showNodeConnectMenu(params, e) {
|
||||
let event = window.event || e;
|
||||
|
||||
hideVueContextmenuName()
|
||||
let x = event.clientX;
|
||||
let y = event.clientY;
|
||||
data.nodeConnectMenuData.axis = {x, y};
|
||||
data.nodeConnectMenuData.params = params;
|
||||
},
|
||||
setSerialNode() {
|
||||
methods.connectAction({belongTo: "commonNodes", type: CommonNodeType.SERIAL})
|
||||
},
|
||||
setParallelNode() {
|
||||
methods.connectAction({belongTo: "commonNodes", type: CommonNodeType.PARALLEL})
|
||||
},
|
||||
setSerialGate() {
|
||||
methods.connectAction({belongTo: "highNodes", type: CommonNodeType.SERIAL})
|
||||
},
|
||||
setParallelGate() {
|
||||
methods.connectAction({belongTo: "highNodes", type: CommonNodeType.PARALLEL})
|
||||
},
|
||||
setConnectNode() {
|
||||
if (methods.hideValidateCurrSelect("0")) {
|
||||
return
|
||||
}
|
||||
methods.handleFlowNodeIds()
|
||||
data.toFlowNodeId = null
|
||||
data.showSetConnectNode = true
|
||||
},
|
||||
doConnectNode(val) {
|
||||
if (methods.hideValidateCurrSelect("0")) {
|
||||
return
|
||||
}
|
||||
let simpleMode = window._flowConfig.globalConfig.isSimpleMode;
|
||||
if (simpleMode !== '1') {
|
||||
data.nodeConnectMenuData.params = {view: {model: props.currSelect}}
|
||||
}
|
||||
useMessageBox()
|
||||
.confirm('是否确认连接到当前选中的节点?')
|
||||
.then(() => {
|
||||
let params = data.nodeConnectMenuData.params;
|
||||
params.toFlowNodeId = val
|
||||
window._jfOperate.doConnectNode(params)
|
||||
data.showSetConnectNode = false
|
||||
if (simpleMode !== '1') {
|
||||
notifyLeft('专业模式不会自动调整连线轨迹,有必要时请手动调整', 'warning', 3000)
|
||||
}
|
||||
})
|
||||
},
|
||||
connectAction(dragInfo) {
|
||||
if (methods.hideValidateCurrSelect("0")) {
|
||||
return
|
||||
}
|
||||
let params = data.nodeConnectMenuData.params;
|
||||
window._jfOperate.connectAction(params, dragInfo)
|
||||
},
|
||||
hideValidateCurrSelect(type) {
|
||||
hideVueContextmenuName()
|
||||
return methods.validateCurrSelect(type);
|
||||
},
|
||||
changeLinkFlowNodeIds(type) {
|
||||
if (methods.hideValidateCurrSelect("1")) {
|
||||
return
|
||||
}
|
||||
changeLinkFlowNodeIds(data, props)
|
||||
data.showLinkFlowNodeIds = false
|
||||
},
|
||||
handleLinkFlowNodeIds(type) {
|
||||
if (methods.hideValidateCurrSelect("1")) {
|
||||
return
|
||||
}
|
||||
data.modifyPointType = type
|
||||
handleLinkFlowNodeIds(data, props)
|
||||
data.showLinkFlowNodeIds = true
|
||||
},
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
$emit("initJsonFlow");
|
||||
})
|
||||
});
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
showPaperContMenu: methods.showPaperContMenu,
|
||||
showNodeContMenu: methods.showNodeContMenu,
|
||||
showNodeConnectMenu: methods.showNodeConnectMenu,
|
||||
showLinkContMenu: methods.showLinkContMenu,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/style/flow-area.scss";
|
||||
@import "../assets/style/flow-paper.css";
|
||||
</style>
|
||||
1303
src/flow/designer/components/flow-attr.vue
Normal file
1303
src/flow/designer/components/flow-attr.vue
Normal file
File diff suppressed because it is too large
Load Diff
411
src/flow/designer/components/flow-clazz.vue
Normal file
411
src/flow/designer/components/flow-clazz.vue
Normal file
@@ -0,0 +1,411 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="160px">
|
||||
|
||||
<el-form-item label="监听类">
|
||||
<el-input class="input-attr" :placeholder="props.clazzPlaceholder" v-model="data.clazz.clazz" clearable></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="data.clazz.httpUrl"
|
||||
@blur="methods.handleHttpUrlBlur" clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="data.clazz.httpMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip content="点击可设置Http请求的参数信息" placement="bottom">
|
||||
<el-button type="primary" size="small" round style="margin-left: 10px"
|
||||
@click="methods.openHttpUrlParams(true)">
|
||||
参数
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="触发时机">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.clazz.methods" multiple
|
||||
clearable placeholder="多个方法名称, 英文逗号分隔, 顺序从左到右">
|
||||
<el-option
|
||||
v-for="(item, index) in props.addType === '0' && props.currSelect.attributes.attrs.cdata.attrs.isAutoAudit === '1' ?
|
||||
props.flowMethods.slice(3) : props.flowMethods"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider v-if="!data.moreInter">
|
||||
<el-button type="primary" link @click="methods.showMoreSetting()"
|
||||
style="margin-left: 10px; font-size: 14px">
|
||||
{{ data.moreInter ? '隐藏更多' : '更多配置' }}
|
||||
</el-button>
|
||||
</el-divider>
|
||||
|
||||
<template v-if="data.moreInter">
|
||||
<div style="margin: 10px 13px">
|
||||
<span style="color: red;font-size: 14px">注: 监听事件允许设置生效条件,用于控制在某种条件下才会执行</span>
|
||||
</div>
|
||||
<el-form-item label="条件模式">
|
||||
<el-radio-group style="width: 313px" @change="methods.handleClazzValType" :disabled="data.existData"
|
||||
v-model="data.clazz.valType">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.VAL_TYPE.slice(2, 5)" :key="index" :label="item.value" style="width: 75px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>若无法切换模式,请先清空监听事件列表</template>
|
||||
<el-icon><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="data.tableFieldData" v-if="data.clazz.valType === '0'"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="data.clazz.varKeyVal" @change="methods.handleVarKeyVal"
|
||||
clearable
|
||||
filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="data.clazz.operator"
|
||||
clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.varValOperator"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="data.clazz.varVal" clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-form-item label="SpEL表达式" v-if="data.clazz.valType === '1'">
|
||||
<el-input class="input-attr" v-model="data.clazz.varKeyVal" clearable @blur="methods.handleClazzVarKeyVal"/>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ PROP_CONST.TEXT_DESC.condSpELExplain }}</template>
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="函数表达式" v-if="data.clazz.valType === '2'">
|
||||
<el-input class="input-attr" v-model="data.clazz.varKeyVal" placeholder="请输入函数表达式" clearable @blur="methods.handleClazzVarKeyVal"/>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ PROP_CONST.TEXT_DESC.condMethodExplain1 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain2 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain3 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain4 }}
|
||||
</template>
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="监听备注">
|
||||
<el-input class="input-attr" type="textarea" v-model="data.clazz.remark"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="监听排序">
|
||||
<el-input-number class="input-attr" v-model="data.clazz.sort" :min="1"></el-input-number>
|
||||
</el-form-item>
|
||||
|
||||
</template>
|
||||
|
||||
<el-button type="primary" round style="margin-left: 185px; margin-top: 30px; margin-bottom: 30px; width: 200px" @click="methods.addFlowNodeClazz(props.addType)">
|
||||
{{ data.clazz.isSelectedRow ? '修改完成': '添加事件' }}
|
||||
</el-button>
|
||||
<el-divider>已添加监听事件列表(点击行可再次修改)</el-divider>
|
||||
<el-empty description="监听事件列表为空" style="margin: 10px 230px" v-if="!data.existData">
|
||||
</el-empty>
|
||||
<el-table :data="data.tableData" border style="width: 100%" max-height="500" v-else
|
||||
highlight-current-row @current-change="methods.handleCurrentChange" ref="tableDataRef">
|
||||
<el-table-column type="index" label="操作" width="55">
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle @click="methods.handleClazzDelete(scope.$index, scope.row, props.addType)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="clazz" :label="t('flowClazz.clazz')" width="130" show-overflow-tooltip/>
|
||||
<el-table-column prop="httpUrl" :label="t('flowClazz.httpUrl')" width="130" show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<el-table-column prop="methods" label="触发时机" width="130" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="props.flowMethods" :value="scope.row.methods"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varKeyVal" label="函数表达式" width="130" show-overflow-tooltip v-if="data.clazz.valType === '2'"/>
|
||||
<el-table-column prop="varKeyVal" label="SpEL表达式" width="130" show-overflow-tooltip v-if="data.clazz.valType === '1'"/>
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" width="130" show-overflow-tooltip v-if="data.clazz.valType === '0'">
|
||||
<template #default="scope">
|
||||
<convert-group-name :options="data.allFieldPerms" :value="scope.row.varKeyVal"
|
||||
:valueKey="'prop'" :showKey="'label'"></convert-group-name>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" width="100" show-overflow-tooltip v-if="data.clazz.valType === '0'">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="DIC_PROP.OPERATOR" :value="scope.row.operator"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" width="100" show-overflow-tooltip v-if="data.clazz.valType === '0'"/>
|
||||
<el-table-column prop="remark" :label="t('flowClazz.remark')" width="70" show-overflow-tooltip/>
|
||||
<el-table-column prop="sort" :label="t('flowClazz.sort')" width="70" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</el-form>
|
||||
|
||||
<el-drawer
|
||||
class="flow-attr-drawer"
|
||||
title="Http请求的参数信息"
|
||||
direction="rtl"
|
||||
append-to-body
|
||||
:size="630" v-if="data.httpUrlParamsVisible"
|
||||
v-model="data.httpUrlParamsVisible">
|
||||
<el-form label-position="left" class="flow-attr flow-param-attr" label-width="150px">
|
||||
<flow-http-param ref="flowHttpParam" :currFlowForm="props.currFlowForm" :httpParam="data.clazz"
|
||||
:flowData="props.flowData"></flow-http-param>
|
||||
</el-form>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowClazz">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {rule, validateNull} from "/@/utils/validate";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
import {DIC_PROP} from "/@/flow/support/dict-prop";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const FlowHttpParam = defineAsyncComponent(() => import('./flow-http-param.vue'));
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
clazzPlaceholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
flowMethods: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
addType: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
});
|
||||
|
||||
const clazzData = {
|
||||
clazz: null,
|
||||
httpUrl: null,
|
||||
httpMethod: 'GET',
|
||||
httpParams: null,
|
||||
methods: null,
|
||||
valType: null,
|
||||
varKeyVal: null,
|
||||
operator: null,
|
||||
varVal: null,
|
||||
remark: null,
|
||||
sort: 1,
|
||||
}
|
||||
const data = reactive({
|
||||
tableFieldData: [],
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
clazz: deepClone(clazzData),
|
||||
httpUrlParamsVisible: false,
|
||||
moreInter: false,
|
||||
existData: false,
|
||||
tableData: []
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
openHttpUrlParams(bool) {
|
||||
if (!data.clazz.httpUrl) {
|
||||
$message.warning("请先输入【Http请求地址】")
|
||||
return
|
||||
}
|
||||
data.httpUrlParamsVisible = bool
|
||||
},
|
||||
handleHttpUrlBlur() {
|
||||
if (!data.clazz.httpUrl) {
|
||||
data.clazz.httpParams = []
|
||||
return;
|
||||
}
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
if (!row) return
|
||||
data.clazz = row
|
||||
data.clazz.isSelectedRow = true
|
||||
},
|
||||
handleVarKeyVal(varKeyVal) {
|
||||
let dots = varKeyVal.split('.').length - 1;
|
||||
if (dots === 2) {
|
||||
data.varValOperator = DIC_PROP.OPERATOR.slice(6)
|
||||
} else {
|
||||
data.varValOperator = DIC_PROP.OPERATOR
|
||||
}
|
||||
},
|
||||
onAddItem(){
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
if (data.tableFieldData.length > 0) return
|
||||
let obj = {varKeyVal: '', operator: '', varVal: ''};
|
||||
data.tableFieldData.push(obj);
|
||||
},
|
||||
addFlowNodeClazz(type) {
|
||||
let clazzes = type === '0' ? props.currSelect.attributes.attrs.cdata.attrs.clazzes : props.flowData.attrs.clazzes;
|
||||
if (!data.clazz.clazz && !data.clazz.httpUrl) {
|
||||
$message.warning("请填写 监听类 或者 Http请求地址")
|
||||
return
|
||||
}
|
||||
if (validateNull(data.clazz.methods)) {
|
||||
$message.warning("触发时机不能为空")
|
||||
return
|
||||
}
|
||||
if (!validateNull(clazzes) && !data.clazz.isSelectedRow) {
|
||||
if (data.clazz.clazz) {
|
||||
let b = methods.validateClazzHttpUrl(clazzes, 'clazz', '监听类');
|
||||
if (b) return;
|
||||
} else {
|
||||
let b = methods.validateClazzHttpUrl(clazzes, 'httpUrl', 'Http请求地址');
|
||||
if (b) return;
|
||||
}
|
||||
}
|
||||
if (data.clazz.clazz && data.clazz.httpUrl) {
|
||||
$message.error("监听类 与 Http请求地址不能同时存在")
|
||||
return;
|
||||
}
|
||||
if (data.clazz.isSelectedRow) {
|
||||
data.clazz.isSelectedRow = false
|
||||
proxy.$refs.tableDataRef.setCurrentRow(null)
|
||||
data.clazz = deepClone(clazzData);
|
||||
} else {
|
||||
let clazz = deepClone(data.clazz);
|
||||
if (type === '0') props.currSelect.attributes.attrs.cdata.attrs.clazzes.unshift(clazz)
|
||||
else props.flowData.attrs.clazzes.unshift(clazz)
|
||||
methods.validateClazzData()
|
||||
}
|
||||
},
|
||||
validateClazzHttpUrl(clazzes, key, errMsg){
|
||||
let find = clazzes.find(f => f[key] === data.clazz[key]);
|
||||
if (find) {
|
||||
$message.warning("请勿重复添加 " + errMsg)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
handleClazzDelete(index: number, row: any, type: string){
|
||||
if (type === '0') props.currSelect.attributes.attrs.cdata.attrs.clazzes.splice(index, 1)
|
||||
else props.flowData.attrs.clazzes.splice(index, 1)
|
||||
methods.validateClazzData()
|
||||
},
|
||||
handleClazzValType(type?) {
|
||||
if (!type) {
|
||||
type = methods.initCurrVarKeyVal()
|
||||
}
|
||||
if (type === DIC_PROP.VAL_TYPE[2].value) {
|
||||
data.varValOperator = DIC_PROP.OPERATOR
|
||||
methods.onAddItem()
|
||||
} else {
|
||||
data.varValOperator = []
|
||||
}
|
||||
data.clazz.varKeyVal = null
|
||||
data.clazz.operator = null
|
||||
data.clazz.varVal = null
|
||||
},
|
||||
handleClazzVarKeyVal() {
|
||||
let val = data.clazz.varKeyVal
|
||||
if (!val) return
|
||||
let valType = data.clazz.valType;
|
||||
if (valType === DIC_PROP.VAL_TYPE[3].value && val.indexOf("#") === -1) {
|
||||
data.clazz.varKeyVal = null
|
||||
$message.warning("当选择SpEL模式时, SpEL表达式必须符合SpEL格式")
|
||||
} else if (valType === DIC_PROP.VAL_TYPE[4].value && val.indexOf("#") === -1) {
|
||||
data.clazz.varKeyVal = null
|
||||
$message.warning("当选择专业模式时, 函数表达式必须符合规定的格式")
|
||||
}
|
||||
},
|
||||
showMoreSetting() {
|
||||
data.moreInter = !data.moreInter
|
||||
},
|
||||
validateClazzData() {
|
||||
let clazzes = props.addType === '0' ? props.currSelect.attributes.attrs.cdata.attrs.clazzes : props.flowData.attrs.clazzes;
|
||||
if (!clazzes) {
|
||||
if (props.addType === '0') props.currSelect.attributes.attrs.cdata.attrs.clazzes = []
|
||||
else props.flowData.attrs.clazzes = []
|
||||
}
|
||||
data.tableData.splice(0, data.tableData.length);
|
||||
if (props.addType === '0') {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.clazzes.forEach(each => data.tableData.push(each))
|
||||
} else {
|
||||
props.flowData.attrs.clazzes.forEach(each => data.tableData.push(each))
|
||||
}
|
||||
data.existData = !validateNull(data.tableData)
|
||||
},
|
||||
initCurrVarKeyVal() {
|
||||
if (data.tableData.length > 0) {
|
||||
data.clazz.valType = data.tableData[0].valType
|
||||
}
|
||||
data.clazz.methods = []
|
||||
return data.clazz.valType
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateClazzData()
|
||||
methods.handleClazzValType()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
527
src/flow/designer/components/flow-con-rule.vue
Normal file
527
src/flow/designer/components/flow-con-rule.vue
Normal file
@@ -0,0 +1,527 @@
|
||||
<template>
|
||||
<el-form-item label="起始节点(可修改)">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.fromFlowNodeId"
|
||||
@change="methods.changeLinkFlowNodeIds('0')"
|
||||
filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.fromFlowNodeIds"
|
||||
:key="item.id"
|
||||
:label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标节点(可修改)">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.toFlowNodeId"
|
||||
@change="methods.changeLinkFlowNodeIds('1')"
|
||||
filterable clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.toFlowNodeIds"
|
||||
:key="item.id"
|
||||
:label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="条件组关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupsType" @change="methods.changeGroupsType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="条件模式">
|
||||
<el-radio-group @change="methods.handleCondValType" :disabled="data.existData"
|
||||
v-model="data.cond.valType">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.VAL_TYPE.slice(2, 6)" :key="index" :label="item.value"
|
||||
style="width: 56px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>若无法切换模式,请先清空条件组列表</template>
|
||||
<el-icon style="margin-left: 30px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>组内条件配置</el-divider>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="data.cond.condGroup"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle @click="methods.onAddItem(true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle @click="methods.handleCondDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable
|
||||
filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.operator" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.varValOperator"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.varVal" clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<el-form-item label="SpEL表达式" v-if="data.cond.valType === '1'">
|
||||
<el-input class="input-attr" v-model="data.cond.varKeyVal" placeholder="请输入SpEL表达式" clearable @blur="methods.handleCondVarKeyVal"/>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ PROP_CONST.TEXT_DESC.condSpELExplain }}</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="函数表达式" v-if="data.cond.valType === '2'">
|
||||
<el-input class="input-attr" v-model="data.cond.varKeyVal" placeholder="请输入函数表达式" clearable @blur="methods.handleCondVarKeyVal"/>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>{{ PROP_CONST.TEXT_DESC.condMethodExplain1 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain2 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain3 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain4 }}
|
||||
</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="data.cond.valType === '2'" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前函数表达式的返回值为字符串 1 ( 满足 ) 或 0 ( 不满足 )</span>
|
||||
</div>
|
||||
|
||||
<template v-if="data.cond.valType === '3'">
|
||||
<el-form-item label="Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="data.cond.varKeyVal"
|
||||
@blur="methods.handleCondVarKeyVal" clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="data.cond.httpMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip content="点击可设置Http请求的参数信息" placement="bottom">
|
||||
<el-button type="primary" size="small" round style="margin-left: 10px"
|
||||
@click="methods.openHttpUrlParams()">
|
||||
{{ data.httpUrlParamsVisible ? '清空' : '参数' }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<flow-http-param ref="flowHttpParam" :currFlowForm="props.currFlowForm" :flowData="props.flowData"
|
||||
:httpParam="props.currSelect.attributes.attrs.cdata.attrs"
|
||||
:httpParamType="DIC_PROP.PARAM_RULE_TYPE[1].value"
|
||||
v-if="data.httpUrlParamsVisible">
|
||||
</flow-http-param>
|
||||
</template>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-button type="primary" round style="margin-left: 185px; margin-top: 30px; margin-bottom: 30px; width: 200px"
|
||||
@click="methods.addFlowNodeCondGroup()">
|
||||
{{ data.oldCurrentRow ? '修改完成': '添加条件组' }}
|
||||
</el-button>
|
||||
<el-divider>已添加条件组列表(点击行可再次修改)</el-divider>
|
||||
<el-empty description="条件组列表为空" style="margin: 10px 230px" v-if="!data.existData">
|
||||
</el-empty>
|
||||
|
||||
<template v-for="(item, index) in data.condGroups" v-else
|
||||
:key="index">
|
||||
|
||||
<el-collapse v-model="data.collapse">
|
||||
<el-collapse-item :name="index">
|
||||
<template #title>
|
||||
{{ '条件组 ' + (index + 1) }}
|
||||
|
||||
<el-icon style="margin-left: 10px" @click="methods.handleCondGroupDelete(index)">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</template>
|
||||
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="item.groupType" @change="methods.changeGroupType(item, index)"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="item.condGroup" border style="width: 100%" max-height="500"
|
||||
highlight-current-row @current-change="methods.handleCurrentChange" :ref="'tableDataRef' + index">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSingleCondDelete(scope.$index, scope.row, index)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<convert-group-name :options="data.allFieldPerms"
|
||||
:value="scope.row.varKeyVal"
|
||||
:valueKey="'prop'" :showKey="'label'"></convert-group-name>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="DIC_PROP.OPERATOR" :value="scope.row.operator"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowConRule">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {rule, validateNull} from "/@/utils/validate";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
import {DIC_PROP} from "/@/flow/support/dict-prop";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
import {PROP_CONST} from "../../support/prop-const";
|
||||
import {changeLinkFlowNodeIds, handleLinkFlowNodeIds} from "./index";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
const FlowHttpParam = defineAsyncComponent(() => import('./flow-http-param.vue'));
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const $emit = defineEmits(["hideAttrConfig"]);
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
attrConfigVisible: null
|
||||
});
|
||||
|
||||
const condData = {
|
||||
httpMethod: 'GET',
|
||||
groupsType: '0',
|
||||
condGroup: [],
|
||||
groupType: '0',
|
||||
valType: '0',
|
||||
varKeyVal: null,
|
||||
operator: null,
|
||||
varVal: null,
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
collapse: [0],
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
cond: deepClone(condData),
|
||||
httpUrlParamsVisible: false,
|
||||
oldCurrentRow: null,
|
||||
condGroups: [],
|
||||
existData: false,
|
||||
modifyPointType: null,
|
||||
fromFlowNodeId: null,
|
||||
fromFlowNodeIds: [],
|
||||
toFlowNodeId: null,
|
||||
toFlowNodeIds: []
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
openHttpUrlParams() {
|
||||
if (!data.cond.varKeyVal) {
|
||||
$message.warning("请先输入【Http请求地址】")
|
||||
return
|
||||
}
|
||||
if (data.httpUrlParamsVisible) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpParams = []
|
||||
data.httpUrlParamsVisible = false
|
||||
} else {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
if (!row) return
|
||||
let condGroupsRow;
|
||||
for (let i = 0; i < data.condGroups.length; i++) {
|
||||
let index = data.condGroups[i].condGroup.indexOf(row);
|
||||
if (index !== -1) {
|
||||
condGroupsRow = data.condGroups[i];
|
||||
}
|
||||
}
|
||||
// 先清空之前选中的其他条件组
|
||||
if (data.oldCurrentRow !== condGroupsRow) {
|
||||
let oldIndex = data.condGroups.indexOf(data.oldCurrentRow);
|
||||
if (oldIndex !== -1) {
|
||||
proxy.$refs['tableDataRef' + oldIndex][0].setCurrentRow(null)
|
||||
}
|
||||
}
|
||||
data.cond = condGroupsRow
|
||||
data.oldCurrentRow = condGroupsRow
|
||||
},
|
||||
handleVarKeyVal(row) {
|
||||
let dots = row.varKeyVal.split('.').length - 1;
|
||||
if (dots === 2) {
|
||||
let find = DIC_PROP.OPERATOR.slice(6).find(f => f.value === row.operator);
|
||||
if (!find) {
|
||||
$message.warning("子表单的字段只能选择包含或不包含")
|
||||
row.operator = null
|
||||
}
|
||||
}
|
||||
},
|
||||
changeGroupsType(groupsType) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.forEach(each => {
|
||||
each.groupsType = groupsType
|
||||
})
|
||||
methods.validateCondData()
|
||||
},
|
||||
changeGroupType(item, index) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups[index].groupType = item.groupType
|
||||
methods.validateCondData()
|
||||
},
|
||||
onAddItem(isAdd) {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
if (data.cond.condGroup.length > 0) {
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
let b = !find.varKeyVal || !find.operator || !find.varVal;
|
||||
if (isAdd && b) {
|
||||
$message.warning("请先填写 表单字段 或 运算符 或 值")
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.cond.condGroup.splice(0, data.cond.condGroup.length);
|
||||
}
|
||||
let obj = {varKeyVal: '', operator: '', varVal: ''};
|
||||
data.cond.condGroup.push(obj);
|
||||
},
|
||||
addFlowNodeCondGroup() {
|
||||
if (validateNull(data.cond.condGroup)) {
|
||||
$message.warning("请先添加组内条件")
|
||||
return
|
||||
}
|
||||
let valType = data.cond.valType;
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
if (!find.varKeyVal || !find.operator || !find.varVal) {
|
||||
$message.warning("表单字段 或 运算符 或 值 不能为空")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.oldCurrentRow) {
|
||||
// 先清空之前选中
|
||||
let index = data.condGroups.indexOf(data.cond);
|
||||
if (index !== -1) {
|
||||
proxy.$refs['tableDataRef' + index][0].setCurrentRow(null)
|
||||
}
|
||||
data.oldCurrentRow = null
|
||||
data.cond = deepClone(condData);
|
||||
} else {
|
||||
let cond = deepClone(data.cond);
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.unshift(cond)
|
||||
methods.validateCondData()
|
||||
methods.updateCondVarKeyVal(true)
|
||||
}
|
||||
},
|
||||
handleCondGroupDelete(index: number) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.splice(index, 1)
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleSingleCondDelete(index: number, row: any, groupIndex) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups[groupIndex].condGroup.splice(index, 1)
|
||||
if (validateNull(props.currSelect.attributes.attrs.cdata.attrs.condGroups[groupIndex].condGroup)) {
|
||||
methods.handleCondGroupDelete(groupIndex)
|
||||
}
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleCondDelete(index: number, row: any) {
|
||||
data.cond.condGroup.splice(index, 1)
|
||||
},
|
||||
handleCondValType(type?) {
|
||||
if (type) {
|
||||
data.cond.varKeyVal = null
|
||||
methods.updateCondVarKeyVal(false)
|
||||
}
|
||||
if (!type) {
|
||||
type = methods.initCurrVarKeyVal()
|
||||
}
|
||||
if (type === DIC_PROP.VAL_TYPE[2].value) {
|
||||
data.varValOperator = DIC_PROP.OPERATOR
|
||||
methods.onAddItem(false)
|
||||
} else {
|
||||
data.varValOperator = []
|
||||
}
|
||||
data.cond.operator = null
|
||||
data.cond.varVal = null
|
||||
},
|
||||
handleCondVarKeyVal() {
|
||||
let val = data.cond.varKeyVal
|
||||
let valType = data.cond.valType;
|
||||
if (!val) {
|
||||
methods.updateCondVarKeyVal(false)
|
||||
return
|
||||
}
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) return
|
||||
if (valType === DIC_PROP.VAL_TYPE[3].value && val.indexOf("#") === -1) {
|
||||
data.cond.varKeyVal = null
|
||||
$message.warning("当选择SpEL模式时, SpEL表达式必须符合SpEL格式")
|
||||
return;
|
||||
} else if (valType === DIC_PROP.VAL_TYPE[4].value && val.indexOf("#") === -1) {
|
||||
data.cond.varKeyVal = null
|
||||
$message.warning("当选择专业模式时, 函数表达式必须符合规定的格式")
|
||||
return;
|
||||
}
|
||||
methods.updateCondVarKeyVal(true)
|
||||
},
|
||||
updateCondVarKeyVal(isSave) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.valType = data.cond.valType
|
||||
if (isSave) {
|
||||
if (data.cond.valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.varKeyVal = PROP_CONST.VAR_KEY_VAL.link
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.varKeyVal = data.cond.varKeyVal
|
||||
}
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpMethod = data.cond.httpMethod
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.varKeyVal = null
|
||||
props.currSelect.attributes.attrs.cdata.attrs.varKeyValName = null
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups = []
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpParams = []
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpMethod = null
|
||||
data.httpUrlParamsVisible = false
|
||||
}
|
||||
},
|
||||
validateCondData() {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (!condGroups) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups = []
|
||||
}
|
||||
data.condGroups.splice(0, data.condGroups.length);
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.forEach(each => data.condGroups.push(each))
|
||||
data.existData = !validateNull(data.condGroups)
|
||||
},
|
||||
initCurrVarKeyVal() {
|
||||
data.cond.valType = props.currSelect.attributes.attrs.cdata.attrs.valType
|
||||
if (data.condGroups.length <= 0) {
|
||||
data.cond.varKeyVal = props.currSelect.attributes.attrs.cdata.attrs.varKeyVal
|
||||
let httpMethod = props.currSelect.attributes.attrs.cdata.attrs.httpMethod
|
||||
if (httpMethod) data.cond.httpMethod = httpMethod
|
||||
} else {
|
||||
data.cond.groupsType = data.condGroups[0].groupsType
|
||||
}
|
||||
let httpParams = props.currSelect.attributes.attrs.cdata.attrs.httpParams;
|
||||
if (!validateNull(httpParams)) {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
return data.cond.valType
|
||||
},
|
||||
handleLinkFlowNodeIds() {
|
||||
handleLinkFlowNodeIds(data, props)
|
||||
},
|
||||
changeLinkFlowNodeIds(type) {
|
||||
data.modifyPointType = type
|
||||
changeLinkFlowNodeIds(data, props, methods, $emit)
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateCondData()
|
||||
methods.handleCondValType()
|
||||
methods.handleLinkFlowNodeIds()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0 || !props.attrConfigVisible) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
125
src/flow/designer/components/flow-curr-job.vue
Normal file
125
src/flow/designer/components/flow-curr-job.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<el-table :data="props.currSelect.attributes.attrs.cdata.defJob.currRunJobs" style="width: 100%">
|
||||
<el-table-column type="index" :label="t('createTable.index')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle @click="onAddItem"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle @click="handleDelete(scope.$index, scope.row)"
|
||||
:disabled="scope.row.isConfigJob === '1'"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" :label="t('runJob.sort')" show-overflow-tooltip width="70">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.sort" :placeholder="t('runJob.inputSortTip')"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jobName" :label="t('runJob.jobName')" show-overflow-tooltip width="150">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.jobName" :placeholder="t('runJob.inputJobNameTip')"></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="jobType" :label="t('runJob.jobType')" show-overflow-tooltip width="100">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.jobType" :placeholder="t('runJob.inputJobTypeTip')" clearable filterable
|
||||
@change="handleRoleType(scope.row)">
|
||||
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_NONE_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="roleId" :label="t('runJob.roleId')" show-overflow-tooltip width="130">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="请输入名称进行模糊搜索" placement="top">
|
||||
<el-select v-model="scope.row.roleId" :placeholder="t('runJob.inputRoleIdTip')" clearable filterable
|
||||
remote :remote-method="(query) => remoteMethodAll(query, scope.row.jobType)" :reserve-keyword="false">
|
||||
<el-option v-for="(item, index) in dicData.users" :key="index" :label="item.name" :value="item.userId"
|
||||
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[0].value"></el-option>
|
||||
<el-option v-for="(item, index) in dicData.roles" :key="index" :label="item.roleName" :value="item.roleId"
|
||||
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[1].value"></el-option>
|
||||
<el-option v-for="(item, index) in dicData.posts" :key="index" :label="item.postName" :value="item.postId"
|
||||
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[2].value"></el-option>
|
||||
<el-option v-for="(item, index) in dicData.depts" :key="index" :label="item.name" :value="item.deptId"
|
||||
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[3].value"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="userId" :label="t('runJob.userId')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<convert-name :options="dicData.userId" :value="scope.row.userId"
|
||||
:valueKey="'userId'" :showKey="'name'"></convert-name>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="startTime" :label="t('runJob.startTime')" show-overflow-tooltip/>
|
||||
<el-table-column prop="status" :label="t('runJob.status')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="DIC_PROP.NODE_STATUS" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowCurrJob">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {onFormLoadedUrl, onLoadDicUrl, remoteMethodAllByKey} from "../../components/convert-name/convert";
|
||||
import {handleChangeJobType} from "../../index";
|
||||
import {DIC_PROP} from "../../support/dict-prop";
|
||||
import {validateNull} from "../../../utils/validate";
|
||||
import {PROP_CONST} from "../../support/prop-const";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义字典
|
||||
const dicData = reactive({});
|
||||
const onLoad = onLoadDicUrl();
|
||||
const onFormLoaded = onFormLoadedUrl({key: "userId"}, ...PROP_CONST.LOAD_USER_ROLE);
|
||||
onMounted(async () => {
|
||||
// await onLoad(dicData);
|
||||
await onFormLoadedCurrRunJobs()
|
||||
})
|
||||
|
||||
const onAddItem = () => {
|
||||
let jobName = props.currSelect.attributes.attrs.cdata.defJob.jobName;
|
||||
let obj = {sort: 1, jobName: jobName, jobType: DIC_PROP.JOB_USER_NONE_TYPE[0].value, roleId: null, userId: null,
|
||||
startTime: null, status: DIC_PROP.NODE_STATUS[0].value};
|
||||
props.currSelect.attributes.attrs.cdata.defJob.currRunJobs.push(obj);
|
||||
}
|
||||
|
||||
const handleDelete = (index: number, row: any) => {
|
||||
let currRunJobs = props.currSelect.attributes.attrs.cdata.defJob.currRunJobs;
|
||||
if (currRunJobs.length === 1) {
|
||||
useMessage().warning("当前节点参与者至少需存在一个参与者");
|
||||
return
|
||||
}
|
||||
props.currSelect.attributes.attrs.cdata.defJob.currRunJobs.splice(index, 1)
|
||||
}
|
||||
|
||||
function remoteMethodAll(query: string, jobType) {
|
||||
remoteMethodAllByKey(onLoad, dicData, query, jobType)
|
||||
}
|
||||
|
||||
function onFormLoadedCurrRunJobs() {
|
||||
let currRunJobs = props.currSelect.attributes.attrs.cdata.defJob.currRunJobs
|
||||
if (validateNull(currRunJobs)) return
|
||||
onFormLoaded(dicData, currRunJobs)
|
||||
}
|
||||
|
||||
function handleRoleType(row) {
|
||||
handleChangeJobType(dicData, row)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
207
src/flow/designer/components/flow-form-http.vue
Normal file
207
src/flow/designer/components/flow-form-http.vue
Normal file
@@ -0,0 +1,207 @@
|
||||
<template>
|
||||
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="160px">
|
||||
<el-form-item label="查询表单Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="props.flowData.attrs.queryOrder"
|
||||
clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="props.flowData.attrs.queryMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>查询表单信息接口(可输入全路径或相对路径)</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新表单Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="props.flowData.attrs.updateOrder"
|
||||
clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="props.flowData.attrs.updateMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>更新表单信息接口(可输入全路径或相对路径)</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>关联表单Http请求头</el-divider>
|
||||
|
||||
<el-table :data="data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[0].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleHttpUrlDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.requestHeader')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp" :placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.paramValType" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.SYS_PARAM_VAL_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('jfAttr.sysVarKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
v-if="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
|
||||
<el-input v-else v-model="scope.row.varKeyVal" clearable> </el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</el-form>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowHttpParam">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {handleFieldProp} from "../../utils/form-perm";
|
||||
import {DIC_PROP} from "../../support/dict-prop";
|
||||
import {PROP_CONST} from "../../support/prop-const";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
attrConfigVisible: null
|
||||
});
|
||||
|
||||
const data = reactive({
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
httpParams: [],
|
||||
paramType: '0',
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
onMounted(async () => {
|
||||
if (!props.attrConfigVisible) return
|
||||
methods.changeTabPane()
|
||||
})
|
||||
|
||||
const methods = {
|
||||
listFormFieldPerms() {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
let formFieldPerms = deepClone(PROP_CONST.SYS_FIELDS);
|
||||
handleFieldProp(formFieldPerms, null)
|
||||
data.allFieldPerms = [{label: '系统字段', options: formFieldPerms}]
|
||||
}
|
||||
},
|
||||
onAddItem(paramFrom, isAdd) {
|
||||
methods.listFormFieldPerms()
|
||||
let value = DIC_PROP.PARAM_VAL_TYPE[0].value;
|
||||
if (data.httpParams.length > 0) {
|
||||
let find = data.httpParams.filter(f => f.paramFrom === paramFrom).find(f => !f.varKeyVal || (f.paramValType !== value && !f.targetProp));
|
||||
if (find) {
|
||||
if (isAdd) {
|
||||
if (!find.varKeyVal) {
|
||||
$message.warning("请先填写 表单字段")
|
||||
return
|
||||
}
|
||||
if (find.paramValType !== value && !find.targetProp) {
|
||||
$message.warning("请先填写 请求头")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.httpParams.splice(0, data.httpParams.length);
|
||||
}
|
||||
let obj = {paramFrom: paramFrom, varKeyVal: null, paramValType: value, targetProp: null};
|
||||
data.httpParams.push(obj);
|
||||
methods.changeHttpUrlParams()
|
||||
},
|
||||
handleHttpUrlDelete(index: number, row: any) {
|
||||
let splice = data.httpParams.filter(f => f.paramFrom === row.paramFrom);
|
||||
splice.splice(index, 1);
|
||||
data.httpParams = splice
|
||||
methods.changeHttpUrlParams()
|
||||
},
|
||||
validateHttpUrlData() {
|
||||
// 兼容老版本
|
||||
let httpParams = props.flowData.attrs.orderParams;
|
||||
if (!httpParams) {
|
||||
props.flowData.attrs.orderParams = []
|
||||
}
|
||||
let queryMethod = props.flowData.attrs.queryMethod;
|
||||
if (!queryMethod) props.flowData.attrs.queryMethod = 'GET'
|
||||
let updateMethod = props.flowData.attrs.updateMethod;
|
||||
if (!updateMethod) props.flowData.attrs.updateMethod = 'PUT'
|
||||
data.httpParams = props.flowData.attrs.orderParams
|
||||
},
|
||||
changeHttpUrlParams() {
|
||||
props.flowData.attrs.orderParams = data.httpParams
|
||||
},
|
||||
changeTabPane() {
|
||||
methods.validateHttpUrlData()
|
||||
methods.listFormFieldPerms()
|
||||
}
|
||||
}
|
||||
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.attrConfigVisible,
|
||||
(val) => {
|
||||
if (!val) return
|
||||
methods.changeTabPane()
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
295
src/flow/designer/components/flow-form-perm.vue
Normal file
295
src/flow/designer/components/flow-form-perm.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<el-form v-if="methods.validateNode(props.currSelect)"
|
||||
label-position="left" class="flow-config-attr" label-width="130px">
|
||||
|
||||
<el-form-item label="全部只读或可编辑" prop="formPermType">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>1、对当前节点表单的字段全部只读 或 全部可编辑。默认全部可编辑
|
||||
<br/> 2、可在下方进一步约束权限,如这里选择全部只读,下方配置某些字段可编辑
|
||||
</template>
|
||||
<el-radio-group v-model="props.currSelect.attributes.attrs.cdata.attrs.formPermType">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.ALL_FORM_PERM_TYPE" :key="index" :label="item.value" style="width: 135px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip placement="top" v-if="props.currSelect.attributes.attrs.cdata.attrs.formPermType">
|
||||
<template #content>清空后可在下方单个字段配置权限或业务侧自行判断</template>
|
||||
<el-button text type="primary" icon="delete" @click="props.currSelect.attributes.attrs.cdata.attrs.formPermType = null">
|
||||
清空
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>请选择表单名称</el-divider>
|
||||
<el-form-item label="PC待办页面">
|
||||
<el-tooltip placement="top">
|
||||
<template #content>若下拉选项为空或没有期望的表单,请先在节点属性-PC待办页面选择</template>
|
||||
<el-select class="input-attr"
|
||||
v-model="props.currSelect.attributes.attrs.cdata.attrs.formId"
|
||||
@change="methods.changeNodeFormId"
|
||||
clearable filterable placeholder="请选择节点属性-PC待办页面">
|
||||
<template v-for="(item, index) in props.formIds">
|
||||
<el-option
|
||||
v-if="methods.filterNodeFormId(item)"
|
||||
:key="index"
|
||||
:label="item.formName+' V'+item.version"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-button @click="methods.addFormPermission" type="primary" round v-if="props.isShowAdd"
|
||||
style="margin-left: 10px;">新增字段
|
||||
</el-button>
|
||||
<el-button @click="methods.resetFormPerm" type="primary" size="small" round v-if="!props.isShowAdd"
|
||||
style="margin-left: 10px;">重置权限
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>参与者可以操作表单字段权限</el-divider>
|
||||
<el-empty description="表单字段权限列表为空" style="margin: 10px 230px" v-if="validateNull(data.formFieldPerms)">
|
||||
</el-empty>
|
||||
<el-form-item v-for="(item, index) in data.formFieldPerms" v-else
|
||||
:label="item.label"
|
||||
:key="index">
|
||||
<el-input style="width: 131px; margin-right: 10px" v-model="item.label" v-if="props.isShowAdd"></el-input>
|
||||
<el-input style="width: 131px; margin-right: 10px" v-model="item.prop" v-if="props.isShowAdd"></el-input>
|
||||
<el-radio-group v-model="item.permType">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.FORM_PERM_TYPE" :key="index"
|
||||
:disabled="props.currSelect.attributes.attrs.cdata.attrs.formPermType === item.value"
|
||||
:label="item.value" style="width: 86px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-button @click.prevent="methods.removeFormPermission(item.prop)" type="primary" size="small" round>
|
||||
删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowFormPerm">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {parseWithFunctions, validateRunFlow} from "../../index";
|
||||
import {buildFieldPerms, handleFormFieldPerms} from "../../utils/form-perm";
|
||||
import {CommonNodeType, HighNodeType} from "../config/type";
|
||||
import {listFormOption} from "/@/api/jsonflow/form-option";
|
||||
import {DIC_PROP} from "../../support/dict-prop";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
formIds: {
|
||||
type: Array,
|
||||
default: null,
|
||||
},
|
||||
isShowAdd: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const data = reactive({
|
||||
formFieldPerms: [],
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
validateCurrSelectAttrs(currSelect?) {
|
||||
if (!currSelect) currSelect = props.currSelect;
|
||||
if (validateNull(currSelect.attributes)) return false
|
||||
return true
|
||||
},
|
||||
validateNode(currSelect) {
|
||||
if (!methods.validateCurrSelectAttrs()) return false;
|
||||
let type = currSelect.attributes.attrs.cdata.type;
|
||||
return type === CommonNodeType.START || type === CommonNodeType.END || type === CommonNodeType.SERIAL || type === CommonNodeType.PARALLEL || type === HighNodeType.VIRTUAL
|
||||
},
|
||||
filterNodeFormId(item) {
|
||||
let pcTodoUrl = props.currSelect.attributes.attrs.cdata.attrs.pcTodoUrl
|
||||
if (!validateNull(pcTodoUrl)) {
|
||||
return pcTodoUrl.includes(item.id)
|
||||
} else return false
|
||||
},
|
||||
changeNodeFormId(value) {
|
||||
if (!methods.validateNode(props.currSelect)) return;
|
||||
if (!value) {
|
||||
methods.clearPermData()
|
||||
return
|
||||
}
|
||||
data.formFieldPerms = []
|
||||
let find = props.formIds.find(f => f.id === value);
|
||||
if (validateNull(find.formInfo)) {
|
||||
methods.handleFormFieldPerms(find)
|
||||
} else {
|
||||
let formInfo = parseWithFunctions(find.formInfo, true)
|
||||
buildFieldPerms(data.formFieldPerms, formInfo.widgetList);
|
||||
}
|
||||
methods.setNodeAttrsFormFieldPerms()
|
||||
},
|
||||
handleFormFieldPerms(find) {
|
||||
// 无需前缀
|
||||
let isReturn = handleFormFieldPerms(data, $message, find, '');
|
||||
if (isReturn) return
|
||||
if (find.isCurrForm === '1' && !validateNull(find.formFieldPerms)) {
|
||||
methods.buildCustomFormPerm(find.formFieldPerms)
|
||||
return;
|
||||
}
|
||||
// 已配置或全部字段
|
||||
methods.handleCustomFormPerm(find.id, null, props.flowData.attrs.id , props.currSelect.id)
|
||||
},
|
||||
initNodeFormId() {
|
||||
if (Object.keys(props.currSelect).length === 0) return
|
||||
if (!methods.validateNode(props.currSelect)) return;
|
||||
let formId = props.currSelect.attributes.attrs.cdata.attrs.formId;
|
||||
if (!formId) {
|
||||
methods.clearPermData()
|
||||
return
|
||||
}
|
||||
// formId必存在权限
|
||||
data.formFieldPerms = props.currSelect.attributes.attrs.cdata.attrs.formFieldPerms;
|
||||
methods.initAddFormPermission(formId)
|
||||
},
|
||||
async initAddFormPermission(formId) {
|
||||
let find = props.formIds.find(f => f.id === formId);
|
||||
if (!find) return
|
||||
let formFieldPerms = []
|
||||
if (find.type === DIC_PROP.FORM_TYPE[1].value) {
|
||||
if (find.isCurrForm === '1') {
|
||||
formFieldPerms = find.formFieldPerms
|
||||
} else {
|
||||
formFieldPerms = await methods.reqCustomFormPerm(formId, DIC_PROP.FORM_DATA_TYPE[0].value, null, null)
|
||||
}
|
||||
}
|
||||
if (find.type !== DIC_PROP.FORM_TYPE[1].value) {
|
||||
if (!validateNull(find.formInfo)) {
|
||||
let formInfo = parseWithFunctions(find.formInfo, true)
|
||||
buildFieldPerms(formFieldPerms, formInfo.widgetList);
|
||||
}
|
||||
}
|
||||
if (validateNull(formFieldPerms)) return
|
||||
formFieldPerms.forEach(each => {
|
||||
let index = data.formFieldPerms.findIndex(f => f.propId ? each.propId === f.propId : each.prop === f.prop);
|
||||
if (index !== -1) {
|
||||
let exist = data.formFieldPerms[index]
|
||||
data.formFieldPerms.splice(index, 1);
|
||||
each.permType = exist.permType
|
||||
data.formFieldPerms.splice(index, 0, each);
|
||||
return
|
||||
}
|
||||
data.formFieldPerms.push(each)
|
||||
})
|
||||
},
|
||||
removeFormPermission(prop) {
|
||||
if (data.formFieldPerms.length === 0) return
|
||||
data.formFieldPerms = data.formFieldPerms.filter(f => f.prop !== prop)
|
||||
methods.setNodeAttrsFormFieldPerms()
|
||||
},
|
||||
setNodeAttrsFormFieldPerms() {
|
||||
// 相同引用
|
||||
props.currSelect.attributes.attrs.cdata.attrs.formFieldPerms = data.formFieldPerms
|
||||
},
|
||||
addFormPermission() {
|
||||
let formId = props.currSelect.attributes.attrs.cdata.attrs.formId;
|
||||
if (!formId) {
|
||||
$message.warning("请先选择表单名称")
|
||||
return
|
||||
}
|
||||
if (!data.formFieldPerms) data.formFieldPerms = []
|
||||
let number = data.formFieldPerms.length + 1;
|
||||
data.formFieldPerms.unshift({
|
||||
prop: 'propName' + number,
|
||||
label: '请输入字段名称'
|
||||
})
|
||||
methods.setNodeAttrsFormFieldPerms()
|
||||
},
|
||||
async reqCustomFormPerm(formId, type, defFlowId, flowNodeId) {
|
||||
if (!type) type = DIC_PROP.FORM_DATA_TYPE[1].value
|
||||
// 判断流程实例独立配置
|
||||
let flowInstId = validateRunFlow(props);
|
||||
let resp = await listFormOption({
|
||||
type: type, formType: DIC_PROP.FORM_TYPE[1].value, formId: formId,
|
||||
flowInstId: flowInstId, defFlowId: defFlowId, flowNodeId: flowNodeId
|
||||
}).catch(() => {
|
||||
$message.error("获取系统表单字段权限失败");
|
||||
})
|
||||
return resp.data
|
||||
},
|
||||
async handleCustomFormPerm(formId, type, defFlowId, flowNodeId) {
|
||||
let formFieldPerms = await methods.reqCustomFormPerm(formId, type, defFlowId, flowNodeId)
|
||||
methods.buildCustomFormPerm(formFieldPerms)
|
||||
},
|
||||
buildCustomFormPerm(formFieldPerms) {
|
||||
if (!validateNull(formFieldPerms)) {
|
||||
// 不影响表单设计信息
|
||||
data.formFieldPerms = deepClone(formFieldPerms)
|
||||
methods.setNodeAttrsFormFieldPerms()
|
||||
} else {
|
||||
methods.clearPermData()
|
||||
$message.warning("当前选择的系统表单无字段信息,请先在表单设计中录入")
|
||||
}
|
||||
},
|
||||
resetFormPerm(){
|
||||
let formId = props.currSelect.attributes.attrs.cdata.attrs.formId;
|
||||
if (!formId) {
|
||||
$message.warning("请先选择表单名称")
|
||||
return
|
||||
}
|
||||
methods.clearPermData()
|
||||
let find = props.formIds.find(f => f.id === formId);
|
||||
if (find.type === DIC_PROP.FORM_TYPE[1].value) {
|
||||
if (find.isCurrForm === '1' && !validateNull(find.formFieldPerms)) {
|
||||
methods.buildCustomFormPerm(find.formFieldPerms)
|
||||
} else {
|
||||
methods.handleCustomFormPerm(formId, DIC_PROP.FORM_DATA_TYPE[0].value, null, null)
|
||||
}
|
||||
} else {
|
||||
methods.changeNodeFormId(formId)
|
||||
}
|
||||
},
|
||||
clearPermData() {
|
||||
data.formFieldPerms = []
|
||||
delete props.currSelect.attributes.attrs.cdata.attrs.formFieldPerms
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.initNodeFormId()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
352
src/flow/designer/components/flow-http-param.vue
Normal file
352
src/flow/designer/components/flow-http-param.vue
Normal file
@@ -0,0 +1,352 @@
|
||||
<template>
|
||||
|
||||
<el-divider>请求头</el-divider>
|
||||
<el-table :data="data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[0].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleHttpUrlDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.requestHeader')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp" :placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.paramValType" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.PARAM_VAL_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('jfAttr.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
v-if="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
|
||||
<el-input v-else v-model="scope.row.varKeyVal" clearable> </el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<el-divider>请求参数</el-divider>
|
||||
|
||||
<el-form-item label="参数类型 :">
|
||||
<el-radio-group v-model="data.paramType">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.PARAM_TYPES" :key="index" :label="item.value"
|
||||
style="width: 56px" @change="methods.handleParamType">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content> 表示以指定的【参数类型】传递【请求参数】 </template>
|
||||
<el-icon style="margin-left: 20px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[1].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleHttpUrlDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.requestParam')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp" :placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.paramValType" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.PARAM_VAL_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('jfAttr.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
v-if="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
|
||||
<el-input v-else v-model="scope.row.varKeyVal" clearable> </el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<el-divider>返回值</el-divider>
|
||||
|
||||
<div v-if="props.httpParamType === DIC_PROP.PARAM_RULE_TYPE[0].value" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前Http请求的返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain5 }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="props.httpParamType === DIC_PROP.PARAM_RULE_TYPE[8].value" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前Http请求的返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain6 }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="props.httpParamType === DIC_PROP.PARAM_RULE_TYPE[1].value" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前Http请求的返回值为字符串 1 ( 满足 ) 或 0 ( 不满足 )</span>
|
||||
</div>
|
||||
|
||||
<el-table :data="data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value)"
|
||||
v-if="props.httpParamType !== DIC_PROP.PARAM_RULE_TYPE[0].value && props.httpParamType !== DIC_PROP.PARAM_RULE_TYPE[1].value
|
||||
&& props.httpParamType !== DIC_PROP.PARAM_RULE_TYPE[8].value"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[2].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleHttpUrlDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.returnParam')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp"
|
||||
:placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.paramValType"
|
||||
:active-value="DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
:active-text="DIC_PROP.PARAM_VAL_TYPE[0].label"
|
||||
:inactive-value="DIC_PROP.PARAM_VAL_TYPE[2].value"
|
||||
:inactive-text="DIC_PROP.PARAM_VAL_TYPE[2].label"
|
||||
inline-prompt>
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowHttpParam">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
import {DIC_PROP} from "../../support/dict-prop";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
httpParam: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
httpParamType: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const data = reactive({
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
httpParams: [],
|
||||
paramType: '0',
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
onMounted(async () => {
|
||||
methods.changeTabPane(props.httpParam)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
initParamType() {
|
||||
let find = data.httpParams.find(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
if (find) data.paramType = find.paramType
|
||||
},
|
||||
handleParamType(val) {
|
||||
let splice = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
splice.forEach(each => each.paramType = val)
|
||||
let res = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value);
|
||||
let res2 = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
data.httpParams = splice
|
||||
methods.changeHttpUrlParams()
|
||||
},
|
||||
listFormFieldPerms() {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
},
|
||||
onAddItem(paramFrom, isAdd) {
|
||||
methods.listFormFieldPerms()
|
||||
let value = DIC_PROP.PARAM_VAL_TYPE[0].value;
|
||||
if (data.httpParams.length > 0) {
|
||||
let find = data.httpParams.filter(f => f.paramFrom === paramFrom).find(f => !f.varKeyVal || (f.paramValType !== value && !f.targetProp));
|
||||
if (find) {
|
||||
if (isAdd) {
|
||||
if (!find.varKeyVal) {
|
||||
$message.warning("请先填写 表单字段")
|
||||
return
|
||||
}
|
||||
if (find.paramValType !== value && !find.targetProp) {
|
||||
if (DIC_PROP.PARAM_FROM[0].value === paramFrom) {
|
||||
$message.warning("请先填写 请求头")
|
||||
} else if (DIC_PROP.PARAM_FROM[1].value === paramFrom) {
|
||||
$message.warning("请先填写 请求参数")
|
||||
} else {
|
||||
$message.warning("请先填写 返回值")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.httpParams.splice(0, data.httpParams.length);
|
||||
}
|
||||
let obj = {paramFrom: paramFrom, varKeyVal: null, paramValType: value, targetProp: null};
|
||||
if (paramFrom === DIC_PROP.PARAM_FROM[1].value) {
|
||||
obj.paramType = data.paramType
|
||||
}
|
||||
data.httpParams.push(obj);
|
||||
methods.changeHttpUrlParams()
|
||||
},
|
||||
handleHttpUrlDelete(index: number, row: any) {
|
||||
let splice = data.httpParams.filter(f => f.paramFrom === row.paramFrom);
|
||||
splice.splice(index, 1);
|
||||
if (DIC_PROP.PARAM_FROM[0].value === row.paramFrom) {
|
||||
let res = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
let res2 = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
} else if (DIC_PROP.PARAM_FROM[1].value === row.paramFrom) {
|
||||
let res = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value);
|
||||
let res2 = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
} else if (DIC_PROP.PARAM_FROM[2].value === row.paramFrom) {
|
||||
let res = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value);
|
||||
let res2 = data.httpParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
}
|
||||
data.httpParams = splice
|
||||
methods.changeHttpUrlParams()
|
||||
},
|
||||
validateHttpUrlData() {
|
||||
// 兼容老版本
|
||||
let httpParams = props.httpParam.httpParams;
|
||||
if (!httpParams) {
|
||||
props.httpParam.httpParams = []
|
||||
}
|
||||
data.httpParams = props.httpParam.httpParams
|
||||
},
|
||||
changeHttpUrlParams() {
|
||||
props.httpParam.httpParams = data.httpParams
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateHttpUrlData()
|
||||
methods.listFormFieldPerms()
|
||||
methods.initParamType()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.httpParam,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
360
src/flow/designer/components/flow-method.vue
Normal file
360
src/flow/designer/components/flow-method.vue
Normal file
@@ -0,0 +1,360 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs class="flow-attr"
|
||||
v-model="data.activeKey">
|
||||
<el-tab-pane name="flow-method">
|
||||
<template #label>
|
||||
<div>
|
||||
<el-icon style="vertical-align: middle;margin-right: 3px">
|
||||
<User/>
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle;">选择审批对象</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="170px">
|
||||
|
||||
<div style="margin: 5px 20px">
|
||||
<span style="color: red;font-size: 14px">注: 当前审批对象可自定义任意扩展(只需写好接口即可), 满足您分配参与者复杂的场景</span>
|
||||
</div>
|
||||
|
||||
<el-divider> 审批对象设置 </el-divider>
|
||||
|
||||
<el-form-item label="审批对象类型">
|
||||
<el-radio-group style="width: 283px" @change="methods.handleUserKeyValFrom"
|
||||
v-model="data.userKeyValFrom">
|
||||
<el-radio v-for="(item, index) in DIC_PROP.FLOW_METHOD_TYPE" :key="index" :label="item.value"
|
||||
:disabled="item.value === '-1'">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="data.userKeyValFrom === '0'">
|
||||
<div style="margin-left: 15px">※ 发起人本人将作为审批人</div>
|
||||
</template>
|
||||
|
||||
<template v-if="data.userKeyValFrom === '1'">
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="谁的主管">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.whoseLeader" @change="methods.changeWhoseLeader"
|
||||
clearable filterable
|
||||
remote :remote-method="remoteMethod" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="用于指定哪个用户的部门主管">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="指定主管">
|
||||
<div>
|
||||
<span><{{ data.whoseLeaderName }} 用户>的第  </span>
|
||||
<el-input-number :min="1" :max="20" :step="1" style="width: 150px"
|
||||
v-model="data.leaderLevel"></el-input-number>
|
||||
<span>  级主管</span>
|
||||
<div style="color: #409EFF; font-size: small;">👉 指定主管为 第 {{ data.leaderLevel }} 级主管</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="提取规则">
|
||||
<el-radio-group style="width: 283px"
|
||||
v-model="data.levelExtract">
|
||||
<el-radio v-for="(item, index) in EXTRACTS.SINGLE_EXTRACT" :key="index" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="data.userKeyValFrom === '2'">
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="谁的主管">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.whoseLeader" @change="methods.changeWhoseLeader"
|
||||
clearable filterable
|
||||
remote :remote-method="remoteMethod" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="用于指定哪个用户的部门主管">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="审批终点">
|
||||
<el-radio-group style="width: 200px" v-model="data.auditEndpoint">
|
||||
<el-radio label="0">直到最上层主管</el-radio>
|
||||
<el-radio label="1">不超过<{{ data.whoseLeaderName }} 用户>的</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="audit-endpoint">
|
||||
第 <el-input-number :min="1" :max="20" :step="1" style="width: 80px" controls-position="right"
|
||||
v-model="data.leaderLevel"></el-input-number> 级主管
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="依次审批顺序">
|
||||
<el-tooltip content="当节点属性【多人审批方式】为依次审批时,审批顺序由选择的顺序决定" placement="bottom">
|
||||
<el-radio-group style="width: 200px" v-model="data.seqAuditSort">
|
||||
<el-radio label="0">下级到上级</el-radio>
|
||||
<el-radio label="1">上级到下级</el-radio>
|
||||
</el-radio-group>
|
||||
</el-tooltip>
|
||||
|
||||
<el-button v-if="data.seqAuditSort" text type="primary" icon="delete" @click="data.seqAuditSort = null">
|
||||
清空
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="提取规则">
|
||||
<el-radio-group style="width: 283px"
|
||||
v-model="data.levelExtract">
|
||||
<el-radio v-for="(item, index) in EXTRACTS.MULTI_EXTRACT" :key="index" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tooltip placement="top" content="必须保证最终至少存在一个主管">
|
||||
<el-icon class="audit-endpoint-extract"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="data.userKeyValFrom === '3'">
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="哪个部门">
|
||||
<el-tooltip content="请输入部门名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.appointDeptId"
|
||||
clearable filterable
|
||||
remote :remote-method="remoteMethodDept" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.depts" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.deptId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="用于指定哪个部门的主管">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="提取规则">
|
||||
<el-radio-group style="width: 283px"
|
||||
v-model="data.levelExtract">
|
||||
<el-radio v-for="(item, index) in EXTRACTS.DEPT_EXTRACT" :key="index" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="data.userKeyValFrom === '4'">
|
||||
<el-divider> </el-divider>
|
||||
<el-form-item label="表单字段">
|
||||
<el-select v-model="data.userKeyVal"
|
||||
clearable
|
||||
filterable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.formFieldPerms"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-button
|
||||
type="primary" round style="margin-left: 185px; margin-top: 50px; width: 200px"
|
||||
@click="methods.confirmMethods">
|
||||
确定
|
||||
</el-button>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="flow-rule">
|
||||
<template #label>
|
||||
<div>
|
||||
<el-icon style="vertical-align: middle;margin-right: 3px">
|
||||
<Setting/>
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle;">设置审批规则</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="150px">
|
||||
<flow-user-rule :currSelect="props.currSelect" :currFlowForm="props.currFlowForm" :flowData="props.flowData"></flow-user-rule>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane name="flow-curr-job" v-if="methods.validateNodeJobCurrJob()">
|
||||
<template #label>
|
||||
<div>
|
||||
<el-icon style="vertical-align: middle;margin-right: 3px">
|
||||
<Setting/>
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle;">节点参与者列表</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="150px">
|
||||
<flow-curr-job :currSelect="props.currSelect"></flow-curr-job>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowMethod">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {onFormLoadedUrl, onLoadDicUrl, remoteMethodByKey} from "/@/flow/components/convert-name/convert";
|
||||
import {validateListFormOption} from "../../utils/form-perm";
|
||||
import {parseUserKeyValName, revParseUserKeyValName, revParseWhoseLeaderName} from "./index";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const FlowUserRule = defineAsyncComponent(() => import('./flow-user-rule.vue'));
|
||||
const FlowCurrJob = defineAsyncComponent(() => import('./flow-curr-job.vue'));
|
||||
const $emit = defineEmits(["openFlowMethods"]);
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const EXTRACTS = {
|
||||
SINGLE_EXTRACT: [{
|
||||
label: '无主管时由上级主管代审批',
|
||||
value: '0'
|
||||
}, {
|
||||
label: '无主管时[报错]处理',
|
||||
value: '1'
|
||||
}],
|
||||
MULTI_EXTRACT: [{
|
||||
label: '无主管时由上级主管代审批,直到满足等级的人数',
|
||||
value: '0'
|
||||
}, {
|
||||
label: '无主管时[按空]处理',
|
||||
value: '1'
|
||||
}],
|
||||
DEPT_EXTRACT: [{
|
||||
label: '无主管时由上级主管代审批',
|
||||
value: '0'
|
||||
}, {
|
||||
label: '无主管时[报错]处理',
|
||||
value: '1'
|
||||
}],
|
||||
}
|
||||
const data = reactive({
|
||||
activeKey: 'flow-method',
|
||||
formFieldPerms: [],
|
||||
userKeyValFrom: '1',
|
||||
whoseLeader: null,
|
||||
whoseLeaderName: '请先指定',
|
||||
leaderLevel: 1,
|
||||
auditEndpoint: '0',
|
||||
seqAuditSort: null,
|
||||
levelExtract: '0',
|
||||
appointDeptId: null,
|
||||
userKeyVal: null,
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
const dicData = reactive({});
|
||||
const onLoad = onLoadDicUrl();
|
||||
const onFormLoaded = onFormLoadedUrl({key: "users", field: "whoseLeader"}, {key: "depts", field: "appointDeptId"});
|
||||
onMounted(async () => {
|
||||
// await onLoad(dicData);
|
||||
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
function remoteMethodDept(query: string) {
|
||||
remoteMethodByKey(query, onLoad, dicData, 'deptName', "depts")
|
||||
}
|
||||
|
||||
async function remoteMethod(query: string) {
|
||||
await remoteMethodByKey(query, onLoad, dicData, 'userName', "users")
|
||||
revParseWhoseLeaderName(data, dicData)
|
||||
}
|
||||
|
||||
const methods = {
|
||||
handleUserKeyValFrom(type) {
|
||||
if (type !== '4' || !validateNull(data.formFieldPerms)) return
|
||||
validateListFormOption(data, props, $message)
|
||||
},
|
||||
confirmMethods() {
|
||||
parseUserKeyValName(props, data, methods)
|
||||
$emit("openFlowMethods", false);
|
||||
},
|
||||
$message(type) {
|
||||
if (type === 'whoseLeader') $message.warning('请选择谁的主管');
|
||||
if (type === 'appointDeptId') $message.warning('请选择指定部门');
|
||||
},
|
||||
changeWhoseLeader(userId) {
|
||||
if (!userId) {
|
||||
data.whoseLeaderName = '请先指定'
|
||||
return
|
||||
}
|
||||
data.whoseLeaderName = dicData.users.find(f => f.userId === userId).name;
|
||||
},
|
||||
validateNodeJobCurrJob() {
|
||||
return !validateNull(props.currSelect.attributes) && props.currSelect.attributes.attrs.cdata.defJob
|
||||
&& !validateNull(props.currSelect.attributes.attrs.cdata.defJob.currRunJobs);
|
||||
},
|
||||
async changeTabPane(val) {
|
||||
if (Object.keys(val).length === 0) {
|
||||
data.activeKey = ''
|
||||
return
|
||||
}
|
||||
// 反解析出已配置项
|
||||
await revParseUserKeyValName(props, data, dicData, methods)
|
||||
await onFormLoaded(dicData, data)
|
||||
revParseWhoseLeaderName(data, dicData)
|
||||
},
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (validateNull(val) || Object.keys(val).length === 0) {
|
||||
data.activeKey = ''
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
810
src/flow/designer/components/flow-node-route.vue
Normal file
810
src/flow/designer/components/flow-node-route.vue
Normal file
@@ -0,0 +1,810 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tabs class="flow-attr"
|
||||
v-model="data.activeKey">
|
||||
<el-tab-pane name="flow-rule">
|
||||
<template #label>
|
||||
<div>
|
||||
<el-icon style="vertical-align: middle;margin-right: 3px">
|
||||
<Setting/>
|
||||
</el-icon>
|
||||
<span style="vertical-align: middle;">设置路由规则</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form label-position="left" class="flow-config-attr" label-width="150px">
|
||||
<div style="margin: 5px 15px"><span
|
||||
style="color: red;font-size: 14px">注:可根据接口返回值 或 表单数据的字段值,配置对应的路由动作(可自定义随意扩展)</span>
|
||||
</div>
|
||||
<el-form-item label="条件组关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupsType" @change="methods.changeGroupsType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且" disabled>
|
||||
</el-switch>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>一个组决定一个路由动作。多条件组满足时只有【开启下一节点】和【驳回到其他节点】可以累加路由动作</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="路由规则模式">
|
||||
<el-radio-group style="width: 313px" @change="methods.handleCondValType" :disabled="data.existData"
|
||||
v-model="data.cond.valType">
|
||||
<el-radio v-for="(item, index) in [DIC_PROP.VAL_TYPE[2], DIC_PROP.VAL_TYPE[4], DIC_PROP.VAL_TYPE[5]]" :key="index" :label="item.value"
|
||||
style="width: 75px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>若无法切换模式,请先清空条件组列表</template>
|
||||
<el-icon>
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>组内条件配置</el-divider>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="data.cond.condGroup"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle @click="methods.onAddItem(true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle @click="methods.handleCondDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable
|
||||
filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.operator" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.varValOperator"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.varVal" clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-form-item label="路由动作">
|
||||
<el-select v-model="data.cond.routeAction" @change="methods.changeRouteAction(data.cond)">
|
||||
<el-option v-for="(item, index) in DIC_PROP.ROUTE_ACTIONS" :key="index" :disabled="item.value.indexOf('_define_') !== -1"
|
||||
:label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="路由到哪个节点" v-if="data.cond.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value">
|
||||
<el-select class="input-attr" v-model="data.cond.toFlowNodeId"
|
||||
clearable filterable>
|
||||
<template v-for="(item, index) in data.toFlowNodeIds" :key="index">
|
||||
<el-option :label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
|
||||
<el-tooltip placement="top" content="组内条件满足时,路由到哪个节点(注意:若节点参与者为空,可指定默认的参与者)">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="data.cond.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value">
|
||||
<el-form-item label="参与者类型">
|
||||
<el-tooltip placement="top" content="若节点参与者为空,可指定默认的参与者">
|
||||
<el-select v-model="data.cond.jobType" @change="methods.changeJobType(data.cond)" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个人来审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[0].value">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.cond.roleId"
|
||||
clearable filterable
|
||||
remote :remote-method="methodsRemote.remoteMethodUser2" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users2" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个人来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个角色审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[1].value">
|
||||
<el-tooltip content="请输入角色名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodRole2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.roles2"
|
||||
:key="index"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个角色来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个岗位审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[2].value">
|
||||
<el-tooltip content="请输入岗位名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodPost2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.posts2"
|
||||
:key="index"
|
||||
:label="item.postName"
|
||||
:value="item.postId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个岗位来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个部门审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[3].value">
|
||||
<el-tooltip content="请输入部门名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodDept2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.depts2"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.deptId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个部门审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item label="驳回到哪个节点" v-if="data.cond.routeAction === DIC_PROP.ROUTE_ACTIONS[3].value">
|
||||
<el-select class="input-attr" v-model="data.cond.toFlowNodeId"
|
||||
clearable filterable>
|
||||
<template v-for="(item, index) in data.toFlowNodeIds" :key="index">
|
||||
<el-option :label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
|
||||
<el-tooltip placement="top" content="组内条件满足时,驳回到哪个节点(注意:必须是已审批过的节点)">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
</template>
|
||||
|
||||
<el-form-item label="函数表达式" v-if="data.cond.valType === '2'">
|
||||
<el-input class="input-attr" v-model="data.cond.varKeyVal" placeholder="请输入函数表达式" clearable @blur="methods.handleCondVarKeyVal"/>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>采用表达式取值 ( 以下两种方式均支持自定义任意扩展 ), 值可以为对象 或 数组, 满足您复杂路由的场景:
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condUserExplain }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain3 }}, 返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain6 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain4 }}
|
||||
</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="data.cond.valType === '2'" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前函数表达式的返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain6 }}</span>
|
||||
</div>
|
||||
|
||||
<template v-if="data.cond.valType === '3'">
|
||||
<el-form-item label="Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="data.cond.varKeyVal"
|
||||
@blur="methods.handleCondVarKeyVal" clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="data.cond.httpMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip content="点击可设置Http请求的参数信息" placement="bottom">
|
||||
<el-button type="primary" size="small" round style="margin-left: 10px"
|
||||
@click="methods.openHttpUrlParams()">
|
||||
{{ data.httpUrlParamsVisible ? '清空' : '参数' }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<flow-http-param ref="flowHttpParam" :currFlowForm="props.currFlowForm" :flowData="props.flowData"
|
||||
:httpParam="props.currSelect.attributes.attrs.cdata.attrs"
|
||||
:httpParamType="DIC_PROP.PARAM_RULE_TYPE[8].value"
|
||||
v-if="data.httpUrlParamsVisible"></flow-http-param>
|
||||
</template>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-button type="primary" round style="margin-left: 185px; margin-top: 30px; margin-bottom: 30px; width: 200px" @click="methods.addFlowNodeCondGroup()">
|
||||
{{ data.oldCurrentRow ? '修改完成': '添加条件组' }}
|
||||
</el-button>
|
||||
<el-divider>已添加条件组列表(点击行可再次修改)</el-divider>
|
||||
<el-empty description="条件组列表为空" style="margin: 10px 230px" v-if="!data.existData">
|
||||
</el-empty>
|
||||
|
||||
<template v-for="(item, index) in data.condGroups" v-else
|
||||
:key="index">
|
||||
|
||||
<el-collapse v-model="data.collapse">
|
||||
<el-collapse-item :name="index">
|
||||
<template #title>
|
||||
{{ '条件组 ' + (index + 1) }}
|
||||
|
||||
<el-icon style="margin-left: 10px" @click="methods.handleCondGroupDelete(index)">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</template>
|
||||
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="item.groupType" @change="methods.changeGroupType(item, index)"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="item.condGroup" border style="width: 100%; margin-bottom: 10px" max-height="500"
|
||||
highlight-current-row @current-change="methods.handleCurrentChange" :ref="'tableDataRef' + index">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSingleCondDelete(scope.$index, scope.row, index)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<convert-group-name :options="data.allFieldPerms"
|
||||
:value="scope.row.varKeyVal"
|
||||
:valueKey="'prop'" :showKey="'label'"></convert-group-name>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="DIC_PROP.OPERATOR" :value="scope.row.operator"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
|
||||
<el-form-item label="路由动作">
|
||||
<el-select v-model="item.routeAction" @change="methods.changeRouteAction(item)">
|
||||
<el-option v-for="(item, index) in DIC_PROP.ROUTE_ACTIONS" :key="index" :disabled="item.value.indexOf('_define_') !== -1"
|
||||
:label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="路由到哪个节点" v-if="item.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value">
|
||||
<el-select class="input-attr" v-model="item.toFlowNodeId"
|
||||
clearable filterable>
|
||||
<template v-for="(item, index) in data.toFlowNodeIds" :key="index">
|
||||
<el-option :label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
|
||||
<el-tooltip placement="top" content="组内条件满足时,路由到哪个节点(注意:若节点参与者为空,可指定默认的参与者)">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="item.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value">
|
||||
<el-form-item label="参与者类型">
|
||||
<el-tooltip placement="top" content="若节点参与者为空,可指定默认的参与者">
|
||||
<el-select v-model="item.jobType" @change="methods.changeJobType(item)" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个人来审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[0].value">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="item.roleId"
|
||||
clearable filterable
|
||||
remote :remote-method="methodsRemote.remoteMethodUser" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个人来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个角色审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[1].value">
|
||||
<el-tooltip content="请输入角色名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodRole" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.roles"
|
||||
:key="index"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个角色来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个岗位审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[2].value">
|
||||
<el-tooltip content="请输入岗位名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodPost" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.posts"
|
||||
:key="index"
|
||||
:label="item.postName"
|
||||
:value="item.postId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个岗位来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个部门审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[3].value">
|
||||
<el-tooltip content="请输入部门名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodDept" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.depts"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.deptId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个部门审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item label="驳回到哪个节点" v-if="item.routeAction === DIC_PROP.ROUTE_ACTIONS[3].value">
|
||||
<el-select class="input-attr" v-model="item.toFlowNodeId"
|
||||
clearable filterable>
|
||||
<template v-for="(item, index) in data.toFlowNodeIds" :key="index">
|
||||
<el-option :label="item.nodeName"
|
||||
:value="item.id">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
|
||||
<el-tooltip placement="top" content="组内条件满足时,驳回到哪个节点(注意:必须是已审批过的节点)">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
</template>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowMethod">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {rule, validateNull} from "/@/utils/validate";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
import {DIC_PROP} from "/@/flow/support/dict-prop";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
import {
|
||||
onFormLoadedUrl,
|
||||
onLoadDicUrl,
|
||||
initRemoteMethodAllByKey
|
||||
} from "../../components/convert-name/convert";
|
||||
import {PROP_CONST} from "../../support/prop-const";
|
||||
import {handleChangeJobType} from "../../index";
|
||||
import {validateNodeType} from "./index";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const FlowHttpParam = defineAsyncComponent(() => import('./flow-http-param.vue'));
|
||||
const $emit = defineEmits(["openFlowRoutes"]);
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const condData = {
|
||||
httpMethod: 'GET',
|
||||
roleId: null,
|
||||
jobType: null,
|
||||
routeAction: null,
|
||||
toFlowNodeId: null,
|
||||
groupsType: '1',
|
||||
condGroup: [],
|
||||
groupType: '0',
|
||||
valType: '0',
|
||||
varKeyVal: null,
|
||||
operator: null,
|
||||
varVal: null,
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
activeKey: 'flow-rule',
|
||||
collapse: [0],
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
cond: deepClone(condData),
|
||||
httpUrlParamsVisible: false,
|
||||
oldCurrentRow: null,
|
||||
condGroups: [],
|
||||
toFlowNodeIds: [],
|
||||
existData: false,
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
const dicData = reactive({});
|
||||
const onLoad = onLoadDicUrl();
|
||||
const onFormLoaded = onFormLoadedUrl(...PROP_CONST.LOAD_USER_ROLE);
|
||||
onMounted(async () => {
|
||||
// await onLoad(dicData);
|
||||
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methodsRemote = initRemoteMethodAllByKey(onLoad, dicData)
|
||||
|
||||
const methods = {
|
||||
changeJobType(item) {
|
||||
handleChangeJobType(dicData, item)
|
||||
},
|
||||
onFormLoaded() {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups
|
||||
if (validateNull(condGroups)) return
|
||||
onFormLoaded(dicData, condGroups)
|
||||
},
|
||||
changeRouteAction(item) {
|
||||
// 切换清空
|
||||
let b = item.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value;
|
||||
if(!b && item.routeAction !== DIC_PROP.ROUTE_ACTIONS[3].value) {
|
||||
data.cond.toFlowNodeId = null
|
||||
}
|
||||
},
|
||||
openHttpUrlParams() {
|
||||
if (!data.cond.varKeyVal) {
|
||||
$message.warning("请先输入【Http请求地址】")
|
||||
return
|
||||
}
|
||||
if (data.httpUrlParamsVisible) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpParams = []
|
||||
data.httpUrlParamsVisible = false
|
||||
} else {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
if (!row) return
|
||||
let condGroupsRow;
|
||||
for (let i = 0; i < data.condGroups.length; i++) {
|
||||
let index = data.condGroups[i].condGroup.indexOf(row);
|
||||
if (index !== -1) {
|
||||
condGroupsRow = data.condGroups[i];
|
||||
}
|
||||
}
|
||||
// 先清空之前选中的其他条件组
|
||||
if (data.oldCurrentRow !== condGroupsRow) {
|
||||
let oldIndex = data.condGroups.indexOf(data.oldCurrentRow);
|
||||
if (oldIndex !== -1) {
|
||||
proxy.$refs['tableDataRef' + oldIndex][0].setCurrentRow(null)
|
||||
}
|
||||
}
|
||||
data.cond = condGroupsRow
|
||||
data.oldCurrentRow = condGroupsRow
|
||||
},
|
||||
handleVarKeyVal(row) {
|
||||
let dots = row.varKeyVal.split('.').length - 1;
|
||||
if (dots === 2) {
|
||||
let find = DIC_PROP.OPERATOR.slice(6).find(f => f.value === row.operator);
|
||||
if (!find && row.operator) {
|
||||
$message.warning("子表单的字段只能选择包含或不包含")
|
||||
row.operator = null
|
||||
}
|
||||
}
|
||||
},
|
||||
changeGroupsType(groupsType) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.forEach(each => {
|
||||
each.groupsType = groupsType
|
||||
})
|
||||
methods.validateCondData()
|
||||
},
|
||||
changeGroupType(item, index) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups[index].groupType = item.groupType
|
||||
methods.validateCondData()
|
||||
},
|
||||
onAddItem(isAdd) {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
if (data.cond.condGroup.length > 0) {
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
let b = !find.varKeyVal || !find.operator || !find.varVal;
|
||||
if (isAdd && b) {
|
||||
$message.warning("请先填写 表单字段 或 运算符 或 值")
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.cond.condGroup.splice(0, data.cond.condGroup.length);
|
||||
}
|
||||
let obj = {varKeyVal: '', operator: '', varVal: ''};
|
||||
data.cond.condGroup.push(obj);
|
||||
},
|
||||
addFlowNodeCondGroup() {
|
||||
if (validateNull(data.cond.condGroup)) {
|
||||
$message.warning("请先添加组内条件")
|
||||
return
|
||||
}
|
||||
let valType = data.cond.valType;
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
if (!find.varKeyVal || !find.operator || !find.varVal) {
|
||||
$message.warning("表单字段 或 运算符 或 值 不能为空")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!methods.validateCondGroupAttrs()) return;
|
||||
if (data.oldCurrentRow) {
|
||||
// 先清空之前选中
|
||||
let index = data.condGroups.indexOf(data.cond);
|
||||
if (index !== -1) {
|
||||
proxy.$refs['tableDataRef' + index][0].setCurrentRow(null)
|
||||
}
|
||||
data.oldCurrentRow = null
|
||||
data.cond = deepClone(condData);
|
||||
} else {
|
||||
let cond = deepClone(data.cond);
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.push(cond)
|
||||
methods.validateCondData()
|
||||
methods.updateCondVarKeyVal(true)
|
||||
}
|
||||
methods.onFormLoaded()
|
||||
},
|
||||
validateCondGroupAttrs() {
|
||||
if (!data.cond.routeAction) {
|
||||
$message.warning("路由动作 不能为空")
|
||||
return false
|
||||
}
|
||||
// 校验动作类型参数
|
||||
let b = data.cond.routeAction === DIC_PROP.ROUTE_ACTIONS[1].value;
|
||||
if(b || data.cond.routeAction === DIC_PROP.ROUTE_ACTIONS[3].value) {
|
||||
if (!data.cond.toFlowNodeId) {
|
||||
$message.warning("路由到哪个节点 不能为空")
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
handleCondGroupDelete(index: number) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.splice(index, 1)
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleSingleCondDelete(index: number, row: any, groupIndex) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups[groupIndex].condGroup.splice(index, 1)
|
||||
if (validateNull(props.currSelect.attributes.attrs.cdata.attrs.condGroups[groupIndex].condGroup)) {
|
||||
methods.handleCondGroupDelete(groupIndex)
|
||||
}
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleCondDelete(index: number, row: any) {
|
||||
data.cond.condGroup.splice(index, 1)
|
||||
},
|
||||
handleCondValType(type?) {
|
||||
if (type) {
|
||||
data.cond.varKeyVal = null
|
||||
methods.updateCondVarKeyVal(false)
|
||||
}
|
||||
if (!type) {
|
||||
type = methods.initCurrVarKeyVal()
|
||||
}
|
||||
if (type === DIC_PROP.VAL_TYPE[2].value) {
|
||||
data.varValOperator = DIC_PROP.OPERATOR
|
||||
methods.onAddItem(false)
|
||||
} else {
|
||||
data.varValOperator = []
|
||||
}
|
||||
data.cond.operator = null
|
||||
data.cond.varVal = null
|
||||
},
|
||||
handleCondVarKeyVal() {
|
||||
let val = data.cond.varKeyVal
|
||||
let valType = data.cond.valType;
|
||||
if (!val) {
|
||||
methods.updateCondVarKeyVal(false)
|
||||
return
|
||||
}
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) return
|
||||
if (valType === DIC_PROP.VAL_TYPE[4].value && val.indexOf("#") === -1) {
|
||||
data.cond.varKeyVal = null
|
||||
$message.warning("当选择专业模式时, 函数表达式必须符合规定的格式")
|
||||
return;
|
||||
}
|
||||
methods.updateCondVarKeyVal(true)
|
||||
},
|
||||
updateCondVarKeyVal(isSave) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.valType = data.cond.valType
|
||||
if (isSave) {
|
||||
if (data.cond.valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.routeKeyVal = PROP_CONST.VAR_KEY_VAL.route
|
||||
props.currSelect.attributes.attrs.cdata.attrs.routeKeyValName = PROP_CONST.VAR_KEY_VAL.routeName
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.routeKeyVal = data.cond.varKeyVal
|
||||
}
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpMethod = data.cond.httpMethod
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.routeKeyVal = null
|
||||
props.currSelect.attributes.attrs.cdata.attrs.routeKeyValName = null
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups = []
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpParams = []
|
||||
props.currSelect.attributes.attrs.cdata.attrs.httpMethod = null
|
||||
data.httpUrlParamsVisible = false
|
||||
}
|
||||
},
|
||||
validateCondData() {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.attrs.condGroups;
|
||||
if (!condGroups) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups = []
|
||||
}
|
||||
data.condGroups.splice(0, data.condGroups.length);
|
||||
props.currSelect.attributes.attrs.cdata.attrs.condGroups.forEach(each => data.condGroups.push(each))
|
||||
data.existData = !validateNull(data.condGroups)
|
||||
},
|
||||
initCurrVarKeyVal() {
|
||||
data.cond.valType = props.currSelect.attributes.attrs.cdata.attrs.valType
|
||||
if (data.condGroups.length <= 0) {
|
||||
data.cond.varKeyVal = props.currSelect.attributes.attrs.cdata.attrs.routeKeyVal
|
||||
let httpMethod = props.currSelect.attributes.attrs.cdata.attrs.httpMethod
|
||||
if (httpMethod) data.cond.httpMethod = httpMethod
|
||||
}
|
||||
let httpParams = props.currSelect.attributes.attrs.cdata.attrs.httpParams;
|
||||
if (!validateNull(httpParams)) {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
return data.cond.valType
|
||||
},
|
||||
handleFlowNodeIds() {
|
||||
data.toFlowNodeIds = []
|
||||
let models = window._jfGraph.getElements();
|
||||
if (validateNull(models)) return
|
||||
models.forEach(each => {
|
||||
if (!validateNodeType(each)) return
|
||||
if (props.currSelect.id !== each.id) {
|
||||
let id = each.id
|
||||
let nodeName = each.attributes.attrs.label.text
|
||||
data.toFlowNodeIds.push({id, nodeName})
|
||||
}
|
||||
})
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateCondData()
|
||||
methods.handleCondValType()
|
||||
methods.handleFlowNodeIds()
|
||||
methods.onFormLoaded()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
361
src/flow/designer/components/flow-sub-param.vue
Normal file
361
src/flow/designer/components/flow-sub-param.vue
Normal file
@@ -0,0 +1,361 @@
|
||||
<template>
|
||||
<el-form label-position="left" class="flow-attr flow-param-attr" label-width="200px">
|
||||
|
||||
<el-divider>关联子流程Http接口</el-divider>
|
||||
|
||||
<el-form-item label="保存子流程表单Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="props.currSelect.attributes.attrs.cdata.attrs.startSubFlow"
|
||||
clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="props.currSelect.attributes.attrs.cdata.attrs.startSubMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>启动子流程时更新子流程表单接口(可输入全路径或相对路径)</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新子流程表单Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="props.currSelect.attributes.attrs.cdata.attrs.restartSubFlow"
|
||||
clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="props.currSelect.attributes.attrs.cdata.attrs.restartSubMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>重入或重启子流程时更新子流程表单接口(可输入全路径或相对路径)</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新父流程表单Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="props.currSelect.attributes.attrs.cdata.attrs.backParFlow"
|
||||
clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="props.currSelect.attributes.attrs.cdata.attrs.backParMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>返回父流程时更新父流程表单接口(可输入全路径或相对路径)</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>关联子流程Http请求头</el-divider>
|
||||
|
||||
<el-table :data="data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[0].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSubFlowDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.requestHeader')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp" :placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.paramValType" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.PARAM_VAL_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('jfAttr.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
v-if="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
|
||||
<el-input v-else v-model="scope.row.varKeyVal" clearable> </el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<el-divider>父流程传参到子流程</el-divider>
|
||||
|
||||
<el-table :data="data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[1].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSubFlowDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('jfAttr.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
v-if="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
|
||||
<el-input v-else v-model="scope.row.varKeyVal" clearable> </el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.paramValType" clearable>
|
||||
<el-option v-for="(item, index) in DIC_PROP.PARAM_VAL_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.subVarKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp" :placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-divider>子流程回参到父流程</el-divider>
|
||||
|
||||
<el-table :data="data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value)"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" :label="t('jfI18n.operate')" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle
|
||||
@click="methods.onAddItem(DIC_PROP.PARAM_FROM[2].value, true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSubFlowDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="targetProp" :label="t('jfAttr.subVarKeyVal2')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.targetProp"
|
||||
:placeholder="scope.row.paramValType === DIC_PROP.PARAM_VAL_TYPE[0].value ? scope.row.varKeyVal : null"
|
||||
clearable></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="paramValType" :label="t('jfAttr.paramValType')" width="145px">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.paramValType"
|
||||
:active-value="DIC_PROP.PARAM_VAL_TYPE[0].value"
|
||||
:active-text="DIC_PROP.PARAM_VAL_TYPE[0].label"
|
||||
:inactive-value="DIC_PROP.PARAM_VAL_TYPE[2].value"
|
||||
:inactive-text="DIC_PROP.PARAM_VAL_TYPE[2].label"
|
||||
inline-prompt>
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal"
|
||||
clearable filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowSubParam">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
import {DIC_PROP} from "../../support/dict-prop";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const data = reactive({
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
subFlowParams: [],
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
onMounted(async () => {
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methods = {
|
||||
listFormFieldPerms() {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
},
|
||||
onAddItem(paramFrom, isAdd) {
|
||||
methods.listFormFieldPerms()
|
||||
let value = DIC_PROP.PARAM_VAL_TYPE[0].value;
|
||||
if (data.subFlowParams.length > 0) {
|
||||
let find = data.subFlowParams.filter(f => f.paramFrom === paramFrom).find(f => !f.varKeyVal || (f.paramValType !== value && !f.targetProp));
|
||||
if (find) {
|
||||
if (isAdd) {
|
||||
if (!find.varKeyVal) {
|
||||
$message.warning("请先填写 表单字段")
|
||||
return
|
||||
}
|
||||
if (find.paramValType !== value && !find.targetProp) {
|
||||
if (DIC_PROP.PARAM_FROM[0].value === paramFrom) {
|
||||
$message.warning("请先填写 请求头")
|
||||
} else {
|
||||
$message.warning("请先填写 子流程表单字段")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.subFlowParams.splice(0, data.subFlowParams.length);
|
||||
}
|
||||
let obj = {paramFrom: paramFrom, varKeyVal: null, paramValType: value, targetProp: null};
|
||||
data.subFlowParams.push(obj);
|
||||
methods.changeSubFlowParams()
|
||||
},
|
||||
handleSubFlowDelete(index: number, row: any) {
|
||||
let splice = data.subFlowParams.filter(f => f.paramFrom === row.paramFrom);
|
||||
splice.splice(index, 1);
|
||||
if (DIC_PROP.PARAM_FROM[0].value === row.paramFrom) {
|
||||
let res = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
let res2 = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
} else if (DIC_PROP.PARAM_FROM[1].value === row.paramFrom) {
|
||||
let res = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value);
|
||||
let res2 = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[2].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
} else if (DIC_PROP.PARAM_FROM[2].value === row.paramFrom) {
|
||||
let res = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[0].value);
|
||||
let res2 = data.subFlowParams.filter(f => f.paramFrom === DIC_PROP.PARAM_FROM[1].value);
|
||||
splice.push(...res)
|
||||
splice.push(...res2)
|
||||
}
|
||||
data.subFlowParams = splice
|
||||
methods.changeSubFlowParams()
|
||||
},
|
||||
validateSubFlowData() {
|
||||
// 兼容老版本
|
||||
let subFlowParams = props.currSelect.attributes.attrs.cdata.attrs.subFlowParams;
|
||||
if (!subFlowParams) {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.subFlowParams = []
|
||||
}
|
||||
let startSubMethod = props.currSelect.attributes.attrs.cdata.attrs.startSubMethod;
|
||||
if (!startSubMethod) props.currSelect.attributes.attrs.cdata.attrs.startSubMethod = 'POST'
|
||||
let restartSubMethod = props.currSelect.attributes.attrs.cdata.attrs.restartSubMethod;
|
||||
if (!restartSubMethod) props.currSelect.attributes.attrs.cdata.attrs.restartSubMethod = 'PUT'
|
||||
let backParMethod = props.currSelect.attributes.attrs.cdata.attrs.backParMethod;
|
||||
if (!backParMethod) props.currSelect.attributes.attrs.cdata.attrs.backParMethod = 'PUT'
|
||||
|
||||
data.subFlowParams = props.currSelect.attributes.attrs.cdata.attrs.subFlowParams
|
||||
},
|
||||
changeSubFlowParams() {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.subFlowParams = data.subFlowParams
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateSubFlowData()
|
||||
methods.listFormFieldPerms()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
666
src/flow/designer/components/flow-user-rule.vue
Normal file
666
src/flow/designer/components/flow-user-rule.vue
Normal file
@@ -0,0 +1,666 @@
|
||||
<template>
|
||||
<el-form-item label="条件组关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupsType" @change="methods.changeGroupsType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且" disabled>
|
||||
</el-switch>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>一个组决定一个参与者。多条件组满足则累加参与者</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="审批规则模式">
|
||||
<el-radio-group style="width: 313px" @change="methods.handleCondValType" :disabled="data.existData"
|
||||
v-model="data.cond.valType">
|
||||
<el-radio v-for="(item, index) in [DIC_PROP.VAL_TYPE[2], DIC_PROP.VAL_TYPE[4], DIC_PROP.VAL_TYPE[5]]" :key="index" :label="item.value"
|
||||
style="width: 75px">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-tooltip placement="top">
|
||||
<template #content>若无法切换模式,请先清空条件组列表</template>
|
||||
<el-icon>
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider>组内条件配置</el-divider>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="data.cond.groupType"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="data.cond.condGroup"
|
||||
border style="width: 100%; margin-bottom: 10px" max-height="500">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #header>
|
||||
<el-button icon="Plus" size="small" type="primary" circle @click="methods.onAddItem(true)"></el-button>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle @click="methods.handleCondDelete(scope.$index, scope.row)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.varKeyVal" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable
|
||||
filterable>
|
||||
<el-option-group
|
||||
v-for="(group, index) in data.allFieldPerms"
|
||||
:key="index"
|
||||
:label="group.label">
|
||||
<el-option
|
||||
v-for="(item, index) in group.options"
|
||||
:disabled="item.prop.indexOf('_define_') !== -1"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.prop">
|
||||
</el-option>
|
||||
</el-option-group>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.operator" @change="methods.handleVarKeyVal(scope.row)"
|
||||
clearable>
|
||||
<el-option
|
||||
v-for="(item, index) in data.varValOperator"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
:value="item.value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.varVal" clearable/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-form-item label="参与者类型">
|
||||
<el-select v-model="data.cond.jobType" @change="methods.changeJobType(data.cond)">
|
||||
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个人来审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[0].value">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="data.cond.roleId"
|
||||
clearable filterable
|
||||
remote :remote-method="methodsRemote.remoteMethodUser2" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users2" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个人来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个角色审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[1].value">
|
||||
<el-tooltip content="请输入角色名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodRole2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.roles2"
|
||||
:key="index"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个角色来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个岗位审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[2].value">
|
||||
<el-tooltip content="请输入岗位名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodPost2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.posts2"
|
||||
:key="index"
|
||||
:label="item.postName"
|
||||
:value="item.postId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个岗位来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个部门审批" v-if="data.cond.jobType === DIC_PROP.JOB_USER_TYPE[3].value">
|
||||
<el-tooltip content="请输入部门名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="data.cond.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodDept2" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.depts2"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.deptId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个部门审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
</template>
|
||||
|
||||
<el-form-item label="函数表达式" v-if="data.cond.valType === '2'">
|
||||
<el-input class="input-attr" v-model="data.cond.varKeyVal" placeholder="请输入函数表达式" clearable @blur="methods.handleCondVarKeyVal"/>
|
||||
|
||||
<el-tooltip placement="top">
|
||||
<template #content>采用表达式取值 ( 以下两种方式均支持自定义任意扩展 ), 值可以为对象 或 数组, 满足您分配参与者复杂的场景:
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condUserExplain }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain3 }}, 返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain5 }}
|
||||
<br />{{ PROP_CONST.TEXT_DESC.condMethodExplain4 }}
|
||||
</template>
|
||||
<el-icon style="margin-left: 10px">
|
||||
<QuestionFilled/>
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<div v-if="data.cond.valType === '2'" style="margin: 10px 13px">
|
||||
<span style="color: #409EFF;font-size: 14px">注: 当前函数表达式的返回值可以为对象 或 数组,{{ PROP_CONST.TEXT_DESC.condMethodExplain5 }}</span>
|
||||
</div>
|
||||
|
||||
<template v-if="data.cond.valType === '3'">
|
||||
<el-form-item label="Http请求地址">
|
||||
<el-input class="input-attr" placeholder="可输入全路径或相对路径" v-model="data.cond.varKeyVal"
|
||||
@blur="methods.handleCondVarKeyVal" clearable>
|
||||
<template #prepend>
|
||||
<el-select v-model="data.cond.httpMethod">
|
||||
<el-option v-for="(item, index) in DIC_PROP.HTTP_METHODS" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-tooltip content="点击可设置Http请求的参数信息" placement="bottom">
|
||||
<el-button type="primary" size="small" round style="margin-left: 10px"
|
||||
@click="methods.openHttpUrlParams()">
|
||||
{{ data.httpUrlParamsVisible ? '清空' : '参数' }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<flow-http-param ref="flowHttpParam" :currFlowForm="props.currFlowForm" :flowData="props.flowData"
|
||||
:httpParam="props.currSelect.attributes.attrs.cdata.defJob"
|
||||
:httpParamType="DIC_PROP.PARAM_RULE_TYPE[0].value"
|
||||
v-if="data.httpUrlParamsVisible"></flow-http-param>
|
||||
</template>
|
||||
|
||||
<template v-if="data.cond.valType === '0'">
|
||||
<el-tooltip content="当节点属性【多人审批方式】为依次审批时,审批顺序由下方条件组的顺序决定" placement="bottom">
|
||||
<el-button type="primary" round style="margin-left: 185px; margin-top: 30px; margin-bottom: 30px; width: 200px" @click="methods.addFlowNodeCondGroup()">
|
||||
{{ data.oldCurrentRow ? '修改完成': '添加条件组' }}
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-divider>已添加条件组列表(点击行可再次修改)</el-divider>
|
||||
<el-empty description="条件组列表为空" style="margin: 10px 230px" v-if="!data.existData">
|
||||
</el-empty>
|
||||
|
||||
<template v-for="(item, index) in data.condGroups" v-else
|
||||
:key="index">
|
||||
|
||||
<el-collapse v-model="data.collapse">
|
||||
<el-collapse-item :name="index">
|
||||
<template #title>
|
||||
{{ '条件组 ' + (index + 1) }}
|
||||
|
||||
<el-icon style="margin-left: 10px" @click="methods.handleCondGroupDelete(index)">
|
||||
<Delete />
|
||||
</el-icon>
|
||||
</template>
|
||||
|
||||
<el-form-item label="组内条件关系">
|
||||
<el-switch
|
||||
v-model="item.groupType" @change="methods.changeGroupType(item, index)"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
inactive-text="或"
|
||||
active-text="且">
|
||||
</el-switch>
|
||||
</el-form-item>
|
||||
|
||||
<el-table :data="item.condGroup" border style="width: 100%; margin-bottom: 10px" max-height="500"
|
||||
highlight-current-row @current-change="methods.handleCurrentChange" :ref="'tableDataRef' + index">
|
||||
|
||||
<el-table-column type="index" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button icon="Minus" size="small" type="danger" circle
|
||||
@click="methods.handleSingleCondDelete(scope.$index, scope.row, index)"></el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varKeyVal" :label="t('flowClazz.varKeyVal')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<convert-group-name :options="data.allFieldPerms"
|
||||
:value="scope.row.varKeyVal"
|
||||
:valueKey="'prop'" :showKey="'label'"></convert-group-name>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="operator" :label="t('flowClazz.operator')" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="DIC_PROP.OPERATOR" :value="scope.row.operator"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="varVal" :label="t('flowClazz.varVal')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
|
||||
<el-form-item label="参与者类型">
|
||||
<el-select v-model="item.jobType" @change="methods.changeJobType(item)">
|
||||
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个人来审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[0].value">
|
||||
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr"
|
||||
v-model="item.roleId"
|
||||
clearable filterable
|
||||
remote :remote-method="methodsRemote.remoteMethodUser" :reserve-keyword="false">
|
||||
<template v-for="(item, index) in dicData.users" :key="index">
|
||||
<el-option :label="item.name"
|
||||
:value="item.userId">
|
||||
</el-option>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个人来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个角色审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[1].value">
|
||||
<el-tooltip content="请输入角色名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodRole" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.roles"
|
||||
:key="index"
|
||||
:label="item.roleName"
|
||||
:value="item.roleId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个角色来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个岗位审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[2].value">
|
||||
<el-tooltip content="请输入岗位名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodPost" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.posts"
|
||||
:key="index"
|
||||
:label="item.postName"
|
||||
:value="item.postId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个岗位来审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="哪个部门审批" v-if="item.jobType === DIC_PROP.JOB_USER_TYPE[3].value">
|
||||
<el-tooltip content="请输入部门名称进行模糊搜索" placement="top">
|
||||
<el-select class="input-attr" v-model="item.roleId"
|
||||
filterable
|
||||
clearable
|
||||
remote :remote-method="methodsRemote.remoteMethodDept" :reserve-keyword="false">
|
||||
<el-option
|
||||
v-for="(item, index) in dicData.depts"
|
||||
:key="index"
|
||||
:label="item.name"
|
||||
:value="item.deptId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-tooltip placement="top" content="组内条件满足时,由哪个部门审批">
|
||||
<el-icon style="margin-left: 10px"><QuestionFilled /></el-icon>
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="FlowUserRule">
|
||||
import {useI18n} from "vue-i18n";
|
||||
import {useMessage} from "/@/hooks/message";
|
||||
import {rule, validateNull} from "/@/utils/validate";
|
||||
import {deepClone} from "/@/utils/other";
|
||||
import {DIC_PROP} from "/@/flow/support/dict-prop";
|
||||
import {buildSysFieldsFormOption} from "../../utils/form-perm";
|
||||
import {onFormLoadedUrl, onLoadDicUrl, initRemoteMethodAllByKey} from "../../components/convert-name/convert";
|
||||
import {PROP_CONST} from "../../support/prop-const";
|
||||
import {handleChangeJobType} from "../../index";
|
||||
|
||||
const {proxy} = getCurrentInstance();
|
||||
const FlowHttpParam = defineAsyncComponent(() => import('./flow-http-param.vue'));
|
||||
|
||||
const {t} = useI18n();
|
||||
const $message = useMessage();
|
||||
const props = defineProps({
|
||||
currFlowForm: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
currSelect: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const condData = {
|
||||
httpMethod: 'GET',
|
||||
roleId: null,
|
||||
jobType: null,
|
||||
groupsType: '1',
|
||||
condGroup: [],
|
||||
groupType: '0',
|
||||
valType: '0',
|
||||
varKeyVal: null,
|
||||
operator: null,
|
||||
varVal: null,
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
collapse: [0],
|
||||
allFieldPerms: [],
|
||||
formFieldPerms: [],
|
||||
cond: deepClone(condData),
|
||||
httpUrlParamsVisible: false,
|
||||
oldCurrentRow: null,
|
||||
condGroups: [],
|
||||
existData: false
|
||||
})
|
||||
|
||||
// 定义字典
|
||||
const dicData = reactive({});
|
||||
const onLoad = onLoadDicUrl();
|
||||
const onFormLoaded = onFormLoadedUrl(...PROP_CONST.LOAD_USER_ROLE);
|
||||
onMounted(async () => {
|
||||
// await onLoad(dicData);
|
||||
|
||||
methods.changeTabPane(props.currSelect)
|
||||
})
|
||||
|
||||
const methodsRemote = initRemoteMethodAllByKey(onLoad, dicData)
|
||||
|
||||
const methods = {
|
||||
changeJobType(item) {
|
||||
handleChangeJobType(dicData, item)
|
||||
},
|
||||
onFormLoaded() {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.defJob.condGroups
|
||||
if (validateNull(condGroups)) return
|
||||
onFormLoaded(dicData, condGroups)
|
||||
},
|
||||
openHttpUrlParams() {
|
||||
if (!data.cond.varKeyVal) {
|
||||
$message.warning("请先输入【Http请求地址】")
|
||||
return
|
||||
}
|
||||
if (data.httpUrlParamsVisible) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpParams = []
|
||||
data.httpUrlParamsVisible = false
|
||||
} else {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
},
|
||||
handleCurrentChange(row) {
|
||||
if (!row) return
|
||||
let condGroupsRow;
|
||||
for (let i = 0; i < data.condGroups.length; i++) {
|
||||
let index = data.condGroups[i].condGroup.indexOf(row);
|
||||
if (index !== -1) {
|
||||
condGroupsRow = data.condGroups[i];
|
||||
}
|
||||
}
|
||||
// 先清空之前选中的其他条件组
|
||||
if (data.oldCurrentRow !== condGroupsRow) {
|
||||
let oldIndex = data.condGroups.indexOf(data.oldCurrentRow);
|
||||
if (oldIndex !== -1) {
|
||||
proxy.$refs['tableDataRef' + oldIndex][0].setCurrentRow(null)
|
||||
}
|
||||
}
|
||||
data.cond = condGroupsRow
|
||||
data.oldCurrentRow = condGroupsRow
|
||||
},
|
||||
handleVarKeyVal(row) {
|
||||
let dots = row.varKeyVal.split('.').length - 1;
|
||||
if (dots === 2) {
|
||||
let find = DIC_PROP.OPERATOR.slice(6).find(f => f.value === row.operator);
|
||||
if (!find && row.operator) {
|
||||
$message.warning("子表单的字段只能选择包含或不包含")
|
||||
row.operator = null
|
||||
}
|
||||
}
|
||||
},
|
||||
changeGroupsType(groupsType) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.defJob.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups.forEach(each => {
|
||||
each.groupsType = groupsType
|
||||
})
|
||||
methods.validateCondData()
|
||||
},
|
||||
changeGroupType(item, index) {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.defJob.condGroups;
|
||||
if (validateNull(condGroups)) return
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups[index].groupType = item.groupType
|
||||
methods.validateCondData()
|
||||
},
|
||||
onAddItem(isAdd) {
|
||||
if (validateNull(data.formFieldPerms)) {
|
||||
buildSysFieldsFormOption(data, props, $message)
|
||||
}
|
||||
if (data.cond.condGroup.length > 0) {
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
let b = !find.varKeyVal || !find.operator || !find.varVal;
|
||||
if (isAdd && b) {
|
||||
$message.warning("请先填写 表单字段 或 运算符 或 值")
|
||||
return
|
||||
}
|
||||
}
|
||||
if (!isAdd) data.cond.condGroup.splice(0, data.cond.condGroup.length);
|
||||
}
|
||||
let obj = {varKeyVal: '', operator: '', varVal: ''};
|
||||
data.cond.condGroup.push(obj);
|
||||
},
|
||||
addFlowNodeCondGroup() {
|
||||
if (validateNull(data.cond.condGroup)) {
|
||||
$message.warning("请先添加组内条件")
|
||||
return
|
||||
}
|
||||
let valType = data.cond.valType;
|
||||
let find = data.cond.condGroup.find(f => !f.varKeyVal || !f.operator || !f.varVal);
|
||||
if (find) {
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
if (!find.varKeyVal || !find.operator || !find.varVal) {
|
||||
$message.warning("表单字段 或 运算符 或 值 不能为空")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data.cond.roleId) {
|
||||
$message.warning("参与者 不能为空")
|
||||
return
|
||||
}
|
||||
if (data.oldCurrentRow) {
|
||||
// 先清空之前选中
|
||||
let index = data.condGroups.indexOf(data.cond);
|
||||
if (index !== -1) {
|
||||
proxy.$refs['tableDataRef' + index][0].setCurrentRow(null)
|
||||
}
|
||||
data.oldCurrentRow = null
|
||||
data.cond = deepClone(condData);
|
||||
} else {
|
||||
let cond = deepClone(data.cond);
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups.push(cond)
|
||||
methods.validateCondData()
|
||||
methods.updateCondVarKeyVal(true)
|
||||
}
|
||||
methods.onFormLoaded()
|
||||
},
|
||||
handleCondGroupDelete(index: number) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups.splice(index, 1)
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleSingleCondDelete(index: number, row: any, groupIndex) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups[groupIndex].condGroup.splice(index, 1)
|
||||
if (validateNull(props.currSelect.attributes.attrs.cdata.defJob.condGroups[groupIndex].condGroup)) {
|
||||
methods.handleCondGroupDelete(groupIndex)
|
||||
}
|
||||
methods.validateCondData()
|
||||
},
|
||||
handleCondDelete(index: number, row: any) {
|
||||
data.cond.condGroup.splice(index, 1)
|
||||
},
|
||||
handleCondValType(type?) {
|
||||
if (type) {
|
||||
data.cond.varKeyVal = null
|
||||
methods.updateCondVarKeyVal(false)
|
||||
}
|
||||
if (!type) {
|
||||
type = methods.initCurrVarKeyVal()
|
||||
}
|
||||
if (type === DIC_PROP.VAL_TYPE[2].value) {
|
||||
data.varValOperator = DIC_PROP.OPERATOR
|
||||
methods.onAddItem(false)
|
||||
} else {
|
||||
data.varValOperator = []
|
||||
}
|
||||
data.cond.operator = null
|
||||
data.cond.varVal = null
|
||||
},
|
||||
handleCondVarKeyVal() {
|
||||
let val = data.cond.varKeyVal
|
||||
let valType = data.cond.valType;
|
||||
if (!val) {
|
||||
methods.updateCondVarKeyVal(false)
|
||||
return
|
||||
}
|
||||
if (valType === DIC_PROP.VAL_TYPE[2].value) return
|
||||
if (valType === DIC_PROP.VAL_TYPE[4].value && val.indexOf("#") === -1) {
|
||||
data.cond.varKeyVal = null
|
||||
$message.warning("当选择专业模式时, 函数表达式必须符合规定的格式")
|
||||
return;
|
||||
}
|
||||
methods.updateCondVarKeyVal(true)
|
||||
},
|
||||
updateCondVarKeyVal(isSave) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.valType = data.cond.valType
|
||||
if (isSave) {
|
||||
if (data.cond.valType === DIC_PROP.VAL_TYPE[2].value) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyVal = PROP_CONST.VAR_KEY_VAL.person
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyValName = PROP_CONST.VAR_KEY_VAL.personName
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyVal = data.cond.varKeyVal
|
||||
}
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpMethod = data.cond.httpMethod
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyVal = null
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyValName = null
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups = []
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpParams = []
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpMethod = null
|
||||
data.httpUrlParamsVisible = false
|
||||
}
|
||||
},
|
||||
validateCondData() {
|
||||
let condGroups = props.currSelect.attributes.attrs.cdata.defJob.condGroups;
|
||||
if (!condGroups) {
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups = []
|
||||
}
|
||||
data.condGroups.splice(0, data.condGroups.length);
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups.forEach(each => data.condGroups.push(each))
|
||||
data.existData = !validateNull(data.condGroups)
|
||||
},
|
||||
initCurrVarKeyVal() {
|
||||
data.cond.valType = props.currSelect.attributes.attrs.cdata.defJob.valType
|
||||
if (data.condGroups.length <= 0) {
|
||||
data.cond.varKeyVal = props.currSelect.attributes.attrs.cdata.defJob.userKeyVal
|
||||
let httpMethod = props.currSelect.attributes.attrs.cdata.defJob.httpMethod
|
||||
if (httpMethod) data.cond.httpMethod = httpMethod
|
||||
}
|
||||
let httpParams = props.currSelect.attributes.attrs.cdata.defJob.httpParams;
|
||||
if (!validateNull(httpParams)) {
|
||||
data.httpUrlParamsVisible = true
|
||||
}
|
||||
return data.cond.valType
|
||||
},
|
||||
changeTabPane(val) {
|
||||
methods.validateCondData()
|
||||
methods.handleCondValType()
|
||||
methods.onFormLoaded()
|
||||
}
|
||||
}
|
||||
// 监听双向绑定
|
||||
watch(
|
||||
() => props.currSelect,
|
||||
(val) => {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return
|
||||
}
|
||||
methods.changeTabPane(val)
|
||||
}
|
||||
);
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../assets/style/flow-attr.scss';
|
||||
</style>
|
||||
252
src/flow/designer/components/index.ts
Normal file
252
src/flow/designer/components/index.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
import {DIC_PROP} from "/@/flow/support/dict-prop";
|
||||
import {PROP_CONST} from "/@/flow/support/prop-const";
|
||||
import {CommonNodeType, HighNodeType} from "/@/flow/designer/config/type";
|
||||
import {notifyLeft} from "/@/flow";
|
||||
import {useMessageBox} from "/@/hooks/message";
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
import {gateAttr, linkAttr, syncJobAttr, syncNodeAttr} from "/@/flow/designer/config/attr-config";
|
||||
import {setPropsNullValue} from "/@/flow/support/common";
|
||||
import {validateListFormOption} from "/@/flow/utils/form-perm";
|
||||
|
||||
/**
|
||||
* 常用工具类
|
||||
*
|
||||
* @author luolin
|
||||
*/
|
||||
// 反解析名称时未加载该常量
|
||||
export function revParseWhoseLeaderName(data, dicData) {
|
||||
// 谁的主管,可自定义更多
|
||||
dicData.users.unshift(PROP_CONST.FLOW_METHOD.whoseLeader)
|
||||
if (!data.whoseLeader) return
|
||||
if (data.whoseLeader === PROP_CONST.FLOW_METHOD.whoseLeader.userId) {
|
||||
data.whoseLeaderName = PROP_CONST.FLOW_METHOD.whoseLeader.name
|
||||
} else {
|
||||
let find = dicData.users.find(f => f.userId === data.whoseLeader);
|
||||
if (find) data.whoseLeaderName = find.name;
|
||||
}
|
||||
}
|
||||
|
||||
export async function revParseUserKeyValName(props, data, dicData, methods) {
|
||||
if (methods.validateCurrSelectDefJob) {
|
||||
if (!methods.validateCurrSelectDefJob()) return;
|
||||
}
|
||||
let valType = props.currSelect.attributes.attrs.cdata.defJob.valType;
|
||||
let userKeyVal = props.currSelect.attributes.attrs.cdata.defJob.userKeyVal;
|
||||
if (!userKeyVal) return;
|
||||
let userKeyValFrom;
|
||||
if (userKeyVal === PROP_CONST.VAR_KEY_VAL.order + 'createUser') {
|
||||
userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[0].value
|
||||
data.activeKey = 'flow-method'
|
||||
} else if (userKeyVal.indexOf('getUserDeptLeaderId') !== -1) {
|
||||
userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[1].value
|
||||
data.whoseLeader = userKeyVal.substring(userKeyVal.indexOf('(Long#') + 6, userKeyVal.indexOf(',Integer#'))
|
||||
data.leaderLevel = parseInt(userKeyVal.substring(userKeyVal.indexOf(',Integer#') + 9, userKeyVal.indexOf(',String#')))
|
||||
data.levelExtract = userKeyVal.substring(userKeyVal.indexOf(',String#') + 8, userKeyVal.indexOf(')'))
|
||||
data.activeKey = 'flow-method'
|
||||
} else if (userKeyVal.indexOf('listUserDeptMultiLeaderId') !== -1) {
|
||||
userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[2].value
|
||||
let lastIndex = userKeyVal.indexOf('String#') - 1;
|
||||
data.whoseLeader = userKeyVal.substring(userKeyVal.indexOf('(Long#') + 6, lastIndex)
|
||||
userKeyVal = userKeyVal.substr(lastIndex)
|
||||
lastIndex = userKeyVal.indexOf('Integer#') - 1;
|
||||
data.auditEndpoint = userKeyVal.substring(userKeyVal.indexOf('String#') + 7, lastIndex)
|
||||
userKeyVal = userKeyVal.substr(lastIndex)
|
||||
lastIndex = userKeyVal.indexOf('String#') - 1;
|
||||
let leaderLevel = userKeyVal.substring(userKeyVal.indexOf('Integer#') + 8, lastIndex)
|
||||
userKeyVal = userKeyVal.substr(lastIndex)
|
||||
if (data.auditEndpoint === '1') data.leaderLevel = parseInt(leaderLevel)
|
||||
lastIndex = userKeyVal.lastIndexOf('String#') - 1;
|
||||
data.seqAuditSort = userKeyVal.substring(userKeyVal.indexOf('String#') + 7, lastIndex)
|
||||
userKeyVal = userKeyVal.substr(lastIndex)
|
||||
data.levelExtract = userKeyVal.substring(userKeyVal.indexOf(')') - 1, userKeyVal.indexOf(')'))
|
||||
data.activeKey = 'flow-method'
|
||||
} else if (userKeyVal.indexOf('getDeptLeaderId') !== -1) {
|
||||
userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[3].value
|
||||
data.appointDeptId = userKeyVal.substring(userKeyVal.indexOf('(Long#') + 6, userKeyVal.indexOf(',String#'))
|
||||
data.levelExtract = userKeyVal.substring(userKeyVal.indexOf(',String#') + 8, userKeyVal.indexOf(')'))
|
||||
} else if (props.currSelect.attributes.attrs.cdata.defJob.userKeyValName) {
|
||||
let find = DIC_PROP.FLOW_METHOD_TYPE.find(f => f.label === props.currSelect.attributes.attrs.cdata.defJob.userKeyValName);
|
||||
// 再次编辑时优先显示为专业模式
|
||||
if (find) {
|
||||
userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[4].value
|
||||
data.userKeyVal = userKeyVal
|
||||
if (methods.handleUserKeyValFrom) methods.handleUserKeyValFrom(userKeyValFrom)
|
||||
data.activeKey = 'flow-method'
|
||||
}
|
||||
} else if (DIC_PROP.VAL_TYPE[4].value === valType && userKeyVal) {
|
||||
if (validateNull(data.formFieldPerms)) await validateListFormOption(data, props)
|
||||
if (!validateNull(data.formFieldPerms)) {
|
||||
let exist = data.formFieldPerms.find(f => f.prop === userKeyVal);
|
||||
if (exist) userKeyValFrom = DIC_PROP.FLOW_METHOD_TYPE[4].value
|
||||
}
|
||||
}
|
||||
if (userKeyValFrom) {
|
||||
data.userKeyValFrom = userKeyValFrom
|
||||
} else {
|
||||
data.activeKey = 'flow-rule'
|
||||
}
|
||||
}
|
||||
|
||||
export function parseUserKeyValName(props, data, methods) {
|
||||
if (methods.validateCurrSelectDefJob) {
|
||||
if (!methods.validateCurrSelectDefJob()) return;
|
||||
}
|
||||
let userKeyVal;
|
||||
if (data.userKeyValFrom === '0') {
|
||||
userKeyVal = PROP_CONST.VAR_KEY_VAL.order + 'createUser'
|
||||
} else if (data.userKeyValFrom === '1') {
|
||||
userKeyVal = '#distActorServiceImpl.getUserDeptLeaderId(Long#'+ data.whoseLeader +',Integer#'+ data.leaderLevel +',String#'+ data.levelExtract +')'
|
||||
} else if (data.userKeyValFrom === '2') {
|
||||
let leaderLevel = 'NULL'
|
||||
if (data.auditEndpoint === '1') leaderLevel = data.leaderLevel
|
||||
let seqAuditSort = 'NULL'
|
||||
if (data.seqAuditSort) seqAuditSort = data.seqAuditSort
|
||||
userKeyVal = '#distActorServiceImpl.listUserDeptMultiLeaderId(Long#'+ data.whoseLeader +',String#'+ data.auditEndpoint +',Integer#'+ leaderLevel +',String#'+ seqAuditSort +',String#'+ data.levelExtract +')'
|
||||
} else if (data.userKeyValFrom === '3') {
|
||||
userKeyVal = '#distActorServiceImpl.getDeptLeaderId(Long#'+ data.appointDeptId +',String#'+ data.levelExtract +')'
|
||||
} else if (data.userKeyValFrom === '4') {
|
||||
userKeyVal = data.userKeyVal
|
||||
}
|
||||
if (data.userKeyValFrom === '1' || data.userKeyValFrom === '2') {
|
||||
if (!data.whoseLeader) {
|
||||
if (methods.$message) methods.$message('whoseLeader')
|
||||
return
|
||||
}
|
||||
}
|
||||
if (data.userKeyValFrom === '3') {
|
||||
if (!data.appointDeptId) {
|
||||
if (methods.$message) methods.$message('appointDeptId')
|
||||
return
|
||||
}
|
||||
}
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyVal = userKeyVal;
|
||||
props.currSelect.attributes.attrs.cdata.defJob.userKeyValName = DIC_PROP.FLOW_METHOD_TYPE.find(f => f.value === data.userKeyValFrom).label;
|
||||
|
||||
props.currSelect.attributes.attrs.cdata.defJob.valType = DIC_PROP.VAL_TYPE[4].value
|
||||
// 清空其他参数
|
||||
props.currSelect.attributes.attrs.cdata.defJob.condGroups = []
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpParams = []
|
||||
props.currSelect.attributes.attrs.cdata.defJob.httpMethod = null
|
||||
}
|
||||
|
||||
export function handleLinkFlowNodeIds(data, props) {
|
||||
data.toFlowNodeIds = []
|
||||
data.fromFlowNodeIds = []
|
||||
let models = window._jfGraph.getElements();
|
||||
data.fromFlowNodeId = props.currSelect.attributes.source.id
|
||||
data.toFlowNodeId = props.currSelect.attributes.target.id
|
||||
// 修正拖拽连线箭头更改目标节点
|
||||
props.currSelect.attributes.attrs.cdata.attrs.fromFlowNodeId = data.fromFlowNodeId
|
||||
props.currSelect.attributes.attrs.cdata.attrs.toFlowNodeId = data.toFlowNodeId
|
||||
models.forEach(each => {
|
||||
if (!validateNodeType(each)) return
|
||||
let id = each.id
|
||||
let nodeName = each.attributes.attrs.label.text
|
||||
if (id !== props.currSelect.attributes.target.id) {
|
||||
data.fromFlowNodeIds.push({id, nodeName})
|
||||
}
|
||||
if (id !== props.currSelect.attributes.source.id) {
|
||||
data.toFlowNodeIds.push({id, nodeName})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function changeLinkFlowNodeIds(data, props, methods?, $emit?) {
|
||||
useMessageBox()
|
||||
.confirm('是否确认修改连线的' + (data.modifyPointType === '0' ? '起点?' : '终点?'))
|
||||
.then(() => {
|
||||
doLinkFlowNodeIds(data, props, methods, $emit)
|
||||
})
|
||||
}
|
||||
|
||||
function doLinkFlowNodeIds(data, props, methods?, $emit?) {
|
||||
if (data.modifyPointType === '0') {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.fromFlowNodeId = data.fromFlowNodeId
|
||||
props.currSelect.set('source', { id: data.fromFlowNodeId });
|
||||
} else {
|
||||
props.currSelect.attributes.attrs.cdata.attrs.toFlowNodeId = data.toFlowNodeId
|
||||
props.currSelect.set('target', { id: data.toFlowNodeId });
|
||||
}
|
||||
if (methods) methods.handleLinkFlowNodeIds()
|
||||
if (window._flowConfig.globalConfig.isSimpleMode === '1') window._jfOperate.layout()
|
||||
else notifyLeft('专业模式不会自动调整连线轨迹,有必要时请手动调整', 'warning', 3000)
|
||||
if ($emit) $emit("hideAttrConfig", false, '1');
|
||||
}
|
||||
|
||||
export function validateNodeType(currSelect, methods?, isVirtual?) {
|
||||
if (methods && !methods.validateCurrSelectAttrs()) return false;
|
||||
let type = currSelect.attributes.attrs.cdata.type;
|
||||
let noVirtual = type === CommonNodeType.START || type === CommonNodeType.END || type === CommonNodeType.SERIAL || type === CommonNodeType.PARALLEL;
|
||||
if (!isVirtual) return noVirtual
|
||||
return noVirtual || type === HighNodeType.VIRTUAL
|
||||
}
|
||||
|
||||
export function handleSyncFlowNodeIds(data, props, methods) {
|
||||
data.syncFlowNodeIds = []
|
||||
if (!methods.validateCurrSelectAttrsAttrs()) return;
|
||||
props.currSelect.attributes.attrs.cdata.attrs.syncFlowNodeId = null
|
||||
let isGateway = props.currSelect.attributes.attrs.cdata.attrs.isGateway;
|
||||
let models = window._jfGraph.getElements();
|
||||
if (validateNull(models)) return
|
||||
models.forEach(each => {
|
||||
let cdata = each.attributes.attrs.cdata;
|
||||
let b = cdata.type === CommonNodeType.SERIAL || cdata.type === CommonNodeType.PARALLEL;
|
||||
if (b && props.currSelect.id !== each.id) {
|
||||
let id = each.id
|
||||
let nodeName = each.attributes.attrs.label.text + "(ID:" + id + ")"
|
||||
let isExist = false
|
||||
if (isGateway === '1') {
|
||||
if (cdata.attrs.isGateway === '1') isExist = true
|
||||
} else {
|
||||
if (cdata.attrs.isGateway !== '1') isExist = true
|
||||
}
|
||||
if (isExist) data.syncFlowNodeIds.push({id, nodeName})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function changeSyncFlowNodeId(id, props, methods, $message) {
|
||||
let models = window._jfGraph.getElements();
|
||||
if (validateNull(models) || !id) return
|
||||
let isGateway = props.currSelect.attributes.attrs.cdata.attrs.isGateway;
|
||||
let cdata = models.find(f => f.id === id).attributes.attrs.cdata;
|
||||
let nodeAttrs: any[];
|
||||
if (isGateway !== '1') {
|
||||
nodeAttrs = Object.keys(syncNodeAttr);
|
||||
if (!validateNull(cdata.defJob)) {
|
||||
setPropsNullValue(props.currSelect.attributes.attrs.cdata.defJob, cdata.defJob, ...Object.keys(syncJobAttr))
|
||||
}
|
||||
} else {
|
||||
nodeAttrs = Object.keys(gateAttr);
|
||||
}
|
||||
setPropsNullValue(props.currSelect.attributes.attrs.cdata.attrs, cdata.attrs, ...nodeAttrs)
|
||||
$message.warning("已同步其他节点的配置,请重新打开查看")
|
||||
methods.hideAttrConfig(false, '1');
|
||||
}
|
||||
|
||||
export function handleSyncFlowNodeRelIds(data, props, methods) {
|
||||
data.syncFlowNodeRelIds = []
|
||||
if (!methods.validateCurrSelectAttrsAttrs()) return;
|
||||
props.currSelect.attributes.attrs.cdata.attrs.syncFlowNodeRelId = null
|
||||
let links = window._jfGraph.getLinks();
|
||||
if (validateNull(links)) return
|
||||
links.forEach(each => {
|
||||
if (props.currSelect.id !== each.id) {
|
||||
let id = each.id
|
||||
let linkName = "ID:" + id
|
||||
let text = each.attributes.labels[0].attrs.text.text;
|
||||
if (text) linkName = text + "(ID:" + id + ")"
|
||||
data.syncFlowNodeRelIds.push({id, linkName})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function changeSyncFlowNodeRelId(id, props, methods, $message) {
|
||||
let links = window._jfGraph.getLinks();
|
||||
if (validateNull(links) || !id) return
|
||||
let cdata = links.find(f => f.id === id).attributes.attrs.cdata;
|
||||
let linkAttrs = Object.keys(linkAttr);
|
||||
setPropsNullValue(props.currSelect.attributes.attrs.cdata.attrs, cdata.attrs, ...linkAttrs)
|
||||
$message.warning("已同步其他连线的配置,请重新打开查看")
|
||||
methods.hideAttrConfig(false, '1');
|
||||
}
|
||||
87
src/flow/designer/components/node-menu.vue
Normal file
87
src/flow/designer/components/node-menu.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="flow-node-menu">
|
||||
<el-menu style="border-right: 0;">
|
||||
<template v-for="(node, index) in props.menuList" :key="index">
|
||||
<el-menu-item style="padding-top: 4px; padding-left: 14px;" v-if="isShowNode(node) && node.type !== HighNodeType.CHILD_FLOW">
|
||||
<el-tooltip :content="getNodeName(node)" placement="right">
|
||||
<div
|
||||
class="el-node-item"
|
||||
draggable="true"
|
||||
@dragstart="dragNode(node.type, props.type)"
|
||||
>
|
||||
<img :src="node.icon" alt="node">
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="NodeMenu">
|
||||
import {HighNodeType} from '../config/type'
|
||||
import {validateNull} from "/@/utils/validate";
|
||||
|
||||
const $emit = defineEmits(["setDragInfo"]);
|
||||
const props = defineProps({
|
||||
menuList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
flowData: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
});
|
||||
|
||||
function isShowNode(node) {
|
||||
if (validateNull(props.flowData)) return true
|
||||
if (node.type !== HighNodeType.JOB && node.type !== HighNodeType.VIRTUAL) {
|
||||
return true
|
||||
}
|
||||
let isJobSeparated = props.flowData.attrs.isJobSeparated;
|
||||
return isJobSeparated === '1';
|
||||
}
|
||||
|
||||
function getNodeName(node) {
|
||||
return node.nodeName + (node.nodeDesc ? node.nodeDesc : '')
|
||||
}
|
||||
|
||||
// 开始拖拽
|
||||
function dragNode(type, belongTo) {
|
||||
$emit("setDragInfo", {
|
||||
type,
|
||||
belongTo
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
/*菜单间距*/
|
||||
.flow-node-menu {
|
||||
|
||||
.el-menu-item {
|
||||
padding: 11px!important;
|
||||
height: 40px!important;
|
||||
}
|
||||
|
||||
.el-node-item {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
cursor: move;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:hover {
|
||||
color: #0960bd;
|
||||
outline: 1px dashed #0960bd;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user