licp
2024-12-18 5d5382d1770819c5546f2130e3d88fa11a75d1fa
完成cnas8.3迁移
已修改4个文件
已添加16个文件
3647 ■■■■ 文件已修改
index.html 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/api/controller.js 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/do/a8-file-handling/ControlledFileApplication.vue 552 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/do/a8-file-handling/DistributionCollectionRecord.vue 614 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/do/a8-file-handling/FileChangeRequest.vue 701 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/do/a8-file-handling/FileList.vue 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/do/a8-file-handling/FileObsoletionRequest.vue 490 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tool/file-preview.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tool/upPdfStamp.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/view/a8-file-handling.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/主任.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/储能.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/射频.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/技术负责人.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/电力.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/综合室.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/装备.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/质量负责人.png 补丁 | 查看 | 原始文档 | blame | 历史
static/img/stamps/通信.png 补丁 | 查看 | 原始文档 | blame | 历史
static/js/menu.js 692 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -1,3 +1,11 @@
<!--
 * @Author: licp lichunping@guanfang.com.cn
 * @Date: 2024-10-28 15:06:45
 * @LastEditors: licp lichunping@guanfang.com.cn
 * @LastEditTime: 2024-12-18 10:21:33
 * @FilePath: \tx-lims-before\index.html
 * @Description: è¿™æ˜¯é»˜è®¤è®¾ç½®,请设置`customMade`, æ‰“å¼€koroFileHeader查看配置 è¿›è¡Œè®¾ç½®: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<!DOCTYPE html>
<html>
<head>
@@ -33,4 +41,5 @@
</body>
<script src="<%= htmlWebpackPlugin.options.url %>/static/luckysheet/plugins/js/plugin.js"></script>
<script src="<%= htmlWebpackPlugin.options.url %>/static/luckysheet/luckysheet.umd.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
</html>
src/assets/api/controller.js
@@ -34,6 +34,7 @@
    evaluate,
    role,
    insProductTemplate,
    manageDocumentList,
  }
}
@@ -428,3 +429,41 @@
  getInsProductTemplate:'/insProductTemplate/getInsProductTemplate',//选择之后查看详情  ä¼ å‚id
  delInsProductTemplate:'/insProductTemplate/delInsProductTemplate',//删除模版  ä¼ å‚id
}
// 8.3 ç®¡ç†ä½“系文件的控制
const manageDocumentList = {
  pageManageDocumentList:'/manageDocumentList/pageManageDocumentList', // æ–‡ä»¶æ¸…单-列表
  doManageDocumentList:'/manageDocumentList/doManageDocumentList', // æ–‡ä»¶æ¸…单-编辑
  uploadFileManageDocumentList:'/manageDocumentList/uploadFileManageDocumentList', // æ–‡ä»¶æ¸…单-附件上传
  exportManageDocumentList:'/manageDocumentList/exportManageDocumentList', // æ–‡ä»¶æ¸…单-附件上传
  delManageDocumentList:'/manageDocumentList/delManageDocumentList', // æ–‡ä»¶æ¸…单-导出
  pageManageDocumentControlled:'/manageDocumentControlled/pageManageDocumentControlled', // æ–‡ä»¶å—控-列表
  addManageDocumentControlled:'/manageDocumentControlled/addManageDocumentControlled', // æ–‡ä»¶å—控-新增
  getManageDocumentControlled:'/manageDocumentControlled/getManageDocumentControlled', // æ–‡ä»¶å—控-查看
  doManageDocumentControlled:'/manageDocumentControlled/doManageDocumentControlled', // æ–‡ä»¶å—控-修改
  delManageDocumentControlled:'/manageDocumentControlled/delManageDocumentControlled', // æ–‡ä»¶å—控-删除
  checkManageDocumentControlled:'/manageDocumentControlled/checkManageDocumentControlled', // æ–‡ä»¶å—控-审核
  checkManageDocumentControlledPdf:'/manageDocumentControlled/checkManageDocumentControlledPdf', // æ–‡ä»¶å—控-获取pdf文件流
  pageManageDocumentCancel:'/manageDocumentCancel/pageManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-列表
  addManageDocumentCancel:'/manageDocumentCancel/addManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-新增
  checkManageDocumentCancel:'/manageDocumentCancel/checkManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-审核
  delManageDocumentCancel:'/manageDocumentCancel/delManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-删除
  getManageDocumentCancel:'/manageDocumentCancel/getManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-查看
  doManageDocumentCancel:'/manageDocumentCancel/doManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-编辑
  exportManageDocumentCancel:'/manageDocumentCancel/exportManageDocumentCancel', // æ–‡ä»¶ä½œåºŸ-导出
  pageManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/pageManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-列表
  addManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/addManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-新增
  delManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/delManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-删除
  getManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/getManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-查看
  doManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/doManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-编辑
  checkManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/checkManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-审核
  exportManageDocumentIssueRecycle:'/manageDocumentIssueRecycle/exportManageDocumentIssueRecycle', // æ–‡ä»¶å‘放回收-导出
  pageManageDocumentAlter:'/manageDocumentAlter/pageManageDocumentAlter', // æ–‡ä»¶å˜æ›´-列表
  delManageDocumentAlter:'/manageDocumentAlter/delManageDocumentAlter', // æ–‡ä»¶å˜æ›´-删除
  getManageDocumentAlter:'/manageDocumentAlter/getManageDocumentAlter', // æ–‡ä»¶å˜æ›´-查看
  addManageDocumentAlter:'/manageDocumentAlter/addManageDocumentAlter', // æ–‡ä»¶å˜æ›´-新增
  doManageDocumentAlter:'/manageDocumentAlter/doManageDocumentAlter', // æ–‡ä»¶å˜æ›´-编辑
  checkManageDocumentAlter:'/manageDocumentAlter/checkManageDocumentAlter', // æ–‡ä»¶å˜æ›´-审核
  checkManageDocumentAlterPdf:'/manageDocumentAlter/checkManageDocumentAlterPdf', // æ–‡ä»¶å˜æ›´-转换流
  exportManageDocumentAlter:'/manageDocumentAlter/exportManageDocumentAlter', // æ–‡ä»¶å˜æ›´-导出
}
src/components/do/a8-file-handling/ControlledFileApplication.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,552 @@
<template>
  <!-- æ–‡ä»¶å—控记录 -->
  <div class="controlled-file-application" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">申请文件编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.documentCode"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">申请人:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.createUserName"
          @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;" v-if="addPower">
        <el-button size="small" type="primary" @click="addDialogVisible=true,addInfo={},file=null">文件受控申请</el-button>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.manageDocumentList.pageManageDocumentControlled"
        :componentData="componentData" :delUrl="$api.manageDocumentList.delManageDocumentControlled" :key="upIndex"/>
    </div>
    <el-dialog
      title="文件受控申请"
      :visible.sync="addDialogVisible"
      width="800px" top="10vh">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.documentCode"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">责任人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.dutyUser" size="small" style="width: 100%;" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件类别:</div>
            <div class="search_input">
              <el-select v-model="addInfo.type" size="small" style="width: 100%;">
                <el-option
                  v-for="item in fileType"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.name"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">上传附件:</div>
            <div class="search_input"><el-upload
            style="margin: 8px 0 0px 50px;"
              action="#"
              :auto-upload="false"
              :multiple="false"
              accept='.pdf' :on-change="handleChangeUpload" v-if="addDialogVisible">
              <el-button size="small" type="primary">上传附件</el-button>
            </el-upload></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作者:</div>
            <div class="search_input">
              <!-- <el-input size="small" placeholder="请输入" clearable v-model="addInfo.writer"></el-input> -->
              <el-select v-model="addInfo.writer" size="small" style="width: 100%;" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.label">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">提交日期:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.submitDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.instructions" type="textarea"
              :rows="2"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="查看附件"
      :visible.sync="lookDialogVisible"
      width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi+'/word/'+currentInfo.url"
      :currentFile="{}" style="height: 90vh;overflow-y: auto;"/>
    </el-dialog>
    <el-dialog
      title="审核"
      :visible.sync="checkDialogVisible"
      width="1000px" top="5vh">
      <UpPdfStamp ref="UpPdfStamp" v-if="checkDialogVisible" @uploadPDF="uploadPDF" :isUpFile="false" style="max-height: 80vh;overflow-y: auto;"></UpPdfStamp>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleCheckSub('不通过')" :loading="noCheckLoading">不通过</el-button>
        <el-button type="primary" @click="handleCheckSub('通过')" :loading="checkLoading">通 è¿‡</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="选择受控章"
      :visible.sync="checkStampDialogVisible"
      width="600px" top="5vh">
      <div class="stamp-list">
        <img :src="'../../../../static/img/stamps/'+item+'.png'" alt="" v-for="(item,index) in stampsList" :key="index" style="width: 120px;height: 80px;margin: 6px;" class="stamp" :class="{active:currentStamp==item}" @click="currentStamp=item">
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="checkStampDialogVisible=false" >取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleCheck0(currentInfo)">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../../tool/value-table.vue'
import filePreview from '../../tool/file-preview.vue'
import UpPdfStamp from '../../tool/upPdfStamp.vue'
export default {
  components: {
    ValueTable,
    filePreview,
    UpPdfStamp
  },
  data() {
    return {
      upLoading: false,
      addPower:false,
      addDialogVisible:false,
      addLoading:false,
      lookDialogVisible:false,
      checkDialogVisible:false,
      checkStampDialogVisible:false,
      componentData: {
        entity: {
          documentCode: null,
          createUserName: null,
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleUpdate',
          font: '编辑',
          type: 'text',
          method: 'handleUpdate',
          field:[],
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy',
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'handleCheck',
          font: '审核',
          type: 'text',
          method: 'handleCheck',
          disabFun: (row, index) => {
            return (row.dutyUserName&&!row.dutyUserName.includes(JSON.parse(localStorage.getItem("user")).name))||row.state=='通过'
          }
        },
        {
          id: 'handleLook',
          font: '查看附件',
          type: 'text',
          method: 'handleLook'
        },
        {
          id: 'handleDown',
          font: '下载附件',
          type: 'text',
          method: 'handleDown'
        }],
        tagField: {
          state:{
            select: [
              {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
        },
        selectField: {
          state:{
            select: []
          },
          signatory:{
            select: []
          },
        },
        datePicker:['effectiveDate'],
        addUpload:['signatoryUrl'],
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      upIndex: 0,
      addInfo:{},
      personList:[],
      fileType:[],
      file:null,
      currentInfo:{},
      checkLoading:false,
      noCheckLoading:false,
      type:'',
      stampsList:['主任','质量负责人','技术负责人','综合室','通信','电力','装备','储能','射频'],
      currentStamp:'主任'
    }
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
    this.getAuthorizedPerson()
    this.selectEnumByCategory()
  },
  methods: {
    getPower(){
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageDocumentControlled') {
          up = true
        }
        if (power[i].menuMethod == 'addManageDocumentControlled') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentControlled') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    getAuthorizedPerson() {
      this.$axios.get(this.$api.user.getUserMenu).then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    selectEnumByCategory() {
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件类别"
      }).then(res => {
        this.fileType = res.data
      })
    },
    // æäº¤
    handleAdd(){
      if(!this.addInfo.documentCode) return this.$message({type:'error',message:"请输入编号"})
      if(!this.addInfo.id){
        // æ–°å¢ž
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if(this.file){
          fd.append("file",this.file.raw);
        }
        for (let m in this.addInfo){
          fd.append(m,this.addInfo[m])
        }
        this.addLoading = true
        this.$axios.post(this.$api.manageDocumentList.addManageDocumentControlled, fd,{
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            noQs:true
          }).then(res => {
            this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '添加成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      }else{
        // ä¿®æ”¹
        let {id,documentCode,dutyUser,type,name,version,writer,submitDate,instructions} = this.addInfo
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if(this.file){
          fd.append("file",this.file.raw);
        }
        fd.append("id",id);
        fd.append("documentCode",documentCode);
        fd.append("dutyUser",dutyUser);
        fd.append("type",type);
        fd.append("name",name);
        fd.append("version",version);
        fd.append("writer",writer);
        fd.append("submitDate",submitDate);
        fd.append("instructions",instructions);
        this.addLoading = true
        this.$axios.post(this.$api.manageDocumentList.doManageDocumentControlled, fd,{
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            noQs:true
          }).then(res => {
            this.addLoading = false
          if (res.code == 200) {
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      }
    },
    handleChangeUpload(file, fileLists){
      this.file = file
      this.$set(this.addInfo,'name',file.name)
    },
    // ç¼–辑
    handleUpdate(row){
      this.title='文件变更申请'
      this.addInfo = this.HaveJson(row)
      this.addDialogVisible = true
    },
    // æŸ¥çœ‹é™„ä»¶
    handleLook(row){
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row){
      this.title='审核'
      this.currentInfo = row
      if(!row.url) return this.$message.warning('文件未上传')
      this.checkStampDialogVisible=true
    },
    handleCheck0(row){
      this.checkStampDialogVisible=false
      this.checkDialogVisible = true
      this.$axios.post(this.$api.manageDocumentList.checkManageDocumentControlledPdf,{id:row.id},{responseType: "blob"}).then(res=>{
        //
        const blob = new Blob([res]);
        const file = new File([blob], row.name, { type: 'application/pdf' })
        this.$refs.UpPdfStamp.lookFile(file,this.currentStamp)
      }).catch(err=>{
        console.log(err)
      })
    },
    handleDown(row){
      if(!row.url) return this.$message.warning('文件未上传')
      let url = this.javaApi+'/word/'+row.url
      const link = document.createElement('a');
      link.href = url;
      link.click();
    },
    async uploadPDF(pdfBlob){
      const formData = new FormData();
      formData.append('file', pdfBlob, this.fileName+'.pdf'); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      formData.append('state', this.type); // æ–‡ä»¶åå­—段
      formData.append('writer', this.currentInfo.writer); // æ–‡ä»¶åå­—段
      let res = await this.$axios.post(this.$api.manageDocumentList.checkManageDocumentControlled, formData,{
        headers: {
            'Content-Type': 'multipart/form-data;'
        },
        noQs: true
      })
      this.checkLoading = false
      this.noCheckLoading = false
      if(res.code==200){
        this.$message({ message: '操作成功', type: 'success' });
        this.checkDialogVisible = false;
        this.refreshTable()
        return true
      }else{
        this.$message({ message: '操作失败', type: 'error' });
        return false
      }
    },
    handleCheckSub(type){
      this.type = type
      if(type == '通过') {
        this.checkLoading = true
      }else{
        this.noCheckLoading = true
      }
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    }
  }
}
</script>
<style scoped>
.title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 40px;
    display: flex;
    align-items: center;
    position: relative;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px);
    padding: 20px;
  }
  .btns{
    position: absolute;
    right: 20px;
    top: 5px;
  }
  .stamp{
    cursor: pointer;
    border: #fff 1px solid;
  }
  .stamp:hover{
    border: #3A7BFA 1px solid;
    box-shadow: inset 0px 0px 15px #3A7BFA;
  }
  .stamp.active{
    border: #3A7BFA 1px solid;
    box-shadow: inset 0px 0px 15px #3A7BFA;
  }
</style>
src/components/do/a8-file-handling/DistributionCollectionRecord.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,614 @@
<template>
  <!-- å‘放回收记录 -->
  <div class="distribution-collection-record" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.documentCode"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.name"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-button size="small" type="primary" @click="addDialogVisible=true,addInfo={},radio='发放'" v-if="addPower">添加发放记录</el-button>
        <el-button size="small" type="primary" v-if="outPower" @click="handleOut" :loading="outLoading">导出</el-button>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.manageDocumentList.pageManageDocumentIssueRecycle"
        :componentData="componentData" :delUrl="$api.manageDocumentList.delManageDocumentIssueRecycle" :key="upIndex"/>
    </div>
    <el-dialog
      :title="'添加'+radio+'记录'"
      :visible.sync="addDialogVisible"
      width="800px" top="10vh">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="changeFileList" :disabled="radio=='回收'" filterable allow-create clearable>
                <el-option
                  v-for="item in fileList"
                  :key="item.documentCode"
                  :label="item.documentCode"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="radio=='发放'">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>发放人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.issueUser" size="small" style="width: 100%;" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-else>
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>回收人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.recycleUser" size="small" style="width: 100%;" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.receiveUser" size="small" style="width: 100%;" :disabled="radio!='发放'" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.name" :disabled="radio=='回收'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" :disabled="radio=='回收'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="addInfo.state" size="small" style="width: 100%;" :disabled="radio=='回收'">
                <el-option :label="item.label" :value="item.value" v-for="(item,index) in fileState" :key="index"></el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="radio=='发放'">
          <div class="search_thing">
            <div class="search_label">发放编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.issueCode"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-else>
          <div class="search_thing">
            <div class="search_label">回收编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.recycleCode"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="radio=='发放'">
          <div class="search_thing">
            <div class="search_label">发放时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.issueDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-else>
          <div class="search_thing">
            <div class="search_label">回收时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.recycleDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="radio=='发放'">
          <div class="search_thing">
            <div class="search_label">发放说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.issueNote" type="textarea"
              :rows="2"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-else>
          <div class="search_thing">
            <div class="search_label">回收说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.recycleNote" type="textarea"
              :rows="2"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;" v-if="radio=='发放'">
          <div class="search_thing">
            <div class="search_label">上传附件:</div>
            <div class="search_input"><el-upload
            style="margin: 8px 0 0px 50px;"
              action="#"
              :auto-upload="false"
              :multiple="false"
              accept='.pdf,.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx' :on-change="handleChangeUpload">
              <el-button size="small" type="primary">上传附件</el-button>
            </el-upload></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="查看附件"
      :visible.sync="lookDialogVisible"
      width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi+'/word/'+currentInfo.url"
      :currentFile="{}" style="height: 90vh;overflow-y: auto;"/>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../../tool/value-table.vue'
import filePreview from '../../tool/file-preview.vue'
export default {
  components: {
    ValueTable,
    filePreview
  },
  data() {
    return {
      ddPower: false,
      outPower:true,
      addInfo: {},
      addPower:true,
      addLoading:false,
      addDialogVisible: false,
      outLoading:false,
      componentData: {
        entity: {
          documentCode: null,
          name: null,
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleUpdate',
          font: '回收记录',
          type: 'text',
          method: 'handleUpdate',
          field:[],
          // disabFun: (row, index) => {
          //   return row.documentState=='通过'
          // }
        },
        {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy',
          disabFun: (row, index) => {
            return row.documentState=='通过'
          }
        },
        {
          id: 'handleLook',
          font: '查看附件',
          type: 'text',
          method: 'handleLook',
          disabFun: (row, index) => {
            return !row.url
          }
        },
        {
          id: 'handleCheck',
          font: '审核',
          type: 'text',
          method: 'handleCheck',
          disabFun: (row, index) => {
            return row.receiveUser!=JSON.parse(localStorage.getItem("user")).userId||row.documentState=='通过'
          }
        },],
        tagField: {
          state:{
            select: [
            {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
        },
        selectField: {
          state:{
            select: [
              {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
          signatory:{
            select: []
          },
        },
        datePicker:['effectiveDate'],
        addUpload:['signatoryUrl'],
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      upIndex: 0,
      personList:[],
      fileList:[],
      fileList0:[],
      radio:'发放',
      fileState:[],
      file:null,
      currentInfo:{},
      lookDialogVisible:false
    }
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
    this.getAuthorizedPerson()
    this.getFileList()
    this.getFileList0()
    this.selectEnumByCategory()
  },
  methods:{
    getPower(){
      let power = JSON.parse(sessionStorage.getItem('power'))
      let out = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'exportManageDocumentIssueRecycle') {
          out = true
        }
        if (power[i].menuMethod == 'addManageDocumentIssueRecycle') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentIssueRecycle') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!add) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    selectEnumByCategory() {
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件状态"
      }).then(res => {
        this.fileState = res.data
        // this.componentData.tagField.state.select = res.data
        // this.componentData.selectField.state.select = res.data
      })
    },
    // èŽ·å–äººå‘˜åˆ—è¡¨
    getAuthorizedPerson() {
      this.$axios.get(this.$api.user.getUserMenu).then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList(){
      this.$axios.post(this.$api.manageDocumentList.pageManageDocumentList,{
        entity: {
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        page:{
          current:-1,
          size:-1
        }
      },{headers: {
            'Content-Type': 'application/json'
          }}).then(res=>{
        this.fileList = res.data.body.records
      }).catch(err=>{})
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--作废文件
    getFileList0(){
      this.$axios.post(this.$api.manageDocumentList.pageManageDocumentCancel,{
        entity: {
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        page:{
          current:-1,
          size:-1
        }
      },{headers: {
            'Content-Type': 'application/json'
          }}).then(res=>{
        this.fileList0 = res.data.body.records
      }).catch(err=>{})
    },
    // å¯¼å‡º
    handleOut(){
      this.outLoading = true
      this.$axios.post(this.$api.manageDocumentList.exportManageDocumentIssueRecycle, {entity:this.componentData.entity},{headers: {
          'Content-Type': 'application/json'
        },responseType: "blob"},).then(res => {
        this.outLoading = false
        this.$message.success('导出成功')
        const blob = new Blob([res],{ type: 'application/octet-stream' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = '发放回收记录.xlsx';
        link.click();
      })
    },
    changeFileList(e){
      if(e){
        let obj = this.fileList.find(a=>a.documentCode == e)
        this.addInfo.name = obj.name
        this.addInfo.version = obj.version
        this.addInfo.state = obj.state
      }
    },
    // æäº¤
    handleAdd(){
      if(!this.addInfo.documentCode){
        this.$message.error('请选择文件')
        return
      }
      if(!this.addInfo.receiveUser){
        this.$message.error('请选择审批人')
        return
      }
      if(this.radio=='发放'){
        if(!this.addInfo.issueUser){
          this.$message.error('请选择发放人')
          return
        }
      }else{
        if(!this.addInfo.recycleUser){
          this.$message.error('请选择回收人')
          return
        }
      }
      this.addLoading = true;
      if(!this.addInfo.id){
        // æ–°å¢žå‘放记录
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if(this.file){
          fd.append("file",this.file.raw);
        }
        for(let key in this.addInfo){
          fd.append(key,this.addInfo[key])
        }
        this.$axios.post(this.$api.manageDocumentList.addManageDocumentIssueRecycle,fd,{
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            noQs:true
          }).then(res=>{
            this.addLoading = false;
          if(res.code==200){
            this.$message.success('发放成功')
            this.addDialogVisible = false
            this.refreshTable()
          }
        })
      }else{
        let {documentCode,id,issueUser,recycleUser,receiveUser,name,version,documentState,issueCode,recycleCode,issueDate,recycleDate,issueNote,recycleNote} = this.addInfo
        // æ·»åŠ å›žæ”¶è®°å½•
        this.$axios.post(this.$api.manageDocumentList.doManageDocumentIssueRecycle,{
          documentCode,id,issueUser,recycleUser,receiveUser,name,version,documentState,issueCode,recycleCode,issueDate,recycleDate,issueNote,recycleNote
        },{headers: {
            'Content-Type': 'application/json'
          },noQS:true}).then(res=>{
            this.addLoading = false;
          if(res.code==200){
            this.$message.success('提交成功')
            this.addDialogVisible = false
            this.refreshTable()
          }
        })
      }
    },
    // æ·»åŠ å›žæ”¶
    handleUpdate(row){
      this.addInfo = this.HaveJson(row)
      this.radio = '回收'
      this.addDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row){
      this.$confirm('是否审核通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            this.$axios.post(this.$api.manageDocumentList.checkManageDocumentIssueRecycle, {id:row.id,documentState:'通过'}).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
            .catch(err => {
            })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            this.$axios.post(this.$api.manageDocumentList.checkManageDocumentIssueRecycle, {id:row.id,documentState:'不通过'}).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
            .catch(err => {
            })
            console.log("取消按钮点击事件,不关闭弹框");
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
          }
      })
    },
    handleChangeUpload(file, fileLists){
      this.file = file
      this.$set(this.addInfo,'name',file.name)
    },
    // æŸ¥çœ‹é™„ä»¶
    handleLook(row){
      this.currentInfo = this.HaveJson(row)
      this.lookDialogVisible = true
    }
  }
}
</script>
<style scoped>
.title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 40px;
    display: flex;
    align-items: center;
    position: relative;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px);
    padding: 20px;
  }
  .btns{
    position: absolute;
    right: 20px;
    top: 5px;
  }
</style>
src/components/do/a8-file-handling/FileChangeRequest.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,701 @@
<template>
  <!-- æ–‡ä»¶å˜æ›´ç”³è¯· -->
  <div class="file-change-request" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">申请文件编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.code"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" v-if="addPower">
        <el-button size="small" type="primary" @click="addDialogVisible=true,addInfo={},currentFile={},title='文件变更申请'">文件变更申请</el-button>
        <el-button size="small" type="primary" v-if="outPower" @click="handleOut" :loading="outLoading">导出</el-button>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.manageDocumentList.pageManageDocumentAlter"
        :componentData="componentData" :delUrl="$api.manageDocumentList.delManageDocumentAlter" :key="upIndex"/>
    </div>
    <el-dialog
      :title="title"
      :visible.sync="addDialogVisible"
      width="950px" top="0vh">
      <el-row style="max-height: 80vh;overflow-y: auto;">
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.code" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.checkUser" size="small" style="width: 100%;" filterable :disabled="title=='审核'">
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">期望变更时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.expectAlterDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;" :disabled="title=='审核'">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">实际变更时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.actuallyAlterDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;"
                :disabled="title=='审核'">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">选择文件:</div>
            <div class="search_input">
              <el-select v-model="addInfo.alterBeforeCode" size="small" style="width: 100%;" @change="getCurrentFile" :disabled="title=='审核'" filterable allow-create clearable>
                <el-option
                  v-for="item in fileList"
                  :key="item.documentCode"
                  :label="item.title"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="24">
          <h4 class="title">当前文件信息</h4>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="currentFile.documentCode" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="currentFile.name" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="currentFile.version" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">提交人:</div>
            <div class="search_input"><el-select v-model="currentFile.createUser" size="small" style="width: 100%;" disabled filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select></div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">审核人:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">作废人:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">提交时间:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="currentFile.createTime" disabled></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">审核时间:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="currentFile.effectiveDate" disabled></el-input></div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">作废时间:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="currentFile.state" size="small" style="width: 100%;" disabled>
                <el-option
                  v-for="item in fileState"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <!-- <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">文件说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.instructions" type="textarea"
              :rows="2" disabled></el-input></div>
          </div>
        </el-col> -->
        <el-col :span="24">
          <h4 class="title">文件变更申请</h4>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后编号:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.alterAfterCode" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.alterAfterName" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">前一版本处理:</div>
            <div class="search_input">
              <el-select v-model="addInfo.method" size="small" style="width: 100%;" :disabled="title=='审核'">
                <el-option label="作废" value="作废"></el-option>
                <el-option label="存档不可用" value="存档不可用">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="8" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更后版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.alterAfterVersion" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="16" style="margin-bottom: 16px;">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">变更说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.alterNote" type="textarea"
              :rows="2" :disabled="title=='审核'"></el-input></div>
          </div>
        </el-col>
        <el-col :span="24" style="margin-bottom: 16px;" v-if="title!='审核'">
          <div class="search_thing" style="width: 100%;">
            <div class="search_label">相关附件:</div>
            <div class="search_input"><el-upload
            style="margin: 8px 0 0px 50px;"
              action="#"
              :auto-upload="false"
              :multiple="false"
              accept='.pdf' :on-change="handleChangeUpload" v-if="addDialogVisible">
              <el-button size="small" type="primary">上传附件</el-button>
            </el-upload></div>
          </div>
        </el-col>
        <UpPdfStamp ref="UpPdfStamp" v-if="title=='审核'&&addDialogVisible" @uploadPDF="uploadPDF" :isUpFile="false"></UpPdfStamp>
      </el-row>
      <span slot="footer" class="dialog-footer" v-if="title!='审核'">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
      <span slot="footer" class="dialog-footer" v-else>
        <el-button @click="handleCheckSub('不通过')" :loading="noCheckLoading">不通过</el-button>
        <el-button type="primary" @click="handleCheckSub('通过')" :loading="checkLoading">通 è¿‡</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="查看附件"
      :visible.sync="lookDialogVisible"
      width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi+'/word/'+currentInfo.alterAfterUrl"
      :currentFile="{}" style="height: 90vh;overflow-y: auto;"/>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../../tool/value-table.vue'
import filePreview from '../../tool/file-preview.vue'
import UpPdfStamp from '../../tool/upPdfStamp.vue'
export default {
  components: {
    ValueTable,
    filePreview,
    UpPdfStamp,
  },
  data() {
    return {
      title:'文件变更申请',
      noCheckLoading:false,
      checkLoading:false,
      addDialogVisible: false,
      addInfo:{},
      componentData: {
        entity: {
          code: null,
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleUpdate',
          font: '编辑',
          type: 'text',
          method: 'handleUpdate',
          field:[],
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy',
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'handleCheck',
          font: '审核',
          type: 'text',
          method: 'handleCheck',
          disabFun: (row, index) => {
            return row.checkUser!=JSON.parse(localStorage.getItem("user")).userId||row.state=='通过'
          }
        },
        {
          id: 'handleLook',
          font: '查看附件',
          type: 'text',
          method: 'handleLook'
        },
        {
          id: 'handleDown',
          font: '下载附件',
          type: 'text',
          method: 'handleDown'
        }],
        tagField: {
          state:{
            select: [
              {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
        },
        selectField: {
          state:{
            select: []
          },
          signatory:{
            select: []
          },
        },
        datePicker:['effectiveDate'],
        addUpload:['signatoryUrl'],
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      upIndex: 0,
      addPower:false,
      outPower:false,
      outLoading:false,
      personList:[],
      fileList:[],
      currentFile:{},
      fileState:[],
      file:null,
      addLoading:false,
      lookDialogVisible:false,
      currentInfo:{
      },
      type:null,
      fileName:null,
    }
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
    this.getAuthorizedPerson()
    this.getFileList()
    this.selectEnumByCategory()
  },
  methods: {
    getPower(){
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let del = false
      let add = false
      let out = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'addManageDocumentAlter') {
          up = true
        }
        if (power[i].menuMethod == 'addManageDocumentAlter') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentAlter') {
          del = true
        }
        if (power[i].menuMethod == 'exportManageDocumentAlter') {
          out = true
        }
      }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    // å¯¼å‡º
    handleOut(){
      this.outLoading = true
      this.$axios.post(this.$api.manageDocumentList.exportManageDocumentAlter, {entity:this.componentData.entity},{headers: {
          'Content-Type': 'application/json'
        },responseType: "blob"},).then(res => {
        this.outLoading = false
        this.$message.success('导出成功')
        const blob = new Blob([res],{ type: 'application/octet-stream' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = '文件变更记录.xlsx';
        link.click();
      })
    },
    getAuthorizedPerson() {
      this.$axios.get(this.$api.user.getUserMenu).then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨--文件清单
    getFileList(){
      this.$axios.post(this.$api.manageDocumentList.pageManageDocumentList,{
        entity: {
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        page:{
          current:-1,
          size:-1
        }
      },{headers: {
        'Content-Type': 'application/json'
      }}).then(res=>{
        this.fileList = res.data.body.records.map(m=>{
          m.title = m.documentCode +':'+m.name
          return m
        })
      }).catch(err=>{})
    },
    // å½“前文件
    getCurrentFile(e){
      this.currentFile = this.fileList.find(m=>m.documentCode==e)
    },
    selectEnumByCategory() {
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件状态"
      }).then(res => {
        this.fileState = res.data
      })
    },
    handleChangeUpload(file, fileLists){
      this.file = file
      this.$set(this.addInfo,'alterAfterName',file.name)
    },
    handleAdd(){
      if(!this.addInfo.code) return this.$message({type:'error',message:"请输入申请编号"})
      if(!this.addInfo.id){
        // æ–°å¢ž
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if(this.file){
          fd.append("file",this.file.raw);
        }
        for (let m in this.addInfo){
          fd.append(m,this.addInfo[m])
        }
        let {name,version,documentCode} = this.currentFile;
        fd.append("alterBeforeName",name);
        fd.append("alterBeforeVersion",version);
        // fd.append("alterBeforeCode",documentCode);
        this.addLoading = true
        this.$axios.post(this.$api.manageDocumentList.addManageDocumentAlter, fd,{
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            noQs:true
          }).then(res => {
            this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '添加成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '添加失败'
            })
          }
        })
      }else{
        // ä¿®æ”¹
        let fd = new FormData();
        //文件信息中raw才是真的文件
        if(this.file){
          fd.append("file",this.file.raw);
        }
        let {name,version} = this.currentFile;
        fd.append("alterBeforeName",name);
        fd.append("alterBeforeVersion",version);
        let {code,checkUser,expectAlterDate,actuallyAlterDate,alterAfterCode,method,alterAfterVersion,alterNote,alterAfterName,id} = this.addInfo
        fd.append("code",code);
        fd.append("checkUser",checkUser);
        fd.append("expectAlterDate",expectAlterDate);
        fd.append("actuallyAlterDate",actuallyAlterDate);
        fd.append("alterAfterCode",alterAfterCode);
        fd.append("method",method);
        fd.append("alterAfterVersion",alterAfterVersion);
        fd.append("alterNote",alterNote);
        fd.append("alterAfterName",alterAfterName);
        fd.append("id",id);
        this.addLoading = true
        this.$axios.post(this.$api.manageDocumentList.doManageDocumentAlter, fd,{
            headers: {
              'Content-Type': 'multipart/form-data'
            },
            noQs:true
          }).then(res => {
            this.addLoading = false
          if (res.code == 200) {
            this.$message({
              type: 'success',
              message: '修改成功'
            })
            this.refreshTable()
            this.addDialogVisible = false
          } else {
            this.$message({
              type: 'error',
              message: '修改失败'
            })
          }
        })
      }
    },
    // ç¼–辑
    handleUpdate(row){
      this.title = '文件变更申请'
      this.addInfo = this.HaveJson(row)
      let alterBeforeCode = this.addInfo.alterBeforeCode
      this.getCurrentFile(alterBeforeCode)
      this.addDialogVisible = true
    },
    // é¢„览
    handleLook(row){
      this.currentInfo = this.HaveJson(row)
      this.lookDialogVisible = true
    },
    // ä¸‹è½½é™„ä»¶
    handleDown(row){
      if(!row.alterAfterUrl) return this.$message.warning('文件未上传')
      let url = this.javaApi+'/word/'+row.alterAfterUrl
      const link = document.createElement('a');
      link.href = url;
      link.click();
    },
    // æ‰“开审核弹框
    handleCheck(row){
      this.title = '审核'
      this.fileName = row.alterAfterName
      if(!row.alterAfterUrl) return this.$message.warning('文件未上传')
      this.addInfo = this.HaveJson(row)
      let alterBeforeCode = this.addInfo.alterBeforeCode
      this.getCurrentFile(alterBeforeCode)
      this.addDialogVisible = true
      this.$axios.post(this.$api.manageDocumentList.checkManageDocumentAlterPdf,{id:row.id},{responseType: "blob"}).then(res=>{
        //
        const blob = new Blob([res]);
        const file = new File([blob], row.name, { type: 'application/pdf' })
        this.$refs.UpPdfStamp.lookFile(file)
        this.currentInfo = row
      }).catch(err=>{
        console.log(err)
      })
    },
    // å®¡æ ¸ä¿å­˜
    async uploadPDF(pdfBlob){
      const formData = new FormData();
      formData.append('file', pdfBlob, this.fileName+'.pdf'); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      formData.append('state', this.type); // æ–‡ä»¶åå­—段
      let res = await this.$axios.post(this.$api.manageDocumentList.checkManageDocumentAlter, formData,{
        headers: {
            'Content-Type': 'multipart/form-data;'
        },
        noQs: true
      })
      this.checkLoading = false
      this.noCheckLoading = false
      if(res.code==200){
        this.$message({ message: '操作成功', type: 'success' });
        this.addDialogVisible = false;
        this.refreshTable()
        return true
      }else{
        this.$message({ message: '操作失败', type: 'error' });
        return false
      }
    },
    // æäº¤å®¡æ ¸
    handleCheckSub(type){
      this.type = type
      if(type == '通过') {
        this.checkLoading = true
      }else{
        this.noCheckLoading = true
      }
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    }
  }
}
</script>
<style scoped>
.title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 40px;
    display: flex;
    align-items: center;
    position: relative;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px);
    padding: 20px;
  }
  .btns{
    position: absolute;
    right: 20px;
    top: 5px;
  }
  h4.title{
    position: relative;
    height: 30px;
    line-height: 30px;
    box-sizing: border-box;
    padding-left: 16px;
    margin-left: 10px;
    margin-bottom: 10px;
  }
  h4.title::after{
    content: '';
    width: 4px;
    height: 20px;
    background: #3A7BFA;
    position: absolute;
    top: 5px;
    left: 0;
  }
</style>
src/components/do/a8-file-handling/FileList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,321 @@
<template>
  <!-- æ–‡ä»¶æ¸…单 -->
  <div class="file-list" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件名称:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.name"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing">
        <div class="search_label">文件状态:</div>
        <div class="search_input">
          <el-select v-model="componentData.entity.state" size="small" @change="refreshTable()">
            <el-option :label="item.label" :value="item.value" v-for="(item,index) in fileState" :key="index"></el-option>
          </el-select>
        </div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-upload :action="action" :multiple="false"
        accept='.xls,.xlsx' :headers="headers" :on-change="beforeUpload"
        :on-error="onError" ref='upload' v-if="addPower" :on-success="handleSuccessUp" :show-file-list="false">
        <el-button size="small" type="primary" :loading="upLoading">导入</el-button></el-upload>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.manageDocumentList.pageManageDocumentList"
        :componentData="componentData" :upUrl="$api.manageDocumentList.doManageDocumentList" :delUrl="$api.manageDocumentList.delManageDocumentList" :key="upIndex"/>
    </div>
    <el-dialog
      title="上传"
      :visible.sync="addDialogVisible"
      width="1000px" top="3vh">
      <UpPdfStamp ref="UpPdfStamp" v-if="addDialogVisible" @uploadPDF="uploadPDF" :isUpFile="true" @uploadPDFErr="uploadPDFErr" style="max-height: 85vh;overflow-y: auto;"></UpPdfStamp>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" v-loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
    <el-dialog
      title="查看附件"
      :visible.sync="lookDialogVisible"
      width="800px" top="5vh" fullscreen>
      <filePreview v-if="lookDialogVisible" :fileUrl="javaApi+'/word/'+currentInfo.url"
      :currentFile="{}" style="height: 90vh;overflow-y: auto;"/>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../../tool/value-table.vue'
import UpPdfStamp from '../../tool/upPdfStamp.vue'
import filePreview from '../../tool/file-preview.vue'
export default {
  components: {
    ValueTable,
    UpPdfStamp,
    filePreview,
  },
  data() {
    return {
      addDialogVisible:false,
      lookDialogVisible:false,
      addPower:false,
      upLoading:false,
      addLoading:false,
      componentData: {
        entity: {
          name: null,
          state: null,
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'update',
          font: '编辑',
          type: 'text',
          method: 'doDiy',
          field:[]
        },
        {
          id: 'handleUp',
          font: '上传',
          type: 'text',
          method: 'handleUp'
        },
        {
          id: 'handleDown',
          font: '下载',
          type: 'text',
          method: 'handleDown'
        },
        {
          id: 'handleLook',
          font: '查看附件',
          type: 'text',
          method: 'handleLook'
        }, {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy'
        },],
        tagField: {
          state:{
            select: []
          },
          type:{
            select: []
          },
        },
        selectField: {
          state:{
            select: []
          },
          type:{
            select: []
          },
        },
        datePicker:['effectiveDate'],
        addUpload:['signatoryUrl'],
        requiredAdd: ['documentCode'],
        requiredUp: ['documentCode'],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      upIndex: 0,
      currentInfo:{},
      fileType:[],
      fileState:[],
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    headers() {
      return {
        'token': sessionStorage.getItem('token')
      }
    },
    action() {
      return this.javaApi +this.$api.manageDocumentList.exportManageDocumentList
    }
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
    this.selectEnumByCategory()
  },
  methods: {
    // ä¸‹è½½æ–‡ä»¶
    handleDown(row) {
      if(!row.url) return this.$message.warning('文件未上传')
      let url = this.javaApi+'/word/'+row.url
      const link = document.createElement('a');
      link.href = url;
      link.click();
    },
    // æŸ¥çœ‹æ–‡ä»¶
    handleLook(row){
      if(!row.url) return this.$message.warning('文件未上传')
      this.currentInfo = row
      this.lookDialogVisible = true
    },
    getPower(){
      let power = JSON.parse(sessionStorage.getItem('power'))
      let up = false
      let upFile = false
      let add = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'doManageDocumentList') {
          up = true
        }
        if (power[i].menuMethod == 'exportManageDocumentList') {
          add = true
        }
        if (power[i].menuMethod == 'uploadFileManageDocumentList') {
          upFile = true
        }
      }
      if (!upFile) {
        this.componentData.do.splice(1, 1)
      }
      if (!up) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    // ä¸Šä¼ æ–‡ä»¶
    handleUp(row) {
      this.currentInfo = row
      this.addDialogVisible = true;
    },
    // æäº¤ä¸Šä¼ 
    handleAdd(){
      this.addLoading = true
      this.$refs['UpPdfStamp'].generatePDF()
    },
    uploadPDFErr(){
      this.addLoading = false
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        // this.upLoading = true;
        return true;
      }
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
      this.$refs.upload.clearFiles()
    },
    handleSuccessUp(response) {
      this.upLoading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()
      }
    },
    selectEnumByCategory() {
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件类别"
      }).then(res => {
        this.fileType = res.data
        this.componentData.tagField.type.select = this.fileType
        this.componentData.selectField.type.select = this.fileType
      })
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件状态"
      }).then(res => {
        this.fileState = res.data
        this.componentData.tagField.state.select = res.data
        this.componentData.selectField.state.select = res.data
      })
    },
    async uploadPDF(pdfBlob) {
      const formData = new FormData();
      formData.append('file', pdfBlob, this.fileName+'.pdf'); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      let res = await this.$axios.post(this.$api.manageDocumentList.uploadFileManageDocumentList, formData,{
        headers: {
            'Content-Type': 'multipart/form-data;'
        },
        noQs: true
      })
      this.addLoading = false
      if(res.code==200){
        this.$message({ message: '上传成功', type: 'success' });
        this.addDialogVisible = false;
        this.refreshTable()
        return true
      }else{
        this.$message({ message: '上传失败', type: 'error' });
        return false
      }
    }
  }
}
</script>
<style scoped>
.title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 40px;
    display: flex;
    align-items: center;
    position: relative;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px);
    padding: 20px;
  }
  .btns{
    position: absolute;
    right: 20px;
    top: 5px;
  }
</style>
src/components/do/a8-file-handling/FileObsoletionRequest.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,490 @@
<template>
  <!-- æ–‡ä»¶ä½œåºŸç”³è¯· -->
  <div class="file-obsoletion-request" style="height: 100%;">
    <div class="search">
      <div class="search_thing">
        <div class="search_label">文件编号:</div>
        <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="componentData.entity.documentCode"
            @keyup.enter.native="refreshTable()"></el-input></div>
      </div>
      <div class="search_thing" style="padding-left: 30px;">
        <el-button size="small" @click="refresh()">重 ç½®</el-button>
        <el-button size="small" type="primary" @click="refreshTable()">查 è¯¢</el-button>
      </div>
      <div class="btns" style="padding-left: 30px;">
        <el-button size="small" type="primary" @click="addDialogVisible=true,addInfo={}" v-if="addPower">文件作废申请</el-button>
        <el-button size="small" type="primary" v-if="outPower" @click="handleOut" :loading="outLoading">导出</el-button>
      </div>
    </div>
    <div class="table">
      <ValueTable ref="ValueTable" :url="$api.manageDocumentList.pageManageDocumentCancel"
        :componentData="componentData" :delUrl="$api.manageDocumentList.delManageDocumentCancel" :key="upIndex"/>
    </div>
    <el-dialog
      title="文件作废申请"
      :visible.sync="addDialogVisible"
      width="800px" top="10vh">
      <el-row>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label"><span style="color:red;margin-right: 4px;">*</span>申请编号:</div>
            <div class="search_input">
              <el-select v-model="addInfo.documentCode" size="small" style="width: 100%;" @change="changeFileList" filterable allow-create clearable>
                <el-option
                  v-for="item in fileList"
                  :key="item.documentCode"
                  :label="item.documentCode"
                  :value="item.documentCode">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">审批人:</div>
            <div class="search_input">
              <el-select v-model="addInfo.checkUser" size="small" style="width: 100%;" filterable>
                <el-option
                  v-for="item in personList"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value">
                </el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件名称:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.name"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件版本:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.version"></el-input></div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">文件状态:</div>
            <div class="search_input">
              <el-select v-model="addInfo.state" size="small" style="width: 100%;" >
                <el-option :label="item.label" :value="item.value" v-for="(item,index) in fileState" :key="index"></el-option>
              </el-select>
            </div>
          </div>
        </el-col>
        <!-- <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作废方式:</div>
            <div class="search_input">
              <el-select v-model="addInfo.method" size="small" style="width: 100%;">
                <el-option label="作废" value="作废"></el-option>
                <el-option label="无效" value="无效"></el-option>
              </el-select>
            </div>
          </div>
        </el-col> -->
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">期望作废时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.expectCancelDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">实际作废时间:</div>
            <div class="search_input">
              <el-date-picker
                v-model="addInfo.actuallyCancelDate"
                type="date"
                size="small"
                placeholder="选择日期"
                format="yyyy-MM-dd"
                value-format="yyyy-MM-dd" style="width: 100%;">
              </el-date-picker>
            </div>
          </div>
        </el-col>
        <el-col :span="12" style="margin-bottom: 16px;">
          <div class="search_thing">
            <div class="search_label">作废说明:</div>
            <div class="search_input"><el-input size="small" placeholder="请输入" clearable v-model="addInfo.cancelNote" type="textarea"
              :rows="2"></el-input></div>
          </div>
        </el-col>
      </el-row>
      <span slot="footer" class="dialog-footer">
        <el-button @click="addDialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="handleAdd" :loading="addLoading">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import ValueTable from '../../tool/value-table.vue'
export default {
  components: {
    ValueTable
  },
  data() {
    return {
      addPower: false,
      outPower:false,
      addInfo: {},
      addLoading:false,
      addDialogVisible: false,
      componentData: {
        entity: {
          documentCode: null,
          state: null,
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleUpdate',
          font: '编辑',
          type: 'text',
          method: 'handleUpdate',
          field:[],
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy',
          disabFun: (row, index) => {
            return row.state=='通过'
          }
        },
        {
          id: 'handleCheck',
          font: '审核',
          type: 'text',
          method: 'handleCheck',
          disabFun: (row, index) => {
            return row.checkUser!=JSON.parse(localStorage.getItem("user")).userId||row.state=='通过'
          }
        },],
        tagField: {
          state:{
            select: [
            {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
        },
        selectField: {
          state:{
            select: [
              {
                value: '通过',
                label: '通过'
              },
              {
                value: '不通过',
                label: '不通过'
              },
            ]
          },
          signatory:{
            select: []
          },
        },
        datePicker:['effectiveDate'],
        addUpload:['signatoryUrl'],
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      entityCopy: {},
      upIndex: 0,
      personList:[],
      fileList:[],
      outLoading:false,
      fileState:[]
    }
  },
  mounted() {
    this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getPower()
    this.getAuthorizedPerson()
    this.getFileList()
    this.selectEnumByCategory()
  },
  methods: {
    getPower(){
      let power = JSON.parse(sessionStorage.getItem('power'))
      let out = false
      let del = false
      let add = false
      // let check = false
      for (var i = 0; i < power.length; i++) {
        if (power[i].menuMethod == 'exportManageDocumentCancel') {
          out = true
        }
        if (power[i].menuMethod == 'addManageDocumentCancel') {
          add = true
        }
        if (power[i].menuMethod == 'delManageDocumentCancel') {
          del = true
        }
        // if (power[i].menuMethod == 'checkManageDocumentControlled') {
        //   check = true
        // }
      }
      // if (!check) {
      //   this.componentData.do.splice(2, 1)
      // }
      if (!del) {
        this.componentData.do.splice(1, 1)
      }
      if (!add) {
        this.componentData.do.splice(0, 1)
      }
      this.addPower = add
      this.outPower = out
    },
    refreshTable() {
      this.$refs['ValueTable'].selectList()
    },
    refresh() {
      this.componentData.entity = this.HaveJson(this.entityCopy)
      this.upIndex++
      this.refreshTable()
    },
    selectEnumByCategory() {
      this.$axios.post(this.$api.enums.selectEnumByCategory, {
        category: "文件状态"
      }).then(res => {
        this.fileState = res.data
        // this.componentData.tagField.state.select = res.data
        // this.componentData.selectField.state.select = res.data
      })
    },
    // èŽ·å–äººå‘˜åˆ—è¡¨
    getAuthorizedPerson() {
      this.$axios.get(this.$api.user.getUserMenu).then(res => {
        let data = []
        res.data.forEach(a => {
          data.push({
            label: a.name,
            value: a.id
          })
        })
        this.personList = data
      })
    },
    // èŽ·å–æ–‡ä»¶åˆ—è¡¨
    getFileList(){
      this.$axios.post(this.$api.manageDocumentList.pageManageDocumentList,{
        entity: {
          orderBy: {
            field: 'createTime',
            order: 'desc'
          }
        },
        page:{
          current:-1,
          size:-1
        }
      },{headers: {
            'Content-Type': 'application/json'
          }}).then(res=>{
        this.fileList = res.data.body.records
      }).catch(err=>{})
    },
    // æäº¤
    handleAdd(){
      if(!this.addInfo.documentCode){
        this.$message.error('请输入申请编号')
        return false
      }
      this.addInfo.method = '作废'
      this.addLoading = true
      if(!this.addInfo.id){
        // æ–°å¢ž
        this.axios.post(this.$api.manageDocumentList.addManageDocumentCancel, this.addInfo,{headers: {
            'Content-Type': 'application/json'
          }}).then(res => {
          this.addLoading = false
          this.refreshTable()
          this.$message({
            type: 'success',
            message: '提交成功'
          })
          this.addDialogVisible = false
        }).catch(err => {})
      }else{
        // ç¼–辑
        this.axios.post(this.$api.manageDocumentList.doManageDocumentCancel, {
          id: this.addInfo.id,
          method: '作废',
          documentCode: this.addInfo.documentCode,
          checkUser: this.addInfo.checkUser,
          name: this.addInfo.name,
          version: this.addInfo.version,
          documentState: this.addInfo.documentState,
          expectCancelDate: this.addInfo.expectCancelDate,
          actuallyCancelDate: this.addInfo.actuallyCancelDate,
          cancelNote: this.addInfo.cancelNote,
        },{headers: {
            'Content-Type': 'application/json'
          }}).then(res => {
          this.addLoading = false
          this.refreshTable()
          this.$message({
            type: 'success',
            message: '提交成功'
          })
          this.addDialogVisible = false
        }).catch(err => {})
      }
    },
    // é€‰ä¸­æ–‡ä»¶
    changeFileList(e){
      if(e){
        let obj = this.fileList.find(a=>a.documentCode == e)
        this.addInfo.name = obj.name
        this.addInfo.version = obj.version
        this.addInfo.documentState = obj.state
      }
    },
    handleUpdate(row){
      this.addInfo = this.HaveJson(row)
      this.addDialogVisible = true
    },
    // å®¡æ ¸
    handleCheck(row){
      this.$confirm('是否审核通过?', '提示', {
        confirmButtonText: '通过',
        cancelButtonText: '不通过',
        type: 'warning',
        closeOnClickModal: false, // ç¦æ­¢ç‚¹å‡»é®ç½©å±‚关闭
        distinguishCancelAndClose: true,
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            // ç‚¹å‡»â€œç¡®å®šâ€æŒ‰é’®ï¼Œå…è®¸å…³é—­
            this.$axios.post(this.$api.manageDocumentList.checkManageDocumentCancel, {id:row.id,state:'通过'}).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
            .catch(err => {
            })
          } else if (action === 'cancel') {
            // ç‚¹å‡»â€œå–消”按钮,不允许关闭
            this.$axios.post(this.$api.manageDocumentList.checkManageDocumentCancel, {id:row.id,state:'不通过'}).then(res => {
              this.refreshTable()
              done();
              this.$message({
                type: 'success',
                message: '提交成功'
              })
            })
            .catch(err => {
            })
            console.log("取消按钮点击事件,不关闭弹框");
          } else if (action === 'close') {
            // ç‚¹å‡»â€œÃ—”按钮,不允许关闭
            done();
            console.log("×按钮点击事件,不关闭弹框");
          }
          }
      })
    },
    // å¯¼å‡º
    handleOut(){
      this.outLoading = true
      this.$axios.post(this.$api.manageDocumentList.exportManageDocumentCancel, {entity:this.componentData.entity},{headers: {
          'Content-Type': 'application/json'
        },responseType: "blob"},).then(res => {
        this.outLoading = false
        this.$message.success('导出成功')
        const blob = new Blob([res],{ type: 'application/octet-stream' });
        const url = URL.createObjectURL(blob);
        const link = document.createElement('a');
        link.href = url;
        link.download = '文件作废表.xlsx';
        link.click();
      })
    }
  }
}
</script>
<style scoped>
.title {
    height: 60px;
    line-height: 60px;
  }
  .search {
    background-color: #fff;
    height: 40px;
    display: flex;
    align-items: center;
    position: relative;
  }
  .search_thing {
    width: 350px;
    display: flex;
    align-items: center;
  }
  .search_label {
    width: 110px;
    font-size: 14px;
    text-align: right;
  }
  .search_input {
    width: calc(100% - 110px);
  }
  .table {
    background-color: #fff;
    width: calc(100% - 40px);
    height: calc(100% - 60px - 80px);
    padding: 20px;
  }
  .btns{
    position: absolute;
    right: 20px;
    top: 5px;
  }
</style>
src/components/tool/file-preview.vue
@@ -4,7 +4,7 @@
      <img :src="fileUrl" alt="Image Preview" />
    </div>
    <div v-if="isPdf">
      <object :data="fileUrl" type="application/pdf" width="100%" height="600px">
      <object :data="fileUrl" type="application/pdf" width="100%" height="750px">
        <p>您的浏览器不支持 PDF é¢„览。<a :href="fileUrl">下载 PDF æ–‡ä»¶</a></p>
      </object>
    </div>
src/components/tool/upPdfStamp.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,164 @@
<template>
  <div class="up-pdf-stamp">
    <div class="work" style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;" v-if="isUpFile">
      <input type="file" @change="handleFileUpload" accept="application/pdf" ref="fileInput" />
    </div>
    <p style="color: red;font-size: 12px;margin: 16px 0;" v-if="canvasNumPages>0">提示:在文件范围内,单击鼠标盖章,双击鼠标已盖好章处可删除当前章</p>
    <canvas ref="pdfCanvas" @click="e=>handleCanvasClick(e,index)" style="border: 1px solid #000;" @dblclick="e=>removeStamp(e,index)" v-for="(item,index) in canvasNumPages" :key="index"></canvas>
  </div>
</template>
<script>
import jsPDF from "jspdf";
export default {
  props:['isUpFile'],
  data() {
    return {
      pdfDoc: null, // å­˜å‚¨ä¸Šä¼ çš„ PDF æ•°æ®
      stamps: [], // è®°å½•盖章的位置
      contextList:[],//canvas列表
      canvasNumPages:0,// å­˜å‚¨ PDF æ€»é¡µæ•°
      stampWidth: 120, // ç›–章宽度
      stampHeight: 80, // ç›–章高度
      stampsName:'',
      stampsList:['主任','质量负责人','技术负责人','综合室','通信','电力','装备','储能','射频'],
      fileName:'文件名'
    };
  },
  methods:{
    handleFileUpload(event){
      const file = event.target.files[0];
      if(file.size>20*1024*1024){
        this.$refs.fileInput.value = ""; // æ¸…空文件输入框内容
        return this.$message.error('文件大小不能超过20M')
      }
      this.lookFile(file)
    },
    lookFile(file,currentStamp){
      this.fileName = file.name
      if(currentStamp){
        this.stampsName = currentStamp
      }else{
        const index = this.stampsList.indexOf(m=>file.name.includes(m))
        if(index>-1){
          this.stampsName = this.stampsList[index]
        }else{
          this.stampsName = '综合室'
        }
      }
      if (file && file.type === 'application/pdf') {
        const reader = new FileReader();
        reader.onload = (e) => {
          const typedArray = new Uint8Array(e.target.result);
          this.loadPDF(typedArray);
        };
        reader.readAsArrayBuffer(file);
      } else {
        this.$message.error('请选择 PDF æ–‡ä»¶');
      }
    },
    loadPDF(typedArray) {
      pdfjsLib.getDocument(typedArray).promise.then(pdfDoc_ => {
        this.pdfDoc = pdfDoc_;
        this.canvasNumPages = this.pdfDoc._pdfInfo.numPages
        this.stamps = []
        this.contextList = []
        for (let i = 1; i <= this.canvasNumPages; i++) {
          this.$nextTick(() => {
            this.renderPage(i); // æ¸²æŸ“页面
          });
          this.stamps.push([])
        }
      });
    },
    // æ¸²æŸ“指定页面
    renderPage(pageNum) {
      this.pdfDoc.getPage(pageNum).then(page => {
        const canvas = this.$refs.pdfCanvas[pageNum-1];
        this.contextList.push(canvas.getContext("2d"))
        const viewport = page.getViewport({ scale: 1.5 });
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        page.render({
          canvasContext: this.contextList[pageNum-1],
          viewport: viewport
        }).promise.then(() => {
          this.stamps[pageNum-1].forEach(m=>{
            this.drawStamps( m.x, m.y,pageNum-1)
          })
        });
      });
    },
    // å•击--添加章
    handleCanvasClick(event,i) {
      const x = event.offsetX;
      const y = event.offsetY;
      const index = this.stamps[i].findIndex(stamp => {
        let x0 = x - stamp.x;
        let y0 =  y - stamp.y;
        return x0>0 && x0 < this.stampWidth && y0>0&& y0 < this.stampHeight;
      });
      if (index > -1) return;
      this.drawStamps( x, y,i)
      this.stamps[i].push({ x, y});
    },
    // åŒå‡»--删除盖章
    removeStamp(event,i) {
      const x = event.offsetX;
      const y = event.offsetY;
      // æŸ¥æ‰¾è¢«åŒå‡»çš„ç›–ç« 
      const index = this.stamps[i].findIndex(stamp => {
        let x0 = x - stamp.x;
        let y0 =  y - stamp.y;
        return x0>0 && x0 < this.stampWidth  && y0>0&& y0 < this.stampHeight;
      });
      if (index === -1) return;
      this.stamps[i].splice(index, 1); // åˆ é™¤æŒ‡å®šçš„ç›–ç« 
      this.contextList[i].clearRect(0, 0, this.contextList[i].width, this.contextList[i].height);
      this.renderPage(i+1)
    },
    // æ¸²æŸ“ç« 
    drawStamps(x,y,index){
      var img = new Image();
      console.log(this.stampsName)
      // è®¾ç½®å›¾ç‰‡æº
      img.src = "/static/img/stamps/"+this.stampsName+".png"; // æ›¿æ¢ä¸ºä½ çš„图片链接
      let that = this
      img.onload = function() {
        // å›¾ç‰‡åŠ è½½å®ŒæˆåŽï¼Œå°†å›¾ç‰‡ç»˜åˆ¶åˆ°canvas上
        that.contextList[index].drawImage(img, x, y, that.stampWidth , that.stampHeight);
      };
    },
    // ç”Ÿæˆ PDF çš„函数
    async generatePDF() {
      if(this.contextList.length===0){
        this.$message({ message: '请先上传PDF文件', type: 'error' });
        this.$emit('uploadPDFErr')
        return false
      }
      const pdf = new jsPDF("p", "mm", "a4");
      for (let i = 0; i < this.contextList.length; i++) {
        const imgData = this.$refs.pdfCanvas[i].toDataURL('image/jpeg', 1.0);
        const pdfWidth = pdf.internal.pageSize.getWidth();
        const pdfHeight = (this.$refs.pdfCanvas[i].height * pdfWidth) / this.$refs.pdfCanvas[i].width;
        pdf.addImage(imgData, "JPEG", 0, 0, pdfWidth, pdfHeight); // å°†å›¾ç‰‡æ·»åŠ åˆ° PDF
        if(i!==this.contextList.length-1){
          pdf.addPage(); // æ·»åŠ æ–°çš„ä¸€é¡µ
        }
      }
      // å°† PDF æ–‡ä»¶ä¿å­˜æˆ–上传
      const pdfOutput = pdf.output('blob'); // èŽ·å– PDF æ–‡ä»¶çš„ Blob å¯¹è±¡
      // ä¸Šä¼ åˆ°åŽç«¯
      return this.$emit('uploadPDF',pdfOutput)
    },
  }
}
</script>
<style scoped>
</style>
src/components/view/a8-file-handling.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
<template>
  <div class="file-handling">
    <el-tabs type="border-card" v-model="activeName" style="height: 100%;">
      <el-tab-pane :label="item.name" :name="item.component" v-for="(item,index) in tabList" :key="index" style="height: 100%;">
        <component :is="item.component" :key="item.component"></component>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import FileList from '../do/a8-file-handling/FileList.vue'
import ControlledFileApplication from '../do/a8-file-handling/ControlledFileApplication.vue'
import DistributionCollectionRecord from '../do/a8-file-handling/DistributionCollectionRecord.vue'
import FileChangeRequest from '../do/a8-file-handling/FileChangeRequest.vue'
import FileObsoletionRequest from '../do/a8-file-handling/FileObsoletionRequest.vue'
export default {
  components: {
    FileList,
    ControlledFileApplication,
    DistributionCollectionRecord,
    FileChangeRequest,
    FileObsoletionRequest
  },
  data() {
    return {
      tabList:[
        {
          name:'文件清单',
          component:'FileList'
        },
        {
          name:'文件受控申请',
          component:'ControlledFileApplication'
        },
        {
          name:'发放回收记录',
          component:'DistributionCollectionRecord'
        },
        {
          name:'文件变更申请',
          component:'FileChangeRequest'
        },
        {
          name:'文件作废申请',
          component:'FileObsoletionRequest'
        },
      ],
      activeName:'FileList'
    };
  },
}
</script>
<style scoped>
.file-handling {
  margin-top: 10px;
  height: calc(100% - 20px);
}
>>>.el-tabs__content{
  height: 100%;
}
</style>
static/img/stamps/Ö÷ÈÎ.png
static/img/stamps/´¢ÄÜ.png
static/img/stamps/É䯵.png
static/img/stamps/¼¼Êõ¸ºÔðÈË.png
static/img/stamps/µçÁ¦.png
static/img/stamps/×ÛºÏÊÒ.png
static/img/stamps/×°±¸.png
static/img/stamps/ÖÊÁ¿¸ºÔðÈË.png
static/img/stamps/ͨÐÅ.png
static/js/menu.js
@@ -307,127 +307,69 @@
        //     p: ""
        // },
    {
            v: "人员总览",
            v: "人员",
            i: "font icon-erjidaohang",
            u: "a6-personnel-overview",
            u: "a6-personnel",
            g: "6.2 äººå‘˜",
            p: "selectPersonnelOverview"
        }, {
            v: "人员明细",
            i: "font icon-erjidaohang",
            u: "a6-personnel-detail",
            g: "6.2 äººå‘˜",
            p: "selectDepartmentLim"
            p: ""
        },
    // {
        //     v: "人员培训",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "人员监督",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "岗位职责",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "人员基本信息",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "工作履历",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "奖惩记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "培训记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "监督记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "任职授权记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "人员能力监控记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "沟通记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.2 äººå‘˜",
        //     p: ""
        // }, {
        //     v: "外来人员管理",
        //     i: "font icon-erjidaohang",
        //     u: "a6-external-personnel-management",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "实验室设施场所信息",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "设施和环境条件要求",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "环境条件引用",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "安全区代表检查",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "安全内务",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // }, {
        //     v: "废物处理交接记录",
        //     i: "font icon-erjidaohang",
        //     u: "a6-waste-handover",
        //     g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
        //     p: ""
        // },
      {
            v: "设施和环境条件",
            i: "font icon-erjidaohang",
            u: "a6-facilities-environment",
            g: "6.3 è®¾æ–½å’ŒçŽ¯å¢ƒæ¡ä»¶",
            p: ""
        },
         {
            v: "设备",
            i: "font icon-erjidaohang",
            u: "a6-device",
            g: "6.4 è®¾å¤‡",
            p: ""
        },
         {
            v: "量值溯源计划",
            i: "font icon-erjidaohang",
            u: "a6-quantity-value-traceability-plan",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        }, {
            v: "标准物质清单",
            i: "font icon-erjidaohang",
            u: "a6-standard-material-list",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        }, {
            v: "标准物质验收",
            i: "font icon-erjidaohang",
            u: "a6-standard-material-accep",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        }, {
            v: "标准物质领用",
            i: "font icon-erjidaohang",
            u: "a6-standard-material-requisition",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        }, {
            v: "过期标样处置",
            i: "font icon-erjidaohang",
            u: "",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        }, {
            v: "服务和供应品采购",
            i: "font icon-erjidaohang",
            u: "a6.service-and-supply-purchase",
            g: "6.6 å¤–部提供的产品和服务",
            p: ""
        },{
            v: "供应商管理",
            i: "font icon-erjidaohang",
            u: "a6-supplier-manage",
            g: "6.6 å¤–部提供的产品和服务",
            p: ""
        },
    {
            v: "设备总览",
            i: "font icon-erjidaohang",
@@ -441,125 +383,13 @@
            g: "6.4 è®¾å¤‡",
            p: "selectDeviceParameter"
        },
    //  {
        //     v: "资源预定",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "作业指导书",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备运行总览",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备档案",
        //     i: "font icon-erjidaohang",
        //     u: "a6-device",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备验收",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备校准",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备核查",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备维护",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备借用",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备故障",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "使用记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "设备停用/启用",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.4 è®¾å¤‡",
        //     p: ""
        // }, {
        //     v: "量值溯源计划",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.5 è®¡é‡æº¯æºæ€§",
        //     p: ""
        // },
    {
            v: "标准物质清单",
            i: "font icon-erjidaohang",
            u: "a6-standard-material-list",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        },
    //  {
        //     v: "标准物质验收",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.5 è®¡é‡æº¯æºæ€§",
        //     p: ""
        // },
     {
            v: "标准物质领用",
            i: "font icon-erjidaohang",
            u: "a6-standard-material-requisition",
            g: "6.5 è®¡é‡æº¯æºæ€§",
            p: ""
        },
    // {
        //     v: "过期标样处置",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.5 è®¡é‡æº¯æºæ€§",
        //     p: ""
        // }, {
        //     v: "服务和供应品采购",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.6 å¤–部提供的产品和服务",
        //     p: ""
        // },{
        //     v: "供应商管理",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "6.6 å¤–部提供的产品和服务",
        //     p: ""
        // }
        }
  ]
    },
    {
@@ -567,203 +397,213 @@
        i: "font icon-guochengyaoqiu",
        p: "",
        c: [
    //   {
        //     v: "检验委托单",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.1 è¦æ±‚、标书和合同评审",
        //     p: ""
        // }, {
        //     v: "合同评审",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.1 è¦æ±‚、标书和合同评审",
        //     p: ""
        // },
    {
            v: "实验室的检测能力档案",
            i: "font icon-erjidaohang",
            u: "a7-standard-method",
            g: "7.2 æ–¹æ³•的选择、验证和确认",
            p: "selectStandardMethodList"
        }
    // , {
        //     v: "标准查新",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.2 æ–¹æ³•的选择、验证和确认",
        //     p: ""
        // }, {
        //     v: "标准方法的变更",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.2 æ–¹æ³•的选择、验证和确认",
        //     p: ""
        // }, {
        //     v: "方法验证",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.2 æ–¹æ³•的选择、验证和确认",
        //     p: ""
        // }, {
        //     v: "抽样",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.3 æŠ½æ ·",
        //     p: ""
        // }, {
        //     v: "检测或校准物品的处置",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.4 æ£€æµ‹æˆ–校准物品的处置",
        //     p: ""
        // }, {
        //     v: "技术记录",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.5 æŠ€æœ¯è®°å½•",
        //     p: ""
        // }, {
        //     v: "测量不确定度的评定",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.6 æµ‹é‡ä¸ç¡®å®šåº¦çš„评定",
        //     p: ""
        // }, {
        //     v: "确保结果有效性",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.7 ç¡®ä¿ç»“果有效性",
        //     p: ""
        // }, {
        //     v: "报告结果",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.8 æŠ¥å‘Šç»“æžœ",
        //     p: ""
        // }, {
        //     v: "投诉详情",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.9 æŠ•诉",
        //     p: ""
        // }, {
        //     v: "投诉情况汇总表",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.9 æŠ•诉",
        //     p: ""
        // }, {
        //     v: "不符合项",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.10 ä¸ç¬¦åˆå·¥ä½œ",
        //     p: ""
        // }, {
        //     v: "不符合项的分布",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.10 ä¸ç¬¦åˆå·¥ä½œ",
        //     p: ""
        // }, {
        //     v: "数据控制和信息管理",
        //     i: "font icon-erjidaohang",
        //     u: "",
        //     g: "7.11 æ•°æ®æŽ§åˆ¶å’Œä¿¡æ¯ç®¡ç†",
        //     p: ""
        // }
      {
        v: "检验委托单",
        i: "font icon-erjidaohang",
        u: "a7-contract-review",
        g: "7.1 è¦æ±‚、标书和合同评审",
        p: "pageProcessOrder"
      }, {
        v: "合同评审",
        i: "font icon-erjidaohang",
        u: "a7-contract-review",
        g: "7.1 è¦æ±‚、标书和合同评审",
        p: "pageProcessOrder"
      }, {
        v: "实验室的检测能力档案",
        i: "font icon-erjidaohang",
        u: "a7-standard-method",
        g: "7.2 æ–¹æ³•的选择、验证和确认",
        p: "selectStandardMethodList"
      }, {
        v: "标准查新",
        i: "font icon-erjidaohang",
        u: "a7-standard-novelty-retrieval",
        g: "7.2 æ–¹æ³•的选择、验证和确认",
        p: ""
      }, {
        v: "标准方法的变更",
        i: "font icon-erjidaohang",
        u: "a7-changes-standard-methods",
        g: "7.2 æ–¹æ³•的选择、验证和确认",
        p: ""
      }, {
        v: "方法验证",
        i: "font icon-erjidaohang",
        u: "a7-method-verification",
        g: "7.2 æ–¹æ³•的选择、验证和确认",
        p: ""
      }, {
        v: "抽样",
        i: "font icon-erjidaohang",
        u: "",
        g: "7.3 æŠ½æ ·",
        p: ""
      }, {
        v: "样品接收",
        i: "font icon-erjidaohang",
        u: "a7-sample-registration",
        g: "7.4 æ£€æµ‹æˆ–校准物品的处置",
        p: "pageProcessTotaldeal"
      },{
        v: "检测或校准物品的处置",
        i: "font icon-erjidaohang",
        u: "a7-sample-disposal",
        g: "7.4 æ£€æµ‹æˆ–校准物品的处置",
        p: "pageProcessTotaldeal"
      }, {
        v: "技术记录",
        i: "font icon-erjidaohang",
        u: "",
        g: "7.5 æŠ€æœ¯è®°å½•",
        p: ""
      }, {
        v: "测量不确定度的评定",
        i: "font icon-erjidaohang",
        u: "a7-uncertainty-evaluation",
        g: "7.6 æµ‹é‡ä¸ç¡®å®šåº¦çš„评定",
        p: "pageProcessEvaluate"
      }, {
        v: "质量监控计划",
        i: "font icon-erjidaohang",
        u: "a7-Ensure-results-validity",
        g: "7.7 ç¡®ä¿ç»“果有效性",
        p: ""
      }, {
        v: "质量监督计划",
        i: "font icon-erjidaohang",
        u: "a7-quality-control-plan",
        g: "7.7 ç¡®ä¿ç»“果有效性",
        p: ""
      }, {
        v: "报告结果",
        i: "font icon-erjidaohang",
        u: "a7-report-results",
        g: "7.8 æŠ¥å‘Šç»“æžœ",
        p: "pageProcessReport"
      },{
        v: "投诉情况汇总表",
        i: "font icon-erjidaohang",
        u: "a7-complaint",
        g: "7.9 æŠ•诉",
        p: "pageProcessComplain"
      }, {
        v: "不符合项",
        i: "font icon-erjidaohang",
        u: "a7-nonconforming-item",
        g: "7.10 ä¸ç¬¦åˆå·¥ä½œ",
        p: ""
      }, {
        v: "不符合项的分布",
        i: "font icon-erjidaohang",
        u: "a7-distribution-of-nonconforming",
        g: "7.10 ä¸ç¬¦åˆå·¥ä½œ",
        p: ""
      }, {
        v: "数据控制和信息管理",
        i: "font icon-erjidaohang",
        u: "",
        g: "7.11 æ•°æ®æŽ§åˆ¶å’Œä¿¡æ¯ç®¡ç†",
        p: ""
      }
  ]
    },
    // {
    //     v: "8 ä½“系管理要求",
    //     i: "font icon-guanlitixiyaoqiu",
    //     p: "",
    //     c: [{
    //         v: "方式",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.1 æ–¹å¼",
    //         p: ""
    //     }, {
    //         v: "管理体系文件",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.2 ç®¡ç†ä½“系文件",
    //         p: ""
    //     }, {
    //         v: "文件清单",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.3 ç®¡ç†ä½“系文件的控制",
    //         p: ""
    //     }, {
    //         v: "文件受控",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.3 ç®¡ç†ä½“系文件的控制",
    //         p: ""
    //     }, {
    //         v: "文件发放回收",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.3 ç®¡ç†ä½“系文件的控制",
    //         p: ""
    //     }, {
    //         v: "文件变更",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.3 ç®¡ç†ä½“系文件的控制",
    //         p: ""
    //     }, {
    //         v: "文件作废",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.3 ç®¡ç†ä½“系文件的控制",
    //         p: ""
    //     }, {
    //         v: "记录的控制",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.4 è®°å½•的控制",
    //         p: ""
    //     }, {
    //         v: "应对风险和机遇的措施",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.5 åº”对风险和机遇的措施",
    //         p: ""
    //     }, {
    //         v: "客户基本信息管理",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.6 æ”¹è¿›",
    //         p: ""
    //     }, {
    //         v: "客户满意度",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.6 æ”¹è¿›",
    //         p: ""
    //     }, {
    //         v: "纠正措施",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.7 çº æ­£æŽªæ–½",
    //         p: ""
    //     }, {
    //         v: "内审管理",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.8 å†…审管理",
    //         p: ""
    //     }, {
    //         v: "管理评审",
    //         i: "font icon-erjidaohang",
    //         u: "",
    //         g: "8.9 ç®¡ç†è¯„审",
    //         p: ""
    //     }]
    // }
    {
        v: "8 ä½“系管理要求",
        i: "font icon-guanlitixiyaoqiu",
        p: "",
        c: [{
            v: "方式",
            i: "font icon-erjidaohang",
            u: "",
            g: "8.1 æ–¹å¼",
            p: ""
        }, {
            v: "管理体系文件",
            i: "font icon-erjidaohang",
            u: "",
            g: "8.2 ç®¡ç†ä½“系文件",
            p: ""
        }, {
            v: "管理体系文件的控制",
            i: "font icon-erjidaohang",
            u: "a8-file-handling",
            g: "8.3 ç®¡ç†ä½“系文件的控制",
            p: "doManageDocumentList pageManageDocumentControlled"
        },{
            v: "文件审批记录",
            i: "font icon-erjidaohang",
            u: "a8-document-approval-records",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordCheck"
        },{
            v: "外来文件确认记录",
            i: "font icon-erjidaohang",
            u: "a8-external-document-confirmation-records",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordTotal"
        },{
            v: "所有文件(内、外部文件)的发放与回收记录",
            i: "font icon-erjidaohang",
            u: "a8-distribution-retrieval-records-all-documents",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordIssueRecycle"
        },{
            v: "文件修订申请审批记录",
            i: "font icon-erjidaohang",
            u: "a8-document-revision-request-approval-records",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordAudit"
        },{
            v: "文件定期审查记录",
            i: "font icon-erjidaohang",
            u: "a8-periodic-document-review-records",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordIntervals"
        },{
            v: "作废文件销毁记录",
            i: "font icon-erjidaohang",
            u: "a8-obsolete-document-destruction-records",
            g: "8.4 è®°å½•的控制",
            p: "pageManageRecordCancel"
        }, {
            v: "应对风险和机遇的措施",
            i: "font icon-erjidaohang",
            u: "a8-measures_deal_risks_opportunities",
            g: "8.5 åº”对风险和机遇的措施",
            p: ""
        }, {
            v: "客户基本信息管理",
            i: "font icon-erjidaohang",
            u: "",
            g: "8.6 æ”¹è¿›",
            p: ""
        }, {
            v: "客户满意度",
            i: "font icon-erjidaohang",
            u: "a8-customer-satisfaction",
            g: "8.6 æ”¹è¿›",
            p: ""
        }, {
            v: "纠正措施",
            i: "font icon-erjidaohang",
            u: "a8-corrective-action",
            g: "8.7 çº æ­£æŽªæ–½",
            p: ""
        }, {
            v: "内审管理",
            i: "font icon-erjidaohang",
            u: "a8-internal-audit-management",
            g: "8.8 å†…审管理",
            p: ""
        }, {
            v: "管理评审",
            i: "font icon-erjidaohang",
            u: "a9-management-review",
            g: "8.9 ç®¡ç†è¯„审",
            p: ""
        }]
    }
]
function computeK() {