研发图纸文件管理系统-前端项目
he wei
2024-12-03 98ff6711d7fb3d4b37846d62a20bcd5c09e25d07
src/pages/resourceManage/product/list.vue
@@ -29,14 +29,28 @@
              onChange: onPageChange,
              onShowSizeChange: onSizeChange,
            }"
            :rowClassName="rowClassFn"
          >
            <template slot="dataIndex" slot-scope="{ index }">
              {{ index + 1 }}
            </template>
            <template slot="title">
              <a-space class="operator">
                <span class="title">产品中心</span>
                <a-button v-if="canUploadBom" type="primary" @click="uploadBom"
                  >新增</a-button
                >
                <a-button type="primary" @click="prodDiff">产品比较</a-button>
                <a-button type="primary" @click="ownerDownloadLog"
                  >我的锁定记录</a-button
                >
              </a-space>
            </template>
            <template slot="enabled" slot-scope="{ record }">
              {{ record.enabled == -1 ? "是" : "否" }}
            </template>
            <template slot="enabled1" slot-scope="{ record }">
              {{ record.enabled == 1 ? "可用" : "不可用" }}
            </template>
            <template slot="isNormal" slot-scope="{ record }">
              {{ record.customCode == "" ? "是" : "否" }}
@@ -46,21 +60,31 @@
                <a @click="upload(record)">上传软件</a>
                <a-divider type="vertical"></a-divider>
              </template> -->
              <a @click="viewLog(record)">日志</a>
              <a @click="viewLog(record)">状态日志</a>
              <a-divider type="vertical"></a-divider>
              <a @click="goDetails(record)">详情</a>
              <a-divider type="vertical"></a-divider>
              <a-popover title="" trigger="hover">
                <a-space direction="vertical" slot="content">
                <a-space class="btn-grp" direction="vertical" slot="content">
                  <!-- TODO -->
                  <a-button
                    :disabled="record.version == -1"
                    v-if="isTester && record.enabled != 1"
                    type="primary"
                    @click="unLock(record)"
                    >解锁</a-button
                  >
                  <a-button type="primary" @click="downloadLog(record)"
                    >下载日志</a-button
                  >
                  <a-button
                    :disabled="record.version != 1"
                    type="primary"
                    @click="edit(record)"
                    >编辑</a-button
                  >
                  <a-button
                    v-if="canDownloadBom"
                    :disabled="record.version == -1"
                    :disabled="record.version == -1 && !isTester"
                    type="primary"
                    @click="checkLock(record)"
                    >下载</a-button
@@ -72,6 +96,25 @@
                    @click="showCustom(record)"
                    >定制</a-button
                  >
                  <a-button
                    type="primary"
                    v-if="canFeedback"
                    @click="showFeedback(record)"
                    >反馈</a-button
                  >
                  <a-badge
                    :count="record.ecrList.length"
                    showZero
                    :number-style="{
                      backgroundColor: record.ecrList.length > 0 ? '#090' : '#900',
                    }"
                  >
                    <a-button
                      type="primary"
                      @click="showEcrlist(record)"
                      >ecr记录</a-button
                      >
                  </a-badge>
                </a-space>
                <a>更多</a>
              </a-popover>
@@ -245,6 +288,38 @@
        <a-tab-pane key="2" tab="差异">
          <diff-list :list="diffData"></diff-list>
        </a-tab-pane>
        <a-tab-pane key="3" :tab="abLabel">
          <a-table
            ref="aTable"
            size="small"
            :scroll="{ y: 700 }"
            bordered
            :columns="abTbl.columns"
            :data-source="abTbl.dataSource"
            :pagination="false"
            rowKey="subCode"
          ></a-table>
          <div style="text-align: right; padding: 8px">
            <a-button
              @click="abTbl.ignore = true"
              :type="abState ? 'danger' : 'primary'"
              :icon="abState ? 'question' : 'check'"
              >{{ abState ? "未确认" : "已确认" }}</a-button
            >
          </div>
        </a-tab-pane>
        <a-tab-pane key="4" :tab="errorLabel">
          <a-table
            ref="aTable"
            size="small"
            :scroll="{ y: 700 }"
            bordered
            :columns="errorTbl.columns"
            :data-source="errorTbl.dataSource"
            :pagination="false"
            rowKey="subCode"
          ></a-table>
        </a-tab-pane>
      </a-tabs>
      <prod-upload
        class="mt8"
@@ -288,7 +363,9 @@
            <div>
              <span class="user">{{ item.owner }}</span> 在
              <span class="time">{{ item.createTime }}</span>
              {{ item.lockFlag ? "锁定" : "激活" }}了版本
              {{
                { "-1": "上传", "0": "激活", "1": "锁定" }[item.lockFlag]
              }}了版本
              <span class="version">{{ item.versionTime }}</span>
            </div>
            <div>操作原因: {{ item.reason ? item.reason : "无" }}</div>
@@ -322,7 +399,7 @@
      </template>
      <!-- 其他附件中存在锁定文件 -->
      <template v-if="otherLockList.length">
        <div class="table-title"> 其他附件中存在锁定文件</div>
        <div class="table-title">其他附件中存在锁定文件</div>
        <a-table
          size="small"
          :scroll="{ y: 150 }"
@@ -335,6 +412,115 @@
        ></a-table>
      </template>
    </a-modal>
    <a-modal
      :visible="feedbackShow"
      :width="800"
      title="问题反馈"
      :destroyOnClose="true"
      :footer="false"
      @cancel="feedbackCancel"
    >
      <feedback-form
        :prod-data="customProd"
        @cancel="feedbackCancel"
        @ok="feedbackOk"
      ></feedback-form>
    </a-modal>
    <!-- ecr列表 -->
    <a-modal
      :visible="ecrListVisible"
      :width="800"
      title="ecr记录"
      :destroyOnClose="true"
      @cancel="ecrListCancel"
    >
      <div class="footer" slot="footer">
        <a-button type="primary" @click="ecrListCancel">关闭</a-button>
      </div>
      <div class="ecr-content">
        <a-table
          ref="aTable"
          size="small"
          :scroll="{ y: 700 }"
          bordered
          :columns="ecrColumns"
          :data-source="ecrList"
          :pagination="false"
          rowKey="id"
        >
          <template slot="changeDesc" slot-scope="text, record">
            <a-tooltip placement="topLeft">
              <template slot="title">
                {{ record.changeDescription }}
              </template>
              {{ record.changeDescription }}
            </a-tooltip>
          </template>
        </a-table>
      </div>
    </a-modal>
    <a-modal
      :visible="errorVisible"
      :footer="null"
      :width="1200"
      title="名称或型号命名不规范"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="errorVisible = false"
    >
      <a-table
        ref="aTable"
        size="small"
        :scroll="{ y: 500 }"
        bordered
        :columns="errorTbl2.columns"
        :data-source="errorTbl2.dataSource"
        :pagination="false"
        rowKey="num"
      ></a-table>
    </a-modal>
    <!-- 操作原因 -->
    <a-modal
      :visible="reasonVisible"
      :width="460"
      title="操作原因"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="reasonCancel"
      @ok="reasonOk"
    >
      <a-form-model-item ref="name" label="操作原因">
        <a-input
          type="textarea"
          v-model="reason"
          placeHolder="请输入操作原因"
        />
      </a-form-model-item>
    </a-modal>
    <download-reason
      :reason-visible.sync="downloadReasonVisible"
      v-if="downloadReasonVisible"
      @ok="downloadReasonOk"
    ></download-reason>
    <download-logs
      :visible.sync="downloadlogVisible"
      v-if="downloadlogVisible"
      :type="12"
      :oprate-info="oprateInfo"
    ></download-logs>
    <a-modal
      :visible="ownerLogVisible"
      title="我的下载记录"
      width="100%"
      :destroyOnClose="true"
      @cancel="ownerLogClose"
      wrapClassName="full-modal"
    >
      <owner-download></owner-download>
      <template v-slot:footer>
        <a-button @click="ownerLogClose">关闭</a-button>
      </template>
    </a-modal>
  </div>
</template>
@@ -343,9 +529,27 @@
import ChangeParts from "./changeParts";
import ProdUpload from "./prodUpload";
import DrawUpload from "@/pages/components/drawUpload";
import DownloadReason from "@/pages/components/downloadReason";
import DownloadLogs from "@/pages/components/downloadLogs";
import getWebUrl from "@/assets/js/tools/getWebUrl";
import { addProduct, downloadBom, getAllProducts, getLogList, getLockedList } from "./apis";
import {
  addProduct,
  downloadBom,
  getAllProducts,
  getLogList,
  getLockedList,
  setpHistoryEnable,
} from "./apis";
import {
  searchDefaultMailUser,
  sendMail,
} from "../../components/emailCard/apis";
import { getUserList } from "../../permission/apis";
import { getRoleUser } from "@/pages/user/apis";
import { submitFeedback } from "@/pages/workplace/apis";
import { productSoftwareSubmit } from "../software/apis";
import { zipParse } from "@/pages/workplace/myDraw/apis";
import { mapGetters } from "vuex";
@@ -354,18 +558,111 @@
import createWs from "@/assets/js/websocket";
import DiffList from "@/pages/components/diffList";
import ApiTable from '../../../components/table/api/ApiTable.vue';
import FeedbackForm from "../components/feedbackForm.vue";
import OwnerDownload from "../components/ownerDownload";
const WSMixin = createWs("product");
export default {
  name: "",
  mixins: [WSMixin],
  data() {
    const abColumns = [
      {
        title: "子件编码",
        dataIndex: "subCode",
        width: 120,
        align: "center",
      },
      {
        title: "子件名称",
        dataIndex: "subName",
        align: "center",
        ellipsis: true,
      },
      {
        title: "子件型号",
        dataIndex: "subModel",
        align: "center",
        ellipsis: true,
      },
    ];
    const errorColumns = [
      {
        title: "子件编码",
        dataIndex: "subCode",
        width: 120,
        align: "center",
      },
      {
        title: "子件名称",
        dataIndex: "subName",
        align: "center",
        ellipsis: true,
      },
      {
        title: "子件型号",
        dataIndex: "subModel",
        align: "center",
        ellipsis: true,
      },
    ];
    const ecrColumns = [
      {
        title: "流水号",
        dataIndex: "number",
        width: 120,
        align: "center",
      },
      {
        title: "申请人",
        dataIndex: "proposer",
        align: "center",
        ellipsis: true,
      },
      {
        title: "申请日期",
        dataIndex: "proposeWebsocket",
        align: "center",
        ellipsis: true,
      },
      {
        title: "创建时间",
        dataIndex: "createTime",
        width: 120,
        align: "center",
      },
      {
        title: "处理方式",
        dataIndex: "solution",
        align: "center",
        ellipsis: true,
      },
      {
        title: "变更原因",
        dataIndex: "changeDescription",
        align: "center",
        ellipsis: true,
        scopedSlots: { customRender: "changeDesc" },
      },
    ];
    return {
      ownerLogVisible: false,
      reason: "",
      reasonVisible: false,
      oprateInfo: "",
      downloadlogVisible: false,
      tester: [],
      downloadReasonVisible: false,
      curObj: null,
      errorVisible: false,
      ecrColumns,
      feedbackShow: false,
      lockListVisible: false,
      currentObj: null,
      bomLockList: [],
      otherLockList: [],
      ecrList: [],
      ecrListVisible: false,
      logVisible: false,
      logList: [],
      fromProd: undefined,
@@ -388,6 +685,8 @@
      },
      prodData: {},
      userList: [],
      userListAll: [],
      mailList: [],
      file: null,
      // title: "",
      fileUrl: "",
@@ -409,6 +708,16 @@
      webUrl: getWebUrl(),
      conditions: {},
      columns: [
        {
          fixed: "left",
          title: "序号",
          dataIndex: "dataIndex",
          key: "dataIndex",
          align: "center",
          width: 60,
          noSearch: true,
          scopedSlots: { customRender: "dataIndex" },
        },
        {
          title: "编号",
          dataIndex: "parentCode",
@@ -450,6 +759,24 @@
          width: 100,
          scopedSlots: { customRender: "isNormal" },
        },
        {
          title: "待复核",
          dataIndex: "enabled",
          dataType: "boolean",
          align: "center",
          searchAble: true,
          width: 100,
          scopedSlots: { customRender: "enabled" },
        },
        {
          title: "是否可用",
          dataIndex: "enabled1",
          dataType: "boolean",
          align: "center",
          searchAble: false,
          width: 100,
          scopedSlots: { customRender: "enabled1" },
        },
        // {
        //   title: "创建时间",
        //   dataIndex: "createTime",
@@ -485,6 +812,40 @@
        },
      ],
      dataSource: [],
      abTbl: {
        ignore: false,
        columns: abColumns,
        dataSource: [],
      },
      errorTbl: {
        columns: errorColumns,
        dataSource: [],
      },
      errorTbl2: {
        columns: [
          {
            title: "子件编码",
            dataIndex: "subCode",
            align: "center",
          },
          {
            title: "子件型号",
            dataIndex: "subModel",
            align: "center",
          },
          {
            title: "子件名称",
            dataIndex: "subName",
            align: "center",
          },
          {
            title: "问题描述",
            dataIndex: "irregularDesc",
            align: "center",
          },
        ],
        dataSource: [],
      },
      bomLockColumns: [
        {
          title: "子件名称",
@@ -500,7 +861,7 @@
          title: "锁定说明",
          dataIndex: "localReason",
          align: "center",
        }
        },
      ],
      otherLockColumns: [
        {
@@ -512,8 +873,8 @@
          title: "锁定说明",
          dataIndex: "localReason",
          align: "center",
        }
      ]
        },
      ],
    };
  },
  components: {
@@ -521,9 +882,117 @@
    ChangeParts,
    ProdUpload,
    DrawUpload,
    DiffList
    DiffList,
    FeedbackForm,
    DownloadReason,
    DownloadLogs,
    OwnerDownload,
  },
  methods: {
    rowClassFn(record) {
      let classList = [];
      if (record.enabled == -1) {
        classList.push("locked");
      }
      if (record.enabled == 0) {
        classList.push("unable");
      }
      return classList;
    },
    unLock(obj) {
      this.curObj = obj;
      this.reasonVisible = true;
    },
    reasonCancel() {
      this.reasonVisible = false;
    },
    reasonOk() {
      let {
        curObj: {
          customCode,
          parentCode,
          version,
          versionTime,
          enabled: lockFlagNow,
        },
        reason,
      } = this;
      let enabled = 1;
      setpHistoryEnable({
        customCode,
        parentCode,
        enabled,
        version,
        reason,
        versionTime,
      }).then((res) => {
        let { code, data } = res.data;
        if (code && data) {
          this.$message.success("操作成功");
          this.sendMessage();
          this.reasonVisible = false;
          // 如果是测试人员解锁确认 则自动发送邮件
          if (lockFlagNow == -1 && this.isTester) {
            this.sendEmail();
          }
        } else {
          this.$message.error("操作失败");
        }
      });
    },
    sendEmail() {
      let { title, content } = this.handleEmailShow(this.curObj, true);
      let params = { mailList: this.mailList, title, content };
      sendMail(params);
    },
    searchAllUserList() {
      getUserList()
        .then((res) => {
          let rs = res.data;
          if (rs.code && rs.data) {
            this.userListAll = rs.data2;
            this.searchDefaultMailUser();
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    searchDefaultMailUser() {
      //  type为3
      let type = 3;
      searchDefaultMailUser(type).then((res) => {
        let rs = res.data;
        let data = [];
        if (rs.code === 1) {
          data = rs.data.map((item) => {
            return item.user;
          });
        }
        this.mailList = this.userListAll
          .filter((o) => data.includes(o.name) && o.mail)
          .map((item) => {
            return item.mail;
          });
      });
    },
    handleEmailShow(record, get) {
      let title =
        "[产品发布记录]" + record.parentModel + " 版本:" + record.versionTime;
      let content = [];
      content.push("物料编码: " + record.parentCode);
      content.push("物料名称: " + record.parentName);
      content.push("规格型号: " + record.parentModel);
      content.push("标准机型: " + (!record.customCode ? "是" : "否"));
      content.push("定制单号: " + (record.customCode || "无"));
      content.push("版本时间: " + record.versionTime);
      if (get) {
        return {
          title,
          content: content.join("\n"),
        };
      }
    },
    onSearch(conditions, searchOptions) {
      // console.log(conditions);
      // console.log(searchOptions);
@@ -551,10 +1020,13 @@
    },
    goDetails(record) {
      // console.log(record);
      const { parentCode, customCode, parentModel } = record;
      const { parentCode, customCode, parentModel, parentName } = record;
      let is0120 = /^0120/.test(parentCode);
      this.$router.push({
        path: "/resource/product-details",
        query: { parentCode, customCode, parentModel },
        path: is0120
          ? "/resource/product-details-0120"
          : "/resource/product-details",
        query: { parentCode, customCode, parentModel, parentName },
      });
    },
    searchData(res) {
@@ -564,7 +1036,12 @@
        let data = [];
        let total = 0;
        if (res.code && res.data) {
          data = res.data2.list;
          data = res.data2.list.map((v) => {
            if ("" != v.customCode) {
              v.ecrList = [];
            }
            return v;
          });
          total = res.data2.total;
        }
        this.dataSource = data;
@@ -575,13 +1052,15 @@
      }
    },
    edit(obj) {
      console.log(obj, 99);
      // console.log(obj, 99);
      this.editObj = obj;
      this.editShow = true;
    },
    checkLock(obj) {
      let loading = this.$layer.loading({ shade: true });
      getLockedList(obj.id).then((res) => {
        const {code, data, data2, data3} = res.data;
        const { code, data, data2, data3 } = res.data;
        this.$layer.close(loading);
        if (code) {
          if (data) {
            // 有锁定
@@ -591,10 +1070,10 @@
            this.lockListVisible = true;
          } else {
            // 没有锁定
            this.download(obj);
            this.showReason(obj);
          }
        } else {
          this.$message.error('查询锁定清单出错');
          this.$message.error("查询锁定清单出错");
        }
      });
    },
@@ -603,17 +1082,29 @@
    },
    lockListOk() {
      this.lockListVisible = false;
      this.download(this.currentObj);
      this.showReason(this.currentObj);
    },
    download(obj) {
      const { id, version } = obj;
      downloadBom(id, version).then((res) => {
    showReason(obj) {
      this.curObj = obj;
      this.downloadReasonVisible = true;
    },
    downloadReasonOk(reason) {
      this.download(reason);
    },
    download(reason) {
      const { id, version, parentCode, customCode } = this.curObj;
      let oprateInfo = parentCode + "_" + customCode;
      let loading = this.$layer.loading({ shade: true });
      downloadBom(id, version, reason, oprateInfo).then((res) => {
        // console.log(res, "===========");
        this.$layer.close(loading);
        let { headers, data, status } = res;
        if (200 == status && data) {
          let url = window.URL.createObjectURL(data);
          const matchRes = /filename=(.*)/.exec(headers["content-disposition"]);
          const fileName = matchRes ? matchRes[1].trim() : "未知文件名.zip";
          const fileName = matchRes
            ? decodeURI(matchRes[1].trim())
            : "未知文件名.zip";
          let link = document.createElement("a");
          link.style.display = "none";
          link.href = url;
@@ -653,9 +1144,11 @@
          const formData = new FormData();
          formData.append("multipartFile", this.file);
          formData.append("mainDTOString", JSON.stringify(obj));
          let loading = this.$layer.loading({ shade: true });
          productSoftwareSubmit(formData)
            .then((res) => {
              // this.$layer.close(loadinobjobj
              this.$layer.close(loading);
              let rs = res.data;
              if (rs.code == 1 && rs.data) {
                this.resList = rs.data2;
@@ -667,7 +1160,7 @@
              }
            })
            .catch((error) => {
              // this.$layer.close(loading);
              this.$layer.close(loading);
              console.log(error);
            });
        }
@@ -714,21 +1207,29 @@
      }
      const { pageCurr, pageSize, conditions, columns } = this;
      let params = {};
      let col, index;
      Object.keys(conditions).forEach((v) => {
        switch (v) {
          case "isNormal":
            if (conditions[v]) {
              params["customCode"] = "";
              columns.forEach((val) => {
              columns.forEach((val, idx) => {
                if (val.dataIndex == "customCode") {
                  val.search.value = "";
                  col = { ...val, search: { value: "", backup: "" } };
                  index = idx;
                }
              });
              this.$set(this.columns, index, col);
            }
            break;
          case "customCode":
            if (params["customCode"] == undefined) {
              params[v] = conditions[v];
            }
            break;
          case "enabled":
            if (conditions[v]) {
              params[v] = -1;
            }
            break;
          default:
@@ -760,6 +1261,11 @@
      this.prodUploadShow = false;
    },
    submit(data) {
      if (this.submitState.code) {
        this.$layer.msg(this.submitState.msg);
        return;
      }
      let loading = this.$layer.loading();
      // console.log(data);
      const { parentCode, parentModel, parentName, bomList } = this.resList;
      const param = {
@@ -773,8 +1279,9 @@
        parentName,
      };
      addProduct(param).then((res) => {
        const { code, msg } = res.data;
        if (code) {
        const { code, data, msg } = res.data;
        this.$layer.close(loading);
        if (code && data) {
          this.$message.success(msg);
          this.prodUploadShow = false;
        } else {
@@ -786,6 +1293,55 @@
      this.customProd = obj;
      this.customShow = true;
    },
    showFeedback(obj) {
      this.customProd = obj;
      this.feedbackShow = true;
    },
    feedbackCancel() {
      this.feedbackShow = false;
    },
    feedbackOk(data) {
      let {
        content,
        multipartFile,
        productId,
        receiverIds,
        receiverNames,
        senderId,
        subVersion,
      } = data;
      let loading = this.$layer.loading({ shade: true });
      const formData = new FormData();
      multipartFile.forEach((v) => {
        formData.append("multipartFileList", v);
      });
      formData.append(
        "feedbackJson",
        JSON.stringify({
          content,
          productId,
          receiverIds,
          receiverNames,
          senderId,
          subVersion,
        })
      );
      submitFeedback(formData).then((res) => {
        let { code, data } = res.data;
        if (code && data) {
          this.$message.success("反馈成功");
          this.feedbackShow = false;
          this.$layer.close(loading);
          this.flag = 0;
          this.page = 1;
          this.searchData();
        } else {
          this.$layer.close(loading);
          this.$message.error("反馈失败");
        }
      });
    },
    custom(data) {
      const { id, parentCode, parentModel, parentName } = this.customProd;
      const param = {
@@ -796,13 +1352,16 @@
        parentModel,
        parentName,
      };
      let loading = this.$layer.loading({ shade: true });
      addProduct(param).then((res) => {
        const { code, msg } = res.data;
        if (code) {
          this.$message.success(msg);
          this.$layer.close(loading);
          this.customShow = false;
        } else {
          this.$message.error(msg);
          this.$layer.close(loading);
        }
      });
    },
@@ -837,30 +1396,78 @@
          }))[0];
        formData.append("baseStr", JSON.stringify(prod));
      }
      zipParse(formData)
        .then((res) => {
          this.$layer.close(loading);
          let { code, data, data2, data3, msg } = res.data;
          if (code && data) {
            this.resList = data2;
            this.diffData = {
              addList: data3.addList,
              delList: data3.deleteList.map((v) => v.materialObj),
              updateList: data3.diffList,
            };
            this.fileUrl = msg;
            this.prodUploadShow = true;
            this.$message.success("解析成功");
          } else {
            this.$message.error(msg);
          }
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
      this.$nextTick(() => {
        zipParse(formData)
          .then((res) => {
            this.$layer.close(loading);
            let { code, data, data2, data3, msg } = res.data;
            if (code && data) {
              this.resList = data2;
              let abAndErr = this.getAbAndError(data2.bomList);
              this.abTbl.dataSource = abAndErr.ab;
              this.errorTbl.dataSource = abAndErr.error;
              this.diffData = {
                addList: data3.addList,
                delList: data3.deleteList.map((v) => v.materialObj),
                updateList: data3.diffList,
              };
              this.fileUrl = msg;
              this.prodUploadShow = true;
              this.$message.success("解析成功");
            } else {
              if (msg == "名称或型号命名不规范") {
                this.errorTbl2.dataSource = data2;
                this.errorVisible = true;
              } else {
                this.$message.error(msg);
              }
            }
          })
          .catch((error) => {
            this.$layer.close(loading);
            console.log(error);
          });
      });
      this.bomUploadShow = false;
      this.$layer.close(loading);
    },
    /**
     * 获取异常和错误的Bom信息
     * @param list
     * @returns {{ab: *[], error: *[]}}
     */
    getAbAndError(list) {
      let ab = ["0101", "0102", "0103", "0105", "0106"];
      let error = ["0104"];
      let result = {
        ab: [],
        error: [],
      };
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        let subCode = item.subCode.trim().slice(0, 4);
        let dwgExist = item.dwgExist;
        if (!dwgExist) {
          let isInAb = false;
          for (let j = 0; j < ab.length; j++) {
            if (ab[j] == subCode) {
              result.ab.push(item);
              isInAb = true;
              break;
            }
          }
          // 是否已经存在ab中
          if (!isInAb) {
            for (let j = 0; j < error.length; j++) {
              if (error[j] == subCode) {
                result.error.push(item);
                break;
              }
            }
          }
        }
      }
      return result;
    },
    getAllProducts() {
      getAllProducts().then((res) => {
@@ -879,7 +1486,7 @@
      return reg.test(txt);
    },
    viewLog(obj) {
      console.log(obj);
      // console.log(obj);
      const { parentCode, customCode } = obj;
      getLogList({ parentCode, customCode }).then((res) => {
        const { code, data } = res.data;
@@ -893,6 +1500,43 @@
    },
    logCancel() {
      this.logVisible = false;
    },
    prodDiff() {
      this.$router.push("/resource/product-diff");
    },
    showEcrlist(record) {
      this.ecrList = record.ecrList;
      this.ecrListVisible = true;
    },
    ecrListCancel() {
      this.ecrListVisible = false;
    },
    getRoleUser() {
      getRoleUser(1)
        .then((res) => {
          let { code, data, data2 } = res.data;
          let list = [];
          if (code && data) {
            // console.log(data);
            list = data2.map((v) => v.name);
          }
          this.tester = list;
        })
        .catch((err) => {
          console.log(err);
        });
    },
    downloadLog(record) {
      // console.log(record);
      let { customCode, parentCode } = record;
      this.oprateInfo = parentCode + "_" + customCode;
      this.downloadlogVisible = true;
    },
    ownerDownloadLog() {
      this.ownerLogVisible = true;
    },
    ownerLogClose() {
      this.ownerLogVisible = false;
    },
  },
  watch: {
@@ -928,6 +1572,14 @@
        this.update = Math.random();
      }, 200);
    },
    prodUploadShow(n) {
      // 关闭弹出框清空数据并不能忽视异常数据
      if (!n) {
        this.errorTbl.dataSource = [];
        this.abTbl.dataSource = [];
        this.abTbl.ignore = false;
      }
    },
  },
  computed: {
    ...mapGetters("account", [
@@ -935,6 +1587,7 @@
      "projectManagerList",
      "generalManagerList",
      "permits",
      "user",
    ]),
    ...mapGetters("setting", ["affixed"]),
    canUploadBom() {
@@ -946,8 +1599,57 @@
    canDownloadBom() {
      return checkPermit(PERMITS.downloadBom, this.permits);
    },
    canFeedback() {
      return checkPermit(PERMITS.feedback, this.permits);
    },
    abLabel() {
      let num = this.abTbl.dataSource.length;
      num = num > 99 ? "99+" : num;
      return "异常(" + num + ")";
    },
    errorLabel() {
      let num = this.errorTbl.dataSource.length;
      num = num > 99 ? "99+" : num;
      return "错误(" + num + ")";
    },
    abState() {
      let result = false;
      if (this.abTbl.dataSource.length != 0) {
        if (this.abTbl.ignore) {
          result = false;
        } else {
          result = true;
        }
      } else {
        result = false;
      }
      return result;
    },
    submitState() {
      let result = {
        code: 0,
        msg: "存在异常或错误的数据,请修复后再提交",
      };
      if (this.abState) {
        result.code = 1;
      } else {
        result.code = 0;
      }
      if (this.errorTbl.dataSource.length != 0) {
        result.code = 1;
      }
      return result;
    },
    isTester() {
      return this.tester.some((v) => v == this.user.name);
    },
  },
  mounted() {
    this.searchAllUserList();
    this.getRoleUser();
    this.getUserByRoleId();
    this.sendMessage();
    this.getAllProducts();
@@ -963,6 +1665,7 @@
.main {
  height: 100%;
  position: relative;
  .inner {
    position: absolute;
    left: 0;
@@ -971,13 +1674,16 @@
    bottom: 0;
  }
}
.img-wraper {
  width: 80px;
  height: 50px;
  display: inline-block;
  .image-view {
    width: 100%;
    height: 100%;
    /deep/img {
      width: 100%;
      height: 100%;
@@ -985,11 +1691,14 @@
    }
  }
}
/deep/table {
  table-layout: fixed;
}
.text-right {
  text-align: right;
  span::after {
    content: ":";
    position: relative;
@@ -997,51 +1706,105 @@
    margin: 0 8px 0 2px;
  }
}
.upload {
  padding: 10px 0;
}
.modal-footer {
  text-align: right;
  button + button {
    margin-left: 8px;
  }
}
.mt8 {
  margin-top: 8px;
}
.from {
  width: 100%;
}
.label {
  display: flex;
  justify-content: flex-end;
  padding-right: 1em;
  align-items: center;
}
.bom-list /deep/ .ant-card-body {
  padding: 8px 24px;
}
.log-content {
  max-height: 400px;
  overflow-y: auto;
  .user {
    color: #23aaf2;
    font-weight: 700;
  }
  .time {
    color: #f9be13;
    font-weight: 700;
  }
  .version {
    color: #0aedb2;
    font-weight: 700;
  }
  .ant-timeline-item:first-of-type {
    padding-top: 6px;
  }
}
.table-title {
  font-weight: 700;
  color: #13c2c2;
}
.btn-grp .ant-btn {
  min-width: 6.4em;
}
/deep/.locked > td {
  background: #fec54b;
}
/deep/.locked.locked.locked.ant-table-row-hover > td,
/deep/.locked.locked.locked:hover > td {
  background: #fcd583;
}
/deep/.unable > td {
  background: #f0637b;
}
/deep/.unable.unable.unable.ant-table-row-hover > td,
/deep/.unable.unable.unable:hover > td {
  background: #ff869a;
}
</style>
<style lang="less">
.full-modal {
  height: 100%;
  .ant-modal {
    max-width: 100%;
    height: 100%;
    top: 0;
    padding-bottom: 0;
    margin: 0;
  }
  .ant-modal-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow: hidden;
    // height: calc(100vh);
  }
  .ant-modal-body {
    flex: 1;
  }
}
</style>