Files
school-developer/src/views/jsonflow/dist-person/flow.vue
吴红兵 1f645dad3e init
2025-12-02 10:37:49 +08:00

371 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="110px" v-loading="loading"
:disabled="operType === 'view'">
<el-row :gutter="24">
<!-- <el-col :span="24" class="mb20">
<el-form-item>
<div style="color: red;font-size: 14px">备注: 当不指定待分配节点时, 默认对当前相同userKey进行全局统一分配</div>
</el-form-item>
</el-col>-->
<el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.code')" prop="code">
<el-select v-model="form.code" :placeholder="t('distPerson.inputCodeTip')" clearable filterable disabled
@change="cascadeChange('code', ['flowInstId'])">
<el-option v-for="(item, index) in dicData.code" :key="index" :label="item.code" :value="item.code"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.flowKey')" prop="flowInstId">
<el-select v-model="form.flowInstId" :placeholder="t('distPerson.inputFlowKeyTip')" clearable filterable disabled
@change="cascadeChange('flowInstId', ['runNodeId'])">
<el-option v-for="(item, index) in cascadeDic.flowInstId" :key="index" :label="item.flowName" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.runNodeId')" prop="runNodeId">
<el-select v-model="form.runNodeId" :placeholder="t('distPerson.inputRunNodeIdTip')" clearable filterable
:disabled="!!props.currJob.distFlowNodeId"
@change="cascadeChange('runNodeId', ['distRunJobId'])">
<el-option v-for="(item, index) in cascadeDic.runNodeId" :key="index" :label="item.nodeName" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.runJobId')" prop="runJobId">
<el-select v-model="form.runJobId" :placeholder="t('distPerson.inputRunJobIdTip')" clearable filterable @change="runJobIdChange">
<el-option v-for="(item, index) in cascadeDic.distRunJobId" :key="index" :label="item.jobName" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.userKey')" prop="userKey" disabled>
<el-input v-model="form.userKey" :placeholder="t('distPerson.inputUserKeyTip')" disabled/>
</el-form-item>
</el-col>
<!-- <el-col :span="12" class="mb20">
<el-form-item :label="t('distPerson.isNowRun')" prop="isNowRun" disabled>
<el-radio-group disabled v-model="form.isNowRun">
<el-radio v-for="(item, index) in DIC_PROP.YES_OR_NO" :key="index" :label="item.value">
{{ getLabelByLanguage(item) }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>-->
</el-row>
<el-row :gutter="48">
<el-col :span="24" class="mb20">
<el-form-item>
<div style="color: red;font-size: 14px">: 分配参与者允许为任意的节点分配参与者, 让分配参与者更自由</div>
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item :label="t('distPerson.roleUserId')" prop="roleUserId">
<el-table :data="form.roleUserId" border style="width: 100%" max-height="500">
<el-table-column type="index" :label="t('distPerson.index')" width="80">
<template #header>
<el-button icon="Plus" size="small" type="primary" circle
@click="methods.onAddItem"></el-button>
</template>
<template #default="scope">
<el-button icon="Minus" size="small" type="danger" circle :disabled="scope.row.isDisabled"
@click="methods.handleDelete(scope.$index, scope.row)"></el-button>
</template>
</el-table-column>
<el-table-column prop="jobType" :label="t('distPerson.jobType')" show-overflow-tooltip >
<template #default="scope">
<el-select v-model="scope.row.jobType" :placeholder="t('distPerson.inputJobTypeTip')" clearable filterable
@change="handleRoleType" :disabled="scope.row.isDisabled">
<el-option v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column prop="roleId" :label="t('distPerson.roleId')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip content="请输入名称进行模糊搜索" placement="top">
<el-select v-model="scope.row.roleId" :placeholder="t('distPerson.inputRoleIdTip')" clearable filterable
:disabled="scope.row.isDisabled"
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="jobName" :label="t('distPerson.jobName')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="可为空为空时参与者的任务名称都相同">
<el-input v-model="scope.row.jobName" :placeholder="t('distPerson.inputJobNameTip')" :disabled="scope.row.isDisabled"/>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="sort" :label="t('distPerson.sort')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="可为空为空时参与者的任务排序值都相同">
<el-input-number :min="1" :max="1000" v-model="scope.row.sort" :placeholder="t('distPerson.inputSortTip')"
:disabled="scope.row.isDisabled"></el-input-number>
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template v-if="operType !== 'view'">
<footer class="el-dialog__footer">
<span class="dialog-footer">
<el-button type="primary" @click="methods.handleUpdate" :disabled="loading">{{
$t('common.confirmButtonText')
}}</el-button>
</span>
</footer>
</template>
</div>
</template>
<script setup lang="ts" name="DistPersonFlow">
import {useMessage} from "/@/hooks/message";
import {getByFlowInstId, saveByFlowInstId} from '/@/api/jsonflow/dist-person'
import {useI18n} from "vue-i18n"
import {
onCascadeChange,
onFormLoadedUrl,
onLoadDicUrl,
remoteMethodAllByKey
} from "/@/flow/components/convert-name/convert";
import {setPropsDataValue, setPropsNull} from '/@/flow/support/common'
import * as orderVue from "/@/api/order/order-key-vue";
import { useUserInfo } from '/@/stores/userInfo';
import {validateNull} from "/@/utils/validate";
import {DIC_PROP} from "/@/flow/support/dict-prop";
import {handleChangeJobType} from "/@/flow";
import {PROP_CONST} from "/@/flow/support/prop-const";
const {t} = useI18n();
const userInfo = useUserInfo();
const emits = defineEmits(["handleJob"]);
// 定义变量内容
const dataFormRef = ref();
const loading = ref(false);
const operType = ref(false);
// 定义字典
const dicData = reactive({});
const onLoad = onLoadDicUrl({key: "code"});
const onFormLoaded = onFormLoadedUrl(...PROP_CONST.LOAD_USER_ROLE);
onMounted(async () => {
await onLoad(dicData);
});
const fields = ['userKey', 'valType', 'isNowRun'];
const cascadeDic = reactive({});
const onCascade = onCascadeChange(cascadeDic, {key: "code", cascades: ["flowInstId"]}, {key: "flowInstId", cascades: ["runNodeId"]}, {key: "runNodeId", cascades: ["distRunJobId"]});
async function cascadeChange(key, cascades) {
await onCascade(form, {key: key, cascades: cascades});
if (key === 'runNodeId') {
setPropsNull(form, ...fields)
form.roleUserId = []
if (!validateNull(cascadeDic.distRunJobId)) return
useMessage().info("当前节点任务非指定参与者KEY类型不允许前端分配参与者");
}
}
function runJobIdChange(newVal){
form.roleUserId = []
if (!newVal) {
setPropsNull(form, ...fields)
return
}
const runJob = cascadeDic.distRunJobId.find(f => f.id === newVal)
setPropsDataValue(form, runJob, fields)
if (form.valType !== DIC_PROP.VAL_TYPE[1].value) {
form.runJobId = null
useMessage().info("当前节点任务非指定参与者KEY类型不允许前端分配参与者");
return;
}
form.runJobId = newVal;
// 重新查询分配信息
methods.handleGetObj(form)
}
function handleRoleType() {
handleChangeJobType(dicData, form)
}
// 提交表单数据
const form = reactive({
code: '',
runNodeId: '',
runJobId: '',
userKey: '',
flowInstId: '',
flowKey: '',
roleUserId: [],
});
// 定义校验规则
const dataRules = ref({
code: [{required: true, message: '工单编号不能为空', trigger: 'blur'}],
runNodeId: [{required: true, message: '节点名称不能为空', trigger: 'blur'}],
runJobId: [{required: true, message: '任务名称不能为空', trigger: 'blur'}],
userKey: [{required: true, message: '参与者KEY不能为空', trigger: 'blur'}],
// roleUserId: [{required: true, message: '参与者不能为空', trigger: 'blur'}],
})
const props = defineProps({
currJob: {
type: Object,
default: null,
},
currElTab: {
type: Object,
default: {},
},
});
function remoteMethodAll(query: string, jobType) {
remoteMethodAllByKey(onLoad, dicData, query, jobType)
}
const methods = {
disableForm() {
operType.value = "view"
},
enableForm() {
operType.value = "flow"
},
async initJobData() {
// 判断是否仅查看
if (props.currElTab.id) {
await orderVue.currElTabIsView(methods, props.currJob, props.currElTab.id, methods.handleUpdate)
}
setPropsDataValue(form, props.currJob, 'code', 'flowKey', 'flowInstId')
await onCascade(form);
form.flowNodeId = props.currJob.distFlowNodeId
// 判断待分配参与者节点ID
if (!form.flowNodeId) return
form.runNodeId = cascadeDic.runNodeId.find(f => form.flowNodeId === f.flowNodeId).id;
await cascadeChange('runNodeId', ['distRunJobId'])
// 动态加减签其中一个即可
runJobIdChange(cascadeDic.distRunJobId[0]?.id)
},
handleGetObj(form) {
// 查询已分配参与者
getByFlowInstId(form).then(response => {
let roleUserId = response.data.roleUserId
// 排除该节点非本人分配参与者(除查看)
roleUserId.forEach(f => {
let b = f.createUser !== userInfo.userInfos.user.userId;
if (b) f.isDisabled = true
})
form.roleUserId = roleUserId
if (validateNull(roleUserId)) return
onFormLoaded(dicData, roleUserId)
})
},
async handleUpdate() {
const valid = await dataFormRef.value.validate().catch(() => {
});
if (!valid) return false;
const validateRoleUser = await methods.validateRoleUser(form)
if (validateRoleUser) {
if (props.currElTab.id) {
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emits)
}
return
}
try {
loading.value = true;
await saveByFlowInstId(form);
if (props.currElTab.id) {
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, true, emits)
}
useMessage().success("分配参与者成功");
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
},
// 校验分配数据
async validateRoleUser(row) {
if (validateNull(row.roleUserId)) return false
if (row.flowNodeId === props.currJob.flowNodeId) {
useMessage().error('待分配参与者节点不能是当前节点本身')
return true
}
// 分配参与者判断是否重复
if (methods.validateDupRoleId(row, 0, '人员')) return true
if (methods.validateDupRoleId(row, 1, '角色')) return true
if (methods.validateDupRoleId(row, 2, '岗位')) return true
if (methods.validateDupRoleId(row, 3, '部门')) return true
return false
},
// 分配参与者判断是否重复
validateDupRoleId(row, typeIndex, msg) {
let roleIds = row.roleUserId.filter(f => f.roleId && f.jobType === DIC_PROP.JOB_USER_TYPE[typeIndex].value).map(roleUser => {
return roleUser.roleId
})
if (new Set(roleIds).size !== roleIds.length) {
useMessage().info("分配的办理 " + msg + " 不能重复, 请重新选择")
return true
}
return false
},
onAddItem() {
if (props.currElTab.id) {
orderVue.currElTabIsSave(props.currJob, props.currElTab.id, false)
}
let obj = {};
form.roleUserId.push(obj);
},
handleDelete(index: number, row: any) {
form.roleUserId.splice(index, 1)
}
}
// 监听双向绑定
watch(
() => props.currJob.id,
() => {
methods.initJobData();
}
);
onMounted(() => {
methods.initJobData()
});
</script>
<style lang="scss" scoped>
.el-dialog__footer {
text-align: center;
.dialog-footer {
text-align: center;
}
}
</style>