gaoluyang
9 小时以前 29be8639dc16b5d82bddc6099b1fa5cdca75f77a
src/views/CNAS/process/ensureResults/qualityControlPlan/index.vue
@@ -25,12 +25,6 @@
      <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;">
            <el-radio-group v-model="yearDetailForm.causeType" @change="getYearDetailPlan" size="small">
              <el-radio-button :value="1">定期监督</el-radio-button>
              <el-radio-button :value="2">动态监督</el-radio-button>
            </el-radio-group>
          </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.supervisePurpose" placeholder="请输入" size="small"
                      @keyup.enter="getYearDetailPlan"></el-input>
@@ -118,33 +112,46 @@
    <!--导入计划-->
    <el-dialog v-model="uploadDia" title="数据导入" width="500px" :close-on-click-modal="false"
      :close-on-press-escape="false">
      <div style="display: flex; align-items: center;">
        <span style="width: 80px">年份:</span>
        <el-date-picker v-model="superviseYear" type="year" value-format="YYYY" clearable size="small" format="YYYY"
          placeholder="选择年">
        </el-date-picker>
        <span style="width: 110px">监督员:</span>
        <el-select v-model="recordUserIds" placeholder="请选择" size="small" @change="splitList" :multiple-limit="2"
          filterable multiple style="width: 100%">
          <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id"></el-option>
        </el-select>
      </div>
      <div style="display: flex;align-items: center;margin: 10px 0">
        <div style="width: 60px">批准人:</div>
        <el-select v-model="ratifyUserId" clearable filterable size="small" style="width: 50%;">
          <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id">
          </el-option>
        </el-select>
      <el-form label-width="70px" size="small">
        <el-form-item label="年份">
          <el-date-picker v-model="superviseYear" type="year" value-format="YYYY" clearable format="YYYY"
            placeholder="选择年" style="width: 100%">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="监督员">
          <el-select v-model="recordUserIds" placeholder="请选择" @change="splitList" :multiple-limit="2"
            filterable multiple style="width: 100%">
            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="批准人">
          <el-select v-model="ratifyUserId" clearable filterable style="width: 100%">
            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px; padding: 8px 12px; border-radius: 4px; background: var(--el-color-primary-light-9); font-size: 13px;">
        <span>第一次导入请先下载模板,按模板格式填写后再上传。</span>
        <el-button link type="primary" @click="downloadTemplate">下载导入模板</el-button>
      </div>
      <div style="margin: 0 auto;">
        <el-upload ref="upload1" :action="action" :auto-upload="false" :file-list="fileList" :headers="uploadHeader"
          :limit="1" accept='.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
          :limit="1" accept=".xls,.xlsx"
          :on-change="beforeUpload" :on-error="onError" :on-success="handleSuccessUp" drag
          :data="{ recordUserIds: recordUserIds1, superviseYear: superviseYear, ratifyUserId: ratifyUserId }"
          name="file">
          <lims-icon name="el-icon-upload"></lims-icon>
          <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
        </el-upload>
      </div>
      <div style="margin-top: 10px; color: var(--el-text-color-secondary); font-size: 12px; line-height: 20px;">
        <div>支持格式:.xls、.xlsx;单个文件不超过10MB。</div>
        <div>监督日期、监控项目、被监督人员为必填项。</div>
        <div>监督日期建议填“年.月”(如 2026.3);填成 2026-03-15 也可以,系统会自动换算为 2026.3。</div>
        <div>被监督人员必须填写系统中已存在的人员姓名,否则整批导入失败。</div>
        <div>导入只读取模板的第一个工作表。</div>
        <div style="color: var(--el-color-warning);">导入后计划为“待批准”:需使用所选批准人账号登录并点击“批准”,批准后才能下发和导出。</div>
      </div>
      <template #footer><span  class="dialog-footer">
        <el-button @click="closeUploadDia">取 消</el-button>
@@ -208,7 +215,7 @@
            } else if (params === 1) {
              return '批准';
            } else {
              return null;
              return '待批准';
            }
          },
          formatType: (params) => {
@@ -217,7 +224,7 @@
            } else if (params === 1) {
              return 'success';
            } else {
              return null;
              return 'warning';
            }
          }
        }, {
@@ -316,8 +323,7 @@
      yearLoading: false,
      yearDetailForm: {
        supervisePurpose: '',
        superviseProject: '',
        causeType: 1
        superviseProject: ''
      },
      yearDetailColumnData: [
        {
@@ -570,13 +576,29 @@
      this.yearPage.size = limit;
      this.getYearPlanList();
    },
    // 下载导入模板
    downloadTemplate() {
      const link = document.createElement('a')
      // 带版本参数避免浏览器继续使用缓存里的旧模板
      link.href = '/import-templates/质量监督计划导入模板.xlsx?v=3'
      link.download = '质量监督计划导入模板.xlsx'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    },
    // 导入流程
    beforeUpload(file) {
      if (!/\.(xls|xlsx)$/i.test(file.name || '')) {
        this.$message.error('请选择 .xls 或 .xlsx 格式的文件');
        this.$refs.upload1.clearFiles()
        return false;
      }
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error('上传文件不超过10M');
        this.$refs.upload1.clearFiles()
        return false;
      }
      return true;
    },
    onError(err, file, fileList) {
      this.$message.error('上传失败')
@@ -585,7 +607,13 @@
    handleSuccessUp(response) {
      this.uploading = false;
      if (response.code == 200) {
        this.$message.success('上传成功');
        const approver = this.userList.find(item => Number(item.id) === Number(this.ratifyUserId))
        const approverName = approver ? approver.name : '所选批准人'
        if (Number(this.ratifyUserId) === Number(this.userId)) {
          this.$message.success('导入成功,请在列表中点击“批准”完成批准,批准后才能下发和导出')
        } else {
          this.$message.success(`导入成功,计划已提交给${approverName}批准;请用该账号登录批准,批准后才能下发和导出`)
        }
        this.recordUserIds = []
        this.superviseYear = ''
        this.fileList = []
@@ -636,7 +664,12 @@
    getUserList() {
      // 质量监督面向全实验室, 人员列表不按部门筛选
      selectUserCondition({ type: 1 }).then((res) => {
        this.userList = res.data || [];
        const list = res.data || []
        // 当前登录用户可能因角色(如 admin)被接口过滤,仍允许选自己作为批准人,避免导入后无人可批准
        if (this.userId && !list.some(item => Number(item.id) === Number(this.userId))) {
          list.unshift({ id: this.userId, name: this.nickName })
        }
        this.userList = list
      })
    },
    // 批准
@@ -747,18 +780,30 @@
      this.getYearDetailPlanList()
    },
    // 获取年度明细表
    // 监督日期统一成 "YYYY.M":兼容 2026-03-15 / 2026/3/15 / 2026年3月15日 等导入写法
    normalizeSuperviseMonth(value) {
      if (!value) return value
      const text = String(value).trim()
      const matched = text.match(/^(\d{4})\s*[./年-]\s*(\d{1,2})(?:\s*[./月-]\s*\d{1,2}\s*日?)?$/)
      if (!matched) return text
      const month = Number(matched[2])
      return month >= 1 && month <= 12 ? `${matched[1]}.${month}` : text
    },
    getYearDetailPlanList() {
      const entity = {
        superviseId: this.superviseId,
        supervisePurpose: this.yearDetailForm.supervisePurpose,
        superviseProject: this.yearDetailForm.superviseProject,
        causeType: this.yearDetailForm.causeType,
      }
      const page = this.yearDetailPage
      this.yearDetailLoading = true
      pageQualitySuperviseDetail({ ...entity, ...page }).then(res => {
        this.yearDetailLoading = false
        this.yearDetailTableData = res.data.records
        // 历史导入的监督日期可能是 2026/3/15、2026-03-15 等完整日期,统一显示成 2026.3
        this.yearDetailTableData = (res.data.records || []).map(item => ({
          ...item,
          superviseTime: this.normalizeSuperviseMonth(item.superviseTime)
        }))
        this.yearDetailPage.total = res.data.total
      }).catch(err => {
        console.log('err---', err);
@@ -779,7 +824,7 @@
    showDialog(type, row) {
      this.formDia = true
      this.$nextTick(() => {
        this.$refs.formDia.openDia(type, row, this.yearDetailForm.causeType)
        this.$refs.formDia.openDia(type, row)
      })
    },
    closeDia() {
@@ -872,7 +917,7 @@
    action() {
      return this.javaApi + '/qualitySupervise/importQualitySupervise'
    },
    ...mapGetters(["userId"]),
    ...mapGetters(["userId", "nickName"]),
  },
};
</script>