Compare commits

...

6 Commits

14 changed files with 788 additions and 259 deletions

View File

@ -12,37 +12,14 @@ import { BasicColumn, FormSchema } from '@/components/Table';
*/
export const columns: BasicColumn[] = [
{
title: '用户名',
dataIndex: 'account',
width: 120,
},
{
title: '昵称',
title: '名称',
dataIndex: 'name',
width: 120,
},
{
title: '所属部门',
dataIndex: 'organizations',
// customRender: ({ value }) => {
// return deptMap[value];
// },
},
];
export const searchFormSchema: FormSchema[] = [
{
field: 'account',
label: '用户名',
component: 'Input',
colProps: { span: 8 },
},
{
field: 'nickname',
label: '昵称',
component: 'Input',
colProps: { span: 8 },
},
];

View File

@ -1,5 +1,5 @@
<template>
<div>
<div class="select-account">
<BasicTable @register="registerTable" :searchInfo="searchInfo"> </BasicTable>
</div>
</template>
@ -69,4 +69,10 @@
getRow
})
</script>
</script>
<style scoped>
.select-account{
display: flex;
height: 100%;
}
</style>

View File

@ -112,7 +112,7 @@
},
beforeFetch: () => {
var temp = {
dbCode: receiceDbCode.value,
code: receiceDbCode.value,
};
return temp;
},

View File

@ -36,7 +36,7 @@
width="100%"
wrap-class-name="full-modal"
v-model:open="previewOpen"
title="流程设计"
title="流程发起"
:destroyOnClose="true"
>
<template #footer> </template>
@ -61,9 +61,9 @@
let cardList = ref();
const previewOpen = ref(false)
const code = ref('')
function launch(code) {
function launch(val) {
previewOpen.value = true
code.value = code
code.value = val
// go('/dashboard/create_preview/add?code=' + code);
}
function closeMolder(){

View File

@ -82,24 +82,17 @@
import { create, saveDraft } from '@/api/sys/WFProcess';
import { getLoadMyUserList } from '@/api/sys/WFDelegate';
import { functionsaveForm } from '@/api/demo/formScheme';
import { useRoute } from 'vue-router';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { useUserStore } from '@/store/modules/user';
import { buildGUID } from '@/utils/uuid';
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
import { functionGetSchemePageList } from '@/api/demo/formScheme';
import { functionGetSchemePageList ,LoadFormScheme} from '@/api/demo/formScheme';
const formBoxRef = ref<any>();
const userStore = useUserStore();
const userInfo: any = userStore.getUserInfo;
const prefixCls = 'preview-box';
const tabStore = useMultipleTabStore();
const router = useRouter();
const flowContent = ref('');
const route = useRoute();
const code: any = route.query.code;
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 13 };
@ -109,7 +102,7 @@
code:String,
})
const emit = defineEmits(['closeModel']);
const keyValue = ref('')
//
const eFormPreview = ref<null | IToolbarMethods>(null);
//
@ -159,18 +152,6 @@
processVisble.value = true;
}
}
async function getForm() {
const list = await functionGetSchemePageList({
schemeInfoId: designerData.formCode,
});
list.items.forEach((element) => {
if (element.id == designerData.formVerison) {
const scheme = JSON.parse(element.scheme);
formConfig.value.schemas = scheme.formInfo.schemas;
console.log(formConfig.value);
}
});
}
async function getDetailInfo() {
let data = await getDetail({ code: props.code });
flowContent.value = data.scheme.flowContent;
@ -186,10 +167,7 @@
}
formConfig.value = currentNode.authFields;
designerData.formCurrentNode = currentNode;
// designerData.isCustmerTitle = currentNode.isCustmerTitle;
// designerData.formVerison = currentNode.formVerison;
// designerData.formCode = currentNode.formCode;
// getForm();
getFormHistory()
}
async function getDelegateUsers() {
const data = await getLoadMyUserList({
@ -208,6 +186,7 @@
querys.schemeCode = '';
designerData.isDraft = true;
if (data) {
closePreview()
return createMessage.success('保存草稿成功');
} else {
return createMessage.error('保存草稿失败');
@ -218,7 +197,7 @@
var querys = {
schemeId: designerData.formCurrentNode.formVerison,
isUpdate: false,
pkey: designerData.formCurrentNode.formRelationId,
pkey: keyValue.value,
pkeyValue: processId,
};
//
@ -230,7 +209,6 @@
.getForm()
.then(async (res) => {
res[designerData.formCurrentNode.formRelationId] = processId;
console.log(res);
for (var item in res) {
if (res[item] == undefined) {
res[item] = '';
@ -240,7 +218,6 @@
}
}
querys.data = JSON.stringify(res);
console.log(querys);
const formValue = await functionsaveForm(querys);
if (formValue) {
handleCreateFlow(processId);
@ -257,12 +234,11 @@
}
async function handleCreateFlow(processId) {
var querys = {
schemeCode: designerData.isDraft ? '' : code,
schemeCode: designerData.isDraft ? '' : props.code,
userId: formData.userId,
title: formData.title,
processId: processId,
};
console.log(querys);
if (!designerData.isDraft) {
await saveDraft(querys);
querys.schemeCode = '';
@ -276,7 +252,19 @@
return createMessage.error('发起流程失败');
}
}
async function getFormHistory() {
const data = await LoadFormScheme({
schemeId: designerData.formCurrentNode.formVerison,
});
if (data) {
const scheme = JSON.parse(data.scheme);
scheme.formInfo.schemas.forEach((element) => {
if (element.field == designerData.formCurrentNode.formRelationId) {
keyValue.value = element.componentProps.fieldName;
}
});
}
}
function closePreview() {
emit('closeModel')
// if (!code) {
@ -301,7 +289,10 @@
display: flex;
}
}
::v-deep .anticon svg {
width: 1em!important;
height: 1em!important;
}
.form-box {
width: 480px;
}

View File

@ -33,6 +33,16 @@
</BasicTable>
<SchemeDrawer @register="registerDrawer" @success="handleSuccess" />
<HistoryDrawer @register="registerHistoryDrawer" @success="handleSuccess" />
<a-modal
width="100%"
wrap-class-name="full-modal"
v-model:open="auditOpen"
title="流程设计"
:destroyOnClose="true"
>
<template #footer> </template>
<Preview ref="posRef" :code="code" @closeModel="closeMolder"></Preview>
</a-modal>
</PageWrapper>
</template>
<script lang="ts" setup>
@ -44,6 +54,7 @@
import { PageWrapper } from '@/components/Page';
import { useDrawer } from '@/components/Drawer';
import { PermissionBtn } from '@/components/PermissionBtn/index';
import Preview from './preview.vue';
import { SchemeTree } from './page';
import { SchemeDrawer } from './page';
@ -58,7 +69,8 @@
defineOptions({ name: 'SchemeManagement' });
const searchInfo = reactive<Recordable>({});
const auditOpen = ref(false);
const code = ref('');
const [registerHistoryDrawer, { openDrawer: openHistoryDrawer }] = useDrawer();
const [registerDrawer, { openDrawer }] = useDrawer();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
@ -109,7 +121,9 @@
return createMessage.warn('请选择一个模板进行编辑');
}
const record = rows[0];
go('/dashboard/scheme_preview/add?code=' + record.code);
auditOpen.value = true;
code.value = record.code
// go('/dashboard/scheme_preview/add?code=' + record.code);
}
async function classifyEdit(record) {
openDrawer(true, {
@ -160,7 +174,8 @@
switch (domId) {
case 'btnAdd':
flowWfDataStore.setWfDataAll([]);
go('/dashboard/scheme_preview/add');
auditOpen.value = true;
// go('/dashboard/scheme_preview/add');
break;
case 'btnEdit':
handleEdit();
@ -172,4 +187,25 @@
break;
}
}
function closeMolder(){
auditOpen.value = false;
clearSelectedRowKeys();
reload();
}
</script>
<style lang="less">
.full-modal {
.ant-modal {
max-width: 100%;
top: 0;
}
.ant-modal-content {
height: calc(100vh);
}
.ant-modal-body {
height: 85%;
}
}
</style>

View File

@ -21,7 +21,7 @@
style="border: 1px solid rgba(0, 0, 0, 0.1)"
ref="modelDesigner"
v-loading="designerData.loading"
:schemeCode="schemeCode"
:schemeCode="props.code"
@save="onSaveDesigner"
/>
</div>
@ -39,19 +39,14 @@
ClearOutlined,
} from '@ant-design/icons-vue';
import { postAdd, update } from '@/api/sys/WFSchemeInfo';
import { useRoute } from 'vue-router';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
import { flowStore } from '@/store/modules/flow';
import { lr_AESEncrypt } from '@/components/ProcessDesigner/package/utils';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const flowWfDataStore = flowStore();
const tabStore = useMultipleTabStore();
const router = useRouter();
const route = useRoute();
const schemeCode = route.query.code;
const props = defineProps({
code: String,
});
const emit = defineEmits(['closeModel']);
const designerOpen = ref(false);
const designerData = reactive({
loading: false,
@ -64,7 +59,7 @@
console.log(formData);
// 1 2稿
formData.scheme.type = Number(type);
if (!schemeCode) {
if (!props.code) {
let data = await postAdd(formData);
if (data) {
closePreview();
@ -84,12 +79,13 @@
}
}
function closePreview() {
if (!schemeCode) {
tabStore.closeTabByKey('/dashboard/scheme_preview/add', router);
} else {
// /dashboard/scheme_preview/add?code=1
tabStore.closeTabByKey('/dashboard/scheme_preview/add?code=' + schemeCode, router);
}
emit('closeModel');
// if (!schemeCode) {
// tabStore.closeTabByKey('/dashboard/scheme_preview/add', router);
// } else {
// // /dashboard/scheme_preview/add?code=1
// tabStore.closeTabByKey('/dashboard/scheme_preview/add?code=' + schemeCode, router);
// }
}
</script>
<style scoped>

View File

@ -1,146 +1,149 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
label:'详情',
onClick: handleDetail.bind(null, record),
},
{
label:'删除',
color: 'error',
popConfirm: {
title: '是否确认删除',
confirm: () => {
handleDelete(record);
},
},
},
]" />
</template>
</template>
</BasicTable>
<a-modal
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" :searchInfo="searchInfo">
<template #toolbar>
<!-- <a-button type="primary" @click="handleCreate"> </a-button> -->
<PermissionBtn @btnEvent="onBtnClicked"></PermissionBtn>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
{
label: '删除',
color: 'error',
popConfirm: {
title: '是否确认删除',
confirm: () => {
handleDelete(record);
},
},
},
]"
/>
</template>
</template>
</BasicTable>
<a-modal
width="100%"
wrap-class-name="full-modal"
v-model:open="auditOpen"
title="详情"
:destroyOnClose="true"
>
<template #footer>
</template>
<Look ref="posRef" :processId="processId"></Look>
<template #footer> </template>
<Initiate ref="posRef" :processId="processId" @closeModel="closeModel"></Initiate>
</a-modal>
</PageWrapper>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive ,ref} from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDraftPage, deleteDraft } from '@/api/sys/WFProcess'
const searchInfo = reactive < Recordable > ({});
import { useGo } from '@/hooks/web/usePage';
import Look from "./process/look.vue"
const go = useGo();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const auditOpen = ref(false)
const processId = ref('')
const [registerTable, { reload }] = useTable({
api: getLoadMyDraftPage,
columns: [
{
title: '标题',
dataIndex: 'title',
},
{
title: '流程模版',
dataIndex: 'schemeName',
},
{
title: '提交人',
dataIndex: 'createUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
],
import { reactive, ref } from 'vue';
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDraftPage, deleteDraft } from '@/api/sys/WFProcess';
const searchInfo = reactive<Recordable>({});
import { useGo } from '@/hooks/web/usePage';
import Initiate from './process/initiate.vue';
const go = useGo();
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
const auditOpen = ref(false);
const processId = ref('');
const [registerTable, { reload }] = useTable({
api: getLoadMyDraftPage,
columns: [
{
title: '标题',
dataIndex: 'title',
},
{
title: '流程模版',
dataIndex: 'schemeName',
},
{
title: '提交人',
dataIndex: 'createUserName',
},
{
title: '创建时间',
dataIndex: 'createDate',
},
],
rowKey: 'id',
formConfig: {
labelWidth: 120,
schemas: [
{
field: '[StartDate, EndDate]',
label: '日期范围',
component: 'RangePicker',
componentProps: {
format: 'YYYY-MM-DD',
placeholder: ['开始日期', '结束日期'],
},
colProps: { span: 8 },
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
{
field: 'keyWord',
label: '关键字',
component: 'Input',
colProps: { span: 8 },
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
async function handleDelete(record) {
var query = {
id: record.id
}
const data = await deleteDraft(query)
if (data) {
reload()
return createMessage.success('删除成功');
}else{
return createMessage.error('删除失败');
}
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
async function handleDelete(record) {
var query = {
id: record.id,
};
const data = await deleteDraft(query);
if (data) {
reload();
return createMessage.success('删除成功');
} else {
return createMessage.error('删除失败');
}
function handleDetail(record) {
processId.value = record.id
auditOpen.value=true
}
function handleDetail(record) {
processId.value = record.id;
auditOpen.value = true;
// go('/dashboard/task_look_preview/detail?processId=' + record.id);
}
}
function closeModel(){
auditOpen.value = false
reload()
}
</script>
<style lang="less">
.full-modal {
.ant-modal {
max-width: 100%;
top:0;
}
.ant-modal-content {
height: calc(100vh);
}
.ant-modal-body {
height: 85%;
}
.full-modal {
.ant-modal {
max-width: 100%;
top: 0;
}
</style>
.ant-modal-content {
height: calc(100vh);
}
.ant-modal-body {
height: 85%;
}
}
</style>

View File

@ -156,7 +156,6 @@
}
}
async function handleRevocation(record) {
console.log(record);
var query = {
taskId: record.id,
id: record.processId,

View File

@ -20,7 +20,7 @@
v-if="formVisble"
></FormViewer>
</a-tab-pane>
<a-tab-pane key="flow" tab="流程信息(审核)" force-render>
<a-tab-pane key="flow" tab="流程信息" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer
v-if="processVisble"
@ -32,6 +32,29 @@
/>
</div>
</a-tab-pane>
<a-tab-pane key="record" tab="流转记录" force-render>
<a-timeline>
<a-timeline-item
v-for="(item, index) in designerData.logs"
:key="index"
:color="item.type"
>
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
<div class="content">
<span
class="link"
v-for="(userName, index2) in item.userNames"
:key="index2"
>{{ userName }}</span
>
{{ item.des }}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-tab-pane>
</a-tabs>
</a-layout-content>
<!-- <a-divider type="vertical" /> -->
@ -79,7 +102,11 @@
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index">
<a-timeline-item
v-for="(item, index) in designerData.nodeLogs"
:key="index"
:color="item.type"
>
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
@ -106,7 +133,7 @@
import { useRoute } from 'vue-router';
import { dateFormat } from '@/utils/base';
import { flowStore } from '@/store/modules/flow';
import { functionsaveForm } from '@/api/demo/formScheme';
import { functionsaveForm, LoadFormScheme } from '@/api/demo/formScheme';
import { FormViewer } from '@/components/FormViewer';
import {
designerDataType,
@ -119,22 +146,14 @@
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
import { useMessage } from '@/hooks/web/useMessage';
const { createMessage } = useMessage();
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
const tabStore = useMultipleTabStore();
const router = useRouter();
const formBoxRef = ref<any>();
const emit = defineEmits(['closeModel']);
const emit = defineEmits(['closeModel']);
const keyValue = ref('');
const flowWfDataStore = flowStore();
const prefixCls = 'preview-box';
const flowContent = ref('');
const flowViewer = ref({});
const route = useRoute();
const processId = route.query.processId;
const taskId: any = route.query.taskId;
const type: any = route.query.type;
const isRead: any = route.query.isRead;
const formRef = ref();
const labelCol = { span: 7 };
const wrapperCol = { span: 24 };
@ -142,11 +161,11 @@
const formVisble = ref(false);
const processVisble = ref(false);
const props = defineProps({
processId:String,
taskId:String,
type:String,
isRead:String,
})
processId: String,
taskId: String,
type: String,
isRead: String,
});
const formData = ref({
des: '',
});
@ -239,6 +258,7 @@
}
designerData.formCurrentNode = currentNode;
formConfig.value = currentNode.authFields;
getFormHistory();
if (props.isRead == 0) {
setLogsAndTasks(data.logs, data.tasks);
getBtns();
@ -267,7 +287,7 @@
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
isFinish: false,
},
];
@ -280,7 +300,7 @@
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
};
taskMap[task.unitId + task.type].userIds.push(task.userId);
taskMap[task.unitId + task.type].userNames.push(task.userName);
@ -293,7 +313,7 @@
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
isFinish: true,
});
}
@ -307,7 +327,7 @@
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
};
taskMap[task.unitId].userIds.push(task.userId);
nodeMap[task.unitId][0].userIds.push(task.userId);
@ -345,7 +365,7 @@
userNames: [log.userName],
des: log.des ? log.des : log.operationName,
time: dateFormat(log.createDate),
type: 'info',
type: 'gray',
});
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
@ -356,7 +376,7 @@
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.operationName,
type: 'info',
type: 'gray',
isFinish: true,
});
@ -449,16 +469,19 @@
var querys = {
schemeId: designerData.formCurrentNode.formVerison,
isUpdate: true,
pkey: designerData.formCurrentNode.formRelationId,
pkey: keyValue.value,
pkeyValue: props.processId,
};
formBoxRef.value
.getForm()
.then(async (res) => {
res[designerData.formCurrentNode.formRelationId] = props.processId;
console.log(res);
for (var item in res) {
if (res[item] == null) {
res[item] = '';
}
}
querys.data = JSON.stringify(res);
console.log(querys);
const formValue = await functionsaveForm(querys);
if (formValue) {
handleSubmit(btn);
@ -501,7 +524,6 @@
des: formData.value.des,
});
} else {
console.log(designerData.currentNode);
if (designerData.currentNode.rejectType == '2' && btn.code == 'disagree') {
designerData.selectRejectNodeVisible = true;
return;
@ -569,7 +591,7 @@
}
}
function closePage() {
emit('closeModel')
emit('closeModel');
// tabStore.closeTabByKey(
// '/dashboard/task_audit_preview/detail?processId=' +
// processId +
@ -591,6 +613,19 @@
return createMessage.error('失败');
}
}
async function getFormHistory() {
const data = await LoadFormScheme({
schemeId: designerData.formCurrentNode.formVerison,
});
if (data) {
const scheme = JSON.parse(data.scheme);
scheme.formInfo.schemas.forEach((element) => {
if (element.field == designerData.formCurrentNode.formRelationId) {
keyValue.value = element.componentProps.fieldName;
}
});
}
}
onBeforeMount(() => {
getTaskInfo();
});

View File

@ -0,0 +1,474 @@
<template>
<PageWrapper :class="prefixCls">
<div class="btn-box">
<a-button type="primary" :icon="h(SendOutlined)" @click="handleSubmit" class="ml-2"
>发起流程
</a-button>
<!-- <a-button
type="primary"
@click="closePage"
class="ml-2"
danger
>关闭
</a-button> -->
</div>
<a-layout>
<a-layout>
<a-layout-content>
<a-tabs v-model:activeKey="activeName" @change="changeActive">
<a-tab-pane key="form" tab="表单信息" v-if="formVisble">
<FormViewer
ref="formBoxRef"
:formConfig="formConfig"
:processId="designerData.process.id"
:formVerison="designerData.formCurrentNode.formVerison"
:formRelationId="designerData.formCurrentNode.formRelationId"
v-if="formVisble"
></FormViewer>
</a-tab-pane>
<a-tab-pane key="flow" tab="流程信息(审核)" force-render>
<div class="process-design" :style="'display: flex; height:' + designerData.height">
<process-viewer
v-if="processVisble"
:key="`designer-${id}`"
:events="['element.click']"
@element-click="elementClick"
:xml="flowContent"
:flowViewer="flowViewer"
/>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-content>
<a-layout-sider v-if="designerData.userLogs.length > 0">
<a-tabs v-model:activeKey="auditName">
<a-tab-pane key="audit" tab="审批信息">
<div class="approval-info">
<auditInfo :data="designerData.userLogs"></auditInfo>
</div>
</a-tab-pane>
</a-tabs>
</a-layout-sider>
</a-layout>
</a-layout>
<!-- 节点记录信息 -->
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index">
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
<div class="content">
<span class="link" v-for="(userName, index2) in item.userNames" :key="index2">{{
userName
}}</span>
{{ item.des }}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-drawer>
</div>
</PageWrapper>
</template>
<script lang="ts" setup>
import { ref, reactive, onBeforeMount, h } from 'vue';
import { SendOutlined } from '@ant-design/icons-vue';
import { FormViewer } from '@/components/FormViewer';
import { ProcessViewer } from '@/components/ProcessViewer';
import { PageWrapper } from '@/components/Page';
import { getBPMN } from '@/api/sys/WFProcess';
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
import { functionsaveForm } from '@/api/demo/formScheme';
import { buildGUID } from '@/utils/uuid';
import { dateFormat } from '@/utils/base';
import { designerDataType, logsType } from './processModel';
import { create } from '@/api/sys/WFProcess';
import auditInfo from './auditInfo.vue';
import { useMessage } from '@/hooks/web/useMessage';
const emit = defineEmits(['closeModel']);
const { createMessage } = useMessage();
const props = defineProps({
processId: String,
});
const prefixCls = 'preview-box';
const flowContent = ref('');
const flowViewer = ref({});
const infoOpen = ref(true);
const formBoxRef = ref<any>();
const formVisble = ref(false);
const processVisble = ref(false);
//
const formConfig = ref<IFormConfig>({
//
schemas: [],
layout: 'horizontal',
labelLayout: 'flex',
labelWidth: 100,
labelCol: {},
wrapperCol: {},
currentItem: {
component: '',
componentProps: {},
},
activeKey: 1,
});
const designerData: designerDataType = reactive({
loading: false,
xmlString: '',
height: document.documentElement.clientHeight - 200.5 + 'px;',
midVisible: false,
isCustmerTitle: false,
nodeUsers: [],
selectUsersVisible: false,
selectTUserVisible: false,
tUserType: 1, // 1 2 ,
isDraft: false,
delegateUsers: [],
task: {},
process: {},
logs: [], //
nodeMap: {}, //
userLogs: [], //
nodeLogs: [],
taskBtns: [],
currentNode: {},
stampList: [],
currentBtn: {
code: '',
name: '',
isNextAuditor: false,
},
wfData: [],
selectRejectNodeVisible: false,
selectSignVisible: false,
formCurrentNode: {},
});
const activeName = ref('form');
const auditName = ref('audit');
function changeActive(activeKey) {
if (activeKey == 'flow') {
processVisble.value = true;
} else {
processVisble.value = false;
}
}
function elementClick(element: { id: string | number }) {
if (element) {
designerData.nodeLogs = designerData.nodeMap[element.id] || [];
infoOpen.value = true;
} else {
designerData.nodeLogs = [];
}
}
async function getDetailInfo() {
let query: any = {
id: props.processId,
};
let data = await getBPMN(query);
flowContent.value = data.flowContent;
flowViewer.value = data.flowViewer;
designerData.process = data.process;
designerData.task = data.task;
let content = JSON.parse(data.scheme.content);
let wfData = content.wfData;
const currentNode = wfData.find((t) => t.type == 'bpmn:StartEvent');
if (currentNode.authFields.length > 0) {
formVisble.value = true;
} else {
activeName.value = 'flow';
processVisble.value = true;
}
designerData.formCurrentNode = currentNode;
formConfig.value = currentNode.authFields;
setLogsAndTasks(data.logs, data.tasks);
// getBtns();
}
function setLogsAndTasks(logs: any[], tasks: any[]) {
const res: logsType[] = [];
const taskMap = {};
const nodeMap = {};
const userLogs: any[] = [];
tasks.forEach(
(task: {
unitId: string | number;
unitName: any;
createDate: any;
type: number;
userId: any;
userName: any;
}) => {
nodeMap[task.unitId] = nodeMap[task.unitId] || [
{
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: false,
},
];
if (task.type == 2) {
taskMap[task.unitId + task.type] = taskMap[task.unitId + task.type] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
};
taskMap[task.unitId + task.type].userIds.push(task.userId);
taskMap[task.unitId + task.type].userNames.push(task.userName);
if (nodeMap[task.unitId].length == 1) {
nodeMap[task.unitId].push({
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
isFinish: true,
});
}
nodeMap[task.unitId][1].userIds.push(task.userId);
nodeMap[task.unitId][1].userNames.push(task.userName);
} else {
taskMap[task.unitId] = taskMap[task.unitId] || {
unitId: task.unitId,
name: task.unitName,
userIds: [],
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
};
taskMap[task.unitId].userIds.push(task.userId);
nodeMap[task.unitId][0].userIds.push(task.userId);
taskMap[task.unitId].userNames.push(task.userName);
nodeMap[task.unitId][0].userNames.push(task.userName);
}
},
);
for (let key in taskMap) {
res.push(taskMap[key]);
}
for (let key in nodeMap) {
nodeMap[key] = nodeMap[key].filter((t: { userIds: string | any[] }) => t.userIds.length > 0);
}
logs.forEach(
(log: {
unitId: string;
unitName: any;
userId: string;
userName: string;
des: string;
operationName: string;
createDate: any;
taskType: number;
operationCode: string;
stampImg: any;
}) => {
res.push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
des: log.des ? log.des : log.operationName,
time: dateFormat(log.createDate),
type: 'info',
});
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
nodeMap[log.unitId].push({
unitId: log.unitId,
name: log.unitName,
userIds: [log.userId],
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.operationName,
type: 'info',
isFinish: true,
});
if (log.taskType == 1 && !['sign'].includes(log.operationCode)) {
//
// const userLogIndex = userLogs.findIndex((t) => t.id == log.unitId);
// if (userLogIndex == -1) {
userLogs.push({
id: log.unitId,
name: log.unitName,
user: log.userName,
time: dateFormat(log.createDate),
des: log.des,
img: log.stampImg,
});
// }
}
},
);
designerData.logs = res;
designerData.nodeMap = nodeMap;
designerData.userLogs = userLogs.sort(function (a, b) {
return a.time < b.time ? -1 : 1;
});
}
function handleSubmit() {
var processId = designerData.process.id;
var querys = {
schemeId: designerData.formCurrentNode.formVerison,
isUpdate: false,
pkey: designerData.formCurrentNode.formRelationId,
pkeyValue: processId,
};
//
if (formVisble.value) {
if (!designerData.formCurrentNode.formRelationId) {
return createMessage.error('请设置表单和流程关联字段');
}
formBoxRef.value
.getForm()
.then(async (res) => {
res[designerData.formCurrentNode.formRelationId] = processId;
for (var item in res) {
if (res[item] == undefined) {
res[item] = '';
if (item.search('_input_guid') != -1) {
res[item] = buildGUID();
}
}
}
querys.data = JSON.stringify(res);
const formValue = await functionsaveForm(querys);
if (formValue) {
handleCreateFlow(processId);
}
})
.catch((error) => {
console.log(error);
activeName.value = 'form';
return;
});
} else {
handleCreateFlow(processId);
}
}
async function handleCreateFlow(processId) {
var querys = {
schemeCode: '',
userId: designerData.process.userId,
title: '',
processId: processId,
};
const data = await create(querys);
if (data) {
closePreview();
return createMessage.success('发起流程成功');
} else {
return createMessage.error('发起流程失败');
}
}
function closePreview() {
emit('closeModel')
}
// function closePage() {
// tabStore.closeTabByKey('/dashboard/task_look_preview/detail?processId=' + processId, router);
// }
onBeforeMount(() => {
getDetailInfo();
});
</script>
<style lang="less" scoped>
::v-deep .ant-tabs-nav-wrap {
padding-left: 10px;
}
::v-deep .ant-layout {
height: 100%;
background-color: @component-background;
}
::v-deep .ant-layout-sider-children {
border-left: 1px solid rgba(5, 5, 5, 0.06);
}
::v-deep .ant-divider-vertical {
height: 100%;
}
.info-box {
display: inline-block;
width: 300px;
position: absolute;
right: 0;
margin-top: 40px;
}
.ant-timeline-item-content {
.title {
color: #909399;
line-height: 1;
margin-bottom: 8px;
font-size: 13px;
}
.type-title {
font-size: 12px;
font-weight: bold;
margin-bottom: 8px;
}
.link {
color: #409eff;
}
}
.preview-box {
height: 100%;
.btn-box {
padding: 10px;
justify-content: flex-end;
display: flex;
}
}
::v-deep .vben-page-wrapper-content {
height: 100%;
margin: 0 0 0 16px;
}
.form-box {
width: 480px;
}
.approval-column {
padding: 10px;
}
::v-deep .ant-layout .ant-layout-sider {
padding-left: 10px;
background-color: @component-background;
flex: 0 0 360px !important;
max-width: 360px !important;
min-width: 360px !important;
width: 360px !important;
}
::v-deep .vben-page-wrapper .vben-page-wrapper-content {
height: 98%;
}
.l-task-btns {
.ant-btn {
margin: 0;
margin-top: 8px;
margin-right: 8px;
}
}
</style>

View File

@ -35,6 +35,25 @@
/>
</div>
</a-tab-pane>
<a-tab-pane key="record" tab="流转记录" force-render>
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.logs" :key="index" :color="item.type">
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
<div class="content">
<span
class="link"
v-for="(userName, index2) in item.userNames"
:key="index2"
>{{ userName }}</span
>
{{ item.des }}
</div>
</a-card>
</a-timeline-item>
</a-timeline>
</a-tab-pane>
</a-tabs>
</a-layout-content>
<a-layout-sider v-if="designerData.userLogs.length > 0">
@ -53,7 +72,7 @@
<div class="info-box" v-if="designerData.nodeLogs.length > 0">
<a-drawer v-model:open="infoOpen" class="custom-class" title="记录信息" placement="right">
<a-timeline>
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index">
<a-timeline-item v-for="(item, index) in designerData.nodeLogs" :key="index" :color="item.type">
<div class="title">{{ item.time }}</div>
<a-card hoverable size="small">
<div class="type-title">{{ item.name }}</div>
@ -77,25 +96,16 @@
import { ProcessViewer } from '@/components/ProcessViewer';
import { PageWrapper } from '@/components/Page';
import { getBPMN } from '@/api/sys/WFProcess';
import { useRoute } from 'vue-router';
import { IFormConfig } from '@/views/demo/form-design/typings/v-form-component';
import { dateFormat } from '@/utils/base';
import { designerDataType, logsType } from './processModel';
import auditInfo from './auditInfo.vue';
import { useMultipleTabStore } from '@/store/modules/multipleTab';
import { useRouter } from 'vue-router';
const props = defineProps({
processId: String,
});
const tabStore = useMultipleTabStore();
const router = useRouter();
const prefixCls = 'preview-box';
const flowContent = ref('');
const flowViewer = ref({});
const route = useRoute();
const processId = props.processId;
// const processId = route.query.processId;
const id = route.query.id;
const infoOpen = ref(true);
const formBoxRef = ref<any>();
const formVisble = ref(false);
@ -210,7 +220,7 @@
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
isFinish: false,
},
];
@ -223,7 +233,7 @@
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
};
taskMap[task.unitId + task.type].userIds.push(task.userId);
taskMap[task.unitId + task.type].userNames.push(task.userName);
@ -236,7 +246,7 @@
userNames: [],
des: '正在查阅',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
isFinish: true,
});
}
@ -250,7 +260,7 @@
userNames: [],
des: '正在审核',
time: `当前-创建时间:${dateFormat(task.createDate)}`,
type: 'primary',
type: 'blue',
};
taskMap[task.unitId].userIds.push(task.userId);
nodeMap[task.unitId][0].userIds.push(task.userId);
@ -288,7 +298,7 @@
userNames: [log.userName],
des: log.des ? log.des : log.operationName,
time: dateFormat(log.createDate),
type: 'info',
type: 'gray',
});
nodeMap[log.unitId] = nodeMap[log.unitId] || [];
@ -299,7 +309,7 @@
userNames: [log.userName],
time: dateFormat(log.createDate),
des: log.des ? log.des : log.operationName,
type: 'info',
type: 'gray',
isFinish: true,
});
if (log.taskType == 1 && !['sign'].includes(log.operationCode)) {

View File

@ -54,4 +54,5 @@ export interface designerDataType {
isCreateAgain: Boolean,
selectRejectNodeVisible:Boolean,
selectSignVisible:Boolean,
formCurrentNode:any
}

View File

@ -56,7 +56,7 @@
const isRead = ref(0);
const type = ref('');
const auditOpen = ref(false);
const [registerTable] = useTable({
const [registerTable,{reload}] = useTable({
api: getLoadMyUncompletedPage,
columns: [
{
@ -148,6 +148,7 @@
}
function closeMolder(){
auditOpen.value = false;
reload()
}
</script>
<style lang="less">