Commit fabdccd981c442823dad0a376dfda453ce8ccc8f

Authored by YunaiV
1 parent 62a86fdf

bpm:流程分配任务的列表 50%

yudao-ui-admin-vue3/package.json
@@ -52,6 +52,7 @@ @@ -52,6 +52,7 @@
52 "vue-i18n": "9.2.2", 52 "vue-i18n": "9.2.2",
53 "vue-router": "^4.1.6", 53 "vue-router": "^4.1.6",
54 "vue-types": "^5.0.2", 54 "vue-types": "^5.0.2",
  55 + "vue3-treeselect": "^0.1.10",
55 "vxe-table": "^4.3.9", 56 "vxe-table": "^4.3.9",
56 "web-storage-cache": "^1.1.1", 57 "web-storage-cache": "^1.1.1",
57 "xe-utils": "^3.5.7" 58 "xe-utils": "^3.5.7"
yudao-ui-admin-vue3/src/router/modules/remaining.ts
@@ -177,6 +177,39 @@ const remainingRouter: AppRouteRecordRaw[] = [ @@ -177,6 +177,39 @@ const remainingRouter: AppRouteRecordRaw[] = [
177 title: '500', 177 title: '500',
178 noTagsView: true 178 noTagsView: true
179 } 179 }
  180 + },
  181 + {
  182 + path: '/bpm',
  183 + component: Layout,
  184 + name: 'bpm',
  185 + meta: {
  186 + hidden: true
  187 + },
  188 + children: [
  189 + {
  190 + path: '/manager/definition',
  191 + component: () => import('@/views/bpm/definition/index.vue'),
  192 + name: 'BpmProcessDefinitionList',
  193 + meta: {
  194 + noCache: true,
  195 + hidden: true,
  196 + canTo: true,
  197 + title: '流程定义',
  198 + activeMenu: 'bpm/definition/index'
  199 + }
  200 + },
  201 + {
  202 + path: '/manager/task-assign-rule',
  203 + component: () => import('@/views/bpm/taskAssignRule/index.vue'),
  204 + name: 'BpmTaskAssignRuleList',
  205 + meta: {
  206 + noCache: true,
  207 + hidden: true,
  208 + canTo: true,
  209 + title: '任务分配规则'
  210 + }
  211 + }
  212 + ]
180 } 213 }
181 ] 214 ]
182 215
yudao-ui-admin-vue3/src/views/bpm/taskAssignRule/index.vue
1 <template> 1 <template>
2 - <div>index</div> 2 + <ContentWrap>
  3 + <!-- 列表 -->
  4 + <XTable @register="registerTable">
  5 + <template #options_default="{ row }">
  6 + <el-tag :key="option" v-for="option in row.options">
  7 + {{ getAssignRuleOptionName(row.type, option) }}
  8 + </el-tag>
  9 + </template>
  10 + <!-- 操作 -->
  11 + <template #actionbtns_default="{ row }" v-if="modelId">
  12 + <vxe-button
  13 + type="text"
  14 + status="primary"
  15 + content="修改"
  16 + icon="vxe-icon-edit"
  17 + @click="handleUpdate(row)"
  18 + />
  19 + </template>
  20 + </XTable>
  21 +
  22 + <!-- 添加/修改弹窗 -->
  23 + <XModal v-model="openVisible" title="修改任务规则" width="800" height="35%" resize>
  24 + <el-form
  25 + ref="xForm"
  26 + :model="formData"
  27 + :rules="formRules"
  28 + label-width="120px"
  29 + class="demo-ruleForm"
  30 + size="default"
  31 + status-icon
  32 + >
  33 + <el-form-item label="任务名称" prop="taskDefinitionName">
  34 + <el-input -model="formData.taskDefinitionName" placeholder="请输入流标标识" disabled />
  35 + </el-form-item>
  36 + <el-form-item label="任务标识" prop="taskDefinitionKey">
  37 + <el-input v-model="formData.taskDefinitionKey" placeholder="请输入任务标识" disabled />
  38 + </el-form-item>
  39 + <el-form-item label="规则类型" prop="type">
  40 + <el-select v-model="formData.type" clearable style="width: 100%">
  41 + <el-option
  42 + v-for="dict in taskAssignRuleTypeDictDatas"
  43 + :key="parseInt(dict.value)"
  44 + :label="dict.label"
  45 + :value="parseInt(dict.value)"
  46 + />
  47 + </el-select>
  48 + </el-form-item>
  49 + <el-form-item v-if="formData.type === 10" label="指定角色" prop="roleIds">
  50 + <el-select v-model="formData.roleIds" multiple clearable style="width: 100%">
  51 + <el-option
  52 + v-for="item in roleOptions"
  53 + :key="parseInt(item.id)"
  54 + :label="item.name"
  55 + :value="parseInt(item.id)"
  56 + />
  57 + </el-select>
  58 + </el-form-item>
  59 + <el-form-item
  60 + label="指定部门"
  61 + prop="deptIds"
  62 + span="24"
  63 + v-if="formData.type === 20 || formData.type === 21"
  64 + >
  65 + <treeselect
  66 + v-model="formData.deptIds"
  67 + :options="deptTreeOptions"
  68 + multiple
  69 + flat
  70 + :defaultExpandLevel="3"
  71 + placeholder="请选择指定部门"
  72 + :normalizer="normalizer"
  73 + />
  74 + </el-form-item>
  75 + <el-form-item label="指定岗位" prop="postIds" span="24" v-if="formData.type === 22">
  76 + <el-select v-model="formData.postIds" multiple clearable style="width: 100%">
  77 + <el-option
  78 + v-for="item in postOptions"
  79 + :key="parseInt(item.id)"
  80 + :label="item.name"
  81 + :value="parseInt(item.id)"
  82 + />
  83 + </el-select>
  84 + </el-form-item>
  85 + <el-form-item
  86 + label="指定用户"
  87 + prop="userIds"
  88 + span="24"
  89 + v-if="formData.type === 30 || formData.type === 31 || formData.type === 32"
  90 + >
  91 + <el-select v-model="formData.userIds" multiple clearable style="width: 100%">
  92 + <el-option
  93 + v-for="item in userOptions"
  94 + :key="parseInt(item.id)"
  95 + :label="item.nickname"
  96 + :value="parseInt(item.id)"
  97 + />
  98 + </el-select>
  99 + </el-form-item>
  100 + <el-form-item label="指定用户组" prop="userGroupIds" v-if="formData.type === 40">
  101 + <el-select v-model="formData.userGroupIds" multiple clearable style="width: 100%">
  102 + <el-option
  103 + v-for="item in userGroupOptions"
  104 + :key="parseInt(item.id)"
  105 + :label="item.name"
  106 + :value="parseInt(item.id)"
  107 + />
  108 + </el-select>
  109 + </el-form-item>
  110 + <el-form-item label="指定脚本" prop="scripts" v-if="formData.type === 50">
  111 + <el-select v-model="formData.scripts" multiple clearable style="width: 100%">
  112 + <el-option
  113 + v-for="dict in taskAssignScriptDictDatas"
  114 + :key="parseInt(dict.value)"
  115 + :label="dict.label"
  116 + :value="parseInt(dict.value)"
  117 + />
  118 + </el-select>
  119 + </el-form-item>
  120 + </el-form>
  121 + <template #footer>
  122 + <XButton type="primary" title="保存" :loading="loading" @click="submitEvent(xForm)" />
  123 + <XButton title="关闭" @click="resetEvent(xForm)" />
  124 + </template>
  125 + </XModal>
  126 + </ContentWrap>
3 </template> 127 </template>
4 -<script setup lang="ts" name="TaskAssignRule"></script> 128 +<script setup lang="ts" name="TaskAssignRule">
  129 +// 全局相关的 import
  130 +import { onMounted, reactive, ref } from 'vue'
  131 +import { ElInput, ElTag, ElOption, ElSelect, ElForm, ElFormItem } from 'element-plus'
  132 +import type { FormInstance } from 'element-plus'
  133 +
  134 +// 业务相关的 import
  135 +import Treeselect from 'vue3-treeselect'
  136 +import 'vue3-treeselect/dist/vue3-treeselect.css'
  137 +import { useXTable } from '@/hooks/web/useXTable'
  138 +import { allSchemas } from './taskAssignRule.data'
  139 +import * as TaskAssignRuleApi from '@/api/bpm/taskAssignRule'
  140 +import { listSimpleRolesApi } from '@/api/system/role'
  141 +import { handleTree } from '@/utils/tree'
  142 +import { listSimplePostsApi } from '@/api/system/post'
  143 +import { getListSimpleUsersApi } from '@/api/system/user'
  144 +import { listSimpleUserGroupsApi } from '@/api/bpm/userGroup'
  145 +import { listSimpleDeptApi } from '@/api/system/dept'
  146 +import { DICT_TYPE, getDictOptions } from '@/utils/dict'
  147 +// import {useI18n} from "@/hooks/web/useI18n";
  148 +// import {useMessage} from "@/hooks/web/useMessage";
  149 +import { useRoute } from 'vue-router'
  150 +
  151 +// const { t } = useI18n() // 国际化
  152 +// const message = useMessage() // 消息弹窗
  153 +// const router = useRouter() // 路由
  154 +const { query } = useRoute()
  155 +
  156 +// ========== 列表相关 ==========
  157 +
  158 +// 流程模型的编号。如果 modelId 非空,则用于流程模型的查看与配置
  159 +const modelId = query.modelId
  160 +// 流程定义的编号。如果 processDefinitionId 非空,则用于流程定义的查看,不支持配置
  161 +const processDefinitionId = query.processDefinitionId
  162 +// 查询参数
  163 +const queryParams = reactive({
  164 + modelId: modelId,
  165 + processDefinitionId: processDefinitionId
  166 +})
  167 +const [registerTable] = useXTable({
  168 + allSchemas: allSchemas,
  169 + params: queryParams,
  170 + getListApi: TaskAssignRuleApi.getTaskAssignRuleList,
  171 + isList: false // TODO 如果 isList 改成 true 时,进入页面不会加载数据
  172 +})
  173 +// 修改任务责任表单
  174 +const xForm = ref<FormInstance>()
  175 +const formData = ref()
  176 +const formRules = reactive({
  177 + type: [{ required: true, message: '规则类型不能为空', trigger: 'change' }],
  178 + roleIds: [{ required: true, message: '指定角色不能为空', trigger: 'change' }],
  179 + deptIds: [{ required: true, message: '指定部门不能为空', trigger: 'change' }],
  180 + postIds: [{ required: true, message: '指定岗位不能为空', trigger: 'change' }],
  181 + userIds: [{ required: true, message: '指定用户不能为空', trigger: 'change' }],
  182 + userGroupIds: [{ required: true, message: '指定用户组不能为空', trigger: 'change' }],
  183 + scripts: [{ required: true, message: '指定脚本不能为空', trigger: 'change' }]
  184 +})
  185 +const loading = ref(false)
  186 +
  187 +const roleOptions = ref() // 角色列表
  188 +const deptOptions = ref() // 部门列表
  189 +const deptTreeOptions = ref()
  190 +const postOptions = ref() // 岗位列表
  191 +const userOptions = ref() // 用户列表
  192 +const userGroupOptions = ref() // 用户组列表
  193 +const taskAssignScriptDictDatas = getDictOptions(DICT_TYPE.BPM_TASK_ASSIGN_SCRIPT)
  194 +const taskAssignRuleTypeDictDatas = getDictOptions(DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE)
  195 +
  196 +// 修改任务分配规则
  197 +const openVisible = ref(false)
  198 +
  199 +// 添加修改弹窗提交修改
  200 +const submitEvent = async (formEl: FormInstance | undefined) => {
  201 + console.log('确认')
  202 + if (!formEl) return
  203 + loading.value = true
  204 + await formEl.validate((valid, fields) => {
  205 + if (valid) {
  206 + console.log('submit!')
  207 + loading.value = false
  208 + openVisible.value = false
  209 + } else {
  210 + console.log('error submit!', fields)
  211 + loading.value = false
  212 + }
  213 + })
  214 +}
  215 +
  216 +const resetEvent = (formEl: FormInstance | undefined) => {
  217 + if (!formEl) return
  218 + formEl.resetFields()
  219 + openVisible.value = false
  220 +}
  221 +
  222 +// 修改任务分配规则
  223 +const handleUpdate = (row) => {
  224 + console.log(row, '修改i数据')
  225 + openVisible.value = true
  226 + formData.value = { ...row }
  227 +}
  228 +// 类型字典
  229 +const getAssignRuleOptionName = (type, option) => {
  230 + if (type === 10) {
  231 + for (const roleOption of roleOptions.value) {
  232 + if (roleOption.id === option) {
  233 + return roleOption.name
  234 + }
  235 + }
  236 + } else if (type === 20 || type === 21) {
  237 + for (const deptOption of deptOptions.value) {
  238 + if (deptOption.id === option) {
  239 + return deptOption.name
  240 + }
  241 + }
  242 + } else if (type === 22) {
  243 + for (const postOption of postOptions.value) {
  244 + if (postOption.id === option) {
  245 + return postOption.name
  246 + }
  247 + }
  248 + } else if (type === 30 || type === 31 || type === 32) {
  249 + for (const userOption of userOptions.value) {
  250 + if (userOption.id === option) {
  251 + return userOption.nickname
  252 + }
  253 + }
  254 + } else if (type === 40) {
  255 + for (const userGroupOption of userGroupOptions.value) {
  256 + if (userGroupOption.id === option) {
  257 + return userGroupOption.name
  258 + }
  259 + }
  260 + } else if (type === 50) {
  261 + option = option + '' // 转换成 string
  262 + for (const dictData of taskAssignScriptDictDatas) {
  263 + if (dictData.value === option) {
  264 + return dictData.label
  265 + }
  266 + }
  267 + }
  268 + return '未知(' + option + ')'
  269 +}
  270 +// 格式化部门的下拉框
  271 +const normalizer = (node) => {
  272 + return {
  273 + id: node.id,
  274 + label: node.name,
  275 + children: node.children
  276 + }
  277 +}
  278 +
  279 +// ========== 初始化 ==========
  280 +onMounted(() => {
  281 + // 获得角色列表
  282 + roleOptions.value = []
  283 + listSimpleRolesApi().then((data) => {
  284 + roleOptions.value.push(...data)
  285 + })
  286 + // 获得部门列表
  287 + deptOptions.value = []
  288 + deptTreeOptions.value = []
  289 + listSimpleDeptApi().then((data) => {
  290 + deptOptions.value.push(...data)
  291 + deptTreeOptions.value.push(...handleTree(data, 'id'))
  292 + })
  293 + // 获得岗位列表
  294 + postOptions.value = []
  295 + listSimplePostsApi().then((data) => {
  296 + postOptions.value.push(...data)
  297 + })
  298 + // 获得用户列表
  299 + userOptions.value = []
  300 + getListSimpleUsersApi().then((data) => {
  301 + userOptions.value.push(...data)
  302 + })
  303 + // 获得用户组列表
  304 + userGroupOptions.value = []
  305 + listSimpleUserGroupsApi().then((data) => {
  306 + userGroupOptions.value.push(...data)
  307 + })
  308 +})
  309 +</script>
yudao-ui-admin-vue3/src/views/bpm/taskAssignRule/taskAssignRule.data.ts 0 → 100644
  1 +import { reactive } from 'vue'
  2 +import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
  3 +import { DICT_TYPE } from '@/utils/dict'
  4 +
  5 +// CrudSchema
  6 +const crudSchemas = reactive<VxeCrudSchema>({
  7 + primaryKey: 'id',
  8 + primaryType: null,
  9 + action: true,
  10 + actionWidth: '200px',
  11 + columns: [
  12 + {
  13 + title: '任务名',
  14 + field: 'taskDefinitionName'
  15 + },
  16 + {
  17 + title: '任务标识',
  18 + field: 'taskDefinitionKey'
  19 + },
  20 + {
  21 + title: '规则类型',
  22 + field: 'category',
  23 + dictType: DICT_TYPE.BPM_TASK_ASSIGN_RULE_TYPE,
  24 + dictClass: 'number'
  25 + },
  26 + {
  27 + title: '规则范围',
  28 + field: 'options',
  29 + table: {
  30 + slots: {
  31 + default: 'options_default'
  32 + }
  33 + }
  34 + }
  35 + ]
  36 +})
  37 +export const { allSchemas } = useVxeCrudSchemas(crudSchemas)