<script lang="ts" setup>
|
import { reactive, ref } from 'vue';
|
|
import { useGlobSetting } from '@jnpf/hooks';
|
import { createImgPreview } from '@jnpf/ui';
|
import { BasicModal, useModalInner } from '@jnpf/ui/modal';
|
import { formatToDateTime } from '@jnpf/utils';
|
|
import { ArrowRightOutlined } from '@ant-design/icons-vue';
|
import { Image } from 'ant-design-vue';
|
|
import { getRecordList } from '#/api/workFlow/task';
|
import { useFlowState } from '#/hooks/flow/useFlowStatus';
|
|
interface State {
|
list: any[];
|
loading: boolean;
|
title: string;
|
}
|
|
const state = reactive<State>({
|
list: [],
|
loading: false,
|
title: '',
|
});
|
const globSetting = useGlobSetting();
|
const apiUrl = ref(globSetting.apiURL);
|
const { getFlowStateContent, getFlowStateColor, getHexColor } = useFlowState();
|
const [registerModal, { changeLoading }] = useModalInner(init);
|
|
function init(data) {
|
changeLoading(true);
|
state.loading = true;
|
state.list = [];
|
state.title = data.title;
|
getRecordList(data.taskId, data.nodeId).then((res) => {
|
state.list = res.data.map((o) => ({ ...o, fileList: o.fileList ? JSON.parse(o.fileList) : [] })) || [];
|
changeLoading(false);
|
state.loading = false;
|
});
|
}
|
function handlePreview(img) {
|
createImgPreview({ imageList: [img] });
|
}
|
</script>
|
<template>
|
<BasicModal v-bind="$attrs" @register="registerModal" :title="state.title" destroy-on-close class="jnpf-flow-record-modal" :footer="null">
|
<div class="record-container" v-if="state.list?.length">
|
<div class="record-item" v-for="item in state.list" :key="item">
|
<div class="record-item-top">
|
<a-avatar :size="40" :src="apiUrl + item.headIcon" class="avatar" />
|
<div class="user-info">
|
<div class="user-name">{{ item.userName }}</div>
|
<div class="handle-time">{{ formatToDateTime(item.handleTime) }}</div>
|
</div>
|
<div class="handle-type">
|
<a-tag :color="getHexColor(getFlowStateColor(item.handleType))" :bordered="false" class="handle-status">
|
{{ getFlowStateContent(item.handleType) }}
|
</a-tag>
|
<ArrowRightOutlined class="arrow-right" v-if="item.handleUserName" />
|
<span class="handle-user-name" :title="item.handleUserName">{{ item.handleUserName }}</span>
|
</div>
|
</div>
|
<div class="record-item-bottom" v-if="item.handleOpinion || item.fileList?.length || item.signImg">
|
<div class="opinion">{{ item.handleOpinion }}</div>
|
<div class="file" v-if="item.fileList?.length">
|
<jnpf-upload-file v-model:value="item.fileList" type="workFlow" detailed simple />
|
</div>
|
<div class="sign" v-if="item.signImg">
|
签名:
|
<Image :width="80" :src="item.signImg" :preview="false" class="sign-img" @click="handlePreview(item.signImg)" />
|
</div>
|
<div class="sign" v-for="child in item.approvalField" :key="child">{{ child.fieldName }}:{{ child.value }}</div>
|
</div>
|
</div>
|
</div>
|
<jnpf-empty v-if="!state.list?.length && !state.loading" />
|
</BasicModal>
|
</template>
|
<style lang="scss">
|
.jnpf-flow-record-modal {
|
.ant-modal-body {
|
& > .scrollbar {
|
padding: 0 20px;
|
}
|
}
|
|
.record-container {
|
height: 600px;
|
padding-top: 20px;
|
|
.record-item {
|
display: flex;
|
flex-direction: column;
|
padding-bottom: 12px;
|
margin-bottom: 12px;
|
border-bottom: 1px solid var(--border-color-base1);
|
|
.record-item-top {
|
display: flex;
|
|
.avatar {
|
margin-right: 12px;
|
}
|
|
.user-info {
|
display: flex;
|
flex: 1;
|
flex-direction: column;
|
overflow: hidden;
|
|
.user-name {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
font-size: 14px;
|
white-space: nowrap;
|
}
|
|
.handle-time {
|
font-size: 14px;
|
color: var(--text-color-secondary);
|
}
|
}
|
|
.handle-type {
|
display: flex;
|
flex-shrink: 0;
|
align-items: center;
|
|
.handle-status {
|
height: 32px;
|
padding-inline: 18px;
|
font-size: 14px;
|
line-height: 32px;
|
border-radius: 50px;
|
}
|
|
.arrow-right {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 20px;
|
height: 20px;
|
margin-right: 10px;
|
color: var(--primary-color);
|
background-color: var(--app-content-background);
|
border-radius: 50%;
|
}
|
|
.handle-user-name {
|
max-width: 150px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
}
|
}
|
|
.record-item-bottom {
|
padding: 10px;
|
margin: 4px 0 0 52px;
|
background-color: var(--app-content-background);
|
border-radius: 4px;
|
|
.file {
|
margin-top: 10px;
|
}
|
|
.sign {
|
display: flex;
|
align-items: center;
|
margin-top: 10px;
|
word-break: break-all;
|
|
.sign-img {
|
width: 80px;
|
cursor: pointer;
|
}
|
}
|
}
|
}
|
}
|
}
|
</style>
|