This commit is contained in:
吴红兵
2025-12-02 10:37:49 +08:00
commit 1f645dad3e
1183 changed files with 147673 additions and 0 deletions

View File

@@ -0,0 +1,409 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-row v-show="showSearch">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item :label="$t('runFlow.initiatorId')" prop="initiatorId" >
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
<el-select v-model="state.queryForm.initiatorId" :placeholder="t('runFlow.inputInitiatorIdTip')" clearable filterable style="max-width: 180px"
remote :remote-method="remoteMethod" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.initiatorId" :key="index" :label="item.name" :value="item.userId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item :label="$t('runFlow.code')" prop="flowInstId" >
<el-select v-model="state.queryForm.flowInstId" :placeholder="t('runFlow.inputCodeTip')" clearable filterable
@change="cascadeChange('flowInstId', ['runNodeId'])" style="max-width: 180px">
<el-option v-for="(item, index) in dicData.flowInstId" :key="index" :label="item.code" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.runNodeId')" prop="runNodeId" >
<el-select v-model="state.queryForm.runNodeId" :placeholder="t('runJob.inputRunNodeIdTip')" clearable filterable style="max-width: 180px"
@change="cascadeChange('runNodeId', ['runJobId'])">
<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-form-item :label="$t('runJob.id')" prop="id" >
<el-select v-model="state.queryForm.id" :placeholder="t('runJob.inputIdTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in cascadeDic.runJobId" :key="index" :label="item.jobName" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.status')" prop="status" >
<el-select v-model="state.queryForm.status" :placeholder="t('runJob.inputStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.NODE_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-tabs v-model="data.activeName" class="demo-tabs" @tab-click="methods.handleTabClick">
<el-tab-pane label="全部" name="-1"></el-tab-pane>
<el-tab-pane label="待办理" name="0"></el-tab-pane>
<el-tab-pane label="被抄送" name="1"></el-tab-pane>
<el-tab-pane label="待阅" name="2"></el-tab-pane>
<el-tab-pane label="被加签" name="3"></el-tab-pane>
</el-tabs>
<right-toolbar v-model:showSearch="showSearch" :export="'jsonflow_runjob_export'"
@exportExcel="exportExcel" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
:row-class-name="tableRowClassName"
@sort-change="sortChangeHandle">
<el-table-column type="index" :label="t('runJob.index')" width="40"/>
<el-table-column prop="initiatorId" :label="t('runFlow.initiatorId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.initiatorId" :value="scope.row.initiatorId"
:valueKey="'userId'" :showKey="'name'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="code" :label="t('runFlow.code')" show-overflow-tooltip/>
<el-table-column prop="flowName" :label="t('runJob.defFlowId')" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="orderId" :label="t('flowApplication.formName')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.orderId" :value="scope.row.orderId"
:valueKey="'id'" :showKey="'formName'"></convert-name>
</template>
</el-table-column>
<!-- <el-table-column prop="runNodeId" :label="t('runJob.runNodeId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.runNodeId" :value="scope.row.runNodeId"
:valueKey="'id'" :showKey="'nodeName'"></convert-name>
</template>
</el-table-column>-->
<el-table-column prop="jobName" :label="t('runJob.jobName')" show-overflow-tooltip/>
<el-table-column prop="jobType" :label="t('runJob.jobType')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.JOB_USER_TYPE" :value="scope.row.jobType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" :label="t('runJob.roleId')">
<template #default="scope">
<convert-role-name :options="{users: state.dicData.users, roles: state.dicData.roles, posts: state.dicData.posts, depts: state.dicData.depts}"
:value="scope.row"></convert-role-name>
</template>
</el-table-column>
<el-table-column prop="receiveTime" :label="t('runJob.startTime')" show-overflow-tooltip width="160px"/>
<el-table-column prop="timeLimit" :label="t('runJob.timeLimit')" 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-column prop="suspension" :label="t('runJob.suspension')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.suspension"></dict-tag>
</template>
</el-table-column>-->
<!-- <el-table-column prop="isRead" :label="t('runJob.isRead')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.isRead"></dict-tag>
</template>
</el-table-column>-->
<el-table-column prop="suspensionReason" :label="t('runJob.suspensionReason')" show-overflow-tooltip/>
<el-table-column prop="parFlowInstId" :label="t('runJob.parFlowInstId')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="点击可查看关联父流程工单信息" v-if="scope.row.parFlowInstId">
<convert-name :options="state.dicData.parFlowInstId" :value="scope.row.parFlowInstId"
:valueKey="'id'" :showKey="'flowName'"
:elTagType="'primary'" @click="methods.handleJobByFlowInstId(scope.row, '1')"></convert-name>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-dropdown style="vertical-align: middle; margin-right: 10px">
<span>
功能
<el-icon class="el-icon--right">
<arrow-down/>
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
@click.native="methods.handleComment(scope.row)">查看审批过程
</el-dropdown-item>
<el-dropdown-item
divided
@click.native="methods.handleFlowPic(scope.row)">查看流程图
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.jobType !== DIC_PROP.JOB_USER_TYPE[0].value"
divided
@click.native="methods.handleSignForJob(scope.row, '1')"
>签收任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[0].value && scope.row.roleId === userInfo.userInfos.user.userId"
divided
@click.native="methods.handleSignForJob(scope.row, '0')"
>反签收任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension === '1'"
divided
@click.native="methods.handleSuspension(scope.row,'0')"
>激活任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension !== '1'"
divided
@click.native="methods.handleSuspension(scope.row,'1')"
>挂起任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension !== '1'"
divided
@click.native="methods.handleJobRoleUserId(scope.row,'0')">
转办任务
</el-dropdown-item>
<el-dropdown-item divided
@click.native="methods.handleEarlyComplete(scope.row)">
提前结束流程
</el-dropdown-item>
<el-dropdown-item divided
@click.native="methods.handleTerminateFlow(scope.row)">
终止流程
</el-dropdown-item>
<el-dropdown-item divided
@click.native="methods.handleInvalidFlow(scope.row)">
作废流程
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-button icon="Stamp" text type="primary"
v-if="scope.row.suspension !== '1' && (scope.row.status === '0' || scope.row.status === '9') && scope.row.belongType !== '2'"
@click="methods.handleJob(scope.row)">审批
</el-button>
<el-button icon="Stamp" text type="primary"
v-if="scope.row.suspension !== '1' && scope.row.belongType === '2' && scope.row.isRead === '0'"
@click="methods.handleJob(scope.row, '0', '1')">查看
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination"/>
</div>
<!-- 查看审批过程 -->
<el-dialog
v-model="data.showComment" v-if="data.showComment"
top="20px"
width="90%"
title="查看审批过程"
append-to-body>
<comment :curr-job="data.currJob"></comment>
</el-dialog>
<!-- 查看流程图 -->
<el-drawer
class="flow-overflow-drawer" direction="rtl"
append-to-body size="90%"
v-model="data.showFlowPic"
>
<flow-photo v-if="data.showFlowPic" :curr-job="data.currJob"></flow-photo>
</el-drawer>
<user-role-picker ref="userRolePicker" :isOnlyOne="true" @onSelectItems="methods.onSelectItems">
</user-role-picker>
</div>
</template>
<script setup lang="ts" name="DoJob">
import {BasicTableProps, useTable} from "/@/hooks/table";
import {useMessage} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
import {onCascadeChange, onLoadDicUrl, onLoaded, remoteMethodByKey} from "/@/flow/components/convert-name/convert";
import * as doJob from '/@/api/jsonflow/do-job'
import {useFlowJob} from "/@/flow/stores/flowJob";
import {useUserInfo} from "/@/stores/userInfo";
import {handleFlowPreview} from "/@/flow/support/extend";
import {PROP_CONST} from "/@/flow/support/prop-const";
import {
handleEarlyComplete, handleInvalidFlow,
handleSignForJob,
handleSuspension, handleTerminateFlow,
onSignForJob, onTurnRunJob
} from "/@/flow/components/handle-job";
const $route = useRoute();
const userInfo = useUserInfo();
const $message = useMessage();
const {proxy} = getCurrentInstance();
// 引入组件
const UserRolePicker = defineAsyncComponent(() => import('../../../flow/components/user-role/picker.vue'));
const Comment = defineAsyncComponent(() => import('../comment/timeline.vue'));
const FlowPhoto = defineAsyncComponent(() => import('../flow-design/view.vue'));
const flowJob = useFlowJob()
const {t} = useI18n()
const $router = useRouter();
// 定义查询字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl({key: "flowInstId"});
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["runNodeId"]}, {key: "runNodeId", cascades: ["runJobId"]});
onMounted(async () => {
let belongType = $route.query.belongType;
if (belongType) {
state.queryForm.belongType = belongType
data.activeName = belongType
}
await onLoad(dicData);
});
function cascadeChange(key, cascades){
onCascade(state.queryForm, {key: key, cascades: cascades});
}
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
const data = reactive({
// 0、转办
nodeUserType: undefined,
currJob: undefined,
queryForm: {},
showComment: false,
showFlowPic: false,
activeName: '-1'
});
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {belongType: data.activeName},
pageList: doJob.fetchTodoPage,
onLoaded: onLoaded({key: "initiatorId"}, {key: "parFlowInstId"}, {key: "orderId"}, {key: "runNodeId"}, ...PROP_CONST.LOAD_USER_ROLE),
descs: ["receive_time"]
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/jsonflow/run-job/export', state.queryForm, 'run-job.xlsx')
}
const tableRowClassName = ({row, rowIndex}) => {
if (row.isRead !== '1') {
return 'row-custom-warning'
}
return ''
}
function remoteMethod(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'userName', "initiatorId")
}
const methods = {
handleTabClick(tab) {
if (data.activeName === tab.paneName) return
state.queryForm.signatureType = null
state.queryForm.belongType = null
if (tab.paneName !== '3') {
state.queryForm.belongType = tab.paneName
} else {
state.queryForm.belongType = '0'
// 仅标识
state.queryForm.signatureType = '-1'
}
getDataList(true)
},
handleJobByFlowInstId(row, type) {
let find;
if (type === '1') {
find = state.dicData.parFlowInstId.find(f => f.id === row.parFlowInstId);
}
methods.handleJob({flowInstId: find.id}, '1', '0')
},
handleJob(row, isView?, isRead?) {
handleFlowPreview($router, row, isView, isRead, $message, flowJob, getDataList)
},
handleJobRoleUserId(row, type) {
data.currJob = row
methods.openJobRoleUserId(type)
},
handleComment(row) {
data.currJob = row
data.showComment = true
},
handleFlowPic(row) {
data.currJob = row
data.showFlowPic = true
},
// 签收反签收任务
handleSignForJob(row, type) {
handleSignForJob(methods, $message, getDataList, row, type)
},
// 反签收任务
onSignForJob(obj) {
onSignForJob($message, flowJob, getDataList, obj)
},
// 挂起激活任务
handleSuspension(row, suspension) {
handleSuspension($message, getDataList, row, suspension)
},
// 选择参与者
openJobRoleUserId(type) {
data.nodeUserType = type
proxy.$refs.userRolePicker.onOpen();
},
onSelectItems(items) {
if (data.nodeUserType === '0') {
methods.onTurnRunJob(items[0])
}
},
// 提前结束流程
handleEarlyComplete(row) {
handleEarlyComplete($message, flowJob, getDataList, row)
},
// 终止流程
handleTerminateFlow(row) {
handleTerminateFlow($message, flowJob, getDataList, row)
},
// 作废流程
handleInvalidFlow(row) {
handleInvalidFlow($message, flowJob, getDataList, row)
},
// 转办任务
onTurnRunJob(role) {
onTurnRunJob($message, flowJob, getDataList, data, role)
}
}
</script>
<style lang="scss">
@import "../../../flow/components/style/flow-drawer.scss";
.el-table .row-custom-warning {
--el-table-tr-bg-color: var(--el-color-warning-light-9);
}
</style>

View File

@@ -0,0 +1,272 @@
<template>
<div>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="110px" v-loading="loading" :disabled="operType === 'view'">
<span style="margin-left: 30px">什么是待跳转参与者当待跳转参与者为空时则默认会跳转到该节点下的全部参与者当待跳转参与者不为空时则会跳转到该节点下指定的参与者{{userRoleIdText}}</span>
<el-row :gutter="24">
<el-divider> 参与者设置 </el-divider>
<el-col :span="24" class="mb20">
<el-form-item label="跳转参与者类型" prop="jobType">
<el-tooltip placement="top">
<template #content>标识待跳转任务参与者类型当待跳转任务存在参与者可不选择</template>
<el-radio-group @change="handleRoleType"
v-model="form.jobType">
<el-radio v-for="(item, index) in DIC_PROP.JOB_USER_TYPE" :key="index" :label="item.value">
{{ item.label }}
</el-radio>
</el-radio-group>
</el-tooltip>
<el-tooltip placement="top" v-if="form.jobType">
<template #content>当待跳转任务存在参与者可不选择</template>
<el-button text type="primary" icon="delete" @click="clearJobType">
清空
</el-button>
</el-tooltip>
</el-form-item>
</el-col>
<el-divider> 任意跳转设置 </el-divider>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runReject.flowInstId')" prop="flowInstId">
<el-input v-model="form.flowInstId" :placeholder="t('runReject.inputFlowInstIdTip')" disabled/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runReject.defFlowId')" prop="defFlowId">
<el-select v-model="form.defFlowId" :placeholder="t('runReject.inputDefFlowIdTip')" clearable filterable disabled>
<el-option v-for="(item, index) in cascadeDic.defFlowId" :key="index" :label="item.flowName" :value="item.defFlowId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runReject.toRunNodeId')" prop="toRunNodeId">
<el-tooltip placement="top" content="若不选择具体的【待跳转参与者】,则默认会跳转到该节点下的全部参与者">
<el-select v-model="form.toRunNodeId" :placeholder="t('runReject.inputToFlowNodeIdTip')" clearable filterable
@change="cascadeChange('toRunNodeId', ['anyJumpUserId', 'anyJumpRoleId', 'anyJumpPostId', 'anyJumpDeptId'])">
<el-option v-for="(item, index) in cascadeDic.toRunNodeId" :key="index" :label="item.nodeName" :value="item.id"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="form.jobType === DIC_PROP.JOB_USER_TYPE[0].value">
<el-form-item label="指定待跳转人员" prop="handleRoleId">
<el-tooltip placement="top">
<template #content>{{validateNull(cascadeDic.anyJumpUserId) ? roleIdText : roleIdText2}}</template>
<el-select v-model="form.handleRoleId" placeholder="请输入用户名称进行模糊搜索" clearable filterable
remote :remote-method="methodsRemote.remoteMethodUser" :reserve-keyword="false">
<el-option v-for="(item, index) in validateNull(cascadeDic.anyJumpUserId) ? dicData.users : cascadeDic.anyJumpUserId"
:key="index" :label="item.name" :value="item.userId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="form.jobType === DIC_PROP.JOB_USER_TYPE[1].value">
<el-form-item label="指定待跳转角色" prop="handleRoleId">
<el-tooltip placement="top">
<template #content>{{validateNull(cascadeDic.anyJumpRoleId) ? roleIdText : roleIdText2}}</template>
<el-select v-model="form.handleRoleId" placeholder="请输入角色名称进行模糊搜索" clearable filterable
remote :remote-method="methodsRemote.remoteMethodRole" :reserve-keyword="false">
<el-option v-for="(item, index) in validateNull(cascadeDic.anyJumpRoleId) ? dicData.roles : cascadeDic.anyJumpRoleId"
:key="index" :label="item.roleName" :value="item.roleId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="form.jobType === DIC_PROP.JOB_USER_TYPE[2].value">
<el-form-item label="指定待跳转岗位" prop="handleRoleId">
<el-tooltip placement="top">
<template #content>{{validateNull(cascadeDic.anyJumpPostId) ? roleIdText : roleIdText2}}</template>
<el-select v-model="form.handleRoleId" placeholder="请输入岗位名称进行模糊搜索" clearable filterable
remote :remote-method="methodsRemote.remoteMethodPost" :reserve-keyword="false">
<el-option v-for="(item, index) in validateNull(cascadeDic.anyJumpPostId) ? dicData.posts : cascadeDic.anyJumpPostId"
:key="index" :label="item.postName" :value="item.postId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="form.jobType === DIC_PROP.JOB_USER_TYPE[3].value">
<el-form-item label="指定待跳转部门" prop="handleRoleId">
<el-tooltip placement="top">
<template #content>{{validateNull(cascadeDic.anyJumpDeptId) ? roleIdText : roleIdText2}}</template>
<el-select v-model="form.handleRoleId" placeholder="请输入部门名称进行模糊搜索" clearable filterable
remote :remote-method="methodsRemote.remoteMethodDept" :reserve-keyword="false">
<el-option v-for="(item, index) in validateNull(cascadeDic.anyJumpDeptId) ? dicData.depts : cascadeDic.anyJumpDeptId"
:key="index" :label="item.name" :value="item.deptId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
</el-row>
</el-form>
<footer class="el-dialog__footer">
<span class="dialog-footer">
<el-button type="primary" @click="handleUpdate" :loading="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</footer>
</div>
</template>
<script setup lang="ts" name="RunAnyJumpForm">
import { useI18n } from "vue-i18n"
import {
onCascadeChange,
onLoadDicUrl,
remoteMethodByKey
} from "/@/flow/components/convert-name/convert";
import {validateNull} from "/@/utils/validate";
import {useMessage} from "/@/hooks/message";
import {handleChangeJobType} from "/@/flow";
const { t } = useI18n();
const $message = useMessage();
const $emit = defineEmits(['onAnyJumpJob']);
// 定义变量内容
const dataFormRef = ref();
const loading = ref(false);
const operType = ref(false);
// 定义字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl();
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["defFlowId"]}, {prefix: "runJob", key: "flowInstId", cascades: ["toRunNodeId"]}, {key: "toRunNodeId"
, cascades: ["anyJumpUserId", "anyJumpRoleId", "anyJumpPostId", "anyJumpDeptId"]});
onMounted(() => {
// onLoad(dicData);
});
function cascadeChange(key, cascades){
cascadeDic.anyJumpUserId = null
cascadeDic.anyJumpRoleId = null
cascadeDic.anyJumpPostId = null
cascadeDic.anyJumpDeptId = null
onCascade(form, {key: key, cascades: cascades});
handleToFlowNodeId(form[key])
}
// 提交表单数据
const form = reactive({
defFlowId: '',
flowInstId: '',
toRunNodeId: '',
handleRoleId: '',
runRejectVO: {},
jobType: '',
});
// 定义校验规则
const dataRules = ref({
defFlowId: [{required: true, message: '流程名称不能为空', trigger: 'blur'}],
flowInstId: [{required: true, message: '流程实例ID不能为空', trigger: 'blur'}],
toRunNodeId: [{required: true, message: '到达节点名称不能为空', trigger: 'blur'}],
})
const props = defineProps({
currJob: {
type: Object,
default: null,
}
});
const roleIdText = '注:当前待跳转节点下可候选待跳转参与者为空,请指定待跳转参与者即为其分配参与者'
const roleIdText2 = '注:当待跳转参与者为空时,则默认会跳转到当前节点显示的全部参与者'
const userRoleIdText = '注:当待跳转节点下任务不存在参与者时,请指定待跳转参与者即为其分配参与者'
function handleToFlowNodeId(val) {
if (!val) return
const runNode = cascadeDic.toRunNodeId.find(f => f.id === val)
form.runRejectVO.toRunNodeId = runNode.id
form.runRejectVO.toFlowNodeId = runNode.flowNodeId
}
function initJobData() {
Object.assign(form, props.currJob)
onCascade(form)
}
function handleRoleType() {
handleChangeJobType(dicData, form)
form.handleRoleId = null
}
function clearJobType() {
form.jobType = ''
form.handleRoleId = null
}
const methodsRemote = {
remoteMethodUser(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'userName', "users")
},
remoteMethodRole(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'roleName', "roles")
},
remoteMethodPost(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'postName', "posts")
},
remoteMethodDept(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'deptName', "depts")
},
}
async function handleUpdate() {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
let b = validateNull(cascadeDic.anyJumpUserId) && validateNull(cascadeDic.anyJumpRoleId)
&& validateNull(cascadeDic.anyJumpPostId) && validateNull(cascadeDic.anyJumpDeptId) && !form.handleRoleId;
if (b) {
$message.warning(roleIdText)
return
}
// 为空则跳转到显示的全部参与者
if (form.jobType) {
form.runRejectVO.handleRoleId = form.handleRoleId
form.runRejectVO.jobType = form.jobType
}
props.currJob.runRejectVO = form.runRejectVO
loading.value = true
try {
$emit('onAnyJumpJob', props.currJob)
setTimeout(() => { // 异步异常
loading.value = false
}, 3000)
} catch (e) {
loading.value = false
}
}
// 监听双向绑定
watch(
() => props.currJob.id,
(val) => {
initJobData();
}
);
onMounted(() => {
initJobData();
});
</script>
<style lang="scss" scoped>
.el-dialog__footer {
text-align: center;
.dialog-footer {
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,311 @@
<template>
<el-dialog :title="title" v-model="visible" width="60%" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="150px" v-loading="loading" :disabled="operType === 'view'">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item :label="$t('runJob.flowInstId')" prop="flowInstId" >
<el-input v-model="form.flowInstId" :placeholder="t('runJob.inputFlowInstIdTip')" disabled/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.defFlowId')" prop="defFlowId">
<el-select v-model="form.defFlowId" :placeholder="t('runJob.inputDefFlowIdTip')" clearable filterable disabled>
<el-option v-for="(item, index) in cascadeDic.defFlowId" :key="index" :label="item.flowName" :value="item.defFlowId"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.runNodeId')" prop="runNodeId">
<el-select v-model="form.runNodeId" :placeholder="t('runJob.inputRunNodeIdTip')" clearable filterable disabled>
<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('runJob.jobName')" prop="jobName">
<el-input v-model="form.jobName" :placeholder="t('runJob.inputJobNameTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.jobType')" prop="jobType">
<el-select v-model="form.jobType" :placeholder="t('runJob.inputJobTypeTip')" clearable filterable
@change="handleRoleType">
<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>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.roleId')" prop="roleId">
<el-tooltip content="请输入名称进行模糊搜索" placement="top">
<el-select v-model="form.roleId" :placeholder="t('runJob.inputRoleIdTip')" clearable filterable
remote :remote-method="(query) => remoteMethodAll(query, form.jobType)" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.users" :key="index" :label="item.name" :value="item.userId"
v-if="form.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="form.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="form.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="form.jobType === DIC_PROP.JOB_USER_TYPE[3].value"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.userId')" prop="userId">
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
<el-select v-model="form.userId" :placeholder="t('runJob.inputUserIdTip')" clearable filterable
remote :remote-method="remoteMethod" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.userId" :key="index" :label="item.name" :value="item.userId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.startTime')" prop="startTime">
<el-date-picker disabled type="datetime" :placeholder="t('runJob.inputStartTimeTip')" v-model="form.startTime" :value-format="dateTimeStr"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.endTime')" prop="endTime">
<el-date-picker disabled type="datetime" :placeholder="t('runJob.inputEndTimeTip')" v-model="form.endTime" :value-format="dateTimeStr"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.userKey')" prop="userKey">
<el-select v-model="form.userKey" :placeholder="t('runJob.inputUserKeyTip')" clearable filterable>
<el-option v-for="(item, index) in dicData.userKey" :key="index" :label="item.userKey" :value="item.userKey"></el-option>
</el-select>
</el-form-item>
</el-col>
<!-- <el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.distFlowNodeId')" prop="distFlowNodeId">
<el-select v-model="form.distFlowNodeId" :placeholder="t('runJob.inputDistFlowNodeIdTip')" clearable filterable>
<el-option v-for="(item, index) in cascadeDic.runNodeId" :key="index" :label="item.nodeName" :value="item.flowNodeId"></el-option>
</el-select>
</el-form-item>
</el-col>-->
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.status')" prop="status">
<el-select disabled v-model="form.status" :placeholder="t('runJob.inputStatusTip')" clearable filterable>
<el-option v-for="(item, index) in DIC_PROP.NODE_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.timeout')" prop="timeout">
<el-input-number :min="1" :max="1000" v-model="form.timeout" :placeholder="t('runJob.inputTimeoutTip')"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.suspension')" prop="suspension">
<el-radio-group v-model="form.suspension">
<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-col :span="12" class="mb20">
<el-form-item :label="t('runJob.suspensionReason')" prop="suspensionReason">
<el-input v-model="form.suspensionReason" :placeholder="t('runJob.inputSuspensionReasonTip')"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="t('runJob.isSkipRejected')" prop="isSkipRejected">
<el-radio-group v-model="form.isSkipRejected">
<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-col :span="12" class="mb20">
<el-form-item :label="t('runJob.isNowRun')" prop="isNowRun">
<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-col :span="12" class="mb20">
<el-form-item :label="t('runJob.sort')" prop="sort">
<el-input-number :min="1" :max="1000" v-model="form.sort" :placeholder="t('runJob.inputSortTip')"></el-input-number>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer v-if="operType !== 'view'">
<span class="dialog-footer">
<el-button @click="visible = false">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="RunJobDialog">
import { useMessage } from "/@/hooks/message";
import { getObj, addObj, putObj } from '/@/api/jsonflow/run-job'
import { useI18n } from "vue-i18n"
import {
onCascadeChange,
onFormLoadedUrl,
onLoadDicUrl,
remoteMethodAllByKey, remoteMethodByKey
} from "/@/flow/components/convert-name/convert";
import {handleChangeJobType} from "/@/flow";
import {PROP_CONST} from "/@/flow/support/prop-const";
const emit = defineEmits(['refresh']);
const { t } = useI18n();
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false);
const loading = ref(false);
const operType = ref(false);
const title = ref('');
// 提交表单数据
const form = reactive({
defFlowId: '',
flowNodeId: '',
nodeJobId: '',
jobType: '',
roleId: '',
userId: '',
startTime: '',
endTime: '',
userKey: '',
distFlowNodeId: '',
timeout: 0,
status: '',
suspension: '',
suspensionReason: '',
isSkipRejected: '0',
createUser: '',
flowKey: '',
flowInstId: '',
runNodeId: '',
isNowRun: '0',
sort: 1,
});
// 定义校验规则
const dataRules = ref({
defFlowId: [{required: true, message: '流程名称不能为空', trigger: 'blur'}],
flowNodeId: [{required: true, message: '节点名称不能为空', trigger: 'blur'}],
nodeJobId: [{required: true, message: '任务名称不能为空', trigger: 'blur'}],
jobType: [{required: true, message: '参与者类型不能为空', trigger: 'blur'}],
timeout: [{required: true, message: '任务时限不能为空', trigger: 'blur'}],
isSkipRejected: [{required: true, message: '被驳回是否可跳过不能为空', trigger: 'blur'}],
})
// 定义查询字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl({key: "userKey"});
const onFormLoaded = onFormLoadedUrl({key: "userId"}, ...PROP_CONST.LOAD_USER_ROLE);
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["defFlowId"]}, {key: "flowInstId", cascades: ["runNodeId"]});
onMounted(() => {
onLoad(dicData);
});
function cascadeChange(key, cascades){
onCascade(form, {key: key, cascades: cascades});
}
function remoteMethod(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'userName', "userId")
}
function remoteMethodAll(query: string, jobType) {
remoteMethodAllByKey(onLoad, dicData, query, jobType)
}
function handleRoleType() {
handleChangeJobType(dicData, form)
}
// 打开弹窗
const openDialog = (type: string, id: string) => {
visible.value = true
operType.value = type;
form.id = ''
if (type === 'add') {
title.value = t('common.addBtn');
} else if (type === 'edit') {
title.value = t('common.editBtn');
} else if (type === 'view') {
title.value = t('common.viewBtn');
}
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
});
// 获取RunJob信息
if (id) {
form.id = id
getRunJobData(id)
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
try {
loading.value = true;
form.id ? await putObj(form) : await addObj(form);
useMessage().success(t(form.id ? 'common.editSuccessText' : 'common.addSuccessText'));
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getRunJobData = (id: string) => {
// 获取数据
loading.value = true
getObj(id).then((res: any) => {
Object.assign(form, res.data)
onFormLoaded(dicData, form);
onCascade(form);
}).finally(() => {
loading.value = false
})
};
// 暴露变量
defineExpose({
openDialog
});
</script>

View File

@@ -0,0 +1,311 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-row v-show="showSearch">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item :label="$t('runFlow.initiatorId')" prop="initiatorId" >
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
<el-select v-model="state.queryForm.initiatorId" :placeholder="t('runFlow.inputInitiatorIdTip')" clearable filterable style="max-width: 180px"
remote :remote-method="remoteMethod" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.initiatorId" :key="index" :label="item.name" :value="item.userId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item :label="$t('runFlow.code')" prop="flowInstId" >
<el-select v-model="state.queryForm.flowInstId" :placeholder="t('runFlow.inputCodeTip')" clearable filterable
@change="cascadeChange('flowInstId', ['runNodeId'])" style="max-width: 180px">
<el-option v-for="(item, index) in dicData.flowInstId" :key="index" :label="item.code" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.runNodeId')" prop="runNodeId" >
<el-select v-model="state.queryForm.runNodeId" :placeholder="t('runJob.inputRunNodeIdTip')" clearable filterable style="max-width: 180px"
@change="cascadeChange('runNodeId', ['runJobId'])">
<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-form-item :label="$t('runJob.id')" prop="id" >
<el-select v-model="state.queryForm.id" :placeholder="t('runJob.inputIdTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in cascadeDic.runJobId" :key="index" :label="item.jobName" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.status')" prop="status" >
<el-select v-model="state.queryForm.status" :placeholder="t('runJob.inputStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.NODE_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.flowStatus')" prop="status" >
<el-select v-model="state.queryForm.flowStatus" :placeholder="t('runJob.inputFlowStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.FLOW_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-tabs v-model="data.activeName" class="demo-tabs" @tab-click="methods.handleTabClick">
<el-tab-pane label="全部" name="-1"></el-tab-pane>
<el-tab-pane label="已办理" name="0"></el-tab-pane>
<el-tab-pane label="被抄送" name="1"></el-tab-pane>
<el-tab-pane label="已阅" name="2"></el-tab-pane>
<el-tab-pane label="被加签" name="3"></el-tab-pane>
</el-tabs>
<right-toolbar v-model:showSearch="showSearch" :export="'jsonflow_runjob_export'"
@exportExcel="exportExcel" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
@sort-change="sortChangeHandle">
<el-table-column type="index" :label="t('runJob.index')" width="40"/>
<el-table-column prop="initiatorId" :label="t('runFlow.initiatorId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.initiatorId" :value="scope.row.initiatorId"
:valueKey="'userId'" :showKey="'name'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="code" :label="t('runFlow.code')" show-overflow-tooltip/>
<el-table-column prop="flowName" :label="t('runJob.defFlowId')" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="orderId" :label="t('flowApplication.formName')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.orderId" :value="scope.row.orderId"
:valueKey="'id'" :showKey="'formName'"></convert-name>
</template>
</el-table-column>
<!-- <el-table-column prop="runNodeId" :label="t('runJob.runNodeId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.runNodeId" :value="scope.row.runNodeId"
:valueKey="'id'" :showKey="'nodeName'"></convert-name>
</template>
</el-table-column>-->
<el-table-column prop="jobName" :label="t('runJob.jobName')" show-overflow-tooltip/>
<el-table-column prop="jobType" :label="t('runJob.jobType')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.JOB_USER_TYPE" :value="scope.row.jobType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" :label="t('runJob.roleId')">
<template #default="scope">
<convert-role-name :options="{users: state.dicData.users, roles: state.dicData.roles, posts: state.dicData.posts, depts: state.dicData.depts }"
:value="scope.row"></convert-role-name>
</template>
</el-table-column>
<el-table-column prop="userId" :label="t('runJob.userId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.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="endTime" :label="t('runJob.endTime')" show-overflow-tooltip/>
<!-- <el-table-column prop="timeLimit" :label="t('runJob.timeLimit')" show-overflow-tooltip/>-->
<el-table-column prop="useTime" :label="t('runJob.useTime')" show-overflow-tooltip/>
<!-- <el-table-column prop="suspensionReason" :label="t('runJob.suspensionReason')" show-overflow-tooltip/>
<el-table-column prop="invalidReason" :label="t('runJob.invalidReason')" 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-column prop="flowStatus" :label="t('runJob.flowStatus')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.FLOW_STATUS" :value="scope.row.flowStatus"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="parFlowInstId" :label="t('runJob.parFlowInstId')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="点击可查看关联父流程工单信息" v-if="scope.row.parFlowInstId">
<convert-name :options="state.dicData.parFlowInstId" :value="scope.row.parFlowInstId"
:valueKey="'id'" :showKey="'flowName'"
:elTagType="'primary'" @click="methods.handleJobByFlowInstId(scope.row, '1')"></convert-name>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="subFlowInstId" :label="t('runJob.subFlowInstId')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="点击可查看关联子流程工单信息" v-if="scope.row.subFlowInstId">
<convert-name :options="state.dicData.subFlowInstId" :value="scope.row.subFlowInstId"
:valueKey="'id'" :showKey="'flowName'"
:elTagType="'primary'" @click="methods.handleJobByFlowInstId(scope.row, '2')"></convert-name>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('common.action')" width="120">
<template #default="scope">
<el-tooltip placement="top">
<template #content>
查看工单
</template>
<el-button text type="primary" icon="view" @click="methods.handleJob(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top">
<template #content>
查看审批过程
</template>
<el-button text type="primary" icon="Operation" @click="methods.handleComment(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top">
<template #content>
查看流程图
</template>
<el-button text type="primary" icon="Share" @click="methods.handleFlowPic(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top" v-if="scope.row.flowStatus === '0' && scope.row.belongType !== '2'">
<template #content>
取回任务
</template>
<el-button text type="primary" icon="CirclePlus" @click="methods.handleRetakeJob(scope.row, '1')">
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination"/>
</div>
<!-- 查看审批过程 -->
<el-dialog v-model="data.showComment" v-if="data.showComment"
top="20px" width="90%"
title="查看审批过程" append-to-body>
<comment :currJob="data.currJob"></comment>
</el-dialog>
<!-- 查看流程图 -->
<el-drawer
class="flow-overflow-drawer" direction="rtl"
append-to-body size="90%"
v-model="data.showFlowPic"
>
<flow-photo v-if="data.showFlowPic" :currJob="data.currJob"></flow-photo>
</el-drawer>
</div>
</template>
<script setup lang="ts" name="HiJob">
import {BasicTableProps, useTable} from "/@/hooks/table";
import {fetchToDonePage, retakeJob} from '/@/api/jsonflow/hi-job'
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
import {onCascadeChange, onLoadDicUrl, onLoaded, remoteMethodByKey} from "/@/flow/components/convert-name/convert";
import {openFlowPreview} from "/@/flow/support/extend";
import {PROP_CONST} from "/@/flow/support/prop-const";
const $message = useMessage();
const {proxy} = getCurrentInstance();
const router = useRouter();
// 引入组件
const Comment = defineAsyncComponent(() => import('../comment/timeline.vue'));
const FlowPhoto = defineAsyncComponent(() => import('../flow-design/view.vue'));
const {t} = useI18n()
// 定义查询字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl({key: "flowInstId"});
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["runNodeId"]}, {key: "runNodeId", cascades: ["runJobId"]});
onMounted(() => {
onLoad(dicData);
});
function cascadeChange(key, cascades){
onCascade(state.queryForm, {key: key, cascades: cascades});
}
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
const data = reactive({
currJob: {},
showComment: false,
showFlowPic: false,
activeName: '-1'
});
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {queryJobType: '0', belongType: data.activeName},
pageList: fetchToDonePage,
onLoaded: onLoaded({key: "userId"}, {key: "initiatorId"}, {key: "parFlowInstId"}, {key: "subFlowInstId"}, {key: "orderId"}, {key: "runNodeId"}, ...PROP_CONST.LOAD_USER_ROLE),
descs: ["end_time"]
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/jsonflow/run-job/export', state.queryForm, 'run-job.xlsx')
}
function remoteMethod(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'userName', "initiatorId")
}
const methods = {
handleTabClick(tab) {
if (data.activeName === tab.paneName) return
state.queryForm.signatureType = null
state.queryForm.belongType = null
if (tab.paneName !== '3') {
state.queryForm.belongType = tab.paneName
} else {
state.queryForm.belongType = '0'
// 仅标识
state.queryForm.signatureType = '-1'
}
getDataList(true)
},
handleJobByFlowInstId(row, type) {
let find;
if (type === '1') {
find = state.dicData.parFlowInstId.find(f => f.id === row.parFlowInstId);
} else {
find = state.dicData.subFlowInstId.find(f => f.id === row.subFlowInstId);
}
methods.handleJob({flowInstId: find.id})
},
handleJob(row) {
openFlowPreview(router, row)
},
handleRetakeJob(row) {
retakeJob(row).then(() => {
getDataList();
})
},
handleComment(row) {
data.currJob = row
data.showComment = true
},
handleFlowPic(row) {
data.currJob = row
data.showFlowPic = true
}
}
</script>
<style lang="scss">
@import "../../../flow/components/style/flow-drawer.scss";
</style>

View File

@@ -0,0 +1,68 @@
export default {
runJob: {
index: '#',
importrunJobTip: 'import RunJob',
id: 'id',
sort: 'sort',
defFlowId: 'defFlowId',
parFlowInstId: 'parFlowInstId',
subFlowInstId: 'subFlowInstId',
flowNodeId: 'flowNodeId',
nodeJobId: 'nodeJobId',
jobType: 'jobType',
roleId: 'roleId',
userId: 'userId',
startTime: 'startTime',
endTime: 'endTime',
timeLimit: 'timeLimit',
useTime: 'useTime',
userKey: 'userKey',
jobName: 'jobName',
distFlowNodeId: 'distFlowNodeId',
timeout: 'timeout',
status: 'status',
suspension: 'suspension',
suspensionReason: 'suspensionReason',
invalidReason: 'invalidReason',
flowStatus: 'flowStatus',
isSkipRejected: 'isSkipRejected',
createUser: 'createUser',
createTime: 'createTime',
flowKey: 'flowKey',
flowInstId: 'flowInstId',
runNodeId: 'runNodeId',
isNowRun: 'isNowRun',
signatureType: 'signatureType',
isRead: 'isRead',
inputIdTip: 'input id',
inputSortTip: 'input sort',
inputDefFlowIdTip: 'input defFlowId',
inputParFlowInstIdTip: 'input parFlowInstId',
inputSubFlowInstIdTip: 'input subFlowInstId',
inputFlowNodeIdTip: 'input flowNodeId',
inputNodeJobIdTip: 'input nodeJobId',
inputJobTypeTip: 'input jobType',
inputRoleIdTip: 'input roleId',
inputUserIdTip: 'input userId',
inputStartTimeTip: 'input startTime',
inputEndTimeTip: 'input endTime',
inputUserKeyTip: 'input userKey',
inputJobNameTip: 'input jobName',
inputDistFlowNodeIdTip: 'input distFlowNodeId',
inputTimeoutTip: 'input timeout',
inputStatusTip: 'input status',
inputFlowStatusTip: 'input flowStatus',
inputSuspensionTip: 'input suspension',
inputSuspensionReasonTip: 'input suspensionReason',
inputIsSkipRejectedTip: 'input isSkipRejected',
inputCreateUserTip: 'input createUser',
inputCreateTimeTip: 'input createTime',
inputFlowKeyTip: 'input flowKey',
inputFlowInstIdTip: 'input flowInstId',
inputRunNodeIdTip: 'input runNodeId',
inputIsNowRunTip: 'input isNowRun',
inputSignatureTypeTip: 'input signatureType',
inputIsReadTip: 'input isRead',
}
}

View File

@@ -0,0 +1,68 @@
export default {
runJob: {
index: '#',
importrunJobTip: '导入任务记录',
id: ' 任务名称',
sort: '排序值',
defFlowId: '流程名称',
parFlowInstId: '关联父流程',
subFlowInstId: '关联子流程',
flowNodeId: '节点名称',
nodeJobId: '任务名称',
jobType: '参与者类型',
roleId: '参与者',
userId: '审批人',
startTime: '开始时间',
endTime: '结束时间',
timeLimit: '任务时限',
useTime: '任务用时',
userKey: '参与者KEY',
jobName: '任务名称',
distFlowNodeId: '待分配参与者节点',
timeout: '任务时限(分钟)',
status: '任务状态',
suspension: '是否挂起',
suspensionReason: '挂起原因',
invalidReason: '作废原因',
flowStatus: '流程状态',
isSkipRejected: '被驳回是否可跳过',
createUser: '创建人',
createTime: '创建时间',
flowKey: '工单流程KEY',
flowInstId: '流程实例ID',
runNodeId: '节点名称',
isNowRun: '被分配后是否立即运行',
signatureType: '加签类型',
isRead: '是否已阅',
inputIdTip: '请输入任务名称',
inputSortTip: '请输入排序值',
inputDefFlowIdTip: '请输入流程名称',
inputParFlowInstIdTip: '请输入关联父流程',
inputSubFlowInstIdTip: '请输入关联子流程',
inputFlowNodeIdTip: '请输入节点名称',
inputNodeJobIdTip: '请输入任务名称',
inputJobTypeTip: '请输入参与者类型',
inputRoleIdTip: '请输入参与者',
inputUserIdTip: '请输入审批人',
inputStartTimeTip: '请输入开始时间',
inputEndTimeTip: '请输入结束时间',
inputUserKeyTip: '请输入参与者KEY',
inputJobNameTip: '请输入任务名称',
inputDistFlowNodeIdTip: '请输入待分配参与者节点',
inputTimeoutTip: '请输入任务时限',
inputStatusTip: '请输入任务状态',
inputFlowStatusTip: '请输入流程状态',
inputSuspensionTip: '请输入是否挂起',
inputSuspensionReasonTip: '请输入挂起原因',
inputIsSkipRejectedTip: '请输入被驳回是否可跳过',
inputCreateUserTip: '请输入创建人',
inputCreateTimeTip: '请输入创建时间',
inputFlowKeyTip: '请输入工单流程KEY',
inputFlowInstIdTip: '请输入流程实例ID',
inputRunNodeIdTip: '请输入节点名称',
inputIsNowRunTip: '请输入被分配后是否立即运行',
inputSignatureTypeTip: '请输入加签类型',
inputIsReadTip: '请输入是否已阅',
}
}

View File

@@ -0,0 +1,510 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-row v-show="showSearch">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item :label="t('runJob.jobType')" prop="jobType">
<el-select v-model="state.queryForm.jobType" :placeholder="t('runJob.inputJobTypeTip')" clearable filterable style="max-width: 180px"
@change="handleRoleType">
<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="t('runJob.roleId')" prop="roleId">
<el-tooltip content="请输入名称进行模糊搜索" placement="top">
<el-select v-model="state.queryForm.roleId" :placeholder="t('runJob.inputRoleIdTip')" clearable filterable style="max-width: 180px"
remote :remote-method="(query) => remoteMethodAll(query, state.queryForm.jobType)" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.users" :key="index" :label="item.name" :value="item.userId"
v-if="state.queryForm.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="state.queryForm.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="state.queryForm.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="state.queryForm.jobType === DIC_PROP.JOB_USER_TYPE[3].value"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item :label="$t('runJob.flowInstId')" prop="flowInstId" >
<el-input :placeholder="t('runJob.inputFlowInstIdTip')" v-model="state.queryForm.flowInstId"
@change="cascadeChange('flowInstId', ['runNodeId'])"
style="max-width: 180px" />
</el-form-item>
<el-form-item :label="$t('runJob.runNodeId')" prop="runNodeId" >
<el-select v-model="state.queryForm.runNodeId" :placeholder="t('runJob.inputRunNodeIdTip')" clearable filterable style="max-width: 180px"
@change="cascadeChange('runNodeId', ['runJobId'])">
<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-form-item :label="$t('runJob.id')" prop="id" >
<el-select v-model="state.queryForm.id" :placeholder="t('runJob.inputIdTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in cascadeDic.runJobId" :key="index" :label="item.jobName" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.status')" prop="status" >
<el-select v-model="state.queryForm.status" :placeholder="t('runJob.inputStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.NODE_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-tooltip placement="top">
<template #content>
{{ $t('common.addBtn') }}
</template>
<el-button icon="Plus" type="primary" class="ml10" @click="formDialogRef.openDialog('add')"
v-auth="'jsonflow_runjob_add'">
</el-button>
</el-tooltip>
<el-tooltip placement="top">
<template #content>
{{ $t('common.delBtn') }}
</template>
<el-button plain :disabled="multiple" icon="Delete" type="primary" class="ml10"
v-auth="'jsonflow_runjob_del'" @click="handleDelete(selectObjs)">
</el-button>
</el-tooltip>
<right-toolbar v-model:showSearch="showSearch" :export="'jsonflow_runjob_export'"
@exportExcel="exportExcel" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
:row-class-name="tableRowClassName"
@sort-change="sortChangeHandle">
<el-table-column type="index" :label="t('runJob.index')" width="40" />
<el-table-column prop="flowInstId" :label="t('runJob.flowInstId')" show-overflow-tooltip/>
<el-table-column prop="defFlowId" :label="t('runJob.defFlowId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.flowInstId" :value="scope.row.defFlowId"
:valueKey="'defFlowId'" :showKey="'flowName'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="runNodeId" :label="t('runJob.runNodeId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.runNodeId" :value="scope.row.runNodeId"
:valueKey="'id'" :showKey="'nodeName'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="jobName" :label="t('runJob.jobName')" show-overflow-tooltip/>
<el-table-column prop="jobType" :label="t('runJob.jobType')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.JOB_USER_TYPE" :value="scope.row.jobType"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="roleId" :label="t('runJob.roleId')">
<template #default="scope">
<convert-role-name :options="{users: state.dicData.users, roles: state.dicData.roles, posts: state.dicData.posts, depts: state.dicData.depts }"
:value="scope.row"></convert-role-name>
</template>
</el-table-column>
<el-table-column prop="userId" :label="t('runJob.userId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.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="endTime" :label="t('runJob.endTime')" show-overflow-tooltip/>
<el-table-column prop="userKey" :label="t('runJob.userKey')" show-overflow-tooltip>
</el-table-column>
<!-- <el-table-column prop="distFlowNodeId" :label="t('runJob.distFlowNodeId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.runNodeId" :value="scope.row.distFlowNodeId"
:valueKey="'flowNodeId'" :showKey="'nodeName'"></convert-name>
</template>
</el-table-column>-->
<el-table-column prop="timeout" :label="t('runJob.timeout')" 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-column prop="suspension" :label="t('runJob.suspension')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.suspension"></dict-tag>
</template>
</el-table-column>-->
<el-table-column prop="suspensionReason" :label="t('runJob.suspensionReason')" show-overflow-tooltip/>
<!-- <el-table-column prop="isSkipRejected" :label="t('runJob.isSkipRejected')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.isSkipRejected"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="isNowRun" :label="t('runJob.isNowRun')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.isNowRun"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="createUser" :label="t('runJob.createUser')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.createUser" :value="scope.row.createUser"
:valueKey="'userId'" :showKey="'name'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="t('runJob.createTime')" show-overflow-tooltip/>-->
<el-table-column prop="flowStatus" :label="t('runJob.flowStatus')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.FLOW_STATUS" :value="scope.row.flowStatus"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="sort" :label="t('runJob.sort')" show-overflow-tooltip/>
<el-table-column :label="$t('common.action')" width="180">
<template #default="scope">
<el-dropdown style="vertical-align: middle; margin-right: 10px">
<span>
功能
<el-icon class="el-icon--right">
<arrow-down/>
</el-icon>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
@click.native="methods.handleComment(scope.row)">查看审批过程
</el-dropdown-item>
<el-dropdown-item
divided
@click.native="methods.handleFlowPic(scope.row)">查看流程图
</el-dropdown-item>
<template v-if="DIC_PROP.FLOW_STATUS[2].value === scope.row.flowStatus">
<template v-if="scope.row.status === '0' || scope.row.status === '9'">
<el-dropdown-item
v-if="scope.row.jobType !== DIC_PROP.JOB_USER_TYPE[0].value"
divided
@click.native="methods.handleSignForJob(scope.row, '1')"
>签收任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.jobType === DIC_PROP.JOB_USER_TYPE[0].value && scope.row.roleId"
divided
@click.native="methods.handleSignForJob(scope.row, '0')"
>反签收任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension === '1'"
divided
@click.native="methods.handleSuspension(scope.row,'0')"
>激活任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension !== '1'"
divided
@click.native="methods.handleSuspension(scope.row,'1')"
>挂起任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension !== '1' && scope.row.roleId"
divided
@click.native="methods.handleJobRoleUserId(scope.row,'0')">
转办任务
</el-dropdown-item>
<el-dropdown-item
v-if="scope.row.suspension !== '1' && !scope.row.roleId"
divided
@click.native="methods.handleJobRoleUserId(scope.row,'1')">
指派人员
</el-dropdown-item>
</template>
<el-dropdown-item divided
@click.native="methods.handleEarlyComplete(scope.row)">
提前结束流程
</el-dropdown-item>
<el-dropdown-item divided
@click.native="methods.handleTerminateFlow(scope.row)">
终止流程
</el-dropdown-item>
<el-dropdown-item divided
@click.native="methods.handleInvalidFlow(scope.row)">
作废流程
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-tooltip placement="top">
<template #content>
{{ $t('common.editBtn') }}
</template>
<el-button icon="edit-pen" text type="primary" @click="formDialogRef.openDialog('edit', scope.row.id)">
</el-button>
</el-tooltip>
<template v-if="!scope.row.roleId || (scope.row.status !== '0' && scope.row.status !== '9')">
<el-tooltip placement="top">
<template #content>
查看工单
</template>
<el-button text type="primary" icon="view" @click="methods.handleHiJob(scope.row)">
</el-button>
</el-tooltip>
</template>
<template v-if="scope.row.roleId && DIC_PROP.FLOW_STATUS[2].value === scope.row.flowStatus">
<el-button icon="Stamp" text type="primary"
v-if="scope.row.suspension !== '1' && (scope.row.status === '0' || scope.row.status === '9') && scope.row.belongType !== '2'"
@click="methods.handleJob(scope.row)">审批
</el-button>
<el-button icon="Stamp" text type="primary"
v-if="scope.row.suspension !== '1' && scope.row.belongType === '2' && scope.row.isRead === '0'"
@click="methods.handleJob(scope.row, '0', '1')">查看
</el-button>
</template>
<!-- <el-tooltip placement="top">
<template #content>
{{ $t('common.viewBtn') }}
</template>
<el-button text type="primary" icon="view" @click="formDialogRef.openDialog('view', scope.row.id)">
</el-button>
</el-tooltip>-->
<!-- <el-tooltip placement="top">
<template #content>
{{ $t('common.delBtn') }}
</template>
<el-button icon="delete" text type="primary" @click="handleDelete([scope.row.id])">
</el-button>
</el-tooltip>-->
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
</div>
<!-- 编辑、新增 -->
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
<!-- 查看审批过程 -->
<el-dialog
v-model="data.showComment" v-if="data.showComment"
top="20px"
width="90%"
title="查看审批过程"
append-to-body>
<comment :curr-job="data.currJob"></comment>
</el-dialog>
<!-- 查看流程图 -->
<el-drawer
class="flow-overflow-drawer" direction="rtl"
append-to-body size="90%"
v-model="data.showFlowPic"
>
<flow-photo v-if="data.showFlowPic" :curr-job="data.currJob"></flow-photo>
</el-drawer>
<user-role-picker ref="userRolePicker" :isOnlyOne="true" @onSelectItems="methods.onSelectItems">
</user-role-picker>
</div>
</template>
<script setup lang="ts" name="systemRunJob">
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/jsonflow/run-job";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useI18n } from "vue-i18n";
import {
onCascadeChange,
onLoadDicUrl,
onLoaded,
remoteMethodAllByKey,
} from "/@/flow/components/convert-name/convert";
import {handleFlowPreview, openFlowPreview} from "/@/flow/support/extend";
import {useFlowJob} from "/@/flow/stores/flowJob";
import {PROP_CONST} from "/@/flow/support/prop-const";
import {handleChangeJobType} from "/@/flow";
import {
handleEarlyComplete, handleInvalidFlow,
handleSignForJob,
handleSuspension,
handleTerminateFlow, onJobNextUserRole,
onSignForJob, onTurnRunJob
} from "/@/flow/components/handle-job";
const $message = useMessage();
const {proxy} = getCurrentInstance();
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
const UserRolePicker = defineAsyncComponent(() => import('../../../flow/components/user-role/picker.vue'));
const Comment = defineAsyncComponent(() => import('../comment/timeline.vue'));
const FlowPhoto = defineAsyncComponent(() => import('../flow-design/view.vue'));
const flowJob = useFlowJob()
const {t} = useI18n()
const $router = useRouter();
// 定义查询字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl();
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["runNodeId"]}, {key: "runNodeId", cascades: ["runJobId"]});
onMounted(() => {
// onLoad(dicData);
});
function cascadeChange(key, cascades){
onCascade(state.queryForm, {key: key, cascades: cascades});
}
// 定义变量内容
const formDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const data = reactive({
// 0、转办 1、指派
nodeUserType: undefined,
currJob: undefined,
queryForm: {},
showComment: false,
showFlowPic: false,
activeName: '-1'
});
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList,
onLoaded: onLoaded({key: "userId"}, {key: "flowInstId"}, {key: "runNodeId"}, ...PROP_CONST.LOAD_USER_ROLE),
descs: ["receive_time"]
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/jsonflow/run-job/export', state.queryForm, 'run-job.xlsx')
}
const tableRowClassName = ({row, rowIndex}) => {
if (row.isRead !== '1') {
return 'row-custom-warning'
}
return ''
}
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm(t('common.delConfirmText'));
} catch {
return;
}
try {
await delObjs(ids);
getDataList();
useMessage().success(t('common.delSuccessText'));
} catch (err: any) {
useMessage().error(err.msg);
}
};
function remoteMethodAll(query: string, jobType) {
remoteMethodAllByKey(onLoad, dicData, query, jobType)
}
function handleRoleType() {
handleChangeJobType(dicData, state.queryForm)
}
const methods = {
handleHiJob(row) {
openFlowPreview($router, row)
},
handleJob(row, isView?, isRead?) {
handleFlowPreview($router, row, isView, isRead, $message, flowJob, getDataList)
},
handleJobRoleUserId(row, type) {
data.currJob = row
methods.openJobRoleUserId(type)
},
// 指定任务参与者
onJobNextUserRole(items) {
onJobNextUserRole($message, items, getDataList, data)
},
handleComment(row) {
data.currJob = row
data.showComment = true
},
handleFlowPic(row) {
data.currJob = row
data.showFlowPic = true
},
// 签收反签收任务
handleSignForJob(row, type) {
handleSignForJob(methods, $message, getDataList, row, type)
},
// 反签收任务
onSignForJob(obj) {
onSignForJob($message, flowJob, getDataList, obj)
},
// 挂起激活任务
handleSuspension(row, suspension) {
handleSuspension($message, getDataList, row, suspension)
},
// 选择参与者
openJobRoleUserId(type) {
data.nodeUserType = type
proxy.$refs.userRolePicker.onOpen();
},
onSelectItems(items) {
if (data.nodeUserType === '0') {
methods.onTurnRunJob(items[0])
} else {
methods.onJobNextUserRole(items)
}
},
// 提前结束流程
handleEarlyComplete(row) {
handleEarlyComplete($message, flowJob, getDataList, row)
},
// 终止流程
handleTerminateFlow(row) {
handleTerminateFlow($message, flowJob, getDataList, row)
},
// 作废流程
handleInvalidFlow(row) {
handleInvalidFlow($message, flowJob, getDataList, row)
},
// 转办任务
onTurnRunJob(role) {
onTurnRunJob($message, flowJob, getDataList, data, role)
}
}
</script>
<style lang="scss">
@import "../../../flow/components/style/flow-drawer.scss";
.el-table .row-custom-warning {
--el-table-tr-bg-color: var(--el-color-warning-light-9);
}
</style>

View File

@@ -0,0 +1,293 @@
<template>
<div class="layout-padding">
<div class="layout-padding-auto layout-padding-view">
<el-row v-show="showSearch">
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
<el-form-item :label="$t('runFlow.initiatorId')" prop="initiatorId" >
<el-tooltip content="请输入用户名称进行模糊搜索" placement="top">
<el-select v-model="state.queryForm.initiatorId" :placeholder="t('runFlow.inputInitiatorIdTip')" clearable filterable style="max-width: 180px"
remote :remote-method="remoteMethod" :reserve-keyword="false">
<el-option v-for="(item, index) in dicData.initiatorId" :key="index" :label="item.name" :value="item.userId"></el-option>
</el-select>
</el-tooltip>
</el-form-item>
<el-form-item :label="$t('runFlow.code')" prop="flowInstId" >
<el-select v-model="state.queryForm.flowInstId" :placeholder="t('runFlow.inputCodeTip')" clearable filterable
@change="cascadeChange('flowInstId', ['runNodeId'])" style="max-width: 180px">
<el-option v-for="(item, index) in dicData.flowInstId" :key="index" :label="item.code" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.runNodeId')" prop="runNodeId" >
<el-select v-model="state.queryForm.runNodeId" :placeholder="t('runJob.inputRunNodeIdTip')" clearable filterable style="max-width: 180px"
@change="cascadeChange('runNodeId', ['runJobId'])">
<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-form-item :label="$t('runJob.id')" prop="id" >
<el-select v-model="state.queryForm.id" :placeholder="t('runJob.inputIdTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in cascadeDic.runJobId" :key="index" :label="item.jobName" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('runJob.status')" prop="status" >
<el-select v-model="state.queryForm.status" :placeholder="t('runJob.inputStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.NODE_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item :label="$t('runJob.flowStatus')" prop="status" >
<el-select v-model="state.queryForm.flowStatus" :placeholder="t('runJob.inputFlowStatusTip')" clearable filterable style="max-width: 180px">
<el-option v-for="(item, index) in DIC_PROP.FLOW_STATUS" :key="index" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>-->
<el-form-item>
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<right-toolbar v-model:showSearch="showSearch" :export="'jsonflow_runjob_export'"
@exportExcel="exportExcel" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
@sort-change="sortChangeHandle">
<el-table-column type="index" :label="t('runJob.index')" width="40"/>
<el-table-column prop="initiatorId" :label="t('runFlow.initiatorId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.initiatorId" :value="scope.row.initiatorId"
:valueKey="'userId'" :showKey="'name'"></convert-name>
</template>
</el-table-column>
<el-table-column prop="code" :label="t('runFlow.code')" show-overflow-tooltip/>
<el-table-column prop="flowName" :label="t('runJob.defFlowId')" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="orderId" :label="t('flowApplication.formName')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.orderId" :value="scope.row.orderId"
:valueKey="'id'" :showKey="'formName'"></convert-name>
</template>
</el-table-column>
<!-- <el-table-column prop="runNodeId" :label="t('runJob.runNodeId')" show-overflow-tooltip>
<template #default="scope">
<convert-name :options="state.dicData.runNodeId" :value="scope.row.runNodeId"
:valueKey="'id'" :showKey="'nodeName'"></convert-name>
</template>
</el-table-column>-->
<el-table-column prop="jobName" :label="t('runJob.jobName')" show-overflow-tooltip/>
<el-table-column prop="startTime" :label="t('runJob.startTime')" show-overflow-tooltip/>
<!-- <el-table-column prop="timeLimit" :label="t('runJob.timeLimit')" 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-column prop="suspension" :label="t('runJob.suspension')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.YES_OR_NO" :value="scope.row.suspension"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="suspensionReason" :label="t('runJob.suspensionReason')" show-overflow-tooltip/>-->
<el-table-column prop="flowStatus" :label="t('runJob.flowStatus')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="DIC_PROP.FLOW_STATUS" :value="scope.row.flowStatus"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="parFlowInstId" :label="t('runJob.parFlowInstId')" show-overflow-tooltip>
<template #default="scope">
<el-tooltip placement="top" content="点击可查看关联父流程工单信息" v-if="scope.row.parFlowInstId">
<convert-name :options="state.dicData.parFlowInstId" :value="scope.row.parFlowInstId"
:valueKey="'id'" :showKey="'flowName'"
:elTagType="'primary'" @click="methods.handleJobByFlowInstId(scope.row, '1')"></convert-name>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-tooltip placement="top">
<template #content>
查看工单
</template>
<el-button text type="primary" icon="view" @click="methods.handleJob(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top">
<template #content>
查看审批过程
</template>
<el-button text type="primary" icon="Operation" @click="methods.handleComment(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top">
<template #content>
查看流程图
</template>
<el-button text type="primary" icon="Share" @click="methods.handleFlowPic(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top" v-if="validateStatus(scope.row)">
<template #content>
指派人员
</template>
<el-button text type="primary" icon="Pointer" @click="methods.handleAppointUser(scope.row)">
</el-button>
</el-tooltip>
<el-tooltip placement="top" v-if="validateStatus(scope.row)">
<template #content>
签收任务
</template>
<el-button text type="primary" icon="CirclePlus" @click="methods.handleSignForJob(scope.row, '1')">
</el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
v-bind="state.pagination"/>
</div>
<!-- 查看审批过程 -->
<el-dialog v-model="data.showComment" v-if="data.showComment"
top="20px" width="90%"
title="查看审批过程" append-to-body>
<comment :currJob="data.currJob"></comment>
</el-dialog>
<!-- 查看流程图 -->
<el-drawer
class="flow-overflow-drawer" direction="rtl"
append-to-body size="90%"
v-model="data.showFlowPic"
>
<flow-photo v-if="data.showFlowPic" :currJob="data.currJob"></flow-photo>
</el-drawer>
<user-role-picker ref="userRolePicker" :isOnlyOne="true" @onSelectItems="methods.onJobNextUserRole">
</user-role-picker>
</div>
</template>
<script setup lang="ts" name="HiJob">
import {BasicTableProps, useTable} from "/@/hooks/table";
import {fetchToDonePage} from '/@/api/jsonflow/hi-job'
import {useMessage, useMessageBox} from "/@/hooks/message";
import {useI18n} from "vue-i18n";
import {onCascadeChange, onLoadDicUrl, onLoaded, remoteMethodByKey} from "/@/flow/components/convert-name/convert";
import {signForJob, appointUser} from "/@/api/jsonflow/do-job";
import {openFlowPreview} from "/@/flow/support/extend";
import {onJobNextUserRole} from "/@/flow/components/handle-job";
const $message = useMessage();
const {proxy} = getCurrentInstance();
// 引入组件
const Comment = defineAsyncComponent(() => import('../comment/timeline.vue'));
const FlowPhoto = defineAsyncComponent(() => import('../flow-design/view.vue'));
const UserRolePicker = defineAsyncComponent(() => import('../../../flow/components/user-role/picker.vue'));
const {t} = useI18n()
const router = useRouter();
// 定义查询字典
const dicData = reactive({});
const cascadeDic = reactive({});
const onLoad = onLoadDicUrl({key: "flowInstId"});
const onCascade = onCascadeChange(cascadeDic, {key: "flowInstId", cascades: ["runNodeId"]}, {key: "runNodeId", cascades: ["runJobId"]});
onMounted(() => {
onLoad(dicData);
});
function cascadeChange(key, cascades){
onCascade(state.queryForm, {key: key, cascades: cascades});
}
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
const data = reactive({
currJob: {},
showComment: false,
showFlowPic: false
});
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {queryJobType: '1', flowStatus: '0'},
pageList: fetchToDonePage,
onLoaded: onLoaded({key: "initiatorId"}, {key: "parFlowInstId"}, {key: "orderId"}, {key: "runNodeId"}),
descs: ["start_time"]
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/jsonflow/run-job/export', state.queryForm, 'run-job.xlsx')
}
function validateStatus(row) {
return (row.status === '0' || row.status === '9') && !row.roleId && row.flowStatus === '0';
}
function remoteMethod(query: string) {
remoteMethodByKey(query, onLoad, dicData, 'userName', "initiatorId")
}
const methods = {
handleJobByFlowInstId(row, type) {
let find;
if (type === '1') {
find = state.dicData.parFlowInstId.find(f => f.id === row.parFlowInstId);
}
methods.handleJob({flowInstId: find.id})
},
handleJob(row) {
openFlowPreview(router, row)
},
// 指派任务
handleAppointUser(row) {
data.currJob = row
proxy.$refs.userRolePicker.onOpen();
},
// 指定任务参与者
onJobNextUserRole(items) {
onJobNextUserRole($message, items, getDataList, data)
},
// 签收任务
handleSignForJob(row, type) {
let obj = {id: row.id, signForType: type};
signForJob(obj).then(() => {
$message.success('操作成功');
getDataList();
})
},
handleComment(row) {
data.currJob = row
data.showComment = true
},
handleFlowPic(row) {
data.currJob = row
data.showFlowPic = true
}
}
</script>
<style lang="scss">
@import "../../../flow/components/style/flow-drawer.scss";
</style>