@@ -0,0 +1,14 @@ | |||
<script setup name="commonLogin"> | |||
import { onMounted } from 'vue' | |||
import { singleLogin } from '@/http/apis/auth' | |||
import { useRoute, useRouter } from 'vue-router' | |||
const route = useRoute(), | |||
router = useRouter() | |||
onMounted(async () => { | |||
const postData = new URLSearchParams() | |||
postData.append('credential', route.query.PROVINCE_FOREIGN_USER_TOKEN) | |||
postData.append('platform', 'PROVINCIAL_BUREAU') | |||
await singleLogin(postData) | |||
router.replace('/') | |||
}) | |||
</script> |
@@ -0,0 +1,266 @@ | |||
<script setup name="applicationRegist"> | |||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue' | |||
// import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
// import useExportExc from '@/utils/useExportExc' | |||
import { list, pushProjectApp } from '@/http/apis/declareMange/applicationRegist' | |||
import store from '@/store' | |||
const router = useRouter(), | |||
{ digitalModifySystem, projectTypeOptions } = store.dictStore.globalDicts, | |||
{ proxy } = getCurrentInstance() | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
type: 'expand' | |||
}, | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '批复时间', | |||
key: 'approvalDate', | |||
prop: 'approvalDate', | |||
width: '110' | |||
}, | |||
{ | |||
label: '批复金额(万元)', | |||
key: 'approvedAmount', | |||
prop: 'approvedAmount', | |||
width: '140' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '120', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// // 导出excel文件 | |||
// { exportLoading, exportData } = useExportExc(), | |||
// handleExcel = () => { | |||
// exportData(() => declareExport(6, { | |||
// ...searchForm, | |||
// createOnMin: searchForm.times?.[0], | |||
// createOnMax: searchForm.times?.[1], | |||
// projectYear: searchForm.projectYear * 1 || undefined, | |||
// times: undefined | |||
// })) | |||
// }, | |||
// 应用注册 | |||
visible = ref(false), | |||
appData = ref(), | |||
showDialog = (data) => { | |||
visible.value = true | |||
appData.value = data | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
window.onmessage = async (event) => { | |||
if (event.data && event.data.msg === '编码已生成,请复制编码查询应用') { | |||
console.log(event.data, '编码') | |||
appData.value['appCode'] = event.data.data | |||
await pushProjectApp(appData.value) | |||
proxy.$message.success('注册成功') | |||
visible.value = false | |||
getTableData() | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<!-- <div>--> | |||
<!-- <el-button--> | |||
<!-- type="primary"--> | |||
<!-- size="small"--> | |||
<!-- plain--> | |||
<!-- :loading="exportLoading"--> | |||
<!-- @click="handleExcel"--> | |||
<!-- >--> | |||
<!-- 导出--> | |||
<!-- </el-button>--> | |||
<!-- </div>--> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #expand="{scope}"> | |||
<div | |||
v-for="(item,index) in scope.row.projectApplications" | |||
:key="index" | |||
class="flex py-8" | |||
style="padding-left: 140px;border-bottom: 1px solid rgb(235, 238, 245)" | |||
> | |||
<p class="flex-1 pr-4"> | |||
应用名称:{{ item.applicationName ||item.relatedExistsApplication }} | |||
</p> | |||
<p class="flex-1 pr-4"> | |||
数改系统:{{ item.digitalModification&&item.digitalModification.split(',').map(i=>digitalModifySystem[i]).join(',')||'-' }} | |||
</p> | |||
<p class="flex-1 pr-4"> | |||
是否初次建设:{{ item.isFirst?'是':'否' }} | |||
</p> | |||
<p class="flex-1 pr-4"> | |||
是否注册:{{ item.isFirst&&item.appCode?'是':item.isFirst&&!item.appCode?'否':'--' }} | |||
</p> | |||
<p class="flex-1"> | |||
<a v-if="!item.appCode" @click="showDialog({projectCode:scope.row.projectCode,appId:item.id})">应用注册</a> | |||
</p> | |||
</div> | |||
</template> | |||
<template #action="{ scope }"> | |||
<a @click="router.push({name:'applicationRegistDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<el-dialog | |||
:model-value="visible" | |||
title="应用注册" | |||
width="80%" | |||
@close="visible=false" | |||
> | |||
<iframe src="https://jdirs.zj.gov.cn/api/system/register-view?X-BG-HMAC-ACCESS-KEY=42bcb49bea174986a3bfdfba7d005566&path=Ovl4aua87eB" width="100%" height="700px"></iframe> | |||
</el-dialog> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,323 @@ | |||
<script setup name = 'constructionPlanDeclare'> | |||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import { genFileId } from 'element-plus' | |||
import store from '@/store' | |||
import { | |||
getConstructionDeclarePlan, | |||
declareConstructionScheme, | |||
declareExport | |||
} from '@/http/apis/declareMange' | |||
import { fileFormatVerification, handleFileSuccess, fileTypes, fileDesc, handleFilePreview } from '@/utils/uploadAction.js' | |||
import useExportExc from '@/utils/useExportExc' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
// 搜索栏表单数据 | |||
const { proxy } = getCurrentInstance(), | |||
formInline = reactive({ | |||
projectName: '', | |||
projectType: '', | |||
projectYear: null, | |||
startTime: '', | |||
endTime: '', | |||
createTimeArr: [] | |||
}), | |||
router = useRouter(), | |||
tableListRef = ref(), | |||
selectData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await getConstructionDeclarePlan({ | |||
...pageParams, | |||
...formInline, | |||
startTime: formInline.createTimeArr?.length | |||
? formInline.createTimeArr[0] | |||
: undefined, | |||
endTime: formInline.createTimeArr?.length | |||
? formInline.createTimeArr[0] | |||
: undefined, | |||
createTimeArr: undefined | |||
}) | |||
selectData.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: 80 | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '200' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '100' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '250' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '140', | |||
fixed: 'right' | |||
} | |||
]), | |||
// projectData = reactive([]), | |||
rules = reactive({ | |||
constructionPlanFile: [ | |||
{ required: true, message: '请上传建设方案', trigger: 'blur' } | |||
] }), | |||
// 数据总数 | |||
total = ref(2), | |||
checkDetail = (detailData) => { | |||
// console.log('detailData', detailData) | |||
router.push({ name: 'projectDeclareDetail', query: { id: detailData.id }}) | |||
}, | |||
// 提交查询 | |||
onSubmit = () => { | |||
getTableData() | |||
}, | |||
formReset = () => { | |||
formInline.projectName = null | |||
formInline.projectType = null | |||
formInline.projectYear = null | |||
formInline.startTime = null | |||
formInline.endTime = null | |||
formInline.createTimeArr = null | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
tableDom = ref(), | |||
handleTable = (value) => { | |||
tableDom.value = value | |||
}, | |||
// handleExcel = () => { | |||
// exportExcel(tableDom.value) | |||
// }, | |||
// 申报方案 | |||
// declarePlan = (val) => { | |||
// projectId.value = val.id | |||
// dialogVisible.value = true | |||
// if (upload.value)upload.value.clearFiles() | |||
// }, | |||
dialogVisible = ref(false), | |||
handleClose = (done) => { | |||
done() | |||
}, | |||
// 文件上传 | |||
uploadUrl = store.dictStore.uploadUrl, | |||
ruleForm = reactive({ | |||
constructionPlanFile: [] | |||
}), | |||
upload = ref(), | |||
planUploadRef = ref(), | |||
constructionPlanRef = ref(), | |||
handleExceed = (files) => { | |||
upload.value.clearFiles() | |||
const file = files[0] | |||
file.uid = genFileId() | |||
upload.value.handleStart(file) | |||
}, | |||
projectId = ref(), | |||
submitUpload = async (formEl) => { | |||
if (!formEl) return | |||
formEl.validate((valid) => { | |||
if (valid) { | |||
declareConstructionSchemeFunction() | |||
} else { | |||
console.log('error submit!') | |||
} | |||
}) | |||
}, | |||
declareConstructionSchemeFunction = async () => { | |||
await declareConstructionScheme({ | |||
projectInfo: { | |||
id: projectId.value, | |||
constructionPlanFile: JSON.stringify(ruleForm.constructionPlanFile && ruleForm.constructionPlanFile.map(i => { | |||
return { | |||
fileId: i.response.data.id, | |||
fileName: i.response.data.originalFileName | |||
} | |||
})[0]) | |||
} | |||
}) | |||
dialogVisible.value = false | |||
ruleForm.constructionPlanFile = [] | |||
proxy.$message.success('提交成功') | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(3, { | |||
...formInline, | |||
year: formInline.year * 1, | |||
startTime: formInline.createTimeArr?.length | |||
? formInline.createTimeArr[0] | |||
: undefined, | |||
endTime: formInline.createTimeArr?.length | |||
? formInline.createTimeArr[0] | |||
: undefined, | |||
createTimeArr: undefined | |||
})) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="formInline" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input v-model="formInline.projectName" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select v-model="formInline.projectType" placeholder="全部" class="w-full"> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="formInline.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="10"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="formInline.createTimeArr" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="14"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="onSubmit">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>待申报的项目</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
plain | |||
size="small" | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
>导出</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="selectData" | |||
:total="total" | |||
@handle-table="handleTable" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="$router.push({name:'declarePlan',query:{id:scope.row.id}})">申报方案</a> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<el-dialog | |||
v-model="dialogVisible" | |||
title="申报建设方案" | |||
width="35%" | |||
:before-close="handleClose" | |||
> | |||
<el-form | |||
ref="constructionPlanRef" | |||
:model="ruleForm" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="auto" | |||
status-icon | |||
> | |||
<el-form-item label="建设方案:" prop="constructionPlanFile"> | |||
<el-upload | |||
ref="planUploadRef" | |||
v-model:file-list="ruleForm.constructionPlanFile" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-exceed="handleExceed" | |||
:on-success="res => handleFileSuccess(res, ruleForm.constructionPlanFile, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button type="primary" @click="submitUpload(constructionPlanRef)"> | |||
提交 | |||
</el-button> | |||
<el-button @click="dialogVisible = false">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,466 @@ | |||
<script setup name="fillContractInfo"> | |||
import { getCurrentInstance, ref, onMounted } from 'vue' | |||
import { changFilesParam, fileFormatVerification, handleFileSuccess, reviewFileParam, fileTypes, fileDesc, handleFilePreview } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import { contractDetail, submitContract, supplement } from '@/http/apis/declareMange/contractRecord' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
route = useRoute() | |||
const formRef = ref(), | |||
moneyValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
rules = { | |||
name: [{ required: true, message: '请输入合同名称' }], | |||
totalAmount: [{ required: true, message: '请输入合同总金额' }, { validator: moneyValidator, trigger: 'blur' }], | |||
supplierBank: [{ required: true, message: '请输入供应商收款开户行' }], | |||
supplierAccount: [{ required: true, message: '请输入供应商收款账号' }], | |||
warrantyPeriod: [{ required: true, message: '请输入质保期' }], | |||
retentionMoney: [{ required: true, message: '请输入质保金' }, { validator: moneyValidator, trigger: 'blur' }], | |||
contractTime: [{ required: true, message: '请选择合同签订完成时间' }], | |||
deliveryTime: [{ required: true, message: '请选择交货日期' }], | |||
attachment: [{ required: true, message: '请上传合同附件' }] | |||
}, | |||
formData = ref({ | |||
attachment: [], | |||
payments: [] | |||
}), | |||
// 付款计划 | |||
column = ref([ | |||
{ | |||
label: '付款笔数', | |||
key: 'number', | |||
slot: 'number' | |||
}, | |||
{ | |||
label: '付款计划', | |||
key: 'planAmount', | |||
slot: 'planAmount' | |||
}, | |||
{ | |||
label: '付款比例(%)', | |||
key: 'ratio', | |||
slot: 'ratio' | |||
}, | |||
{ | |||
label: '付款金额(万元)', | |||
key: 'paymentAmount', | |||
slot: 'paymentAmount' | |||
}, | |||
{ | |||
label: '预计付款时间', | |||
key: 'paymentTime', | |||
slot: 'paymentTime' | |||
}, | |||
{ | |||
label: '操作', | |||
key: 'action', | |||
slot: 'action', | |||
width: 80 | |||
} | |||
]), | |||
// 添加付款计划 | |||
add = () => { | |||
formData.value.payments.push({}) | |||
}, | |||
// 删除付款计划 | |||
del = (index) => { | |||
formData.value.payments.splice(index, 1) | |||
}, | |||
// 计算付款比例 | |||
blurMoney = (row) => { | |||
row.ratio = Math.floor((row.paymentAmount / formData.value.totalAmount * 1) * 100 * 100) / 100 | |||
}, | |||
// 提交 | |||
submitLoading = ref(false), | |||
submit = async (formEl) => { | |||
console.log(formData.value) | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid, err) => { | |||
if (valid) { | |||
if (!route.query.isReplenishment) { | |||
if (!formData.value.payments?.length) { | |||
proxy.$message.warning('请至少添加一个付款计划') | |||
return | |||
} | |||
const totalMoney = formData.value.payments.reduce((acc, cur) => { | |||
return acc + cur.paymentAmount | |||
}, 0) | |||
if (totalMoney !== formData.value.totalAmount) { | |||
proxy.$message.warning('付款金额总和必须等于合同总金额') | |||
return | |||
} | |||
submitLoading.value = true | |||
const postData = { | |||
...formData.value, | |||
projectId: route.query.id, | |||
attachment: formData.value.attachment && JSON.stringify(changFilesParam(formData.value.attachment)) | |||
} | |||
try { | |||
await submitContract(postData) | |||
submitLoading.value = false | |||
proxy.$message.success('提交成功') | |||
router.go(-1) | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
} else { | |||
submitActualPaymentAmount() | |||
} | |||
} | |||
}) | |||
}, | |||
// 提交补充金额 | |||
submitActualPaymentAmount = async () => { | |||
submitLoading.value = true | |||
try { | |||
const postData = [] | |||
formData.value.payments.forEach(i => { | |||
if ((i.actualPaymentAmount || i.actualPaymentAmount === 0) && !i.isReplenishment) { | |||
postData.push({ | |||
actualPaymentAmount: i.actualPaymentAmount, | |||
id: i.id, | |||
projectCode: i.projectCode | |||
}) | |||
} | |||
}) | |||
await supplement(postData) | |||
proxy.$message.success('提交成功') | |||
router.go(-1) | |||
submitLoading.value = false | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
}, | |||
// 获取详情 | |||
getDetail = async () => { | |||
const res = await contractDetail(route.query.id) | |||
if (res.data) { | |||
formData.value = { | |||
...res.data, | |||
attachment: res.data.attachment ? reviewFileParam(JSON.parse(res.data.attachment)) : [], | |||
payments: res.data.payments?.map(i => { | |||
return { | |||
...i, | |||
isReplenishment: !!i.actualPaymentAmount | |||
} | |||
}) || [] | |||
} | |||
} | |||
}, | |||
validActualPaymentAmount = (rule, value, callback, index) => { | |||
if (value < 0) { | |||
callback('实际支付金额必须大于等于0') | |||
} else if (index === 0) { | |||
if (value > formData.value.payments[index].paymentAmount) { | |||
callback('实际支付金额不能超过合同计划付款金额') | |||
} | |||
} else { | |||
let maxData = formData.value.payments[index].paymentAmount | |||
for (let i = 0; i < index; i++) { | |||
maxData += formData.value.payments[i].paymentAmount - formData.value.payments[i]?.actualPaymentAmount || 0 | |||
} | |||
if (value > maxData) { | |||
callback(`实际支付金额不能超过${maxData}万元`) | |||
} | |||
} | |||
callback() | |||
} | |||
onMounted(() => { | |||
getDetail() | |||
if (route.query.isReplenishment) { | |||
column.value = [ | |||
{ | |||
label: '付款笔数', | |||
key: 'number', | |||
slot: 'number' | |||
}, | |||
{ | |||
label: '付款计划', | |||
key: 'planAmount', | |||
slot: 'planAmount' | |||
}, | |||
{ | |||
label: '付款比例(%)', | |||
key: 'ratio', | |||
slot: 'ratio' | |||
}, | |||
{ | |||
label: '付款金额(万元)', | |||
key: 'paymentAmount', | |||
slot: 'paymentAmount' | |||
}, | |||
{ | |||
label: '预计付款时间', | |||
key: 'paymentTime', | |||
slot: 'paymentTime' | |||
}, | |||
{ | |||
label: '实际支付金额(万元)', | |||
key: 'actualPaymentAmount', | |||
slot: 'actualPaymentAmount', | |||
width: 180 | |||
} | |||
] | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<div class="fillPurchasingResult footerPage"> | |||
<el-card class="w-full"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item label="合同名称" prop="name"> | |||
<el-input | |||
v-model="formData.name" | |||
maxlength="50" | |||
placeholder="请输入" | |||
:disabled="!!$route.query.isReplenishment" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="合同总金额" prop="totalAmount"> | |||
<el-input | |||
v-model.number="formData.totalAmount" | |||
placeholder="请填写" | |||
:disabled="!!$route.query.isReplenishment" | |||
> | |||
<template #suffix>万元</template> | |||
</el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商收款开户行" prop="supplierBank"> | |||
<el-input | |||
v-model="formData.supplierBank" | |||
maxlength="50" | |||
placeholder="请输入" | |||
:disabled="!!$route.query.isReplenishment" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商收款账号" prop="supplierAccount"> | |||
<el-input | |||
v-model="formData.supplierAccount" | |||
maxlength="50" | |||
placeholder="请输入" | |||
:disabled="!!$route.query.isReplenishment" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="质保期" prop="warrantyPeriod"> | |||
<el-input | |||
v-model="formData.warrantyPeriod" | |||
maxlength="50" | |||
placeholder="请输入" | |||
:disabled="!!$route.query.isReplenishment" | |||
@input="formData.warrantyPeriod=formData.warrantyPeriod?.replace(/[^\d]/g,'')" | |||
> | |||
<template #suffix> | |||
年 | |||
</template> | |||
</el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="质保金" prop="retentionMoney"> | |||
<el-input | |||
v-model.number="formData.retentionMoney" | |||
placeholder="请填写" | |||
:disabled="!!$route.query.isReplenishment" | |||
> | |||
<template #suffix>万元</template> | |||
</el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="合同签订完成时间" | |||
prop="contractTime" | |||
> | |||
<el-date-picker | |||
v-model="formData.contractTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="交货日期" | |||
prop="deliveryTime" | |||
> | |||
<el-date-picker | |||
v-model="formData.deliveryTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="12"> | |||
<el-form-item label="合同附件" prop="attachment"> | |||
<el-upload | |||
v-model:file-list="formData.attachment" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.attachment)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="formData.payments" | |||
:pagination="false" | |||
:empty-temp="false" | |||
> | |||
<template #number="{scope}"> | |||
<span>第{{ scope.$index+1 }}笔</span> | |||
</template> | |||
<template #planAmount="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`payments[${scope.$index}].planAmount`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="scope.row.planAmount" | |||
placeholder="请填写" | |||
:disabled="!!$route.query.isReplenishment" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #ratio="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`payments[${scope.$index}].ratio`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input v-model.number="scope.row.ratio" placeholder="自动计算" disabled /> | |||
</el-form-item> | |||
</template> | |||
<template #paymentAmount="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`payments[${scope.$index}].paymentAmount`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input-number | |||
v-model="scope.row.paymentAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
:disabled="!!$route.query.isReplenishment" | |||
@mousewheel.prevent | |||
@blur="blurMoney(scope.row)" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #paymentTime="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`payments[${scope.$index}].paymentTime`" | |||
:rules="[{ required: true, message: '请选择' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-date-picker | |||
v-model="scope.row.paymentTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
:disabled="!!$route.query.isReplenishment" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #action="{scope}"> | |||
<a class="text-danger" @click="del(scope.$index)">删除</a> | |||
</template> | |||
<template #actualPaymentAmount="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
label-width="0" | |||
:prop="`payments[${scope.$index}].actualPaymentAmount`" | |||
:rules="[{ validator: (rule,value,callback)=>validActualPaymentAmount(rule,value,callback,scope.$index)}]" | |||
style="margin-bottom: 25px;margin-top: 20px" | |||
> | |||
<el-input-number | |||
v-model="scope.row.actualPaymentAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
:disabled="scope.row.isReplenishment" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</template> | |||
</table-list> | |||
<el-button | |||
v-if="!$route.query.isReplenishment" | |||
type="primary" | |||
icon="Plus" | |||
plain | |||
class="w-full mt-8" | |||
@click="add" | |||
>添加付款计划</el-button> | |||
<p v-if="$route.query.isReplenishment" class="text-danger text-14">温馨提示:请谨慎填写实际支付金额,填写后不允许修改</p> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<div class="footer"> | |||
<el-button @click="router.go(-1)"> 返回 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submit(formRef)"> 提交 </el-button> | |||
</div> | |||
</div> | |||
</template> |
@@ -0,0 +1,224 @@ | |||
<script setup name="contractRecord"> | |||
import { ref, reactive, onMounted } from 'vue' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { list } from '@/http/apis/declareMange/contractRecord' | |||
import store from '@/store' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
const router = useRouter() | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
activeName = ref('1'), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '成交金额(万元)', | |||
key: 'transactionAmount', | |||
prop: 'transactionAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '成交时间', | |||
key: 'transactionTime', | |||
prop: 'transactionTime', | |||
width: '120' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '190', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list(activeName.value, { | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
tabChange = (val) => { | |||
activeName.value = val | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(7, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
})) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8 tab-card"> | |||
<template #header> | |||
<div class="flex justify-between items-center"> | |||
<el-tabs v-model="activeName" @tab-change="tabChange"> | |||
<el-tab-pane label="待完善合同信息" name="1" /> | |||
<el-tab-pane label="已完善合同信息" name="2" /> | |||
</el-tabs> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="activeName==='1'" @click="router.push({ name: 'fillContractInfo', query: { id: scope.row.id }})">填写合同信息</a> | |||
<a v-if="activeName==='2'&&!scope.row.supplemented" @click="router.push({ name: 'fillContractInfo', query: { id: scope.row.id,isReplenishment:true }})">补充实际付款金额</a> | |||
<a @click="router.push({name:'contractRecordDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,132 @@ | |||
<script name="applyDialog" setup> | |||
import { ref, getCurrentInstance, watch } from 'vue' | |||
import { changFilesParam, fileFormatVerification, handleFileSuccess, fileTypes, fileDesc, handleFilePreview } from '@/utils/uploadAction.js' | |||
import { delayedApply } from '@/http/apis/declareMange/delayApply' | |||
import store from '@/store' | |||
const { proxy } = getCurrentInstance(), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object | |||
}), | |||
emits = defineEmits(['close']), | |||
loading = ref(false), | |||
dialogForm = ref({ | |||
supportingMaterials: [] | |||
}), | |||
rules = { | |||
'delayedMonth': [{ required: true, message: '请输入延期时长' }], | |||
'delayedReason': [{ required: true, message: '请输入延期理由' }], | |||
'supportingMaterials': [{ required: true, message: '请上传' }] | |||
}, | |||
dialogFormRef = ref(), | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid) => { | |||
if (valid) { | |||
loading.value = true | |||
try { | |||
const postData = { | |||
...dialogForm.value, | |||
supportingMaterials: dialogForm.value?.supportingMaterials?.length && JSON.stringify(changFilesParam(dialogForm.value.supportingMaterials)) || undefined, | |||
projectId: props.data.id | |||
} | |||
await delayedApply(postData) | |||
proxy.$message.success('提交成功!') | |||
loading.value = false | |||
emits('close', true) | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
} | |||
) | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
console.log('props.data', props.data) | |||
} else { | |||
dialogForm.value = { higherLineSuperOrgReviewComments: [] } | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="申请延期" | |||
width="600px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<el-form | |||
ref="dialogFormRef" | |||
:model="dialogForm" | |||
:rules="rules" | |||
label-width="auto" | |||
status-icon | |||
class="mt-16" | |||
> | |||
<el-form-item label="延期时长" prop="delayedMonth"> | |||
<el-input | |||
v-model="dialogForm.delayedMonth" | |||
placeholder="请填写需要延长几个月" | |||
@input="dialogForm.delayedMonth=dialogForm.delayedMonth?.replace(/[^\d]/g,'')" | |||
> | |||
<template #suffix>月</template> | |||
</el-input> | |||
</el-form-item> | |||
<el-form-item label="延期理由" prop="delayedReason"> | |||
<el-input | |||
v-model="dialogForm.delayedReason" | |||
type="textarea" | |||
maxlength="1000" | |||
show-word-limit | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="佐证材料:" prop="supportingMaterials"> | |||
<el-upload | |||
v-model:file-list="dialogForm.supportingMaterials" | |||
class=" w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, dialogForm.supportingMaterials, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<el-button | |||
type="primary" | |||
:loading="loading" | |||
@click="submit(dialogFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button | |||
@click="emits('close')" | |||
> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,225 @@ | |||
<script setup name="delayApply"> | |||
import { ref, reactive, onMounted } from 'vue' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { list } from '@/http/apis/declareMange/delayApply' | |||
import ApplyDialog from './components/applyDialog.vue' | |||
import store from '@/store' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
const router = useRouter() | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '批复金额(万元)', | |||
key: 'approvedAmount', | |||
prop: 'approvedAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '计划验收时间', | |||
key: 'planAcceptanceTime', | |||
prop: 'planAcceptanceTime', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '180', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(10, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
})) | |||
}, | |||
// 申请延期 | |||
applyDelay = (data) => { | |||
dialogData.visible = true | |||
dialogData.data = data | |||
}, | |||
dialogData = reactive({ | |||
visible: undefined, | |||
data: undefined | |||
}), | |||
close = (flag) => { | |||
dialogData.visible = false | |||
flag && getTableData() | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="10"> | |||
<el-form-item label="计划验收时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="scope.row.canDelayApply" @click="applyDelay(scope.row)">申请延期</a> | |||
<a @click="router.push({name:'delayApplyDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<apply-dialog :visible="dialogData.visible" :data="dialogData.data" @close="close" /> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,794 @@ | |||
<script name="declarationFinal" setup> | |||
import { onMounted, ref, nextTick, getCurrentInstance, reactive } from 'vue' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
import * as echarts from 'echarts' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import { submitFinal } from '@/http/apis/declareMange/finalInspectionDeclare' | |||
import { projectDetail } from '@/http/apis/projectStoreManage/projectStore' | |||
import ActualPerformanceIndicatorsDialog | |||
from '@/pages/declareManage/initialInspectionRecord/uploadInitMaterials/components/actualPerformanceIndicatorsDialog.vue' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
route = useRoute(), | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter() | |||
const collapseModal = ['1', '2', '3', '4', '5', '6', '7'], | |||
formRef = ref(), | |||
formData = ref({ | |||
finalAcceptanceMaterials: [ | |||
{ | |||
title: '一、项目前期材料', | |||
data: [ | |||
{ | |||
name: '信息化项目立项批复文件', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '市政府采购计划表', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '采购需求', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '中标通知书', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '技术(软件、系统等)开发合同(协议)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '设备采购合同(协议)含采购内容清单、以及合同上规定交付的所有文档', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '第三方监理合同(协议)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '其他前期资料(含中标单位营业执照、工程相关资质等)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '二、项目开工资料', | |||
data: [ | |||
{ | |||
name: '工程开工报告单(工程名称、建设单位、承建单位、施工单位、计划开工和完工日期、工程实施主要内容、建设单位审批意见及盖章日期,承建单位、施工单位盖章日期)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '软件类系统开发、部署等功能介绍', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '隐蔽工程类设计图、材料选材、施工计划等(可另作图册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '购置到位的设备产品证书、开箱证明、序列号等(可另附成册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '项目组名单及人员介绍资料', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '三、项目实施过程资料', | |||
data: [ | |||
{ | |||
name: '设备安装时间、位置一览表等', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '软件类系统开发、部署等完成情况对照表', | |||
isHave: true, | |||
required: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '历次多方讨论会议记录表、项目变更单等原始凭证', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '信息安全等级保护测评报告', | |||
isHave: true, | |||
required: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '商业密码应用评估报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '财务审计报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '变更申请单', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '变更批复文件', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '四、项目试运行资料', | |||
data: [ | |||
{ | |||
name: '试运行报告及整改情况(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '试运行情况业主单位意见(领导签字、单位盖章)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '历次巡检流程及记录表等原始凭证', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '用户使用报告', | |||
isHave: true, | |||
required: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: 'IRS应用试运行报告', | |||
isHave: true, | |||
required: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '五、项目完工资料', | |||
data: [ | |||
{ | |||
name: '工程类竣工报告(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '完工整体运行情况报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '监理总结报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '第三方项目评测报告(另册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '业主单位组织的初验专家意见及名单,整改情况', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '各类系统、场地、设备使用的管理手册、操作手册、维护手册(可另册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '售后服务承诺等(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '终验意见', | |||
isHave: true, | |||
required: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
} | |||
] | |||
}), | |||
// 材料表格 | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '材料名称', | |||
key: 'name', | |||
prop: 'name' | |||
}, | |||
{ | |||
label: '是否有材料', | |||
key: 'isHave', | |||
slot: 'isHave', | |||
width: 100 | |||
}, | |||
{ | |||
label: '附件/说明(支持扩展名:.doc .docx .pdf)', | |||
key: 'files', | |||
slot: 'files' | |||
} | |||
], | |||
applications = ref([ | |||
{ | |||
name: '应用1', | |||
status: '运行中', | |||
memoryRate: 11, | |||
cpuRate: 33, | |||
cpRate: 44 | |||
}, | |||
{ | |||
name: '应用2', | |||
status: '运行中', | |||
memoryRate: 68, | |||
cpuRate: 43, | |||
cpRate: 30 | |||
} | |||
]), | |||
applicationData = ref({}) | |||
let chart1, chart2, chart3 | |||
const chart1Ref = ref(), chart2Ref = ref(), chart3Ref = ref(), | |||
getCirChartOptions = (precent, color, text) => { | |||
const colorList = [color, 'rgba(0, 0, 0, 0.1)'] | |||
return { | |||
legend: { | |||
show: false | |||
}, | |||
graphic: [ | |||
{ | |||
type: 'text', | |||
left: 'center', | |||
top: '48%', | |||
style: { | |||
text: `${precent}%`, | |||
fill: '#333333', // 文字的颜色 | |||
fontSize: 16, | |||
fontWeight: 'bold', | |||
fontFamily: 'DINAlternate-Bold, DINAlternate' | |||
} | |||
}, | |||
{ | |||
type: 'text', | |||
left: 'center', | |||
bottom: '0', | |||
style: { | |||
text: `${text}`, | |||
fill: '#333333', // 文字的颜色 | |||
fontSize: 12 | |||
} | |||
} | |||
], | |||
series: [ | |||
{ | |||
type: 'pie', | |||
radius: ['58%', '75%'], | |||
center: ['50%', '50%'], | |||
avoidLabelOverlap: false, | |||
data: [ | |||
{ | |||
value: precent | |||
}, | |||
{ | |||
value: 100 - precent | |||
} | |||
], | |||
itemStyle: { | |||
color: function (params) { | |||
return colorList[params.dataIndex] | |||
} | |||
}, | |||
labelLine: { | |||
show: false | |||
} | |||
} | |||
] | |||
} | |||
}, | |||
initChart1 = () => { | |||
if (!chart1) chart1 = echarts.init(chart1Ref.value) | |||
const option = getCirChartOptions(applicationData.value.memoryRate, '#5ADE92', | |||
'近三个月内存平均使用率') | |||
chart1.setOption(option) | |||
}, | |||
initChart2 = () => { | |||
if (!chart2) chart2 = echarts.init(chart2Ref.value) | |||
const option = getCirChartOptions(applicationData.value.cpuRate, '#0967FD', | |||
'近三个月CPU平均使用率') | |||
chart2.setOption(option) | |||
}, | |||
initChart3 = () => { | |||
if (!chart3) chart3 = echarts.init(chart3Ref.value) | |||
const option = getCirChartOptions(applicationData.value.cpRate, '#ffae00', | |||
'近三个月磁盘平均使用率') | |||
chart3.setOption(option) | |||
}, | |||
getChart = () => { | |||
initChart1() | |||
initChart2() | |||
initChart3() | |||
}, | |||
// 切换应用 | |||
tabName = ref(0), | |||
changeApp = (index) => { | |||
tabName.value = index | |||
applicationData.value = applications.value[index] | |||
getChart() | |||
}, | |||
// 提交 | |||
submitLoading = ref(false), | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid, err) => { | |||
if (valid) { | |||
submitLoading.value = true | |||
const postData = { | |||
id: route.query.id, | |||
isCompletedLogCollection: formData.value.isCompletedLogCollection, | |||
finalAcceptanceMaterials: JSON.stringify(formData.value.finalAcceptanceMaterials), | |||
actualPerformanceIndicators: formData.value.actualPerformanceIndicators && JSON.stringify(formData.value.actualPerformanceIndicators) || undefined | |||
} | |||
try { | |||
await submitFinal(route.name === 'declarationFinal' ? 1 : 2, { projectInfo: postData }) | |||
submitLoading.value = false | |||
proxy.$message.success('提交成功') | |||
router.go(-1) | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
} else { | |||
console.log(err) | |||
} | |||
}) | |||
}, | |||
getProjectDetail = async () => { | |||
const res = await projectDetail(route.query.id) | |||
formData.value = { | |||
isCompletedLogCollection: res.data.isCompletedLogCollection, | |||
finalAcceptanceMaterials: res.data.finalAcceptanceMaterials && JSON.parse(res.data.finalAcceptanceMaterials) || res.data.preliminaryInspectionMaterials && JSON.parse(res.data.preliminaryInspectionMaterials), | |||
actualPerformanceIndicators: res.data.actualPerformanceIndicators && JSON.parse(res.data.actualPerformanceIndicators) || res.data.actualPerformanceIndicators && JSON.parse(res.data.actualPerformanceIndicators) | |||
} | |||
formData.value.finalAcceptanceMaterials = formData.value.finalAcceptanceMaterials.map(i => { | |||
return { | |||
...i, | |||
data: i.data.map(j => { | |||
return { | |||
...j, | |||
isHave: ['软件类系统开发、部署等完成情况对照表', '信息安全等级保护测评报告', '用户使用报告', 'IRS应用试运行报告', '终验意见'].includes(j.name) ? true : j.isHave, | |||
required: ['软件类系统开发、部署等完成情况对照表', '信息安全等级保护测评报告', '用户使用报告', 'IRS应用试运行报告', '终验意见'].includes(j.name) ? true : j.required | |||
} | |||
}) | |||
} | |||
}) | |||
if (res.data.projectApplications?.length) { | |||
if (res.data.projectApplications.map(i => i.secrecyGrade).includes(3) || res.data.projectApplications.map(i => i.secrecyGrade).includes(4) || res.data.projectApplications.map(i => i.secrecyGrade).includes(5)) { | |||
formData.value.finalAcceptanceMaterials = formData.value.finalAcceptanceMaterials.map(i => { | |||
return { | |||
...i, | |||
data: i.data.map(j => { | |||
return { | |||
...j, | |||
isHave: ['商业密码应用评估报告'].includes(j.name) ? true : j.isHave, | |||
required: ['商业密码应用评估报告'].includes(j.name) ? true : j.required | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
} | |||
applications.value = res.data.projectApplications?.map((i, index) => { | |||
return { | |||
name: i.applicationName || i.relatedExistsApplication, | |||
status: '运行中', | |||
finalIrsApps: res.data.finalIrsApps[index] | |||
} | |||
}) || [] | |||
applicationData.value = applications.value[0] | |||
}, | |||
// 实际成效指标 | |||
column1 = [ | |||
{ | |||
label: '核心业务', | |||
prop: 'businessName', | |||
key: 'businessName' | |||
}, | |||
{ | |||
label: '实际成效指标', | |||
prop: 'name', | |||
key: 'name' | |||
}, | |||
{ | |||
label: '数值', | |||
prop: 'nums', | |||
key: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
prop: 'unit', | |||
key: 'unit' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
projectContentDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
projectContentIndex = ref(), | |||
showProjectContentDialog = (data, index) => { | |||
projectContentDialogData.data = data | |||
projectContentDialogData.visible = true | |||
projectContentIndex.value = index | |||
}, | |||
setContent = (data) => { | |||
if (projectContentIndex.value === undefined) { | |||
formData.value.actualPerformanceIndicators = formData.value.actualPerformanceIndicators?.length ? [...formData.value.actualPerformanceIndicators, ...data] : data | |||
} else { | |||
formData.value.actualPerformanceIndicators[projectContentIndex.value] = data[0] | |||
} | |||
}, | |||
delProjectContent = (index) => { | |||
formData.value.actualPerformanceIndicators.splice(index, 1) | |||
} | |||
onMounted(async () => { | |||
await nextTick() | |||
// getChart() | |||
getProjectDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class="uploadInitfinalAcceptanceMaterials footerPage"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
label-position="right" | |||
label-width="90px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="table-form" | |||
> | |||
<el-collapse v-model="collapseModal"> | |||
<el-collapse-item v-if="applications?.length" name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">关联的应用信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<el-tabs v-model="tabName" tab-position="left" @tab-change="changeApp"> | |||
<el-tab-pane | |||
v-for="(item,index) in applications" | |||
:key="index" | |||
:label="item.name" | |||
:name="index" | |||
/> | |||
<div class="pl-24"> | |||
<p class="font-semibold text-14 mb-16">应用状态:<span class="text-primary">{{ applicationData.status }}</span></p> | |||
<p class="font-semibold text-14">资源概览</p> | |||
<div class="p-16"> | |||
<el-row class="mb-16"> | |||
<el-col :span="12"> | |||
<p class="mb-8">云资源使用情况</p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="云资源实例使用数"> | |||
{{ applicationData?.finalIrsApps?.cloudResourceUsage.instancesNum }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="云资源产品"> | |||
暂无 | |||
</el-descriptions-item> | |||
<el-descriptions-item label="云资源利用率"> | |||
{{ applicationData?.finalIrsApps?.cloudResourceUsage.utilizationRate }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-8">数据使用情况</p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="数据共享申请量"> | |||
{{ applicationData?.finalIrsApps?.dataUsage.sharedApplicationVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="数据共享使用量"> | |||
{{ applicationData?.finalIrsApps?.dataUsage.sharedUsage }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-31"></p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="协同接口调用量"> | |||
{{ applicationData?.finalIrsApps?.dataUsage.collaborativeInterfaceCallVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="数据共享调用量"> | |||
{{ applicationData?.finalIrsApps?.dataUsage.sharedInterfaceCallVolume }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-8">组件使用情况</p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="组件申请量"> | |||
{{ applicationData?.finalIrsApps?.componentUsage.applicationVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="组件调用量"> | |||
{{ applicationData?.finalIrsApps?.componentUsage.callVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="组件使用量"> | |||
{{ applicationData?.finalIrsApps?.componentUsage.useVolume }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-31"></p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="统一组件调用量"> | |||
{{ applicationData?.finalIrsApps?.componentUsage.unifyCallolVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="使用组件"> | |||
暂无 | |||
</el-descriptions-item> | |||
<el-descriptions-item label="使用强制类组件"> | |||
暂无 | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-8">产生数据</p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="产生数据量"> | |||
{{ applicationData?.finalIrsApps?.generateData.volume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="产生数据共享使用量"> | |||
{{ applicationData?.finalIrsApps?.generateData.sharedUseVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="数据接口被调用量"> | |||
{{ applicationData?.finalIrsApps?.generateData.dataInterfaceCallsVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="使用批量数据"> | |||
暂无 | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12" class="mb-16"> | |||
<p class="mb-31"></p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="产生数据共享申请量"> | |||
{{ applicationData?.finalIrsApps?.generateData.sharedApplicationVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="产生数据审批通过率"> | |||
{{ applicationData?.finalIrsApps?.generateData.approvalPassRate }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="协同接口被调用量"> | |||
{{ applicationData?.finalIrsApps?.generateData.collaborativeInterfaceCallVolume }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="使用共享接口"> | |||
暂无 | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
<el-col :span="12"> | |||
<p class="mb-8">试运行报告</p> | |||
<el-descriptions :column="1" border> | |||
<el-descriptions-item label="试运行报告通过率"> | |||
{{ applicationData?.finalIrsApps?.operationReport.passRate }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
<template v-if="false"> | |||
<p class="font-semibold text-14">云资源利用率</p> | |||
<el-row> | |||
<el-col :span="8"> | |||
<div ref="chart1Ref" style="height: 200px"></div> | |||
</el-col> | |||
<el-col :span="8"> | |||
<div ref="chart2Ref" style="height: 200px"></div> | |||
</el-col> | |||
<el-col :span="8"> | |||
<div ref="chart3Ref" style="height: 200px"></div> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
</div> | |||
</el-tabs> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="7" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">实施信息</div> | |||
</template> | |||
<el-form-item | |||
label="是否完成日志数据归集" | |||
label-width="170" | |||
prop="isCompletedLogCollection" | |||
:rules="[{required:true,message:'请选择'}]" | |||
> | |||
<el-radio-group v-model="formData.isCompletedLogCollection"> | |||
<el-radio :label="true">是</el-radio> | |||
<el-radio :label="false">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item | |||
label="实际成效指标" | |||
label-width="170" | |||
prop="actualPerformanceIndicators" | |||
:rules="[{required:true,message:'请选择'}]" | |||
> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.actualPerformanceIndicators" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
</el-collapse-item> | |||
<el-collapse-item | |||
v-for="(item,index) in formData.finalAcceptanceMaterials" | |||
:key="index" | |||
:name="index+2+''" | |||
class="mb-16" | |||
> | |||
<template #title> | |||
<div class="collapse-title">{{ item.title }}</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="item.data" | |||
:pagination="false" | |||
:empty-temp="false" | |||
> | |||
<template #isHave="{scope}"> | |||
<el-switch v-model="scope.row.isHave" :disabled="scope.row.required" /> | |||
</template> | |||
<template #files="{scope}"> | |||
<template v-if="scope.$index>=0"> | |||
<el-form-item | |||
v-if="scope.row.isHave" | |||
:prop="`finalAcceptanceMaterials[${index}].data[${scope.$index}].files`" | |||
:rules="[{ required: true, message: '请上传' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
class="uploadFormItem" | |||
> | |||
<el-upload | |||
v-model:file-list="scope.row.files" | |||
class="w-full table-upload" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, scope.row.files)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain size="small">选择文件</el-button> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
:prop="`finalAcceptanceMaterials[${index}].data[${scope.$index}].reason`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input v-model="scope.row.reason" placeholder="请填写缺少该材料的原因" maxlength="50" /> | |||
</el-form-item> | |||
</template> | |||
</template> | |||
</table-list> | |||
</el-collapse-item> | |||
</el-collapse> | |||
</el-form> | |||
<div class="footer"> | |||
<el-button @click="router.go(-1)"> 返回 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submit(formRef)"> 提交 </el-button> | |||
</div> | |||
</div> | |||
<actual-performance-indicators-dialog | |||
:visible="projectContentDialogData.visible" | |||
:data="projectContentDialogData.data" | |||
@set-content="setContent" | |||
@close="projectContentDialogData.visible=false" | |||
/> | |||
</template> | |||
<style lang="less"> | |||
.uploadInitfinalAcceptanceMaterials{ | |||
.table-form{ | |||
.uploadFormItem{ | |||
.el-form-item__error{ | |||
position: absolute; | |||
left: 100px; | |||
top:16px; | |||
transform: translateY(-50%); | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,210 @@ | |||
<script setup name="finalInspectionDeclare"> | |||
import { ref, reactive, onMounted } from 'vue' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { list } from '@/http/apis/declareMange/finalInspectionDeclare' | |||
import store from '@/store' | |||
const router = useRouter() | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '批复金额(万元)', | |||
key: 'approvedAmount', | |||
prop: 'approvedAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '计划验收时间', | |||
key: 'planAcceptanceTime', | |||
prop: 'planAcceptanceTime', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '180', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(0), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(9, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
})) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="10"> | |||
<el-form-item label="计划验收时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="router.push({ name: 'declarationFinal', query: { id: scope.row.id }})">终验申报</a> | |||
<a @click="router.push({name:'finalInspectionDeclareDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,226 @@ | |||
<script setup name="initialInspectionRecord"> | |||
import { ref, reactive, onMounted } from 'vue' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { list } from '@/http/apis/declareMange/initialInspectionRecord' | |||
import store from '@/store' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
const router = useRouter() | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '年度预算(万元)', | |||
key: 'annualPlanAmount', | |||
prop: 'annualPlanAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '成交金额(万元)', | |||
key: 'transactionAmount', | |||
prop: 'transactionAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '合同金额(万元)', | |||
key: 'contractAmount', | |||
prop: 'contractAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '交货日期', | |||
key: 'deliveryTime', | |||
prop: 'deliveryTime', | |||
width: '200' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '180', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(8, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
})) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="router.push({ name: 'uploadInitMaterials', query: { id: scope.row.id }})">上传初验材料</a> | |||
<a @click="router.push({name:'initialInspectionRecordDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,186 @@ | |||
<script setup name="actualPerformanceIndicatorsDialog"> | |||
import { ref, watch } from 'vue' | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object | |||
}), | |||
form = ref({ | |||
perIndicator: [] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
perIndicator: [{ required: true, message: '请至少添加一个实际成效指标' }] | |||
}, | |||
column = [ | |||
{ | |||
label: '核心业务名称', | |||
key: 'businessName', | |||
slot: 'businessName', | |||
width: 140 | |||
}, | |||
{ | |||
label: '实际成效指标名称', | |||
key: 'name', | |||
slot: 'name', | |||
width: 140 | |||
}, | |||
{ | |||
label: '数值', | |||
key: 'nums', | |||
slot: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
key: 'unit', | |||
slot: 'unit' | |||
}, | |||
{ | |||
label: '操作', | |||
key: 'action', | |||
slot: 'action', | |||
width: 70 | |||
} | |||
], | |||
// 添加 | |||
add = () => { | |||
form.value.perIndicator.push({}) | |||
}, | |||
del = (index) => { | |||
form.value.perIndicator.splice(index, 1) | |||
}, | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
await formEl.validate(async (valid) => { | |||
if (valid) { | |||
const data = JSON.parse(JSON.stringify(form.value.perIndicator)) | |||
emits('setContent', data) | |||
emits('close', true) | |||
} | |||
}) | |||
}, | |||
isShowAdd = ref(true), | |||
emits = defineEmits(['close', 'setContent']) | |||
watch( | |||
() => props.visible, | |||
async (val) => { | |||
if (val && props.data) { | |||
isShowAdd.value = !props.data | |||
form.value.perIndicator = [JSON.parse(JSON.stringify(props.data))] | |||
} else { | |||
isShowAdd.value = true | |||
formRef.value?.resetFields() | |||
form.value = { | |||
perIndicator: [] | |||
} | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="添加" | |||
:size="840" | |||
@close="emits('close')" | |||
> | |||
<el-form | |||
ref="formRef" | |||
label-suffix=":" | |||
:model="form" | |||
:rules="rules" | |||
label-width="160" | |||
> | |||
<el-button | |||
v-if="isShowAdd" | |||
type="primary" | |||
plain | |||
icon="Plus" | |||
class="w-full mb-8" | |||
@click="add" | |||
>添加 | |||
</el-button> | |||
<table-list | |||
:pagination="false" | |||
:column="column" | |||
:empty-temp="false" | |||
:data="form.perIndicator" | |||
> | |||
<template #businessName="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].businessName`" | |||
:rules="[{required:true,message:' '}]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="form.perIndicator[scope.$index].businessName" | |||
placeholder="请输入" | |||
maxlength="50" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #name="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].name`" | |||
:rules="[{required:true,message:' '}]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="form.perIndicator[scope.$index].name" | |||
placeholder="请输入" | |||
maxlength="50" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #nums="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].nums`" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input-number | |||
v-model="form.perIndicator[scope.$index].nums" | |||
:controls="false" | |||
class="flex-1 mr-8" | |||
placeholder="请输入" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #unit="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].unit`" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="form.perIndicator[scope.$index].unit" | |||
placeholder="请输入" | |||
maxlength="10" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #action="{scope}"> | |||
<a class="text-danger cursor-pointer" @click="del(scope.$index)">移除</a> | |||
</template> | |||
</table-list> | |||
</el-form> | |||
<template #footer> | |||
<el-button type="primary" @click="submit(formRef)">提交</el-button> | |||
<el-button @click="emits('close')">取消</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,581 @@ | |||
<script name="uploadInitpreliminaryInspectionMaterials" setup> | |||
import { getCurrentInstance, onMounted, reactive, ref } from 'vue' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
import { preInsDetail, submitPreIns } from '@/http/apis/declareMange/initialInspectionRecord' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import ActualPerformanceIndicatorsDialog | |||
from '@/pages/declareManage/initialInspectionRecord/uploadInitMaterials/components/actualPerformanceIndicatorsDialog.vue' | |||
import { projectDetail } from '@/http/apis/projectStoreManage/projectStore' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
route = useRoute(), | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter() | |||
const collapseModal = ['1', '2', '3', '4', '5', '6', '7'], | |||
formRef = ref(), | |||
formData = ref({ | |||
acceptancePersons: [ | |||
{ | |||
personName: '', | |||
unit: '' | |||
} | |||
], | |||
actualPerformanceIndicators: [], | |||
preliminaryInspectionMaterials: [ | |||
{ | |||
title: '一、项目前期材料', | |||
data: [ | |||
{ | |||
name: '信息化项目立项批复文件', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '市政府采购计划表', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '采购需求', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '中标通知书', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '技术(软件、系统等)开发合同(协议)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '设备采购合同(协议)含采购内容清单、以及合同上规定交付的所有文档', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '第三方监理合同(协议)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '其他前期资料(含中标单位营业执照、工程相关资质等)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '二、项目开工资料', | |||
data: [ | |||
{ | |||
name: '工程开工报告单(工程名称、建设单位、承建单位、施工单位、计划开工和完工日期、工程实施主要内容、建设单位审批意见及盖章日期,承建单位、施工单位盖章日期)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '软件类系统开发、部署等功能介绍', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '隐蔽工程类设计图、材料选材、施工计划等(可另作图册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '购置到位的设备产品证书、开箱证明、序列号等(可另附成册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '项目组名单及人员介绍资料', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '三、项目实施过程资料', | |||
data: [ | |||
{ | |||
name: '设备安装时间、位置一览表等', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '软件类系统开发、部署等完成情况对照表', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '历次多方讨论会议记录表、项目变更单等原始凭证', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '信息安全等级保护测评报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '商业密码应用评估报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '财务审计报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '变更申请单', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '变更批复文件', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '四、项目试运行资料', | |||
data: [ | |||
{ | |||
name: '试运行报告及整改情况(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '试运行情况业主单位意见(领导签字、单位盖章)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '历次巡检流程及记录表等原始凭证', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '用户使用报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: 'IRS应用试运行报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
}, | |||
{ | |||
title: '五、项目完工资料', | |||
data: [ | |||
{ | |||
name: '工程类竣工报告(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '完工整体运行情况报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '监理总结报告', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '第三方项目评测报告(另册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '业主单位组织的初验专家意见及名单,整改情况', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '各类系统、场地、设备使用的管理手册、操作手册、维护手册(可另册)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '售后服务承诺等(建设单位)', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
}, | |||
{ | |||
name: '终验意见', | |||
isHave: true, | |||
files: [], | |||
reason: '' | |||
} | |||
] | |||
} | |||
] | |||
}), | |||
// 增加验收人员 | |||
add = () => { | |||
formData.value.acceptancePersons.push({}) | |||
}, | |||
// 删除验收人员 | |||
del = (index) => { | |||
formData.value.acceptancePersons.splice(index, 1) | |||
}, | |||
// 材料表格 | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '材料名称', | |||
key: 'name', | |||
prop: 'name' | |||
}, | |||
{ | |||
label: '是否有材料', | |||
key: 'isHave', | |||
slot: 'isHave', | |||
width: 100 | |||
}, | |||
{ | |||
label: '附件/说明(支持扩展名:.doc .docx .pdf)', | |||
key: 'files', | |||
slot: 'files' | |||
} | |||
], | |||
// 获取详情 | |||
getDetail = async () => { | |||
const res = await preInsDetail(route.query.id) | |||
if (res.data) { | |||
formData.value = { | |||
...res.data, | |||
acceptancePersons: res.data.acceptancePersons ? res.data.acceptancePersons : [ | |||
{ | |||
personName: '', | |||
unit: '' | |||
} | |||
], | |||
actualPerformanceIndicators: res.data.actualPerformanceIndicators && JSON.parse(res.data.actualPerformanceIndicators)?.length ? JSON.parse(res.data.actualPerformanceIndicators) : formData.value.actualPerformanceIndicators, | |||
preliminaryInspectionMaterials: res.data.preliminaryInspectionMaterials && JSON.parse(res.data.preliminaryInspectionMaterials)?.length ? JSON.parse(res.data.preliminaryInspectionMaterials) : formData.value.preliminaryInspectionMaterials | |||
} | |||
} | |||
}, | |||
// 提交 | |||
submitLoading = ref(false), | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid, err) => { | |||
if (valid) { | |||
submitLoading.value = true | |||
const postData = { | |||
...formData.value, | |||
actualPerformanceIndicators: formData.value.actualPerformanceIndicators && JSON.stringify(formData.value.actualPerformanceIndicators), | |||
preliminaryInspectionMaterials: JSON.stringify(formData.value.preliminaryInspectionMaterials) | |||
} | |||
try { | |||
await submitPreIns(postData) | |||
submitLoading.value = false | |||
proxy.$message.success('提交成功') | |||
router.go(-1) | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
} else { | |||
console.log(err) | |||
} | |||
}) | |||
}, | |||
// 实际成效指标 | |||
column1 = [ | |||
{ | |||
label: '核心业务', | |||
prop: 'businessName', | |||
key: 'businessName' | |||
}, | |||
{ | |||
label: '实际成效指标', | |||
prop: 'name', | |||
key: 'name' | |||
}, | |||
{ | |||
label: '数值', | |||
prop: 'nums', | |||
key: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
prop: 'unit', | |||
key: 'unit' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
projectContentDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
projectContentIndex = ref(), | |||
showProjectContentDialog = (data, index) => { | |||
projectContentDialogData.data = data | |||
projectContentDialogData.visible = true | |||
projectContentIndex.value = index | |||
}, | |||
setContent = (data) => { | |||
if (projectContentIndex.value === undefined) { | |||
formData.value.actualPerformanceIndicators = [...formData.value.actualPerformanceIndicators, ...data] | |||
} else { | |||
formData.value.actualPerformanceIndicators[projectContentIndex.value] = data[0] | |||
} | |||
}, | |||
delProjectContent = (index) => { | |||
formData.value.actualPerformanceIndicators.splice(index, 1) | |||
}, | |||
getProjectDetail = async () => { | |||
const res = await projectDetail(route.query.id) | |||
if (res.data.projectApplications?.length) { | |||
if (res.data.projectApplications.map(i => i.secrecyGrade).includes(3) || res.data.projectApplications.map(i => i.secrecyGrade).includes(4) || res.data.projectApplications.map(i => i.secrecyGrade).includes(5)) { | |||
formData.value.preliminaryInspectionMaterials = formData.value.preliminaryInspectionMaterials.map(i => { | |||
return { | |||
...i, | |||
data: i.data.map(j => { | |||
return { | |||
...j, | |||
required: j.name === '商业密码应用评估报告' ? true : j.required | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
} | |||
} | |||
onMounted(() => { | |||
getDetail() | |||
getProjectDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class="uploadInitpreliminaryInspectionMaterials footerPage"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
label-position="right" | |||
label-width="90px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="table-form" | |||
> | |||
<el-collapse v-model="collapseModal"> | |||
<el-collapse-item name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">验收人员信息</div> | |||
</template> | |||
<div class="p-24"> | |||
<el-row v-for="(item,index) in formData.acceptancePersons" :key="index" :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="验收人员" | |||
:prop="`acceptancePersons[${index}].personName`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input v-model="item.personName" placeholder="请填写姓名" maxlength="50" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="所在单位" | |||
:prop="`acceptancePersons[${index}].unit`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input v-model="item.unit" placeholder="请填写单位" maxlength="50" /> | |||
</el-form-item> | |||
</el-col> | |||
<a | |||
v-if="formData.acceptancePersons?.length>1" | |||
class="text-danger absolute top-4" | |||
style="right: -12px" | |||
@click="del(index)" | |||
>删除</a> | |||
</el-row> | |||
<el-button | |||
type="primary" | |||
plain | |||
icon="Plus" | |||
size="small" | |||
@click="add" | |||
>增加</el-button> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="7" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">实施信息</div> | |||
</template> | |||
<el-form-item | |||
label="是否完成日志数据归集" | |||
label-width="170" | |||
prop="isCompletedLogCollection" | |||
:rules="[{required:true,message:'请选择'}]" | |||
> | |||
<el-radio-group v-model="formData.isCompletedLogCollection"> | |||
<el-radio :label="true">是</el-radio> | |||
<el-radio :label="false">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item | |||
label="实际成效指标" | |||
label-width="170" | |||
prop="actualPerformanceIndicators" | |||
:rules="[{required:true,message:'请选择'}]" | |||
> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.actualPerformanceIndicators" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
</el-collapse-item> | |||
<el-collapse-item | |||
v-for="(item,index) in formData.preliminaryInspectionMaterials" | |||
:key="index" | |||
:name="index+2+''" | |||
class="mb-16" | |||
> | |||
<template #title> | |||
<div class="collapse-title">{{ item.title }}</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="item.data" | |||
:pagination="false" | |||
:empty-temp="false" | |||
> | |||
<template #isHave="{scope}"> | |||
<el-switch v-model="scope.row.isHave" :disabled="scope.row.required" /> | |||
</template> | |||
<template #files="{scope}"> | |||
<template v-if="scope.$index>=0"> | |||
<el-form-item | |||
v-if="scope.row.isHave" | |||
:prop="`preliminaryInspectionMaterials[${index}].data[${scope.$index}].files`" | |||
:rules="[{ required: true, message: '请上传' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
class="uploadFormItem" | |||
> | |||
<el-upload | |||
v-model:file-list="scope.row.files" | |||
class="w-full table-upload" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, scope.row.files)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain size="small">选择文件</el-button> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
:prop="`preliminaryInspectionMaterials[${index}].data[${scope.$index}].reason`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input v-model="scope.row.reason" placeholder="请填写缺少该材料的原因" maxlength="50" /> | |||
</el-form-item> | |||
</template> | |||
</template> | |||
</table-list> | |||
</el-collapse-item> | |||
</el-collapse> | |||
</el-form> | |||
<div class="footer"> | |||
<el-button @click="router.go(-1)"> 返回 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submit(formRef)"> 提交 </el-button> | |||
</div> | |||
</div> | |||
<actual-performance-indicators-dialog | |||
:visible="projectContentDialogData.visible" | |||
:data="projectContentDialogData.data" | |||
@set-content="setContent" | |||
@close="projectContentDialogData.visible=false" | |||
/> | |||
</template> | |||
<style lang="less"> | |||
.uploadInitpreliminaryInspectionMaterials{ | |||
.table-form{ | |||
.uploadFormItem{ | |||
.el-form-item__error{ | |||
position: absolute; | |||
left: 100px; | |||
top:16px; | |||
transform: translateY(-50%); | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,69 @@ | |||
<script setup name="basicInfo"> | |||
import { onMounted, ref } from 'vue' | |||
import { applicationList } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const userInfo = storeToRefs(store.userStore).userInfo, | |||
props = defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}), | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '关联IRS应用名称', | |||
prop: 'applicationName', | |||
key: 'applicationName' | |||
}, | |||
{ | |||
label: 'IRS应用编码', | |||
prop: 'applicationCode', | |||
key: 'applicationCode' | |||
}, | |||
{ | |||
label: '一本账重大应用名称', | |||
prop: 'baseAccountAppName', | |||
key: 'baseAccountAppName' | |||
}, | |||
{ | |||
label: '"领域大脑"一本账名称', | |||
prop: 'baseBrainName', | |||
key: 'baseBrainName' | |||
} | |||
], | |||
data = ref([]), | |||
appList = ref([]) | |||
onMounted(async () => { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode }) | |||
appList.value = res.data | |||
data.value = props?.detailData?.baseProjSysCode?.split(';')?.map((i, k) => { | |||
return { | |||
applicationCode: i, | |||
applicationName: props?.detailData?.baseProjSys?.split(';')[k] || '', | |||
baseAccountAppName: props?.detailData?.baseAccountAppName?.split(';')[k] || '', | |||
baseBrainName: props?.detailData?.baseBrainName?.split(';')[k] || '' | |||
} | |||
}) || [] | |||
}) | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<el-descriptions-item label="关联IRS应用名称"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="data" | |||
:empty-temp="false" | |||
/> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,186 @@ | |||
<script setup name="applyInfo"> | |||
import { onMounted, ref } from 'vue' | |||
import Accessory from '@/components/accessory/index.vue' | |||
const props = defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
basicInfoData: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
dictionaryList: Array | |||
}) | |||
const column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '项目名称', | |||
prop: 'baseProjName', | |||
key: 'baseProjName' | |||
}, | |||
{ | |||
label: '预算年度', | |||
prop: 'baseProjSetYear', | |||
key: 'baseProjSetYear' | |||
} | |||
], | |||
column1 = [ | |||
{ | |||
label: '项目主要内容', | |||
prop: 'mainContent', | |||
key: 'mainContent' | |||
}, | |||
{ | |||
label: '业务对象', | |||
prop: 'businessObject', | |||
key: 'businessObject' | |||
} | |||
], | |||
// 立项依据 | |||
buildBasisColumn = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '依据项', | |||
key: 'title', | |||
prop: 'title' | |||
}, | |||
{ | |||
label: '依据文件名', | |||
slot: 'fileName' | |||
}, | |||
{ | |||
label: '文件(支持word、pdf格式)', | |||
slot: 'action', | |||
width: 300 | |||
} | |||
], | |||
buildBasisTableData = ref([]), | |||
tableListRef = ref() | |||
onMounted(() => { | |||
buildBasisTableData.value = props.detailData?.baseProjBasis?.split(';')?.map((i, index) => { | |||
const file = `[${props.detailData?.baseProjBasisFile.replace(/}];/g, '}],')}]` | |||
return { | |||
title: props.dictionaryList?.filter(k => k.type === 'PROJECT_BASIS')?.find(j => j.value === i)?.label, | |||
fileList: props.detailData?.baseProjBasisFile ? JSON.parse(file)[index] : [], | |||
value: i | |||
} | |||
}) | |||
}) | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<el-descriptions-item label="发改编码"> | |||
{{ detailData?.baseDevelopCode ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="财政编码"> | |||
{{ detailData?.setProjCodeFinan ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目起止时间"> | |||
<span v-if="detailData?.baseProjStartTime&&detailData?.baseProjEndTime">{{ detailData?.baseProjStartTime?.split(' ')[0] }} ~ {{ detailData?.baseProjEndTime?.split(' ')[0] }}</span> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="预算年度"> | |||
{{ detailData?.baseProjSetYear ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目总投资"> | |||
{{ detailData?.baseProjTotalAmount ||'-' }}万元 | |||
</el-descriptions-item> | |||
<el-descriptions-item label="申报年度预算"> | |||
{{ detailData?.baseProjDeclAmount ||'-' }}万元 | |||
</el-descriptions-item> | |||
<el-descriptions-item label="建设层级"> | |||
{{ dictionaryList?.filter(i => i.type === 'BUILD_LEVEL').find(i=>i.value===detailData?.baseProjConsClass)?.label ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!(basicInfoData?.baseConstructionType?.split(';')?.includes('03')&&!basicInfoData?.baseConstructionType?.split(';')?.includes('01'))" label="贯通层级"> | |||
{{ dictionaryList?.filter(i => i.type === 'LINK_UP_LEVEL').find(i=>i.value===detailData?.baseLowestLevel)?.label ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="历年项目名称" :span="2"> | |||
<span v-if="detailData.missing">缺失</span> | |||
<table-list | |||
v-else | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="detailData.baseHistorProjs" | |||
:empty-temp="false" | |||
/> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="预算来源" :span="2"> | |||
{{ detailData?.baseProjAmountOri?.split(';').map(i=>dictionaryList?.filter(j => j.type === 'BUDGET_SOURCE').find(k=>k.value===i)?.label).join('、') ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="预算来源说明" :span="2"> | |||
{{ detailData?.baseBasisAmountOri ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="立项依据" :span="2"> | |||
<table-list | |||
ref="tableListRef" | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="buildBasisColumn" | |||
:data="buildBasisTableData" | |||
> | |||
<template #fileName="{scope}"> | |||
{{ scope.row.fileList[0].originalFileName }} | |||
</template> | |||
<template #action="{scope}"> | |||
<p v-for="(file,fileIndex) in scope.row.fileList" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
</table-list> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="立项依据说明" :span="2"> | |||
{{ detailData?.baseBasisEstablish ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目概述" :span="2"> | |||
{{ detailData?.baseProjIntro ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目内容与预期成效" :span="2"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="detailData?.beseExpectedResults&&JSON.parse(detailData?.beseExpectedResults)" | |||
:empty-temp="false" | |||
/> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目申报书" :span="2"> | |||
<template v-if="detailData?.baseProjApplyFile&&JSON.parse(detailData?.baseProjApplyFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseProjApplyFile&&JSON.parse(detailData?.baseProjApplyFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjType==='01'||basicInfoData?.baseProjType==='02'" label="可行性研究报告" :span="2"> | |||
<template v-if="detailData?.baseResearchReportFile&&JSON.parse(detailData?.baseResearchReportFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseResearchReportFile&&JSON.parse(detailData?.baseResearchReportFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="其他附件" :span="2"> | |||
<template v-if="detailData?.baseProjOtherFile&&JSON.parse(detailData?.baseProjOtherFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseProjOtherFile&&JSON.parse(detailData?.baseProjOtherFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="备注" :span="2"> | |||
{{ detailData?.baseProjRemark ||'-' }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,72 @@ | |||
<script setup name="basicInfo"> | |||
import store from '@/store' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
dictionaryList: Array, | |||
templateTypeListData: Array | |||
}) | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<!-- <el-descriptions-item label="是否涉密项目">--> | |||
<!-- {{ dictionaryList?.filter(i => i.type === 'CLASSIFIED').find(i=>i.value===detailData?.baseProjIsConfidentiality)?.label ||'-' }}--> | |||
<!-- </el-descriptions-item>--> | |||
<el-descriptions-item label="项目是否归集省里" span="2"> | |||
{{ detailData?.push?'是':'否' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目名称" span="2"> | |||
{{ detailData?.baseProjName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目类型"> | |||
{{ detailData?.baseProjType&&projectTypeOptions[detailData?.baseProjType]||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="内容类别"> | |||
{{ detailData?.baseConstructionType?.split(';').map(i=>dictionaryList?.filter(j => j.type === 'CONTENT_TYPE').find(k=>k.value===i)?.label).join('、') ||'-' }} | |||
</el-descriptions-item> | |||
<!-- <el-descriptions-item label="项目状态">--> | |||
<!-- {{ dictionaryList?.filter(i => i.type === 'PROJECT_STATUS').find(i=>i.value===detailData?.baseProjSetProg)?.label ||'-' }}--> | |||
<!-- </el-descriptions-item>--> | |||
<el-descriptions-item label="上级主管单位类型"> | |||
{{ detailData?.baseProvManDeprtType===1?'省级':detailData?.baseProvManDeprtType===2?'非省级':'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="上级主管单位"> | |||
{{ detailData?.baseProvManDeprt ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="本级主管单位"> | |||
{{ detailData?.baseManDeprt ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="本级主管单位统一社会信用代码"> | |||
{{ detailData?.baseManDepartUsci ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="建设单位"> | |||
{{ detailData?.baseBuildDeprt ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="建设单位统一信用代码"> | |||
{{ detailData?.baseBuildDepartUsci ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目负责人"> | |||
{{ detailData?.baseProjPrincipal ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="负责人手机号码"> | |||
{{ detailData?.baseProjPrincipalCall ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目联系人"> | |||
{{ detailData?.baseProjContacts ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="联系人手机号码"> | |||
{{ detailData?.baseProjContactsCall ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="系统定位" :span="2"> | |||
{{ detailData?.systemPosition ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="绩效评价类型" :span="2"> | |||
{{ templateTypeListData?.find(i=>i.id===detailData?.templateType)?.name||"-" }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,59 @@ | |||
<script setup name="coreBusiness"> | |||
import { onMounted, ref } from 'vue' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const userInfo = storeToRefs(store.userStore).userInfo, | |||
props = defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}), | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
// { | |||
// label: '业务编号', | |||
// key: 'oid', | |||
// prop: 'oid' | |||
// }, | |||
{ | |||
label: '业务名称', | |||
key: 'matterName', | |||
prop: 'matterName' | |||
}, | |||
{ | |||
label: '所属单位', | |||
key: 'orgName', | |||
prop: 'orgName' | |||
} | |||
], | |||
data = ref([]) | |||
onMounted(async () => { | |||
data.value = props?.detailData?.baseCoreBusinessCode?.split(';')?.map((i, k) => { | |||
return { | |||
oid: i, | |||
matterName: props?.detailData?.baseCoreBusiness?.split(';')[k], | |||
orgName: userInfo.value.empPosUnitName | |||
} | |||
}) || [] | |||
}) | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<el-descriptions-item label="核心业务"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="data" | |||
:empty-temp="false" | |||
/> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,139 @@ | |||
<script setup name="empMaterials"> | |||
import Accessory from '@/components/accessory/index.vue' | |||
defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
approvalInfoData: { | |||
type: Object | |||
}, | |||
baseProjSetYear: { | |||
type: String, | |||
default: '' | |||
} | |||
}) | |||
const column1 = [ | |||
{ | |||
label: '核心业务', | |||
prop: 'businessName', | |||
key: 'businessName' | |||
}, | |||
{ | |||
label: '实际成效指标', | |||
prop: 'name', | |||
key: 'name' | |||
}, | |||
{ | |||
label: '数值', | |||
prop: 'nums', | |||
key: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
prop: 'unit', | |||
key: 'unit' | |||
} | |||
] | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<el-descriptions-item label="是否完成日志数据归集" :span="2"> | |||
{{ detailData.baseLogAggregation==='1'?'是':'否' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="实际成效指标" :span="2"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="detailData.baseBusinessMetrics&&JSON.parse(detailData.baseBusinessMetrics)||[]" | |||
:empty-temp="false" | |||
/> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="(['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)&&basicInfoData?.baseConstructionType?.includes('01'))||!basicInfoData?.baseConstructionType?.includes('01')" label="信息安全等级保护测评报告" :span="2"> | |||
<template v-if="detailData?.baseInforLevelFile&&JSON.parse(detailData?.baseInforLevelFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseInforLevelFile&&JSON.parse(detailData?.baseInforLevelFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" label="商业密码应用评估报告" :span="2"> | |||
<template v-if="detailData?.basePasswAssessFile&&JSON.parse(detailData?.basePasswAssessFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.basePasswAssessFile&&JSON.parse(detailData?.basePasswAssessFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="第三方验收测试报告" :span="2"> | |||
<template v-if="detailData?.baseThirdAcceptFile&&JSON.parse(detailData?.baseThirdAcceptFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseThirdAcceptFile&&JSON.parse(detailData?.baseThirdAcceptFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03','04'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" label="用户使用报告" :span="2"> | |||
<template v-if="detailData?.baseUserConsFile&&JSON.parse(detailData?.baseUserConsFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseUserConsFile&&JSON.parse(detailData?.baseUserConsFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="监理总结报告" :span="2"> | |||
<template v-if="detailData?.baseEstaSummFile&&JSON.parse(detailData?.baseEstaSummFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseEstaSummFile&&JSON.parse(detailData?.baseEstaSummFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03','04'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" label="运维总结报告" :span="2"> | |||
<template v-if="detailData?.baseOperatMaintenSummFile&&JSON.parse(detailData?.baseOperatMaintenSummFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseOperatMaintenSummFile&&JSON.parse(detailData?.baseOperatMaintenSummFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjSetProg==='07'" label="终验意见" :span="2"> | |||
<template v-if="detailData?.baseFinalExpertOpinionFile&&JSON.parse(detailData?.baseFinalExpertOpinionFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseFinalExpertOpinionFile&&JSON.parse(detailData?.baseFinalExpertOpinionFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目延期申请表" :span="2"> | |||
<template v-if="detailData?.baseEngineerPostpoFile&&JSON.parse(detailData?.baseEngineerPostpoFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseEngineerPostpoFile&&JSON.parse(detailData?.baseEngineerPostpoFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="变更报告" :span="2"> | |||
<template v-if="detailData?.baseEngineerAlterFile&&JSON.parse(detailData?.baseEngineerAlterFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseEngineerAlterFile&&JSON.parse(detailData?.baseEngineerAlterFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="变更批复文件" :span="2"> | |||
<template v-if="detailData?.baseChanFile&&JSON.parse(detailData?.baseChanFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseChanFile&&JSON.parse(detailData?.baseChanFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,77 @@ | |||
<script setup name="projectApprovalInfo"> | |||
import Accessory from '@/components/accessory/index.vue' | |||
defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
dictionaryList: Array | |||
}) | |||
</script> | |||
<template> | |||
<el-descriptions :column="2" border> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjSetProg!=='01'" label="评审结果"> | |||
{{ dictionaryList?.filter(i => i.type === 'REVIEW_RESULTS').find(i=>i.value===detailData?.baseReviewResults)?.label ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjIsConfidentiality === '01'&&!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" label="等保定级"> | |||
{{ dictionaryList?.filter(i => i.type === 'EQUAL_PROTECTION_RATING').find(i=>i.value===detailData?.equalProtectionLevel)?.label ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjSetProg!=='01'" label="评审意见" :span="2"> | |||
{{ detailData?.baseReviewOpinion||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="basicInfoData?.baseProjSetProg!=='01'" label="评审意见附件" :span="2"> | |||
<template v-if="detailData?.baseReviewCommentsFile&&JSON.parse(detailData?.baseReviewCommentsFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.baseReviewCommentsFile&&JSON.parse(detailData?.baseReviewCommentsFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" label="立项批复文件" :span="2"> | |||
<template v-if="detailData?.approvalFile&&JSON.parse(detailData?.approvalFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.approvalFile&&JSON.parse(detailData?.approvalFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','03'].includes(basicInfoData?.baseProjSetProg)" label="建议总投资"> | |||
{{ detailData?.baseExpertTotalMoney||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','03'].includes(basicInfoData?.baseProjSetProg)" label="建议年度预算"> | |||
{{ detailData?.baseExpertYearMoney||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" label="建议批复总投资"> | |||
{{ detailData?.baseInitialReviewTotalMoney||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" label="建议批复年度预算"> | |||
{{ detailData?.baseProjReplyAmount||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)" label="年度预算下达金额"> | |||
{{ detailData?.releaseYearMoney||'-' }} | |||
</el-descriptions-item> | |||
<template v-if="detailData?.baseProjReplyAmount>=5000&&['04','05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-descriptions-item label="初步设计方案" :span="2"> | |||
<template v-if="detailData?.preliminaryDesignScheme&&JSON.parse(detailData?.preliminaryDesignScheme)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.preliminaryDesignScheme&&JSON.parse(detailData?.preliminaryDesignScheme)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="初步设计方案批复函" :span="2"> | |||
<template v-if="detailData?.preliminaryDesignFile&&JSON.parse(detailData?.preliminaryDesignFile)?.length"> | |||
<p v-for="(file,fileIndex) in detailData?.preliminaryDesignFile&&JSON.parse(detailData?.preliminaryDesignFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</template> | |||
<span v-else>-</span> | |||
</el-descriptions-item> | |||
</template> | |||
</el-descriptions> | |||
</template> |
@@ -0,0 +1,94 @@ | |||
<script setup name="basicInfo"> | |||
import Accessory from '@/components/accessory/index.vue' | |||
import NoData from '@/components/noData/index.vue' | |||
defineProps({ | |||
detailData: { | |||
type: Array, | |||
default: () => [] | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
baseProjSetYear: { | |||
type: String, | |||
default: '' | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<template v-if="detailData?.length"> | |||
<el-descriptions | |||
v-for="(item,index) in detailData" | |||
:key="index" | |||
:column="2" | |||
border | |||
class="mb-16" | |||
> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-descriptions-item label="标段名称"> | |||
{{ item?.baseBidName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="采购方式"> | |||
{{ dictionaryList?.filter(i => i.type === 'PURCHASE_METHOD').find(i=>i.value===item?.baseProjPurchaseWay)?.label ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="预算执行确认书编号"> | |||
{{ item?.basePurchaseCode ||'-' }} | |||
</el-descriptions-item> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<el-descriptions-item label="采购代理机构"> | |||
{{ item?.basePurchasingAgencies ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="采购代理机构统一社会信用代码"> | |||
{{ item?.baseUnifiedCreditCode ||'-' }} | |||
</el-descriptions-item> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-descriptions-item label="中标(成交)时间"> | |||
{{ item?.baseWinningBidTime ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="中标(成交)金额"> | |||
{{ item?.baseProjPurchaseAmount ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="中标(成交)供应商名称"> | |||
{{ item?.baseConsDeprt ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="中标(成交)供应商统一社会信用代码"> | |||
{{ item?.baseConsDeprtUsci ||'-' }} | |||
</el-descriptions-item> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<el-descriptions-item label="项目款支付时间"> | |||
{{ item?.basePaymentTime ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="项目款支付金额"> | |||
{{ item?.paymentProgress ||'-' }}万元 | |||
</el-descriptions-item> | |||
</template> | |||
<template v-if="['05','06','07','00']?.includes(basicInfoData?.baseProjSetProg)"> | |||
<el-descriptions-item label="招标(采购)文件"> | |||
<p v-for="(file,fileIndex) in item?.purchaseFile&&JSON.parse(item?.purchaseFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="中标(成交)通知"> | |||
<p v-for="(file,fileIndex) in item?.biddingFile&&JSON.parse(item?.biddingFile)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="采购合同"> | |||
<p v-for="(file,fileIndex) in item?.purchaseContract&&JSON.parse(item?.purchaseContract)" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.originalFileName" :file-id="file.id" /> | |||
</p> | |||
</el-descriptions-item> | |||
</template> | |||
</el-descriptions> | |||
</template> | |||
<no-data v-else /> | |||
</template> |
@@ -0,0 +1,142 @@ | |||
<script setup name="projectCollectionEnterDetail"> | |||
import { onMounted, ref } from 'vue' | |||
import { useRoute } from 'vue-router' | |||
import BasicInfo from './components/basicInfo.vue' | |||
import { dictionary } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
import { detail } from '@/http/apis/declareMange/operationProjectRecord' | |||
import ApplyInfo from './components/applyInfo.vue' | |||
import ApplicationInfo from './components/applicationInfo.vue' | |||
import CoreBusiness from './components/coreBusiness.vue' | |||
import ProjectApprovalInfo from './components/projectApprovalInfo.vue' | |||
import EmpMaterials from './components/empMaterials.vue' | |||
import PurchaseInfo from './components/purchaseInfo.vue' | |||
import store from '@/store' | |||
import { templateTypeList } from '@/http/apis/performanceEvaluation/indicatorTemplate' | |||
const { statusGjOptions } = store.dictStore.globalDicts || {} | |||
const | |||
tabList = ref(['项目基本信息', '项目申报信息', '项目关联信息', '核心业务', '项目立项评审信息', '项目采购、资金支付信息', '实施材料信息']), | |||
activeName = ref('项目基本信息'), | |||
changeTab = (val) => { | |||
activeName.value = val | |||
}, | |||
route = useRoute(), | |||
detailData = ref(), | |||
getDetail = async () => { | |||
const id = route.query.type === '1' ? route.query.id : route.query.draftId | |||
const res = await detail(route.query.type, id) | |||
detailData.value = { | |||
...res.data, | |||
apply: { | |||
...res.data.apply, | |||
baseHistorProjs: res.data.apply?.baseHistorProjId?.split(';').map((i, k) => { | |||
return { | |||
baseProjId: i, | |||
baseProjName: res.data.apply?.baseHistorProjName.split(';')[k], | |||
baseProjSetYear: res.data.apply?.baseHistorProjYear.split(';')[k] | |||
} | |||
}) || [] | |||
} | |||
} | |||
if ((detailData.value?.baseinfo?.baseConstructionType?.split(';')?.length === 1 && detailData.value?.baseinfo?.baseConstructionType?.split(';').includes('02'))) { | |||
tabList.value = tabList.value.filter(i => i !== '项目关联信息') | |||
} | |||
if (detailData.value?.baseinfo?.baseProjSetProg === '01') { | |||
tabList.value = tabList.value.filter(i => i !== '项目立项评审信息') | |||
} | |||
}, | |||
dictionaryList = ref([]), | |||
templateTypeListData = ref(), | |||
getTemplateTypeList = async () => { | |||
const res = await templateTypeList() | |||
templateTypeListData.value = res.data | |||
} | |||
onMounted(async () => { | |||
getTemplateTypeList() | |||
dictionaryList.value = (await dictionary()).data | |||
getDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class="px-20 pt-10 pb-20 overflow-auto"> | |||
<el-card shadow="never" class="mb-16"> | |||
<div class="card-header"> | |||
<div class="flex justify-between items-center"> | |||
<div class="flex-1"> | |||
<p class="font-bold">{{ detailData?.baseinfo?.baseProjName }}</p> | |||
<div class="mt-8 search"> | |||
<el-form label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<el-form-item label="建设单位">{{ detailData?.baseinfo?.baseBuildDeprt||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="主管单位">{{ detailData?.baseinfo?.baseManDeprt||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="创建时间">{{ detailData?.baseinfo?.createOn||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="更新时间">{{ detailData?.baseinfo?.updateOn||'-' }}</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
</div> | |||
<div class="textRight"> | |||
<span :class="`text-${statusGjOptions[detailData?.baseinfo?.baseProjSetProg.slice(-1)]?.color}`"> | |||
{{ dictionaryList?.filter(i => i.type === 'PROJECT_STATUS').find(i=>i.value===detailData?.baseinfo?.baseProjSetProg)?.label ||'-' }} | |||
</span> | |||
<p>状态</p> | |||
</div> | |||
</div> | |||
</div> | |||
</el-card> | |||
<el-card shadow="never" class="tab-card"> | |||
<template #header> | |||
<el-tabs v-model="activeName" @tab-change="changeTab"> | |||
<el-tab-pane | |||
v-for="(item,index) in tabList" | |||
:key="index" | |||
:label="item" | |||
:name="item" | |||
/> | |||
</el-tabs> | |||
</template> | |||
<basic-info | |||
v-if="activeName==='项目基本信息'" | |||
:detail-data="detailData?.baseinfo" | |||
:dictionary-list="dictionaryList" | |||
:template-type-list-data="templateTypeListData" | |||
/> | |||
<apply-info | |||
v-if="activeName==='项目申报信息'" | |||
:detail-data="detailData?.apply" | |||
:dictionary-list="dictionaryList" | |||
:basic-info-data="detailData?.baseinfo" | |||
/> | |||
<application-info v-if="activeName==='项目关联信息'" :detail-data="detailData?.apply" /> | |||
<core-business v-if="activeName==='核心业务'" :detail-data="detailData?.apply" /> | |||
<project-approval-info | |||
v-if="activeName==='项目立项评审信息'" | |||
:detail-data="detailData?.approve" | |||
:dictionary-list="dictionaryList" | |||
:basic-info-data="detailData?.baseinfo" | |||
/> | |||
<purchase-info | |||
v-if="activeName==='项目采购、资金支付信息'" | |||
:basic-info-data="detailData?.baseinfo" | |||
:base-proj-set-year="detailData?.apply?.baseProjSetYear" | |||
:dictionary-list="dictionaryList" | |||
:detail-data="detailData?.procures" | |||
/> | |||
<emp-materials | |||
v-if="activeName==='实施材料信息'" | |||
:detail-data="detailData?.mimplement" | |||
:basic-info-data="detailData?.baseinfo" | |||
:base-proj-set-year="detailData?.apply?.baseProjSetYear" | |||
:approval-info-data="detailData?.approve" | |||
/> | |||
</el-card> | |||
</div> | |||
</template> |
@@ -0,0 +1,201 @@ | |||
<script setup name="operationProjectRecord"> | |||
import { getCurrentInstance, onMounted, reactive, ref } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import ElTree from '@/components/elTree/index.vue' | |||
import { list, del } from '@/http/apis/declareMange/operationProjectRecord' | |||
import { getIsShowRegionTree, getTreeParams } from '@/utils/getIsShowRegionTree' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const | |||
userInfo = storeToRefs(store.userStore).userInfo, | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
searchForm = reactive({ | |||
projectName: undefined, | |||
buildOrg: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '项目编号', | |||
key: 'baseProjId', | |||
prop: 'baseProjId' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'baseProjName', | |||
prop: 'baseProjName' | |||
}, | |||
{ | |||
label: '建设单位', | |||
key: 'baseBuildDeprt', | |||
prop: 'baseBuildDeprt' | |||
}, | |||
{ | |||
label: '行政区划', | |||
key: 'baseAreaName', | |||
prop: 'baseAreaName' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'baseProjDeclAmount', | |||
prop: 'baseProjDeclAmount', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '160', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
areaCode = ref(), | |||
getTree = (value) => { | |||
areaCode.value = value.regionLevel === 3 ? value.regionCode : undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
activeName = ref('1'), | |||
changeTab = (val) => { | |||
activeName.value = val | |||
reset() | |||
}, | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list(activeName.value, { | |||
...pageParams, | |||
...searchForm, | |||
regionCode: areaCode.value | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.projectName = undefined | |||
searchForm.buildOrg = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 删除· | |||
deleteItem = (data) => { | |||
proxy.$messageBox | |||
.confirm('确定要删除该项吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await del(activeName.value, activeName.value === '1' ? data.baseProjId : data.draftId) | |||
proxy.$message.success('删除成功!') | |||
await getTableData() | |||
}) | |||
} | |||
onMounted(() => { | |||
if (!getIsShowRegionTree(['SUPER_ADMIN', 'REGION_MANAGER'])) { | |||
areaCode.value = userInfo.value.regionCode | |||
getTableData(tableListRef.value.pageParams) | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-container class="overflow-y-auto"> | |||
<div class="px-20 pt-10 pb-20 w-full"> | |||
<el-row> | |||
<el-col | |||
v-if="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER'])" | |||
:span="4" | |||
class="pr-16" | |||
> | |||
<elTree :params="getTreeParams({'SUPER_ADMIN':false,'REGION_MANAGER':false})" @get-tree="getTree" /> | |||
</el-col> | |||
<el-col :span="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER'])?20:24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目单位"> | |||
<el-input | |||
v-model="searchForm.buildOrg" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8 tab-card"> | |||
<template #header> | |||
<div class="flex justify-between items-center"> | |||
<el-tabs v-model="activeName" @tab-change="changeTab"> | |||
<el-tab-pane label="项目列表" name="1" /> | |||
<el-tab-pane label="草稿箱" name="2" /> | |||
</el-tabs> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
icon="Plus" | |||
@click="router.push({ name: 'operationProjectEdit'})" | |||
>录入项目</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="$router.push({name:'operationProjectRecordDetail', query: { id: scope.row.baseProjId,draftId: scope.row.draftId,type:activeName }})">查看</a> | |||
<a @click="$router.push({ name: 'operationProjectEdit', query: { id: scope.row.baseProjId, draftId: scope.row.draftId, type: activeName }})">编辑</a> | |||
<a class="text-danger" @click="deleteItem(scope.row)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</el-container> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,261 @@ | |||
<script name="projectCollectionEnterBasicInfo" setup> | |||
import { onMounted, ref, watch } from 'vue' | |||
import { applicationList } from '@/http/apis/declareMange' | |||
import store from '@/store' | |||
import { storeToRefs } from 'pinia' | |||
import { useRoute } from 'vue-router' | |||
const userInfo = storeToRefs(store.userStore).userInfo, | |||
route = useRoute(), | |||
props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
} | |||
}), | |||
{ | |||
accountAppNameOption, | |||
domainBrainAccountOptions | |||
} = store.dictStore.globalDicts || {}, | |||
formRef = ref(), | |||
currentRules = ref(), | |||
formData = ref({ | |||
applications: [] | |||
}), | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '关联IRS应用名称', | |||
slot: 'application', | |||
key: 'application' | |||
}, | |||
{ | |||
label: 'IRS应用编码', | |||
slot: 'applicationCode', | |||
key: 'applicationCode' | |||
}, | |||
{ | |||
label: '一本账重大应用名称', | |||
slot: 'baseAccountAppName', | |||
key: 'baseAccountAppName' | |||
}, | |||
{ | |||
label: '"领域大脑"一本账名称', | |||
slot: 'baseBrainName', | |||
key: 'baseBrainName' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
add = () => { | |||
formData.value.applications.push({ | |||
application: undefined | |||
}) | |||
}, | |||
del = (index) => { | |||
formData.value.applications.splice(index, 1) | |||
}, | |||
appList = ref([]) | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.basicInfoData, val => { | |||
if (val?.baseProjIsConfidentiality === '02' || val?.baseProjSetProg === '00') { | |||
currentRules.value = {} | |||
} else { | |||
currentRules.value = { | |||
applications: [{ required: true, message: '请至少关联一个应用' }] | |||
} | |||
} | |||
formRef.value?.clearValidate() | |||
}, { deep: true, immediate: true }) | |||
onMounted(async () => { | |||
if (!route.query.id) { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode }) | |||
appList.value = res.data | |||
} | |||
}) | |||
watch(() => props.detail, async val => { | |||
if (val) { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode }) | |||
appList.value = res.data | |||
formData.value = { | |||
applications: val.apply.baseProjSysCode?.split(';')?.map((i, k) => { | |||
return { | |||
application: appList.value?.find(j => j.applicationCode === i) || { applicationCode: i, applicationName: val.apply?.baseProjSys?.split(';')[k] || '' }, | |||
baseAccountAppName: val.apply?.baseAccountAppName?.split(';')[k] || '', | |||
baseBrainName: val.apply?.baseBrainName?.split(';')[k] || '' | |||
} | |||
}) || [] | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
:validate-on-rule-change="false" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseConstructionType?.includes('01')&&!(basicInfoData?.baseProjType==='01'&&(basicInfoData?.baseProjSetProg==='01'||basicInfoData?.baseProjSetProg==='02'))" | |||
key="applications1" | |||
label="关联IRS应用名称" | |||
prop="applications" | |||
> | |||
<p class="text-right w-full mb-8"> | |||
<el-button type="primary" @click="add">添加关联应用</el-button> | |||
</p> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="formData.applications" | |||
:empty-temp="false" | |||
> | |||
<template #application="{scope}"> | |||
<el-form-item v-if="scope.$index>=0" :prop="`applications[${scope.$index}].application`" :rules="[{required:true,message:' '}]"> | |||
<el-select | |||
v-model="formData.applications[scope.$index].application" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="applicationCode" | |||
filterable | |||
> | |||
<el-option | |||
v-for="(item, index) in appList" | |||
:key="index" | |||
:label="item.applicationName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #applicationCode="{scope}"> | |||
<el-form-item> | |||
<el-input disabled :model-value="scope.row.application?.applicationCode" /> | |||
</el-form-item> | |||
</template> | |||
<template #baseAccountAppName="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`applications[${scope.$index}].baseAccountAppName`" | |||
> | |||
<el-select v-model="scope.row.baseAccountAppName"> | |||
<el-option | |||
v-for="(item,index) in accountAppNameOption" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #baseBrainName="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`applications[${scope.$index}].baseBrainName`" | |||
> | |||
<el-select v-model="scope.row.baseBrainName"> | |||
<el-option | |||
v-for="(item,index) in domainBrainAccountOptions" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #action="{scope}"> | |||
<a class="text-danger" @click="del(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-form-item> | |||
<el-form-item v-else key="applications2" label="关联IRS应用名称"> | |||
<p class="text-right w-full mb-8"> | |||
<el-button type="primary" @click="add">添加关联应用</el-button> | |||
</p> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="formData.applications" | |||
:empty-temp="false" | |||
> | |||
<template #application="{scope}"> | |||
<el-form-item v-if="scope.$index>=0" :prop="`applications[${scope.$index}].application`" :rules="[{required:true,message:' '}]"> | |||
<el-select | |||
v-model="formData.applications[scope.$index].application" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="applicationCode" | |||
filterable | |||
> | |||
<el-option | |||
v-for="(item, index) in appList" | |||
:key="index" | |||
:label="item.applicationName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #applicationCode="{scope}"> | |||
<el-form-item> | |||
<el-input disabled :model-value="scope.row.application?.applicationCode" /> | |||
</el-form-item> | |||
</template> | |||
<template #baseAccountAppName="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`applications[${scope.$index}].baseAccountAppName`" | |||
> | |||
<el-select v-model="scope.row.baseAccountAppName"> | |||
<el-option | |||
v-for="(item,index) in accountAppNameOption" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #baseBrainName="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`applications[${scope.$index}].baseBrainName`" | |||
> | |||
<el-select v-model="scope.row.baseBrainName"> | |||
<el-option | |||
v-for="(item,index) in domainBrainAccountOptions" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #action="{scope}"> | |||
<a class="text-danger" @click="del(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> |
@@ -0,0 +1,425 @@ | |||
<script name="projectCollectionEnterBasicInfo" setup> | |||
import { computed, onMounted, reactive, ref, watch } from 'vue' | |||
import { districtList, getOrganizationByCode } from '@/http/apis/commonApi' | |||
import OrgTree from '@/components/orgTree/index.vue' | |||
import UserDialog from '@/pages/projectCollection/projectCollectionEnter/components/userDialog.vue' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
import LineOrgDialog from '@/pages/projectCollection/projectCollectionEnter/components/lineOrgDialog.vue' | |||
import { templateTypePage } from '@/http/apis/performanceEvaluation/indicatorTemplate' | |||
const { projectOpeOptions } = | |||
store.dictStore.globalDicts || {} | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}), | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
formRef = ref(), | |||
formData = ref({ | |||
baseProjIsConfidentiality: '01', | |||
// baseProjSetProg: '07', | |||
push: true | |||
// baseProjType: '04' | |||
}), | |||
userValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (formData.value.baseProjPrincipal === formData.value.baseProjContacts && formData.value.baseProjPrincipalCall === formData.value.baseProjContactsCall) { | |||
callback('项目负责人与项目联系人不能相同') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
currentRules = computed(() => { | |||
if (formData.value.baseProjIsConfidentiality === '02') { | |||
return { | |||
baseProjIsConfidentiality: [{ required: true, message: '请选择是否涉密项目' }], | |||
baseProjName: [{ required: true, message: '请填写项目名称', trigger: 'blur' }] | |||
} | |||
} else { | |||
return { | |||
push: [{ required: true, message: '请选择是否归集省里', type: Boolean }], | |||
baseProjIsConfidentiality: [{ required: true, message: '请选择是否涉密项目' }], | |||
baseProjName: [{ required: true, message: '请填写项目名称' }], | |||
baseProjType: [{ required: true, message: '请选择项目类型' }], | |||
baseArea: [{ required: true, message: '请选择所属区划' }], | |||
baseConstructionType: [{ required: true, message: '请选择内容类别' }], | |||
baseProjSetProg: [{ required: true, message: '请选择项目状态' }], | |||
baseProvManDeprtType: [{ required: true, message: '请选择上级主管单位类型' }], | |||
baseProvManDeprt: [{ required: true, message: '请选择上级主管单位' }], | |||
baseManDeprt: [{ required: true, message: '请选择本级主管单位' }], | |||
baseManDepartUsci: [{ required: true, message: '请填写本级主管单位统一社会信用代码' }], | |||
baseBuildDeprt: [{ required: true, message: '请填写建设单位' }], | |||
baseBuildDepartUsci: [{ required: true, message: '请填写建设单位统一信用代码' }], | |||
baseProjPrincipal: [{ required: true, message: '请选择项目负责人' }, { validator: userValidator }], | |||
baseProjPrincipalCall: [{ required: true, message: '请选择项目负责人' }], | |||
baseProjContacts: [{ required: true, message: '请选择项目联系人' }, { validator: userValidator }], | |||
baseProjContactsCall: [{ required: true, message: '请选择联系人手机号码' }], | |||
systemPosition: [{ required: true, message: '请填写系统定位' }], | |||
templateType: [{ required: true, message: '请选择绩效评价类型' }] | |||
} | |||
} | |||
}), | |||
isDisabledCreditCode = ref({}), | |||
getCode = async (name, code) => { | |||
const res = await getOrganizationByCode(code || userInfo.value.empPosUnitCode) | |||
isDisabledCreditCode.value[name] = !!res.data.unifiedSocialCreditCode | |||
formData.value[name] = res.data.unifiedSocialCreditCode || formData.value[name] | |||
}, | |||
regionTree = ref([]), | |||
// 单位选择 | |||
orgProps = reactive({ | |||
field: undefined, | |||
unitVisible: false, | |||
data: undefined, | |||
title: undefined, | |||
type: undefined, | |||
params: undefined | |||
}), | |||
showOrgTree = (fieldName) => { | |||
orgProps.fieldName = fieldName | |||
orgProps.unitVisible = true | |||
orgProps.title = '选择单位' | |||
orgProps.type = 'UNIT' | |||
orgProps.showCheckbox = true | |||
orgProps.defaultProps = { | |||
children: 'children', | |||
label: 'title', | |||
value: 'key', | |||
isLeaf: 'isLeaf' | |||
} | |||
orgProps.params = { | |||
onlyUnit: true | |||
} | |||
orgProps.data = formData.value[`${fieldName}Ding`] ? [{ | |||
key: formData.value[`${fieldName}Ding`], | |||
title: formData.value[fieldName] | |||
}] : [] | |||
console.log(orgProps.data) | |||
}, | |||
closeOrg = () => { | |||
orgProps.unitVisible = false | |||
}, | |||
getOrgData = (data) => { | |||
formData.value[orgProps.fieldName + 'Ding'] = data?.[0].key || undefined | |||
formData.value[orgProps.fieldName] = data?.[0].title || undefined | |||
if (orgProps.fieldName === 'baseManDeprt' || orgProps.fieldName === 'baseBuildDeprt') { getCode(orgProps.fieldName === 'baseManDeprt' ? 'baseManDepartUsci' : 'baseBuildDepartUsci', formData.value[orgProps.fieldName + 'Ding']) } | |||
}, | |||
// 选择负责人、联系人 | |||
userDialogData = reactive({ | |||
visible: false, | |||
params: {} | |||
}), | |||
filedName = ref(), | |||
filedPhone = ref(), | |||
showUserDialog = (name, phone) => { | |||
userDialogData.visible = true | |||
filedName.value = name | |||
filedPhone.value = phone | |||
}, | |||
getUserData = (data) => { | |||
formData.value[filedName.value] = data.name | |||
formData.value[filedPhone.value] = data.phoneNo | |||
}, | |||
// 上级主管单位类型 | |||
changeBaseProvManDeprtType = (val, data) => { | |||
formData.value.baseProvManDeprtDing = '' | |||
formData.value.baseProvManDeprt = '' | |||
}, | |||
lineOrgDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
showLineDialog = () => { | |||
lineOrgDialogData.visible = true | |||
lineOrgDialogData.data = { | |||
businessStripCode: formData.value.baseProvManDeprtDing | |||
} | |||
}, | |||
getBaseProvManDeprt = (data) => { | |||
formData.value.baseProvManDeprtDing = data.businessStripCode | |||
formData.value.baseProvManDeprt = data.businessStripName | |||
lineOrgDialogData.visible = false | |||
}, | |||
emits = defineEmits(['getBasicInfoData']), | |||
templateTypeListData = ref(), | |||
getTemplateTypeList = async () => { | |||
const res = await templateTypePage({ | |||
pageNumber: 1, | |||
pageSize: 10000 | |||
}) | |||
templateTypeListData.value = res?.data?.records || [] | |||
} | |||
defineExpose({ formRef, formData }) | |||
onMounted(async () => { | |||
getTemplateTypeList() | |||
const res = await districtList({ regionCode: 330500, regionLevel: 2 }) | |||
regionTree.value = res.data | |||
}) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
...val.baseinfo, | |||
baseProjIsConfidentiality: '01', | |||
// baseProjSetProg: '07', | |||
baseProvManDeprtType: val.baseinfo?.baseProvManDeprtType + '' || '', | |||
baseConstructionType: val.baseinfo?.baseConstructionType?.split(';') || [] | |||
} | |||
} | |||
}) | |||
watch(() => formData.value.baseProjIsConfidentiality, val => { | |||
formRef.value.clearValidate() | |||
}) | |||
watch(() => formData.value, val => { | |||
emits('getBasicInfoData', formData.value) | |||
}, { deep: true }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
:validate-on-rule-change="false" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item prop="push" label="项目是否归集省里" class="flex-form-item"> | |||
<el-switch v-model="formData['push']" class="mr-8" /> | |||
<el-tooltip | |||
class="box-item" | |||
content="选择是的情况下,会将项目信息推送至省里进行归集;选择否的情况下,不会将项目信息推至省里。" | |||
placement="top" | |||
> | |||
<div class="flex items-center"> | |||
<el-icon class="cursor-pointer"><QuestionFilled /></el-icon> | |||
</div> | |||
</el-tooltip> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="8"> | |||
<el-form-item label="是否涉密项目" prop="baseProjIsConfidentiality"> | |||
<el-select | |||
v-model="formData.baseProjIsConfidentiality" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'CLASSIFIED')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称" prop="baseProjName"> | |||
<el-input v-model="formData.baseProjName" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型" prop="baseProjType"> | |||
<el-select | |||
v-model="formData.baseProjType" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectOpeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="8"> | |||
<el-form-item label="所属区划" prop="baseArea"> | |||
<el-select v-model="formData.baseArea" value-key="baseAreaCode" class="w-full"> | |||
<el-option | |||
v-for="(item,index) in regionTree?.children" | |||
:key="index" | |||
:label="item.name==='市本级'?'丽水市':item.name" | |||
:value="{baseAreaCode:item.regionCode,baseAreaName:item.name==='市本级'?'丽水市':item.name}" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="内容类别" prop="baseConstructionType"> | |||
<el-checkbox-group v-model="formData.baseConstructionType"> | |||
<el-checkbox v-for="(item,index) in dictionaryList?.filter(i => i.type === 'CONTENT_TYPE')" :key="index" :label="item.value">{{ item.label }}</el-checkbox> | |||
</el-checkbox-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目状态" prop="baseProjSetProg"> | |||
<el-select | |||
v-model="formData.baseProjSetProg" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'PROJECT_STATUS')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="上级主管单位类型" prop="baseProvManDeprtType"> | |||
<el-radio-group v-model="formData.baseProvManDeprtType" @change="changeBaseProvManDeprtType"> | |||
<el-radio label="1">省级</el-radio> | |||
<el-radio label="2">非省级</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="上级主管单位" prop="baseProvManDeprt"> | |||
<el-input | |||
v-if="formData.baseProvManDeprtType==='2'" | |||
v-model="formData.baseProvManDeprt" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('baseProvManDeprt')" | |||
/> | |||
<el-input | |||
v-else | |||
v-model="formData.baseProvManDeprt" | |||
placeholder="请选择" | |||
readonly | |||
@click="showLineDialog" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="本级主管单位" prop="baseManDeprt"> | |||
<el-input | |||
v-model="formData.baseManDeprt" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('baseManDeprt',)" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="本级主管单位统一社会信用代码" prop="baseManDepartUsci"> | |||
<el-input v-model="formData.baseManDepartUsci" placeholder="请填写" :disabled="isDisabledCreditCode['baseManDepartUsci']" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设单位" prop="baseBuildDeprt"> | |||
<el-input | |||
v-model="formData.baseBuildDeprt" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('baseBuildDeprt',)" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设单位统一信用代码" prop="baseBuildDepartUsci"> | |||
<el-input v-model="formData.baseBuildDepartUsci" placeholder="请填写" :disabled="isDisabledCreditCode['baseBuildDepartUsci']" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目负责人" prop="baseProjPrincipal"> | |||
<el-input | |||
v-model="formData.baseProjPrincipal" | |||
readonly | |||
placeholder="请选择,温馨提示:项目负责人请填写领导信息" | |||
@click="showUserDialog('baseProjPrincipal','baseProjPrincipalCall')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="负责人手机号码" prop="baseProjPrincipalCall"> | |||
<el-input | |||
v-model="formData.baseProjPrincipalCall" | |||
readonly | |||
placeholder="请选择" | |||
@click="showUserDialog('baseProjPrincipal','baseProjPrincipalCall')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目联系人" prop="baseProjContacts"> | |||
<el-input | |||
v-model="formData.baseProjContacts" | |||
readonly | |||
placeholder="请选择" | |||
@click="showUserDialog('baseProjContacts','baseProjContactsCall')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="联系人手机号码" prop="baseProjContactsCall"> | |||
<el-input | |||
v-model="formData.baseProjContactsCall" | |||
readonly | |||
placeholder="请选择" | |||
@click="showUserDialog('baseProjContacts','baseProjContactsCall')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="系统定位" prop="systemPosition"> | |||
<el-input | |||
v-model="formData.systemPosition" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="2000" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="绩效评价类型" prop="templateType"> | |||
<el-radio-group v-model="formData.templateType"> | |||
<el-radio | |||
v-for="(v,k) in templateTypeListData" | |||
:key="k" | |||
:label="v.id" | |||
> | |||
{{ v.name }} | |||
</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<org-tree | |||
:visible="orgProps.unitVisible" | |||
:show-checkbox="false" | |||
:default-data="orgProps.data" | |||
:title="orgProps.title" | |||
:type="orgProps.type" | |||
:default-props="orgProps.defaultProps" | |||
:params="orgProps.params" | |||
@close="closeOrg" | |||
@get-select-unit="getOrgData" | |||
/> | |||
<user-dialog | |||
:visible="userDialogData.visible" | |||
:params="userDialogData.params" | |||
@close="userDialogData.visible=false" | |||
@get-user-data="getUserData" | |||
/> | |||
<line-org-dialog | |||
:visible="lineOrgDialogData.visible" | |||
:data="lineOrgDialogData.data" | |||
@close="lineOrgDialogData.visible=false" | |||
@get-base-prov-man-deprt="getBaseProvManDeprt" | |||
/> | |||
</template> |
@@ -0,0 +1,110 @@ | |||
<script name="projectCollectionEnterBudgetInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import store from '@/store' | |||
const { budgetSourceOptions } = store.dictStore.globalDicts || {} | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
} | |||
}), | |||
formRef = ref(), | |||
moneyValidator = (rule, value, callback) => { // 金额校验 | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
formData = ref({}), | |||
rules = { | |||
declareAmount: [{ required: true, message: '请填写申报金额', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
approvalAmount: [{ required: true, message: '请填写批复金额', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
budgetSource: [{ required: true, message: '请选择预算来源', trigger: 'change' }], | |||
projectYear: [{ required: true, message: '请选择预算年度', trigger: 'blur' }] | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
declareAmount: val.declareAmount, | |||
approvalAmount: val.approvalAmount, | |||
budgetSource: val.budgetSource, | |||
projectYear: `${val.projectYear}` | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="6"> | |||
<el-form-item label="申报金额" prop="declareAmount"> | |||
<el-input-number | |||
v-model="formData.declareAmount" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="批复金额" prop="approvalAmount"> | |||
<el-input-number | |||
v-model="formData.approvalAmount" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="预算来源" prop="budgetSource"> | |||
<el-select | |||
v-model="formData.budgetSource" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in budgetSourceOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k*1" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="预算年度" prop="projectYear"> | |||
<el-date-picker | |||
v-model="formData.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> |
@@ -0,0 +1,193 @@ | |||
<script name="coreBusiness" setup> | |||
import { reactive, ref, nextTick, watch } from 'vue' | |||
import { getCoreBusinessData } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
} | |||
}), | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
coreBusiness: [{ required: false, message: '请至少选择一个核心业务' }] | |||
}, | |||
// 选择核心业务 | |||
selectCoreBusiness = () => { | |||
coreBusinessvisible.value = true | |||
getCoreBusinessTableData({ pageNumber: 1, pageSize: 10 }, true) | |||
}, | |||
column = [ | |||
{ | |||
type: 'index', | |||
label: '序号', | |||
width: 60 | |||
}, | |||
// { | |||
// label: '业务编号', | |||
// key: 'oid', | |||
// prop: 'oid' | |||
// }, | |||
{ | |||
label: '业务名称', | |||
key: 'matterName', | |||
prop: 'matterName' | |||
}, | |||
{ | |||
label: '所属单位', | |||
key: 'orgName', | |||
prop: 'orgName' | |||
} | |||
], | |||
tableListRef = ref(), | |||
coreBusinessData = ref([]), | |||
coreBusinesstotal = ref(0), | |||
column2 = [ | |||
{ | |||
type: 'selection' | |||
}, | |||
// { | |||
// label: '业务编号', | |||
// prop: 'oid', | |||
// key: 'oid' | |||
// }, | |||
{ | |||
label: '业务名称', | |||
prop: 'matterName', | |||
key: 'matterName' | |||
}, | |||
{ | |||
label: '所属单位', | |||
prop: 'orgName', | |||
key: 'orgName' | |||
} | |||
], | |||
coreBusinessvisible = ref(false), | |||
getCoreBusinessTableData = async (pageParams = tableListRef.value?.pageParams, flag) => { | |||
var orgCode = [] | |||
props?.basicInfoData?.baseManDeprtDing && orgCode.push(props.basicInfoData.baseManDeprtDing) | |||
props?.basicInfoData?.baseBuildDeprtDing && orgCode.push(props.basicInfoData.baseBuildDeprtDing) | |||
const res = await getCoreBusinessData({ | |||
...pageParams, | |||
businessName: coreBusinessParams.businessName, | |||
orgCode: orgCode.join(',') | |||
}) | |||
coreBusinessData.value = res.data.data | |||
coreBusinesstotal.value = res.data.total | |||
await nextTick() | |||
if (flag) { | |||
coreBusinessData.value && coreBusinessData.value.forEach(item => { | |||
const dataIds = formData.value.coreBusiness && formData.value.coreBusiness.map(i => i.id * 1) || [] | |||
if (dataIds.includes(item.id)) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} else { | |||
tableListRef.value.toggleRowSelect(item, false) | |||
} | |||
}) | |||
} | |||
}, | |||
searchCoreBussiness = () => { | |||
getCoreBusinessTableData() | |||
}, | |||
coreBusinessTempotary = ref(), | |||
selectionCoreBusinessChange = (data) => { | |||
coreBusinessTempotary.value = data | |||
}, | |||
coreBusinessParams = reactive({ | |||
businessName: undefined | |||
}), | |||
handleReset = () => { | |||
coreBusinessParams.businessName = '' | |||
}, | |||
confirmCoreBusiness = () => { | |||
formData.value.coreBusiness = coreBusinessTempotary.value | |||
coreBusinessvisible.value = false | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
coreBusiness: val.apply?.baseCoreBusinessCode?.split(';')?.map((i, k) => { | |||
return { | |||
id: i, | |||
matterName: val.apply?.baseCoreBusiness?.split(';')[k], | |||
orgName: userInfo.value.empPosUnitName | |||
} | |||
}) || [] | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="0" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24" class="mb-16"> | |||
<el-button type="primary" class="float-right" @click="selectCoreBusiness"> | |||
选择核心业务 | |||
</el-button> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="formData.coreBusiness" | |||
:empty-temp="false" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<el-dialog | |||
title="选择核心业务" | |||
:close-on-click-modal="false" | |||
:before-close="()=>coreBusinessvisible=false" | |||
:model-value="coreBusinessvisible" | |||
width="700px" | |||
> | |||
<el-row style="margin-bottom: 16px" :gutter="20"> | |||
<el-col :span="12"> | |||
<el-input v-model="coreBusinessParams.businessName" placeholder="请输入" /> | |||
</el-col> | |||
<el-col :span="12"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="searchCoreBussiness">查询</el-button> | |||
<el-button @click="handleReset">重置</el-button> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column2" | |||
:data="coreBusinessData" | |||
:total="coreBusinesstotal" | |||
@selection-change="selectionCoreBusinessChange" | |||
@get-table-data="getCoreBusinessTableData" | |||
/> | |||
<template #footer> | |||
<el-button type="primary" @click="confirmCoreBusiness"> 提交 </el-button> | |||
<el-button @click="coreBusinessvisible = false"> 关闭 </el-button> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,559 @@ | |||
<script name="empMaterials" setup> | |||
import { reactive, ref, watch } from 'vue' | |||
import { fileFormatVerification, handleFileError, handleFileSuccess, handleFilePreview, reviewFileParam, fileTypes, fileDesc } from '@/utils/uploadAction' | |||
import store from '@/store' | |||
import ActualPerformanceIndicatorsDialog | |||
from '@/pages/declareManage/initialInspectionRecord/uploadInitMaterials/components/actualPerformanceIndicatorsDialog.vue' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
data: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
approvalInfoData: { | |||
type: Object | |||
}, | |||
baseProjSetYear: { | |||
type: String, | |||
default: '' | |||
} | |||
}), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
formRef = ref(), | |||
formData = ref({ | |||
feasibilityStudyReport: [], | |||
approvedFile: [], | |||
purchaseFile: [], | |||
acceptanceLetter: [], | |||
purchaseContract: [], | |||
acceptanceReport: [], | |||
changeApprovalDoc: [], | |||
baseBusinessMetrics: [] | |||
}), | |||
fileRule = [{ required: true, message: '请选择文件' }], | |||
currentRules = ref({ | |||
baseInitialOpinionFile: fileRule, | |||
baseInforLevelFile: fileRule, | |||
basePasswAssessFile: fileRule, | |||
baseThirdAcceptFile: fileRule, | |||
baseCheckFile: fileRule, | |||
baseFinanlAuditFile: fileRule, | |||
baseUserConsFile: fileRule, | |||
baseEstaSummFile: fileRule, | |||
baseOperatMaintenSummFile: fileRule, | |||
baseFinalExpertOpinionFile: fileRule, | |||
baseEngineerPostpoFile: fileRule, | |||
baseEngineerAlterFile: fileRule, | |||
baseChanFile: fileRule, | |||
baseBusinessMetrics: [{ required: true, message: '请添加' }], | |||
baseLogAggregation: [{ required: true, message: '请选择' }] | |||
}), | |||
// 实际成效指标 | |||
column1 = [ | |||
{ | |||
label: '核心业务', | |||
prop: 'businessName', | |||
key: 'businessName' | |||
}, | |||
{ | |||
label: '实际成效指标', | |||
prop: 'name', | |||
key: 'name' | |||
}, | |||
{ | |||
label: '数值', | |||
prop: 'nums', | |||
key: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
prop: 'unit', | |||
key: 'unit' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
projectContentDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
projectContentIndex = ref(), | |||
showProjectContentDialog = (data, index) => { | |||
projectContentDialogData.data = data | |||
projectContentDialogData.visible = true | |||
projectContentIndex.value = index | |||
}, | |||
setContent = (data) => { | |||
if (projectContentIndex.value === undefined) { | |||
formData.value.baseBusinessMetrics = [...formData.value.baseBusinessMetrics, ...data] | |||
} else { | |||
formData.value.baseBusinessMetrics[projectContentIndex.value] = data[0] | |||
} | |||
}, | |||
delProjectContent = (index) => { | |||
formData.value.baseBusinessMetrics.splice(index, 1) | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.basicInfoData, val => { | |||
if (val.baseProjIsConfidentiality === '02' || val?.baseProjSetProg === '00') { | |||
currentRules.value = {} | |||
} else { | |||
currentRules.value = { | |||
baseInitialOpinionFile: fileRule, | |||
baseInforLevelFile: fileRule, | |||
basePasswAssessFile: fileRule, | |||
baseThirdAcceptFile: fileRule, | |||
baseCheckFile: fileRule, | |||
baseFinanlAuditFile: fileRule, | |||
baseUserConsFile: fileRule, | |||
baseEstaSummFile: fileRule, | |||
baseOperatMaintenSummFile: fileRule, | |||
baseFinalExpertOpinionFile: fileRule, | |||
baseEngineerPostpoFile: fileRule, | |||
baseEngineerAlterFile: fileRule, | |||
baseChanFile: fileRule, | |||
baseBusinessMetrics: [{ required: true, message: '请添加' }], | |||
baseLogAggregation: [{ required: true, message: '请选择' }] | |||
} | |||
} | |||
formRef.value.clearValidate() | |||
}, { deep: true }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
...val.mimplement, | |||
baseInitialOpinionFile: val.mimplement?.baseInitialOpinionFile ? reviewFileParam(JSON.parse(val.mimplement.baseInitialOpinionFile)) : [], | |||
baseInforLevelFile: val.mimplement?.baseInforLevelFile ? reviewFileParam(JSON.parse(val.mimplement.baseInforLevelFile)) : [], | |||
basePasswAssessFile: val.mimplement?.basePasswAssessFile ? reviewFileParam(JSON.parse(val.mimplement.basePasswAssessFile)) : [], | |||
baseThirdAcceptFile: val.mimplement?.baseThirdAcceptFile ? reviewFileParam(JSON.parse(val.mimplement.baseThirdAcceptFile)) : [], | |||
baseCheckFile: val.mimplement?.baseCheckFile ? reviewFileParam(JSON.parse(val.mimplement.baseCheckFile)) : [], | |||
baseFinanlAuditFile: val.mimplement?.baseFinanlAuditFile ? reviewFileParam(JSON.parse(val.mimplement.baseFinanlAuditFile)) : [], | |||
baseUserConsFile: val.mimplement?.baseUserConsFile ? reviewFileParam(JSON.parse(val.mimplement.baseUserConsFile)) : [], | |||
baseEstaSummFile: val.mimplement?.baseEstaSummFile ? reviewFileParam(JSON.parse(val.mimplement.baseEstaSummFile)) : [], | |||
baseOperatMaintenSummFile: val.mimplement?.baseOperatMaintenSummFile ? reviewFileParam(JSON.parse(val.mimplement.baseOperatMaintenSummFile)) : [], | |||
baseFinalExpertOpinionFile: val.mimplement?.baseFinalExpertOpinionFile ? reviewFileParam(JSON.parse(val.mimplement.baseFinalExpertOpinionFile)) : [], | |||
baseEngineerPostpoFile: val.mimplement?.baseEngineerPostpoFile ? reviewFileParam(JSON.parse(val.mimplement.baseEngineerPostpoFile)) : [], | |||
baseEngineerAlterFile: val.mimplement?.baseEngineerAlterFile ? reviewFileParam(JSON.parse(val.mimplement.baseEngineerAlterFile)) : [], | |||
baseChanFile: val.mimplement?.baseChanFile ? reviewFileParam(JSON.parse(val.mimplement.baseChanFile)) : [], | |||
baseBusinessMetrics: val.mimplement?.baseBusinessMetrics && JSON.parse(val.mimplement?.baseBusinessMetrics) || [] | |||
} | |||
} | |||
}) | |||
watch(() => props.data, val => { | |||
}, | |||
{ immediate: true, deep: true }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
:validate-on-rule-change="false" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
v-if="baseProjSetYear*1>=2024" | |||
label="是否完成日志数据归集" | |||
label-width="170" | |||
prop="baseLogAggregation" | |||
> | |||
<el-radio-group v-model="formData.baseLogAggregation"> | |||
<el-radio label="1">是</el-radio> | |||
<el-radio label="2">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="是否完成日志数据归集" | |||
label-width="170" | |||
> | |||
<el-radio-group v-model="formData.baseLogAggregation"> | |||
<el-radio label="1">是</el-radio> | |||
<el-radio label="2">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
v-if="baseProjSetYear*1>=2024" | |||
label="实际成效指标" | |||
label-width="170" | |||
prop="baseBusinessMetrics" | |||
> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.baseBusinessMetrics" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="实际成效指标" | |||
label-width="170" | |||
> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.baseBusinessMetrics" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="(['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)&&basicInfoData?.baseConstructionType?.includes('01'))||!basicInfoData?.baseConstructionType?.includes('01')" :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg==='07'&&basicInfoData?.baseConstructionType?.includes('01')&&['03','04','05'].includes(approvalInfoData?.equalProtectionLevel)" | |||
label="信息安全等级保护测评报告" | |||
prop="baseInforLevelFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseInforLevelFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseInforLevelFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="信息安全等级保护测评报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseInforLevelFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseInforLevelFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" :span="8"> | |||
<el-form-item | |||
v-if="['01','02'].includes(approvalInfoData?.equalProtectionLevel)||baseProjSetYear*1<2023" | |||
label="商业密码应用评估报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.basePasswAssessFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.basePasswAssessFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="商业密码应用评估报告" | |||
prop="basePasswAssessFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.basePasswAssessFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.basePasswAssessFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="第三方验收测试报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseThirdAcceptFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseThirdAcceptFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03','04'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" :span="8"> | |||
<el-form-item | |||
v-if="baseProjSetYear*1<2023||['05','06','07'].includes(basicInfoData?.baseProjSetProg)" | |||
label="用户使用报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseUserConsFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseUserConsFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="用户使用报告" | |||
prop="baseUserConsFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseUserConsFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseUserConsFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="监理总结报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseEstaSummFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseEstaSummFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03','04'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg==='07'&&baseProjSetYear*1>=2023" | |||
label="运维总结报告" | |||
prop="baseOperatMaintenSummFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseOperatMaintenSummFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseOperatMaintenSummFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="运维总结报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseOperatMaintenSummFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseOperatMaintenSummFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="basicInfoData?.baseProjSetProg==='07'" :span="8"> | |||
<el-form-item | |||
label="终验意见" | |||
prop="baseFinalExpertOpinionFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseFinalExpertOpinionFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseFinalExpertOpinionFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="项目延期申请表" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseEngineerPostpoFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseEngineerPostpoFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="变更报告" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseEngineerAlterFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseEngineerAlterFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="变更批复文件" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseChanFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseChanFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<actual-performance-indicators-dialog | |||
:visible="projectContentDialogData.visible" | |||
:data="projectContentDialogData.data" | |||
@set-content="setContent" | |||
@close="projectContentDialogData.visible=false" | |||
/> | |||
</template> |
@@ -0,0 +1,124 @@ | |||
<script name="relatedIrsAppDialog" setup> | |||
import { nextTick, ref, watch } from 'vue' | |||
import { govStripList } from '@/http/apis/declareMange' | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object, | |||
column: { | |||
type: Array, | |||
default: () => { | |||
return [ | |||
{ | |||
type: 'radio', | |||
key: 'businessStripCode', | |||
width: '60' | |||
}, | |||
{ | |||
label: '单位名称', | |||
key: 'businessStripName', | |||
prop: 'businessStripName', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '单位编码', | |||
key: 'businessStripCode', | |||
prop: 'businessStripCode', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
} | |||
] | |||
} | |||
} | |||
}), | |||
searchForm = ref({ | |||
name: undefined | |||
}), | |||
// 表格数据 | |||
tableListRef = ref(), | |||
total = ref(0), | |||
tableData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await govStripList({ ...pageParams, ...searchForm.value }) | |||
tableData.value = res.data | |||
await nextTick() | |||
tableListRef.value.setRadio(props?.data?.businessStripCode || '') | |||
}, | |||
// 搜索 | |||
search = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
reset = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
searchForm.value.businessStripName = undefined | |||
getTableData() | |||
}, | |||
selectData = ref(), | |||
radioChange = (val) => { | |||
selectData.value = val | |||
}, | |||
submit = async () => { | |||
emits('getBaseProvManDeprt', selectData.value) | |||
emits('close', true) | |||
}, | |||
emits = defineEmits(['close', 'getBaseProvManDeprt']) | |||
watch(() => props.visible, async (val) => { | |||
if (val) { | |||
await nextTick() | |||
await getTableData() | |||
} else { | |||
tableListRef.value.tableRef.clearSelection() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="选择单位" | |||
:width="840" | |||
@close="emits('close')" | |||
> | |||
<el-form :model="searchForm" label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="单位名称"> | |||
<el-input v-model="searchForm.businessStripName" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="search_btn"> | |||
<el-button type="primary" @click="search">搜索</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:total="total" | |||
row-key="appId" | |||
:pagination="false" | |||
@radio-change="radioChange" | |||
@get-table-data="getTableData" | |||
/> | |||
<template #footer> | |||
<div class="flex justify-center"> | |||
<el-button type="primary" @click="submit">确定</el-button> | |||
<el-button @click="emits('close')">取消</el-button> | |||
</div> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,216 @@ | |||
<script name="projectCollectionEnterManageInfo" setup> | |||
import { onMounted, reactive, ref, watch } from 'vue' | |||
import OrgTree from '@/components/orgTree/index.vue' | |||
import store from '@/store' | |||
import { getTreeParams } from '@/utils/getIsShowRegionTree' | |||
import { districtList } from '@/http/apis/commonApi' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
} | |||
}), | |||
{ baseProjConsClassOptions } = store.dictStore.globalDicts || {}, | |||
// 行政区划 | |||
areaOptions = ref([]), | |||
formRef = ref(), | |||
formData = ref({}), | |||
// 手机号码校验 | |||
checkTelPhone = (rule, value, callback) => { | |||
if (value === '') { | |||
return callback(new Error('请输入正确的手机号')) | |||
} else { | |||
const regIdCard = | |||
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/ | |||
if (regIdCard.test(value)) { | |||
callback() | |||
} else { | |||
return callback(new Error('请输入正确的手机号')) | |||
} | |||
} | |||
}, | |||
rules = { | |||
areaCode: [{ required: true, message: '请选择行政区划', trigger: 'change' }], | |||
buildOrg: [{ required: true, message: '请选择建设单位', trigger: 'change' }], | |||
responsibleMan: [{ required: true, message: '请填写项目负责人', trigger: 'blur' }], | |||
responsibleManMobile: [ | |||
{ required: true, message: '请填写项目负责人手机号', trigger: 'blur' }, | |||
{ validator: checkTelPhone, trigger: 'blur' } | |||
], | |||
contactName: [{ required: true, message: '请填写项目联系人', trigger: 'blur' }], | |||
contactPhone: [ | |||
{ required: true, message: '请填写项目联系人手机号', trigger: 'blur' }, | |||
{ validator: checkTelPhone, trigger: 'blur' } | |||
], | |||
higherSuperOrg: [{ required: true, message: '请选择上级业务主管部门', trigger: 'change' }], | |||
superOrg: [{ required: true, message: '请选择本级业务主管部门', trigger: 'change' }], | |||
constructionOrg: [{ required: true, message: '请选择建设单位', trigger: 'change' }], | |||
buildLevel: [{ required: true, message: '请选择建设层级', trigger: 'change' }] | |||
}, | |||
// 单位选择 | |||
orgProps = reactive({ | |||
field: undefined, | |||
unitVisible: false, | |||
data: undefined, | |||
title: undefined, | |||
type: undefined, | |||
params: undefined | |||
}), | |||
showOrgTree = (field) => { | |||
orgProps.field = field | |||
orgProps.unitVisible = true | |||
orgProps.title = '选择单位' | |||
orgProps.type = 'UNIT' | |||
orgProps.showCheckbox = true | |||
orgProps.defaultProps = { | |||
children: 'children', | |||
label: 'title', | |||
value: 'key', | |||
isLeaf: 'isLeaf' | |||
} | |||
orgProps.params = { | |||
onlyUnit: true | |||
} | |||
orgProps.data = formData.value[`${field}Code`] ? [{ | |||
key: formData.value[`${field}Code`], | |||
title: formData.value[field] | |||
}] : [] | |||
}, | |||
closeOrg = () => { | |||
orgProps.unitVisible = false | |||
}, | |||
getOrgData = (data) => { | |||
formData.value[`${orgProps.field}Code`] = data?.[0].key || undefined | |||
formData.value[orgProps.field] = data?.[0].title || undefined | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
areaCode: ['330500', val.areaCode], | |||
responsibleMan: val.responsibleMan, | |||
responsibleManMobile: val.responsibleManMobile, | |||
contactName: val.contactName, | |||
contactPhone: val.contactPhone, | |||
higherSuperOrg: val.higherSuperOrg, | |||
superOrg: val.superOrg, | |||
constructionOrg: val.constructionOrg, | |||
constructionOrgCreditCode: val.constructionOrgCreditCode, | |||
buildLevel: val.buildLevel, | |||
buildOrg: val.buildOrg, | |||
buildOrgCode: val.buildOrgCode | |||
} | |||
} | |||
}) | |||
onMounted(async () => { | |||
areaOptions.value = [(await districtList(getTreeParams({ 'SUPER_ADMIN': false, 'REGION_MANAGER': false }))).data] | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="8"> | |||
<el-form-item label="行政区划" prop="areaCode"> | |||
<el-cascader | |||
v-model="formData.areaCode" | |||
class="w-full" | |||
:props="{label:'name',value:'regionCode'}" | |||
:options="areaOptions" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目负责人" prop="responsibleMan"> | |||
<el-input v-model="formData.responsibleMan" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目负责人手机号" prop="responsibleManMobile"> | |||
<el-input v-model="formData.responsibleManMobile" maxlength="11" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="项目联系人" prop="contactName"> | |||
<el-input v-model="formData.contactName" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="项目联系人手机号" prop="contactPhone"> | |||
<el-input v-model="formData.contactPhone" maxlength="11" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="上级业务主管部门" prop="higherSuperOrg"> | |||
<el-input | |||
v-model="formData.higherSuperOrg" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('higherSuperOrg')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="本级业务主管部门" prop="superOrg"> | |||
<el-input | |||
v-model="formData.superOrg" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('superOrg')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设单位" prop="buildOrg"> | |||
<el-input | |||
v-model="formData.buildOrg" | |||
placeholder="请选择" | |||
readonly | |||
@click="showOrgTree('buildOrg')" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设单位统一信用代码" prop="constructionOrgCreditCode"> | |||
<el-input v-model="formData.constructionOrgCreditCode" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设层级" prop="buildLevel"> | |||
<el-select | |||
v-model="formData.buildLevel" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(value, key) in baseProjConsClassOptions" | |||
:key="key" | |||
:label="value" | |||
:value="key*1" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<org-tree | |||
:visible="orgProps.unitVisible" | |||
:show-checkbox="false" | |||
:default-data="orgProps.data" | |||
:title="orgProps.title" | |||
:type="orgProps.type" | |||
:default-props="orgProps.defaultProps" | |||
:params="orgProps.params" | |||
@close="closeOrg" | |||
@get-select-unit="getOrgData" | |||
/> | |||
</template> |
@@ -0,0 +1,263 @@ | |||
<script name="projectCollectionEnterOtherMaterials" setup> | |||
import { ref, watch } from 'vue' | |||
import { fileFormatVerification, handleFileError, handleFileSuccess, handleFilePreview, reviewFileParam, fileTypes, fileDesc } from '@/utils/uploadAction' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
data: { | |||
type: Object | |||
} | |||
}), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
formRef = ref(), | |||
formData = ref({ | |||
feasibilityStudyReport: [], | |||
approvedFile: [], | |||
purchaseFile: [], | |||
acceptanceLetter: [], | |||
purchaseContract: [], | |||
acceptanceReport: [], | |||
changeApprovalDoc: [] | |||
}), | |||
fileRule = [{ required: true, message: '请选择文件' }], | |||
rules = { | |||
feasibilityStudyReport: fileRule, | |||
approvedFile: fileRule, | |||
purchaseFile: fileRule, | |||
acceptanceLetter: fileRule, | |||
purchaseContract: fileRule, | |||
acceptanceReport: fileRule, | |||
changeApprovalDoc: fileRule, | |||
constructionOrg: [{ required: true, message: '请填写承建单位' }], | |||
constructionOrgCreditCode: [{ required: true, message: '请填写承建单位统一信用代码' }] | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
feasibilityStudyReport: reviewFileParam(JSON.parse(val.feasibilityStudyReport)), | |||
approvedFile: reviewFileParam(JSON.parse(val.approvedFile)), | |||
purchaseFile: reviewFileParam(JSON.parse(val.purchaseFile)), | |||
acceptanceLetter: reviewFileParam(JSON.parse(val.acceptanceLetter)), | |||
purchaseContract: reviewFileParam(JSON.parse(val.purchaseContract)), | |||
acceptanceReport: reviewFileParam(JSON.parse(val.acceptanceReport)), | |||
changeApprovalDoc: reviewFileParam(JSON.parse(val.changeApprovalDoc)), | |||
constructionOrg: val.constructionOrg, | |||
constructionOrgCreditCode: val.constructionOrgCreditCode, | |||
supervisorOrg: val.supervisorOrg, | |||
supervisorOrgCreditCode: val.supervisorOrgCreditCode | |||
} | |||
} | |||
}) | |||
watch(() => props.data, val => { | |||
}, | |||
{ immediate: true, deep: true }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="可行性研究报告(建设方案、运维方案)" | |||
:prop="props.data.status===1||props.data.status===2?'':'feasibilityStudyReport'" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.feasibilityStudyReport" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.feasibilityStudyReport)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="立项批复文件" | |||
prop="approvedFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.approvedFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.approvedFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="采购文件" | |||
prop="purchaseFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.purchaseFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.purchaseFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标通知书" | |||
prop="acceptanceLetter" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.acceptanceLetter" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.acceptanceLetter)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="采购合同" | |||
prop="purchaseContract" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.purchaseContract" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.purchaseContract)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="验收报告" | |||
prop="acceptanceReport" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.acceptanceReport" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.acceptanceReport)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="变更批复文件" | |||
prop="changeApprovalDoc" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.changeApprovalDoc" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.changeApprovalDoc)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="承建单位" :prop="props.data.status===3||props.data.status===4||props.data.status===6?'constructionOrg':''"> | |||
<el-input v-model="formData.constructionOrg" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="承建单位统一信用代码" :prop="props.data.status===3||props.data.status===4||props.data.status===6?'constructionOrgCreditCode':''"> | |||
<el-input v-model="formData.constructionOrgCreditCode" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="监理单位" prop="supervisorOrg"> | |||
<el-input v-model="formData.supervisorOrg" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="监理单位统一信用代码" prop="supervisorOrgCreditCode"> | |||
<el-input v-model="formData.supervisorOrgCreditCode" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> |
@@ -0,0 +1,69 @@ | |||
<script name="projectCollectionEnterProgressInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
} | |||
}), | |||
{ baseProjSetProgOptions } = store.dictStore.globalDicts || {}, | |||
formRef = ref(), | |||
formData = ref({}), | |||
rules = { | |||
status: [{ required: true, message: '请选择项目状态', trigger: 'change' }] | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
console.log(val) | |||
if (val) { | |||
formData.value = { | |||
status: val.status, | |||
applicationName: val.applicationName, | |||
applicationIrsCode: val.applicationIrsCode | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目状态" prop="status"> | |||
<el-select | |||
v-model="formData.status" | |||
class="w-full" | |||
placeholder="请选择" | |||
clearable | |||
> | |||
<el-option | |||
v-for="(v,k) in baseProjSetProgOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k*1" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="关联应用" prop="applicationName"> | |||
<el-input v-model="formData.applicationName" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="关联应用IRS编码" prop="applicationIrsCode"> | |||
<el-input v-model="formData.applicationIrsCode" maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> |
@@ -0,0 +1,365 @@ | |||
<script name="projectApprovalInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import { fileFormatVerification, handleFileError, handleFileSuccess, handleFilePreview, reviewFileParam, fileTypes, fileDesc } from '@/utils/uploadAction' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
formRef = ref(), | |||
formData = ref({ | |||
}), | |||
currentRules = ref([]) | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
...val.approve, | |||
baseReviewCommentsFile: val.approve?.baseReviewCommentsFile && reviewFileParam(JSON.parse(val.approve.baseReviewCommentsFile)) || [], | |||
approvalFile: val.approve?.approvalFile && reviewFileParam(JSON.parse(val.approve.approvalFile)) || [], | |||
preliminaryDesignScheme: val.approve?.preliminaryDesignScheme && reviewFileParam(JSON.parse(val.approve.preliminaryDesignScheme)) || [], | |||
preliminaryDesignFile: val.approve?.preliminaryDesignFile && reviewFileParam(JSON.parse(val.approve.preliminaryDesignFile)) || [] | |||
} | |||
} | |||
}) | |||
const fileRule = [{ required: true, message: '请上传' }], | |||
emits = defineEmits(['getApprovalInfoData']) | |||
watch(() => props.basicInfoData, val => { | |||
if (val?.baseProjIsConfidentiality === '02') { | |||
currentRules.value = {} | |||
} else { | |||
currentRules.value = { | |||
baseReviewResults: [{ required: true, message: '请选择评审结果' }], | |||
equalProtectionLevel: [{ required: true, message: '请选择等保定级' }], | |||
baseReviewOpinion: [{ required: true, message: '请填写评审意见' }], | |||
baseReviewCommentsFile: fileRule, | |||
approvalFile: fileRule, | |||
baseExpertTotalMoney: [{ required: true, message: '请填写建议总投资' }], | |||
baseExpertYearMoney: [{ required: true, message: '请填写建议年度预算' }], | |||
baseInitialReviewTotalMoney: [{ required: true, message: '请填写建议批复总投资' }], | |||
baseProjReplyAmount: [{ required: true, message: '请填写建议批复年度预算' }], | |||
releaseYearMoney: [{ required: true, message: '请填写年度预算下达金额' }], | |||
preliminaryDesignScheme: fileRule, | |||
preliminaryDesignFile: fileRule | |||
} | |||
} | |||
formRef.value?.clearValidate() | |||
}, { deep: true, immediate: true }) | |||
watch(() => formData.value, val => { | |||
emits('getApprovalInfoData', val) | |||
}, { deep: true }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
:validate-on-rule-change="false" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col v-if="basicInfoData?.baseProjSetProg!=='01'" :span="8"> | |||
<el-form-item label="评审结果" prop="baseReviewResults"> | |||
<el-select v-model="formData.baseReviewResults" class="w-full"> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'REVIEW_RESULTS')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="basicInfoData?.baseProjIsConfidentiality === '01'&&!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseConstructionType?.includes('01')&&basicInfoData?.baseProjSetProg!=='04'" | |||
key="equalProtectionLevel1" | |||
label="等保定级" | |||
prop="equalProtectionLevel" | |||
> | |||
<el-select v-model="formData.equalProtectionLevel" class="w-full"> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'EQUAL_PROTECTION_RATING')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
key="equalProtectionLevel2" | |||
label="等保定级" | |||
> | |||
<el-select v-model="formData.equalProtectionLevel" class="w-full"> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'EQUAL_PROTECTION_RATING')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="basicInfoData?.baseProjSetProg!=='01'" :span="24"> | |||
<el-form-item label="评审意见" prop="baseReviewOpinion"> | |||
<el-input | |||
v-model="formData.baseReviewOpinion" | |||
type="textarea" | |||
show-word-limit | |||
:maxlength="500" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="basicInfoData?.baseProjSetProg!=='01'" :span="8"> | |||
<el-form-item | |||
label="评审意见附件" | |||
prop="baseReviewCommentsFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseReviewCommentsFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseReviewCommentsFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item | |||
label="立项批复文件" | |||
prop="approvalFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.approvalFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.approvalFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item label="建议总投资" prop="baseExpertTotalMoney"> | |||
<el-input-number | |||
v-model="formData.baseExpertTotalMoney" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item label="建议年度预算" prop="baseExpertYearMoney"> | |||
<el-input-number | |||
v-model="formData.baseExpertYearMoney" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item label="建议批复总投资" prop="baseInitialReviewTotalMoney"> | |||
<el-input-number | |||
v-model="formData.baseInitialReviewTotalMoney" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!['01','02','03'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item label="建议批复年度预算" prop="baseProjReplyAmount"> | |||
<el-input-number | |||
v-model="formData.baseProjReplyAmount" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item label="年度预算下达金额" prop="releaseYearMoney"> | |||
<el-input-number | |||
v-model="formData.releaseYearMoney" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="formData.baseProjReplyAmount>=5000&&['04','05','06','07','00'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg!=='04'" | |||
key="preliminaryDesignScheme1" | |||
label="初步设计方案" | |||
prop="preliminaryDesignScheme" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.preliminaryDesignScheme" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.preliminaryDesignScheme)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
key="preliminaryDesignScheme2" | |||
label="初步设计方案" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.preliminaryDesignScheme" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.preliminaryDesignScheme)" | |||
:on-error="handleFileError" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
types: [ | |||
'application/pdf', | |||
] | |||
}) | |||
" | |||
accept=".pdf" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持格式:pdf</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="formData.baseProjReplyAmount>=5000&&['04','05','06','07','00'].includes(basicInfoData?.baseProjSetProg)" :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg!=='04'" | |||
key="preliminaryDesignFile1" | |||
label="初步设计方案批复函" | |||
prop="preliminaryDesignFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.preliminaryDesignFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.preliminaryDesignFile)" | |||
:on-error="handleFileError" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
types: [ | |||
'application/pdf', | |||
] | |||
}) | |||
" | |||
accept=".pdf" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持格式:pdf</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
key="preliminaryDesignFile2" | |||
label="初步设计方案批复函" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.preliminaryDesignFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.preliminaryDesignFile)" | |||
:on-error="handleFileError" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
types: [ | |||
'application/pdf', | |||
] | |||
}) | |||
" | |||
accept=".pdf" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持格式:pdf</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
@@ -0,0 +1,198 @@ | |||
<script setup name="projectContentDialog"> | |||
import { ref, watch } from 'vue' | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object | |||
}), | |||
form = ref({ | |||
perIndicator: [] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
mainContent: [{ required: true, message: '请输入项目主要内容' }], | |||
businessObject: [{ required: true, message: '请输入业务对象' }], | |||
perIndicator: [{ required: true, message: '请至少添加一个预期成效指标' }] | |||
}, | |||
column = [ | |||
{ | |||
label: '预期成效指标名称', | |||
key: 'name', | |||
slot: 'name', | |||
width: 140 | |||
}, | |||
{ | |||
label: '符号', | |||
key: 'symbol', | |||
slot: 'symbol' | |||
}, | |||
{ | |||
label: '数值', | |||
key: 'nums', | |||
slot: 'nums' | |||
}, | |||
{ | |||
label: '单位', | |||
key: 'unit', | |||
slot: 'unit' | |||
}, | |||
{ | |||
label: '操作', | |||
key: 'action', | |||
slot: 'action', | |||
width: 70 | |||
} | |||
], | |||
// 添加 | |||
add = () => { | |||
form.value.perIndicator.push({}) | |||
}, | |||
del = (index) => { | |||
form.value.perIndicator.splice(index, 1) | |||
}, | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
await formEl.validate(async (valid) => { | |||
if (valid) { | |||
const data = JSON.parse(JSON.stringify(form.value)) | |||
emits('setContent', data) | |||
emits('close', true) | |||
} | |||
}) | |||
}, | |||
emits = defineEmits(['close', 'setContent']) | |||
watch( | |||
() => props.visible, | |||
async (val) => { | |||
if (val && props.data) { | |||
form.value = JSON.parse(JSON.stringify(props.data)) | |||
} else { | |||
formRef.value?.resetFields() | |||
form.value = { | |||
perIndicator: [] | |||
} | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="添加" | |||
:size="840" | |||
@close="emits('close')" | |||
> | |||
<el-form | |||
ref="formRef" | |||
label-suffix=":" | |||
:model="form" | |||
:rules="rules" | |||
label-width="160" | |||
> | |||
<el-form-item label="项目主要内容" prop="mainContent"> | |||
<el-input | |||
v-model="form.mainContent" | |||
placeholder="请输入" | |||
maxlength="100" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="业务对象" prop="businessObject"> | |||
<el-input | |||
v-model="form.businessObject" | |||
placeholder="请输入" | |||
maxlength="100" | |||
/> | |||
</el-form-item> | |||
<el-button | |||
type="primary" | |||
plain | |||
icon="Plus" | |||
class="w-full mb-8" | |||
@click="add" | |||
>添加 | |||
</el-button> | |||
<table-list | |||
:pagination="false" | |||
:column="column" | |||
:empty-temp="false" | |||
:data="form.perIndicator" | |||
> | |||
<template #name="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].name`" | |||
:rules="[{required:true,message:' '}]" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="form.perIndicator[scope.$index].name" | |||
placeholder="请输入" | |||
maxlength="50" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #symbol="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].symbol`" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-select v-model="form.perIndicator[scope.$index].symbol"> | |||
<el-option label="等于" value="等于" /> | |||
<el-option label="大于" value="大于" /> | |||
<el-option label="大于等于" value="大于等于" /> | |||
<el-option label="小于" value="小于" /> | |||
<el-option label="小于等于" value="小于等于" /> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #nums="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].nums`" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input-number | |||
v-model="form.perIndicator[scope.$index].nums" | |||
:controls="false" | |||
class="flex-1 mr-8" | |||
placeholder="请输入" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #unit="{scope}"> | |||
<el-form-item | |||
v-if="scope.$index>=0" | |||
:prop="`perIndicator[${scope.$index}].unit`" | |||
label-width="0" | |||
style="margin-bottom: 0" | |||
> | |||
<el-input | |||
v-model="form.perIndicator[scope.$index].unit" | |||
placeholder="请输入" | |||
maxlength="10" | |||
/> | |||
</el-form-item> | |||
</template> | |||
<template #action="{scope}"> | |||
<a class="text-danger cursor-pointer" @click="del(scope.$index)">移除</a> | |||
</template> | |||
</table-list> | |||
</el-form> | |||
<template #footer> | |||
<el-button type="primary" @click="submit(formRef)">提交</el-button> | |||
<el-button @click="emits('close')">取消</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,716 @@ | |||
<script name="projectCollectionEnterBasicInfo" setup> | |||
import { reactive, ref, watch } from 'vue' | |||
import RelatedProjectDialog from '@/pages/projectCollection/projectCollectionEnter/components/relatedProjectDialog.vue' | |||
import ProjectContentDialog from '@/pages/projectCollection/projectCollectionEnter/components/projectContentDialog.vue' | |||
import { reviewFileParam, fileFormatVerification, handleFileSuccess, handleFileError, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
// { budgetSourceOptions } = store.dictStore.globalDicts || {}, | |||
formRef = ref(), | |||
formData = ref({ | |||
baseHistorProjs: [], | |||
beseExpectedResults: [] | |||
}), | |||
currentRules = ref({ | |||
baseProjTime: [{ required: true, message: '请选择项目起止时间' }], | |||
baseProjSetYear: [{ required: true, message: '请选择预算年度' }], | |||
baseProjTotalAmount: [{ required: true, message: '请填写项目总投资' }], | |||
baseProjDeclAmount: [{ required: true, message: '请填写申报年度预算' }], | |||
baseProjConsClass: [{ required: true, message: '请选择建设层级' }], | |||
baseLowestLevel: [{ required: true, message: '请选择贯通层级' }], | |||
baseProjAmountOri: [{ required: true, message: '请选择预算来源' }], | |||
baseBasisAmountOri: [{ required: true, message: '请填写预算来源说明' }], | |||
baseProjBasis: [{ required: true, message: '请选择立项依据' }], | |||
baseBasisEstablish: [{ required: true, message: '请填写立项依据说明' }], | |||
baseProjIntro: [{ required: true, message: '请填写项目概述' }], | |||
beseExpectedResults: [{ required: true, message: '请至少添加一个项目内容与预期成效' }], | |||
baseOperatMaintenFile: [{ required: true, message: '请上传' }], | |||
baseHistorProjs: [{ required: true, message: '请关联项目', type: 'array' }], | |||
baseProjApplyFile: [{ required: true, message: '请上传' }] | |||
}), | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '项目名称', | |||
prop: 'baseProjName', | |||
key: 'baseProjName' | |||
}, | |||
{ | |||
label: '预算年度', | |||
prop: 'baseProjSetYear', | |||
key: 'baseProjSetYear' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
// 立项依据 | |||
buildBasisColumn = [ | |||
{ | |||
type: 'selection' | |||
}, | |||
{ | |||
label: '依据项', | |||
key: 'title', | |||
prop: 'title' | |||
}, | |||
{ | |||
label: '依据文件名', | |||
slot: 'fileName' | |||
}, | |||
{ | |||
label: '文件(支持word、pdf格式)', | |||
slot: 'action', | |||
width: 300 | |||
} | |||
], | |||
buildBasisTableData = ref([ | |||
{ | |||
id: 1, | |||
title: '政策、法规', | |||
fileName: '', | |||
fileList: [] | |||
}, | |||
{ | |||
id: 2, | |||
title: '规划或决策部署', | |||
fileName: '', | |||
fileList: [] | |||
}, | |||
{ | |||
id: 3, | |||
title: '上级下达任务', | |||
fileName: '', | |||
fileList: [] | |||
}, | |||
{ | |||
id: 4, | |||
title: '领导批示', | |||
fileName: '', | |||
fileList: [] | |||
}, | |||
{ | |||
id: 5, | |||
title: '单位核心业务或单位职能', | |||
fileName: '', | |||
fileList: [] | |||
}, | |||
{ | |||
id: 6, | |||
title: '其他', | |||
fileName: '', | |||
fileList: [] | |||
} | |||
]), | |||
selectionChange = (val) => { | |||
formData.value.baseProjBasis = val.map(i => i) | |||
}, | |||
column1 = [ | |||
{ | |||
label: '项目主要内容', | |||
prop: 'mainContent', | |||
key: 'mainContent' | |||
}, | |||
{ | |||
label: '业务对象', | |||
prop: 'businessObject', | |||
key: 'businessObject' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
key: 'action' | |||
} | |||
], | |||
// 关联项目 | |||
relatedProjectDialogData = reactive({ | |||
visible: false | |||
}), | |||
showRelatedProjectDialog = () => { | |||
relatedProjectDialogData.visible = true | |||
relatedProjectDialogData.data = formData.value.baseHistorProjs | |||
}, | |||
getProjectList = (data) => { | |||
formData.value.baseHistorProjs = data.map(i => { | |||
return { | |||
baseProjName: i.projectName, | |||
baseProjSetYear: i.projectYear, | |||
baseProjId: i.id | |||
} | |||
}) | |||
}, | |||
delPro = (index) => { | |||
formData.value.baseHistorProjs.splice(index, 1) | |||
}, | |||
// 项目内容与预期成效 | |||
projectContentDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
projectContentIndex = ref(), | |||
showProjectContentDialog = (data, index) => { | |||
projectContentDialogData.data = data | |||
projectContentDialogData.visible = true | |||
projectContentIndex.value = index | |||
}, | |||
setContent = (data) => { | |||
if (projectContentIndex.value === undefined) { | |||
formData.value.beseExpectedResults.push(data) | |||
} else { | |||
formData.value.beseExpectedResults[projectContentIndex.value] = data | |||
} | |||
}, | |||
delProjectContent = (index) => { | |||
formData.value.beseExpectedResults.splice(index, 1) | |||
}, | |||
emits = defineEmits(['getProYear']), | |||
tableListRef = ref() | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.dictionaryList, val => { | |||
if (val) { | |||
buildBasisTableData.value = [] | |||
props.dictionaryList?.filter(i => i.type === 'PROJECT_BASIS').forEach(i => { | |||
buildBasisTableData.value.push({ | |||
title: i.label, | |||
fileName: '', | |||
fileList: [], | |||
value: i.value | |||
}) | |||
}) | |||
} | |||
}) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
formData.value = { | |||
...val.apply, | |||
baseProjTime: val.apply?.baseProjStartTime ? [val.apply?.baseProjStartTime.slice(0, 10), val.apply?.baseProjEndTime.slice(0, 10)] : [], | |||
baseHistorProjs: val.apply?.baseHistorProjId?.split(';').map((i, k) => { | |||
return { | |||
baseProjId: i, | |||
baseProjName: val.apply?.baseHistorProjName.split(';')[k], | |||
baseProjSetYear: val.apply?.baseHistorProjYear.split(';')[k] | |||
} | |||
}) || [], | |||
baseProjAmountOri: val.apply?.baseProjAmountOri && val.apply?.baseProjAmountOri?.split(';'), | |||
baseProjBasis: val.apply?.baseProjBasis?.split(';')?.map((i, index) => { | |||
const file = `[${val.apply?.baseProjBasisFile.replace(/}];/g, '}],')}]` | |||
return { | |||
title: buildBasisTableData.value?.find(j => j.value === i)?.title, | |||
fileList: val.apply?.baseProjBasisFile ? reviewFileParam(JSON.parse(file)[index]) : [], | |||
value: i | |||
} | |||
}), | |||
beseExpectedResults: val.apply?.beseExpectedResults && JSON.parse(val.apply?.beseExpectedResults) || [], | |||
baseProjApplyFile: val.apply?.baseProjApplyFile ? reviewFileParam(JSON.parse(val.apply.baseProjApplyFile)) : [], | |||
baseOperatMaintenFile: val.apply?.baseOperatMaintenFile ? reviewFileParam(JSON.parse(val.apply.baseOperatMaintenFile)) : [], | |||
baseProjOtherFile: val.apply?.baseProjOtherFile ? reviewFileParam(JSON.parse(val.apply.baseProjOtherFile)) : [] | |||
} | |||
const baseProjBasis = formData.value.baseProjBasis ? JSON.parse(JSON.stringify(formData.value.baseProjBasis)) : [] | |||
if (val.apply?.baseProjBasis?.split(';')?.length) { | |||
const dataIds = val.apply?.baseProjBasis?.split(';') | |||
buildBasisTableData.value && buildBasisTableData.value.forEach(item => { | |||
if (dataIds.includes(item.value)) { | |||
item.fileList = baseProjBasis.find(i => i.value === item.value)?.fileList | |||
item.fileName = baseProjBasis.find(i => i.value === item.value)?.fileName | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} | |||
}) | |||
} | |||
} | |||
}) | |||
watch(() => props.basicInfoData, val => { | |||
if (val.baseProjIsConfidentiality === '02') { | |||
currentRules.value = {} | |||
} else { | |||
currentRules.value = { | |||
baseProjTime: [{ required: true, message: '请选择项目起止时间' }], | |||
baseProjSetYear: [{ required: true, message: '请选择预算年度' }], | |||
baseProjDeclAmount: [{ required: true, message: '请填写申报年度预算' }], | |||
baseProjConsClass: [{ required: true, message: '请选择建设层级' }], | |||
baseLowestLevel: [{ required: true, message: '请选择贯通层级' }], | |||
baseProjAmountOri: [{ required: true, message: '请选择预算来源' }], | |||
baseBasisAmountOri: [{ required: true, message: '请填写预算来源说明' }], | |||
baseProjBasis: [{ required: true, message: '请选择立项依据' }], | |||
baseBasisEstablish: [{ required: true, message: '请填写立项依据说明' }], | |||
baseProjIntro: [{ required: true, message: '请填写项目概述' }], | |||
beseExpectedResults: [{ required: true, message: '请至少添加一个项目内容与预期成效' }], | |||
baseOperatMaintenFile: [{ required: true, message: '请上传' }], | |||
baseHistorProjs: [{ required: true, message: '请关联项目', type: 'array' }], | |||
baseProjApplyFile: [{ required: true, message: '请上传' }] | |||
} | |||
} | |||
formRef.value?.clearValidate() | |||
}, { deep: true }) | |||
watch(() => formData.value.baseProjSetYear, val => { | |||
emits('getProYear', val) | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
:validate-on-rule-change="false" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="8"> | |||
<el-form-item label="发改编码" prop="baseDevelopCode"> | |||
<el-input v-model="formData.baseDevelopCode" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="财政编码" prop="setProjCodeFinan"> | |||
<el-input v-model="formData.setProjCodeFinan" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目起止时间" prop="baseProjTime"> | |||
<el-date-picker | |||
v-model="formData.baseProjTime" | |||
type="daterange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度" prop="baseProjSetYear"> | |||
<el-date-picker | |||
v-model="formData.baseProjSetYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目总投资" prop="baseProjTotalAmount"> | |||
<el-input-number | |||
v-model="formData.baseProjTotalAmount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
class="input-amount" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="formData.baseProjSetYear*1>=2023" | |||
key="baseProjDeclAmount1" | |||
label="申报年度预算" | |||
prop="baseProjDeclAmount" | |||
> | |||
<el-input-number | |||
v-model="formData.baseProjDeclAmount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
class="input-amount" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
<el-form-item v-else key="baseProjDeclAmount2" label="申报年度预算"> | |||
<el-input-number | |||
v-model="formData.baseProjDeclAmount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
class="input-amount" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="建设层级" prop="baseProjConsClass"> | |||
<el-select | |||
v-model="formData.baseProjConsClass" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'BUILD_LEVEL')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="!(basicInfoData?.baseConstructionType?.includes('03')&&!basicInfoData?.baseConstructionType?.includes('01'))" :span="8"> | |||
<el-form-item v-if="basicInfoData?.baseConstructionType?.includes('01')" label="贯通层级" prop="baseLowestLevel"> | |||
<el-select | |||
v-model="formData.baseLowestLevel" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'LINK_UP_LEVEL')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item v-else label="贯通层级"> | |||
<el-select | |||
v-model="formData.baseLowestLevel" | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'LINK_UP_LEVEL')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item v-if="!formData.missing" label="历年项目名称" prop="baseHistorProjs"> | |||
<span class="text-[#666666]">是否缺失:</span> | |||
<el-switch v-model="formData.missing" /> | |||
<p class="text-right w-full mb-8"> | |||
<el-button type="primary" @click="showRelatedProjectDialog">关联历年项目</el-button> | |||
</p> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="formData.baseHistorProjs" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a class="text-danger" @click="delPro(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-form-item> | |||
<el-form-item v-else label="历年项目名称" prop="missing"> | |||
<span class="text-[#666666]">是否缺失:</span> | |||
<el-switch v-model="formData.missing" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="预算来源" prop="baseProjAmountOri"> | |||
<el-checkbox-group v-model="formData.baseProjAmountOri"> | |||
<el-checkbox | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'BUDGET_SOURCE')" | |||
:key="index" | |||
:label="item.value" | |||
> | |||
{{ item.label }} | |||
</el-checkbox> | |||
</el-checkbox-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item v-if="formData.baseProjAmountOri?.includes('00')" label="预算来源说明" prop="baseBasisAmountOri"> | |||
<el-input | |||
v-model="formData.baseBasisAmountOri" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="150" | |||
/> | |||
</el-form-item> | |||
<el-form-item v-else label="预算来源说明"> | |||
<el-input | |||
v-model="formData.baseBasisAmountOri" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="150" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="立项依据" prop="baseProjBasis"> | |||
<table-list | |||
ref="tableListRef" | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="buildBasisColumn" | |||
:data="buildBasisTableData" | |||
@selection-change="selectionChange" | |||
> | |||
<template #fileName="{scope}"> | |||
<el-form-item v-if="formData.baseProjBasis&&formData.baseProjBasis.map(i=>i.value).includes(scope.row.value)"> | |||
<el-input | |||
:value="formData.baseProjBasis[formData.baseProjBasis.findIndex(i=>i.value===scope.row.value)]?.fileList?.[0]?.name" | |||
placeholder="请输入" | |||
:maxlength="50" | |||
:disabled="true" | |||
/> | |||
</el-form-item> | |||
<el-input v-else :disabled="true" /> | |||
</template> | |||
<template #action="{scope}"> | |||
<el-form-item | |||
v-if="formData.baseProjBasis&&formData.baseProjBasis.map(i=>i.value).includes(scope.row.value)" | |||
class="basicUploadItem" | |||
:rules="{required: true,message:'请上传'}" | |||
:prop="`baseProjBasis[${formData.baseProjBasis.findIndex(i=>i.value===scope.row.value)}].fileList`" | |||
> | |||
<el-upload | |||
ref="materialUploadRef" | |||
v-model:file-list="formData.baseProjBasis[formData.baseProjBasis.findIndex(i=>i.value===scope.row.value)].fileList" | |||
class="flex items-center flex-col w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseProjBasis[formData.baseProjBasis.findIndex(i=>i.value===scope.row.value)].fileList, true)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<template #trigger> | |||
<div> | |||
<a>上传</a> | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<span v-else class="text-info cursor-not-allowed">上传</span> | |||
</template> | |||
</table-list> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="立项依据说明" prop="baseBasisEstablish"> | |||
<el-input | |||
v-model="formData.baseBasisEstablish" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="150" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="项目概述" prop="baseProjIntro"> | |||
<el-input | |||
v-model="formData.baseProjIntro" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="2000" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item v-if="formData.baseProjSetYear*1>=2023" label="项目内容与预期成效" prop="beseExpectedResults"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.beseExpectedResults" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
<el-form-item v-else label="项目内容与预期成效"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column1" | |||
:data="formData.beseExpectedResults" | |||
:empty-temp="false" | |||
> | |||
<template #action="{scope}"> | |||
<a @click="showProjectContentDialog(scope.row,scope.$index)">编辑</a> | |||
<a class="text-danger" @click="delProjectContent(scope.$index)">删除</a> | |||
</template> | |||
</table-list> | |||
<p class="text-right w-full mt-8"> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="()=>showProjectContentDialog()" | |||
>添加</el-button> | |||
</p> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="formData.baseProjSetYear*1<2023" | |||
label="项目申报书" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseProjApplyFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseProjApplyFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else-if="formData.baseProjSetYear*1>=2023&&['01','02','04','05'].includes(basicInfoData?.baseProjType)" | |||
label="项目申报书" | |||
prop="baseProjApplyFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseProjApplyFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseProjApplyFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="8"> | |||
<el-form-item | |||
label="可行性研究报告" | |||
prop="baseResearchReportFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseResearchReportFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseResearchReportFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="运维方案" | |||
prop="baseOperatMaintenFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseOperatMaintenFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseOperatMaintenFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="其他附件" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.baseProjOtherFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.baseProjOtherFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4" plain>上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="备注" | |||
> | |||
<el-input | |||
v-model="formData.baseProjRemark" | |||
type="textarea" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<related-project-dialog | |||
:visible="relatedProjectDialogData.visible" | |||
:data="relatedProjectDialogData.data" | |||
@get-project-list="getProjectList" | |||
@close="relatedProjectDialogData.visible=false" | |||
/> | |||
<project-content-dialog | |||
:visible="projectContentDialogData.visible" | |||
:data="projectContentDialogData.data" | |||
@set-content="setContent" | |||
@close="projectContentDialogData.visible=false" | |||
/> | |||
</template> |
@@ -0,0 +1,720 @@ | |||
<script name="purchaseInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import { fileFormatVerification, handleFileError, handleFileSuccess, handleFilePreview, reviewFileParam, fileTypes, fileDesc } from '@/utils/uploadAction' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
detail: { | |||
type: Object | |||
}, | |||
basicInfoData: { | |||
type: Object | |||
}, | |||
baseProjSetYear: { | |||
type: String, | |||
default: '' | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
formRef = ref(), | |||
formData = ref({ | |||
sections: [{ | |||
purchaseFile: [], | |||
biddingFile: [], | |||
purchaseContract: [] | |||
}] | |||
}), | |||
currentRules = {}, | |||
add = () => { | |||
formData.value.sections.push({}) | |||
}, | |||
del = (index) => { | |||
formData.value.sections.splice(index, 1) | |||
} | |||
defineExpose({ formRef, formData }) | |||
watch(() => props.basicInfoData, val => { | |||
if (val?.baseProjIsConfidentiality === '02' || val?.baseProjSetProg === '00') { | |||
currentRules.value = {} | |||
} else { | |||
currentRules.value = { | |||
sections: [{ required: true, message: '请至少添加一个标段' }] | |||
} | |||
} | |||
formRef.value?.clearValidate() | |||
}, { deep: true, immediate: true }) | |||
watch(() => props.detail, val => { | |||
if (val) { | |||
if (props.detail?.procures?.length) { | |||
formData.value = { | |||
sections: props.detail?.procures?.map(i => { | |||
return { | |||
...i, | |||
purchaseFile: i.purchaseFile ? reviewFileParam(JSON.parse(i.purchaseFile)) : [], | |||
biddingFile: i.biddingFile ? reviewFileParam(JSON.parse(i.biddingFile)) : [], | |||
purchaseContract: i.purchaseContract ? reviewFileParam(JSON.parse(i.purchaseContract)) : [] | |||
} | |||
}) || [{ | |||
purchaseFile: [], | |||
biddingFile: [], | |||
purchaseContract: [] | |||
}] | |||
} | |||
} | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="currentRules" | |||
label-position="top" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<template v-for="(item,index) in formData.sections" :key="index"> | |||
<el-button | |||
v-if="formData.sections?.length>1" | |||
type="danger" | |||
icon="Delete" | |||
link | |||
class="float-right" | |||
@click="del(index)" | |||
>删除</el-button> | |||
<template v-if="basicInfoData?.baseProjIsConfidentiality!=='02'&&basicInfoData?.baseProjSetProg!=='00'"> | |||
<el-row :gutter="40"> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="24"> | |||
<el-form-item label="标段名称" :prop="`sections[${index}].baseBidName`" :rules="[{required:true,message:'请填写'}]"> | |||
<el-input v-model="formData.sections[index].baseBidName" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购方式" :prop="`sections[${index}].baseProjPurchaseWay`" :rules="[{required:true,message:'请选择'}]"> | |||
<el-select v-model="formData.sections[index].baseProjPurchaseWay" class="w-full"> | |||
<el-option | |||
v-for="(row,key) in dictionaryList?.filter(i => i.type === 'PURCHASE_METHOD')" | |||
:key="key" | |||
:label="row.label" | |||
:value="row.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算执行确认书编号" :prop="`sections[${index}].basePurchaseCode`"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchaseCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<template v-if="['01','02','03','04','06'].includes(item.baseProjPurchaseWay)&&baseProjSetYear*1>=2023"> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构" :prop="`sections[${index}].basePurchasingAgencies`" :rules="[{required:true,message:'请填写'}]"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchasingAgencies" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构统一社会信用代码" :prop="`sections[${index}].baseUnifiedCreditCode`" :rules="[{required:true,message:'请填写'}]"> | |||
<el-input | |||
v-model="formData.sections[index].baseUnifiedCreditCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-else> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构" :prop="`sections[${index}].basePurchaseCode`"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchasingAgencies" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构统一社会信用代码" :prop="`sections[${index}].baseUnifiedCreditCode`"> | |||
<el-input | |||
v-model="formData.sections[index].baseUnifiedCreditCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)时间" | |||
:prop="`sections[${index}].baseWinningBidTime`" | |||
:rules="[{ required: true, message: '请选择' }]" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].baseWinningBidTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)金额" | |||
:prop="`sections[${index}].baseProjPurchaseAmount`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input-number | |||
v-model="formData.sections[index].baseProjPurchaseAmount" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)供应商名称" | |||
:prop="`sections[${index}].baseConsDeprt`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input | |||
v-model="formData.sections[index].baseConsDeprt" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="中标(成交)供应商统一社会信用代码" :prop="`sections[${index}].baseConsDeprtUsci`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input | |||
v-model="formData.sections[index].baseConsDeprtUsci" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg==='05'||baseProjSetYear*1<2023" | |||
label="项目款支付时间" | |||
:prop="`sections[${index}].basePaymentTime`" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].basePaymentTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="项目款支付时间" | |||
:prop="`sections[${index}].basePaymentTime`" | |||
:rules="[{ required: true, message: '请选择' }]" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].basePaymentTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item v-if="basicInfoData?.baseProjSetProg==='05'||baseProjSetYear*1<2023" label="项目款支付金额" :prop="`sections[${index}].paymentProgress`"> | |||
<el-input-number | |||
v-model="formData.sections[index].paymentProgress" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="项目款支付金额" | |||
:prop="`sections[${index}].paymentProgress`" | |||
:rules="[{ required: true, message: '请选择' }]" | |||
> | |||
<el-input-number | |||
v-model="formData.sections[index].paymentProgress" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</el-row> | |||
<el-row> | |||
<template v-if="['05','06','07','00']?.includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="item.baseProjPurchaseWay==='00'" | |||
label="招标(采购)文件" | |||
:prop="`sections[${index}].purchaseFile`" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="招标(采购)文件" | |||
:prop="`sections[${index}].purchaseFile`" | |||
:rules="[{required:true,message:'请上传'}]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="item.baseProjPurchaseWay==='00'||item.baseProjPurchaseWay==='05'" | |||
label="中标(成交)通知" | |||
:prop="`sections[${index}].biddingFile`" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].biddingFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].biddingFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="中标(成交)通知" | |||
:prop="`sections[${index}].biddingFile`" | |||
:rules="[{required:true,message:'请上传'}]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].biddingFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].biddingFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:on-preview="handleFilePreview" | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="采购合同" | |||
:prop="`sections[${index}].purchaseContract`" | |||
:rules="[{required:true,message:'请上传'}]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseContract" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseContract)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</el-row> | |||
</template> | |||
<template v-else> | |||
<el-row :gutter="40"> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="24"> | |||
<el-form-item label="标段名称" :prop="`sections[${index}].baseBidName`"> | |||
<el-input v-model="formData.sections[index].baseBidName" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购方式" :prop="`sections[${index}].baseProjPurchaseWay`" :rules="[{required:false,message:'请选择'}]"> | |||
<el-select v-model="formData.sections[index].baseProjPurchaseWay" class="w-full"> | |||
<el-option | |||
v-for="(row,key) in dictionaryList?.filter(i => i.type === 'PURCHASE_METHOD')" | |||
:key="key" | |||
:label="row.label" | |||
:value="row.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算执行确认书编号" :prop="`sections[${index}].basePurchaseCode`"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchaseCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<template v-if="['01','02','03','04','06'].includes(item.baseProjPurchaseWay)&&baseProjSetYear*1>=2023"> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构" :prop="`sections[${index}].basePurchaseCode`" :rules="[{required:false,message:'请填写'}]"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchasingAgencies" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构统一社会信用代码" :prop="`sections[${index}].baseUnifiedCreditCode`" :rules="[{required:false,message:'请填写'}]"> | |||
<el-input | |||
v-model="formData.sections[index].baseUnifiedCreditCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-else> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构" :prop="`sections[${index}].basePurchaseCode`"> | |||
<el-input | |||
v-model="formData.sections[index].basePurchasingAgencies" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="采购代理机构统一社会信用代码" :prop="`sections[${index}].baseUnifiedCreditCode`"> | |||
<el-input | |||
v-model="formData.sections[index].baseUnifiedCreditCode" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)时间" | |||
:prop="`sections[${index}].baseWinningBidTime`" | |||
:rules="[{ required: false, message: '请选择' }]" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].baseWinningBidTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)金额" | |||
:prop="`sections[${index}].baseProjPurchaseAmount`" | |||
:rules="[{ required: false, message: '请输入' }]" | |||
> | |||
<el-input-number | |||
v-model="formData.sections[index].baseProjPurchaseAmount" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="中标(成交)供应商名称" | |||
:prop="`sections[${index}].baseConsDeprt`" | |||
:rules="[{ required: false, message: '请输入' }]" | |||
> | |||
<el-input | |||
v-model="formData.sections[index].baseConsDeprt" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="中标(成交)供应商统一社会信用代码" :prop="`sections[${index}].baseConsDeprtUsci`" :rules="[{ required: false, message: '请输入' }]"> | |||
<el-input | |||
v-model="formData.sections[index].baseConsDeprtUsci" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-if="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="basicInfoData?.baseProjSetProg==='05'||baseProjSetYear*1<2023" | |||
label="项目款支付时间" | |||
:prop="`sections[${index}].basePaymentTime`" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].basePaymentTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="项目款支付时间" | |||
:prop="`sections[${index}].basePaymentTime`" | |||
:rules="[{ required: false, message: '请选择' }]" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].basePaymentTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item v-if="basicInfoData?.baseProjSetProg==='05'||baseProjSetYear*1<2023" label="项目款支付金额" :prop="`sections[${index}].paymentProgress`"> | |||
<el-input-number | |||
v-model="formData.sections[index].paymentProgress" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="项目款支付金额" | |||
:prop="`sections[${index}].paymentProgress`" | |||
:rules="[{ required: false, message: '请选择' }]" | |||
> | |||
<el-input-number | |||
v-model="formData.sections[index].paymentProgress" | |||
class="input-amount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>万元</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</el-row> | |||
<el-row> | |||
<template v-if="['05','06','07','00']?.includes(basicInfoData?.baseProjSetProg)"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="item.baseProjPurchaseWay==='00'" | |||
label="招标(采购)文件" | |||
:prop="`sections[${index}].purchaseFile`" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="招标(采购)文件" | |||
:prop="`sections[${index}].purchaseFile`" | |||
:rules="[{required:false,message:'请上传'}]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
v-if="item.baseProjPurchaseWay==='00'" | |||
label="中标(成交)通知" | |||
:prop="`sections[${index}].biddingFile`" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].biddingFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].biddingFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="中标(成交)通知" | |||
:prop="`sections[${index}].biddingFile`" | |||
:rules="[{required:false,message:'请上传'}]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].biddingFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].biddingFile)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="采购合同" | |||
:prop="`sections[${index}].purchaseContract`" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].purchaseContract" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].purchaseContract)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
multiple | |||
:limit="10" | |||
> | |||
<el-button type="primary" class="mr-4">上传文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
</el-row> | |||
</template> | |||
<el-divider v-if="index<formData.sections?.length-1" /> | |||
</template> | |||
</el-form> | |||
<p> | |||
<el-button | |||
type="primary" | |||
plain | |||
icon="Plus" | |||
class="w-full" | |||
@click="add" | |||
>添加标段</el-button> | |||
</p> | |||
</template> |
@@ -0,0 +1,117 @@ | |||
<script name="relatedIrsAppDialog" setup> | |||
import { nextTick, ref, watch } from 'vue' | |||
import { applicationList } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object, | |||
column: { | |||
type: Array, | |||
default: () => { | |||
return [ | |||
{ | |||
type: 'radio', | |||
width: '55', | |||
key: 'appId' | |||
}, | |||
{ | |||
label: '应用名称', | |||
prop: 'name', | |||
key: 'name' | |||
} | |||
] | |||
} | |||
} | |||
}), | |||
searchForm = ref({ | |||
name: undefined | |||
}), | |||
// 表格数据 | |||
tableListRef = ref(), | |||
total = ref(0), | |||
tableData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode, ...searchForm.value }) | |||
tableData.value = res.data.records | |||
total.value = res.data.total | |||
await nextTick() | |||
tableListRef.value.setRadio(props?.data?.appId || '') | |||
}, | |||
// 搜索 | |||
search = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
reset = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
searchForm.value.name = undefined | |||
getTableData() | |||
}, | |||
selectData = ref(), | |||
radioChange = (val) => { | |||
selectData.value = val | |||
}, | |||
submit = async () => { | |||
emits('getIrsApp', selectData.value) | |||
emits('close', true) | |||
}, | |||
emits = defineEmits(['close', 'getIrsApp']) | |||
watch(() => props.visible, async (val) => { | |||
if (val) { | |||
await nextTick() | |||
await getTableData() | |||
} else { | |||
tableListRef.value.tableRef.clearSelection() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="选择项目" | |||
:width="840" | |||
@close="emits('close')" | |||
> | |||
<el-form :model="searchForm" label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="应用名称"> | |||
<el-input v-model="searchForm.name" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="search_btn"> | |||
<el-button type="primary" @click="search">搜索</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:total="total" | |||
row-key="appId" | |||
@radio-change="radioChange" | |||
@get-table-data="getTableData" | |||
/> | |||
<template #footer> | |||
<div class="flex justify-center"> | |||
<el-button type="primary" @click="submit">确定</el-button> | |||
<el-button @click="emits('close')">取消</el-button> | |||
</div> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,171 @@ | |||
<script name="relatedProjectDialog" setup> | |||
import { nextTick, ref, watch, reactive } from 'vue' | |||
import { list } from '@/http/apis/projectStoreManage/projectStore' | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object, | |||
column: { | |||
type: Array, | |||
default: () => { | |||
return [ | |||
{ | |||
type: 'selection', | |||
reserveSelection: true, | |||
width: '55', | |||
fixed: 'left' | |||
}, | |||
{ | |||
label: '项目名称', | |||
prop: 'projectName', | |||
key: 'projectName' | |||
}, | |||
{ | |||
label: '预算年度', | |||
prop: 'projectYear', | |||
key: 'projectYear', | |||
width: 80 | |||
} | |||
] | |||
} | |||
} | |||
}), | |||
searchForm = reactive({ | |||
projectName: undefined, | |||
projectYear: undefined | |||
}), | |||
// 表格数据 | |||
tableListRef = ref(), | |||
total = ref(0), | |||
tableData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await list({ | |||
...pageParams, | |||
...searchForm | |||
}) | |||
tableData.value = res.data.records | |||
total.value = res.data.total | |||
selectCopyData.value = JSON.parse(JSON.stringify(selectData.value)) | |||
if (selectCopyData.value?.length) { | |||
tableData.value && tableData.value.forEach(item => { | |||
const dataIds = selectCopyData.value.map(i => i.id) | |||
if (dataIds.includes(item.id) && !tableListRef.value.getSelectRows().map(i => i.id).includes(item.id)) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} | |||
}) | |||
} | |||
}, | |||
// 搜索 | |||
search = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.projectName = undefined | |||
searchForm.projectYear = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 表格多选 | |||
selectData = ref([]), | |||
selectCopyData = ref([]), | |||
selectionChange = (val) => { | |||
const ids = val.map(i => i.id) | |||
tableData.value.forEach(row => { | |||
if (ids.includes(row.id)) { | |||
selectData.value.push(row) | |||
} else { | |||
selectData.value = selectData.value.filter(i => i.id !== row.id) | |||
} | |||
}) | |||
}, | |||
submit = async () => { | |||
const obj = {} | |||
const data = selectData.value.reduce((cur, next) => { | |||
obj[next.id] ? '' : obj[next.id] = true && cur.push(next) | |||
return cur | |||
}, []) | |||
emits('getProjectList', data) | |||
emits('close', true) | |||
}, | |||
emits = defineEmits(['close', 'getProjectList']) | |||
watch(() => props.visible, async (val) => { | |||
if (val) { | |||
await nextTick() | |||
if (props.data?.length) { | |||
selectData.value = props.data.map(i => { | |||
return { | |||
id: i.baseProjId, | |||
projectName: i.baseProjName, | |||
projectYear: i.baseProjSetYear | |||
} | |||
}) | |||
} | |||
reset() | |||
} else { | |||
tableListRef.value.tableRef.clearSelection() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="选择项目" | |||
:width="840" | |||
@close="emits('close')" | |||
> | |||
<el-form :model="searchForm" label-suffix=":" size="small"> | |||
<el-row :gutter="16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input v-model="searchForm.projectName" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目预算年度" prop="projectYear"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
value-format="YYYY" | |||
placeholder="请选择" | |||
style="width: 100%" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">搜索</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:total="total" | |||
row-key="id" | |||
@selection-change="selectionChange" | |||
@get-table-data="getTableData" | |||
/> | |||
<template #footer> | |||
<div class="flex justify-center"> | |||
<el-button type="primary" @click="submit">确定</el-button> | |||
<el-button @click="emits('close')">取消</el-button> | |||
</div> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,149 @@ | |||
<script setup name="userDialog"> | |||
import { reactive, ref, watch } from 'vue' | |||
import { userList } from '@/http/apis/systemManage/userManage' | |||
const props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: { | |||
type: Array, | |||
default: undefined | |||
}, | |||
params: { | |||
type: Object, | |||
default: () => { | |||
return {} | |||
} | |||
} | |||
}), | |||
emits = defineEmits(['close', 'getUserData']), | |||
column = [ | |||
{ | |||
type: 'radio', | |||
key: 'userId', | |||
width: 60 | |||
}, | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: 60 | |||
}, | |||
{ | |||
label: '姓名', | |||
key: 'name', | |||
prop: 'name' | |||
}, | |||
{ | |||
label: '所属单位(主职)', | |||
key: 'orgName', | |||
prop: 'orgName', | |||
showOverflowTooltip: true, | |||
width: 250 | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'phoneNo', | |||
prop: 'phoneNo', | |||
width: '150' | |||
} | |||
], | |||
tableListRef = ref(), | |||
total = ref(0), | |||
tableData = ref([]), | |||
searchForm = reactive({ | |||
name: undefined | |||
}), | |||
getTableData = async (pageParams = tableListRef.value?.pageParams) => { | |||
const res = await userList({ | |||
...pageParams, | |||
...searchForm, | |||
...props.params | |||
}) | |||
total.value = res.data.total | |||
tableData.value = res.data.records || [] | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.name = undefined | |||
searchForm.phoneNo = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
userData = ref(), | |||
radioChange = (val) => { | |||
userData.value = val | |||
}, | |||
submit = () => { | |||
emits('getUserData', userData.value) | |||
emits('close') | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
getTableData() | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="项目负责人/项目联系人" | |||
width="70%" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<div class="search mb-16"> | |||
<el-form label-suffix=":" :model="searchForm" size="small"> | |||
<el-row :gutter="16"> | |||
<el-col :span="8"> | |||
<el-form-item label="用户姓名"> | |||
<el-input v-model="searchForm.name" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="联系电话"> | |||
<el-input v-model="searchForm.phoneNo" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item class="btn"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
class="mt-15" | |||
:data="tableData" | |||
:total="total" | |||
row-key="userId" | |||
@radio-change="radioChange" | |||
@get-table-data="getTableData" | |||
/> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button @click="emits('close')">关闭</el-button> | |||
<el-button | |||
type="primary" | |||
@click="submit" | |||
> | |||
提交 | |||
</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,281 @@ | |||
<script name="projectCollectionEnter" setup> | |||
import BasicInfo from './components/basicInfo.vue' | |||
import { getCurrentInstance, onMounted, ref } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import { changFilesParam } from '@/utils/uploadAction' | |||
import ProjectDeclareInfo from './components/projectDeclareInfo.vue' | |||
import ApplicationInfo from './components/applicationInfo.vue' | |||
import CoreBusiness from './components/coreBusiness.vue' | |||
import ProjectApprovalInfo from './components/projectApprovalInfo.vue' | |||
import PurchaseInfo from './components/purchaseInfo.vue' | |||
import EmpMaterials from './components/empMaterials.vue' | |||
import { dictionary } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
import { detail, save, draftSave } from '@/http/apis/declareMange/operationProjectRecord' | |||
const { proxy } = getCurrentInstance(), | |||
route = useRoute(), | |||
router = useRouter(), | |||
collapseModal = ['1', '2', '3', '4', '5', '6', '7'], | |||
formRefs = {}, | |||
submitLoading = ref(false), | |||
dictionaryList = ref(), | |||
detailData = ref(), | |||
getDetail = async () => { | |||
const id = route.query.type === '1' ? route.query.id : route.query.draftId | |||
const res = await detail(route.query.type, id) | |||
detailData.value = res.data | |||
}, | |||
submit = async () => { | |||
submitLoading.value = true | |||
try { | |||
const arr = Object.values(formRefs).map(async i => i?.formRef && await i.formRef.validate()) | |||
await Promise.all(arr) | |||
const postData = changePostData() | |||
// const postData = changePostData() | |||
// console.log(postData) | |||
// const formData = formRefs.map(i => i.formData).reduce((result, obj) => ({ ...result, ...obj }), {}) | |||
await save(postData) | |||
submitLoading.value = false | |||
proxy.$message.success('提交成功!') | |||
router.go(-1) | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
}, | |||
basicInfoData = ref(), | |||
getBasicInfoData = (data) => { | |||
basicInfoData.value = data | |||
}, | |||
baseProjSetYear = ref(), | |||
getProYear = (data) => { | |||
baseProjSetYear.value = data | |||
}, | |||
approvalInfoData = ref(), | |||
getApprovalInfoData = (data) => { | |||
approvalInfoData.value = data | |||
}, | |||
changePostData = () => { | |||
const baseinfo = JSON.parse(JSON.stringify(formRefs['baseinfo'].formData)) | |||
const apply = JSON.parse(JSON.stringify(formRefs['apply'].formData)) | |||
const application = formRefs['application'] && JSON.parse(JSON.stringify(formRefs['application'].formData)) || {} | |||
const baseCore = formRefs['baseCore'] && JSON.parse(JSON.stringify(formRefs['baseCore'].formData)) || {} | |||
const approve = formRefs['approve'] && JSON.parse(JSON.stringify(formRefs['approve'].formData)) || {} | |||
const procures = formRefs['procures'] && JSON.parse(JSON.stringify(formRefs['procures'].formData)) || [] | |||
const cimplement = formRefs['cimplement'] && JSON.parse(JSON.stringify(formRefs['cimplement'].formData)) || [] | |||
return { | |||
baseProjId: route.query.id || '', | |||
draftId: route.query.draftId * 1 || '', | |||
baseinfo: { | |||
...baseinfo, | |||
baseProvManDeprtType: baseinfo?.baseProvManDeprtType * 1 || undefined, | |||
baseConstructionType: baseinfo?.baseConstructionType?.join(';') | |||
// baseAreaCode: baseinfo?.baseArea?.baseAreaCode || undefined, | |||
// baseAreaName: baseinfo?.baseArea?.baseAreaName || undefined, | |||
// baseArea: undefined | |||
}, | |||
apply: { | |||
...apply, | |||
baseProjStartTime: apply?.baseProjTime?.length ? apply?.baseProjTime[0] + ' 00:00:00' : undefined, | |||
baseProjEndTime: apply?.baseProjTime?.length ? apply?.baseProjTime[1] + ' 00:00:00' : undefined, | |||
baseProjTime: undefined, | |||
baseHistorProjId: apply?.missing ? '' : apply?.baseHistorProjs?.map(i => i.baseProjId)?.join(';'), | |||
baseHistorProjName: apply?.missing ? '' : apply?.baseHistorProjs?.map(i => i.baseProjName)?.join(';'), | |||
baseHistorProjYear: apply?.missing ? '' : apply?.baseHistorProjs?.map(i => i.baseProjSetYear)?.join(';'), | |||
baseProjAmountOri: apply?.baseProjAmountOri?.join(';') || undefined, | |||
baseProjBasis: apply?.baseProjBasis?.map(i => i.value)?.join(';') || undefined, | |||
baseProjBasisFile: apply?.baseProjBasis?.map(i => i.fileList && JSON.stringify(changFilesParam(i.fileList)))?.join(';') || '', | |||
beseExpectedResults: apply?.beseExpectedResults?.length && JSON.stringify(apply.beseExpectedResults) || '', | |||
baseProjApplyFile: ((['01', '02', '04', '05'].includes(baseinfo?.baseProjType) && apply?.baseProjSetYear * 1 >= 2023) || apply?.baseProjSetYear * 1 < 2023) && apply?.baseProjApplyFile?.length ? JSON.stringify(changFilesParam(apply?.baseProjApplyFile)) : '', | |||
baseOperatMaintenFile: apply?.baseOperatMaintenFile?.length ? JSON.stringify(changFilesParam(apply?.baseOperatMaintenFile)) : '', | |||
baseProjOtherFile: apply?.baseProjOtherFile?.length ? JSON.stringify(changFilesParam(apply?.baseProjOtherFile)) : '', | |||
baseHistorProjs: undefined, | |||
...application, | |||
baseProjSysCode: application?.applications?.map(i => i.application.applicationCode).join(';') || '', | |||
baseProjSys: application?.applications?.map(i => i.application.applicationName).join(';') || '', | |||
baseAccountAppName: application?.applications?.map(i => i.baseAccountAppName).join(';') || '', | |||
baseBrainName: application?.applications?.map(i => i.baseBrainName).join(';') || '', | |||
applications: undefined, | |||
...baseCore, | |||
baseCoreBusinessCode: baseCore?.coreBusiness?.map(i => i.id).join(';') || '', | |||
baseCoreBusiness: baseCore?.coreBusiness?.map(i => i.matterName).join(';') || '', | |||
baseCoreBusinessOrg: baseCore?.coreBusiness?.map(i => i.orgName).join(';') || '', | |||
coreBusiness: undefined | |||
}, | |||
approve: { | |||
...approve, | |||
baseReviewResults: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewResults : '', | |||
baseReviewOpinion: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewOpinion : '', | |||
baseReviewCommentsFile: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewCommentsFile?.length && JSON.stringify(changFilesParam(approve?.baseReviewCommentsFile)) : '', | |||
equalProtectionLevel: baseinfo?.baseProjIsConfidentiality === '01' && !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.equalProtectionLevel : '', | |||
approvalFile: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.approvalFile?.length && JSON.stringify(changFilesParam(approve?.approvalFile)) : '', | |||
baseExpertTotalMoney: !['01', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseExpertTotalMoney : '', | |||
baseExpertYearMoney: !['01', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseExpertYearMoney : '', | |||
baseInitialReviewTotalMoney: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseInitialReviewTotalMoney : '', | |||
baseProjReplyAmount: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseProjReplyAmount : '', | |||
releaseYearMoney: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) ? approve?.releaseYearMoney : '', | |||
preliminaryDesignScheme: approve?.baseProjReplyAmount >= 5000 && ['04', '05', '06', '07', '00'].includes(baseinfo.baseProjSetProg) ? approve?.preliminaryDesignScheme?.length && JSON.stringify(changFilesParam(approve.preliminaryDesignScheme)) : '', | |||
preliminaryDesignFile: approve?.baseProjReplyAmount >= 5000 && ['04', '05', '06', '07', '00'].includes(baseinfo.baseProjSetProg) ? approve?.preliminaryDesignFile?.length && JSON.stringify(changFilesParam(approve.preliminaryDesignFile)) : '' | |||
}, | |||
procures: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && procures?.sections?.map(i => { | |||
return { | |||
...i, | |||
baseBidName: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseBidName || '', | |||
baseProjPurchaseWay: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseProjPurchaseWay || '', | |||
basePurchaseCode: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.basePurchaseCode || '', | |||
basePurchasingAgencies: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.basePurchasingAgencies || '', | |||
baseUnifiedCreditCode: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.baseUnifiedCreditCode || '', | |||
baseWinningBidTime: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseWinningBidTime || '', | |||
baseProjPurchaseAmount: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseProjPurchaseAmount || '', | |||
baseConsDeprt: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseConsDeprt || '', | |||
baseConsDeprtUsci: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseConsDeprtUsci || '', | |||
basePaymentTime: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.basePaymentTime || '', | |||
paymentProgress: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.paymentProgress || '', | |||
purchaseFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.purchaseFile?.length ? JSON.stringify(changFilesParam(i.purchaseFile)) : '', | |||
biddingFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.biddingFile?.length ? JSON.stringify(changFilesParam(i.biddingFile)) : '', | |||
purchaseContract: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.purchaseContract?.length ? JSON.stringify(changFilesParam(i.purchaseContract)) : '' | |||
} | |||
}) || [], | |||
mimplement: { | |||
...cimplement, | |||
baseInitialOpinionFile: cimplement?.baseInitialOpinionFile?.length ? JSON.stringify(changFilesParam(cimplement.baseInitialOpinionFile)) : '', | |||
baseInforLevelFile: ((['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && baseinfo?.baseConstructionType?.includes('01')) || !baseinfo?.baseConstructionType?.includes('01')) && cimplement?.baseInforLevelFile?.length ? JSON.stringify(changFilesParam(cimplement.baseInforLevelFile)) : '', | |||
basePasswAssessFile: (['04', '05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.basePasswAssessFile?.length ? JSON.stringify(changFilesParam(cimplement.basePasswAssessFile)) : '', | |||
baseThirdAcceptFile: cimplement.baseThirdAcceptFile?.length ? JSON.stringify(changFilesParam(cimplement.baseThirdAcceptFile)) : '', | |||
baseCheckFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && cimplement?.baseCheckFile?.length ? JSON.stringify(changFilesParam(cimplement.baseCheckFile)) : '', | |||
baseFinanlAuditFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && approve?.releaseYearMoney * 1 >= 2000 && cimplement?.baseFinanlAuditFile?.length ? JSON.stringify(changFilesParam(cimplement.baseFinanlAuditFile)) : '', | |||
baseUserConsFile: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.baseUserConsFile?.length ? JSON.stringify(changFilesParam(cimplement.baseUserConsFile)) : '', | |||
baseEstaSummFile: cimplement?.baseEstaSummFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseEstaSummFile)) : '', | |||
baseOperatMaintenSummFile: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.baseOperatMaintenSummFile?.length ? JSON.stringify(changFilesParam(cimplement.baseOperatMaintenSummFile)) : '', | |||
baseFinalExpertOpinionFile: baseinfo?.baseProjSetProg === '07' && cimplement.baseFinalExpertOpinionFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseFinalExpertOpinionFile)) : '', | |||
baseEngineerPostpoFile: cimplement?.baseEngineerPostpoFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseEngineerPostpoFile)) : '', | |||
baseEngineerAlterFile: cimplement?.baseEngineerAlterFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseEngineerAlterFile)) : '', | |||
baseChanFile: cimplement?.baseChanFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseChanFile)) : '', | |||
baseBusinessMetrics: cimplement?.baseBusinessMetrics?.length ? JSON.stringify(cimplement?.baseBusinessMetrics) : '' | |||
} | |||
} | |||
}, | |||
// 暂存 | |||
saveLoading = ref(false), | |||
saveDraft = async () => { | |||
saveLoading.value = true | |||
const postData = changePostData() | |||
try { | |||
await draftSave(postData) | |||
saveLoading.value = false | |||
proxy.$message.success('暂存成功!') | |||
router.go(-1) | |||
} catch (e) { | |||
saveLoading.value = false | |||
} | |||
} | |||
onMounted(async () => { | |||
dictionaryList.value = (await dictionary()).data | |||
if (route.query.id) getDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class="footerPage"> | |||
<div> | |||
<el-collapse v-model="collapseModal"> | |||
<el-collapse-item name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目基本信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<basic-info | |||
:ref="el=>formRefs['baseinfo']=el" | |||
:detail="detailData" | |||
:dictionary-list="dictionaryList" | |||
@get-basic-info-data="getBasicInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="2" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目申报信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<project-declare-info | |||
:ref="el=>formRefs['apply']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:dictionary-list="dictionaryList" | |||
@get-pro-year="getProYear" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="!(basicInfoData?.baseConstructionType?.length===1&&basicInfoData?.baseConstructionType.includes('02'))" name="3" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目关联信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<application-info :ref="el=>formRefs['application']=el" :detail="detailData" :basic-info-data="basicInfoData" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="4" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">核心业务</div> | |||
</template> | |||
<div class="pb-24"> | |||
<core-business :ref="el=>formRefs['baseCore']=el" :detail="detailData" :basic-info-data="basicInfoData" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="basicInfoData?.baseProjSetProg!=='01'" name="5" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目立项评审信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<project-approval-info | |||
:ref="el=>formRefs['approve']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:dictionary-list="dictionaryList" | |||
@get-approval-info-data="getApprovalInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="6" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目采购、资金支付信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<purchase-info | |||
:ref="el=>formRefs['procures']=el" | |||
:detail="detailData" | |||
:dictionary-list="dictionaryList" | |||
:base-proj-set-year="baseProjSetYear" | |||
:basic-info-data="basicInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="7" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">实施材料信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<emp-materials | |||
:ref="el=>formRefs['cimplement']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:base-proj-set-year="baseProjSetYear" | |||
:approval-info-data="approvalInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<div class="footer"> | |||
<el-button @click="$router.go(-1)"> 返回 </el-button> | |||
<el-button | |||
v-if="route.query.type!=='1'" | |||
type="primary" | |||
:loading="saveLoading" | |||
plain | |||
@click="saveDraft" | |||
> 暂存 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submit"> 提交 </el-button> | |||
</div> | |||
</el-collapse></div> | |||
</div> | |||
</template> |
@@ -0,0 +1,128 @@ | |||
<script name="approvalDialog" setup> | |||
import { ref, getCurrentInstance, watch } from 'vue' | |||
import { changFilesParam, fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
import { preExamineDeclare } from '@/http/apis/declareMange' | |||
const { proxy } = getCurrentInstance(), | |||
uploadUrl = store.dictStore.uploadUrl, | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: Object | |||
}), | |||
emits = defineEmits(['close']), | |||
loading = ref(false), | |||
dialogForm = ref({ | |||
higherLineSuperOrgReviewComments: [] | |||
}), | |||
rules = { | |||
'higherLineSuperOrgReviewComments': [{ required: true, message: '请选择' }] | |||
}, | |||
dialogFormRef = ref(), | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
save() | |||
return | |||
} | |||
formEl.validate(async (valid) => { | |||
if (valid) { | |||
save() | |||
} | |||
} | |||
) | |||
}, | |||
save = async () => { | |||
loading.value = true | |||
try { | |||
await preExamineDeclare({ | |||
projectInfo: { | |||
...dialogForm.value, | |||
higherLineSuperOrgReviewComments: dialogForm.value?.higherLineSuperOrgReviewComments?.length && JSON.stringify(changFilesParam(dialogForm.value.higherLineSuperOrgReviewComments)) || undefined, | |||
id: props.data.id | |||
} | |||
}) | |||
proxy.$message.success('发起成功!') | |||
loading.value = false | |||
emits('close', true) | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
console.log('props.data', props.data) | |||
} else { | |||
dialogForm.value = { higherLineSuperOrgReviewComments: [] } | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="预审申报" | |||
width="600px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<div> | |||
<p>根据《浙江省电子政务重大应用项目联审》要求,提交预审后:</p> | |||
<p>1、市级大于1000万元的重大项目将由省级数改牵头部门及业务主管单位进行联审</p> | |||
<p>2、区县申报项目将由市级数改牵头部门及业务主管单位进行联审,大于500万元的重大项目联审后会提交省里进行备案。</p> | |||
</div> | |||
<template v-if="false"> | |||
<p>提交后将发起项目预审流程,确定提交吗?</p> | |||
<el-form | |||
v-if="data.needUploadSuperLineFile" | |||
ref="dialogFormRef" | |||
:model="dialogForm" | |||
:rules="rules" | |||
label-position="top" | |||
label-width="auto" | |||
status-icon | |||
class="mt-16" | |||
> | |||
<el-form-item label="上级条线主管单位审核意见:" prop="higherLineSuperOrgReviewComments"> | |||
<el-upload | |||
v-model:file-list="dialogForm.higherLineSuperOrgReviewComments" | |||
class=" w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, dialogForm.higherLineSuperOrgReviewComments, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-form> | |||
</template> | |||
<template #footer> | |||
<el-button | |||
type="primary" | |||
:loading="loading" | |||
@click="submit(dialogFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button | |||
@click="emits('close')" | |||
> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,261 @@ | |||
<script setup name="preExaminationDeclare"> | |||
import { ref, reactive, onMounted, h } from 'vue' | |||
import { getPreExamineList, declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import PreExaminationDialog from './components/preExaminationDialog.vue' | |||
import store from '@/store' | |||
const { statusOptions, projectTypeOptions } = store.dictStore.globalDicts || {} | |||
// 搜索栏表单数据 | |||
const | |||
router = useRouter(), | |||
searchForm = reactive({ | |||
projectName: undefined, | |||
buildUnitName: undefined, | |||
projectType: undefined, | |||
year: undefined, | |||
times: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: 200, | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: 80 | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '申报单位', | |||
key: 'buildOrg', | |||
prop: 'buildOrg', | |||
width: '120', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
showOverflowTooltip: true, | |||
width: '180', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status].color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name + '-' + statusOptions[row.status]?.name | |||
) | |||
] | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '160', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await getPreExamineList({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0] || undefined, | |||
createOnMax: searchForm.times?.[1] || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.projectName = undefined | |||
searchForm.buildUnitName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.projectYear = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(2, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0] || undefined, | |||
createOnMax: searchForm.times?.[1] || undefined, | |||
times: undefined | |||
})) | |||
}, | |||
// 预审申报 | |||
preExamDeclare = (data) => { | |||
dialogData.visible = true | |||
dialogData.data = data | |||
}, | |||
dialogData = reactive({ | |||
visible: undefined, | |||
data: undefined | |||
}), | |||
close = (flag) => { | |||
dialogData.visible = false | |||
flag && getTableData() | |||
}, | |||
checkDetail = (data) => { | |||
router.push({ name: 'preExaminationDeclareDetail', query: { id: data.id }}) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input v-model="searchForm.projectName" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select v-model="searchForm.projectType" placeholder="全部" class="w-full"> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
value-format="YYYY" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="10"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
:editable="false" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="14"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>待申报的项目</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
>导出</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<div class="mb-8"> | |||
<el-alert | |||
title="温馨提示" | |||
:closable="false" | |||
type="info" | |||
description="一级单位用户有权限进行[申报预审]操作,若您无权操作,请联系您上级单位管理员" | |||
show-icon | |||
class="primary-alert" | |||
/> | |||
</div> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="scope.row.canPreDeclared" @click="preExamDeclare(scope.row)">申报预审</a> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-row> | |||
<pre-examination-dialog :visible="dialogData.visible" :data="dialogData.data" @close="close" /> | |||
</template> | |||
<style lang='less' scoped> | |||
.container{ | |||
position: relative; | |||
.funcBtn{ | |||
position: absolute; | |||
top: 0; | |||
right: 26px; | |||
} | |||
} | |||
:deep(.el-form--inline .el-form-item) { | |||
display: inline-flex; | |||
vertical-align: middle; | |||
margin-right: 8px; | |||
} | |||
</style> |
@@ -0,0 +1,252 @@ | |||
<script setup name="projectAdjustment"> | |||
import { ref, reactive, onMounted, h } from 'vue' | |||
import { declareExport, projectAdjustmentList } from '@/http/apis/declareMange' | |||
import store from '@/store' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
const { statusOptionsCascader, statusOptions, projectTypeOptions } = | |||
store.dictStore.globalDicts || {}, | |||
router = useRouter() | |||
// 搜索栏表单数据 | |||
const formInline = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '220', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status]?.color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name + '-' + statusOptions[row.status]?.name | |||
) | |||
] | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
showOverflowTooltip: true, | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '150px', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await projectAdjustmentList({ | |||
...pageParams, | |||
...formInline, | |||
createOnMin: formInline.times?.[0], | |||
createOnMax: formInline.times?.[1], | |||
projectYear: formInline.projectYear * 1 || undefined, | |||
status: formInline.status?.[formInline.status.length - 1], | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
formInline.status = undefined | |||
formInline.projectYear = undefined | |||
formInline.projectName = undefined | |||
formInline.projectType = undefined | |||
formInline.createOnMin = undefined | |||
formInline.createOnMax = undefined | |||
formInline.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(4, { | |||
...formInline, | |||
createOnMin: formInline.times?.[0], | |||
createOnMax: formInline.times?.[1], | |||
projectYear: formInline.projectYear * 1 || undefined, | |||
status: formInline.status?.[formInline.status.length - 1], | |||
times: undefined | |||
})) | |||
}, | |||
reDeclare = (row) => { | |||
if (row.status === 20005) { | |||
router.push({ name: 'declarationFinal', query: { id: row.id }}) | |||
} else { | |||
router.push({ name: 'declarePage', query: { id: row.id }}) | |||
} | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="formInline" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="formInline.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="formInline.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目状态"> | |||
<el-cascader | |||
v-model="formInline.status" | |||
class="w-full" | |||
:props="{label:'name',value:'code'}" | |||
:options="statusOptionsCascader.map(i=>{ | |||
return { | |||
...i, | |||
children:i?.children?.filter(j=>j.color==='danger') | |||
} | |||
})" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="20"> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="formInline.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="formInline.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="4"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>待调整的项目</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="scope.row.status!==10009" @click="reDeclare(scope.row)">重新申报</a> | |||
<a @click="router.push({name:'projectDeclareDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,298 @@ | |||
<script name="accessory" setup> | |||
import { ref } from 'vue' | |||
import { fileFormatVerification, handleFileSuccess, reviewFileParam, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => { | |||
return {} | |||
} | |||
}, | |||
projectType: { | |||
type: String, | |||
default: '' | |||
}, | |||
declareAmount: { | |||
type: Number | |||
} | |||
}) | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
formData = ref({ | |||
constructionPlanFile: [], | |||
preliminaryPlanFile: [], | |||
mainResponsibilitiesApplicantFile: [], | |||
supportingMaterialsFile: [], | |||
calculationTotalInvestmentFile: [], | |||
projectApplicationForm: [], | |||
mainAccusationDoc: [] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
preliminaryPlanFile: [ | |||
{ required: true, message: '请上传初步方案', trigger: 'blur' } | |||
], | |||
supportingMaterialsFile: [ | |||
{ required: true, message: '请上传佐证材料', trigger: 'blur' } | |||
], | |||
calculationTotalInvestmentFile: [ | |||
{ required: true, message: '请上传项目总投资测算明细', trigger: 'blur' } | |||
], | |||
mainResponsibilitiesApplicantFile: [ | |||
{ required: true, message: '请上传申报单位主要职责(单位三定方案)', trigger: 'blur' } | |||
], | |||
projectApplicationForm: [{ required: true, message: '请上传项目申报书' }], | |||
baseResearchReportFile: [{ required: true, message: '请上传可行性研究报告' }], | |||
constructionPlanFile: [{ required: true, message: '请上传建设方案' }], | |||
mainAccusationDoc: [{ required: true, message: '请上传申报单位主要职责(单位三定方案)', trigger: 'blur' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
constructionPlanFile: data.constructionPlanFile ? reviewFileParam(JSON.parse(data.constructionPlanFile)) : [], | |||
preliminaryPlanFile: data.preliminaryPlanFile ? reviewFileParam(JSON.parse(data.preliminaryPlanFile)) : [], | |||
mainResponsibilitiesApplicantFile: data.mainResponsibilitiesApplicantFile ? reviewFileParam(JSON.parse(data.mainResponsibilitiesApplicantFile)) : [], | |||
supportingMaterialsFile: data.supportingMaterialsFile ? reviewFileParam(JSON.parse(data.supportingMaterialsFile)) : [], | |||
baseResearchReportFile: data.baseResearchReportFile ? reviewFileParam(JSON.parse(data.baseResearchReportFile)) : [], | |||
calculationTotalInvestmentFile: data.calculationTotalInvestmentFile ? reviewFileParam(JSON.parse(data.calculationTotalInvestmentFile)) : [], | |||
projectApplicationForm: data.projectApplicationForm ? reviewFileParam(JSON.parse(data.projectApplicationForm)) : [], | |||
baseProjOtherFile: data.baseProjOtherFile ? reviewFileParam(JSON.parse(data.baseProjOtherFile)) : [], | |||
mainAccusationDoc: data.mainAccusationDoc ? reviewFileParam(JSON.parse(data.mainAccusationDoc)) : [] | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item label="初步设计方案"> | |||
<el-upload | |||
v-model:file-list="formData.preliminaryPlanFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, formData.preliminaryPlanFile, true)" | |||
:before-upload="file=>fileFormatVerification(file, { | |||
types: fileTypes | |||
})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="12"> | |||
<el-form-item | |||
label="佐证材料" | |||
prop="supportingMaterialsFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.supportingMaterialsFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.supportingMaterialsFile)" | |||
:before-upload="file=>fileFormatVerification(file, { | |||
types: fileTypes | |||
})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="12"> | |||
<el-form-item label="项目总投资测算明细" prop="calculationTotalInvestmentFile"> | |||
<el-upload | |||
ref="investmentCalculationDetailsRef" | |||
v-model:file-list="formData.calculationTotalInvestmentFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.calculationTotalInvestmentFile)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="12"> | |||
<el-form-item | |||
label="申报单位主要职责(单位三定方案)" | |||
prop="mainResponsibilitiesApplicantFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.mainResponsibilitiesApplicantFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.mainResponsibilitiesApplicantFile)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="projectType!=='03'&&false" :span="12"> | |||
<el-form-item label="项目申报书" prop="projectApplicationForm"> | |||
<el-upload | |||
v-model:file-list="formData.projectApplicationForm" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, formData.projectApplicationForm, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="projectType!=='03'" :span="12"> | |||
<el-form-item label="可行性研究报告" prop="baseResearchReportFile"> | |||
<el-upload | |||
v-model:file-list="formData.baseResearchReportFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, formData.baseResearchReportFile, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="$route.name==='declarePlan'||[10012,10013,10016].includes(detailData?.status)" :span="12"> | |||
<el-form-item label="建设方案" prop="constructionPlanFile"> | |||
<el-upload | |||
v-model:file-list="formData.constructionPlanFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-success="res => handleFileSuccess(res, formData.constructionPlanFile, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="其他附件"> | |||
<el-upload | |||
ref="baseProjOtherFileRef" | |||
v-model:file-list="formData.baseProjOtherFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.baseProjOtherFile)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item v-if="declareAmount>=1000" label="申报单位主要职责文件(单位三定职责)" prop="mainAccusationDoc"> | |||
<el-upload | |||
ref="mainAccusationDocRef" | |||
v-model:file-list="formData.mainAccusationDoc" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.mainAccusationDoc)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,158 @@ | |||
<script name="annualPaymentPlan" setup> | |||
import { ref } from 'vue' | |||
const formData = ref({}), | |||
formRef = ref(), | |||
moneyValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
rules = { | |||
annualPlanAmount: [ | |||
{ required: true, message: '请输入年度支付金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
annualPlanHaveAmount: [ | |||
{ required: true, message: '请输入自有资金', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
annualPlanGovOwnFinanceAmount: [ | |||
{ | |||
required: true, | |||
message: '请输入政府投资-本级财政资金', | |||
trigger: 'blur' | |||
}, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
annualPlanGovSuperiorFinanceAmount: [ | |||
{ | |||
required: true, | |||
message: '请输入政府投资-上级补助资金', | |||
trigger: 'blur' | |||
}, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
annualPlanBankLendingAmount: [ | |||
{ required: true, message: '请输入银行贷款', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
annualPlanOtherAmount: [{ required: true, message: '请输入其他', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
annualPlanAmount: data.annualPlanAmount, | |||
annualPlanHaveAmount: data.annualPlanHaveAmount, | |||
annualPlanGovOwnFinanceAmount: data.annualPlanGovOwnFinanceAmount, | |||
annualPlanGovSuperiorFinanceAmount: data.annualPlanGovSuperiorFinanceAmount, | |||
annualPlanBankLendingAmount: data.annualPlanBankLendingAmount, | |||
annualPlanOtherAmount: data.annualPlanOtherAmount | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item label="年度支付金额" prop="annualPlanAmount"> | |||
<el-input-number | |||
v-model="formData.annualPlanAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="自有资金" prop="annualPlanHaveAmount"> | |||
<el-input-number | |||
v-model="formData.annualPlanHaveAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="政府投资-本级财政资金" | |||
prop="annualPlanGovOwnFinanceAmount" | |||
> | |||
<el-input-number | |||
v-model="formData.annualPlanGovOwnFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="政府投资-上级补助资金" | |||
prop="annualPlanGovSuperiorFinanceAmount" | |||
> | |||
<el-input-number | |||
v-model="formData.annualPlanGovSuperiorFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="银行贷款" prop="annualPlanBankLendingAmount"> | |||
<el-input-number | |||
v-model="formData.annualPlanBankLendingAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="其他" prop="annualPlanOtherAmount"> | |||
<el-input-number | |||
v-model="formData.annualPlanOtherAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,460 @@ | |||
<script name="appBasicInfo" setup> | |||
import { watch, ref } from 'vue' | |||
import store from '@/store' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import { applicationList, piotTasks } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
const { | |||
accountAppNameOption, | |||
constructionLevel, | |||
applicationType, | |||
businessField, | |||
publisher, | |||
useScope, | |||
digitalModifySystem, | |||
domainBrainAccountOptions | |||
} = store.dictStore.globalDicts || {}, | |||
uploadUrl = store.dictStore.uploadUrl, | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
props = defineProps({ | |||
data: { | |||
type: Object, | |||
default: null | |||
}, | |||
drawerVisible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
isInnovateWholeProvinceShare: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}), | |||
formData = ref({ | |||
experimentsFile: [] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
isFirst: [{ required: true, message: '请选择是否为首次建设' }], | |||
applicationName: [ | |||
{ required: true, message: '请填写应用名称' } | |||
], | |||
relatedExistsApplication: [{ required: true, message: '请选择IRS注册应用' }], | |||
relatedExistsApplicationCode: [{ required: true, message: '请选择IRS应用编码' }], | |||
pilotTasksName: [{ required: true, message: '请选择试点任务名称' }], | |||
pilotTasksCode: [{ required: true, message: '请选择试点任务编号' }], | |||
importantTaskName: [{ required: true, message: '所属重大应用名称' }], | |||
importantTaskCode: [{ required: true, message: '所属重大应用编码' }], | |||
subSceneApplicationName: [{ required: true, message: '所属子场景应用名称' }], | |||
experimentsFile: [{ required: true, message: '请上传试点文件' }], | |||
applicationType: [{ required: true, message: '请选择应用类型' }], | |||
buildLevel: [{ required: true, message: '请选择建设层级', trigger: 'change' }], | |||
isUniteBuild: [{ required: true, message: '请选择是否为统建应用' }], | |||
unionBuildKind: [{ required: true, message: '请选择统建类型' }], | |||
isDigitalModification: [{ required: true, message: '请选择是否为数改系统' }], | |||
digitalModification: [{ required: true, message: '请选择数改系统' }], | |||
bizDomain: [{ required: true, message: '请选择业务领域' }], | |||
publishSide: [{ required: true, message: '请选择发布端' }], | |||
isAccountAppName: [{ required: true, message: '请选择是否S2一本账名称' }], | |||
accountAppName: [{ required: true, message: '请选择S2一本账名称' }], | |||
domainBrainAccount: [{ required: true, message: '请选择领域“大脑”一本账' }], | |||
isBizCooperate: [{ required: true, message: '请选择是否为业务协同' }], | |||
bizCooperateInfo: [{ required: true, message: '请填写业务协同描述' }], | |||
usesRangeRemark: [{ required: true, message: '请选择使用范围' }], | |||
applicationSummary: [{ required: true, message: '请填写应用简介' }], | |||
applicationRemark: [{ required: true, message: '请填写应用备注' }], | |||
applicationEstimateFile: [{ required: true, message: '请上传总投资测算明细' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 清空校验 | |||
clearValidate = () => { | |||
formRef.value.clearValidate() | |||
}, | |||
// 获取irs应用列表 | |||
applicationOptions = ref([]), | |||
getApplicationOptions = async () => { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode }) | |||
applicationOptions.value = res.data | |||
}, | |||
// 获取试点任务列表 | |||
piotTasksOptions = ref([]), | |||
getPiotTasksOptions = async () => { | |||
const res = await piotTasks() | |||
piotTasksOptions.value = res.data | |||
}, | |||
// 修改关联应用 | |||
changeIrsApp = (data) => { | |||
formData.value.relatedExistsApplicationCode = data.applicationCode | |||
}, | |||
// 修改试点任务 | |||
changePilotTask = (data) => { | |||
formData.value.pilotTasksCode = data.taskCode | |||
formData.value.importantTaskName = data.importantTaskName | |||
formData.value.importantTaskCode = data.importantTaskCode | |||
formData.value.subSceneApplicationName = data.subSceneApplicationName | |||
}, | |||
// 修改是否初次建设 | |||
changeIsFirst = () => { | |||
if (formData.value.isFirst === 1) { | |||
formData.value.relatedExistsApplication = undefined | |||
formData.value.relatedExistsApplicationCode = undefined | |||
} else { | |||
formData.value.applicationName = undefined | |||
} | |||
} | |||
watch( | |||
() => props.drawerVisible, | |||
val => { | |||
if (val) { | |||
formData.value = { | |||
...props.data, | |||
isFirst: props.data.isFirst || undefined | |||
} | |||
getApplicationOptions() | |||
getPiotTasksOptions() | |||
} | |||
}, | |||
{ immediate: true } | |||
) | |||
defineExpose({ validForm, formData, clearValidate }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="20"> | |||
<el-col v-if="!props.isInnovateWholeProvinceShare" :span="12"> | |||
<el-form-item label="是否初次建设" prop="isFirst" @change="changeIsFirst"> | |||
<el-radio-group v-model="formData.isFirst"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="2">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<template v-if="formData.isFirst===2||props.isInnovateWholeProvinceShare"> | |||
<el-col :span="12"> | |||
<el-form-item label="关联IRS已注册应用" prop="relatedExistsApplication"> | |||
<el-select | |||
v-model="formData.relatedExistsApplication" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="applicationCode" | |||
@change="changeIrsApp" | |||
> | |||
<el-option | |||
v-for="(item, index) in applicationOptions" | |||
:key="index" | |||
:label="item.applicationName" | |||
:value="{applicationCode:item.applicationCode,applicationName:item.applicationName}" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="IRS应用编码" prop="relatedExistsApplicationCode"> | |||
<el-input v-model="formData.relatedExistsApplicationCode" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<template v-if="props.isInnovateWholeProvinceShare"> | |||
<el-col :span="12"> | |||
<el-form-item label="试点任务名称" prop="pilotTasksName"> | |||
<el-select | |||
v-model="formData.pilotTasksName" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="taskCode" | |||
@change="changePilotTask" | |||
> | |||
<el-option | |||
v-for="(item, index) in piotTasksOptions" | |||
:key="index" | |||
:label="item.taskName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="试点任务编号" prop="pilotTasksCode"> | |||
<el-input v-model="formData.pilotTasksCode" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="所属重大应用名称" prop="importantTaskName"> | |||
<el-input v-model="formData.importantTaskName" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="所属重大应用编码" prop="importantTaskCode"> | |||
<el-input v-model="formData.importantTaskCode" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="所属子场景应用名称" prop="subSceneApplicationName"> | |||
<el-input v-model="formData.subSceneApplicationName" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="试点文件" prop="experimentsFile"> | |||
<el-upload | |||
ref="preliminaryPlanRef" | |||
v-model:file-list="formData.experimentsFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.experimentsFile, true)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<el-col v-if="formData.isFirst===1&&!props.isInnovateWholeProvinceShare" :span="12"> | |||
<el-form-item label="应用名称" prop="applicationName"> | |||
<el-input | |||
v-model="formData.applicationName" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="应用类型" prop="applicationType"> | |||
<el-select v-model="formData.applicationType" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in applicationType" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="建设层级" prop="buildLevel"> | |||
<el-radio-group v-model="formData.buildLevel"> | |||
<el-radio | |||
v-for="(item, index) in constructionLevel" | |||
:key="index" | |||
:label="index*1" | |||
>{{ item }} | |||
</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="是否统建应用" prop="isUniteBuild"> | |||
<el-radio-group v-model="formData.isUniteBuild"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item v-if="formData.isUniteBuild===1" label="统建类型" prop="unionBuildKind"> | |||
<el-radio-group v-model="formData.unionBuildKind"> | |||
<el-radio :label="1">全省统建</el-radio> | |||
<el-radio :label="2">全市统建</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="是否数改系统" prop="isDigitalModification"> | |||
<el-radio-group v-model="formData.isDigitalModification"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item v-if="formData.isDigitalModification===1" label="数改系统" prop="digitalModification"> | |||
<el-select | |||
v-model="formData.digitalModification" | |||
multiple | |||
collapse-tags | |||
collapse-tags-tooltip | |||
placeholder="请选择" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v, k) in digitalModifySystem" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="业务领域" prop="bizDomain"> | |||
<el-select v-model="formData.bizDomain" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in businessField" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="发布端" prop="publishSide"> | |||
<el-select v-model="formData.publishSide" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in publisher" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="是否S2一本账名称" prop="isAccountAppName"> | |||
<el-radio-group v-model="formData.isAccountAppName"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item v-if="formData.isAccountAppName === 1" label="S2一本账名称" prop="accountAppName"> | |||
<el-select | |||
v-model="formData.accountAppName" | |||
placeholder="请选择" | |||
class="w-full" | |||
clearable | |||
> | |||
<el-option | |||
v-for="(item, index) in accountAppNameOption" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item v-if="formData.isAccountAppName === 1 && formData.isDigitalModification===1" label="领域“大脑”一本账" prop="domainBrainAccount"> | |||
<el-select v-model="formData.domainBrainAccount" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in domainBrainAccountOptions" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="是否业务协同" prop="isBizCooperate"> | |||
<el-radio-group v-model="formData.isBizCooperate"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
v-if="formData.isBizCooperate === 1" | |||
label="业务协同描述" | |||
prop="bizCooperateInfo" | |||
><el-input | |||
v-model="formData.bizCooperateInfo" | |||
:autosize="{ minRows: 2, maxRows: 4 }" | |||
maxlength="2000" | |||
type="textarea" | |||
placeholder="请填写" | |||
/> </el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item label="使用范围" prop="usesRangeRemark"> | |||
<el-cascader | |||
v-model="formData.usesRangeRemark" | |||
:options="useScope" | |||
class="w-full" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="应用简介" | |||
prop="applicationSummary" | |||
><el-input | |||
v-model="formData.applicationSummary" | |||
:autosize="{ minRows: 2, maxRows: 4 }" | |||
maxlength="2000" | |||
type="textarea" | |||
placeholder="请填写" | |||
/> </el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="应用备注" | |||
prop="applicationRemark" | |||
><el-input | |||
v-model="formData.applicationRemark" | |||
:autosize="{ minRows: 2, maxRows: 4 }" | |||
maxlength="2000" | |||
type="textarea" | |||
placeholder="请填写" | |||
/> </el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="应用总投资测算明细" | |||
prop="applicationEstimateFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.applicationEstimateFile" | |||
class="upload-demo" | |||
:action="uploadUrl" | |||
multiple | |||
:on-success="res => handleFileSuccess(res, formData.applicationEstimateFile, false)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="10" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button plain type="primary">选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,185 @@ | |||
<script name="appResourceInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import store from '@/store' | |||
const { | |||
netEnvOptions | |||
} = store.dictStore.globalDicts || {} | |||
const props = defineProps({ | |||
data: { | |||
type: Object, | |||
default: null | |||
} | |||
}), | |||
formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
useGovCloud: [{ required: true, message: '请选择是否使用政务云资源' }], | |||
cloudsType: [{ required: true, message: '请填写云资源类型' }], | |||
cloudsFoundationSpecifications: [{ required: true, message: '请填写云资源基础规格' }], | |||
cloudsNumber: [{ required: true, message: '请填写云资源台数' }], | |||
cloudsDescription: [{ required: true, message: '请填写云资源台数' }], | |||
netEnv: [{ required: true, message: '请选择网络环境' }], | |||
useCommonData: [{ required: true, message: '请选择是否使用公共数据' }], | |||
dataName: [{ required: true, message: '请输入公共数据名称' }], | |||
useCommonComponent: [{ required: true, message: '请选择是否使用公共组件' }], | |||
commonComponents: [{ required: true, message: '请输入公共组件名称' }], | |||
produceCommonComponent: [{ required: true, message: '请选择是否使用公共组件' }], | |||
produceCommonComponents: [{ required: true, message: '请填写预计组件名称' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 清空校验 | |||
clearValidate = () => { | |||
formRef.value.clearValidate() | |||
} | |||
watch( | |||
() => props.data, | |||
val => { | |||
formData.value = { | |||
useGovCloud: props.data.useGovCloud, | |||
cloudsType: props.data.cloudsType, | |||
cloudsFoundationSpecifications: props.data.cloudsFoundationSpecifications, | |||
cloudsNumber: props.data.cloudsNumber, | |||
cloudsDescription: props.data.cloudsDescription, | |||
netEnv: props.data.netEnv, | |||
useCommonData: props.data.useCommonData, | |||
dataName: props.data.dataName, | |||
useCommonComponent: props.data.useCommonComponent, | |||
commonComponents: props.data.commonComponents, | |||
produceCommonComponent: props.data.produceCommonComponent, | |||
produceCommonComponents: props.data.produceCommonComponents | |||
} | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
defineExpose({ validForm, formData, clearValidate }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="20"> | |||
<el-col :span="24"> | |||
<el-form-item label="是否使用政务云资源" prop="useGovCloud"> | |||
<el-radio-group v-model="formData.useGovCloud"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<template v-if="formData.useGovCloud === 1"> | |||
<el-col :span="12"> | |||
<el-form-item label="云资源类型" prop="cloudsType"> | |||
<el-input | |||
v-model="formData.cloudsType" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="云资源基础规格" prop="cloudsFoundationSpecifications"> | |||
<el-input | |||
v-model="formData.cloudsFoundationSpecifications" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="云资源台数" prop="cloudsNumber"> | |||
<el-input | |||
v-model="formData.cloudsNumber" | |||
placeholder="请填写" | |||
maxlength="6" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="云资源用途描述" prop="cloudsDescription"> | |||
<el-input | |||
v-model="formData.cloudsDescription" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<el-col :span="24"> | |||
<el-form-item label="网络环境" prop="netEnv"> | |||
<el-radio-group v-model="formData.netEnv"> | |||
<el-radio v-for="(v,k) in netEnvOptions" :key="k" :label="k*1">{{ v }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="是否使用公共数据" prop="useCommonData"> | |||
<el-radio-group v-model="formData.useCommonData"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item v-if="formData.useCommonData === 1" label="数据名称" prop="dataName"> | |||
<el-input | |||
v-model="formData.dataName" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item label="是否使用公共组件" prop="useCommonComponent"> | |||
<el-radio-group v-model="formData.useCommonComponent"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item v-if="formData.useCommonComponent === 1" label="使用公共组件名称" prop="commonComponents"> | |||
<el-input | |||
v-model="formData.commonComponents" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item label="是否产生公共组件" prop="produceCommonComponent"> | |||
<el-radio-group v-model="formData.produceCommonComponent"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item v-if="formData.produceCommonComponent === 1" label="预计产生组件名称" prop="produceCommonComponents"> | |||
<el-input | |||
v-model="formData.produceCommonComponents" | |||
placeholder="请填写" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,85 @@ | |||
<script name="appSafeInfo" setup> | |||
import { ref, watch } from 'vue' | |||
import store from '@/store' | |||
const { | |||
insuranceLevel | |||
} = store.dictStore.globalDicts || {} | |||
const props = defineProps({ | |||
data: { | |||
type: Object, | |||
default: null | |||
} | |||
}), | |||
formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
secrecyGrade: [{ required: true, message: '请选择等保级别' }], | |||
passwordGrade: [{ required: true, message: '密码测评级别' }], | |||
nationalItSpec: [{ required: true, message: '请选择是否符合相关规范' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 清空校验 | |||
clearValidate = () => { | |||
formRef.value.clearValidate() | |||
} | |||
watch( | |||
() => props.data, | |||
val => { | |||
formData.value = { | |||
secrecyGrade: props.data.secrecyGrade, | |||
passwordGrade: props.data.passwordGrade, | |||
nationalItSpec: props.data.nationalItSpec | |||
} | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
defineExpose({ validForm, formData, clearValidate }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="20"> | |||
<el-col :span="24"> | |||
<el-form-item label="等保级别" prop="secrecyGrade"> | |||
<el-radio-group v-model="formData.secrecyGrade"> | |||
<el-radio v-for="(v,k) in insuranceLevel" :key="k" :label="k*1">{{ v }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="密码测评级别" prop="passwordGrade"> | |||
<el-radio-group v-model="formData.passwordGrade"> | |||
<el-radio v-for="(v,k) in insuranceLevel" :key="k" :label="k*1">{{ v }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="是否符合国家信息技术应用创新相关规范" prop="nationalItSpec"> | |||
<el-radio-group v-model="formData.nationalItSpec"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,330 @@ | |||
<script name="appBasicInfo" setup> | |||
import { watch, ref, getCurrentInstance } from 'vue' | |||
import store from '@/store' | |||
import { applicationList } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
const { | |||
publisher, | |||
insuranceLevel, | |||
applicationType, | |||
accountAppNameOption, | |||
domainBrainAccountOptions | |||
} = store.dictStore.globalDicts || {}, | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
{ proxy } = getCurrentInstance(), | |||
props = defineProps({ | |||
data: { | |||
type: Object, | |||
default: null | |||
}, | |||
drawerVisible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
isFirst: { | |||
type: Number, | |||
default: undefined | |||
}, | |||
coreBusiness: { | |||
type: Array, | |||
default: () => { | |||
return [] | |||
} | |||
} | |||
}), | |||
formData = ref({ | |||
coreBusinessList: [{}] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
applicationName: [ | |||
{ required: true, message: '请填写应用名称' } | |||
], | |||
relatedExistsApplication: [{ required: true, message: '请选择IRS注册应用' }], | |||
relatedExistsApplicationCode: [{ required: true, message: '请选择IRS应用编码' }], | |||
applicationType: [{ required: true, message: '请选择应用类型' }], | |||
publishSide: [{ required: true, message: '请选择发布端' }], | |||
applicationSummary: [{ required: true, message: '请填写应用简介' }], | |||
secrecyGrade: [{ required: true, message: '请选择等保级别' }], | |||
passwordGrade: [{ required: true, message: '请选择密码测评级别' }], | |||
accountAppName: [{ required: true, message: '请选择' }], | |||
domainBrainAccount: [{ required: true, message: '请选择' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate((valid) => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 清空校验 | |||
clearValidate = () => { | |||
formRef.value.clearValidate() | |||
}, | |||
// 获取irs应用列表 | |||
applicationOptions = ref([]), | |||
getApplicationOptions = async () => { | |||
const res = await applicationList({ areaCode: userInfo.value.regionCode }) | |||
applicationOptions.value = res.data | |||
}, | |||
// 修改关联应用 | |||
changeIrsApp = (data) => { | |||
formData.value.relatedExistsApplicationCode = data.applicationCode | |||
}, | |||
// 添加核心业务 | |||
addCore = () => { | |||
if (props.coreBusiness?.length <= formData.value.coreBusinessList?.length) { | |||
proxy.$message.warning(`最多添加${props.coreBusiness?.length || 1}个核心业务`) | |||
return | |||
} | |||
formData.value.coreBusinessList.push({}) | |||
}, | |||
// 删除核心业务 | |||
delCore = (index) => { | |||
formData.value.coreBusinessList.splice(index, 1) | |||
} | |||
watch( | |||
() => props.drawerVisible, | |||
val => { | |||
if (val) { | |||
formData.value = { | |||
...props.data, | |||
coreBusinessList: props.data.coreBusinessList?.length ? props.data.coreBusinessList : [{}] | |||
} | |||
getApplicationOptions() | |||
} | |||
}, | |||
{ immediate: true } | |||
) | |||
watch( | |||
() => props.data, | |||
val => { | |||
formData.value = { | |||
...props.data, | |||
coreBusinessList: props.data.coreBusinessList?.length ? props.data.coreBusinessList : [{}] | |||
} | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
defineExpose({ validForm, formData, clearValidate }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="20"> | |||
<template v-if="(props.isFirst===0&&userInfo.regionCode==='331123')||userInfo.regionCode!=='331123'"> | |||
<el-col :span="12"> | |||
<el-form-item label="关联IRS已注册应用" prop="relatedExistsApplication"> | |||
<el-select | |||
v-model="formData.relatedExistsApplication" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="applicationCode" | |||
@change="changeIrsApp" | |||
> | |||
<el-option | |||
v-for="(item, index) in applicationOptions" | |||
:key="index" | |||
:label="item.applicationName" | |||
:value="{applicationCode:item.applicationCode,applicationName:item.applicationName}" | |||
/> | |||
</el-select> | |||
<p class="text-12 text-danger" style="line-height: 1.4">温馨提示:首次建设项目请先去IRS平台注册后再关联应用</p> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="IRS应用编码" prop="relatedExistsApplicationCode"> | |||
<el-input v-model="formData.relatedExistsApplicationCode" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<el-col v-else :span="12"> | |||
<el-form-item label="应用名称" prop="applicationName"> | |||
<el-input | |||
v-model="formData.applicationName" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="应用类型" prop="applicationType"> | |||
<el-select v-model="formData.applicationType" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in applicationType" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="发布端" prop="publishSide"> | |||
<el-select v-model="formData.publishSide" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in publisher" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="应用简介" | |||
prop="applicationSummary" | |||
><el-input | |||
v-model="formData.applicationSummary" | |||
:autosize="{ minRows: 2, maxRows: 4 }" | |||
maxlength="2000" | |||
type="textarea" | |||
placeholder="请填写" | |||
/> </el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="一本账重大应用名称"> | |||
<el-select | |||
v-model="formData.accountAppName" | |||
placeholder="请选择" | |||
class="w-full" | |||
clearable | |||
> | |||
<el-option | |||
v-for="(item, index) in accountAppNameOption" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="领域“大脑”一本账"> | |||
<el-select v-model="formData.domainBrainAccount" placeholder="请选择" class="w-full"> | |||
<el-option | |||
v-for="(item, index) in domainBrainAccountOptions" | |||
:key="index" | |||
:label="item" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="等保级别" prop="secrecyGrade"> | |||
<el-radio-group v-model="formData.secrecyGrade"> | |||
<el-radio v-for="(v,k) in insuranceLevel" :key="k" :label="k*1">{{ v }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="密码测评级别" prop="passwordGrade"> | |||
<el-radio-group v-model="formData.passwordGrade"> | |||
<el-radio v-for="(v,k) in insuranceLevel" :key="k" :label="k*1">{{ v }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<div | |||
v-for="(item,index) in formData.coreBusinessList" | |||
:key="index" | |||
class="py-24 pr-60 mb-16 relative" | |||
style="background: rgb(245, 248, 250);" | |||
> | |||
<el-row> | |||
<el-col :span="12"> | |||
<el-form-item label="核心业务" :prop="`coreBusinessList[${index}].coreBusiness`" :rules="[{required:true,message:'请选择'}]"> | |||
<el-select v-model="formData.coreBusinessList[index].coreBusiness" placeholder="请选择核心业务" class="w-full"> | |||
<el-option | |||
v-for="(row,key) in props.coreBusiness" | |||
:key="key" | |||
:label="row.matterName" | |||
:value="row.matterName" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="分值" :prop="`coreBusinessList[${index}].score`" :rules="[{required:true,message:'请输入'}]"> | |||
<el-input-number | |||
v-model="formData.coreBusinessList[index].score" | |||
class="input-amount f" | |||
placeholder="请填写" | |||
:min="0.01" | |||
:max="10" | |||
:precision="2" | |||
:controls="false" | |||
@mousewheel.prevent | |||
> | |||
<template #suffix>分</template> | |||
</el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="业务指标名称" :prop="`coreBusinessList[${index}].businessIndicatorName`" :rules="[{required:true,message:'请输入'}]"> | |||
<el-input v-model="formData.coreBusinessList[index].businessIndicatorName" :maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="业务指标描述" :prop="`coreBusinessList[${index}].businessIndicatorDescription`" :rules="[{required:true,message:'请输入'}]"> | |||
<el-input v-model="formData.coreBusinessList[index].businessIndicatorDescription" :maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="指标设计依据" | |||
:prop="`coreBusinessList[${index}].indexDesignBasis`" | |||
style="margin-bottom: 0" | |||
:rules="[{required:true,message:'请输入'}]" | |||
> | |||
<el-input v-model="formData.coreBusinessList[index].indexDesignBasis" :maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="指标计算方法" | |||
:prop="`coreBusinessList[${index}].indexCalculationMethod`" | |||
style="margin-bottom: 0" | |||
:rules="[{required:true,message:'请输入'}]" | |||
> | |||
<el-input v-model="formData.coreBusinessList[index].indexCalculationMethod" :maxlength="50" placeholder="请填写" /> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-button | |||
v-if="formData.coreBusinessList?.length>1" | |||
type="danger" | |||
link | |||
plain | |||
class="absolute top-10 right-8" | |||
@click="delCore(index)" | |||
>删除</el-button> | |||
</div> | |||
<p> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
icon="Plus" | |||
plain | |||
class="ml-80 block" | |||
@click="addCore" | |||
>添加核心业务</el-button> | |||
</p> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,289 @@ | |||
<script name="applications" setup> | |||
import { getCurrentInstance, ref, h, nextTick } from 'vue' | |||
import AppBasicInfo from './appBasicInfo.vue' | |||
import AppSafeInfo from './appSafeInfo.vue' | |||
import AppResourceInfo from './appResourceInfo.vue' | |||
import { ElMessageBox } from 'element-plus' | |||
import { useRoute } from 'vue-router' | |||
import ApplicationInfo from '@/pages/declareManage/projectDeclare/declarePage/components/applicationInfo.vue' | |||
defineProps({ | |||
isInnovateWholeProvinceShare: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
isFirst: { | |||
type: Number, | |||
default: undefined | |||
}, | |||
coreBusiness: { | |||
type: Array, | |||
default: () => { | |||
return [] | |||
} | |||
} | |||
}) | |||
const route = useRoute(), | |||
{ proxy } = getCurrentInstance(), | |||
formData = ref({ | |||
applicationList: [] | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
includeApplication: [ | |||
{ required: true, message: '请选择是否包含应用', trigger: 'blur' } | |||
], | |||
applicationList: [ | |||
{ required: true, message: '请添加应用', trigger: 'blur' } | |||
] | |||
}, | |||
column = [ | |||
{ | |||
type: 'index', | |||
label: '序号', | |||
width: 60 | |||
}, | |||
{ | |||
label: '应用名称', | |||
key: 'applicationName', | |||
prop: 'applicationName', | |||
render: row => h('span', row.applicationName || row.relatedExistsApplication?.applicationName || '') | |||
}, | |||
// { | |||
// label: '数改系统', | |||
// key: 'digitalModification', | |||
// prop: 'digitalModification', | |||
// render: row => h('span', row.digitalModification?.map(i => digitalModifySystem[i]).join(',')) | |||
// }, | |||
{ | |||
label: '操作', | |||
slot: 'action' | |||
} | |||
], | |||
// 删除应用 | |||
deleteApplication = (index) => { | |||
proxy.$messageBox | |||
.confirm('确定要删除该项吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(() => { | |||
formData.value.applicationList.splice(index, 1) | |||
}) | |||
}, | |||
// 编辑、新增应用 | |||
drawerVisible = ref(false), | |||
collapseModal = ref(['1', '2', '3']), | |||
applicationData = ref({}), | |||
appBasicInfoRef = ref(), | |||
appSafeInfoRef = ref(), | |||
appResourceInfoRef = ref(), | |||
applicationInfoRef = ref(), | |||
isEdit = ref(false), | |||
appIndex = ref(), | |||
editApplication = async (index, row) => { | |||
isEdit.value = true | |||
appIndex.value = index | |||
applicationData.value = row | |||
drawerVisible.value = true | |||
await nextTick() | |||
applicationInfoRef.value.clearValidate() | |||
}, | |||
addApplication = async () => { | |||
isEdit.value = false | |||
applicationData.value = {} | |||
drawerVisible.value = true | |||
await nextTick() | |||
applicationInfoRef.value.clearValidate() | |||
}, | |||
handleDrawerClose = () => { | |||
ElMessageBox.confirm('确定要关闭应用编辑页面吗?') | |||
.then(() => { | |||
close() | |||
}) | |||
.catch(() => { | |||
}) | |||
}, | |||
close = () => { | |||
// appSafeInfoRef.value.clearValidate() | |||
// appResourceInfoRef.value.clearValidate() | |||
// appBasicInfoRef.value.clearValidate() | |||
applicationInfoRef.value.formData = {} | |||
applicationInfoRef.value.clearValidate() | |||
drawerVisible.value = false | |||
}, | |||
// 暂存 | |||
save = () => { | |||
if (!isEdit.value) { | |||
formData.value.applicationList.push({ | |||
// ...appBasicInfoRef.value.formData, | |||
// ...appSafeInfoRef.value.formData, | |||
// ...appResourceInfoRef.value.formData | |||
...applicationInfoRef.value.formData | |||
}) | |||
} else { | |||
formData.value.applicationList[appIndex.value] = { | |||
// ...appBasicInfoRef.value.formData, | |||
// ...appSafeInfoRef.value.formData, | |||
// ...appResourceInfoRef.value.formData | |||
...applicationInfoRef.value.formData | |||
} | |||
} | |||
close() | |||
}, | |||
// 提交 | |||
submitApplication = () => { | |||
const form = [] | |||
// form.push(new Promise((resolve, reject) => { | |||
// appBasicInfoRef.value.validForm((valid) => { | |||
// if (valid) resolve() | |||
// }) | |||
// })) | |||
// form.push(new Promise((resolve, reject) => { | |||
// appSafeInfoRef.value.validForm((valid) => { | |||
// if (valid) resolve() | |||
// }) | |||
// })) | |||
// form.push(new Promise((resolve, reject) => { | |||
// appResourceInfoRef.value.validForm((valid) => { | |||
// if (valid) resolve() | |||
// }) | |||
// })) | |||
form.push(new Promise((resolve, reject) => { | |||
applicationInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
Promise.all([...form]).then(() => { | |||
save() | |||
}) | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
const appname = route.query.isDraft ? 'applicationList' : 'projectApplications' | |||
formData.value = { | |||
includeApplication: data.includeApplication, | |||
applicationList: data[appname]?.length ? data[appname].map(i => { | |||
return { | |||
...i, | |||
relatedExistsApplication: i.relatedExistsApplication ? { applicationCode: i.relatedExistsApplicationCode, applicationName: i.relatedExistsApplication } : undefined | |||
} | |||
}) : [] | |||
} | |||
}, | |||
// 修改是否包含应用 | |||
changeIncludeApplication = () => { | |||
formData.value.applicationList = [] | |||
} | |||
defineExpose({ validForm, formData, applicationData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="是否包含应用" | |||
label-width="atuo" | |||
prop="includeApplication" | |||
> | |||
<el-radio-group v-model="formData.includeApplication" @change="changeIncludeApplication"> | |||
<el-radio :label="1">是</el-radio> | |||
<el-radio :label="0">否</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="formData.includeApplication === 1" :span="24"> | |||
<el-form-item label="包含的应用" prop="applicationList"> | |||
<el-button | |||
type="primary" | |||
plain | |||
class="w-full mb-10" | |||
icon="Plus" | |||
@click="addApplication" | |||
>添加应用</el-button> | |||
<table-list | |||
class="w-full" | |||
:pagination="false" | |||
:data="formData.applicationList" | |||
:column="column" | |||
> | |||
<template #action="{scope}"> | |||
<a | |||
@click="editApplication(scope.$index, scope.row)" | |||
>编辑</a> | |||
<a | |||
class="text-red-400" | |||
@click="deleteApplication(scope.$index)" | |||
>删除</a> | |||
</template> | |||
</table-list> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<el-drawer | |||
v-model="drawerVisible" | |||
title="添加应用" | |||
:before-close="handleDrawerClose" | |||
:size="1000" | |||
> | |||
<el-collapse v-if="false" v-model="collapseModal"> | |||
<el-collapse-item name="1"> | |||
<template #title> | |||
<div class="collapse-title">基本信息</div> | |||
</template> | |||
<app-basic-info | |||
ref="appBasicInfoRef" | |||
:data="applicationData" | |||
:is-innovate-whole-province-share="isInnovateWholeProvinceShare" | |||
:drawer-visible="drawerVisible" | |||
/> | |||
</el-collapse-item> | |||
<el-collapse-item name="2"> | |||
<template #title> | |||
<div class="collapse-title">安全信息</div> | |||
</template> | |||
<app-safe-info ref="appSafeInfoRef" :data="applicationData" /> | |||
</el-collapse-item> | |||
<el-collapse-item name="3"> | |||
<template #title> | |||
<div class="collapse-title">资源信息</div> | |||
</template> | |||
<app-resource-info ref="appResourceInfoRef" :data="applicationData" /> | |||
</el-collapse-item> | |||
</el-collapse> | |||
<application-info | |||
ref="applicationInfoRef" | |||
:data="applicationData" | |||
:is-first="isFirst" | |||
:core-business="coreBusiness" | |||
:drawer-visible="drawerVisible" | |||
/> | |||
<template #footer> | |||
<div class="applyBottomBtn flexCenter marginTop"> | |||
<el-button @click="handleDrawerClose"> 关闭 </el-button> | |||
<el-button type="primary" plain @click="save"> 暂存 </el-button> | |||
<el-button type="primary" @click="submitApplication"> 确定 </el-button> | |||
</div> | |||
</template> | |||
</el-drawer> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,189 @@ | |||
<script name="coreBusiness" setup> | |||
import { reactive, ref, nextTick } from 'vue' | |||
import { getCoreBusinessData } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const props = defineProps({ | |||
basicInfoData: { | |||
type: Object | |||
} | |||
}) | |||
const userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
coreBusiness: [{ required: true, message: '请至少选择一个核心业务' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 选择核心业务 | |||
selectCoreBusiness = () => { | |||
coreBusinessvisible.value = true | |||
getCoreBusinessTableData({ pageNumber: 1, pageSize: 10 }, true) | |||
}, | |||
column = [ | |||
{ | |||
type: 'index', | |||
label: '序号', | |||
width: 60 | |||
}, | |||
// { | |||
// label: '业务编号', | |||
// key: 'oid', | |||
// prop: 'oid' | |||
// }, | |||
{ | |||
label: '业务名称', | |||
key: 'matterName', | |||
prop: 'matterName' | |||
}, | |||
{ | |||
label: '所属单位', | |||
key: 'orgName', | |||
prop: 'orgName' | |||
} | |||
], | |||
tableListRef = ref(), | |||
coreBusinessData = ref([]), | |||
coreBusinesstotal = ref(0), | |||
column2 = [ | |||
{ | |||
type: 'selection' | |||
}, | |||
// { | |||
// label: '业务编号', | |||
// prop: 'oid', | |||
// key: 'oid' | |||
// }, | |||
{ | |||
label: '业务名称', | |||
prop: 'matterName', | |||
key: 'matterName' | |||
}, | |||
{ | |||
label: '所属单位', | |||
prop: 'orgName', | |||
key: 'orgName' | |||
} | |||
], | |||
coreBusinessvisible = ref(false), | |||
getCoreBusinessTableData = async (pageParams = tableListRef.value?.pageParams, flag) => { | |||
var orgCode = [] | |||
props?.basicInfoData?.superOrgCode && orgCode.push(props.basicInfoData.superOrgCode) | |||
userInfo.value?.empPosUnitCode && orgCode.push(userInfo.value.empPosUnitCode) | |||
const res = await getCoreBusinessData({ | |||
...pageParams, | |||
businessName: coreBusinessParams.businessName, | |||
orgCode: orgCode.join(',') | |||
}) | |||
coreBusinessData.value = res.data.data | |||
coreBusinesstotal.value = res.data.total | |||
await nextTick() | |||
if (flag) { | |||
coreBusinessData.value && coreBusinessData.value.forEach(item => { | |||
const dataIds = formData.value.coreBusiness && formData.value.coreBusiness.map(i => i.id) || [] | |||
if (dataIds.includes(item.id)) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} else { | |||
tableListRef.value.toggleRowSelect(item, false) | |||
} | |||
}) | |||
} | |||
}, | |||
searchCoreBussiness = () => { | |||
getCoreBusinessTableData() | |||
}, | |||
coreBusinessTempotary = ref(), | |||
selectionCoreBusinessChange = (data) => { | |||
coreBusinessTempotary.value = data | |||
}, | |||
coreBusinessParams = reactive({ | |||
businessName: undefined | |||
}), | |||
handleReset = () => { | |||
coreBusinessParams.businessName = '' | |||
}, | |||
confirmCoreBusiness = () => { | |||
formData.value.coreBusiness = coreBusinessTempotary.value | |||
coreBusinessvisible.value = false | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
coreBusiness: data.coreBusiness ? JSON.parse(data.coreBusiness) : [] | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="0" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24" class="mb-16"> | |||
<el-button type="primary" class="float-right" @click="selectCoreBusiness"> | |||
选择核心业务 | |||
</el-button> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item prop="coreBusiness"> | |||
<table-list | |||
:pagination="false" | |||
style="width: 100%" | |||
:column="column" | |||
:data="formData.coreBusiness" | |||
:empty-temp="false" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<el-dialog | |||
title="选择核心业务" | |||
:close-on-click-modal="false" | |||
:before-close="()=>coreBusinessvisible=false" | |||
:model-value="coreBusinessvisible" | |||
width="700px" | |||
> | |||
<el-row style="margin-bottom: 16px" :gutter="20"> | |||
<el-col :span="12"> | |||
<el-input v-model="coreBusinessParams.businessName" placeholder="请输入" /> | |||
</el-col> | |||
<el-col :span="12"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="searchCoreBussiness">查询</el-button> | |||
<el-button @click="handleReset">重置</el-button> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column2" | |||
:data="coreBusinessData" | |||
:total="coreBusinesstotal" | |||
@selection-change="selectionCoreBusinessChange" | |||
@get-table-data="getCoreBusinessTableData" | |||
/> | |||
<template #footer> | |||
<el-button type="primary" @click="confirmCoreBusiness"> 提交 </el-button> | |||
<el-button @click="coreBusinessvisible = false"> 关闭 </el-button> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,81 @@ | |||
<script name="fundsAllocation" setup> | |||
import { ref } from 'vue' | |||
const formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
softwareDevelopmentAmount: [{ required: true, message: '请输入软件开发', trigger: 'blur' }], | |||
cloudHardwarePurchaseAmount: [ | |||
{ required: true, message: '请输入云资源、硬件配置', trigger: 'blur' } | |||
], | |||
thirdPartyAmount: [{ required: true, message: '请输入第三方服务', trigger: 'blur' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
softwareDevelopmentAmount: data.softwareDevelopmentAmount, | |||
cloudHardwarePurchaseAmount: data.cloudHardwarePurchaseAmount, | |||
thirdPartyAmount: data.thirdPartyAmount | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="8"> | |||
<el-form-item label="软件开发" prop="softwareDevelopmentAmount"> | |||
<el-input-number | |||
v-model="formData.softwareDevelopmentAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="云资源、硬件配置" prop="cloudHardwarePurchaseAmount"> | |||
<el-input-number | |||
v-model="formData.cloudHardwarePurchaseAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="第三方服务" prop="thirdPartyAmount"> | |||
<el-input-number | |||
v-model="formData.thirdPartyAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,189 @@ | |||
<script name="fundsInfo" setup> | |||
import { ref } from 'vue' | |||
defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => { | |||
return {} | |||
} | |||
} | |||
}) | |||
const formData = ref({ | |||
}), | |||
formRef = ref(), | |||
moneyValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
rules = { | |||
projectYear: [{ required: true, message: '请选择预算年度' }], | |||
declareAmount: [{ required: true, message: '请输入申报金额', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
declareHaveAmount: [{ required: true, message: '请输入自有资金', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
declareGovOwnFinanceAmount: [ | |||
{ | |||
required: true, | |||
message: '请输入政府投资-本级财政资金', | |||
trigger: 'blur' | |||
}, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
declareGovSuperiorFinanceAmount: [ | |||
{ | |||
required: true, | |||
message: '请输入政府投资-上级补助资金', | |||
trigger: 'blur' | |||
}, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
declareBankLendingAmount: [{ required: true, message: '请输入银行贷款', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
declareOtherAmount: [{ required: true, message: '请输入其他资金', trigger: 'blur' }, { validator: moneyValidator, trigger: 'blur' }], | |||
consultancy: [{ required: true, message: '请填写咨询公司' }], | |||
baseBasisAmountOri: [{ required: true, message: '请填写预算来源说明' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
projectYear: data.projectYear ? data.projectYear + '' : null, | |||
declareAmount: data.declareAmount, | |||
declareHaveAmount: data.declareHaveAmount, | |||
declareGovOwnFinanceAmount: data.declareGovOwnFinanceAmount, | |||
declareGovSuperiorFinanceAmount: data.declareGovSuperiorFinanceAmount, | |||
declareBankLendingAmount: data.declareBankLendingAmount, | |||
declareOtherAmount: data.declareOtherAmount, | |||
baseBasisAmountOri: data.baseBasisAmountOri || '', | |||
consultancy: data.consultancy || '' | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item label="预算年度" prop="projectYear"> | |||
<el-date-picker | |||
v-model="formData.projectYear" | |||
:disabled="$route.name==='declarePlan'||[10012,10013,10016].includes(detailData?.status)" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="申报金额" prop="declareAmount"> | |||
<el-input-number | |||
v-model="formData.declareAmount" | |||
placeholder="请填写" | |||
:min="0.000001" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="自有资金" prop="declareHaveAmount"> | |||
<el-input-number | |||
v-model="formData.declareHaveAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="政府投资-本级财政资金" prop="declareGovOwnFinanceAmount"> | |||
<el-input-number | |||
v-model="formData.declareGovOwnFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="政府投资-上级补助资金" prop="declareGovSuperiorFinanceAmount"> | |||
<el-input-number | |||
v-model="formData.declareGovSuperiorFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
><template #append>万元</template></el-input-number> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="银行贷款" prop="declareBankLendingAmount"> | |||
<el-input-number | |||
v-model="formData.declareBankLendingAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="其他资金" prop="declareOtherAmount"> | |||
<el-input-number | |||
v-model="formData.declareOtherAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="($route.name==='declarePlan'||[10012,10013,10016].includes(detailData?.status))&&formData.declareAmount>400" :span="12"> | |||
<el-form-item label="咨询公司" prop="consultancy"> | |||
<el-input | |||
v-model="formData.consultancy" | |||
placeholder="请填写" | |||
maxlength="100" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="formData.declareOtherAmount>0" :span="24"> | |||
<el-form-item label="预算来源说明" prop="baseBasisAmountOri"> | |||
<el-input | |||
v-model="formData.baseBasisAmountOri" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请填写" | |||
:maxlength="150" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,106 @@ | |||
<script setup name="hiddenAppForm"> | |||
import { nextTick, ref, watch } from 'vue' | |||
// import appBasicInfo from './appBasicInfo.vue' | |||
// import appSafeInfo from './appSafeInfo.vue' | |||
// import appResourceInfo from './appResourceInfo.vue' | |||
import ApplicationInfo from '@/pages/declareManage/projectDeclare/declarePage/components/applicationInfo.vue' | |||
const props = defineProps({ | |||
applicationList: Array, | |||
isFirst: { | |||
type: Number, | |||
default: undefined | |||
} | |||
}), | |||
// appBasicInfoRef = ref(), | |||
// appSafeInfoRef = ref(), | |||
// appResourceInfoRef = ref(), | |||
applicationInfoRef = ref(), | |||
applicationData = ref([]), | |||
validCount = ref(0), | |||
drawerVisible = ref(), | |||
validAllAppForm = async (callback) => { | |||
drawerVisible.value = true | |||
validCount.value = 0 | |||
for (const item of props.applicationList) { // 不能用forEach,因为不会等异步的执行完成才执行下一条 | |||
await doAsyncOperation(item) | |||
} | |||
setTimeout(async () => { | |||
drawerVisible.value = false | |||
callback(validCount.value === props.applicationList.length) | |||
}) | |||
}, | |||
doAsyncOperation = async (data) => { | |||
applicationData.value = JSON.parse(JSON.stringify(data)) | |||
await nextTick() // 必须nextTick,不然赋值视图上不会更新 | |||
return new Promise((resolve, reject) => { | |||
const form = [] | |||
// form.push(new Promise((resolve, reject) => { | |||
// appBasicInfoRef.value.validForm((valid) => { | |||
// if (valid) { | |||
// resolve() | |||
// } else { | |||
// reject(false) | |||
// } | |||
// }) | |||
// })) | |||
// form.push(new Promise((resolve, reject) => { | |||
// appSafeInfoRef.value.validForm((valid) => { | |||
// if (valid) { | |||
// resolve() | |||
// } else { | |||
// reject(false) | |||
// } | |||
// }) | |||
// })) | |||
// form.push(new Promise((resolve, reject) => { | |||
// appResourceInfoRef.value.validForm((valid) => { | |||
// if (valid) { | |||
// resolve() | |||
// } else { | |||
// reject(false) | |||
// } | |||
// }) | |||
// })) | |||
form.push(new Promise((resolve, reject) => { | |||
applicationInfoRef.value.validForm((valid) => { | |||
if (valid) { | |||
resolve() | |||
} else { | |||
reject(false) | |||
} | |||
}) | |||
})) | |||
Promise.all([...form]).then(() => { | |||
validCount.value++ | |||
}).finally(() => { | |||
resolve() | |||
}) | |||
}) | |||
} | |||
watch( | |||
() => props.applicationList, | |||
() => { | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
defineExpose({ validAllAppForm }) | |||
</script> | |||
<template> | |||
<div style="display: none"> | |||
<!-- <app-basic-info--> | |||
<!-- ref="appBasicInfoRef"--> | |||
<!-- :data="applicationData"--> | |||
<!-- :drawer-visible="drawerVisible"--> | |||
<!-- :is-innovate-whole-province-share="isInnovateWholeProvinceShare"--> | |||
<!-- />--> | |||
<!-- <app-safe-info ref="appSafeInfoRef" :data="applicationData" />--> | |||
<!-- <app-resource-info ref="appResourceInfoRef" :data="applicationData" />--> | |||
<application-info | |||
ref="applicationInfoRef" | |||
:data="applicationData" | |||
:is-first="isFirst" | |||
/> | |||
</div> | |||
</template> |
@@ -0,0 +1,103 @@ | |||
<script name="newModuleForm" setup> | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import { onMounted, ref } from 'vue' | |||
import store from '@/store' | |||
const | |||
uploadUrl = store.dictStore.uploadUrl, | |||
props = defineProps({ | |||
data: { | |||
type: Object, | |||
default: null | |||
} | |||
}), | |||
formData = ref({ | |||
formList: [] | |||
}), | |||
formRef = ref(), | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
} | |||
onMounted(() => { | |||
formData.value = props.data | |||
}) | |||
defineExpose({ validForm, formData }) | |||
</script> | |||
<template> | |||
<el-form | |||
v-if="formData&&formData.formList?.length" | |||
ref="formRef" | |||
:model="formData" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
@submit.prevent | |||
> | |||
<el-row :gutter="40"> | |||
<el-col | |||
v-for="(eachForm,order) in props.data&&props.data.formList" | |||
:key="order" | |||
:span="12" | |||
> | |||
<el-form-item | |||
:label="eachForm.name" | |||
:prop="`formList[${order}].value`" | |||
:rules="[{ | |||
required:eachForm.props.required, | |||
message:'请完善必填内容' | |||
}]" | |||
> | |||
<el-input | |||
v-if="eachForm.props.type === '输入'" | |||
v-model="formData.formList[order].value" | |||
placeholder="请输入" | |||
:maxlength="eachForm.props.maxLength" | |||
/> | |||
<el-input-number | |||
v-else-if="eachForm.props.type === '数值输入'" | |||
v-model="formData.formList[order].value" | |||
placeholder="请输入" | |||
:min="eachForm.props.minNumber" | |||
:max="eachForm.props.maxNumber" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
<el-radio-group v-else-if="eachForm.props.type === '单选'" v-model="formData.formList[order].value"> | |||
<el-radio v-for="( radioOption,radioIndex ) in eachForm.props.options" :key="radioIndex" :label="radioOption.name">{{ radioOption.name }}</el-radio> | |||
</el-radio-group> | |||
<el-checkbox-group v-else-if="eachForm.props.type === '多选'" v-model="formData.formList[order].value"> | |||
<el-checkbox v-for="( checkboxOption,checkboxIndex ) in eachForm.props.options" :key="checkboxIndex" :label="checkboxOption.name">{{ checkboxOption.name }}</el-checkbox> | |||
</el-checkbox-group> | |||
<el-upload | |||
v-else | |||
v-model:file-list="formData.formList[order].value" | |||
class="w-full" | |||
:limit="eachForm.props.fileNumber" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.formList[order].value, false)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,92 @@ | |||
<script name="safetyInput" setup> | |||
import { ref } from 'vue' | |||
const formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
engineeringSpeedOne: [ | |||
{ required: true, message: '请填写第一季度进度', trigger: 'blur' } | |||
], | |||
engineeringSpeedTwo: [ | |||
{ required: true, message: '请填写第二季度进度', trigger: 'blur' } | |||
], | |||
engineeringSpeedThree: [ | |||
{ required: true, message: '请填写第三季度进度', trigger: 'blur' } | |||
], | |||
engineeringSpeedFour: [ | |||
{ required: true, message: '请填写第四季度进度', trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
engineeringSpeedOne: data.engineeringSpeedOne, | |||
engineeringSpeedTwo: data.engineeringSpeedTwo, | |||
engineeringSpeedThree: data.engineeringSpeedThree, | |||
engineeringSpeedFour: data.engineeringSpeedFour | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item label="第一季度" prop="engineeringSpeedOne"> | |||
<el-input | |||
v-model="formData.engineeringSpeedOne" | |||
maxlength="50" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="第二季度" prop="engineeringSpeedTwo"> | |||
<el-input | |||
v-model="formData.engineeringSpeedTwo" | |||
maxlength="50" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="第三季度" prop="engineeringSpeedThree"> | |||
<el-input | |||
v-model="formData.engineeringSpeedThree" | |||
maxlength="50" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="第四季度" prop="engineeringSpeedFour"> | |||
<el-input | |||
v-model="formData.engineeringSpeedFour" | |||
maxlength="50" | |||
placeholder="请填写" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,53 @@ | |||
<script name="projectRemark" setup> | |||
import { ref } from 'vue' | |||
const formData = ref({}), | |||
formRef = ref(), | |||
rules = {}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
projectRemarks: data.projectRemarks | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="备注" | |||
> | |||
<el-input | |||
v-model="formData.projectRemarks" | |||
maxlength="2000" | |||
type="textarea" | |||
placeholder="请填写" | |||
show-word-limit | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,179 @@ | |||
<script name="provincialExamine" setup> | |||
import { nextTick, reactive, ref } from 'vue' | |||
import { govStripList } from '@/http/apis/declareMange' | |||
const formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
operationManageUnitName: [{ required: true, message: '请选择业务主管部门' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
operationManageUnit: data.operationManageUnit, | |||
operationManageUnitName: '' | |||
} | |||
if (data.operationManageUnit) { | |||
getTableData(true) | |||
} | |||
}, | |||
dialogVisible = ref(false), | |||
tableListRef = ref(), | |||
searchForm = reactive({ | |||
businessStripName: undefined | |||
}), | |||
showDialog = async () => { | |||
dialogVisible.value = true | |||
getTableData() | |||
}, | |||
column = [ | |||
{ | |||
type: 'selection', | |||
key: 'businessStripCode', | |||
width: '60' | |||
}, | |||
{ | |||
label: '单位名称', | |||
key: 'businessStripName', | |||
prop: 'businessStripName', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '单位编码', | |||
key: 'businessStripCode', | |||
prop: 'businessStripCode', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
} | |||
], | |||
tableData = ref(), | |||
getTableData = async (flag) => { | |||
const res = await govStripList({ ...searchForm }) | |||
tableData.value = res.data | |||
await nextTick() | |||
const operationManageUnitName = [] | |||
tableData.value && tableData.value.forEach(item => { | |||
const dataIds = formData.value?.operationManageUnit?.split(',') || [] | |||
if (dataIds.includes(item.businessStripCode)) { | |||
if (!flag) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} else { | |||
operationManageUnitName.push(item.businessStripName) | |||
} | |||
} | |||
}) | |||
if (flag) { | |||
formData.value.operationManageUnitName = operationManageUnitName.join(',') || '' | |||
} | |||
}, | |||
reset = () => { | |||
searchForm.businessStripName = undefined | |||
getTableData() | |||
}, | |||
selectUnit = ref([]), | |||
selectionChange = (val) => { | |||
selectUnit.value = val | |||
}, | |||
submit = () => { | |||
dialogVisible.value = false | |||
formData.value.operationManageUnitName = selectUnit.value.map(i => i.businessStripName).join(',') | |||
formData.value.operationManageUnit = selectUnit.value.map(i => i.businessStripCode).join(',') | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="24"> | |||
<el-form-item label="业务主管部门(省级)" prop="operationManageUnitName"> | |||
<el-input | |||
v-model="formData.operationManageUnitName" | |||
placeholder="请选择" | |||
readonly | |||
@click="showDialog" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<el-dialog | |||
:model-value="dialogVisible" | |||
title="上级条线主管单位" | |||
width="60%" | |||
@close="dialogVisible = false" | |||
> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
class="mb-16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="单位名称"> | |||
<el-input | |||
v-model="searchForm.businessStripName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="16"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="getTableData" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:pagination="false" | |||
style="height: 600px;overflow: auto" | |||
@get-table-data="getTableData" | |||
@selection-change="selectionChange" | |||
/> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button @click="dialogVisible = false">关闭</el-button> | |||
<el-button | |||
type="primary" | |||
@click="submit" | |||
> | |||
提交 | |||
</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,81 @@ | |||
<script name="reviewCheck" setup> | |||
import { ref } from 'vue' | |||
const props = defineProps({ | |||
detailData: { | |||
type: Object, | |||
default: () => { | |||
return {} | |||
} | |||
}, | |||
data: { | |||
type: Array, | |||
default: () => [] | |||
} | |||
}) | |||
const formData = ref({ | |||
reviewChecklist: props.data | |||
}), | |||
formRef = ref(), | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
reviewChecklist: data.reviewChecklist | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
label-suffix=":" | |||
label-position="top" | |||
scroll-to-error | |||
> | |||
<template v-for="(item,index) in formData.reviewChecklist" :key="index"> | |||
<p class="font-bold text-16">{{ item.title }}</p> | |||
<template v-for="(child,key) in item.modules" :key="key"> | |||
<el-row :gutter="16" class="items-center"> | |||
<el-col :span="9"> | |||
<el-form-item :label="child.subTitle"> | |||
<el-input v-model="child.content" type="textarea" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="否决情形"> | |||
<el-input v-model="child.rejectionSituation" type="textarea" disabled /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="9"> | |||
<el-form-item | |||
label="响应情况" | |||
class="flex-form-item" | |||
style="margin-bottom: 14px" | |||
:prop="`reviewChecklist[${index}].modules[${key}].responseSituation`" | |||
:rules="[{required:true,message:'请输入'}]" | |||
> | |||
<el-input v-model="child.responseSituation" /> | |||
</el-form-item> | |||
<el-form-item | |||
label="对应页面" | |||
class="flex-form-item" | |||
style="margin-bottom: 0" | |||
:prop="`reviewChecklist[${index}].modules[${key}].corrPageNum`" | |||
:rules="[{required:true,message:'请输入'}]" | |||
> | |||
<el-input v-model="child.corrPageNum" /> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
</template> | |||
</el-form> | |||
</template> |
@@ -0,0 +1,143 @@ | |||
<script name="safetyInput" setup> | |||
import { ref, getCurrentInstance } from 'vue' | |||
const { proxy } = getCurrentInstance(), | |||
formData = ref({ | |||
safetyInput: [{}] | |||
}), | |||
formRef = ref(), | |||
moneyValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
rules = { | |||
safetyInputTitle: [ | |||
{ required: true, message: '请输入投入项', trigger: 'blur' } | |||
], | |||
safetyInputDescribe: [ | |||
{ required: true, message: '请输入内容描述', trigger: 'blur' } | |||
], | |||
safetyInputAmount: [ | |||
{ required: true, message: '请输入金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
safetyInput: data.safetyInputDescribe ? JSON.parse(data.safetyInputDescribe) : [{}] | |||
} | |||
}, | |||
// 添加 | |||
add = () => { | |||
if (formData.value.safetyInput.length >= 10) { | |||
proxy.$message.warning('最多添加10项') | |||
return | |||
} | |||
formData.value.safetyInput.push({}) | |||
}, | |||
// 删除 | |||
del = (index) => { | |||
formData.value.safetyInput.splice(index, 1) | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<div | |||
v-for="(item,index) in formData.safetyInput" | |||
:key="index" | |||
style="background: #f5f8fa" | |||
class="p-8 mb-16 relative" | |||
> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="投入项" | |||
:prop="`safetyInput[${index}].safetyInputTitle`" | |||
:rules="{ | |||
required: true, | |||
message: '请输入', | |||
}" | |||
> | |||
<el-input | |||
v-model="formData.safetyInput[index].safetyInputTitle" | |||
placeholder="请输入" | |||
:maxlength="50" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="内容描述" | |||
:prop="`safetyInput[${index}].safetyInputDescribe`" | |||
:rules="{ | |||
required: true, | |||
message: '请输入', | |||
}" | |||
> | |||
<el-input | |||
v-model="formData.safetyInput[index].safetyInputDescribe" | |||
:rows="4" | |||
maxlength="2000" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="金额(万元)" | |||
:prop="`safetyInput[${index}].safetyInputDescribe`" | |||
:rules="{ | |||
required: true, | |||
message: '请输入', | |||
}" | |||
> | |||
<el-input-number | |||
v-model="formData.safetyInput[index].safetyInputAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<span v-if="formData.safetyInput.length>1" class="text-danger absolute right-8 top-8 cursor-pointer" @click="del(index)">删除</span> | |||
</div> | |||
<el-button | |||
type="primary" | |||
icon="Plus" | |||
plain | |||
@click="add" | |||
>添加投入项</el-button> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.el-upload-list{ | |||
width: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,870 @@ | |||
<script name="declarePage" setup> | |||
import { getCurrentInstance, nextTick, onMounted, reactive, ref } from 'vue' | |||
import { getFormConfig } from '@/http/apis/systemManage/formConfiguration' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
import BasicInfo from './components/basicInfo.vue' | |||
import FundsInfo from './components/fundsInfo.vue' | |||
import FundsAllocation from './components/fundsAllocation.vue' | |||
import AnnualPaymentPlan from './components/annualPaymentPlan.vue' | |||
import CoreBusiness from './components/coreBusiness.vue' | |||
import SafetyInput from './components/safetyInput.vue' | |||
import ProjectImageProgress from './components/projectImageProgress.vue' | |||
import Accessory from './components/accessory.vue' | |||
import ProjectRemark from './components/projectRemark.vue' | |||
import NewModuleForm from './components/newModuleForm.vue' | |||
import Applications from './components/applications.vue' | |||
import HiddenAppForm from './components/hiddenAppForm.vue' | |||
import FlowRecordDialog from '@/pages/projectStoreManage/projectStore/projectDetail/components/flowRecordDialog.vue' | |||
import { declareConstructionScheme, getDraftDetail, projectStart, saveDraft } from '@/http/apis/declareMange' | |||
import { projectDetail } from '@/http/apis/projectStoreManage/projectStore' | |||
import { annualPlanModify } from '@/http/apis/projectStoreManage/annualPlanStore' | |||
import { adjustAndHandle, progressDetail } from '@/http/apis/toDoCenter/todoList' | |||
import { changFilesParam, reviewFileParam } from '@/utils/uploadAction' | |||
import { dictionary } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
import ReviewCheck from '@/pages/declareManage/projectDeclare/declarePage/components/reviewCheck.vue' | |||
import { getIsShowReviewCheck } from '@/utils/getIsShowReviewCheck' | |||
import ProvincialExamine from '@/pages/declareManage/projectDeclare/declarePage/components/provincialExamine.vue' | |||
const { proxy } = getCurrentInstance(), | |||
route = useRoute(), | |||
router = useRouter(), | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
formConfig = ref({}), | |||
collapseModal = ref(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']), | |||
basicInfoRef = ref(), // 基本信息 | |||
fundsInfoRef = ref(), // 资金申报情况 | |||
fundsAllocationRef = ref(), // 资金分配情况 | |||
provincialExamineRef = ref(), // 重大项目省级联审 | |||
annualPaymentPlanRef = ref(), // 年度计划支付 | |||
coreBusinessRef = ref(), // 核心业务 | |||
safetyInputRef = ref(), // 安全投入 | |||
projectImageProgressRef = ref(), // 工程形象进度 | |||
accessoryRef = ref(), // 附件 | |||
projectRemarkRef = ref(), // 备注 | |||
newModuleformRef = ref({}), // 新增模块 | |||
applicationsRef = ref(), // 应用 | |||
hiddenAppFormRef = ref(), | |||
reviewCheckRef = ref(), // 审查清单 | |||
// 提交 | |||
submitAllForm = () => { | |||
const form = [] | |||
if (basicInfoRef.value.formData?.baseProjIsConfidentiality === '02') { | |||
form.push(new Promise((resolve, reject) => { | |||
basicInfoRef.value.validForm((valid) => { | |||
if (valid) { | |||
resolve() | |||
} | |||
}) | |||
})) | |||
} else { | |||
form.push(new Promise((resolve, reject) => { | |||
basicInfoRef.value.validForm((valid) => { | |||
if (valid) { | |||
if (fundsInfoRef.value.formData.declareAmount >= 1000 && basicInfoRef.value.formData.baseProvManDeprtType === '2') { | |||
basicInfoRef.value.formData.baseProvManDeprtType = '' | |||
reject('根据《浙江省电子政务重大应用项目联审》要求:大于1000万元的重大项目将由省级数改牵头部门及业务主管单位进行联审,请将上级主管单位修改为您对应条线的省级主管单位。') | |||
} else { | |||
resolve() | |||
} | |||
} | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
fundsInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
fundsAllocationRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
annualPaymentPlanRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
formConfig.value.isCoreBusiness && form.push(new Promise((resolve, reject) => { | |||
coreBusinessRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
formConfig.value.isSafetyInput && form.push(new Promise((resolve, reject) => { | |||
safetyInputRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
formConfig.value.isProjectImageProgress && form.push(new Promise((resolve, reject) => { | |||
projectImageProgressRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
getIsShowReviewCheck() && formConfig.value.isReviewChecklist && (route.name === 'declarePlan' || [10012, 10013, 10016].includes(detailData.value?.status)) && form.push(new Promise((resolve, reject) => { | |||
reviewCheckRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
accessoryRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
for (const key in newModuleformRef.value) { | |||
form.push(new Promise((resolve, reject) => { | |||
newModuleformRef.value[key].validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
} | |||
applicationsRef.value && form.push(new Promise((resolve, reject) => { | |||
applicationsRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
fundsInfoRef.value.validForm((valid) => { | |||
if (valid) { | |||
const total = floatAdd([fundsInfoRef.value.formData.declareHaveAmount, fundsInfoRef.value.formData.declareGovOwnFinanceAmount, fundsInfoRef.value.formData.declareGovSuperiorFinanceAmount, fundsInfoRef.value.formData.declareBankLendingAmount, fundsInfoRef.value.formData.declareOtherAmount]) | |||
if (fundsInfoRef.value.formData.declareAmount > 0 && fundsInfoRef.value.formData.declareAmount === total) { resolve() } else { | |||
reject('资金申报情况:5类资金总和必须等于申报金额') | |||
} | |||
} | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
fundsAllocationRef.value.validForm(valid => { | |||
if (valid) { | |||
const total = floatAdd([fundsAllocationRef.value.formData.softwareDevelopmentAmount, fundsAllocationRef.value.formData.cloudHardwarePurchaseAmount, fundsAllocationRef.value.formData.thirdPartyAmount]) | |||
if (fundsInfoRef.value.formData.declareAmount > 0 && fundsInfoRef.value.formData.declareAmount === total) { resolve() } else { | |||
reject('资金分配情况:3类资金总和必须等于申报金额') | |||
} | |||
} | |||
}) | |||
})) | |||
applicationsRef.value?.formData.includeApplication === 1 && form.push(new Promise((resolve, reject) => { | |||
hiddenAppFormRef.value.validAllAppForm((valid) => { | |||
if (valid) { | |||
resolve() | |||
} else { | |||
reject('请完善已添加的应用信息') | |||
} | |||
}) | |||
})) | |||
} | |||
Promise.all([...form]).then(async () => { | |||
if (basicInfoRef.value.formData?.baseProjIsConfidentiality === '02') { | |||
saveData(1) | |||
} else { | |||
if (formConfig.value.isSafetyInput) { | |||
const num = safetyInputRef.value?.formData.safetyInput.reduce((acc, cur) => acc + cur.safetyInputAmount, 0) | |||
const precent = (num / fundsInfoRef.value.formData.declareAmount) * 100 | |||
if (precent < 5) { | |||
proxy.$messageBox | |||
.confirm(`当前安全投入占比低于5%,确认要提交吗?`, '确认要提交吗?', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
saveData(1) | |||
}) | |||
} else { | |||
saveData(1) | |||
} | |||
} else { | |||
saveData(1) | |||
} | |||
} | |||
}).catch(err => { | |||
if (err) { | |||
proxy.$message.warning(err) | |||
} | |||
}) | |||
}, | |||
floatAdd = (args) => { | |||
const data = [] | |||
args.forEach(i => { | |||
try { | |||
data.push(i.toString().split('.')[1].length) | |||
} catch (e) { | |||
data.push(0) | |||
} | |||
}) | |||
const m = Math.pow(10, Math.max(...data)) | |||
let sum = 0 | |||
args.forEach(item => { | |||
sum += item * m | |||
}) | |||
return sum / m | |||
}, | |||
// 保存草稿 | |||
toSaveDraft = async () => { | |||
saveData(2) | |||
}, | |||
// 设置应用是否填写完全的值 | |||
changeIsFirst = (val) => { | |||
if (applicationsRef.value?.formData && applicationsRef.value?.formData.includeApplication === 1 && applicationsRef.value?.formData?.applicationList?.length) { | |||
applicationsRef.value.formData.applicationList = applicationsRef.value.formData?.applicationList?.map(data => { | |||
return { | |||
...data, | |||
applicationName: val ? data.applicationName : undefined, | |||
relatedExistsApplication: !val ? data.relatedExistsApplication : undefined, | |||
relatedExistsApplicationCode: !val ? data.relatedExistsApplication : undefined | |||
} | |||
}) | |||
} | |||
}, | |||
saveLoading = ref(false), | |||
submitLoading = ref(false), | |||
saveData = async (type) => { | |||
// const buildBasis = basicInfoRef.value.formData?.buildBasis?.map(i => { | |||
// return { | |||
// ...i, | |||
// fileList: changFilesParam(i.fileList), | |||
// fileName: i.fileList?.[0].name || '' | |||
// } | |||
// }) | |||
var postData = {} | |||
if (basicInfoRef.value.formData?.baseProjIsConfidentiality === '02') { | |||
postData = { | |||
isRemarks: formConfig.value.isRemarks, | |||
isOpenCoreBusiness: formConfig.value.isCoreBusiness, | |||
isOpenSafetyInput: formConfig.value.isSafetyInput, | |||
isEngineeringSpeed: formConfig.value.isProjectImageProgress, | |||
isReviewChecklist: formConfig.value.isReviewChecklist, | |||
id: route.query.id * 1 || undefined, | |||
baseProjIsConfidentiality: basicInfoRef.value.formData?.baseProjIsConfidentiality, | |||
projectName: basicInfoRef.value.formData?.projectName, | |||
projectType: basicInfoRef.value.formData?.projectType, | |||
baseConstructionType: basicInfoRef.value.formData?.baseConstructionType?.join(';') || '', | |||
responsibleMan: basicInfoRef.value.formData?.responsibleMan, | |||
responsibleManMobile: basicInfoRef.value.formData?.responsibleManMobile, | |||
contactName: basicInfoRef.value.formData?.contactName, | |||
contactPhone: basicInfoRef.value.formData?.contactPhone, | |||
buildOrgName: basicInfoRef.value.formData?.buildOrgName, | |||
orgCreditCode: basicInfoRef.value.formData?.orgCreditCode, | |||
baseProvManDeprtType: basicInfoRef.value.formData.baseProvManDeprtType * 1 || undefined, | |||
higherSuperOrg: basicInfoRef.value.formData?.higherSuperOrg, | |||
higherSuperOrgCode: basicInfoRef.value.formData?.higherSuperOrgCode, | |||
superOrg: basicInfoRef.value.formData?.superOrg, | |||
superOrgCode: basicInfoRef.value.formData?.superOrgCode, | |||
superOrgCreditCode: basicInfoRef.value.formData?.superOrgCreditCode, | |||
projectYear: basicInfoRef.value.formData?.projectYear * 1, | |||
declareAmount: basicInfoRef.value.formData?.declareAmount, | |||
annualPlanAmount: basicInfoRef.value.formData?.declareAmount | |||
} | |||
} else { | |||
postData = { | |||
isRemarks: formConfig.value.isRemarks, | |||
isOpenCoreBusiness: formConfig.value.isCoreBusiness, | |||
isOpenSafetyInput: formConfig.value.isSafetyInput, | |||
isEngineeringSpeed: formConfig.value.isProjectImageProgress, | |||
isReviewChecklist: formConfig.value.isReviewChecklist, | |||
id: route.query.id * 1 || undefined, | |||
...basicInfoRef.value.formData, | |||
...fundsInfoRef.value.formData, | |||
...fundsAllocationRef.value.formData, | |||
bizDomain: basicInfoRef.value.formData?.isDigitalReform === 1 ? basicInfoRef.value.formData.bizDomain.join(',') : undefined, | |||
baseConstructionType: basicInfoRef.value.formData?.baseConstructionType?.join(';') || '', | |||
baseProvManDeprtType: basicInfoRef.value.formData.baseProvManDeprtType * 1 || undefined, | |||
projectYear: fundsInfoRef.value.formData?.projectYear * 1, | |||
beginTime: basicInfoRef.value.formData?.buildDuration?.length && basicInfoRef.value.formData.buildDuration[0], | |||
endTime: basicInfoRef.value.formData?.buildDuration?.length && basicInfoRef.value.formData.buildDuration[1], | |||
buildDuration: undefined, | |||
lowestLevel: !(basicInfoRef.value.formData?.baseConstructionType?.includes('03') && !basicInfoRef.value.formData?.baseConstructionType?.includes('01')) && basicInfoRef.value.formData?.lowestLevel || '', | |||
// buildBasis: buildBasis && JSON.stringify(buildBasis), | |||
baseProjBasis: basicInfoRef.value.formData?.baseProjBasis?.map(i => i.value)?.join(';') || undefined, | |||
baseProjBasisFile: basicInfoRef.value.formData?.baseProjBasis?.map(i => i.fileList && JSON.stringify(changFilesParam(i.fileList)))?.join(';') || '', | |||
cloudType: basicInfoRef.value.formData?.isCloud && basicInfoRef.value.formData?.cloudType?.length && basicInfoRef.value.formData.cloudType.join(',') || undefined, | |||
baseHistorProjId: basicInfoRef.value.formData?.baseHistorProjs?.map(i => i.baseProjId)?.join(';') || '', | |||
baseHistorProjName: basicInfoRef.value.formData?.baseHistorProjs?.map(i => i.baseProjName)?.join(';') || '', | |||
baseHistorProjYear: basicInfoRef.value.formData?.baseHistorProjs?.map(i => i.baseProjSetYear)?.join(';') || '', | |||
baseHistorProjs: undefined, | |||
beseExpectedResults: basicInfoRef.value.formData?.beseExpectedResults?.length && JSON.stringify(basicInfoRef.value.formData.beseExpectedResults) || '', | |||
baseBasisAmountOri: fundsInfoRef.value?.formData.declareOtherAmount > 0 && fundsInfoRef.value.formData?.baseBasisAmountOri || '', | |||
consultancy: fundsInfoRef.value?.formData.declareAmount > 400 && fundsInfoRef.value.formData?.consultancy || '', | |||
operationManageUnit: fundsInfoRef.value?.formData.declareAmount >= 1000 && provincialExamineRef.value.formData.operationManageUnit || undefined, | |||
...applicationsRef.value?.formData, | |||
...annualPaymentPlanRef.value.formData, | |||
...accessoryRef.value.formData, | |||
constructionPlanFile: accessoryRef.value.formData?.constructionPlanFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.constructionPlanFile)), | |||
preliminaryPlanFile: accessoryRef.value.formData?.preliminaryPlanFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.preliminaryPlanFile)), | |||
mainResponsibilitiesApplicantFile: accessoryRef.value.formData?.mainResponsibilitiesApplicantFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.mainResponsibilitiesApplicantFile)), | |||
supportingMaterialsFile: accessoryRef.value.formData?.supportingMaterialsFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.supportingMaterialsFile)), | |||
calculationTotalInvestmentFile: accessoryRef.value.formData?.calculationTotalInvestmentFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.calculationTotalInvestmentFile)), | |||
projectApplicationForm: basicInfoRef.value.formData?.projectType !== '03' && accessoryRef.value.formData?.projectApplicationForm && JSON.stringify(changFilesParam(accessoryRef.value.formData.projectApplicationForm)) || '', | |||
baseResearchReportFile: basicInfoRef.value.formData?.projectType !== '03' && accessoryRef.value.formData?.baseResearchReportFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.baseResearchReportFile)) || '', | |||
baseProjOtherFile: accessoryRef.value.formData?.baseProjOtherFile && JSON.stringify(changFilesParam(accessoryRef.value.formData.baseProjOtherFile)), | |||
mainAccusationDoc: fundsInfoRef.value?.formData.declareAmount >= 1000 && accessoryRef.value.formData?.mainAccusationDoc && JSON.stringify(changFilesParam(accessoryRef.value.formData.mainAccusationDoc)) || '', | |||
reviewChecklist: reviewCheckRef.value?.formData?.reviewChecklist || undefined | |||
} | |||
if (formConfig.value.isCoreBusiness) { | |||
postData = Object.assign(postData, { ...coreBusinessRef.value.formData, coreBusiness: coreBusinessRef.value.formData.coreBusiness && JSON.stringify(coreBusinessRef.value.formData.coreBusiness) }) | |||
} | |||
if (formConfig.value.isSafetyInput) { | |||
// ...safetyInputRef.value.formData | |||
postData = Object.assign(postData, { | |||
safetyInputDescribe: JSON.stringify(safetyInputRef.value.formData.safetyInput) | |||
}) | |||
} | |||
if (formConfig.value.isProjectImageProgress) { | |||
postData = Object.assign(postData, { ...projectImageProgressRef.value.formData }) | |||
} | |||
if (formConfig.value.isRemark) { | |||
postData = Object.assign(postData, { ...projectRemarkRef.value.formData }) | |||
} | |||
if (applicationsRef.value?.formData?.includeApplication && applicationsRef.value?.formData.applicationList?.length) { | |||
postData.applicationList = applicationsRef.value.formData.applicationList.map(i => { | |||
return { | |||
...i, | |||
isFirst: !basicInfoRef.value.formData?.isFirst ? 0 : 1, | |||
relatedExistsApplication: ((!basicInfoRef.value.formData?.isFirst && userInfo.value.regionCode === '331123') || userInfo.regionCode !== '331123') && i.relatedExistsApplication?.applicationName || undefined, | |||
relatedExistsApplicationCode: ((!basicInfoRef.value.formData?.isFirst && userInfo.value.regionCode === '331123') || userInfo.regionCode !== '331123') && i.relatedExistsApplicationCode || undefined, | |||
applicationName: (basicInfoRef.value.formData?.isFirst && userInfo.regionCode === '331123') && i.applicationName || undefined, | |||
coreBusinessList: i.coreBusinessList.map(j => { | |||
return { | |||
...j, | |||
projectId: detailData.value?.projectId || undefined, | |||
projectCode: detailData.value?.projectCode || undefined | |||
} | |||
}) | |||
} | |||
}) | |||
} | |||
if (formConfig.value.safetyInputModular?.length) { | |||
postData.safetyInputModular = [] | |||
for (const key in newModuleformRef.value) { | |||
postData.safetyInputModular.push( | |||
newModuleformRef.value[key].formData | |||
) | |||
} | |||
const safetyInputModular = postData.safetyInputModular.map(i => { | |||
return { | |||
...i, | |||
formList: i.formList.map(j => { | |||
return { | |||
...j, | |||
value: !j.value ? undefined : j.props.type === '文件上传' ? changFilesParam(j.value) : j.value | |||
} | |||
}) | |||
} | |||
}) | |||
postData.safetyInputModular = JSON.stringify(safetyInputModular) | |||
} else { | |||
postData.safetyInputModular = undefined | |||
} | |||
} | |||
if (type === 1) { | |||
submitLoading.value = true | |||
try { | |||
const data = { | |||
projectInfo: { ...postData, id: !route.query.isDraft ? postData.id : undefined, draftId: route.query.isDraft ? route.query.id * 1 : undefined } | |||
} | |||
if (route.name === 'declarePage') { | |||
await projectStart(!route.query.isDraft && route.query.id ? 2 : 1, data)// 申报 | |||
} else if (route.name === 'planEdit') { | |||
await annualPlanModify(data.projectInfo) // 年度计划编辑 | |||
} else if (route.name === 'handleAfterGiveBack') { | |||
await adjustAndHandle({ | |||
...data, | |||
projectId: route.query.id, | |||
instanceId: route.query.instanceId, | |||
taskId: route.query.taskId | |||
}) | |||
} else if (route.name === 'declarePlan') { | |||
await declareConstructionScheme(data) | |||
} | |||
proxy.$message.success('提交成功') | |||
submitLoading.value = false | |||
if (route.name === 'projectDeclare') { | |||
router.push({ name: 'projectDeclare' }) | |||
} else { | |||
router.go(-1) | |||
} | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
} else if (type === 2) { | |||
saveLoading.value = true | |||
try { | |||
await saveDraft({ | |||
projectInfo: { ...postData }, | |||
user: userInfo.value // 测试需要 | |||
}) | |||
proxy.$message.success('保存成功') | |||
saveLoading.value = false | |||
router.go(-1) | |||
} catch (e) { | |||
saveLoading.value = false | |||
} | |||
} | |||
}, | |||
// 回显 | |||
detailData = ref({}), | |||
// allApplicationsDone = ref(1), // 所有应用信息校验字段 | |||
setData = () => { | |||
basicInfoRef.value.setFormData(detailData.value) | |||
if (detailData.value?.baseProjIsConfidentiality !== '02') { | |||
fundsInfoRef.value.setFormData(detailData.value) | |||
fundsAllocationRef.value.setFormData(detailData.value) | |||
annualPaymentPlanRef.value.setFormData(detailData.value) | |||
formConfig.value.isCoreBusiness && coreBusinessRef.value.setFormData(detailData.value) | |||
formConfig.value.isSafetyInput && safetyInputRef.value.setFormData(detailData.value) | |||
formConfig.value.isProjectImageProgress && projectImageProgressRef.value.setFormData(detailData.value) | |||
accessoryRef.value.setFormData(detailData.value) | |||
formConfig.value.isRemark && projectRemarkRef.value.setFormData(detailData.value) | |||
// detailData.value.safetyInputModular?.length && newModuleformRef.value.setFormData(detailData.value) | |||
applicationsRef.value?.setFormData(detailData.value) | |||
setTimeout(() => { | |||
provincialExamineRef.value?.setFormData(detailData.value) | |||
}) | |||
} | |||
}, | |||
// 被退回处理 | |||
// 获取审核详情 | |||
flowData = ref({ | |||
processProgressVo: { | |||
progressInfo: [ | |||
] | |||
} | |||
}), | |||
lastData = ref(), | |||
getFlowData = async () => { | |||
const res = await progressDetail({ instanceId: route.query.instanceId, projectId: route.query.id, nodeId: route.query.nodeId }) | |||
flowData.value = { | |||
...res.data, | |||
processProgressVo: { | |||
...res.data.processProgressVo, | |||
progressInfo: changeProgressInfo(res.data.processProgressVo.progressInfo) | |||
} | |||
} | |||
lastData.value = flowData.value.processProgressVo.progressInfo.slice(-1)[0]?.children?.slice(-1)[0] || flowData.value.processProgressVo.progressInfo.slice(-1)[0] | |||
}, | |||
// 审核记录 | |||
flowRecordDialogData = reactive({ | |||
visible: false, | |||
flowData: undefined | |||
}), | |||
showFlowRecordDialog = (data) => { | |||
flowRecordDialogData.visible = true | |||
flowRecordDialogData.flowData = flowData.value.processProgressVo.progressInfo | |||
}, | |||
changeProgressInfo = (data) => { | |||
data.forEach(res => { | |||
if (res.children) { | |||
const nodeIds = [] | |||
const newChildren = [] | |||
res.children.forEach(child => { | |||
if (!nodeIds.includes(child.nodeId)) { | |||
nodeIds.push(child.nodeId) | |||
newChildren.push({ | |||
nodeId: child.nodeId, | |||
approvalMode: child.approvalMode, | |||
name: child.name, | |||
taskId: child.taskId, | |||
nodeType: child.nodeType, | |||
list: [{ ...child }], | |||
userIds: [child.userId] | |||
}) | |||
} else { | |||
newChildren.find(i => i.nodeId === child.nodeId).list.push(child) | |||
newChildren.find(i => i.nodeId === child.nodeId).userIds.push(child.userId) | |||
} | |||
}) | |||
res.children = newChildren | |||
} else { | |||
res['userIds'] = [res.userId] | |||
} | |||
}) | |||
return data | |||
}, | |||
closeFlowRecordDialog = () => { | |||
flowRecordDialogData.visible = false | |||
}, | |||
dictionaryList = ref([]), | |||
basicInfoData = ref(), | |||
getBasicInfoData = (data) => { | |||
basicInfoData.value = data | |||
} | |||
onMounted(async () => { | |||
dictionaryList.value = (await dictionary()).data | |||
if (!route.query.id) { | |||
const res = await getFormConfig({ | |||
regionCode: userInfo.value.regionCode | |||
}) | |||
formConfig.value = { | |||
isCoreBusiness: res.data.isCoreBusiness, | |||
isProjectImageProgress: res.data.isProjectImageProgress, | |||
isRemark: res.data.isRemark, | |||
isSafetyInput: res.data.isSafetyInput, | |||
safetyInputModular: res.data.safetyInputModular || [] | |||
} | |||
} else { | |||
var res = {}, res1 = {}, reviewChecklist = [], isReviewChecklist = false | |||
if (route.query?.isDraft) { | |||
res = await getDraftDetail({ id: route.query.id }) | |||
} else { | |||
res = await projectDetail(route.query.id) | |||
res1 = await getFormConfig({ | |||
regionCode: userInfo.value.regionCode | |||
}) | |||
if ((route.name === 'declarePlan' || [10012, 10013, 10016].includes(detailData.value?.status))) { | |||
isReviewChecklist = res.data.reviewChecklist && JSON.parse(res.data.reviewChecklist)?.length ? true : res1.data.isReviewChecklist | |||
reviewChecklist = res1.data.reviewChecklist && JSON.parse(res1.data.reviewChecklist) || [] | |||
} | |||
} | |||
detailData.value = { | |||
...res.data, | |||
reviewChecklist: res.data.reviewChecklist ? JSON.parse(res.data.reviewChecklist) : undefined | |||
} | |||
const safetyInputModular = res.data.safetyInputModular && JSON.parse(res.data.safetyInputModular).map(i => { | |||
return { | |||
...i, | |||
formList: i.formList.map(j => { | |||
return { | |||
...j, | |||
value: !j.value ? undefined : j.props.type === '文件上传' ? reviewFileParam(j.value) : j.value | |||
} | |||
}) | |||
} | |||
}) | |||
formConfig.value = { | |||
isCoreBusiness: res.data.isOpenCoreBusiness, | |||
isProjectImageProgress: res.data.isEngineeringSpeed, | |||
isRemark: res.data.isRemark, | |||
isSafetyInput: res.data.isOpenSafetyInput, | |||
safetyInputModular: safetyInputModular || [], | |||
isReviewChecklist, | |||
reviewChecklist | |||
} | |||
nextTick(() => { | |||
setData() | |||
}) | |||
if (route.name === 'handleAfterGiveBack') { | |||
getFlowData() | |||
} | |||
} | |||
if (formConfig.value.safetyInputModular?.length) { | |||
let index = 11 | |||
formConfig.value.safetyInputModular.forEach(i => { | |||
collapseModal.value.push(index++ + '') | |||
}) | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<div class="declarePage footerPage"> | |||
<!-- 退回编辑--> | |||
<div v-if="route.name==='handleAfterGiveBack'" class="errorTip mb-16"> | |||
<el-icon class="icon"><Warning /></el-icon> | |||
<div> | |||
<p class="title">流程被退回</p> | |||
<p> | |||
<span>{{ detailData?.projectName }}的{{ flowData?.processProgressVo?.processDefName }}被退回,请根据审核记录调整项目信息</span> | |||
<el-button | |||
type="primary" | |||
plain | |||
size="small" | |||
class="ml-16" | |||
@click="showFlowRecordDialog" | |||
>查看审核记录</el-button> | |||
</p> | |||
</div> | |||
</div> | |||
<!-- 建设方案申报--> | |||
<el-card v-if="route.name==='declarePlan'" shadow="never" class="mb-16"> | |||
<div class="card-header"> | |||
<div class="flex justify-between items-center"> | |||
<div class="flex-1"> | |||
<p class="font-bold">{{ detailData.projectName }}</p> | |||
<div class="mt-8 search"> | |||
<el-form label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<el-form-item label="申报单位">{{ detailData.buildOrgName||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="主管单位">{{ detailData.superOrg||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="创建时间">{{ detailData.createOn||'-' }}</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</el-card> | |||
<el-row> | |||
<el-col class="leftCol" :span="24"> | |||
<el-collapse v-model="collapseModal"> | |||
<el-collapse-item name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">基本信息</div> | |||
</template> | |||
<div class="p-24"> | |||
<basic-info | |||
ref="basicInfoRef" | |||
:detail-data="detailData" | |||
:dictionary-list="dictionaryList" | |||
:declare-amount="fundsInfoRef?.formData.declareAmount" | |||
@change-is-first="changeIsFirst" | |||
@get-basic-info-data="getBasicInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<template v-if="basicInfoRef?.formData?.baseProjIsConfidentiality==='01'"> | |||
<el-collapse-item v-if="basicInfoRef?.formData?.baseProjIsConfidentiality==='01'" name="2" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title"> | |||
<span>资金申报情况(单位:万元)</span> | |||
<span class="text-info">申报金额 = 自有资金 + 政府投资-本级财政资金 + 政府投资-上级补助资金 + 银行贷款 + 其他资金</span> | |||
</div> | |||
</template> | |||
<div class="p-24"> | |||
<funds-info ref="fundsInfoRef" :detail-data="detailData" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="basicInfoRef?.formData?.baseProjIsConfidentiality==='01'" name="3" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title"> | |||
资金分配情况(单位:万元) | |||
<span class="text-info">软件开发 + 云资源、硬件配置 + 第三方服务 = 申报金额</span> | |||
</div> | |||
</template> | |||
<div class="p-24"> | |||
<funds-allocation ref="fundsAllocationRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="fundsInfoRef?.formData.declareAmount>=1000&&basicInfoRef?.formData?.baseProjIsConfidentiality==='01'" name="10" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title"> | |||
重大项目省级联审信息 | |||
</div> | |||
</template> | |||
<div class="p-24"> | |||
<provincial-examine ref="provincialExamineRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item | |||
v-if="basicInfoRef?.formData?.baseProjIsConfidentiality==='01'" | |||
name="4" | |||
class="mb-16" | |||
> | |||
<template #title> | |||
<div class="collapse-title"> | |||
年度支付计划(单位:万元) | |||
<span class="text-info">年度支付金额 = 自有资金 + 政府投资-本级财政资金 + 政府投资-上级补助资金 + 银行贷款 + 其他资金</span> | |||
</div> | |||
</template> | |||
<div class="p-24"> | |||
<annual-payment-plan ref="annualPaymentPlanRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="formConfig.isCoreBusiness" name="5" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">核心业务</div> | |||
</template> | |||
<div class="p-24"> | |||
<core-business ref="coreBusinessRef" :basic-info-data="basicInfoRef?.formData" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="formConfig.isSafetyInput" name="6" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">安全投入</div> | |||
</template> | |||
<div class="p-24"> | |||
<safety-input ref="safetyInputRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="formConfig.isProjectImageProgress" name="7" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">工程形象进度</div> | |||
</template> | |||
<div class="p-24"> | |||
<projectImageProgress ref="projectImageProgressRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="getIsShowReviewCheck()&&formConfig.isReviewChecklist&&($route.name==='declarePlan'||[10012,10013,10016].includes(detailData?.status))" name="8" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">审查清单</div> | |||
</template> | |||
<div class="p-24"> | |||
<review-check ref="reviewCheckRef" :detail-data="detailData" :data="detailData.reviewChecklist||formConfig.reviewChecklist" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="8" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">附件</div> | |||
</template> | |||
<div class="p-24"> | |||
<accessory | |||
ref="accessoryRef" | |||
:detail-data="detailData" | |||
:project-type="basicInfoRef?.formData?.projectType" | |||
:declare-amount="fundsInfoRef?.formData.declareAmount" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="formConfig.isRemark" name="9" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">备注</div> | |||
</template> | |||
<div class="p-24"> | |||
<projectRemark ref="projectRemarkRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<template v-if="formConfig.safetyInputModular?.length"> | |||
<el-collapse-item | |||
v-for="(item,index) in formConfig.safetyInputModular" | |||
:key="index" | |||
:name="11+index+''" | |||
class="mb-16" | |||
> | |||
<template #title> | |||
<div class="collapse-title">{{ item.moduleName }}</div> | |||
</template> | |||
<div class="p-24"> | |||
<newModuleForm :ref="el => {newModuleformRef[item.id] = el}" :data="item" /> | |||
</div> | |||
</el-collapse-item> | |||
</template> | |||
<el-collapse-item | |||
v-if="($route.name==='declarePlan')||([10012,10016,10013].includes(detailData.status))" | |||
name="4" | |||
class="mb-16" | |||
> | |||
<template #title> | |||
<div class="collapse-title">应用信息</div> | |||
</template> | |||
<div class="p-24"> | |||
<applications ref="applicationsRef" :is-first="basicInfoRef?.formData?.isFirst" :core-business="coreBusinessRef?.formData?.coreBusiness" /> | |||
</div> | |||
</el-collapse-item> | |||
</template> | |||
</el-collapse> | |||
</el-col> | |||
</el-row> | |||
<hidden-app-form | |||
ref="hiddenAppFormRef" | |||
:application-list="applicationsRef?.formData?.applicationList" | |||
:is-first="basicInfoRef?.formData?.isFirst" | |||
/> | |||
<div class="footer"> | |||
<el-button @click="router.go(-1)"> 返回 </el-button> | |||
<el-button | |||
v-if="route.name==='declarePage'&&(!route.query.id||(route.query.id&&route.query.isDraft))" | |||
plain | |||
type="primary" | |||
:loading="saveLoading" | |||
@click="toSaveDraft" | |||
> 暂 存 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submitAllForm"> 提交审核 </el-button> | |||
</div> | |||
</div> | |||
<flow-record-dialog :visible="flowRecordDialogData.visible" :flow-data="flowRecordDialogData.flowData" @close="closeFlowRecordDialog" /> | |||
</template> | |||
<style lang="less" scoped> | |||
.declarePage { | |||
//position: relative; | |||
.errorTip{ | |||
background: #FFF0EF; | |||
border-radius: 4px; | |||
border: 1px solid #FF9E99; | |||
padding: 18px 24px; | |||
display: flex; | |||
font-size: 14px; | |||
color: rgba(0,0,0,0.85); | |||
.icon{ | |||
color:#FF3B30; | |||
font-size: 24px; | |||
margin-right: 8px; | |||
} | |||
.title{ | |||
font-size: 20px; | |||
font-weight: 500; | |||
color: rgba(0,0,0,0.85); | |||
line-height: 28px; | |||
margin-bottom: 17px; | |||
} | |||
} | |||
} | |||
:deep(.el-collapse) { | |||
.el-collapse-item__header { | |||
padding: 0px 16px; | |||
font-size: 14px; | |||
} | |||
.el-collapse-item__content { | |||
padding: 16px 16px 16px 0px; | |||
} | |||
.el-collapse-item__header.is-active { | |||
border-bottom: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.collapse-title { | |||
flex: 1 0 90%; | |||
order: 1; | |||
.el-collapse-item__header { | |||
flex: 1 0 auto; | |||
order: -1; | |||
} | |||
.el-input-number { | |||
width: 150px !important; | |||
} | |||
} | |||
} | |||
.btnClass { | |||
:deep(.el-form-item__content) { | |||
line-height: 24px; | |||
} | |||
} | |||
.marginTop { | |||
margin-top: 16px; | |||
} | |||
.delClass { | |||
color: #e65151; | |||
} | |||
.btn { | |||
display: flex; | |||
align-items: center; | |||
justify-content: center; | |||
color: rgba(0, 100, 235, 1); | |||
width: 100%; | |||
padding: 2px 0px; | |||
border-radius: 4px; | |||
border: 1px solid rgba(0, 100, 235, 1); | |||
cursor: pointer; | |||
} | |||
.bottomBtn { | |||
width: calc(100% - 201px); | |||
position: fixed; | |||
z-index: 999; | |||
right: 0px; | |||
bottom: 0px; | |||
background: #fff; | |||
padding: 10px 0px; | |||
border-top: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.applyBottomBtn { | |||
width: 1000px; | |||
position: fixed; | |||
z-index: 999; | |||
right: 0px; | |||
bottom: 0px; | |||
background: #fff; | |||
padding: 10px 0px; | |||
border-top: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.ocupation{ | |||
height: 80px; | |||
} | |||
</style> |
@@ -0,0 +1,61 @@ | |||
<script setup> | |||
import { ref, onMounted } from 'vue' | |||
import { useRoute } from 'vue-router' | |||
import projectInfo from '../../../projectStoreManage/projectStore/projectDetail/components/projectInfo.vue' | |||
import { getDraftDetail } from '@/http/apis/declareMange' | |||
const route = useRoute(), | |||
// 项目详情 | |||
detailData = ref({ | |||
projectName: '12', | |||
status: 10002, | |||
stage: 1 | |||
}), | |||
GetProjectDetail = async () => { | |||
const detailRes = await getDraftDetail({ id: route.query.id }) | |||
detailData.value = detailRes.data | |||
} | |||
onMounted(() => { | |||
GetProjectDetail() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-card class="w-full"> | |||
<div class="card-header"> | |||
<span class="font-bold">{{ detailData.projectName }}</span> | |||
<div class="mt-8 search"> | |||
<el-form label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<el-form-item label="申报单位">{{ detailData.buildOrgName||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="主管单位">{{ detailData.superOrg||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="创建时间">{{ detailData.beginTime||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="更新时间">{{ detailData.updatedAt||'-' }}</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
</div> | |||
</el-card> | |||
<el-card class="mt-10 w-full"> | |||
<project-info :detail-data="detailData" /> | |||
</el-card> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> | |||
.textSize{ | |||
font-size: 13px; | |||
margin-top: 10px; | |||
} | |||
.myCardTab{ | |||
:deep(.el-tabs__header){ | |||
margin: 0; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,427 @@ | |||
<script setup name = 'projectDeclare'> | |||
import { ref, reactive, h, onMounted, getCurrentInstance } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import { getProjectList, draftList, declareExport, removeProject } from '@/http/apis/declareMange' | |||
import store from '@/store' | |||
import useExportExc from '@/utils/useExportExc' | |||
const { | |||
statusOptionsCascader, statusOptions, | |||
projectConTypeOptions | |||
} = store.dictStore.globalDicts || {}, | |||
{ proxy } = getCurrentInstance(), | |||
// 搜索栏表单数据 | |||
searchForm = reactive({ | |||
stage: undefined, | |||
status: undefined, | |||
projectName: '', | |||
projectType: undefined, | |||
projectYear: undefined, | |||
createTiming_: undefined | |||
}), | |||
// 获取项目列表 | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const params = { | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.createTiming_?.length && searchForm.createTiming_[0], | |||
createOnMax: searchForm.createTiming_?.length && searchForm.createTiming_[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
createTiming_: undefined, | |||
status: searchForm.status?.[searchForm.status.length - 1] | |||
} | |||
const res = tabStatus.value ? await getProjectList(params) : await draftList(params) | |||
projectData.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
activeName = ref('已申报'), | |||
// 切换栏 | |||
handleClick = (tab, event) => { | |||
switch (tab.props.name) { | |||
case '已申报': | |||
tabStatus.value = true | |||
formReset() | |||
break | |||
case '草稿箱': | |||
tabStatus.value = false | |||
formReset() | |||
break | |||
default: | |||
break | |||
} | |||
}, | |||
tabStatus = ref(true), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '250', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '100' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '120' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '100' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
showOverflowTooltip: true, | |||
width: '180' | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '220', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${row.status && statusOptions[row.status]?.color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${row.status && statusOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name + '-' + statusOptions[row.status]?.name | |||
) | |||
] | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '200', | |||
fixed: 'right' | |||
} | |||
]), | |||
column2 = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '250', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '100' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declareAmount', | |||
prop: 'declareAmount', | |||
width: '120' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '80' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
showOverflowTooltip: true, | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '160', | |||
fixed: 'right' | |||
} | |||
]), | |||
projectData = ref([]), | |||
// 数据总数 | |||
total = ref(1), | |||
editProject = (row) => { | |||
$router.push({ name: 'declarePage', query: { id: row.id, isDraft: 1 }}) | |||
}, | |||
checkDetail = (detailData) => { | |||
if (tabStatus.value) { | |||
$router.push({ name: 'projectDeclareDetail', query: { id: detailData.id }}) | |||
} else { | |||
$router.push({ name: 'draftDetails', query: { id: detailData.id }}) | |||
} | |||
}, | |||
reDeclare = (row) => { | |||
if (row.status === 20005) { | |||
$router.push({ name: 'reDeclarationFinal', query: { id: row.id }}) | |||
} else { | |||
$router.push({ name: 'declarePage', query: { id: row.id }}) | |||
} | |||
}, | |||
// 提交查询 | |||
onSearch = () => { | |||
getTableData() | |||
}, | |||
formReset = () => { | |||
searchForm.status = undefined | |||
searchForm.projectName = undefined | |||
searchForm.createTiming_ = undefined | |||
searchForm.projectType = undefined | |||
searchForm.projectYear = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
$router = useRouter(), | |||
// 去项目申报页 | |||
toDeclarePage = () => { | |||
$router.push({ name: 'declarePage' }) | |||
}, | |||
tableListRef = ref(), | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(1, { | |||
...searchForm, | |||
createOnMin: searchForm.createTiming_?.length && searchForm.createTiming_[0], | |||
createOnMax: searchForm.createTiming_?.length && searchForm.createTiming_[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
status: searchForm.status?.[searchForm.status.length - 1] | |||
})) | |||
}, | |||
dictionaryList = ref([]), | |||
// 删除项目 | |||
remove = (data) => { | |||
proxy.$messageBox | |||
.confirm(`确定要删除${data.projectName}吗?`, '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await removeProject(data.projectCode) | |||
proxy.$message.success('删除成功') | |||
getTableData() | |||
}) | |||
} | |||
onMounted(async () => { | |||
tabStatus.value = ref(true) | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-card class="w-full search"> | |||
<!-- 已申报 --> | |||
<el-form | |||
v-show="tabStatus" | |||
size="small" | |||
:model="searchForm" | |||
label-suffix=":" | |||
> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称" class="w-full"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectConTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item v-show="tabStatus" label="项目状态"> | |||
<el-cascader | |||
v-model="searchForm.status" | |||
class="w-full" | |||
:props="{label:'name',value:'code'}" | |||
:options="statusOptionsCascader" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
class="w-full" | |||
type="year" | |||
format="YYYY" | |||
value-format="YYYY" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间" class="w-full"> | |||
<el-date-picker | |||
v-model="searchForm.createTiming_" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="4"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="onSearch">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<!-- 草稿箱 --> | |||
<el-form | |||
v-show="!tabStatus" | |||
label-suffix=":" | |||
:model="searchForm" | |||
size="small" | |||
> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称" class="w-full"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictionaryList?.filter(i => i.type === 'PROJECT_TYPE')" | |||
:key="index" | |||
:label="item.label" | |||
:value="item.value" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
class="w-full" | |||
type="year" | |||
value-format="YYYY" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="16"> | |||
<el-col :span="10"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.createTiming_" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="14"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="onSearch">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8 tab-card"> | |||
<template #header> | |||
<div class="flex justify-between items-center"> | |||
<el-tabs v-model="activeName" @tab-click="handleClick"> | |||
<el-tab-pane label="已申报" name="已申报" /> | |||
<el-tab-pane label="草稿箱" name="草稿箱" /> | |||
</el-tabs> | |||
<div> | |||
<el-button | |||
v-show="tabStatus" | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
>导出</el-button> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
icon="plus" | |||
@click="toDeclarePage" | |||
>项目申报</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="tabStatus ? column : column2" | |||
:data="projectData" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
<a v-if="!tabStatus" @click="editProject(scope.row)">编辑</a> | |||
<a v-if="tabStatus && [10002,10005,10007,10013,20005].includes(scope.row.status)" @click="reDeclare(scope.row)">重新申报</a> | |||
<a v-if="tabStatus && [10007].includes(scope.row.status)" @click="remove(scope.row)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> | |||
@@ -0,0 +1,154 @@ | |||
<script name="implementPlanDialog" setup> | |||
import { getCurrentInstance, nextTick, ref, watch } from 'vue' | |||
import { operationDetail, pushOperation } from '@/http/apis/declareMange/purchaseResults' | |||
import { projectDetail } from '@/http/apis/projectStoreManage/projectStore' | |||
const { proxy } = getCurrentInstance(), | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
data: { | |||
type: Object, | |||
default: () => {} | |||
} | |||
}), | |||
emits = defineEmits(['close']), | |||
formData = ref({}), | |||
formRef = ref(), | |||
validatorTime1 = (rule, value, callback) => { | |||
if (new Date(value).getTime() >= new Date(formData.value.finalInspectionDate).getTime()) { | |||
return callback(new Error('项目开工时间必须在项目终验时间之前')) | |||
} else if (new Date(value).getTime() >= new Date(formData.value.initialInspectionDate).getTime()) { | |||
return callback(new Error('项目开工时间必须在项目初验时间之前')) | |||
} else if (new Date(value).getTime() >= new Date(formData.value.startTrialOperationDate).getTime()) { | |||
return callback(new Error('项目开工时间必须在项目试运行开始时间之前')) | |||
} else { | |||
return callback() | |||
} | |||
}, | |||
validatorTime2 = (rule, value, callback) => { | |||
if (new Date(value).getTime() <= new Date(formData.value.projectStartDate).getTime()) { | |||
return callback(new Error('项目初验时间必须在项目开工时间之后')) | |||
} else if (new Date(value).getTime() >= new Date(formData.value.startTrialOperationDate).getTime()) { | |||
return callback(new Error('项目初验时间必须在项目试运行开始时间之前')) | |||
} else if (new Date(value).getTime() >= new Date(formData.value.finalInspectionDate).getTime()) { | |||
return callback(new Error('项目初验时间必须在项目终验时间之前')) | |||
} else { | |||
return callback() | |||
} | |||
}, | |||
validatorTime3 = (rule, value, callback) => { | |||
if (new Date(value).getTime() <= new Date(formData.value.projectStartDate).getTime()) { | |||
return callback(new Error('项目试运行开始时间必须在项目开工时间之后')) | |||
} else if (new Date(value).getTime() <= new Date(formData.value.initialInspectionDate).getTime()) { | |||
return callback(new Error('项目试运行开始时间必须在项目初验时间之后')) | |||
} else if (new Date(value).getTime() >= new Date(formData.value.finalInspectionDate).getTime()) { | |||
return callback(new Error('项目初验时间必须在项目终验时间之前')) | |||
} else { | |||
return callback() | |||
} | |||
}, | |||
rules = { | |||
projectStartDate: [{ required: true, message: '请输入' }, { validator: validatorTime1 }], | |||
initialInspectionDate: [{ required: true, message: '请选择' }, { validator: validatorTime2 }], | |||
startTrialOperationDate: [{ required: true, message: '请选择' }, { validator: validatorTime3 }], | |||
finalInspectionDate: [{ required: true, message: '请选择' }] | |||
}, | |||
loading = ref(false), | |||
submit = async (formEl) => { | |||
if (!formEl) return | |||
await formEl.validate(async valid => { | |||
if (valid) { | |||
loading.value = true | |||
try { | |||
const postData = { | |||
...formData.value, | |||
projectId: props.data.id | |||
} | |||
await pushOperation(postData) | |||
proxy.$message.success('提交成功!') | |||
loading.value = false | |||
emits('close', true) | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
}) | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
await nextTick() | |||
formRef.value.clearValidate() | |||
const detail = await projectDetail(props.data.id) | |||
const res = await operationDetail(props.data.id) | |||
formData.value = res?.data ? { | |||
...res.data, | |||
finalInspectionDate: detail.data.planAcceptanceTime | |||
} : { | |||
finalInspectionDate: detail.data.planAcceptanceTime | |||
} | |||
} | |||
} | |||
) | |||
defineExpose({ formRef }) | |||
</script> | |||
<template> | |||
<el-dialog :model-value="visible" title="填写实施计划" @close="emits('close')"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-suffix=":" | |||
label-width="140" | |||
> | |||
<el-form-item label="项目开工时间" prop="projectStartDate"> | |||
<el-date-picker | |||
v-model="formData.projectStartDate" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD HH:mm:ss" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="项目初验时间" prop="initialInspectionDate"> | |||
<el-date-picker | |||
v-model="formData.initialInspectionDate" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD HH:mm:ss" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="试运行开始时间" prop="startTrialOperationDate"> | |||
<el-date-picker | |||
v-model="formData.startTrialOperationDate" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD HH:mm:ss" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
<el-form-item label="项目终验时间" prop="finalInspectionDate"> | |||
<el-date-picker | |||
v-model="formData.finalInspectionDate" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD HH:mm:ss" | |||
placeholder="请选择" | |||
disabled | |||
/> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button type="primary" :loading="loading" @click="submit(formRef)">提交</el-button> | |||
<el-button @click="emits('close')">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,355 @@ | |||
<script setup name="fillPurchasingResult"> | |||
import { getCurrentInstance, onMounted, ref } from 'vue' | |||
import { changFilesParam, fileFormatVerification, handleFileSuccess, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import { submitResult } from '@/http/apis/declareMange/purchaseResults' | |||
import { dictionary } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
route = useRoute() | |||
const formRef = ref(), | |||
// 手机号码校验 | |||
checkTelPhone = (rule, value, callback) => { | |||
if (value === '') { | |||
return callback(new Error('请输入正确的手机号')) | |||
} else { | |||
const regIdCard = | |||
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/ | |||
if (regIdCard.test(value)) { | |||
callback() | |||
} else { | |||
return callback(new Error('请输入正确的手机号')) | |||
} | |||
} | |||
}, | |||
rules = { | |||
bidName: [{ required: true, message: '请输入标段名称' }], | |||
supplier: [{ required: true, message: '请输入供应商' }], | |||
supplierContact: [{ required: true, message: '请输入供应商联系人' }], | |||
supplierContactInfo: [ | |||
{ required: true, message: '请输入供应商联系方式' }, | |||
{ validator: checkTelPhone, trigger: 'blur' } | |||
], | |||
purchaseMethod: [{ required: true, message: '请选择采购方式' }], | |||
transactionAmount: [{ required: true, message: '请输入成交金额' }], | |||
transactionTime: [{ required: true, message: '请选择成交时间' }], | |||
biddingDoc: [{ required: true, message: '请上传投标文件' }], | |||
bidDoc: [{ required: true, message: '请上传招标文件' }], | |||
acceptanceLetter: [{ required: true, message: '请上传中标通知书' }] | |||
}, | |||
formData = ref({ | |||
sections: [{ | |||
biddingDoc: [], | |||
bidDoc: [], | |||
acceptanceLetter: [] | |||
}] | |||
}), | |||
submitLoading = ref(false), | |||
submit = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid) => { | |||
if (valid) { | |||
submitLoading.value = true | |||
const postData = { | |||
projectId: route.query.id, | |||
tenders: formData.value.sections.map(i => { | |||
return { | |||
...i, | |||
biddingDoc: i.biddingDoc && JSON.stringify(changFilesParam(i.biddingDoc)), | |||
bidDoc: i.bidDoc && JSON.stringify(changFilesParam(i.bidDoc)), | |||
acceptanceLetter: i.acceptanceLetter && JSON.stringify(changFilesParam(i.acceptanceLetter)) | |||
} | |||
}) | |||
} | |||
try { | |||
await submitResult(postData) | |||
submitLoading.value = false | |||
proxy.$message.success('提交成功') | |||
router.go(-1) | |||
} catch (e) { | |||
submitLoading.value = false | |||
} | |||
} | |||
}) | |||
}, | |||
// 添加标段 | |||
add = () => { | |||
if (formData.value.sections?.length >= 10) { | |||
proxy.$message.warning('最多添加10个标段') | |||
return | |||
} | |||
formData.value.sections.push({ | |||
biddingDoc: [], | |||
bidDoc: [], | |||
acceptanceLetter: [] | |||
}) | |||
}, | |||
// 删除标段 | |||
del = (index) => { | |||
formData.value.sections.splice(index, 1) | |||
}, | |||
dictionaryList = ref([]) | |||
onMounted(async () => { | |||
dictionaryList.value = (await dictionary()).data | |||
}) | |||
</script> | |||
<template> | |||
<div class="fillPurchasingResult footerPage"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="180px" | |||
label-suffix=":" | |||
scroll-to-error | |||
> | |||
<el-card v-for="(item,index) in formData.sections" :key="index" class="w-full mb-16"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>标段{{ index+1 }}</span> | |||
<el-button | |||
v-if="formData.sections?.length>1" | |||
link | |||
type="danger" | |||
@click="del(index)" | |||
>删除</el-button> | |||
</div> | |||
</template> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item label="标段名称" :prop="`sections[${index}].bidName`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input v-model="formData.sections[index].bidName" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商" :prop="`sections[${index}].supplier`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input v-model="formData.sections[index].supplier" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商统一社会信用代码" :prop="`sections[${index}].supplierSocialCreditCode`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input v-model="formData.sections[index].supplierSocialCreditCode" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商联系人" :prop="`sections[${index}].supplierContact`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input v-model="formData.sections[index].supplierContact" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="供应商联系方式" :prop="`sections[${index}].supplierContactInfo`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input v-model="formData.sections[index].supplierContactInfo" maxlength="11" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item label="采购方式" :prop="`sections[${index}].purchaseMethod`" :rules="[{ required: true, message: '请选择' }]"> | |||
<el-radio-group v-model="formData.sections[index].purchaseMethod"> | |||
<el-radio | |||
v-for="(row,key) in dictionaryList?.filter(i => i.type === 'PURCHASE_METHOD')" | |||
:key="key" | |||
:label="row.value" | |||
>{{ row.label }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="成交金额" :prop="`sections[${index}].transactionAmount`" :rules="[{ required: true, message: '请输入' }]"> | |||
<el-input-number | |||
v-model="formData.sections[index].transactionAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="成交时间" | |||
:prop="`sections[${index}].transactionTime`" | |||
:rules="[{ required: true, message: '请选择' }]" | |||
> | |||
<el-date-picker | |||
v-model="formData.sections[index].transactionTime" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="40"> | |||
<el-col :span="12"> | |||
<el-form-item v-if="['00','05'].includes(formData.sections[index].purchaseMethod)" label="采购代理机构"> | |||
<el-input v-model="formData.sections[index].agency" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="采购代理机构" | |||
:prop="`sections[${index}].agency`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input v-model="formData.sections[index].agency" maxlength="50" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item v-if="['00','05'].includes(formData.sections[index].purchaseMethod)" label="采购代理机构统一社会信用代码"> | |||
<el-input v-model="formData.sections[index].purchaseSocialCreditCode" placeholder="请输入" /> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="采购代理机构统一社会信用代码" | |||
:prop="`sections[${index}].purchaseSocialCreditCode`" | |||
:rules="[{ required: true, message: '请输入' }]" | |||
> | |||
<el-input v-model="formData.sections[index].purchaseSocialCreditCode" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="预算执行确认书编号"> | |||
<el-input v-model="formData.sections[index].budgetExecConfirmNo" placeholder="请输入" /> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="投标文件" | |||
:prop="`sections[${index}].biddingDoc`" | |||
:rules="[{ required: true, message: '请上传' }]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].biddingDoc" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].biddingDoc)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
v-if="formData.sections[index].purchaseMethod!=='00'" | |||
label="招标文件" | |||
:prop="`sections[${index}].bidDoc`" | |||
:rules="[{ required: true, message: '请上传' }]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].bidDoc" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].bidDoc)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="招标文件" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].bidDoc" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].bidDoc)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
v-if="!['00','05'].includes(formData.sections[index].purchaseMethod)" | |||
label="中标通知书" | |||
:prop="`sections[${index}].acceptanceLetter`" | |||
:rules="[{ required: true, message: '请上传' }]" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].acceptanceLetter" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].acceptanceLetter)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
<el-form-item | |||
v-else | |||
label="中标通知书" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.sections[index].acceptanceLetter" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, formData.sections[index].acceptanceLetter)" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" plain>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持{{ fileDesc }}文件 | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-card> | |||
<p> | |||
<el-button | |||
type="primary" | |||
plain | |||
icon="Plus" | |||
class="w-full" | |||
@click="add" | |||
>添加标段</el-button> | |||
</p> | |||
</el-form> | |||
<div class="footer"> | |||
<el-button @click="router.go(-1)"> 返回 </el-button> | |||
<el-button type="primary" :loading="submitLoading" @click="submit(formRef)"> 提交 </el-button> | |||
</div> | |||
</div> | |||
</template> |
@@ -0,0 +1,252 @@ | |||
<script setup name="purchaseResults"> | |||
import { ref, reactive, onMounted, h } from 'vue' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
import { useRouter } from 'vue-router' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { purchaseList } from '@/http/apis/declareMange/purchaseResults' | |||
import ImplementPlanDialog from '@/pages/declareManage/purchaseResults/components/implementPlanDialog.vue' | |||
import store from '@/store' | |||
const router = useRouter(), | |||
{ | |||
statusOptions, | |||
projectTypeOptions | |||
} = store.dictStore.globalDicts || {} | |||
// 搜索栏表单数据 | |||
const searchForm = reactive({ | |||
projectType: undefined, | |||
status: undefined, | |||
projectYear: undefined, | |||
projectName: undefined, | |||
createOnMin: undefined, | |||
createOnMax: undefined, | |||
times: [] | |||
}), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '80' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '批复金额(万元)', | |||
key: 'approvedAmount', | |||
prop: 'approvedAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: 80 | |||
}, | |||
{ | |||
label: '批复时间', | |||
key: 'approvalDate', | |||
prop: 'approvalDate', | |||
width: '200' | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
showOverflowTooltip: true, | |||
width: '180', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status].color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name + '-' + statusOptions[row.status]?.name | |||
) | |||
] | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '200' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '180', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await purchaseList({ | |||
...pageParams, | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 数据总数 | |||
total = ref(2), | |||
// 提交查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
formReset = () => { | |||
searchForm.projectYear = undefined | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.createOnMin = undefined | |||
searchForm.createOnMax = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(6, { | |||
...searchForm, | |||
createOnMin: searchForm.times?.[0], | |||
createOnMax: searchForm.times?.[1], | |||
projectYear: searchForm.projectYear * 1 || undefined, | |||
times: undefined | |||
})) | |||
}, | |||
// 实施计划 | |||
implementPlanDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
showImplementPlanDialog = (data) => { | |||
implementPlanDialogData.visible = true | |||
implementPlanDialogData.data = data | |||
}, | |||
close = (flag) => { | |||
implementPlanDialogData.visible = false | |||
flag && getTableData() | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="w-full search"> | |||
<el-form :model="searchForm" size="small" label-suffix=":"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="formReset">重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
plain | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
> | |||
导出 | |||
</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="scope.row.status===20001" @click="router.push({ name: 'fillPurchasingResult', query: { id: scope.row.id }})">填写采购结果</a> | |||
<a v-if="scope.row.status===20006" @click="showImplementPlanDialog(scope.row)">填写实施计划</a> | |||
<a @click="router.push({name:'purchasingResultDetail',query:{id:scope.row.id}})">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<implement-plan-dialog :visible="implementPlanDialogData.visible" :data="implementPlanDialogData.data" @close="close" /> | |||
</template> | |||
<style lang="less" scoped></style> |
@@ -0,0 +1,289 @@ | |||
<script setup name="projectStore"> | |||
import { getCurrentInstance, h, onMounted, reactive, ref } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import store from '@/store' | |||
import { renewalProjectDelete, renewalProjectList } from '@/http/apis/projectStoreManage/renewalProjectTreasury' | |||
import useExportExc from '@/utils/useExportExc' | |||
import { declareExport } from '@/http/apis/declareMange' | |||
const | |||
{ proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
{ reAuditStatusOptions, projectTypeOptions } = store.dictStore.globalDicts || {}, | |||
searchForm = reactive({ | |||
projectName: undefined, | |||
projectType: undefined, | |||
approvalStatus: undefined, | |||
year: undefined, | |||
times: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectType', | |||
prop: 'projectType', | |||
minWidth: '80', | |||
render: row => h('span', projectTypeOptions[row.projectType] || '-') | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '80' | |||
}, | |||
{ | |||
label: '下一年度支付金额(万元)', | |||
key: 'annualPaymentAmount', | |||
prop: 'annualPaymentAmount', | |||
width: '200' | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'approvalStatus', | |||
prop: 'approvalStatus', | |||
width: '180', | |||
render: row => [ | |||
h('span', { | |||
class: [ | |||
'dot mr-4', | |||
`bg-${row.approvalStatus === 'PENDING' ? 'warning' : row.approvalStatus === 'PASS' ? 'success' : 'danger'}` | |||
] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${row.approvalStatus === 'PENDING' ? 'warning' : row.approvalStatus === 'PASS' ? 'success' : 'danger'}` | |||
}, | |||
row.approvalStatus === 'PENDING' ? '待审核' : row.approvalStatus === 'PASS' ? '审核通过' : '审核不通过' | |||
) | |||
] | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '200', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
areaCode = ref(), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await renewalProjectList({ | |||
...pageParams, | |||
...searchForm, | |||
year: searchForm.year * 1 || undefined, | |||
startTime: searchForm.times?.[0] || undefined, | |||
endTime: searchForm.times?.[1] || undefined, | |||
regionCode: areaCode.value || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.projectName = undefined | |||
searchForm.projectType = undefined | |||
searchForm.approvalStatus = undefined | |||
searchForm.maxDeclareAmount = undefined | |||
searchForm.maxApprovalAmount = undefined | |||
searchForm.year = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 导出excel文件 | |||
{ exportLoading, exportData } = useExportExc(), | |||
handleExcel = () => { | |||
exportData(() => declareExport(5, { | |||
...searchForm, | |||
year: searchForm.year * 1 || undefined, | |||
maxDeclareAmount: searchForm.maxDeclareAmount * 1 || undefined, | |||
maxApprovalAmount: searchForm.maxApprovalAmount * 1 || undefined, | |||
startTime: searchForm.times?.[0] || undefined, | |||
endTime: searchForm.times?.[1] || undefined, | |||
areaCode: areaCode.value || undefined, | |||
times: undefined | |||
})) | |||
}, | |||
deleteItem = (data) => { | |||
proxy.$messageBox | |||
.confirm('确定要删除该项吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await renewalProjectDelete({ projectRenewalId: data.id }) | |||
proxy.$message.success('删除成功!') | |||
getTableData() | |||
}) | |||
}, | |||
checkDetail = (row) => { | |||
router.push({ name: 'renewProjectDetail', query: { id: row.id }}) | |||
}, | |||
redeclare = (row) => { | |||
router.push({ name: 'renewalCapitalDeclare', query: { id: row.id }}) | |||
} | |||
onMounted(async () => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
class="mb-16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目类型"> | |||
<el-select | |||
v-model="searchForm.projectType" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in projectTypeOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="项目状态"> | |||
<el-select | |||
v-model="searchForm.approvalStatus" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(v,k) in reAuditStatusOptions" | |||
:key="k" | |||
:label="v" | |||
:value="k" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row | |||
:gutter="16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="预算年度"> | |||
<el-date-picker | |||
v-model="searchForm.year" | |||
type="year" | |||
value-format="YYYY" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="创建时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
:editable="false" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="4"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>申报列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
plain | |||
size="small" | |||
:loading="exportLoading" | |||
@click="handleExcel" | |||
>导出</el-button> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
icon="Plus" | |||
@click="router.push({ name: 'renewalCapitalDeclare'})" | |||
>续建资金申报</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
<a v-if="scope.row.approvalStatus==='NOT_PASS'" @click="redeclare(scope.row)">重新申报</a> | |||
<a v-if="scope.row.approvalStatus==='NOT_PASS'" class="text-danger" @click="deleteItem(scope.row)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,377 @@ | |||
<script setup name='renewProjectDetail'> | |||
import { getCurrentInstance, h, onMounted, reactive, ref, watch } from 'vue' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import { renewalDeclaredDetail } from '@/http/apis/declareMange/renewalProjectCapitalDeclare' | |||
import store from '@/store' | |||
import { renewalProjectAsscess } from '@/http/apis/projectStoreManage/renewalProjectTreasury' | |||
import { contractDetail } from '@/http/apis/declareMange/contractRecord' | |||
const { statusOptions, projectTypeOptions, statusGjOptions } = | |||
store.dictStore.globalDicts || {}, | |||
tableListRef = ref(), | |||
ruleFormRef = ref(), | |||
router = useRouter(), | |||
route = useRoute(), | |||
total = ref(0), | |||
dialogFormVisible = ref(false), | |||
{ proxy } = getCurrentInstance(), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectType', | |||
prop: 'projectType', | |||
minWidth: '80', | |||
render: row => h('span', projectTypeOptions[row.projectType] || '-') | |||
}, | |||
{ | |||
label: '批复总金额(万元)', | |||
key: 'approvalAmount', | |||
prop: 'approvalAmount', | |||
width: 150 | |||
}, | |||
{ | |||
label: '累计年度投资资金', | |||
key: 'annualAccumulateAmountList', | |||
slot: 'annualAccumulateAmountList', | |||
width: 150 | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '120', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name ? `${statusOptions[row.stage]?.name}-${statusOptions[row.status]?.name}` : statusGjOptions[row.status]?.name || '-' | |||
) | |||
] | |||
} | |||
]), | |||
data = ref([]), | |||
form = reactive({}), | |||
rules = reactive({ | |||
recommend: [ | |||
{ required: true, message: '请填写审核意见', trigger: 'blur' } | |||
] | |||
}), | |||
submitForm = async (formEl) => { | |||
if (!formEl) return | |||
await formEl.validate(async (valid) => { | |||
if (valid) { | |||
await renewalProjectAsscess({ | |||
...form, | |||
projectRenewalId: route.query.id, | |||
result: false | |||
}) | |||
dialogFormVisible.value = false | |||
proxy.$message.success('审核成功!') | |||
router.push({ name: 'renewalProjectTreasury' }) | |||
} else { | |||
console.log('error submit!') | |||
} | |||
}) | |||
}, | |||
redeclare = () => { | |||
router.push({ name: 'renewalCapitalDeclare', query: { id: route.query.id }}) | |||
}, | |||
adopt = () => { | |||
proxy.$messageBox | |||
.confirm('确认审核通过吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await renewalProjectAsscess({ | |||
projectRenewalId: route.query.id, | |||
result: true | |||
}) | |||
proxy.$message.success('审核成功!') | |||
router.push({ name: 'renewalProjectTreasury' }) | |||
}) | |||
}, | |||
goBack = () => { | |||
router.go(-1) | |||
}, | |||
routeName = ref(''), | |||
detail = ref({}), | |||
getDetail = async () => { | |||
const res = await renewalDeclaredDetail(route.query.id) | |||
detail.value = res.data | |||
data.value = [{ ...res.data }] | |||
getPayInfo(data.value[0].projectId) | |||
}, | |||
// 支付信息 | |||
payColumn = [ | |||
{ | |||
label: '付款笔数', | |||
key: 'number', | |||
slot: 'number' | |||
}, | |||
{ | |||
label: '付款计划', | |||
key: 'planAmount', | |||
slot: 'planAmount' | |||
}, | |||
{ | |||
label: '付款比例(%)', | |||
key: 'ratio', | |||
slot: 'ratio' | |||
}, | |||
{ | |||
label: '付款金额(万元)', | |||
key: 'paymentAmount', | |||
slot: 'paymentAmount' | |||
}, | |||
{ | |||
label: '预计付款时间', | |||
key: 'paymentTime', | |||
slot: 'paymentTime' | |||
}, | |||
{ | |||
label: '实际支付金额(万元)', | |||
key: 'actualPaymentAmount', | |||
slot: 'actualPaymentAmount', | |||
width: 180 | |||
} | |||
], | |||
paymentsData = ref(), | |||
getPayInfo = async (id) => { | |||
const res = await contractDetail(id) | |||
paymentsData.value = res?.data?.payments || [] | |||
} | |||
watch( | |||
route, | |||
(val) => { | |||
routeName.value = route.meta.title | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
onMounted(() => { | |||
getDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class=""> | |||
<el-alert | |||
v-if="detail.approvalStatus==='NOT_PASS'" | |||
title="审核不通过" | |||
type="error" | |||
:description="`审核意见:${detail.auditOpinion||'-'}`" | |||
show-icon | |||
/> | |||
<el-alert | |||
v-if="detail.approvalStatus==='PASS'" | |||
title="审核通过" | |||
type="success" | |||
:description="`审核意见:${detail.auditOpinion||'-'}`" | |||
show-icon | |||
/> | |||
<el-card class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>申报信息</span> | |||
</div> | |||
</template> | |||
<div class="flex justify-around"> | |||
<div style="font-size: 14px;flex-shrink:0">关联项目:</div> | |||
<table-list | |||
ref="tableListRef" | |||
class="flex-1 mb-16" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
:height="200" | |||
:pagination="false" | |||
> | |||
<template #annualAccumulateAmountList="{scope}"> | |||
<p v-for="(item,index) in scope.row.annualAccumulateAmountList" :key="index">{{ index+1 }}、{{ item.projectYear }}年投资{{ item.annualAmount }}万元</p> | |||
</template> | |||
</table-list> | |||
</div> | |||
<p class="font-bold mb-8">支付信息</p> | |||
<table-list | |||
ref="tableListRef" | |||
:column="payColumn" | |||
:data="paymentsData" | |||
:pagination="false" | |||
:empty-temp="false" | |||
class="mb-16" | |||
> | |||
<template #number="{scope}"> | |||
<span>第{{ scope.$index+1 }}笔</span> | |||
</template> | |||
<template #planAmount="{scope}"> | |||
{{ scope.row.planAmount }} | |||
</template> | |||
<template #ratio="{scope}"> | |||
{{ scope.row.ratio }} | |||
</template> | |||
<template #paymentAmount="{scope}"> | |||
{{ scope.row.paymentAmount }} | |||
</template> | |||
<template #paymentTime="{scope}"> | |||
{{ scope.row.paymentTime }} | |||
</template> | |||
<template #actualPaymentAmount="{scope}"> | |||
{{ scope.row.actualPaymentAmount }} | |||
</template> | |||
</table-list> | |||
<template v-if="detail.annualAccumulateAmountList?.filter((i,key)=>key!==0&&i.projectYear!==detail.projectYear)?.length"> | |||
<p class="font-bold mt-20">历史续建资金信息</p> | |||
<el-descriptions | |||
v-for="(item,index) in detail.annualAccumulateAmountList.filter((i,key)=>key!==0&&i.projectYear!==detail.projectYear)" | |||
:key="index" | |||
class="mt-20" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="预算年度" | |||
span="1" | |||
width="250px" | |||
> | |||
{{ item.projectYear }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
:label="`${item.projectYear}年支付金额(万元)`" | |||
width="250px" | |||
> | |||
{{ item.annualAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="自有金额(万元)"> | |||
{{ item.haveAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政府投资-本级财政资金(万元)"> | |||
{{ item.govOwnFinanceAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政府投资-上级补助资金(万元)"> | |||
{{ item.govSuperiorFinanceAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="银行贷款(万元)"> | |||
{{ item.bankLendingAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="其他(万元)" | |||
span="2" | |||
> | |||
{{ item.otherAmount }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</template> | |||
<el-descriptions | |||
class="mt-20" | |||
title="申报续建资金信息" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="预算年度" | |||
span="1" | |||
width="250px" | |||
> | |||
{{ detail.projectYear }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
:label="`${detail.projectYear}年支付金额(万元)`" | |||
width="250px" | |||
> | |||
{{ detail.annualPaymentAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="自有金额(万元)"> | |||
{{ detail.haveAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政府投资-本级财政资金(万元)"> | |||
{{ detail.govOwnFinanceAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政府投资-上级补助资金(万元)"> | |||
{{ detail.govSuperiorFinanceAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="银行贷款(万元)"> | |||
{{ detail.bankLendingAmount }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="其他(万元)" | |||
span="2" | |||
> | |||
{{ detail.otherAmount }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<div class="flex justify-center items-center mt-10"> | |||
<el-button | |||
v-if="routeName =='续建项目资金申报详情'&&detail.approvalStatus==='NOT_PASS'" | |||
class="mr-20" | |||
type="primary" | |||
@click="redeclare" | |||
>重新申报</el-button> | |||
<template v-if="routeName !=='续建项目资金申报详情'&&detail.approvalStatus==='PENDING'"> | |||
<el-button | |||
class="mr-20" | |||
type="primary" | |||
@click="adopt" | |||
>通过</el-button> | |||
<el-button | |||
class="mr-20" | |||
type="danger" | |||
@click="dialogFormVisible = true" | |||
>不通过</el-button> | |||
</template> | |||
<el-button | |||
plain | |||
@click="goBack" | |||
>返回</el-button> | |||
</div> | |||
</el-card> | |||
<el-dialog | |||
v-model="dialogFormVisible" | |||
title="不通过" | |||
> | |||
<el-form | |||
ref="ruleFormRef" | |||
:model="form" | |||
:rules="rules" | |||
status-icon | |||
> | |||
<el-form-item | |||
label="审核意见" | |||
label-width="auto" | |||
prop="auditOpinion" | |||
> | |||
<el-input | |||
v-model="form.auditOpinion" | |||
maxlength="200" | |||
placeholder="请输入" | |||
show-word-limit | |||
type="textarea" | |||
/> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button | |||
type="primary" | |||
@click="submitForm(ruleFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button @click="dialogFormVisible = false">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<style lang='less' scoped> </style> |
@@ -0,0 +1,862 @@ | |||
<script setup name='renewalCapitalDeclare'> | |||
import { reactive, ref, onMounted, h, getCurrentInstance } from 'vue' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import store from '@/store' | |||
import { | |||
convertToCollection, | |||
renewalDeclared, | |||
renewalDeclaredDetail, | |||
libAllList | |||
} from '@/http/apis/declareMange/renewalProjectCapitalDeclare' | |||
import { detail } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
import { storeToRefs } from 'pinia' | |||
import { dictionary, save } from '@/http/apis/projectCollection/projectCollectionEnter' | |||
import BasicInfo from '@/pages/projectCollection/projectCollectionEnter/components/basicInfo.vue' | |||
import ProjectDeclareInfo from '@/pages/projectCollection/projectCollectionEnter/components/projectDeclareInfo.vue' | |||
import ApplicationInfo from '@/pages/projectCollection/projectCollectionEnter/components/applicationInfo.vue' | |||
import CoreBusiness from '@/pages/projectCollection/projectCollectionEnter/components/coreBusiness.vue' | |||
import ProjectApprovalInfo from '@/pages/projectCollection/projectCollectionEnter/components/projectApprovalInfo.vue' | |||
import PurchaseInfo from '@/pages/projectCollection/projectCollectionEnter/components/purchaseInfo.vue' | |||
import EmpMaterials from '@/pages/projectCollection/projectCollectionEnter/components/empMaterials.vue' | |||
import { contractDetail } from '@/http/apis/declareMange/contractRecord' | |||
import { changFilesParam } from '@/utils/uploadAction' | |||
const { proxy } = getCurrentInstance(), | |||
{ statusOptions, statusGjOptions, projectTypeOptions } = store.dictStore.globalDicts || {}, | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
router = useRouter(), | |||
route = useRoute(), | |||
// 列表 | |||
column = reactive([ | |||
{ | |||
type: 'radio', | |||
key: 'id', | |||
width: '50' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectType', | |||
prop: 'projectType', | |||
minWidth: '80', | |||
render: row => h('span', projectTypeOptions[row.projectType] || '-') | |||
}, | |||
{ | |||
label: '批复总金额(万元)', | |||
key: 'approvedAmount', | |||
prop: 'approvedAmount', | |||
width: '180' | |||
}, | |||
{ | |||
label: '累计年度投资资金', | |||
key: 'annualAccumulateAmountList', | |||
slot: 'annualAccumulateAmountList', | |||
width: '180' | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '180', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name ? `${statusOptions[row.stage]?.name}-${statusOptions[row.status]?.name}` : statusGjOptions[row.status]?.name || '-' | |||
) | |||
] | |||
} | |||
]), | |||
column1 = reactive([ | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '200', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectType', | |||
prop: 'projectType', | |||
minWidth: '80', | |||
render: row => h('span', projectTypeOptions[row.projectType] || '-') | |||
}, | |||
{ | |||
label: '批复总金额(万元)', | |||
key: 'approvalAmount', | |||
prop: 'approvalAmount', | |||
width: 150 | |||
}, | |||
{ | |||
label: '累计年度投资资金', | |||
key: 'annualAccumulateAmountList', | |||
slot: 'annualAccumulateAmountList', | |||
width: 150 | |||
}, | |||
{ | |||
label: '项目状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '120', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `bg-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `text-${statusOptions[row.status]?.color || statusGjOptions[row.status]?.color}` | |||
}, | |||
row.status && statusOptions[row.stage]?.name ? `${statusOptions[row.stage]?.name}-${statusOptions[row.status]?.name}` : statusGjOptions[row.status]?.name || '-' | |||
) | |||
] | |||
} | |||
]), | |||
total = ref(0), | |||
data = ref([]), | |||
tableListRef = ref(), | |||
maxYear = ref(), | |||
totalAmount = ref(0), | |||
approvedAmount = ref(), | |||
radioChange = (val) => { | |||
ruleForm.value.projectId = val.id | |||
ruleForm.value.projectCode = val.projectCode | |||
maxYear.value = val.annualAccumulateAmountList?.length > 1 && val.annualAccumulateAmountList.reduce((acc, cur) => Math.max(acc.projectYear, cur.projectYear)) || val.annualAccumulateAmountList[0].projectYear | |||
totalAmount.value = val.annualAccumulateAmountList?.map(i => i.annualAmount)?.reduce((acc, cur) => { return acc + cur }, 0) | |||
approvedAmount.value = val.approvedAmount | |||
getPayInfo(val.id) | |||
getProjectDetail(val.projectCode, val.fromType) | |||
}, | |||
searchForm = reactive({ | |||
projectName: undefined | |||
}), | |||
search = () => { | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await libAllList({ | |||
...pageParams, | |||
projectName: searchForm.projectName | |||
}) | |||
data.value = res.data.records.map(i => { | |||
return { | |||
...i, | |||
isRadioDisabled: i.annualAccumulateAmountList?.map(i => i.annualAmount)?.reduce((acc, cur) => { return acc + cur }, 0) === i.approvedAmount | |||
} | |||
}) | |||
total.value = res.data.total | |||
}, | |||
// 表单 | |||
ruleFormRef = ref(), | |||
moneyValidator = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
moneyValidator1 = (rule, value, callback) => { | |||
if (!value) callback() | |||
if (!/^\d+(\.\d{1,6})?$/.test(value)) { | |||
callback('请输入正确格式,最多保留六位小数') | |||
} else if (value * 1 >= 100000000) { | |||
callback('请输入正确格式,小于100000000') | |||
} | |||
let maxData = 0 | |||
paymentsData.value.forEach(i => { | |||
if (new Date(i.paymentTime).getFullYear() < ruleForm.value.projectYear * 1) { | |||
maxData += i.paymentAmount - i.actualPaymentAmount | |||
} | |||
}) | |||
maxData += paymentsData.value.find(i => new Date(i.paymentTime).getFullYear() === ruleForm.value.projectYear * 1)?.paymentAmount | |||
if (value > maxData) { | |||
callback(`支付金额最大不能超过${maxData}万元`) | |||
} else { | |||
callback() | |||
} | |||
}, | |||
// yearValidator = (rule, value, callback) => { | |||
// if (!value) callback() | |||
// if (!paymentsData.value?.length) { | |||
// callback('未有支付信息,无法提交') | |||
// } | |||
// const years1 = paymentsData.value.map(i => new Date(i.paymentTime).getFullYear() + '') | |||
// // const years2 = paymentsData.value.filter(i => i.actualPaymentAmount || i.actualPaymentAmount === 0).map(i => new Date(i.paymentTime).getFullYear() + '') | |||
// if (!years1.includes(value)) { | |||
// callback('未有所选年度的支付计划,无法提交') | |||
// } else { | |||
// callback() | |||
// } | |||
// // else if (!years2.includes(value)) { | |||
// // callback('未填写当年度的实际支付金额,请去合同备案补充”') | |||
// // } | |||
// }, | |||
disabledDate = (time) => { | |||
return new Date(time).getFullYear() <= new Date().getFullYear() | |||
}, | |||
rules = reactive({ | |||
projectId: [ | |||
{ required: true, message: '请选择关联项目', trigger: 'blur' } | |||
], | |||
projectYear: [ | |||
{ required: true, message: '请选择预算年度', trigger: 'blur' } | |||
// { validator: yearValidator, trigger: 'blur' } | |||
], | |||
annualPaymentAmount: [ | |||
{ required: true, message: '请输入年度支付金额', trigger: 'blur' }, | |||
{ validator: moneyValidator1, trigger: 'blur' } | |||
], | |||
haveAmount: [ | |||
{ required: true, message: '请输入自有资金金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
govOwnFinanceAmount: [ | |||
{ required: true, message: '请输入政府投资-本级财政资金金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
govSuperiorFinanceAmount: [ | |||
{ required: true, message: '请输入政府投资-上级补助资金金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
bankLendingAmount: [ | |||
{ required: true, message: '请输入银行贷款金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
], | |||
otherAmount: [ | |||
{ required: true, message: '请输入其他金额', trigger: 'blur' }, | |||
{ validator: moneyValidator, trigger: 'blur' } | |||
] | |||
}), | |||
ruleForm = ref({ | |||
id: route.query.id || undefined, | |||
orgCode: userInfo.empPosUnitCode, | |||
regionCode: userInfo.regionCode | |||
}), | |||
// floatAdd = (args) => { | |||
// const data = [] | |||
// args.forEach(i => { | |||
// try { | |||
// data.push(i.toString().split('.')[1].length) | |||
// } catch (e) { | |||
// data.push(0) | |||
// } | |||
// }) | |||
// const m = Math.pow(10, Math.max(...data)) | |||
// let sum = 0 | |||
// args.forEach(item => { | |||
// sum += item * m | |||
// }) | |||
// return sum / m | |||
// }, | |||
submitForm = async (formEl) => { | |||
if (!formEl) return | |||
await formEl.validate(async (valid, fields) => { | |||
if (valid) { | |||
// if (ruleForm.value.projectYear * 1 <= maxYear.value * 1) { | |||
// proxy.$message.warning('预算年度必须大于累计投资的最大年度') | |||
// return | |||
// } | |||
// if (floatAdd([ruleForm.value.annualPaymentAmount, totalAmount.value]) > approvedAmount.value) { | |||
// proxy.$message.warning('累计年度投资金额必须小于等于批复总金额') | |||
// return | |||
// } | |||
if (errorText.value) { | |||
proxy.$message.error(errorText.value) | |||
return | |||
} | |||
// const total = floatAdd([ruleForm.value.haveAmount, ruleForm.value.govOwnFinanceAmount, ruleForm.value.govSuperiorFinanceAmount, ruleForm.value.bankLendingAmount, ruleForm.value.otherAmount]) | |||
// if (total !== ruleForm.value.annualPaymentAmount) { | |||
// proxy.$message.warning('各资金来源的和必须等于年度支付金额') | |||
// return | |||
// } | |||
if (!route.query.id) { | |||
const arr = Object.values(formRefs).map(async i => i?.formRef && await i.formRef.validate()) | |||
await Promise.all(arr) | |||
} | |||
const postData = { | |||
...ruleForm.value, | |||
projectYear: ruleForm.value.projectYear * 1 | |||
} | |||
await renewalDeclared(postData) | |||
!route.query.id && submitProject() | |||
} else { | |||
console.log('error submit!', fields) | |||
} | |||
}) | |||
}, | |||
getDetail = async () => { | |||
const res = await renewalDeclaredDetail(route.query.id) | |||
ruleForm.value = { ...res.data, projectYear: res.data.projectYear + '' } | |||
data.value = [{ ...res.data }] | |||
maxYear.value = res.data.annualAccumulateAmountList?.length > 1 && res.data.annualAccumulateAmountList.reduce((acc, cur) => Math.max(acc.projectYear, cur.projectYear)) || res.data.annualAccumulateAmountList[0].projectYear | |||
totalAmount.value = res.data.annualAccumulateAmountList?.map(i => i.annualAmount)?.reduce((acc, cur) => { return acc + cur }, 0) | |||
approvedAmount.value = res.data.approvalAmount | |||
getPayInfo(res.data.projectId) | |||
}, | |||
// 支付信息 | |||
payColumn = [ | |||
{ | |||
label: '付款笔数', | |||
key: 'number', | |||
slot: 'number' | |||
}, | |||
{ | |||
label: '付款计划', | |||
key: 'planAmount', | |||
slot: 'planAmount' | |||
}, | |||
{ | |||
label: '付款比例(%)', | |||
key: 'ratio', | |||
slot: 'ratio' | |||
}, | |||
{ | |||
label: '付款金额(万元)', | |||
key: 'paymentAmount', | |||
slot: 'paymentAmount' | |||
}, | |||
{ | |||
label: '预计付款时间', | |||
key: 'paymentTime', | |||
slot: 'paymentTime' | |||
}, | |||
{ | |||
label: '实际支付金额(万元)', | |||
key: 'actualPaymentAmount', | |||
slot: 'actualPaymentAmount', | |||
width: 180 | |||
} | |||
], | |||
paymentsData = ref(), | |||
errorText = ref(''), | |||
getPayInfo = async (id) => { | |||
const res = await contractDetail(id) | |||
paymentsData.value = res?.data?.payments || [] | |||
errorText.value = '' | |||
// if (!paymentsData.value?.length) { | |||
// errorText.value = '该项目未有支付信息' | |||
// proxy.$message.error(errorText.value) | |||
// return | |||
// } | |||
// let count = 0 | |||
// paymentsData.value.forEach(i => { | |||
// if (new Date(i.paymentTime).getTime() < new Date().getTime() && !(i.actualPaymentAmount || i.actualPaymentAmount === 0)) { | |||
// count++ | |||
// } | |||
// }) | |||
// if (count > 0) { | |||
// errorText.value = '超过预付款时间的支付计划未填写实际支付金额,请去合同备案补充' | |||
// proxy.$message.error(errorText.value) | |||
// return | |||
// } | |||
return | |||
}, | |||
// 补充信息 | |||
formRefs = {}, | |||
detailData = ref(), | |||
basicInfoData = ref(), | |||
getBasicInfoData = (data) => { | |||
basicInfoData.value = data | |||
}, | |||
dictionaryList = ref(), | |||
baseProjSetYear = ref(), | |||
getProYear = (data) => { | |||
baseProjSetYear.value = data | |||
}, | |||
approvalInfoData = ref(), | |||
getApprovalInfoData = (data) => { | |||
approvalInfoData.value = data | |||
}, | |||
baseProjName = ref(), | |||
getProjectDetail = async (projectCode, fromType) => { | |||
let res = {} | |||
// 归集项目详情使用detail 申报项目详情使用convertToCollection | |||
if (fromType === '2') { | |||
res = await detail('1', projectCode) | |||
} else { | |||
res = await convertToCollection(projectCode) | |||
} | |||
baseProjName.value = res.data.baseinfo.baseProjName | |||
detailData.value = { | |||
...res.data, | |||
baseinfo: { | |||
...res.data.baseinfo, | |||
baseProjType: '03' | |||
}, | |||
cimplement: { | |||
...res.data.cimplement, | |||
baseCheckFile: res.data.cimplement?.baseCheckFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseCheckFile))) || undefined, | |||
baseInitialOpinionFile: res.data.cimplement?.baseInitialOpinionFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseInitialOpinionFile))) || undefined, | |||
baseEstaSummFile: res.data.cimplement?.baseEstaSummFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseEstaSummFile))) || undefined, | |||
baseSummReportFile: res.data.cimplement?.baseEstaSummFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseSummReportFile))) || undefined, | |||
baseThirdAcceptFile: res.data.cimplement?.baseEstaSummFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseThirdAcceptFile))) || undefined, | |||
baseInforLevelFile: res.data.cimplement?.baseInforLevelFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseInforLevelFile))) || undefined, | |||
basePasswAssessFile: res.data.cimplement?.basePasswAssessFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.basePasswAssessFile))) || undefined, | |||
baseFinanlAuditFile: res.data.cimplement?.baseFinanlAuditFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseFinanlAuditFile))) || undefined, | |||
baseUserConsFile: res.data.cimplement?.baseUserConsFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseUserConsFile))) || undefined, | |||
baseFinalExpertOpinionFile: res.data.cimplement?.baseFinalExpertOpinionFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseFinalExpertOpinionFile))) || undefined, | |||
baseEngineerPostpoFile: res.data.cimplement?.baseEngineerPostpoFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseEngineerPostpoFile))) || undefined, | |||
baseChangeFormFile: res.data.cimplement?.baseChangeFormFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseChangeFormFile))) || undefined, | |||
baseChanFile: res.data.cimplement?.baseChanFile && JSON.stringify(changFilesParam(JSON.parse(res.data.cimplement?.baseChanFile))) || undefined | |||
} | |||
} | |||
}, | |||
changeYear = () => { | |||
detailData.value.baseinfo.baseProjName = baseProjName.value + `(${ruleForm.value.projectYear})` | |||
}, | |||
changePostData = () => { | |||
const baseinfo = JSON.parse(JSON.stringify(formRefs['baseinfo'].formData)) | |||
const apply = JSON.parse(JSON.stringify(formRefs['apply'].formData)) | |||
const application = formRefs['application'] && JSON.parse(JSON.stringify(formRefs['application'].formData)) || {} | |||
const baseCore = formRefs['baseCore'] && JSON.parse(JSON.stringify(formRefs['baseCore'].formData)) || {} | |||
const approve = formRefs['approve'] && JSON.parse(JSON.stringify(formRefs['approve'].formData)) || {} | |||
const procures = formRefs['procures'] && JSON.parse(JSON.stringify(formRefs['procures'].formData)) || [] | |||
const cimplement = formRefs['cimplement'] && JSON.parse(JSON.stringify(formRefs['cimplement'].formData)) || [] | |||
return { | |||
baseProjId: '', | |||
baseinfo: { | |||
...baseinfo, | |||
baseProvManDeprtType: baseinfo?.baseProvManDeprtType * 1 || undefined, | |||
baseConstructionType: baseinfo?.baseConstructionType?.join(';') | |||
// baseAreaCode: baseinfo?.baseArea?.baseAreaCode || undefined, | |||
// baseAreaName: baseinfo?.baseArea?.baseAreaName || undefined, | |||
// baseArea: undefined | |||
}, | |||
apply: { | |||
...apply, | |||
baseProjStartTime: apply?.baseProjTime?.length ? apply?.baseProjTime[0] + ' 00:00:00' : undefined, | |||
baseProjEndTime: apply?.baseProjTime?.length ? apply?.baseProjTime[1] + ' 00:00:00' : undefined, | |||
baseProjTime: undefined, | |||
baseHistorProjId: apply?.missing || baseinfo?.baseProjType === '01' ? '' : apply?.baseHistorProjs?.map(i => i.baseProjId)?.join(';'), | |||
baseHistorProjName: apply?.missing || baseinfo?.baseProjType === '01' ? '' : apply?.baseHistorProjs?.map(i => i.baseProjName)?.join(';'), | |||
baseHistorProjYear: apply?.missing || baseinfo?.baseProjType === '01' ? '' : apply?.baseHistorProjs?.map(i => i.baseProjSetYear)?.join(';'), | |||
baseProjAmountOri: apply?.baseProjAmountOri?.join(';') || undefined, | |||
baseProjBasis: apply?.baseProjBasis?.map(i => i.value)?.join(';') || undefined, | |||
baseProjBasisFile: apply?.baseProjBasis?.map(i => i.fileList && JSON.stringify(changFilesParam(i.fileList)))?.join(';') || '', | |||
beseExpectedResults: apply?.beseExpectedResults?.length && JSON.stringify(apply.beseExpectedResults) || '', | |||
baseProjApplyFile: ((['01', '02', '04', '05'].includes(baseinfo?.baseProjType) && apply?.baseProjSetYear * 1 >= 2023) || apply?.baseProjSetYear * 1 < 2023) && apply?.baseProjApplyFile?.length ? JSON.stringify(changFilesParam(apply?.baseProjApplyFile)) : '', | |||
baseResearchReportFile: (baseinfo?.baseProjType === '01' || baseinfo?.baseProjType === '02') && apply?.baseResearchReportFile?.length ? JSON.stringify(changFilesParam(apply?.baseResearchReportFile)) : '', | |||
baseProjOtherFile: apply?.baseProjOtherFile?.length ? JSON.stringify(changFilesParam(apply?.baseProjOtherFile)) : '', | |||
baseHistorProjs: undefined, | |||
...application, | |||
baseProjSysCode: application?.applications?.map(i => i.application.applicationCode).join(';') || '', | |||
baseProjSys: application?.applications?.map(i => i.application.applicationName).join(';') || '', | |||
baseAccountAppName: application?.applications?.map(i => i.baseAccountAppName).join(';') || '', | |||
baseBrainName: application?.applications?.map(i => i.baseBrainName).join(';') || '', | |||
applications: undefined, | |||
...baseCore, | |||
baseCoreBusinessCode: baseCore?.coreBusiness?.map(i => i.id).join(';') || '', | |||
baseCoreBusiness: baseCore?.coreBusiness?.map(i => i.matterName).join(';') || '', | |||
baseCoreBusinessOrg: baseCore?.coreBusiness?.map(i => i.orgName).join(';') || '', | |||
coreBusiness: undefined, | |||
baseProjId: '' | |||
}, | |||
approve: { | |||
...approve, | |||
baseReviewResults: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewResults : '', | |||
baseReviewOpinion: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewOpinion : '', | |||
baseReviewCommentsFile: baseinfo?.baseProjSetProg !== '01' ? approve?.baseReviewCommentsFile?.length && JSON.stringify(changFilesParam(approve?.baseReviewCommentsFile)) : '', | |||
equalProtectionLevel: baseinfo?.baseProjIsConfidentiality === '01' && !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.equalProtectionLevel : '', | |||
approvalFile: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.approvalFile?.length && JSON.stringify(changFilesParam(approve?.approvalFile)) : '', | |||
baseExpertTotalMoney: !['01', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseExpertTotalMoney : '', | |||
baseExpertYearMoney: !['01', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseExpertYearMoney : '', | |||
baseInitialReviewTotalMoney: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseInitialReviewTotalMoney : '', | |||
baseProjReplyAmount: !['01', '02', '03'].includes(baseinfo?.baseProjSetProg) ? approve?.baseProjReplyAmount : '', | |||
releaseYearMoney: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) ? approve?.releaseYearMoney : '', | |||
preliminaryDesignScheme: approve?.baseProjReplyAmount >= 5000 && ['04', '05', '06', '07', '00'].includes(baseinfo.baseProjSetProg) ? approve?.preliminaryDesignScheme?.length && JSON.stringify(changFilesParam(approve.preliminaryDesignScheme)) : '', | |||
preliminaryDesignFile: approve?.baseProjReplyAmount >= 5000 && ['04', '05', '06', '07', '00'].includes(baseinfo.baseProjSetProg) ? approve?.preliminaryDesignFile?.length && JSON.stringify(changFilesParam(approve.preliminaryDesignFile)) : '' | |||
}, | |||
procures: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && procures?.sections?.map(i => { | |||
return { | |||
...i, | |||
baseBidName: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseBidName || '', | |||
baseProjPurchaseWay: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseProjPurchaseWay || '', | |||
basePurchaseCode: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.basePurchaseCode || '', | |||
basePurchasingAgencies: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.basePurchasingAgencies || '', | |||
baseUnifiedCreditCode: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.baseUnifiedCreditCode || '', | |||
baseWinningBidTime: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseWinningBidTime || '', | |||
baseProjPurchaseAmount: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseProjPurchaseAmount || '', | |||
baseConsDeprt: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseConsDeprt || '', | |||
baseConsDeprtUsci: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.baseConsDeprtUsci || '', | |||
basePaymentTime: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.basePaymentTime || '', | |||
paymentProgress: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && i.paymentProgress || '', | |||
purchaseFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.purchaseFile?.length ? JSON.stringify(changFilesParam(i.purchaseFile)) : '', | |||
biddingFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.biddingFile?.length ? JSON.stringify(changFilesParam(i.biddingFile)) : '', | |||
purchaseContract: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && i.purchaseContract?.length ? JSON.stringify(changFilesParam(i.purchaseContract)) : '' | |||
} | |||
}) || [], | |||
cimplement: { | |||
...cimplement, | |||
baseInitialOpinionFile: cimplement?.baseInitialOpinionFile?.length ? JSON.stringify(changFilesParam(cimplement.baseInitialOpinionFile)) : '', | |||
baseInforLevelFile: ((['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && baseinfo?.baseConstructionType?.includes('01')) || !baseinfo?.baseConstructionType?.includes('01')) && cimplement?.baseInforLevelFile?.length ? JSON.stringify(changFilesParam(cimplement.baseInforLevelFile)) : '', | |||
basePasswAssessFile: (['04', '05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.basePasswAssessFile?.length ? JSON.stringify(changFilesParam(cimplement.basePasswAssessFile)) : '', | |||
baseThirdAcceptFile: cimplement.baseThirdAcceptFile?.length ? JSON.stringify(changFilesParam(cimplement.baseThirdAcceptFile)) : '', | |||
baseCheckFile: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.baseCheckFile?.length ? JSON.stringify(changFilesParam(cimplement.baseCheckFile)) : '', | |||
baseFinanlAuditFile: ['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) && approve?.releaseYearMoney * 1 >= 2000 && cimplement?.baseFinanlAuditFile?.length ? JSON.stringify(changFilesParam(cimplement.baseFinanlAuditFile)) : '', | |||
baseUserConsFile: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.baseUserConsFile?.length ? JSON.stringify(changFilesParam(cimplement.baseUserConsFile)) : '', | |||
baseEstaSummFile: cimplement?.baseEstaSummFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseEstaSummFile)) : '', | |||
baseSummReportFile: (['05', '06', '07', '00'].includes(baseinfo?.baseProjSetProg) || apply?.baseProjSetYear * 1 < 2023) && cimplement?.baseSummReportFile?.length ? JSON.stringify(changFilesParam(cimplement.baseSummReportFile)) : '', | |||
baseFinalExpertOpinionFile: baseinfo?.baseProjSetProg === '07' && cimplement.baseFinalExpertOpinionFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseFinalExpertOpinionFile)) : '', | |||
baseEngineerPostpoFile: cimplement?.baseEngineerPostpoFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseEngineerPostpoFile)) : '', | |||
baseChangeFormFile: cimplement?.baseChangeFormFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseChangeFormFile)) : '', | |||
baseChanFile: cimplement?.baseChanFile?.length ? JSON.stringify(changFilesParam(cimplement?.baseChanFile)) : '' | |||
} | |||
} | |||
}, | |||
submitProject = async () => { | |||
const postData = changePostData() | |||
await save(postData) | |||
proxy.$message.success('提交成功!') | |||
router.go(-1) | |||
} | |||
onMounted(async () => { | |||
dictionaryList.value = (await dictionary()).data | |||
if (route.query.id) { | |||
getDetail() | |||
} else { | |||
getTableData() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<div class="footerPage"> | |||
<el-alert | |||
v-if="ruleForm.approvalStatus==='NOT_PASS'" | |||
style="marginBottom:20px;" | |||
title="审核不通过" | |||
type="error" | |||
:description="`审核意见:${ruleForm.auditOpinion}`" | |||
show-icon | |||
/> | |||
<el-card class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>申报信息</span> | |||
</div> | |||
</template> | |||
<el-form | |||
ref="ruleFormRef" | |||
:model="ruleForm" | |||
:rules="rules" | |||
label-width="auto" | |||
class="demo-ruleForm" | |||
status-icon | |||
> | |||
<el-input | |||
v-if="!$route.query.id" | |||
v-model="searchForm.projectName" | |||
placeholder="搜索项目名称" | |||
style="width: 200px;margin-left: 100px;" | |||
class="mb-8" | |||
> | |||
<template #append> | |||
<el-button icon="Search" @click="search" /> | |||
</template> | |||
</el-input> | |||
<el-form-item | |||
label="关联项目" | |||
prop="projectId" | |||
:label-width="100" | |||
clas="mb-16" | |||
> | |||
<table-list | |||
v-if="!route.query.id" | |||
ref="tableListRef" | |||
:column="column" | |||
:height="350" | |||
:data="data" | |||
:total="total" | |||
class="w-full" | |||
row-key="id" | |||
@radio-change="radioChange" | |||
@get-table-data="getTableData" | |||
> | |||
<template #annualAccumulateAmountList="{scope}"> | |||
<p v-for="(item,index) in scope.row.annualAccumulateAmountList" :key="index">{{ index+1 }}、{{ item.projectYear }}年投资{{ item.annualAmount }}万元</p> | |||
</template> | |||
</table-list> | |||
<table-list | |||
v-else | |||
ref="tableListRef" | |||
:column="column1" | |||
:data="data" | |||
:height="200" | |||
:pagination="false" | |||
class="flex-1" | |||
><template #annualAccumulateAmountList="{scope}"> | |||
<p v-for="(item,index) in scope.row.annualAccumulateAmountList" :key="index">{{ index+1 }}、{{ item.projectYear }}年投资{{ item.annualAmount }}万元</p> | |||
</template></table-list> | |||
</el-form-item> | |||
<p class="mb-16 flex items-center"> | |||
<span class="mr-24">支付信息</span> | |||
<span class="text-danger text-14">温馨提示:实际支付金额请去合同信息填写</span> | |||
</p> | |||
<table-list | |||
ref="tableListRef" | |||
:column="payColumn" | |||
:data="paymentsData" | |||
:pagination="false" | |||
:empty-temp="false" | |||
class="mb-16" | |||
> | |||
<template #number="{scope}"> | |||
<span>第{{ scope.$index+1 }}笔</span> | |||
</template> | |||
<template #planAmount="{scope}"> | |||
{{ scope.row.planAmount }} | |||
</template> | |||
<template #ratio="{scope}"> | |||
{{ scope.row.ratio }} | |||
</template> | |||
<template #paymentAmount="{scope}"> | |||
{{ scope.row.paymentAmount }} | |||
</template> | |||
<template #paymentTime="{scope}"> | |||
{{ scope.row.paymentTime }} | |||
</template> | |||
<template #actualPaymentAmount="{scope}"> | |||
{{ scope.row.actualPaymentAmount }} | |||
</template> | |||
</table-list> | |||
<p style="margin-bottom: 16px;">申报续建资金信息</p> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="预算年度" | |||
prop="projectYear" | |||
> | |||
<el-date-picker | |||
v-model="ruleForm.projectYear" | |||
type="year" | |||
placeholder="请选择" | |||
format="YYYY" | |||
value-format="YYYY" | |||
:disabled-date="disabledDate" | |||
@change="changeYear" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
:label="`${ruleForm.projectYear||''}支付金额`" | |||
prop="annualPaymentAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.annualPaymentAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="自有资金(万元)" | |||
prop="haveAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.haveAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="政府投资-本级财政资金(万元)" | |||
prop="govOwnFinanceAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.govOwnFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="政府投资-上级补助资金(万元)" | |||
prop="govSuperiorFinanceAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.govSuperiorFinanceAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="银行贷款(万元)" | |||
prop="bankLendingAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.bankLendingAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="20"> | |||
<el-col :span="12"> | |||
<el-form-item | |||
label="其他" | |||
prop="otherAmount" | |||
> | |||
<el-input-number | |||
v-model="ruleForm.otherAmount" | |||
placeholder="请填写" | |||
:min="0" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<template v-if="!route.query.id"> | |||
<p style="margin-bottom: 16px;">补充项目信息</p> | |||
<el-collapse> | |||
<el-collapse-item name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目基本信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<basic-info | |||
:ref="el=>formRefs['baseinfo']=el" | |||
:detail="detailData" | |||
:dictionary-list="dictionaryList" | |||
:is-supplemented="true" | |||
@get-basic-info-data="getBasicInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="2" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目申报信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<project-declare-info | |||
:ref="el=>formRefs['apply']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:dictionary-list="dictionaryList" | |||
:is-supplemented="true" | |||
@get-pro-year="getProYear" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="!(basicInfoData?.baseConstructionType?.length===1&&basicInfoData?.baseConstructionType.includes('01'))" name="3" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目关联信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<application-info | |||
:ref="el=>formRefs['application']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:is-supplemented="true" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="4" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">核心业务</div> | |||
</template> | |||
<div class="pb-24"> | |||
<core-business :ref="el=>formRefs['baseCore']=el" :detail="detailData" :is-supplemented="true" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-if="basicInfoData?.baseProjSetProg!=='01'" name="5" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目立项评审信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<project-approval-info | |||
:ref="el=>formRefs['approve']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:dictionary-list="dictionaryList" | |||
:is-supplemented="true" | |||
@get-approval-info-data="getApprovalInfoData" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item v-show="['05','06','07','00'].includes(basicInfoData?.baseProjSetProg)||baseProjSetYear*1<2023" name="6" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">项目采购、资金支付信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<purchase-info | |||
:ref="el=>formRefs['procures']=el" | |||
:detail="detailData" | |||
:dictionary-list="dictionaryList" | |||
:base-proj-set-year="baseProjSetYear" | |||
:basic-info-data="basicInfoData" | |||
:is-supplemented="true" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="7" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">实施材料信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<emp-materials | |||
:ref="el=>formRefs['cimplement']=el" | |||
:detail="detailData" | |||
:basic-info-data="basicInfoData" | |||
:base-proj-set-year="baseProjSetYear" | |||
:approval-info-data="approvalInfoData" | |||
:is-supplemented="true" | |||
/> | |||
</div> | |||
</el-collapse-item> | |||
</el-collapse> | |||
</template> | |||
</el-form> | |||
</el-card> | |||
</div> | |||
<div class="footer"> | |||
<el-button | |||
type="primary" | |||
@click="submitForm(ruleFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button @click="router.go(-1)">返回</el-button> | |||
</div> | |||
</template> | |||
<style lang='less' scoped> </style> |
@@ -0,0 +1,431 @@ | |||
<script name="expertEnroll" setup> | |||
import { getCurrentInstance, ref, onMounted, reactive } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import BasicInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/basicInfo.vue' | |||
import EduInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/eduInfo.vue' | |||
import JobInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/jobInfo.vue' | |||
import ProfessionalInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/professionalInfo.vue' | |||
import RecommendInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/recommendInfo.vue' | |||
import { expertEdit, expertSignUp, registration } from '@/http/apis/expertManage/expertStore' | |||
import { downloadFileUrl } from '@/utils/uploadAction.js' | |||
import { getExpertDetail } from '@/http/apis/expertManage/expertVerify' | |||
import { getVerificationCode } from '@/http/apis/auth' | |||
import getTimeDiffer from '@/utils/getTimeDiffer' | |||
import ExpertOtherInfo from '@/pages/expertManage/expertStore/addOrEditExpert/components/expertOtherInfo.vue' | |||
const { proxy } = getCurrentInstance(), | |||
route = useRoute(), | |||
router = useRouter(), | |||
formData = ref({ | |||
basicInfo: { | |||
// isDingUser: false | |||
} | |||
}), | |||
collapseModal = ref(['1', '2', '3', '4', '5', '6']), | |||
basicInfoRef = ref(), // 基本信息 | |||
eduInfoRef = ref(), // 学历信息 | |||
jobInfoRef = ref(), // 职业信息 | |||
professionalInfoRef = ref(), // 专业信息 | |||
recommendInfoRef = ref(), // 推荐信息 | |||
expertOtherInfoRef = ref(), // 其他信息 | |||
// 提交 | |||
submitForm = async () => { | |||
const form = [] | |||
form.push(new Promise((resolve, reject) => { | |||
basicInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
eduInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
jobInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
professionalInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
recommendInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
expertOtherInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
Promise.all([...form]).then(async () => { | |||
saveData() | |||
}).catch(err => { | |||
if (err) { | |||
proxy.$message.warning(err) | |||
} | |||
}) | |||
}, | |||
saveData = async () => { | |||
var data = { | |||
expertUserId: route.query.id || undefined, | |||
basicInfo: { | |||
...basicInfoRef.value.formData, | |||
// isDingUser: formData.value.basicInfo.isDingUser, | |||
avatarUrl: basicInfoRef.value.formData?.avatarFile?.fileId && await downloadFileUrl(basicInfoRef.value.formData.avatarFile.fileId), | |||
expertIntentionWorkRegions: | |||
basicInfoRef.value.formData.expertIntentionWorkRegions?.map((i, index) => ({ | |||
regionName: i.unionCode?.join('@@'), | |||
regionCode: i.unionCode?.slice(-1)[0]?.split('##')[0], | |||
regionLevel: i.unionCode?.slice(-1)[0]?.split('##')[2] | |||
})), | |||
expertRegionInfo: { | |||
regionName: basicInfoRef.value.formData.expertRegionInfo?.join('@@'), | |||
regionCode: basicInfoRef.value.formData.expertRegionInfo?.slice(-1)[0].split('##')[0], | |||
regionLevel: basicInfoRef.value.formData.expertRegionInfo?.slice(-1)[0].split('##')[2] | |||
}, | |||
political: basicInfoRef.value.formData.political && [basicInfoRef.value.formData.political] || [], | |||
expertSource: basicInfoRef.value.formData.expertSource && [basicInfoRef.value.formData.expertSource] || [], | |||
expertType: basicInfoRef.value.formData.expertType && [basicInfoRef.value.formData.expertType] || [] | |||
}, | |||
eduInfo: { | |||
...eduInfoRef.value.formData, | |||
edu: eduInfoRef.value.formData.edu && [eduInfoRef.value.formData.edu], | |||
degree: eduInfoRef.value.formData.degree && [eduInfoRef.value.formData.degree], | |||
degreeCertificateFile: eduInfoRef.value.formData.degreeCertificateFile && await Promise.all( | |||
eduInfoRef.value.formData.degreeCertificateFile && eduInfoRef.value.formData.degreeCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [], | |||
graduationCertificateFile: eduInfoRef.value.formData.graduationCertificateFile && await Promise.all( | |||
eduInfoRef.value.formData.graduationCertificateFile && eduInfoRef.value.formData.graduationCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [] | |||
}, | |||
jobInfo: { | |||
...jobInfoRef.value.formData, | |||
administrativeRank: jobInfoRef.value.formData.administrativeRank && [jobInfoRef.value.formData.administrativeRank] || [], | |||
jobStatus: jobInfoRef.value.formData.jobStatus && [jobInfoRef.value.formData.jobStatus] || [], | |||
companyAttribute: jobInfoRef.value.formData.companyAttribute && [jobInfoRef.value.formData.companyAttribute] || [] | |||
}, | |||
professionalInfo: { | |||
...professionalInfoRef.value.formData, | |||
goodAt: professionalInfoRef.value.formData.goodAt && [professionalInfoRef.value.formData.goodAt] || [], | |||
titleLevel: professionalInfoRef.value.formData.titleLevel && [professionalInfoRef.value.formData.titleLevel] || [], | |||
titleCertificateFile: professionalInfoRef.value.formData.titleCertificateFile && await Promise.all( | |||
professionalInfoRef.value.formData.titleCertificateFile && professionalInfoRef.value.formData.titleCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [], | |||
technicalExpertise: professionalInfoRef.value.formData.technicalExpertise && professionalInfoRef.value.formData.technicalExpertise.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}), | |||
industrySector: professionalInfoRef.value.formData.industrySector && professionalInfoRef.value.formData.industrySector.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}) | |||
}, | |||
recommendInfo: { | |||
...recommendInfoRef.value.formData, | |||
recommendedWay: recommendInfoRef.value.formData.recommendedWay && [recommendInfoRef.value.formData.recommendedWay] || [], | |||
recommendationProofFile: recommendInfoRef.value.formData.recommendationProofFile && await Promise.all( | |||
recommendInfoRef.value.formData.recommendationProofFile && recommendInfoRef.value.formData.recommendationProofFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [] | |||
}, | |||
expertOtherInfo: { | |||
...expertOtherInfoRef.value.formData, | |||
other: expertOtherInfoRef.value.formData.other && expertOtherInfoRef.value.formData.other.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}) | |||
} | |||
} | |||
if (route.name === 'expertEnroll') { | |||
showSmsDiaglog(data) | |||
} else { | |||
if (!route.query.id) { | |||
await expertSignUp(data) | |||
proxy.$message.success('专家新增成功') | |||
router.go(-1) | |||
} else { | |||
await expertEdit(data) | |||
proxy.$message.success('专家编辑成功') | |||
router.go(-1) | |||
} | |||
} | |||
}, | |||
// 专家报名-短信验证 | |||
smsDialogData = reactive({ | |||
visible: false, | |||
data: {} | |||
}), | |||
showSmsDiaglog = (data) => { | |||
smsDialogData.data = data | |||
smsDialogData.visible = true | |||
}, | |||
smsDialogFormRef = ref(), | |||
smsDialogForm = ref({ | |||
verificationCode: '' | |||
}), | |||
smsDialogRules = { | |||
'verificationCode': [{ required: true, message: '请输入' }] | |||
}, | |||
smsDialogLoading = ref(false), | |||
submitSms = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid) => { | |||
if (valid) { | |||
await registration({ | |||
...smsDialogData.data, | |||
verificationCode: smsDialogForm.value.verificationCode | |||
}) | |||
proxy.$message.success('提交成功') | |||
router.go(0) | |||
} | |||
} | |||
) | |||
}, | |||
timer = ref(null), | |||
count = ref(0), | |||
getVerificationCodeFunc = async () => { | |||
await getVerificationCode({ mobile: basicInfoRef.value.formData.phoneNo, verificationType: 'EXPERT_REGISTER' }) | |||
proxy.$message.success('验证码已发送') | |||
const TIME_COUNT = 60 | |||
if (!timer.value) { | |||
count.value = TIME_COUNT | |||
timer.value = setInterval(() => { | |||
if (count.value > 0 && count.value <= TIME_COUNT) { | |||
count.value-- | |||
} else { | |||
clearInterval(timer.value) | |||
timer.value = null | |||
} | |||
}, 1000) | |||
} | |||
}, | |||
// 获取详情 | |||
getDetail = async () => { | |||
const res = await getExpertDetail({ expertUserId: route.query.id }) | |||
basicInfoRef.value.setFormData(res.data.basicInfo) | |||
eduInfoRef.value.setFormData(res.data.eduInfo) | |||
jobInfoRef.value.setFormData(res.data.jobInfo) | |||
professionalInfoRef.value.setFormData(res.data.professionalInfo) | |||
recommendInfoRef.value.setFormData(res.data.recommendInfo) | |||
expertOtherInfoRef.value.setFormData(res.data.expertOtherInfo) | |||
}, | |||
// 是否失效 | |||
isFailure = ref(false), | |||
getIsFailure = () => { | |||
const time = window.atob(route.query.time) | |||
if (getTimeDiffer(new Date(), new Date(time * 1), 'd') > 3) { | |||
isFailure.value = true | |||
} | |||
} | |||
onMounted(() => { | |||
if (route.query.time) { | |||
getIsFailure() | |||
setInterval(() => { | |||
getIsFailure() | |||
}, 10000) | |||
} else { | |||
isFailure.value = true | |||
} | |||
if (route.query.id) { | |||
getDetail() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<div class="expertEnroll footerPage" :class="{ 'relative':route.path === 'expertEnroll'}"> | |||
<div class="top">丽水市信息化专家报名</div> | |||
<template v-if="!isFailure"> | |||
<div class="px-[107px] mt-[-60px]"> | |||
<el-collapse v-model="collapseModal"> | |||
<el-collapse-item name="1" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">基本信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<basic-info ref="basicInfoRef" :basic-info="formData.basicInfo" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="2" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">学历信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<edu-info ref="eduInfoRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="3" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">职业信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<job-info ref="jobInfoRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="4" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">专业信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<professional-info ref="professionalInfoRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="5" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">推荐信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<recommend-info ref="recommendInfoRef" /> | |||
</div> | |||
</el-collapse-item> | |||
<el-collapse-item name="6" class="mb-16"> | |||
<template #title> | |||
<div class="collapse-title">其他信息</div> | |||
</template> | |||
<div class="pb-24"> | |||
<expert-other-info ref="expertOtherInfoRef" /> | |||
</div> | |||
</el-collapse-item> | |||
</el-collapse> | |||
</div> | |||
<div class="footer"> | |||
<el-button | |||
type="primary" | |||
@click="submitForm" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button @click="router.go(-1)">取消</el-button> | |||
</div> | |||
</template> | |||
<template v-else> | |||
<img src="@/assets/images/link-failure-img.png" style="width: 320px;height: 245px;margin: 160px auto 0" /> | |||
<p style="color: #83868C;" class="mt-32 text-19 text-center">链接已失效,请联系管理员</p> | |||
</template> | |||
<el-dialog | |||
:model-value="smsDialogData.visible" | |||
title="短信验证" | |||
width="400px" | |||
destroy-on-close | |||
@close="smsDialogData.visible=false" | |||
> | |||
<el-form | |||
ref="smsDialogFormRef" | |||
:model="smsDialogForm" | |||
:rules="smsDialogRules" | |||
label-width="auto" | |||
label-suffix=":" | |||
> | |||
<el-form-item label="手机号"> | |||
<span>{{ basicInfoRef.formData.phoneNo }}</span> | |||
</el-form-item> | |||
<el-form-item label="验证码" prop="verificationCode"> | |||
<el-input v-model="smsDialogForm.verificationCode" placeholder="请输入验证码"> | |||
<template #suffix> | |||
<a v-if="!count" class="itemBlue" @click="getVerificationCodeFunc"> 获取验证码</a> | |||
<span v-else class="itemBlue">{{ count }}</span> | |||
</template> | |||
</el-input> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<el-button | |||
type="primary" | |||
:loading="smsDialogLoading" | |||
@click="submitSms(smsDialogFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button | |||
@click="smsDialogData.visible=false" | |||
> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<style lang="less" scoped> | |||
.expertEnroll{ | |||
.top{ | |||
background: url("@/assets/images/expertTopBg.png"); | |||
background-size: 100% 100%; | |||
background-repeat: no-repeat; | |||
padding-top: 60px; | |||
padding-bottom: 117px; | |||
font-size: 53px; | |||
font-weight: 600; | |||
color: #FFFFFF; | |||
text-align: center; | |||
line-height: 75px; | |||
} | |||
.header{ | |||
height: 60px; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
background-color: #fff; | |||
margin-bottom: 15px; | |||
font-size: 20px; | |||
} | |||
:deep(.el-collapse) { | |||
.el-collapse-item__header { | |||
padding: 0px 16px; | |||
font-size: 14px; | |||
} | |||
.el-collapse-item__content { | |||
padding: 16px 16px 16px 0px; | |||
// margin-left: -50px; | |||
} | |||
.el-collapse-item__header.is-active { | |||
border-bottom: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.collapse-title { | |||
flex: 1 0 90%; | |||
order: 1; | |||
.el-collapse-item__header { | |||
flex: 1 0 auto; | |||
order: -1; | |||
} | |||
.el-input-number { | |||
width: 150px !important; | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,124 @@ | |||
<script name="leaveDialog" setup> | |||
import { ref, getCurrentInstance, watch } from 'vue' | |||
import { leaveSave } from '@/http/apis/expertManage/expertReview' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const userInfo = storeToRefs(store.userStore).userInfo | |||
const | |||
{ proxy } = getCurrentInstance(), | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: { | |||
type: Object, | |||
default: undefined | |||
}, | |||
title: { | |||
type: String, | |||
default: undefined | |||
} | |||
}), | |||
emits = defineEmits(['close']), | |||
formRef = ref(), | |||
form = ref({ | |||
}), | |||
rules = { | |||
postscript: [{ required: true, message: '请输入请假原因', trigger: 'blur' }] | |||
}, | |||
submit = async formEl => { | |||
if (!formEl) { | |||
return | |||
} | |||
await formEl.validate(async valid => { | |||
if (valid) { | |||
await leaveSave({ | |||
...form.value, | |||
type: 3, | |||
expertId: props.data.expertId || userInfo.value.userId, | |||
meetingId: props.data.meetingId | |||
}) | |||
proxy.$message.success('提交成功!') | |||
emits('close', true) | |||
} | |||
}) | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
console.log(props.data) | |||
} else { | |||
formRef.value.resetFields() | |||
form.value = {} | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
:title="props.title||`填写请假原因-${data?.meetingName}`" | |||
width="600px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<el-form | |||
ref="formRef" | |||
:model="form" | |||
:rules="rules" | |||
label-width="auto" | |||
label-suffix=":" | |||
> | |||
<el-row> | |||
<template v-if="data?.connecter"> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="联系人" | |||
> | |||
{{ data?.connecter }} | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="联系方式" | |||
>{{ data?.contact }}</el-form-item> | |||
</el-col> | |||
</template> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="请假原因" | |||
prop="postscript" | |||
> | |||
<el-input | |||
v-model="form.postscript" | |||
maxlength="200" | |||
placeholder="请输入" | |||
show-word-limit | |||
type="textarea" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<template #footer> | |||
<div class="flex justify-center"> | |||
<el-button | |||
class="ml-22" | |||
type="primary" | |||
@click="submit(formRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button | |||
@click="emits('close')" | |||
> | |||
关闭 | |||
</el-button> | |||
</div> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,171 @@ | |||
<script name="meetingsLeaveDialog" setup> | |||
import { ref, reactive, watch, h } from 'vue' | |||
import meetingProjectDialog from '../../reviewMeeting/components/meetingProjectDialog.vue' | |||
import store from '@/store' | |||
import leaveDialog from './leaveDialog.vue' | |||
import { meetingListForLeave } from '@/http/apis/expertManage/expertReview' | |||
import { storeToRefs } from 'pinia' | |||
const props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
} | |||
}), | |||
userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
emits = defineEmits(['close']), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '会议名称', | |||
key: 'meetingName', | |||
prop: 'meetingName', | |||
minWidth: '180', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '评审类型', | |||
key: 'meetingTypeName', | |||
prop: 'meetingTypeName' | |||
}, | |||
{ | |||
label: '评审项目', | |||
key: 'projectName', | |||
slot: 'projectName', | |||
minWidth: '80' | |||
}, | |||
{ | |||
label: '联系人/联系方式', | |||
key: 'contact', | |||
prop: 'contact', | |||
minWidth: '180', | |||
render: row => h('span', row.connecter + '/' + row.contact) | |||
}, | |||
{ | |||
label: '是否参与', | |||
key: 'isAbsent', | |||
prop: 'isAbsent', | |||
width: '80', | |||
render: row => h('span', row.expertStatus === 3 || row.expertStatus === 5 ? '是' : '否') | |||
}, | |||
{ | |||
label: '是否请假', | |||
key: 'isAbsent', | |||
prop: 'isAbsent', | |||
width: '80', | |||
render: row => h('span', row.expertStatus === 5 ? '是' : '否') | |||
}, | |||
{ | |||
label: '会议状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '80', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `${row.status === 1 ? 'bg-success' : row.status === 3 ? 'bg-danger' : ''}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `${row.status === 1 ? 'text-success' : row.status === 3 ? 'text-danger' : ''}` | |||
}, | |||
row.status === 1 ? '正常' : '已取消' | |||
) | |||
] | |||
}, | |||
{ | |||
label: '评审时间', | |||
key: 'startTime', | |||
prop: 'startTime', | |||
width: '280', | |||
render: row => h('span', row.startTime + '~' + row.endTime) | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '80', | |||
fixed: 'right' | |||
} | |||
]), | |||
tableData = ref(), | |||
total = ref(0), | |||
tableListRef = ref(), | |||
getTableData = async (pageParams = tableListRef.value?.pageParams) => { | |||
const res = await meetingListForLeave({ | |||
...pageParams, | |||
expertId: userInfo.value.userId | |||
}) | |||
total.value = res.data.total | |||
tableData.value = res.data.records | |||
}, | |||
// 查看项目 | |||
viewProject = (data) => { | |||
meetingProjectDialogData.value.visible = true | |||
meetingProjectDialogData.value.meetingId = data.meetingId | |||
}, | |||
meetingProjectDialogData = ref({ | |||
visible: false, | |||
meetingId: undefined | |||
}), | |||
closeMeetingProjectDialog = () => { | |||
meetingProjectDialogData.value.visible = false | |||
}, | |||
// 请假 | |||
leaveDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
leave = (data) => { | |||
leaveDialogData.visible = true | |||
leaveDialogData.data = data | |||
}, | |||
closeLeaveDialog = (flag) => { | |||
leaveDialogData.visible = false | |||
flag && getTableData() | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
getTableData() | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="会议请假" | |||
width="80%" | |||
@close="emits('close')" | |||
> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:total="total" | |||
:data="tableData" | |||
@get-table-data="getTableData" | |||
> | |||
<template #projectName="{scope}"> | |||
<a @click="viewProject(scope.row)">查看</a> | |||
</template> | |||
<template #action="{scope}"> | |||
<a v-if="scope.row.expertStatus !== 5" @click="leave(scope.row)">请假</a> | |||
<span v-else>-</span> | |||
</template> | |||
</table-list> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button @click="emits('close')">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
<meeting-project-dialog :visible="meetingProjectDialogData.visible" :meeting-id="meetingProjectDialogData.meetingId" @close="closeMeetingProjectDialog" /> | |||
<leave-dialog :visible="leaveDialogData.visible" :data="leaveDialogData.data" @close="closeLeaveDialog" /> | |||
</template> | |||
@@ -0,0 +1,88 @@ | |||
<script setup name="memberOpinion"> | |||
import store from '@/store' | |||
import Accessory from '@/components/accessory/index.vue' | |||
defineProps({ | |||
memberOpinions: Array | |||
}) | |||
const { reviewResultOptions } = store.dictStore.globalDicts || {} | |||
</script> | |||
<template> | |||
<div class="memberOpinion"> | |||
<div v-for="(item,index) in memberOpinions" :key="index" class="box mb-16"> | |||
<div class="flex items-center justify-between title"> | |||
<p class="name font-bold flex items-center"> | |||
<span>{{ item.creator }}</span> | |||
<el-tag v-if="item.isFinal" class="ml-8">最终评审意见</el-tag> | |||
</p> | |||
<p class="time"> | |||
<svg-icon name="time" class="mr-2" /> | |||
<span>{{ item.createOn }}</span> | |||
</p> | |||
</div> | |||
<div class="content"> | |||
<div v-for="(option,key) in item.reviewTemplateOptions" :key="key" class="item"> | |||
<p class="label">{{ option.title }}:</p> | |||
<div> | |||
<p class="value">{{ option.optionsValue }}。</p> | |||
<p class="value">{{ option.otherAdvice }}</p> | |||
</div> | |||
</div> | |||
<div class="item"> | |||
<p class="label">其他意见或建议:</p> | |||
<p class="value">{{ item. otherAdvice }}</p> | |||
</div> | |||
<div class="item"> | |||
<p class="label">附件:</p> | |||
<p class="value"> | |||
<accessory :file-name="item.attachFile?.originalFileName" :file-id="item?.attachFileId" /> | |||
</p> | |||
</div> | |||
<div class="item"> | |||
<p class="label">评审结果:</p> | |||
<p class="value "> | |||
<span | |||
:class="`dot ${item.reviewResult===1?'bg-success':item.reviewResult===2?'bg-warning':'bg-danger'}`" | |||
></span> | |||
<span>{{ reviewResultOptions[item.reviewResult] }}</span> | |||
</p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<style lang="less"> | |||
.memberOpinion{ | |||
.box{ | |||
background: #FFFFFF; | |||
box-shadow: 0px 3px 6px 0px rgba(62,99,170,0.06); | |||
border-radius: 4px; | |||
border: 1px solid #D8DADF; | |||
padding: 24px; | |||
.title{ | |||
margin-bottom: 24px; | |||
.time{ | |||
display: flex; | |||
align-items: center; | |||
color: rgba(0,0,0,0.45); | |||
} | |||
} | |||
.content{ | |||
.item{ | |||
display: flex; | |||
align-items: center; | |||
&:not(:last-of-type){ | |||
margin-bottom: 8px; | |||
} | |||
} | |||
.label{ | |||
color: rgba(0,0,0,0.45); | |||
} | |||
.value{ | |||
color: rgba(0,0,0,0.65); | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,188 @@ | |||
<script setup name="projectList"> | |||
import { reactive } from 'vue' | |||
import store from '@/store' | |||
import noData from '@/components/noData/index.vue' | |||
const { projectTypeOptions, businessTerritory, meetingTypeOptions } = store.dictStore.globalDicts || {}, | |||
props = defineProps({ | |||
listData: Array, | |||
// 分页 | |||
pageSizes: { | |||
type: Array, | |||
default: () => [10, 20, 30, 40] | |||
}, | |||
total: { | |||
type: Number, | |||
default: 0 | |||
}, | |||
small: { | |||
type: Boolean, | |||
default: false | |||
} | |||
}), | |||
emits = defineEmits(['getTableData', 'preExamDeclare', 'toDetail']), | |||
// 分页 | |||
pageParams = reactive({ | |||
pageNumber: 1, | |||
pageSize: props.pageSizes[0] | |||
}), | |||
handleSizeChange = () => { | |||
emits('getTableData', pageParams) | |||
}, | |||
handleCurrentChange = () => { | |||
emits('getTableData', pageParams) | |||
}, | |||
goToDetail = (item) => { | |||
if (new Date().getTime() >= new Date(item.reviewTime).getTime() && (!item.reviewed || (item.isHeadman && item.reviewed < 2))) { | |||
emits('toDetail', item, 1) | |||
} else { | |||
emits('toDetail', item, 2) | |||
} | |||
} | |||
defineExpose({ pageParams }) | |||
</script> | |||
<template> | |||
<div class="projectList"> | |||
<template v-if="listData?.length"> | |||
<div v-for="(item,index) in listData" :key="index" class="list"> | |||
<div class="left"> | |||
<svg-icon | |||
name="projectIcon" | |||
class="icon" | |||
/> | |||
<div class="info"> | |||
<div class="tit"> | |||
<p class="mb-4 pointTit" @click="goToDetail(item)">{{ item.projectName }}</p> | |||
<el-tag v-if="item.bizDomain">{{ businessTerritory[item.bizDomain] }}</el-tag> | |||
</div> | |||
<el-row :gutter="4"> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">申报单位:</span> | |||
<span class="value">{{ item.buildOrgName || '-' }}</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">项目类型:</span> | |||
<span class="value">{{ projectTypeOptions[item.projectType] || '-' }}</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">申报金额:</span> | |||
<span class="value">{{ item.declaredAmount || '-' }}万元</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">预算年度:</span> | |||
<span class="value">{{ item.projectYear }}年</span> | |||
</el-col> | |||
<el-col :span="12" class="mb-8"> | |||
<span class="label">评审时间:</span> | |||
<span class="value">{{ item.reviewTime }}~{{ item.endReviewTime }}</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">评审类型:</span> | |||
<span class="value">{{ meetingTypeOptions[item.reviewType] }}</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">联系人:</span> | |||
<span class="value">{{ item.connecter }}</span> | |||
</el-col> | |||
<el-col :span="6" class="mb-8"> | |||
<span class="label">联系方式:</span> | |||
<span class="value">{{ item.contact }}</span> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</div> | |||
<div class="right"> | |||
<a v-if="new Date().getTime()>=new Date(item.reviewTime).getTime()&&(!item.reviewed||(item.isHeadman&&item.reviewed<2))" @click="emits('toDetail',item,1)">处理</a> | |||
<a v-else @click="emits('toDetail',item,2)">详情</a> | |||
</div> | |||
</div> | |||
</template> | |||
<noData v-else /> | |||
<el-pagination | |||
v-model:currentPage="pageParams.pageNumber" | |||
v-model:page-size="pageParams.pageSize" | |||
:small="small" | |||
background | |||
:page-sizes="props.pageSizes" | |||
layout="total, sizes, prev, pager, next" | |||
:total="props.total" | |||
@size-change="handleSizeChange" | |||
@current-change="handleCurrentChange" | |||
/> | |||
</div> | |||
</template> | |||
<style lang="less"> | |||
.projectList { | |||
.list { | |||
display: flex; | |||
align-items: center; | |||
justify-content: space-between; | |||
font-size: 14px; | |||
padding: 16px; | |||
box-shadow: inset 0px -1px 0px 0px #D8DADF; | |||
.left { | |||
display: flex; | |||
flex: 1; | |||
.icon { | |||
font-size: 44px; | |||
margin-right: 24px; | |||
} | |||
.info { | |||
flex: 1; | |||
.tit { | |||
font-weight: 400; | |||
color: rgba(0, 0, 0, 0.85); | |||
margin: 11px 0 16px; | |||
} | |||
.label { | |||
color: rgba(0, 0, 0, 0.45); | |||
} | |||
.value { | |||
color: rgba(0, 0, 0, 0.65); | |||
} | |||
.statusTag { | |||
font-weight: 400; | |||
line-height: 18px; | |||
border-radius: 4px; | |||
display: inline-block; | |||
padding: 4px; | |||
&.status-warning { | |||
color: #FFA43D; | |||
background: rgba(255, 164, 61, 0.06); | |||
} | |||
&.status-success { | |||
color: #4ECB74; | |||
background: rgba(78,203,116,0.06); | |||
} | |||
&.status-danger { | |||
color: #FF3B30; | |||
background: rgba(255,59,48,0.06); | |||
} | |||
} | |||
} | |||
} | |||
.right{ | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
a{ | |||
margin:0 | |||
} | |||
} | |||
} | |||
.el-pagination { | |||
padding: 16px 16px 0 16px; | |||
flex-wrap: wrap; | |||
justify-content: flex-end; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,157 @@ | |||
<script name="reviewCommentsDialog" setup> | |||
import { ref, onMounted } from 'vue' | |||
import { fileFormatVerification, handleFileSuccess, handleFileError, handleFilePreview, fileTypes, fileDesc } from '@/utils/uploadAction.js' | |||
import store from '@/store' | |||
const | |||
uploadUrl = store.dictStore.uploadUrl, | |||
props = defineProps({ | |||
templateData: Object | |||
}), | |||
formRef = ref(), | |||
form = ref({ | |||
templates: [], | |||
attachments: [] | |||
}), | |||
rules = { | |||
otherAdvice: [{ required: true, message: '请输入意见', trigger: 'blur' }], | |||
reviewResult: [{ required: true, message: '请选择评审结果', trigger: 'blur' }] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
} | |||
onMounted(async () => { | |||
form.value.templates = props.templateData.templates.map(i => { | |||
return { | |||
optionSerialNo: undefined, | |||
otherAdvice: '', | |||
questionSerialNo: i.serialNo | |||
} | |||
}) | |||
form.value.templateId = props.templateData.templateId | |||
}) | |||
defineExpose({ validForm, form }) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="form" | |||
:rules="rules" | |||
label-width="auto" | |||
label-suffix=":" | |||
label-position="top" | |||
class="reviewForm" | |||
> | |||
<el-row> | |||
<template v-if="form.templates?.length"> | |||
<el-col | |||
v-for="(item,index) in templateData.templates" | |||
:key="index" | |||
:span="24" | |||
> | |||
<el-form-item | |||
:label="item.title" | |||
:prop="`templates[${index}].optionSerialNo`" | |||
:rules="[{required:true,message:'请选择'}]" | |||
> | |||
<el-checkbox-group v-if="item.optionType===2" v-model="form.templates[index].optionSerialNo"> | |||
<el-checkbox | |||
v-for="(option,key) in item.options" | |||
:key="key" | |||
:label="option.serialNo" | |||
>{{ option.option }}</el-checkbox> | |||
</el-checkbox-group> | |||
<el-radio-group | |||
v-else | |||
v-model="form.templates[index].optionSerialNo" | |||
class="myWrap" | |||
> | |||
<el-radio | |||
v-for="(option,key) in item.options" | |||
:key="key" | |||
:label="option.serialNo" | |||
>{{ option.option }}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item | |||
:prop="`templates[${index}].otherAdvice`" | |||
> | |||
<el-input | |||
v-model="form.templates[index].otherAdvice" | |||
:rows="2" | |||
type="textarea" | |||
:placeholder="`请输入${item.title}的其他意见或建议`" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</template> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="其他意见或建议" | |||
prop="otherAdvice" | |||
> | |||
<el-input | |||
v-model="form.otherAdvice" | |||
:rows="2" | |||
maxlength="200" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请输入其他意见或建议" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="附件" | |||
prop="attachments" | |||
> | |||
<el-upload | |||
v-model:file-list="form.attachments" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-success="res => handleFileSuccess(res, form.attachments,true)" | |||
:on-error="handleFileError" | |||
:before-upload="file=>fileFormatVerification(file, {types: fileTypes})" | |||
:accept="fileTypes.map(i=>`.${i}`).join(',')" | |||
:limit="1" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button type="primary" class="mr-4">上传附件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip">支持{{ fileDesc }}文件</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24" class="result"> | |||
<el-form-item | |||
label="评审结果" | |||
prop="reviewResult" | |||
class="mb-0" | |||
> | |||
<el-radio-group | |||
v-model="form.reviewResult" | |||
class="ml-4" | |||
> | |||
<el-radio :label="1">评审通过</el-radio> | |||
<el-radio :label="2">通过需调整</el-radio> | |||
<el-radio :label="3">修改方案后重新评审</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.reviewForm{ | |||
.result{ | |||
background: rgba(0,87,255,0.06); | |||
border-radius: 4px; | |||
border: 1px solid #0057FF; | |||
padding:24px 24px 0; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,141 @@ | |||
<script name="fillReviewComments" setup> | |||
import { getCurrentInstance, onMounted, ref } from 'vue' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import reviewComments from '../components/reviewComments.vue' | |||
import memberOpinion from '../components/memberOpinion.vue' | |||
import { template } from '@/http/apis/expertManage/reviewTemplateConfig' | |||
import { listForGroupLeader, save, templatesById } from '@/http/apis/expertManage/expertReview' | |||
const { proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
route = useRoute(), | |||
// 获取模板 | |||
templateData = ref(), | |||
getTemplate = async () => { | |||
const res = await template({ templateType: route.query.reviewType, regionCode: route.query.regionCode }) | |||
templateData.value = res.data | |||
reviewVisible.value = true | |||
}, | |||
reviewVisible = ref(false), | |||
// 提交 | |||
loading = ref(false), | |||
reviewCommentsRef = ref(), | |||
submit = () => { | |||
reviewCommentsRef.value.validForm(async (valid) => { | |||
if (valid) { | |||
loading.value = true | |||
const postData = { | |||
meetingId: route.query.meetingId, | |||
projectId: route.query.projectId, | |||
projectCode: route.query.projectCode, | |||
...reviewCommentsRef.value.form, | |||
reviewTemplateOptions: reviewCommentsRef.value.form.templates.map(i => { | |||
return { | |||
...i, | |||
optionSerialNo: Array.isArray(i.optionSerialNo) ? i.optionSerialNo.map(r => r) : [i.optionSerialNo] | |||
} | |||
}), | |||
attachFileId: reviewCommentsRef.value.form.attachments?.length && reviewCommentsRef.value.form.attachments[0].response.data.id || undefined, | |||
isFinal: route.query.type * 1 === 2, | |||
templates: undefined, | |||
attachments: undefined | |||
} | |||
try { | |||
await save(postData) | |||
proxy.$message.success('提交成功') | |||
loading.value = false | |||
router.go(-2) | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
}) | |||
}, | |||
// 组员意见-抽屉 | |||
drawerVisible = ref(false), | |||
templatesData = ref([]), // 模板数据 | |||
memberOpinions = ref([]), // 组员意见 | |||
showDrawer = async () => { | |||
const res = await listForGroupLeader({ projectId: route.query.projectId, meetingId: route.query.meetingId }) | |||
const res1 = await templatesById({ templateIds: res.data.map(i => i.templateId).join(',') }) | |||
templatesData.value = res1.data | |||
memberOpinions.value = res.data && res.data.map(i => { | |||
return { | |||
...i, | |||
reviewTemplateOptions: i.reviewTemplateOptions && i.reviewTemplateOptions.map(temp => { | |||
const data = templatesData.value.find(j => i.templateId === j.templateId).templates | |||
return { | |||
...temp, | |||
title: data.find(r => r.serialNo === temp.questionSerialNo)?.title, | |||
optionsValue: data.find(r => r.serialNo === temp.questionSerialNo)?.options.filter(j => temp.optionSerialNo.includes(j.serialNo)).map(j => j.option).join('、') | |||
} | |||
}) || [] | |||
} | |||
}) || [] | |||
drawerVisible.value = true | |||
} | |||
onMounted(() => { | |||
getTemplate() | |||
}) | |||
</script> | |||
<template> | |||
<div class="footerPage"> | |||
<el-card class="w-full" shadow="never"> | |||
<el-row :gutter="16"> | |||
<el-col :span="14"> | |||
<review-comments v-if="reviewVisible" ref="reviewCommentsRef" :template-data="templateData" /> | |||
</el-col> | |||
<!-- 最终意见显示按钮--> | |||
<el-col v-if="route.query.type*1===2" :span="10"> | |||
<div | |||
v-if="!drawerVisible" | |||
class="viewBtn" | |||
@click="showDrawer" | |||
> | |||
<svg-icon name="eye" /> | |||
<span>查看评审意见</span> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
</el-card> | |||
<div class="footer"> | |||
<el-button type="primary" :loading="loading" @click="submit">提交</el-button> | |||
<el-button @click="router.go(-1)">关闭</el-button> | |||
</div> | |||
</div> | |||
<el-drawer | |||
v-model="drawerVisible" | |||
title="组员意见" | |||
style="position: absolute" | |||
direction="rtl" | |||
size="40%" | |||
:modal="false" | |||
:append-to-body="false" | |||
modal-class="myDrawerModal" | |||
> | |||
<member-opinion :member-opinions="memberOpinions" /> | |||
</el-drawer> | |||
</template> | |||
<style lang="less"> | |||
.viewBtn{ | |||
width: 36px; | |||
background: rgba(0,87,255,0.08); | |||
border-radius: 4px; | |||
border: 1px solid #0057FF; | |||
padding: 8px; | |||
font-size: 14px; | |||
display: flex; | |||
align-items: center; | |||
flex-direction: column; | |||
text-align: center; | |||
justify-content: center; | |||
color: #0057FF; | |||
cursor: pointer; | |||
} | |||
.myDrawerModal{ | |||
position: static !important; | |||
} | |||
</style> |
@@ -0,0 +1,66 @@ | |||
<script name='handleExpertReview' setup> | |||
import { onMounted, ref } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import projectInfo from '../../../projectStoreManage/projectStore/projectDetail/components/projectInfo.vue' | |||
import { getProjectDetail } from '@/http/apis/declareMange' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
import { meetingBasicInfo } from '@/http/apis/expertManage/reviewMeeting' | |||
// 项目详情 | |||
const userInfo = storeToRefs(store.userStore).userInfo || {}, | |||
detailData = ref({}), | |||
router = useRouter(), | |||
route = useRoute(), | |||
getDetail = async () => { | |||
const res = await getProjectDetail({ id: route.query.projectId }) | |||
detailData.value = res.data | |||
}, | |||
toReviewComments = (type) => { | |||
router.push({ name: 'fillReviewComments', query: { ...route.query, type, regionCode: basicInfo.value.regionCode, projectCode: detailData.value.projectCode }}) | |||
}, | |||
// 获取会议详情 | |||
basicInfo = ref(), | |||
getMeetingDetail = async () => { | |||
const res = await meetingBasicInfo(route.query.meetingId) | |||
basicInfo.value = res.data | |||
} | |||
onMounted(() => { | |||
getDetail() | |||
getMeetingDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class="w-full footerCard handleExpertReview"> | |||
<div | |||
v-waterMarker="{text:userInfo.realName+userInfo.phoneNo.substring(userInfo.phoneNo.length - 4)}" | |||
style="position: absolute;pointer-events: none;width:100%;height:100%" | |||
> | |||
</div> | |||
<project-info :detail-data="detailData" /> | |||
<div class="footer"> | |||
<template v-if="new Date().getTime()>=new Date(basicInfo?.startTime).getTime()&&route.query.type==='1'"> | |||
<el-button | |||
v-if="route.query.reviewed==='0'" | |||
type="primary" | |||
@click="toReviewComments(1)" | |||
>填写评审意见</el-button> | |||
<el-button | |||
v-if="route.query.isHeadman==='true'&&route.query.reviewed==='1'" | |||
type="primary" | |||
@click="toReviewComments(2)" | |||
>填写最终意见</el-button> | |||
</template> | |||
<el-button | |||
plain | |||
@click="router.go(-1)" | |||
>返回</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<style lang='less'> | |||
.handleExpertReview{ | |||
padding-bottom: 56px; | |||
} | |||
</style> |
@@ -0,0 +1,189 @@ | |||
<script setup name='expertReview'> | |||
import { reactive, ref, onMounted } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import { listReviewProject } from '@/http/apis/expertManage/expertReview' | |||
import projectList from './components/projectList.vue' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
import meetingsLeaveDialog from './components/meetingsLeaveDialog.vue' | |||
const userInfo = storeToRefs(store.userStore).userInfo, | |||
listRef = ref(), | |||
router = useRouter(), | |||
searchForm = reactive({ | |||
projectName: undefined, | |||
buildOrgName: undefined | |||
}), | |||
// 列表数据 | |||
data = ref([]), | |||
total = ref(0), | |||
count = ref(0), | |||
getTableData = async (pageParams = listRef.value.pageParams) => { | |||
const res = await listReviewProject({ | |||
...pageParams, | |||
...searchForm, | |||
reviewed: activeName.value, | |||
userId: userInfo.value.userId | |||
}) | |||
console.log(activeName.value) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
if (activeName.value === 'false') { | |||
count.value = res.data.total | |||
} | |||
}, | |||
// 查询 | |||
search = () => { | |||
getTableData() | |||
}, | |||
// 重置 | |||
reset = () => { | |||
searchForm.projectName = undefined | |||
searchForm.buildOrgName = undefined | |||
listRef.value.pageParams.pageNumber = 1 | |||
listRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
activeName = ref('false'), | |||
handleClick = ({ props }) => { | |||
activeName.value = props.name | |||
getTableData() | |||
}, | |||
// 详情 | |||
toDetail = (item, type) => { | |||
router.push({ | |||
name: 'handleExpertReview', | |||
query: { | |||
projectId: item.projectId, // 项目id | |||
meetingId: item.meetingId, // 会议id | |||
isHeadman: item.isHeadman, // 是否组长 | |||
reviewType: item.reviewType, // 评审类型 | |||
type, | |||
reviewed: item.reviewed | |||
} | |||
}) | |||
}, | |||
// 会议请假 | |||
meetingsLeaveDialogData = reactive({ | |||
visible: false | |||
}), | |||
showMeetingsLeaveDialog = () => { | |||
meetingsLeaveDialogData.visible = true | |||
}, | |||
closeMeetingsLeaveDialog = () => { | |||
meetingsLeaveDialogData.visible = false | |||
} | |||
onMounted(() => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row class="box-card"> | |||
<el-col :span="24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="项目名称"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="申报单位"> | |||
<el-input | |||
v-model="searchForm.buildOrgName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8 tab-card"> | |||
<template #header> | |||
<div class="flex justify-between items-center"> | |||
<el-tabs v-model="activeName" @tab-click="handleClick"> | |||
<el-tab-pane :label="`待评审(${count})`" name="false" /> | |||
<el-tab-pane label="已评审" name="true" /> | |||
</el-tabs> | |||
<el-button | |||
type="primary" | |||
plain | |||
size="small" | |||
@click="showMeetingsLeaveDialog" | |||
>会议请假</el-button> | |||
</div> | |||
</template> | |||
<project-list | |||
ref="listRef" | |||
:list-data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
@to-detail="toDetail" | |||
/> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<meetings-leave-dialog :visible="meetingsLeaveDialogData.visible" @close="closeMeetingsLeaveDialog" /> | |||
</template> | |||
<style lang='less' scoped> | |||
.projectDynamicContainer{ | |||
height: 540px; | |||
overflow: scroll; | |||
.projectDynamic { | |||
width: 100%; | |||
height: 150px; | |||
// background-color: #bfc; | |||
border-bottom: solid 1px rgba(216, 218, 223); | |||
margin-bottom: 10px; | |||
display: flex; | |||
.leftPart{ | |||
width: 84px; | |||
height: auto; | |||
display: flex; | |||
justify-content: center; | |||
} | |||
.rightPart{ | |||
flex: 1; | |||
height: auto; | |||
.checkDetail{ | |||
color: rgba(0, 87, 255, 1); | |||
cursor: pointer; | |||
} | |||
} | |||
.projectAvartarStyle{ | |||
width: 44px; | |||
height: 44px; | |||
} | |||
} | |||
} | |||
.el-pagination { | |||
padding: 16px 16px 0 16px; | |||
flex-wrap: wrap; | |||
justify-content: flex-end; | |||
}</style> |
@@ -0,0 +1,546 @@ | |||
<script name="basicInfo" setup> | |||
import { onMounted, ref } from 'vue' | |||
import store from '@/store' | |||
import { storeToRefs } from 'pinia' | |||
import { districtList } from '@/http/apis/commonApi' | |||
import { fileFormatVerification, downloadFileUrl } from '@/utils/uploadAction.js' | |||
import { zzdInfo } from '@/http/apis/expertManage/expertStore' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
userInfo = storeToRefs(store.userStore).userInfo, | |||
{ nationList } = store.dictStore.globalDicts, | |||
{ tagList } = storeToRefs(store.dictStore), | |||
formData = ref({ | |||
expertIntentionWorkRegions: [{}], // 履职意向 | |||
avatarFile: { fileId: '' } | |||
}), | |||
formRef = ref(), | |||
// 手机号码校验 | |||
checkTelPhone = (rule, value, callback) => { | |||
if (value === '') { | |||
return callback(new Error('请输入正确的手机号')) | |||
} else { | |||
const regIdCard = | |||
/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/ | |||
if (regIdCard.test(value)) { | |||
callback() | |||
} else { | |||
return callback(new Error('请输入正确的手机号')) | |||
} | |||
} | |||
}, | |||
idCardValidator = (rule, value, callback) => { | |||
const _IDRe18 = /^([1-6][1-9]|50)\d{4}(18|19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ | |||
const _IDre15 = /^([1-6][1-9]|50)\d{4}\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}$/ | |||
// 校验身份证: | |||
if (!(_IDRe18.test(value) || _IDre15.test(value))) { | |||
callback('请输入正确格式') | |||
} else { | |||
callback() | |||
} | |||
}, | |||
rules = { | |||
phoneNo: [ | |||
{ required: true, message: '请输入手机号', trigger: 'blur' }, | |||
{ validator: checkTelPhone, trigger: 'blur' } | |||
], | |||
name: [ | |||
{ required: true, message: '请输入姓名', trigger: 'blur' } | |||
], | |||
gender: [ | |||
{ required: true, message: '请选择性别', trigger: 'blur' } | |||
], | |||
hometown: [ | |||
{ required: true, message: '请选择籍贯', trigger: 'blur' } | |||
], | |||
nationality: [ | |||
{ required: true, message: '请选择民族', trigger: 'blur' } | |||
], | |||
political: [ | |||
{ required: true, message: '请选择政治面貌', trigger: 'blur' } | |||
], | |||
idCard: [ | |||
{ required: true, message: '请输入正确的身份证号', trigger: 'blur' }, | |||
{ validator: idCardValidator, tigger: 'blur' } | |||
], | |||
birth: [ | |||
{ required: true, message: '请选择出生年月', trigger: 'blur' } | |||
], | |||
bankNo: [ | |||
{ required: true, message: '请输入银行卡号', trigger: 'blur' } | |||
], | |||
bank: [ | |||
{ required: false, message: '请输入开户行', trigger: 'blur' } | |||
], | |||
email: [ | |||
{ required: false, message: '请输入电子邮箱', trigger: 'blur' }, | |||
{ | |||
pattern: /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, | |||
message: '请输入正确邮箱', | |||
trigger: 'blur' | |||
} | |||
], | |||
expertSource: [ | |||
{ | |||
required: true, | |||
trigger: 'change', | |||
message: '请选择专家来源' | |||
} | |||
], | |||
expertRegionInfo: [ | |||
{ | |||
required: true, | |||
trigger: 'change', | |||
message: '请选择专家级别' | |||
} | |||
], | |||
expertIntentionWorkRegions: [ | |||
{ | |||
required: true, | |||
trigger: 'change', | |||
message: '请选择履职意向' | |||
} | |||
], | |||
expertType: [ | |||
{ required: true, message: '请选择专家类型', trigger: 'blur' } | |||
], | |||
avatarUrl: [ | |||
{ | |||
required: true, | |||
message: '请上传免冠照' | |||
} | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = async (data) => { | |||
formData.value = { | |||
...data, | |||
political: data.political?.[0] || undefined, | |||
expertSource: data.expertSource?.[0] || undefined, | |||
expertType: data.expertType?.[0] || undefined, | |||
expertRegionInfo: data.expertRegionInfo.regionName?.split('@@').slice(1), | |||
expertIntentionWorkRegions: data.expertIntentionWorkRegions?.map(i => { return { unionCode: i.regionName.split('@@').slice(1) } }), | |||
avatarUrl: data?.avatarFile?.fileId && await downloadFileUrl(data.avatarFile.fileId), | |||
avatarFile: data?.avatarFile || { fileId: '' } | |||
} | |||
}, | |||
regionTree = ref(), | |||
// 增加或删除履职意向 | |||
updateWorkRegions = (type, index) => { | |||
if (type === 'add') { | |||
formData.value.expertIntentionWorkRegions.push({ | |||
id: new Date().getTime() | |||
}) | |||
} else { | |||
formData.value.expertIntentionWorkRegions.splice(index, 1) | |||
} | |||
}, | |||
// 上传免冠照 | |||
handleAvatarSuccess = res => { | |||
formData.value.avatarFile['fileId'] = res.data.id | |||
downloadFileUrl(res.data.id).then(res => { | |||
formData.value.avatarUrl = res | |||
}) | |||
}, | |||
// 获取浙政钉信息 | |||
getZzdInfo = async () => { | |||
const res = await zzdInfo({ phoneNo: formData.value.phoneNo }) | |||
formData.value.isDingUser = res.data.isDingUser | |||
if (res.data.isDingUser) { | |||
formData.value.name = res.data.name | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
const res = await districtList({ regionCode: 330500, regionLevel: 2 }) | |||
regionTree.value = [res.data] | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="120px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="basicInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="手机号" | |||
prop="phoneNo" | |||
> | |||
<el-input | |||
v-model="formData.phoneNo" | |||
placeholder="请输入" | |||
:maxlength="11" | |||
:disabled="!!$route.query.id||$route.name==='selfEditExpertInfo'" | |||
@blur="getZzdInfo" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="姓名" | |||
prop="name" | |||
> | |||
<el-input | |||
v-model="formData.name" | |||
placeholder="请输入" | |||
:disabled="!!$route.query.id||$route.name==='selfEditExpertInfo'" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="性别" | |||
prop="gender" | |||
> | |||
<el-select | |||
v-model="formData.gender" | |||
class="w-full" | |||
placeholder="请选择" | |||
> | |||
<el-option value="1" label="男" /> | |||
<el-option value="0" label="女" /> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="籍贯" | |||
prop="hometown" | |||
> | |||
<el-input | |||
v-model="formData.hometown" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="民族" | |||
prop="nationality" | |||
> | |||
<el-select | |||
v-model="formData.nationality" | |||
class="m-2 w-full" | |||
placeholder="请选择" | |||
> | |||
<el-option | |||
v-for="item in nationList" | |||
:key="item.id" | |||
:label="item.info" | |||
:value="item.info" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="政治面貌" | |||
prop="political" | |||
> | |||
<el-select | |||
v-model="formData.political" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.politicalDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="身份证" | |||
prop="idCard" | |||
> | |||
<el-input | |||
v-model="formData.idCard" | |||
placeholder="请输入" | |||
:maxlength="18" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="办公电话" | |||
prop="officePhone" | |||
> | |||
<el-input | |||
v-model="formData.officePhone" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="出生年月" | |||
prop="birth" | |||
> | |||
<el-date-picker | |||
v-model="formData.birth" | |||
type="month" | |||
placeholder="请选择" | |||
format="YYYY-MM" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="银行卡号" | |||
prop="bankNo" | |||
> | |||
<el-input | |||
v-model="formData.bankNo" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="开户银行" | |||
prop="bank" | |||
> | |||
<el-input | |||
v-model="formData.bank" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="电子邮箱" | |||
prop="email" | |||
> | |||
<el-input | |||
v-model="formData.email" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="false" :span="8"> | |||
<el-form-item | |||
label="入库意向" | |||
prop="expertSource" | |||
> | |||
<el-select | |||
v-model="formData.expertSource" | |||
class="w-full" | |||
placeholder="请选择" | |||
clearable | |||
> | |||
<el-option | |||
v-for="(item,index) in tagList && | |||
tagList.length && | |||
tagList.find(i => i.tagCode === 'expert_source') | |||
.children" | |||
:key="index" | |||
:label="item.tagName" | |||
:value="item.unionCode" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="专家级别" | |||
prop="expertRegionInfo" | |||
> | |||
<el-cascader | |||
v-model="formData.expertRegionInfo" | |||
:options="regionTree" | |||
:props="{ | |||
value: 'unionCode', | |||
label: 'name' | |||
}" | |||
clearable | |||
placeholder="请选择" | |||
class="w-full" | |||
:disabled="$route.name==='selfEditExpertInfo'||$route.query.id&&userInfo.regionCode!==formData?.expertRegionInfo?.[formData.expertRegionInfo?.length-1].split('##')[0]" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="专家来源" | |||
> | |||
<el-select | |||
v-model="formData.expertSource" | |||
class="w-full" | |||
placeholder="请选择" | |||
clearable | |||
value-key="tagCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.expertSourceDict" | |||
:key="index" | |||
:label="item.tagName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="专家类型" | |||
prop="expertType" | |||
> | |||
<el-select | |||
v-model="formData.expertType" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.expertTypeDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="履职意向" | |||
prop="expertIntentionWorkRegions" | |||
> | |||
<el-row | |||
v-for="(item, index) in formData | |||
.expertIntentionWorkRegions" | |||
:key="item.id" | |||
class="intention-item w-full" | |||
> | |||
<el-col :span="24"> | |||
<el-cascader | |||
v-model=" | |||
formData.expertIntentionWorkRegions[index] | |||
.unionCode | |||
" | |||
:options="regionTree" | |||
:props="{ | |||
value: 'unionCode', | |||
label: 'name' | |||
}" | |||
clearable | |||
style="width: 100%" | |||
class="mb-4" | |||
/> | |||
<span | |||
v-if="index > 0" | |||
style="position: absolute; right: -20px" | |||
@click="updateWorkRegions('del', index)" | |||
> | |||
<el-icon> | |||
<Delete color="#D40000" /> | |||
</el-icon> | |||
</span> | |||
</el-col> | |||
</el-row> | |||
<p class="addGhostBtn mt-8 w-full"> | |||
<el-button | |||
class="w-full" | |||
type="primary" | |||
plain | |||
style="margin: 0" | |||
@click="updateWorkRegions('add')" | |||
> | |||
+ 增加履职意向地区 | |||
</el-button> | |||
</p> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
class="avatarForm" | |||
label="一寸免冠照" | |||
prop="avatarUrl" | |||
style="margin-bottom: 32px" | |||
> | |||
<el-upload | |||
class="avatar-uploader" | |||
:action="uploadUrl" | |||
:show-file-list="false" | |||
:on-success="handleAvatarSuccess" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
size: 500, | |||
types: ['png', 'jpg', 'jpeg'] | |||
}) | |||
" | |||
accept="image/png,image/jpeg" | |||
> | |||
<img | |||
v-if="formData.avatarUrl" | |||
:src="formData.avatarUrl" | |||
class="avatar" | |||
/> | |||
<i v-else class="el-icon-plus avatar-uploader-icon"> | |||
<el-icon><Camera /></el-icon> | |||
</i> | |||
</el-upload> | |||
<div class="limit-name ml-4">请上传蓝底1寸免冠照片,小于500Kb</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.basicInfo{ | |||
.avatarForm { | |||
:deep(.el-form-item__content) { | |||
display: block; | |||
} | |||
} | |||
.avatar-uploader { | |||
.el-upload { | |||
background: #edf4ff; | |||
border-radius: 4px; | |||
border: 1px dashed #007df1; | |||
cursor: pointer; | |||
position: relative; | |||
overflow: hidden; | |||
&:hover { | |||
border-color: #409eff; | |||
} | |||
} | |||
.avatar-uploader-icon { | |||
border-radius: 4px; | |||
border: 1px dashed #007df1; | |||
font-size: 28px; | |||
color: #007df1; | |||
width: 104px; | |||
height: 104px; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
} | |||
.avatar { | |||
width: 80px; | |||
height: 80px; | |||
display: block; | |||
} | |||
} | |||
.limit-name { | |||
margin-top: 13px; | |||
color: #999999; | |||
font-size: 12px; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,232 @@ | |||
<script name="eduInfo" setup> | |||
import { onMounted, getCurrentInstance, ref } from 'vue' | |||
import store from '@/store' | |||
import { districtList } from '@/http/apis/commonApi' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview } from '@/utils/uploadAction.js' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
{ proxy } = getCurrentInstance(), | |||
formData = ref({ | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
edu: [ | |||
{ required: true, message: '请选择学历', trigger: 'blur' } | |||
], | |||
degree: [ | |||
{ required: true, message: '请选择学位', trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
fileExceed = (files, uploadFiles) => { | |||
proxy.$message.warning('仅限上传一个文件') | |||
}, | |||
// 回显 | |||
setFormData = async (data) => { | |||
formData.value = { | |||
...data, | |||
edu: data.edu?.[0] || undefined, | |||
degree: data.degree?.[0] || undefined, | |||
degreeCertificateFile: data.degreeCertificateFile && data.degreeCertificateFile.map(i => { | |||
return { | |||
name: i.fileName, | |||
response: { | |||
data: { | |||
id: i.fileId | |||
} | |||
}, | |||
fileUrlById: i.url | |||
} | |||
}), | |||
graduationCertificateFile: data.graduationCertificateFile && data.graduationCertificateFile.map(i => { | |||
return { | |||
name: i.fileName, | |||
response: { | |||
data: { | |||
id: i.fileId | |||
} | |||
}, | |||
fileUrlById: i.url | |||
} | |||
}) | |||
} | |||
}, | |||
regionTree = ref() | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
const res = await districtList({ regionCode: 330500, regionLevel: 2 }) | |||
regionTree.value = [res.data] | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="100px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="eduInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="毕业学校" | |||
prop="school" | |||
> | |||
<el-input | |||
v-model="formData.school" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="毕业时间" | |||
prop="graduatedAt" | |||
> | |||
<el-date-picker | |||
v-model="formData.graduatedAt" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="所学专业" | |||
prop="academicTitle" | |||
> | |||
<el-input | |||
v-model="formData.academicTitle" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="学历" prop="edu"> | |||
<el-select | |||
v-model="formData.edu" | |||
placeholder="请选择学历" | |||
value-key="dictionaryCode" | |||
clearable | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item, index) in store.dictStore.eduDict " | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="学位" prop="degree"> | |||
<el-select | |||
v-model="formData.degree" | |||
placeholder="请选择学位" | |||
value-key="dictionaryCode" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item, index) in store.dictStore.degreeDict " | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="毕业证书" | |||
prop="graduationCertificateFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.graduationCertificateFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-exceed="fileExceed" | |||
:on-success=" | |||
res => | |||
handleFileSuccess( | |||
res, | |||
formData.graduationCertificateFile | |||
) | |||
" | |||
:on-preview="handleFilePreview" | |||
accept="application/pdf,image/png,image/jpeg" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
size: 1024, | |||
types: ['png', 'jpg', 'jpeg','pdf']})" | |||
> | |||
<el-button | |||
type="primary" | |||
plain | |||
>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持扩展名:.pdf.png .jpg .pdf ,文件大小不超过1M | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="学位证书" | |||
prop="degreeCertificateFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.degreeCertificateFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-exceed="fileExceed" | |||
:limit="1" | |||
:on-success=" | |||
res => | |||
handleFileSuccess( | |||
res, | |||
formData.degreeCertificateFile | |||
) | |||
" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
size: 1024, | |||
types: ['png', 'jpg', 'jpeg','pdf'] | |||
}) | |||
" | |||
accept="application/pdf,image/png,image/jpeg,image/jpg" | |||
:on-preview="handleFilePreview" | |||
> | |||
<el-button | |||
type="primary" | |||
plain | |||
>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持扩展名:.pdf.png .jpg .pdf,文件大小不超过1M | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.eduInfo{ | |||
} | |||
</style> |
@@ -0,0 +1,80 @@ | |||
<script name="expertOtherInfo" setup> | |||
import { onMounted, ref } from 'vue' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const { tagList } = storeToRefs(store.dictStore), | |||
formData = ref({ | |||
}), | |||
formRef = ref(), | |||
rules = {}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
...data, | |||
other: data.other && data.other.map(i => `${i.tagName}##${i.tagCode}`) | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="120px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="expertOtherInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="24"> | |||
<el-form-item label="其他标签"> | |||
<el-tree-select | |||
v-model="formData.other" | |||
placeholder="请选择其他标签" | |||
:data=" | |||
tagList && | |||
tagList.length && | |||
tagList.find(i => i.tagCode === 'other').children||[] | |||
" | |||
:props="{ | |||
label: 'tagName', | |||
value: 'unionCode' | |||
}" | |||
node-key="unionCode" | |||
collapse-tags | |||
multiple | |||
show-checkbox | |||
check-on-click-node | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="备注" | |||
> | |||
<el-input | |||
v-model="formData.remark" | |||
maxlength="200" | |||
show-word-limit | |||
type="textarea" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.expertOtherInfo{ | |||
} | |||
</style> |
@@ -0,0 +1,315 @@ | |||
<script name="jobInfo" setup> | |||
import { onMounted, ref } from 'vue' | |||
import { getOrgLevelByLevel, getOrgTree } from '@/http/apis/systemManage/unitManage' | |||
import { getBusinessstripLine } from '@/http/apis/commonApi' | |||
import store from '@/store' | |||
const formData = ref({ | |||
companyAttribute: undefined | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
company: [ | |||
{ required: true, message: '请上选择工作单位', trigger: 'blur' } | |||
], | |||
companyUniqCode: [ | |||
{ required: true, message: '工作单位code不能为空', trigger: 'blur' } | |||
], | |||
legalEntityCode: [ | |||
{ required: true, message: '请输入单位法人编号', trigger: 'blur' } | |||
], | |||
administrativeDuties: [ | |||
{ required: true, message: '请输入行政职务', trigger: 'blur' } | |||
], | |||
startWorkAt: [ | |||
{ required: true, message: '请选择开始工作日期', trigger: 'blur' } | |||
], | |||
administrativeRank: [ | |||
{ required: true, message: '请选择行政职级', trigger: 'blur' } | |||
], | |||
jobStatus: [ | |||
{ required: true, message: '请选择在职状态', trigger: 'blur' } | |||
], | |||
retiredAt: [ | |||
{ required: true, message: '请选退休日期', trigger: 'blur' } | |||
], | |||
companyAttribute: [ | |||
{ required: true, message: '请选单位类型', trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
...data, | |||
administrativeRank: data.administrativeRank?.[0] || undefined, | |||
jobStatus: data.jobStatus?.[0] || undefined, | |||
companyAttribute: data.companyAttribute?.[0] || undefined | |||
} | |||
}, | |||
// 工作单位 | |||
orgTreeRef = ref(), | |||
changeCompany = () => { | |||
formData.value.company = orgTreeRef.value.getCurrentNode().name | |||
}, | |||
// 获取单位组织架构 | |||
loadNode = async (node, resolve) => { | |||
if (node.level === 0) { | |||
const res = await getOrgLevelByLevel({ | |||
isCompetentUnit: true, | |||
isSuperiorLineCompetentUnit: true | |||
}) | |||
resolve(res.data) | |||
} else { | |||
const res = await getOrgLevelByLevel({ | |||
parentCode: node.data.organizationCode | |||
}) | |||
if (res.data?.length) { | |||
resolve(res.data) | |||
} else { | |||
resolve([]) | |||
} | |||
} | |||
}, | |||
lineListData = ref([]), | |||
getLineList = async () => { | |||
const res = await getBusinessstripLine() | |||
lineListData.value = res.data | |||
}, | |||
companyTreeData = ref(), | |||
getCompany = (data) => { | |||
const items = [] | |||
data.forEach(i => { | |||
items.push({ | |||
name: i.title, | |||
organizationCode: i.key, | |||
children: i.children?.lengt ? getCompany(i.children) : [] | |||
}) | |||
}) | |||
return items | |||
}, | |||
remoteMethod = async (query) => { | |||
const res = await getOrgTree({ organizationName: query }) | |||
companyTreeData.value = getCompany(res.data) | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
getLineList() | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="120px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="jobInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="工作单位" | |||
prop="company" | |||
> | |||
<el-tree-select | |||
ref="orgTreeRef" | |||
v-model="formData.companyUniqCode" | |||
:data="companyTreeData" | |||
class="w-full" | |||
node-key="organizationCode" | |||
lazy | |||
:check-strictly="true" | |||
:load="loadNode" | |||
:cache-data="formData.company&&formData.companyUniqCode?[{organizationCode:formData.companyUniqCode,name:formData.company}]:[]" | |||
:props="{ | |||
label:'name', | |||
value:'organizationCode' | |||
}" | |||
filterable | |||
remote | |||
:remote-method="remoteMethod" | |||
@change="changeCompany" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="工作单位code" | |||
prop="formData.companyUniqCode" | |||
> | |||
<el-input | |||
v-model="formData.companyUniqCode" | |||
placeholder="请选择" | |||
disabled | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="单位法人编号" | |||
> | |||
<el-input | |||
v-model="formData.legalEntityCode" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="行政职务" | |||
prop="administrativeDuties" | |||
> | |||
<el-input | |||
v-model="formData.administrativeDuties" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="开始工作日期" | |||
prop="startWorkAt" | |||
> | |||
<el-date-picker | |||
v-model="formData.startWorkAt" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="行政职级" | |||
prop="administrativeRank" | |||
> | |||
<el-select | |||
v-model="formData.administrativeRank" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.administrativeRankDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="在职状态" | |||
prop="jobStatus" | |||
> | |||
<el-select | |||
v-model="formData.jobStatus" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.jobStatusDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col v-if="formData.jobStatus?.dictionaryName==='退休'" :span="8"> | |||
<el-form-item | |||
label="退休日期" | |||
prop="retiredAt" | |||
> | |||
<el-date-picker | |||
v-model="formData.retiredAt" | |||
type="date" | |||
format="YYYY-MM-DD" | |||
value-format="YYYY-MM-DD" | |||
placeholder="请选择" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="单位类型" | |||
prop="companyAttribute" | |||
> | |||
<el-select | |||
v-model="formData.companyAttribute" | |||
placeholder="请选择" | |||
class="w-full" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.companyAttributeDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="条线"> | |||
<el-select | |||
v-model="formData.businessStrips" | |||
multiple | |||
value-key="businessStripCode" | |||
filterable | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in lineListData" | |||
:key="index" | |||
:label="item.businessStripName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="工作地址" | |||
prop="address" | |||
> | |||
<el-input | |||
v-model="formData.address" | |||
maxlength="50" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="工作经历" | |||
prop="experience" | |||
> | |||
<el-input | |||
v-model="formData.experience" | |||
maxlength="200" | |||
:rows="5" | |||
type="textarea" | |||
show-word-limit | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.jobInfo{ | |||
} | |||
</style> |
@@ -0,0 +1,347 @@ | |||
<script name="professionalInfo" setup> | |||
import { getCurrentInstance, onMounted, reactive, ref } from 'vue' | |||
import store from '@/store' | |||
import orgTree from '@/components/orgTree/index.vue' | |||
import { storeToRefs } from 'pinia' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview } from '@/utils/uploadAction.js' | |||
const uploadUrl = store.dictStore.uploadUrl | |||
const { tagList } = storeToRefs(store.dictStore), | |||
{ proxy } = getCurrentInstance(), | |||
formData = ref({ | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
technicalTitles: [ | |||
{ required: true, message: '请输入技术职称', trigger: 'blur' } | |||
], | |||
titleLevel: [ | |||
{ required: true, message: '请选择职称级别', trigger: 'blur' } | |||
], | |||
goodAt: [ | |||
{ required: true, message: '请选择擅长方向', trigger: 'blur' } | |||
], | |||
technicalExpertise: [ | |||
{ required: true, message: '请选择技术专长', trigger: 'blur' } | |||
], | |||
industrySector: [ | |||
{ required: true, message: '请选择行业领域', trigger: 'blur' } | |||
], | |||
avoidCompanyList: [ | |||
{ required: true, message: '请输入回避单位', trigger: 'blur' } | |||
], | |||
titleCertificateFile: [ | |||
{ required: true, message: '请上传职称证明', trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
fileExceed = (files, uploadFiles) => { | |||
proxy.$message.warning('仅限上传一个文件') | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
...data, | |||
goodAt: data.goodAt && data.goodAt || undefined, | |||
titleLevel: data.titleLevel && data.titleLevel[0] || undefined, | |||
industrySector: data.industrySector && data.industrySector.map(i => `${i.tagName}##${i.tagCode}`), | |||
technicalExpertise: data.technicalExpertise && data.technicalExpertise.map(i => `${i.tagName}##${i.tagCode}`), | |||
titleCertificateFile: data.titleCertificateFile && data.titleCertificateFile.map(i => { | |||
return { | |||
name: i.fileName, | |||
response: { | |||
data: { | |||
id: i.fileId | |||
} | |||
}, | |||
fileUrlById: i.url | |||
} | |||
}) | |||
} | |||
}, | |||
handleChangeTreeTag = (checkedKeys, checkedNodes, name) => { | |||
console.log(checkedNodes) | |||
}, | |||
// 回避单位单位 | |||
orgProps = reactive({ | |||
unitVisible: false, | |||
showCheckbox: false, | |||
data: undefined, | |||
name: undefined | |||
}), | |||
showOrgTree = (name) => { | |||
orgProps.name = name | |||
orgProps.unitVisible = true | |||
orgProps.showCheckbox = true | |||
orgProps.data = formData.value.avoidCompanyList?.map(i => { | |||
return { | |||
key: i.companyUniqCode, | |||
title: i.companyName | |||
} | |||
}) | |||
}, | |||
closeOrg = () => { | |||
orgProps.unitVisible = false | |||
}, | |||
getOrgData = (data, expandedKeys) => { | |||
formData.value[orgProps.name] = data.map(i => { | |||
return { | |||
companyUniqCode: i.key, | |||
companyName: i.title | |||
} | |||
}) | |||
}, | |||
// 删除回避单位 | |||
delTag = (index) => { | |||
formData.value.avoidCompanyList.splice(index, 1) | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="120px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="professionalInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="技术职称" | |||
prop="technicalTitles" | |||
> | |||
<el-input | |||
v-model="formData.technicalTitles" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="职称级别" | |||
prop="titleLevel" | |||
> | |||
<el-select | |||
v-model="formData.titleLevel" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.titleLevelDict " | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="擅长方向" | |||
prop="goodAt" | |||
> | |||
<el-select | |||
v-model="formData.goodAt" | |||
class="w-full" | |||
placeholder="请选择" | |||
clearable | |||
value-key="tagCode" | |||
multiple | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.goodAtDict" | |||
:key="index" | |||
:label="item.tagName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="技术专长" | |||
prop="technicalExpertise" | |||
> | |||
<el-tree-select | |||
v-model="formData.technicalExpertise" | |||
class="w-full" | |||
placeholder="请选择技术专长" | |||
:data=" | |||
tagList && | |||
tagList.length && | |||
tagList.find(i => i.tagCode === 'technical_expertise') | |||
.children||[] | |||
" | |||
:props="{ | |||
label: 'tagName', | |||
value: 'unionCode' | |||
}" | |||
node-key="unionCode" | |||
collapse-tags | |||
multiple | |||
show-checkbox | |||
check-on-click-node | |||
@check=" | |||
(checkedKeys, checkedNodes) => | |||
handleChangeTreeTag( | |||
checkedKeys, | |||
checkedNodes, | |||
'technicalExpertise' | |||
) | |||
" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="行业领域" | |||
prop="industrySector" | |||
> | |||
<el-tree-select | |||
v-model="formData.industrySector" | |||
class="w-full" | |||
placeholder="请选择行业领域" | |||
:data=" | |||
tagList && | |||
tagList.length && | |||
tagList.find(i => i.tagCode === 'industry_sector').children||[] | |||
" | |||
:props="{ | |||
label: 'tagName', | |||
value: 'unionCode' | |||
}" | |||
node-key="unionCode" | |||
collapse-tags | |||
multiple | |||
show-checkbox | |||
check-on-click-node | |||
@check=" | |||
(checkedKeys, checkedNodes) => | |||
handleChangeTreeTag( | |||
checkedKeys, | |||
checkedNodes, | |||
'industrySector' | |||
) | |||
" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="获奖情况" | |||
prop="awards" | |||
> | |||
<el-input | |||
v-model="formData.awards" | |||
maxlength="200" | |||
show-word-limit | |||
type="textarea" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="表彰奖励" | |||
prop="recognitionReward" | |||
> | |||
<el-input | |||
v-model="formData.recognitionReward" | |||
maxlength="200" | |||
show-word-limit | |||
type="textarea" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="回避单位" | |||
prop="avoidCompanyList" | |||
> | |||
<div class="flex flex-col items-start"> | |||
<el-button | |||
type="primary" | |||
@click="showOrgTree('avoidCompanyList')" | |||
> | |||
<el-icon> | |||
<Plus /> | |||
</el-icon>选择回避单位 | |||
</el-button> | |||
<p> | |||
<el-tag | |||
v-for="(item,index) in formData.avoidCompanyList" | |||
:key="index" | |||
class="mr-8" | |||
closable | |||
@close="delTag(index)" | |||
> | |||
{{ item.companyName }} | |||
</el-tag> | |||
</p> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="职称证明" | |||
prop="titleCertificateFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.titleCertificateFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:on-exceed="fileExceed" | |||
:limit="1" | |||
:on-success=" | |||
res => | |||
handleFileSuccess( | |||
res, | |||
formData.titleCertificateFile | |||
) | |||
" | |||
:on-preview="handleFilePreview" | |||
accept="application/pdf,image/png,image/jpeg" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
types: ['png', 'jpg', 'jpeg','pdf'],size:1024})" | |||
> | |||
<el-button | |||
type="primary" | |||
plain | |||
>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持扩展名:.pdf .png .jpg .pdf,文件大小不超过1M | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
<org-tree | |||
:visible="orgProps.unitVisible" | |||
:show-checkbox="orgProps.showCheckbox" | |||
:default-data="orgProps.data" | |||
@close="closeOrg" | |||
@get-select-unit="getOrgData" | |||
/> | |||
</template> | |||
<style lang="less"> | |||
.professionalInfo{ | |||
} | |||
</style> |
@@ -0,0 +1,124 @@ | |||
<script name="recommendInfo" setup> | |||
import { getCurrentInstance, onMounted, ref } from 'vue' | |||
import store from '@/store' | |||
import { fileFormatVerification, handleFileSuccess, handleFilePreview } from '@/utils/uploadAction.js' | |||
const uploadUrl = store.dictStore.uploadUrl, | |||
{ proxy } = getCurrentInstance(), | |||
formData = ref({ | |||
}), | |||
formRef = ref(), | |||
rules = { | |||
recommendedWay: [ | |||
{ required: true, message: '请选择推荐类型', trigger: 'blur' } | |||
], | |||
recommendationProofFile: [ | |||
{ required: true, message: '请上传推荐证明', trigger: 'blur' } | |||
] | |||
}, | |||
// 校验 | |||
validForm = (callback) => { | |||
formRef.value.validate(valid => { | |||
callback(valid) | |||
}) | |||
}, | |||
fileExceed = (files, uploadFiles) => { | |||
proxy.$message.warning('仅限上传一个文件') | |||
}, | |||
// 回显 | |||
setFormData = (data) => { | |||
formData.value = { | |||
...data, | |||
recommendedWay: data.recommendedWay?.[0] || undefined, | |||
recommendationProofFile: data.recommendationProofFile && data.recommendationProofFile.map(i => { | |||
return { | |||
name: i.fileName, | |||
response: { | |||
data: { | |||
id: i.fileId | |||
} | |||
}, | |||
fileUrlById: i.url | |||
} | |||
}) | |||
} | |||
} | |||
defineExpose({ validForm, formData, setFormData }) | |||
onMounted(async () => { | |||
}) | |||
</script> | |||
<template> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-position="right" | |||
label-width="120px" | |||
label-suffix=":" | |||
scroll-to-error | |||
class="recommendInfo" | |||
> | |||
<el-row :gutter="8"> | |||
<el-col :span="8"> | |||
<el-form-item | |||
label="推荐类型" | |||
prop="recommendedWay" | |||
> | |||
<el-select | |||
v-model="formData.recommendedWay" | |||
class="w-full" | |||
placeholder="请选择" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.recommendedWayDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="24"> | |||
<el-form-item | |||
label="推荐证明" | |||
prop="recommendationProofFile" | |||
> | |||
<el-upload | |||
v-model:file-list="formData.recommendationProofFile" | |||
class="w-full" | |||
:action="uploadUrl" | |||
:limit="1" | |||
:on-exceed="fileExceed" | |||
:on-success=" | |||
res => | |||
handleFileSuccess( | |||
res, | |||
formData.recommendationProofFile | |||
) | |||
" | |||
:on-preview="handleFilePreview" | |||
accept="application/pdf,image/png,image/jpeg,image/jpg" | |||
:before-upload=" | |||
file => | |||
fileFormatVerification(file, { | |||
types:['png', 'jpg', 'jpeg','pdf'],size:1024})" | |||
> | |||
<el-button | |||
type="primary" | |||
plain | |||
>选择文件</el-button> | |||
<template #tip> | |||
<div class="el-upload__tip"> | |||
支持扩展名:.pdf .png .jpg .pdf ,文件大小不超过1M | |||
</div> | |||
</template> | |||
</el-upload> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</template> | |||
<style lang="less"> | |||
.recommendInfo{ | |||
} | |||
</style> |
@@ -0,0 +1,409 @@ | |||
<script name="addOrEditExpert" setup> | |||
import { getCurrentInstance, ref, onMounted, reactive } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import basicInfo from './components/basicInfo.vue' | |||
import eduInfo from './components/eduInfo.vue' | |||
import jobInfo from './components/jobInfo.vue' | |||
import professionalInfo from './components/professionalInfo.vue' | |||
import recommendInfo from './components/recommendInfo.vue' | |||
import expertOtherInfo from './components/expertOtherInfo.vue' | |||
import { expertEdit, expertSignUp, modifyApply, registration } from '@/http/apis/expertManage/expertStore' | |||
import { downloadFileUrl } from '@/utils/uploadAction.js' | |||
import { getExpertDetail } from '@/http/apis/expertManage/expertVerify' | |||
import { getVerificationCode } from '@/http/apis/auth' | |||
import { storeToRefs } from 'pinia' | |||
import store from '@/store' | |||
const { proxy } = getCurrentInstance(), | |||
route = useRoute(), | |||
router = useRouter(), | |||
formData = ref({ | |||
basicInfo: { | |||
// isDingUser: false | |||
} | |||
}), | |||
basicInfoRef = ref(), // 基本信息 | |||
eduInfoRef = ref(), // 学历信息 | |||
jobInfoRef = ref(), // 职业信息 | |||
professionalInfoRef = ref(), // 专业信息 | |||
recommendInfoRef = ref(), // 推荐信息 | |||
expertOtherInfoRef = ref(), // 其他信息 | |||
// 提交 | |||
submitForm = async () => { | |||
const form = [] | |||
form.push(new Promise((resolve, reject) => { | |||
basicInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
eduInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
jobInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
professionalInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
recommendInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
form.push(new Promise((resolve, reject) => { | |||
expertOtherInfoRef.value.validForm((valid) => { | |||
if (valid) resolve() | |||
}) | |||
})) | |||
Promise.all([...form]).then(async () => { | |||
saveData() | |||
}).catch(err => { | |||
if (err) { | |||
proxy.$message.warning(err) | |||
} | |||
}) | |||
}, | |||
saveData = async () => { | |||
var data = { | |||
expertUserId: route.name === 'selfEditExpertInfo' ? userInfo.value.userId : route.query.id || undefined, | |||
basicInfo: { | |||
...basicInfoRef.value.formData, | |||
isDingUser: basicInfoRef.value.formData.isDingUser, | |||
avatarUrl: basicInfoRef.value.formData?.avatarFile?.fileId && await downloadFileUrl(basicInfoRef.value.formData.avatarFile.fileId), | |||
expertIntentionWorkRegions: | |||
basicInfoRef.value.formData.expertIntentionWorkRegions?.map((i, index) => ({ | |||
regionName: i.unionCode?.join('@@'), | |||
regionCode: i.unionCode?.slice(-1)[0]?.split('##')[0], | |||
regionLevel: i.unionCode?.slice(-1)[0]?.split('##')[2] | |||
})), | |||
expertRegionInfo: { | |||
regionName: basicInfoRef.value.formData.expertRegionInfo?.join('@@'), | |||
regionCode: basicInfoRef.value.formData.expertRegionInfo?.slice(-1)[0].split('##')[0], | |||
regionLevel: basicInfoRef.value.formData.expertRegionInfo?.slice(-1)[0].split('##')[2] | |||
}, | |||
political: basicInfoRef.value.formData.political && [basicInfoRef.value.formData.political] || [], | |||
expertSource: basicInfoRef.value.formData.expertSource && [basicInfoRef.value.formData.expertSource] || [], | |||
expertType: basicInfoRef.value.formData.expertType && [basicInfoRef.value.formData.expertType] || [] | |||
}, | |||
eduInfo: { | |||
...eduInfoRef.value.formData, | |||
edu: eduInfoRef.value.formData.edu && [eduInfoRef.value.formData.edu], | |||
degree: eduInfoRef.value.formData.degree && [eduInfoRef.value.formData.degree], | |||
degreeCertificateFile: eduInfoRef.value.formData.degreeCertificateFile && await Promise.all( | |||
eduInfoRef.value.formData.degreeCertificateFile && eduInfoRef.value.formData.degreeCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [], | |||
graduationCertificateFile: eduInfoRef.value.formData.graduationCertificateFile && await Promise.all( | |||
eduInfoRef.value.formData.graduationCertificateFile && eduInfoRef.value.formData.graduationCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [] | |||
}, | |||
jobInfo: { | |||
...jobInfoRef.value.formData, | |||
administrativeRank: jobInfoRef.value.formData.administrativeRank && [jobInfoRef.value.formData.administrativeRank] || [], | |||
jobStatus: jobInfoRef.value.formData.jobStatus && [jobInfoRef.value.formData.jobStatus] || [], | |||
companyAttribute: jobInfoRef.value.formData.companyAttribute && [jobInfoRef.value.formData.companyAttribute] || [] | |||
}, | |||
professionalInfo: { | |||
...professionalInfoRef.value.formData, | |||
goodAt: professionalInfoRef.value.formData.goodAt.map(i => { | |||
return { | |||
...i, | |||
tagFieldName: 'good_at' | |||
} | |||
}) || [], | |||
titleLevel: professionalInfoRef.value.formData.titleLevel && [professionalInfoRef.value.formData.titleLevel] || [], | |||
titleCertificateFile: professionalInfoRef.value.formData.titleCertificateFile && await Promise.all( | |||
professionalInfoRef.value.formData.titleCertificateFile && professionalInfoRef.value.formData.titleCertificateFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [], | |||
technicalExpertise: professionalInfoRef.value.formData.technicalExpertise && professionalInfoRef.value.formData.technicalExpertise.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}), | |||
industrySector: professionalInfoRef.value.formData.industrySector && professionalInfoRef.value.formData.industrySector.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}) | |||
}, | |||
recommendInfo: { | |||
...recommendInfoRef.value.formData, | |||
recommendedWay: recommendInfoRef.value.formData.recommendedWay && [recommendInfoRef.value.formData.recommendedWay] || [], | |||
recommendationProofFile: recommendInfoRef.value.formData.recommendationProofFile && await Promise.all( | |||
recommendInfoRef.value.formData.recommendationProofFile && recommendInfoRef.value.formData.recommendationProofFile.map(async i => { | |||
return { | |||
fileName: i.name, | |||
fileId: i.response.data.id, | |||
url: i.fileUrlById | |||
} | |||
}) | |||
) || [] | |||
}, | |||
expertOtherInfo: { | |||
...expertOtherInfoRef.value.formData, | |||
other: expertOtherInfoRef.value.formData.other && expertOtherInfoRef.value.formData.other.map(i => { | |||
return { | |||
tagCode: i.split('##')[1], | |||
tagName: i.split('##')[0] | |||
} | |||
}) | |||
} | |||
} | |||
if (route.name === 'expertEnroll') { | |||
showSmsDiaglog(data) | |||
} else { | |||
if (!route.query.id && route.name !== 'selfEditExpertInfo') { | |||
await expertSignUp(data) | |||
proxy.$message.success('专家新增成功') | |||
router.go(-1) | |||
} else { | |||
const apiFn = route.name === 'selfEditExpertInfo' ? modifyApply : expertEdit | |||
await apiFn(data) | |||
proxy.$message.success(route.name === 'selfEditExpertInfo' ? '申请成功' : '专家编辑成功') | |||
route.name !== 'selfEditExpertInfo' && router.go(-1) | |||
} | |||
} | |||
}, | |||
// 专家报名-短信验证 | |||
smsDialogData = reactive({ | |||
visible: false, | |||
data: {} | |||
}), | |||
showSmsDiaglog = (data) => { | |||
smsDialogData.data = data | |||
smsDialogData.visible = true | |||
}, | |||
smsDialogFormRef = ref(), | |||
smsDialogForm = ref({ | |||
verificationCode: '' | |||
}), | |||
smsDialogRules = { | |||
'verificationCode': [{ required: true, message: '请输入' }] | |||
}, | |||
smsDialogLoading = ref(false), | |||
submitSms = async (formEl) => { | |||
if (!formEl) { | |||
return | |||
} | |||
formEl.validate(async (valid) => { | |||
if (valid) { | |||
await registration({ | |||
...smsDialogData.data, | |||
verificationCode: smsDialogForm.value.verificationCode | |||
}) | |||
proxy.$message.success('提交成功') | |||
router.go(0) | |||
} | |||
} | |||
) | |||
}, | |||
timer = ref(null), | |||
count = ref(0), | |||
getVerificationCodeFunc = async () => { | |||
await getVerificationCode({ mobile: basicInfoRef.value.formData.phoneNo, verificationType: 'RECOMMENDATION_PROOF_FILE_SUBMIT' }) | |||
proxy.$message.success('验证码已发送') | |||
const TIME_COUNT = 60 | |||
if (!timer.value) { | |||
count.value = TIME_COUNT | |||
timer.value = setInterval(() => { | |||
if (count.value > 0 && count.value <= TIME_COUNT) { | |||
count.value-- | |||
} else { | |||
clearInterval(timer.value) | |||
timer.value = null | |||
} | |||
}, 1000) | |||
} | |||
}, | |||
// 获取详情 | |||
getDetail = async () => { | |||
const res = await getExpertDetail({ expertUserId: route.name === 'selfEditExpertInfo' ? userInfo.value.userId : route.query.id }) | |||
// formData.value.basicInfo.isDingUser = res.data.basicInfo.isDingUser | |||
basicInfoRef.value.setFormData(res.data.basicInfo) | |||
eduInfoRef.value.setFormData(res.data.eduInfo) | |||
jobInfoRef.value.setFormData(res.data.jobInfo) | |||
professionalInfoRef.value.setFormData(res.data.professionalInfo) | |||
recommendInfoRef.value.setFormData(res.data.recommendInfo) | |||
expertOtherInfoRef.value.setFormData(res.data.expertOtherInfo) | |||
}, | |||
userInfo = storeToRefs(store.userStore).userInfo | |||
onMounted(() => { | |||
if (route.query.id || route.name === 'selfEditExpertInfo') { | |||
getDetail() | |||
} | |||
}) | |||
</script> | |||
<template> | |||
<div class="addOrEditExpert footerPage" :class="{ 'relative':route.path === 'expertEnroll'}"> | |||
<div v-if="route.name === 'expertEnroll'" class="header">丽水市信息化专家报名</div> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div class="card-header flex items-center justify-between"> | |||
<span>基本信息</span> | |||
<!-- <span class="flex items-center">是否在浙政钉组内: | |||
<el-switch | |||
v-model="formData.basicInfo.isDingUser" | |||
inline-prompt | |||
active-text="是" | |||
inactive-text="否" | |||
/> | |||
</span> --> | |||
</div> | |||
</template> | |||
<basic-info ref="basicInfoRef" :basic-info="formData.basicInfo" /> | |||
</el-card> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div> | |||
<span>学历信息</span> | |||
</div> | |||
</template> | |||
<edu-info ref="eduInfoRef" /> | |||
</el-card> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div> | |||
<span>职业信息</span> | |||
</div> | |||
</template> | |||
<job-info ref="jobInfoRef" /> | |||
</el-card> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div> | |||
<span>专业信息</span> | |||
</div> | |||
</template> | |||
<professional-info ref="professionalInfoRef" /> | |||
</el-card> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div> | |||
<span>推荐信息</span> | |||
</div> | |||
</template> | |||
<recommend-info ref="recommendInfoRef" /> | |||
</el-card> | |||
<el-card shadow="never" class="mb-16"> | |||
<template #header> | |||
<div> | |||
<span>其他信息</span> | |||
</div> | |||
</template> | |||
<expert-other-info ref="expertOtherInfoRef" /> | |||
</el-card> | |||
<div class="footer"> | |||
<el-button | |||
type="primary" | |||
@click="submitForm" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button @click="router.go(-1)">取消</el-button> | |||
</div> | |||
<el-dialog | |||
:model-value="smsDialogData.visible" | |||
title="短信验证" | |||
width="400px" | |||
destroy-on-close | |||
@close="smsDialogData.visible=false" | |||
> | |||
<el-form | |||
ref="smsDialogFormRef" | |||
:model="smsDialogForm" | |||
:rules="smsDialogRules" | |||
label-width="auto" | |||
label-suffix=":" | |||
> | |||
<el-form-item label="手机号"> | |||
<span>{{ basicInfoRef.formData.phoneNo }}</span> | |||
</el-form-item> | |||
<el-form-item label="验证码" prop="verificationCode"> | |||
<el-input v-model="smsDialogForm.verificationCode" placeholder="请输入验证码"> | |||
<template #suffix> | |||
<a v-if="!count" class="itemBlue" @click="getVerificationCodeFunc"> 获取验证码</a> | |||
<span v-else class="itemBlue">{{ count }}</span> | |||
</template> | |||
</el-input> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<el-button | |||
type="primary" | |||
:loading="smsDialogLoading" | |||
@click="submitSms(smsDialogFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button | |||
@click="smsDialogData.visible=false" | |||
> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<style lang="less" scoped> | |||
.addOrEditExpert{ | |||
.header{ | |||
height: 60px; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
background-color: #fff; | |||
margin-bottom: 15px; | |||
font-size: 20px; | |||
} | |||
:deep(.el-collapse) { | |||
.el-collapse-item__header { | |||
padding: 0px 16px; | |||
font-size: 14px; | |||
} | |||
.el-collapse-item__content { | |||
padding: 16px 16px 16px 0px; | |||
// margin-left: -50px; | |||
} | |||
.el-collapse-item__header.is-active { | |||
border-bottom: 1px solid rgba(0, 0, 0, 0.1); | |||
} | |||
.collapse-title { | |||
flex: 1 0 90%; | |||
order: 1; | |||
.el-collapse-item__header { | |||
flex: 1 0 auto; | |||
order: -1; | |||
} | |||
.el-input-number { | |||
width: 150px !important; | |||
} | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,168 @@ | |||
<script name="evaluateDialog" setup> | |||
import { getCurrentInstance, nextTick, ref, watch } from 'vue' | |||
import { judgeDetail, judgeSubmit } from '@/http/apis/expertManage/expertStore' | |||
const { proxy } = getCurrentInstance(), | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false | |||
}, | |||
data: { | |||
type: Object, | |||
default: () => {} | |||
}, | |||
isEdit: { | |||
type: Boolean, | |||
default: true | |||
} | |||
}), | |||
emits = defineEmits(['close']), | |||
formData = ref({}), | |||
formRef = ref(), | |||
rules = { | |||
score: [{ required: true, message: '请输入' }], | |||
attended: [{ required: true, message: '请选择' }], | |||
performance: [{ required: true, message: '请选择' }], | |||
advised: [{ required: true, message: '请选择' }], | |||
leaveEarly: [{ required: true, message: '请选择' }], | |||
brokeRule: [{ required: true, message: '请选择' }], | |||
brokeRuleContent: [{ required: true, message: '请选择' }] | |||
}, | |||
loading = ref(false), | |||
submit = async (formEl) => { | |||
if (!formEl) return | |||
await formEl.validate(async valid => { | |||
if (valid) { | |||
loading.value = true | |||
try { | |||
const postData = { | |||
...formData.value | |||
} | |||
await judgeSubmit(postData) | |||
proxy.$message.success('提交成功!') | |||
loading.value = false | |||
emits('close', true) | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
}) | |||
}, | |||
getDetail = async () => { | |||
const res = await judgeDetail(props.data.meetingExpertId) | |||
formData.value = { | |||
...res.data | |||
} | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
await nextTick() | |||
formRef.value.clearValidate() | |||
formData.value = { | |||
meetingExpertId: props.data.meetingExpertId, | |||
meetingId: props.data.meetingId | |||
} | |||
if (!props.isEdit) { | |||
getDetail() | |||
} | |||
} | |||
} | |||
) | |||
defineExpose({ formRef }) | |||
</script> | |||
<template> | |||
<el-dialog :model-value="visible" :title="isEdit?'履职评价':'查看评价'" @close="emits('close')"> | |||
<el-form | |||
ref="formRef" | |||
:model="formData" | |||
:rules="rules" | |||
label-suffix=":" | |||
> | |||
<el-form-item v-if="isEdit" label="评分" prop="score"> | |||
<el-input-number | |||
v-model="formData.score" | |||
placeholder="请对该专家在本次会议的表现进行评分,最低0分,满分10分" | |||
:min="0" | |||
:max="10" | |||
:controls="false" | |||
@mousewheel.prevent | |||
/> | |||
</el-form-item> | |||
<el-form-item v-else label="评分"> | |||
<span>{{ formData.score }}</span> | |||
</el-form-item> | |||
<el-form-item v-if="isEdit" label="专家是否参加" prop="attended"> | |||
<el-radio-group v-model="formData.attended"> | |||
<el-radio :label="1">准时参加</el-radio> | |||
<el-radio :label="2">迟到</el-radio> | |||
<el-radio :label="3">缺席</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item v-else label="专家是否参加"> | |||
<span>{{ formData.attended===1?'准时参加':formData.attended===2?'迟到':'缺席' }}</span> | |||
</el-form-item> | |||
<template v-if="formData.attended!==3"> | |||
<el-form-item v-if="isEdit" label="专家参与程度" prop="performance"> | |||
<el-radio-group v-model="formData.performance"> | |||
<el-radio :label="1">积极</el-radio> | |||
<el-radio :label="2">消极</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item v-else label="专家参与程度"> | |||
<span>{{ formData.performance===1?'积极':formData.performance===2?'消极':'-' }}</span> | |||
</el-form-item> | |||
<el-form-item v-if="isEdit" label="专家是否提出专业建议" prop="advised"> | |||
<el-radio-group v-model="formData.advised"> | |||
<el-radio :label="true">有提出</el-radio> | |||
<el-radio :label="false">未提出</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item v-else label="专家是否提出专业建议"> | |||
<span>{{ formData.advised?'有提出':'未提出' }}</span> | |||
</el-form-item> | |||
<el-form-item v-if="isEdit" label=" 专家是否早退" prop="leaveEarly"> | |||
<el-radio-group v-model="formData.leaveEarly"> | |||
<el-radio :label="false">未早退</el-radio> | |||
<el-radio :label="true">早退</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item v-else label="专家是否早退"> | |||
<span>{{ formData.leaveEarly?'早退':'未早退' }}</span> | |||
</el-form-item> | |||
<el-form-item v-if="isEdit" label="专家有无违规行为" prop="brokeRule"> | |||
<el-radio-group v-model="formData.brokeRule"> | |||
<el-radio :label="false">无</el-radio> | |||
<el-radio :label="true">有</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item v-else label="专家有无违规行为"> | |||
<span>{{ formData.brokeRule?'有':'无' }}</span> | |||
</el-form-item> | |||
<template v-if="formData.brokeRule"> | |||
<el-form-item v-if="isEdit" label="违规行为" prop="brokeRuleContent"> | |||
<el-input | |||
v-model="formData.brokeRuleContent" | |||
placeholder="请填写" | |||
type="textarea" | |||
:maxlength="200" | |||
show-word-limit | |||
/> | |||
</el-form-item> | |||
<el-form-item v-else label="违规行为"> | |||
<span>{{ formData.brokeRuleContent }}</span> | |||
</el-form-item> | |||
</template> | |||
</template> | |||
</el-form> | |||
<template v-if="isEdit" #footer> | |||
<span class="dialog-footer"> | |||
<el-button type="primary" :loading="loading" @click="submit(formRef)">提交</el-button> | |||
<el-button @click="emits('close')">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,147 @@ | |||
<script> | |||
import { defineComponent } from 'vue' | |||
export default defineComponent({ | |||
beforeRouteEnter (to, from, next) { | |||
if (to.query.name) { | |||
to.meta.title = '履职记录-' + to.query.name | |||
} | |||
next() | |||
} | |||
}) | |||
</script> | |||
<script setup name='deputyActivityRecord'> | |||
import { reactive, ref, onMounted, h } from 'vue' | |||
import { getDeputyActivityRecord } from '@/http/apis/expertManage/expertStore' | |||
import MeetingProjectDialog from '@/pages/expertManage/reviewMeeting/components/meetingProjectDialog.vue' | |||
import { useRoute } from 'vue-router' | |||
import EvaluateDialog from '@/pages/expertManage/expertStore/deputyActivityRecord/components/evaluateDialog.vue' | |||
const route = useRoute(), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '会议名称', | |||
key: 'meetingName', | |||
prop: 'meetingName', | |||
minWidth: '80', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '评审项目', | |||
slot: 'projectName', | |||
minWidth: '100', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '评审时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '180' | |||
}, | |||
{ | |||
label: '是否参会', | |||
key: 'inviteStatus', | |||
prop: 'inviteStatus', | |||
width: '150', | |||
render: row => h('span', '是') | |||
}, | |||
{ | |||
label: '是否请假', | |||
key: 'expertStatus', | |||
prop: 'expertStatus', | |||
width: '150', | |||
render: row => h('span', row.expertStatus === 5 ? '是' : '否') | |||
}, | |||
{ | |||
label: '是否评价', | |||
key: 'hasJudge', | |||
prop: 'hasJudge', | |||
width: '150', | |||
render: row => h('span', row.hasJudge ? '是' : '否') | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '100', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await getDeputyActivityRecord({ | |||
...pageParams, | |||
expertId: route.query.id | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
// 查看项目 | |||
viewProject = (data) => { | |||
meetingProjectDialogData.value.visible = true | |||
meetingProjectDialogData.value.meetingId = data.meetingId | |||
}, | |||
meetingProjectDialogData = ref({ | |||
visible: false, | |||
meetingId: undefined | |||
}), | |||
close = () => { | |||
meetingProjectDialogData.value.visible = false | |||
}, | |||
// 履职评价 | |||
evaluateDialogData = reactive({ | |||
visible: false, | |||
data: {}, | |||
isEdit: true | |||
}), | |||
evaluateDialogRef = ref(), | |||
showEvaluateDialog = (data, isEdit) => { | |||
evaluateDialogData.data = data | |||
evaluateDialogData.isEdit = isEdit | |||
evaluateDialogData.visible = true | |||
}, | |||
closeEvaluateDialog = (flag) => { | |||
evaluateDialogData.visible = false | |||
flag && getTableData() | |||
} | |||
onMounted(() => { | |||
getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<div class=""> | |||
<el-card class="box-card"> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #projectName="{scope}"> | |||
<a @click="viewProject(scope.row)">查看</a> | |||
</template> | |||
<template #action="{scope}"> | |||
<a v-if="!scope.row.hasJudge" @click="showEvaluateDialog(scope.row,true)">履职评价</a> | |||
<a v-else @click="showEvaluateDialog(scope.row,false)">查看评价</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<meeting-project-dialog :visible="meetingProjectDialogData.visible" :meeting-id="meetingProjectDialogData.meetingId" @close="close" /> | |||
</div> | |||
<evaluate-dialog | |||
ref="evaluateDialogRef" | |||
:visible="evaluateDialogData.visible" | |||
:data="evaluateDialogData.data" | |||
:is-edit="evaluateDialogData.isEdit" | |||
@close="closeEvaluateDialog" | |||
/> | |||
</template> | |||
@@ -0,0 +1,315 @@ | |||
<script setup name='expertDetail'> | |||
import { ref, onMounted } from 'vue' | |||
import { useRoute, useRouter } from 'vue-router' | |||
import { getExpertDetail } from '@/http/apis/expertManage/expertVerify' | |||
import Accessory from '@/components/accessory/index.vue' | |||
const route = useRoute() | |||
const router = useRouter() | |||
const activeName = ref('basicInfo') | |||
const handleClick = (tab, event) => { | |||
console.log(tab, event) | |||
} | |||
const expertInfo = ref({ basicInfo: {}, eduInfo: {}, jobInfo: {}, professionalInfo: {}, recommendInfo: {}}) | |||
const getVerifyDetail = async () => { | |||
const res = await getExpertDetail({ expertUserId: route.query.id }) | |||
expertInfo.value = res.data | |||
} | |||
// 查看文件 | |||
const view = (data) => { | |||
const routeUrl = router.resolve({ | |||
path: '/fileView', | |||
query: { id: data } | |||
}) | |||
window.open(routeUrl.href, '_blank') | |||
} | |||
onMounted(async () => { | |||
getVerifyDetail() | |||
}) | |||
</script> | |||
<template> | |||
<div class=""> | |||
<el-card class="box-card"> | |||
<el-tabs | |||
v-model="activeName" | |||
class="demo-tabs" | |||
@tab-click="handleClick" | |||
> | |||
<el-tab-pane | |||
label="基本信息" | |||
name="basicInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="专家名称" | |||
span="1" | |||
width="200px" | |||
> | |||
{{ expertInfo.basicInfo.name }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="是否在浙政钉组织"> | |||
{{ expertInfo.basicInfo.isDingUser?'是':'否' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="手机号码" | |||
width="200px" | |||
> | |||
{{ expertInfo.basicInfo.phoneNo }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="性别"> | |||
{{ expertInfo.basicInfo.gender === '1' ? '男': '女' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="籍贯"> | |||
{{ expertInfo.basicInfo.hometown ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="民族"> | |||
{{ expertInfo.basicInfo.nationality ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政治面貌"> | |||
{{ expertInfo.basicInfo.political?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="身份证号"> | |||
{{ expertInfo.basicInfo.idCard||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="办公电话"> | |||
{{ expertInfo.basicInfo.officePhone||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="出生年月"> | |||
{{ expertInfo.basicInfo.birth ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="银行卡号"> | |||
{{ expertInfo.basicInfo.bankNo||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="开户银行"> | |||
{{ expertInfo.basicInfo.bank||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="电子邮箱"> | |||
{{ expertInfo.basicInfo.email||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家级别"> | |||
{{ expertInfo.basicInfo?.expertRegionInfo?.regionName.split('@@').map(i=>i.split('##')[1]).join('-') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家来源"> | |||
{{ expertInfo.basicInfo.expertSource?.[0].tagName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家类型"> | |||
{{ expertInfo.basicInfo.expertType?.[0].dictionaryName||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="履职意向"> | |||
{{ expertInfo.basicInfo.expertIntentionWorkRegions?.map(i=>i.regionName.split('@@').map(j=>j.split('##')[1]).join('-')).join(';') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="头像(免冠照)" | |||
span="2" | |||
> | |||
<a target="_blank" @click="view(expertInfo.basicInfo.avatarFile.fileId)">{{ expertInfo.basicInfo.avatarFile?.fileName }}</a> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
<el-tab-pane | |||
label="学历信息" | |||
name="eduInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="毕业院校" | |||
span="2" | |||
width="200px" | |||
> | |||
{{ expertInfo.eduInfo.school||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="毕业时间"> | |||
{{ expertInfo.eduInfo.graduatedAt||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="所学专业" | |||
width="200px" | |||
> | |||
{{ expertInfo.eduInfo.academicTitle ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学位"> | |||
{{ expertInfo.eduInfo.degree?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学历"> | |||
{{ expertInfo.eduInfo.edu?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="毕业证书"> | |||
<p v-for="(file,fileIndex) in expertInfo.eduInfo.graduationCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学位证书"> | |||
<p v-for="(file,fileIndex) in expertInfo.eduInfo.degreeCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
<el-tab-pane | |||
label="职业信息" | |||
name="professionInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="工作单位" | |||
width="200px" | |||
> | |||
{{ expertInfo.jobInfo.company||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作单位code"> | |||
{{ expertInfo.jobInfo.companyUniqCode ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="单位法人编号" | |||
width="200px" | |||
> | |||
{{ expertInfo.jobInfo.legalEntityCode||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行政职务"> | |||
{{ expertInfo.jobInfo.administrativeDuties ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="开始工作日期"> | |||
{{ expertInfo.jobInfo.startWorkAt ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行政职级"> | |||
{{ expertInfo.jobInfo.administrativeRank?.[0].dictionaryName||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="在职状态"> | |||
{{ expertInfo.jobInfo.jobStatus?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="退休日期"> | |||
{{ expertInfo.jobInfo.retiredAt||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="单位类型"> | |||
{{ expertInfo.jobInfo.companyAttribute?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="条线"> | |||
{{ expertInfo.jobInfo?.businessStrips?.map(i=>i.businessStripName).join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作地址"> | |||
{{ expertInfo.jobInfo.address||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作经历"> | |||
{{ expertInfo.jobInfo.experience||'-' }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
<el-tab-pane | |||
label="专业信息" | |||
name="majorInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="技术职称" | |||
width="200px" | |||
> | |||
{{ expertInfo.professionalInfo.technicalTitles||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="职称级别"> | |||
{{ expertInfo.professionalInfo.titleLevel?.[0].dictionaryName ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="擅长方向" | |||
width="200px" | |||
> | |||
{{ expertInfo.professionalInfo.goodAt?.map(i=>i.tagName).join('、') ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="技术专长"> | |||
<span v-for="(item,index) in expertInfo.professionalInfo.technicalExpertise" :key="index">{{ item.tagName }} </span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行业领域"> | |||
<span v-for="(item,index) in expertInfo.professionalInfo.industrySector" :key="index">{{ item.tagName }} </span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="获奖情况"> | |||
{{ expertInfo.professionalInfo.awards||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="表彰奖励"> | |||
{{ expertInfo.professionalInfo.recognitionReward ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="回避单位"> | |||
<span v-for="(item, index) in expertInfo.professionalInfo.avoidCompanyList" :key="index">{{ item.companyName }} </span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="职称证明"> | |||
<p v-for="(file,fileIndex) in expertInfo.professionalInfo.titleCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
<el-tab-pane | |||
label="推荐信息" | |||
name="recommendInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="推荐类型" | |||
width="200px" | |||
> | |||
{{ expertInfo.recommendInfo.recommendedWay?.[0].dictionaryName||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
width="200px" | |||
label="推荐证明" | |||
> | |||
<p v-for="(file,fileIndex) in expertInfo.recommendInfo.recommendationProofFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
<el-tab-pane | |||
label="其他信息" | |||
name="otherInfo" | |||
> | |||
<el-descriptions | |||
class="mt-20" | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="其他标签" | |||
width="200px" | |||
> | |||
{{ expertInfo.expertOtherInfo?.other?.map(i=>i.tagName)?.join('、') ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
width="200px" | |||
label="备注" | |||
> | |||
{{ expertInfo.expertOtherInfo?.remark ||'-' }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-tab-pane> | |||
</el-tabs> | |||
</el-card> | |||
</div> | |||
</template> | |||
<style lang='less' scoped> </style> |
@@ -0,0 +1,249 @@ | |||
<script setup name="expertStore"> | |||
import { getCurrentInstance, onMounted, reactive, ref } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import ElTree from '@/components/elTree/index.vue' | |||
import store from '@/store' | |||
import { storeToRefs } from 'pinia' | |||
import { delivery, getExpertList } from '@/http/apis/expertManage/expertStore' | |||
import { getIsShowRegionTree, getTreeParams } from '@/utils/getIsShowRegionTree' | |||
const | |||
{ dictList } = storeToRefs(store.dictStore), | |||
router = useRouter(), | |||
{ proxy } = getCurrentInstance(), | |||
searchForm = reactive({ | |||
expertName: undefined, | |||
company: undefined, | |||
expertTypeDictionaryCode: undefined, | |||
status: undefined, | |||
maxDeclareAmount: undefined, | |||
maxApprovalAmount: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '专家姓名', | |||
key: 'expertName', | |||
prop: 'expertName', | |||
minWidth: '80', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '工作单位', | |||
key: 'company', | |||
prop: 'company', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'phoneNo', | |||
prop: 'phoneNo', | |||
width: '120' | |||
}, | |||
{ | |||
label: '专家类型', | |||
key: 'expertType[0].dictionaryName', | |||
prop: 'expertType[0].dictionaryName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createTime', | |||
prop: 'createTime', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '240', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
areaCode = ref(), | |||
getTree = (value) => { | |||
searchForm.intentionRegionInfo = { | |||
regionCode: value.regionCode, | |||
regionLevel: value.regionLevel | |||
} | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await getExpertList({ | |||
...pageParams, | |||
...searchForm, | |||
year: searchForm.year * 1 || undefined, | |||
areaCode: areaCode.value || undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.expertName = undefined | |||
searchForm.company = undefined | |||
searchForm.expertTypeDictionaryCode = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
toAddorEditExpert = (row) => { | |||
if (row.userId) { | |||
router.push({ name: 'addOrEditExpert', query: { id: row.userId }}) | |||
} else { | |||
router.push({ name: 'addOrEditExpert' }) | |||
} | |||
}, | |||
checkDetail = (row) => { | |||
router.push({ name: 'expertDetail', query: { id: row.userId }}) | |||
}, | |||
checkDeputyActivityRecord = (row) => { | |||
router.push({ name: 'deputyActivityRecord', query: { id: row.userId, name: row.expertName }}) | |||
}, | |||
expertApply = () => { | |||
const timestamp = new Date().getTime() | |||
const time = window.btoa(timestamp) | |||
const routeData = router.resolve({ | |||
name: 'expertEnroll', | |||
query: { time } | |||
}) | |||
window.open(routeData.href, '_blank') | |||
}, | |||
del = (data) => { | |||
proxy.$messageBox | |||
.confirm(`确定要删除${data.expertName}专家吗?`, '提示!', { | |||
type: 'warning' | |||
}).then(async () => { | |||
await delivery(data.userId) | |||
proxy.$message.success('删除成功') | |||
getTableData() | |||
}) | |||
} | |||
onMounted(() => { | |||
if (!getIsShowRegionTree(['SUPER_ADMIN', 'REGION_MANAGER', 'EXPERT_ADMIN'])) getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-col | |||
v-if="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])" | |||
style="padding-right: 16px" | |||
:span="4" | |||
> | |||
<elTree :params="getTreeParams({'SUPER_ADMIN':false,'REGION_MANAGER':false,'EXPERT_ADMIN':false})" @get-tree="getTree" /> | |||
</el-col> | |||
<el-col :span="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])?20:24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
class="mb-16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="专家姓名"> | |||
<el-input | |||
v-model="searchForm.expertName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="工作单位"> | |||
<el-input | |||
v-model="searchForm.company" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="专家类型"> | |||
<el-select | |||
v-model="searchForm.expertTypeDictionaryCode" | |||
placeholder="全部" | |||
class="w-full" | |||
> | |||
<el-option | |||
v-for="(item,index) in dictList && | |||
dictList.length && | |||
dictList.find(i => i.dictionaryName === 'expert_type') | |||
.dictionaryList" | |||
:key="index" | |||
:label="item.describe" | |||
:value="item.dictionaryCode" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
plain | |||
size="small" | |||
icon="Plus" | |||
@click="toAddorEditExpert" | |||
>新增专家</el-button> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
@click="expertApply" | |||
>专家报名</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="toAddorEditExpert(scope.row)">编辑</a> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
<a @click="checkDeputyActivityRecord(scope.row)">履职记录</a> | |||
<a class="text-danger" @click="del(scope.row)">删除</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,234 @@ | |||
<script setup name='expertVerify'> | |||
import elTree from '@/components/elTree/index.vue' | |||
import { reactive, ref, onMounted, h } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import { getExpertVerifyList } from '@/http/apis/expertManage/expertVerify' | |||
import { getIsShowRegionTree, getTreeParams } from '@/utils/getIsShowRegionTree' | |||
import store from '@/store' | |||
const tableListRef = ref(), | |||
router = useRouter(), | |||
searchForm = reactive({ | |||
expertName: undefined, | |||
companyName: undefined, | |||
expertType: undefined, | |||
applyStatusList: ['pending_review'], | |||
maxDeclareAmount: undefined, | |||
maxApprovalAmount: undefined | |||
}), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '专家姓名', | |||
key: 'name', | |||
prop: 'name', | |||
minWidth: '80', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '工作单位', | |||
key: 'company', | |||
prop: 'company', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'phoneNo', | |||
prop: 'phoneNo', | |||
width: '120' | |||
}, | |||
{ | |||
label: '专家类型', | |||
key: 'expertType', | |||
prop: 'expertType', | |||
width: '80', | |||
render: row => h('span', row?.expertType?.[0].dictionaryName || '-') | |||
}, | |||
{ | |||
label: '报名时间', | |||
key: 'applyTime', | |||
prop: 'applyTime', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '200', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
areaCode = ref(), | |||
getTree = (value) => { | |||
searchForm.expertRegionInfo = { | |||
regionCode: value.regionCode, | |||
regionLevel: value.regionLevel | |||
} | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await getExpertVerifyList({ | |||
...pageParams, | |||
...searchForm, | |||
year: searchForm.year * 1 || undefined, | |||
maxDeclareAmount: searchForm.maxDeclareAmount * 1 || undefined, | |||
maxApprovalAmount: searchForm.maxApprovalAmount * 1 || undefined, | |||
startTime: searchForm.times?.[0] || undefined, | |||
endTime: searchForm.times?.[1] || undefined, | |||
areaCode: areaCode.value || undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
activeName = ref('待审核'), | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.expertName = undefined | |||
searchForm.companyName = undefined | |||
searchForm.expertType = undefined | |||
searchForm.maxDeclareAmount = undefined | |||
searchForm.maxApprovalAmount = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
checkDetail = (data) => { | |||
if (activeName.value === '待审核') { | |||
router.push({ name: 'expertVerifyAction', query: { applyId: data.id, applyType: data.applyType }}) | |||
} else { | |||
router.push({ name: 'verifyDetail', query: { applyId: data.id }}) | |||
} | |||
}, | |||
handleClick = ({ props: { name }}) => { | |||
if (name === '待审核') { | |||
searchForm.applyStatusList = ['pending_review'] | |||
getTableData() | |||
} else { | |||
searchForm.applyStatusList = ['passed', 'refused', 'revoked'] | |||
getTableData() | |||
} | |||
} | |||
onMounted(() => { | |||
if (!getIsShowRegionTree(['SUPER_ADMIN', 'REGION_MANAGER', 'EXPERT_ADMIN'])) getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-col | |||
v-if="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])" | |||
style="padding-right: 16px" | |||
:span="4" | |||
> | |||
<elTree :params="getTreeParams({'SUPER_ADMIN':false,'REGION_MANAGER':false,'EXPERT_ADMIN':false})" @get-tree="getTree" /> | |||
</el-col> | |||
<el-col :span="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])?20:24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
class="mb-16" | |||
> | |||
<el-col :span="8"> | |||
<el-form-item label="专家姓名"> | |||
<el-input | |||
v-model="searchForm.expertName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="工作单位"> | |||
<el-input | |||
v-model="searchForm.companyName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="专家类型"> | |||
<el-select | |||
v-model="searchForm.expertType" | |||
placeholder="全部" | |||
class="w-full" | |||
value-key="dictionaryCode" | |||
> | |||
<el-option | |||
v-for="(item,index) in store.dictStore.expertTypeDict" | |||
:key="index" | |||
:label="item.dictionaryName" | |||
:value="item" | |||
/> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row | |||
:gutter="16" | |||
> | |||
<el-col :span="24"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8 tab-card"> | |||
<template #header> | |||
<el-tabs | |||
v-model="activeName" | |||
class="demo-tabs" | |||
@tab-click="handleClick" | |||
> | |||
<el-tab-pane | |||
label="待审核" | |||
name="待审核" | |||
/> | |||
<el-tab-pane | |||
label="已审核" | |||
name="已审核" | |||
/> | |||
</el-tabs> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #action="{ scope }"> | |||
<a @click="checkDetail(scope.row)">{{ activeName==='待审核'?'处理':'详情' }}</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,428 @@ | |||
<script setup name='verifyDetail'> | |||
import { getCurrentInstance, ref, reactive, watch, onMounted, nextTick } from 'vue' | |||
import { | |||
getExpertVerifyDetail, | |||
submitVerifyResult, | |||
getExpertDetail, | |||
modifyDetail | |||
} from '@/http/apis/expertManage/expertVerify' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import Accessory from '@/components/accessory/index.vue' | |||
import store from '@/store' | |||
const { expertAuditStatusOptions } = store.dictStore.globalDicts | |||
const activeName = ref('basicInfo'), | |||
{ proxy } = getCurrentInstance(), | |||
dialogFormVisible = ref(false), | |||
route = useRoute(), | |||
router = useRouter(), | |||
routeName = ref(''), | |||
form = reactive({ | |||
applyId: route.query.applyId | |||
}), | |||
rules = reactive({ | |||
auditOpinion: [ | |||
{ required: true, message: '请填写审核意见', trigger: 'blur' } | |||
] | |||
}), | |||
ruleFormRef = ref(''), | |||
submitForm = async (formEl) => { | |||
if (!formEl) return | |||
await formEl.validate(async (valid, fields) => { | |||
if (valid) { | |||
if (recommendTitle.value === '通过') { | |||
form.applyResult = true | |||
} else { | |||
form.applyResult = false | |||
} | |||
await submitVerifyResult(form) | |||
form.auditOpinion = undefined | |||
dialogFormVisible.value = false | |||
proxy.$message.success('审核意见提交成功!') | |||
router.push({ name: 'expertVerify' }) | |||
} else { | |||
console.log('error submit!', fields) | |||
} | |||
}) | |||
}, | |||
recommendTitle = ref(''), | |||
adopt = (title) => { | |||
recommendTitle.value = title | |||
dialogFormVisible.value = true | |||
nextTick(() => { | |||
ruleFormRef.value.resetFields() | |||
}) | |||
}, | |||
goBack = () => { | |||
router.push({ name: 'expertVerify' }) | |||
}, | |||
expertDetail = ref({ basicInfo: {}, eduInfo: {}, jobInfo: {}, professionalInfo: {}, recommendInfo: {}}), | |||
verifyInfo = ref(), | |||
getVerifyDetail = async () => { | |||
const res = await getExpertVerifyDetail({ applyId: route.query.applyId }) | |||
verifyInfo.value = res.data | |||
}, | |||
getExpertDetailRequest = async () => { | |||
const apiFn = route.query.applyType === 'expert_info_modify_admin' ? modifyDetail : getExpertDetail | |||
const res = await apiFn({ expertUserId: verifyInfo.value.expertUserId }) | |||
expertDetail.value = res.data | |||
}, | |||
// 查看文件 | |||
view = (data) => { | |||
const routeUrl = router.resolve({ | |||
path: '/fileView', | |||
query: { id: data } | |||
}) | |||
window.open(routeUrl.href, '_blank') | |||
} | |||
onMounted(async () => { | |||
await getVerifyDetail() | |||
await getExpertDetailRequest() | |||
}) | |||
watch( | |||
route, | |||
(val) => { | |||
routeName.value = route.meta.title | |||
}, | |||
{ immediate: true, deep: true } | |||
) | |||
</script> | |||
<template> | |||
<div class="footerPage"> | |||
<el-card | |||
v-if="routeName ==='专家审核详情'" | |||
shadow="never" | |||
class="mb-16" | |||
> | |||
<div> | |||
<div class="flex justify-between items-center"> | |||
<div class="flex-1"> | |||
<p class="font-bold">关于{{ expertDetail.basicInfo.name }}的专家审核结果</p> | |||
<div class="mt-8 search"> | |||
<el-form label-suffix=":"> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<el-form-item label="审核人">{{ verifyInfo?.auditor||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="审核时间">{{ verifyInfo?.auditTime||'-' }}</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="审核意见">{{ verifyInfo?.auditOption||'-' }}</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
</div> | |||
<div class="textRight"> | |||
<p> | |||
<span :class="`dot mr-4 bg-${verifyInfo&&verifyInfo.auditStatus&&expertAuditStatusOptions[verifyInfo.auditStatus]?.color}`"></span> | |||
<span :class="`font-semibold text-${verifyInfo&&verifyInfo.auditStatus&&expertAuditStatusOptions[verifyInfo.auditStatus]?.color}`">{{ verifyInfo&&verifyInfo.auditStatus&&expertAuditStatusOptions[verifyInfo.auditStatus]?.name }}</span> | |||
</p> | |||
<p>审核结果</p> | |||
</div> | |||
</div> | |||
</div> | |||
</el-card> | |||
<el-card class="tab-card" shadow="never"> | |||
<template #header> | |||
<el-tabs v-model="activeName"> | |||
<el-tab-pane label="基本信息" name="basicInfo" /> | |||
<el-tab-pane label="学历信息" name="eduInfo" /> | |||
<el-tab-pane label="职业信息" name="professionInfo" /> | |||
<el-tab-pane label="专业信息" name="majorInfo" /> | |||
<el-tab-pane label="推荐信息" name="recommendInfo" /> | |||
<el-tab-pane label="其他信息" name="expertOtherInfo" /> | |||
</el-tabs> | |||
</template> | |||
<el-descriptions | |||
v-if="activeName==='basicInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="专家名称" | |||
span="1" | |||
width="200px" | |||
> | |||
{{ expertDetail.basicInfo.name }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="是否在浙政钉组织" width="200px"> | |||
{{ expertDetail.basicInfo.isDingUser?'是':'否' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="手机号码" | |||
width="200px" | |||
> | |||
{{ expertDetail.basicInfo.phoneNo }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="性别"> | |||
{{ expertDetail.basicInfo.gender === '1' ? '男': '女' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="籍贯"> | |||
{{ expertDetail.basicInfo.hometown }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="民族"> | |||
{{ expertDetail.basicInfo.nationality }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="政治面貌"> | |||
{{ expertDetail.basicInfo.political?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="身份证号"> | |||
{{ expertDetail.basicInfo.idCard }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="办公电话"> | |||
{{ expertDetail.basicInfo.officePhone }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="出生年月"> | |||
{{ expertDetail.basicInfo.birth }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="银行卡号"> | |||
{{ expertDetail.basicInfo.bankNo }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="开户银行"> | |||
{{ expertDetail.basicInfo.bank }} | |||
</el-descriptions-item> | |||
<el-descriptions-item span="1" label="电子邮箱"> | |||
{{ expertDetail.basicInfo.email }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家级别"> | |||
{{ expertDetail.basicInfo?.expertRegionInfo?.regionName.split('@@').map(i=>i.split('##')[1]).join('-') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家来源"> | |||
{{ expertDetail.basicInfo.expertSource?.[0].tagName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家类型"> | |||
{{ expertDetail.basicInfo.expertType?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="履职意向"> | |||
{{ expertDetail.basicInfo.expertIntentionWorkRegions?.map(i=>i.regionName.split('@@').map(j=>j.split('##')[1]).join('-')).join(';') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="头像(免冠照)" | |||
span="2" | |||
> | |||
<a target="_blank" @click="view(expertDetail.basicInfo.avatarFile.fileId)">{{ expertDetail.basicInfo.avatarFile?.fileName }}</a> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<el-descriptions | |||
v-if="activeName==='eduInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="毕业院校" | |||
span="2" | |||
width="200px" | |||
> | |||
{{ expertDetail.eduInfo.school }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="毕业时间"> | |||
{{ expertDetail.eduInfo.graduatedAt }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="所学专业" | |||
width="200px" | |||
> | |||
{{ expertDetail.eduInfo.academicTitle }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学位"> | |||
{{ expertDetail.eduInfo.degree?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学历"> | |||
{{ expertDetail.eduInfo.edu?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="毕业证书"> | |||
<p v-for="(file,fileIndex) in expertDetail.eduInfo.graduationCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="学位证书"> | |||
<p v-for="(file,fileIndex) in expertDetail.eduInfo.degreeCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<el-descriptions | |||
v-if="activeName==='professionInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="工作单位" | |||
width="200px" | |||
> | |||
{{ expertDetail.jobInfo.company }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作单位code" width="200px"> | |||
{{ expertDetail.jobInfo.companyUniqCode }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="单位法人编号" | |||
width="200px" | |||
> | |||
{{ expertDetail.jobInfo.legalEntityCode }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行政职务"> | |||
{{ expertDetail.jobInfo.administrativeDuties }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="开始工作日期"> | |||
{{ expertDetail.jobInfo.startWorkAt }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行政职级"> | |||
{{ expertDetail.jobInfo.administrativeRank?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="在职状态"> | |||
{{ expertDetail.jobInfo.jobStatus?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="退休日期"> | |||
{{ expertDetail.jobInfo.retiredAt }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="单位类型"> | |||
{{ expertDetail.jobInfo.companyAttribute?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作地址"> | |||
{{ expertDetail.jobInfo.address }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="工作经历"> | |||
{{ expertDetail.jobInfo.experience }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<el-descriptions | |||
v-if="activeName==='majorInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="技术职称" | |||
width="200px" | |||
> | |||
{{ expertDetail.professionalInfo.technicalTitles }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="职称级别" width="200px"> | |||
{{ expertDetail.professionalInfo.titleLevel?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="擅长方向" | |||
width="200px" | |||
> | |||
{{ expertDetail.professionalInfo.goodAt?.map(i=>i.tagName).join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="技术专长"> | |||
{{ expertDetail.professionalInfo.technicalExpertise?.[0].tagName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行业领域"> | |||
{{ expertDetail.professionalInfo.industrySector?.[0].tagName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="获奖情况"> | |||
{{ expertDetail.professionalInfo.awards }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="表彰奖励"> | |||
{{ expertDetail.professionalInfo.recognitionReward }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="回避单位"> | |||
<span v-for="(item,index) in expertDetail.professionalInfo.avoidCompanyList" :key="index">{{ item.companyName }} </span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="职称证明"> | |||
<p v-for="(file,fileIndex) in expertDetail.professionalInfo.titleCertificateFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<el-descriptions | |||
v-if="activeName==='recommendInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="推荐类型" | |||
width="200px" | |||
> | |||
{{ expertDetail.recommendInfo.recommendedWay?.[0].dictionaryName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
width="200px" | |||
label="推荐证明" | |||
> | |||
<p v-for="(file,fileIndex) in expertDetail.recommendInfo.recommendationProofFile" :key="fileIndex" class="mb-4"> | |||
<accessory :file-name="file.fileName" :file-id="file.fileId" /> | |||
</p> | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
<el-descriptions | |||
v-if="activeName==='expertOtherInfo'" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item | |||
label="其他标签" | |||
width="200px" | |||
> | |||
{{ expertDetail.expertOtherInfo?.other?.map(i=>i.tagName)?.join('、') ||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
width="200px" | |||
label="备注" | |||
> | |||
{{ expertDetail.expertOtherInfo?.remark ||'-' }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-card> | |||
<div class="footer"> | |||
<el-button | |||
v-if="routeName !=='专家审核详情'" | |||
type="primary" | |||
@click="adopt('通过')" | |||
>通过</el-button> | |||
<el-button | |||
v-if="routeName !=='专家审核详情'" | |||
plain | |||
type="danger" | |||
@click="adopt('驳回')" | |||
>驳回</el-button> | |||
<el-button | |||
@click="goBack" | |||
>返回</el-button> | |||
</div> | |||
</div> | |||
<el-dialog | |||
v-model="dialogFormVisible" | |||
:title="recommendTitle" | |||
> | |||
<el-form | |||
ref="ruleFormRef" | |||
:model="form" | |||
:rules="rules" | |||
status-icon | |||
> | |||
<el-form-item | |||
label="审核意见" | |||
label-width="auto" | |||
prop="auditOpinion" | |||
> | |||
<el-input | |||
v-model="form.auditOpinion" | |||
maxlength="200" | |||
placeholder="请输入" | |||
show-word-limit | |||
type="textarea" | |||
/> | |||
</el-form-item> | |||
</el-form> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button | |||
type="primary" | |||
@click="submitForm(ruleFormRef)" | |||
> | |||
提交 | |||
</el-button> | |||
<el-button @click="dialogFormVisible = false">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
<style lang='less' scoped> </style> |
@@ -0,0 +1,218 @@ | |||
<script setup name="driverDialog"> | |||
import { getCurrentInstance, reactive, ref, watch } from 'vue' | |||
import { getExpertList } from '@/http/apis/expertManage/expertStore' | |||
import store from '@/store' | |||
import { districtList } from '@/http/apis/commonApi' | |||
const { proxy } = getCurrentInstance(), | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: { | |||
type: Array, | |||
default: undefined | |||
}, | |||
selectExpertType: { | |||
type: Number, | |||
default: 1 | |||
} | |||
}), | |||
emits = defineEmits(['close', 'getUserData']), | |||
searchForm = reactive({ | |||
expertRegionLevel: undefined, | |||
expertName: undefined, | |||
company: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
column = [ | |||
{ | |||
type: 'selection', | |||
reserveSelection: true, | |||
width: '55' | |||
}, | |||
{ | |||
label: '姓名', | |||
key: 'expertName', | |||
prop: 'expertName' | |||
}, | |||
{ | |||
label: '工作单位', | |||
key: 'company', | |||
prop: 'company', | |||
showOverflowTooltip: true, | |||
width: 250 | |||
}, | |||
{ | |||
label: '专家级别', | |||
key: 'expertRegionInfo', | |||
slot: 'expertRegionInfo', | |||
width: '150' | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'phoneNo', | |||
prop: 'phoneNo', | |||
width: '150' | |||
}, | |||
{ | |||
label: '专家类型', | |||
key: 'expertType[0].dictionaryName', | |||
prop: 'expertType[0].dictionaryName', | |||
width: '150' | |||
} | |||
], | |||
tableData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value?.pageParams) => { | |||
const res = await getExpertList({ | |||
...pageParams, | |||
...searchForm, | |||
expertRegionInfo: searchForm.expertRegionInfo ? { | |||
regionCode: searchForm.expertRegionInfo.slice(-1)[0].split('##')[0], | |||
regionLevel: searchForm.expertRegionInfo.slice(-1)[0].split('##')[2], | |||
regionName: searchForm.expertRegionInfo.slice(-1)[0].split('##')[1] | |||
} : undefined | |||
}) | |||
total.value = res.data.total | |||
tableData.value = res.data.records || [] | |||
const selectCopyData = JSON.parse(JSON.stringify(selectData.value)) | |||
if (selectCopyData?.length) { | |||
tableData.value && tableData.value.forEach(item => { | |||
const dataIds = selectCopyData.map(i => i.userId * 1) | |||
if (dataIds.includes(item.userId)) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} | |||
}) | |||
} | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.expertRegionInfo = undefined | |||
searchForm.expertName = undefined | |||
searchForm.company = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
selectData = ref([]), | |||
selectionChange = val => { | |||
// selectData.value = val | |||
const ids = val.map(i => i.userId) | |||
tableData.value.forEach(row => { | |||
if (ids.includes(row.userId)) { | |||
selectData.value.push(row) | |||
} else { | |||
selectData.value = selectData.value.filter(i => i.userId !== row.userId) | |||
} | |||
}) | |||
}, | |||
confirm = () => { | |||
const obj = {} | |||
const data = selectData.value.reduce((cur, next) => { | |||
obj[next.userId] ? '' : obj[next.userId] = true && cur.push(next) | |||
return cur | |||
}, []) | |||
if (props.selectExpertType === 1 && data?.length > 10) { | |||
proxy.$message.warning('最多选择10位人员') | |||
} else { | |||
emits('getUserData', data) | |||
} | |||
}, | |||
regionTree = ref([]) | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
if (props.data?.length) { | |||
selectData.value = props.data.map(i => i) | |||
} | |||
const res = await districtList({ regionCode: 330500, regionLevel: 2 }) | |||
regionTree.value = [res.data] | |||
getTableData() | |||
store.userStore.setRoleStore() | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="选择人员" | |||
width="840px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<div class="search mb-16"> | |||
<el-form label-suffix=":" :model="searchForm" size="small"> | |||
<el-row :gutter="16" class="mb-16"> | |||
<el-col :span="8"> | |||
<el-form-item label="专家级别"> | |||
<el-cascader | |||
v-model="searchForm.expertRegionInfo" | |||
:options="regionTree" | |||
placeholder="请选择" | |||
class="w-full" | |||
:props="{ | |||
value:'unionCode', | |||
label:'name' | |||
}" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="专家姓名"> | |||
<el-input | |||
v-model="searchForm.expertName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="工作单位"> | |||
<el-input | |||
v-model="searchForm.company" | |||
maxlength="11" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row> | |||
<el-col :span="24"> | |||
<el-form-item class="btn"> | |||
<el-button type="primary" @click="search">查询</el-button> | |||
<el-button @click="reset">重置</el-button> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:total="total" | |||
row-key="userId" | |||
@selection-change="selectionChange" | |||
@get-table-data="getTableData" | |||
> | |||
<template #expertRegionInfo="{scope}"> | |||
<span>{{ scope.row?.expertRegionInfo?.regionName||'-' }}</span> | |||
</template> | |||
</table-list> | |||
<template #footer> | |||
<el-button type="primary" size="small" @click="confirm"> | |||
确定 | |||
</el-button> | |||
<el-button size="small" @click="emits('close')"> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,149 @@ | |||
<script setup name="driverDialog"> | |||
import { nextTick, reactive, ref, watch } from 'vue' | |||
import { getMeetingProjectList } from '@/http/apis/expertManage/reviewMeeting' | |||
import store from '@/store' | |||
const { projectTypeOptions } = store.dictStore.globalDicts || {} | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
data: { | |||
type: Array, | |||
default: undefined | |||
}, | |||
meetingType: { | |||
type: String, | |||
default: '1' | |||
}, | |||
dictionaryList: { | |||
type: Array, | |||
default: undefined | |||
} | |||
}), | |||
emits = defineEmits(['close', 'getProjectData']), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
column = reactive([ | |||
{ | |||
type: 'selection', | |||
width: '50' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '申报单位', | |||
key: 'buildOrg', | |||
prop: 'buildOrg', | |||
minWidth: '120', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
slot: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '100' | |||
}, | |||
{ | |||
label: '申报金额', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '100' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '80' | |||
} | |||
]), | |||
tableData = ref([]), | |||
getTableData = async (pageParams = tableListRef.value?.pageParams) => { | |||
const res = await getMeetingProjectList({ | |||
meetingType: props.meetingType, | |||
...pageParams | |||
}) | |||
total.value = res.data.total | |||
tableData.value = res.data.records || [] | |||
await nextTick() | |||
const selectCopyData = JSON.parse(JSON.stringify(selectData.value)) || [] | |||
if (selectCopyData?.length) { | |||
tableData.value && tableData.value.forEach(item => { | |||
const dataIds = selectCopyData.map(i => i.id * 1) | |||
if (dataIds.includes(item.id)) { | |||
tableListRef.value.toggleRowSelect(item, true) | |||
} | |||
}) | |||
} | |||
}, | |||
selectData = ref([]), | |||
selectionChange = val => { | |||
const ids = val.map(i => i.id) | |||
tableData.value.forEach(row => { | |||
if (ids.includes(row.id)) { | |||
selectData.value.push(row) | |||
} else { | |||
selectData.value = selectData.value.filter(i => i.id !== row.id) | |||
} | |||
}) | |||
}, | |||
confirm = () => { | |||
const obj = {} | |||
const data = selectData.value.reduce((cur, next) => { | |||
obj[next.id] ? '' : obj[next.id] = true && cur.push(next) | |||
return cur | |||
}, []) | |||
emits('getProjectData', data) | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
if (props.data?.length) { | |||
selectData.value = props.data.map(i => i) | |||
} | |||
getTableData() | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="添加项目" | |||
width="840px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:total="total" | |||
row-key="id" | |||
@selection-change="selectionChange" | |||
@get-table-data="getTableData" | |||
> | |||
<template #projectTypeName="{scope}"> | |||
{{ projectTypeOptions[scope.row?.projectType] }} | |||
</template> | |||
</table-list> | |||
<template #footer> | |||
<el-button type="primary" size="small" @click="confirm"> | |||
确定 | |||
</el-button> | |||
<el-button size="small" @click="emits('close')"> | |||
关闭 | |||
</el-button> | |||
</template> | |||
</el-dialog> | |||
</template> |
@@ -0,0 +1,92 @@ | |||
<script name="meetingProjectDialog" setup> | |||
import { ref, reactive, watch } from 'vue' | |||
import { projects } from '@/http/apis/expertManage/reviewMeeting' | |||
const props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
meetingId: { | |||
type: Number, | |||
default: null | |||
} | |||
}), | |||
emits = defineEmits(['close']), | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '申报单位', | |||
key: 'buildOrg', | |||
prop: 'buildOrg', | |||
minWidth: '80', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '100' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declaredAmount', | |||
prop: 'declaredAmount', | |||
width: '150' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear', | |||
width: '80' | |||
} | |||
]), | |||
tableData = ref(), | |||
getTableData = async () => { | |||
const res = await projects(props.meetingId) | |||
tableData.value = res.data | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
getTableData() | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="评审项目" | |||
width="60%" | |||
@close="emits('close')" | |||
> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="tableData" | |||
:pagination="false" | |||
@get-table-data="getTableData" | |||
/> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button @click="emits('close')">关闭</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
</template> | |||
@@ -0,0 +1,263 @@ | |||
<script setup name="reviewMeeting"> | |||
import { h, onMounted, reactive, ref } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
import ElTree from '@/components/elTree/index.vue' | |||
import { meetingList } from '@/http/apis/expertManage/reviewMeeting' | |||
import MeetingProjectDialog from './components/meetingProjectDialog.vue' | |||
import { getIsShowRegionTree, getTreeParams } from '@/utils/getIsShowRegionTree' | |||
const | |||
router = useRouter(), | |||
searchForm = reactive({ | |||
name: undefined, | |||
projectName: undefined, | |||
times: undefined | |||
}), | |||
tableListRef = ref(), | |||
total = ref(0), | |||
// 列表数据 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '会议名称', | |||
key: 'meetingName', | |||
prop: 'meetingName', | |||
minWidth: '180', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '评审项目', | |||
key: 'projectName', | |||
slot: 'projectName', | |||
minWidth: '80' | |||
}, | |||
{ | |||
label: '评审时间', | |||
key: 'startTime', | |||
prop: 'startTime', | |||
width: '290', | |||
render: row => h('span', row.startTime + '~' + row.endTime) | |||
}, | |||
{ | |||
label: '会议状态', | |||
key: 'status', | |||
prop: 'status', | |||
width: '80', | |||
render: row => [ | |||
h('span', { | |||
class: ['dot mr-4', `${row.status === 1 ? 'bg-success' : row.status === 3 ? 'bg-danger' : ''}`] | |||
}), | |||
h( | |||
'span', | |||
{ | |||
class: `${row.status === 1 ? 'text-success' : row.status === 3 ? 'text-danger' : ''}` | |||
}, | |||
row.status === 1 ? '正常' : '已取消' | |||
) | |||
] | |||
}, | |||
{ | |||
label: '抽取方式', | |||
key: 'inviteType', | |||
prop: 'inviteType', | |||
width: '80', | |||
render: row => h('span', row.inviteType === 1 ? '随机抽取' : '指定抽取') | |||
}, | |||
{ | |||
label: '抽取状态', | |||
key: 'inviteStatus', | |||
prop: 'inviteStatus', | |||
width: '80', | |||
render: row => h('span', !row.inviteStatus ? '抽取中' : '抽取结束') | |||
}, | |||
{ | |||
label: '名单确认状态', | |||
key: 'confirmedRoster', | |||
prop: 'confirmedRoster', | |||
width: '120', | |||
render: row => [ | |||
h( | |||
'span', | |||
{ | |||
class: `${row.confirmedRoster ? 'text-success' : ''}` | |||
}, | |||
row.confirmedRoster ? '已确认' : '未确认' | |||
) | |||
] | |||
}, | |||
{ | |||
label: '创建时间', | |||
key: 'createOn', | |||
prop: 'createOn', | |||
width: '180' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '80', | |||
fixed: 'right' | |||
} | |||
]), | |||
data = ref([]), | |||
getTree = (value) => { | |||
searchForm.regionCode = value.regionCode | |||
searchForm.regionLevel = value.regionLevel | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
getTableData() | |||
}, | |||
getTableData = async (pageParams = tableListRef.value.pageParams) => { | |||
const res = await meetingList({ | |||
...pageParams, | |||
...searchForm, | |||
startTime: searchForm.times?.[0] || undefined, | |||
endTime: searchForm.times?.[1] || undefined, | |||
times: undefined | |||
}) | |||
data.value = res.data.records | |||
total.value = res.data.total | |||
}, | |||
search = () => { | |||
getTableData() | |||
}, | |||
reset = () => { | |||
searchForm.name = undefined | |||
searchForm.projectName = undefined | |||
searchForm.times = undefined | |||
tableListRef.value.pageParams.pageNumber = 1 | |||
tableListRef.value.pageParams.pageSize = 10 | |||
getTableData() | |||
}, | |||
// 新增会议 | |||
toAddMeeting = (data) => { | |||
router.push({ name: 'addMeeting' }) | |||
}, | |||
checkDetail = (row) => { | |||
router.push({ name: 'meetingDetail', query: { id: row.meetingId }}) | |||
}, | |||
// 查看项目 | |||
viewProject = (data) => { | |||
meetingProjectDialogData.value.visible = true | |||
meetingProjectDialogData.value.meetingId = data.meetingId | |||
}, | |||
meetingProjectDialogData = ref({ | |||
visible: false, | |||
meetingId: undefined | |||
}), | |||
close = () => { | |||
meetingProjectDialogData.value.visible = false | |||
} | |||
onMounted(() => { | |||
if (!getIsShowRegionTree(['SUPER_ADMIN', 'REGION_MANAGER', 'EXPERT_ADMIN'])) getTableData() | |||
}) | |||
</script> | |||
<template> | |||
<el-row> | |||
<el-col | |||
v-if="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])" | |||
style="padding-right: 16px" | |||
:span="4" | |||
> | |||
<elTree :params="getTreeParams({'SUPER_ADMIN':false,'REGION_MANAGER':false,'EXPERT_ADMIN':true})" @get-tree="getTree" /> | |||
</el-col> | |||
<el-col :span="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])?20:24"> | |||
<el-card class="w-full search"> | |||
<el-form | |||
:model="searchForm" | |||
size="small" | |||
label-suffix=":" | |||
> | |||
<el-row | |||
:gutter="16" | |||
class="mb-16" | |||
> | |||
<el-col :span="12"> | |||
<el-form-item label="会议名称"> | |||
<el-input | |||
v-model="searchForm.name" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="12"> | |||
<el-form-item label="评审项目"> | |||
<el-input | |||
v-model="searchForm.projectName" | |||
placeholder="请输入" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row | |||
:gutter="16" | |||
> | |||
<el-col :span="16"> | |||
<el-form-item label="评审时间"> | |||
<el-date-picker | |||
v-model="searchForm.times" | |||
type="datetimerange" | |||
:editable="false" | |||
format="YYYY-MM-DD HH:mm" | |||
value-format="YYYY-MM-DD HH:mm" | |||
range-separator="-" | |||
start-placeholder="开始时间" | |||
end-placeholder="结束时间" | |||
/> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item class="btn"> | |||
<div class="flex"> | |||
<el-button | |||
type="primary" | |||
@click="search" | |||
>查询</el-button> | |||
<el-button | |||
@click="reset" | |||
>重置</el-button> | |||
</div> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</el-card> | |||
<el-card class="w-full mt-8"> | |||
<template #header> | |||
<div class="flex justify-between"> | |||
<span>列表</span> | |||
<div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
icon="Plus" | |||
@click="toAddMeeting" | |||
>新增会议</el-button> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="data" | |||
:total="total" | |||
@get-table-data="getTableData" | |||
> | |||
<template #projectName="{scope}"> | |||
<a @click="viewProject(scope.row)">查看</a> | |||
</template> | |||
<template #action="{ scope }"> | |||
<a @click="checkDetail(scope.row)">详情</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
<meeting-project-dialog :visible="meetingProjectDialogData.visible" :meeting-id="meetingProjectDialogData.meetingId" @close="close" /> | |||
</template> | |||
<style lang='less' scoped> | |||
</style> |
@@ -0,0 +1,860 @@ | |||
<script setup name='meetingDetail'> | |||
import { ref, reactive, onMounted, h, getCurrentInstance, nextTick } from 'vue' | |||
import { useRouter, useRoute } from 'vue-router' | |||
import { | |||
batchAppoint, | |||
confirmedRoster, convertToAppoint, expertConfirm, | |||
expertRelease, | |||
inviteExpertList, | |||
meetingBasicInfo, | |||
meetingCancel, | |||
meetingInviteRuleDetail, setUpHeadman, stopInvite, | |||
continueInvite, listReview, expertRemove, exportTable | |||
} from '@/http/apis/expertManage/reviewMeeting' | |||
import store from '@/store' | |||
import addExpertDialog from '../addMeeting/components/addExpertDialog.vue' | |||
import { districtList } from '@/http/apis/commonApi' | |||
import { templatesById } from '@/http/apis/expertManage/expertReview' | |||
import memberOpinion from '@/pages/expertManage/expertReview/components/memberOpinion.vue' | |||
import LeaveDialog from '@/pages/expertManage/expertReview/components/leaveDialog.vue' | |||
const { proxy } = getCurrentInstance(), | |||
router = useRouter(), | |||
route = useRoute(), | |||
{ meetingTypeOptions } = store.dictStore.globalDicts || {}, | |||
dialogVisible = ref(false), | |||
// 评审项目 | |||
column = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '项目名称', | |||
key: 'projectName', | |||
prop: 'projectName', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '申报单位', | |||
key: 'buildOrg', | |||
prop: 'buildOrg', | |||
minWidth: '80', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '项目类型', | |||
key: 'projectTypeName', | |||
prop: 'projectTypeName', | |||
width: '80' | |||
}, | |||
{ | |||
label: '申报金额(万元)', | |||
key: 'declareAmount', | |||
prop: 'declareAmount' | |||
}, | |||
{ | |||
label: '预算年度', | |||
key: 'projectYear', | |||
prop: 'projectYear' | |||
}, | |||
{ | |||
label: '评审结果', | |||
key: 'reviewResult', | |||
prop: 'reviewResult', | |||
render: row => h('span', row.reviewResult || '-') | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '80', | |||
fixed: 'right' | |||
} | |||
]), | |||
column2 = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '规则', | |||
key: 'ruleId', | |||
slot: 'ruleId' | |||
}, | |||
{ | |||
label: '申请人数', | |||
key: 'inviteCnt', | |||
prop: 'inviteCnt' | |||
}, | |||
{ | |||
label: '已确认参会人数', | |||
key: 'agreeCnt', | |||
slot: 'agreeCnt' | |||
}, | |||
{ | |||
label: '实抽人数', | |||
key: 'noticedCnt', | |||
prop: 'noticedCnt' | |||
} | |||
]), | |||
column3 = reactive([ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '专家姓名', | |||
key: 'name', | |||
prop: 'name', | |||
width: '140', | |||
render: row => h('span', `${row.name}${row.isHeadman ? '(组长)' : ''}`) | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'contact', | |||
slot: 'contact', | |||
width: '120' | |||
}, | |||
{ | |||
label: '匹配规则', | |||
key: 'ruleId', | |||
slot: 'ruleId' | |||
}, | |||
{ | |||
label: '是否参加', | |||
key: 'confirmedAttend', | |||
prop: 'confirmedAttend', | |||
render: row => h('span', `${row.noticeStatus === '已通知' && row.confirmedAttend ? '确认参加' : row.noticeStatus === '已通知' && !row.confirmedAttend ? '拒绝参加' : '-'}`) | |||
}, | |||
{ | |||
label: '专家请假', | |||
key: 'leaved', | |||
slot: 'leaved' | |||
}, | |||
{ | |||
label: '语音通知状态', | |||
key: 'noticeStatus', | |||
prop: 'noticeStatus', | |||
width: '200' | |||
}, | |||
{ | |||
label: '语音通知时间', | |||
key: 'noticeTime', | |||
prop: 'noticeTime', | |||
width: '200' | |||
} | |||
]), | |||
column4 = reactive([ | |||
{ | |||
type: 'radio', | |||
key: 'expertId', | |||
width: '60' | |||
}, | |||
{ | |||
label: '专家姓名', | |||
key: 'name', | |||
prop: 'name' | |||
}, | |||
{ | |||
label: '工作单位', | |||
key: 'company', | |||
prop: 'company', | |||
minWidth: '150', | |||
showOverflowTooltip: true | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'mobile', | |||
slot: 'mobile' | |||
}, | |||
{ | |||
label: '专家类型', | |||
key: 'expertTypeName', | |||
prop: 'expertTypeName' | |||
} | |||
]), | |||
column5 = reactive([ | |||
{ | |||
label: '专家姓名', | |||
key: 'name', | |||
prop: 'name', | |||
render: row => h('span', `${row.name}${row.isHeadman ? '(组长)' : ''}`) | |||
}, | |||
{ | |||
label: '手机号码', | |||
key: 'mobile', | |||
slot: 'mobile' | |||
}, | |||
{ | |||
label: '是否参会', | |||
key: 'status', | |||
prop: 'status', | |||
render: row => h('span', row.status === 3 ? '是' : row.status === 4 || row.status === 5 || row.status === 7 ? '否' : '-') | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: '180', | |||
fixed: 'right' | |||
} | |||
]), | |||
// 获取会议详情 | |||
basicInfo = ref({}), | |||
inviteRuleDetail = ref({}), | |||
isExpertConfirmed = ref(false), | |||
getDetail = async () => { | |||
const res = await meetingBasicInfo(route.query.id) | |||
isExpertConfirmed.value = res.data.confirmedRoster | |||
const res1 = await meetingInviteRuleDetail(route.query.id) | |||
basicInfo.value = res.data | |||
inviteRuleDetail.value = res1.data | |||
}, | |||
// 抽取情况、通知情况 | |||
inviteExpertListData = ref({}), | |||
getInviteExpertList = async () => { | |||
const res = await inviteExpertList(route.query.id) | |||
console.log(res.data) | |||
inviteExpertListData.value = res.data | |||
}, | |||
// 查看规则 | |||
ruleDialogData = reactive({ | |||
visible: false, | |||
data: [] | |||
}), | |||
viewRule = (id) => { | |||
ruleDialogData.visible = true | |||
ruleDialogData.data = inviteRuleDetail.value.randomRules.find(i => i.id === id) | |||
}, | |||
// 取消会议 | |||
cancelMeeting = () => { | |||
proxy.$messageBox | |||
.confirm('确认取消该会议吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await meetingCancel({ meetingId: route.query.id * 1 }) | |||
proxy.$message.success('取消会议成功!') | |||
onLoad() | |||
}) | |||
}, | |||
// 释放专家 | |||
releaseExpert = () => { | |||
proxy.$messageBox | |||
.confirm('确认释放专家吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await expertRelease({ meetingId: route.query.id * 1 }) | |||
proxy.$message.success('释放专家成功!') | |||
onLoad() | |||
}) | |||
}, | |||
// 1重发短信、2、3确认召开会议 | |||
reText = (type) => { | |||
let text = `${type === 1 ? '确认重发短信' : '确认召开会议'}` | |||
if (type === 3) { | |||
const data = inviteExpertListData.value.inviteStatistics?.filter(i => i.inviteCnt > i.agreeCnt).map(i => '规则' + (inviteRuleDetail.value?.randomRules?.findIndex(j => j.id === i.ruleId) + 1)).join('、') | |||
if (data) { | |||
text = `${data}人数不够,确认召开会议` | |||
} | |||
} | |||
proxy.$messageBox | |||
.confirm(`${text}吗?`, '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await confirmedRoster({ meetingId: route.query.id * 1 }) | |||
proxy.$message.success('操作成功!') | |||
onLoad() | |||
}) | |||
}, | |||
// 指定抽取-是否所有专家已参会或是不参会 | |||
IsAllExpertAttend = () => { | |||
if (inviteExpertListData.value.inviteExpertList.filter(i => !i.status && i.inviteType !== 1)?.length) { | |||
return false | |||
} | |||
return true | |||
}, | |||
// 终止抽取 | |||
stopInvites = () => { | |||
proxy.$messageBox | |||
.confirm('确认终止抽取吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await stopInvite(route.query.id * 1) | |||
proxy.$message.success('终止抽取成功!') | |||
onLoad() | |||
}) | |||
}, | |||
// 参会、不参会 | |||
confirmExpert = (data, agreed) => { | |||
proxy.$messageBox | |||
.confirm(`确认${agreed ? '参会' : '不参会'}吗?`, '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await expertConfirm({ | |||
agreed, | |||
expertMeetingId: data.expertMeetingId, | |||
meetingId: route.query.id * 1 | |||
}) | |||
onLoad() | |||
}) | |||
}, | |||
// 指定抽取-移除 | |||
removeExpert = async (row) => { | |||
await expertRemove({ expertMeetingId: row.expertMeetingId, meetingId: row.meetingId }) | |||
proxy.$message.success('移除成功!') | |||
onLoad() | |||
}, | |||
// 设置组长 | |||
tableHeadListRef = ref(), | |||
headManData = ref(), | |||
radioChange = (val) => { | |||
headManData.value = val | |||
}, | |||
showHeadManDialog = async () => { | |||
dialogVisible.value = true | |||
await nextTick() // 必须 | |||
tableHeadListRef.value.setRadio(inviteExpertListData.value?.inviteExpertList?.find(i => i.isHeadman)?.expertId || '') | |||
}, | |||
submitUpHeadman = async () => { | |||
dialogVisible.value = false | |||
await setUpHeadman({ | |||
agreed: true, | |||
expertMeetingId: headManData.value.expertMeetingId, | |||
meetingId: route.query.id * 1 | |||
}) | |||
proxy.$message.success('设置组长成功!') | |||
onLoad() | |||
}, | |||
// 指定专家-补充 | |||
expertDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
regionTree = ref([]), | |||
showExpertDialog = () => { | |||
expertDialogData.visible = true | |||
}, | |||
getExpertData = async (row) => { | |||
await batchAppoint({ | |||
expertIdList: row.map(i => i.userId), | |||
meetingId: route.query.id * 1 | |||
}) | |||
expertDialogData.visible = false | |||
proxy.$message.success('添加成功!') | |||
onLoad() | |||
}, | |||
// 转为指定抽取 | |||
toAppointInvite = async () => { | |||
await convertToAppoint({ meetingId: route.query.id * 1 }) | |||
proxy.$message.success('转为指定抽取成功!') | |||
onLoad() | |||
}, | |||
// 刷新 | |||
reloadLoaing = ref(false), | |||
onLoad = async (flag) => { | |||
reloadLoaing.value = !flag && true | |||
await getDetail() | |||
await getInviteExpertList() | |||
reloadLoaing.value = false | |||
}, | |||
// 随机邀请人数是否足够 | |||
getIsEnough = () => { | |||
if (inviteExpertListData.value.inviteStatistics.filter(i => i.agreeCnt !== i.inviteCnt)?.length) { | |||
return true | |||
} | |||
return false | |||
}, | |||
// 续抽 | |||
continueInvites = () => { | |||
proxy.$messageBox | |||
.confirm('续抽后,将重新通知已拒绝参会的专家们,确定继续吗?', '提示!', { | |||
type: 'warning' | |||
}) | |||
.then(async () => { | |||
await continueInvite({ meetingId: route.query.id * 1 }) | |||
proxy.$message.success('续抽成功!') | |||
onLoad() | |||
}) | |||
}, | |||
// 查看评审意见详情 | |||
// 所有意见-抽屉 | |||
drawerVisible = ref(false), | |||
templatesData = ref([]), // 模板数据 | |||
memberOpinions = ref([]), // 所有意见 | |||
showReviewDetail = async (data) => { | |||
const res = await listReview({ projectId: data.projectId, meetingId: route.query.id }) | |||
const res1 = await templatesById({ templateIds: res.data.map(i => i.templateId).join(',') }) | |||
templatesData.value = res1.data | |||
memberOpinions.value = res.data && res.data.map(i => { | |||
return { | |||
...i, | |||
reviewTemplateOptions: i.reviewTemplateOptions && i.reviewTemplateOptions.map(temp => { | |||
const data = templatesData.value.find(j => i.templateId === j.templateId).templates | |||
return { | |||
...temp, | |||
title: data.find(r => r.serialNo === temp.questionSerialNo)?.title, | |||
optionsValue: data.find(r => r.serialNo === temp.questionSerialNo)?.options.filter(j => temp.optionSerialNo.includes(j.serialNo)).map(j => j.option).join('、') | |||
} | |||
}) || [] | |||
} | |||
}) || [] | |||
drawerVisible.value = true | |||
}, | |||
tableName = { | |||
1: '劳务费发放审批单', | |||
2: '专家费用单', | |||
3: '专家抽取表', | |||
4: '项目评审单' | |||
}, | |||
handleCommand = async (command) => { | |||
const res = await exportTable(command, route.query.id) | |||
let suffix = 'docx' | |||
if (res.type === 'application/zip') { | |||
suffix = 'zip' | |||
} | |||
const url = URL.createObjectURL(res) | |||
const link = document.createElement('a') | |||
link.style.display = 'none' | |||
link.href = url | |||
link.download = `${tableName[command]}.${suffix}` | |||
document.body.appendChild(link) | |||
link.click() | |||
document.body.removeChild(link) | |||
window.URL.revokeObjectURL(url) | |||
}, | |||
// 请假 | |||
leaveDialogData = reactive({ | |||
visible: false, | |||
data: undefined | |||
}), | |||
leave = (row) => { | |||
leaveDialogData.visible = true | |||
leaveDialogData.data = { | |||
expertId: row.expertId, | |||
meetingId: route.query.id | |||
} | |||
}, | |||
closeLeaveDialog = (flag) => { | |||
leaveDialogData.visible = false | |||
flag && getInviteExpertList() | |||
} | |||
onMounted(async () => { | |||
getDetail() | |||
getInviteExpertList() | |||
const res = await districtList() | |||
regionTree.value.push(res.data) | |||
}) | |||
</script> | |||
<template> | |||
<el-card class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>会议信息</span> | |||
</div> | |||
</template> | |||
<el-descriptions | |||
title="" | |||
:column="2" | |||
border | |||
> | |||
<el-descriptions-item label="会议名称"> | |||
{{ basicInfo.meetingName }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="评审类型"> | |||
{{ meetingTypeOptions[basicInfo.meetingType] }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="评审项目" | |||
:span="2" | |||
> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:pagination="false" | |||
style="max-height: 200px;width:95%" | |||
:data="basicInfo.projects" | |||
> | |||
<template #action="{ scope }"> | |||
<a v-if="scope.row.reviewResult" @click="showReviewDetail(scope.row)">详情</a> | |||
</template> | |||
</table-list> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="评审时间"> | |||
{{ basicInfo.startTime }}~{{ basicInfo.endTime }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="评审耗时" | |||
> | |||
{{ basicInfo.meetingUsageTime===1?'半天':'一天' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="评审地点"> | |||
{{ basicInfo.meetingAddress }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="评委到场时间"> | |||
{{ basicInfo.judgesAttendanceTime }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="联系人"> | |||
{{ basicInfo.connecter }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="联系方式"> | |||
{{ basicInfo.contact }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="会议状态"> | |||
<span :class="`dot mr-4 ${basicInfo.status === 1 ? 'bg-success' : 'bg-danger'}`"></span> | |||
<span :class="`${basicInfo.status === 1 ? 'text-success' : 'text-danger'}`">{{ basicInfo.status===1?'正常': '已取消' }}</span> | |||
</el-descriptions-item> | |||
<el-descriptions-item label="抽取方式"> | |||
{{ basicInfo.inviteType === 1 ? '随机抽取' : basicInfo.inviteType === 2?'指定抽取':'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="抽取状态"> | |||
{{ basicInfo.invitedStopped?'抽取结束':!basicInfo.inviteStatus ? '抽取中' :'抽取结束' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家名单确认状态"> | |||
{{ basicInfo.confirmedRoster? '已确认' : '未确认' }} | |||
</el-descriptions-item> | |||
<template v-if="basicInfo.inviteType === 1"> | |||
<el-descriptions-item label="部门、条线回避规则"> | |||
{{ inviteRuleDetail.avoidInfo?.avoidType===2?'回避条线':inviteRuleDetail.avoidInfo?.avoidType===1?'回避单位':inviteRuleDetail.avoidInfo?.avoidType===3?'不回避':'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item | |||
label="回避单位" | |||
> {{ inviteRuleDetail.avoidInfo?.avoidUnits?.map(i=>i).join('、')||"-" }}</el-descriptions-item> | |||
<el-descriptions-item label="回避专家"> | |||
{{ inviteRuleDetail.avoidInfo?.experts?.map(i=>i.name).join('、')||"-" }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="回避条线"> | |||
{{ inviteRuleDetail.avoidInfo?.avoidOrgs?.map(i=>i).join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="回避次数"> | |||
{{ inviteRuleDetail.avoidInfo?.weekInviteCount||'-' }} | |||
</el-descriptions-item> | |||
</template> | |||
<el-descriptions-item | |||
v-else | |||
label="邀请理由" | |||
:span="2" | |||
>{{ basicInfo?.inviteRule?.appointRule?.inviteDesc||'-' }}</el-descriptions-item> | |||
</el-descriptions> | |||
</el-card> | |||
<!-- 随机抽取--> | |||
<template v-if="basicInfo.inviteType === 1"> | |||
<el-card class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>抽取情况</span> | |||
<div> | |||
<el-button | |||
v-if="basicInfo.invitedStopped||basicInfo.inviteStatus" | |||
class="button" | |||
type="primary" | |||
plain | |||
@click="toAppointInvite" | |||
>转为指定抽取</el-button> | |||
<el-button | |||
v-if="basicInfo.status===1&&(basicInfo.invitedStopped||basicInfo.inviteStatus)&&getIsEnough()" | |||
class="button" | |||
type="primary" | |||
plain | |||
@click="continueInvites" | |||
>续抽</el-button> | |||
<!-- <el-button--> | |||
<!-- v-if="basicInfo.status===1&&(basicInfo.invitedStopped||basicInfo.inviteStatus)&&!basicInfo.confirmedRoster"--> | |||
<!-- class="button"--> | |||
<!-- type="primary"--> | |||
<!-- @click="reText(3)"--> | |||
<!-- >确认召开会议</el-button>--> | |||
</div> | |||
</div> | |||
</template> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column2" | |||
:pagination="false" | |||
:data="inviteExpertListData.inviteStatistics" | |||
> | |||
<template #agreeCnt="{ scope }"> | |||
<div class="flex items-center"> | |||
<span>{{ scope.row.agreeCnt }}</span> | |||
<el-icon | |||
v-if="scope.row.agreeCnt===scope.row.inviteCnt" | |||
class="ml-8" | |||
style="color: #4ecb74" | |||
><Select /></el-icon> | |||
</div> | |||
</template> | |||
<template | |||
#ruleId="{scope}" | |||
> | |||
<a @click="viewRule(scope.row.ruleId)">规则{{ inviteRuleDetail?.randomRules?.findIndex(i => i.id === scope.row.ruleId)+1||'' }}</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<el-card class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>通知情况</span> | |||
<el-button | |||
v-if="!basicInfo.invitedStopped" | |||
class="button" | |||
type="danger" | |||
plain | |||
@click="stopInvites" | |||
>终止抽取</el-button> | |||
</div> | |||
</template> | |||
<el-alert | |||
type="warning" | |||
:description="`共有${inviteExpertListData.inviteExpertList?.length}位专家,已通知${inviteExpertListData.inviteExpertList?.filter(i=>i.noticeStatus==='已通知')?.length}位,尚未通知${inviteExpertListData.inviteExpertList?.filter(i=>i.noticeStatus==='未通知')?.length}位。`" | |||
show-icon | |||
:closable="false" | |||
/> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column3" | |||
:pagination="false" | |||
class="mt-15" | |||
:data="inviteExpertListData.inviteExpertList" | |||
> | |||
<template #contact="{scope}"> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="scope.row.contact" | |||
> | |||
<span>{{ scope.row.contact?.replace(/(\d{3})\d*(\d{4})/, '$1****$2') }}</span> | |||
</el-tooltip> | |||
</template> | |||
<template #leaved="{scope}"> | |||
<a v-if="!scope.row.leaved&&scope.row.confirmedAttend" @click="leave(scope.row)">请假</a> | |||
<span v-else-if="scope.row.leaved">已请假</span> | |||
<span v-else>-</span> | |||
</template> | |||
<template #ruleId="{ scope }"> | |||
<a @click="viewRule(scope.row.ruleId)">规则{{ inviteRuleDetail?.randomRules?.findIndex(i => i.id === scope.row.ruleId)+1||'' }}</a> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
</template> | |||
<!-- 指定抽取--> | |||
<el-card v-else class="box-card"> | |||
<template #header> | |||
<div class="card-header"> | |||
<span>通知情况</span> | |||
<span v-if="basicInfo.status===1"> | |||
<el-button | |||
v-if="!isExpertConfirmed" | |||
class="button" | |||
plain | |||
@click="showExpertDialog" | |||
>添加专家</el-button> | |||
<el-button | |||
v-if="!basicInfo.confirmedRoster&&IsAllExpertAttend()" | |||
class="button" | |||
type="primary" | |||
plain | |||
@click="reText(2)" | |||
>确认召开会议</el-button> | |||
</span> | |||
</div> | |||
</template> | |||
<el-alert | |||
type="warning" | |||
:description="`共有${inviteExpertListData.inviteExpertList?.length}位专家,确认参会${inviteExpertListData.inviteExpertList?.filter(i=>i.status===3)?.length}位。`" | |||
show-icon | |||
:closable="false" | |||
/> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column5" | |||
:pagination="false" | |||
class="mt-15" | |||
:data="inviteExpertListData.inviteExpertList" | |||
> | |||
<template #mobile="{scope}"> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="scope.row.mobile" | |||
> | |||
<span>{{ scope.row.mobile?.replace(/(\d{3})\d*(\d{4})/, '$1****$2') }}</span> | |||
</el-tooltip> | |||
</template> | |||
<template #action="{ scope }"> | |||
<div v-if="!scope.row.status&&scope.row.inviteType!==1"> | |||
<a @click="confirmExpert(scope.row,true)">参会</a> | |||
<a @click="confirmExpert(scope.row,false)">不参会</a> | |||
<a class="text-danger" @click="removeExpert(scope.row)">移除</a> | |||
</div> | |||
<div v-else> | |||
<span>-</span> | |||
</div> | |||
</template> | |||
</table-list> | |||
</el-card> | |||
<div class="flex h-60 items-center justify-between bg-white "> | |||
<div class="flex items-center ml-20"> | |||
<el-button plain @click="router.go(-1)">返回</el-button> | |||
<el-button plain :loading="reloadLoaing" @click="onLoad(false)">刷新</el-button> | |||
<el-button | |||
v-if="basicInfo.status===1" | |||
type="danger" | |||
plain | |||
@click="cancelMeeting" | |||
>取消会议</el-button> | |||
<el-button | |||
v-if="basicInfo.status===1&&basicInfo.inviteStatus" | |||
type="danger" | |||
plain | |||
@click="releaseExpert" | |||
>释放专家</el-button> | |||
</div> | |||
<div class="flex items-center mr-20"> | |||
<el-button | |||
v-if="basicInfo.status===1&&basicInfo.confirmedRoster" | |||
plain | |||
type="primary" | |||
@click="showHeadManDialog" | |||
>设置专家组长</el-button> | |||
<el-button | |||
v-if="basicInfo.status===1&&basicInfo.confirmedRoster" | |||
plain | |||
type="primary" | |||
@click="reText(1)" | |||
>重发短信</el-button> | |||
<el-dropdown v-if="basicInfo.status===1&&basicInfo.confirmedRoster" class="ml-12" @command="handleCommand"> | |||
<el-button type="primary" plain> | |||
导出<el-icon class="el-icon--right"><arrow-down /></el-icon> | |||
</el-button> | |||
<template #dropdown> | |||
<el-dropdown-menu> | |||
<el-dropdown-item command="1">劳务费发放审批单</el-dropdown-item> | |||
<el-dropdown-item command="2">专家费用单</el-dropdown-item> | |||
<el-dropdown-item command="3">专家抽取表</el-dropdown-item> | |||
<el-dropdown-item command="4">项目评审单</el-dropdown-item> | |||
</el-dropdown-menu> | |||
</template> | |||
</el-dropdown> | |||
</div> | |||
</div> | |||
<el-dialog | |||
v-model="dialogVisible" | |||
title="设置专家组长" | |||
width="50%" | |||
> | |||
<table-list | |||
ref="tableHeadListRef" | |||
:column="column4" | |||
:pagination="false" | |||
class="mt-15" | |||
:data="inviteExpertListData.inviteExpertList.filter(i=>i.status===3)" | |||
@radio-change="radioChange" | |||
> | |||
<template #mobile="{scope}"> | |||
<el-tooltip | |||
class="box-item" | |||
effect="dark" | |||
:content="scope.row.mobile" | |||
> | |||
<span>{{ scope.row.mobile?.replace(/(\d{3})\d*(\d{4})/, '$1****$2') }}</span> | |||
</el-tooltip> | |||
</template> | |||
</table-list> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button @click="dialogVisible = false">关闭</el-button> | |||
<el-button | |||
type="primary" | |||
@click="submitUpHeadman" | |||
> | |||
提交 | |||
</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
<el-dialog | |||
v-model="ruleDialogData.visible" | |||
title="规则" | |||
width="70%" | |||
> | |||
<el-descriptions :column="3"> | |||
<el-descriptions-item label="内外围:"> | |||
{{ ruleDialogData.data?.expertDicts?.find(i=>i.expertDict==='expert_type')?.dictCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="履职意向:"> | |||
{{ ruleDialogData.data?.intentionRegions?.map(i=>i.regionName).join('-') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家来源:"> | |||
{{ ruleDialogData.data?.expertTags?.find(i=>i.expertTag==='expert_source')?.tagCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="职称级别:"> | |||
{{ ruleDialogData.data?.expertDicts?.find(i=>i.expertDict==='title_level')?.dictCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="擅长方向:"> | |||
{{ ruleDialogData.data?.expertTags?.find(i=>i.expertTag==='good_at')?.tagCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="技术专长:"> | |||
{{ ruleDialogData.data?.expertTags?.find(i=>i.expertTag==='technical_expertise')?.tagCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="行业领域:"> | |||
{{ ruleDialogData.data?.expertTags?.find(i=>i.expertTag==='industry_sector')?.tagCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="其他标签:"> | |||
{{ ruleDialogData.data?.expertTags?.find(i=>i.expertTag==='other')?.tagCodes.join('、')||'-' }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="专家级别:"> | |||
{{ ruleDialogData.data?.expertRegions?.map(i=>i.regionName).join('-') }} | |||
</el-descriptions-item> | |||
<el-descriptions-item label="邀请数量:"> | |||
{{ ruleDialogData.data.count }} | |||
</el-descriptions-item> | |||
</el-descriptions> | |||
</el-dialog> | |||
<add-expert-dialog | |||
:visible="expertDialogData.visible" | |||
:data="expertDialogData.data" | |||
:region-tree="regionTree" | |||
@get-user-data="getExpertData" | |||
@close="expertDialogData.visible = false" | |||
/> | |||
<el-drawer | |||
v-model="drawerVisible" | |||
title="评审详情" | |||
style="position: absolute" | |||
direction="rtl" | |||
size="70%" | |||
:modal="false" | |||
:append-to-body="false" | |||
modal-class="myDrawerModal" | |||
> | |||
<member-opinion :member-opinions="memberOpinions" /> | |||
</el-drawer> | |||
<leave-dialog | |||
:visible="leaveDialogData.visible" | |||
:data="leaveDialogData.data" | |||
title="填写请假原因" | |||
@close="closeLeaveDialog" | |||
/> | |||
</template> | |||
<style lang='less' scoped> | |||
.box-card{ | |||
margin-bottom: 20px; | |||
.card-header { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: center; | |||
} | |||
} | |||
</style> | |||
@@ -0,0 +1,251 @@ | |||
<script setup name='reviewTemplateConfig'> | |||
import { reactive, ref, onMounted, getCurrentInstance } from 'vue' | |||
import ElTree from '@/components/elTree/index.vue' | |||
import { template, save } from '@/http/apis/expertManage/reviewTemplateConfig' | |||
import { getIsShowRegionTree, getTreeParams } from '@/utils/getIsShowRegionTree' | |||
const { proxy } = getCurrentInstance(), | |||
searchForm = reactive({ | |||
regionCode: undefined, | |||
templateType: '1' | |||
}), | |||
// 地区 | |||
getTree = (data) => { | |||
searchForm.regionCode = data.regionLevel === 3 ? data.regionCode : undefined | |||
getTemplate() | |||
}, | |||
// 切换模板类型 | |||
handleClickTab = ({ props }) => { | |||
searchForm.templateType = props.name | |||
getTemplate() | |||
}, | |||
// 获取模板 | |||
getTemplate = async () => { | |||
try { | |||
const res = await template({ ...searchForm, templateType: searchForm.templateType * 1 }) | |||
formData.value = res.data || { templates: [] } | |||
} catch (e) { | |||
formData.value = { templates: [] } | |||
} | |||
}, | |||
// 模板列表 | |||
column = [ | |||
{ | |||
label: '序号', | |||
type: 'index', | |||
width: '60' | |||
}, | |||
{ | |||
label: '意见标题', | |||
slot: 'title' | |||
}, | |||
{ | |||
label: '选项类型', | |||
slot: 'optionType', | |||
width: 120 | |||
}, | |||
{ | |||
label: '包含的选项', | |||
slot: 'options' | |||
}, | |||
{ | |||
label: '操作', | |||
slot: 'action', | |||
width: 60 | |||
} | |||
], | |||
formData = ref({ | |||
templates: [] | |||
}), | |||
formRef = ref(), | |||
// 增加问题 | |||
addTemp = () => { | |||
formData.value.templates.push({ title: '', optionType: undefined, options: [{}] }) | |||
}, | |||
// 删除 | |||
removeTemp = (index) => { | |||
formData.value.templates.splice(index, 1) | |||
}, | |||
// 增加选项 | |||
addOptions = (index) => { | |||
formData.value.templates[index].options.push({ option: '' }) | |||
}, | |||
// 删除选项 | |||
removeOption = (index, key) => { | |||
formData.value.templates[index].options.splice(key, 1) | |||
}, | |||
loading = ref(false), | |||
submit = async formEl => { | |||
if (!formEl) { | |||
return | |||
} | |||
await formEl.validate(async valid => { | |||
if (valid) { | |||
const postData = getData() | |||
loading.value = true | |||
try { | |||
await save(postData) | |||
proxy.$message.success('提交成功!') | |||
loading.value = false | |||
} catch (e) { | |||
loading.value = false | |||
} | |||
} | |||
}) | |||
}, | |||
// 插入序号 | |||
getData = () => { | |||
return { | |||
regionCode: searchForm.regionCode, | |||
templateType: searchForm.templateType * 1, | |||
templates: formData.value?.templates.map((item, index) => { | |||
return { | |||
...item, | |||
serialNo: index, | |||
options: item.options.map((option, key) => { | |||
return { | |||
...option, | |||
serialNo: key | |||
} | |||
}) | |||
} | |||
}) || [] | |||
} | |||
} | |||
onMounted(() => { | |||
if (!getIsShowRegionTree(['SUPER_ADMIN', 'REGION_MANAGER', 'EXPERT_ADMIN'])) getTemplate() | |||
}) | |||
</script> | |||
<template> | |||
<el-row :gutter="16"> | |||
<el-col | |||
v-if="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])" | |||
style="padding-right: 16px" | |||
:span="4" | |||
> | |||
<elTree :params="getTreeParams({'SUPER_ADMIN':false,'REGION_MANAGER':false,'EXPERT_ADMIN':false})" @get-tree="getTree" /> | |||
</el-col> | |||
<el-col :span="getIsShowRegionTree(['SUPER_ADMIN','REGION_MANAGER','EXPERT_ADMIN'])?20:24"> | |||
<el-card class="w-full tab-card footerCard"> | |||
<template #header> | |||
<el-tabs | |||
v-model="searchForm.templateType" | |||
class="demo-tabs" | |||
@tab-click="handleClickTab" | |||
> | |||
<el-tab-pane | |||
label="初步方案评审模版" | |||
name="1" | |||
/> | |||
<el-tab-pane | |||
label="建设方案评审模版" | |||
name="2" | |||
/> | |||
<el-tab-pane | |||
label="验收评审模版" | |||
name="3" | |||
/> | |||
<el-tab-pane | |||
label="部门联审模版" | |||
name="4" | |||
/> | |||
<el-tab-pane | |||
label="公平性审查" | |||
name="5" | |||
/> | |||
</el-tabs> | |||
</template> | |||
<el-form ref="formRef" :model="formData"> | |||
<table-list | |||
ref="tableListRef" | |||
:column="column" | |||
:data="formData?.templates||[]" | |||
:pagination="false" | |||
> | |||
<template #title="{scope}"> | |||
<el-form-item | |||
v-if="formData.templates[scope.$index]" | |||
:prop="`templates[${scope.$index}].title`" | |||
:rules="[ | |||
{ | |||
required: true, | |||
message: '请输入', | |||
} | |||
]" | |||
> | |||
<el-input v-model="formData.templates[scope.$index].title" /> | |||
</el-form-item> | |||
</template> | |||
<template #optionType="{scope}"> | |||
<el-form-item | |||
v-if="formData.templates[scope.$index]" | |||
:prop="`templates[${scope.$index}].optionType`" | |||
:rules="[ | |||
{ | |||
required: true, | |||
message: '请选择', | |||
} | |||
]" | |||
> | |||
<el-select v-model="formData.templates[scope.$index].optionType"> | |||
<el-option label="单选" :value="1" /> | |||
<el-option label="多选" :value="2" /> | |||
</el-select> | |||
</el-form-item> | |||
</template> | |||
<template #options="{scope}"> | |||
<template v-if="formData.templates[scope.$index]"> | |||
<div | |||
v-for="(item,key) in formData.templates[scope.$index].options" | |||
:key="key" | |||
class="flex items-center mb-8" | |||
> | |||
<el-form-item | |||
class="flex-1" | |||
style="margin-bottom: 0;" | |||
:prop="`templates[${scope.$index}].options[${key}].option`" | |||
:rules="[ | |||
{ | |||
required: true, | |||
message: '请输入', | |||
} | |||
]" | |||
> | |||
<el-input v-model="formData.templates[scope.$index].options[key].option" /> | |||
</el-form-item> | |||
<svg-icon name="deleteIcon" class="ml-4 cursor-pointer text-24" @click="removeOption(scope.$index,key)" /> | |||
</div> | |||
<el-button | |||
type="primary" | |||
size="small" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="addOptions(scope.$index)" | |||
>添加选项</el-button> | |||
</template> | |||
</template> | |||
<template #action="{scope}"> | |||
<a v-if="formData.templates[scope.$index]" class="text-danger" @click="removeTemp(scope.$index)">移除</a> | |||
</template> | |||
</table-list> | |||
</el-form> | |||
<el-button | |||
type="primary" | |||
class="w-full" | |||
plain | |||
icon="Plus" | |||
@click="addTemp" | |||
>添加意见类型</el-button> | |||
<div class="footer"> | |||
<el-button type="primary" :loading="loading" @click="submit(formRef)"> | |||
提交 | |||
</el-button> | |||
</div> | |||
</el-card> | |||
</el-col> | |||
</el-row> | |||
</template> | |||
<style lang='less' scoped> </style> |
@@ -0,0 +1,108 @@ | |||
<script name="leaveDialog" setup> | |||
import { watch } from 'vue' | |||
import { useRouter } from 'vue-router' | |||
const | |||
props = defineProps({ | |||
visible: { | |||
type: Boolean, | |||
default: false, | |||
required: true | |||
}, | |||
initData: { | |||
type: Array, | |||
default: () => { | |||
return [ | |||
{ | |||
name: '配置单位流程', | |||
remark: '用于项目审核,请先配置单位默认流程。', | |||
path: 'systemManage/unitSet/flowPathConfiguration' | |||
}, | |||
// { | |||
// name: '配置财政编码', | |||
// remark: '用于生成项目唯一编码。', | |||
// path: 'unitSet/fiscalCodeSet' | |||
// }, | |||
{ | |||
name: '配置印章编码', | |||
remark: '用于电子签章。', | |||
path: 'systemManage/unitSet/fiscalCodeSet' | |||
}] | |||
} | |||
} | |||
}), | |||
router = useRouter(), | |||
emits = defineEmits(['close']), | |||
getUrlParams = (url) => { | |||
// 通过 ? 分割获取后面的参数字符串 | |||
const urlStr = url?.split('?')[1] || '' | |||
if (!urlStr) { | |||
return {} | |||
} | |||
// 创建空对象存储参数 | |||
const obj = {} | |||
// 再通过 & 将每一个参数单独分割出来 | |||
const paramsArr = urlStr.split('&') | |||
for (let i = 0, len = paramsArr.length; i < len; i++) { | |||
// 再通过 = 将每一个参数分割为 key:value 的形式 | |||
const arr = paramsArr[i].split('=') | |||
obj[arr[0]] = arr[1] | |||
} | |||
return obj | |||
}, | |||
view = (path) => { | |||
const routeUrl = router.resolve({ | |||
path: `/systemManage/${path}`, | |||
query: getUrlParams(path) | |||
}) | |||
window.open(routeUrl.href, '_blank') | |||
} | |||
watch( | |||
() => props.visible, | |||
async val => { | |||
if (val) { | |||
console.log(val) | |||
} | |||
} | |||
) | |||
</script> | |||
<template> | |||
<el-dialog | |||
:model-value="visible" | |||
title="初始化引导" | |||
width="600px" | |||
destroy-on-close | |||
@close="emits('close')" | |||
> | |||
<div> | |||
<el-alert | |||
title="为保证正常申报项目,请完成以下配置工作:" | |||
:closable="false" | |||
type="info" | |||
show-icon | |||
class="primary-alert" | |||
/> | |||
</div> | |||
<div class="p-16"> | |||
<el-steps | |||
direction="vertical" | |||
:space="100" | |||
:active="-1" | |||
> | |||
<el-step | |||
v-for="(item, index) in initData.filter(i=>i.name!=='配置财政编码')" | |||
:key="index" | |||
:title="item.name" | |||
:status="item.isFinish?'success':'wait'" | |||
> | |||
<template #description> | |||
<p>{{ item.remark }}</p> | |||
<el-button link type="primary" @click="view(item.path)">前往配置</el-button> | |||
</template> | |||
</el-step> | |||
</el-steps> | |||
</div> | |||
</el-dialog> | |||
</template> | |||