Browse Source

chore: compose task

master
wangxiang 2 years ago
parent
commit
c7b0dbf82d
No known key found for this signature in database
GPG Key ID: 1BA7946AB6B232E4
  1. 26
      src/api/platform/workflow/controller/form.ts
  2. 6
      src/api/platform/workflow/controller/model.ts
  3. 60
      src/api/platform/workflow/controller/task.ts
  4. 19
      src/api/platform/workflow/entity/formProperty.ts
  5. 12
      src/api/platform/workflow/entity/formType.ts
  6. 8
      src/views/system/menu/menu.data.ts
  7. 85
      src/views/workflow/extension/form/index.vue
  8. 21
      src/views/workflow/process/index.vue
  9. 161
      src/views/workflow/task/TaskForm.vue

26
src/api/platform/workflow/controller/form.ts

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
/**
* api模板规范代码参考,
* Copyright © 2023-2023 <a href="https://godolphinx.org"></a> All rights reserved.
* author wangxiang4
*/
import { Workflow } from '/@/api/platform/workflow/entity/workflow';
import { defHttp } from '/@/utils/http/axios';
import { FormProperty } from '/@/api/platform/workflow/entity/formProperty';
enum Api {
startProcessDefinition = '/workflow_proxy/workflow/form/startProcessDefinition',
getTaskFormData = '/workflow_proxy/workflow/form/getTaskFormData',
getProcessStartEventFormData = '/workflow_proxy/workflow/form/getProcessStartEventFormData',
auditTask = '/workflow_proxy/workflow/form/auditTask',
getHistoryFormTaskData = '/workflow_proxy/workflow/form/getHistoryFormTaskData',
}
export const startProcessDefinition = (data: Partial<Workflow>) => defHttp.post<string>({ url: Api.startProcessDefinition, data });
export const getTaskFormData = (taskId: string) => defHttp.get<FormProperty[]>({ url: `${Api.getTaskFormData}/${taskId}` });
export const getProcessStartEventFormData = (processDefId: string) => defHttp.get<FormProperty[]>({ url: `${Api.getProcessStartEventFormData}/${processDefId}` });
export const auditTask = (data: Partial<Workflow>) => defHttp.post({ url: Api.auditTask, data });
export const getHistoryFormTaskData = (params?: Recordable) => defHttp.get<Recordable[]>({ url: Api.getHistoryFormTaskData, params });

6
src/api/platform/workflow/controller/model.ts

@ -17,9 +17,15 @@ enum Api { @@ -17,9 +17,15 @@ enum Api {
}
export const listModel = (params?: Partial<WorkflowModelParams>) => defHttp.get<WorkflowModelResult>({url: Api.list, params}, { isReturnResultResponse: true });
export const getModelXml = (modelId: string) => defHttp.get<string>({url: `${Api.getBpmnXml}/${modelId}` });
export const delModel = (ids: string) => defHttp.delete({ url: `${Api.del}/${ids}` });
export const copyModel = (modelId: string)=> defHttp.post({ url: `${Api.copy}/${modelId}` });
export const deployModel = (modelId: string, category: string)=> defHttp.post({ url: Api.deploy, params: { id: modelId, category } });
export const saveModel = (modelId: string, params: Recordable)=> defHttp.post({url: `${Api.save}/${modelId}`, data: params});
export const bpmnXmlDownload = (modelId: string) => defHttp.get<BlobPart>({url: `${Api.bpmnXmlDownload}/${modelId}` });

60
src/api/platform/workflow/controller/task.ts

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
/**
* api模板规范代码参考,
* Copyright © 2023-2023 <a href="https://godolphinx.org"></a> All rights reserved.
* author wangxiang4
*/
import { Workflow } from '/@/api/platform/workflow/entity/workflow';
import { defHttp } from '/@/utils/http/axios';
import { ProcessInstanceInfoResult } from '/@/api/platform/workflow/entity/processInstanceInfo';
import { HistoryTaskInfoResult } from '/@/api/platform/workflow/entity/historyTaskInfo';
enum Api {
list = '/workflow_proxy/workflow/task/list',
historyFlowChangeList = '/workflow_proxy/workflow/task/historyFlowChangeList',
historyList = '/workflow_proxy/workflow/task/historyList',
getTaskDefinition = '/workflow_proxy/workflow/task/getTaskDefinition',
complete = '/workflow_proxy/workflow/task/complete',
getPaintDiagramXml = '/workflow_proxy/workflow/task/getPaintDiagramXml',
removeTask = '/workflow_proxy/workflow/task/removeTask',
auditTask = '/workflow_proxy/workflow/task/auditTask',
undoTask = '/workflow_proxy/workflow/task/undoTask',
delegateTask = '/workflow_proxy/workflow/task/delegateTask',
claim = '/workflow_proxy/workflow/task/claim',
cancelClaim = '/workflow_proxy/workflow/task/cancelClaim',
transferTask = '/workflow_proxy/workflow/task/transferTask',
rollBackTaskList = '/workflow_proxy/workflow/task/rollBackTaskList',
rejectTask = '/workflow_proxy/workflow/task/rejectTask',
getFlowChart = '/workflow_proxy/workflow/task/getFlowChart',
}
export const listTodoTask = (params?: Recordable) => defHttp.get<ProcessInstanceInfoResult>({ url: Api.list, params }, { isReturnResultResponse: true });
export const listHistoryFlowChange = (processInsId: string) => defHttp.get<Workflow[]>({ url: `${Api.historyFlowChangeList}/${processInsId}` });
export const listHistoryTask = (params?: Recordable) => defHttp.get<HistoryTaskInfoResult>({ url: Api.historyList, params }, { isReturnResultResponse: true });
export const getTaskDefinition = (params?: Partial<Workflow>)=> defHttp.get<Workflow>({ url: Api.getTaskDefinition, params });
export const complete = (data: Partial<Workflow>)=> defHttp.post({ url: Api.complete, data });
export const getPaintDiagramXml = (processInsId: string)=> defHttp.get({ url: `${Api.getPaintDiagramXml}/${processInsId}` });
export const removeTask = (taskId: string , reason: string ) => defHttp.delete({url: Api.removeTask, params: { taskId, reason } });
export const auditTask = (data: Partial<Workflow>)=> defHttp.post({ url: Api.auditTask, data });
export const undoTask = (data: Recordable)=> defHttp.post({ url: Api.undoTask, data });
export const delegateTask = (taskId: string, userId: string) => defHttp.post({url: Api.delegateTask, params: { taskId, userId } });
export const claim = (taskId: string)=> defHttp.post({ url: `${Api.claim}/${taskId}` });
export const cancelClaim = (taskId: string)=> defHttp.post({ url: `${Api.cancelClaim}/${taskId}` });
export const transferTask = (taskId: string, userId: string)=> defHttp.post({ url: Api.transferTask, params: { taskId, userId } });
export const rollBackTaskList = (taskId: string)=> defHttp.get<Workflow[]>({ url: `${Api.rollBackTaskList}/${taskId}` });
export const rejectTask = (data: Recordable) => defHttp.post({ url: Api.rejectTask, data });
export const getFlowChart = (processInsId: string)=> defHttp.get({ url: `${Api.getFlowChart}/${processInsId}` });

19
src/api/platform/workflow/entity/formProperty.ts

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
import type { FormType } from './formType';
export interface FormProperty {
/** The key used to submit the property */
id: string;
/** The display label */
name: string;
/** Type of the property. */
type: FormType;
/** Optional value that should be used to display in this property */
value: string;
/** Is this property read to be displayed in the form and made accessible */
readable: boolean;
/** Is this property expected when a user submits the form? */
isWritable: boolean;
/** Is this property a required input field */
required: boolean;
[key:string]: any;
}

12
src/api/platform/workflow/entity/formType.ts

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
export interface FormType {
/** Name for the form type. */
name: string;
/**
* Retrieve type specific extra information like the list of values for enum types or the format for date types. Look in the userguide for which extra information keys each type provides and what
* return type they give.
*/
information: Recordable;
[key:string]: any;
}

8
src/views/system/menu/menu.data.ts

@ -29,7 +29,7 @@ export const columns: BasicColumn[] = [ @@ -29,7 +29,7 @@ export const columns: BasicColumn[] = [
dataIndex: 'icon',
width: 100,
customRender: ({ record }) => {
return record.icon ? h(Icon, { icon: record.icon }) : h(Tag, { color: 'red' }, () => '暂无图标');
return record.icon ? h(Icon, { icon: record.icon }) : h(Tag, { color: 'warning' }, () => '暂无图标');
}
},
{
@ -41,14 +41,14 @@ export const columns: BasicColumn[] = [ @@ -41,14 +41,14 @@ export const columns: BasicColumn[] = [
title: '权限标识',
dataIndex: 'permission',
customRender: ({record}) => {
return record.permission || h(Tag, { color: 'red' }, () => '暂无数据');
return record.permission || h(Tag, { color: 'warning' }, () => '暂无数据');
}
},
{
title: '组件',
dataIndex: 'component',
customRender: ({record}) => {
return record.component || h(Tag, { color: 'red' }, () => '暂无数据');
return record.component || h(Tag, { color: 'warning' }, () => '暂无数据');
}
},
{
@ -60,7 +60,7 @@ export const columns: BasicColumn[] = [ @@ -60,7 +60,7 @@ export const columns: BasicColumn[] = [
// 采用二进制~~取反,只要为null或者0等等一些其他的空元素都会转为0
// 第一次取反会运算为-1,在后一次取反会运算为0
const enable = ~~hideMenu === 0;
const color = enable ? 'green' : 'red';
const color = enable ? 'green' : 'warning';
const text = enable ? '显示' : '隐藏';
return h(Tag, { color: color }, () => text);
}

85
src/views/workflow/extension/form/index.vue

@ -5,49 +5,50 @@ @@ -5,49 +5,50 @@
fixedHeight
dense
>
<BasicTree class="m-4 mr-0 overflow-hidden bg-white w-1/4 xl:w-1/5"
search
:clickRowToExpand="false"
:treeData="state.treeData"
:fieldNames="{ key: 'id', title: 'name' }"
@select="handleSelect"
>
<template #toolbarRight>
<a-button
type="primary"
shape="circle"
size="small"
@click="handleFormCategoryAdd()"
>
<PlusOutlined/>
</a-button>
</template>
<template #title="data">
<span class="custom-tree-node">
<span>{{ data.name }}</span>
<span>
<a-button type="link"
size="small"
@click="handleFormCategoryAdd(data)"
>
<PlusOutlined/>
</a-button>
<a-button type="link"
size="small"
@click="handleFormCategoryEdit(data)"
>
<FormOutlined/>
</a-button>
<a-button type="link"
size="small"
@click="handleFormCategoryDel(data)"
>
<DeleteOutlined/>
</a-button>
<div class="m-4 mr-0 overflow-hidden bg-white w-1/4 xl:w-1/5">
<BasicTree search
:clickRowToExpand="false"
:treeData="state.treeData"
:fieldNames="{ key: 'id', title: 'name' }"
@select="handleSelect"
>
<template #toolbarRight>
<a-button
type="primary"
shape="circle"
size="small"
@click="handleFormCategoryAdd()"
>
<PlusOutlined/>
</a-button>
</template>
<template #title="data">
<span class="custom-tree-node">
<span>{{ data.name }}</span>
<span>
<a-button type="link"
size="small"
@click="handleFormCategoryAdd(data)"
>
<PlusOutlined/>
</a-button>
<a-button type="link"
size="small"
@click="handleFormCategoryEdit(data)"
>
<FormOutlined/>
</a-button>
<a-button type="link"
size="small"
@click="handleFormCategoryDel(data)"
>
<DeleteOutlined/>
</a-button>
</span>
</span>
</span>
</template>
</BasicTree>
</template>
</BasicTree>
</div>
<BasicTable
class="w-3/4 xl:w-4/5"
@register="registerTable"

21
src/views/workflow/process/index.vue

@ -5,16 +5,17 @@ @@ -5,16 +5,17 @@
fixedHeight
dense
>
<BasicTree class="m-4 mr-0 overflow-hidden bg-white w-1/4 xl:w-1/5"
title="流程分类"
toolbar
search
defaultExpandAll
:clickRowToExpand="false"
:treeData="state.treeData"
:fieldNames="{ key: 'id', title: 'name' }"
@select="handleSelect"
/>
<div class="m-4 mr-0 overflow-hidden bg-white w-1/4 xl:w-1/5">
<BasicTree title="流程分类"
toolbar
search
defaultExpandAll
:clickRowToExpand="false"
:treeData="state.treeData"
:fieldNames="{ key: 'id', title: 'name' }"
@select="handleSelect"
/>
</div>
<BasicTable class="w-3/4 xl:w-4/5" @register="registerTable">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">

161
src/views/workflow/task/TaskForm.vue

@ -0,0 +1,161 @@ @@ -0,0 +1,161 @@
<template>
<LayoutContent style="min-height: 100vh">
<h4 style="text-align:center">{{formTitle}}</h4>
</LayoutContent>
</template>
<script lang="ts" setup>
/**
* 提供模板规范代码参考,请尽量保证编写代码风格跟模板规范代码一致
* 采用vben-动态表格表单封装组件编写,采用 setup 写法
* Copyright © 2023-2023 <a href="https://godolphinx.org">海豚生态开源社区</a> All rights reserved.
* author wangxiang4
*/
import { ref, unref,reactive, toRaw } from 'vue';
import { LayoutContent } from 'ant-design-vue';
import {TreeItem} from '/@/components/Tree';
import {useForm} from '/@/components/Form';
import {formSchema} from '/@/views/system/role/role.data';
import {DrawerProps, useDrawerInner} from '/@/components/Drawer';
import {listToTree} from '/@/utils/helper/treeHelper';
import {getRoleMenuIds, listMenu} from '/@/api/platform/system/controller/menu';
import {addRole, editRole, getRole} from '/@/api/platform/system/controller/role';
/** 类型规范统一声明定义区域 */
interface WindowState {
//
formTitle: string;
// key
formKey: string;
// (1:,2:)
formType: string;
//
formPath: '';
//
formReadOnly: false;
// ID
businessId: '';
//
taskFormData: [],
//
taskSelectedTab: 'formInfo',
// ID
taskId: '',
// key
taskDefKey: '',
// ID
processDefId: '',
// ID
processInsId: '',
// Key
processDefKey: '',
//
status: '',
//
historyFlowChangeList: [],
//
buttons: [],
//
isCC: false,
//
isAssign: false,
//
printInfo: {
id: 'printForm',
popTitle: '',
extraCss: '',
extraHead: '<meta http-equiv="Content-Language" content="zh-cn"/>'
},
//
auditForm: {
message: '',
mesCode: '',
mesName: '',
// ID
userIds: '',
// ID
assignee: ''
}
}
/** 通用变量统一声明区域 */
const state = reactive<WindowState>({
//
tag: '',
//
menuTree: [],
//
checkedKeys: {},
});
/** https://v3.cn.vuejs.org/api/options-data.html#emits */
const emit = defineEmits(['success', 'register']);
const [registerForm, { resetFields, setFieldsValue, validate, clearValidate }] = useForm({
labelWidth: 100,
schemas: formSchema,
showActionButtonGroup: false,
baseColProps: { span: 24 }
});
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data: BoxPayload = { _tag: '' }) => {
//
await resetFields();
await clearValidate();
//
state.tag = data._tag;
state.menuTree = listToTree(await listMenu());
const roleId = data.record?.id;
const props: Partial<DrawerProps> = { confirmLoading: false };
// tag
switch (state.tag) {
case 'add':
props.title = '新增角色';
break;
case 'edit':
props.title = '编辑角色';
const result = await getRoleMenuIds(roleId);
const role = await getRole(roleId);
const checked = {
checkedKeys: result.extend?.filter(item => item.checkeType == '1')?.map(item=> item.menuId),
halfCheckedKeys: result.extend.filter(item => item.checkeType == '2')?.map(item=> item.menuId)
};
state.checkedKeys = checked;
await setFieldsValue(Object.assign({}, role, { menuIds: checked.checkedKeys }));
break;
}
// :
setDrawerProps(props);
});
/** 处理选中的半复选框合并至勾选数据中 */
function handleHalfCheckedKeysMerge (checkedKeys: string[], e) {
state.checkedKeys = { checkedKeys, halfCheckedKeys: e.halfCheckedKeys };
}
/** 处理弹出框提交 */
async function handleSubmit() {
try {
//
const formData = await validate();
//
setDrawerProps({ confirmLoading: true });
formData.menuIds = toRaw(state.checkedKeys);
// tag
switch (state.tag) {
case 'add':
await addRole(formData);
break;
case 'edit':
await editRole(formData);
break;
}
//
closeDrawer();
emit('success');
} finally {
setDrawerProps({ confirmLoading: false });
}
}
</script>
Loading…
Cancel
Save