gaoluyang
2025-02-27 dbb368d910c38781d862dc394e13a7779183bd01
Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
# src/views/CNAS/externalService/serviceAndSupplyPro/index.vue
已修改16个文件
已添加6个文件
2208 ■■■■■ 文件已修改
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro.js 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/process/sampleDisposal.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/systemManagement/documentControl.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/UpPdfStamp/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/file.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/AddProject.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableList.vue 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableOverview.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableProject.vue 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue 468 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/component/contents.vue 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/externalService/serviceAndSupplyPro/index.vue 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/sampleDisposal/index.vue 238 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/correctiveAction/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/ControlledFileApplication.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/documentControl/components/FileList.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/systemManagement/measuresDealRisks/components/listRiskAnalysisControlPlans.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/inspectionTask/index.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/performance/class/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -55,6 +55,7 @@
    "jspdf": "^3.0.0",
    "mammoth": "^1.9.0",
    "nprogress": "0.2.0",
    "pako": "^2.1.0",
    "print-js": "^1.6.0",
    "quill": "2.0.2",
    "screenfull": "5.0.2",
src/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro.js
@@ -8,3 +8,223 @@
    params: query
  })
}
export function deleteProcurementSuppliesList(query) {
  return request({
    url: '/procurementSuppliesList/deleteProcurementSuppliesList',
    method: 'delete',
    params: query
  })
}
export function exportProcurementSuppliesList(query) {
  return request({
    url: "/procurementSuppliesList/exportProcurementSuppliesList",
    method: "get",
    responseType: "blob",
    params: query,
  });
}
export function addProcurementSuppliesList(query) {
  return request({
    url: '/procurementSuppliesList/addProcurementSuppliesList',
    method: 'post',
    data: query,
  })
}
export function selectEnumByCategory(query) {
  return request({
    url: '/enum/selectEnumByCategory',
    method: 'post',
    data: query,
  })
}
export function updateProcurementSuppliesList(query) {
  return request({
    url: '/procurementSuppliesList/updateProcurementSuppliesList',
    method: 'post',
    data: query,
  })
}
// æœåŠ¡å’Œä¾›åº”å“é‡‡è´­
export function selectSupplierManagementAll(query) {
  return request({
    url: '/supplierManagement/selectSupplierManagementAll',
    method: 'get',
    params: query
  })
}
export function addProcurementSuppliesExpends(query) {
  return request({
    url: '/procurementSuppliesExpends/addProcurementSuppliesExpends',
    method: 'post',
    data: query,
  })
}
export function deleteProcurementSuppliesExpends(query) {
  return request({
    url: '/procurementSuppliesExpends/deleteProcurementSuppliesExpends',
    method: 'delete',
    params: query
  })
}
export function procurementSuppliesExpendlist(query) {
  return request({
    url: '/procurementSuppliesExpends/procurementSuppliesExpendlist/',
    method: 'get',
    params: query
  })
}
export function exportProcurementSuppliesStoreExcel(query) {
  return request({
    url: '/procurementSuppliesStore/exportExcel',
    method: "get",
    responseType: "blob",
    params: query,
  })
}
// æ–°å¢žèŠ‚ç‚¹
export function addSuppliersDirectoryContents(query) {
  return request({
    url: '/suppliersDirectoryContents/addSuppliersDirectoryContents',
    method: 'post',
    data: query,
  })
}
// ç¼–辑节点
export function updateSuppliersDirectoryContents(query) {
  return request({
    url: '/suppliersDirectoryContents/updateSuppliersDirectoryContents',
    method: 'post',
    data: query,
  })
}
// åˆ é™¤èŠ‚ç‚¹
export function deleteSuppliersDirectoryContentsById(query) {
  return request({
    url: '/suppliersDirectoryContents/deleteSuppliersDirectoryContentsById',
    method: 'delete',
    params: query
  })
}
// é‡‡è´­ç‰©èµ„目录删除
export function deleteProcurementSuppliesContentById(query) {
  return request({
    url: '/procurementSuppliesContents/deleteProcurementSuppliesContentById',
    method: 'delete',
    params: query
  })
}
// æŸ¥è¯¢æ‰€æœ‰èŠ‚ç‚¹
export function getSuppliersDirectoryContentsNodeNames(query) {
  return request({
    url: '/suppliersDirectoryContents/getSuppliersDirectoryContentsNodeNames',
    method: 'get',
    params: query
  })
}
// é‡‡è´­ç‰©èµ„目录获取节点名称
export function getProcurementSuppliesContentsNodeNames(query) {
  return request({
    url: '/procurementSuppliesContents/getNodeNames',
    method: 'get',
    params: query
  })
}
//获取用户列表
export function selectUserCondition(query) {
  return request({
    url: "/system/newUser/selectUserCondition",
    method: "get",
    params: query,
  });
}
// é‡‡è´­ç‰©èµ„目录详情
export function selectProcurementSuppliesContentById(query) {
  return request({
    url: "/procurementSuppliesContents/selectProcurementSuppliesContentById",
    method: "get",
    params: query,
  });
}
// é‡‡è´­ç‰©èµ„目录列表
export function directoryListing(query) {
  return request({
    url: "/procurementSuppliesContents/directoryListing",
    method: "get",
    params: query,
  });
}
// è€—材入库修改
export function updateStore(query) {
  return request({
    url: '/procurementSuppliesStore/updateStore',
    method: 'post',
    data: query,
  })
}
// è€—材入库新增
export function addStore(query) {
  return request({
    url: '/procurementSuppliesStore/addStore',
    method: 'post',
    data: query,
  })
}
// æ ¹æ®id查询耗材入库
export function selectStoreById(query) {
  return request({
    url: "/procurementSuppliesStore/selectStoreById",
    method: "get",
    params: query,
  });
}
// è€—材入库列表
export function storeList(query) {
  return request({
    url: "/procurementSuppliesStore/storeList",
    method: "get",
    params: query,
  });
}
// è€—材入库删除
export function deleteStore(query) {
  return request({
    url: '/procurementSuppliesStore/deleteStore',
    method: 'delete',
    params: query
  })
}
// é‡‡è´­ç‰©èµ„目录新增
export function addProcurementSuppliesContents(query) {
  return request({
    url: '/procurementSuppliesContents/addProcurementSuppliesContents',
    method: 'post',
    data: query,
  })
}
src/api/cnas/process/sampleDisposal.js
@@ -63,3 +63,12 @@
    params: query,
  });
}
//查看历史
export function pageProcessTotaldeal(query) {
  return request({
    url: "/processTotaldeal/pageProcessTotaldeal",
    method: "get",
    params: query,
  });
}
src/api/cnas/systemManagement/documentControl.js
@@ -120,7 +120,7 @@
  return request({
    url: "/manageDocumentIssueRecycle/addManageDocumentIssueRecycle",
    method: "post",
    responseType: "blob",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    data: data,
  });
}
src/components/UpPdfStamp/index.vue
@@ -12,6 +12,7 @@
<script>
import jsPDF from "jspdf";
import file from '@/utils/file.js'
export default {
  props: ['isUpFile'],
  data() {
@@ -142,8 +143,7 @@
      }
      const pdf = new jsPDF("p", "mm", "a4");
      for (let i = 0; i < this.contextList.length; i++) {
        console.log(2222, this.contextList.length, this.$refs.pdfCanvas[i])
        const imgData = this.$refs.pdfCanvas[i].toDataURL('image/jpeg', 1.0);
        const imgData = this.$refs.pdfCanvas[i].toDataURL('image/jpeg', 0.7);
        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
src/utils/file.js
@@ -1,48 +1,55 @@
import { convertToHtml } from 'mammoth';
import Vue from 'vue'
import { convertToHtml } from "mammoth";
import pako from "pako";
import Vue from "vue";
export default {
  async convertFileToHtml(url) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', Vue.prototype.javaApi+url, true);//获取文件流的接口
    xhr.open("GET", Vue.prototype.javaApi + url, true); //获取文件流的接口
    xhr.send();
    xhr.responseType = "blob";//不能漏
    xhr.responseType = "blob"; //不能漏
    let xhrPromise = new Promise((resolve, reject) => {
      xhr.onload = async function () {
        if (this.status === 200) {
          // è¿”回的文件流,转换成blob对象
          var blob = new Blob([this.response],{ type:'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
          var blob = new Blob([this.response], {
            type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
          });
          // ä½¿ç”¨mammoth将Word转换为HTML
          let reader = new FileReader();
          reader.readAsArrayBuffer(blob);
          let htmlContentPromise = new Promise((resolve, reject) => {
            reader.onload = async function () {
              var arrayBuffer = xhr.response; //arrayBuffer
              const result = await convertToHtml({ arrayBuffer: arrayBuffer })
              let html = result.value.replace(//g, '')
              .replace('<h1>', '<h1 style="text-align: center;">')
              .replace(/<table>/g, '<table style="border-collapse: collapse;border: 1px solid #000;">')
              .replace(/<tr>/g, '<tr style="height: 30px;">')
              .replace(/<td>/g, '<td style="border: 1px solid #000;">')
              .replace(/<p>/g, '<p style="text-indent: 2em;">')
              .replace(/<a [^>]*>/g, "")
              .replace(/<\/a>/g, "")
              const result = await convertToHtml({ arrayBuffer: arrayBuffer });
              let html = result.value
                .replace(//g, "")
                .replace("<h1>", '<h1 style="text-align: center;">')
                .replace(
                  /<table>/g,
                  '<table style="border-collapse: collapse;border: 1px solid #000;">'
                )
                .replace(/<tr>/g, '<tr style="height: 30px;">')
                .replace(/<td>/g, '<td style="border: 1px solid #000;">')
                .replace(/<p>/g, '<p style="text-indent: 2em;">')
                .replace(/<a [^>]*>/g, "")
                .replace(/<\/a>/g, "");
              // .replace(/em/g, "cm");
              resolve(html)
              resolve(html);
            };
          })
          resolve(await htmlContentPromise)
          });
          resolve(await htmlContentPromise);
        }
      }
    })
    return await xhrPromise
      };
    });
    return await xhrPromise;
  },
  downloadIamge(imgsrc, name) {//下载图片地址和图片名
  downloadIamge(imgsrc, name) {
    //下载图片地址和图片名
    var image = new Image();
    // è§£å†³è·¨åŸŸ Canvas æ±¡æŸ“问题
    image.setAttribute("crossOrigin", "anonymous");
    image.onload = function() {
    image.onload = function () {
      var canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
@@ -57,5 +64,19 @@
      a.dispatchEvent(event); // è§¦å‘a的单击事件
    };
    image.src = imgsrc;
  }
  },
  // åŽ‹ç¼©blob
  compressBlob(blob) {
    const reader = new FileReader();
    reader.readAsArrayBuffer(blob);
    return new Promise((resolve) => {
      reader.onload = () => {
        const arrayBuffer = reader.result;
        const uint8Array = new Uint8Array(arrayBuffer);
        const compressedData = pako.deflate(uint8Array);
        const compressedBlob = new Blob([compressedData], { type: blob.type });
        resolve(compressedBlob);
      };
    });
  },
};
src/views/CNAS/externalService/serviceAndSupplyPro/component/AddProject.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
<template>
  <el-dialog
    :title="dialogTitle"
    width="60%"
    :visible.sync="dialogVisible"
  >
    <el-form :model="model" label-width="100px">
      <el-col :span="12">
        <el-form-item label="项目名称">
          <el-select
            v-model="model.name"
            placeholder="请选择项目名称"
            style="width: 100%"
            :disabled="row ? true:false"
            @change="handleSelect"
          >
            <el-option
              v-for="(v, i) in consumableOptions"
              :label="v.consumablesName"
              :value="v"
              :key="i"
            />
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="消耗数量">
          <el-input-number v-model="model.amount" :min="0" :step="1" placeholder="请输入消耗数量"></el-input-number>
        </el-form-item>
      </el-col>
    </el-form>
    <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
            <el-button type="primary" @click="sumbit">ç¡® å®š</el-button>
        </span>
  </el-dialog>
</template>
<script>
import {
  addProcurementSuppliesExpends,
  procurementSuppliesList
} from "@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro";
export default {
  data() {
    return {
      dialogTitle: "",
      dialogVisible: false,
      model: {
        listId: undefined,
        name: ""
      },
      consumableOptions: [],
      row: undefined
    }
  },
  created() {
    this.fetchConsumableOptions()
  },
  methods: {
    fetchConsumableOptions() {
      procurementSuppliesList().then(res => {
        if (res.code === 200) {
          this.consumableOptions = res.data.records
        }
      })
    },
    openDialog(row) {
      if(row) {
        console.log(row, 'true')
        this.dialogTitle = `${row.consumablesName}添加消耗项`
        this.row = row
        this.model.listId = row.id
        this.model.name = row.consumablesName
      } else {
        this.dialogTitle = '添加消耗项'
      }
      this.dialogVisible = true
    },
    handleSelect(item) {
      console.log(item)
      this.model.listId = item.id
      this.model.name = item.consumablesName
    },
    sumbit() {
      addProcurementSuppliesExpends(this.model).then(res => {
        if (res.code === 200) {
          this.dialogVisible = false
          this.$emit('submit')
        }
      })
    }
    }
  }
</script>
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,240 @@
<template>
  <div>
    <TableCard :showTitle="false">
      <template slot="form">
        <div class="action-box">
          <div></div>
          <div class="flex">
            <el-button icon="el-icon-plus" size="small" type="primary" @click="showDialog(undefined)">
              æ–°å»º
            </el-button>
            <el-button icon="el-icon-upload2" size="small" @click="exportExcel">
              å¯¼å‡ºExcel
            </el-button>
          </div>
        </div>
      </template>
      <template v-slot:table>
        <limsTable
          :column="columns"
          :currentChange="rowClick"
          :height="'25vh'"
          :highlightCurrentRow="true"
          :isSelection="false"
          :rowStyle="tableRowStyle"
          :table-data="tableData"
          rowKey="id"
          style="margin-top: 18px; padding: 0 15px;"
        >
          <template v-slot:consumablesTypeSlot="{row}">
            {{ findType(row.consumablesType) }}
          </template>
          <template v-slot:operation="scope">
            <el-button size="small" type="text" @click="showDialog(scope.row)">编辑</el-button>
            <el-button size="small" style="color: #f56c6c" type="text" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </limsTable>
        <div class="pagination">
          <div></div>
          <el-pagination
            :page-size="pagination.pageSize"
            :page-sizes="[10, 20, 30, 40]"
            :total="pagination.total"
            layout="total, sizes, prev, pager, next, jumper"
            @current-change="handleCurrent"
            @size-change="handleSize"
          >
          </el-pagination>
        </div>
      </template>
    </TableCard>
    <el-divider></el-divider>
    <div>
      <ConsumableProject ref="consumableProject"></ConsumableProject>
    </div>
    <Edit ref="editRef" :contentsId="contentsId" @submit="fetchData"/>
  </div>
</template>
<script>
import TableCard from './index.vue';
import Edit from "./Edit.vue"
import limsTable from '@/components/Table/lims-table.vue'
import {
  deleteProcurementSuppliesList,
  procurementSuppliesList,
  exportProcurementSuppliesList
} from "@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro";
import ConsumableProject from "./ConsumableProject.vue"
export default {
  dicts: ["consumables_type"],
  components: {
    TableCard, limsTable,Edit, ConsumableProject
  },
  props: {
    contentsId: {
      type: Number,
      required: true,
    }
  },
  watch: {
    contentsId(newVal, oldVal) {
      if (newVal !== 0) {
        this.fetchData()
      }
    }
  },
  data() {
    return {
      columns: [
        {
          label: "货号",
          prop: "itemNumber"
        },
        {
          label: "类别",
          prop: "consumablesType",
          dataType: "slot",
          slot: "consumablesTypeSlot"
        },
        {
          label: "名称",
          prop: "consumablesName"
        },
        {
          label: "规格",
          prop: "specifications"
        },
        {
          label: "参考供应商",
          prop: "supplierName"
        },
        {
          label: "库存下限",
          prop: "lowerLimit"
        },
        {
          label: "当前库存",
          prop: "currentAmount"
        },
        {
          label: "计量单位",
          prop: "unit"
        },
        {
          label: "备注",
          prop: "remark"
        },
        {
          label: "负责人",
          prop: "personInChargeName"
        },
        {
          label: "最近更新人",
          prop: "updateUserName"
        },
        {
          label: "最近更新日期",
          prop: "updateTime"
        },
        {
          fixed: 'right',
          label: "操作",
          width: 120,
          dataType: "slot",
          slot: "operation"
        }
      ],
      tableData: [],
      pagination: {
        current: 1,
        pageSize: 20,
        total: 0
      },
      options: [],
    }
  },
  mounted() {
    this.fetchData()
    this.options = this.dict.type.consumables_type;
  },
  methods: {
    async fetchData() {
      procurementSuppliesList({ contentId: this.contentsId}).then(res => {
        if (res.code === 200) {
          this.tableData = res.data.records
          if (this.tableData.length > 0) {
            this.rowClick(this.tableData[0])
          }
        }
      })
    },
    findType(val) {
      this.$nextTick()
      let res
      const e = this.options.find(item => item.value == val)
      if(e) {
        res = e.label
      } else {
        res = '-'
      }
      return res
    },
    showDialog(row) {
      this.$refs.editRef.openDialog(row);
    },
    async exportExcel() {
      exportProcurementSuppliesList({parentId:this.contentsId}).then(res => {
        const blob = new Blob([res], {type: 'application/octet-stream'});
        this.$download.saveAs(blob, '耗材列表.xlsx')
        this.$message.success('导出成功')
      })
    },
    handleCurrent() {
    },
    handleSize() {
    },
    handleDelete(row) {
      deleteProcurementSuppliesList({ id:row.id }).then(res => {
        if (res.code === 200) {
          this.$message.success('删除成功')
          this.fetchData()
        }
      })
    },
    rowClick(row) {
      this.$refs.consumableProject.fetchListId(row)
    },
    tableRowStyle({row}) {
      if(row.currentAmount <= row.lowerLimit) {
        return { background: '#ffcaca' }
      } else {
        return {}
      }
    }
  }
}
</script>
<style scoped>
.flex {
  display: flex;
}
.action-box {
  width: 100%;
  padding-top: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.pagination {
  padding-top: 15px;
  padding-right: 10px;
  display: flex;
  justify-content: space-between
}
</style>
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableOverview.vue
@@ -29,7 +29,6 @@
import TableCard from './index.vue';
import { procurementSuppliesList } from "@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro"
import limsTable from '@/components/Table/lims-table.vue'
import axios from "axios";
export default {
    components: { CardPanel, TableCard, limsTable },
src/views/CNAS/externalService/serviceAndSupplyPro/component/ConsumableProject.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,164 @@
<template>
  <div>
    <TableCard :showTitle="false">
      <template slot="form">
        <div class="action-box">
          <div></div>
          <div class="flex">
            <el-button icon="el-icon-plus" size="small" type="primary" @click="showDialog">
              æ·»åŠ é¡¹ç›®
            </el-button>
            <el-button icon="el-icon-upload2" size="small" @click="exportExcel">
              å¯¼å‡º
            </el-button>
          </div>
        </div>
      </template>
      <template v-slot:table>
        <limsTable
          :column="columns"
          :height="'25vh'"
          :isSelection="true"
          :table-data="tableData"
          style="margin-top: 18px; padding: 0 15px;"
        >
          <template v-slot:operation="scope">
            <el-button size="small" type="text" @click="deleteData(scope.row)">删除</el-button>
          </template>
        </limsTable>
        <div class="pagination">
          <div></div>
          <el-pagination
            :page-size="pagination.pageSize"
            :page-sizes="[10, 20, 30, 40]"
            :total="pagination.total"
            layout="total, sizes, prev, pager, next, jumper"
            @current-change="handleCurrent"
            @size-change="handleSize"
          >
          </el-pagination>
        </div>
      </template>
    </TableCard>
    <AddProject ref="AddProjectRef" @submit="fetchData"/>
  </div>
</template>
<script>
import TableCard from './index.vue';
import limsTable from '@/components/Table/lims-table.vue'
import Edit from "./Edit.vue"
import AddProject from './AddProject.vue';
import {
  deleteProcurementSuppliesExpends,
  procurementSuppliesExpendlist
} from "@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro";
export default {
  components: {
    TableCard, limsTable, Edit, AddProject
  },
  data() {
    return {
      columns: [
        // {
        //   label: "编号"
        // },
        {
          label: "项目名称",
          prop: "listName"
        },
        {
          label: "消耗数量",
          prop: "amount"
        },
        {
          label: "录入人",
          prop: "enterUserName"
        },
        {
          label: "最近更新人",
          prop: "updateUserName"
        },
        {
          label: "最近更新日期",
          prop: "updateTime"
        },
        {
          label: "操作",
          dataType: "slot",
          slot: "operation"
        }
      ],
      tableData: [],
      pagination: {
        current: 1,
        pageSize: 20,
        total: 0
      },
      listId: 0,
      row: undefined
    }
  },
  mounted() {
    this.fetchData()
  },
  methods: {
    fetchListId(row) {
      if(row) {
        this.listId = row.id
        this.row = row
      }
      this.fetchData()
    },
    async fetchData() {
      if (this.listId === 0) return
      procurementSuppliesExpendlist({
        procurementSuppliesListId:this.listId
      }).then(res => {
        if (res.code === 200) {
          this.tableData = res.data
        }
      })
    },
    showDialog() {
      this.$refs.AddProjectRef.openDialog(this.row);
    },
    deleteData(row) {
      deleteProcurementSuppliesExpends({ expendId:row.expendId}).then(res => {
        if (res.code === 200) {
          this.$message.success('删除成功')
          this.fetchData()
        }
      })
    },
    handleCurrent() {
    },
    handleSize() {
    },
    exportExcel() {
    }
  }
}
</script>
<style scoped>
.flex {
  display: flex;
}
.action-box {
  width: 100%;
  padding-top: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.pagination {
  padding-top: 15px;
  padding-right: 10px;
  display: flex;
  justify-content: space-between
}
</style>
src/views/CNAS/externalService/serviceAndSupplyPro/component/Edit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,252 @@
<template>
  <el-dialog
    :visible.sync="dialogVisible"
    title="添加耗材项目信息"
    width="70%"
  >
    <el-form ref="modelForm" :model="model" :rules="rules" label-width="100px">
      <el-col :span="12">
        <el-form-item label="耗材类型" prop="consumablesType">
          <el-select v-model="model.consumablesType" placeholder="请选择耗材类型" size="small" style="width: 100%">
            <el-option v-for="(v, i) in dict.type.consumables_type" :key="i" :label="v.label" :value="v.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="货号">
          <el-input v-model="model.itemNumber" placeholder="请输入货号" size="small"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="耗材名称">
          <el-input v-model="model.consumablesName" placeholder="请输入耗材名称" size="small"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="规格">
          <el-input v-model="model.specifications" placeholder="请输入规格" size="small"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="计量单位">
          <el-input v-model="model.unit" placeholder="请输入计量单位" size="small"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="参考价格">
          <el-input-number v-model="model.referencePrice" :min="0" :precision="2" :step="0.01" placeholder="请输入参考价格"
                           size="small"></el-input-number>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="存放位置">
          <el-select v-model="model.contentId" placeholder="请选择存放位置" size="small" style="width: 100%">
            <el-option v-for="(v, i) in procurementSuppliesContentOptions" :key="i" :label="v.nodeName"
                       :value="v.id"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="负责人">
          <el-select v-model="model.personInCharge" placeholder="请选择负责人" size="small" style="width: 100%">
            <el-option v-for="(v, i) in userOptions" :key="i" :label="v.name" :value="v.id"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="库存上限">
          <el-input-number v-model="model.upperLimit" :min="0" :step="1" placeholder="请输入库存上限" size="small"></el-input-number>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="库存下限">
          <el-input-number v-model="model.lowerLimit" :min="0" :step="1" placeholder="请输入库存下限" size="small"></el-input-number>
        </el-form-item>
      </el-col>
      <el-col :span="24">
        <el-form-item label="供应商">
          <el-select v-model="model.supplier" placeholder="请选择供应商" size="small" style="width: 100%">
            <el-option v-for="(v, i) in supplierOptions" :key="i" :label="v.supplierName"
                       :value="v.supplierManagementId"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="24">
        <el-form-item label="耗材图标">
          <div class="rows">
            <el-input v-model="model.consumablesIcon" placeholder="请输入耗材图标" size="small" style="width: 90%;"/>
            <el-upload
              ref="upload"
              :action="action"
              :headers="uploadHeader"
              :on-success="onSuccessIcon"
              :show-file-list="false"
              style="float: left; margin: 0 12px 0 20px;"
            >
              <el-button slot="trigger" class="uploadFile" size="small" type="primary">浏览</el-button>
            </el-upload>
          </div>
        </el-form-item>
      </el-col>
      <el-col :span="24">
        <el-form-item label="耗材附件">
          <div class="rows">
            <el-input v-model="model.attachment" placeholder="请输入耗材附件" size="small" style="width: 90%;"/>
            <el-upload
              ref="upload"
              :action="action"
              :on-success="onSuccessFile"
              :show-file-list="false"
              :headers="uploadHeader"
              style="float: left; margin: 0 12px 0 20px;"
            >
              <el-button slot="trigger" class="uploadFile" size="small" type="primary">浏览</el-button>
            </el-upload>
          </div>
        </el-form-item>
      </el-col>
      <el-col :span="24">
        <el-form-item label="备注">
          <el-input
            v-model="model.remark"
            :rows="2"
            placeholder="请输入备注"
            size="small"
            type="textarea"
          >
          </el-input>
        </el-form-item>
      </el-col>
    </el-form>
    <span slot="footer" class="dialog-footer">
            <el-button @click="resetForm">取 æ¶ˆ</el-button>
            <el-button type="primary" @click="submit">保 å­˜</el-button>
        </span>
  </el-dialog>
</template>
<script>
import {
  addProcurementSuppliesList,
  updateProcurementSuppliesList,
  selectSupplierManagementAll,
  getProcurementSuppliesContentsNodeNames,
  selectUserCondition
} from '@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro'
export default {
  data() {
    return {
      dialogVisible: false,
      model: {
        consumablesType: undefined,
        consumablesIcon: undefined,
        attachment: undefined,
      },
      procurementSuppliesContentOptions: [],
      userOptions: [],
      supplierOptions: [],
      rules: {
        consumablesType: [{ required: true, message: '请选择耗材类型', trigger: 'blur' }],
      },
    }
  },
  dicts: ["consumables_type"],
  props: {
    contentsId: {
      type: Number,
      required: true,
    }
  },
  computed: {
    action() {
      return this.javaApi + '/personBasicInfo/saveCNASFile'
    }
  },
  mounted() {
    this.findProcurementSuppliesContentOptions()
    this.findUserOptions()
    this.findSupplierOptions()
  },
  methods: {
    // é‡ç½®è¡¨å•
    resetForm() {
      this.$refs.modelForm.resetFields();
      this.dialogVisible = false
    },
    openDialog(row) {
      if (row) {
        console.log("row", row)
        this.model = row
      } else {
        this.model = {}
      }
      this.dialogVisible = true
    },
    findProcurementSuppliesContentOptions() {
      getProcurementSuppliesContentsNodeNames().then(res => {
        if (res.code === 200) {
          this.procurementSuppliesContentOptions = res.data
        }
      })
    },
    findUserOptions() {
      selectUserCondition().then(res => {
        if (res.code === 200) {
          this.userOptions = res.data
        }
      })
    },
    findSupplierOptions() {
      selectSupplierManagementAll().then(res => {
        if (res.code === 200) {
          this.supplierOptions = res.data
        }
      })
    },
    async onSuccessIcon(response) {
      this.$set(this.model, "consumablesIcon", response.data)
    },
    async onSuccessFile(response) {
      this.$set(this.model, "attachment", response.data)
    },
    submit() {
      this.$refs.modelForm.validate((valid) => {
        if (valid) {
          if (this.model.id) {
            updateProcurementSuppliesList(this.model).then(res => {
              if (res.code === 200) {
                this.dialogVisible = false
              }
            })
          } else {
            addProcurementSuppliesList(this.model).then(res => {
              if (res.code === 200) {
                this.dialogVisible = false
                this.$emit('submit')
              }
            })
          }
        }
      })
    }
  }
}
</script>
<style scoped>
>>>.el-dialog {
  margin: 6vh auto 50px !important;
}
>>> .el-dialog__body {
  max-height: 42em;
  overflow-y: auto;
}
.rows {
  width: 100%;
  display: flex;
  justify-content: space-between;
}
>>>.el-form-item__content {
  line-height: 39px;
}
</style>
src/views/CNAS/externalService/serviceAndSupplyPro/component/Store.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,468 @@
<template>
  <div>
    <div style="
        display: flex;
        justify-content: flex-end;
        margin-right: 20px;
        margin-bottom: 20px;
      ">
      <el-button icon="el-icon-plus" size="small" type="primary" @click="addOrUpdateStore('add')">添加
      </el-button>
      <el-button icon="el-icon-download" size="small" @click="importExcel">
        å¯¼å‡ºexcel
      </el-button>
    </div>
    <div class="table">
      <limsTable
        :column="tableColumn"
        :height="'calc(100vh - 20em)'"
        :table-data="storageTableData"
        :table-loading="tableLoading"
        style="padding: 0 10px;margin-bottom: 16px"
        :page="page"
        @pagination="pagination">
      </limsTable>
    </div>
    <!-- ç¼–辑-新增弹框 -->
    <el-dialog :before-close="handleClose" :close-on-click-modal="false"
               :close-on-press-escape="false" :title="title"
               :visible.sync="dialogVisible" width="70%">
      <!-- å…¥åº“单 -->
      <div>
        <div style="display: flex; align-items: center">
          <span style="margin-left: 10px">入库单</span>
        </div>
        <el-form ref="formModel" :model="form" label-width="auto">
          <el-col :span="12">
            <el-form-item label="入库单号">
              <el-input v-model="form.oddNumbers" placeholder="请输入入库单号" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="入库库存">
              <el-input v-model="form.inventory" placeholder="请输入入库库存" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="入库总金额">
              <el-input v-model="form.totalAmount" placeholder="请输入入库总金额" size="small"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="入库日期">
              <el-date-picker v-model="form.storageTime" format="yyyy-MM-dd"
                              placeholder="选择日期"
                              size="small"
                              style="width: 100%" type="date" value-format="yyyy-MM-dd"></el-date-picker>
            </el-form-item>
          </el-col>
            <el-col :span="12">
              <el-form-item label="入库人">
                <el-select v-model="form.storageUser" size="small" style="width: 100%">
                  <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
                </el-select>
              </el-form-item>
            </el-col>
          <el-col :span="12">
            <el-form-item label="入库说明">
              <el-input v-model="form.remark" :rows="2" placeholder="请输入内容" type="textarea">
              </el-input>
            </el-form-item>
          </el-col>
        </el-form>
      </div>
      <!-- å…¥åº“明细 -->
      <div>
        <div>入库明细</div>
        <div class="input-form">
          <div>
            <div>
              <span>耗材名称:</span>
              <el-select v-model="formTwo.id" filterable placeholder="请选择耗材名称" size="small" style="width: 70%">
                <el-option v-for="(v, i) in consumableOptions" :key="i" :label="v.consumablesName"
                  :value="v.id"></el-option>
              </el-select>
            </div>
          </div>
          <div>
            <div>
              <span>单价:</span>
              <el-input v-model="formTwo.unitPrice" placeholder="请输入单价" size="small" style="width: 70%">
              </el-input>
            </div>
          </div>
          <div>
            <div>
              <span>入库数量:</span>
              <el-input v-model="formTwo.storeNumber" placeholder="请输入入库数量" size="small" style="width: 70%">
              </el-input>
            </div>
          </div>
          <div>
            <div>
              <span>总价:</span>
              <el-input v-model="formTwo.totalPrice" placeholder="请输入总价" size="small" style="width: 70%">
              </el-input>
            </div>
          </div>
          <el-button size="mini" type="primary"
            @click="addTableData">添加
          </el-button>
        </div>
        <el-table :data="consumables" style="margin-top: 10px">
          <el-table-column label="编号" type="index" width="120px"></el-table-column>
          <el-table-column label="货号" prop="itemNumber"></el-table-column>
          <el-table-column label="类别" prop="type"></el-table-column>
          <el-table-column label="名称" prop="consumablesName"></el-table-column>
          <el-table-column label="规格" prop="specifications"></el-table-column>
          <el-table-column label="参考供应商" prop="supplier"></el-table-column>
          <el-table-column label="计量单位" prop="unit"></el-table-column>
          <el-table-column label="单价" prop="unitPrice"></el-table-column>
          <el-table-column label="入库数量" prop="storeNumber"></el-table-column>
          <el-table-column label="总价" prop="totalPrice"></el-table-column>
          <el-table-column label="操作" width="80px">
            <template slot-scope="scope">
              <el-button size="mini" style="color: #f56c6c" type="text" @click="deleteTableData(scope.$index)">删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleClose">取 æ¶ˆ</el-button>
        <el-button type="primary" :loading="saveLoading" @click="save">保 å­˜</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addStore,
  deleteStore,
  exportProcurementSuppliesStoreExcel,
  procurementSuppliesList,
  selectStoreById,
  selectUserCondition,
  storeList,
  updateStore
} from '@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro'
import limsTable from '@/components/Table/lims-table.vue'
export default {
  computed: {
    title() {
      return this.dialogType == "add" ? "新建入库" : "编辑入库";
    },
  },
  dicts: ["consumables_type"],
  props: {
    contentsId: {
      type: Number,
      default: 0
    }
  },
  watch: {
  },
  data() {
    return {
      mutiList: [],
      consumables: [],
      users: [],
      form: {
        oddNumbers: null,
        inventory: null,
        totalAmount: null,
        storageTime: null,
        storageUser: null,
        remark: null,
      },
      formTwo: {
        consumablesName: null,
        unitPrice: null,
        storeNumber: null,
        totalPrice: null,
      },
      dialogVisible: false,
      dialogType: "",
      upIndex: 0,
      tableColumn: [
        {
          label: '入库单号',
          prop: 'oddNumbers',
          minWidth: '100'
        },
        {
          label: '耗材名称',
          prop: 'consumablesName',
          minWidth: '100'
        },
        {
          label: '入库数量',
          prop: 'storeNumber',
          minWidth: '100'
        },
        {
          label: '入库总价',
          prop: 'totalPrice',
          minWidth: '100'
        },
        {
          label: '入库人',
          prop: 'storageUserName',
          minWidth: '100'
        }, {
          label: '入库日期',
          prop: 'storageTime',
          minWidth: '100'
        }, {
          label: '说明',
          prop: 'remark',
          minWidth: '100'
        }, {
          label: '登记人',
          prop: 'registrantName',
          minWidth: '160'
        },{
          label: '登记日期',
          prop: 'registrantTime',
          minWidth: '100'
        },
        {
          dataType: 'action',
          fixed: 'right',
          minWidth: '120',
          label: '操作',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.addOrUpdateStore('edit', row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: '#f56c6c',
              clickFun: (row) => {
                this.deleteStore(row)
              },
            }
          ]
        }
      ],
      tableLoading: false,
      page: {
        total: 0,
        size: 10,
        current: 1
      },
      consumableOptions: [],
      options: [],
      storageTableData: [],
      searchForm: {
        orderBy: {
          field: "id",
          order: "desc",
        },
      },
      saveLoading: false,
    };
  },
  components: {
    limsTable,
  },
  mounted() {
    this.searchList();
    this.getUserList();
    this.fetchListOptions()
    this.options = this.dict.type.consumables_type
  },
  methods: {
    // ä¿å­˜
    save() {
      let data = {
        store: this.form,
        consumables: this.consumables,
      };
      this.saveLoading = true;
      if (this.dialogType === "update") {
        updateStore(data).then((res) => {
          this.saveLoading = false
          if (res.code == 200) {
            this.$message.success("修改成功");
            this.handleClose();
            // this.$refs.selectList()
            this.searchList()
          }
        }).catch((err) => {
          this.saveLoading = false
        })
      } else {
        addStore(data).then((res) => {
          this.saveLoading = false
          if (res.code == 200) {
            this.$message.success("新增成功");
            this.handleClose();
            // this.$refs.selectList()
            this.searchList()
          }
        }).catch((err) => {
          this.saveLoading = false
        })
      }
    },
    findType(val) {
      console.log(val)
      return this.options.find(item => item.value === val).label
    },
    // æ·»åŠ è¡¨æ ¼æ•°æ®
    addTableData() {
      this.$nextTick()
      console.log('this.consumableOptions',this.consumableOptions)
      this.consumableOptions.forEach(item => {
        if (item.id === this.formTwo.id) {
          this.consumables.push({
            itemNumber: null,
            type: this.findType(item.consumablesType),
            consumablesName: item.consumablesName,
            specifications: item.specifications,
            supplier: item.supplierName,
            unit: item.unit,
            unitPrice: this.formTwo.unitPrice,
            storeNumber: this.formTwo.storeNumber,
            totalPrice: this.formTwo.totalPrice,
          });
        }
      })
    },
    deleteTableData(index) {
      this.consumables.splice(index, 1);
    },
    // æ‰“开弹框
    addOrUpdateStore(type,row) {
      if (type === 'edit') {
        this.dialogType = "update";
        selectStoreById({id:row.id}).then(res => {
          if (res.code === 201) return
          this.consumables = res.data.consumables
          this.form = {...res.data.store}
        }).catch(err => {
          console.log('err---', err);
        })
      } else {
        this.dialogType = "add";
      }
      this.dialogVisible = true;
    },
    // æŸ¥è¯¢åˆ—表
    searchList () {
      this.tableLoading = true
      storeList({...this.page,...this.searchForm}).then(res => {
        this.tableLoading = false
        if (res.code === 200){
          this.storageTableData = res.data.records
          this.page.total = res.data.total
        }
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
      })
    },
    // å¯¼å‡ºexcel
    async importExcel() {
      exportProcurementSuppliesStoreExcel({parentId:this.contentsId}).then(res => {
        const blob = new Blob([res], {type: 'application/octet-stream'});
        this.$download.saveAs(blob, '耗材入库.xlsx')
        this.$message.success('导出成功')
      })
    },
    handleClose() {
      this.form = {
        oddNumbers: null,
        inventory: null,
        totalAmount: null,
        storageTime: null,
        storageUser: null,
        remark: null,
      };
      this.formTwo = {
        consumablesName: null,
        unitPrice: null,
        storeNumber: null,
        totalPrice: null,
      };
      this.consumables = [];
      this.dialogVisible = false;
    },
    viewIssued(row) {
      console.log(row);
    },
    // èŽ·å–æ‰€æœ‰ç”¨æˆ·
    getUserList() {
      selectUserCondition().then((res) => {
          this.users = res.data;
        });
    },
    async fetchListOptions() {
      procurementSuppliesList({contentsId: this.contentsId}).then(res => {
        if (res.code === 200) {
          this.consumableOptions = res.data.records
        }
      })
    },
    // åˆ é™¤
    deleteStore (row) {
      this.$confirm('此操作将永久删除该数据, æ˜¯å¦ç»§ç»­?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.tableLoading = true
        console.log('row>>>>>>>>>>>>>>s',row)
        deleteStore({
          id:row.id,
          consumablesId:row.consumablesId
        }).then(res => {
          this.tableLoading = false
          if (res.code === 200){
            this.$message.success('删除成功')
            this.searchList()
          }
        }).catch(err => {
          this.tableLoading = false
          console.log('err---', err);
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    pagination(page) {
      this.page.size = page.limit
      this.searchList();
    },
  },
};
</script>
<style scoped>
.el-dialog {
  margin: 6vh auto 50px !important;
}
.el-dialog__body {
  max-height: 42em;
  overflow-y: auto;
}
.input-form {
  display: flex;
  margin: 10px 0;
}
</style>
src/views/CNAS/externalService/serviceAndSupplyPro/component/contents.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,312 @@
<template>
  <div class="parent-class">
    <div style="display: flex; justify-content: flex-end; margin-right: 20px">
      <el-button
        type="primary"
        @click="addContents"
        size="small"
        icon="el-icon-plus"
        >添加子节点</el-button
      >
      <el-button
        type="danger"
        @click="deletetContents"
        size="small"
        icon="el-icon-delete"
        >删除子节点</el-button
      >
      <el-button
        type="warning"
        @click="updateContents"
        size="small"
        icon="el-icon-edit"
        >更新子节点</el-button
      >
    </div>
    <el-form label-width="100px">
      <el-form-item label="节点名称">
        <el-input
          v-model="form.nodeName"
          style="width: 200px"
          size="small"
        ></el-input>
      </el-form-item>
      <el-form-item label="代号">
        <el-input
          v-model="form.code"
          style="width: 200px"
          size="small"
        ></el-input>
      </el-form-item>
      <el-form-item label="更新人">
        <el-select v-model="form.updateUser">
          <el-option
            v-for="item in users"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          ></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="更新时间">
        <el-input
          v-model="form.updateTime"
          style="width: 200px"
          size="small"
        ></el-input>
      </el-form-item>
    </el-form>
    <!-- æ–°å¢žå¼¹æ¡† -->
    <el-dialog title="添加节点" :visible.sync="dialogVisible" width="40%">
      <el-form
        label-width="100px"
        :model="addForm"
        ref="addForm"
        :rules="rules"
      >
        <el-form-item label="父节点名称">
          <!-- <el-select v-model="addForm.parentId">
              <el-option v-for="(item,index) in nodeNames" :key="index" :label="item.nodeName" :value="item.id"></el-option>
            </el-select> -->
          <el-cascader
            v-model="addForm.parentId"
            :options="treeData"
            :props="{ checkStrictly: true, value: 'id', label: 'nodeName' }"
            clearable
          ></el-cascader>
        </el-form-item>
        <el-form-item label="节点名称" prop="nodeName">
          <el-input
            v-model="addForm.nodeName"
            style="width: 200px"
            size="small"
          ></el-input>
        </el-form-item>
        <el-form-item label="代号">
          <el-input
            v-model="addForm.code"
            style="width: 200px"
            size="small"
          ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 æ¶ˆ</el-button>
        <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
import {
  addSuppliersDirectoryContents,
  updateSuppliersDirectoryContents,
  deleteSuppliersDirectoryContentsById,
  getSuppliersDirectoryContentsNodeNames,
  selectUserCondition,
  selectProcurementSuppliesContentById,
  getProcurementSuppliesContentsNodeNames,
  addProcurementSuppliesContents, deleteProcurementSuppliesContentById
} from '@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro'
export default {
  props: {
    id: {
      type: Number,
      default: 0,
    },
    treeData: {
      type: Array,
      default: () => [],
    },
    from: {
      type: String,
      default: "耗材树"
    }
  },
  data() {
    return {
      nodeNames: [],
      users: [],
      dialogVisible: false,
      form: {
        nodeName: "",
        code: "",
        updateUser: "",
        updateTime: "",
      },
      addForm: {
        nodeName: "",
        code: "",
        updateUser: "",
        updateTime: "",
        parentId: null,
      },
      rules: {
        nodeName: [
          { required: true, message: "请输入节点名称", trigger: "blur" },
        ],
      },
    };
  },
  mounted() {
    if (this.id !== 0) {
      this.getContentsDetail();
    }
    this.getNodeNames();
    this.getUserList();
  },
  watch: {
    id(newVal, oldVal) {
      if (newVal !== 0) {
        console.log(newVal, oldVal);
        this.getContentsDetail();
      }
    },
  },
  methods: {
    // èŽ·å–ç›®å½•è¯¦æƒ…
    getContentsDetail() {
      selectProcurementSuppliesContentById({id:this.id})
        .then((res) => {
          if (res.data == null) {
            this.form = {
              nodeName: "",
              code: "",
              updateUser: "",
              updateTime: "",
            };
            return;
          }
          this.form = res.data;
        });
    },
    // æ–°å»º
    addContents() {
      this.dialogVisible = true;
      this.resetForm();
    },
    resetForm() {
      this.addForm = {
        nodeName: "",
        code: "",
        updateUser: "",
        updateTime: "",
        parentId: null,
      };
    },
    async submitForm() {
      let flag = true;
      this.$refs.addForm.validate((valid) => {
        if (!valid) {
          flag = false;
          return false;
        }
      });
      if (this.addForm.parentId) {
        this.addForm.parentId =
          this.addForm.parentId[this.addForm.parentId.length - 1];
      }
      if (!flag) {
        return;
      }
      try {
        let res = null
        console.log('this.from',this.from)
        if(this.from == '耗材树' ){
          console.log('111')
          res = await addProcurementSuppliesContents(this.addForm)
        }else {
          console.log('222')
          res = await addSuppliersDirectoryContents(this.addForm)
        }
        if (res.code === 200) {
          this.$message.success("添加成功");
          this.dialogVisible = false;
          this.$emit("contentsUpdate", res.data);
          this.getContentsDetail();
        }
      }catch (error){
        this.$message.error("添加失败");
      }
    },
    // æ›´æ–°
    updateContents() {
      Object.keys(this.form).forEach((key) => {
        if (key == "children") {
          delete this.form[key];
        }
      });
      updateSuppliersDirectoryContents(this.form).then((res) => {
          if (res.code === 200) {
            this.$message.success("更新成功");
            this.$emit("contentsUpdate", this.id);
            this.dialogVisible = false;
            this.getContentsDetail();
          }
        });
    },
    // åˆ é™¤
    deletetContents() {
      if (
        this.form.id == null ||
        this.form.id == "" ||
        this.form.id == undefined
      ) {
        this.$message.error("请选择要删除的节点");
        return;
      }
      this.$confirm("此操作将删除该节点, æ˜¯å¦ç»§ç»­?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      }).then(() => {
        if(this.from == '耗材树'){
          deleteProcurementSuppliesContentById({id:this.form.id}).then((res) => {
            if (res.code == 200) {
              this.$message.success("删除成功");
              this.$emit("contentsUpdate", this.form.parentId, true);
              this.getContentsDetail();
            }
          });
        }else {
          deleteSuppliersDirectoryContentsById({id:this.form.id}).then((res) => {
            if (res.code == 200) {
              this.$message.success("删除成功");
              this.$emit("contentsUpdate", this.form.parentId, true);
              this.getContentsDetail();
            }
          });
        }
      });
    },
    // èŽ·å–æ‰€æœ‰ç›®å½•èŠ‚ç‚¹
    getNodeNames() {
      if(this.from == '耗材树'){
        getProcurementSuppliesContentsNodeNames().then(res => {
          this.nodeNames = res.data;
        })
      }else {
        getSuppliersDirectoryContentsNodeNames().then(res => {
          this.nodeNames = res.data;
        })
      }
    },
    // èŽ·å–æ‰€æœ‰ç”¨æˆ·
    getUserList() {
      selectUserCondition().then((res) => {
        this.users = res.data;
      })
    },
  },
  created() {},
};
</script>
  <style scoped>
.parent-class {
  margin-top: 20px;
}
</style>
src/views/CNAS/externalService/serviceAndSupplyPro/index.vue
@@ -27,30 +27,33 @@
        <el-tab-pane label="耗材总览" name="first" :lazy="true">
          <ConsumableOverview v-if="activeName == 'first'" :contentsId="contentsId"></ConsumableOverview>
        </el-tab-pane>
<!--        <el-tab-pane label="耗材列表" name="second" :lazy="true">-->
<!--          <ConsumableList v-if="activeName == 'second'" :contentsId="contentsId"></ConsumableList>-->
<!--        </el-tab-pane>-->
<!--        <el-tab-pane label="耗材入库" name="third" :lazy="true">-->
<!--          <Store v-if="activeName == 'third'" :contentsId="contentsId"></Store>-->
<!--        </el-tab-pane>-->
<!--        <el-tab-pane label="目录维护" name="fourth" :lazy="true">-->
<!--          <Contents-->
<!--            v-if="activeName == 'fourth'"-->
<!--            :id="contentsId"-->
<!--            @contentsUpdate="contentsUpdate"-->
<!--            :treeData="treeData"-->
<!--            from="耗材树"-->
<!--          ></Contents>-->
<!--        </el-tab-pane>-->
        <el-tab-pane label="耗材列表" name="second" :lazy="true">
          <ConsumableList v-if="activeName == 'second'" :contentsId="contentsId"></ConsumableList>
        </el-tab-pane>
        <el-tab-pane label="耗材入库" name="third" :lazy="true">
          <Store v-if="activeName == 'third'" :contentsId="contentsId"></Store>
        </el-tab-pane>
        <el-tab-pane label="目录维护" name="fourth" :lazy="true">
          <Contents
            v-if="activeName == 'fourth'"
            :id="contentsId"
            @contentsUpdate="contentsUpdate"
            :treeData="treeData"
            from="耗材树"
          ></Contents>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>
<script>
// import Contents from "@/tabs/do/a6.service-and-supply-purchase/contents.vue";
// import Store from "@/tabs/do/a6.service-and-supply-purchase/store.vue";
import ConsumableOverview from "../serviceAndSupplyPro/component/ConsumableOverview.vue";
// import ConsumableList from "@/tabs/do/a6.service-and-supply-purchase/ConsumableList.vue"
import Contents from "./component/contents.vue";
import Store from "./component/Store.vue";
import ConsumableOverview from "./component/ConsumableOverview.vue";
import ConsumableList from "./component/ConsumableList.vue"
import {
  directoryListing
} from '@/api/cnas/externalService/serviceAndSupplyPro/serviceAndSupplyPro'
export default {
  data() {
@@ -70,10 +73,10 @@
    };
  },
  components: {
    // Contents,
    // Store,
    ConsumableOverview
    // ConsumableList
    Contents,
    Store,
    ConsumableOverview,
    ConsumableList
  },
  watch: {
    contentsId(newVal, oldVal) {
@@ -129,9 +132,7 @@
    },
    // æŸ¥è¯¢æ‰€æœ‰ç›®å½•
    getTreeData() {
      this.$axios
        .get(this.$api.procurementSuppliesContents.directoryListing)
        .then((res) => {
      directoryListing().then((res) => {
          this.treeData = res.data;
        });
    },
src/views/CNAS/process/sampleDisposal/index.vue
@@ -1,20 +1,11 @@
<template>
  <div class="sample-disposal">
    <el-row class="title">
      <el-col :span="20" style="padding-left: 20px;text-align: left;">检测或校准物品的处置</el-col>
      <el-col :span="4" style="text-align: right;">
        <!-- <el-button size="medium" type="primary" @click="handleDown" v-loading="outLoading" style="margin-right: 16px;">导出</el-button> -->
      </el-col>
    </el-row>
    <el-tabs type="border-card" v-model="activeName" style="height: 100%;" @tab-click="queryParams.totaldealId = ''">
      <el-tab-pane label="填写" name="填写" style="height: 100%;" :key="1">
        <el-button size="small" type="primary" @click="handleAdd0" style="margin-left: 20px;"
          v-if="addPower">新增</el-button>
        <el-button size="small" type="primary" @click="handleAdd0" style="margin-left: 20px;">新增</el-button>
        <div class="table" style="height: calc(100% - 200px)" v-if="activeName == '填写'">
          <lims-table :tableData="tableData" :column="column" :tableLoading="tableLoading"
            :height="'calc(100vh - 290px)'" :page="page" @pagination="pagination"></lims-table>
          <!-- <ValueTable ref="ValueTable0" :url="$api.processTotaldeal.pageProcessDeal" :componentData="componentData0"
            :key="upIndex0" :delUrl="$api.processTotaldeal.delProcessDeal" /> -->
        </div>
      </el-tab-pane>
      <el-tab-pane label="历史记录" name="历史记录" style="height: 100%;" :key="2">
@@ -22,7 +13,7 @@
          <div class="search_thing">
            <div class="search_label">年月:</div>
            <div class="search_input">
              <el-date-picker v-model="componentData.entity.month" type="month" placeholder="选择月" format="yyyy-MM"
              <el-date-picker v-model="queryParams0.month" type="month" placeholder="选择月" format="yyyy-MM"
                value-format="yyyy-MM" size="small" @change="refreshTable()">
              </el-date-picker>
            </div>
@@ -33,8 +24,8 @@
          </div>
        </div>
        <div class="table">
          <!-- <ValueTable ref="ValueTable" :url="$api.processTotaldeal.pageProcessTotaldeal" :componentData="componentData"
            :key="upIndex" /> -->
          <lims-table :tableData="tableData0" :column="column0" :tableLoading="tableLoading"
            :height="'calc(100vh - 300px)'" :page="page0" @pagination="pagination0"></lims-table>
        </div>
      </el-tab-pane>
    </el-tabs>
@@ -122,6 +113,7 @@
  checkProcessTotaldeal,
  ratifyProcessTotaldeal,
  delProcessDeal,
  pageProcessTotaldeal,
} from "@/api/cnas/process/sampleDisposal";
export default {
  components: {
@@ -142,105 +134,6 @@
      noCheckLoading: false,
      checkLoading: false,
      // åŽ†å²åˆ—è¡¨
      componentData: {
        entity: {
          month: null,
          orderBy: {
            field: 'id',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleLook',
          font: '查看',
          type: 'text',
          method: 'handleLook',
        }, {
          id: 'handleDown0',
          font: '下载',
          type: 'text',
          method: 'handleDown0',
          disabFun: (row, index) => {
            return !row.url
          }
        },
        // {
        //   id: 'handleAdd',
        //   font: '填写',
        //   type: 'text',
        //   method: 'handleAdd',
        //   disabFun: (row, index) => {
        //     return row.submitState=='已提交'
        //   }
        // },
        {
          id: 'handleSubmit',
          font: '提交',
          type: 'text',
          method: 'handleSubmit',
          disabFun: (row, index) => {
            return !!row.submitState && row.submitState != '待提交'
          }
        }, {
          id: 'handleCheck',
          font: '审核',
          type: 'text',
          method: 'handleCheck',
          disabFun: (row, index) => {
            return row.examineState == '通过' || row.submitState == '待提交'
          }
        }, {
          id: 'handleApproval',
          font: '批准',
          type: 'text',
          method: 'handleApproval',
          disabFun: (row, index) => {
            return row.ratifyState == '通过' || row.submitState == '待提交'
          }
        }],
        tagField: {},
        selectField: {},
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      // æ ·å“åˆ—表
      componentData0: {
        entity: {
          totaldealId: null,
          orderBy: {
            field: 'id',
            order: 'desc'
          }
        },
        isIndex: true,
        showSelect: false,
        select: false,
        do: [{
          id: 'handleAdd0',
          font: '修改',
          type: 'text',
          method: 'handleAdd0'
        }, {
          id: 'delete',
          font: '删除',
          type: 'text',
          method: 'doDiy'
        }],
        tagField: {},
        selectField: {},
        requiredAdd: [],
        requiredUp: [],
        needSort: [],
        inputType: ''
      },
      upIndex0: 100,
      entityCopy: {},
      upIndex: 0,
      addInfo: {},//新增样品
      customPageList: [],
      currentInfo: {
@@ -285,12 +178,81 @@
        current: 0,
      },
      tableLoading: false,
      queryParams0: {},
      tableData0: [],
      column0: [
        { label: "月份", prop: "month" },
        { label: "总数量", prop: "totalNum" },
        { label: "提交人", prop: "submitUserName" },
        { label: "审核人", prop: "examineUserName" },
        { label: "批准人", prop: "ratifyUserName" },
        {
          dataType: "action",
          fixed: "right",
          label: "操作",
          operation: [
            {
              name: "查看",
              type: "text",
              clickFun: (row) => {
                this.handleLook(row);
              },
            },
            {
              name: "下载",
              type: "text",
              clickFun: (row) => {
                this.handleDown0(row);
              },
              disabled: (row) => {
                return !row.url
              }
            },
            {
              name: "提交",
              type: "text",
              clickFun: (row) => {
                this.handleSubmit(row);
              },
              disabled: (row) => {
                return !!row.submitState && row.submitState != '待提交'
              }
            },
            {
              name: "审核",
              type: "text",
              clickFun: (row) => {
                this.handleCheck(row);
              },
              disabled: (row) => {
                return row.examineState == '通过' || row.submitState == '待提交'
              }
            },
            {
              name: "批准",
              type: "text",
              clickFun: (row) => {
                this.handleApproval(row);
              },
              disabled: (row) => {
                return row.ratifyState == '通过' || row.submitState == '待提交'
              }
            },
          ],
        },
      ],
      page0: {
        total: 0,
        size: 10,
        current: 0,
      },
    };
  },
  mounted() {
    // this.entityCopy = this.HaveJson(this.componentData.entity);
    this.getCustomPageList()
    // this.getPower()
    this.getList()
    this.getList0()
  },
  methods: {
    getPower() {
@@ -364,13 +326,34 @@
      this.getList();
    },
    refresh() {
      this.queryParams = {};
      this.page.current = 1;
      this.getList();
      this.queryParams0 = {};
      this.page0.current = 1;
      this.getList0();
    },
    refreshTable() {
      this.page.current = 1;
      this.getList();
      this.page0.current = 1;
      this.getList0();
    },
    getList0() {
      this.tableLoading = true;
      let param = { ...this.queryParams0, ...this.page };
      delete param.total;
      pageProcessTotaldeal({ ...param })
        .then((res) => {
          this.tableLoading = false;
          if (res.code === 200) {
            this.tableData0 = res.data.records;
            this.page0.total = res.data.total;
          }
        })
        .catch((err) => {
          this.tableLoading = false;
        });
    },
    pagination0({ page, limit }) {
      this.page0.current = page;
      this.page0.size = limit;
      this.getList0();
    },
    // å¡«å†™
    // handleAdd(row){
@@ -404,7 +387,8 @@
            type: 'success',
            message: '编辑成功!'
          });
          this.$refs.ValueTable0.selectList()
          this.page.current = 0;
          this.getList();
        }).catch(err => { });
      } else {
        // æ–°å¢ž
@@ -420,7 +404,8 @@
            type: 'success',
            message: '新增成功!'
          });
          this.$refs.ValueTable0.selectList()
          this.page.current = 0;
          this.getList();
        }).catch(err => { });
      }
    },
@@ -439,7 +424,7 @@
            type: 'success',
            message: '提交成功!'
          });
          this.$refs['ValueTable'].selectList()
          this.refreshTable()
        }).catch(err => { });
      })
    },
@@ -451,7 +436,8 @@
      this.activeName = '填写'
      this.queryParams.totaldealId = row.id
      this.$nextTick(() => {
        this.$refs['ValueTable0'].selectList()
        this.page.current = 0;
        this.getList();
      })
    },
    commonFun(row, callbanck) {
@@ -461,8 +447,8 @@
        current: -1,
        size: -1, ...this.queryParams
      }).then(res => {
        this.currentInfo.arr = res.data.body.records
        this.lookDialogVisible = true
        this.currentInfo.arr = res.data.records
        if (callbanck) {
          callbanck()
        }
@@ -497,7 +483,7 @@
            type: 'success',
            message: '操作成功!'
          });
          this.$refs['ValueTable'].selectList()
          this.refreshTable()
          this.lookDialogVisible = false
        }).catch(err => { });
      } else if (this.title0 == '批准') {
@@ -512,7 +498,7 @@
            type: 'success',
            message: '操作成功!'
          });
          this.$refs['ValueTable'].selectList()
          this.refreshTable()
          this.lookDialogVisible = false
        }).catch(err => { });
      }
@@ -574,7 +560,6 @@
.table {
  background-color: #fff;
  width: calc(100% - 40px);
  height: calc(100% - 60px - 140px);
  padding: 20px;
}
@@ -586,7 +571,6 @@
.tables {
  table-layout: fixed;
  width: 100%;
  margin-top: 10px;
}
.tables td {
src/views/CNAS/systemManagement/correctiveAction/index.vue
@@ -109,8 +109,8 @@
      page: {
        size: 20,
        current: 1,
        total: 0,
      },
      total: 0,
      correctiveInfo: false,
      viewTestRecordDialog: false,
    };
@@ -131,7 +131,7 @@
        this.tableLoading = false
        if (res.code === 201) return
        this.tableData = res.data.records
        this.total = res.data.total
        this.page.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
        this.tableLoading = false
src/views/CNAS/systemManagement/documentControl/components/ControlledFileApplication.vue
@@ -470,18 +470,25 @@
      formData.append('state', this.type); // æ–‡ä»¶åå­—段
      formData.append('writer', this.currentInfo.writer); // æ–‡ä»¶åå­—段
      let res = await checkManageDocumentControlled(formData)
      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
      try {
        let res = await checkManageDocumentControlled(formData)
        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
        }
      } catch (e) {
        this.checkLoading = false
        this.noCheckLoading = false
      }
    },
    handleCheckSub(type) {
      this.type = type
src/views/CNAS/systemManagement/documentControl/components/FileList.vue
@@ -334,17 +334,22 @@
      formData.append('file', pdfBlob, fileName); // æ–‡ä»¶å­—段
      formData.append('id', this.currentInfo.id); // æ–‡ä»¶åå­—段
      let res = await uploadFileManageDocumentList(formData)
      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
      try {
        let res = await uploadFileManageDocumentList(formData)
        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
        }
      } catch (e) {
        this.addLoading = false
      }
    },
    handleDelete(row) {
      this.$confirm("是否删除该条数据?", "提示", {
src/views/CNAS/systemManagement/measuresDealRisks/components/hazardIdentificationRiskAssessment.vue
@@ -13,7 +13,7 @@
        <el-button size="small" @click="openDownloadDia">导出</el-button>
      </div>
    </div>
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)">
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)" key="table1">
      <el-table-column type="index" label="序号" width="120">
        <template v-slot="scope">
          <span>{{ (page.current - 1) * page.size + scope.$index + 1 }}</span>
@@ -142,7 +142,7 @@
      page: {
        total: 0,
        size: 10,
        current: 0,
        current: 1,
      },
      tableData: [],
      loading: false
src/views/CNAS/systemManagement/measuresDealRisks/components/listRiskAnalysisControlPlans.vue
@@ -13,7 +13,7 @@
        <el-button size="small" @click="openDownloadDia">导出</el-button>
      </div>
    </div>
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)">
    <el-table :data="tableData" style="width: 100%" height="calc(100vh - 18em)" key="table0">
      <el-table-column type="index" label="序号" width="120">
        <template v-slot="scope">
          <span>{{ (search.current - 1) * search.size + scope.$index + 1 }}</span>
src/views/business/inspectionTask/index.vue
@@ -518,10 +518,18 @@
          prop: "insResult",
          dataType: "tag",
          formatData: (params) => {
            return this.insResultList.find((m) => m.value == params).label;
            let obj = this.insResultList.find((m) => m.value == params)
            if (obj) {
              return this.insResultList.find((m) => m.value == params).label;
            } else {
              return ''
            }
          },
          formatType: (params) => {
            return this.insResultList.find((m) => m.value == params).type;
            let obj = this.insResultList.find((m) => m.value == params)
            if (obj) {
              return this.insResultList.find((m) => m.value == params).type;
            }
          },
        },
        {
src/views/performance/class/index.vue
@@ -808,7 +808,7 @@
      }
    },
    getUsers() {
      selectUserCondition().then((res) => {
      selectUserCondition({ type: 1 }).then((res) => {
        if (res.code === 201) {
          return;
        }