吴羡
3 天以前 0a40c5890d13d9f2de5c3ab663876afecbfbefbe
Merge remote-tracking branch 'origin/master'
已修改3个文件
280 ■■■■■ 文件已修改
src/api/structural/laboratory.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/CNAS/process/method/standardMethod/index.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/structural/capabilityAndLaboratory/laboratory/index.vue 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/structural/laboratory.js
@@ -8,6 +8,16 @@
    params: query
  })
}
// 按ID查询资质详情
export function getCertificationById(id) {
  return request({
    url: '/certification/getCertificationById',
    method: 'get',
    params: { id }
  })
}
// 添加资质明细列表
export function addCertificationDetail(query) {
  return request({
@@ -16,6 +26,25 @@
    data: query
  })
}
// 更新资质资料
export function updateCertificationDetail(data) {
  return request({
    url: '/certification/updateCertificationDetail',
    method: 'put',
    data
  })
}
// 更新资质图片
export function updateCertificationImage(data) {
  return request({
    url: '/certification/updateCertificationImage',
    method: 'put',
    data
  })
}
// 删除资质明细列表
export function delCertificationDetail(query) {
  return request({
src/views/CNAS/process/method/standardMethod/index.vue
@@ -65,12 +65,6 @@
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="是否产品标准" prop="isProduct">
          <el-select v-model="addForm.isProduct" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option label="否" :value="0"></el-option>
            <el-option label="是" :value="1"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="是否启用" prop="isUse">
          <el-select v-model="addForm.isUse" size="small" clearable placeholder="请选择" style="width: 100%">
            <el-option label="否" :value="0"></el-option>
@@ -150,26 +144,6 @@
        {label: "标准描述", prop: "name", width: "100px"},
        {label: "备注", prop: "remark"},
        {
          label: "是否产品标准",
          prop: "isProduct",
          width: "100px",
          dataType: "tag",
          formatData: (params) => {
            if (params == 0) {
              return "否";
            } else {
              return "是";
            }
          },
          formatType: (params) => {
            if (params == 0) {
              return "danger";
            } else {
              return "primary";
            }
          },
        },
        {
          label: "是否启用",
          prop: "isUse",
          formatData: (params) => {
@@ -246,9 +220,6 @@
      addRules: {
        code: [{required: true, message: "请输入标准编号", trigger: "blur"}],
        name: [{required: true, message: "请输入标准描述", trigger: "blur"}],
        isProduct: [
          {required: true, message: "请选择是否产品标准", trigger: "change"},
        ],
        isUse: [
          {required: true, message: "请选择是否启用", trigger: "change"},
        ],
src/views/structural/capabilityAndLaboratory/laboratory/index.vue
@@ -3,7 +3,7 @@
    <div>
      <el-form :model="queryParams" ref="queryForm" size="small" :inline="true">
        <el-form-item label="资质名称" prop="name">
          <el-select v-model="queryParams.name" placeholder="选择资质名称" size="small" @change="refreshTable(), list = []">
          <el-select v-model="queryParams.name" placeholder="选择资质名称" size="small" @change="handleQuery">
            <el-option v-for="dict in dict.type.cnas_method_qualification" :key="dict.value" :label="dict.label"
              :value="dict.value">
              {{ dict.label }}
@@ -11,7 +11,7 @@
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" @click="refreshTable">查询</el-button>
          <el-button type="primary" size="small" @click="handleQuery">查询</el-button>
          <el-button size="small" @click="refresh">重置</el-button>
        </el-form-item>
      </el-form>
@@ -25,7 +25,7 @@
          </el-radio-group>
        </el-col>
        <el-col :span="12" style="text-align: right" v-if="radio === 0">
          <el-button size="small" type="primary" @click="openAdd">资质更新</el-button>
          <el-button size="small" type="primary" @click="openAdd">资质新增</el-button>
          <el-button size="small" :icon="$icon('el-icon-delete')" @click="handleDel">删除</el-button>
        </el-col>
      </el-row>
@@ -37,7 +37,7 @@
    </div>
    <div class="table" v-if="radio === 1" v-loading="pageLoading" @scroll="scrollFn">
      <el-row :gutter="16">
        <el-col :span="8" v-for="(m, i) in list" :key="i" :xs="24" :sm="12" :md="8" :lg="8" :xl="6"
        <el-col :span="8" v-for="m in list" :key="m.id" :xs="24" :sm="12" :md="8" :lg="8" :xl="6"
          style="margin-bottom: 16px">
          <div class="table-item">
            <el-image style="
@@ -45,7 +45,7 @@
                height: 102px;
                margin-right: 20px;
                border-radius: 16px;
              " :src="javaApi + '/img/' + m.imageUrl">
              " :src="getImageUrl(m.imageUrl)">
              <template #error><div  class="image-error" style="
                  width: 100px;
                  height: 100px;
@@ -69,6 +69,15 @@
                <el-tag :type="m.state === 0 ? 'danger' : 'success'" size="small">{{ m.state === 0 ? "失效" : "有效"
                  }}</el-tag>
              </p>
              <el-upload :action="uploadAction" :headers="headers" :show-file-list="false"
                :disabled="!!overviewUploading[m.id]"
                accept="image/jpg,image/jpeg,image/png" :before-upload="file => beforeOverviewImageUpload(file, m)"
                :on-success="response => handleOverviewImageSuccess(response, m)"
                :on-error="() => handleOverviewImageError(m.id)">
                <el-button link type="primary" size="small" :loading="!!overviewUploading[m.id]">
                  {{ m.imageUrl ? "更换图片" : "上传图片" }}
                </el-button>
              </el-upload>
            </div>
          </div>
        </el-col>
@@ -89,7 +98,7 @@
          style="display: flex; margin: 0 auto; color: var(--lims-text-3)">已经没有更多啦~</el-button>
      </div>
    </div>
    <el-dialog title="资质更新" v-model="qualificationsConnectVisible" width="400px">
    <el-dialog :title="dialogTitle" v-model="qualificationsConnectVisible" width="400px" @closed="resetDialog">
      <el-form ref="formDataRef" :model="formData" label-position="right" :rules="formDataRules" label-width="78px">
        <el-form-item label="资质名称" prop="name">
          <el-select v-model="formData.name" placeholder="请选择" style="width: 100%" size="small" clearable>
@@ -121,21 +130,26 @@
        <el-form-item label="资质图片">
          <el-upload ref="upload" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'imageUrl')"
            accept="image/jpg,image/jpeg,image/png" :multiple="false" :limit="1" :headers="headers"
            :on-change="beforeUpload" :on-error="onError">
            :show-file-list="false" :before-upload="beforeFormImageUpload" :on-error="() => onError('imageUrl')">
            <template #trigger><el-button  size="small" type="primary">选取图片</el-button></template>
          </el-upload>
          <el-image v-if="formData.imageUrl" class="qualification-preview" :src="getImageUrl(formData.imageUrl)" fit="cover" />
        </el-form-item>
        <el-form-item label="资质附件">
          <el-upload ref="upload1" :action="uploadAction" :on-success="(m) => handleSuccessUpImg(m, 'fileUrl')"
            accept="image/jpg,image/jpeg,image/png,application/pdf,.doc,.docx" :headers="headers" :multiple="false"
            :limit="1" :on-change="beforeUpload1" :on-error="onError1">
            :limit="1" :show-file-list="false" :before-upload="beforeFormFileUpload" :on-error="() => onError('fileUrl')">
            <template #trigger><el-button  size="small" type="primary">选取文件</el-button></template>
          </el-upload>
          <el-button v-if="formData.fileUrl" link type="primary" size="small" @click="handleDownLoad(formData)">
            已有附件:{{ getFileName(formData.fileUrl) }}
          </el-button>
        </el-form-item>
      </el-form>
      <template #footer><span  class="dialog-footer">
        <el-button @click="qualificationsConnectVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmQualifications" :loading="loading">确 定</el-button>
        <el-button type="primary" @click="confirmQualifications" :loading="loading"
          :disabled="imageUploading || fileUploading">确 定</el-button>
      </span></template>
    </el-dialog>
  </div>
@@ -146,7 +160,10 @@
import {
  addCertificationDetail,
  delCertificationDetail,
  getCertificationById,
  getCertificationDetail,
  updateCertificationDetail,
  updateCertificationImage,
} from "@/api/structural/laboratory";
import { getToken } from "@/utils/auth";
@@ -177,6 +194,13 @@
          label: "操作",
          operation: [
            {
              name: "资质更新",
              type: "text",
              clickFun: (row) => {
                this.openEdit(row);
              },
            },
            {
              name: "附件下载",
              type: "text",
              clickFun: (row) => {
@@ -194,6 +218,7 @@
      tableLoading: false,
      qualificationsList: [],
      qualificationsConnectVisible: false,
      dialogTitle: "资质新增",
      formData: {},
      formDataRules: {
        name: [
@@ -211,6 +236,10 @@
        ],
      },
      loading: false,
      imageUploading: false,
      fileUploading: false,
      overviewUploading: {},
      scrollHandler: null,
      pageLoading: false,
      isLoding: false, // 加载中,loading图标,默认为true
      finishLoding: false, // 加载完成,显示已经没有更多了
@@ -223,14 +252,32 @@
    };
  },
  mounted() {
    this.scrollHandler = this.throttle(this.scrollFn.bind(this), 200);
    window.addEventListener("scroll", this.scrollHandler);
    this.refreshTable();
  },
  methods: {
    selectorSwitch(radio) {
      if (radio === 1) {
        this.list = [];
        this.reloadOverview();
      } else {
        this.page.current = 1;
        this.refreshTable();
      }
    },
    handleQuery() {
      if (this.radio === 0) {
        this.page.current = 1;
        this.refreshTable();
      } else {
        this.reloadOverview();
      }
    },
    reloadOverview() {
      this.currentPage = 1;
      this.list = [];
      this.finishLoding = false;
      this.refreshTable();
    },
    refreshTable() {
      if (this.radio === 0) {
@@ -251,12 +298,6 @@
          this.isLoding = true;
        } else {
          this.pageLoading = true;
        }
        if (this.list.length === 0) {
          window.addEventListener(
            "scroll",
            this.throttle(this.scrollFn, 20000)
          );
        }
        getCertificationDetail({
          current: this.currentPage,
@@ -290,16 +331,13 @@
    },
    // 重置
    refresh() {
      this.queryParams.name = "";
      if (this.radio === 0) {
        this.queryParams.name = "";
        this.page.size = 10;
        this.page.current = 1;
        this.refreshTable();
      } else {
        this.finishLoding = false;
        this.currentPage = 1;
        this.list = [];
        this.refreshTable();
        this.reloadOverview();
      }
    },
    // 表格多选
@@ -307,6 +345,7 @@
      this.selection = selection;
    },
    pagination(page) {
      this.page.current = page.page;
      this.page.size = page.limit;
      this.refreshTable();
    },
@@ -335,57 +374,140 @@
      this.$download.saveAs(row.fileUrl, row.fileUrl);
    },
    openAdd() {
      this.qualificationsConnectVisible = true;
      this.$nextTick(() => {
        this.$refs.upload.clearFiles();
        this.$refs.upload1.clearFiles();
      });
      this.dialogTitle = "资质新增";
      this.formData = {};
      this.qualificationsConnectVisible = true;
      this.clearUploadFiles();
    },
    openEdit(row) {
      this.dialogTitle = "资质更新";
      this.loading = true;
      getCertificationById(row.id).then((res) => {
        if (res.code !== 200 || !res.data) return;
        this.formData = { ...res.data };
        this.qualificationsConnectVisible = true;
        this.clearUploadFiles();
      }).finally(() => {
        this.loading = false;
      });
    },
    resetDialog() {
      this.formData = {};
      this.dialogTitle = "资质新增";
      this.imageUploading = false;
      this.fileUploading = false;
      this.clearUploadFiles();
      this.$refs.formDataRef?.clearValidate();
    },
    clearUploadFiles() {
      this.$nextTick(() => {
        this.$refs.upload?.clearFiles();
        this.$refs.upload1?.clearFiles();
      });
    },
    handleSuccessUpImg(response, name) {
      if (response.code === 200) {
      this.setFormUploadState(name, false);
      if (response && response.code === 200 && response.data && response.data.url) {
        this.formData[name] = response.data.url;
        this.$message.success(name === 'imageUrl' ? "图片上传成功" : "附件上传成功");
        this.clearUploadFiles();
      } else {
        this.$message.error("上传失败");
      }
    },
    beforeUpload(file) {
    validateImage(file) {
      const allowed = ["image/jpeg", "image/png"];
      if (!allowed.includes(file.type)) {
        this.$message.error("仅支持JPG、JPEG、PNG图片");
        return false;
      }
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error("上传文件不超过10M");
        this.$refs.upload.clearFiles();
        return false;
      } else {
        return true;
      }
      return true;
    },
    onError(err, file, fileList) {
      this.$message.error("上传失败");
      this.$refs.upload.clearFiles();
    beforeFormImageUpload(file) {
      const valid = this.validateImage(file);
      this.imageUploading = valid;
      return valid;
    },
    beforeUpload1(file) {
    beforeFormFileUpload(file) {
      const extension = (file.name.split('.').pop() || '').toLowerCase();
      const allowed = ["jpg", "jpeg", "png", "pdf", "doc", "docx"];
      if (!allowed.includes(extension)) {
        this.$message.error("仅支持JPG、JPEG、PNG、PDF、DOC、DOCX文件");
        return false;
      }
      if (file.size > 1024 * 1024 * 10) {
        this.$message.error("上传文件不超过10M");
        this.$refs.upload1.clearFiles();
        return false;
      } else {
        return true;
      }
      this.fileUploading = true;
      return true;
    },
    onError1(err, file, fileList) {
    setFormUploadState(name, value) {
      if (name === 'imageUrl') this.imageUploading = value;
      if (name === 'fileUrl') this.fileUploading = value;
    },
    onError(name) {
      this.setFormUploadState(name, false);
      this.$message.error("上传失败");
      this.$refs.upload1.clearFiles();
      this.clearUploadFiles();
    },
    beforeOverviewImageUpload(file, row) {
      const valid = this.validateImage(file);
      if (valid) this.overviewUploading[row.id] = true;
      return valid;
    },
    handleOverviewImageSuccess(response, row) {
      if (!response || response.code !== 200 || !response.data || !response.data.url) {
        this.overviewUploading[row.id] = false;
        this.$message.error("图片上传失败");
        return;
      }
      const imageUrl = response.data.url;
      updateCertificationImage({ id: row.id, imageUrl }).then((res) => {
        if (res.code !== 200) return;
        row.imageUrl = imageUrl;
        this.$message.success("图片更新成功");
      }).finally(() => {
        this.overviewUploading[row.id] = false;
      });
    },
    handleOverviewImageError(id) {
      this.overviewUploading[id] = false;
      this.$message.error("图片上传失败");
    },
    getImageUrl(imageUrl) {
      if (!imageUrl) return "";
      if (/^https?:\/\//i.test(imageUrl)) return imageUrl;
      if (imageUrl.startsWith('/')) return this.javaApi + imageUrl;
      return this.javaApi + '/img/' + imageUrl;
    },
    getFileName(fileUrl) {
      if (!fileUrl) return "";
      return fileUrl.split(/[\\/]/).pop();
    },
    confirmQualifications() {
      if (this.imageUploading || this.fileUploading) {
        this.$message.warning("请等待文件上传完成");
        return;
      }
      this.$refs["formDataRef"].validate((valid) => {
        if (valid) {
          this.loading = true;
          addCertificationDetail({ ...this.formData })
          const submit = this.dialogTitle === "资质新增"
            ? addCertificationDetail
            : updateCertificationDetail;
          submit({ ...this.formData })
            .then((res) => {
              this.loading = false;
              if (res.code !== 200) return;
              this.$message.success("已提交");
              this.refreshTable();
              this.resetForm("formDataRef");
              this.qualificationsConnectVisible = false;
              this.handleQuery();
            })
            .catch((err) => {
            .finally(() => {
              this.loading = false;
            });
        }
@@ -428,7 +550,7 @@
    },
  },
  unmounted() {
    window.removeEventListener("scroll", this.throttle(), false);
    if (this.scrollHandler) window.removeEventListener("scroll", this.scrollHandler);
  },
};
</script>
@@ -450,4 +572,12 @@
  align-items: center;
  justify-content: space-between;
}
.qualification-preview {
  width: 72px;
  height: 72px;
  margin-left: 10px;
  border-radius: 8px;
  vertical-align: middle;
}
</style>