研发图纸文件管理系统-前端项目
he wei
2023-06-26 2c90b10e4c8563f8e586f31d834a2af6df031363
U sop修改
5个文件已修改
500 ■■■■ 已修改文件
src/pages/resourceManage/software/list.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/sopFile/apis.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/sopFile/descRes.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/sopFile/list.vue 372 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/sopFile/rowRes.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/list.vue
@@ -213,7 +213,7 @@
  updateSoftwareLock,
} from "./apis";
import { mapGetters } from "vuex";
import EmailCard from "../../components/emailCard/";
import EmailCard from "../../components/emailCard";
export default {
  name: "",
src/pages/resourceManage/sopFile/apis.js
@@ -28,10 +28,22 @@
    data
  })
}
/**
 * 更新sop说明文件
 * @param {*} data 解析结果 添加id
 * @returns
 */
export const updateSop = (data) => {
  return axios({
    method: "POST",
    url: "sop/updateSop",
    data
  })
}
/**
 * 列表查询
 * @param {*} params {code, model}
 * @param {*} params {code, model, pageCurr, pageSize}
 * @param {*} data [{chileType: ['通用', '基础'], parentType: '组装'}]
 * @returns 
 */
src/pages/resourceManage/sopFile/descRes.vue
@@ -85,6 +85,11 @@
      return this.info.sopProductList || [];
    },
  },
  watch: {
    info() {
      this.format();
    }
  },
  methods: {
    format() {
      // let list = [
@@ -102,7 +107,12 @@
      //   },
      // ];
      // fileType=组装-线束;组装-复用;组装-test;测试-单板;测试-联调;生产-线束;
      let fileType = this.info.fileType;
      let {
        fileType,
        fileTypeList,
      } = this.info;
      fileType = fileType || '';
      fileTypeList = fileTypeList || [];
      let selected = fileType.split(";").filter((v) => v != "");
      let _types = {};
      selected.forEach((v) => {
@@ -110,7 +120,7 @@
        _types[arr[0]] = _types[arr[0]] || [];
        _types[arr[0]].push(arr[1]);
      });
      let list = this.info.fileTypeList.map((v) => {
      let list = fileTypeList.map((v) => {
        let name = Object.keys(v)[0];
        return {
          name,
src/pages/resourceManage/sopFile/list.vue
@@ -32,19 +32,13 @@
            <template slot="title">
              <a-space class="operator">
                <span class="title">SOP</span>
                <a-upload
                  v-if="canUpload"
                  :before-upload="beforeUpload"
                  :showUploadList="false"
                  @change="uploadChange"
                  accept=".xls,.xlsx"
                <a-button v-if="canUpload" type="primary" @click="showUpload"
                  >新增</a-button
                >
                  <a-button type="primary">新增</a-button>
                </a-upload>
              </a-space>
            </template>
            <template slot="action" slot-scope="{ record }">
              <a-popover title="" trigger="hover">
              <a-popover v-if="!record.currentFlag" title="" trigger="hover">
                <div class="" slot="content" style="width: 450px">
                  <a-table
                    size="small"
@@ -56,32 +50,47 @@
                    :expandRowByClick="true"
                    :row-key="(record1, index) => index"
                  >
                    <!-- <template slot="action" slot-scope="record1">
                      123{{ record1 }}
                    </template> -->
                  </a-table>
                </div>
                <a>适用产品</a>
              </a-popover>
              <a-tag v-else class="tag-all" color="#f50"> 适用全部 </a-tag>
              <template v-if="canDownload">
                <a-divider type="vertical"></a-divider>
                <a @click="downloadFile(record)">下载</a>
              </template>
              <a-divider type="vertical"></a-divider>
              <!-- <a class="action-button" @click="viewPdf(record)">预览</a> -->
              <a class="action-button" @click="downloadFile(record)">下载</a>
              <!-- <a class="action-button" @click="viewHistory(record)">历史详情</a> -->
              <a-popover title="" trigger="hover">
                <a-space class="btn-grp" direction="vertical" slot="content">
                  <a-button
                    v-if="canUpload"
                    type="primary"
                    @click="updateDesc(record)"
                    >更新说明</a-button
                  >
                  <!-- <a-button
                    v-if="canLock"
                    type="primary"
                    @click="lock(record)"
                    >{{ record.lockFlag ? "解锁" : "锁定" }}</a-button
                  > -->
                  <a-button
                    v-if="canUpload"
                    type="primary"
                    @click="handleEmailShow(record)"
                    >邮件通知</a-button
                  >
                </a-space>
                <a>更多</a>
              </a-popover>
            </template>
          </advance-table>
        </a-card>
      </a-spin>
    </div>
    <!-- 弹窗 解析结果 -->
    <a-modal
      :visible="resShow"
      title="解析结果"
      :destroyOnClose="true"
      :maskClosable="false"
      :width="800"
      okText="提交"
      @cancel="resCancel"
      @ok="uploadOk"
    >
      <desc-res :info="resObj"></desc-res>
    </a-modal>
    <pop
      :visible.sync="popVisible"
      :x="popPosition.x"
@@ -89,6 +98,74 @@
      :position="popPosition.dir"
      :info="popInfo"
    ></pop>
    <a-modal
      :visible="uploadShow"
      :footer="null"
      :width="800"
      title="上传软件"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="uploadCancel"
    >
      <div class="">
        <template v-if="!onlyXls">
          <a-row type="flex" class="row">
            <a-col flex="6em" class="label">sop包</a-col>
            <a-col :flex="1">
              <a-upload
                class="upload"
                :before-upload="beforeUpload"
                @change="uploadChange"
                accept=".zip,.rar"
              >
                <a-button type="primary">选压缩包</a-button>
              </a-upload>
            </a-col>
          </a-row>
        </template>
        <a-row type="flex" class="row">
          <a-col flex="6em" class="label">SOP说明</a-col>
          <a-col :flex="1">
            <a-upload
              class="upload"
              :before-upload="beforeUpload"
              @change="uploadChange1"
              accept=".xls,.xlsx"
            >
              <a-button type="primary">说明文件</a-button>
            </a-upload>
          </a-col>
        </a-row>
        <div class="sub-title">说明文件解析结果</div>
        <div class="res-content">
          <desc-res :info="resObj"></desc-res>
        </div>
        <div class="modal-footer">
          <a-button type="danger" @click="uploadCancel"> 取消 </a-button>
          <a-button v-if="!onlyXls" type="primary" @click="uploadSop">
            提交
          </a-button>
          <a-button v-else type="primary" @click="applyModel"> 提交 </a-button>
        </div>
      </div>
    </a-modal>
    <a-modal
      :visible="emailShow"
      :footer="null"
      :width="760"
      title="邮件发送"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="emailCancel"
    >
      <email-card
        :visible.sync="emailShow"
        :users="userList"
        :title="emailInfo.title"
        :content="emailInfo.content"
        v-if="emailShow"
      ></email-card>
    </a-modal>
  </div>
</template>
@@ -98,7 +175,16 @@
import checkPermit from "@/assets/js/tools/checkPermit";
import PERMITS from "@/assets/js/const/const_permits";
import { mapGetters } from "vuex";
import { fileParse, addSop, getList, getSopType1, getSopType2 } from "./apis";
import EmailCard from "../../components/emailCard";
import { getUserList } from "../../permission/apis";
import {
  fileParse,
  addSop,
  getList,
  getSopType1,
  getSopType2,
  updateSop,
} from "./apis";
import offset from "@/assets/js/tools/offset";
import Pop from "./pop";
import DescRes from "./descRes";
@@ -108,10 +194,19 @@
    AdvanceTable,
    Pop,
    DescRes,
    EmailCard,
  },
  name: "list",
  data() {
    return {
      emailShow: false,
      emailInfo: {
        title: "",
        content: "",
      },
      userList: [],
      onlyXls: false,
      uploadShow: false,
      webUrl: getWebUrl(),
      prodsColumns: [
        {
@@ -125,10 +220,18 @@
          align: "center",
          width: 180,
        },
        // {
        //   title: "操作",
        //   dataIndex: "operation",
        //   align: "center",
        //   width: 180,
        //   scopedSlots: { customRender: "action" },
        // },
      ],
      file: null,
      file1: null,
      resObj: {},
      popInfo: {},
      resShow: false,
      popVisible: false,
      popPosition: {
        x: 500,
@@ -246,7 +349,7 @@
          title: "操作",
          dataIndex: "operation",
          align: "center",
          width: 140,
          width: 200,
          fixed: "right",
          scopedSlots: { customRender: "action" },
          noSearch: true,
@@ -257,8 +360,15 @@
  },
  computed: {
    ...mapGetters("account", ["permits"]),
    ...mapGetters("setting", ["affixed"]),
    canUpload() {
      return checkPermit(PERMITS.uploadSoftware, this.permits);
    },
    canDownload() {
      return checkPermit(PERMITS.downloadSoftware, this.permits);
    },
    canLock() {
      return checkPermit(PERMITS.lockOther, this.permits);
    },
  },
  watch: {
@@ -295,6 +405,115 @@
    },
  },
  methods: {
    searchAllUserList() {
      getUserList()
        .then((res) => {
          let rs = res.data;
          if (rs.code && rs.data) {
            this.userList = rs.data2;
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    showUpload() {
      this.file = null;
      this.file1 = null;
      this.resObj = {};
      this.onlyXls = false;
      this.uploadShow = true;
    },
    updateDesc(row) {
      this.file = null;
      this.file1 = null;
      this.resObj = { rowId: row.id };
      this.onlyXls = true;
      this.uploadShow = true;
    },
    uploadCancel() {
      this.uploadShow = false;
    },
    handleEmailShow(record) {
      this.emailInfo.title =
        "[sop发布记录]" + record.fileName + " 版本号:" + record.fileVersion;
      this.emailInfo.content = record.releaseNotes;
      this.emailShow = true;
    },
    emailCancel() {
      this.emailShow = false;
    },
    uploadSop() {
      if (!this.file) {
        this.$message.error("请选择要上传的压缩包");
        return false;
      }
      if (!this.file1) {
        this.$message.error("请选择sop说明文件");
        return false;
      }
      if (!this.resObj.fileName) {
        this.$message.error("sop说明文件解析异常");
        return false;
      }
      // let info = this.resData[0];
      // if(!info.boardNumber || !info.type) {
      //   this.$error({
      //     title: '系统提示',
      //     content: '缺少板号或软件类型,请输入板号和软件类型',
      //   });
      //   return false;
      // }
      let loading = this.$layer.loading();
      const formData = new FormData();
      formData.append("multipartFile", this.file);
      // formData.append("file2", this.file1);
      formData.append("sopStr", JSON.stringify(this.resObj));
      addSop(formData)
        .then((res) => {
          let { code, data, msg } = res.data;
          if (code) {
            this.uploadShow = false;
            this.$message.success("上传成功");
            this.searchData();
          } else {
            this.$message.error("解析失败");
          }
          this.$layer.close(loading);
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
    },
    applyModel() {
      if (!this.file1) {
        this.$message.error("请选择sop说明文件");
        return false;
      }
      if (!this.resObj.fileName) {
        this.$message.error("sop说明文件解析异常");
        return false;
      }
      let loading = this.$layer.loading();
      updateSop(this.resObj)
        .then((res) => {
          let { code, data, msg } = res.data;
          if (code) {
            this.uploadShow = false;
            this.$message.success("上传成功");
            this.searchData();
          } else {
            this.$message.error("解析失败");
          }
          this.$layer.close(loading);
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
    },
    getSopType1() {
      getSopType1()
        .then((res) => {
@@ -390,16 +609,39 @@
      return false;
    },
    uploadChange(data) {
      const { file, fileList } = data;
      if (fileList.length > 1) {
        fileList.shift();
      }
      if (fileList.length) {
        this.file = fileList[0].originFileObj;
      } else {
        this.file = null;
      }
    },
    uploadChange1(data) {
      const { file, fileList } = data;
      if (fileList.length > 1) {
        fileList.shift();
      }
      if (fileList.length) {
        this.file1 = fileList[0].originFileObj;
      } else {
        this.file1 = null;
        this.resObj = [];
        return false;
      }
      let loading = this.$layer.loading();
      const formData = new FormData();
      formData.append("multipartFile", data.file);
      formData.append("multipartFile", this.file1);
      fileParse(formData)
        .then((res) => {
          this.$layer.close(loading);
          let { code, data, data2 } = res.data;
          if (code && data) {
            let rowId = this.resObj.rowId;
            this.resObj = data2;
            this.resShow = true;
            this.resObj.id = rowId;
            this.$message.success("解析成功");
          } else {
            this.$message.error("解析失败");
@@ -410,25 +652,13 @@
          console.log(error);
        });
    },
    resCancel() {
      this.resShow = false;
    },
    uploadOk() {
      addSop(this.resObj).then((res) => {
        let { code, data, msg } = res.data;
        if (code) {
          this.$message.success("上传成功");
          this.resShow = false;
          this.searchData();
        } else {
          this.$message.error(msg);
        }
      });
    },
    resize() {
      setTimeout(() => {
        this.update = Math.random();
      }, 200);
    },
    activeFN() {
      this.resize();
    },
    onSearch(conditions, searchOptions, col) {
      // console.log(conditions);
@@ -462,12 +692,12 @@
    parentTypeChange(val) {
      let _search = this.columns[1].search;
      _search.value = [];
      this.conditions['chileType'] = [];
      this.conditions["chileType"] = [];
      this.getSopType2(val);
    },
    searchData() {
      const { pageCurr, pageSize, conditions, columns } = this;
      let params = {};
      let params = { pageCurr, pageSize };
      let data = {};
      Object.keys(conditions).forEach((v) => {
        switch (v) {
@@ -486,11 +716,14 @@
      getList(params, params2)
        .then((res) => {
          let { code, data, data2 } = res.data;
          let total = 0;
          if (code && data) {
            // console.log(data2);
            list = data2;
            list = data2.list;
            total = data2.total;
          }
          this.dataSource = list;
          this.total = total;
          this.getSopType1();
          if (-1 == this.update) {
            this.update = Math.random();
@@ -522,8 +755,12 @@
  },
  mounted() {
    this.searchData();
    this.searchAllUserList();
    this.getSopType1();
    window.addEventListener("resize", this.resize);
  },
  destroyed() {
    window.removeEventListener("resize", this.resize);
  },
};
</script>
@@ -557,12 +794,47 @@
/deep/table {
  table-layout: fixed;
}
.modal-footer {
  text-align: right;
  button + button {
    margin-left: 8px;
  }
}
.label {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding-right: 0.4em;
  height: 32px;
  &::after {
    content: ":";
  }
}
.row ~ .row {
  margin-top: 10px;
}
.sub-title {
  font-size: 14px;
  font-weight: 700;
  margin-top: 10px;
}
.res-content {
  max-height: 260px;
  overflow-y: auto;
  margin-bottom: 10px;
}
.btn-grp button {
  width: 6.4em;
}
.tag-all {
  margin: 0;
}
/deep/ .ant-table-fixed-right {
  .ant-table-body-outer {
    margin-bottom: 0 !important;
  }
  .ant-table-body-inner {
   overflow-x: hidden;
 }
    overflow-x: hidden;
  }
}
</style>
src/pages/resourceManage/sopFile/rowRes.vue
@@ -9,9 +9,29 @@
          <th class="col-1">文件名称</th>
          <td colspan="8">{{ info.fileName }}</td>
        </tr>
        <tr>
        <!-- <tr>
          <th class="col-1">文件类型</th>
          <td colspan="8">{{ info.fileType }}</td>
        </tr> -->
        <tr
          v-for="(item, idx) in typeList"
          :key="'li1_' + idx"
          :rowspan="0 == idx ? sumRows : 1"
        >
          <template v-if="0 == idx">
            <th class="col-1" :rowspan="sumRows">文件类型</th>
          </template>
          <td
            v-for="(sub, i) in item"
            :colspan="item.length == 2 ? 4 : 1"
            :key="'li2_' + i"
          >
            <template v-if="item.length != 2 && sub.name">
              <a-icon v-if="sub.checked" type="check-square" />
              <a-icon v-else type="border" />
            </template>
            {{ sub.name }}
          </td>
        </tr>
        <tr>
          <th class="col-1">文件版本</th>
@@ -60,6 +80,8 @@
  },
  data() {
    return {
      sumRows: 2,
      typeList: [],
    };
  },
  computed: {
@@ -67,10 +89,84 @@
      return this.info.sopProductList || [];
    },
  },
  watch: {
    info() {
      this.format();
    }
  },
  methods: {
    format() {
      // fileType=组装-线束;组装-复用;组装-test;测试-单板;测试-联调;生产-线束;
      let { fileType } = this.info;
      fileType = fileType || "";
      let selected = fileType.split(";").filter((v) => v != "");
      let _types = {};
      selected.forEach((v) => {
        let arr = v.split("-");
        _types[arr[0]] = _types[arr[0]] || [];
        _types[arr[0]].push(arr[1]);
      });
      let list = Object.keys(_types).map((v) => {
        let name = v;
        return {
          name,
          labels: _types[v].map((item) => {
            return {
              name: item,
              checked: true,
            };
          }),
        };
      });
      let resList = [];
      for (let i = 0, j = list.length; i < j; i += 2) {
        // 同一行两个类别占用的最大行数
        let rows = 0;
        let row0 = 0;
        let row1 = 0;
        let item0 = list[i];
        let item1 = list[i + 1];
        // 是否有第二个元素
        let hasItem1 = i + 1 < j;
        // 当前行的第一个类占用的行数
        row0 = Math.ceil(item0.labels.length / 4);
        if (hasItem1) {
          row1 = Math.ceil(item1.labels.length / 4);
        }
        rows = Math.max(row0, row1);
        let trs = [
          [{ name: item0.name }, { name: hasItem1 ? item1.name : "" }],
        ];
        for (let m = 0; m < rows; m++) {
          let idx0 = m * 4;
          let idx1 = m * 4 + 1;
          let idx2 = m * 4 + 2;
          let idx3 = m * 4 + 3;
          let li0 = [];
          let li1 = [];
          li0[0] = item0.labels[idx0] || {};
          li0[1] = item0.labels[idx1] || {};
          li0[2] = item0.labels[idx2] || {};
          li0[3] = item0.labels[idx3] || {};
          if (hasItem1) {
            li1[0] = item1.labels[idx0] || {};
            li1[1] = item1.labels[idx1] || {};
            li1[2] = item1.labels[idx2] || {};
            li1[3] = item1.labels[idx3] || {};
          } else {
            li1 = [{}, {}, {}, {}];
          }
          trs.push([...li0, ...li1]);
        }
        resList.push(...trs);
      }
      this.sumRows = resList.length;
      this.typeList = resList;
    },
  },
  mounted() {
    this.format();
  },
};
</script>