liding
2026-10-29 4019314f9ebd833dd9fb69bbbaa05b2de4ed47f7
refactor(inspection-order): 重构委托单管理支持可重复绑定及历次下单记录
已修改4个文件
211 ■■■■■ 文件已修改
src/api/cnas/process/demand/demand.js 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/demand/index.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/productOrder/components/addOrder.vue 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/process/demand/demand.js
@@ -21,6 +21,30 @@
    params: query
  })
}
// 查询可重复绑定的检验委托单
export function pageSelectableInspectionOrder(query) {
  return request({
    url: '/inspectionOrder/pageSelectableInspectionOrder',
    method: 'get',
    params: query
  })
}
// 查询委托单的历次下单记录
export function pageInspectionOrderBindings(query) {
  return request({
    url: '/inspectionOrder/pageInspectionOrderBindings',
    method: 'get',
    params: query
  })
}
// 查询委托单附件
export function listInspectionOrderAttachments(query) {
  return request({
    url: '/inspectionOrder/listInspectionOrderAttachments',
    method: 'get',
    params: query
  })
}
// 委托单检验新增
export function addInspectionOrder(query) {
  return request({
src/views/CNAS/process/demand/index.vue
@@ -37,23 +37,11 @@
        <el-table-column align="center" label="序号" type="index"></el-table-column>
        <el-table-column label="委托单号" prop="inspectionOrderCode" min-width="160" show-overflow-tooltip></el-table-column>
        <el-table-column label="试样名称" prop="sampleName" show-overflow-tooltip></el-table-column>
        <el-table-column label="委托编号" prop="entrustCode" show-overflow-tooltip>
          <template slot-scope="scope">{{ scope.row.entrustCode || '待生成' }}</template>
        </el-table-column>
        <el-table-column label="关联状态" min-width="90">
          <template slot-scope="scope">{{ scope.row.bindingStatus === 1 ? '已绑定' : '未绑定' }}</template>
        </el-table-column>
        <el-table-column label="下单状态" min-width="90">
          <template slot-scope="scope">{{ orderStateText(scope.row.orderState) }}</template>
        </el-table-column>
        <el-table-column label="检验进度" prop="insProgress" min-width="90">
          <template slot-scope="scope">{{ scope.row.insProgress || '--' }}</template>
        </el-table-column>
        <el-table-column label="检验结果" min-width="90">
          <template slot-scope="scope">{{ insResultText(scope.row.insResult) }}</template>
        </el-table-column>
        <el-table-column label="报告状态" min-width="90">
          <template slot-scope="scope">{{ reportStatusText(scope.row.reportStatus) }}</template>
        <el-table-column label="下单次数" min-width="90">
          <template slot-scope="scope">{{ scope.row.bindingCount || 0 }}</template>
        </el-table-column>
        <el-table-column label="委托时间" prop="commissionDate" show-overflow-tooltip></el-table-column>
        <el-table-column label="型号" prop="modelNo" show-overflow-tooltip></el-table-column>
@@ -79,14 +67,9 @@
            <el-button size="mini" type="text" @click="goUpdate(scope.row)">编辑</el-button>
            <el-button size="mini" type="text" @click="handleLook(scope.row)">查看</el-button>
            <el-button size="mini" style="color:#F56C6C" type="text" @click="deleteOrder(scope.row)">删除</el-button>
            <el-button :disabled="!scope.row.fileUrl" size="mini" type="text" @click="openDownloadDia(scope.row)">下载</el-button>
            <el-button v-if="canChangeBinding(scope.row)" size="mini" type="text" @click="openChangeBinding(scope.row)">变更关联</el-button>
            <el-upload ref='upload' :action="action" :data="{ inspectionOrderId: scope.row.inspectionOrderId }"
              :headers="uploadHeader" :on-error="onError" :on-success="handleSuccessUp" :show-file-list="false"
              accept='image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx,.xlsx' name="file"
              style="background: transparent;display: inline;margin-left: 4px">
              <span style="color: #409EFF">上传</span>
            </el-upload>
            <el-button size="mini" type="text" @click="openDownloadDia(scope.row)">导出</el-button>
            <el-button size="mini" type="text" @click="openBindingRecords(scope.row)">下单记录</el-button>
            <el-button size="mini" type="text" @click="openAllAttachments(scope.row)">全部附件</el-button>
          </template>
        </el-table-column>
      </el-table>
@@ -394,10 +377,54 @@
          定</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="bindingRecordsVisible" title="历次下单记录" width="1000px" append-to-body>
      <el-table v-loading="bindingRecordsLoading" :data="bindingRecords" border>
        <el-table-column prop="entrustCode" label="委托编号" min-width="150">
          <template slot-scope="scope">{{ scope.row.entrustCode || '待生成' }}</template>
        </el-table-column>
        <el-table-column label="下单状态" width="90">
          <template slot-scope="scope">{{ scope.row.orderDeleted === 1 ? '已删除' : orderStateText(scope.row.orderState) }}</template>
        </el-table-column>
        <el-table-column prop="insProgress" label="检验进度" width="90" />
        <el-table-column label="检验结果" width="90">
          <template slot-scope="scope">{{ insResultText(scope.row.insResult) }}</template>
        </el-table-column>
        <el-table-column prop="sampleTakerUser" label="领样人" width="100" />
        <el-table-column prop="sampleData" label="领样日期" width="110" />
        <el-table-column prop="reportCount" label="正式报告" width="90" />
        <el-table-column label="操作" width="230">
          <template slot-scope="scope">
            <el-button size="mini" type="text" :disabled="scope.row.orderDeleted === 1"
              @click="openBindingAttachments(scope.row)">附件</el-button>
            <el-button size="mini" type="text" @click="downloadBindingOrder(scope.row)">导出</el-button>
            <el-button v-if="canChangeBinding(scope.row)" size="mini" type="text"
              @click="openChangeBinding(scope.row)">变更关联</el-button>
            <el-upload v-if="scope.row.orderDeleted !== 1" :action="bindingUploadAction"
              :data="{ bindingId: scope.row.id }" :headers="uploadHeader" :show-file-list="false"
              :on-success="handleBindingUploadSuccess" :on-error="onError" :before-upload="beforeUpload"
              accept="image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx,.xlsx" name="file"
              style="display:inline;margin-left:8px">
              <span style="color:#409EFF">上传</span>
            </el-upload>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination :current-page="bindingPage.current" :page-size="bindingPage.size" :total="bindingPage.total"
        layout="->,total, prev, pager, next" @current-change="changeBindingPage" />
    </el-dialog>
    <el-dialog :visible.sync="attachmentVisible" title="下单附件" width="650px" append-to-body>
      <el-table :data="attachmentList" border>
        <el-table-column prop="fileName" label="文件名" show-overflow-tooltip />
        <el-table-column prop="sourceType" label="来源" width="100" />
        <el-table-column prop="createTime" label="上传时间" width="160" />
        <el-table-column label="操作" width="80">
          <template slot-scope="scope"><el-button type="text" @click="$download.saveAs(scope.row.fileUrl, scope.row.fileName)">下载</el-button></template>
        </el-table-column>
      </el-table>
    </el-dialog>
    <el-dialog :visible.sync="downloadDialog" title="下载" width="600px">
      <span>
        <el-button :loading="outLoading" plain type="primary" @click="orderReportDown">下载委托单</el-button>
        <el-button :loading="outLoading" plain type="primary" @click="orderFormDown">下载委托报告</el-button>
      </span>
      <span slot="footer" class="dialog-footer">
        <el-button @click="downloadDialog = false">取 消</el-button>
@@ -443,7 +470,9 @@
  addInspectionOrder, delInspectionOrder, exportInspectionOrder,
  changeInspectionOrderBinding,
  getInspectionOrderOne,
  pageUnboundInspectionOrder,
  pageSelectableInspectionOrder,
  pageInspectionOrderBindings,
  listInspectionOrderAttachments,
  pageInspectionOrder,
  updateInspectionOrder
} from "@/api/cnas/process/demand/demand";
@@ -516,6 +545,13 @@
        inspectionOrderId: [{ required: true, message: '请选择新的委托单', trigger: 'change' }],
        reason: [{ required: true, message: '请输入变更原因', trigger: 'blur' }]
      },
      bindingRecordsVisible: false,
      bindingRecordsLoading: false,
      bindingRecords: [],
      bindingInspectionOrderId: null,
      bindingPage: { current: 1, size: 10, total: 0 },
      attachmentVisible: false,
      attachmentList: [],
      commissionUnitDialogVisible: false,
      commissionUnitLoading: false,
      commissionUnitList: [],
@@ -542,8 +578,8 @@
    this.refreshTable()
  },
  computed: {
    action() {
      return this.javaApi + '/inspectionOrder/uploadInspectionOrderFile'
    bindingUploadAction() {
      return this.javaApi + '/inspectionOrder/uploadInspectionOrderBindingFile'
    }
  },
  methods: {
@@ -644,7 +680,7 @@
    },
    searchUnboundInspectionOrders(keyword) {
      this.bindingLoading = true
      pageUnboundInspectionOrder({ current: 1, size: 20, inspectionOrderCode: keyword }).then(res => {
      pageSelectableInspectionOrder({ current: 1, size: 20, inspectionOrderCode: keyword }).then(res => {
        this.unboundInspectionOrders = res.data.records || []
      }).finally(() => {
        this.bindingLoading = false
@@ -658,10 +694,64 @@
          this.$message.success('关联已变更')
          this.changeBindingVisible = false
          this.refreshTable()
          this.loadBindingRecords()
        }).finally(() => {
          this.bindingSubmitting = false
        })
      })
    },
    openBindingRecords(row) {
      this.bindingInspectionOrderId = row.inspectionOrderId
      this.bindingPage.current = 1
      this.bindingRecordsVisible = true
      this.loadBindingRecords()
    },
    loadBindingRecords() {
      if (!this.bindingInspectionOrderId) return
      this.bindingRecordsLoading = true
      pageInspectionOrderBindings({
        inspectionOrderId: this.bindingInspectionOrderId,
        current: this.bindingPage.current,
        size: this.bindingPage.size
      }).then(res => {
        this.bindingRecords = res.data.records || []
        this.bindingPage.total = res.data.total || 0
      }).finally(() => { this.bindingRecordsLoading = false })
    },
    changeBindingPage(page) {
      this.bindingPage.current = page
      this.loadBindingRecords()
    },
    openBindingAttachments(binding) {
      listInspectionOrderAttachments({
        inspectionOrderId: binding.inspectionOrderId,
        bindingId: binding.id
      }).then(res => {
        this.attachmentList = res.data || []
        this.attachmentVisible = true
      })
    },
    openAllAttachments(row) {
      listInspectionOrderAttachments({ inspectionOrderId: row.inspectionOrderId }).then(res => {
        this.attachmentList = res.data || []
        this.attachmentVisible = true
      })
    },
    downloadBindingOrder(binding) {
      exportInspectionOrder({
        inspectionOrderId: binding.inspectionOrderId,
        bindingId: binding.id
      }).then(res => {
        const blob = new Blob([res], { type: 'application/octet-stream' })
        this.$download.saveAs(blob, `${binding.inspectionOrderCode || '检验委托单'}_${binding.entrustCode || binding.insOrderId}.docx`)
      })
    },
    handleBindingUploadSuccess(response) {
      if (response && response.code === 200) {
        this.$message.success('上传成功')
      } else {
        this.$message.error((response && response.message) || '上传失败')
      }
    },
    addOrderDetailList() {
      if (this.currentInfo.orderDetailList == null) {
@@ -796,15 +886,6 @@
      this.downloadDialog = true
      this.download = row
    },
    // 委托单下载
    orderFormDown() {
      let url = this.download.fileUrl;
      const link = document.createElement('a');
      link.href = this.javaApi + url;
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
    },
    // 委托报告下载
    orderReportDown() {
      this.outLoading = true;
@@ -817,17 +898,9 @@
        this.outLoading = false;
      })
    },
    // 上传
    handleSuccessUp(response,) {
      if (response.code == 200) {
        this.$message.success('上传成功');
        this.refreshTable()
      }
    },
    beforeUpload(file) {
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload.clearFiles()
        return false;
      } else {
        return true;
src/views/business/productOrder/components/addOrder.vue
@@ -667,7 +667,7 @@
import {
  addInsOrderWithInspectionOrder,
  getInspectionOrderForPlaceOrder,
  pageUnboundInspectionOrder
  pageSelectableInspectionOrder
} from "@/api/cnas/process/demand/demand";
export default {
@@ -804,6 +804,7 @@
      },
      type: [],
      inspectionOrderLoading: false,
      inspectionOrderRequestId: null,
      inspectionOrderDialogVisible: false,
      inspectionOrderTableData: [],
      inspectionOrderSelection: [],
@@ -976,6 +977,7 @@
  },
  methods: {
    openInspectionOrderList() {
      this.inspectionOrderRequestId = this.createRequestId()
      this.inspectionOrderSelection = []
      this.inspectionOrderQuery.inspectionOrderCode = ''
      this.inspectionOrderPage.current = 1
@@ -984,7 +986,7 @@
    },
    getInspectionOrderList() {
      this.inspectionOrderLoading = true
      pageUnboundInspectionOrder({
      pageSelectableInspectionOrder({
        ...this.inspectionOrderPage,
        ...this.inspectionOrderQuery
      }).then(res => {
@@ -1043,9 +1045,6 @@
        this.addObj.appointed = inspectionOrder.appointed || this.addObj.appointed
        this.addObj.send = inspectionOrder.send === null || inspectionOrder.send === undefined
          ? this.addObj.send : inspectionOrder.send
        if (/^\d+$/.test(inspectionOrder.quantity || '')) {
          this.addObj.sampleNum = Number(inspectionOrder.quantity)
        }
        this.sample.sample = inspectionOrder.sampleName || this.sample.sample
        this.sample.model = inspectionOrder.modelNo || this.sample.model
        this.$message.success('已带入检验委托单信息')
@@ -1554,6 +1553,7 @@
        const submitRequest = inspectionOrderId
          ? addInsOrderWithInspectionOrder({
            inspectionOrderId,
            requestId: this.inspectionOrderRequestId || (this.inspectionOrderRequestId = this.createRequestId()),
            insOrder: {...insOrder, typeSource: -1},
            sampleList: sampleList
          })
@@ -1565,12 +1565,24 @@
          this.saveLoad = false
          this.$message.success('已提交')
          this.bsm3Dia = false;
          this.inspectionOrderRequestId = null
          this.closeOpenPage()
        }).catch(e=>{
          this.saveLoad = false
        })
      }
    },
      createRequestId() {
        if (window.crypto && typeof window.crypto.randomUUID === 'function') {
          return window.crypto.randomUUID()
        }
        const bytes = new Uint8Array(16)
        window.crypto.getRandomValues(bytes)
        bytes[6] = (bytes[6] & 0x0f) | 0x40
        bytes[8] = (bytes[8] & 0x3f) | 0x80
        const hex = Array.from(bytes, value => value.toString(16).padStart(2, '0')).join('')
        return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`
      },
      upInsOrderOfState(state) {
        if (state == 1) {
          this.saveLoad = true
@@ -2487,7 +2499,7 @@
</script>
<style scoped>
>>>.warning-row {
::v-deep .warning-row {
  color: #1890FF;
}
.node_i {
vue.config.js
@@ -9,7 +9,7 @@
const name = process.env.VUE_APP_TITLE || "LIMS实验室管理系统"; // 网页标题
const port = process.env.port || process.env.npm_config_port || 80; // 端口
const port = process.env.port || process.env.npm_config_port || 99; // 端口
// vue.config.js 配置说明
//官方vue.config.js 参考文档 https://cli.vuejs.org/zh/config/#css-loaderoptions