zhouwx
2024-06-12 bcc1ce55aa699450905c68f957198428ed251c48
项目补录
已修改4个文件
已添加3个文件
679 ■■■■■ 文件已修改
src/api/backManage/supplement.js 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/menu.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/projectManage/components/rateConclusion.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/projectManage/components/signConfirm.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/projectSupplement/components/supplemenrtDialog.vue 411 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/safetyReview/projectSupplement/index.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/backManage/supplement.js
对比新文件
@@ -0,0 +1,39 @@
import request from '@/utils/request'
export function getSupplementList(params) {
    return request({
        url: '/manage/project-supplement/list',
        method: 'get',
        params: params
    })
}
export function addSupplement(data) {
    return request({
        url: '/manage/project-supplement/add',
        method: 'post',
        data: data
    })
}
export function editSupplement(params) {
    return request({
        url: `/manage/project-supplement/edit`,
        method: 'put',
        data: params
    })
}
export function getSupplementDetail(params) {
    return request({
        url: '/manage/project-supplement/detail/' + params.projectId,
        method: 'get',
    })
}
export function delSupplement(data) {
    return request({
        url: `/manage/project-supplement/remove/` + data.id,
        method: 'delete'
    })
}
src/layout/components/Sidebar/menu.js
@@ -7,6 +7,11 @@
            meta: { title: '项目管理',icon: 'form',affix: true }
        },
        {
            path: '/projectSupplement',
            name: 'projectSupplement',
            meta: { title: '项目补录',icon: 'form',affix: true }
        },
        {
            path: '/institution',
            name: 'Institution',
            meta: { title: '机构公示',icon: 'chart',affix: true }
@@ -102,6 +107,12 @@
            meta: { title: '项目管理',icon: 'form',affix: true }
        },
        {
            path: '/projectSupplement',
            name: 'projectSupplement',
            meta: { title: '项目补录',icon: 'form',affix: true }
        },
        {
            path: '/userManage',
            redirect: '/userManage/supervise',
            meta: { title: '用户管理',icon: 'peoples'},
src/router/index.js
@@ -156,6 +156,19 @@
    ]
  },
  {
    path: '/projectSupplement',
    component: Layout,
    redirect: '/projectSupplement',
    children: [
      {
        path: '/projectSupplement',
        component: () => import('@/views/safetyReview/projectSupplement/index.vue'),
        name: 'projectSupplement',
        meta: { title: '项目补录',icon: 'form', affix: true }
      }
    ]
  },
  {
    path: '/process',
    component: Layout,
    redirect: '/process',
src/views/safetyReview/projectManage/components/rateConclusion.vue
@@ -30,17 +30,18 @@
                :disabled="projectType === 'view' || isEnd"
                 :headers="state.header"
                 method="post"
                 :on-success="handleAvatarSuccess"
                :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='1'
                 :limit='15'
                 :before-upload="picSize"
            >
              <el-button type="primary">附件上传</el-button>
              <el-button type="primary">评价报告上传</el-button>
              <template #tip>
                <div class="el-upload__tip">上传文件尺寸小于5M,最多可上传1份</div>
                <div class="el-upload__tip">上传文件尺寸小于15M,最多可上传15份,多张图片建议合并为PDF文件规范上传。</div>
              </template>
            </el-upload>
          </el-form-item>
@@ -173,16 +174,16 @@
}
const picSize = async (rawFile) => {
  if(rawFile.size / 1024 / 1024 > 2){
  if(rawFile.size / 1024 / 1024 > 15){
    ElMessage({
      type: 'warning',
      message: '文件大小不能超过2M'
      message: '文件大小不能超过15M'
    });
    return false
  }
};
const handleAvatarSuccess = (res) => {
const handleAvatarSuccess = (res,uploadFile) => {
  if(res.code === 200){
    getProcessFiles()
    ElMessage({
src/views/safetyReview/projectManage/components/signConfirm.vue
@@ -5,14 +5,11 @@
      <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">
      <el-table-column label="项目担任角色" prop="username" align="center" width="180">
        <template #default="scope">
          <span>{{ scope.row.planPerson.playRole === 1?'项目负责人': scope.row.planPerson.playRole === 2?
              '项目组成员':scope.row.planPerson.playRole === 3?
                  '过程控制负责人':scope.row.planPerson.playRole === 4?
                      '机构评价负责人':scope.row.planPerson.playRole === 5?
                          '技术负责人':scope.row.planPerson.playRole === 6?'内部审核员':''}}
          </span>
          <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"/>
@@ -134,6 +131,12 @@
        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)
src/views/safetyReview/projectSupplement/components/supplemenrtDialog.vue
对比新文件
@@ -0,0 +1,411 @@
<template>
  <div class="notice">
    <el-dialog
        v-model="dialogVisible"
        :title="title"
        width="550px"
        :before-close="handleClose"
    >
      <el-form :model="state.form" size="default" ref="suppleRef" :rules="state.formRules" label-width="110px" >
        <el-form-item label="所属机构:"  prop="agencyId">
          <el-input v-if="isAgency" v-model="state.agencyName" disabled></el-input>
          <el-select v-model="state.form.agencyId" v-else style="width: 100%" :disabled="isReview" v-loadMore="loadMore" class="m-2" placeholder="请选择机构" popper-class="more_select_dropdown"   >
            <el-option
                v-for="item in state.agencyList"
                :key="item.id"
                :label="item.name"
                :value="item.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="项目名称:" prop="name">
          <el-input v-model.trim="state.form.name" placeholder="请输入项目名称" :disabled="isReview"></el-input>
        </el-form-item>
        <el-form-item label="项目时间:" prop="filingDate">
          <el-date-picker
              :disabled="isReview"
              style="width: 100%"
              v-model="state.form.filingDate"
              type="date"
              value-format="YYYY-MM-DD"
              placeholder="请选择项目时间"
              size="default"
          />
        </el-form-item>
        <el-form-item label="报告撰写人:" prop="writer">
          <el-input v-model.trim="state.form.writer" placeholder="请输入报告撰写人" :disabled="isReview"></el-input>
        </el-form-item>
        <el-form-item label="报告审批人:" prop="reviewer">
          <el-input v-model.trim="state.form.reviewer" placeholder="请输入报告审批人" :disabled="isReview"></el-input>
        </el-form-item>
        <el-form-item label="报告扫描件:" prop="files">
          <el-upload
              style="width: 100%;"
              :disabled="isReview"
              accept="image/*,.pdf,.doc,.docx,.xlsx,.xls"
              :action="state.uploadUrl"
              :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" v-if="!isReview">上传文件尺寸小于15M,最多可上传15份,多张图片建议合并为PDF文件规范上传。</div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer v-if="!isReview">
        <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 {reactive, ref, toRefs} from 'vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {addLaw, editLaw, getLawDetail} from "@/api/backManage/law";
import axios from "axios";
import {getToken} from "@/utils/auth";
import {delAccessoryFile} from "@/api/projectManage/project";
import {addSupplement, editSupplement, getSupplementDetail} from "@/api/backManage/supplement";
import Cookies from "js-cookie";
import {delPic} from "@/api/login";
import {getInsitutionList} from "@/api/backManage/insitution";
import {get} from "@vueuse/core";
const emit = defineEmits(["getList"]);
const dialogVisible = ref(false);
const title = ref("");
const suppleRef = ref();
const isReview = ref(false);
const law = ref(1)
const state = reactive({
  form: {
    agencyId: '',
    id: '',
    name: '',
    filingDate: '',
    writer: '',
    reviewer:'',
    files: []
  },
  formRules:{
    agencyId:[{ required: true, message: '请选择所属机构', trigger: 'blur' }],
    name: [{ required: true, message: '请填写项目名称', trigger: 'blur' }],
    writer: [{ required: true, message: '请填写报告撰写人', trigger: 'blur' }],
    reviewer: [{ required: true, message: '请填写报告审批人', trigger: 'blur' }],
    files: [{ required: true, message: '请上传报告扫描件', trigger: 'blur' }],
    filingDate:[{ required: true, message: '请选择项目时间', trigger: 'blur' }],
  },
  uploadUrl: import.meta.env.VITE_APP_BASE_API + '/system/common/uploadFile',
  header: {
    Authorization: getToken()
  },
  fileList: [],
  agencyName:'',
  agencyId: '',
  agencyList: [],
  pageNum: 1,
  pageSize: 10
})
const isAgency = ref(false);
const getUserInfoAgency = () => {
  const userInfo = JSON.parse(Cookies.get('userInfo'))
  if (userInfo.identity === 1) {
    state.agencyName = userInfo.agentName;
    state.form.agencyId = userInfo.agentId;
    isAgency.value = true;
  } else {
    getAgency()
  }
}
const openDialog = async (type, value) => {
  await getUserInfoAgency();
  isReview.value = false;
  title.value = type === 'add' ? '新增' : type ==='edit' ? '编辑' : '查看' ;
  if(type === 'edit' || type === 'review') {
    const param = {
      projectId: value.id
    }
    const res = await getSupplementDetail(param);
    if(res.code === 200){
      state.form = res.data
      state.form.filingDate = res.data.filingDate.substring(0,10)
      state.fileList = res.data.files.map(item => {
        return {
          ...item,
          name: item.originName,
        }
      })
      console.log('state.fileList',state.form)
    }else{
      ElMessage.warning(res.message)
    }
  }
  if(type === 'add'|| type ==='edit'){
    isReview.value = false;
  }
  if(type === 'review') {
    isReview.value = true;
  }
  dialogVisible.value = true;
}
const onSubmit = async () => {
  const valid = await suppleRef.value.validate();
  if(valid){
    if(title.value === '新增'){
      state.form.filingDate = state.form.filingDate.concat(" 00:00:00")
      state.form.filingDate = state.form.filingDate.substring(0,19)
      state.form.files = state.fileList.map(i=>{
        return {
          originName: i.response.data.originName,
          fileName: i.response.data.filename,
          path: i.response.data.path,
        }
      })
      console.log('dd',state.form)
      const {id, ...data} = JSON.parse(JSON.stringify(state.form))
      // data.agencyId = state.agencyId
      const res = await addSupplement(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '新增成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      reset();
      suppleRef.value.clearValidate();
      dialogVisible.value = false;
    }else if(title.value === '编辑') {
      state.form.filingDate = state.form.filingDate.concat(" 00:00:00")
      state.form.filingDate = state.form.filingDate.substring(0,19)
      console.log('dd',state.form)
      state.form.files = state.fileList.map(i=>{
        return {
          originName: i.response ? i.response.data.originName : i.originName,
          fileName: i.response ? i.response.data.filename : i.fileName ,
          path: i.response ? i.response.data.path : i.path ,
        }
      })
      const {...data} = JSON.parse(JSON.stringify(state.form))
      // data.agencyId = state.agencyId
      const res = await editSupplement(data)
      if(res.code === 200){
        ElMessage({
          type: 'success',
          message: '编辑成功'
        });
      }else{
        ElMessage.warning(res.message)
      }
      emit("getList")
      reset();
      suppleRef.value.clearValidate();
      dialogVisible.value = false;
    }
  }
}
const handleClose = () => {
  reset();
  suppleRef.value.clearValidate();
  dialogVisible.value = false;
}
const reset = () => {
  state.form = {
    agencyId: '',
    id: '',
    name: '',
    filingDate: '',
    writer: '',
    reviewer:'',
    files: []
  }
  state.fileList = [];
}
const handleAvatarSuccess = (res,uploadFile) => {
  if(res.code === 200){
    state.form.files = state.fileList;
    ElMessage({
      type: 'success',
      message: '文件上传成功'
    })
  }else {
    state.fileList.splice(state.fileList.indexOf(uploadFile),1)
    ElMessage({
      type: 'warning',
      message: 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 handleRemove = async (file, uploadFiles) => {
  ElMessageBox.confirm(
      '确定删除该附件?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        let path = "";
        if(file.path){
          path = file.path
        }else {
          path = file.response.data.path
        }
        const res = await delPic({path:path})
        if(res.code == 200){
          ElMessage({
            type: 'success',
            message: '文件已删除'
          })
          state.form.files = state.fileList;
        }else{
          ElMessage({
            type: 'warning',
            message: res.message
          })
        }
      })
      .catch(()=>{
      })
}
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 finshed = ref(false)
const getAgency = async () => {
  const queryParams = {
    pageNum: state.pageNum,
    pageSize: state.pageSize,
  }
  const res = await getInsitutionList(queryParams)
  if(res.code == 200){
    if(res.data.pageNum === state.pageNum){
      finshed.value = false;
      if(state.pageNum == 1){
        state.agencyList = res.data.list
      }else {
        state.agencyList =state.agencyList .concat(res.data.list)
      }
    }else {
      finshed.value = true;
    }
  }else{
    ElMessage.warning(res.message)
  }
}
//触底函数
const loadMore = () => {
  console.log(' 触底了');
  // 防抖处理
  setTimeout(() => {
    if (finshed.value) return //值为true,则代表没有数据了
    state.pageNum += 1
    getAgency()
  }, 500)
}
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;
  }
}
.reviewTable {
  :deep(table){
    border: 1px solid #ccc;
    text-align: center;
  }
  :deep(table td){
    border: 1px solid #ccc;
    text-align: center;
    padding: 0 5px;
  }
  :deep(table th){
    border: 1px solid #ccc;
  }
}
</style>
src/views/safetyReview/projectSupplement/index.vue
对比新文件
@@ -0,0 +1,173 @@
<template>
  <div class="app-container">
    <div style="margin-bottom: 10px">
      <el-button
          type="primary"
          plain
          icon="Plus"
          @click="openDialog('add',{})"
      >新增</el-button>
      <span style="font-size: 15px;color: #ed5565;margin-left: 15px">补录今年1-6月的历史项目</span>
    </div>
    <!-- 表格数据 -->
    <el-table v-loading="loading" :data="dataList" :border="true">
      <el-table-column label="项目名称" prop="name" align="center" width="180" />
      <el-table-column label="项目时间" prop="filingDate" align="center" :show-overflow-tooltip="true"  />
      <el-table-column label="报告撰写人" prop="writer" align="center" :show-overflow-tooltip="true"  />
      <el-table-column label="报告审批人" prop="reviewer" align="center" width="200" />
      <el-table-column label="报告扫描件"  align="center" >
        <template #default="scope">
          <div v-for="(item,index) in scope.row.files" :key="index">
            <span style="color: #1890ff;cursor: pointer" @click="showFile(item)">{{item.originName}}</span>
          </div>
        </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="openDialog('review',scope.row)" >查看</el-button>
          <el-button link type="primary"  @click="openDialog('edit',scope.row)" >编辑</el-button>
          <el-button link type="danger"  @click="handleDelete(scope.row)" >删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <div class="pag-container">
      <el-pagination
          v-model:current-page="data.queryParams.pageNum"
          v-model:page-size="data.queryParams.pageSize"
          :page-sizes="[10,15,20,25]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
      />
    </div>
    <suppleDialog ref="dRef" @getList="getList"></suppleDialog>
  </div>
</template>
<script setup>
import {getCurrentInstance, onMounted, reactive, ref, toRefs} from "vue";
import suppleDialog from './components/supplemenrtDialog.vue'
import {ElMessage, ElMessageBox} from "element-plus";
import {delSupplement, getSupplementList} from "@/api/backManage/supplement";
import axios from "axios";
import {getToken} from "@/utils/auth";
const { proxy } = getCurrentInstance();
const loading = ref(false);
const dRef = ref();
const data = reactive({
  queryParams: {
    pageNum: 1,
    pageSize: 10,
  },
  total: 0,
  dataList: []
});
const { queryParams, total, dataList } = toRefs(data);
onMounted(() => {
  getList();
});
const getList = async () => {
  loading.value = true;
  const res = await getSupplementList(data.queryParams);
  if(res.code === 200){
    dataList.value = res.data.list.map(item => {
      return {
        ...item,
        filingDate: item.filingDate.substring(0,10),
        files: item.files.map(f => {
          return {
            ...f,
            type:f.originName.substring(f.originName.lastIndexOf(".") + 1)
          }
        })
      }
    })
    console.log("dataList.value",dataList.value)
    total.value = res.data.total
  }else{
    ElMessage.warning(res.message)
  }
  loading.value = false;
}
const handleSizeChange = (val) => {
  data.queryParams.pageNum = 1
  data.queryParams.pageSize = val
  getList()
}
const handleCurrentChange = (val) => {
  data.queryParams.pageNum = val
  getList()
}
const openDialog = (type, value) => {
  dRef.value.openDialog(type, value);
}
const handleDelete = (val) => {
  ElMessageBox.confirm(
      '确定删除此条数据?',
      '提示',
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
      .then( async() => {
        const res = await delSupplement(val);
        if(res.code === 200){
          ElMessage({
            type: 'success',
            message: '删除成功'
          });
         await getList();
        }else{
          ElMessage.warning(res.message)
        }
      })
}
const showFile = (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.originName);
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    } else {
      this.$message.error('获取文件失败')
    }
  })
}
</script>
<style lang="scss">
.pag-container{
  float: right;
  margin-top: 10px;
}
</style>