liding
4 小时以前 8690e8f223d07cc4aedc3f7c1a38316f223b20cc
feat(quality-monitor): 重构质量监控计划模块并集成检验任务流程
已添加1个文件
已修改9个文件
1336 ■■■■■ 文件已修改
src/api/cnas/process/ensureResults/qualityMonitor.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/process/method/methodVerification.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Table/lims-table.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue 788 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/inspectionTask/index.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/business/inspectionTask/inspection.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/cnas/process/ensureResults/qualityMonitor.js
@@ -1,6 +1,38 @@
// è´¨é‡ç›‘控计划页面相关接口
import request from '@/utils/request'
export function createAnnualPlan(data) {
  return request({ url: '/qualityMonitor/createAnnualPlan', method: 'post', data })
}
export function getAnnualPlan(params) {
  return request({ url: '/qualityMonitor/getAnnualPlan', method: 'get', params })
}
export function submitAnnualPlan(qualityMonitorId) {
  return request({ url: '/qualityMonitor/submitAnnualPlan', method: 'post', data: { qualityMonitorId } })
}
export function dispatchInspectionTask(qualityMonitorDetailsId) {
  return request({ url: '/qualityMonitor/dispatchInspectionTask', method: 'post', data: { qualityMonitorDetailsId } })
}
export function cancelInspectionTask(qualityMonitorDetailsId) {
  return request({ url: '/qualityMonitor/cancelInspectionTask', method: 'post', data: { qualityMonitorDetailsId } })
}
export function getInspectionEvaluation(qualityMonitorDetailsId) {
  return request({ url: '/qualityMonitor/getInspectionEvaluation', method: 'get', params: { qualityMonitorDetailsId } })
}
export function submitInspectionEvaluation(data) {
  return request({ url: '/qualityMonitor/submitInspectionEvaluation', method: 'post', data })
}
export function approveInspectionEvaluation(data) {
  return request({ url: '/qualityMonitor/approveInspectionEvaluation', method: 'post', data })
}
// ç›‘控年度计划列表
export function pageQualityMonitor(query) {
  return request({
src/api/cnas/process/method/methodVerification.js
@@ -47,6 +47,15 @@
  })
}
// æŒ‰å½“前所选设备实时读取校准证书
export function getCurrentCalibrationFiles(query) {
  return request({
    url: '/processMethodVerify/getCurrentCalibrationFiles',
    method: 'get',
    params: query,
  })
}
// ä¿®æ”¹æ ‡å‡†æ–¹æ³•验证
export function updateMethodVerify(data) {
  return request({
src/components/Table/lims-table.vue
@@ -35,7 +35,7 @@
        :label="item.label"
        :prop="item.prop"
        :show-overflow-tooltip="item.dataType === 'action' || item.dataType === 'slot' ? false : true"
        :min-width="columnWidth(item)"
        :min-width="columnMinWidth(item)"
        :sortable="item.sortable ? true : false"
        :type="item.type"
        :width="columnWidth(item)"
@@ -214,6 +214,14 @@
})
function columnWidth(item) {
  if (item.minWidth) return undefined
  return item.dataType === 'action' ? actionColumnWidth.value : item.width
}
// é…ç½® minWidth æ—¶åªçº¦æŸæœ€å°å®½åº¦ï¼ŒæŠŠå‰©ä½™ç©ºé—´äº¤ç»™ Element Plus è‡ªåŠ¨åˆ†é…ã€‚
// æœªé…ç½® minWidth çš„æ—§é¡µé¢ç»§ç»­æ²¿ç”¨åŽŸæœ‰å›ºå®š width è¡Œä¸ºã€‚
function columnMinWidth(item) {
  if (item.minWidth) return item.minWidth
  return item.dataType === 'action' ? actionColumnWidth.value : item.width
}
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/detailFormDialog.vue
@@ -1,45 +1,73 @@
<template>
  <div>
    <el-dialog title="编辑" v-model="formDia"
    <el-dialog :title="operationType === 'add' ? '新增质控项目' : '编辑质控项目'" v-model="formDia"
               :close-on-click-modal="false"
               :close-on-press-escape="false"
               width="80%" @close="closeDia">
      <el-form :model="form" :rules="rules" ref="form" label-width="140px">
        <el-col :span="12">
          <el-form-item label="监控目的" prop="monitorPurpose">
            <el-input v-model="form.monitorPurpose" size="small" clearable></el-input>
          <el-form-item label="序号" prop="sortNo">
            <el-input-number v-model="form.sortNo" :min="1" style="width:100%" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="计划开展时间" prop="plannedTime">
            <el-input v-model="form.plannedTime" size="small" clearable></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="监控项目" prop="monitorProject">
          <el-form-item label="质控项目" prop="monitorProject">
            <el-input v-model="form.monitorProject" size="small" clearable></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="参加单位(人员)" prop="participant">
            <el-input v-model="form.participant" size="small" clearable></el-input>
          <el-form-item label="技术标准" prop="technicalStandardText">
            <el-input v-model="form.technicalStandardText" size="small" clearable placeholder="标准编号及名称;非检测类可填写程序文件或/" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="预算(元)" prop="budget">
            <el-input v-model="form.budget" size="small" clearable></el-input>
          <el-form-item label="质控方式" prop="monitorWay">
            <el-input v-model="form.monitorWay" size="small" clearable placeholder="如盲样检测、人员比对、监督检查" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="组织人员" prop="organization">
            <el-input v-model="form.organization" size="small" clearable></el-input>
          <el-form-item label="完成时限" prop="completionMonth">
            <el-date-picker v-model="form.completionMonth" type="month" value-format="YYYY-MM" format="YYYY.MM" style="width:100%" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="监控方式" prop="monitorWay">
            <el-input v-model="form.monitorWay" size="small" clearable></el-input>
          <el-form-item label="负责人" prop="responsibleUserId">
            <el-select v-model="form.responsibleUserId" filterable style="width:100%">
              <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="事项类别" prop="itemKind">
            <el-select v-model="form.itemKind" style="width: 100%">
              <el-option label="非检测类" value="OTHER" />
              <el-option label="检测类" value="INSPECTION" />
            </el-select>
          </el-form-item>
        </el-col>
        <template v-if="form.itemKind === 'INSPECTION'">
          <el-col :span="12"><el-form-item label="检测标准" prop="standardMethodId">
            <el-select v-model="form.standardMethodId" filterable style="width: 100%" placeholder="请选择检测标准" @change="handleStandardChange">
              <el-option v-for="item in standardOptions" :key="item.id" :value="item.id" :label="`${item.code || ''} ${item.name || ''}`" />
            </el-select>
          </el-form-item></el-col>
          <el-col :span="12"><el-form-item label="原始记录模板" prop="templateIds">
            <el-select v-model="form.templateIds" multiple collapse-tags filterable style="width: 100%" placeholder="可选择多个模板">
              <el-option v-for="item in templateOptions" :key="item.id" :value="item.id" :label="item.name" />
            </el-select>
          </el-form-item></el-col>
          <el-col :span="12"><el-form-item label="样品名称"><el-input v-model="form.sampleName" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="样品规格"><el-input v-model="form.sampleSpec" /></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="检测员"><el-select v-model="form.inspectorUserId" filterable style="width: 100%">
            <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
          </el-select></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="评价人"><el-select v-model="form.evaluatorUserId" filterable style="width: 100%">
            <el-option v-for="item in userOptions" :key="item.id" :value="item.id" :label="item.name" />
          </el-select></el-form-item></el-col>
          <el-col :span="12"><el-form-item label="任务截止日">
            <el-date-picker v-model="form.dueDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
          </el-form-item></el-col>
        </template>
      </el-form>
      <template #footer><span  class="dialog-footer">
                    <el-button @click="closeDia">取 æ¶ˆ</el-button>
@@ -54,6 +82,9 @@
  addQualityMonitorDetail,
  updateQualityMonitorDetail
} from "@/api/cnas/process/ensureResults/qualityMonitor";
import { selectStandardMethodList } from '@/api/cnas/process/method/standardMethod';
import { selectStandardTemplatePageList } from '@/api/standard/model';
import { selectUserCondition } from '@/api/performance/class';
export default {
  name: 'detailFormDialog',
@@ -66,6 +97,10 @@
      formDia: false,
      form: {
        qualityMonitorDetailsId: '',
        sortNo: null,
        technicalStandardText: '',
        completionMonth: '',
        responsibleUserId: null,
        monitorPurpose: '',
        plannedTime: '',
        monitorProject: '',
@@ -73,10 +108,26 @@
        budget: '',
        organization: '',
        monitorWay: '',
        itemKind: 'OTHER',
        standardMethodId: null,
        templateId: null,
        templateIds: [],
        sampleName: '',
        sampleSpec: '',
        inspectorUserId: null,
        evaluatorUserId: null,
        dueDate: null,
      },
      standardOptions: [],
      templateOptions: [],
      userOptions: [],
      rules: {
        monitorPurpose: [{ required: true, message: '请输入监控目的', trigger: 'blur' }],
        monitorProject: [{ required: true, message: '请输入监控项目', trigger: 'blur' }],
        monitorProject: [{ required: true, message: '请输入质控项目', trigger: 'blur' }],
        technicalStandardText: [{ required: true, message: '请输入技术标准', trigger: 'blur' }],
        monitorWay: [{ required: true, message: '请输入质控方式', trigger: 'blur' }],
        completionMonth: [{ required: true, message: '请选择完成时限', trigger: 'change' }],
        responsibleUserId: [{ required: true, message: '请选择负责人', trigger: 'change' }],
        templateIds: [{ required: true, type: 'array', min: 1, message: '请至少选择一个原始记录模板', trigger: 'change' }],
      },
      upLoad: false,
      operationType: '',
@@ -86,18 +137,59 @@
  methods: {
    openDia(type, row) {
      this.formDia = true
      selectStandardMethodList({ current: 1, size: 1000 }).then(res => { this.standardOptions = res.data?.records || res.data || [] })
      selectStandardTemplatePageList({ current: 1, size: 1000 }).then(res => { this.templateOptions = res.data?.records || res.data || [] })
      selectUserCondition({ type: 1 }).then(res => { this.userOptions = res.data || [] })
      this.operationType = type
      if (type === 'edit') {
        this.searchInfo(row)
      }
    },
    searchInfo (row) {
      this.form = {...row}
      const templateIds = row.templateIds
        ? String(row.templateIds).split(',').filter(Boolean).map(id => Number(id))
        : (row.templateId ? [Number(row.templateId)] : [])
      this.form = {...row, itemKind: row.itemKind || 'OTHER', templateIds}
    },
    handleStandardChange(id) {
      const standard = this.standardOptions.find(item => Number(item.id) === Number(id))
      if (standard) this.form.technicalStandardText = `${standard.code || ''} ${standard.name || ''}`.trim()
      this.form.templateIds = []
      this.form.templateId = null
    },
    buildEntity () {
      const entity = this.HaveJson(this.form)
      const templateIds = Array.isArray(this.form.templateIds)
        ? this.form.templateIds.map(id => Number(id)).filter(id => Number.isInteger(id) && id > 0)
        : []
      entity.templateIds = templateIds.join(',') || null
      entity.templateId = templateIds.length ? templateIds[0] : null
      entity.reviewerUserId = null
      return entity
    },
    // æäº¤è¡¨å•
    submitForm () {
      this.$refs['form'].validate((valid) => {
        if (valid) {
          if (this.form.itemKind === 'INSPECTION') {
            const required = ['standardMethodId','sampleName','inspectorUserId','evaluatorUserId','dueDate']
            if (required.some(key => !this.form[key])) {
              this.$message.warning('请补齐检测标准、模板、样品、检测员、评价人和任务截止日')
              return
            }
            if (!Array.isArray(this.form.templateIds) || !this.form.templateIds.length) {
              this.$message.warning('请至少选择一个原始记录模板')
              return
            }
            if (this.form.inspectorUserId === this.form.evaluatorUserId) {
              this.$message.warning('检测员不能同时担任评价人')
              return
            }
            if (this.form.dueDate.slice(0, 7) > this.form.completionMonth) {
              this.$message.warning('任务截止日不能晚于计划完成月份')
              return
            }
          }
          if (this.operationType === 'add') {
            this.handleAdd()
          } else {
@@ -108,7 +200,7 @@
    },
    // æäº¤æ–°å¢ž
    handleAdd () {
      let entity = this.HaveJson(this.form)
      let entity = this.buildEntity()
      entity.qualityMonitorId = this.qualityMonitorId
      this.upLoad = true
      addQualityMonitorDetail(entity).then(res => {
@@ -122,7 +214,7 @@
    },
    // æäº¤ä¿®æ”¹
    handleEdit () {
      const entity = this.HaveJson(this.form)
      const entity = this.buildEntity()
      this.upLoad = true
      updateQualityMonitorDetail(entity).then(res => {
        this.upLoad = false
src/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,233 @@
<template>
  <el-dialog v-model="visible" title="质量控制评价记录" width="min(960px, 94vw)" @closed="$emit('close')">
    <div class="record-code">记录编号:LMSY-CX30-JL03</div>
    <el-alert v-if="row"
              :title="`监控任务 ${row.inspectionTaskCode || row.entrustCode || ''} Â· ${row.monitorProject || ''}`"
              type="info"
              :closable="false"/>
    <el-alert v-if="!canEdit" :title="editNotice" :type="loaded ? 'warning' : 'info'"
              :closable="false" style="margin-top:8px"/>
    <el-form :model="form" label-width="110px" style="margin-top: 16px">
      <el-row :gutter="12">
        <el-col :span="12">
          <el-form-item label="检测项目">
            <el-input :model-value="row?.monitorProject" disabled/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="检测时间">
            <el-input :model-value="inspectionDateDisplay" readonly placeholder="原始记录复核后自动带入"/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="检测样品">
            <el-input :model-value="row?.sampleName || row?.sample" disabled/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="所用设备">
            <el-input :model-value="form.rawEquipmentDescription || ''" type="textarea"
                      :autosize="{ minRows: 1, maxRows: 6 }" readonly placeholder="原始记录复核后自动带入"/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="设备规格">
            <el-input :model-value="form.rawEquipmentSpec || ''" type="textarea" :autosize="{ minRows: 1, maxRows: 6 }"
                      readonly/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="设备编号">
            <el-input :model-value="form.rawEquipmentCode || ''" type="textarea" :autosize="{ minRows: 1, maxRows: 6 }"
                      readonly/>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="监督员">
            <el-select v-model="form.supervisorUserId" filterable style="width: 100%" :disabled="!canEdit">
              <el-option v-for="person in supervisorOptions" :key="person.id" :value="person.id" :label="person.name"/>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="被监督人员">
            <el-input :model-value="supervisedPersonName" disabled/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="检测情况及评价">
        <el-input v-model="form.evaluationConclusion" type="textarea" :rows="4" :disabled="!canEdit"/>
      </el-form-item>
      <el-table :data="form.resultRows" border style="width:100%">
        <el-table-column label="人员姓名" min-width="120">
          <template #default>{{ supervisedPersonName }}</template>
        </el-table-column>
        <el-table-column label="当日检测数据" min-width="180">
          <template #default="{ row: item }"><span :title="item.itemName || ''">{{
              item.measuredValue
            }} {{ item.unit === '/' ? '' : item.unit }}</span></template>
        </el-table-column>
        <el-table-column label="盲样值" min-width="180">
          <template #default="{ row: item }">
            <el-input v-model="item.referenceValue" :disabled="!canEdit" placeholder="评价人填写"/>
          </template>
        </el-table-column>
      </el-table>
      <el-checkbox v-if="canEdit" v-model="form.measurementConfirmed" style="margin:12px 0">
        å·²æ ¸å¯¹å½“日检测数据与已复核原始记录一致
      </el-checkbox>
      <el-form-item label="评价人员签字">
        <el-input
            :model-value="form.reviewUser ? `${form.reviewUser} ${form.reviewTime || ''}` : '提交后记录评价人及日期'"
            disabled/>
      </el-form-item>
      <el-form-item label="纠正措施及预防措施">
        <el-input v-model="form.correctiveAction" type="textarea" :rows="2" :disabled="!canEdit"/>
      </el-form-item>
      <el-row :gutter="12">
        <el-col :span="12">
          <el-form-item label="纠正责任人">
            <el-select v-model="form.correctiveResponsibleUserId" filterable clearable style="width:100%"
                       :disabled="!canEdit">
              <el-option v-for="person in people" :key="person.id" :value="person.id" :label="person.name"/>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="完成日期">
            <el-date-picker v-model="form.correctiveDueDate" type="date" value-format="YYYY-MM-DD" style="width:100%"
                            :disabled="!canEdit"/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="验证情况">
        <el-input v-model="form.verificationResult" type="textarea" :rows="2" :disabled="!canEdit"/>
      </el-form-item>
      <el-row :gutter="12">
        <el-col :span="12">
          <el-form-item label="验证责任人">
            <el-select v-model="form.verificationResponsibleUserId" filterable clearable style="width:100%"
                       :disabled="!canEdit">
              <el-option v-for="person in people" :key="person.id" :value="person.id" :label="person.name"/>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="验证日期">
            <el-date-picker v-model="form.verificationDate" type="date" value-format="YYYY-MM-DD" style="width:100%"
                            :disabled="!canEdit"/>
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item v-if="form.ratifyOpinion" label="批准意见">
        <el-input :model-value="form.ratifyOpinion" disabled/>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="visible = false">关闭</el-button>
      <el-button v-if="canEdit" type="primary" :loading="loading" @click="save">提交评价</el-button>
      <template v-if="canApprove">
        <el-button :loading="loading" @click="approve(false)">退回评价</el-button>
        <el-button type="primary" :loading="loading" @click="approve(true)">批准归档</el-button>
      </template>
    </template>
  </el-dialog>
</template>
<script>
import {mapGetters} from '@/utils/store-compat';
import {selectUserCondition} from '@/api/performance/class';
import {
  getInspectionEvaluation,
  submitInspectionEvaluation,
  approveInspectionEvaluation
} from '@/api/cnas/process/ensureResults/qualityMonitor';
export default {
  name: 'InspectionEvaluationDialog',
  emits: ['close'],
  data() {
    return {visible: false, loading: false, loaded: false, loadError: '', row: null, people: [], form: {resultRows: []}}
  },
  computed: {
    ...mapGetters(['userId']),
    canEdit() {
      return this.loaded && this.form.evaluationEditable === true
    },
    inspectionDateDisplay() {
      const dates = this.form.rawInspectionDates || []
      if (!dates.length) return ''
      return dates.length === 1 ? dates[0] : `${dates[0]} ï½ž ${dates[dates.length - 1]}`
    },
    editNotice() {
      if (!this.loaded) return '正在读取评价记录和编辑权限…'
      return this.loadError || this.form.evaluationEditReason || '当前账号只能查看评价记录'
    },
    canApprove() {
      return !!this.form.detailsEvaluateId && this.form.isFinish !== 1 && Number(this.userId) === Number(this.row?.planRatifyUserId)
    },
    supervisedPersonName() {
      const id = this.form.inspectorUserId || this.row?.inspectorUserId
      return this.people.find(person => Number(person.id) === Number(id))?.name || ''
    },
    supervisorOptions() {
      const inspectorId = Number(this.form.inspectorUserId || this.row?.inspectorUserId)
      const evaluatorId = Number(this.row?.evaluatorUserId)
      return this.people.filter(person => Number(person.id) !== inspectorId && Number(person.id) !== evaluatorId)
    }
  },
  methods: {
    open(row) {
      this.row = row
      this.loaded = false
      this.loadError = ''
      this.form = {
        qualityMonitorDetailsId: row.qualityMonitorDetailsId,
        inspectorUserId: row.inspectorUserId,
        resultRows: [],
        measurementConfirmed: false
      }
      this.visible = true
      selectUserCondition({type: 1}).then(res => {
        this.people = res.data || []
      })
      getInspectionEvaluation(row.qualityMonitorDetailsId).then(res => {
        if (res.data) this.form = {...res.data, resultRows: res.data.resultRows || [], measurementConfirmed: false}
      }).catch(() => {
        this.loadError = '评价记录读取失败,请刷新后重试'
      }).finally(() => {
        this.loaded = true
      })
    },
    save() {
      if (!this.form.supervisorUserId || !this.form.evaluationConclusion?.trim() || !this.form.resultRows?.length || this.form.resultRows.some(item => !item.measuredValue || !item.referenceValue?.trim()) || !this.form.measurementConfirmed) {
        this.$message.warning('请选择监督员,填写检测情况及评价、盲样值,并核对原始记录检测数据')
        return
      }
      this.loading = true
      submitInspectionEvaluation(this.form).then(() => {
        this.$message.success('评价已提交')
        this.visible = false
      }).finally(() => {
        this.loading = false
      })
    },
    approve(approved) {
      this.$prompt('请输入批准或退回意见', approved ? '批准评价' : '退回评价', {inputValue: this.form.ratifyOpinion || ''}).then(({value}) => {
        this.loading = true
        approveInspectionEvaluation({
          qualityMonitorDetailsId: this.row.qualityMonitorDetailsId,
          approved,
          opinion: value
        }).then(() => {
          this.$message.success(approved ? '评价已归档' : '评价已退回')
          this.visible = false
        }).finally(() => {
          this.loading = false
        })
      }).catch(() => {
      })
    }
  }
}
</script>
src/views/CNAS/process/ensureResults/ensureResultsValidity/index.vue
@@ -1,38 +1,80 @@
<template>
  <!--  7.7质量监控计划-->
  <div class="app-container">
    <div class="table-card">
      <div style="display: flex;justify-content: space-between">
        <div style="display: flex;">
          <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
            <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">计划名称</span>
            <el-input size="small" placeholder="请输入" clearable v-model="yearForm.monitorName"
                      @keyup.enter="getYearPlanList"></el-input>
          </div>
          <div style="line-height: 30px;">
            <el-button type="primary" size="small" @click="getYearPlanList">查询</el-button>
            <el-button size="small" @click="clearYear">重置</el-button>
          </div>
    <section v-if="pageMode === 'list'" class="plan-list-card">
      <div class="plan-list-toolbar">
        <div class="plan-list-filters">
          <span class="annual-plan-label">计划年度</span>
          <el-date-picker v-model="selectedYear" type="year" value-format="YYYY" format="YYYYå¹´" :clearable="false"
            size="small" style="width: 130px" @change="handleYearChange" />
          <span class="filter-label">计划名称</span>
          <el-input v-model="yearForm.monitorName" clearable placeholder="请输入" size="small" style="width: 220px"
            @keyup.enter="getYearPlanList" />
          <el-button type="primary" size="small" @click="getYearPlanList">查询</el-button>
          <el-button size="small" @click="clearYear">重置</el-button>
        </div>
        <div style="line-height: 30px;">
          <el-button size="small" type="primary" @click="leadInto">导入</el-button>
        <div class="plan-list-actions">
          <el-button size="small" @click="leadInto">导入</el-button>
          <el-button type="primary" size="small" @click="openCreatePlan">新建年度计划</el-button>
        </div>
      </div>
      <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage" :tableLoading="yearLoading"
                  :height="'calc(100vh - 34em)'" @pagination="pagination" :rowClick="rowClick" key="yearTableData"></lims-table>
      <lims-table :tableData="yearTableData" :column="yearColumnData" :page="yearPage"
        :tableLoading="yearLoading" :height="'calc(100vh - 11em)'" @pagination="pagination" key="yearTableData">
        <template #planActions="{ row }">
          <div class="detail-actions">
            <el-button link type="primary" size="small" @click="openPlan(row)">查看计划</el-button>
            <el-button v-if="canReviewRow(row)" link type="primary" size="small" @click="examinePlan(row)">审核</el-button>
            <el-button v-if="canApproveRow(row)" link type="primary" size="small" @click="approvalPlan(row)">批准</el-button>
            <el-dropdown trigger="click" @command="command => handlePlanCommand(command, row)">
              <el-button link type="primary" size="small">更多⌄</el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item command="export" :disabled="row.ratifyStatus !== 1">导出年度计划</el-dropdown-item>
                  <el-dropdown-item command="delete" divided :disabled="!canDeleteRow(row)">删除</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </template>
      </lims-table>
    </section>
    <template v-else>
    <div class="annual-plan-header">
      <div class="annual-plan-main">
        <el-button link type="primary" size="small" @click="backToPlanList">← è¿”回年度计划</el-button>
        <span class="annual-plan-label">{{ selectedYear }}年度</span>
        <template v-if="currentPlan">
          <strong>{{ currentPlan.monitorName }}</strong>
          <el-tag :type="planStatusType">{{ planStatusText }}</el-tag>
          <span>编制:{{ currentPlan.writeName || '-' }} {{ formatDate(currentPlan.writeTime) }}</span>
          <span>审核:{{ currentPlan.examineName || '-' }}</span>
          <span>批准:{{ currentPlan.ratifyName || '-' }}</span>
        </template>
        <el-tag v-else type="info">该年度尚未建立计划</el-tag>
      </div>
      <div class="annual-plan-actions">
        <el-button v-if="canEditPlan" type="primary" size="small" @click="submitPlan">提交审核</el-button>
        <el-button v-if="canReviewPlan" type="primary" size="small" @click="examinePlan(currentPlan)">审核</el-button>
        <el-button v-if="canApprovePlan" type="primary" size="small" @click="approvalPlan(currentPlan)">批准</el-button>
        <el-button size="small" @click="leadInto">导入</el-button>
        <el-button v-if="currentPlan" size="small" :disabled="currentPlan.ratifyStatus !== 1" @click="handleDown(currentPlan)">导出年度计划</el-button>
      </div>
    </div>
    <div style="margin-top: 20px">
      <div style="display: flex;justify-content: space-between">
    <div class="plan-detail-card">
      <div class="plan-detail-toolbar">
        <div style="display: flex;">
          <span class="section-title">质控项目</span>
          <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
            <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">监控目的</span>
            <el-input v-model="yearDetailForm.monitorPurpose" placeholder="请输入" size="small"
            <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">质控项目</span>
            <el-input v-model="yearDetailForm.monitorProject" placeholder="请输入" size="small"
                      @keyup.enter="getYearDetailPlanList"></el-input>
          </div>
          <div style="margin-bottom: 18px;margin-right: 10px;display: flex;align-items: center;line-height: 32px;">
            <span style="width: 88px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">监控项目</span>
            <el-input v-model="yearDetailForm.monitorProject" placeholder="请输入" size="small"
                      @keyup.enter="getYearDetailPlanList"></el-input>
            <span style="width: 70px;font-size: 14px;font-weight: 700;color: var(--lims-text-2);">负责人</span>
            <el-select v-model="yearDetailForm.responsibleUserId" clearable filterable size="small" style="width: 160px">
              <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
          </div>
          <div style="line-height: 30px;">
            <el-button type="primary" size="small" @click="getYearDetailPlanList">查询</el-button>
@@ -40,14 +82,65 @@
          </div>
        </div>
        <div style="line-height: 30px;">
          <el-button size="small" type="primary" @click="exportSignatureTemplate">导出签名模板</el-button>
          <el-button size="small" type="primary" @click="showDialog('add')">新增</el-button>
<!--          <el-button size="small" type="primary" @click="exportSignatureTemplate">导出签名模板</el-button>-->
          <el-button size="small" type="primary" :disabled="!canEditPlan" @click="showDialog('add')">新增质控项目</el-button>
        </div>
      </div>
      <lims-table :tableData="yearDetailTableData" :column="yearDetailColumnData" :page="yearDetailPage"
        :tableLoading="yearDetailLoading" :height="'calc(100vh - 34em)'" @pagination="pagination1" ref="yearDetailTableData"
        key="yearDetailTableData"></lims-table>
        :tableLoading="yearDetailLoading" :height="'calc(100vh - 15em)'" @pagination="pagination1" ref="yearDetailTableData"
        key="yearDetailTableData">
        <template #detailActions="{ row }">
          <div class="detail-actions">
            <el-button link type="primary" size="small" :disabled="!canEditPlan || !!row.inspectionTaskId"
              @click="showDialog('edit', row)">编辑</el-button>
            <el-button v-if="row.itemKind !== 'INSPECTION'" link type="primary" size="small"
              @click="carryOut(row)">实施</el-button>
            <el-button v-else-if="!row.inspectionTaskId" link type="primary" size="small"
              :disabled="row.planRatifyStatus !== 1" @click="dispatchTask(row)">下发任务</el-button>
            <el-button v-else link type="primary" size="small" @click="evaluate(row)">
              {{ row.inspectionTaskState === 5 ? '评价记录' : '评价要求' }}
            </el-button>
            <el-dropdown trigger="click" @command="command => handleDetailCommand(command, row)">
              <el-button link type="primary" size="small">更多⌄</el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="complete">完成报告</el-dropdown-item>
                  <el-dropdown-item v-if="row.itemKind !== 'INSPECTION'" command="evaluate">评价</el-dropdown-item>
                  <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && !row.inspectionTaskId" command="requirement">评价要求</el-dropdown-item>
                  <el-dropdown-item v-if="row.itemKind === 'INSPECTION' && row.inspectionTaskId" command="cancel"
                    :disabled="row.inspectionTaskOrderState !== 1 || row.inspectionTaskState !== 0">取消任务</el-dropdown-item>
                  <el-dropdown-item command="attachment">附件上传</el-dropdown-item>
                  <el-dropdown-item command="export">导出</el-dropdown-item>
                  <el-dropdown-item command="delete" divided
                    :disabled="!canEditPlan || !!row.inspectionTaskId">删除</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </template>
      </lims-table>
    </div>
    </template>
    <el-dialog v-model="createPlanDialog" title="新建年度质量控制计划" width="520px">
      <el-form :model="planForm" label-width="90px">
        <el-form-item label="年度">
          <el-date-picker v-model="planForm.monitorYear" type="year" value-format="YYYY" format="YYYYå¹´"
            :clearable="false" style="width: 100%" placeholder="请选择年度" />
        </el-form-item>
        <el-form-item label="计划名称"><el-input v-model="planForm.monitorName" /></el-form-item>
        <el-form-item label="审核人">
          <el-select v-model="planForm.examineUserId" filterable style="width:100%">
            <el-option v-for="item in responsibleOptions" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="createPlanDialog=false">取消</el-button>
        <el-button type="primary" :loading="createPlanLoading" @click="createPlan">确定</el-button>
      </template>
    </el-dialog>
    <!--新增修改弹框-->
    <detail-form-dialog v-if="formDia" ref="formDia" :qualityMonitorId="qualityMonitorId"
      @closeDia="closeDia"></detail-form-dialog>
@@ -56,6 +149,8 @@
      @closeCarryOutDia="closeCarryOutDia"></carry-out-dialog>
    <!--评价流程弹框-->
    <evaluate-dialog v-if="evaluateDialog" ref="evaluateDialog" @closeEvaDia="closeEvaDia"></evaluate-dialog>
    <inspection-evaluation-dialog v-if="inspectionEvaluateDialog" ref="inspectionEvaluateDialog"
      @close="closeInspectionEvaluateDialog" />
    <el-dialog v-model="examineDialog" title="审核" width="30%" @close="closeExamineDia">
      <span>
        å®¡æ ¸å¤‡æ³¨ï¼š
@@ -170,17 +265,20 @@
<script>
import DetailFormDialog from './components/detailFormDialog.vue';
import InspectionEvaluationDialog from './components/inspectionEvaluationDialog.vue';
import CarryOutDialog from './components/carryOutDialog.vue';
import EvaluateDialog from './components/evaluateDialog.vue';
import filePreview from "@/components/Preview/filePreview.vue";
import limsTable from "@/components/Table/lims-table.vue";
import {
  createAnnualPlan, getAnnualPlan, submitAnnualPlan,
  delQualityMonitorDetail,
  delQualitySupervise,
  examineQualityMonitor, exportQualityMonitorDetail, exportQualityMonitorEvaluate, exportQualityMonitorRatify,
  pageQualityMonitor, pageQualityMonitorDetail, ratifyFinishReport,
  ratifyQualityMonitor
} from "@/api/cnas/process/ensureResults/qualityMonitor";
import { dispatchInspectionTask, cancelInspectionTask } from "@/api/cnas/process/ensureResults/qualityMonitor";
import { selectUserCondition } from "@/api/performance/class";
import { mapGetters } from "@/utils/store-compat";
import ViewRecord from "./components/ViewRecord.vue";
@@ -188,11 +286,19 @@
export default {
  name: 'EnsureResultsValidity',
  // import å¼•入的组件需要注入到对象中才能使用
  components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog },
  components: {ViewRecord, limsTable, filePreview, EvaluateDialog, CarryOutDialog, DetailFormDialog, InspectionEvaluationDialog },
  data() {
    // è¿™é‡Œå­˜æ”¾æ•°æ®
    return {
      ViewRecord: false,
      inspectionEvaluateDialog: false,
      pageMode: 'list',
      selectedYear: String(new Date().getFullYear()),
      currentPlan: null,
      selectedPlanId: null,
      createPlanDialog: false,
      createPlanLoading: false,
      planForm: { monitorYear: String(new Date().getFullYear()), monitorName: '', examineUserId: null },
      examineUserId: '',
      responsibleOptions: [],
      yearForm: {
@@ -207,247 +313,92 @@
        {
          label: '计划名称',
          prop: 'monitorName',
          width: '150px'
          minWidth: '220px'
        }, {
          label: '计划年度',
          prop: 'monitorYear',
          width: '100px'
        }, {
          dataType: 'tag',
          label: '计划状态',
          prop: 'workflowStatus',
          width: '110px',
          formatData: (value, row) => this.planWorkflowText(value),
          formatType: value => this.planWorkflowType(value)
        }, {
          label: '编制人',
          prop: 'writeName',
          width: '100'
          minWidth: '100px'
        }, {
          label: '编制日期',
          prop: 'writeTime',
          width: '160'
        }, {
          dataType: 'tag',
          label: '审核状态',
          prop: 'examineStatus',
          width: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不通过';
            } else if (params === 1) {
              return '通过';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '审核内容',
          prop: 'examineRemark',
          width: '100'
          minWidth: '150px',
          formatData: value => this.formatDate(value)
        }, {
          label: '审核人',
          prop: 'examineName',
          width: '100'
          minWidth: '100px'
        }, {
          label: '审核日期',
          prop: 'examineTime',
          width: '160'
        }, {
          dataType: 'tag',
          label: '批准状态',
          prop: 'ratifyStatus',
          width: '100',
          formatData: (params) => {
            if (params === 0) {
              return '不批准';
            } else if (params === 1) {
              return '批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return 'danger';
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
            }
          }
        }, {
          label: '批准内容',
          prop: 'ratifyRemark',
          width: '100'
          minWidth: '150px',
          formatData: value => this.formatDate(value)
        }, {
          label: '批准人',
          prop: 'ratifyName',
          width: '100'
          minWidth: '100px'
        }, {
          label: '批准日期',
          prop: 'ratifyTime',
          width: '160'
          minWidth: '150px',
          formatData: value => this.formatDate(value)
        }, {
          dataType: 'action',
          dataType: 'slot',
          slot: 'planActions',
          label: '操作',
          fixed: 'right',
          operation: [
            {
              name: '审核',
              type: 'text',
              disabled: (row) => {
                if (row.examineStatus === 1 || this.userId != row.examineUserId) {
                  return true
                } else {
                  return false
                }
              },
              clickFun: (row) => {
                this.examinePlan(row)
              }
            },
            {
              name: '批准',
              type: 'text',
              disabled: (row) => {
                if (row.ratifyStatus === 1 || row.examineStatus !== 1 || this.userId != row.ratifyUserId) {
                  return true
                } else {
                  return false
                }
              },
              clickFun: (row) => {
                this.approvalPlan(row)
              }
            },
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.handleDown(row)
              },
              disabled: (row) => {
                if (row.ratifyStatus !== 1) {
                  return true
                } else {
                  return false
                }
              },
            },
            {
              name: '删除',
              type: 'text',
              color: 'var(--el-color-danger)',
              clickFun: (row) => {
                this.delPlan(row)
              },
              disabled: (row) => {
                if (row.examineStatus === 1) {
                  return true;
                } else {
                  return false;
                }
              },
            }
          ]
          width: '220px'
        }],
      yearTableData: [],  // å¹´è¡¨
      yearLoading: false,
      yearDetailForm: {
        monitorPurpose: '',
        monitorProject: '',
        responsibleUserId: null,
      },
      yearDetailColumnData: [
        {
          label: '监控目的',
          prop: 'monitorPurpose',
          width: '150px',
          showOverflowTooltip: true,
        }, {
          label: '计划开展时间',
          prop: 'plannedTime',
          width: '150px'
        }, {
          label: '监控项目',
          label: '质控项目',
          prop: 'monitorProject',
          width: '150px'
          minWidth: '140px'
        }, {
          label: '参加单位(人员)',
          prop: 'participant',
          width: '190px'
          label: '技术标准',
          prop: 'technicalStandardText',
          minWidth: '220px'
        }, {
          label: '预算(元)',
          prop: 'budget',
          width: '150px'
        }, {
          label: '组织人员',
          prop: 'organization',
          width: '150px'
        }, {
          label: '监控方式',
          label: '质控方式',
          prop: 'monitorWay',
          width: '150px'
        },{
          dataType: 'tag',
          label: '实施状态',
          prop: 'detailsRatifyStatus',
          width: '100',
          formatData: (params) => {
            if (params === 0) {
              return '未开始';
            } else if (params === 1) {
              return '待评价';
            }  else if (params === 2) {
              return '不批准';
            } else if (params === 3) {
              return '已批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return '';
            } else if (params === 1) {
              return 'warning';
            } else if (params === 2) {
              return 'danger';
            }  else if (params === 3) {
              return 'success';
            } else {
              return null;
            }
          }
        },{
          dataType: 'tag',
          label: '报告状态',
          prop: 'reportStatus',
          width: '100',
          formatData: (params) => {
            if (params === 0) {
              return '未开始';
            } else if (params === 1) {
              return '待评价';
            }  else if (params === 2) {
              return '不批准';
            } else if (params === 3) {
              return '已批准';
            } else {
              return null;
            }
          },
          formatType: (params) => {
            if (params === 0) {
              return '';
            } else if (params === 1) {
              return 'warning';
            } else if (params === 2) {
              return 'danger';
            }  else if (params === 3) {
              return 'success';
            } else {
              return null;
            }
          }
          minWidth: '120px'
        }, {
          label: '完成时限',
          prop: 'completionMonth',
          width: '110px',
          formatData: value => value ? value.replace('-', '.') : ''
        }, {
          label: '负责人',
          prop: 'responsibleName',
          minWidth: '100px'
        }, {
          label: '评价人',
          prop: 'evaluatorName',
          minWidth: '100px'
        }, {
          label: '事项类别', prop: 'itemKind', width: '100px',
          formatData: value => value === 'INSPECTION' ? '检测类' : '非检测类'
        }, {
          label: '监控任务编号', prop: 'inspectionTaskCode', minWidth: '150px'
        }, {
          label: '任务状态', prop: 'inspectionTaskState', width: '100px',
          formatData: value => this.inspectionTaskStatus(value)
        },{
          dataType: 'tag',
          label: '评价状态',
@@ -480,61 +431,11 @@
            }
          }
        }, {
          dataType: 'action',
          dataType: 'slot',
          slot: 'detailActions',
          label: '操作',
          fixed: 'right',
          operation: [
            {
              name: '编辑',
              type: 'text',
              clickFun: (row) => {
                this.showDialog('edit', row)
              }
            },
            {
              name: '实施',
              type: 'text',
              clickFun: (row) => {
                this.carryOut(row)
              }
            },
            {
              name: '完成报告',
              type: 'text',
              clickFun: (row) => {
                this.record(row)
              },
            },
            {
              name: '评价',
              type: 'text',
              clickFun: (row) => {
                this.evaluate(row)
              }
            },
            {
              name: '附件上传',
              type: 'text',
              clickFun: (row) => {
                this.viewTestRecord(row)
              }
            },
            {
              name: '导出',
              type: 'text',
              clickFun: (row) => {
                this.downLoadPost(row);
              },
            },
            {
              name: '删除',
              type: 'text',
              color: 'var(--el-color-danger)',
              clickFun: (row) => {
                this.delYearPlanDetail(row)
              }
            }
          ]
          width: '220px'
        }
      ],
      yearDetailTableData: [], // å¹´æ˜Žç»†è¡¨
@@ -574,31 +475,91 @@
    };
  },
  mounted() {
    this.getUserList()
    this.getYearPlanList()
  },
  // æ–¹æ³•集合
  methods: {
    // æŸ¥è¯¢å¹´åº¦è®¡åˆ’表
    getYearPlanList() {
      const entity = {
        monitorName: this.yearForm.monitorName,
      }
      const page = this.yearPage
      this.yearLoading = true
      pageQualityMonitor({ ...entity, ...page }).then(res => {
        this.yearLoading = false
        this.yearTableData = res.data.records
        this.yearPage.total = res.data.total
        if (this.yearTableData.length > 0) {
          this.rowClick(this.yearTableData[0])
        }
      }).catch(err => {
        console.log('err---', err);
      const entity = {
        monitorYear: this.selectedYear,
        monitorName: this.yearForm.monitorName
      }
      return pageQualityMonitor({ ...entity, ...this.yearPage }).then(res => {
        this.yearTableData = res.data?.records || []
        this.yearPage.total = res.data?.total || 0
      }).finally(() => {
        this.yearLoading = false
      })
    },
    loadAnnualPlan() {
      if (!this.selectedPlanId) return Promise.resolve()
      return this.loadPlanVersion()
    },
    loadPlanVersion() {
      if (!this.selectedPlanId) return Promise.resolve()
      return getAnnualPlan({ monitorYear: this.selectedYear, qualityMonitorId: this.selectedPlanId }).then(res => {
        this.currentPlan = res.data || null
        this.qualityMonitorId = this.currentPlan?.qualityMonitorId || ''
        this.yearDetailPage.current = 1
        return this.getYearDetailPlanList()
      })
    },
    openPlan(row, addFirstDetail = false) {
      this.selectedYear = String(row.monitorYear || this.selectedYear)
      this.selectedPlanId = row.qualityMonitorId
      this.pageMode = 'detail'
      return this.loadPlanVersion().then(() => {
        if (addFirstDetail) this.showDialog('add')
      })
    },
    backToPlanList() {
      this.pageMode = 'list'
      this.currentPlan = null
      this.qualityMonitorId = ''
      this.yearDetailForm = { monitorProject: '', responsibleUserId: null }
      this.getYearPlanList()
    },
    handleYearChange() {
      this.yearPage.current = 1
      this.getYearPlanList()
    },
    openCreatePlan() {
      this.planForm = {
        monitorYear: String(new Date().getFullYear()),
        monitorName: '',
        examineUserId: null
      }
      this.createPlanDialog = true
    },
    createPlan() {
      if (!this.planForm.monitorYear || !this.planForm.monitorName || !this.planForm.examineUserId) {
        this.$message.warning('请选择年度、填写计划名称并选择审核人')
        return
      }
      this.createPlanLoading = true
      createAnnualPlan({ ...this.planForm }).then(res => {
        this.createPlanDialog = false
        this.selectedYear = String(res.data.monitorYear)
        this.yearPage.current = 1
        this.$message.success('年度计划已创建,请填写第一个质控项目')
        return this.getYearPlanList().then(() => this.openPlan(res.data, true))
      }).finally(() => { this.createPlanLoading = false })
    },
    submitPlan() {
      this.$confirm('提交后质控项目将锁定,确认提交审核?', '提交审核').then(() => {
        submitAnnualPlan(this.qualityMonitorId).then(() => {
          this.$message.success('已提交审核')
          this.loadPlanVersion()
          this.getYearPlanList()
        })
      }).catch(() => {})
    },
    clearYear() {
      this.yearForm.monitorName = ''
      this.yearPage.current = 1
      this.getYearPlanList()
    },
    pagination({ page, limit }) {
@@ -609,10 +570,11 @@
    pagination1({ page, limit }) {
      this.yearDetailPage.current = page;
      this.yearDetailPage.size = limit;
      this.getYearPlanList();
      this.getYearDetailPlanList();
    },
    leadInto() {
      this.uploadDia = true
      this.planYear = this.selectedYear
      this.getUserList()
    },
    // å¯¼å…¥æµç¨‹
@@ -636,7 +598,7 @@
        this.timer = setTimeout(() => {
          this.uploadDia = false
          this.fileList = []
          this.planYear = ''
          this.planYear = this.selectedYear
          this.examineUserId = ''
          this.getYearPlanList()
        }, 1000)
@@ -650,7 +612,7 @@
        return;
      }
      if (!this.examineUserId) {
        this.$message.warning('请选择批准人')
        this.$message.warning('请选择审核人')
        return;
      }
      this.$refs.upload.submit();
@@ -678,7 +640,7 @@
    closeExamineDia() {
      this.examineDialog = false
      this.examineInfo.examineRemark = ''
      this.getYearPlanList()
      this.refreshPlanData()
    },
    // æ‰¹å‡†
    approvalPlan(row) {
@@ -701,7 +663,14 @@
    closeRatifyDia() {
      this.ratifyDialog = false
      this.ratifyInfo.ratifyRemark = ''
      this.getYearPlanList()
      this.refreshPlanData()
    },
    refreshPlanData() {
      return this.getYearPlanList().then(() => {
        if (this.pageMode === 'detail' && this.selectedPlanId) {
          return this.loadPlanVersion()
        }
      })
    },
    // æ‰¹å‡†æŠ¥å‘Š
    handleApproval(status) {
@@ -762,8 +731,8 @@
    getYearDetailPlanList() {
      const entity = {
        qualityMonitorId: this.qualityMonitorId,
        monitorPurpose: this.yearDetailForm.monitorPurpose,
        monitorProject: this.yearDetailForm.monitorProject,
        responsibleUserId: this.yearDetailForm.responsibleUserId,
      }
      const page = this.yearDetailPage
      this.yearDetailLoading = true
@@ -771,7 +740,7 @@
        this.yearDetailLoading = false
        this.yearDetailTableData = res.data.records
        this.yearDetailPage.total = res.data.total
        this.$refs.yearDetailTableData.$refs.multipleTable.doLayout()
        this.$nextTick(() => this.$refs.yearDetailTableData?.$refs?.multipleTable?.doLayout())
      }).catch(err => {
        console.log('err---', err);
        this.yearDetailLoading = false
@@ -780,8 +749,8 @@
    // é‡ç½®æ˜Žç»†è¡¨
    clearDetail() {
      this.yearDetailForm = {
        monitorPurpose: '',
        monitorProject: ''
        monitorProject: '',
        responsibleUserId: null
      }
      this.getYearDetailPlanList()
    },
@@ -862,6 +831,11 @@
    // end
    // æ‰“开评价弹框
    evaluate(row) {
      if (row.itemKind === 'INSPECTION') {
        this.inspectionEvaluateDialog = true
        this.$nextTick(() => this.$refs.inspectionEvaluateDialog.open(row))
        return
      }
      this.evaluateDialog = true
      this.$nextTick(() => {
        this.$refs.evaluateDialog.openDia(row)
@@ -870,6 +844,26 @@
    closeEvaDia() {
      this.evaluateDialog = false
      this.getYearDetailPlanList()
    },
    closeInspectionEvaluateDialog() {
      this.inspectionEvaluateDialog = false
      this.getYearDetailPlanList()
    },
    dispatchTask(row) {
      this.$confirm(`确认下发“${row.monitorProject}”的质量监控检验任务?`, '下发任务').then(() => {
        dispatchInspectionTask(row.qualityMonitorDetailsId).then(res => {
          this.$message.success(`已下发监控任务:${res.data.entrustCode}`)
          this.getYearDetailPlanList()
        })
      }).catch(() => {})
    },
    cancelTask(row) {
      this.$confirm(`确认取消监控任务“${row.inspectionTaskCode}”?已取消任务会保留历史记录。`, '取消任务').then(() => {
        cancelInspectionTask(row.qualityMonitorDetailsId).then(() => {
          this.$message.success('任务已取消')
          this.getYearDetailPlanList()
        })
      }).catch(() => {})
    },
    // é™„件上传
    viewTestRecord (row) {
@@ -885,6 +879,14 @@
    },
    // æ‰“开年度明细新增、修改弹框
    showDialog(type, row) {
      if (!this.qualityMonitorId) {
        this.$message.warning('请先新建年度质量控制计划')
        return
      }
      if (!this.canEditPlan) {
        this.$message.warning('当前计划状态不能维护质控项目')
        return
      }
      this.formDia = true
      this.$nextTick(() => {
        this.$refs.formDia.openDia(type, row)
@@ -949,11 +951,93 @@
      link.target = '_blank';
      document.body.appendChild(link);
      link.click();
    },
    formatDate(value) {
      return value ? String(value).slice(0, 10) : '-'
    },
    planWorkflowText(value) {
      return ({
        DRAFT: '草稿',
        PENDING_REVIEW: '待审核',
        REVIEW_REJECTED: '审核退回',
        PENDING_APPROVAL: '待批准',
        APPROVAL_REJECTED: '批准退回',
        APPROVED: '已批准'
      })[value] || '历史计划'
    },
    planWorkflowType(value) {
      return ({
        DRAFT: 'info',
        PENDING_REVIEW: 'warning',
        REVIEW_REJECTED: 'danger',
        PENDING_APPROVAL: 'warning',
        APPROVAL_REJECTED: 'danger',
        APPROVED: 'success'
      })[value] || 'info'
    },
    canReviewRow(row) {
      return row.workflowStatus === 'PENDING_REVIEW'
        && Number(this.userId) === Number(row.examineUserId)
    },
    canApproveRow(row) {
      return row.workflowStatus === 'PENDING_APPROVAL'
        && Number(this.userId) === Number(row.ratifyUserId)
    },
    canDeleteRow(row) {
      return Number(this.userId) === Number(row.writeUserId)
        && ['DRAFT', 'REVIEW_REJECTED', 'APPROVAL_REJECTED'].includes(row.workflowStatus || 'DRAFT')
    },
    handlePlanCommand(command, row) {
      if (command === 'export') this.handleDown(row)
      if (command === 'delete') this.delPlan(row)
    },
    inspectionTaskStatus(value) {
      const map = { 0: '待检测', 1: '检测中', 2: '检测中', 3: '待复核', 4: '复核退回', 5: '待评价' }
      return value === null || value === undefined ? '未下发' : (map[value] || '处理中')
    },
    handleDetailCommand(command, row) {
      const handlers = {
        complete: () => this.record(row),
        evaluate: () => this.evaluate(row),
        requirement: () => this.evaluate(row),
        cancel: () => this.cancelTask(row),
        attachment: () => this.viewTestRecord(row),
        export: () => this.downLoadPost(row),
        delete: () => this.delYearPlanDetail(row)
      }
      handlers[command]?.()
    }
  },
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    ...mapGetters(["userId", "nickName"]),
    effectivePlanStatus() {
      if (!this.currentPlan) return ''
      if (this.currentPlan.workflowStatus) return this.currentPlan.workflowStatus
      if (this.currentPlan.ratifyStatus === 1) return 'APPROVED'
      if (this.currentPlan.ratifyStatus === 0) return 'APPROVAL_REJECTED'
      if (this.currentPlan.examineStatus === 1) return 'PENDING_APPROVAL'
      if (this.currentPlan.examineStatus === 0) return 'REVIEW_REJECTED'
      return 'DRAFT'
    },
    planStatusText() {
      return ({DRAFT:'草稿',PENDING_REVIEW:'待审核',REVIEW_REJECTED:'审核退回',PENDING_APPROVAL:'待批准',APPROVAL_REJECTED:'批准退回',APPROVED:'已批准'})[this.effectivePlanStatus] || '历史计划'
    },
    planStatusType() {
      return ({DRAFT:'info',PENDING_REVIEW:'warning',REVIEW_REJECTED:'danger',PENDING_APPROVAL:'warning',APPROVAL_REJECTED:'danger',APPROVED:'success'})[this.effectivePlanStatus] || 'info'
    },
    canEditPlan() {
      return !!this.currentPlan && Number(this.userId) === Number(this.currentPlan.writeUserId)
        && ['DRAFT','REVIEW_REJECTED','APPROVAL_REJECTED'].includes(this.effectivePlanStatus)
    },
    canReviewPlan() {
      return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_REVIEW'
        && Number(this.userId) === Number(this.currentPlan.examineUserId)
    },
    canApprovePlan() {
      return !!this.currentPlan && this.effectivePlanStatus === 'PENDING_APPROVAL'
        && Number(this.userId) === Number(this.currentPlan.ratifyUserId)
    },
    action() {
      return this.javaApi + '/qualityMonitor/importQualityMonitor'
    },
@@ -967,4 +1051,84 @@
};
</script>
<style scoped></style>
<style scoped>
.plan-list-card {
  min-width: 0;
  padding: 14px 16px;
  background: var(--lims-card-bg, var(--el-bg-color));
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
}
.plan-list-toolbar,
.plan-list-filters,
.plan-list-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.plan-list-toolbar {
  justify-content: space-between;
  margin-bottom: 14px;
}
.filter-label {
  margin-left: 8px;
  font-size: 14px;
  font-weight: 700;
  color: var(--lims-text-2);
  white-space: nowrap;
}
.annual-plan-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  margin-bottom: 16px;
  background: var(--lims-card-bg, var(--el-bg-color));
  border: 1px solid var(--el-border-color-light);
  border-radius: 4px;
}
.annual-plan-main, .annual-plan-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.annual-plan-label { font-weight: 700; color: var(--lims-text-2); }
.plan-detail-card {
  min-width: 0;
  background: var(--lims-card-bg, var(--el-bg-color));
}
.plan-detail-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
}
.section-title {
  display: inline-flex;
  align-items: center;
  margin-right: 18px;
  font-size: 15px;
  font-weight: 700;
  color: var(--lims-text-1, var(--el-text-color-primary));
  white-space: nowrap;
}
.detail-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  white-space: nowrap;
}
@media (max-width: 1200px) {
  .annual-plan-header {
    align-items: flex-start;
    flex-direction: column;
  }
  .annual-plan-actions {
    width: 100%;
  }
}
</style>
src/views/CNAS/process/method/methodVerification/component/calibrationsFileDia.vue
@@ -2,6 +2,8 @@
  <div>
    <el-dialog v-model="filesDialogVisible" title="查看校准证书" width="80%" @closed="closeFilesLook">
      <div>
        <el-alert v-if="!tableLoading && tableData.length === 0" type="info" :closable="false"
                  title="所选设备暂无校准证书"/>
        <limsTable
          ref="yearTable"
          :column="columnData"
@@ -18,7 +20,7 @@
      fullscreen
      title="查看附件" top="5vh" width="800px">
      <filePreview v-if="lookDialogVisible" :currentFile="{}"
                   :fileUrl="javaApi+'/img/'+currentInfo.fileUrl" style="max-height: 90vh;overflow-y: auto;"/>
                   :fileUrl="fileUrl(currentInfo)" style="max-height: 90vh;overflow-y: auto;"/>
    </el-dialog>
  </div>
</template>
@@ -27,6 +29,7 @@
import filePreview from '@/components/Preview/filePreview.vue';
import limsTable from '@/components/Table/lims-table.vue'
import file from '@/utils/file';
import { getCurrentCalibrationFiles } from '@/api/cnas/process/method/methodVerification'
export default {
  name: 'calibrationsFileDia',
@@ -88,10 +91,24 @@
  },
  // æ–¹æ³•集合
  methods: {
    openDia(row) {
    fileUrl(row) {
      const image = /\.(png|jpe?g|gif|bmp|webp)$/i.test(row.fileUrl || '')
      return this.javaApi + (image ? '/img/' : '/word/') + row.fileUrl
    },
    openDia(row = {}) {
      this.filesDialogVisible = true
      this.info = row
      this.tableData = this.info.calibrationsFileList
      this.tableData = row.calibrationsFileList || []
      if (row.useCurrentDevices) {
        const deviceIds = [...new Set((row.machineAttachmentList || []).map(device => device.deviceId).filter(Boolean))]
        if (!deviceIds.length) return
        this.tableLoading = true
        getCurrentCalibrationFiles({deviceIds: deviceIds.join(',')}).then(res => {
          if (res.code === 200) this.tableData = res.data || []
        }).finally(() => {
          this.tableLoading = false
        })
      }
    },
    closeFilesLook () {
      this.filesDialogVisible = false
@@ -104,7 +121,7 @@
    // ä¸‹è½½
    upload (row) {
      let url = '';
      if(row.type==1){
      if (/\.(png|jpe?g|gif|bmp|webp)$/i.test(row.fileUrl || '')) {
        url = this.javaApi+'/img/'+row.fileUrl
        file.downloadIamge(url,row.fileName)
      }else{
src/views/CNAS/process/method/methodVerification/component/wordFormDIa.vue
@@ -57,11 +57,11 @@
                <el-select v-model="form.confirmUser" multiple :multiple-limit="5" placeholder="请选择检测人员" :disabled="isView">
                  <el-option v-for="user in userList" :key="user.id" :label="user.name" :value="user.id"/>
                </el-select>
                <el-link v-if="operationType !== 'add'" type="primary" @click="viewWorkPermit">查看上岗证</el-link>
                <el-link type="primary" @click="viewWorkPermit">查看上岗证</el-link>
              </div>
              <div v-if="item.key === 'equipment'" class="row-extra">
                <el-link type="primary" @click="viewDevice">查看设备</el-link>
                <el-link v-if="operationType !== 'add'" type="primary" @click="viewCalibrationsFileDia">查看校准证书
                <el-link type="primary" @click="viewCalibrationsFileDia">查看校准证书
                </el-link>
              </div>
            </td>
@@ -237,7 +237,14 @@
      this.openChild('deviceVisible', 'device', this.form)
    },
    viewCalibrationsFileDia() {
      this.openChild('calibrationVisible', 'calibration', this.form)
      if (this.operationType === 'add' && !(this.form.machineAttachmentList || []).some(device => device.deviceId)) {
        this.$message.warning('请先选择设备')
        return
      }
      this.openChild('calibrationVisible', 'calibration', {
        ...this.form,
        useCurrentDevices: this.operationType === 'add'
      })
    },
    viewTestRecord() {
      this.openChild('recordVisible', 'record', this.info)
src/views/business/inspectionTask/index.vue
@@ -3,7 +3,7 @@
    <div style="height: 100%">
      <div class="search">
        <el-form :model="queryParams" ref="queryParams" size="small" :inline="true">
          <el-form-item label="委托编号" prop="entrustCode">
          <el-form-item :label="taskSource === 'QUALITY_MONITOR' ? '监控任务编号' : '委托编号'" prop="entrustCode">
            <el-input v-model="queryParams.entrustCode" clearable placeholder="请输入" size="small"
                      @keyup.enter="refreshTable()"></el-input>
          </el-form-item>
@@ -29,7 +29,7 @@
      <div class="center" v-loading="tableLoading">
        <div class="center-options">
          <div style="display: flex; align-items: center">
            <span style="font-size: 14px">试验室:</span>
            <span style="font-size: 14px">任务来源:</span>
            <ul class="tab">
              <li v-for="(m, i) in tabList" :key="i" :class="{ active: i == tabIndex }" @click="handleTab(m, i)">
                {{ m.label.replace("试验室", "") }}
@@ -45,7 +45,7 @@
            <span>{{ page.total }}</span>
          </div>
        </div>
        <lims-table :tableData="tableData" :column="column" :page="page"
        <lims-table :tableData="tableData" :column="displayColumns" :page="page"
          :rowClassName="rowClassName" :height="'calc(100vh - 300px)'" @pagination="pagination"
          key="tableData0">
          <template #action="scope"><div>
@@ -56,7 +56,7 @@
                  (scope.row.userName && !scope.row.userName.includes(nickName))
                )"
                       @click="handleInspection(scope.row)">检验</el-button>
            <el-button link type="primary" size="small" :disabled="(
            <el-button v-if="scope.row.taskSource !== 'QUALITY_MONITOR'" link type="primary" size="small" :disabled="(
                  scope.row.userName == null ||
                  scope.row.insState == 5 ||
                  scope.row.insState == 3 ||
@@ -64,12 +64,13 @@
                )"
                       @click="handleConnect(scope.row)">交接</el-button>
            <el-button link type="primary" size="small" @click="viewInspectInfo(scope.row)">原始记录</el-button>
            <el-popover placement="bottom" trigger="hover" style="margin-left: 6px" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||(scope.row.userName && !scope.row.userName.includes(nickName)))">
            <el-button v-if="scope.row.taskSource === 'QUALITY_MONITOR'" link type="primary" size="small" @click="showMonitorRequirement(scope.row)">{{ Number(scope.row.insState) === 5 ? '评价记录' : '评价要求' }}</el-button>
            <el-popover v-if="scope.row.taskSource !== 'QUALITY_MONITOR'" placement="bottom" trigger="hover" style="margin-left: 6px" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||(scope.row.userName && !scope.row.userName.includes(nickName)))">
              <template #reference>
                <el-button link type="primary" size="small" :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
                <el-button link type="primary" size="small" :disabled="(scope.row.taskSource === 'QUALITY_MONITOR' || scope.row.insState != 3 || scope.row.userName == null ||
                  (scope.row.userName && !scope.row.userName.includes(nickName)))">更多</el-button>
              </template>
              <div>
              <div v-if="scope.row.taskSource !== 'QUALITY_MONITOR'">
                <el-button :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
                  (scope.row.userName && !scope.row.userName.includes(nickName)))" style="margin-left: 10px" link type="primary" size="small" @click="download(scope.row)">下载报告</el-button>
                <el-button :disabled="(scope.row.insState != 3 || scope.row.userName == null ||
@@ -80,6 +81,23 @@
        </lims-table>
      </div>
    </div>
    <el-dialog v-model="monitorRequirementVisible" title="质量监控评价要求" width="560px">
      <el-descriptions :column="1" border>
        <el-descriptions-item label="监控任务编号">{{ monitorRequirement.entrustCode }}</el-descriptions-item>
        <el-descriptions-item label="监控项目">{{ monitorRequirement.monitorProject }}</el-descriptions-item>
        <el-descriptions-item label="监控目的">{{ monitorRequirement.monitorPurpose }}</el-descriptions-item>
        <el-descriptions-item label="监控方式">{{ monitorRequirement.monitorWay }}</el-descriptions-item>
        <el-descriptions-item label="检测标准">{{ monitorRequirement.standardCode }}</el-descriptions-item>
        <el-descriptions-item label="样品及规格">{{ monitorRequirement.sample }} {{ monitorRequirement.sampleSpec }}</el-descriptions-item>
        <el-descriptions-item label="完成期限">{{ monitorRequirement.dueDate }}</el-descriptions-item>
      </el-descriptions>
      <p>请在“原始记录”中填写检测数据,复核通过后由评价人员填写质量控制评价记录。</p>
      <template #footer>
        <el-button @click="monitorRequirementVisible=false">关闭</el-button>
        <el-button v-if="Number(monitorRequirement.insState) === 5" type="primary" @click="openMonitorEvaluation">打开评价记录</el-button>
      </template>
    </el-dialog>
    <inspection-evaluation-dialog v-if="inspectionEvaluateDialog" ref="inspectionEvaluateDialog" @close="inspectionEvaluateDialog=false" />
    <el-dialog v-model="claimVisible" title="提示" width="400px">
      æ˜¯å¦è®¤é¢†å§”托编号<span style="color: #33c130">{{
        sampleUserForm.entrustCode
@@ -210,10 +228,11 @@
import {getRetestResult} from "@/api/business/rawMaterialOrder";
import onlyoffice from "@/components/Onlyoffice/onlyoffice.vue";
import filePreview from "@/components/Preview/filePreview.vue";
import InspectionEvaluationDialog from "@/views/CNAS/process/ensureResults/ensureResultsValidity/components/inspectionEvaluationDialog.vue";
export default {
  name: 'InspectionTask',
  components: {
    filePreview, onlyoffice,
    filePreview, onlyoffice, InspectionEvaluationDialog,
    limsTable,
    viewManHourDia,
    UnPassRetestResult
@@ -221,10 +240,18 @@
  dicts: ["urgency_level", "inspection_task_state","material_prop_type"],
  computed: {
    ...mapGetters(["nickName", "userId"]),
    displayColumns() {
      return this.column.filter(item => this.taskSource === 'QUALITY_MONITOR'
        ? !['typeSource', 'orderType'].includes(item.prop)
        : !['monitorProject', 'dueDate'].includes(item.prop))
    },
  },
  data() {
    return {
      issuedVisible: false,
      monitorRequirementVisible: false,
      monitorRequirement: {},
      inspectionEvaluateDialog: false,
      fullscreen: false,
      lookDialogVisible: false,
      option: null,
@@ -245,7 +272,8 @@
      },
      claimVisible: false,
      tabList: [
        { label: "委托", value: -1 },
        { label: "委托", value: "ENTRUSTED" },
        { label: "质量监控", value: "QUALITY_MONITOR" },
        // { label: "原材料", value: 1 },
        // { label: "外购", value: 0 },
      ],
@@ -255,6 +283,7 @@
      insStateList: [],
      state: 0, // 0:台账页,1:检验页面,2检验页面(复核),默认为0,3数据查看
      typeSource: -1, // 0:外购成品下单,1:原材料下单
      taskSource: 'ENTRUSTED',
      sonLaboratory: null, // 0:委托,1:原材料
      activeFace: 0, // 1:下单,2:查看,3:审核,默认为0
      currentId: null,
@@ -328,12 +357,14 @@
      tableData: [],
      column: [
        {
          label: "委托编号",
          label: "任务编号",
          prop: "entrustCode",
          width: "160px",
          dataType: "link",
          linkMethod: "selectAllByOne",
        },
        { label: "监控项目", prop: "monitorProject", width: "150px" },
        { label: "计划期限", prop: "dueDate", width: "120px" },
        { label: "样品名称", prop: "sample", width: "160px" },
        {
          label: "下单类别",
@@ -445,6 +476,7 @@
    this.getAuthorizedPerson();
    this.queryParams.userId = this.userId;
    this.queryParams.typeSource = this.typeSource
    this.queryParams.taskSource = this.taskSource
    this.currentTime = getYearAndMonthAndDays();
    this.getDicts("urgency_level").then((response) => {
      this.urgencyLevel = this.dictToValue(response.data);
@@ -464,9 +496,19 @@
      this.inspectionTaskState = this.dictToValue(response.data);
    });
    this.queryParams.typeSource = this.typeSource
    this.queryParams.taskSource = this.taskSource
    this.refreshTable();
  },
  methods: {
    showMonitorRequirement(row) {
      this.monitorRequirement = row
      this.monitorRequirementVisible = true
    },
    openMonitorEvaluation() {
      this.monitorRequirementVisible = false
      this.inspectionEvaluateDialog = true
      this.$nextTick(() => this.$refs.inspectionEvaluateDialog.open(this.monitorRequirement))
    },
    getList() {
      this.tableLoading = true;
      let param = { ...this.queryParams, ...this.page };
@@ -505,7 +547,8 @@
    refreshTable(e) {
      this.page.current = 1;
      this.queryParams.tabLabel = this.tabLabel;
      this.queryParams.typeSource = this.typeSource;
      this.queryParams.taskSource = this.taskSource;
      this.queryParams.typeSource = this.taskSource === 'ENTRUSTED' ? -1 : null;
      this.getList();
    },
    // ä¸‹è½½æŠ¥å‘Š
@@ -576,11 +619,15 @@
    },
    handleTab(m, i) {
      this.tabIndex = i;
      this.typeSource =m.value;
      this.taskSource = m.value;
      this.queryParams.sonLaboratory = "";
      this.refreshTable();
    },
    selectAllByOne(row) {
      if (row.taskSource === 'QUALITY_MONITOR') {
        this.viewInspectInfo(row)
        return
      }
      this.isCopper = row.isCopper;
      this.customsInspection = row;
      this.activeFace = 2;
@@ -647,6 +694,7 @@
          sonLaboratory: this.sonLaboratory,
          state: this.state,
          typeSource: this.typeSource,
          taskSource: row.taskSource,
          orderId: this.orderId
        },
      });
@@ -673,6 +721,7 @@
          sonLaboratory: this.sonLaboratory,
          state: this.state,
          typeSource: this.typeSource,
          taskSource: row.taskSource,
          orderId: this.orderId,
        },
      });
src/views/business/inspectionTask/inspection.vue
@@ -396,7 +396,7 @@
        </div>
        <div class="search_input" style="width: 100%">
          <el-select v-model="verifyUser" clearable filterable placeholder="请选择" size="small" style="width: 100%">
            <el-option v-for="(item, i) in personList" :key="i" :label="item.label" :value="item.value">
            <el-option v-for="(item, i) in reviewerOptions" :key="i" :label="item.label" :value="item.value">
            </el-option>
          </el-select>
        </div>
@@ -554,6 +554,7 @@
      state: null,
      inspectorList: null,
      typeSource: null,
      taskSource: null,
      sagData: [],
      sagForm: {
        sampleCode: null,
@@ -727,6 +728,11 @@
  // ç”¨äºŽä¸Šä¼ æ–‡ä»¶çš„信息
  computed: {
    ...mapGetters(["userId"]),
    reviewerOptions() {
      return this.taskSource === 'QUALITY_MONITOR'
        ? this.personList.filter(item => Number(item.value) !== Number(this.userId))
        : this.personList;
    },
    action() {
      return this.javaApi + "/insOrderPlan/uploadFile";
    },
@@ -831,14 +837,16 @@
  },
  methods: {
    syncRouteContext() {
      const { sonLaboratory, orderId, state, inspectorList, typeSource } = this.$route.query;
      const { sonLaboratory, orderId, state, inspectorList, typeSource, taskSource } = this.$route.query;
      const orderChanged = this.id !== orderId;
      this.sonLaboratory = sonLaboratory;
      this.orderId = orderId;
      this.state = state;
      this.inspectorList = inspectorList;
      this.typeSource = typeSource;
      this.taskSource = taskSource;
      if (orderChanged) {
        if (taskSource === 'QUALITY_MONITOR') this.verifyUser = null;
        this.tableLists = [];
        this.tableList = [];
        this.sampleProduct = [];
@@ -1000,6 +1008,7 @@
        laboratory: this.sonLaboratory,
      }).then(async (res) => {
        this.insOrder = res.data.insOrder;
        this.taskSource = this.insOrder.taskSource || this.taskSource;
        if(res.data.insOrder.ifsOrderType==='02wg'){
          //查询零件属性
          this.getPartProps(res.data.insOrder.ifsInventoryId)
@@ -1759,6 +1768,10 @@
      }
    },
    openAddCheck() {
      if (this.taskSource === 'QUALITY_MONITOR') {
        this.upInsReview(1);
        return;
      }
      this.addCheck = true;
    },
    // æ”¶é›†æ¨¡æ¿çº§æ£€æµ‹æ¡ä»¶çš„缺失项(每个模板都要填全)