Files
mosr-web/src/views/project-demand/requirement/add.vue

565 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" class="add-block">
<baseTitle title="需求征集信息录入"></baseTitle>
<el-form :model="formData" ref="demandForm" :rules="rules">
<el-row gutter="30">
<el-col :span="8">
<el-form-item label="征集名称" prop="requirementName" label-width="96">
<el-input v-model="formData.requirementName" placeholder="请输入名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="征集类型" prop="collectType" label-width="105">
<el-select v-model="formData.collectType" placeholder="请选择征集类型" clearable filterable>
<el-option
v-for="item in cacheStore.getDict('collect_type')"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="需求上报截止时间" prop="deadline">
<el-config-provider>
<el-date-picker
v-model="formData.deadline"
type="date"
placeholder="需求上报截止时间"
value-format="YYYY-MM-DD"
:disabled-date="disabledDate"
/>
</el-config-provider>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="是否专项资金" prop="isSpecialFund">
<el-select v-model="formData.isSpecialFund" placeholder="是否专项资金" clearable filterable>
<el-option :value="true" label="是"></el-option>
<el-option :value="false" label="否"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="专项资金名称" prop="specialFundId" v-if="formData.isSpecialFund">
<el-select v-model="formData.specialFundId" placeholder="请选择专项资金名称" clearable filterable>
<el-option
v-for="item in specialFundOption"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" style="margin-bottom: -25px">
<el-form-item label="征集公司" :required="true" prop="" class="company-select" label-width="96">
<div style="width: 100%">
<el-button color="#DED0B2" @click="showCompany">{{ selectedCompanyList.length === 0 ? '请选择征集公司' : '更改' }}
</el-button>
</div>
<div :class="showExpendClass(showMoreCompany)">{{ getName(selectedCompanyList) }}</div>
<div style="color: #2a99ff;text-align: center;width: 100%;font-size: 15px;cursor: pointer"
@click="handleExpend">
{{ showExpendText }}
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
<baseTitle title="征集说明"></baseTitle>
<el-input
v-model="formData.collectExplain"
style="width:100%"
:rows="5"
type="textarea"
placeholder="请输入征集说明"
/>
<div style="display: flex;align-items: center">
<baseTitle title="申请文件" style="margin-right: 10px"></baseTitle>
<file-upload v-if="checkFormPrem('fileList')" @getFile="getFile"/>
</div>
<fvTable style="width: 100%;max-height: 162px;" height="162" v-if="showTable"
:tableConfig="tableConfig" :data="formData.fileList"
:isSettingCol="false" :pagination="false" perm="EDIT">
<template #empty>
<el-empty :image-size="55" description="暂无数据" style="padding: 0"/>
</template>
</fvTable>
<div class="approval-record">
<div style="display: flex;align-items: center;justify-content: flex-start;">
<div class="base-title">流程图</div>
<el-switch
v-model="changeDiagram"
style="--el-switch-on-color:#BEA266 ; --el-switch-off-color:#cecdcd;margin-left: 10px"
/>
</div>
<process-diagram-viewer mode="view" v-if="processDiagramViewer&&changeDiagram"/>
</div>
<div style="width: 100%;height: 30px"></div>
<div class="oper-page-btn">
<el-button color="#DED0B2" v-if="routerName==='Requirement/add'" @click="handleSubmit(demandForm)">提交</el-button>
<el-button color="#DED0B2" v-else @click="handleResubmit">重新提交</el-button>
<el-button @click="handleBack">返回</el-button>
</div>
<company-picker :multiple="true" ref="companyRef" title="请选择征集公司" @ok="selected"
v-model:value="selectedCompanyList"/>
<file-preview ref="filePreviewRef" v-if="filePreviewShow" :fileName="filePreviewParam.fileName" :fileUrl="filePreviewParam.fileUrl"
:fileType="filePreviewParam.fileType"/>
</div>
</template>
<script setup lang="jsx">
import {useAuthStore} from '@/stores/userstore.js'
import {useProcessStore} from '@/stores/processStore.js';
import {
getWorkflowInfo,
addRequirement,
getFormInfo,
resubmit,
deleteFile,
downloadFile
} from "@/api/project-demand/index.js";
import FileUpload from "@/components/FileUpload.vue";
import ProcessDiagramViewer from '@/views/workflow/common/ProcessDiagramViewer.vue';
import {ElNotification} from "element-plus";
import {useRoute, useRouter} from 'vue-router'
import {getSubCompOpt} from '@/api/user/user.js'
import {useTagsView} from '@/stores/tagsview.js'
import {getFundOption} from "@/api/special-fund";
import CompanyPicker from "@/components/DetailComponent/CompanyPicker.vue";
import {useCacheStore} from '@/stores/cache.js'
const filePreviewParam = ref({
fileUrl: '',
fileName: '',
fileType: 'pdf'
})
const filePreviewShow = ref(false)
const cacheStore = useCacheStore()
const companyRef = ref()
const showExpendText = ref('')
const showMoreCompany = ref(false)
const selectedCompanyList = ref([])
// const companyList = ref([])
const changeDiagram = ref(false)
const tagsViewStore = useTagsView()
const authStore = useAuthStore()
const router = useRouter()
const route = useRoute()
const demandForm = ref()
const dateValue = ref()
const formData = ref({
requirementName: '',
companyIds: [],
collectType: '科技创新与信息化系统建设',
deadline: '',
collectExplain: '',
fileList: [],
isSpecialFund: false
})
const routerName = ref(router.currentRoute.value.name)
const processDiagramViewer = ref(false)
const companyOption = ref([])
const specialFundOption = ref([])
const form = ref(null)
const fileList = ref([])
const loading = ref(false)
const showTable = ref(true)
const processStore = useProcessStore()
const processInstanceData = ref()
const formPermMap = ref(new Map());
const companyNameArray = ref([])
const rules = reactive({
requirementName: [{required: true, message: '请输入征集名称', trigger: ['blur','change']}],
// companyIds: [{required: true, message: '请选择征集公司', trigger: ['blur','change']}],
collectType: [{required: true, message: '请选择征集类型', trigger: ['blur','change']}],
deadline: [{required: true, message: '请选择截止时间', trigger: ['blur','change']}],
specialFundId: [{required: true, message: '请选择专项资金名称', trigger: ['blur','change']}],
})
const tableConfig = reactive({
columns: [
{
prop: 'index',
type: 'index',
label: '序号',
align: 'center',
width: '80',
},
{
prop: 'originalFileName',
label: '文件名',
align: 'center',
showOverflowTooltip: false,
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',
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>
<popover-delete name={row.originalFileName} type={'文件'} btnType={'danger'}
perm={['mosr:requirement:del']}
onDelete={() => handleDelete(row)}/>
</div>
)
}
}
]
})
const clickToPreview = (row) => {
filePreviewShow.value = false
filePreviewParam.value = {
fileUrl: row.url,
fileName: row.originalFileName,
fileType: row.fileType
}
nextTick(()=>{
filePreviewShow.value = true
})
// filePreviewRef.value.show()
}
const disabledDate = (time) => {
return time.getTime() < Date.now() - 8.64e7//不能选择之后的数据
}
const handleExpend = () => {
showMoreCompany.value = !showMoreCompany.value;
showExpendClass(showMoreCompany.value)
}
const showExpendClass = (showMoreCompany) => {
if (!showMoreCompany) {
if (selectedCompanyList.value.length === 0) {
showExpendText.value = ''
return ''
} else if (selectedCompanyList.value.length > 14) {
showExpendText.value = '展开'
return 'company-style'
}
} else {
showExpendText.value = '收缩'
return ''
}
}
const getName = (list) => {
return list.map(item => item.label).join('')
}
const showCompany = () => {
companyRef.value.show()
}
const selected = (select) => {
formData.value.companyIds=[]
for (let val of select) {
formData.value.companyIds.push(val.value)
}
selectedCompanyList.value = select
}
const checkFormPrem = (formKey) => {
if (formPermMap.value.hasOwnProperty(formKey)) {
let formItem = formPermMap.value[formKey];
return formItem.perm === 'EDIT'
} else {
return true;
}
}
const handleDownload = (row) => {
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()
})
}
const getSpecialFundName = (val) => {
let label
specialFundOption.value.forEach(item => {
if (item.value == val) {
label = item.label
}
})
return label
}
const compositeParam = (item) => {
let tag = ''
if (!formData.value.collectType && routerName.value === 'Requirement/add') {
tag = '需求征集'
} else if (!formData.value.collectType && routerName.value === 'Requirement/edit') {
tag = '需求征集'
}
if (formData.value.collectType) {
tag = formData.value.collectType
}
return {
fileId: item.id,
size: item.size,
originalFileName: item.originalFilename,
fileType: item.fileType,
url: item.url,
processNodeTag: null,
tag: tag,
newFile: true,
userId: authStore.userinfo.userId
}
}
const getFile = (val) => {
showTable.value = false
let fileObj = compositeParam(val)
formData.value.fileList.push(fileObj)
nextTick(() => {
showTable.value = true
})
}
const init = async () => {
const res = await getSubCompOpt()
companyOption.value = res.data
const resFund = await getFundOption()
specialFundOption.value = resFund.data
getWorkflowInfo().then(res => {
if (res.code === 1000) {
let data = res.data
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;
formPermMap.value = data.formPermMap
// const entriesArray = Object.entries(data.formPermMap);// 使用Map构造函数将键值对数组转换为Map对象
// formPermMap.value = new Map(entriesArray);
nextTick(() => {
processDiagramViewer.value = true
})
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const submitParam = (item) => {
let files = []
item.fileList.forEach(item => {
let obj = {
fileId: item.fileId,
tag: item.tag
}
files.push(obj)
})
return {
collectExplain: item.collectExplain,
collectType: item.collectType,
companyIds: item.companyIds,
deadline: item.deadline,
requirementId: item.requirementId ? item.requirementId : 0,
requirementName: item.requirementName,
fileList: files,
deploymentId: processInstanceData.value.deploymentId,
isSpecialFund: item.isSpecialFund,
specialFundId: item.specialFundId,
specialFund: getSpecialFundName(item.specialFundId)
}
}
const handleSubmit = async (instance) => {
if (!instance) return
instance.validate(async (valid) => {
if (!valid) {
ElNotification({
title: '提示',
message: '请完善数据,再提交!',
type: 'error'
})
return;
}
if (formData.value.companyIds.length === 0) {
ElNotification({
title: '提示',
message: '请选择征集公司',
type: 'error'
})
return;
}
const {msg, code} = await addRequirement(submitParam(formData.value))
ElNotification({
title: '提示',
message: msg,
type: code === 1000 ? 'success' : 'error'
})
if (code === 1000) {
tagsViewStore.delVisitedViews(router.currentRoute.value.path)
await router.push({
name: 'Requirement'
})
}
})
}
const handleResubmit = () => {
resubmit(submitParam(formData.value)).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: 'Requirement'
})
}
})
}
const matterTree = (array,data, id) => {
if (id) {
data.forEach(item => {
if (item.value == id) {
let obj={
label:item.label,
value:item.value
}
array.push(obj);
}
if (item.children && item.children.length > 0) {
matterTree(array,item.children,id)
}
})
return array;
}
}
const getCompanyOptionItem = (val) => {
if (val !== undefined) {
val.forEach(item => {
matterTree(companyNameArray.value, companyOption.value, item)
})
}
return companyNameArray.value;
}
const getDetailInfo = async () => {
getFormInfo(route.query.id).then(res => {
if (res.code === 1000) {
if (res.data.companyIds[0] == -1) {
selectedCompanyList.value = [
{
value:-1,
label:'所有公司'
}
]
} else {
selectedCompanyList.value = getCompanyOptionItem(res.data.companyIds)
}
formData.value = res.data
if (res.data.fileList.length !== 0) {
showTable.value = false
nextTick(() => {
showTable.value = true
})
}
} else {
ElNotification({
title: '提示',
message: res.msg,
type: 'error'
})
}
})
}
const handleBack = () => {
history.back()
}
const handleDelete = (row) => {
deleteFile(row.fileId).then(res => {
ElNotification({
title: '提示',
message: res.msg,
type: res.code === 1000 ? 'success' : 'error'
})
if (res.code === 1000) {
formData.value.fileList.splice(formData.value.fileList.findIndex((item) => item.fileId === row.fileId), 1);
// showTable.value = formData.value.fileList.length !== 0;
}
});
}
onMounted(async () => {
loading.value = true
await init()
if (route.query.id) {
await getDetailInfo()
}
loading.value = false
})
</script>
<style lang="scss" scoped>
:deep(.el-empty__description) {
margin-top: 0;
}
.company-select {
:deep(.el-form-item__content .el-select__wrapper ) {
width: 750px;
}
.company-style {
//width: 98%;
min-height: 30px;
max-height: 60px;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 2;
display: -webkit-box;
-webkit-box-orient: vertical;
}
.company {
color: #fff;
height: auto;
}
}
:deep(.el-table--fit ) {
height: 300px !important;
}
.add-block {
//display: flex;
//justify-content: space-between;
overflow-x: hidden;
overflow-y: auto;
a {
cursor: pointer;
font-size: 14px;
color: #2a99ff;
}
.approval-record {
position: relative;
}
}
</style>