研发图纸文件管理系统-前端项目
he wei
2025-03-06 1164846f7c10c66264a3a88d16a31ac2fcc3a51d
U 软件添加上传源码包功能 由李文涛上传 下载
2个文件已修改
1886 ■■■■ 已修改文件
src/pages/resourceManage/software/apis.js 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/list.vue 1841 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/resourceManage/software/apis.js
@@ -107,3 +107,48 @@
    }
  })
}
/**
 * 根据软件名称 下载源码
 * fileName
 */
export const downLoadCode = (fileName) => {
  return axios({
    method: "GET",
    url: "softcode/downLoadCode",
    responseType: "blob",
    params: {
      fileName
    }
  })
}
/**
 * 查询日期三天内的所有上传软件名称
 * createTime 上传日期
 */
export const getFileNameByCreateTime = (createTime) => {
  return axios({
    method: "GET",
    url: "softcode/getFileNameByCreateTime",
    params: {
      createTime
    }
  })
}
/**
 * 源码包上传
 * file
 * fileNames
 */
export const uploadCode = (data) => {
  return axios({
    method: "POST",
    url: "softcode/uploadCode",
    headers: {
      "Content-Type": "multipart/form-data"
    },
    data
  })
}
src/pages/resourceManage/software/list.vue
@@ -3,100 +3,59 @@
    <div class="inner" ref="wraper">
      <a-spin class="" :spinning="spinning" tip="拼命加载中...">
        <a-card>
          <advance-table
            ref="table"
            class="doc-center-table"
            :data-source="dataSource"
            :columns="columns"
            title=""
            :row-key="(record, index) => index"
            @search="onSearch"
            @refresh="onRefresh"
            @reset="onReset"
            :format-conditions="true"
            :scroll="{ x: 2020, y }"
            :pagination="{
              current: pageCurr,
              pageSize: pageSize,
              total: total,
              showSizeChanger: true,
              showLessItems: true,
              showQuickJumper: true,
              pageSizeOptions: ['10', '20', '50', '100'],
              showTotal: (total, range) =>
                `第 ${range[0]}-${range[1]} 条,总计 ${total} 条`,
              onChange: onPageChange,
              onShowSizeChange: onSizeChange,
            }"
            :rowClassName="rowClassFn"
          >
          <advance-table ref="table" class="doc-center-table" :data-source="dataSource" :columns="columns" title=""
            :row-key="(record, index) => index" @search="onSearch" @refresh="onRefresh" @reset="onReset"
            :format-conditions="true" :scroll="{ x: 2020, y }" :pagination="{
                                current: pageCurr,
                                pageSize: pageSize,
                                total: total,
                                showSizeChanger: true,
                                showLessItems: true,
                                showQuickJumper: true,
                                pageSizeOptions: ['10', '20', '50', '100'],
                                showTotal: (total, range) =>
                                  `第 ${range[0]}-${range[1]} 条,总计 ${total} 条`,
                                onChange: onPageChange,
                                onShowSizeChange: onSizeChange,
                              }" :rowClassName="rowClassFn">
            <template slot="dataIndex" slot-scope="{ index }">
              {{ index + 1 }}
            </template>
            <template slot="title">
              <a-space>
                <span class="title">软件中心</span>
                <a-button
                  v-if="canUploadSoftware"
                  type="primary"
                  @click="showUpload"
                  >上传软件</a-button
                >
                <a-button v-if="canUploadSoftware" type="primary" @click="showUpload">上传软件</a-button>
              </a-space>
            </template>
            <template slot="tags" slot-scope="tags">
              <a-tag :color="tags.record.codeFlag ? 'green' : 'red'">{{ tags.text }}</a-tag>
            </template>
            <template slot="action" slot-scope="{ record }">
              <a-popover title="" trigger="hover">
                <div class="" slot="content" style="width: 450px">
                  <a-table
                    size="small"
                    :scroll="{ y: 300 }"
                    bordered
                    :columns="prodsColumns"
                    :data-source="record.links"
                    :pagination="false"
                    :expandRowByClick="true"
                    :row-key="(record1, index) => index"
                  >
                  <a-table size="small" :scroll="{ y: 300 }" bordered :columns="prodsColumns" :data-source="record.links"
                    :pagination="false" :expandRowByClick="true" :row-key="(record1, index) => index">
                  </a-table>
                </div>
                <a>适用机型</a>
              </a-popover>
              <template v-if="canDownloadSoftware">
                <a-divider type="vertical"></a-divider>
                <a
                  :disabled="!!record.soft.lockFlag && !isTester"
                  @click="download(record)"
                  >下载</a
                >
                <a :disabled="!!record.soft.lockFlag && !isTester" @click="download(record)">下载</a>
                <a-divider type="vertical"></a-divider>
              </template>
              <a-popover title="" trigger="hover">
                <a-space class="btn-grp" direction="vertical" slot="content">
                  <a-button
                    v-if="canUploadSoftware"
                    :disabled="!!record.soft.lockFlag"
                    type="primary"
                    @click="updateDesc(record)"
                    >更新说明</a-button
                  >
                  <a-button
                    v-if="record.soft.lockFlag !== -1 ? canLock : isTester"
                    type="primary"
                    @click="lock(record)"
                    >{{ record.soft.lockFlag ? "解锁" : "锁定" }}</a-button
                  >
                  <a-button
                    v-if="canUploadSoftware"
                    type="primary"
                    @click="handleEmailShow(record)"
                    >邮件通知</a-button
                  >
                  <a-button
                    type="primary"
                    :disabled="!isTester"
                    @click="handleConfirmDelete(record)"
                    >删除</a-button
                  >
                  <a-button v-if="canUploadSoftware" :disabled="!!record.soft.lockFlag" type="primary"
                    @click="updateDesc(record)">更新说明</a-button>
                  <a-button v-if="record.soft.lockFlag !== -1 ? canLock : isTester" type="primary"
                    @click="lock(record)">{{ record.soft.lockFlag ? "解锁" : "锁定" }}</a-button>
                  <a-button v-if="canUploadSoftware" type="primary" @click="handleEmailShow(record)">邮件通知</a-button>
                  <a-button type="primary" :disabled="!isTester" @click="handleConfirmDelete(record)">删除</a-button>
                  <template v-if="isCoder">
                    <a-button type="primary" v-if="record.codeFlag" @click="downloadSource(record)">下载源码</a-button>
                    <a-button type="primary" @click="uploadSourceClick(record)">上传源码</a-button>
                  </template>
                </a-space>
                <a>更多</a>
              </a-popover>
@@ -106,39 +65,22 @@
      </a-spin>
    </div>
    <!-- 上传软件 -->
    <a-modal
      :visible="uploadShow"
      :footer="null"
      :width="760"
      :title="onlyXls ? '更新发布说明' : '上传软件'"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="uploadCancel"
    >
    <a-modal :visible="uploadShow" :footer="null" :width="760" :title="onlyXls ? '更新发布说明' : '上传软件'" :destroyOnClose="true"
      :maskClosable="false" @cancel="uploadCancel">
      <div class="">
        <template v-if="!onlyXls">
          <a-row type="flex" class="row">
            <a-col flex="6em" class="label">更新时间</a-col>
            <a-col :flex="1">
              <a-date-picker
                format="YYYY-MM-DD HH:mm:ss"
                valueFormat="YYYY-MM-DD HH:mm:ss"
                :allowClear="false"
                :disabled-date="disabledDate"
                :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }"
                v-model="versionTime"
              />
              <a-date-picker format="YYYY-MM-DD HH:mm:ss" valueFormat="YYYY-MM-DD HH:mm:ss" :allowClear="false"
                :disabled-date="disabledDate" :show-time="{ defaultValue: moment('00:00:00', 'HH:mm:ss') }"
                v-model="versionTime" />
            </a-col>
          </a-row>
          <a-row type="flex" class="row">
            <a-col flex="6em" class="label">软件包</a-col>
            <a-col :flex="1">
              <a-upload
                class="upload"
                :before-upload="beforeUpload"
                @change="uploadChange"
                accept=".zip,.rar"
              >
              <a-upload class="upload" :before-upload="beforeUpload" @change="uploadChange" accept=".zip,.rar">
                <a-button type="primary">选择软件</a-button>
              </a-upload>
            </a-col>
@@ -147,12 +89,7 @@
        <a-row type="flex" class="row">
          <a-col flex="6em" class="label">软件说明</a-col>
          <a-col :flex="1">
            <a-upload
              class="upload"
              :before-upload="beforeUpload"
              @change="uploadChange1"
              accept=".xls,.xlsx"
            >
            <a-upload class="upload" :before-upload="beforeUpload" @change="uploadChange1" accept=".xls,.xlsx">
              <a-button type="primary">说明文件</a-button>
            </a-upload>
          </a-col>
@@ -170,795 +107,928 @@
        </div>
      </div>
    </a-modal>
    <pop
      :visible.sync="popVisible"
      :x="popPosition.x"
      :y="popPosition.y"
      :info="popInfo"
      :position="popPosition.dir"
    ></pop>
    <pop :visible.sync="popVisible" :x="popPosition.x" :y="popPosition.y" :info="popInfo" :position="popPosition.dir">
    </pop>
    <!-- 操作原因 -->
    <a-modal
      :visible="reasonVisible"
      :width="460"
      title="操作原因"
      :destroyOnClose="true"
      :maskClosable="false"
      @cancel="reasonCancel"
      @ok="reasonOk"
    >
    <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-input type="textarea" v-model="reason" placeHolder="请输入操作原因" />
      </a-form-model-item>
    </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 :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>
    <!-- 上传源码包 -->
    <a-modal :visible="uploadSourceShow" :footer="null" :width="760" title="上传软件源码包" :destroyOnClose="true"
      :maskClosable="false" @cancel="uploadSourceCancel">
      <div class="">
        <template>
          <a-row type="flex" class="row">
            <a-col flex="6em" class="label">对应软件</a-col>
            <a-col :flex="1">
              <a-select mode="multiple" placeholder="请选择对应的软件" show-search v-model="names" style="width: 36em;">
                <a-select-option v-for="(item, idx) in otherSoftList" :key="'soft_' + idx" :value="item.fileName">
                  {{ item.fileName }} <span class="version">({{ item.version }})</span>
                </a-select-option>
              </a-select>
            </a-col>
          </a-row>
          <a-row type="flex" class="row">
            <a-col flex="6em" class="label">软件源码包</a-col>
            <a-col :flex="1">
              <a-upload class="upload" :before-upload="beforeUpload" @change="sourceUploadChange" accept=".zip,.rar">
                <a-button type="primary">选择软件</a-button>
              </a-upload>
            </a-col>
          </a-row>
        </template>
        <div class="modal-footer">
          <a-button type="danger" @click="uploadSourceCancel"> 取消 </a-button>
          <a-button type="primary" @click="uploadSource"> 提交 </a-button>
        </div>
      </div>
    </a-modal>
  </div>
</template>
<script>
import AdvanceTable from "@/components/table/advance/AdvanceTable";
import checkPermit from "@/assets/js/tools/checkPermit";
import PERMITS from "@/assets/js/const/const_permits";
import DescRes from "./descRes";
import Pop from "./pop";
import offset from "@/assets/js/tools/offset";
import moment from "moment";
import { getUserList } from "../../permission/apis";
    import AdvanceTable from "@/components/table/advance/AdvanceTable";
    import checkPermit from "@/assets/js/tools/checkPermit";
    import PERMITS from "@/assets/js/const/const_permits";
    import DescRes from "./descRes";
    import Pop from "./pop";
    import offset from "@/assets/js/tools/offset";
    import moment from "moment";
    import { getUserList } from "../../permission/apis";
import { message, Modal } from "ant-design-vue";
    import { message, Modal } from "ant-design-vue";
import {
  getList,
  downLoadSoftware,
  excelParse,
  productSoftwareSubmit,
  applyModel,
  updateSoftwareLock,
  deleteSoftwareApi,
} from "./apis";
import { mapGetters } from "vuex";
import EmailCard from "../../components/emailCard";
import {
  searchDefaultMailUser,
  sendMail,
} from "../../components/emailCard/apis";
    import {
        getList,
        downLoadSoftware,
        excelParse,
        productSoftwareSubmit,
        applyModel,
        updateSoftwareLock,
        deleteSoftwareApi,
        downLoadCode,
        getFileNameByCreateTime,
        uploadCode,
    } from "./apis";
    import { mapGetters } from "vuex";
    import EmailCard from "../../components/emailCard";
    import {
        searchDefaultMailUser,
        sendMail,
    } from "../../components/emailCard/apis";
import { getRoleUser } from "@/pages/user/apis";
// TODO
// const tester = ["李桂华"];
    import { getRoleUser } from "@/pages/user/apis";
    // TODO
    // const tester = ["李桂华"];
export default {
  name: "",
  data() {
    return {
      mailList: [],
      tester: [],
      versionTime: moment().format("YYYY-MM-DD HH:mm:ss"),
      reasonVisible: false,
      reason: "",
      currentObj: null,
      popVisible: false,
      popPosition: {
        x: 0,
        y: 0,
        dir: "bottom",
      },
      popInfo: [],
      onlyXls: false,
      resData: [],
      file: null,
      file1: null,
      uploadShow: false,
      spinning: false,
      loading: false,
      pageCurr: 1,
      pageSize: 10,
      total: 0,
      y: 400,
      update: -1,
      conditions: {},
      columns: [
        {
          fixed: "left",
          title: "序号",
          dataIndex: "dataIndex",
          key: "dataIndex",
          align: "center",
          width: 60,
          noSearch: true,
          scopedSlots: { customRender: "dataIndex" },
        },
        {
          title: "状态",
          dataIndex: "soft.lockFlag",
          dataType: "select",
          align: "center",
          width: 140,
          visible: false,
          searchAble: true,
          noSearch: true,
          search: {
            default: 0,
            selectOptions: [
              {
                title: "全部",
                value: 11,
              },
              {
                title: "可用",
                value: 0,
              },
              {
                title: "不可用",
                value: 12,
              },
              {
                title: "待测试",
                value: -1,
              },
            ],
          },
          // customCell: this.customCell,
        },
        {
          title: "名称",
          dataIndex: "soft.fileName",
          align: "center",
          searchAble: true,
          customCell: this.customCell,
        },
        {
          title: "上传日期",
          dataIndex: "soft.createTime",
          align: "center",
          noSearch: true,
          customCell: this.customCell,
        },
        {
          title: "类型",
          dataIndex: "soft.type",
          align: "center",
          width: 180,
          noSearch: true,
          customCell: this.customCell,
        },
        {
          title: "版本",
          dataIndex: "soft.version",
          align: "center",
          searchAble: true,
          customCell: this.customCell,
        },
        {
          title: "负责人",
          dataIndex: "soft.owner",
          align: "center",
          searchAble: true,
          width: 160,
          customCell: this.customCell,
        },
        {
          title: "适用机型号",
          dataIndex: "applyModel",
          align: "center",
          searchAble: true,
          visible: false,
        },
        {
          title: "适用机料号",
          dataIndex: "applyMaterialCode",
          align: "center",
          searchAble: true,
          visible: false,
        },
        {
          title: "板号",
          dataIndex: "soft.boardNumber",
          align: "center",
          searchAble: true,
          customCell: this.customCell,
        },
        {
          title: "升级说明",
          dataIndex: "soft.releaseNotes",
          align: "center",
          noSearch: true,
          customCell: this.customCell,
        },
        {
          title: "最后一次操作原因",
          dataIndex: "soft.localReason",
          align: "center",
          noSearch: true,
          customCell: this.customCell,
        },
        {
          title: "操作",
          dataIndex: "operation",
          align: "center",
          width: 228,
          fixed: "right",
          scopedSlots: { customRender: "action" },
          noSearch: true,
        },
      ],
      dataSource: [],
      prodsColumns: [
        {
          title: "型号",
          dataIndex: "applyModel",
          align: "center",
          searchAble: true,
        },
        {
          title: "料号",
          dataIndex: "applyMaterialCode",
          align: "center",
          width: 180,
          noSearch: true,
        },
      ],
      emailShow: false,
      emailInfo: {
        title: "",
        content: "",
      },
      userList: [],
    };
  },
  components: {
    EmailCard,
    AdvanceTable,
    DescRes,
    Pop,
  },
  methods: {
    moment,
    rowClassFn(record) {
      let classList = [];
      if (record.soft.lockFlag == -1) {
        classList.push("locked");
      }
      return classList;
    },
    disabledDate(current) {
      // Can not select days before today and today
      return current > moment().endOf("day");
    },
    onSearch(conditions, searchOptions) {
      // console.log(conditions);
      // console.log(searchOptions, "options");
      this.pageCurr = 1;
      this.conditions = conditions;
      this.searchData();
    },
    onPageChange(page, pageSize) {
      this.pageCurr = page;
      this.pageSize = pageSize;
      this.searchData();
    },
    onSizeChange(current, size) {
      this.pageCurr = 1;
      this.pageSize = size;
      this.searchData();
    },
    onRefresh(conditions) {
      this.conditions = conditions;
      this.searchData();
    },
    onReset(conditions) {
      // console.log(conditions, "reset");
      this.conditions = conditions;
      this.searchData();
    },
    searchData() {
      const { pageCurr, pageSize, conditions } = this;
      let params = {};
      if (undefined == conditions["soft.lockFlag"]) {
        conditions["soft.lockFlag"] = 11;
      }
      Object.keys(conditions).forEach((v) => {
        switch (v) {
          case "soft.lockFlag":
            params["lockFlag"] = conditions[v];
            break;
          case "soft.fileName":
            params["fileName"] = conditions[v];
            break;
          case "soft.owner":
            params["owner"] = conditions[v];
            break;
          case "soft.boardNumber":
            params["boardNumber"] = conditions[v];
            break;
          case "soft.version":
            params["version"] = conditions[v];
            break;
          default:
            params[v] = conditions[v];
            break;
        }
      });
      getList(pageCurr, pageSize, params).then((res) => {
        res = res.data;
        // console.log(res);
        let data = [];
        let total = 0;
        if (res.code && res.data) {
          data = res.data2.list.map((v) => {
            let soft = v.softwares[0];
            return {
              id: soft.id,
              soft,
              links: v.softwares,
            };
          });
          total = res.data2.total;
        }
        this.dataSource = data;
        this.total = total;
        if (-1 == this.update) {
          this.update = Math.random();
        }
      });
    },
    download(obj) {
      const { id } = obj;
      let loading = this.$layer.loading();
      downLoadSoftware(id).then((res) => {
        // console.log(res, "===========");
        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
            ? decodeURI(matchRes[1].trim())
            : "未知文件名.zip";
          let link = document.createElement("a");
          link.style.display = "none";
          link.href = url;
          link.download = fileName;
          document.body.appendChild(link);
          link.click();
          this.$layer.close(loading);
          document.body.removeChild(link);
          window.URL.revokeObjectURL(url);
        } else {
          this.$layer.close(loading);
          this.$message.error("操作失败");
        }
      });
    },
    resize() {
      setTimeout(() => {
        this.update = Math.random();
      }, 200);
    },
    activeFN() {
      this.resize();
    },
    showUpload() {
      this.file = null;
      this.file1 = null;
      this.resData = [];
      this.onlyXls = false;
      this.versionTime = moment().format("YYYY-MM-DD HH:mm:ss");
      this.uploadShow = true;
    },
    updateDesc() {
      this.file = null;
      this.file1 = null;
      this.resData = [];
      this.onlyXls = true;
      this.uploadShow = true;
    },
    beforeUpload() {
      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.resData = [];
        return false;
      }
      const formData = new FormData();
      formData.append("multipartFile", this.file1);
      excelParse(formData).then((res) => {
        const { code, data, data2, msg } = res.data;
        let list = [];
        if (code && data) {
          list = data2;
          this.$message.success(msg);
        } else {
          this.$message.error("解析失败");
        }
        this.resData = list;
      });
    },
    uploadCancel() {
      this.uploadShow = false;
    },
    uploadSoftware() {
      if (!this.file) {
        this.$message.error("请选择要上传的软件包");
        return false;
      }
      if (!this.file1) {
        this.$message.error("请选择软件说明文件");
        return false;
      }
      if (!this.resData.length) {
        this.$message.error("软件说明文件解析异常");
        return false;
      }
      let info = this.resData[0];
      if (!info.boardNumber || !info.type) {
        this.$error({
          title: "系统提示",
          content: "缺少板号或软件类型,请输入板号和软件类型",
        });
        return false;
      }
      let loading = this.$layer.loading();
    export default {
        name: "",
        data() {
            return {
                mailList: [],
                tester: [],
                versionTime: moment().format("YYYY-MM-DD HH:mm:ss"),
                reasonVisible: false,
                reason: "",
                currentObj: null,
                popVisible: false,
                uploadSourceShow: false,
                names: [],
                otherSoftList: [],
                popPosition: {
                    x: 0,
                    y: 0,
                    dir: "bottom",
                },
                popInfo: [],
                onlyXls: false,
                resData: [],
                file: null,
                file1: null,
                sourceFile: null,
                uploadShow: false,
                spinning: false,
                loading: false,
                pageCurr: 1,
                pageSize: 10,
                total: 0,
                y: 400,
                update: -1,
                conditions: {},
                columns: [
                    {
                        fixed: "left",
                        title: "序号",
                        dataIndex: "dataIndex",
                        key: "dataIndex",
                        align: "center",
                        width: 60,
                        noSearch: true,
                        scopedSlots: { customRender: "dataIndex" },
                    },
                    {
                        title: "状态",
                        dataIndex: "soft.lockFlag",
                        dataType: "select",
                        align: "center",
                        width: 140,
                        visible: false,
                        searchAble: true,
                        noSearch: true,
                        search: {
                            default: 0,
                            selectOptions: [
                                {
                                    title: "全部",
                                    value: 11,
                                },
                                {
                                    title: "可用",
                                    value: 0,
                                },
                                {
                                    title: "不可用",
                                    value: 12,
                                },
                                {
                                    title: "待测试",
                                    value: -1,
                                },
                            ],
                        },
                        // customCell: this.customCell,
                    },
                    {
                        title: "名称",
                        dataIndex: "soft.fileName",
                        align: "center",
                        searchAble: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "上传日期",
                        dataIndex: "soft.createTime",
                        align: "center",
                        noSearch: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "是否已上传源码",
                        dataIndex: "codeFlagStr",
                        align: "center",
                        noSearch: true,
                        customCell: this.customCell,
            scopedSlots: { customRender: 'tags' },
                    },
          {
                        title: "源码包名称",
                        dataIndex: "codeName",
                        align: "center",
                        width: 180,
                        noSearch: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "类型",
                        dataIndex: "soft.type",
                        align: "center",
                        width: 180,
                        noSearch: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "版本",
                        dataIndex: "soft.version",
                        align: "center",
                        searchAble: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "负责人",
                        dataIndex: "soft.owner",
                        align: "center",
                        searchAble: true,
                        width: 160,
                        customCell: this.customCell,
                    },
                    {
                        title: "适用机型号",
                        dataIndex: "applyModel",
                        align: "center",
                        searchAble: true,
                        visible: false,
                    },
                    {
                        title: "适用机料号",
                        dataIndex: "applyMaterialCode",
                        align: "center",
                        searchAble: true,
                        visible: false,
                    },
                    {
                        title: "板号",
                        dataIndex: "soft.boardNumber",
                        align: "center",
                        searchAble: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "升级说明",
                        dataIndex: "soft.releaseNotes",
                        align: "center",
                        noSearch: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "最后一次操作原因",
                        dataIndex: "soft.localReason",
                        align: "center",
                        noSearch: true,
                        customCell: this.customCell,
                    },
                    {
                        title: "操作",
                        dataIndex: "operation",
                        align: "center",
                        width: 228,
                        fixed: "right",
                        scopedSlots: { customRender: "action" },
                        noSearch: true,
                    },
                ],
                dataSource: [],
                prodsColumns: [
                    {
                        title: "型号",
                        dataIndex: "applyModel",
                        align: "center",
                        searchAble: true,
                    },
                    {
                        title: "料号",
                        dataIndex: "applyMaterialCode",
                        align: "center",
                        width: 180,
                        noSearch: true,
                    },
                ],
                emailShow: false,
                emailInfo: {
                    title: "",
                    content: "",
                },
                userList: [],
            };
        },
        components: {
            EmailCard,
            AdvanceTable,
            DescRes,
            Pop,
        },
        methods: {
            moment,
            rowClassFn(record) {
                let classList = [];
                if (record.soft.lockFlag == -1) {
                    classList.push("locked");
                }
                return classList;
            },
            disabledDate(current) {
                // Can not select days before today and today
                return current > moment().endOf("day");
            },
            onSearch(conditions, searchOptions) {
                // console.log(conditions);
                // console.log(searchOptions, "options");
                this.pageCurr = 1;
                this.conditions = conditions;
                this.searchData();
            },
            onPageChange(page, pageSize) {
                this.pageCurr = page;
                this.pageSize = pageSize;
                this.searchData();
            },
            onSizeChange(current, size) {
                this.pageCurr = 1;
                this.pageSize = size;
                this.searchData();
            },
            onRefresh(conditions) {
                this.conditions = conditions;
                this.searchData();
            },
            onReset(conditions) {
                // console.log(conditions, "reset");
                this.conditions = conditions;
                this.searchData();
            },
            searchData() {
                const { pageCurr, pageSize, conditions } = this;
                let params = {};
                if (undefined == conditions["soft.lockFlag"]) {
                    conditions["soft.lockFlag"] = 11;
                }
                Object.keys(conditions).forEach((v) => {
                    switch (v) {
                        case "soft.lockFlag":
                            params["lockFlag"] = conditions[v];
                            break;
                        case "soft.fileName":
                            params["fileName"] = conditions[v];
                            break;
                        case "soft.owner":
                            params["owner"] = conditions[v];
                            break;
                        case "soft.boardNumber":
                            params["boardNumber"] = conditions[v];
                            break;
                        case "soft.version":
                            params["version"] = conditions[v];
                            break;
                        default:
                            params[v] = conditions[v];
                            break;
                    }
                });
                getList(pageCurr, pageSize, params).then((res) => {
                    res = res.data;
                    // console.log(res);
                    let data = [];
                    let total = 0;
                    if (res.code && res.data) {
                        data = res.data2.list.map((v) => {
                            let soft = v.softwares[0];
                            return {
                                id: soft.id,
                                fileName: v.fileName,
                                codeFlag: v.codeFlag,
                codeName: v.codeName || '--',
                                codeFlagStr: v.codeFlag ? '已上传源码' : '未上传源码',
                                soft,
                                links: v.softwares,
                            };
                        });
                        total = res.data2.total;
                    }
                    this.dataSource = data;
                    this.total = total;
                    if (-1 == this.update) {
                        this.update = Math.random();
                    }
                });
            },
            download(obj) {
                const { id } = obj;
                let loading = this.$layer.loading();
                downLoadSoftware(id).then((res) => {
                    // console.log(res, "===========");
                    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
                            ? decodeURI(matchRes[1].trim())
                            : "未知文件名.zip";
                        let link = document.createElement("a");
                        link.style.display = "none";
                        link.href = url;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        this.$layer.close(loading);
                        document.body.removeChild(link);
                        window.URL.revokeObjectURL(url);
                    } else {
                        this.$layer.close(loading);
                        this.$message.error("操作失败");
                    }
                });
            },
            resize() {
                setTimeout(() => {
                    this.update = Math.random();
                }, 200);
            },
            activeFN() {
                this.resize();
            },
            showUpload() {
                this.file = null;
                this.file1 = null;
                this.resData = [];
                this.onlyXls = false;
                this.versionTime = moment().format("YYYY-MM-DD HH:mm:ss");
                this.uploadShow = true;
            },
            updateDesc() {
                this.file = null;
                this.file1 = null;
                this.resData = [];
                this.onlyXls = true;
                this.uploadShow = true;
            },
            beforeUpload() {
                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.resData = [];
                    return false;
                }
                const formData = new FormData();
                formData.append("multipartFile", this.file1);
                excelParse(formData).then((res) => {
                    const { code, data, data2, msg } = res.data;
                    let list = [];
                    if (code && data) {
                        list = data2;
                        this.$message.success(msg);
                    } else {
                        this.$message.error("解析失败");
                    }
                    this.resData = list;
                });
            },
            uploadCancel() {
                this.uploadShow = false;
            },
            uploadSoftware() {
                if (!this.file) {
                    this.$message.error("请选择要上传的软件包");
                    return false;
                }
                if (!this.file1) {
                    this.$message.error("请选择软件说明文件");
                    return false;
                }
                if (!this.resData.length) {
                    this.$message.error("软件说明文件解析异常");
                    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("file1", this.file);
      formData.append("file2", this.file1);
      formData.append("fontUpdateTime", this.versionTime);
      formData.append("softwareStr", JSON.stringify(this.resData));
      productSoftwareSubmit(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);
        });
    },
    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("file1", this.file);
                formData.append("file2", this.file1);
                formData.append("fontUpdateTime", this.versionTime);
                formData.append("softwareStr", JSON.stringify(this.resData));
                productSoftwareSubmit(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);
                    });
            },
            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("解析失败");
          }
          this.$layer.close(loading);
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
    },
    cellMouseenter(e, obj) {
      // console.log("enter", e, obj);
      const wraper = this.$refs.wraper;
      const { clientHeight, clientWidth } = wraper;
      const { target, clientX, clientY } = e;
      let { left: x, top: y } = offset(wraper);
      x = clientX - x;
      y = clientY - y;
      // 如果clientHeight 小于380 * 2 则左右布局
      let dir = "bottom";
      if (clientHeight < 380 * 2) {
        if (x + 420 + 18 > clientWidth) {
          dir = "left";
        } else {
          dir = "right";
        }
        if (y < 180) {
          y = 180;
        } else if (y > clientHeight - 378) {
          y = clientHeight / 2;
        }
      } else {
        if (y + 18 + 360 > clientHeight) {
          // y = clientHeight - 378;
          dir = "top";
        } else {
          dir = "bottom";
        }
        if (x < 300) {
          x = 300;
        }
        if (x + 300 > clientWidth) {
          x = clientWidth - 300;
        }
      }
      this.popPosition.x = x;
      this.popPosition.y = y;
      this.popPosition.dir = dir;
      this.popInfo = obj.links;
      this.popVisible = true;
    },
    cellMouseleave(e, obj) {
      // console.log("leave", obj);
      this.popVisible = false;
    },
    customCell(record) {
      return {
        on: {
          mouseenter: (e) => this.cellMouseenter(e, record),
          mouseleave: (e) => this.cellMouseleave(e, record),
        },
      };
    },
    reasonCancel() {
      this.reasonVisible = false;
    },
    reasonOk() {
      let {
        soft: { fileUrl, lockFlag },
      } = this.currentObj;
      // 多传一个当前状态
      let lockFlagNow = lockFlag;
      lockFlag = !lockFlag * 1;
      let params = {
        fileUrl,
        localReason: this.reason,
        lockFlag,
        lockFlagNow,
      };
      updateSoftwareLock(params).then((res) => {
        const { code, data } = res.data;
        if (code && data) {
          this.$message.success("操作成功");
          this.reasonVisible = false;
          // 如果是测试人员解锁确认 则自动发送邮件
          if (lockFlagNow == -1 && this.isTester) {
            this.sendEmail();
          }
          this.searchData();
        } else {
          this.$message.error("操作失败");
        }
      });
    },
    sendEmail() {
      let { title, content } = this.handleEmailShow(this.currentObj, true);
      let params = { mailList: this.mailList, title, content };
      sendMail(params);
    },
    lock(record) {
      this.reason = "";
      this.currentObj = record;
      this.reasonVisible = true;
    },
    handleEmailShow(record, get) {
      this.emailInfo.title =
        "[软件发布记录]" +
        record.soft.fileName +
        " 版本号:" +
        record.soft.version;
      let { soft, links } = record;
      let content = [];
      content.push("软件基本信息");
      content.push("文件名称: " + soft.fileName);
      content.push("板号: " + soft.boardNumber);
      content.push("软件类型: " + soft.type);
      content.push("软件版本: " + soft.version);
      content.push("软件基于版本: " + soft.basedVersion);
      content.push("软件负责人: " + soft.owner);
      content.push("归档日期: " + soft.filingDate);
      content.push("软件类型: " + soft.type);
      content.push("软件适用机型");
      links.forEach((v) => {
        content.push(
          "物料编码: " + v.applyMaterialCode + " 规格型号: " + v.applyModel
        );
      });
      content.push("发布说明: " + soft.releaseNotes);
      this.emailInfo.content = content.join("\n");
      if (get) {
        return {
          title: this.emailInfo.title,
          content: content.join("\n"),
        };
      }
      this.emailShow = true;
    },
    emailCancel() {
      this.emailShow = false;
    },
    searchAllUserList() {
      getUserList()
        .then((res) => {
          let rs = res.data;
          if (rs.code && rs.data) {
            this.userList = rs.data2;
            this.searchDefaultMailUser();
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    searchDefaultMailUser() {
      // 软件 type为1
      let type = 1;
      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.userList
          .filter((o) => data.includes(o.name) && o.mail)
          .map((item) => {
            return item.mail;
          });
      });
    },
    getRoleUser() {
      getRoleUser(0)
        .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);
        });
    },
    handleConfirmDelete(obj) {
      Modal.confirm({
        content: () => "删除当前软件,删除后无法恢复,请注意!!!",
        onOk: async () => {
          try {
            const res = await deleteSoftwareApi(
              obj.soft.fileName,
              obj.soft.version
            );
            const rs = res.data;
            if (rs.code === 1 && rs.data) {
              this.$message.success("删除成功。");
            } else {
              this.$message.error("删除失败!!!");
            }
            this.searchData();
          } catch (e) {
            this.$message.error("删除失败,请联系开发人员!!!");
            console.log(e);
          }
        },
      });
    },
  },
  watch: {
    update(n) {
      if (-1 != n && !this._inactive) {
        this.$nextTick(() => {
          const table = this.$refs.table;
          const header = document.querySelectorAll(
            ".doc-center-table .ant-table-header"
          )[0].clientHeight;
          const bar = document.querySelectorAll(".header-bar")[0].clientHeight;
          if (table.fullScreen) {
            this.y = table.$el.clientHeight - bar - header - 64;
          } else {
            const wraper = this.$refs.wraper.clientHeight;
            const card = document.querySelectorAll(".ant-card-body")[0];
            const { paddingBottom, paddingTop } = getComputedStyle(card, null);
            const h =
              wraper -
              header -
              64 -
              bar -
              parseInt(paddingBottom) -
              parseInt(paddingTop);
            // console.log(h, "h",wraper, header, bar );
            this.y = h;
          }
        });
      }
    },
    affixed() {
      setTimeout(() => {
        this.update = Math.random();
      }, 200);
    },
  },
  computed: {
    ...mapGetters("account", ["permits", "user"]),
    ...mapGetters("setting", ["affixed"]),
    canUploadSoftware() {
      return checkPermit(PERMITS.uploadSoftware, this.permits);
    },
    canDownloadSoftware() {
      return checkPermit(PERMITS.downloadSoftware, this.permits);
    },
    canLock() {
      return checkPermit(PERMITS.lockOther, this.permits);
    },
    isTester() {
      return this.tester.some((v) => v == this.user.name);
    },
  },
  mounted() {
    this.getRoleUser();
    this.searchData();
    this.searchAllUserList();
    window.addEventListener("resize", this.resize);
  },
  destroyed() {
    window.removeEventListener("resize", this.resize);
  },
};
                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("解析失败");
                        }
                        this.$layer.close(loading);
                    })
                    .catch((error) => {
                        this.$layer.close(loading);
                        console.log(error);
                    });
            },
            cellMouseenter(e, obj) {
                // console.log("enter", e, obj);
                const wraper = this.$refs.wraper;
                const { clientHeight, clientWidth } = wraper;
                const { target, clientX, clientY } = e;
                let { left: x, top: y } = offset(wraper);
                x = clientX - x;
                y = clientY - y;
                // 如果clientHeight 小于380 * 2 则左右布局
                let dir = "bottom";
                if (clientHeight < 380 * 2) {
                    if (x + 420 + 18 > clientWidth) {
                        dir = "left";
                    } else {
                        dir = "right";
                    }
                    if (y < 180) {
                        y = 180;
                    } else if (y > clientHeight - 378) {
                        y = clientHeight / 2;
                    }
                } else {
                    if (y + 18 + 360 > clientHeight) {
                        // y = clientHeight - 378;
                        dir = "top";
                    } else {
                        dir = "bottom";
                    }
                    if (x < 300) {
                        x = 300;
                    }
                    if (x + 300 > clientWidth) {
                        x = clientWidth - 300;
                    }
                }
                this.popPosition.x = x;
                this.popPosition.y = y;
                this.popPosition.dir = dir;
                this.popInfo = obj.links;
                this.popVisible = true;
            },
            cellMouseleave(e, obj) {
                // console.log("leave", obj);
                this.popVisible = false;
            },
            customCell(record) {
                return {
                    on: {
                        mouseenter: (e) => this.cellMouseenter(e, record),
                        mouseleave: (e) => this.cellMouseleave(e, record),
                    },
                };
            },
            reasonCancel() {
                this.reasonVisible = false;
            },
            reasonOk() {
                let {
                    soft: { fileUrl, lockFlag },
                } = this.currentObj;
                // 多传一个当前状态
                let lockFlagNow = lockFlag;
                lockFlag = !lockFlag * 1;
                let params = {
                    fileUrl,
                    localReason: this.reason,
                    lockFlag,
                    lockFlagNow,
                };
                updateSoftwareLock(params).then((res) => {
                    const { code, data } = res.data;
                    if (code && data) {
                        this.$message.success("操作成功");
                        this.reasonVisible = false;
                        // 如果是测试人员解锁确认 则自动发送邮件
                        if (lockFlagNow == -1 && this.isTester) {
                            this.sendEmail();
                        }
                        this.searchData();
                    } else {
                        this.$message.error("操作失败");
                    }
                });
            },
            sendEmail() {
                let { title, content } = this.handleEmailShow(this.currentObj, true);
                let params = { mailList: this.mailList, title, content };
                sendMail(params);
            },
            lock(record) {
                this.reason = "";
                this.currentObj = record;
                this.reasonVisible = true;
            },
            handleEmailShow(record, get) {
                this.emailInfo.title =
                    "[软件发布记录]" +
                    record.soft.fileName +
                    " 版本号:" +
                    record.soft.version;
                let { soft, links } = record;
                let content = [];
                content.push("软件基本信息");
                content.push("文件名称: " + soft.fileName);
                content.push("板号: " + soft.boardNumber);
                content.push("软件类型: " + soft.type);
                content.push("软件版本: " + soft.version);
                content.push("软件基于版本: " + soft.basedVersion);
                content.push("软件负责人: " + soft.owner);
                content.push("归档日期: " + soft.filingDate);
                content.push("软件类型: " + soft.type);
                content.push("软件适用机型");
                links.forEach((v) => {
                    content.push(
                        "物料编码: " + v.applyMaterialCode + " 规格型号: " + v.applyModel
                    );
                });
                content.push("发布说明: " + soft.releaseNotes);
                this.emailInfo.content = content.join("\n");
                if (get) {
                    return {
                        title: this.emailInfo.title,
                        content: content.join("\n"),
                    };
                }
                this.emailShow = true;
            },
            emailCancel() {
                this.emailShow = false;
            },
            searchAllUserList() {
                getUserList()
                    .then((res) => {
                        let rs = res.data;
                        if (rs.code && rs.data) {
                            this.userList = rs.data2;
                            this.searchDefaultMailUser();
                        }
                    })
                    .catch((error) => {
                        console.log(error);
                    });
            },
            searchDefaultMailUser() {
                // 软件 type为1
                let type = 1;
                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.userList
                        .filter((o) => data.includes(o.name) && o.mail)
                        .map((item) => {
                            return item.mail;
                        });
                });
            },
            getRoleUser() {
                getRoleUser(0)
                    .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);
                    });
            },
            handleConfirmDelete(obj) {
                Modal.confirm({
                    content: () => "删除当前软件,删除后无法恢复,请注意!!!",
                    onOk: async () => {
                        try {
                            const res = await deleteSoftwareApi(
                                obj.soft.fileName,
                                obj.soft.version
                            );
                            const rs = res.data;
                            if (rs.code === 1 && rs.data) {
                                this.$message.success("删除成功。");
                            } else {
                                this.$message.error("删除失败!!!");
                            }
                            this.searchData();
                        } catch (e) {
                            this.$message.error("删除失败,请联系开发人员!!!");
                            console.log(e);
                        }
                    },
                });
            },
            // 查询其他版本 与当前软件上传日期前三天内的列表
            getOtherSoft(date) {
                return getFileNameByCreateTime(date).then((res) => {
                    let { code, data, data2 } = res.data;
                    let list = [];
                    if (code && data) {
                        console.log(data);
                        list = data2;
                    }
                    this.otherSoftList = list;
                    return list;
                })
                    .catch((err) => {
                        console.log(err);
                        return [];
                    });
            },
            sourceUploadChange(data) {
                const { file, fileList } = data;
                if (fileList.length > 1) {
                    fileList.shift();
                }
                if (fileList.length) {
                    this.sourceFile = fileList[0].originFileObj;
                } else {
                    this.sourceFile = null;
                }
            },
            // 上传源码包
            uploadSource(record) {
                if (!this.sourceFile) {
                    this.$message.error("请选择要上传的源码包");
                    return false;
                }
                if (!this.names.length) {
                    this.$message.error("请选择源码包对应的软件");
                    return false;
                }
                let loading = this.$layer.loading();
                const formData = new FormData();
                formData.append("file", this.sourceFile);
                formData.append("fileNames", this.names.join(','));
                uploadCode(formData)
                    .then((res) => {
                        let { code, data, msg } = res.data;
                        if (code) {
                            this.uploadSourceShow = false;
                            this.$message.success('上传成功');
                            this.searchData();
                        } else {
                            this.$message.error('上传失败');
                        }
                        this.$layer.close(loading);
                    })
                    .catch((error) => {
                        this.$layer.close(loading);
                        console.log(error);
                    });
            },
            // 下载源码包
            downloadSource(record) {
                let loading = this.$layer.loading();
                downLoadCode(record.fileName).then((res) => {
                    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
                            ? decodeURI(matchRes[1].trim())
                            : "未知文件名.zip";
                        let link = document.createElement("a");
                        link.style.display = "none";
                        link.href = url;
                        link.download = fileName;
                        document.body.appendChild(link);
                        link.click();
                        this.$layer.close(loading);
                        document.body.removeChild(link);
                        window.URL.revokeObjectURL(url);
                    } else {
                        this.$layer.close(loading);
                        this.$message.error("操作失败");
                    }
                });
            },
            async uploadSourceClick(obj) {
                console.log('obj', obj, '=============');
                this.currentObj = obj;
                let date = obj.soft.createTime.split(' ')[0];
                await this.getOtherSoft(date);
                this.names = [obj.fileName];
                this.uploadSourceShow = true;
            },
            uploadSourceCancel() {
                this.uploadSourceShow = false;
            },
        },
        watch: {
            update(n) {
                if (-1 != n && !this._inactive) {
                    this.$nextTick(() => {
                        const table = this.$refs.table;
                        const header = document.querySelectorAll(
                            ".doc-center-table .ant-table-header"
                        )[0].clientHeight;
                        const bar = document.querySelectorAll(".header-bar")[0].clientHeight;
                        if (table.fullScreen) {
                            this.y = table.$el.clientHeight - bar - header - 64;
                        } else {
                            const wraper = this.$refs.wraper.clientHeight;
                            const card = document.querySelectorAll(".ant-card-body")[0];
                            const { paddingBottom, paddingTop } = getComputedStyle(card, null);
                            const h =
                                wraper -
                                header -
                                64 -
                                bar -
                                parseInt(paddingBottom) -
                                parseInt(paddingTop);
                            // console.log(h, "h",wraper, header, bar );
                            this.y = h;
                        }
                    });
                }
            },
            affixed() {
                setTimeout(() => {
                    this.update = Math.random();
                }, 200);
            },
        },
        computed: {
            ...mapGetters("account", ["permits", "user"]),
            ...mapGetters("setting", ["affixed"]),
            canUploadSoftware() {
                return checkPermit(PERMITS.uploadSoftware, this.permits);
            },
            canDownloadSoftware() {
                return checkPermit(PERMITS.downloadSoftware, this.permits);
            },
            canLock() {
                return checkPermit(PERMITS.lockOther, this.permits);
            },
            isTester() {
                return this.tester.some((v) => v == this.user.name);
            },
            isCoder() {
                return '李文涛' == this.user.name;
            }
        },
        mounted() {
            this.getRoleUser();
            this.searchData();
            this.searchAllUserList();
            window.addEventListener("resize", this.resize);
        },
        destroyed() {
            window.removeEventListener("resize", this.resize);
        },
    };
</script>
<style scoped lang="less">
.main {
  height: 100%;
  position: relative;
  .inner {
    position: absolute;
    left: 0;
@@ -967,58 +1037,79 @@
    bottom: 0;
  }
}
/deep/table {
  table-layout: fixed;
}
.modal-footer {
  text-align: right;
  button + button {
  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 {
.row~.row {
  margin-top: 10px;
}
.upload {
  display: flex;
  /deep/.ant-upload-list {
    flex: 1;
    position: relative;
    & > div {
    &>div {
      position: absolute;
      left: 0;
      right: 0;
    }
  }
}
.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;
}
/deep/.locked > td {
/deep/.locked>td {
  background: #fec54b;
}
/deep/.locked.locked.locked.ant-table-row-hover > td,
/deep/.locked.locked.locked:hover > td {
/deep/.locked.locked.locked.ant-table-row-hover>td,
/deep/.locked.locked.locked:hover>td {
  background: #fcd583;
}
.version {
  color: #090;
  display: inline-block;
  font-weight: bold;
  padding: 0 0.4em;
  margin-left: 0.4em;
}
</style>