Files
mosr-web/src/components/DetailComponent/ApprovalDetail.vue

602 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-loading="loading">
<el-row v-if="type==='execute'">
<el-col :span="24">
<baseTitle :title="'附件信息'" style="margin-bottom: 5px"></baseTitle>
</el-col>
<el-form :model="attachmentParam" inline style="margin-top: 15px;margin-left: 15px">
<el-form-item label="标签" prop="tag">
<el-select v-model="attachmentParam.tag" placeholder="请选择标签" clearable filterable style="width: 300px">
<el-option
v-for="item in tagsOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleSearchImplementationFileList" color="#DED0B2">搜索</el-button>
</el-form-item>
</el-form>
<fvTable style="width: 100%;min-height:160px;max-height: 160px" v-if="showAttachmentTable" height="160"
:tableConfig="executeTableConfig" class="execute-table"
:data="otherAttachmentList" :isSettingCol="false" :pagination="false">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
</el-row>
<baseTitle v-if="type!='phase'" :title="getTagName(type)+getTitleInfo(data.taskId)"></baseTitle>
<fvForm :schema="schema" @getInstance="(e)=>form = e" style="margin-left: 15px"></fvForm>
<el-form :model="formData" label-width="auto" style="margin-top: -15px">
<file-component :title="getTagName(type)+'附件'" :tag="getTagName(type)"
v-model:value="formData.fileList" :processViewer="processViewer"
:file-list-show="fileListShow"/>
</el-form>
<div v-if="data.taskId">
<baseTitle title="审核意见"></baseTitle>
<el-form-item prop="_value">
<el-input
v-model="_value"
:rows="3"
type="textarea"
placeholder="请输入审核意见"
/>
</el-form-item>
</div>
<div class="approval-record">
<div class="approval-title" style="margin-top: -15px">
<baseTitle title="审批记录"></baseTitle>
<div class="diagram">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd"
/>
</div>
</div>
<div class="process">
<operation-render v-if="processViewer && data.operationList && data.operationList.length > 0&&!changeDiagram"
:operation-list="data.operationList"
:state="data.state"/>
<process-diagram-viewer v-if="processViewer&&changeDiagram" :id-name="idName?idName:type"/>
</div>
</div>
<file-preview ref="filePreviewRef" :fullscreen="fullscreen" v-if="filePreviewShow"
:fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import {ElLoading, ElNotification} from 'element-plus';
import {downloadFile} from "@/api/project-demand";
import {searchImplementationFileList} from "@/api/project-manage/attachment";
import {getTags} from "@/api/project-manage";
const attachmentParam = reactive({
tag: ''
})
const tagsOption = ref([])
const uploadState = ref(false)
const showAttachmentTable = ref(true)
const otherAttachmentList = ref([])
const executeTableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
// width: 700,
currentRender: ({row, index}) => (
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center',
// width: 200,
},
{
prop: 'size',
label: '文件大小',
align: 'center',
// width: 450,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
return (
<div>
<el-button type="primary" link onClick={() => handleDownload(row)}>下载</el-button>
</div>
)
}
}
]
})
const changeDiagram = ref(false)
const props = defineProps({
formData: {
type: Object,
default: {}
},
data: {
type: Object,
default: {}
},
processViewer: {
type: Boolean,
default: false
},
companyOption: {
type: Array,
default: []
},
fileListShow: {
type: String,
default: 'READ'
},
preProcessShow: {
type: String,
default: 'READ'
},
// approval 立项, execute 实施, 归档 archivist
type: {
type: String,
default: 'approval'
},
loading: {
type: Boolean,
default: false
},
value: {
type: String,
default: ''
},
idName: {
type: String,
default: ''
}
})
const form = ref()
const editSingleTableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: 85,
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
width: 400,
currentRender: ({row, index}) => (
<div style="color: #2a99ff;cursor: pointer;" onClick={() => clickToPreview(row)}>{row.originalFileName}</div>)
},
{
prop: 'tag',
label: '标签',
align: 'center'
},
{
prop: 'size',
label: '文件大小',
align: 'center',
width: 150,
currentRender: ({row, index}) => (parseInt(row.size / 1024) + 'KB')
},
{
prop: 'oper',
label: '操作',
align: 'center',
showOverflowTooltip: false,
currentRender: ({row, index}) => {
let btn = []
btn.push({label: '下载', func: () => handleDownload(row), type: 'primary'})
// if (row.newFile) {
// btn.push({label: '删除', func: () => handleDelete(row), type: 'primary'})
// }
return (
<div style={{width: '100%'}}>
{
btn.map(item => (
<el-button
type={item.type}
onClick={() => item.func()}
link>
{item.label}
</el-button>
))
}
{
row.newFile ? <popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
perm={['mosr:requirement:del']}
onDelete={() => handleDelete(row)}/>
: ''
}
</div>
)
}
}
]
})
let preProcess = {
label: '前置流程',
prop: 'preProcess',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.preProcess ? props.formData.preProcess.map((item, index) => {
return <span><a target="_blank" style={{color: '#409EFF', cursor: 'pointer'}}
href={props.formData.preProcessBaseUrl + item.requestId}>{item.requestName} {index != (props.formData.preProcess.length - 1) ?
<span></span> : ''}</a></span>
}) : <span>{'--'}</span>
}
</div>
)
}
const schema = computed(() => {
let arr
if (props.type == 'approval') {
arr = [
{
label: '项目负责人',
prop: 'projectChargePerson',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.projectChargePerson ?
<span>{props.formData.projectChargePerson.name} </span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '项目成员',
prop: 'projectPersonList',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.projectPersonList ? props.formData.projectPersonList.map((item, index) => {
return <span>{item.name}
<span>{index != props.formData.projectPersonList?.length - 1 ? '' : ''}</span></span>
}) : <span>{'--'}</span>
}
</div>
)
},
{
label: '部门分管领导',
prop: 'optionalChargeLeadership',
colProps: {
span: 6
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => {
return <span>{item.name} </span>
}) : <span>{'--'}</span>
}
</div>
)
},
]
if (props.preProcessShow == 'EDIT') {
preProcess = {
label: '前置流程',
prop: 'preProcess',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
<select-pre-process formData={props.formData}/>
}
</div>
)
}
}
arr.push(preProcess)
arr.push({
label: '项目立项附件',
prop: 'singleFile',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => {
let singleFileArray = [props.formData.singleFile]
return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
tableConfig={editSingleTableConfig}
data={singleFileArray} isSettingCol={false} pagination={false}>
</fvTable>
: <span>--</span>
}
})
} else if (props.type == 'execute') {
arr = [{
label: '部门分管领导',
prop: 'optionalChargeLeadership',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
props.formData.optionalChargeLeadership?.length > 0 ? props.formData.optionalChargeLeadership.map(item => {
return <span>{item.name} </span>
}) : <span>{'--'}</span>
}
</div>
)
},]
if (props.preProcessShow == 'EDIT') {
preProcess = {
label: '前置流程',
prop: 'preProcess',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => (
<div>
{
<select-pre-process formData={props.formData}/>
}
</div>
)
}
}
arr.push(preProcess)
arr.push(
{
label: '项目验收附件',
prop: 'singleFile',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => {
let singleFileArray = [props.formData.singleFile]
return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
tableConfig={editSingleTableConfig}
data={singleFileArray} isSettingCol={false} pagination={false}>
</fvTable>
: <span>--</span>
}
})
} else if (props.type == 'archivist') {
arr = [
{
label: '项目归档附件',
prop: 'singleFile',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => {
let singleFileArray = [props.formData.singleFile]
return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
tableConfig={editSingleTableConfig}
data={singleFileArray} isSettingCol={false} pagination={false}>
</fvTable>
: <span>--</span>
}
},
]
} else if (props.type == 'phase') {
arr = [
{
label: '阶段变更附件',
prop: 'singleFile',
colProps: {
span: 24
},
labelWidth: 'left',
component: () => {
let singleFileArray = [props.formData.singleFile]
return props.formData.singleFile ? <fvTable style="width: 100%;max-height: 80px;" height="80"
tableConfig={editSingleTableConfig}
data={singleFileArray} isSettingCol={false} pagination={false}>
</fvTable>
: <span>--</span>
}
},
]
}
return arr
})
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: ''
})
const filePreviewShow = ref(false)
const route = useRoute()
const emit = defineEmits(['update:value'])
const _value = computed({
get() {
return props.value;
},
set(val) {
emit("update:value", val);
}
})
const clickToPreview = (row) => {
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(() => {
filePreviewShow.value = true
})
}
const getTagsOption = () => {
if (!route.query.projectId) return
getTags(route.query.projectId).then(res => {
if (res.code === 1000) {
tagsOption.value = res.data
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleSearchImplementationFileList = () => {
let params = {
targetId: route.query.projectId,
targetState: "40"
}
if (attachmentParam.tag) {
tagsOption.value.forEach(item => {
if (item.value === attachmentParam.tag) {
attachmentParam.tag = item.label
}
})
params.tag = attachmentParam.tag
}
searchImplementationFileList(params).then(res => {
showAttachmentTable.value = false
if (res.code === 1000) {
otherAttachmentList.value = res.data.fileList
uploadState.value = res.data.upload
nextTick(() => {
showAttachmentTable.value = true
})
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const getTitleInfo = (taskId) => {
if (taskId) {
return '审批'
} else {
return '信息'
}
}
const getTagName = (type) => {
switch (type) {
case 'approval':
return '项目立项'
case 'execute':
return '项目验收'
case 'archivist':
return '项目归档'
case 'phase':
return '阶段变更'
}
}
const handleDownload = (row) => {
const loading = ElLoading.service({fullscreen: true})
downloadFile(row.fileId).then(res => {
const blob = new Blob([res])
let a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = row.originalFileName
a.click()
loading.close()
})
}
watchEffect(() => {
Object.keys(props.formData).length && (form.value?.setValues(props.formData))
})
if (props.formData.mode == 'view' && props.type == 'execute') {
handleSearchImplementationFileList()
getTagsOption()
}
watch(() => props.loading, (newVal) => {
props.loading = newVal
}, {deep: true})
</script>
<style lang="scss">
.execute-table {
.el-table__header {
.el-table__cell:last-child {
.cell {
margin-left: -160px !important;
}
}
}
.el-table__body {
.el-table__cell:last-child {
.cell {
margin-left: -160px !important;
}
}
}
}
</style>
<style lang="scss" scoped>
:deep(.el-table__header) {
.is-leaf:first-child {
.cell {
margin-left: 10px !important;
white-space: nowrap;
padding: 0;
}
}
}
:deep(.el-table__body) {
.el-table__cell:first-child {
.cell {
margin-left: 5px !important;
}
}
}
</style>