chore: 我的待办 提取公共组件
This commit is contained in:
parent
ed9448d1ba
commit
e56672864f
@ -14,14 +14,16 @@ export interface TaskInfo {
|
|||||||
permissionList?: any;
|
permissionList?: any;
|
||||||
userList?: any;
|
userList?: any;
|
||||||
formCustom: string;
|
formCustom: string;
|
||||||
formPath: string;
|
formPath?: any;
|
||||||
flowCode: string;
|
flowCode: string;
|
||||||
version: string;
|
version: string;
|
||||||
flowStatus: string;
|
flowStatus: string;
|
||||||
flowStatusName: string;
|
flowStatusName: string;
|
||||||
transactorNames: string;
|
assigneeIds: string;
|
||||||
|
assigneeNames: string;
|
||||||
processedBy: string;
|
processedBy: string;
|
||||||
type: string;
|
type: string;
|
||||||
nodeRatio?: any;
|
nodeRatio?: any;
|
||||||
nickName: string;
|
createBy: string;
|
||||||
|
createByName: string;
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,8 @@ function handleClick() {
|
|||||||
</Descriptions>
|
</Descriptions>
|
||||||
<div class="flex items-center justify-between text-[14px]">
|
<div class="flex items-center justify-between text-[14px]">
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<VbenAvatar :alt="info.nickName" class="size-[24px]" src="" />
|
<VbenAvatar :alt="info.createByName" class="size-[24px]" src="" />
|
||||||
<span class="opacity-50">{{ info.nickName }}</span>
|
<span class="opacity-50">{{ info.createByName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="opacity-50">更新时间: 2222-22-22</div>
|
<div class="opacity-50">更新时间: 2222-22-22</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { FlowInfoResponse } from '#/api/workflow/instance/model';
|
||||||
|
import type { TaskInfo } from '#/api/workflow/task/model';
|
||||||
|
|
||||||
|
import { onUnmounted, ref, watch } from 'vue';
|
||||||
|
|
||||||
|
import { Fallback, VbenAvatar } from '@vben/common-ui';
|
||||||
|
import { DictEnum } from '@vben/constants';
|
||||||
|
|
||||||
|
import { Card, Divider, TabPane, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { flowInfo } from '#/api/workflow/instance';
|
||||||
|
import { renderDict } from '#/utils/render';
|
||||||
|
|
||||||
|
import { ApprovalTimeline } from '.';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ApprovalPanel',
|
||||||
|
inheritAttrs: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{ task?: TaskInfo }>();
|
||||||
|
|
||||||
|
const currentFlowInfo = ref<FlowInfoResponse>();
|
||||||
|
watch(
|
||||||
|
() => props.task,
|
||||||
|
async (task) => {
|
||||||
|
if (!task) return null;
|
||||||
|
const resp = await flowInfo(task.businessId);
|
||||||
|
currentFlowInfo.value = resp;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => (currentFlowInfo.value = undefined));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Card
|
||||||
|
v-if="task"
|
||||||
|
:body-style="{ overflowY: 'auto', height: '100%' }"
|
||||||
|
:title="`编号: ${task.id}`"
|
||||||
|
class="thin-scrollbar flex-1 overflow-y-hidden"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<div class="flex flex-col gap-5 p-4">
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="text-2xl font-bold">{{ task.flowName }}</div>
|
||||||
|
<div>
|
||||||
|
<component
|
||||||
|
:is="renderDict(task.flowStatus, DictEnum.WF_BUSINESS_STATUS)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<VbenAvatar :alt="task.createByName" class="size-[24px]" src="" />
|
||||||
|
<span>{{ task.createByName }}</span>
|
||||||
|
<div class="flex items-center opacity-50">
|
||||||
|
<span>XXXX有限公司</span>
|
||||||
|
<Divider type="vertical" />
|
||||||
|
<span>提交于: {{ task.createTime }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Tabs v-if="currentFlowInfo" class="flex-1">
|
||||||
|
<TabPane key="1" tab="审批详情">
|
||||||
|
<div class="h-fulloverflow-y-auto">
|
||||||
|
<!-- <Alert message="该页面仅为静态页 后期可能会用到!" type="info" /> -->
|
||||||
|
<iframe
|
||||||
|
:src="`/workflow/leave-inner?readonly=true&id=${task.businessId}`"
|
||||||
|
class="h-[300px] w-full"
|
||||||
|
></iframe>
|
||||||
|
<Divider />
|
||||||
|
<ApprovalTimeline :list="currentFlowInfo.list" />
|
||||||
|
</div>
|
||||||
|
</TabPane>
|
||||||
|
<TabPane key="2" tab="审批流程图">
|
||||||
|
<img
|
||||||
|
:src="`data:image/png;base64,${currentFlowInfo.image}`"
|
||||||
|
class="rounded-lg border"
|
||||||
|
/>
|
||||||
|
</TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
<!-- 固定底部 -->
|
||||||
|
<div
|
||||||
|
class="border-t-solid bg-background absolute bottom-0 left-0 w-full border-t-[1px] p-3"
|
||||||
|
>
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<Space>
|
||||||
|
<a-button type="primary">通过</a-button>
|
||||||
|
<a-button danger type="primary">驳回</a-button>
|
||||||
|
<a-button>其他</a-button>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
<Fallback v-else title="点击左侧选择" />
|
||||||
|
</template>
|
@ -7,6 +7,9 @@ import { Timeline, TimelineItem } from 'ant-design-vue';
|
|||||||
* TODO: 仅为demo 后期会替换
|
* TODO: 仅为demo 后期会替换
|
||||||
*/
|
*/
|
||||||
import { VbenAvatar } from '@vben/common-ui';
|
import { VbenAvatar } from '@vben/common-ui';
|
||||||
|
import { DictEnum } from '@vben/constants';
|
||||||
|
|
||||||
|
import { renderDict } from '#/utils/render';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
list: Flow[];
|
list: Flow[];
|
||||||
@ -19,17 +22,15 @@ const props = defineProps<{
|
|||||||
<template #dot>
|
<template #dot>
|
||||||
<div class="relative rounded-full border">
|
<div class="relative rounded-full border">
|
||||||
<VbenAvatar :alt="item.approveName" class="size-[36px]" src="" />
|
<VbenAvatar :alt="item.approveName" class="size-[36px]" src="" />
|
||||||
<div
|
|
||||||
class="border-background absolute bottom-0 right-0 size-[16px] rounded-full border-2 bg-green-500 content-['']"
|
|
||||||
>
|
|
||||||
<div class="flex items-center justify-center">
|
|
||||||
<span class="icon-[mdi--success-bold] text-white"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="ml-2 flex flex-col gap-0.5">
|
<div class="ml-2 flex flex-col gap-0.5">
|
||||||
<div class="font-bold">{{ item.nodeName }}</div>
|
<div class="flex items-center gap-1">
|
||||||
|
<div class="font-bold">{{ item.nodeName }}</div>
|
||||||
|
<component
|
||||||
|
:is="renderDict(item.flowStatus, DictEnum.WF_TASK_STATUS)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div>{{ item.approveName }}</div>
|
<div>{{ item.approveName }}</div>
|
||||||
<div>{{ item.updateTime }}</div>
|
<div>{{ item.updateTime }}</div>
|
||||||
<div v-if="item.message" class="rounded-lg border p-1">
|
<div v-if="item.message" class="rounded-lg border p-1">
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
export { default as ApprovalCard } from './approval-card.vue';
|
export { default as ApprovalCard } from './approval-card.vue';
|
||||||
|
export { default as ApprovalPanel } from './approval-panel.vue';
|
||||||
export { default as ApprovalTimeline } from './approval-timeline.vue';
|
export { default as ApprovalTimeline } from './approval-timeline.vue';
|
||||||
|
@ -4,24 +4,15 @@ import type { TaskInfo } from '#/api/workflow/task/model';
|
|||||||
|
|
||||||
import { computed, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
import { Fallback, Page, VbenAvatar } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import {
|
import { Empty, InputSearch } from 'ant-design-vue';
|
||||||
Card,
|
|
||||||
Divider,
|
|
||||||
Empty,
|
|
||||||
InputSearch,
|
|
||||||
Space,
|
|
||||||
TabPane,
|
|
||||||
Tabs,
|
|
||||||
Tag,
|
|
||||||
} from 'ant-design-vue';
|
|
||||||
import { debounce } from 'lodash-es';
|
import { debounce } from 'lodash-es';
|
||||||
|
|
||||||
import { flowInfo } from '#/api/workflow/instance';
|
import { flowInfo } from '#/api/workflow/instance';
|
||||||
import { pageByTaskWait } from '#/api/workflow/task';
|
import { pageByTaskWait } from '#/api/workflow/task';
|
||||||
|
|
||||||
import { ApprovalCard, ApprovalTimeline } from '../components';
|
import { ApprovalCard, ApprovalPanel } from '../components';
|
||||||
|
|
||||||
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
|
const emptyImage = Empty.PRESENTED_IMAGE_SIMPLE;
|
||||||
|
|
||||||
@ -70,12 +61,14 @@ const handleScroll = debounce(async (e: Event) => {
|
|||||||
const currentInstance = ref<FlowInfoResponse>();
|
const currentInstance = ref<FlowInfoResponse>();
|
||||||
|
|
||||||
const lastSelectId = ref('');
|
const lastSelectId = ref('');
|
||||||
|
const currentTask = ref<TaskInfo>();
|
||||||
async function handleCardClick(item: TaskInfo) {
|
async function handleCardClick(item: TaskInfo) {
|
||||||
const { id, businessId } = item;
|
const { id, businessId } = item;
|
||||||
// 点击的是同一个
|
// 点击的是同一个
|
||||||
if (lastSelectId.value === id) {
|
if (lastSelectId.value === id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
currentTask.value = item;
|
||||||
// 反选状态 & 如果已经点击了 不变 & 保持只能有一个选中
|
// 反选状态 & 如果已经点击了 不变 & 保持只能有一个选中
|
||||||
taskList.value.forEach((item) => {
|
taskList.value.forEach((item) => {
|
||||||
item.active = item.id === id;
|
item.active = item.id === id;
|
||||||
@ -85,25 +78,6 @@ async function handleCardClick(item: TaskInfo) {
|
|||||||
const resp = await flowInfo(businessId);
|
const resp = await flowInfo(businessId);
|
||||||
currentInstance.value = resp;
|
currentInstance.value = resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
const instanceInfo = computed(() => {
|
|
||||||
if (!currentInstance.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const length = currentInstance.value.list.length;
|
|
||||||
if (length === 2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 最末尾为申请人
|
|
||||||
const info = currentInstance.value.list[length - 1]!;
|
|
||||||
return {
|
|
||||||
id: info.instanceId,
|
|
||||||
createTime: info.createTime,
|
|
||||||
approveName: info.approveName,
|
|
||||||
flowName: info.flowName ?? '未知流程',
|
|
||||||
businessId: '1867081791031750658',
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -142,69 +116,7 @@ const instanceInfo = computed(() => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Card
|
<ApprovalPanel :task="currentTask" />
|
||||||
v-if="currentInstance && instanceInfo"
|
|
||||||
:body-style="{ overflowY: 'auto', height: '100%' }"
|
|
||||||
:title="`编号: ${instanceInfo.id}`"
|
|
||||||
class="thin-scrollbar flex-1 overflow-y-hidden"
|
|
||||||
size="small"
|
|
||||||
>
|
|
||||||
<div class="flex flex-col gap-5 p-4">
|
|
||||||
<div class="flex flex-col gap-3">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<div class="text-2xl font-bold">{{ instanceInfo.flowName }}</div>
|
|
||||||
<div>
|
|
||||||
<Tag color="warning">申请中</Tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<VbenAvatar
|
|
||||||
:alt="instanceInfo.approveName"
|
|
||||||
class="size-[24px]"
|
|
||||||
src=""
|
|
||||||
/>
|
|
||||||
<span>{{ instanceInfo.approveName }}</span>
|
|
||||||
<div class="flex items-center opacity-50">
|
|
||||||
<span>XXXX有限公司</span>
|
|
||||||
<Divider type="vertical" />
|
|
||||||
<span>提交于: {{ instanceInfo.createTime }}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Tabs class="flex-1">
|
|
||||||
<TabPane key="1" tab="审批详情">
|
|
||||||
<div class="h-fulloverflow-y-auto">
|
|
||||||
<!-- <Alert message="该页面仅为静态页 后期可能会用到!" type="info" /> -->
|
|
||||||
<iframe
|
|
||||||
:src="`/workflow/leave-inner?readonly=true&id=${instanceInfo.businessId}`"
|
|
||||||
class="h-[300px] w-full"
|
|
||||||
></iframe>
|
|
||||||
<Divider />
|
|
||||||
<ApprovalTimeline :list="currentInstance.list" />
|
|
||||||
</div>
|
|
||||||
</TabPane>
|
|
||||||
<TabPane key="2" tab="审批流程图">
|
|
||||||
<img
|
|
||||||
:src="`data:image/png;base64,${currentInstance.image}`"
|
|
||||||
class="rounded-lg border"
|
|
||||||
/>
|
|
||||||
</TabPane>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
<!-- 固定底部 -->
|
|
||||||
<div
|
|
||||||
class="border-t-solid bg-background absolute bottom-0 left-0 w-full border-t-[1px] p-3"
|
|
||||||
>
|
|
||||||
<div class="flex justify-end">
|
|
||||||
<Space>
|
|
||||||
<a-button type="primary">通过</a-button>
|
|
||||||
<a-button danger type="primary">驳回</a-button>
|
|
||||||
<a-button>其他</a-button>
|
|
||||||
</Space>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
<Fallback v-else title="点击左侧选择" />
|
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
@ -12,4 +12,5 @@ export enum DictEnum {
|
|||||||
SYS_YES_NO = 'sys_yes_no', // 是否
|
SYS_YES_NO = 'sys_yes_no', // 是否
|
||||||
WF_BUSINESS_STATUS = 'wf_business_status', // 业务状态
|
WF_BUSINESS_STATUS = 'wf_business_status', // 业务状态
|
||||||
WF_FORM_TYPE = 'wf_form_type', // 表单类型
|
WF_FORM_TYPE = 'wf_form_type', // 表单类型
|
||||||
|
WF_TASK_STATUS = 'wf_task_status', // 任务状态
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user