流程发起接口对接,流程任务页面布局

ly
刘妍 2024-03-20 16:58:08 +08:00
parent 52f1233354
commit 1a975d5445
25 changed files with 2112 additions and 28 deletions

View File

@ -1,12 +1,26 @@
// WFProcess 流程模版基本信息
import { defHttp } from '@/utils/http/axios';
import {CreateParams} from './model/WFProcessModel'
import {CreateParams,DeleteDraftParams,RevokeAuditParams} from './model/WFProcessModel'
import {MyUncompletedParams} from './model/WFTaskModel'
enum Api {
// 创建流程
Create = '/api/WFProcess/Create',
SaveDraft='/api/WFProcess/SaveDraft'
// 保存草稿
SaveDraft='/api/WFProcess/SaveDraft',
// 我的流程
LoadMyPage='/api/WFProcess/LoadMyPage',
// 我的草稿
LoadMyDraftPage='/api/WFProcess/LoadMyDraftPage',
// 删除草稿
DeleteDraft='/api/WFProcess/DeleteDraft',
// 催办
Urge='/api/WFProcess/Urge',
// 撤销
Revoke='/api/WFProcess/Revoke',
// 审核撤销
RevokeAudit='/api/WFProcess/RevokeAudit',
}
@ -31,4 +45,60 @@ export function create( params?:CreateParams) {
params,
},
);
}
/**
* @description: getLoadMyPage
*/
export function getLoadMyPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyPage, params });
}
/**
* @description: getLoadMyDraftPage
*/
export function getLoadMyDraftPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyDraftPage, params });
}
/**
* @description: 稿
*/
export function deleteDraft( params:DeleteDraftParams) {
return defHttp.post(
{
url: Api.DeleteDraft+"?id="+params.id,
params,
},
);
}
/**
* @description:
*/
export function urge( params:DeleteDraftParams) {
return defHttp.post(
{
url: Api.Urge+"?id="+params.id,
params,
},
);
}
/**
* @description:
*/
export function revoke( params:DeleteDraftParams) {
return defHttp.post(
{
url: Api.Revoke+"?id="+params.id,
params,
},
);
}
/**
* @description:
*/
export function revokeAudit(params:RevokeAuditParams) {
return defHttp.post(
{
url: Api.RevokeAudit+"?id="+params.id+"&taskId="+params.taskId,
params,
},
);
}

40
src/api/sys/WFTask.ts Normal file
View File

@ -0,0 +1,40 @@
// WFTask
import { defHttp } from '@/utils/http/axios';
import {MyUncompletedParams} from './model/WFTaskModel'
enum Api {
// 我的待办
LoadMyUncompletedPage = '/api/WFTask/LoadMyUncompletedPage',
// 我的已办
LoadMyCompletedPage='/api/WFTask/LoadMyCompletedPage',
// 我的传阅
LoadMyReadPage='/api/WFTask/LoadMyReadPage',
// 我的委托
LoadMyDelegatePage='/api/WFTask/LoadMyDelegatePage',
}
/**
* @description: getLoadMyUncompletedPage
*/
export function getLoadMyUncompletedPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyUncompletedPage, params });
}
/**
* @description: getLoadMyCompletedPage
*/
export function getLoadMyCompletedPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyCompletedPage, params });
}
/**
* @description: getLoadMyReadPage
*/
export function getLoadMyReadPage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyReadPage, params });
}
/**
* @description: getLoadMyDelegatePage
*/
export function getLoadMyDelegatePage(params?: MyUncompletedParams) {
return defHttp.get({ url: Api.LoadMyDelegatePage, params });
}

View File

@ -5,7 +5,7 @@
processId: string,
schemeCode: string,
title: string,
userId: string,
userId?: string,
toUserId: string,
nextUsers: {
additionalProp1: string,
@ -18,4 +18,17 @@
stampImg: string,
stampPassWord: string,
nextId: string
}
}
/**
* @description: 稿
*/
export interface DeleteDraftParams {
id: string,
}
/**
* @description:
*/
export interface RevokeAuditParams {
id: string,
taskId:string,
}

View File

@ -0,0 +1,10 @@
/**
* @description:
*/
export interface MyUncompletedParams {
keyWord: string;
page: number;
limit: number;
startDate: string;
endDate: string;
}

View File

@ -44,8 +44,8 @@ const transform: AxiosTransform = {
return res.data;
}
// 错误的时候返回
const { data } = res;
if (!data) {
// return '[HTTP] Request has no return value';
throw new Error(t('sys.api.apiRequestFailed'));
@ -160,7 +160,7 @@ const transform: AxiosTransform = {
(config as Recordable).headers.Authorization = options.authenticationScheme
? `${options.authenticationScheme} ${token}`
: token;
config.headers['X-Token'] = token;
config.headers['X-Token'] = token;
}
return config;
},
@ -235,10 +235,10 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
// 基础接口地址
// baseURL: globSetting.apiUrl,
headers: {
headers: {
'Content-Type': ContentTypeEnum.JSON,
'T-Token':getToken()
},
'T-Token': getToken()
},
// 如果是form-data格式
// headers: { 'Content-Type': ContentTypeEnum.FORM_URLENCODED },
// 数据处理方式

View File

@ -39,17 +39,19 @@
import { SendOutlined, SaveOutlined, CloseCircleOutlined, ZoomInOutlined, RotateLeftOutlined, RotateRightOutlined, ClearOutlined } from '@ant-design/icons-vue';
import { getDetail } from '@/api/sys/WFSchemeInfo'
import { create ,saveDraft} from '@/api/sys/WFProcess'
import { create, saveDraft } from '@/api/sys/WFProcess'
import { getLoadMyUserList } from '@/api/sys/WFDelegate'
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 { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const userStore = useUserStore();
console.log()
const userInfo = userStore.getUserInfo
console.log(userInfo)
const prefixCls = 'preview-box'
const tabStore = useMultipleTabStore();
const router = useRouter();
@ -95,7 +97,7 @@
async function getDetailInfo() {
let data = await getDetail({ code: code })
flowContent.value = data.scheme.flowContent
formData.userId = userInfo.account
formData.userId = userInfo.id
let content = JSON.parse(data.scheme.content)
let wfData = content.wfData
const currentNode = wfData.find(t => t.type == "bpmn:StartEvent")
@ -118,16 +120,19 @@
userId: formData.userId,
title: formData.title,
processId: buildGUID()
}
if (!designerData.isDraft) {
await saveDraft(querys)
querys.schemeCode = ''
designerData.isDraft = true
}
console.log(querys)
const data = await create(querys)
closePreview()
if (data) {
closePreview()
return createMessage.info('创建成功');
} else {
return createMessage.error('创建失败');
}
}
function closePreview() {

View File

@ -6,8 +6,7 @@
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
icon: 'clarity:info-standard-line',
tooltip: '预览',
label:'预览',
onClick: handleHistory.bind(null, record),
}
]" />

View File

@ -10,7 +10,8 @@
import { BasicDrawer, useDrawerInner } from '@/components/Drawer';
import { postAdd, update } from '@/api/sys/sysDataItemDetail';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
defineOptions({ name: 'SchemeDrawer' });
const emit = defineEmits(['success', 'register']);
@ -52,12 +53,23 @@
querys.itemValue = values.itemValue
querys.sortCode = values.sortCode
const data = await update(querys);
closeDrawer();
emit('success');
if (data) {
closeDrawer();
emit('success');
return createMessage.info('编辑成功');
} else {
return createMessage.error('编辑失败');
}
} else {
const data = await postAdd('FlowSort', values);
closeDrawer();
emit('success');
if (data) {
closeDrawer();
emit('success');
return createMessage.info('创建成功');
} else {
return createMessage.error('创建失败');
}
}
} finally {

View File

@ -17,6 +17,8 @@
import { Card, Row, Col, Spin, Modal } from 'ant-design-vue';
import { BasicModal, useModal } from '@/components/Modal';
import { router } from '@/router';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const [register, { closeModal, openModal }] = useModal();
defineOptions({ name: 'DeptTree' });
@ -30,9 +32,13 @@
var query = {
id: selectItemId.value
}
console.log(query)
const data = await del(query);
emit('success')
if (data) {
emit('success')
return createMessage.info('删除成功');
} else {
return createMessage.error('删除失败');
}
}
async function fetch() {

View File

@ -12,8 +12,7 @@
<template v-if="column.key === 'action'">
<TableAction :actions="[
{
icon: 'clarity:info-standard-line',
tooltip: '查看历史记录',
label:'历史记录',
onClick: handleHistory.bind(null, record),
}
]" />

View File

@ -0,0 +1,120 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :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:'撤销',
onClick: handleRevocation.bind(null, record),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyCompletedPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyCompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '审核',
dataIndex: 'operationName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == '1') {
const color = 'ref';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
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 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record){
console.log(record)
}
function handleRevocation(record){
console.log(record)
}
</script>

View File

@ -0,0 +1,165 @@
import { FormSchema } from '@/components/Form';
export interface ListItem {
key: string;
title: string;
description: string;
extra?: string;
avatar?: string;
color?: string;
}
// tab的list
export const settingList = [
{
key: '1',
name: '待办任务',
component: 'UncompletedTask',
},
{
key: '2',
name: '发起任务',
component: 'CreateFlow',
},
{
key: '3',
name: '委托任务',
component: 'DelegateTask',
},
{
key: '4',
name: '已办任务',
component: 'CompletedTask',
},
{
key: '5',
name: '我的流程',
component: 'MyTask',
},
{
key: '6',
name: '我的传阅',
component: 'ReadTask',
},
{
key: '7',
name: '我的草稿',
component: 'MyDraft',
},
];
// 基础设置 form
export const baseSetschemas: FormSchema[] = [
{
field: 'email',
component: 'Input',
label: '邮箱',
colProps: { span: 18 },
},
{
field: 'name',
component: 'Input',
label: '昵称',
colProps: { span: 18 },
},
{
field: 'introduction',
component: 'InputTextArea',
label: '个人简介',
colProps: { span: 18 },
},
{
field: 'phone',
component: 'Input',
label: '联系电话',
colProps: { span: 18 },
},
{
field: 'address',
component: 'Input',
label: '所在地区',
colProps: { span: 18 },
},
];
// 安全设置 list
export const secureSettingList: ListItem[] = [
{
key: '1',
title: '账户密码',
description: '当前密码强度::强',
extra: '修改',
},
{
key: '2',
title: '密保手机',
description: '已绑定手机138****8293',
extra: '修改',
},
{
key: '3',
title: '密保问题',
description: '未设置密保问题,密保问题可有效保护账户安全',
extra: '修改',
},
{
key: '4',
title: '备用邮箱',
description: '已绑定邮箱ant***sign.com',
extra: '修改',
},
{
key: '5',
title: 'MFA 设备',
description: '未绑定 MFA 设备,绑定后,可以进行二次确认',
extra: '修改',
},
];
// 账号绑定 list
export const accountBindList: ListItem[] = [
{
key: '1',
title: '绑定淘宝',
description: '当前未绑定淘宝账号',
extra: '绑定',
avatar: 'ri:taobao-fill',
color: '#ff4000',
},
{
key: '2',
title: '绑定支付宝',
description: '当前未绑定支付宝账号',
extra: '绑定',
avatar: 'fa-brands:alipay',
color: '#2eabff',
},
{
key: '3',
title: '绑定钉钉',
description: '当前未绑定钉钉账号',
extra: '绑定',
avatar: 'ri:dingding-fill',
color: '#2eabff',
},
];
// 新消息通知 list
export const msgNotifyList: ListItem[] = [
{
key: '1',
title: '账户密码',
description: '其他用户的消息将以站内信的形式通知',
},
{
key: '2',
title: '系统消息',
description: '系统消息将以站内信的形式通知',
},
{
key: '3',
title: '待办任务',
description: '待办任务将以站内信的形式通知',
},
];

View File

@ -0,0 +1,116 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :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:'撤销',
onClick: handleRevocation.bind(null, record),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDelegatePage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyDelegatePage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'isUrge',
width: 80,
customRender: ({ record }) => {
if (record.isUrge == '1') {
const color = 'ref';
const text = '催办';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '正常';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
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 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record){
console.log(record)
}
function handleRevocation(record){
console.log(record)
}
</script>

View File

View File

@ -1,3 +1,57 @@
<template>
流程任务
</template>
<ScrollContainer>
<div ref="wrapperRef" :class="prefixCls">
<Tabs tab-position="left" :tabBarStyle="tabBarStyle">
<template v-for="item in settingList" :key="item.key">
<TabPane :tab="item.name">
<component :is="tabs[item.component]" />
</TabPane>
</template>
</Tabs>
</div>
</ScrollContainer>
</template>
<script lang="ts" setup>
import { Tabs } from 'ant-design-vue';
import { ScrollContainer } from '@/components/Container';
import { settingList } from './data';
import CreateFlow from '../create/index.vue'
import UncompletedTask from './uncompletedTask.vue'
import CompletedTask from './completedTask.vue'
import MyTask from './myTask.vue'
import ReadTask from './readTask.vue'
import MyDraft from './myDraft.vue'
import DelegateTask from './delegateTask.vue'
const TabPane = Tabs.TabPane;
const tabs = {
CreateFlow,
UncompletedTask,
CompletedTask,
MyTask,
ReadTask,
MyDraft,
DelegateTask,
};
const prefixCls = 'account-setting';
const tabBarStyle = {
width: '220px',
};
</script>
<style lang="less">
.account-setting {
margin: 12px;
background-color: @component-background;
.base-title {
padding-left: 0;
}
.ant-tabs-tab-active {
background-color: @item-active-bg;
}
}
</style>

View File

@ -0,0 +1,108 @@
<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:'删除',
color: 'error',
popConfirm: {
title: '是否确认删除',
confirm: () => {
handleDelete(record);
},
},
},
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyDraftPage, deleteDraft } from '@/api/sys/WFProcess'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = 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 },
},
],
},
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.info('删除成功');
}else{
return createMessage.error('删除失败');
}
}
</script>

View File

@ -0,0 +1,164 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :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:'催办',
onClick: handleUrge.bind(null, record),
},
{
label:'撤销',
popConfirm: {
title: '是否撤销流程',
confirm: () => {
handleRevocation(record);
},
},
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive, h } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyPage, urge, revoke, revokeAudit } from '@/api/sys/WFProcess'
import { Tag, Switch } from 'ant-design-vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm, createMessage } = useMessage();
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyPage,
columns: [
{
title: '标题',
dataIndex: 'title',
},
{
title: '流程模版',
dataIndex: 'schemeName',
},
{
title: '状态',
dataIndex: 'isFinished',
width: 80,
customRender: ({ record }) => {
if (record.isFinished == '1') {
const color = 'ref';
const text = '结束';
return h(Tag, { color: color }, () => text);
} else if (record.isAgain == '1') {
const color = 'orange';
const text = '重新提交';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '审批中';
return h(Tag, { color: color }, () => text);
}
},
},
{
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 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 200,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record) {
console.log(record)
}
async function handleUrge(record) {
var query = {
id: record.id
}
const data = await urge(query)
if (data) {
reload()
return createMessage.info('催办成功');
} else {
return createMessage.error('催办失败');
}
}
async function handleRevocation(record) {
console.log(record)
var query = {
id: record.id
}
if (record.isStart == 0) {
const data = await revoke(query)
if (data) {
reload()
return createMessage.info('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
else if (record.isCancel == 1) {
const data = await revokeAudit(query)
if (data) {
reload()
return createMessage.info('撤销成功');
} else {
return createMessage.error('撤销失败');
}
}
}
</script>

View File

@ -0,0 +1,575 @@
<template>
<l-fullscreen-dialog
:title="`${title}`"
:visible.sync="midVisible"
:showOk="false"
@closed="handleClosed"
@opened="handleOpened"
ref="formDialog"
>
<template #headerRight v-if="isRead && task && task.f_State == 1" >
<el-button size="mini" type="primary" @click="handleRead" >{{$t('确认阅读')}}</el-button>
</template>
<l-layout class="l-tab-page" :right="400">
<l-panel :style="{'padding-right':isRead?'':0 }" >
<div class="l-auto-window" style="padding: 0 8px;" >
<el-tabs v-model="activeName" @tab-click="handleTabClick" >
<el-tab-pane v-if="hasWfForm" :label="$t('表单信息')" name="form">
<div class="l-rblock" v-loading="formSchemeLoding">
<template v-if="showForm" >
<l-form-viewer
v-if="formType == '1'"
:formInfo="formInfo"
:isWfForm="true"
:authFieldsMap="formAuthFieldsMap"
ref="wfForm"
></l-form-viewer>
<component ref="wfForm" v-else :requiredMap="formRequiredMap" :authFieldsMap="formAuthFieldsMap" :isWfForm="true" :is="sysFormComponent"></component>
</template>
</div>
</el-tab-pane>
<el-tab-pane :label="$t('流程信息')" name="wfinfo">
<l-layout style="background: #f1f2f5;" :right="320">
<l-panel class="flow-panel" style="padding:0;padding-top:0;" >
<template #title>
<el-button-group>
<el-tooltip effect="dark" :content="$t('复原')" placement="bottom">
<el-button size="mini" icon="el-icon-aim" @click="resetZoom"></el-button>
</el-tooltip>
<el-tooltip effect="dark" :content="$t('放大')" placement="bottom">
<el-button size="mini" icon="el-icon-zoom-in" @click="handlerZoom(0.1)"></el-button>
</el-tooltip>
<el-tooltip effect="dark" :content="$t('缩小')" placement="bottom">
<el-button size="mini" icon="el-icon-zoom-out" @click="handlerZoom(-0.1)"></el-button>
</el-tooltip>
</el-button-group>
<div style="float:right;" >
<el-tag size="small" effect="plain" style="margin-right: 8px;">正在审核</el-tag>
<el-tag size="small" effect="plain" style="margin-right: 8px;" type="success">已审核</el-tag>
</div>
</template>
<b-wflow-viewer
ref="bflow"
@elementClick="elementClick"
>
</b-wflow-viewer>
</l-panel>
<template #right >
<l-panel v-if="nodeLogs.length>0" class="flow-panel" style="padding:0;padding-top:0;" >
<template #title >
记录信息
</template>
<div class="l-rblock l-time-line-wraper" style="padding:8px;overflow:hidden auto;" >
<el-timeline>
<el-timeline-item :type="item.type" v-for="(item,index) in nodeLogs" :key="index" :timestamp="item.time" placement="top">
<el-card shadow="hover">
<div class="title" >{{item.name}}</div>
<div class="content">
<l-user v-for="(userId,index2) in item.userIds" :key="index2" :value="userId" ></l-user>
{{item.des}}
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</l-panel>
</template>
</l-layout>
</el-tab-pane>
<el-tab-pane :label="$t('流转记录')" name="wflogs">
<div class="l-rblock l-time-line-wraper" style="padding:8px;overflow:hidden auto;" >
<el-timeline>
<el-timeline-item :type="item.type" v-for="(item,index) in logs" :key="index" :timestamp="item.time" placement="top">
<el-card shadow="hover">
<div class="title" >{{item.name}}</div>
<div class="content">
<l-user v-for="(userId,index2) in item.userIds" :key="index2" :value="userId" ></l-user>
{{item.des}}
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</el-tab-pane>
</el-tabs>
</div>
</l-panel>
<template #right v-if="!isRead">
<l-panel style="padding-left:0;" title="审批栏" >
<div class="l-rblock" style="padding:8px;" >
<el-form :model="formData" :rules="myRules" size="mini" ref="form" >
<el-form-item :label="isCreateAgain?'备注':'审批意见'" prop="des">
<el-input
type="textarea"
v-model="formData.des"
placeholder="请输入"
rows="3"
>
</el-input >
</el-form-item>
<el-form-item class="l-task-btns" >
<el-button v-for="(btn,index) in taskBtns" :key="index" :type="btn.type" @click="handleBtnClick(btn)" >{{btn.name}}</el-button>
</el-form-item>
</el-form>
<l-wf-audit-info :data="userLogs" ></l-wf-audit-info>
</div>
</l-panel>
</template>
</l-layout>
<l-dialog
:width="500"
:height="nodeUsers.length * 48 + 88"
title="选择下一审核节点人员"
:visible.sync="selectUsersVisible"
@ok="handleSelectUsersSave"
@close="handleSelectUsersCloseForm"
:showClose="false"
>
<select-users ref="selectUsers" :nodeList="nodeUsers"></select-users>
</l-dialog>
<l-dialog
:title="$t(tUserType == 1?`选择转移人员`:`选择加签人员`)"
:visible.sync="selectTUserVisible"
:height="480"
width="1024px"
:hasBtns="false"
>
<l-user-select-panel @change="handleChange" :multiple="false" ref="userSelectPanel" ></l-user-select-panel>
</l-dialog>
<l-dialog
:title="$t('驳回节点选择')"
:visible.sync="selectRejectNodeVisible"
:height="136"
:width="500"
@ok="handleSelectRejectNodeSave"
@close="handleRejectNodeCloseForm"
:showClose="false"
>
<select-reject-node ref="selectRejectNode" :nodeList="completedNodes"></select-reject-node>
</l-dialog>
<!--选择签章-->
<l-dialog
:title="$t('选择签章')"
:visible.sync="selectSignVisible"
:height="480"
:width="508"
@ok="handleSelectSignSave"
@closed="handleSelectSignCloseForm"
@opened="handleSelectSignOpenForm"
>
<select-sign ref="SelectSign" ></select-sign>
</l-dialog>
</l-fullscreen-dialog>
</template>
<script>
import mixin from '../../../mixins/wf'
import SelectUsers from './selectAuditUsers.vue'
import SelectRejectNode from './selectRejectNode.vue'
import SelectSign from './selectSign.vue'
const api = window.$api.workflow.process
const apiStamp = window.$api.workflow.stamp
export default {
mixins:[mixin()],
components:{
SelectUsers,
SelectRejectNode,
SelectSign
},
props:{
isCreateAgain:Boolean,
isRead:Boolean
},
data () {
return {
midVisible:false,
formData:{
des:''
},
rules:{
des:[
{ required: true, message: '请填写审批意见',trigger: 'blur' }
],
},
currentBtn:null,
nodeUsers:[],
selectUsersVisible:false,
selectTUserVisible:false,
tUserType:1, // 1 2 ,
selectRejectNodeVisible:false, //
selectSignVisible:false, //
stampList:[]
}
},
computed:{
myRules(){
if(this.isCreateAgain || this.isRead){
return {}
}
else{
return this.rules
}
},
completedNodes(){
const nodes = this.$deepClone(this.wfData)
return nodes.filter(t=>t.hasFinish && t.id != this.currentNode.id)
},
},
watch:{
visible: {
handler (n) {
this.midVisible = n
}
},
},
methods:{
resetZoom(){
this.$refs.bflow.reset()
},
handlerZoom(r){
this.$refs.bflow.handlerZoom(r)
},
elementClick(node){
if(node){
this.nodeLogs = this.nodeMap[node.id] || []
}
else{
this.nodeLogs = []
}
},
resetFormToMe(){
this.$refs.form && this.$refs.form.resetFields()
this.taskBtns = []
},
setForm(){
this.$refs.form && this.$refs.form.clearValidate()
this.currentNode = this.wfData.find(t=>t.id == this.task.f_UnitId)
//
const btns = []
if(this.currentNode.type =='startEvent'){
btns.push({
code:'learun_create',
name:'提交',
type:'primary'
})
}
else{
this.currentNode.btnlist.forEach(btn => {
if(btn.code == 'agree'){
btn.type = 'primary'
}
else if(btn.code == 'disagree'){
btn.type = 'danger'
}
btns.push(btn)
})
if(this.currentNode.isAddSign){
btns.push({
code:'learun_sign',
name:'加签',
type:'success'
})
}
if(this.currentNode.isTransfer){
btns.push({
code:'learun_transfer',
name:'转移',
type:'success'
})
}
}
this.taskBtns = btns
},
validateForm(){
return this.$formValidateWraper(this.$refs.form)
},
handleBtnClick(btn){
this.$refs.formDialog.showLoading('流程处理中...')
this.$nextTick(async ()=>{
this.currentBtn = btn
if(!(await this.validateForm())){
this.$refs.formDialog.hideLoading()
return
}
if(!(await this.validateWfForm())){
this.$refs.formDialog.hideLoading()
return
}
if(!(await this.saveWfForm(btn.code))){
this.$refs.formDialog.hideLoading()
return
}
let res
switch(btn.code){
case 'learun_create':
res = await this.$awaitWraper(api.createAgain({
processId:this.processId,
des:`重新提交${this.formData.des?'-':''}${this.formData.des}`
}))
break
case 'learun_sign':
this.tUserType = 2
this.selectTUserVisible = true
break
case 'learun_transfer':
this.tUserType = 1
this.selectTUserVisible = true
break
default:
if(this.task.f_Type == 6){//
res = await this.$awaitWraper(api.signAudit(this.taskId,{
code:btn.code,
name:btn.name,
des:this.formData.des
}))
}
else {
if(this.currentNode.rejectType == '2' && btn.code == 'disagree'){
this.selectRejectNodeVisible = true
this.$refs.formDialog.hideLoading()
return
}
if(btn.isSign){
//
const stampList = await this.$awaitWraper(apiStamp.getList(this.loginInfo.f_UserId))
if(stampList && stampList.length >0){
this.stampList = stampList
this.selectSignVisible = true
this.$refs.formDialog.hideLoading()
return
}
}
res = await this.audit()
}
break
}
this.$refs.formDialog.hideLoading()
if(res){
this.midVisible = false
this.$emit('refresh')
}
})
},
async audit(){
//
if(this.currentBtn.isNextAuditor){
const res = await api.getNextUsers({processId:this.processId,nodeId:this.currentNode.id})
const nodeUserMap = res.data.data
const nodeUsers = []
for(let key in nodeUserMap){
const nodeUserItem = nodeUserMap[key]
if(nodeUserItem.length > 1){
nodeUsers.push({
name:this.wfData.find(t=>t.id == key).name,
id:key,
options:nodeUserItem.map(t=>{return{value:t.id,label:t.name} })
})
}
}
this.nodeUsers = nodeUsers
if(this.nodeUsers.length > 0){
this.selectUsersVisible = true
return
}
}
return await this.$awaitWraper(api.audit(this.taskId,{
code:this.currentBtn.code,
name:this.currentBtn.name,
des:this.formData.des
}))
},
handleSelectUsersSave(){
this.selectUsersVisible = false
this.$refs.formDialog.showLoading('流程处理中...')
const nextUsers = this.$refs.selectUsers.getForm()
this.$nextTick(async ()=>{
const res = await this.$awaitWraper(api.audit(this.taskId,{
code:this.currentBtn.code,
name:this.currentBtn.name,
nextUsers: nextUsers,
des:this.formData.des
}))
if(res){
this.midVisible = false
}
this.$refs.formDialog.hideLoading()
this.$emit('refresh')
})
},
handleSelectUsersCloseForm(){
this.$refs.selectUsers.resetForm()
},
handleChange(userInfo){
if(userInfo){
const title = this.tUserType == 1?'转移':'加签'
if(this.loginInfo.f_UserId == userInfo.f_UserId){
this.$message({
type: 'warning',
message: `${title}不能给自己本人`
})
return
}
this.$confirm(`是否确定${title}${userInfo.f_RealName}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.selectTUserVisible = false
this.$refs.formDialog.showLoading('流程处理中...')
this.$nextTick(async ()=>{
let res
if(this.tUserType == 1){
res = await this.$awaitWraper(api.transferUser(this.taskId,{
toUserId:userInfo.f_UserId,
des:`转移给${userInfo.f_RealName}${this.formData.des?'-':''}${this.formData.des}`
}))
}
else{
res = await this.$awaitWraper(api.sign(this.taskId,{
toUserId:userInfo.f_UserId,
des:`加签给${userInfo.f_RealName}${this.formData.des?'-':''}${this.formData.des}`
}))
}
this.$refs.formDialog.hideLoading()
if(res){
this.midVisible = false
this.$emit('refresh')
}
})
}).catch(() => {
this.$message({
type: 'info',
message: `已取消${title}`
})
})
}
},
async handleSelectRejectNodeSave(){
if(await this.$refs.selectRejectNode.validateForm()){
this.$refs.formDialog.showLoading('流程处理中...')
const nextId = this.$refs.selectRejectNode.getForm()
this.selectRejectNodeVisible = false
this.$nextTick(async ()=>{
const res = await this.$awaitWraper(api.audit(this.taskId,{
code:this.currentBtn.code,
name:this.currentBtn.name,
nextId: nextId,
des:this.formData.des
}))
if(res){
this.midVisible = false
}
this.$refs.formDialog.hideLoading()
this.$emit('refresh')
})
}
},
handleRejectNodeCloseForm(){
this.$refs.selectRejectNode.resetForm()
},
async handleRead(){
this.$refs.formDialog.showLoading('流程处理中...')
const res = await this.$awaitWraper(api.readAudit(this.taskId))
if(res){
this.midVisible = false
}
this.$refs.formDialog.hideLoading()
this.$emit('refresh')
},
//
async handleSelectSignSave(){
if(await this.$refs.SelectSign.validateForm()){
this.$refs.formDialog.showLoading('流程处理中...')
const {f_StampId,f_Password} = this.$refs.SelectSign.getForm()
this.selectSignVisible = false
this.$nextTick(async ()=>{
const res = await this.$awaitWraper(api.audit(this.taskId,{
code:this.currentBtn.code,
name:this.currentBtn.name,
stampImg:f_StampId,
stampPassWord:f_Password,
des:this.formData.des
}))
if(res){
this.midVisible = false
}
this.$refs.formDialog.hideLoading()
this.$emit('refresh')
})
}
},
handleSelectSignCloseForm(){
this.$refs.SelectSign.resetForm()
},
handleSelectSignOpenForm(){
this.$refs.SelectSign.setForm(this.stampList)
}
}
}
</script>
<style lang="scss">
.l-task-btns{
.el-button{
margin: 0;
margin-top: 8px;
margin-right: 8px;
}
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<l-fullscreen-dialog
:title="`${$t('查看流程')}【${title}】`"
:visible.sync="midVisible"
:showOk="false"
@closed="handleClosed"
@opened="handleOpened"
ref="formDialog"
>
<l-layout class="l-tab-page" :right="400">
<l-panel :style="{ 'padding-right':userLogs.length >0?0:''}" >
<div class="l-auto-window" style="padding: 0 8px;" >
<el-tabs v-model="activeName" @tab-click="handleTabClick" >
<el-tab-pane v-if="hasWfForm" :label="$t('表单信息')" name="form">
<div class="l-rblock" v-loading="formSchemeLoding">
<template v-if="showForm" >
<l-form-viewer
v-if="formType == '1'"
:formInfo="formInfo"
:isWfForm="true"
:authFieldsMap="formAuthFieldsMap"
ref="wfForm"
></l-form-viewer>
<component ref="wfForm" v-else :requiredMap="formRequiredMap" :authFieldsMap="formAuthFieldsMap" :isWfForm="true" :is="sysFormComponent"></component>
</template>
</div>
</el-tab-pane>
<el-tab-pane :label="$t('流程信息')" name="wfinfo">
<l-layout style="background: #f1f2f5;" :right="320">
<l-panel class="flow-panel" style="padding:0;padding-top:0;" >
<template #title>
<el-button-group>
<el-tooltip effect="dark" :content="$t('复原')" placement="bottom">
<el-button size="mini" icon="el-icon-aim" @click="resetZoom"></el-button>
</el-tooltip>
<el-tooltip effect="dark" :content="$t('放大')" placement="bottom">
<el-button size="mini" icon="el-icon-zoom-in" @click="handlerZoom(0.1)"></el-button>
</el-tooltip>
<el-tooltip effect="dark" :content="$t('缩小')" placement="bottom">
<el-button size="mini" icon="el-icon-zoom-out" @click="handlerZoom(-0.1)"></el-button>
</el-tooltip>
</el-button-group>
<div style="float:right;" >
<el-tag size="small" effect="plain" style="margin-right: 8px;">正在审核</el-tag>
<el-tag size="small" effect="plain" style="margin-right: 8px;" type="success">已审核</el-tag>
</div>
</template>
<b-wflow-viewer
ref="bflow"
@elementClick="elementClick"
>
</b-wflow-viewer>
</l-panel>
<template #right >
<l-panel v-if="nodeLogs.length>0" class="flow-panel" style="padding:0;padding-top:0;" >
<template #title >
记录信息
</template>
<div class="l-rblock l-time-line-wraper" style="padding:8px;overflow:hidden auto;" >
<el-timeline>
<el-timeline-item :type="item.type" v-for="(item,index) in nodeLogs" :key="index" :timestamp="item.time" placement="top">
<el-card shadow="hover">
<div class="title" >{{item.name}}</div>
<div class="content">
<l-user v-for="(userId,index2) in item.userIds" :key="index2" :value="userId" ></l-user>
{{item.des}}
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</l-panel>
</template>
</l-layout>
</el-tab-pane>
<el-tab-pane :label="$t('流转记录')" name="wflogs">
<div class="l-rblock l-time-line-wraper" style="padding:8px;overflow:hidden auto;" >
<el-timeline>
<el-timeline-item :type="item.type" v-for="(item,index) in logs" :key="index" :timestamp="item.time" placement="top">
<el-card shadow="hover">
<div class="title" >{{item.name}}</div>
<div class="content">
<l-user v-for="(userId,index2) in item.userIds" :key="index2" :value="userId" ></l-user>
{{item.des}}
</div>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</el-tab-pane>
</el-tabs>
</div>
</l-panel>
<template #right >
<l-panel v-if="userLogs.length >0" style="padding-left:0;" title="审批信息" >
<div class="l-rblock" style="padding:8px;" >
<l-wf-audit-info :data="userLogs" ></l-wf-audit-info>
</div>
</l-panel>
</template>
</l-layout>
</l-fullscreen-dialog>
</template>
<script>
import mixin from '../../../mixins/wf'
export default {
mixins:[mixin()],
data () {
return {
midVisible:false,
}
},
watch:{
visible: {
handler (n) {
this.midVisible = n
}
},
},
methods:{
resetZoom(){
this.$refs.bflow.reset()
},
handlerZoom(r){
this.$refs.bflow.handlerZoom(r)
},
elementClick(node){
if(node){
this.nodeLogs = this.nodeMap[node.id] || []
}
else{
this.nodeLogs = []
}
},
setForm(){
if(this.type == 'look' && this.task)
{
this.currentNode = this.wfData.find(t=>t.id == this.task.f_UnitId)
}
else{
this.currentNode = this.wfData.find(t=>t.type == 'startEvent')
}
}
}
}
</script>

View File

@ -0,0 +1,39 @@
<template>
<div class="l-from-body" >
<el-form :model="formData" size="mini" ref="form" label-width="108px" >
<el-col :span="24" v-for="(item,index) in nodeList" :key="index" >
<el-form-item :label="item.name" :prop="item.id">
<l-select multiple v-model="formData[item.id]" :options="item.options" ></l-select>
</el-form-item>
</el-col>
</el-form>
</div>
</template>
<script>
export default {
props:{
nodeList:{
type:Array,
default:()=>[]
}
},
data(){
return {
formData:{
}
}
},
created () {
},
computed:{
},
methods:{
resetForm(){
this.formData = {}
},
getForm(){
return this.$deepClone(this.formData)
}
}
}
</script>

View File

@ -0,0 +1,48 @@
<template>
<div class="l-from-body" >
<el-form :model="formData" size="mini" ref="form" label-width="64px" >
<el-col :span="24">
<el-form-item label="驳回到" prop="nodeId">
<l-select labelKey="name" valueKey="id" v-model="formData.nodeId" :options="nodeList" ></l-select>
</el-form-item>
</el-col>
</el-form>
</div>
</template>
<script>
export default {
props:{
nodeList:{
type:Array,
default:()=>[]
}
},
data(){
return {
formData:{
nodeId:''
},
rules:{
nodeId: [
{ required: true, message: '请选择流转节点' },
]
},
}
},
created () {
},
computed:{
},
methods:{
resetForm(){
this.$refs.form && this.$refs.form.resetFields()
},
validateForm(){
return this.$refs.form.validate()
},
getForm(){
return this.formData.nodeId
}
}
}
</script>

View File

@ -0,0 +1,160 @@
<template>
<l-layout :bottom="46">
<template #bottom >
<el-form style="padding-right:16px;" v-if="selectItem.f_IsNotPassword == 1" :model="formData" :rules="rules" size="mini" ref="form" label-width="64px" >
<el-col :span="24">
<el-form-item label="密码" prop="f_Password">
<el-input type="password" v-model="formData.f_Password"></el-input>
</el-form-item>
</el-col>
</el-form>
</template>
<div class="sign-type-list" >
<div @click="handleChange(item)" :class="['sign-type-list--item',{'checked':selectValue == item.f_StampId }]" v-for="(item,index) in signList" :key="index" >
<div class="sign-type-list--imgdiv" >
<img class="sign-type-list--img" :src="`${apiUrl}system/annexesfile/${item.f_ImgFile}?token=${token}`" >
<div class="sign-type-list--checked" v-if="selectValue == item.f_StampId" >
<i class="el-icon-check" ></i>
</div>
</div>
<p class="sign-type-list--label" >{{$t(item.f_StampName)}}</p>
</div>
</div>
</l-layout>
</template>
<script>
export default {
data(){
return {
signList:[],
selectValue:'',
selectItem:{},
formData:{
f_Password:''
},
rules: {
f_Password: [
{ required: true, message: '请填写密码',trigger: 'blur' }
]
},
}
},
created () {
},
computed:{
},
methods:{
resetForm(){
this.selectValue = ''
this.selectItem = {}
this.signList = []
this.$refs.form && this.$refs.form.resetFields()
},
async validateForm(){
if(this.selectValue){
if(this.selectItem.f_IsNotPassword == 1){
if(await this.$refs.form.validate()){
if(this.selectItem.f_Password == this.$md5(this.formData.f_Password)){
return true
}
else{
this.$message({
type: 'error',
message: this.$t('密码错误!')
})
}
}
}
else{
return true
}
}
else{
this.$message({
type: 'error',
message: this.$t('请选择签章!')
})
}
return false
},
handleChange(item){
this.selectItem = item
this.selectValue = item.f_StampId
},
setForm(data){
this.signList = this.$deepClone(data)
if(this.signList.length == 1){
this.selectItem = this.signList[0]
this.selectValue = this.signList[0].f_StampId
}
},
getForm(){
return this.selectItem
}
}
}
</script>
<style lang="scss" scoped>
.sign-type-list{
display: flex;
flex-wrap: wrap;
padding-top: 16px;
overflow: auto;
height: 100%;
width: 100%;
position: relative;
box-sizing: border-box;
&--item{
width: 144px;
margin:0 0 16px 16px;
}
&--imgdiv{
width: 144px;
height: 144px;
border-radius: 2px;
overflow: hidden;
cursor: pointer;
position: relative;
border: 1px solid #f1f2f5;
padding: 4px;
}
&--item.checked &--imgdiv{
border: 1px solid #409eff;
}
&--img{
width: 100%;
}
&--label{
font-size: 12px;
color: #606266;
margin-top: 8px;
text-align: center;
}
&--checked{
border: 12px solid #409eff;
border-left: 12px solid transparent;
border-bottom: 12px solid transparent;
border-top-right-radius: 2px;
position: absolute;
right: 3px;
top: 3px;
.el-icon-check{
position: absolute;
top: -10px;
left: -2px;
font-size: 12px;
color: #fff;
}
}
}
</style>

View File

@ -0,0 +1,116 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :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:'撤销',
onClick: handleRevocation.bind(null, record),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyReadPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyReadPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'state',
width: 80,
customRender: ({ record }) => {
if (record.state == '1') {
const color = 'ref';
const text = '未阅';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '已阅';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
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 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record){
console.log(record)
}
function handleRevocation(record){
console.log(record)
}
</script>

View File

@ -0,0 +1,108 @@
<template>
<PageWrapper dense contentFullHeight fixedHeight contentClass="flex">
<BasicTable @register="registerTable" @fetch-success="onFetchSuccess" :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),
}
]" />
</template>
</template>
</BasicTable>
</PageWrapper>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
import { BasicTable, useTable, TableAction } from '@/components/Table';
import { PageWrapper } from '@/components/Page';
import { getLoadMyUncompletedPage } from '@/api/sys/WFTask'
import { Tag, Switch } from 'ant-design-vue';
const searchInfo = reactive < Recordable > ({});
const [registerTable, { reload, expandAll, getSelectRows, clearSelectedRowKeys }] = useTable({
api: getLoadMyUncompletedPage,
columns: [
{
title: '任务',
dataIndex: 'unitName',
},
{
title: '标题',
dataIndex: 'processTitle',
},
{
title: '状态',
dataIndex: 'isUrge',
width: 80,
customRender: ({ record }) => {
if (record.isUrge == '1') {
const color = 'ref';
const text = '催办';
return h(Tag, { color: color }, () => text);
} else {
const color = 'green';
const text = '正常';
return h(Tag, { color: color }, () => text);
}
},
},
{
title: '提交人',
dataIndex: 'processUserName',
},
{
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 },
},
],
},
useSearchForm: true,
showTableSetting: true,
bordered: true,
handleSearchInfoFn(info) {
return info;
},
actionColumn: {
width: 100,
title: '操作',
dataIndex: 'action',
// slots: { customRender: 'action' },
},
});
function handleDetail(record){
console.log(record)
}
</script>

View File

@ -0,0 +1,4 @@
export default {
wfName:'handleWF',
name:'handleWF'
}