研发图纸文件管理系统-前端项目
he wei
2022-09-13 306f5db64ccdb418fb5025334e1cefacdb470194
U 按需求修改
11个文件已修改
364 ■■■■■ 已修改文件
src/assets/js/const/const_permits.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layouts/tabs/TabsView.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/components/filesTable.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/materialsCenter/apis.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/materialsCenter/list.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/product/apis.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/product/details/details.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/product/list.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/apis.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/descRes.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/list.vue 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/const/const_permits.js
@@ -6,5 +6,6 @@
  
  uploadBom: 10009,
  uploadSoftware: 10008,
  lockBom: 10010
  lockBom: 10010,
  lockOther: 10011
}
src/layouts/tabs/TabsView.vue
@@ -30,9 +30,13 @@
import AKeepAlive from '@/components/cache/AKeepAlive'
import TabsHead from '@/layouts/tabs/TabsHead'
import createWs from "@/assets/js/websocket";
const WSMixin = createWs("loginCheck");
export default {
  name: 'TabsView',
  i18n: require('./i18n'),
  mixins: [WSMixin],
  components: {TabsHead, PageToggleTransition, Contextmenu, AdminLayout , AKeepAlive },
  data () {
    return {
@@ -308,6 +312,19 @@
        }
      })
    },
    onWSMessage(res) {
      res = JSON.parse(res.data);
      console.log(res, "loginCheck");
      // this.searchData(res);
      if (!res.data.checkLogin.data) {
        this.$layer.msg(res.data.checkLogin.msg);
        //this.WSClose2();
        setTimeout(() => {
          this.$router.push("/login");
          location.reload();
        }, 2000);
      }
    },
    ...mapMutations('setting', ['correctPageMinHeight'])
  }
}
src/pages/components/filesTable.vue
@@ -1,5 +1,5 @@
<template>
  <div class="" :style="{ width: width + 'px' }">
  <div class="">
    <a-table
      ref="aTable"
      size="small"
@@ -9,13 +9,18 @@
      :data-source="dataSource"
      :pagination="false"
      :rowKey="(record, index) => index"
      :rowClassName="(record) => (1 == record.lockFlag ? 'is-lock' : '')"
    >
      <template slot="action" slot-scope="text, record">
        <div v-if="record.url">
          <a @click="view(record)">预览</a>
          <template v-if="canDownloadOther">
          <a v-if="!record.lockFlag" @click="view(record)">预览</a>
          <template v-if="canDownloadOther && !record.lockFlag">
            <a-divider type="vertical"></a-divider>
            <a @click="downloadLog(record)">下载</a>
          </template>
          <template v-if="canLockOther">
            <a-divider v-if="!record.lockFlag" type="vertical"></a-divider>
            <a @click="lock(record)">{{ record.lockFlag ? "解锁" : "锁定" }}</a>
          </template>
        </div>
      </template>
@@ -28,6 +33,23 @@
    >
      <img alt="example" style="width: 100%" :src="imgUrl" />
    </a-modal>
    <a-modal
      :width="400"
      :visible="reasonVisible"
      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>
  </div>
</template>
@@ -35,6 +57,7 @@
import getWebUrl from "@/assets/js/tools/getWebUrl";
import { dwgReview } from "@/pages/workplace/apis";
import { downloadLog } from "@/pages/system/logs/apis";
import { updateAttachLock } from "@/pages/resourceManage/materialsCenter/apis";
import checkPermit from "@/assets/js/tools/checkPermit";
import PERMITS from "@/assets/js/const/const_permits";
import { mapGetters } from "vuex";
@@ -47,9 +70,11 @@
        return [];
      },
    },
    width: {
      type: Number,
      default: 600,
    info: {
      type: Object,
      default() {
        return null;
      },
    },
  },
  data() {
@@ -67,15 +92,23 @@
        width: 100,
      },
      {
        title: "操作原因",
        dataIndex: "localReason",
        align: "center",
      },
      {
        title: "操作",
        dataIndex: "operation",
        key: "operation",
        align: "center",
        width: 100,
        width: 140,
        scopedSlots: { customRender: "action" },
      },
    ];
    return {
      reason: "",
      reasonVisible: false,
      currObj: null,
      columns,
      y: 500,
      imgUrl: "",
@@ -142,29 +175,85 @@
      document.body.removeChild(link);
      downloadLog(parentModel, subModel);
    },
    lock(obj) {
      this.currObj = obj;
      this.reason = '';
      this.reasonVisible = true;
    },
    reasonCancel() {
      this.reasonVisible = false;
    },
    reasonOk() {
      if (!this.id) {
        this.$message.error("无效的物料ID");
        return false;
      }
      let obj = this.currObj;
      let lockFlag = !obj.lockFlag * 1;
      let params = {
        attachName: obj.fileName,
        localReason: this.reason,
        lockFlag,
        materialId: this.id,
      };
      updateAttachLock([params]).then((res) => {
        const { code, data, msg } = res.data;
        if (code && data) {
          this.$message.success(msg);
          obj.lockFlag = lockFlag;
          obj.localReason = this.reason;
          this.reasonVisible = false;
        } else {
          this.$message.error(msg);
        }
      });
    },
  },
  computed: {
    dataSource() {
      let attachLocks = this.attachLocks;
      let reg = /(.*\\+)*(.*)$/;
      return this.list.map((item) => {
        let fileName = item.match(reg)[2];
        let arr = fileName.split(".");
        let fileType = arr.length ? arr[arr.length - 1].toLowerCase() : "";
        let localReason = "";
        let lockFlag = 0;
        attachLocks.forEach((v) => {
          if (v.attachName == fileName) {
            localReason = v.localReason;
            lockFlag = v.lockFlag;
          }
        });
        return {
          fileName,
          fileType,
          url: item,
          localReason,
          lockFlag,
        };
      });
    },
    id() {
      return this.info ? this.info.id : 0;
    },
    attachLocks() {
      return this.info ? this.info.attachLocks : [];
    },
    ...mapGetters("account", ["permits"]),
    canDownloadOther() {
      return checkPermit(PERMITS.canDownloadOther, this.permits);
      return checkPermit(PERMITS.downloadOther, this.permits);
    },
    canLockOther() {
      return checkPermit(PERMITS.lockOther, this.permits);
    },
  },
  mounted() {},
};
</script>
<style scoped>
<style lang="less" scoped>
/deep/.is-lock td {
  background: #ddd;
}
</style>
src/pages/resourceManage/materialsCenter/apis.js
@@ -111,7 +111,7 @@
}
/**
 * 根据物料id查询物料信息
 *
 * @returns
 */
export const uploadOthers = (data) => {
@@ -123,4 +123,15 @@
    },
    data
  })
}
/**
 * 修改附件锁定状态
 * @returns
 */
export const updateAttachLock = (data) => {
  return axios({
    method: "POST",
    url: "attachLock/updateAttachLock",
    data
  })
}
src/pages/resourceManage/materialsCenter/list.vue
@@ -129,11 +129,11 @@
      title="附件"
      :destroyOnClose="true"
      :maskClosable="false"
      :width="650"
      :width="850"
      :footer="null"
      @cancel="fileListCancel"
    >
      <files-table :list="fileList"></files-table>
      <files-table :list="fileList" :info="info"></files-table>
      <div class="footer">
        <a-space>
          <a-button @click="fileListCancel">关闭</a-button>
@@ -141,9 +141,10 @@
            v-if="canUpload"
            :before-upload="beforeUpload"
            @change="fileUploadChange"
            :showUploadList="false"
            multiple
            accept=".zip"
          >
            <!-- :showUploadList="false" -->
            <a-button type="primary">上传附件</a-button>
          </a-upload>
        </a-space>
@@ -165,8 +166,8 @@
import { dwgReview } from "@/pages/workplace/apis";
import { downloadLog } from "@/pages/system/logs/apis";
import { mapGetters } from "vuex";
import checkPermit from '@/assets/js/tools/checkPermit';
import PERMITS from '@/assets/js/const/const_permits';
import checkPermit from "@/assets/js/tools/checkPermit";
import PERMITS from "@/assets/js/const/const_permits";
import createWs from "@/assets/js/websocket";
const WSMixin = createWs("material");
@@ -175,6 +176,7 @@
  mixins: [WSMixin],
  data() {
    return {
      info: {},
      fileListShow: false,
      fileList: [],
      resShow: false,
@@ -336,7 +338,7 @@
      return this.isAdd ? "批量增加关联关系" : "批量解除关联关系";
    },
    ...mapGetters("setting", ["affixed"]),
    ...mapGetters('account', ['permits']),
    ...mapGetters("account", ["permits"]),
    canUpload() {
      return checkPermit(PERMITS.uploadBom, this.permits);
    },
@@ -394,7 +396,7 @@
        pageCurr,
        ...params,
      };
      console.log("=====9=", data, JSON.stringify(data));
      // console.log("=====9=", data, JSON.stringify(data));
      this.SOCKET.send(JSON.stringify(data));
    },
    onWSMessage(res) {
@@ -495,8 +497,11 @@
        subCode,
        subModel,
      };
      formData.append("multipartFile", data.file);
      formData.append("materialStr", JSON.stringify(obj));
      data.fileList.forEach((v, i) => {
        formData.append("file", v.originFileObj);
      });
      uploadOthers(formData)
        .then((res) => {
          this.$layer.close(loading);
@@ -561,7 +566,7 @@
      this.resize();
    },
    panelShow(obj) {
      const { id, dwgUrl } = obj;
      const { id, dwgUrl, attachLocks } = obj;
      this.currentObj = obj;
      getFileList(id).then((res) => {
        const { code, data, data2 } = res.data;
@@ -569,10 +574,11 @@
        if (code && data) {
          list = data2;
        }
        this.fileList = list;
        if (dwgUrl) {
          this.fileList.unshift(dwgUrl);
          list.unshift(dwgUrl);
        }
        this.info = { attachLocks, id };
        this.fileList = list;
        this.fileListShow = true;
      });
    },
src/pages/resourceManage/product/apis.js
@@ -79,4 +79,16 @@
    url: "product/setpHistoryEnable",
    params
  })
}
/**
 * 产品操作日志查询
 * customCode=1&parentCode=1
 * @returns
 */
export const getLogList = (params) => {
  return axios({
    method: "GET",
    url: "productLockLog/listByParentCodeAndCustomCode",
    params
  })
}
src/pages/resourceManage/product/details/details.vue
@@ -173,6 +173,24 @@
    >
      <diff-list :list="diffData"></diff-list>
    </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>
  </a-layout>
</template>
@@ -202,6 +220,8 @@
  mixins: [WSMixin],
  data() {
    return {
      reasonVisible: false,
      reason: '',
      lastId: undefined,
      diffShow: false,
      diffData: [],
@@ -570,22 +590,30 @@
      this.diffShow = false;
    },
    changeStatus() {
      this.reasonVisible = true;
    },
    reasonCancel() {
      this.reasonVisible = false;
    },
    reasonOk() {
      let {
        currentVersion: { customCode, parentCode, enabled, version },
        currentVersion: { customCode, parentCode, enabled, version, versionTime },
        reason
      } = this;
      enabled = !enabled * 1;
      setpHistoryEnable({ customCode, parentCode, enabled, version }).then(
      setpHistoryEnable({ customCode, parentCode, enabled, version, reason, versionTime }).then(
        (res) => {
          let { code, data } = res.data;
          if (code && data) {
            this.$message.success("操作成功");
            this.currentVersion.enabled = enabled;
            this.reasonVisible = false;
          } else {
            this.$message.error("操作失败");
          }
        }
      );
    },
    }
  },
  mounted() {
    this.sendMessage();
src/pages/resourceManage/product/list.vue
@@ -46,13 +46,21 @@
                <a @click="upload(record)">上传软件</a>
                <a-divider type="vertical"></a-divider>
              </template> -->
              <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-button type="primary" @click="edit(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"
                    type="primary"
                    @click="download(record)"
                    >下载</a-button
@@ -60,6 +68,7 @@
                  <a-button
                    type="primary"
                    v-if="canUploadBom"
                    :disabled="record.version == -1"
                    @click="showCustom(record)"
                    >定制</a-button
                  >
@@ -260,6 +269,33 @@
        @cancel="customCancel"
      ></prod-upload>
    </a-modal>
    <!-- 日志 -->
    <a-modal
      :visible="logVisible"
      :footer="null"
      :width="800"
      title="操作日志"
      :destroyOnClose="true"
      @cancel="logCancel"
    >
      <div class="log-content">
        <a-timeline v-if="logList.length">
          <a-timeline-item
            v-for="(item, idx) in logList"
            :key="'log_' + idx"
            :color="item.lockFlag == 1 ? 'red' : 'green'"
          >
            <p>
              <span class="user">{{ item.owner }}</span
              > 在 <span class="time">{{ item.createTime }}</span
              > {{ item.lockFlag ? "锁定" : "激活" }}了版本 <span class="version">{{ item.versionTime }}</span>
            </p>
            <p>操作原因: {{ item.reason ? item.reason : "无" }}</p>
          </a-timeline-item>
        </a-timeline>
        <a-empty v-else />
      </div>
    </a-modal>
  </div>
</template>
@@ -270,7 +306,7 @@
import DrawUpload from "@/pages/components/drawUpload";
import getWebUrl from "@/assets/js/tools/getWebUrl";
import { addProduct, downloadBom, getAllProducts } from "./apis";
import { addProduct, downloadBom, getAllProducts, getLogList } from "./apis";
import { productSoftwareSubmit } from "../software/apis";
import { zipParse } from "@/pages/workplace/myDraw/apis";
import { mapGetters } from "vuex";
@@ -286,6 +322,8 @@
  mixins: [WSMixin],
  data() {
    return {
      logVisible: false,
      logList: [],
      fromProd: undefined,
      prodList: [],
      diffData: {},
@@ -734,6 +772,22 @@
      const reg = new RegExp(str, "ig");
      return reg.test(txt);
    },
    viewLog(obj) {
      console.log(obj);
      const { parentCode, customCode } = obj;
      getLogList({ parentCode, customCode }).then((res) => {
        const { code, data } = res.data;
        if (code) {
          this.logList = data;
          this.logVisible = true;
        } else {
          this.$message.error("日志查询失败");
        }
      });
    },
    logCancel() {
      this.logVisible = false;
    },
  },
  watch: {
    update(n) {
@@ -861,4 +915,20 @@
.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;
  }
}
</style>
src/pages/resourceManage/software/apis.js
@@ -67,3 +67,15 @@
    data
  })
}
/**
 *
 * @returns
 */
export const applyModel = (data) => {
  return axios({
    method: "PUT",
    url: "software/applyModel",
    data
  })
}
src/pages/resourceManage/software/descRes.vue
@@ -10,6 +10,10 @@
          <td colspan="3">{{ summarize.fileName }}</td>
        </tr>
        <tr>
          <th>板号</th>
          <td colspan="3">{{ summarize.boardNumber }}</td>
        </tr>
        <tr>
          <th>软件类型</th>
          <td colspan="3">{{ summarize.type }}</td>
        </tr>
src/pages/resourceManage/software/list.vue
@@ -61,6 +61,10 @@
                <a-divider type="vertical"></a-divider>
                <a @click="download(record)">下载</a>
              </template>
              <template v-if="canUploadSoftware">
                <a-divider type="vertical"></a-divider>
                <a @click="updateDesc(record)">更新说明</a>
              </template>
            </template>
          </advance-table>
        </a-card>
@@ -77,7 +81,7 @@
      @cancel="uploadCancel"
    >
      <div class="">
        <a-row type="flex" class="row">
        <a-row v-if="!onlyXls" type="flex" class="row">
          <a-col flex="6em" class="label">软件包</a-col>
          <a-col :flex="1">
            <a-upload
@@ -109,7 +113,8 @@
        </div>
        <div class="modal-footer">
          <a-button type="danger" @click="uploadCancel"> 取消 </a-button>
          <a-button type="primary" @click="uploadSoftware"> 提交 </a-button>
          <a-button v-if="!onlyXls" type="primary" @click="uploadSoftware"> 提交 </a-button>
          <a-button v-else type="primary" @click="applyModel"> 提交 </a-button>
        </div>
      </div>
    </a-modal>
@@ -127,6 +132,7 @@
  downLoadSoftware,
  excelParse,
  productSoftwareSubmit,
  applyModel
} from "./apis";
import { mapGetters } from "vuex";
@@ -134,6 +140,7 @@
  name: "",
  data() {
    return {
      onlyXls: false,
      resData: [],
      file: null,
      file1: null,
@@ -171,7 +178,7 @@
          dataIndex: "soft.owner",
          align: "center",
          searchAble: true,
          width: 160
          width: 160,
        },
        {
          title: "适用机型号",
@@ -197,7 +204,7 @@
          title: "操作",
          dataIndex: "operation",
          align: "center",
          width: 168,
          width: 228,
          fixed: "right",
          scopedSlots: { customRender: "action" },
          noSearch: true,
@@ -218,7 +225,7 @@
          width: 180,
          noSearch: true,
        },
      ]
      ],
    };
  },
  components: {
@@ -257,10 +264,10 @@
      Object.keys(conditions).forEach((v) => {
        switch (v) {
          case "soft.fileName":
            params[v] = conditions['fileName'];
            params[v] = conditions["fileName"];
            break;
          case "soft.owner":
            params[v] = conditions['owner'];
            params[v] = conditions["owner"];
            break;
          default:
            params[v] = conditions[v];
@@ -326,6 +333,14 @@
      this.file = null;
      this.file1 = null;
      this.resData = [];
      this.onlyXls = false;
      this.uploadShow = true;
    },
    updateDesc() {
      this.file = null;
      this.file1 = null;
      this.resData = [];
      this.onlyXls = true;
      this.uploadShow = true;
    },
    beforeUpload() {
@@ -407,6 +422,37 @@
          console.log(error);
        });
    },
    applyModel() {
      if (!this.file1) {
        this.$message.error("请选择软件说明文件");
        return false;
      }
      if (!this.resData.length) {
        this.$message.error("软件说明文件解析异常");
        return false;
      }
      let loading = this.$layer.loading();
      const formData = new FormData();
      formData.append("multipartFile", this.file1);
      formData.append("softwareStr", JSON.stringify(this.resData));
      applyModel(formData)
        .then((res) => {
          let { code, data, msg } = res.data;
          if (code) {
            this.uploadShow = false;
            this.$message.success(msg);
            this.searchData();
          } else {
            this.$message.error(msg);
          }
          this.$layer.close(loading);
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
    },
  },
  watch: {
    update(n) {