Files
mosr-web/src/views/project-management/implementation/phase.vue

628 lines
17 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 class="apply-block" v-loading="loading">
<baseTitle title="项目基本信息"></baseTitle>
<fvForm :schema="schema" @getInstance="(e)=>baseForm = e" label-position="left" label-width="left"
style="margin-left: 15px"></fvForm>
<baseTitle title="阶段变更信息" style="margin-top: -10px"></baseTitle>
<el-form :model="formData" label-width="auto" :rules="rules">
<el-form-item label="抄送人员" label-width="110">
<Ttsup :modelValue="chooseUserInfo()" @clickCopyUser="chooseUser"/>
</el-form-item>
<el-form-item label="阶段变更" label-width="110" prop="changeState">
<el-select v-model="formData.changeState" placeholder="请选择阶段变更" filterable clearable style="width: 300px">
<el-option v-for="item in cacheStore.getDict('fee_stage')" :key="item.value" :label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="状态变更" label-width="110" prop="stateChange">
<el-select v-model="formData.stateChange" placeholder="请选择状态变更" filterable clearable style="width: 300px">
<el-option v-for="item in cacheStore.getDict('state_change')" :key="item.value" :label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-form>
<user-picker :multiple="true" ref="userPicker" title="请选择抄送人员" v-model:value="userList"
@ok="ccPersonPickerOkOrCancel" @cancelOrClear="ccPersonPickerOkOrCancel"/>
<AttachmentUpload ref="attachment" label="阶段变更附件" :showTable="showTable" v-model:otherFileList="otherFileList" templateName="科技创新项目变更模板" :templateDownloadBtnShow="true"
@getAttachment="getAttachment" v-model:singleList="singleList" :showSingleTable="showSingleTable"
@getOtherFile="getOtherFile" :showFileList="true" :formData="formData" tag="阶段变更"
:preview="name === 'Phase/edit'"/>
<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>
<el-empty :image-size="100" description="暂无审批记录"
v-if="processDiagramViewer&& !opentionData?.operationList&&!changeDiagram"/>
<!-- <process-diagram-viewer mode="view" v-if="processDiagramViewer&&changeDiagram"/>-->
<div class="process">
<operation-render
v-if="processDiagramViewer&& opentionData?.operationList && opentionData?.operationList.length > 0&&!changeDiagram"
:operation-list="opentionData?.operationList"
:state="opentionData.state"/>
<process-diagram-viewer mode="view" v-if="processDiagramViewer&&changeDiagram"/>
</div>
</div>
<div class="oper-page-btn">
<el-button color="#DED0B2" v-if="name==='Phase/change'" @click="handleSubmit">提交</el-button>
<el-button color="#DED0B2" v-else @click="handleResubmit">重新提交</el-button>
</div>
</div>
</template>
<script setup lang="jsx">
import OperationRender from '@/views/workflow/common/OperationRender.vue'
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import UserPicker from "@/views/workflow/process/common/UserPicker.vue";
import Ttsup from './components/ToolToShowUserPicker.vue'
import {getPhaseProcess, submitPhaseChange, getPhaseDetail, resubmitPhaseForm} from "@/api/project-manage";
import {ElNotification} from "element-plus";
import {useProcessStore} from '@/stores/processStore.js';
import {useTagsView} from '@/stores/tagsview.js'
import {computed, ref} from "vue";
import {getBaseInfoApi} from "@/components/steps/api";
import {useCacheStore} from '@/stores/cache.js'
import {toThousands} from '@/utils/changePrice.js'
const cacheStore = useCacheStore()
const changeDiagram = ref(false)
const tagsViewStore = useTagsView()
const router = useRouter()
const route = useRoute()
const attachment = ref()
const userPicker = ref()
const opentionData = ref({})
const showSingleTable = ref(false)
const singleList = ref([])
const name = ref(router.currentRoute.value.name)
const loading = ref(false)
const formData = ref({
changeState:'0',
stateChange:'',
isStop:'0'
})
const file = ref({})
const deploymentId = ref()
const showTable = ref(true)
const otherFileList = ref([])
const processInstanceData = ref()
const processDiagramViewer = ref(true)
const userList = ref([])
const processStore = useProcessStore()
const baseFormData = ref([])
const rules = reactive({
changeState: [{required: true, message: '请选择变更状态', trigger: ['blur', 'change']}],
})
const schema = computed(() => {
return [
{
label: '承办单位',
prop: 'affiliatedCompany',
colProps: {
span: 6
}
},
{
label: '项目名称',
prop: 'projectName',
colProps: {
span: 6
}
},
{
label: '开始时间',
prop: 'startTime',
colProps: {
span: 6
}
},
{
label: '结束时间',
prop: 'endTime',
colProps: {
span: 6
}
},
{
label: '项目类型',
prop: 'projectType',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.projectType ?
<span>{filterDict(cacheStore.getDict('project_type'), baseFormData.value?.projectType)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '研发主体',
prop: 'rdSubject',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.rdSubject ?
<span>{filterDict(cacheStore.getDict('rd_subject'), baseFormData.value?.rdSubject)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '出资类型',
prop: 'investmentType',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.investmentType ?
<span>{filterDict(cacheStore.getDict('invest_type'), baseFormData.value?.investmentType)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '所属业务板块',
prop: 'businessSegment',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.businessSegment ?
<span>{filterDict(cacheStore.getDict('business_segment'), baseFormData.value?.businessSegment)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '标准制定',
prop: 'technicalStandard',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.technicalStandard ?
<span>{filterDict(cacheStore.getDict('technical_standard'), baseFormData.value?.technicalStandard)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '项目影响',
prop: 'projectImpact',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.projectImpact ?
<span>{filterDict(cacheStore.getDict('project_impact'), baseFormData.value?.projectImpact)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '预估经费预算',
prop: 'economicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.economicEstimate ?
<span>{toThousands(baseFormData.value?.economicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
}, {
label: '实际经费预算',
prop: 'actualEconomicEstimate',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.actualEconomicEstimate ?
<span>{toThousands(baseFormData.value?.actualEconomicEstimate)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '产学研联合',
prop: 'industryUniversityResearch',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.industryUniversityResearch ?
<span>{filterDict(cacheStore.getDict('industry_university'), baseFormData.value?.industryUniversityResearch)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '开展政府申报',
prop: 'governmentDeclaration',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.governmentDeclaration ?
<span>{filterDict(cacheStore.getDict('government_declaration'), baseFormData.value?.governmentDeclaration)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '所属专项资金项目',
prop: 'specialFund',
colProps: {
span: 6
}
}, {
label: '预估专项资金(元)',
prop: 'forecastSpecialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.forecastSpecialFundAmount ?
<span>{toThousands(baseFormData.value?.forecastSpecialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '实际专项资金(元)',
prop: 'specialFundAmount',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.specialFundAmount ?
<span>{toThousands(baseFormData.value?.specialFundAmount)}</span>
: <span>{'--'}</span>
}
</div>
)
},
{
label: '是否在预算内',
prop: 'isWithinBudget',
colProps: {
span: 6
},
component: () => (
<div>
{
baseFormData.value?.isWithinBudget!=null ? baseFormData.value?.isWithinBudget?
<span>{'预算内'}</span>
: <span>{'预算外'}</span>:'--'
}
</div>
)
},
{
label: '部门分管领导',
prop: 'optionalChargeLeadership',
colProps: {
span: 6
}
},
{
label: '主项目',
prop: 'masterProjectName',
colProps: {
span: 6
}
}
]
})
const baseForm = ref()
localStorage.removeItem('originallySelectedList')
//匹配字典值,返回对应值的字典标签
const filterDict = (data, value) => {
if (data === undefined || value === undefined) return;
let label = ''
let result = []
if (value instanceof Array) {
value.forEach(item1 => {
data.find(item => {
if (item.value == item1) {
result.push(item.label)
}
})
})
label = result.map(item => item).join('')
} else {
if (data instanceof Array) {
data.find(item => {
if (item.value == value) {
label = item.label
}
})
}
}
return label
}
const getBaseInfo = async () => {
try {
const {code, data} = await getBaseInfoApi(route.query.projectId)
baseForm.value.setValues(data)
baseFormData.value = data
} catch {
}
}
getBaseInfo()
const compositeParam = (item) => {
let tag = ''
if (name.value === 'Phase/change') {
tag = '阶段变更'
}
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
newFile: false,
tag: tag
}
}
const getAttachment = (val) => {
// console.log('上传文件getAttachment', val)
showSingleTable.value = false
formData.value.singleFile = compositeParam(val)
singleList.value.push(compositeParam(val))
nextTick(() => {
showSingleTable.value = true
if (attachment.value.singleFile == null) {
attachment.value.validate()
ElNotification({
title: '提示',
message: '请上传附件',
type: 'error'
})
return;
} else {
attachment.value.clearValidate()
}
})
}
watch(() => singleList.value, (newVal) => {
showSingleTable.value = newVal.length !== 0;
}, {deep: true})
const getOtherFile = (val) => {
// console.log('上传文件getOtherFile', val)
showTable.value = false
let fileObj = compositeParam(val)
otherFileList.value.push(fileObj)
nextTick(() => {
showTable.value = true
})
}
const getFileParam = (item) => {
return {
fileId: item.fileId,
tag: item.tag
}
}
const chooseUser = () => {
userPicker.value.showUserPicker()
}
const chooseUserInfo = () => {
if (userList.value == null) return;
if (userList.value.length > 0) {
return userList.value.map(item => {
return item.name
}).join('')
} else {
return null
}
}
const ccPersonPickerOkOrCancel = (select) => {
console.log('select', select)
userList.value = select
}
const handleSubmit = async () => {
let files = []
otherFileList.value?.forEach(item => {
files.push(getFileParam(item))
})
let userIds = []
if (userList.value && userList.value.length > 0) {
userIds = userList.value?.map(item => {
return item.id
})
}
if (formData.value.singleFile !== undefined) {
formData.value.singleFile = getFileParam(formData.value.singleFile)
}
let params = {
deploymentId: deploymentId.value,
requirementId: route.query.id,
fileList: files,
// singleFile: formData.value.singleFile,
projectId: route.query.projectId,
userIds: userIds,
changeState:formData.value.changeState,
stateChange:formData.value.stateChange
}
if (!attachment.value.isHaveOneFile) {
attachment.value.validate()
ElNotification({
title: '提示',
message: '请上传附件',
type: 'error'
})
return;
} else {
attachment.value.clearValidate()
}
console.log('params', params)
let res = await submitPhaseChange(params)
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
await router.push({
name: 'Implementation'
})
}
}
const handleResubmit = () => {
let otherFiles = []
if (name.value === 'Phase/edit') {
attachment.value.allFileList?.forEach(item => {
otherFiles.push(getFileParam(item))
})
}
let userIds = []
if (userList.value && userList.value.length > 0) {
userIds = userList.value?.map(item => {
return item.id
})
}
if (!attachment.value.isHaveOneFile) {
attachment.value.validate()
ElNotification({
title: '提示',
message: '请上传附件',
type: 'error'
})
return;
} else {
attachment.value.clearValidate()
}
let params = {
deploymentId: deploymentId.value,
requirementId: route.query.id,
fileList: otherFiles,
// singleFile: attachment.value.singleFile,
projectId: route.query.projectId,
userIds: userIds,
changeState:formData.value.changeState,
stateChange:formData.value.stateChange
}
// console.log('重新提交params', params)
resubmitPhaseForm(params).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
router.push({
name: 'Implementation'
})
}
})
}
const init = async () => {
const {msg, code, data} = await getPhaseProcess()
processDiagramViewer.value = false
if (code === 1000) {
deploymentId.value = data.deploymentId
processInstanceData.value = data
processStore.setDesign(data)
processStore.runningList.value = data.runningList;
processStore.endList.value = data.endList;
processStore.noTakeList.value = data.noTakeList;
processStore.refuseList.value = data.refuseList;
processStore.passList.value = data.passList;
nextTick(() => {
processDiagramViewer.value = true
})
} else {
ElNotification({
title: '提示',
message: msg,
type: 'error'
})
}
}
const getDetailInfo = async () => {
getPhaseDetail(route.query.projectId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
userList.value = res.data.formData.userInfoList ? res.data.formData.userInfoList : []
formData.value = res.data.formData
opentionData.value = res.data
loading.value = false
}
})
}
onMounted(async () => {
await init()
if (name.value === 'Phase/edit') {
loading.value = true
await getDetailInfo()
}
})
</script>
<style scoped>
.apply-block {
margin: 15px 0;
padding: 0 30px;
}
</style>