From 2aac44c550cdb242225a2a18f7238fb41c618779 Mon Sep 17 00:00:00 2001 From: zhouwx <1175765986@qq.com> Date: 星期一, 06 一月 2025 09:21:57 +0800 Subject: [PATCH] bug修改 --- src/views/safetyReview/testManage/process.vue | 1149 ++++++++ src/layout/components/Sidebar/menu.js | 46 src/views/safetyReview/testManage/components/employNoticeRecord.vue | 206 + src/views/safetyReview/testManage/components/evaluatePlan.vue | 521 +++ src/views/safetyReview/userManage/expertUsers/components/projectDialog.vue | 8 src/views/safetyReview/testManage/index.vue | 748 +++++ src/layout/components/Sidebar/Logo.vue | 2 src/views/safetyReview/testManage/components/projectArchive.vue | 390 ++ src/views/safetyReview/testManage/components/techLeaderReview.vue | 267 ++ src/views/safetyReview/testManage/components/mapLocation.vue | 162 + src/views/safetyReview/testManage/components/processCtrlReview.vue | 364 ++ src/views/safetyReview/testManage/components/riskAnalysis.vue | 474 +++ src/views/safetyReview/testManage/components/deviceDialog.vue | 140 + src/views/safetyReview/testManage/components/rateConclusion.vue | 311 ++ src/views/safetyReview/projectManage/components/employNoticeRecord.vue | 126 src/views/safetyReview/testManage/components/innerReview.vue | 276 ++ src/views/safetyReview/testManage/components/signConfirm.vue | 184 + src/views/safetyReview/testManage/components/confirmEndDialog.vue | 233 + src/router/index.js | 46 src/views/safetyReview/userManage/institutionUsers/index.vue | 1 src/utils/request.js | 11 .env.development | 2 src/views/safetyReview/testManage/components/uploadReviewRcd.vue | 241 + src/views/safetyReview/testManage/components/contractManage.vue | 137 + src/views/safetyReview/testManage/components/worksDialog.vue | 205 + .env.production | 2 src/views/safetyReview/testManage/components/evaluateTaskNotice.vue | 197 + src/views/safetyReview/testManage/components/expertsList.vue | 344 ++ src/views/safetyReview/projectManage/index.vue | 90 src/views/safetyReview/testManage/components/siteCheckRcd.vue | 693 +++++ src/views/safetyReview/testManage/components/confirmEnd.vue | 252 + 31 files changed, 7,809 insertions(+), 19 deletions(-) diff --git a/.env.development b/.env.development index 9d8beb7..13276f3 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,5 @@ # 页面标题 -VITE_APP_TITLE = 智慧安评 +VITE_APP_TITLE = 新疆智慧安评 # 开发环境配置 VITE_APP_ENV = 'development' diff --git a/.env.production b/.env.production index e42547e..3cc0239 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,5 @@ # 页面标题 -VITE_APP_TITLE = 智慧安评 +VITE_APP_TITLE = 新疆智慧安评 # 生产环境配置 VITE_APP_ENV = 'production' diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue index f8239d1..d213725 100644 --- a/src/layout/components/Sidebar/Logo.vue +++ b/src/layout/components/Sidebar/Logo.vue @@ -63,7 +63,7 @@ width: 32px; height: 32px; vertical-align: middle; - margin-right: 8px; + margin-right: 0px; } & .sidebar-title { diff --git a/src/layout/components/Sidebar/menu.js b/src/layout/components/Sidebar/menu.js index e5107c1..f5c83fb 100644 --- a/src/layout/components/Sidebar/menu.js +++ b/src/layout/components/Sidebar/menu.js @@ -1,10 +1,27 @@ import Layout from '@/layout' const menu = { adminMenu: [ + // { + // path: '/project', + // name: 'Project', + // meta: { title: '项目管理',icon: 'form',affix: true } + // }, { - path: '/project', - name: 'Project', - meta: { title: '项目管理',icon: 'form',affix: true } + path: '/projectManage', + redirect: '/projectManage/project', + meta: { title: '项目管理',icon: 'clipboard'}, + children: [ + { + path: 'project', + name: 'project', + meta: { title: '安全评价',icon: 'monitor'} + }, + { + path: 'test', + name: 'test', + meta: { title: '检验检测',icon: 'list'} + }, + ] }, { path: '/projectSupplement', @@ -101,10 +118,27 @@ ], agencyMenu: [ + // { + // path: '/project', + // name: 'Project', + // meta: { title: '项目管理',icon: 'form',affix: true } + // }, { - path: '/project', - name: 'Project', - meta: { title: '项目管理',icon: 'form',affix: true } + path: '/projectManage', + redirect: '/projectManage/project', + meta: { title: '项目管理',icon: 'clipboard'}, + children: [ + { + path: 'project', + name: 'project', + meta: { title: '安全评价',icon: 'monitor'} + }, + { + path: 'test', + name: 'test', + meta: { title: '检验检测',icon: 'list'} + }, + ] }, { path: '/projectSupplement', diff --git a/src/router/index.js b/src/router/index.js index 49e47c5..7a208d4 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -142,19 +142,40 @@ } ] }, + // { + // path: '/project', + // component: Layout, + // redirect: '/project', + // children: [ + // { + // path: '/project', + // component: () => import('@/views/safetyReview/projectManage/index.vue'), + // name: 'Project', + // meta: { title: '项目管理',icon: 'form', affix: true } + // } + // ] + // }, { - path: '/project', + path: '/projectManage', component: Layout, - redirect: '/project', + redirect: '/projectManage/project', + meta: { title: '项目管理'}, children: [ { - path: '/project', + path: 'project', component: () => import('@/views/safetyReview/projectManage/index.vue'), name: 'Project', - meta: { title: '项目管理',icon: 'form', affix: true } - } + meta: { title: '安全评价',icon: 'form', affix: true } + }, + { + path: 'test', + component: () => import('@/views/safetyReview/testManage/index.vue'), + name: 'Test', + meta: { title: '检验检测',icon: 'form', affix: true } + }, ] }, + { path: '/projectSupplement', component: Layout, @@ -177,7 +198,20 @@ path: '/process', component: () => import('@/views/safetyReview/projectManage/process.vue'), name: 'Process', - meta: { title: '项目信息管理'} + meta: { title: '安全评价信息管理'} + } + ] + }, + { + path: '/processTest', + component: Layout, + redirect: '/processTest', + children: [ + { + path: '/processTest', + component: () => import('@/views/safetyReview/testManage/process.vue'), + name: 'ProcessTest', + meta: { title: '检验检测信息管理'} } ] }, diff --git a/src/utils/request.js b/src/utils/request.js index 68d1bdd..b4e5100 100644 --- a/src/utils/request.js +++ b/src/utils/request.js @@ -132,6 +132,17 @@ }, error => { console.log('err' + error) + if (error.response) { + // 请求已发出,但服务器响应的状态码不在 2xx 范围内 + console.log('responseresponseresponseresponseresponseresponse') + } else if (error.request) { + // 请求已发出,但没有收到响应 + console.log('requestrequestrequestrequestrequestrequestrequest') + } else { + // 发生了一些问题导致请求不能发送到服务器 + console.log('error33333333') + } + let { message } = error; if (message == "Network Error") { message = "后端接口连接异常"; diff --git a/src/views/safetyReview/projectManage/components/employNoticeRecord.vue b/src/views/safetyReview/projectManage/components/employNoticeRecord.vue index 4a7ae99..d84f6ee 100644 --- a/src/views/safetyReview/projectManage/components/employNoticeRecord.vue +++ b/src/views/safetyReview/projectManage/components/employNoticeRecord.vue @@ -64,12 +64,31 @@ </el-table-column> </el-table> </el-form> + <el-upload + style="margin-top: 25px;width: 250px" + :disabled="projectType === 'view' || isEnd" + accept=".pdf" + :action="state.uploadUrl" + :data="{moduleType: 12,projectId: props.projectId}" + :headers="state.header" + method="post" + :limit="state.imgLimit" + :before-upload="beforeUpload" + :on-success="handleAvatarSuccess" + v-model:file-list="state.fileList" + :on-preview="handlePreview" + :on-remove="handleRemove"> + <el-button type="primary">上传从业告知书pdf</el-button> + <template #tip> + <div class="el-upload__tip">只能上传pdf类型,最多上传1份</div> + </template> + </el-upload> </div> </template> <script setup> import {defineEmits, defineProps, onMounted, reactive, ref, watchEffect} from "vue" -import {ElMessage} from "element-plus" +import {ElMessage, ElMessageBox} from "element-plus" import {Search} from '@element-plus/icons-vue' import {addWorkRecord, editWorkRecord, getWorkDetail} from "@/api/projectManage/employNoticeRcd" import {getWorks, editWorks} from "@/api/projectManage/evaPlan" @@ -77,6 +96,10 @@ const props = defineProps(['projectId']) const emit = defineEmits(["getNextStatus"]) import { useRoute } from 'vue-router' +import {getToken} from "@/utils/auth"; +import {getFiles} from "@/api/projectManage/siteCheckRcd"; +import {delAccessoryFile} from "@/api/projectManage/project"; +import axios from "axios"; const route = useRoute() const state = reactive({ formData: { @@ -92,9 +115,16 @@ rules: { timeRange: [{required: true, message: '请选择技术服务期限', trigger: 'blur'}], investigationPlanDate: [{required: true, message: '请选择计划现场勘验时间', trigger: 'blur'}] - } + }, + imgLimit: 1, + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + fileList: [] }) +const isEnd = ref('') const isAmin = ref(false) const formRef = ref() onMounted(() => { @@ -104,7 +134,9 @@ } if(props.projectId){ getWorksList(props.projectId) + getProcessFiles(props.projectId); } + isEnd.value = Cookies.get('end') }); @@ -113,12 +145,19 @@ state.formData.projectId = val state.projectId = val projectType.value = route.query.type; + isEnd.value = Cookies.get('end') // await getWorksList(val) if(type === 'detail' || type === 'edit' ){ const res = await getWorkDetail({projectId: val}) if(res.code == 200){ state.formData = JSON.parse(JSON.stringify(res.data)) state.formData.timeRange = [state.formData.serviceStartDate,state.formData.serviceEndDate] + // state.fileList = res.data.accessoryFiles.map(item => { + // return { + // ...item, + // name: item.originName, + // } + // }) }else { ElMessage.warning(res.message) } @@ -189,7 +228,90 @@ } await getWorksList(props.projectId) } +const beforeUpload = (file) => { + let fileType = file.name.substring(file.name.lastIndexOf(".") + 1); + if (fileType === 'pdf') { + } else { + ElMessage.error("文件类型必须为pdf格式") + return false + } +} +const handleAvatarSuccess = (res) => { + if(res.code === 200){ + getProcessFiles() + ElMessage({ + type: 'success', + message: '文件上传成功' + }) + }else { + state.fileList.splice(state.fileList.indexOf(uploadFile),1) + ElMessage({ + type: 'warning', + message: res.message + }) + } +} +const handleRemove = async (file, uploadFiles) => { + if (file && file.status === 'success') { + ElMessageBox.confirm( + '确定删除该附件?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(async () => { + let accessoryFileId = ""; + if (file.id) { + accessoryFileId = file.id + } else { + accessoryFileId = file.response.data.id + } + const res = await delAccessoryFile(accessoryFileId) + if (res.code == 200) { + ElMessage({ + type: 'success', + message: '文件已删除' + }) + await getProcessFiles() + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } + }) + .catch(() => { + getProcessFiles() + }) + } +} +const getProcessFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId ,moduleType: 12}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.fileList = res.data.map(i=>{ + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + }else{ + state.fileList = [] + } + }else { + ElMessage.warning(res.message) + } +} +const handlePreview = (file) => { + const url = file.url + window.open(url) +} defineExpose({ riskOpen }); diff --git a/src/views/safetyReview/projectManage/index.vue b/src/views/safetyReview/projectManage/index.vue index 6aca90d..856a82e 100644 --- a/src/views/safetyReview/projectManage/index.vue +++ b/src/views/safetyReview/projectManage/index.vue @@ -65,6 +65,15 @@ </div> </div> </div> + + <div style="margin-top: 10px;margin-bottom: 15px;margin-left: 20px;"> + <div style="font-size: 18px;font-weight: 800;color: #ed5565;display: flex"> + 当前存在未完结:安全评价项目 <div style="cursor: pointer;border-radius: 8px;padding: 0 5px" :class="{active: isActive}" @click="chooseUn" >{{search.num.safetyTotal}}</div> 个,检验检测项目 + {{search.num.safetyCheckTotal}} + 个,共 {{search.num.unFinishTotal}} 个 + </div> + </div> + <!-- 表格数据 --> <el-table v-loading="loading" :data="dataList" :border="true" ref="tableRef" :height="tableHeight" style="width: 100%;"> <el-table-column label="序号" width="80" align="center" type="index" ></el-table-column> @@ -170,6 +179,28 @@ size="large" /> </el-form-item> + <el-form-item label="机构名称" > + <el-select + v-model="search.queryParams.agencyName" + filterable + remote + @change="selectValue" + reserve-keyword + placeholder="所属机构" + remote-show-suffix + :remote-method="getCompanyList" + :loading="loadingCompany" + style="width:100%" + clearable + > + <el-option + v-for="item in companyList" + :key="item.id" + :label="item.name" + :value="item.name" + /> + </el-select> + </el-form-item> <el-form-item label="项目名称" > <el-input v-model.trim="search.queryParams.name" placeholder="请输入项目名称"></el-input> </el-form-item> @@ -232,8 +263,10 @@ import {getDict} from "@/api/login"; import {getDictList} from "@/api/backManage/evaluate"; import Cookies from "js-cookie" +import {getAllAgency} from "@/api/backManage/insitution"; const router = useRouter(); +const isActive = ref(false) const loading = ref(false); const direction = ref('rtl'); const showDrawer = ref(false); @@ -248,6 +281,7 @@ pageNum: 1, pageSize: 20, name: '', + agencyName: '', client: '', province: '', city: '', @@ -255,6 +289,8 @@ business: '', estimateType: '', phase: '', + safetyCheck: 0, + unFinish: null, params:{ lostMaterial: null } @@ -265,9 +301,14 @@ investigationTotal: 0, reviewTotal: 0, reportTotal: 0, - archiveTotal: 0 + archiveTotal: 0, + unFinishTotal: 0, + safetyCheckTotal: 0, + safetyTotal: 0 } }); +const companyList = ref([]) +const loadingCompany = ref(false) const searchTime = ref([]); const area = ref([]); const businessList = ref([]); @@ -311,6 +352,7 @@ chooseType.value = val; search.queryParams.phase = val; getList(); + getStatistics() } const getList = async () => { loading.value = true; @@ -350,10 +392,12 @@ search.queryParams.pageNum = 1; search.queryParams.pageSize = val getList() + getStatistics() } const handleCurrentChange = (val) => { search.queryParams.pageNum = val getList() + getStatistics() } const toProcess = (type,value,toPath) => { value.type = type; @@ -432,6 +476,7 @@ pageNum: 1, pageSize: 20, name: '', + agencyName: '', client: '', province: '', city: '', @@ -439,6 +484,8 @@ business: '', estimateType: '', phase: '', + safetyCheck: 0, + unFinish: null, params: { lostMaterial: null } @@ -502,12 +549,53 @@ console.log("val",val) toProcess('edit',val,toPath); } +const selectValue = (val) => { + console.log('val',val) + if(val == ""){ + companyList.value = [] + } + // data.companyList.forEach(item => { + // if(item.name === val){ + // data.queryParams.companyId = item.id + // } + // }) +} +const getCompanyList = async (val)=>{ + if(val != ""){ + loadingCompany.value = true; + const queryParams = { + name: val + } + const res = await getAllAgency(queryParams) + if (res.code == 200) { + loadingCompany.value = false; + companyList.value = res.data + } else { + ElMessage.warning(res.message) + } + } +} + +const chooseUn = () => { + isActive.value = !isActive.value + if(isActive.value){ + search.queryParams.unFinish = 1 + }else { + search.queryParams.unFinish = null + } + getList() + getStatistics() +} </script> <style scoped lang="scss"> .project-container{ + .active { + background-color: #fdb0b7; + //border: 1px solid #dab4f6; + } .header{ margin: 15px 10px; display: flex; diff --git a/src/views/safetyReview/testManage/components/confirmEnd.vue b/src/views/safetyReview/testManage/components/confirmEnd.vue new file mode 100644 index 0000000..46d0c33 --- /dev/null +++ b/src/views/safetyReview/testManage/components/confirmEnd.vue @@ -0,0 +1,252 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-button type="primary" @click="addRectify('add',{})" :disabled="projectType ==='view' || isEnd ">新增整改</el-button> + </el-col> + </el-row> + <el-table :data="state.recitificationList" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="整改时间" prop="rectifyTime" align="center"></el-table-column> + <el-table-column label="提交时间" prop="updateTime" align="center"></el-table-column> + <el-table-column label="整改说明" prop="reason" align="center"></el-table-column> + <el-table-column label="整改人" prop="rectifyPerson" align="center"></el-table-column> + <el-table-column label="附件" prop="" align="center"> + <template #default="scope"> + <span @click="handlePreview(scope.row.accessoryFile)" style="color: #3b82f6;cursor:pointer">{{scope.row.accessoryFile.originName}}</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button link type="primary" @click="addRectify('edit',scope.row)" :disabled="projectType ==='view' || isEnd ">编辑</el-button> + <el-button link type="danger" @click="del(scope.row)" :disabled="projectType ==='view' || isEnd ">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-form> + <div class="pag-container"> + <el-pagination + v-model:current-page="state.queryParams.pageNum" + v-model:page-size="state.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <confirm-end-dialog ref="confirmRef" @getList="getList(props.projectId)"></confirm-end-dialog> + </div> + +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {addRecord, editRecord, getDetail} from "@/api/projectManage/contractMng"; +import Cookies from "js-cookie"; +import { getToken } from "@/utils/auth"; +import confirmEndDialog from './confirmEndDialog.vue' +import {delProject, getAccessoryFile, getProjectStatus} from "@/api/projectManage/project"; +import {delRecitification, doConfirm, getRecognitionList} from "@/api/projectManage/riskAnalysis"; +import axios from "axios"; +import { useRoute } from 'vue-router' +const route = useRoute() +const confirmRef = ref(null); +const emit = defineEmits(["getNextStatus"]); +const props = defineProps(['projectId']) +const state = reactive({ + formData: {}, + queryParams: { + pageNum: 1, + pageSize: 10, + }, + recitificationList: [], +}) + +const isEnd = ref(false) +const total = ref(0); +const isAmin = ref(false) +const formRef = ref(); +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(props.projectId){ + state.formData.projectId = props.projectId; + getList(state.formData.projectId); + getStatus(state.formData.projectId); + } + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; + + +}); +const getStatus = async (projectId) => { + const res = await getProjectStatus(projectId); + if(res.code == 200){ + if(res.data === 14){ + isEnd.value = true + } + } +} + + + +const getList = async (val) => { + const res = await getRecognitionList({projectId: val}); + if(res.code == 200){ + state.recitificationList = res.data.list; + total.value = res.data.total; + }else { + ElMessage.warning(res.message) + } +} + +const projectType = ref('') + +const riskOpen = async (type,val) => { + // await getList(val); + projectType.value = route.query.type; + state.formData.projectId = val; + + if(type === 'confirm') { + const res = await doConfirm({projectId: val}); + if (res.code == 200) { + ElMessage.success('保存成功') + Cookies.set('end',true) + isEnd.value = true; + formRef.value.clearValidate(); + emit('getNextStatus', state.formData.projectId); + } else { + ElMessage.warning(res.message) + } + } +} + +const addRectify = (type,val)=>{ + val.projectId = state.formData.projectId; + confirmRef.value.openDialog(type,val) +} + +const delRectify = (index)=>{ + state.rectifyList.splice(index,1) +} +const handleSizeChange = (val) => { + state.queryParams.pageNum = 1; + state.queryParams.pageSize = val + getList(props.projectId) +} +const handleCurrentChange = (val) => { + state.queryParams.pageNum = val + getList(props.projectId) +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + // state.registerForm.agency.reportPath = res.data.path + }else{ + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const handleRemove = async (file, uploadFiles) => { + const res = await delPic({path: state.registerForm.agency.reportPath}) + if(res.code == 200){ + ElMessage({ + type: 'success', + message: '文件已删除' + }) + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } +} +const handlePreview = (file) => { + const url = import.meta.env.VITE_APP_BASE_API + '/' + file.path + axios.get( url,{ + headers: + { + 'Content-Type': 'application/json', + 'Authorization':getToken(), + }, + responseType: 'blob' + } + ).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", file.originName); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) +} +const del = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delRecitification(val) + if(res.code == 200){ + ElMessage.success('数据删除成功') + getList(props.projectId) + }else{ + ElMessage.warning(res.message) + } + }) +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} +.pag-container{ + float: right; + margin-top: 20px; +} + +</style> diff --git a/src/views/safetyReview/testManage/components/confirmEndDialog.vue b/src/views/safetyReview/testManage/components/confirmEndDialog.vue new file mode 100644 index 0000000..ef1a404 --- /dev/null +++ b/src/views/safetyReview/testManage/components/confirmEndDialog.vue @@ -0,0 +1,233 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="state.title" + width="550px" + :before-close="handleClose" + > + <el-form :model="state.form" size="default" ref="formRef" :rules="state.formRules" label-width="110px" > + <el-form-item label="整改时间:" prop="rectifyTime" > + <el-date-picker + style="width: 100%" + v-model="state.form.rectifyTime" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="请选择日期" + size="large" + /> + </el-form-item> + <el-form-item label="整改人:" prop="rectifyPerson"> + <el-input v-model.trim="state.form.rectifyPerson" show-word-limit type="text" size="large" placeholder="请输入整改人" /> + </el-form-item> + <el-form-item label="整改说明:" prop="reason"> + <el-input v-model.trim="state.form.reason" show-word-limit type="text" size="large" placeholder="请输入整改说明"/> + </el-form-item> + <el-form-item prop="fileList"> + <el-upload accept=".pdf" + :action="state.uploadUrl" + :disabled="state.disabled" + :headers="state.header" + method="post" + :limit="state.imgLimit" + :before-upload="beforeUpload" + :on-success="handleAvatarSuccess" + v-model:file-list="state.form.fileList" + :on-remove="handleRemove" + :data="state.uploadData" + :on-preview="handlePreview" + > + <el-button type="primary">附件上传</el-button> + <template #tip> + <div class="el-upload__tip"> + 只能上传pdf类型,且只能上传一个 + </div> + </template> + </el-upload> + + </el-form-item> + </el-form> + <template #footer > + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {defineEmits, nextTick, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import axios from "axios"; +import {getToken} from "@/utils/auth"; +import {delAccessoryFile} from "@/api/projectManage/project"; +import {addRate, addRecitification, editRecitification} from "@/api/projectManage/riskAnalysis"; +const emit = defineEmits(["getList"]); +const formRef = ref(null) +const state = reactive({ + title: '', + form: { + id: null, + }, + formRules:{ + rectifyTime: [{ required: true, message: '请选择整改时间', trigger: 'blur' }], + rectifyPerson: [{ required: true, message: '请输入整改人', trigger: 'blur' }], + fileList: [{ required: true, message: '请上传附件', trigger: 'blur' }], + reason:[{ required: true, message: '请输入整改说明', trigger: 'blur' }], + }, + imgLimit: 1, + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + uploadData: { + moduleType: 11 + }, + +}) +const dialogVisible = ref(false) + +const openDialog = (type, value) => { + state.uploadData.projectId = value.projectId; + state.title = type === 'add' ? '新增' : '编辑' ; + if(state.title === '编辑'){ + state.form = value; + state.form.fileList = [value.accessoryFile] + state.form.fileList[0].name = value.accessoryFile.originName + } + dialogVisible.value = true +} + +const beforeUpload = (file) => { + let fileType = file.name.substring(file.name.lastIndexOf(".") + 1); + if (fileType === 'pdf') { + } else { + ElMessage.error("文件类型必须为pdf格式") + return false + } +} +const handleAvatarSuccess = (res) => { + if(res.code === 200){ + console.log("file",state.form.fileList) + ElMessage({ + type: 'success', + message: '文件上传成功' + }) + }else { + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const handlePreview = (file) => { + let path = ""; + if(file.path){ + path = file.path + }else { + path = file.response.data.path + + } + const url = import.meta.env.VITE_APP_BASE_API + '/' + path + axios.get( url,{ + headers: + { + 'Content-Type': 'application/json', + 'Authorization':getToken(), + }, + responseType: 'blob' + } + ).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", file.name); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) +} +const onSubmit = async () => { + const valid = await formRef.value.validate(); + if(valid){ + state.form.fileId = state.form.fileList ? state.form.fileList[0].response ? state.form.fileList[0].response.data.id : state.form.fileList[0].id : ''; + if(state.title === '新增'){ + const {id,fileList, ...data} = JSON.parse(JSON.stringify(state.form)) + data.projectId = state.uploadData.projectId; + console.log("Add",data) + const res = await addRecitification(data); + if (res.code == 200) { + ElMessage.success('保存成功') + handleClose(); + emit('getList'); + } else { + ElMessage.warning(res.message) + } + }else if(state.title === '编辑'){ + const {ileList, ...data} = JSON.parse(JSON.stringify(state.form)) + data.projectId = state.uploadData.projectId; + const res = await editRecitification(data); + if (res.code == 200) { + ElMessage.success('编辑成功') + handleClose(); + emit('getList'); + } else { + ElMessage.warning(res.message) + } + } + } +} +const handleRemove = async (file, uploadFiles) => { + if(file && file.status == 'success') { + + + console.log("file", file) + let accessoryFileId = ""; + if (file.id) { + accessoryFileId = file.id + } else { + accessoryFileId = file.response.data.id + + } + const res = await delAccessoryFile(accessoryFileId) + if (res.code == 200) { + ElMessage({ + type: 'success', + message: '文件已删除' + }) + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } + } +} + +const handleClose = () => { + state.form = { + id: null, + rectifyTime: '', + rectifyPerson: '', + reason: '', + fileList: [] + } + formRef.value.clearValidate(); + dialogVisible.value = false; + +} +defineExpose({ + openDialog +}); +</script> + +<style scoped lang="scss"> + +</style> diff --git a/src/views/safetyReview/testManage/components/contractManage.vue b/src/views/safetyReview/testManage/components/contractManage.vue new file mode 100644 index 0000000..97e9064 --- /dev/null +++ b/src/views/safetyReview/testManage/components/contractManage.vue @@ -0,0 +1,137 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="contractSignDate" label="合同签订日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.contractSignDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="18"> + <el-form-item prop="contractMoney"> + <template #label> + 项目合同额<span style="font-size: 13px;color: red;font-weight: normal;display: inline-block;margin-left: 6px" @input="state.formData.contractMoney= state.formData.contractMoney.replace(/[^\d|\.]/g,'')" + >预估合同金额,归档阶段可以进行修改。仅支持数字,单位万元,小数点后最多两位,数值范围(0.01-999.99)</span> + </template> + <el-input + + v-model.trim="state.formData.contractMoney" + size="large" + placeholder="请输入项目合同额" + @input="state.formData.contractMoney= state.formData.contractMoney.replace(/[^0-9.\/\-]/g,'')" + + > + <template #append>万元</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-form-item label="项目合同额说明"> + <el-input + v-model="state.formData.contractIntroduction" + :autosize="{ minRows: 6 }" + maxlength="100" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + </el-form> + </div> + +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import {addRecord, editRecord, getDetail} from "@/api/projectManage/contractMng"; +import Cookies from "js-cookie"; +const emit = defineEmits(["getNextStatus"]); + +const state = reactive({ + formData: { + id: '', + projectId: null, + contractSignDate: '', + contractMoney: '', + contractIntroduction: '' + }, + rules: { + contractSignDate: [{required: true, message: '请选择合同签订日期', trigger: 'blur'}], + contractMoney: [{required: true, message: '请输入项目合同额', trigger: 'blur'}] + } +}) + +const isAmin = ref(false) +const formRef = ref(); +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } +}); + +const riskOpen = async (type,val) => { + state.formData.projectId = val; + if(type === 'detail' || type === 'edit' ){ + const res = await getDetail({projectId: val}); + if(res.code == 200){ + if(res.data){ + state.formData = res.data; + } + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await addRecord(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', state.formData.projectId); + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await editRecord(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/deviceDialog.vue b/src/views/safetyReview/testManage/components/deviceDialog.vue new file mode 100644 index 0000000..0419b10 --- /dev/null +++ b/src/views/safetyReview/testManage/components/deviceDialog.vue @@ -0,0 +1,140 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="500px" + :before-close="handleClose" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-position="top"> + <el-form-item label="设备名称:" prop="deviceName"> + <el-input v-model.trim="state.form.deviceName" maxlength="30" show-word-limit type="text" size="large"/> + </el-form-item> + <el-form-item label="开始时间:" prop="startDate"> + <el-date-picker + style="width: 100%" + v-model="state.form.startDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + <el-form-item label="结束时间:" prop="endDate"> + <el-date-picker + style="width: 100%" + v-model="state.form.endDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + </el-dialog> + </div> +</template> +<script setup> +import {defineProps, nextTick, reactive, ref, toRefs} from 'vue' +import {ElMessage} from "element-plus"; +import {addDevice, editDevice} from "@/api/projectManage/evaPlan" +const dialogVisible = ref(false) +const title = ref("") +const busRef = ref() +const props = defineProps(['workList','typeList']) +const emit = defineEmits(["getList"]) +const state = reactive({ + form: { + id: null, + projectId: null, + deviceName: '', + startDate: '', + endDate: '' + }, + formRules:{ + deviceName: [{ required: true, message: '请填写设备名称', trigger: 'blur' }], + startDate: [{ required: true, message: '请选择开始日期', trigger: 'blur' }], + endDate: [{ required: true, message: '请选择结束日期', trigger: 'blur' }] + } +}) + +const openDialog = async (type, value,projectId) => { + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' + state.form.projectId = projectId + if(type == 'add'){ + nextTick(()=>{ + busRef.value.resetFields() + }) + }else if(type === 'edit') { + state.form = JSON.parse(JSON.stringify(value)) + } + dialogVisible.value = true; +} + +const onSubmit = async () => { + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + const {id,...data} = state.form + const res = await addDevice(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; + }else if(title.value === '编辑'){ + const {...data} = state.form + const res = await editDevice(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '修改成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/safetyReview/testManage/components/employNoticeRecord.vue b/src/views/safetyReview/testManage/components/employNoticeRecord.vue new file mode 100644 index 0000000..4a7ae99 --- /dev/null +++ b/src/views/safetyReview/testManage/components/employNoticeRecord.vue @@ -0,0 +1,206 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="12"> + <el-form-item prop="timeRange" label="技术服务期限"> + <el-date-picker + v-model="state.formData.timeRange" + style="width: 100%" + type="daterange" + range-separator="至" + start-placeholder="开始日期" + end-placeholder="结束日期" + value-format="YYYY-MM-DD 00:00:00" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="investigationPlanDate" label="计划现场勘验时间"> + <el-date-picker + style="width: 100%" + v-model="state.formData.investigationPlanDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="18"> + <div style="display: flex;align-items: center">项目组成员<el-icon style="margin-left: 10px;margin-right: 4px"><InfoFilled /></el-icon><span style="font-size: 13px">金属、非金属矿及其他矿采选业:安全、机械、电气、采矿、通风、地质、水工结构</span></div> + </el-col> + </el-row> + <el-table :data="state.planPersons" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="评价组成员" prop="person.name" align="center" :show-overflow-tooltip="true"> + <template #default="scope"> + <span v-if="scope.row.jobType === 2">{{ scope.row.person.name }} (组长)</span> + <span v-else>{{scope.row.person.name}}</span> + </template> + </el-table-column> + <el-table-column label="专业能力/资格证书" prop="person.certificateNo" align="center" :show-overflow-tooltip="true"> + <template #default="scope"> + {{ getCertNo(scope.row) }} + </template> + </el-table-column> + <el-table-column label="承担工作" prop="work" align="center" class-name="small-padding fixed-width"></el-table-column> + <el-table-column label="承诺后期前往现场勘验" prop="laterPromise" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + {{(scope.row.laterPromise==1 || scope.row.laterPromise==true)?'是':'否'}} + </template> + </el-table-column> + <el-table-column label="未到现场勘验原因" prop="reason" align="center" class-name="small-padding fixed-width"></el-table-column> + <el-table-column label="是否已告知" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-radio-group v-model="scope.row.informed" size="large" @change="(value)=>changePerson(value,scope.row)" :disabled="projectType==='view'"> + <el-radio :label="1" size="large">是</el-radio> + <el-radio :label="0" size="large">否</el-radio> + </el-radio-group> + </template> + </el-table-column> + </el-table> + </el-form> + </div> +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref, watchEffect} from "vue" +import {ElMessage} from "element-plus" +import {Search} from '@element-plus/icons-vue' +import {addWorkRecord, editWorkRecord, getWorkDetail} from "@/api/projectManage/employNoticeRcd" +import {getWorks, editWorks} from "@/api/projectManage/evaPlan" +import Cookies from "js-cookie" +const props = defineProps(['projectId']) +const emit = defineEmits(["getNextStatus"]) +import { useRoute } from 'vue-router' +const route = useRoute() +const state = reactive({ + formData: { + id: null, + projectId: null, + timeRange: [], + serviceStartDate: '', + serviceEndDate: '', + investigationPlanDate: '' + }, + projectId: null, + planPersons: [], + rules: { + timeRange: [{required: true, message: '请选择技术服务期限', trigger: 'blur'}], + investigationPlanDate: [{required: true, message: '请选择计划现场勘验时间', trigger: 'blur'}] + } +}) + +const isAmin = ref(false) +const formRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(props.projectId){ + getWorksList(props.projectId) + } + +}); + +const projectType = ref(''); +const riskOpen = async (type,val) => { + state.formData.projectId = val + state.projectId = val + projectType.value = route.query.type; + // await getWorksList(val) + if(type === 'detail' || type === 'edit' ){ + const res = await getWorkDetail({projectId: val}) + if(res.code == 200){ + state.formData = JSON.parse(JSON.stringify(res.data)) + state.formData.timeRange = [state.formData.serviceStartDate,state.formData.serviceEndDate] + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + state.formData.serviceStartDate = state.formData.timeRange[0] + state.formData.serviceEndDate = state.formData.timeRange[1] + if(type === 'add'){ + const {timeRange,id,...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await addWorkRecord(data) + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', state.projectId); + } else { + ElMessage.warning(res.message) + } + + }else if(type === 'clickEdit'){ + const {timeRange, ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await editWorkRecord(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const getWorksList = async (id) =>{ + const works = await getWorks({projectId: id ? id : props.projectId}) + if(works.code == 200){ + state.planPersons = works.data + }else { + ElMessage.warning(works.message) + } +} + +const getCertNo = (row)=>{ + const obj = JSON.parse(row.person.certificateNo) + const noArr = Object.values(obj) + return row.person.majorNames.map((item,index)=>{ + return item + '(' + noArr[index] + ')' + }).join(',') +} + +const changePerson = async (value,row)=>{ + const params = { + id: row.id, + projectId: row.projectId, + informed: value + } + const res = await editWorks(params) + if(res.code === 200){ + console.log(res.message) + }else{ + ElMessage.warning(res.message) + } + await getWorksList(props.projectId) +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/evaluatePlan.vue b/src/views/safetyReview/testManage/components/evaluatePlan.vue new file mode 100644 index 0000000..d0300d5 --- /dev/null +++ b/src/views/safetyReview/testManage/components/evaluatePlan.vue @@ -0,0 +1,521 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="startDate" label="评价开始时间"> + <el-date-picker + style="width: 100%" + v-model="state.formData.startDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="endDate" label="评价结束时间"> + <el-date-picker + style="width: 100%" + v-model="state.formData.endDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="auser.name" label="机构评价负责人"> + <el-input + v-model.trim="state.formData.auser.name" + size="large" + placeholder="请选择机构评价负责人" + @focus="openExperts('机构评价负责人')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('机构评价负责人')"/> + </template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="18"> + <div style="display: flex;align-items: center">评价日程安排<el-icon style="margin-left: 10px;margin-right: 4px"><InfoFilled /></el-icon><span style="font-size: 13px">不涉及的日程安排日期可不填</span></div> + </el-col> + </el-row> + <el-table :data="state.formData.estimateSchedules" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="评价日程安排" prop="name" align="center" :show-overflow-tooltip="true"/> + <el-table-column label="开始时间" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-date-picker + style="width: 100%" + v-model="scope.row.startDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </template> + </el-table-column> + <el-table-column label="结束时间" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-date-picker + style="width: 100%" + v-model="scope.row.endDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </template> + </el-table-column> + </el-table> + <el-row> + <el-col :span="18"> + <div style="display: flex;align-items: center">项目组成员<el-icon style="margin-left: 10px;margin-right: 4px"><InfoFilled /></el-icon><span style="font-size: 13px">金属、非金属矿及其他矿采选业:安全、机械、电气、采矿、通风、地质、水工结构</span></div> + </el-col> + <el-col :span="6"> + <div style="width: 100%;display: flex;justify-content: right"> + <el-button type="primary" icon="Plus" @click="openWorksDialog('add',{})" :disabled="projectType==='view' || isEnd">添加成员</el-button> + </div> + </el-col> + </el-row> + <el-table :data="state.planPersons" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="评价组成员" prop="person.name" align="center" :show-overflow-tooltip="true"> + <template #default="scope"> + <span v-if="scope.row.jobType === 2">{{ scope.row.person.name }} (组长)</span> + <span v-else>{{scope.row.person.name}}</span> + </template> + </el-table-column> + <el-table-column label="专业能力/资格证书" prop="person.certificateNo" align="center" :show-overflow-tooltip="true"> + <template #default="scope"> + {{ getCertNo(scope.row) }} + </template> + </el-table-column> +<!-- <el-table-column label="专业能力" header-align="center" :show-overflow-tooltip="true"></el-table-column>--> + <el-table-column label="承担工作" prop="work" align="center" class-name="small-padding fixed-width"></el-table-column> + <el-table-column label="承诺后期前往现场勘验" prop="laterPromise" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + {{(scope.row.laterPromise==1 || scope.row.laterPromise==true)?'是':'否'}} + </template> + </el-table-column> + <el-table-column label="未到现场勘验原因" prop="reason" align="center" class-name="small-padding fixed-width"></el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button link @click="openWorksDialog('edit',scope.row)" :disabled="projectType==='view' || isEnd">修改</el-button> + <el-button link type="danger" @click="delMember(scope.row)" :disabled="projectType==='view' || isEnd">删除</el-button> + </template> + </el-table-column> + </el-table> + <el-row> + <el-col :span="18"> + <div style="display: flex;align-items: center">所需仪器设备</div> + </el-col> + <el-col :span="6"> + <div style="width: 100%;display: flex;justify-content: right"> + <el-button type="primary" icon="Plus" @click="openDeviceDialog('add',{})" :disabled="projectType==='view' || isEnd">添加设备</el-button> + </div> + </el-col> + </el-row> + <el-table :data="state.devices" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="设备名称" prop="deviceName" align="center" class-name="small-padding fixed-width"/> + <el-table-column label="开始时间" prop="startDate" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + {{scope.row.startDate.substring(0,10)}} + </template> + </el-table-column> + <el-table-column label="结束时间" prop="endDate" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + {{scope.row.endDate.substring(0,10)}} + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button link @click="openDeviceDialog('edit',scope.row)" :disabled="projectType==='view' || isEnd">修改</el-button> + <el-button link type="danger" @click="delDeviceItem(scope.row)" :disabled="projectType==='view' || isEnd">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-form> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + <works-dialog ref="worksRef" @getList="getWorksList" :workList="state.workList" :typeList="state.jobTypeList"></works-dialog> + <device-dialog ref="deviceRef" @getList="getDeviceList"></device-dialog> + </div> +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref} from "vue" +import {ElMessage, ElMessageBox} from "element-plus" +import {Search} from '@element-plus/icons-vue' +import {addRecord, editRecord, getDetail, getWorks, getDevice, delWorks, delDevice} from "@/api/projectManage/evaPlan" +import Cookies from "js-cookie" +import ExpertsList from "./expertsList" +import WorksDialog from './worksDialog' +import DeviceDialog from './deviceDialog' +const props = defineProps(['projectId']) +const emit = defineEmits(["getNextStatus"]) +import { useRoute } from 'vue-router' +const route = useRoute() +const state = reactive({ + formData: { + id: null, + projectId: null, + auser: { + name: '' + }, + auserId: null, + estimateSchedules: [ + { + id: null, + sort: 1, + name: '勘验准备', + startDate: '', + endDate: '', + scheduleType: 1, + projectId: null + }, + { + id: null, + sort: 2, + name: '现场勘验', + startDate: '', + endDate: '', + scheduleType: 2, + projectId: null + }, + { + id: null, + sort: 3, + name: '材料分析整理', + startDate: '', + endDate: '', + scheduleType: 3, + projectId: null + }, + { + id: null, + sort: 4, + name: '评价报告编写', + startDate: '', + endDate: '', + scheduleType: 4, + projectId: null + }, + { + id: null, + sort: 5, + name: '整改情况现场确认', + startDate: '', + endDate: '', + scheduleType: 5, + projectId: null + }, + { + id: null, + sort: 6, + name: '整理评价报告', + startDate: '', + endDate: '', + scheduleType: 6, + projectId: null + }, + { + id: null, + sort: 7, + name: '报告审核', + startDate: '', + endDate: '', + scheduleType: 7, + projectId: null + }, + { + id: null, + sort: 8, + name: '报告修改', + startDate: '', + endDate: '', + scheduleType: 8, + projectId: null + }, + ], + planPersons: [], + devices: [], + startDate: '', + endDate: '' + }, + projectId: null, + planPersons: [], + devices: [], + rules: { + "auser.name": [{required: true, message: '请填写机构评价负责人', trigger: 'change'}], + startDate: [{required: true, message: '请选择评价开始时间', trigger: 'change'}], + endDate: [{required: true, message: '请选择评价结束时间', trigger: 'change'}] + }, + workList: [ + {value: '报告编制',label: '报告编制'}, + {value: '文字校对',label: '文字校对'}, + {value: '现场勘验',label: '现场勘验'}, + {value: '资料收集整理',label: '资料收集整理'} + ], + jobTypeList: [ + {value: 1,label: '普通人员'}, + {value: 2,label: '组长'}, + ] +}) + +const isAmin = ref(false) +const formRef = ref() +const expertsListRef = ref() +const worksRef = ref() +const deviceRef = ref() +onMounted(async () => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true + } + if(props.projectId){ + await getWorksList(props.projectId) + await getDeviceList(props.projectId) + } + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; +}) + +const projectType = ref(''); +const isEnd = ref('') +const riskOpen = async (type,val) => { + state.formData.projectId = val + isEnd.value = Cookies.get('end') + state.projectId = val + projectType.value = route.query.type; + for(let i of state.formData.estimateSchedules){ + i.projectId = val + } + // await getWorksList(val) + // await getDeviceList(val) + if(type === 'detail' || type === 'edit' ){ + const res = await getDetail({projectId: val}) + if(res.code == 200){ + state.formData = JSON.parse(JSON.stringify(res.data)) + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + + const params = Object.assign({}, state.formData.estimateSchedules); + let i = 0 + + for (const key in params) { + if ((params[key].startDate == '' || params[key].startDate == null ) && (params[key].endDate == '' || params[key].endDate == null)) { + delete params[key].startDate; + delete params[key].endDate; + i++ + } + + } + console.log('data',params) + const finData = Object.entries(params).map(([key, value]) => ({ + ...value, + })); + if(i == finData.length){ + ElMessage.warning("请选择至少一个的日程安排日期"); + return; + } + try { + finData.forEach(item =>{ + // debugger + console.log(item.endDate,'item.endDate') + if(item.startDate && (item.startDate !='' || item.startDate !=null)){ + if(item.endDate =='' || item.endDate ==null){ + ElMessage.warning("请完善涉及的日程安排结束日期"); + throw new Error('Loop stopped') + } + } + if(item.endDate && (item.endDate !='' || item.endDate !=null)){ + if(item.startDate =='' || item.startDate ==null){ + ElMessage.warning("请完善涉及的日程安排开始日期"); + throw new Error('Loop stopped') + } + } + }) + }catch (e) { + throw new Error(e) + } + + data.estimateSchedules = finData + + const res = await addRecord(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', state.formData.projectId); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + const params = Object.assign({}, state.formData.estimateSchedules); + let i = 0 + for (const key in params) { + if (params[key].startDate == '' && params[key].endDate == '') { + delete params[key].startDate; + delete params[key].endDate; + i++; + } + } + const finData = Object.entries(params).map(([key, value]) => ({ + ...value, + })); + if(i == finData.length){ + ElMessage.warning("请选择至少一个的日程安排日期"); + return; + } + try { + finData.forEach(item =>{ + // debugger + console.log(item.endDate,'item.endDate') + if(item.startDate && (item.startDate !='' || item.startDate !=null)){ + if(item.endDate =='' || item.endDate ==null){ + ElMessage.warning("请完善涉及的日程安排结束日期"); + throw new Error('Loop stopped') + } + } + if(item.endDate && (item.endDate !='' || item.endDate !=null)){ + if(item.startDate =='' || item.startDate ==null){ + ElMessage.warning("请完善涉及的日程安排开始日期"); + + throw new Error('Loop stopped') + } + } + }) + }catch (e) { + throw new Error(e) + } + data.estimateSchedules = finData + const res = await editRecord(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const getWorksList = async (id) =>{ + const works = await getWorks({projectId: id ? id : props.projectId}) + if(works.code == 200){ + state.planPersons = works.data + }else { + ElMessage.warning(works.message) + } +} + +const getDeviceList = async (id) =>{ + const device = await getDevice({projectId: id ? id : props.projectId}) + if(device.code == 200){ + state.devices = device.data + }else { + ElMessage.warning(device.message) + } +} + +const getCertNo = (row)=>{ + const obj = JSON.parse(row.person.certificateNo) + const noArr = Object.values(obj) + return row.person.majorNames.map((item,index)=>{ + return item + '(' + noArr[index] + ')' + }).join(',') +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + state.formData.auser.name = obj.name + state.formData.auserId = obj.id +} + +const openWorksDialog = (type,data)=>{ + worksRef.value.openDialog(type,data,props.projectId) +} + +const openDeviceDialog = (type,data)=>{ + deviceRef.value.openDialog(type,data,props.projectId) +} + +const delMember = (row)=>{ + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delWorks(row.id) + if(res.code == 200){ + ElMessage.success('数据删除成功') + await getWorksList() + }else{ + ElMessage.warning(res.message) + } + }) +} + +const delDeviceItem = (row)=>{ + console.log(row,'row') + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delDevice(row.id) + if(res.code == 200){ + ElMessage.success('数据删除成功') + await getDeviceList() + }else{ + ElMessage.warning(res.message) + } + }) +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/evaluateTaskNotice.vue b/src/views/safetyReview/testManage/components/evaluateTaskNotice.vue new file mode 100644 index 0000000..21f2034 --- /dev/null +++ b/src/views/safetyReview/testManage/components/evaluateTaskNotice.vue @@ -0,0 +1,197 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="leader.name" label="项目负责人"> + <el-input + v-model.trim="state.formData.leader.name" + size="large" + placeholder="请选择项目负责人" + @focus="openExperts('项目负责人')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('项目负责人')"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="linkMan" label="联系人"> + <el-input + v-model.trim="state.formData.linkMan" + size="large" + placeholder="请选择联系人" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="linkPhone" label="联系电话"> + <el-input + v-model.trim="state.formData.linkPhone" + size="large" + placeholder="请选择联系电话" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="传真"> + <el-input + v-model.trim="state.formData.fax" + size="large" + placeholder="请选择传真" + > + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item label="任务下达人"> + <el-input + v-model.trim="state.formData.transmitPerson" + size="large" + placeholder="请选择任务下达人" + @focus="openExperts('任务下达人')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('任务下达人')"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="transmitDate" label="任务下达时间"> + <el-date-picker + style="width: 100%" + v-model="state.formData.transmitDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {addRecord, editRecord, getDetail} from "@/api/projectManage/evaTaskNotice"; +import Cookies from "js-cookie" +import ExpertsList from "./expertsList"; +const emit = defineEmits(["getNextStatus"]); + +const state = reactive({ + formData: { + id: '', + projectId: null, + leader: { + name: '' + }, + fax: '', + leaderId: null, + linkMan: '', + transmitPerson: '', + transmitDate: '' + }, + rules: { + "leader.name": [{required: true, message: '请选择项目负责人', trigger: 'change'}], + linkMan: [{required: true, message: '请输入联系人', trigger: 'blur'}], + linkPhone: [{required: true, message: '请输入联系电话', trigger: 'blur'}], + transmitDate: [{required: true, message: '请选择任务下达时间', trigger: 'change'}] + } +}) +const props = { + expandTrigger: 'hover', + value: 'name', + label: 'name' +} +const isAmin = ref(false) +const formRef = ref() +const expertsListRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } +}) + +const riskOpen = async (type,val) => { + state.formData.projectId = val + if(type === 'detail' || type === 'edit' ){ + const res = await getDetail({projectId: val}); + if(res.code == 200){ + state.formData = res.data; + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await addRecord(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', state.formData.projectId); + + } else { + ElMessage.warning(res.message) + } + }else{ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await editRecord(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + if(type == '项目负责人'){ + state.formData.leader.name = obj.name + state.formData.leaderId = obj.id + } + if(type == '任务下达人'){ + state.formData.transmitPerson = obj.name + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/expertsList.vue b/src/views/safetyReview/testManage/components/expertsList.vue new file mode 100644 index 0000000..2a65f18 --- /dev/null +++ b/src/views/safetyReview/testManage/components/expertsList.vue @@ -0,0 +1,344 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="60%" + > + <el-form :model="queryParams" :inline="true" label-width="90px"> + <el-form-item label="专业类别"> + <el-radio-group v-model="queryParams.expertType"> + <el-radio-button label="">全部</el-radio-button> + <el-radio-button label="1">安全评价</el-radio-button> + <el-radio-button label="2">检验检测</el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item label="姓名"> + <el-input + v-model.trim="queryParams.name" + placeholder="姓名" + style="width: 250px" + /> + </el-form-item> + <el-form-item label="手机号"> + <el-input + v-model.trim="queryParams.phone" + placeholder="手机号" + style="width: 250px" + /> + </el-form-item> + <el-form-item label="评价师等级"> + <el-select v-model="queryParams.level" style="width: 250px" placeholder="评价师等级" > + <el-option + v-for="item in levelList" + :key="item.id" + :label="item.name" + :value="item.name" + /> + </el-select> + </el-form-item> + <el-form-item label="专业方向"> + <el-select v-model="queryParams.major" clearable value-key="id" style="width: 250px" placeholder="专业方向"> + <el-option + v-for="item in majorList" + :key="item.id" + :label="item.label" + :value="item.id" + /> + </el-select> + </el-form-item> + <el-form-item label="职务"> + <el-select v-model="queryParams.post" clearable style="width: 250px" placeholder="请选择职务"> + <el-option + v-for="item in postList" + :key="item.id" + :label="item.name" + :value="item.name" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="Search" @click="search">搜索</el-button> + <el-button icon="Refresh" @click="research">重置</el-button> + </el-form-item> + </el-form> + <el-table v-loading="loading" ref="tableRef" :data="dataList" :border="true" @select="select" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" /> + <el-table-column label="用户ID" prop="id" align="center" /> + <el-table-column label="姓名" prop="name" align="center" width="110" /> + <el-table-column label="手机号" prop="phone" align="center" width="125" /> + <el-table-column label="用户名" prop="username" align="center" width="110" /> + <el-table-column label="性别" prop="sex" align="center" > + <template #default="scope"> + <span v-if="scope.row.sex === 0">男</span> + <span v-if="scope.row.sex === 1">女</span> + </template> + </el-table-column> + <el-table-column label="所属机构" prop="agency.name" align="center" width="110" /> + <el-table-column label="社保" prop="socialSecurity" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.socialAttach && scope.row.socialAttach.length>0"> + <el-image + style="width: 100px; height: 100px" + :src= "scope.row.socialAttach[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.socialAttach" + :initial-index="0" + fit="cover" + :preview-teleported= true + /> + </div> + </template> + </el-table-column> + <el-table-column label="医保" prop="medicalInsurance" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.medicalAttach && scope.row.medicalAttach.length>0"> + <el-image + style="width: 100px; height: 100px" + :src="scope.row.medicalAttach[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.medicalAttach" + :initial-index="0" + fit="cover" + :preview-teleported= true + /> + </div> + </template> + </el-table-column> + <el-table-column label="工资清单" prop="salaryList" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.salaryAttach && scope.row.salaryAttach.length>0"> + <el-image + style="width: 100px; height: 100px" + :src= "scope.row.salaryAttach[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.salaryAttach" + :initial-index="0" + fit="cover" + :preview-teleported= true + /> + </div> + </template> + </el-table-column> + <el-table-column label="职务" prop="post" align="center" width="120" /> + <el-table-column label="职称" prop="jobTitle" align="center" /> + <el-table-column label="专业方向" prop="majorNames" align="center" width="100" /> + <el-table-column label="评价师等级" prop="level" align="center" width="100" /> + <el-table-column label="业绩汇总" prop="summary" align="center"> + <template #default="scope"> + <div style="cursor:pointer;color: #3b82f6;" @click="openList(scope.row)"> + <span>{{scope.row.projectCount}}</span> + </div> + </template> + </el-table-column> + <el-table-column label="最近评价时间" prop="lastEstimateTime" align="center" width="120" /> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> +<!-- <template #footer>--> +<!-- <span class="dialog-footer">--> +<!-- <el-button @click="dialogVisible = false" size="default">取 消</el-button>--> +<!-- <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>--> +<!-- </span>--> +<!-- </template>--> + </el-dialog> + <project-dialog ref="projectRef" @getList="getList"></project-dialog> + </div> +</template> +<script setup> +import {getCurrentInstance, onMounted, reactive, ref, toRefs,defineEmits} from "vue"; +import {getDictList} from "@/api/backManage/evaluate"; +import {ElMessage, ElMessageBox} from "element-plus"; +import projectDialog from "@/views/safetyReview/userManage/expertUsers/components/projectDialog.vue" +import Cookies from "js-cookie"; +import {delMonitor, getExpertList, getMonitorList} from "@/api/sysUsers"; +const { proxy } = getCurrentInstance(); +const loading = ref(false); +const emit = defineEmits(['getName']) +const data = reactive({ + queryParams: { + pageNum: 1, + pageSize: 10, + expertType: "", + name: '', + phone: '', + level: '', + major: null, + post: '' + }, + total: 0, + dataList: [], + majorList: [], + levelList: [ + { + id: '1', + name: '一级' + }, + { + id: '2', + name: '二级' + }, + { + id: '3', + name: '三级' + }, + { + id: '4', + name: '其他' + }, + ], + postList: [ + { + id: '1', + name: '法人' + }, + { + id: '2', + name: '过程控制负责人' + }, + { + id: '3', + name: '机构负责人' + }, + { + id: '4', + name: '技术负责人' + }, + { + id: '5', + name: '员工' + }, + ], + dialogVisible: false, + title: '', + selected: [] +}) +const tableRef = ref() +const { queryParams, total, dataList, majorList, levelList, postList, dialogVisible,title,selected } = toRefs(data); + +const openDialog = (type) => { + getMajor() + research() + data.selected = [] + data.title = type + data.dialogVisible = true +} + +const onSubmit = async () => { + if(data.selected.length>0) + emit('getName',data.title,data.selected[data.selected.length - 1]) + data.dialogVisible = false +} + +const getList = async () => { + loading.value = true + const res = await getExpertList(data.queryParams) + if(res.code == 200){ + data.dataList = res.data.list.map(item => { + return{ + ...item, + socialAttach: item.socialAttach.map(s => { return import.meta.env.VITE_APP_BASE_API + '/' + s.path}), + medicalAttach: item.medicalAttach.map(s => { return import.meta.env.VITE_APP_BASE_API + '/' + s.path}), + salaryAttach: item.salaryAttach.map(s => { return import.meta.env.VITE_APP_BASE_API + '/' + s.path}), + lastEstimateTime: item.personProjectVO ? item.personProjectVO.lastEstimateTime.slice(0,10) : '', + projectCount: item.personProjectVO ? item.personProjectVO.projectCount : '' + } + }) + console.log('RES',data.dataList) + data.total = res.data.total + }else{ + ElMessage.warning(res.message) + } + loading.value = false +} +const projectRef = ref(); +const openList = (val) => { + projectRef.value.openDialog(val); +} + +const getMajor = async () => { + const queryParams = { + pageNum: 1, + pageSize: 50, + dictType: 'sys_major_orientation' + } + const res = await getDictList(queryParams); + if(res.code === 200){ + data.majorList = res.data.list + }else{ + ElMessage.warning(res.message) + } +} + +const select = ((selection, row) => { + tableRef.value.clearSelection() + if(selection.length == 0) { + return + } + tableRef.value.toggleRowSelection(row, true); +}) + +const handleSelectionChange = (val) => { + data.selected = val + if(data.selected.length>0){ + emit('getName',data.title,data.selected[data.selected.length - 1]) + data.dialogVisible = false + } + + +} + +const search = ()=>{ + data.queryParams.pageNum = 1 + getList() +} + +const research = ()=>{ + data.queryParams = { + pageNum: 1, + pageSize: 10, + expertType: "", + name: '', + phone: '', + level: '', + major: null, + post: '' + } + getList() +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + + ::v-deep(.el-table th.el-table__cell:nth-child(1) .cell) { + visibility: hidden; + } + + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/safetyReview/testManage/components/innerReview.vue b/src/views/safetyReview/testManage/components/innerReview.vue new file mode 100644 index 0000000..9b3ad96 --- /dev/null +++ b/src/views/safetyReview/testManage/components/innerReview.vue @@ -0,0 +1,276 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="auditDate" label="审核日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.auditDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="assessor.name" label="内部审核员"> + <el-input + v-model.trim="state.formData.assessor.name" + size="large" + placeholder="请选择内部审核员" + @focus="openExperts('内部审核员')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('内部审核员')"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="内部审核确认日期" prop="affirmDate"> + <el-date-picker + style="width: 100%" + v-model="state.formData.affirmDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + </el-row> +<!-- <el-row :gutter="30">--> +<!-- <el-col :span="6">--> +<!-- <el-form-item label="附件上传">--> +<!-- <el-upload accept="image/*" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="handleAvatarSuccess" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='state.imgLimit' v-model:file-list="state.fileList" list-type="picture-card" :before-upload="picSize" :on-remove="handleRemove" :before-remove="beforeRemove">--> +<!-- <el-icon><Plus /></el-icon>--> +<!-- <template #tip>--> +<!-- <div class="el-upload__tip">上传jpg/png图片尺寸小于5M,最多可上传1张</div>--> +<!-- </template>--> +<!-- </el-upload>--> +<!-- </el-form-item>--> +<!-- </el-col>--> +<!-- </el-row>--> + <el-table :data="state.tableData" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="内容" prop="content" header-align="center" :show-overflow-tooltip="true"/> + <el-table-column label="选择" header-align="center" class-name="small-padding fixed-width" width="175"> + <template #default="scope"> + <el-radio-group v-model="scope.row.status" > + <el-radio :label="1">是</el-radio> + <el-radio :label="0">否</el-radio> + </el-radio-group> + </template> + </el-table-column> + </el-table> + <el-form-item prop="suggestions" label="存在问题及建议"> + <el-input + v-model.trim="state.formData.suggestions" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + </el-form> +<!-- <el-dialog v-model="state.dialogImg">--> +<!-- <el-image style="width: 100%; height: 100%" :src="state.dialogImageUrl"/>--> +<!-- </el-dialog>--> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {addInnerReview, editInnerReview, getInnerReviewDetail} from "@/api/projectManage/innerReview" +import {delPic} from "@/api/login" +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import ExpertsList from "./expertsList"; +const emit = defineEmits(["getNextStatus"]); + +const state = reactive({ + formData: { + id: '', + projectId: '', + auditDate:'', + auditType: 1, + assessor: { + name: '' + }, + assessorId: null, + affirmDate: '', + suggestions: '' + }, + rules: { + "assessor.name": [{required: true, message: '请选择内部审核员', trigger: 'change'}], + auditDate: [{required: true, message: '请选择审核日期', trigger: 'change'}], + affirmDate: [{required: true, message: '请选择内部审核确认日期', trigger: 'change'}] + }, + tableData: [ + {id: 1, content: '评价依据是否充分、准确、有效',key: 'isBasis', status: 1}, + {id: 2, content: '评价范围是否与合同一致', key: 'isScope', status: 1}, + {id: 3, content: '危险有害因素识别是否全面', key: 'isDangerOverall', status: 1}, + {id: 4, content: '评价单元划分是否合理', key: 'isUnitDivision', status: 1}, + {id: 5, content: '评价方法选择是否适当', key: 'isMethodSelection', status: 1}, + {id: 6, content: '对策措施与建议是否可行', key: 'isMeasure', status: 1}, + {id: 7, content: '结论是否正确', key: 'isConclusion', status: 1}, + {id: 8, content: '格式是否符合要求', key: 'isFormat', status: 1}, + {id: 9, content: '附件与附图是否有效及规范', key: 'isFile', status: 1}, + {id: 10, content: '文字、数据是否准确', key: 'isText', status: 1}, + {id: 11, content: '已按要求修改完成', key: 'isAmendFinish', status: 1}, + {id: 12, content: '可报技术负责人审核', key: 'isReportAudit', status: 1} + ], + imgLimit: 1, + fileList: [], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile', + header: { + Authorization: getToken() + }, + dialogImageUrl: '', + dialogImg: false +}) + +const isAmin = ref(false) +const formRef = ref() +const expertsListRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } +}) + +const riskOpen = async (type,val) => { + state.formData.projectId = val + if(type === 'detail' || type === 'edit' ){ + const res = await getInnerReviewDetail({projectId: val,auditType: 1}); + if(res.code == 200){ + state.formData = res.data + for(let key in res.data){ + for(let item of state.tableData){ + if(item.key == key){ + item.status = res.data[key]==true?1:0 + } + } + } + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + data[i.key] = i.status + } + const res = await addInnerReview(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', val); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + data[i.key] = i.status + } + const res = await editInnerReview(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + state.formData.assessor.name = obj.name + state.formData.assessorId = obj.id +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handlePictureCardPreview = (uploadFile) => { + state.dialogImageUrl = uploadFile.url + state.dialogImg = true +}; + + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + // state.registerForm.agency.reportPath = res.data.path + }else{ + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const handleRemove = async (file, uploadFiles) => { + const res = await delPic({path: state.registerForm.agency.reportPath}) + if(res.code == 200){ + ElMessage({ + type: 'success', + message: '文件已删除' + }) + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/mapLocation.vue b/src/views/safetyReview/testManage/components/mapLocation.vue new file mode 100644 index 0000000..aa943a8 --- /dev/null +++ b/src/views/safetyReview/testManage/components/mapLocation.vue @@ -0,0 +1,162 @@ +<template> + <el-dialog + v-model="state.mapLocationVisible" + append-to-body + :close-on-click-modal="false" + width="75%" + :title="state.title" + > + <div class="mapLocation_head"> + <div> + <el-alert + title="点击地点获取经纬度信息" + type="info" + :closable="false" + > + </el-alert> + </div> + <div class="mapLocation_latlng"> + <span>经度:</span> + <el-input class="mapLocation_latlng_input" id="lng" v-model.trim="state.longitude" @change="getAdress"></el-input> + </div> + <div class="mapLocation_latlng"> + <span>纬度:</span> + <el-input class="mapLocation_latlng_input" id="lat" v-model.trim="state.latitude" @change="getAdress"></el-input> + </div> + <div class="mapLocation_latlng"> + <span>地址:</span> + <el-input class="mapLocation_latlng_input" id="lat" v-model.trim="state.BAddress"></el-input> + </div> + + </div> + <div class="mapLocation_body"> + <baidu-map class="map" @ready="getAdress" ak="BkZdiHBj9aGrMdVFM48r2njNiMzsekga" v="3.0" type="API" :center="state.center" :zoom="state.zoom" scroll-wheel-zoom @click="getPosition"> + <div style="position: absolute;z-index: 999;margin-top: -495px"> + <label>搜索:<input v-model="state.keyword"></label> + <bm-local-search + :keyword="state.keyword" + :auto-viewport="true" + location="新疆" + :pageCapacity="3" + ></bm-local-search> + </div> + <bm-marker :position="{lng: state.longitude, lat: state.latitude}" :dragging="true" animation="BMAP_ANIMATION_BOUNCE"> + <bm-label content="选择地点" :labelStyle="{color: 'red', fontSize : '24px'}" :offset="{width: -35, height: 30}"/> + </bm-marker> + </baidu-map> + </div> + <div align="right" style="margin-top: 10px"> + <el-button @click="state.mapLocationVisible = false">取消</el-button> + <el-button type="primary" @click="submitLatLng()">确认</el-button> + </div> + </el-dialog> +</template> + +<script setup> +import {ref, onMounted, reactive, toRefs, defineComponent, defineExpose, defineEmits, watch} from 'vue'; +import { BaiduMap,BmMarker,BmLocalSearch } from 'vue-baidu-map-3x' +const state = reactive({ + title: '', + longitude: '', + latitude: '', + mapLocationVisible: false, + zoom: 7, + center: { + lng: '116.42585576793277', + lat: '39.88973394962104' + }, + keyword:'', + location: '', + BAddress: '' +}) + +const emit = defineEmits(['giveLatLng']) + +onMounted(() => { + // ...(mounted钩子中的代码不变) +}); +const map = reactive({}) + +const getPosition = ({type, target, point, pixel, overlay})=>{ + state.longitude = point.lng + state.latitude = point.lat + getAdress() +} + +const openMapLocation=(longitude,latitude)=>{ + if(longitude != ""){ + state.longitude = longitude + state.latitude = latitude + state.zoom = 13 + state.center = { + lng: longitude, + lat: latitude + } + }else { + + state.zoom = 7 + state.center = { + lng: '87.61552721758208', + lat: '43.839018284106565' + } + } + + state.mapLocationVisible = true +} + +const submitLatLng=()=>{ + state.mapLocationVisible = false + emit('giveLatLng',state.longitude,state.latitude); +} + +const initMap=()=>{ + +} +const myGeo = ref(null) +const getAdress = () => { + myGeo.value = new BMap.Geocoder(); + const pt = new BMap.Point(state.longitude, state.latitude); + myGeo.value.getLocation(pt,function(result){ + state.BAddress = result.address; //获取到当前定位的详细地址信息 + }, + { enableHighAccuracy: true } + ); +} + +defineExpose({ + openMapLocation +}) +</script> + +<style lang="scss" scoped> +.map { + width: 100%; + height: 500px; + + :deep(.BMap_cpyCtrl){ + display: none!important; + visibility: hidden!important; + } + + :deep(.anchorBL) { + display: none!important; + visibility: hidden!important; + } +} +.mapLocation_head{ + width:100%; + height:100px; +} +.mapLocation_body{ + width:100%; + height:500px +} +.mapLocation_latlng{ + padding-top:10px; + display:inline-block; + margin-right: 20px; +} +.mapLocation_latlng_input{ + width:250px; +} +</style> diff --git a/src/views/safetyReview/testManage/components/processCtrlReview.vue b/src/views/safetyReview/testManage/components/processCtrlReview.vue new file mode 100644 index 0000000..85ec8b9 --- /dev/null +++ b/src/views/safetyReview/testManage/components/processCtrlReview.vue @@ -0,0 +1,364 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="auditDate" label="审核日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.auditDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="processLeader.name" label="过程控制负责人"> + <el-input + v-model.trim="state.formData.processLeader.name" + size="large" + placeholder="请选择过程控制负责人" + @focus="openExperts('过程控制负责人')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('过程控制负责人')"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="isFullProcess" label="审核结论:是否满足过程控制要求"> + <el-radio-group v-model="state.formData.isFullProcess" > + <el-radio :label="1">是</el-radio> + <el-radio :label="0">否</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + <el-table :data="state.tableData" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="过程控制关键点" prop="content" header-align="center" :show-overflow-tooltip="true"/> + <el-table-column label="审核结果" header-align="center" class-name="small-padding fixed-width" width="175"> + <template #default="scope"> + <el-radio-group v-model="scope.row.status" @change="changeStatus(scope.row)"> + <el-radio :label="1">符合</el-radio> + <el-radio :label="0">不符合</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column label="不符合描述" header-align="center" class-name="small-padding fixed-width" width="700"> + <template #default="scope"> + <el-input + v-model.trim="scope.row.reason" + size="large" + :disabled="scope.row.status == 1" + placeholder="如不符合,请填写不符合描述" + /> + </template> + </el-table-column> + </el-table> + <el-form-item prop="suggestions" label="存在问题及建议"> + <el-input + v-model.trim="state.formData.suggestions" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-row :gutter="30"> + <el-col :span="18"> + <el-form-item label="附件上传" prop="assAccessoryFiles"> + <el-upload accept="image/*,.pdf,.doc,.docx,.xlsx,.xls" :action="state.uploadUrl" :data="{moduleType: 8,projectId: props.projectId}" :headers="state.header" method="post" :on-success="handleAvatarSuccess" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='1' v-model:file-list="state.fileList" :before-upload="picSize" :disabled="projectType === 'view' || isEnd" :on-remove="handleRemove" > + <el-button type="primary">附件上传</el-button> + <template #tip> + <div class="el-upload__tip">上传文件尺寸小于5M,最多可上传1份</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-dialog v-model="state.dialogImg"> + <el-image style="width: 100%; height: 100%" :src="state.dialogImageUrl"/> + </el-dialog> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {delFile, getFiles} from "@/api/projectManage/siteCheckRcd" +import {addProcessCtrl, editProcessCtrl,getProcessCtrlDetail} from "@/api/projectManage/processCtrl" +import {delPic} from "@/api/login" +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import ExpertsList from "./expertsList"; +import axios from "axios"; +import { useRoute } from 'vue-router' +const route = useRoute() +const props = defineProps(['projectId']) +const emit = defineEmits(["getNextStatus"]); + +const state = reactive({ + formData: { + id: null, + projectId: null, + auditDate: '', + processLeader: {name: ''}, + processLeaderId: null, + isFullProcess: null, + suggestions: '' + }, + rules: { + auditDate: [{required: true, message: '请选择审核日期', trigger: 'blur'}], + 'processLeader.name': [{required: true, message: '请选择过程控制负责人', trigger: 'change'}], + isFullProcess: [{required: true, message: '请选择审核结论', trigger: 'blur'}] + }, + tableData: [ + {id: 1, content: '风险分析', status: 1, key:'isRiskAnalyse', reasonKey: 'riskAnalyseDes', reason: ''}, + {id: 2, content: '签订合同', status: 1, key:'isSignContract', reasonKey: 'signContractDes', reason: ''}, + {id: 3, content: '评价任务通知书', status: 1, key:'isEstimateTask', reasonKey: 'estimateTaskDes', reason: ''}, + {id: 4, content: '编制安全评价项目计划书', status: 1, key:'isEstimatePlan', reasonKey: 'estimatePlanDes', reason: ''}, + {id: 5, content: '被评价单位提供材料清单', status: 1, key:'isProvideMaterials', reasonKey: 'provideMaterialsDes', reason: ''}, + {id: 6, content: '从业告知', status: 1, key:'isWorkNotification', reasonKey: 'workNotificationDes', reason: ''}, + {id: 7, content: '现场勘验记录及影像资料', status: 1, key:'isInvestigationSite', reasonKey: 'investigationSiteDes', reason: ''}, + {id: 8, content: '评价报告内部审核', status: 1, key:'isInteriorAudit', reasonKey: 'interiorAuditDes', reason: ''}, + {id: 9, content: '技术负责人审核', status: 1, key:'isTechnolgyAudit', reasonKey: 'technolgyAuditDes', reason: ''}, + {id: 6, content: '评价报告外审意见', status: 1, key:'isExteriorAudit', reasonKey: 'exteriorAuditDes', reason: ''}, + {id: 7, content: '评价项目网上信息公开', status: 1, key:'isOpenInformation', reasonKey: 'openInformationDes', reason: ''}, + // {id: 8, content: '二维码的使用', status: 1, key:'isUseQrcode', reasonKey: 'useQrcodeDes', reason: ''}, + {id: 9, content: '报告归档材料完整性', status: 1, key:'isFullMaterials', reasonKey: 'fullMaterialsDes', reason: ''} + ], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + disabled:false +}) + +const isAmin = ref(false) +const formRef = ref() +const expertsListRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + getProcessFiles(props.projectId) + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; +}) + +const projectType = ref(''); +const isEnd = ref('') +const riskOpen = async (type,val) => { + state.formData.projectId = val + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; + if(type === 'detail' || type === 'edit' ){ + if(type === 'detail'){ + state.disabled = true + } + const res = await getProcessCtrlDetail({projectId: val}); + if(res.code == 200){ + state.formData = res.data + state.formData.isFullProcess = res.data.isFullProcess==true?1:0 + for(let key in res.data){ + for(let item of state.tableData){ + if(item.key == key){ + item.status = res.data[key]==true?1:0 + } + if(item.reasonKey == key){ + item.reason = res.data[key] + } + } + } + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id,processLeader, ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + if(i.status == 1){ + i.reason = '' + }else{ + if(i.reason == ''){ + ElMessage.warning("请完善不符合项描述"); + return + } + } + data[i.key] = i.status + data[i.reasonKey] = i.reason + } + const res = await addProcessCtrl(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', val); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const {processLeader, ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + data[i.key] = i.status + data[i.reasonKey] = i.reason + if(i.status == 1){ + i.reason = '' + } + } + const res = await editProcessCtrl(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} +const changeStatus = (val) => { + if(val.status == 1 && val.reason != "") { + const index = state.tableData.findIndex(item => item.id == val.id) + state.tableData[index].reason = "" + } +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + state.formData.processLeader.name = obj.name + state.formData.processLeaderId = obj.id +} + +const getProcessFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 8}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.fileList = res.data.map(i=>{ + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + }else{ + state.fileList = [] + } + }else { + ElMessage.warning(res.message) + } +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handlePictureCardPreview = (uploadFile) => { + axios.get(uploadFile.url,{headers:{'Content-Type': 'application/json','Authorization': `${getToken()}`,'uid':`${Cookies.get('uid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + window.open(link.href) + } else { + ElMessage({ + type: 'warning', + message: '文件读取失败' + }); + } + }) +}; + + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + getProcessFiles() + }else{ + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const handleRemove = async (file, uploadFile) => { + if(file && file.status == 'success') { + ElMessageBox.confirm( + '确定删除该附件?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(async () => { + const res = await delFile(file.id) + if (res.code == 200) { + ElMessage({ + type: 'success', + message: '文件已删除' + }) + await getProcessFiles() + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } + }) + .catch(() => { + getProcessFiles() + }) + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/projectArchive.vue b/src/views/safetyReview/testManage/components/projectArchive.vue new file mode 100644 index 0000000..85aff7c --- /dev/null +++ b/src/views/safetyReview/testManage/components/projectArchive.vue @@ -0,0 +1,390 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="10"> +<!-- <el-button type="primary" :disabled="projectType === 'edit'" @click="addUpload">新增附件列表</el-button>--> + <span style="font-size: 20px;font-weight: 600">附件列表</span> + <span style="font-size: 13px;color: rgb(232, 78, 79);font-weight: 400;margin-left: 10px">项目列表仅支持pdf、jpg、jpeg 等格式上传</span> + </el-col> + </el-row> + <el-table :data="state.uploadList" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="名称" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <span type="text" size="large">{{scope.row.name}}</span> + </template> + </el-table-column> + <el-table-column label="是否必须文件" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-radio-group v-model="scope.row.type" > + <el-radio :label="1">是</el-radio> + <el-radio :label="0">否</el-radio> + </el-radio-group> + </template> + </el-table-column> + <el-table-column label="原因说明" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-input v-model="scope.row.remark" show-word-limit type="text" size="large" /> + </template> + </el-table-column> + <el-table-column label="附件上传" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-upload accept=".pdf,.doc,.docx" + :action="state.uploadUrl" + :disabled="projectType === 'view' || isEnd" + :headers="state.header" + method="post" + :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile,scope.row)" + v-model:file-list="scope.row.fileList" + :on-remove="handleRemove" + :data="state.uploadData" + :on-preview="handlePreview" + > + <el-button type="primary">附件上传</el-button> + </el-upload> + </template> + </el-table-column> +<!-- <el-table-column label="操作" align="center" class-name="small-padding fixed-width">--> +<!-- <template #default="scope">--> +<!-- <el-button link type="danger" @click="delUpload(scope.$index)">删除</el-button>--> +<!-- </template>--> +<!-- </el-table-column>--> + </el-table> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item label="合同签订日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.contractSignDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="18"> + <el-form-item prop="actualContractMoney"> + <template #label> + 项目合同额<span style="font-size: 13px;color: red;font-weight: normal;display: inline-block;margin-left: 6px">预估合同金额,归档阶段可以进行修改。仅支持数字,单位万元,小数点后最多两位,数值范围(0.01-999.99)</span> + </template> + <el-input + v-model.trim="state.actualContract.actualContractMoney" + @input="state.actualContract.actualContractMoney= state.actualContract.actualContractMoney.replace(/[^0-9.\/\-]/g,'')" + size="large" + placeholder="请输入项目合同额" + > + <template #append>万元</template> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-form-item label="实际合同额说明"> + <el-input + v-model.trim="state.actualContract.actualContractIntroduction" + :autosize="{ minRows: 6 }" + maxlength="100" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + </el-form> + </div> + +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import {addRecord, editRecord, getDetail} from "@/api/projectManage/contractMng"; +import Cookies from "js-cookie"; +import { getToken } from "@/utils/auth"; +import axios from "axios"; +import {delAccessoryFile, getAccessoryFile} from "@/api/projectManage/project"; +import {addProcessMaterial, getProcessMaterialDetail, editProcessMaterial} from "@/api/projectManage/riskAnalysis"; +import { useRoute } from 'vue-router' +const route = useRoute() +const props = defineProps(['projectId']) +const emit = defineEmits(["getNextStatus"]); +const state = reactive({ + formData: { + id: '', + contractSignDate: '', + + }, + actualContract: { + actualContractMoney: '', + actualContractIntroduction: '' + }, + uploadList: [ + { + name: '安全评价过程控制记录文档', + type: 1, + remark: '', + }, + { + name: '项目发票电子版', + type: 1, + remark: '', + }, + { + name: '项目转账记录/入账证明', + type: 1, + remark: '', + } + ], + rules: { + contractSignDate: [{required: true, message: '请选择合同签订日期', trigger: 'blur'}], + }, + fileList: [], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + uploadData: { + moduleType: 9 + }, +}) + +const isAmin = ref(false) +const formRef = ref(); +onMounted(async () => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(props.projectId){ + state.uploadData.projectId = props.projectId; + await getRecord(state.uploadData.projectId); + // const res = await getAccessoryFile({projectId: val,moduleType: 9}); + // console.log('res',res) + } + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; +}); + +const getRecord = async (val) =>{ + const res = await getDetail({projectId: val}); + if(res.code == 200){ + state.formData = res.data; + state.actualContract.actualContractMoney = res.data.actualContractMoney; + state.actualContract.actualContractIntroduction = res.data.actualContractIntroduction; + }else { + ElMessage.warning(res.message) + } +} + +const projectType = ref('') +const isEnd = ref('') +const riskOpen = async (type,val) => { + projectType.value = route.query.type; + isEnd.value = Cookies.get('end') + state.uploadData.projectId = val; + if(type === 'detail' || type === 'edit' ){ + const res = await getProcessMaterialDetail({projectId: val}); + if(res.code == 200){ + state.uploadList = res.data; + state.uploadList.forEach((item,index) => { + if(item.accessoryFile){ + item.accessoryFile.name = item.accessoryFile.originName + state.uploadList[index].fileList = [item.accessoryFile]; + } + }) + + console.log("res",state.uploadList) + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + + if(state.actualContract.actualContractMoney == '' || !state.actualContract.actualContractMoney) { + ElMessage.warning("请输入项目合同额"); + return; + } + console.log(state.uploadList,'state.uploadList') + const file = state.uploadList.map(item => { + return{ + id: item.id ? item.id : null, + fileId: item.fileList && item.fileList.length>0 ? item.fileList[0].response ? item.fileList[0].response.data.id : item.fileList[0].id : '', + name: item.name, + type: item.type, + remark: item.remark, + projectId: val + } + }) + + let isOk = false; + try{ + state.uploadList.forEach(item => { + if(item.type == 1 && (!item.fileList || item.fileList .length == 0) && item.remark == ""){ + isOk = true; + throw Error(); + } + }) + }catch (e) {} + + if(isOk){ + ElMessage.warning("请上传附件或完善原因说明!"); + return; + } + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + data.actualContractMoney = state.actualContract.actualContractMoney; + data.actualContractIntroduction = state.actualContract.actualContractIntroduction; + const params = { + projectId: val, + projectMaterials: file, + contract: data + } + console.log("params",params) + if(type === 'add'){ + const res = await addProcessMaterial(params); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', val); + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const res = await editProcessMaterial(params); + if (res.code == 200) { + ElMessage.success('变更成功') + projectType.value='edit'; + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + + +const addUpload = ()=>{ + let file = { + name: '', + type: 1, + remark: '', + } + state.uploadList.push(file) +} + +const delUpload = (index)=>{ + state.uploadList.splice(index,1) +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handleAvatarSuccess = (res, uploadFile,val) => { + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '文件上传成功' + }) + }else { + const delVal = state.uploadList.findIndex(i => i.id === val.id); + state.uploadList[delVal].fileList.splice(state.uploadList[delVal].fileList.indexOf(uploadFile),1) + ElMessage({ + type: 'warning', + message: res.message + }) + } +} + +const handlePreview = (file) => { + let path = ""; + if(file.path){ + path = file.path + }else { + path = file.response.data.path + + } + const url = import.meta.env.VITE_APP_BASE_API + '/' + path + axios.get( url,{ + headers: + { + 'Content-Type': 'application/json', + 'Authorization':getToken(), + }, + responseType: 'blob' + } + ).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", file.name); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) +} + +const handleRemove = async (file, uploadFiles) => { + if (file && file.status == 'success') { + console.log("file", file) + let accessoryFileId = ""; + if (file.id) { + accessoryFileId = file.id + } else { + accessoryFileId = file.response.data.id + + } + const res = await delAccessoryFile(accessoryFileId) + if (res.code == 200) { + // ElMessage({ + // type: 'success', + // message: '文件已删除' + // }) + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } +} +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/rateConclusion.vue b/src/views/safetyReview/testManage/components/rateConclusion.vue new file mode 100644 index 0000000..d8ce84c --- /dev/null +++ b/src/views/safetyReview/testManage/components/rateConclusion.vue @@ -0,0 +1,311 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-form-item prop="conclusion" label="评价结论"> + <el-input + v-model.trim="state.formData.conclusion" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-row :gutter="30"> + <el-col :span="9"> + <el-form-item prop="isReviseManual" label="评价报告修改说明"> +<!-- <el-radio-group v-model="state.formData.isReviseManual" >--> +<!-- <el-radio :label="1">是</el-radio>--> +<!-- <el-radio :label="0">否</el-radio>--> +<!-- </el-radio-group>--> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="18"> + <el-form-item> + <el-upload + accept="image/*,.pdf,.doc,.docx,.xlsx,.xls" + :action="state.uploadUrl" + :disabled="projectType === 'view' || isEnd" + :headers="state.header" + method="post" + :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile)" + :on-exceed="showTip" + v-model:file-list="state.fileList" + :on-remove="handleRemove" + :data="state.uploadData" + :on-preview="handlePreview" + :limit='15' + :before-upload="picSize" + > + <el-button type="primary">评价报告上传</el-button> + <template #tip> + <div class="el-upload__tip">上传文件尺寸小于15M,最多可上传15份,多张图片建议合并为PDF文件规范上传。</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + </el-form> + </div> +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {addRate, addRisk, editRate, editRisk, getRateDetail, getRiskDetail} from "@/api/projectManage/riskAnalysis" +import {delPic} from "@/api/login" +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import {delAccessoryFile, getAccessoryFile} from "@/api/projectManage/project"; +import axios from "axios"; +import {delFile, getFiles} from "@/api/projectManage/siteCheckRcd"; +import { useRoute } from 'vue-router' +const route = useRoute() +const emit = defineEmits(["getNextStatus"]); +const prop = defineProps(['projectId']) +const state = reactive({ + formData: { + isReviseManual: 1, + }, + rules: { + conclusion: [{required: true, message: '请输入评价结论', trigger: 'blur'}], + }, + imgLimit: 3, + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + fileList: [], + uploadData: { + moduleType: 7 + }, + disabled: false +}) +const props = { + expandTrigger: 'hover', + value: 'name', + label: 'name' +} +const isAmin = ref(false) +const formRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(prop.projectId){ + const val = prop.projectId; + state.uploadData.projectId = val; + getProcessFiles(val); + } + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; +}) + +const projectType = ref(''); +const isEnd = ref('') +const riskOpen = async (type,val) => { + state.uploadData.projectId = val; + projectType.value = route.query.type; + isEnd.value = Cookies.get('end') + if(type === 'detail' || type === 'edit' ){ + if(type === 'detail'){ + state.disabled = true + } + const res = await getRateDetail({projectId: val}); + if(res.code == 200){ + if(res.data){ + state.formData = res.data; + state.formData.isReviseManual = res.data.isReviseManual ? 1 : 0 + state.fileList = res.data.accessoryFiles.map(item => { + return { + ...item, + name: item.originName, + } + }) + } + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(state.fileList && state.fileList.length<=0 ){ + ElMessage.warning('请上传评价报告') + return + } + + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id,attachments, ...data} = JSON.parse(JSON.stringify(state.formData)) + data.projectId = val; + data.accessoryFiles = state.fileList + const res = await addRate(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', val); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { attachments, ...data} = JSON.parse(JSON.stringify(state.formData)) + data.accessoryFiles = state.fileList + const res = await editRate(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +// 上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 15){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过15M' + }); + return false + } +}; + +const handleAvatarSuccess = (res,uploadFile) => { + if(res.code === 200){ + getProcessFiles() + ElMessage({ + type: 'success', + message: '文件上传成功' + }) + }else { + state.fileList.splice(state.fileList.indexOf(uploadFile),1) + ElMessage({ + type: 'warning', + message: res.message + }) + } + +} +const handlePreview = (file) => { + let path = ""; + if(file.path){ + path = file.path + }else { + path = file.response.data.path + + } + const url = import.meta.env.VITE_APP_BASE_API + '/' + path + axios.get( url,{ + headers: + { + 'Content-Type': 'application/json', + 'Authorization':getToken(), + }, + responseType: 'blob' + } + ).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + link.setAttribute("download", file.name); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } else { + this.$message.error('获取文件失败') + } + }) +} +const getProcessFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : prop.projectId ,moduleType: 7}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.fileList = res.data.map(i=>{ + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + }else{ + state.fileList = [] + } + }else { + ElMessage.warning(res.message) + } +} + +const handleRemove = async (file, uploadFiles) => { + if (file && file.status === 'success') { + ElMessageBox.confirm( + '确定删除该附件?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(async () => { + let accessoryFileId = ""; + if (file.id) { + accessoryFileId = file.id + } else { + accessoryFileId = file.response.data.id + } + const res = await delAccessoryFile(accessoryFileId) + if (res.code == 200) { + ElMessage({ + type: 'success', + message: '文件已删除' + }) + await getProcessFiles() + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } + }) + .catch(() => { + getProcessFiles() + }) + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/riskAnalysis.vue b/src/views/safetyReview/testManage/components/riskAnalysis.vue new file mode 100644 index 0000000..0010859 --- /dev/null +++ b/src/views/safetyReview/testManage/components/riskAnalysis.vue @@ -0,0 +1,474 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="project.name" label="项目名称"> + <el-input + maxlength="100" + show-word-limit + v-model.trim="state.formData.project.name" + size="large" + placeholder="请输入项目名称" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.client" label="委托单位"> + <el-input + v-model.trim="state.formData.project.client" + + size="large" + placeholder="请输入委托单位" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.creditCode" label="委托单位统一社会信用代码"> + <el-input + v-model.trim="state.formData.project.creditCode" + size="large" + placeholder="请输入委托单位统一社会信用代码" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.address" label="详细地址"> + <el-input + maxlength="100" + show-word-limit + v-model.trim="state.formData.project.address" + size="large" + placeholder="请输入详细地址" + > + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="project.estimateType" label="类型"> + <el-input v-model="state.formData.project.estimateType" disabled></el-input> +<!-- <el-select v-model="state.formData.project.estimateType" class="m-2" size="large" placeholder="请选择" style="width: 100%" >--> +<!-- <el-option--> +<!-- v-for="item in state.estimateTypeList"--> +<!-- :key="item.id"--> +<!-- :label="item.label"--> +<!-- :value="item.id"--> +<!-- />--> +<!-- </el-select>--> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.code" label="项目编号"> + <el-input + v-model.trim="state.formData.project.code" + size="large" + placeholder="请输入项目编号" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.invest" label="项目投资金额"> + <el-input + @input="state.formData.project.invest= state.formData.project.invest.replace(/[^0-9.\/\-]/g,'')" + v-model.trim="state.formData.project.invest" + size="large" + placeholder="请输入项目投资金额" + > + <template #append>万元</template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="project.area" label="所属区域"> + <el-cascader + v-model="state.formData.project.area" + :options="state.addressList" + :props="props" + @change="handleChange" + style="width: 100%" + size="large" + /> + </el-form-item> + </el-col> + </el-row> + <el-row el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="project.business" label="业务范围"> + <el-select v-model="state.formData.project.business" class="m-2" size="large" placeholder="请选择" style="width: 100%" > + <el-option + v-for="item in state.businessList" + :key="item.id" + :label="item.label" + :value="item.id" + /> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-form-item prop="project.introduction" label="基本概括"> + <el-input + v-model.trim="state.formData.project.introduction" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-form-item prop="riskCharacter" label="行业风险特性"> + <el-input + v-model.trim="state.formData.riskCharacter" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-form-item prop="surroundings" label="周边环境"> + <el-input + v-model.trim="state.formData.surroundings" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-form-item prop="equipment" label="主要生产装置"> + <el-input + v-model.trim="state.formData.equipment" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-form-item prop="technology" label="生产工艺概况"> + <el-input + v-model="state.formData.technology" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + <el-table :data="state.tableData" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="内容" prop="content" header-align="center" :show-overflow-tooltip="true"/> + <el-table-column label="选择" header-align="center" class-name="small-padding fixed-width" width="175"> + <template #default="scope"> + <el-radio-group v-model="scope.row.status" > + <el-radio :label="1">{{scope.row.id ==='6' ? '可行': '是'}}</el-radio> + <el-radio :label="0">{{scope.row.id ==='6' ? '不可行': '否'}}</el-radio> + </el-radio-group> + </template> + </el-table-column> + </el-table> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="estimateDate" label="评估日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.estimateDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="techOpinion" label="技术负责人意见"> + <el-input + v-model="state.formData.techOpinion" + size="large" + maxlength="30" + show-word-limit + placeholder="技术负责人意见" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="riskOpinion" label="风险评估人意见"> + <el-input + v-model="state.formData.riskOpinion" + size="large" + maxlength="30" + show-word-limit + placeholder="风险评估人意见" + > + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="agencyOpinon" label="机构评价负责人意见"> + <el-input + maxlength="30" + show-word-limit + v-model="state.formData.agencyOpinon" + size="large" + placeholder="机构评价负责人意见" + > + </el-input> + </el-form-item> + </el-col> + </el-row> + + </el-form> + </div> + +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {getDictList} from "@/api/backManage/evaluate"; +import {ElMessage} from "element-plus"; +import {getDict} from "@/api/login"; +import {getRegionTree} from "@/api/area"; +import {addRisk, editRisk, getRiskDetail} from "@/api/projectManage/riskAnalysis"; +import Cookies from "js-cookie"; +const emit = defineEmits(["getNextStatus"]); + +const isAmin = ref(false) +const formRef = ref(); +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + // getRiskList(); + getBusinessList(); + getArea(); +}); +const state = reactive({ + formData: { + project: { + id: '', + name: '', + client: '', + creditCode: '', + address:'', + estimateType: '检验检测', + code: '', + invest: '', + area: [], + district: '', + city: '', + province: '', + business: '', + introduction: '', + }, + id: '', + riskCharacter: '', + surroundings: '', + equipment: '', + technology: '', + isInBusiness: true, + isSatisfyNeed: true, + isNeedExpert: true, + isFinishReport: true, + isAcceptChargess: true, + isFeasibility: true, + estimateDate: '', + techOpinion: '', + riskOpinion: '', + agencyOpinon: '' + }, + rules: { + "project.name": [{required: true, message: '请填写项目名称', trigger: 'blur'}], + "project.client": [{required: true, message: '请填写委托单位', trigger: 'blur'}], + "project.creditCode": [{required: true, message: '请填写委托单位统一社会信用代码', trigger: 'blur'}], + // "project.estimateType": [{required: true, message: '请选择类型', trigger: 'blur'}], + "project.address": [{required: true, message: '请填写详细地址', trigger: 'blur'}], + "project.invest": [{required: true, message: '请填写投资金额', trigger: 'blur'}], + "project.area": [{required: true, message: '请选择所属区域', trigger: 'blur'}], + "project.business": [{required: true, message: '请选择业务范围', trigger: 'blur'}], + "project.introduction": [{required: true, message: '请填写基本概况', trigger: 'blur'}], + riskCharacter: [{required: true, message: '请填写行业风险特性', trigger: 'blur'}], + surroundings: [{required: true, message: '请填写周边环境', trigger: 'blur'}], + estimateDate: [{required: true, message: '请选择评估日期', trigger: 'blur'}], + techOpinion: [{required: true, message: '请填写技术负责人意见', trigger: 'blur'}], + riskOpinion: [{required: true, message: '请填写风险评估人意见', trigger: 'blur'}], + agencyOpinon: [{required: true, message: '请填写机构评价负责人意见', trigger: 'blur'}], + }, + estimateTypeList: [], + addressList: [], + businessList: [], + tableData: [ + { + id: '1', + content: '评价项目是否在本机构资质业务范围内', + status: 1 + }, + { + id: '2', + content: '评价人员专业构成是否满足评价项目需要', + status: 1 + }, + { + id: '3', + content: '是否需要聘请相关专业的技术专家', + status: 1 + }, + { + id: '4', + content: '是否能在约定的时间内完成评价报告', + status: 1 + }, + { + id: '5', + content: '评价费用是否在本机构所接受的范围内', + status: 1 + }, + { + id: '6', + content: '项目的可行性(风险分析结论)', + status: 1 + }, + ] +}) +const props = { + expandTrigger: 'hover', + value: 'name', + label: 'name' +} + + +// const getRiskList = async () => { +// const res = await getDictList({dictType: "sys_assess_type"}); +// if(res.code === 200){ +// state.estimateTypeList = res.data.list +// }else{ +// ElMessage.warning(res.message) +// } +// } +const getBusinessList = async () => { + const res = await getDict({dictType: 'sys_business_scope'}) + if(res.code === 200){ + state.businessList = res.data + }else{ + ElMessage.warning(res.message) + } +} +const getArea = async ()=>{ + const type = 1 + const res = await getRegionTree({name: '',parentId: null,regionType: type}) + if(res.code == 200){ + state.addressList = res.data + }else{ + ElMessage.warning(res.message) + } +} +const riskOpen = async (type,val) => { + console.log("type",type,val) + if(type === 'detail' || type === 'edit' ){ + const res = await getRiskDetail({projectId: val}); + if(res.code == 200){ + state.formData = res.data; + state.formData.project.estimateType = '检验检测' + state.formData.project.business = parseInt(res.data.project.business); + if(res.data.project.province == '北京市' || res.data.project.province == '天津市' || res.data.project.province == '上海市' || res.data.project.province == '重庆市' || res.data.project.province == '香港特别行政区' || res.data.project.province == '澳门特别行政区'){ + state.formData.project.area = [res.data.project.province] + }else{ + state.formData.project.area = [res.data.project.province,res.data.project.city]; + } + state.tableData[0].status = res.data.isInBusiness ? 1 : 0; + state.tableData[1].status = res.data.isSatisfyNeed ? 1 : 0; + state.tableData[2].status = res.data.isNeedExpert ? 1 : 0; + state.tableData[3].status = res.data.isFinishReport ? 1 : 0; + state.tableData[4].status = res.data.isAcceptChargess ? 1 : 0; + state.tableData[5].status = res.data.isFeasibility ? 1 : 0; + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + state.formData.project.estimateType = 33 + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + delete data.project.area; + delete data.project.id; + if(data.project.province == '北京市' || data.project.province == '天津市' || data.project.province == '上海市' || data.project.province == '重庆市' || data.project.province == '香港特别行政区' || data.project.province == '澳门特别行政区'){ + data.project.city = data.project.province + } + data.isInBusiness = state.tableData[0].status === 1; + data.isSatisfyNeed = state.tableData[1].status === 1; + data.isNeedExpert = state.tableData[2].status === 1; + data.isFinishReport = state.tableData[3].status === 1; + data.isAcceptChargess = state.tableData[4].status === 1; + data.isFeasibility = state.tableData[5].status === 1; + const res = await addRisk(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', res.data); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + data.id = val; + data.project.id = val; + if(data.project.province == '北京市' || data.project.province == '天津市' || data.project.province == '上海市' || data.project.province == '重庆市' || data.project.province == '香港特别行政区' || data.project.province == '澳门特别行政区'){ + data.project.city = data.project.province + } + delete data.project.area; + data.isInBusiness = state.tableData[0].status === 1 + data.isSatisfyNeed = state.tableData[1].status === 1 + data.isNeedExpert = state.tableData[2].status === 1 + data.isFinishReport = state.tableData[3].status === 1 + data.isAcceptChargess = state.tableData[4].status === 1 + data.isFeasibility = state.tableData[5].status === 1 + const res = await editRisk(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const handleChange = (value) => { + // if(state.registerForm.agency.attribute == 0){ + // state.registerForm.agency.province = '新疆维吾尔自治区' + // state.registerForm.agency.city = value[0]?value[0]:'' + // state.registerForm.agency.district = value[1]?value[1]:'' + // }else{ + state.formData.project.province = value[0]?value[0]:'' + state.formData.project.city = value[1]?value[1]:'' + state.formData.project.district = value[2]?value[2]:'' + // } +} + + + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/signConfirm.vue b/src/views/safetyReview/testManage/components/signConfirm.vue new file mode 100644 index 0000000..d0b7d93 --- /dev/null +++ b/src/views/safetyReview/testManage/components/signConfirm.vue @@ -0,0 +1,184 @@ +<template> + <div class="riskBox"> + <el-table v-loading="loading" ref="tableRef" :data="tableData" :border="true" style="margin-top: 20px"> + <el-table-column label="序号" type="index" width="55" /> + <el-table-column label="人员姓名" prop="planPerson.person.name" align="center"/> + <el-table-column label="联系电话" prop="planPerson.person.phone" align="center"/> + <el-table-column label="职位" prop="planPerson.person.post" align="center"/> + <el-table-column label="项目担任角色" prop="username" align="center" width="180"> + <template #default="scope"> + <div v-for="(item,index) in scope.row.playRolesName" :key="index"> + <span>{{item.roleName}}</span><span v-if="index!==scope.row.playRolesName.length-1">,</span> + </div> + </template> + </el-table-column> + <el-table-column label="评价师等级" prop="planPerson.person.level" align="center"/> + <el-table-column label="专业能力" prop="planPerson.person.majorNames" align="center"/> + <el-table-column label="工作类型" align="center"> + <template #default="scope"> + <span>{{scope.row.planPerson.jobType === 1 ? '普通人员' : scope.row.planPerson.jobType === 2?'组长': ''}}</span> + </template> + </el-table-column> + <el-table-column label="扫脸时间" prop="faceRecord.updateTime" align="center" width="120"/> + <el-table-column label="是否扫脸" prop="username" align="center"> + <template #default="scope"> + <span v-if="scope.row.facePic.length>0">是</span> + <span v-else>否</span> + </template> + </el-table-column> +<!-- <el-table-column label="是否变更" prop="username" align="center"/>--> + <el-table-column label="人脸照片" prop="socialSecurity" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.facePic && scope.row.facePic.length>0"> + <el-image + style="width: 100px; height: 100px" + :src= "scope.row.facePic[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.facePic" + :initial-index="0" + fit="cover" + :preview-teleported=true + /> + </div> + </template> + </el-table-column> + <el-table-column label="签字图片" prop="socialSecurity" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.signPic && scope.row.signPic.length>0"> + <el-image + style="width: 100px; height: 100px" + :src= "scope.row.signPic[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.signPic" + :initial-index="0" + fit="cover" + :preview-teleported=true + /> + </div> + </template> + </el-table-column> + <el-table-column label="承诺书" prop="socialSecurity" align="center" width="120"> + <template #default="scope"> + <div class="demo-image__preview" v-if="scope.row.commitPic && scope.row.commitPic.length>0"> + <el-image + style="width: 100px; height: 100px" + :src= "scope.row.commitPic[0]" + :zoom-rate="1.2" + :max-scale="7" + :min-scale="0.2" + :preview-src-list="scope.row.commitPic" + :initial-index="0" + fit="cover" + :preview-teleported=true + /> + </div> + </template> + </el-table-column> + </el-table> + </div> +</template> +<script setup> + +import {defineEmits, defineProps, onMounted, reactive, ref, toRefs} from "vue"; +import {ElMessage} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import { + addFaceRecognition, + addRisk, checkAll, + editRisk, + getRecognitionDetail, + getRiskDetail +} from "@/api/projectManage/riskAnalysis" +import {delPic} from "@/api/login" +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import {getDetail} from "@/api/projectManage/contractMng"; +const emit = defineEmits(["getNextStatus"]); +const props = defineProps(['projectId']) +const state = reactive({ + loading: false, + queryParams: { + pageNum: 1, + pageSize: 10, + }, + total: 0, + tableData: [] +}) + +const {loading,queryParams,total,tableData} = toRefs(state) + +const isAmin = ref(false) +const formRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(props.projectId){ + getRecognition(props.projectId); + } +}) +const getRecognition = async (val) =>{ + const res = await getRecognitionDetail({projectId: val}); + if(res.code == 200){ + state.tableData = res.data.map(item => { + return { + ...item, + facePic: item.faceRecord.facePath ? [import.meta.env.VITE_APP_BASE_API + '/' + item.faceRecord.facePath ] : [], + signPic: item.signPath ? [import.meta.env.VITE_APP_BASE_API + '/' + item.signPath] : [], + commitPic: item.insurancePath ? [import.meta.env.VITE_APP_BASE_API + '/' + item.insurancePath] : [], + playRolesName: item.planPerson.playRoles.map(role => { + const roleName = role === 1?'项目负责人':role === 2? '项目组成员':role === 3? '过程控制负责人':role === 4? '机构评价负责人':role === 5? '技术负责人':role === 6?'内部审核员':'' + return{ + roleName + } + }) + } + }) + console.log("res", state.tableData) + }else { + ElMessage.warning(res.message) + } +} + + + +const riskOpen = async (type,val) => { + // if((type === 'detail' || type === 'edit') && !props.projectId){ + // getRecognition(val); + // } + if(type === 'add' || type === 'clickEdit') { + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const res = await addFaceRecognition({projectId: val}); + if (res.code == 200) { + ElMessage.success('保存成功') + emit('getNextStatus', val); + } else { + ElMessage.warning(res.message) + } + } + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/siteCheckRcd.vue b/src/views/safetyReview/testManage/components/siteCheckRcd.vue new file mode 100644 index 0000000..97d1178 --- /dev/null +++ b/src/views/safetyReview/testManage/components/siteCheckRcd.vue @@ -0,0 +1,693 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30" style="margin-bottom: 20px"> + <el-col :span="28"> + <el-alert title="说明:现场勘验记录由项目组成员通过APP端进行信息填报,组长完成现场勘验并在APP端提交后,电脑可对资料信息完善并进行下一步操作。" type="warning" /> + </el-col> +<!-- <el-col :span="6" style="display:flex;justify-content: right">--> +<!-- <el-button type="primary">全部查看</el-button>--> +<!-- <el-button type="primary">全部下载</el-button>--> +<!-- </el-col>--> + </el-row> + <el-row :gutter="30" style="margin-bottom: 30px" v-if="state.data.length>0"> + <el-col :span="28"> + <div style="display: flex;align-items: center"> + <span style="font-size: 22px;font-weight: 600;margin-top: 10px;">记录编号:{{ chooseItem.index }}(提交时间:{{chooseItem.createTime}})</span> + <div style="display: flex;align-items: center;flex-wrap: wrap"> + <div v-for="(item,index) in state.data"> + <el-check-tag style="margin-left: 20px;margin-top:10px;cursor: pointer;padding: 15px 25px" :checked="chooseItem.id === item.id" size="large" @click="chooseRecord(item,index)">记录编号{{ index+1 }}</el-check-tag> + </div> + </div> + </div> + + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="investigationDate" label="现场勘验时间"> + <el-date-picker + style="width: 100%" + v-model="state.formData.investigationDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item prop="location" label="现场勘验位置"> + <el-input + v-model.trim="state.formData.location" + size="large" + placeholder="请填写现场勘验位置" + @focus="openLocation" + > + + <template #append> + <el-button :icon="Search" @click="openLocation"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="isSafetyCheck" label="编制现场安全检查表"> + <el-radio-group v-model="state.formData.isSafetyCheck" size="large" @change="changeRadio" :disabled="projectType==='view' || isEnd"> + <el-radio :label="1" size="large">是</el-radio> + <el-radio :label="0" size="large">否</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + <el-row :gutter="30"> + <el-col :span="24" v-if="state.formData.isSafetyCheck == 1"> + <el-form-item label="安全检查表上传" prop="assAccessoryFiles"> + <el-upload :disabled="projectType==='view' || isEnd" accept="image/*,.pdf,.doc,.docx,.xlsx,.xls" :action="state.uploadUrl" :data="{moduleType: 5,projectId: props.projectId}" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile,5)" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='1' v-model:file-list="state.safetyList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles,5)"> + <el-button type="primary">附件上传</el-button> + <template #tip> + <div class="el-upload__tip">上传文件尺寸小于5M,最多可上传1份</div> + </template> + </el-upload> + </el-form-item> + </el-col> + <el-col :span="24" v-if="state.formData.isSafetyCheck == 0"> + <el-form-item prop="recordData" label="现场勘验记录"> + <el-input + v-model.trim="state.formData.recordData" + :autosize="{ minRows: 6 }" + maxlength="200" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + </el-col> + </el-row> + <el-row style="border: 1px dashed #999;border-radius: 4px;padding: 10px;margin-top: 20px"> + <el-col :span="24"> + <el-form-item label="主要装置前合影照片" prop="deviceImages"> + <el-upload accept="image/*" :disabled="projectType === 'view' || isEnd" :action="state.uploadUrl" :data="{moduleType: 1,projectId: props.projectId}" list-type="picture-card" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile,1)" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='10' v-model:file-list="state.beforeDeviceList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles,1)" > + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传照片尺寸小于5M,最多可上传10张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row style="border: 1px dashed #999;border-radius: 4px;padding: 10px;margin-top: 20px"> + <el-col :span="24"> + <el-form-item label="现场勘验照片" prop="investingationImages"> + <el-upload accept="image/*" :disabled="projectType === 'view' || isEnd" :action="state.uploadUrl" :data="{moduleType: 2,projectId: props.projectId}" list-type="picture-card" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile,2)" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='10' v-model:file-list="state.siteCheckList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles,2)" > + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传照片尺寸小于5M,最多可上传10张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-row style="border: 1px dashed #999;border-radius: 4px;padding: 10px;margin-top: 20px;margin-bottom: 20px"> + <el-col :span="24"> + <el-form-item label="企业陪同人员照片" prop="companyImages"> + <el-upload :disabled="projectType === 'view' || isEnd" accept="image/*" :action="state.uploadUrl" :data="{moduleType: 3,projectId: props.projectId}" list-type="picture-card" :headers="state.header" method="post" :on-success="(res, uploadFile)=>handleAvatarSuccess(res, uploadFile,3)" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='10' v-model:file-list="state.companyList" :before-upload="picSize" :on-remove="(file, uploadFiles)=>handleRemove(file, uploadFiles,3)" > + <el-icon><Plus /></el-icon> + <template #tip> + <div class="el-upload__tip">上传照片尺寸小于5M,最多可上传10张</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + </el-form> + <el-dialog v-model="state.imgDialog"> + <img style="width: 100%" :src="state.imgUrl" alt="Preview Image" /> + </el-dialog> + <map-location ref="mapLocationRef" @giveLatLng="achieveLatLng"></map-location> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue" +import {ElMessage, ElMessageBox} from "element-plus" +import {Search} from '@element-plus/icons-vue' +import { + addSiteCheck, + editSiteCheck, + getSiteCheckDetail, + delFile, + getFiles, + getDetailById, doSiteCheck +} from "@/api/projectManage/siteCheckRcd"; +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import { useRoute } from 'vue-router' +const route = useRoute() +const props = defineProps(['projectId']) +const emit = defineEmits(["getNextStatus"]) +import MapLocation from "./mapLocation.vue" +const direction = ref('rtl'); +const size = ref('400px') +const showDrawer = ref(false); +let checkSafetyFiles = (rule, value, callback)=>{ + if(state.safetyList.length === 0){ + callback(new Error('请上传现场安全检查表')) + }else{ + callback() + } +} + +let checkInvestFiles = (rule, value, callback)=>{ + if(state.siteCheckList.length === 0){ + callback(new Error('请上传现场勘验照片')) + }else{ + callback() + } +} + +let checkCompanyFiles = (rule, value, callback)=>{ + if(state.companyList.length === 0){ + callback(new Error('请上传企业陪同人员照片')) + }else{ + callback() + } +} + + + +const state = reactive({ + data: [], + formData: { + id: null, + projectId: null, + investigationDate: '', + location: '', + isSafetyCheck: null, + recordData: '', + assAccessoryFiles: [], + deviceImages: [], + investingationImages: [], + companyImages:[] + }, + projectId: null, + planPersons: [], + rules: { + investigationDate: [{required: true, message: '请选择现场勘验时间', trigger: 'blur'}], + location: [{required: true, message: '请选择现场勘验位置', trigger: 'change'}], + isSafetyCheck: [{required: true, message: '请选择是否编制现场安全检查表', trigger: 'blur'}], + recordData: [{required: true, message: '请填写现场勘验记录', trigger: 'blur'}], + assAccessoryFiles: [{required: true, validator: checkSafetyFiles, trigger: 'blur'}], + // investingationImages: [{required: true, validator: checkInvestFiles, trigger: 'blur'}], + // ccompanyImages: [{required: true, validator: checkCompanyFiles, trigger: 'blur'}] + }, + beforeDeviceList: [], + siteCheckList: [], + companyList: [], + safetyList: [], + imgLimit: 1, + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + imgDialog: false, + imgUrl: '' +}) + +const isAmin = ref(false) +const formRef = ref() +const mapLocationRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + if(props.projectId){ + getDetail(props.projectId) + } + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; + +}); + +const chooseRecord = async (item, index) => { + state.formData = item; + state.data.forEach((i,index) => { + if(i.id === item.id){ + chooseItem.value = i; + chooseItem.value.index = index+1; + + } + }) + await getPicDetail(item.id); + showDrawer.value = false; +} + +const chooseItem = ref(); +const getDetail = async (val) => { + const res = await getSiteCheckDetail({projectId: val}); + if(res.code == 200){ + if(res.data && res.data.length > 0){ + Cookies.set('btn','变更') + state.data = res.data; + state.formData = res.data[0]; + chooseItem.value = state.formData; + chooseItem.value.index = 1; + + await getPicDetail(state.formData.id) + }else { + Cookies.set('btn','保存') + } + + }else { + ElMessage.warning(res.message) + } +} +const getPicDetail = async (val) => { + const res = await getDetailById(val); + if(res.code == 200){ + if(res.data){ + state.formData = res.data; + doPic(res.data) + } + }else { + ElMessage.warning(res.message) + } +} + +const doPic = (val) => { + state.beforeDeviceList = val.deviceImages?.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.siteCheckList = val.investingationImages?.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.companyList = val.companyImages?.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.safetyList = val.assAccessoryFiles?.map(i=>{ + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) +} + +const changeRadio = () => { + if(state.formData.isSafetyCheck == 1){ + getSafetyFiles() + } +} + +const projectType = ref(''); +const isEnd = ref('') +const riskOpen = async (type,val) => { + state.formData.projectId = val + isEnd.value = Cookies.get('end') + state.projectId = val + projectType.value = route.query.type; + if(type === 'sixEnd') { + const res = await doSiteCheck({projectId: val}); + if(res.code == 200) { + emit('getNextStatus', val); + }else { + ElMessage.warning(res.message) + } + } + if(type === 'detail' || type === 'edit' ){ + // await getDetail(val) + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + if(!state.data.length >0){ + await saveData(val); + }else { + await editData(); + } + }else if(type === 'clickEdit'){ + await editData(); + } + } + } +} + +const saveData = async (val) => { + + if(state.formData.isSafetyCheck == 1){ + state.formData.recordData = '' + } + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await addSiteCheck(data); + if (res.code == 200) { + ElMessage.success('保存成功') + // const res = await doSiteCheck({projectId: val}); + // if(res.code == 200) { + if(state.formData.isSafetyCheck == 0){ + if(state.safetyList && state.safetyList.length >0){ + console.log('删除原有附件',state.safetyList[0]) + let id = state.safetyList[0].response.data.id + const res = await delFile(id) + if(res.code == 200){ + console.log('删除原有附件') + await getSafetyFiles() + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } + } + } + await getDetail(val) + formRef.value.clearValidate(); + // emit('getNextStatus', val); + // }else { + // ElMessage.warning(res.message) + // } + + } else { + ElMessage.warning(res.message) + } +} +const editData = async () => { + + if(state.formData.isSafetyCheck == 1){ + state.formData.recordData = '' + } + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + const res = await editSiteCheck(data); + if (res.code == 200) { + ElMessage.success('变更成功') + if(state.formData.isSafetyCheck == 0 && state.safetyList.length>0){ + const res = await delFile(state.safetyList[0].id) + if(res.code == 200){ + await getSafetyFiles() + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } + } + await getPicDetail(chooseItem.value.id) + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } +} + + +const getBeforeFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 1,processId:chooseItem.value.id }) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.beforeDeviceList = res.data.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + processId: state.formData.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.formData.deviceImages = state.beforeDeviceList; + }else{ + state.beforeDeviceList=[] + } + }else { + ElMessage.warning(res.message) + } +} + +const getSiteCheckFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 2,processId:chooseItem.value.id}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.siteCheckList = res.data.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + processId: state.formData.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.formData.investingationImages = state.siteCheckList; + }else{ + state.siteCheckList = [] + } + }else { + ElMessage.warning(res.message) + } +} + +const getCompanyFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 3,processId:chooseItem.value.id}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.companyList = res.data.map(i=>{ + return { + name: i.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + processId: state.formData.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.formData.companyImages = state.companyList; + }else{ + state.companyList=[] + } + }else { + ElMessage.warning(res.message) + } +} + +const getSafetyFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 5,processId: chooseItem.value? chooseItem.value.id:''}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.safetyList = res.data.map(i=>{ + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + processId: state.formData.id, + projectId: i.projectId, + moduleType: i.moduleType + } + }) + state.formData.assAccessoryFiles = state.safetyList + }else{ + state.safetyList = [] + } + }else { + ElMessage.warning(res.message) + } +} + +const openLocation = ()=>{ + mapLocationRef.value.openMapLocation(state.formData.location.split(',')[0],state.formData.location.split(',')[1]) +} + +const achieveLatLng=(lng,lat)=>{ + if(lng && lat){ + state.formData.location = lng + ',' + lat + }else { + ElMessage.warning('请选择勘验位置') + } + +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handlePictureCardPreview = (uploadFile) => { + console.log(uploadFile,'file') + state.imgUrl = uploadFile.url + state.imgDialog = true +}; + + +const handleAvatarSuccess = (res, uploadFile, type) => { + if(res.code == 200){ + if(type == 1){ + let obj = { + name: res.data.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + res.data.path, + id: res.data.id, + processId: state.formData.id, + projectId: res.data.projectId, + moduleType: res.data.moduleType + } + state.formData.deviceImages.push(obj); + // getBeforeFiles() + } + if(type == 2){ + let obj = { + name: res.data.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + res.data.path, + id: res.data.id, + processId: state.formData.id, + projectId: res.data.projectId, + moduleType: res.data.moduleType + } + state.formData.investingationImages.push(obj); + // getSiteCheckFiles() + } + if(type == 3){ + let obj = { + name: res.data.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + res.data.path, + id: res.data.id, + processId: state.formData.id, + projectId: res.data.projectId, + moduleType: res.data.moduleType + } + state.formData.companyImages.push(obj); + // getCompanyFiles() + } + if(type == 5){ + let obj = { + name: res.data.fileName, + url: import.meta.env.VITE_APP_BASE_API + '/' + res.data.path, + id: res.data.id, + processId: state.formData.id, + projectId: res.data.projectId, + moduleType: res.data.moduleType + } + state.formData.assAccessoryFiles.push(obj); + console.log(res,'res') + // getSafetyFiles() + } + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } +} + +const handleRemove = async (file, uploadFiles,type) => { + if(file && file.status == 'success') { + ElMessageBox.confirm( + '确定删除该附件?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then(async () => { + const res = await delFile(file.id) + if (res.code == 200) { + ElMessage({ + type: 'success', + message: '文件已删除' + }) + if (type == 1) { + const index = state.formData.deviceImages.findIndex(v => v.id === file.id) + state.formData.deviceImages.splice(index, 1); + + } + if (type == 2) { + const index = state.formData.investingationImages.findIndex(v => v.id === file.id) + state.formData.investingationImages.splice(index, 1); + + } + if (type == 3) { + const index = state.formData.companyImages.findIndex(v => v.id === file.id) + state.formData.companyImages.splice(index, 1); + } + if (type == 5) { + const index = state.formData.assAccessoryFiles.findIndex(v => v.id === file.id) + state.formData.assAccessoryFiles.splice(index, 1); + } + } else { + ElMessage({ + type: 'warning', + message: res.message + }) + } + }) + .catch(() => { + // if(type == 1){ + // getBeforeFiles() + // } + // if(type == 2){ + // getSiteCheckFiles() + // } + // if(type == 3){ + // getCompanyFiles() + // } + // if(type == 5){ + // getSafetyFiles() + // } + }) + } + +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} +.textColor{ + color: #3b82f6; +} + + +</style> diff --git a/src/views/safetyReview/testManage/components/techLeaderReview.vue b/src/views/safetyReview/testManage/components/techLeaderReview.vue new file mode 100644 index 0000000..1b25136 --- /dev/null +++ b/src/views/safetyReview/testManage/components/techLeaderReview.vue @@ -0,0 +1,267 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="6"> + <el-form-item prop="auditDate" label="审核日期"> + <el-date-picker + style="width: 100%" + v-model="state.formData.auditDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item prop="assessor.name" label="技术负责人"> + <el-input + v-model.trim="state.formData.assessor.name" + size="large" + placeholder="请选择技术负责人" + @focus="openExperts('技术负责人')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('技术负责人')"/> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="确认日期" prop="affirmDate"> + <el-date-picker + style="width: 100%" + v-model="state.formData.affirmDate" + type="date" + value-format="YYYY-MM-DD 00:00:00" + placeholder="选择日期" + size="large" + /> + </el-form-item> + </el-col> + </el-row> +<!-- <el-row :gutter="30">--> +<!-- <el-col :span="6">--> +<!-- <el-form-item label="附件上传">--> +<!-- <el-upload accept="image/*" :action="state.uploadUrl" :headers="state.header" method="post" :on-success="handleAvatarSuccess" :on-exceed="showTip" :on-preview="handlePictureCardPreview" :limit='state.imgLimit' v-model:file-list="state.fileList" list-type="picture-card" :before-upload="picSize" :on-remove="handleRemove" :before-remove="beforeRemove">--> +<!-- <el-icon><Plus /></el-icon>--> +<!-- <template #tip>--> +<!-- <div class="el-upload__tip">上传jpg/png图片尺寸小于5M,最多可上传1张</div>--> +<!-- </template>--> +<!-- </el-upload>--> +<!-- </el-form-item>--> +<!-- </el-col>--> +<!-- </el-row>--> + <el-table :data="state.tableData" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="内容" prop="content" header-align="center" :show-overflow-tooltip="true"/> + <el-table-column label="选择" header-align="center" class-name="small-padding fixed-width" width="175"> + <template #default="scope"> + <el-radio-group v-model="scope.row.status" > + <el-radio :label="1">是</el-radio> + <el-radio :label="0">否</el-radio> + </el-radio-group> + </template> + </el-table-column> + </el-table> + <el-form-item label="存在问题及建议"> + <el-input + v-model.trim="state.formData.suggestions" + :autosize="{ minRows: 6 }" + maxlength="500" + show-word-limit + type="textarea"> + </el-input> + </el-form-item> + </el-form> + <el-dialog v-model="state.dialogImg"> + <el-image style="width: 100%; height: 100%" :src="state.dialogImageUrl"/> + </el-dialog> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {addInnerReview, editInnerReview, getInnerReviewDetail} from "@/api/projectManage/innerReview" +import {delPic} from "@/api/login" +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import ExpertsList from "./expertsList"; +const emit = defineEmits(["getNextStatus"]) + +const state = reactive({ + formData: { + id: '', + projectId: '', + auditDate:'', + auditType: 2, + assessor: { + name: '' + }, + assessorId: null, + affirmDate: '', + suggestions: '' + }, + rules: { + "assessor.name": [{required: true, message: '请选择技术负责人', trigger: 'change'}], + auditDate: [{required: true, message: '请选择审核日期', trigger: 'change'}], + affirmDate: [{required: true, message: '请选择确认日期', trigger: 'change'}] + }, + tableData: [ + {id: 1, content: '报告中所列评价依据是否得到引用和验证',key: 'isBasisQuote', status: 1}, + {id: 2, content: '现场收集的有关资料是否齐全、有效',key: 'isData', status: 1}, + {id: 3, content: '危险有害因素识别是否充分', key: 'isDangerFull',status: 1}, + {id: 4, content: '报告是否有重大遗漏', key: 'isOmission',status: 1}, + {id: 5, content: '评价方法选用是否合理', key: 'isMethodRational',status: 1}, + {id: 6, content: '对策措施及建议是否具有针对性、合理性', key: 'isMeasureEquitable',status: 1}, + {id: 7, content: '评价结论及格式是否正确', key: 'isConclusionRight',status: 1}, + {id: 8, content: '已按要求修改完成', key: 'isAmendFinish',status: 1}, + {id: 9, content: '可报过程控制负责人审核', key: 'isReportAudit',status: 1} + ], + imgLimit: 1, + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile', + header: { + Authorization: getToken() + }, + dialogImageUrl: '', + dialogImg: false +}) + +const isAmin = ref(false) +const formRef = ref() +const expertsListRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } +}) + +const riskOpen = async (type,val) => { + state.formData.projectId = val + if(type === 'detail' || type === 'edit' ){ + const res = await getInnerReviewDetail({projectId: val,auditType: 2}); + if(res.code == 200){ + state.formData = res.data + for(let key in res.data){ + for(let item of state.tableData){ + if(item.key == key){ + item.status = res.data[key]==true?1:0 + } + } + } + }else { + ElMessage.warning(res.message) + } + } + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const {id, ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + data[i.key] = i.status + } + const res = await addInnerReview(data); + if (res.code == 200) { + ElMessage.success('保存成功') + formRef.value.clearValidate(); + emit('getNextStatus', val); + + } else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const { ...data} = JSON.parse(JSON.stringify(state.formData)) + for(let i of state.tableData){ + data[i.key] = i.status + } + const res = await editInnerReview(data); + if (res.code == 200) { + ElMessage.success('变更成功') + formRef.value.clearValidate(); + // emit('getNextStatus', data.project.id); + } else { + ElMessage.warning(res.message) + } + } + } + } +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + state.formData.assessor.name = obj.name + state.formData.assessorId = obj.id +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + + +const handleAvatarSuccess = (res, uploadFile) => { + if(res.code == 200){ + // state.registerForm.agency.reportPath = res.data.path + }else{ + ElMessage({ + type: 'warning', + message: '文件上传失败' + }) + } +} + +const handleRemove = async (file, uploadFiles) => { + const res = await delPic({path: state.registerForm.agency.reportPath}) + if(res.code == 200){ + ElMessage({ + type: 'success', + message: '文件已删除' + }) + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/uploadReviewRcd.vue b/src/views/safetyReview/testManage/components/uploadReviewRcd.vue new file mode 100644 index 0000000..e528f9b --- /dev/null +++ b/src/views/safetyReview/testManage/components/uploadReviewRcd.vue @@ -0,0 +1,241 @@ +<template> + <div class="riskBox"> + <el-form ref="formRef" :model="state.formData" :rules="state.rules" class="register-form" label-position="top"> + <el-row :gutter="30"> + <el-col :span="18"> + <el-form-item label="附件上传"> + <el-upload :disabled="projectType === 'view' || isEnd" accept="image/*,.pdf,.doc,.docx" :action="state.uploadUrl" :data="{moduleType: 6,projectId: props.projectId}" :headers="state.header" method="post" :on-success="handleAvatarSuccess" :on-exceed="showTip" v-model:file-list="state.fileList" :before-upload="picSize" :on-remove="handleRemove"> + <el-button type="primary">上传评审记录</el-button> + <template #tip> + <div class="el-upload__tip">上传文件尺寸尺寸小于5M</div> + </template> + </el-upload> + </el-form-item> + </el-col> + </el-row> + <el-table :data="state.tableData" :border="true" style="margin: 20px 0"> + <el-table-column label="序号" width="60" align="center" type="index"></el-table-column> + <el-table-column label="原名称" prop="originName" align="center" :show-overflow-tooltip="true"/> + <el-table-column label="操作" header-align="center" class-name="small-padding fixed-width" width="120"> + <template #default="scope"> + <el-button link type="primary" @click="checkFile(scope.row)">查看</el-button> + <el-button link type="danger" @click="handleRemove(scope.row,[])" :disabled="projectType === 'view'">删除</el-button> + </template> + </el-table-column> + </el-table> + </el-form> + </div> +</template> +<script setup> + +import {defineEmits, onMounted, reactive, ref} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {delFile, getFiles, getReviewDone} from "@/api/projectManage/siteCheckRcd"; +import { getToken } from "@/utils/auth"; +import Cookies from "js-cookie" +import axios from 'axios' +import { useRoute } from 'vue-router' +const route = useRoute() +const emit = defineEmits(["getNextStatus"]); +const props = defineProps(['projectId']) +const state = reactive({ + formData: {}, + rules: {}, + tableData: [], + uploadUrl: import.meta.env.VITE_APP_BASE_API + '/manage/accessory-file/uploadFile', + header: { + Authorization: getToken() + }, + fileList: [] +}) + +const isAmin = ref(false) +const formRef = ref() +onMounted(() => { + const userInfo = JSON.parse(Cookies.get('userInfo')) + if(userInfo.identity === 0){ + isAmin.value = true; + } + getReviewFiles(props.projectId) + isEnd.value = Cookies.get('end') + projectType.value = route.query.type; +}) + +const projectType = ref(''); +const isEnd = ref('') +const riskOpen = async (type,val) => { + projectType.value = route.query.type; + isEnd.value = Cookies.get('end') + if(type === 'detail' || type === 'edit' ){ + await getReviewFiles + } + + if(type === 'add' || type === 'clickEdit') { + const valid = await formRef.value.validate(); + if(valid){ + if (isAmin.value) { + ElMessage.warning("当前用户暂无权限"); + return; + } + if(type === 'add'){ + const res = await getFiles({projectId: val,moduleType: 6}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.tableData = res.data + ElMessage.success('保存成功') + getReviewDone({projectId: val}).then((res)=>{ + if(res.code == 200){ + emit('getNextStatus', val); + }else{ + ElMessage.warning(res.message) + } + }) + }else{ + state.tableData=[] + ElMessage.warning('请上传评审记录附件') + } + }else { + ElMessage.warning(res.message) + } + }else if(type === 'clickEdit'){ + const res = await getFiles({projectId: val,moduleType: 6}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.tableData = res.data + ElMessage.success('变更成功') + }else{ + state.tableData=[] + ElMessage.warning('请上传评审记录附件') + } + }else { + ElMessage.warning(res.message) + } + } + } + } +} + +const getReviewFiles = async (id)=>{ + const res = await getFiles({projectId: id ? id : props.projectId,moduleType: 6}) + if(res.code == 200){ + if(res.data && res.data.length>0){ + state.tableData = res.data + state.fileList = res.data.map(i => { + return { + name: i.originName, + url: import.meta.env.VITE_APP_BASE_API + '/' + i.path, + id: i.id, + projectId: i.projectId, + moduleType: i.moduleType + + } + }) + }else{ + state.tableData=[] + } + }else { + ElMessage.warning(res.message) + } +} + +// 图片上传 +const showTip =()=>{ + ElMessage({ + type: 'warning', + message: '超出文件上传数量' + }); +} + +const picSize = async (rawFile) => { + if(rawFile.size / 1024 / 1024 > 5){ + ElMessage({ + type: 'warning', + message: '文件大小不能超过5M' + }); + return false + } +}; + +const handlePictureCardPreview = (uploadFile) => { + console.log(uploadFile,'file') + state.imgUrl = uploadFile.url + state.imgDialog = true +}; + + +const handleAvatarSuccess = (res, uploadFile, type) => { + if(res.code == 200){ + getReviewFiles() + }else{ + state.fileList.splice(state.fileList.indexOf(uploadFile),1) + ElMessage({ + type: 'warning', + message: res.message + }) + } +} + +const handleRemove = async (file, uploadFiles) => { + if(file && file.status == 'success'){ + ElMessageBox.confirm( + '确定删除该附件?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delFile(file.id) + if(res.code == 200){ + ElMessage({ + type: 'success', + message: '文件已删除' + }) + await getReviewFiles() + }else{ + ElMessage({ + type: 'warning', + message: res.message + }) + } + }) + .catch(()=>{ + getReviewFiles() + }) + } + +} + +const checkFile = async (file)=>{ + axios.get(import.meta.env.VITE_APP_BASE_API +'/' + file.path,{headers:{'Content-Type': 'application/json','Authorization': `${getToken()}`,'uid':`${Cookies.get('uid')}`},responseType: 'blob'}).then(res=>{ + if (res) { + const link = document.createElement('a') + let blob = new Blob([res.data],{type: res.data.type}) + link.style.display = "none"; + link.href = URL.createObjectURL(blob); // 创建URL + window.open(link.href) + } else { + ElMessage({ + type: 'warning', + message: '文件读取失败' + }); + } + }) +} + +defineExpose({ + riskOpen +}); + + +</script> +<style scoped lang="scss"> +.riskBox{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } +} + +</style> diff --git a/src/views/safetyReview/testManage/components/worksDialog.vue b/src/views/safetyReview/testManage/components/worksDialog.vue new file mode 100644 index 0000000..43e654f --- /dev/null +++ b/src/views/safetyReview/testManage/components/worksDialog.vue @@ -0,0 +1,205 @@ +<template> + <div class="notice"> + <el-dialog + v-model="dialogVisible" + :title="title" + width="500px" + :before-close="handleClose" + > + <el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-position="top"> + <el-form-item label="评价组成员:" prop="person.name"> + <el-input + v-model.trim="state.form.person.name" + size="large" + placeholder="请选择评价组成员" + @focus="openExperts('评价组成员')" + > + <template #append> + <el-button :icon="Search" @click="openExperts('评价组成员')"/> + </template> + </el-input> + </el-form-item> + <el-form-item label="工作类型:" prop="jobType"> + <el-select v-model="state.form.jobType" placeholder="工作类型" style="width: 100%" size="large"> + <el-option v-for="(item,index) in props.typeList" :key="index" :label="item.label" :value="item.value"/> + </el-select> + </el-form-item> +<!-- <el-form-item label="专业能力:" prop="person.major">--> +<!-- <el-select v-model="state.form.person.majorName" placeholder="专业能力" style="width: 100%" size="large" @change="getCerNo">--> +<!-- <el-option v-for="(item,index) in state.form.person.majorNames" :key="index" :label="item" :value="item"/>--> +<!-- </el-select>--> +<!-- </el-form-item>--> +<!-- <el-form-item label="资格证书:" prop="person.certificateNo">--> +<!-- <el-input--> +<!-- v-model="state.form.person.certificateNo"--> +<!-- size="large"--> +<!-- readonly--> +<!-- />--> +<!-- </el-form-item>--> + <el-form-item label="承担工作:" prop="work"> + <el-select v-model="state.form.work" multiple placeholder="承担工作" style="width: 100%" size="large"> + <el-option v-for="item in props.workList" :key="item.value" :label="item.label" :value="item.value"/> + </el-select> + </el-form-item> + <el-form-item label="承诺后期前往现场勘验:" prop="laterPromise"> + <el-radio-group v-model="state.form.laterPromise" size="large"> + <el-radio :label="1" size="large">是</el-radio> + <el-radio :label="0" size="large">否</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="未到现场勘验原因:"> + <el-input v-model.trim="state.form.reason" maxlength="30" show-word-limit type="text" size="large"/> + </el-form-item> + </el-form> + <template #footer> + <span class="dialog-footer"> + <el-button @click="handleClose" size="default">取 消</el-button> + <el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button> + </span> + </template> + <experts-list ref="expertsListRef" @getName="getSelected"></experts-list> + </el-dialog> + </div> +</template> +<script setup> +import {defineProps, nextTick, reactive, ref, toRefs} from 'vue' +import {ElMessage} from "element-plus"; +import {Search} from '@element-plus/icons-vue' +import {addWorks, editWorks} from "@/api/projectManage/evaPlan" +import ExpertsList from "./expertsList" + +const dialogVisible = ref(false); +const title = ref(""); +const busRef = ref(); +const expertsListRef = ref() +const props = defineProps(['workList','typeList']) +const emit = defineEmits(["getList"]); +const state = reactive({ + form: { + id: null, + person: { + name: '', + // major: {}, + // certificateNo: '', + // certs: '', + // majorName: '', + // majorNames: [], + // ids: [] + }, + personId: null, + jobType: null, + projectId: null, + informed: 0, + work: [], + laterPromise: 0, + reason: '' + }, + formRules:{ + 'person.name': [{ required: true, message: '请选择评价组成员', trigger: 'change' }], + 'person.major': [{ required: true, message: '请选择专业能力', trigger: 'blur' }], + work: [{ required: true, message: '请选择承担工作', trigger: 'blur' }], + jobType: [{ required: true, message: '请选择工作类型', trigger: 'blur' }] + }, + +}) + +const openDialog = async (type, value,projectId) => { + title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' + state.form.projectId = projectId + if(type == 'add'){ + nextTick(()=>{ + busRef.value.resetFields() + }) + }else if(type === 'edit') { + state.form = JSON.parse(JSON.stringify(value)) + state.form.work = value.work.split(',') + state.form.laterPromise = value.laterPromise?1:0 + } + dialogVisible.value = true; +} + +const openExperts = (type) =>{ + expertsListRef.value.openDialog(type) +} + +const getSelected = (type,obj)=>{ + state.form.person.name = obj.name + state.form.personId = obj.id + // state.form.person.certs = obj.certificateNo + // state.form.person.majorNames = obj.majorNames + // state.form.person.ids = obj.major.split(',') +} + +// const getCerNo = () =>{ +// const i = state.form.person.majorNames.indexOf(state.form.person.majorName) +// const obj = JSON.parse(state.form.person.certs) +// state.form.person.certificateNo = Object.values(obj)[i] +// state.form.person.major[state.form.person.ids[i]] = state.form.person.certificateNo +// } + +const onSubmit = async () => { + const valid = await busRef.value.validate(); + if(valid){ + if(title.value === '新增'){ + const {id,work,...data} = state.form + data['work'] = state.form.work.join(',') + // const {name,major,...rest} = state.form.person + // data.person = { name,major } + // data.person.major = JSON.stringify(state.form.person.major) + const res = await addWorks(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '新增成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; + }else if(title.value === '编辑'){ + const {...data} = state.form + data['work'] = state.form.work.join(',') + const res = await editWorks(data) + if(res.code === 200){ + ElMessage({ + type: 'success', + message: '修改成功' + }); + }else{ + ElMessage.warning(res.message) + } + emit("getList") + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; + } + } +} + +const handleClose = () => { + busRef.value.clearValidate(); + busRef.value.resetFields() + dialogVisible.value = false; +} + +defineExpose({ + openDialog +}); + +</script> + +<style scoped lang="scss"> +.notice{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + .file { + display: flex; + flex-direction: column; + align-items: flex-start; + } +} +</style> diff --git a/src/views/safetyReview/testManage/index.vue b/src/views/safetyReview/testManage/index.vue new file mode 100644 index 0000000..deabb40 --- /dev/null +++ b/src/views/safetyReview/testManage/index.vue @@ -0,0 +1,748 @@ +<template> + <div class="project-container"> + <div class="header"> + <el-button type="success" icon="Plus" @click="toProcess('add',{})">新增</el-button> + <vue3-json-excel + :json-data="dataList" + :fields="fields" + name="项目信息表.xlsx" + style="margin-right: 5px;margin-left: 5px" + > + <el-button type="warning">导出</el-button> + </vue3-json-excel> + <el-button type="primary" icon="Filter" @click="showDrawer = true">筛选</el-button> + </div> + <div class="middle"> + <div class="card-box"> + <div class="box-left" @click="choose('')"> + <div class="font-left"> + <div>项目</div> + <div>总数</div> + </div> + <div class="font-right">{{search.num.projectTotal}}</div> + </div> + <div class="box-right"> + <div class="inbox" @click="choose(1)" style="box-shadow: rgba(132, 122, 253, 0.2) 0 3px 5px 0;" :class="{btn1: chooseType === 1}"> + <div class="top" style="background: linear-gradient(90deg, rgb(127, 118, 253), rgb(218, 180, 246));"> + <span class="top-right-font">风险分析及计划评价</span> + </div> + <div class="bottom"> + <span class="top-right-font-bottom">{{search.num.riskTotal}}</span> + </div> + </div> + <div class="inbox" @click="choose(2)" style="box-shadow: rgba(255, 142, 139, 0.15) 0 3px 5px 0;" :class="{btn2: chooseType === 2}"> + <div class="top" style="background: linear-gradient(90deg, rgb(255, 140, 138), rgb(239, 186, 141));"> + <span class="top-right-font">现场勘验</span> + </div> + <div class="bottom"> + <span class="top-right-font-bottom">{{search.num.investigationTotal}}</span> + </div> + </div> + <div class="inbox" @click="choose(3)" style="box-shadow: rgba(222, 106, 169, 0.15) 0 3px 5px 0;" :class="{btn3: chooseType === 3}"> + <div class="top" style="background: linear-gradient(90deg, rgb(229, 119, 180), rgb(249, 159, 192));"> + <span class="top-right-font">项目审核</span> + </div> + <div class="bottom"> + <span class="top-right-font-bottom">{{search.num.reviewTotal}}</span> + </div> + </div> + <div class="inbox" @click="choose(4)" style="box-shadow: rgba(109, 177, 254, 0.2) 0 3px 5px 0;" :class="{btn4: chooseType === 4}"> + <div class="top" style="background: linear-gradient(90deg, rgb(54, 115, 255), rgb(124, 196, 242));"> + <span class="top-right-font">出具报告</span> + </div> + <div class="bottom"> + <span class="top-right-font-bottom">{{search.num.reportTotal}}</span> + </div> + </div> + <div class="inbox" @click="choose(5)" style="box-shadow: rgba(88, 211, 137, 0.2) 0 3px 5px 0;" :class="{btn5: chooseType === 5}"> + <div class="top" style="background: linear-gradient(90deg, rgb(0, 195, 151), rgb(114, 232, 200));"> + <span class="top-right-font">项目归档</span> + </div> + <div class="bottom"> + <span class="top-right-font-bottom">{{search.num.archiveTotal}}</span> + </div> + </div> + </div> + </div> + </div> + + <div style="margin-top: 10px;margin-bottom: 15px;margin-left: 20px;"> + <div style="font-size: 18px;font-weight: 800;color: #ed5565;display: flex"> + 当前存在未完结:安全评价项目 {{search.num.safetyTotal}} 个,检验检测项目 + <div style="cursor: pointer;border-radius: 8px;padding: 0 5px" :class="{active: isActive}" @click="chooseUn" >{{search.num.safetyCheckTotal}}</div> + 个,共 {{search.num.unFinishTotal}} 个 + </div> + </div> + + <!-- 表格数据 --> + <el-table v-loading="loading" :data="dataList" :border="true" ref="tableRef" :height="tableHeight" style="width: 100%;"> + <el-table-column label="序号" width="80" align="center" type="index" ></el-table-column> + <el-table-column label="项目名称" prop="name" align="center" :show-overflow-tooltip="true" width="180" /> + <el-table-column label="填报机构" prop="agencyName" align="center" :show-overflow-tooltip="true" width="180" /> + <el-table-column label="委托单位" prop="client" align="center" :show-overflow-tooltip="true" width="180"/> + <el-table-column label="所属地市" align="center" width="250"> + <template #default="scope"> + {{scope.row.area}} + </template> + </el-table-column> + <el-table-column label="类型" prop="estimateTypeName" align="center" width="150"/> + <el-table-column label="业务范围" prop="businessName" align="center" :show-overflow-tooltip="true" width="150"/> + <el-table-column label="项目负责人" prop="leaderName" align="center" width="120" :show-overflow-tooltip="true"/> + <el-table-column label="项目阶段" align="center" width="200"> + <template #default="scope"> + <div v-if="scope.row.process === 1" class="process1"> + <span>风险分析及计划评价</span> + </div> + <div v-else-if="scope.row.process === 2" class="process1 process2"> + <span>现场勘验</span> + </div> + <div v-else-if="scope.row.process === 3" class="process1 process3"> + <span>项目审核</span> + </div> + <div v-else-if="scope.row.process === 4" class="process1 process4"> + <span>出具报告</span> + </div> + <div v-else class="process1 process5"> + <span>项目归档</span> + </div> + </template> + </el-table-column> + <el-table-column label="项目实施天数" prop="filingDate" align="center" width="150"/> +<!-- <el-table-column label="项目变更" prop="" align="center" width="120">--> +<!-- <template #default="scope">--> +<!-- <div style="cursor:pointer;color: #3b82f6;" >--> +<!-- <span v-if="scope.row.process !== 1" @click="goMenu('toFive',scope.row)">{{}}</span>--> +<!-- <span v-else></span>--> +<!-- </div>--> +<!-- </template>--> +<!-- </el-table-column>--> + <el-table-column label="预估金额(万元)" prop="contractMoney" align="center" width="130"/> + <el-table-column label="归档金额(万元)" prop="actualContractMoney" align="center" width="130"/> + <el-table-column label="缺失要件" align="center" width="150"> + <template #default="scope"> + <div style="cursor:pointer;color: #3b82f6;" > + <span v-if="scope.row.process === 5" @click="goMenu('toTwelve',scope.row)">{{scope.row.missingMaterialCnt}}</span> + <span v-else></span> + </div> + </template> + </el-table-column> + <el-table-column label="归档确认" prop="" align="center" width="150"> + <template #default="scope"> + <div style="cursor:pointer;color: #3b82f6;" > + <span v-if="scope.row.process === 5" @click="goMenu('toThirteen',scope.row)">{{scope.row.activeConfirm}}</span> +<!-- <span v-else></span>--> + </div> + </template> + </el-table-column> + <el-table-column fixed="right" label="操作" align="center" class-name="small-padding fixed-width" width="180"> + <template #default="scope"> + <el-button link type="primary" @click="toProcess('view',scope.row)">查看</el-button> + <el-button link type="primary" v-if="scope.row.reportProgress !== 14" @click="toProcess('edit',scope.row)">编辑</el-button> + <el-button link type="danger" v-if="(isAgency && scope.row.reportProgress !== 14) || (!isAgency && scope.row.reportProgress !== 14)" @click="del(scope.row)">删除</el-button> + </template> + </el-table-column> + </el-table> + + <div class="pag-container"> + <el-pagination + v-model:current-page="search.queryParams.pageNum" + v-model:page-size="search.queryParams.pageSize" + :page-sizes="[10,15,20,25]" + layout="total, sizes, prev, pager, next, jumper" + :total="total" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> + <el-drawer v-model="showDrawer" :direction="direction" :with-header="false" :size="size" > + <template #default> + <div class="drawer"> + <el-form ref="drawerRef" class="register-form" label-position="top"> + <el-form-item label="时间选择"> + <el-date-picker + v-model="searchTime" + type="daterange" + @change="changeTime" + range-separator="至" + start-placeholder="开始日期" + end-placeholder="结束日期" + value-format="YYYY-MM-DD" + /> + </el-form-item> + <el-form-item label="所属区域"> + <el-cascader + v-model="area" + :options="addressList" + :props="props" + @change="handleChange" + style="width: 100%" + size="large" + /> + </el-form-item> + <el-form-item label="机构名称" > + <el-select + v-model="search.queryParams.agencyName" + filterable + remote + @change="selectValue" + reserve-keyword + placeholder="所属机构" + remote-show-suffix + :remote-method="getCompanyList" + :loading="loadingCompany" + style="width:100%" + clearable + > + <el-option + v-for="item in companyList" + :key="item.id" + :label="item.name" + :value="item.name" + /> + </el-select> + </el-form-item> + <el-form-item label="项目名称" > + <el-input v-model.trim="search.queryParams.name" placeholder="请输入项目名称"></el-input> + </el-form-item> + <el-form-item label="委托单位"> + <el-input v-model.trim="search.queryParams.client" placeholder="委托单位"></el-input> + </el-form-item> + <el-form-item label="业务范围"> + <el-select v-model="search.queryParams.business" class="m-2" size="large" placeholder="请选择" style="width: 100%" > + <el-option + v-for="item in businessList" + :key="item.id" + :label="item.label" + :value="item.id" + /> + </el-select> + </el-form-item> +<!-- <el-form-item label="类型">--> +<!-- <el-select v-model="search.queryParams.estimateType" class="m-2" size="large" placeholder="请选择" style="width: 100%" >--> +<!-- <el-option--> +<!-- v-for="item in estimateTypeList"--> +<!-- :key="item.id"--> +<!-- :label="item.label"--> +<!-- :value="item.id"--> +<!-- />--> +<!-- </el-select>--> +<!-- </el-form-item>--> + <el-form-item label="缺失要件"> + <el-select v-model="search.queryParams.params.lostMaterial" class="m-2" size="large" placeholder="请选择" style="width: 100%" > + <el-option + v-for="item in missingList" + :key="item.id" + :label="item.label" + :value="item.id" + /> + </el-select> + </el-form-item> + + </el-form> + </div> + </template> + <template #footer> + <div style="flex: auto"> + <el-button type="primary" @click="searchClick">查询</el-button> + <el-button type="warning" @click="reset">重置</el-button> + <el-button @click="confirmClick">取消</el-button> + + </div> + </template> + </el-drawer> + + </div> + +</template> + +<script setup> +import {onMounted, reactive, ref} from "vue"; +import {delProject, getProjectList, getProjectStatistics} from "@/api/projectManage/project"; +import {ElMessage, ElMessageBox} from "element-plus"; +import {getRegionTree} from "@/api/area"; +import {getDict} from "@/api/login"; +import {getDictList} from "@/api/backManage/evaluate"; +import Cookies from "js-cookie" +import {getAllAgency} from "@/api/backManage/insitution"; +const router = useRouter(); + +const loading = ref(false); +const direction = ref('rtl'); +const showDrawer = ref(false); +const size = ref('400px') +const props = { + expandTrigger: 'hover', + value: 'name', + label: 'name' +} +const search = reactive({ + queryParams: { + pageNum: 1, + pageSize: 20, + name: '', + agencyName: '', + client: '', + province: '', + city: '', + district: '', + business: '', + estimateType: '', + phase: '', + safetyCheck: 1, + params:{ + lostMaterial: null + } + }, + num: { + projectTotal: 0, + riskTotal: 0, + investigationTotal: 0, + reviewTotal: 0, + reportTotal: 0, + archiveTotal: 0, + unFinishTotal: 0, + safetyCheckTotal: 0, + safetyTotal: 0 + } +}); +const companyList = ref([]) +const loadingCompany = ref(false) +const searchTime = ref([]); +const area = ref([]); +const businessList = ref([]); +const addressList = ref([]); +const estimateTypeList = ref([]); +const missingList = ref([ + { + id: 1, + label: '是' + }, + { + id: 0, + label: '否' + } +]) +const tableRef = ref(null); +const tableHeight = ref(0); +const dataList = ref([]); +const total = ref(0); +const isAgency = ref(false); +onMounted(() => { + Cookies.remove('projectId') + Cookies.remove('end') + Cookies.remove('btn') + getList(); + getStatistics(); + getArea(); + getBusinessList(); + getRiskList(); + tableHeight.value = window.innerHeight - tableRef.value.$el.offsetTop - 170; + // 监听浏览器高度变化 + window.onresize = () => { + tableHeight.value = window.innerHeight - tableRef.value.$el.offsetTop - 170; + }; + const userInfo = JSON.parse(Cookies.get('userInfo')) + isAgency.value = userInfo.identity === 1; + +}); +const chooseType = ref(''); +const choose = (val) => { + chooseType.value = val; + search.queryParams.phase = val; + getList(); + getStatistics() +} +const getList = async () => { + loading.value = true; + const res = await getProjectList(search.queryParams); + if(res.code == 200){ + dataList.value = res.data.list.map(item => { + return { + ...item, + process: item.reportProgress <= 4 ? 1 : item.reportProgress > 4 && item.reportProgress <= 6 ? 2 : item.reportProgress > 6 && item.reportProgress <= 9 ? 3 : item.reportProgress > 9 && item.reportProgress <= 11 ? 4 : 5, + leaderName: item.leader ? item.leader.name : '', + area: item.district ? item.province + '/' + item.city + '/' + item.district : item.city != item.province ? item.province + '/' + item.city: item.province , + filingDate: item.filingDate ? conversionDays(item.filingDate,item.createTime) : conversionDays('',item.createTime), + contractMoney: item.contract ? item.contract.contractMoney : '', + actualContractMoney: item.contract ? item.contract.actualContractMoney : '', + activeConfirm: item.personRecognition ? item.personRecognition.recognitionCnt + '/' + item.personRecognition.personCnt: '', + missingMaterialCnt: 3-item.materialCnt, + activeConfirmOut: item.personRecognition ? "\'" + item.personRecognition.recognitionCnt + '/' + item.personRecognition.personCnt: '', + } + }) + total.value = res.data.total + loading.value = false; + console.log('11',dataList.value) + }else{ + ElMessage.warning(res.message) + } +} +const getStatistics = async () => { + const {pageNum,pageSize, ...data} = JSON.parse(JSON.stringify(search.queryParams)) + const res = await getProjectStatistics(data); + if(res.code == 200){ + search.num = res.data + }else{ + ElMessage.warning(res.message) + } +} +const handleSizeChange = (val) => { + search.queryParams.pageNum = 1; + search.queryParams.pageSize = val + getList() + getStatistics() +} +const handleCurrentChange = (val) => { + search.queryParams.pageNum = val + getList() + getStatistics() +} +const toProcess = (type,value,toPath) => { + value.type = type; + router.push({ path: '/processTest', query: {id: value.id, type: type, toPath: toPath, process: value.reportProgress}}); +} + +const getArea = async ()=>{ + const type = 1 + const res = await getRegionTree({name: '',parentId: null,regionType: type}) + if(res.code == 200){ + addressList.value = res.data + }else{ + ElMessage.warning(res.message) + } +} +const getBusinessList = async () => { + const res = await getDict({dictType: 'sys_business_scope'}) + if(res.code === 200){ + businessList.value = res.data + }else{ + ElMessage.warning(res.message) + } +} +const getRiskList = async () => { + const res = await getDictList({dictType: "sys_assess_type"}); + if(res.code === 200){ + estimateTypeList.value = res.data.list + }else{ + ElMessage.warning(res.message) + } +} + +const del = (val) => { + ElMessageBox.confirm( + '确定删除此条数据?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + const res = await delProject(val) + if(res.code == 200){ + ElMessage.success('数据删除成功') + getList() + getStatistics() + + }else{ + ElMessage.warning(res.message) + } + }) +} +const confirmClick = () => { + showDrawer.value = false; +} +const changeTime=(value)=>{ + if(!value){ + search.queryParams.params.endTime = "" + search.queryParams.params.startTime = "" + } +} +const searchClick = () => { + if(searchTime.value && searchTime.value.length>0){ + search.queryParams.params.startTime = searchTime.value[0] + search.queryParams.params.endTime = searchTime.value[1] + } + getList(); + getStatistics(); + showDrawer.value = false; +} +const reset = () => { + searchTime.value = []; + area.value = []; + search.queryParams = { + pageNum: 1, + pageSize: 20, + name: '', + agencyName: '', + client: '', + province: '', + city: '', + district: '', + business: '', + estimateType: '', + phase: '', + safetyCheck: 1, + params: { + lostMaterial: null + } + } + chooseType.value = ''; + getList(); + getStatistics(); + showDrawer.value = false; +} +const conversionDays = (time,createTime) => { + let day = ""; + if(time) { + day = new Date(time).getTime() - new Date(createTime).getTime();//日期转时间戳 + }else { + day = Date.now() - new Date(createTime).getTime();//日期转时间戳 + } + return Math.floor(day / 86400000) ;//时间戳获取天数 +} +const handleChange = (value) => { + // if(state.registerForm.agency.attribute == 0){ + // state.registerForm.agency.province = '新疆维吾尔自治区' + // state.registerForm.agency.city = value[0]?value[0]:'' + // state.registerForm.agency.district = value[1]?value[1]:'' + // }else{ + search.queryParams.province = value[0]?value[0]:'' + search.queryParams.city = value[1]?value[1]:'' + search.queryParams.district = value[2]?value[2]:'' + // } +} +// 导出表格 +const fields = ref({ + '项目名称':'name', + '委托单位':'client', + '所属地市': 'area', + '类型': 'estimateTypeName', + '业务范围': 'businessName', + '项目负责人': 'leaderName', + '项目阶段': { + field: 'process', + callback: (value) => { + if (value === 1) { + return '风险分析及计划评价' + } else if(value === 2){ + return '现场勘验' + }else if(value === 3){ + return '项目审核' + }else if(value === 4){ + return '出具报告' + }else if(value === 5){ + return '项目归档' + } + } + }, + '项目实施天数': 'filingDate', + '预估金额(万元)': 'contractMoney', + '归档金额(万元)': 'actualContractMoney', + '缺失要件': 'missingMaterialCnt', + '归档确认': 'activeConfirmOut' +}); +const goMenu = (toPath,val) => { + console.log("val",val) + toProcess('edit',val,toPath); +} + +const selectValue = (val) => { + console.log('val',val) + if(val == ""){ + companyList.value = [] + } + // data.companyList.forEach(item => { + // if(item.name === val){ + // data.queryParams.companyId = item.id + // } + // }) +} +const getCompanyList = async (val)=>{ + if(val != ""){ + loadingCompany.value = true; + const queryParams = { + name: val + } + const res = await getAllAgency(queryParams) + if (res.code == 200) { + loadingCompany.value = false; + companyList.value = res.data + + } else { + ElMessage.warning(res.message) + } + } +} + +const isActive = ref(false) +const chooseUn = () => { + isActive.value = !isActive.value + if(isActive.value){ + search.queryParams.unFinish = 1 + }else { + search.queryParams.unFinish = null + } + getList() + getStatistics() +} + +</script> + +<style scoped lang="scss"> +.project-container{ + .active { + background-color: #fdb0b7; + //border: 1px solid #dab4f6; + } + .header{ + margin: 15px 10px; + display: flex; + align-items: center; + justify-content: flex-end; + } + .middle{ + height: 99px; + margin-bottom: 20px; + } + .card-box{ + margin: 20px; + height: 99px; + background: #fff; + box-shadow: 0 3px 10px 0 rgba(62,62,62,.25); + border-radius: 10px; + display: flex; + .box-left{ + width: 20%; + min-width: 200px; + height: 99px; + background: #fff; + box-shadow: 0 0 5px 0 rgba(62,62,62,.2); + border-radius: 10px; + display: flex; + margin-left: -15px; + align-items: center; + cursor: pointer; + padding-left: 2%; + .font-left{ + width: 40px; + height: 40px; + font-size: 20px; + font-weight: 400; + color: #9198ad; + line-height: 18px; + font-family: fantasy; + } + .font-right{ + position: relative; + left: 7%; + top: -3px; + height: 40px; + font-size: 36px; + font-family: fantasy; + font-weight: 400; + color: #222733; + } + } + .box-left:hover{ + border: 1px solid #4378f1 + } + .box-right{ + width: 80%; + height: 99px; + border-radius: 10px; + margin-left: 15px; + display: flex; + align-items: center; + justify-content: space-between; + .inbox{ + width: 19%; + height: 76px; + background: #fff; + border-radius: 5px; + cursor: pointer; + .top{ + width: 100%; + height: 39px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + .top-right-font{ + font-size: 16px; + color: #fff; + line-height: 39px; + margin-left: 10px; + } + } + .bottom{ + height: 37px; + .top-right-font-bottom{ + font-size: 20px; + color: #333; + line-height: 37px; + margin-left: 20px; + font-family: fantasy; + } + } + } + .inbox:nth-child(1):hover{ + border: 1px solid #dab4f6; + } + .inbox:nth-child(2):hover{ + border: 1px solid #efba8d; + } + .inbox:nth-child(3):hover{ + border: 1px solid #f99fc0; + } + .inbox:nth-child(4):hover{ + border: 1px solid #7cc4f2; + } + .inbox:nth-child(5):hover{ + border: 1px solid #72e8c8; + } + } + } + .btn1{ + border: 1px solid #dab4f6; + } + .btn2{ + border: 1px solid #efba8d; + } + .btn3{ + border: 1px solid #f99fc0; + } + .btn4{ + border: 1px solid #7cc4f2; + } + .btn5{ + border: 1px solid #72e8c8; + } + .pag-container{ + float: right; + margin-top: 20px; + } + .process1{ + border-radius: 5px; + color: rgb(255, 255, 255); + padding: 5px 10px; + background: linear-gradient(90deg, rgb(127, 118, 253), rgb(218, 180, 246)); + } + .process2{ + background: linear-gradient(90deg, rgb(255, 140, 138), rgb(239, 186, 141)); + } + .process3 { + background: linear-gradient(90deg, rgb(229, 119, 180), rgb(249, 159, 192));; + } + .process4 { + background: linear-gradient(90deg, rgb(54, 115, 255), rgb(124, 196, 242));; + } + .process5 { + background: linear-gradient(90deg, rgb(0, 195, 151), rgb(114, 232, 200));; + } + .drawer{ + :deep(.el-form .el-form-item__label) { + font-size: 15px; + } + } + +} +</style> diff --git a/src/views/safetyReview/testManage/process.vue b/src/views/safetyReview/testManage/process.vue new file mode 100644 index 0000000..d0a9785 --- /dev/null +++ b/src/views/safetyReview/testManage/process.vue @@ -0,0 +1,1149 @@ +<template> + <div class="process-container"> + <div class="flow"> + <div class="content" :class="{show: isShowMenu}" > + <div class="content-middle" @click="clickMenu(true)"> + <div class="project-title"> +<!-- <img :src="projectPng">--> + <span>项目</span> + <span>阶段</span> + </div> + <div v-for="item in menuList" :key="item.id" style="flex: 1" :class="{choose: item.status === 1 || item.status === 2}"> + <div class="header-item"> + <div class="item-content"> + <img v-if="item.status === 0" :src="status0Png"> + <img v-else-if="item.status === 1" :src="status1Png"> + <img v-else :src="status2Png"> + <span class="text-eclipse" style="margin-left: 5px">{{item.name}}</span> + </div> + </div> + <div v-for="child in item.subMenus" :key="child.id" @click="chooseSubMenu(child,true)"> + <div class="down-item" :class="{itemActive: child.status === 1 || child.status === 3, itemPrev: child.status === 2}"> + <div class="item-icon-status0" v-if="child.status === 0">{{child.id}}</div> + <div class="item-icon-status0 item-icon-status1" v-else-if="child.status === 1 || (selectedObj.status === 3 && child.id === selectedObj.id)">{{child.id}}</div> + <div class="item-icon-status0 item-icon-status2" v-else-if="child.status === 2 "><img :src="itemStatus2Png"></div> + <div class="item-icon-status0 item-icon-status4 " v-else-if="nextObj.status === 4 && child.id === nextObj.id">{{child.id}}</div> + <div class="text-eclipse" style="margin-right: 15%">{{child.name}}</div> + <div v-if="child.status === 1 || (selectedObj.status === 1 && child.id ===selectedObj.id)" class="item-icon-status0 item-icon-status2"><img :src="status1Png"></div> + <div v-if="nextObj.status === 4 && child.id === nextObj.id" class="item-icon-status0 item-icon-status4" ><img :src="status1Png"></div> + </div> + <div></div> + </div> + </div> + </div> + <div class="content-bottom" @click="clickMenu(false)"></div> + </div> + </div> + + <div class="middle" :style="'height:' + middleHeight + 'px'"> + <el-card> + <div class="card-header">{{selectedObj.id}}- {{selectedObj.name}}</div> + <div class="card-content"> + <div :style="'height:' + middleContentHeight + 'px'" style="overflow-y: scroll;"> + <rickAnalysis ref="riskRef" v-if="selectedObj.id === 1" @getNextStatus="getNextStatus"></rickAnalysis> + <contract-manage ref="contractMngRef" v-if="selectedObj.id === 2" @getNextStatus="getNextStatus"></contract-manage> + <evaluate-task-notice ref="evaluteRef" v-if="selectedObj.id === 3" @getNextStatus="getNextStatus"></evaluate-task-notice> + <evaluate-plan ref="evalPlanRef" v-if="selectedObj.id === 4" @getNextStatus="getNextStatus" :projectId="projectId"></evaluate-plan> + <employ-notice-record ref="employNoticeRcdRef" v-if="selectedObj.id === 5" @getNextStatus="getNextStatus" :projectId="projectId"></employ-notice-record> + <site-check-rcd ref="siteCheckRcdRef" v-if="selectedObj.id === 6" @getNextStatus="getNextStatus" :projectId="projectId"></site-check-rcd> + <inner-review ref="innerReviewRef" v-if="selectedObj.id === 7" @getNextStatus="getNextStatus"></inner-review> + <tech-leader-review ref="techReviewRef" v-if="selectedObj.id === 8" @getNextStatus="getNextStatus"></tech-leader-review> + <upload-review-rcd ref="uploadReviewRef" v-if="selectedObj.id === 9" @getNextStatus="getNextStatus" :projectId="projectId"></upload-review-rcd> + <rate-conclusion ref="rateConRef" v-if="selectedObj.id === 10" @getNextStatus="getNextStatus" :projectId="projectId"></rate-conclusion> + <process-ctrl-review ref="proCtrlRef" v-if="selectedObj.id === 11" @getNextStatus="getNextStatus" :projectId="projectId"></process-ctrl-review> + <project-archive ref="proArchRef" v-if="selectedObj.id === 12" @getNextStatus="getNextStatus" :projectId="projectId"></project-archive> + <sign-confirm ref="signConfirmRef" v-if="selectedObj.id === 13" @getNextStatus="getNextStatus" :projectId="projectId"></sign-confirm> + <confirm-end ref="confirmEndRef" v-if="selectedObj.id === 14" @getNextStatus="getNextStatus" :projectId="projectId"></confirm-end> + </div> + <div style="display: flex;align-items: center;justify-content: center;margin-bottom: -30px;margin-top: 10px"> + <el-button type="primary" v-if="selectedObj.id !== 1" style="width: 80px" @click="back">上一步</el-button> + <el-button type="warning" style="width: 80px" v-if="(projectStatus === 'add' && selectedObj.status === 1 && selectedObj.id !== 14)||(projectStatus === 'edit' && selectedObj.status === 1 && selectedObj.id !== 14) " @click="save">保存</el-button> + <el-button type="warning" style="width: 80px" v-if="(projectStatus === 'edit' && selectedObj.status !== 1 && selectedObj.id !== 13 && selectedObj.id !== 14 && reportProcess != 14) || (projectStatus === 'add' && selectedObj.status !== 1 && selectedObj.id !== 14 && reportProcess != 14) " @click="clickEdit">变更</el-button> + <el-button type="warning" style="width: 80px" v-if="selectedObj.id === 14 && selectedObj.status === 1 && reportProcess != 14" @click="confirm">确认完结</el-button> + <el-button type="primary" style="width: 80px" v-if="selectedObj.id !== 14" @click="next">下一步</el-button> + </div> + </div> + </el-card> + </div> + <div class="bottom"> + <el-button type="primary" v-if="selectedObj.id === 3" plain @click="downloadFile"> + 评价任务通知书<el-icon class="el-icon--right"><Download /></el-icon> + </el-button> + <el-button type="primary" v-if="selectedObj.id === 13" plain @click="downloadCommitFile"> + 承诺书<el-icon class="el-icon--right"><Download /></el-icon> + </el-button> + </div> + </div> +</template> + +<script setup> + +import {onMounted, ref} from "vue"; +import {ElMessage, ElMessageBox} from "element-plus"; +import rickAnalysis from "./components/riskAnalysis.vue" +import contractManage from "./components/contractManage.vue" +import evaluateTaskNotice from "./components/evaluateTaskNotice.vue" +import {Download} from '@element-plus/icons-vue' +import projectPng from "@/assets/images/project.png" +import status0Png from "@/assets/images/status0.png" +import status1Png from "@/assets/images/status1.png" +import status2Png from "@/assets/images/status2.png" +import itemStatus2Png from "@/assets/images/itemStatus2-1.png" +import { useRoute } from 'vue-router' +import {getProjectStatus} from "@/api/projectManage/project" +import ContractManage from "./components/contractManage"; +import EvaluateTaskNotice from "./components/evaluateTaskNotice" +import EvaluatePlan from "./components/evaluatePlan"; +import EmployNoticeRecord from "./components/employNoticeRecord" +import SiteCheckRcd from "./components/siteCheckRcd" +import InnerReview from "./components/innerReview" +import TechLeaderReview from "./components/techLeaderReview" +import UploadReviewRcd from "./components/uploadReviewRcd" +import RateConclusion from "./components/rateConclusion" +import ProcessCtrlReview from "./components/processCtrlReview" +import ProjectArchive from "./components/projectArchive" +import SignConfirm from "./components/signConfirm" +import ConfirmEnd from "./components/confirmEnd" +import Cookies from "js-cookie" +import {delMonitor} from "@/api/sysUsers"; +const route = useRoute() +const menuList = ref([ + { + id: 'a', + name: '风险分析及计划评价', + status: 1 , + subMenus: [ + { + id: 1, + name: '项目风险分析', + status: 1 // 0:未完成,1:选中待完成,2:已完成 ,3:选中已完成,4:未选中待完成 + }, + { + id: 2, + name: '合同管理', + status: 0 + }, + { + id: 3, + name: '评价任务通知', + status: 0 + }, + { + id: 4, + name: '评价项目计划', + status: 0 + }, + ] + }, + { + id: 'b', + name: '现场勘验', + status: 0, + subMenus: [ + { + id: 5, + name: '从业告知', + status: 0 + }, + { + id: 6, + name: '现场勘验', + status: 0 + }, + ] + }, + { + id: 'c', + name: '项目审核', + status: 0, + subMenus: [ + { + id: 7, + name: '内部审核', + status: 0 + }, + { + id: 8, + name: '技术负责人审核', + status: 0 + }, + { + id: 9, + name: '审核记录', + status: 0 + }, + ] + }, + { + id: 'd', + name: '出具报告', + status: 0, + subMenus: [ + { + id: 10, + name: '评价结论', + status: 0 + }, + { + id: 11, + name: '过程控制负责人审核', + status: 0 + } + ] + }, + { + id: 'e', + name: '项目归档', + status: 0, + subMenus: [ + { + id: 12, + name: '项目归档', + status: 0 + }, + { + id: 13, + name: '签字确认', + status: 0 + }, + { + id: 14, + name: '确认完结', + status: 0 + }, + ] + }, +]) +const riskRef = ref(); +const contractMngRef = ref() +const evaluteRef = ref() +const evalPlanRef = ref() +const employNoticeRcdRef = ref() +const siteCheckRcdRef = ref() +const innerReviewRef = ref() +const techReviewRef = ref() +const uploadReviewRef = ref() +const rateConRef = ref() +const proCtrlRef = ref() +const proArchRef = ref() +const signConfirmRef = ref() +const confirmEndRef = ref() + +const isShowMenu = ref(false) +const selectedObj = ref({}) +const middleHeight = ref(0) +const middleContentHeight = ref(0) +const projectId = ref() +const projectStatus = ref() +const toPath = ref(); +const reportProcess = ref(); +onMounted(() => { + middleHeight.value = window.innerHeight - 250; + middleContentHeight.value = window.innerHeight - 385; + // 监听浏览器高度变化 + window.onresize = () => { + middleHeight.value = window.innerHeight - 250; + middleContentHeight.value = window.innerHeight - 385; + }; + if(route.query.type !== 'add'){ + projectStatus.value = route.query.type; + projectId.value = route.query.id; + toPath.value = route.query.toPath; + reportProcess.value = route.query.process; + getStatus(projectId.value); + }else { + projectStatus.value = route.query.type; + selectedObj.value = { + id: 1, + name: '项目风险分析', + status: 1 + } + } +}); +const nextObj = ref({}) +const setMenuList = (id) => { + menuList.value[id].subMenus.forEach(item => { + item.status = 2; + }) +} +const getStatus = async (projectId) => { + const res = await getProjectStatus(projectId); + if(res.code == 200){ + reportProcess.value = res.data + let fiveObj = {} + if(toPath.value && toPath.value === 'toFive' ){ + fiveObj = menuList.value[1].subMenus[0] + } + if(res.data <= 4 ){ + menuList.value[0].subMenus.forEach(item => { + if(item.id <= res.data){ + item.status = 2 + } + if(projectStatus.value !== 'view'){ + if(item.id === res.data + 1){ + item.status = 4; + nextObj.value = item; + } + } + if(item.id === res.data){ + item.status = 3; + selectedObj.value =item; + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + }) + menuList.value[0].status = 1; + console.log("menu11",menuList.value) + } + if(res.data >=4 && res.data <=6){ + setMenuList(0) + if(res.data === 4){ + menuList.value[0].subMenus[3].status = 3; + } + + menuList.value[1].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(projectStatus.value !== 'view'){ + if(item.id === res.data + 1){ + item.status = 4; + nextObj.value = item; + } + } + if(item.id === res.data){ + item.status = 3; + selectedObj.value =item; + + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 1; + console.log("menu22",menuList.value) + + } + if(res.data >= 6 && res.data <= 9){ + setMenuList(0); + setMenuList(1); + if(res.data === 6){ + menuList.value[1].subMenus[1].status = 3; + } + menuList.value[2].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(projectStatus.value !== 'view'){ + if(item.id === res.data + 1){ + item.status = 4; + nextObj.value = item; + } + } + if(item.id === res.data){ + item.status = 3; + selectedObj.value =item; + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 1; + } + if(res.data >= 9 && res.data <=11){ + setMenuList(0); + setMenuList(1); + setMenuList(2); + if(res.data === 9){ + menuList.value[2].subMenus[2].status = 3; + } + menuList.value[3].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(projectStatus.value !== 'view'){ + if(item.id === res.data + 1){ + item.status = 4; + nextObj.value = item; + } + } + if(item.id === res.data){ + item.status = 3; + selectedObj.value =item; + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 2; + menuList.value[3].status = 1; + } + if(res.data >= 11){ + setMenuList(0); + setMenuList(1); + setMenuList(2); + setMenuList(3); + if(res.data === 11){ + menuList.value[3].subMenus[1].status = 3; + } + let twelveObj = {}; + let thirteenObj = {}; + menuList.value[4].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(projectStatus.value !== 'view'){ + if(item.id === res.data + 1){ + item.status = 4; + nextObj.value = item; + } + } + if(item.id === res.data){ + item.status = 3; + selectedObj.value =item; + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 2; + menuList.value[3].status = 2; + menuList.value[4].status = 1; + if(res.data === 14 && res.data === item.id){ + item.status = 3; + menuList.value[4].status = 2; + selectedObj.value =item; + } + if(toPath.value && toPath.value === 'toTwelve' && item.id === 12){ + twelveObj = item; + }else if(toPath.value && toPath.value === 'toThirteen' && item.id === 13){ + thirteenObj = item; + } + }) + if(toPath.value && toPath.value === 'toTwelve' && twelveObj){ + chooseSubMenu(twelveObj,true) + }else if(toPath.value && toPath.value === 'toThirteen' && thirteenObj){ + chooseSubMenu(thirteenObj,true) + } + } + if(toPath.value && toPath.value === 'toFive' && fiveObj){ + chooseSubMenu(fiveObj,true) + } + + }else{ + ElMessage.warning(res.message) + } +} + +const clickMenu = (val) => { + isShowMenu.value = !isShowMenu.value +} + +const downloadFile = () => { + const link = document.createElement('a') + link.href = 'files/evaluateNotice.doc' + link.target = '_blank' + link.download = '评价任务通知书.doc' + link.click() +} +const downloadCommitFile = () => { + const link = document.createElement('a') + link.href = 'files/commitLetter.doc' + link.target = '_blank' + link.download = '承诺书.doc' + link.click() +} + + +const sixBtn = ref(""); +const chooseSubMenu = (val,flag) => { + if(val.status === 0) { + setTimeout(() => { + isShowMenu.value = false; + ElMessage({ + type: 'warning', + message: '请按顺序操作,未完成步骤无法查看!' + }); + }, 10) + }else if(val.status === 1){ + setTimeout(() => { + isShowMenu.value = false; + selectedObj.value = val; + + }, 10) + }else if(val.status === 2){ + setTimeout(() => { + isShowMenu.value = false; + if((val !== selectedObj.value && nextObj.value === selectedObj.value) || nextObj.value === selectedObj.value){ + nextObj.value = selectedObj.value; + } + if(nextObj.value !== val) { + selectedObj.value.status = 2 + } + + selectedObj.value = val; + selectedObj.value.status = 3; + nextObj.value.status = 4; + //跳转 + }, 10) + if(flag){ + setTimeout(() => { + goRouter(selectedObj.value.id) + }, 10) + } + + }else if (val.status === 3) { + setTimeout(() => { + isShowMenu.value = false; + selectedObj.value = val; + //跳转 + }, 10) + }else if (val.status === 4) { + setTimeout(() => { + if(val.id === 6){ + sixBtn.value = Cookies.get('btn') + } + console.log('sixBtn.value',sixBtn.value) + isShowMenu.value = false; + nextObj.value = selectedObj.value; + selectedObj.value = val; + selectedObj.value.status = 1; + nextObj.value.status = 2; + nextObj.value = val; + //跳转 + }, 10) + } +} +const next = () => { + if(selectedObj.value.status === 3){ + if(selectedObj.value.id + 1 <= 4){ + nextMenu(0) + }else if (selectedObj.value.id+ 1 >4 && selectedObj.value.id+ 1 <= 6){ + nextMenu(1) + }else if (selectedObj.value.id+ 1 >6 && selectedObj.value.id+ 1 <= 9){ + nextMenu(2) + }else if (selectedObj.value.id+ 1 >9 && selectedObj.value.id+ 1 <= 11){ + nextMenu(3) + }else if (selectedObj.value.id+ 1 >11){ + nextMenu(4) + } + }else if(selectedObj.value.id === 6){ + if(selectedObj.value.id === 6) { + ElMessageBox.confirm( + '确定结束现场勘验?', + '提示', + { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning', + }) + .then( async() => { + goRouter(selectedObj.value.id,'sixEnd') + }) + } + } else { + setTimeout(() => { + isShowMenu.value = false; + ElMessage({ + type: 'warning', + message: '请按顺序操作,未完成步骤无法查看!' + }); + }, 10) + } + // + // setTimeout( () => { + // goRouter(selectedObj.value.id) + // }, 100) +} + +const nextMenu = (id) => { + menuList.value[id].subMenus.forEach( item => { + if(item.id === selectedObj.value.id + 1){ + chooseSubMenu(item,true); + } + }) +} + +const backMenu = (id) => { + menuList.value[id].subMenus.forEach(async item => { + if(item.id === selectedObj.value.id - 1){ + await chooseSubMenu(item,true); + } + }) +} + +//上一步——回退(查看详情) +const back = () => { + if(selectedObj.value.id-1 <= 4){ + backMenu(0) + }else if (selectedObj.value.id-1 >4 && selectedObj.value.id-1 <= 6){ + backMenu(1) + }else if (selectedObj.value.id-1 >6 && selectedObj.value.id-1 <= 9){ + backMenu(2) + }else if (selectedObj.value.id-1 >9 && selectedObj.value.id-1 <= 11){ + backMenu(3) + }else if (selectedObj.value.id-1 >11){ + backMenu(4) + } + // setTimeout( () => { + // goRouter(selectedObj.value.id) + // }, 100) + +} +const clickEdit = () => { + goRouter(selectedObj.value.id,'clickEdit') +} +const getNextStatus = async (val) => { + projectId.value = val + const res = await getProjectStatus(val); + if(res.code == 200){ + reportProcess.value = res.data + if(res.data <=4){ + menuList.value[0].subMenus.forEach(item => { + if(item.id <= res.data){ + item.status = 2 + } + if(item.id === res.data + 1){ + item.status = 1; + selectedObj.value =item; + nextObj.value = item; + } + // else if(item.id === res.data ){ + // item.status = 3; + // selectedObj.value =item; + // }else if(item.id === res.data + 1){ + // item.status = 4; + // nextObj.value = item; + // } + }) + menuList.value[0].status = 1; + console.log("menu11",menuList.value) + } + if(res.data >=4 && res.data<=6){ + setMenuList(0) + menuList.value[1].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(item.id === res.data + 1){ + item.status = 1; + selectedObj.value =item; + nextObj.value = item; + } + // if(item.id === res.data){ + // item.status = 3; + // selectedObj.value =item; + // } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 1; + console.log("menu22",menuList.value) + } + if(res.data >= 6 && res.data <= 9){ + setMenuList(0); + setMenuList(1); + menuList.value[2].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(item.id === res.data + 1){ + item.status = 1; + selectedObj.value =item; + nextObj.value = item; + } + // if(item.id === res.data){ + // item.status = 3; + // selectedObj.value =item; + // } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 1; + } + if(res.data >= 9 && res.data <=11){ + setMenuList(0); + setMenuList(1); + setMenuList(2); + menuList.value[3].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(item.id === res.data + 1){ + item.status = 1; + selectedObj.value =item; + nextObj.value = item; + } + // if(item.id === res.data){ + // item.status = 3; + // selectedObj.value =item; + // } + }) + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 2; + menuList.value[3].status = 1; + } + if(res.data >= 11){ + setMenuList(0); + setMenuList(1); + setMenuList(2); + setMenuList(3); + // if(res.data === 11){ + // menuList.value[3].subMenus[1].status = 3; + // } + menuList.value[4].subMenus.forEach(item => { + if(item.id <= res.data) { + item.status = 2 + } + if(item.id === res.data + 1){ + item.status = 1; + selectedObj.value =item; + nextObj.value = item; + } + // if(item.id === res.data){ + // item.status = 3; + // selectedObj.value =item; + // } + menuList.value[0].status = 2; + menuList.value[1].status = 2; + menuList.value[2].status = 2; + menuList.value[3].status = 2; + menuList.value[4].status = 1; + if(res.data === 14 && res.data === item.id){ + item.status = 3; + menuList.value[4].status = 2; + selectedObj.value =item; + } + }) + + } + } +} + +const save = () => { + // if(selectedObj.value.id === 6) { + // ElMessageBox.confirm( + // '确定结束现场勘验?', + // '提示', + // { + // confirmButtonText: '确定', + // cancelButtonText: '取消', + // type: 'warning', + // }) + // .then( async() => { + // goRouter(selectedObj.value.id,'add') + // }) + // }else { + goRouter(selectedObj.value.id,'add') + // } + + +} +const confirm = () => { + goRouter(selectedObj.value.id,'confirm') +} + +const goRouter = (val,type) => { + switch (val){ + case 1: + if(type === 'add'){ + riskRef.value.riskOpen('add',''); + }else if (type === 'clickEdit'){ + riskRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + riskRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + riskRef.value.riskOpen('edit',projectId.value); + } + } + console.log("1") + break; + case 2: + if(type === 'add'){ + contractMngRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + contractMngRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + contractMngRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + contractMngRef.value.riskOpen('edit',projectId.value); + } + } + console.log("2") + break; + case 3: + if(type === 'add'){ + evaluteRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + evaluteRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + evaluteRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + evaluteRef.value.riskOpen('edit',projectId.value); + } + } + console.log("3") + break; + case 4: + if(type === 'add'){ + evalPlanRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + evalPlanRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + evalPlanRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + evalPlanRef.value.riskOpen('edit',projectId.value); + } + } + console.log("4") + break; + case 5: + if(type === 'add'){ + employNoticeRcdRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + employNoticeRcdRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + employNoticeRcdRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + employNoticeRcdRef.value.riskOpen('edit',projectId.value); + } + } + console.log("5") + break; + case 6: + if(type === 'add'){ + siteCheckRcdRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + siteCheckRcdRef.value.riskOpen('clickEdit',projectId.value); + }else if (type === 'sixEnd'){ + siteCheckRcdRef.value.riskOpen('sixEnd',projectId.value); + } else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + siteCheckRcdRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + siteCheckRcdRef.value.riskOpen('edit',projectId.value); + } + } + console.log("6") + break; + case 7: + if(type === 'add'){ + innerReviewRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + innerReviewRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + innerReviewRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + innerReviewRef.value.riskOpen('edit',projectId.value); + } + } + console.log("7") + break; + case 8: + if(type === 'add'){ + techReviewRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + techReviewRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + techReviewRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + techReviewRef.value.riskOpen('edit',projectId.value); + } + } + console.log("8") + break; + case 9: + if(type === 'add'){ + uploadReviewRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + uploadReviewRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + uploadReviewRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + uploadReviewRef.value.riskOpen('edit',projectId.value); + } + } + console.log("9") + break; + case 10: + if(type === 'add'){ + rateConRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + rateConRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + rateConRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + rateConRef.value.riskOpen('edit',projectId.value); + } + } + console.log("10") + break; + case 11: + if(type === 'add'){ + proCtrlRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + proCtrlRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + proCtrlRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + proCtrlRef.value.riskOpen('edit',projectId.value); + } + } + console.log("11") + break; + case 12: + if(type === 'add'){ + proArchRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + proArchRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + proArchRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + proArchRef.value.riskOpen('edit',projectId.value); + } + } + console.log("12") + break; + case 13: + if(type === 'add'){ + signConfirmRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + signConfirmRef.value.riskOpen('clickEdit',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + signConfirmRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + signConfirmRef.value.riskOpen('edit',projectId.value); + } + } + console.log("13") + break; + case 14: + if(type === 'add'){ + confirmEndRef.value.riskOpen('add',projectId.value); + }else if (type === 'clickEdit'){ + confirmEndRef.value.riskOpen('clickEdit',projectId.value); + } + else if (type === 'confirm'){ + confirmEndRef.value.riskOpen('confirm',projectId.value); + }else { + if(projectStatus.value === 'view' || projectStatus.value === 'add'){ + confirmEndRef.value.riskOpen('detail',projectId.value); + }else if(projectStatus.value === 'edit'){ + confirmEndRef.value.riskOpen('edit',projectId.value); + } + } + console.log("14") + break; + } +} + +</script> + +<style scoped lang="scss"> +.process-container{ + height: 100%; + .flow{ + position: relative; + height: 85px; + background: transparent; + .content{ + z-index: 10; + top: 0; + left: 0; + right: 0; + min-height: 85px; + max-height: 85px; + cursor: pointer; + background-color: hsla(0,0%,100%,.97); + //background-image: url(../../../assets/images/bg2.png); + background-repeat: no-repeat; + background-size: 100% 84px; + overflow: hidden; + transition: max-height .3s linear; + position: absolute; + .content-bottom{ + position: relative; + height: 18px; + text-align: center; + background-color: transparent; + pointer-events: none; + } + .content-bottom:after { + content: " "; + cursor: pointer; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + pointer-events: auto; + transform: translateX(-50%); + width: 118px; + background-image: url(../../../assets/images/back1.png); + } + .choose .header-item{ + color: #fff; + background-image: url(../../../assets/images/choosed.png); + } + } + .show{ + cursor: default; + max-height: 600px; + } + .content-middle{ + padding-left: 37px; + padding-right: 27px; + display: flex; + flex-direction: row; + box-shadow: 0 0 18px 3px rgba(145,146,171,.2); + .project-title{ + margin-right: 20px; + height: 85px; + display: flex; + align-items: center; + flex-shrink: 1; + flex-direction: column; + justify-content: center; + font-size: 20px; + font-weight: 700; + color: rgb(255, 140, 138); + } + } + .header-item{ + position: relative; + height: 83px; + color: #5d6c8e; + flex: 1; + margin-left: -2%; + display: flex; + align-items: center; + justify-content: center; + background-repeat: no-repeat; + background-size: 100% 100%; + background-image: url(../../../assets/images/header.png); + cursor: pointer; + .item-content{ + width: 80%; + padding: 0 20px; + display: flex; + align-items: center; + margin-left: 8%; + margin-bottom: 2px; + font-size: 20px; + font-weight: 400; + } + } + .down-item{ + height: 47px; + margin: 30px auto 10px auto; + font-size: 19px; + color: #626c8b; + border: 1px solid #fff; + background: rgba(233 223 211 / 20%); + border-radius: 8px; + display: flex; + align-items: center; + width: 80%; + padding-left: 20px; + padding-right: 15px; + cursor: pointer; + .item-icon-status0{ + width: 21px; + height: 21px; + color: #fff; + font-size: 16px; + line-height: 20px; + text-align: center; + border-radius: 50%; + background: #f3ccb0; + margin-right: 10px; + min-width: 21px; + min-height: 21px; + } + .item-icon-status1{ + color: #f17235; + background: #fff; + } + .item-icon-status2{ + background: transparent; + } + .item-icon-status4{ + background: #0cca8f; + } + } + .itemActive{ + cursor: pointer; + color: #fff; + border: 1px solid #c6e6ff; + background: linear-gradient(90deg,rgb(239, 186, 141),rgb(255, 140, 138)); + } + .itemPrev{ + cursor: pointer; + color: #f38323; + border: 1px solid #f5e4cf; + background: rgb(249 210 170 / 40%); + } + .itemPrev:hover{ + transform: scale(1.1); + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -o-transform: scale(1.1); + -ms-transform: scale(1.1); + } + } + .middle{ + padding: 10px; + .card-header{ + height: 50px; + line-height: 26px; + font-weight: 700; + padding: 12px 56px; + font-size: 18px; + color: #fff; + background-image: url(../../../assets/images/cardHeader2.png); + background-size: 100% 100%; + background-repeat: no-repeat; + margin: -20px; + } + .card-content{ + padding: 20px 60px; + margin-top: 20px; + } + ::-webkit-scrollbar { + display: none; + } + } + .bottom{ + height: 60px; + background: rgb(255, 255, 255); + padding: 9px 10px; + } + .text-eclipse{ + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + font-size: 16px; + } + + +} + +</style> diff --git a/src/views/safetyReview/userManage/expertUsers/components/projectDialog.vue b/src/views/safetyReview/userManage/expertUsers/components/projectDialog.vue index 1c1b972..0b6bcfb 100644 --- a/src/views/safetyReview/userManage/expertUsers/components/projectDialog.vue +++ b/src/views/safetyReview/userManage/expertUsers/components/projectDialog.vue @@ -154,7 +154,13 @@ const toProcess = (type,value,toPath) => { dialogVisible.value = false; value.type = type; - router.push({ path: '/process', query: {id: value.id, type: type, toPath: toPath}}); + if(value.estimateType == 33){ + router.push({ path: '/processTest', query: {id: value.id, type: type, toPath: toPath}}); + }else{ + router.push({ path: '/process', query: {id: value.id, type: type, toPath: toPath}}); + } + + } const goMenu = (toPath,val) => { console.log("val",val) diff --git a/src/views/safetyReview/userManage/institutionUsers/index.vue b/src/views/safetyReview/userManage/institutionUsers/index.vue index 4915282..44ed63e 100644 --- a/src/views/safetyReview/userManage/institutionUsers/index.vue +++ b/src/views/safetyReview/userManage/institutionUsers/index.vue @@ -46,6 +46,7 @@ </div> <!-- 表格数据 --> <el-table v-loading="loading" :data="dataList" :border="true"> + <el-table-column label="序号" type="index" align="center" width="60" /> <el-table-column label="用户ID" prop="id" align="center"/> <el-table-column label="机构名称" prop="agency.name" align="center"/> <el-table-column label="信用代码" prop="agency.creditCode" align="center"/> -- Gitblit v1.9.2