From 36704dbc78007ca051633aa015c1094de3a2630a Mon Sep 17 00:00:00 2001 From: he wei <858544502@qq.com> Date: 星期五, 12 一月 2024 18:01:20 +0800 Subject: [PATCH] UA 技术规格书 --- src/pages/resourceManage/specification/rowRes.vue | 98 ++ src/pages/resourceManage/product/list.vue | 7 src/pages/resourceManage/specification/versionList.vue | 130 +++ src/pages/resourceManage/specification/history.vue | 424 ++++++++++++ src/pages/resourceManage/specification/list.vue | 996 +++++++++++++++++++++++++++++ src/pages/resourceManage/specification/pop.vue | 176 +++++ src/pages/resourceManage/specification/index.js | 2 src/router/config.js | 16 src/pages/resourceManage/specification/apis.js | 86 ++ src/pages/resourceManage/specification/descRes.vue | 94 ++ 10 files changed, 2,026 insertions(+), 3 deletions(-) diff --git a/src/pages/resourceManage/product/list.vue b/src/pages/resourceManage/product/list.vue index 29269f8..cc41d4c 100644 --- a/src/pages/resourceManage/product/list.vue +++ b/src/pages/resourceManage/product/list.vue @@ -1208,16 +1208,19 @@ } const { pageCurr, pageSize, conditions, columns } = this; let params = {}; + let col, index; Object.keys(conditions).forEach((v) => { switch (v) { case "isNormal": if (conditions[v]) { params["customCode"] = ""; - columns.forEach((val) => { + columns.forEach((val, idx) => { if (val.dataIndex == "customCode") { - val.search.value = ""; + col = { ...val, search: { value: "", backup: "" } }; + index = idx; } }); + this.$set(this.columns, index, col); } break; case "customCode": diff --git a/src/pages/resourceManage/specification/apis.js b/src/pages/resourceManage/specification/apis.js new file mode 100644 index 0000000..f9068ad --- /dev/null +++ b/src/pages/resourceManage/specification/apis.js @@ -0,0 +1,86 @@ +import axios from "@/assets/axios"; + +/** + * 鍒楄〃 + * @returns + */ +export const getList = (pageNum, pageSize, data) => { + return axios({ + method: "POST", + url: "technicalSpecification/getInfo", + params: { pageNum, pageSize, ...data }, + }); +}; + +/** + * 瑙f瀽瑙勬牸涔﹁鏄� + * multipartFile + * @returns + */ +export const excelParse = (data) => { + return axios({ + method: "POST", + url: "technicalSpecification/excelParse", + headers: { + "Content-Type": "multipart/form-data", + }, + data, + }); +}; + +/** + * 瑙f瀽瑙勬牸涔﹁鏄� + * file1 file2 + * technicalSpecificationStr + * @returns + */ +export const upload = (data) => { + return axios({ + method: "POST", + url: "technicalSpecification/upload", + headers: { + "Content-Type": "multipart/form-data", + }, + data, + }); +}; + +/** + * 鏇存柊閿佸畾鐘舵�� + * {id lockFlag reason} + * @returns + */ +export const updateLock = (params) => { + return axios({ + method: "POST", + url: "technicalSpecification/updateLock", + params, + }); +}; + +/** + * 鏌ヨ鎸囧畾id鐨勮鏄庝功鐨勯攣瀹氭棩蹇� + * {id} + * @returns + */ +export const getLogs = (id) => { + return axios({ + method: "GET", + url: "technicalSpecificationLog/getLockLogInfoById", + params: { id }, + }); +}; + + +/** + * 鏌ヨ鎸囧畾鎶�鏈鏍间功鐨勬墍鏈夌増鏈� + * {applyCustomCode, applyMaterialCode, applyModel} + * @returns + */ +export const getVersions = (params) => { + return axios({ + method: "POST", + url: "technicalSpecification/getVersionByInfo", + params, + }); +}; \ No newline at end of file diff --git a/src/pages/resourceManage/specification/descRes.vue b/src/pages/resourceManage/specification/descRes.vue new file mode 100644 index 0000000..603b87f --- /dev/null +++ b/src/pages/resourceManage/specification/descRes.vue @@ -0,0 +1,94 @@ +<template> + <div class=""> + <table class="table"> + <tbody> + <tr> + <th class="title" colspan="6">鏂囦欢鍩烘湰淇℃伅</th> + </tr> + <tr> + <th class="col-1">鏂囦欢鍚嶇О</th> + <td colspan="5">{{ info.fileName }}</td> + </tr> + <tr> + <th class="col-1">杞欢绫诲瀷</th> + <td colspan="5">{{ info.type }}</td> + </tr> + <tr> + <th class="col-1">鏂囦欢鐗堟湰</th> + <td colspan="1">{{ info.version }}</td> + <th class="col-1">鍩轰簬鐗堟湰</th> + <td colspan="3">{{ info.basedVersion }}</td> + </tr> + <tr> + <th class="col-1">璐熻矗浜�</th> + <td colspan="1">{{ info.owner }}</td> + <th class="col-1">褰掓。鏃ユ湡</th> + <td colspan="3">{{ info.filingDate }}</td> + </tr> + <tr> + <th class="title" colspan="6">瑙勬牸涔﹂�傜敤鏈哄瀷</th> + </tr> + <tr> + <th class="col-1">鐗╂枡缂栫爜</th> + <td colspan="1">{{ info.applyMaterialCode }}</td> + <th class="col-1">瑙勬牸鍨嬪彿</th> + <td colspan="1">{{ info.applyModel }}</td> + <th class="col-1">瀹氬埗鍗曞彿</th> + <td colspan="1">{{ info.applyCustomCode }}</td> + </tr> + <tr> + <th class="col-1">鍙戝竷璇存槑</th> + <td colspan="5">{{ info.releaseNotes }}</td> + </tr> + </tbody> + </table> + </div> +</template> + +<script> +export default { + name: "", + props: { + info: { + type: Object, + default() { + return {}; + }, + }, + }, + data() { + return {}; + }, + computed: {}, + watch: {}, + methods: {}, + + mounted() {}, +}; +</script> + +<style lang="less" scoped> +.table { + width: 100%; + // table-layout: fixed; + border-collapse: collapse; + th, + td { + border: 1px #333 solid; + padding: 4px; + } + td { + // color: #13c2c2; + color: #333; + } + .title { + font-weight: 900; + padding-left: 2em; + font-style: italic; + } +} +.col-1 { + // word-break:break-all; + width: 6.4em; +} +</style> diff --git a/src/pages/resourceManage/specification/history.vue b/src/pages/resourceManage/specification/history.vue new file mode 100644 index 0000000..5f0a2da --- /dev/null +++ b/src/pages/resourceManage/specification/history.vue @@ -0,0 +1,424 @@ +<template> + <div class="main"> + <a-layout class="main"> + <a-layout-sider width="260"> + <list class="list" :list="versionList" @select="selectChanged"></list> + </a-layout-sider> + <a-layout> + <a-layout-header> + <a-card> + <a-descriptions title="璇︽儏" bordered> + <a-descriptions-item label="鏂囦欢鍚嶇О">{{ + currentVersion.fileName + }}</a-descriptions-item> + <a-descriptions-item label="鐗堟湰鍙�">{{ + currentVersion.version + }}</a-descriptions-item> + <a-descriptions-item label="涓婁紶鏃堕棿">{{ + currentVersion.createTime + }}</a-descriptions-item> + <a-descriptions-item label="璐熻矗浜�">{{ + currentVersion.owner + }}</a-descriptions-item> + <a-descriptions-item label="鏂囦欢绫诲瀷">{{ + currentVersion.type + }}</a-descriptions-item> + <a-descriptions-item label="褰掓。鏃ユ湡">{{ + currentVersion.filingDate + }}</a-descriptions-item> + <a-descriptions-item label="鍙戝竷璇存槑">{{ + currentVersion.releaseNotes + }}</a-descriptions-item> + </a-descriptions> + </a-card> + </a-layout-header> + <a-layout-content> + <div class="wraper" ref="wraper"> + <div class="inner"> + <div class="title">閫傜敤浜у搧</div> + <a-table + v-if="currentVersion.fileName" + ref="aTable" + size="small" + bordered + :columns="columns" + :data-source="dataSource" + :pagination="false" + rowKey="id" + > + </a-table> + </div> + </div> + </a-layout-content> + <a-layout-footer> + <a-card> + <template> + <a-button + v-if="currentVersion.lockFlag == 0" + type="primary" + @click="view(currentVersion)" + >棰勮</a-button + > + <a-button + v-if="canLock()" + type="primary" + @click="lock" + >閿佸畾</a-button + > + <a-button + v-if="canUnLock()" + type="primary" + @click="lock()" + >瑙i攣</a-button + > + <a-button type="primary" @click="viewLog">閿佸畾鏃ュ織</a-button> + </template> + </a-card> + </a-layout-footer> + </a-layout> + </a-layout> + <!-- 鎿嶄綔鍘熷洜 --> + <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-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.status == 0 ? 'red' : 'green'" + > + <div> + <span class="user">{{ item.userName }}</span> 鍦� + <span class="time">{{ item.createTime }}</span> + {{ item.status == 0 ? "閿佸畾" : "瑙i攣" }}浜嗙増鏈� + <span class="version">{{ item.fileVersion }}</span> + </div> + <div>鎿嶄綔鍘熷洜: {{ item.reason ? item.reason : "鏃�" }}</div> + </a-timeline-item> + </a-timeline> + <a-empty v-else /> + </div> + </a-modal> + </div> +</template> + +<script> +import List from "./versionList"; +import getWebUrl from "@/assets/js/tools/getWebUrl"; +import { updateLock, getVersions, getLogs } from "./apis"; +import checkPermit from "@/assets/js/tools/checkPermit"; +import PERMITS from "@/assets/js/const/const_permits"; +import { mapGetters } from "vuex"; +export default { + name: "", + + data() { + let { applyMaterialCode, applyModel, applyCustomCode } = this.$route.query; + return { + logList: [], + logVisible: false, + reasonVisible: false, + reason: "", + applyMaterialCode, + applyModel, + applyCustomCode, + versionList: [], + webUrl: getWebUrl(), + currentVersion: {}, + columns: [ + { + title: "鐗╂枡缂栫爜", + dataIndex: "applyMaterialCode", + align: "center", + }, + { + title: "鐗╂枡鍨嬪彿", + dataIndex: "applyModel", + align: "center", + }, + { + title: "瀹氬埗鍗曞彿", + dataIndex: "applyCustomCode", + align: "center", + }, + ], + dataSource: [], + }; + }, + components: { + List, + }, + computed: { + ...mapGetters("account", ["permits", 'user']), + canUpload() { + return checkPermit(PERMITS.uploadSoftware, this.permits); + }, + canDownload() { + return checkPermit(PERMITS.downloadSoftware, this.permits); + }, + }, + watch: {}, + methods: { + canLock() { + let row = this.currentVersion; + let uname = this.user.name; + return row.owner == uname && row.lockFlag == 0; + }, + canUnLock() { + let row = this.currentVersion; + let uname = this.user.name; + // flag 涓�1 鏄彲鎿嶄綔鐨� + return row.owner == uname && row.lockFlag == 1 && row.flag == 1; + }, + view(obj) { + let { fileUrl } = obj; + window.open(this.webUrl + fileUrl); + }, + viewLog() { + // console.log(obj); + const { id } = this.currentVersion; + getLogs(id).then((res) => { + const { code, data, data2 } = res.data; + if (code) { + this.logList = data2; + this.logVisible = true; + } else { + this.$message.error("鏃ュ織鏌ヨ澶辫触"); + } + }); + }, + logCancel() { + this.logVisible = false; + }, + downloadFile() { + // console.log(record); + let record = this.currentVersion; + let loading = this.$layer.loading(); + let link = document.createElement("a"); + link.style.display = "none"; + let url = this.webUrl + record.fileUrl; + let fileName = record.fileUrl.split("/").pop(); + link.href = url; + link.download = fileName; + document.body.appendChild(link); + link.click(); + this.$layer.close(loading); + document.body.removeChild(link); + }, + getVersions() { + let { applyMaterialCode, applyModel, applyCustomCode } = this; + getVersions({ applyMaterialCode, applyModel, applyCustomCode }).then( + (res) => { + const { code, data, data2 } = res.data; + let list = []; + if (code && data) { + list = data2; + } + this.versionList = list; + } + ); + }, + selectChanged(obj) { + // console.log(obj, "--=="); + this.currentVersion = obj; + this.dataSource = [obj]; + }, + reasonCancel() { + this.reasonVisible = false; + }, + reasonOk() { + let { id, lockFlag } = this.currentVersion; + let reason = this.reason; + lockFlag = lockFlag == 0 ? 1 : 0; + updateLock({id, lockFlag, reason}).then((res) => { + const { code } = res.data; + if (code) { + this.$message.success("鎿嶄綔鎴愬姛"); + this.reasonVisible = false; + this.currentVersion.lockFlag = lockFlag; + } else { + this.$message.error("鎿嶄綔澶辫触"); + } + }); + }, + lock() { + this.reason = ""; + this.reasonVisible = true; + }, + }, + mounted() { + this.getVersions(); + }, + beforeDestroy() {}, +}; +</script> + +<style scoped lang="less"> +.main { + height: 100%; + .ant-layout-header, + .ant-layout-sider { + background: transparent; + } + .ant-layout-header { + height: auto; + } + .list { + height: 100%; + } + .wraper { + height: 100%; + position: relative; + .inner { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + } + } + /deep/.ant-layout { + margin-left: 10px; + } + .ant-layout-header { + padding: 0; + line-height: inherit; + margin-bottom: 10px; + } + .ant-btn + .ant-btn { + margin-left: 1em; + } + .ant-layout-content { + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + color: rgba(0, 0, 0, 0.65); + font-size: 14px; + font-variant: tabular-nums; + line-height: 1.5; + list-style: none; + -webkit-font-feature-settings: "tnum"; + font-feature-settings: "tnum"; + position: relative; + background: #fff; + border-radius: 2px; + -webkit-transition: all 0.3s; + transition: all 0.3s; + padding: 24px; + zoom: 1; + /deep/.ant-descriptions-item-label { + width: 12rem; + text-align: right; + } + } + .ant-layout-footer { + padding: 0; + } + .img-wraper { + width: 80px; + height: 50px; + display: inline-block; + .image-view { + width: 100%; + height: 100%; + /deep/img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + } + /deep/.is-replace > td { + background: #00eaff; + } + /deep/.is-replace.is-replace.ant-table-row-hover > td, + /deep/.is-replace.is-replace:hover > td { + background: #affaff; + } + /deep/.ant-table-row-level-1 > td { + background: #ff8ea2; + } + /deep/.ant-table-row-level-1.ant-table-row-level-1.ant-table-row-hover > td, + /deep/.ant-table-row-level-1.ant-table-row-level-1:hover > td { + background: #ffbcc9; + } + .title { + margin-bottom: 20px; + color: rgba(0, 0, 0, 0.85); + font-weight: bold; + font-size: 16px; + line-height: 1.5; + } +} +.diff-content { + display: flex; + flex-direction: column; + height: 400px; + .footer { + text-align: right; + .btn { + padding: 6px; + display: inline-block; + background: #00eaff; + border-radius: 4px; + color: #fff; + } + } + .img-wrap { + flex: 1; + } + &.full { + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + height: auto; + } +} +.img-wrap { + width: 100%; + position: relative; + .img-wrap-inner { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } +} +.all { + padding: 10px 20px; + font-size: 22px; +} +</style> diff --git a/src/pages/resourceManage/specification/index.js b/src/pages/resourceManage/specification/index.js new file mode 100644 index 0000000..37bd0be --- /dev/null +++ b/src/pages/resourceManage/specification/index.js @@ -0,0 +1,2 @@ +import list from './list'; +export default list; \ No newline at end of file diff --git a/src/pages/resourceManage/specification/list.vue b/src/pages/resourceManage/specification/list.vue new file mode 100644 index 0000000..ec19f15 --- /dev/null +++ b/src/pages/resourceManage/specification/list.vue @@ -0,0 +1,996 @@ +<template> + <div class="main"> + <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="{ 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, + }" + > + <template slot="title"> + <a-space class="operator"> + <span class="title">鎶�鏈鏍间功</span> + <a-button v-if="canUploadBom" type="primary" @click="showUpload" + >鏂板</a-button + > + </a-space> + </template> + <template slot="status" slot-scope="{ record }"> + <a-tag color="green" v-if="!record.lockFlag">鍙敤</a-tag> + <a-tag color="red" v-else>涓嶅彲鐢�</a-tag> + </template> + <template slot="action" slot-scope="{ record }"> + <a-button type="primary" @click="viewLog(record)" + >閿佸畾鏃ュ織</a-button + > + <a-divider type="vertical"></a-divider> + <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="record.lockFlag == 0" + type="primary" + @click="view(record)" + >棰勮</a-button + > + <a-button + v-if="canLock(record)" + type="primary" + @click="lock(record)" + >閿佸畾</a-button + > + <a-button + v-if="canUnLock(record)" + type="primary" + @click="lock(record)" + >瑙i攣</a-button + > + <!-- <a-button + v-if="canUpload" + type="primary" + @click="handleEmailShow(record)" + >閭欢閫氱煡</a-button + > --> + <a-button type="primary" @click="goHistory(record)" + >鍘嗗彶鐗堟湰</a-button + > + </a-space> + <a>鏇村</a> + </a-popover> + </template> + </advance-table> + </a-card> + </a-spin> + </div> + <pop + :visible.sync="popVisible" + :x="popPosition.x" + :y="popPosition.y" + :position="popPosition.dir" + :info="popInfo" + ></pop> + <a-modal + :visible="uploadShow" + :footer="null" + :width="800" + title="涓婁紶SOP" + :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-upload + class="upload" + :before-upload="beforeUpload" + @change="uploadChange" + accept=".zip,.rar,.pdf" + > + <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">瑙勬牸涔﹁鏄�</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">璇存槑鏂囦欢瑙f瀽缁撴灉</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" + :type="2" + v-if="emailShow" + ></email-card> + </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-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.status == 0 ? 'red' : 'green'" + > + <div> + <span class="user">{{ item.userName }}</span> 鍦� + <span class="time">{{ item.createTime }}</span> + {{ item.status == 0 ? "閿佸畾" : "瑙i攣" }}浜嗙増鏈� + <span class="version">{{ item.fileVersion }}</span> + </div> + <div>鎿嶄綔鍘熷洜: {{ item.reason ? item.reason : "鏃�" }}</div> + </a-timeline-item> + </a-timeline> + <a-empty v-else /> + </div> + </a-modal> + + <!-- 鏃ュ織 --> + <a-modal + :visible="pdfInfo.visible" + :footer="null" + :width="960" + title="鏂囦欢棰勮" + :destroyOnClose="true" + @cancel="pdfCancel" + > + <div style="height:600px; overflow-y: auto"> + <iframe :src="pdfInfo.src"></iframe> + </div> + </a-modal> + </div> +</template> + +<script> +import AdvanceTable from "@/components/table/advance/AdvanceTable"; +import getWebUrl from "@/assets/js/tools/getWebUrl"; +import checkPermit from "@/assets/js/tools/checkPermit"; +import PERMITS from "@/assets/js/const/const_permits"; +import { mapGetters } from "vuex"; +import EmailCard from "../../components/emailCard"; +import { getUserList } from "../../permission/apis"; +import { + excelParse, + upload, + getList, + updateLock, + getLogs, + // updateSop, +} from "./apis"; + +import { sendMail } from "../../components/emailCard/apis"; + +import offset from "@/assets/js/tools/offset"; +import Pop from "./pop"; +import DescRes from "./descRes"; +import getFileTypeAndName from "@/assets/js/tools/getFileTypeAndName"; +import VuePdf from "vue-pdf"; + +export default { + components: { + AdvanceTable, + Pop, + DescRes, + EmailCard, + VuePdf, + }, + name: "list", + data() { + return { + pdfInfo: { + visible: false, + src: "", + loadedRatio: 0, + page: 1, + numPages: 0, + rotate: 0, + }, + rowFileName: "", + logList: [], + logVisible: false, + currentObj: null, + reasonVisible: false, + reason: "", + emailShow: false, + emailInfo: { + title: "", + content: "", + }, + userList: [], + onlyXls: false, + uploadShow: false, + webUrl: getWebUrl(), + prodsColumns: [ + { + title: "鐗╂枡缂栫爜", + dataIndex: "code", + align: "center", + }, + { + title: "鍨�/鏉垮彿", + dataIndex: "model", + align: "center", + width: 180, + }, + // { + // title: "鎿嶄綔", + // dataIndex: "operation", + // align: "center", + // width: 180, + // scopedSlots: { customRender: "action" }, + // }, + ], + file: null, + file1: null, + resObj: {}, + popInfo: {}, + popVisible: false, + popPosition: { + x: 500, + y: 100, + dir: "bottom", + }, + spinning: false, + loading: false, + pageCurr: 1, + pageSize: 20, + total: 0, + y: 400, + update: -1, + conditions: {}, + columns: [ + { + title: "鏂囦欢鍚嶇О", + dataIndex: "fileName", + align: "center", + width: 140, + // searchAble: true, + customCell: this.customCell, + }, + { + title: "鏂囦欢鐗堟湰", + dataIndex: "version", + align: "center", + width: 80, + searchAble: false, + customCell: this.customCell, + }, + { + title: "鍩轰簬鐗堟湰", + dataIndex: "basedVersion", + align: "center", + width: 80, + searchAble: false, + customCell: this.customCell, + }, + { + title: "鍙戝竷鏃堕棿", + dataIndex: "createTime", + align: "center", + width: 160, + customCell: this.customCell, + }, + { + title: "璐熻矗浜�", + dataIndex: "owner", + align: "center", + searchAble: true, + width: 90, + customCell: this.customCell, + }, + { + title: "閫傜敤浜у搧鏂欏彿", + dataIndex: "applyMaterialCode", + searchAble: true, + align: "center", + width: 120, + customCell: this.customCell, + }, + { + title: "閫傜敤浜у搧鍨嬪彿", + dataIndex: "applyModel", + searchAble: true, + align: "center", + width: 120, + customCell: this.customCell, + }, + { + title: "閫傜敤浜у搧瀹氬埗鍗曞彿", + dataIndex: "applyCustomCode", + searchAble: true, + align: "center", + width: 140, + customCell: this.customCell, + }, + { + title: "鏍囧噯鏈哄瀷", + dataIndex: "isNormal", + dataType: "boolean", + align: "center", + width: 40, + searchAble: true, + noSearch: true, + visible: false, + }, + { + title: "鍙戝竷璇存槑", + dataIndex: "releaseNotes", + align: "center", + width: 260, + customCell: this.customCell, + }, + { + title: "鏄惁鍙敤", + dataIndex: "lockFlag", + dataType: "boolean", + align: "center", + searchAble: true, + width: 100, + // search: { + // default: true, + // }, + scopedSlots: { customRender: "status" }, + }, + { + title: "鎿嶄綔", + dataIndex: "operation", + align: "center", + width: 200, + fixed: "right", + scopedSlots: { customRender: "action" }, + noSearch: true, + }, + ], + dataSource: [], + }; + }, + computed: { + ...mapGetters("account", ["permits", "user"]), + ...mapGetters("setting", ["affixed"]), + canUploadBom() { + return checkPermit(PERMITS.uploadBom, this.permits); + }, + canUpload() { + return checkPermit(PERMITS.uploadSoftware, this.permits); + }, + canDownload() { + return checkPermit(PERMITS.downloadSop, this.permits); + }, + }, + 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); + this.y = h; + } + }); + } + }, + affixed() { + setTimeout(() => { + this.update = Math.random(); + }, 200); + }, + }, + methods: { + view(obj) { + let { fileUrl } = obj; + window.open(this.webUrl + fileUrl); + }, + canLock(row) { + let uname = this.user.name; + return row.owner == uname && row.lockFlag == 0; + }, + canUnLock(row) { + let uname = this.user.name; + // flag 涓�1 鏄彲鎿嶄綔鐨� + return row.owner == uname && row.lockFlag == 1 && row.flag == 1; + }, + 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.rowFileName = row.fileName; + this.onlyXls = true; + this.uploadShow = true; + }, + uploadCancel() { + this.uploadShow = false; + }, + sendEmail() { + let { title, content } = this.handleEmailShow(this.curObj, true); + let params = { mailList: this.mailList, title, content }; + sendMail(params); + }, + handleEmailShow(record, get) { + let title = + "[鎶�鏈鏍间功鍙戝竷璁板綍]" + record.fileName + " 鐗堟湰锛�" + record.version; + let content = []; + content.push("璐熻矗浜�: " + record.owner); + content.push("褰掓。鏃ユ湡: " + record.filingDate); + content.push("鐗╂枡缂栫爜: " + record.applyMaterialCode); + content.push("鐗╂枡鍚嶇О: " + record.applyModel); + content.push("瑙勬牸鍨嬪彿: " + record.applyModel); + content.push("鏍囧噯鏈哄瀷: " + (!record.applyCustomCode ? "鏄�" : "鍚�")); + content.push("瀹氬埗鍗曞彿: " + (record.applyCustomCode || "鏃�")); + content.push("鐗堟湰: " + record.version); + content.push("鍙戝竷璇存槑: " + record.releaseNotes); + if (get) { + return { + title, + content: content.join("\n"), + }; + } + }, + emailCancel() { + this.emailShow = false; + }, + uploadSop() { + if (!this.file) { + this.$message.error("璇烽�夋嫨瑕佷笂浼犵殑鏂囦欢"); + return false; + } + if (!this.file1) { + this.$message.error("璇烽�夋嫨璇存槑鏂囦欢"); + return false; + } + if (!this.resObj.fileName) { + this.$message.error("璇存槑鏂囦欢瑙f瀽寮傚父"); + return false; + } + // 濡傛灉鏂囦欢鍚嶇О != 璇存槑閲岀殑鏂囦欢鍚嶇О + 鏂囦欢鐗堟湰 鍒欐姤閿欐嫆缁� + let reg = /(.*)\..{1,5}$/; + let name1 = this.file.name.match(reg)[1]; + let { fileName, version, type } = this.resObj; + let name2 = fileName + version; + + if (type.toLowerCase() != "pdf") { + this.$message.error("瑙勬牸涔︽枃浠剁被鍨嬩笉姝g‘"); + return false; + } + + if (name1.toLowerCase() != name2.toLowerCase()) { + console.log(name1.toLowerCase() + "&&&&&&" + name2.toLowerCase()); + 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("technicalSpecificationStr", JSON.stringify(this.resObj)); + upload(formData) + .then((res) => { + let { code, data, msg } = res.data; + if (code && data) { + this.uploadShow = false; + this.$message.success("涓婁紶鎴愬姛"); + 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.resObj.fileName) { + this.$message.error("璇存槑鏂囦欢瑙f瀽寮傚父"); + return false; + } + + if ( + this.rowFileName.toLowerCase() != this.resObj.fileName.toLowerCase() + ) { + this.$message.error("璇存槑鏂囦欢涓庤鏉¤褰曞彲鑳戒笉鍖归厤"); + 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("瑙f瀽澶辫触"); + // } + // 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 < 400) { + x = 400; + } + if (x + 400 > clientWidth) { + x = clientWidth - 400; + } + } + this.popPosition.x = x; + this.popPosition.y = y; + this.popPosition.dir = dir; + this.popInfo = obj; + 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), + }, + }; + }, + 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.resObj = []; + return false; + } + let loading = this.$layer.loading(); + const formData = new FormData(); + formData.append("multipartFile", this.file1); + excelParse(formData) + .then((res) => { + this.$layer.close(loading); + let { code, data, data2, msg } = res.data; + if (code && data) { + let rowId = this.resObj.rowId; + this.resObj = data2; + this.resObj.id = rowId; + this.$message.success("瑙f瀽鎴愬姛"); + } else { + this.$message.error(msg); + } + }) + .catch((error) => { + this.$layer.close(loading); + console.log(error); + }); + }, + resize() { + setTimeout(() => { + this.update = Math.random(); + }, 200); + }, + activeFN() { + this.resize(); + }, + onSearch(conditions, searchOptions, col) { + // console.log(conditions); + // console.log(searchOptions, "00", col); + 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) { + this.conditions = conditions; + this.searchData(); + }, + searchData() { + const { pageCurr, pageSize, conditions, columns } = this; + let params2 = {}; + // console.log(this.conditions["status"]); + let col, index; + Object.keys(conditions).forEach((v) => { + switch (v) { + case "isNormal": + if (conditions[v]) { + params2["applyCustomCode"] = ""; + columns.forEach((val, idx) => { + if (val.dataIndex == "applyCustomCode") { + col = { ...val, search: { value: "", backup: "" } }; + index = idx; + } + }); + this.$set(this.columns, index, col); + } + break; + default: + params2[v] = conditions[v]; + break; + } + }); + let list = []; + getList(pageCurr, pageSize, params2) + .then((res) => { + let { code, data, data2 } = res.data; + let total = 0; + if (code && data) { + // console.log(data2); + list = data2.list; + total = data2.total; + } + this.dataSource = list.map((item) => { + const fileInfo = getFileTypeAndName(item.fileUrl); + item.isCanPreview = fileInfo.type === "pdf"; + return item; + }); + this.total = total; + if (-1 == this.update) { + this.update = Math.random(); + } + }) + .catch((err) => { + console.log(err); + }); + }, + downloadFile(record) { + const fileInfo = getFileTypeAndName(record.fileUrl); + let url = this.webUrl + record.fileUrl; + if (fileInfo.type === "pdf") { + // 棰勮 + window.open(url); + } else { + // 涓嬭浇 + let loading = this.$layer.loading(); + let link = document.createElement("a"); + link.style.display = "none"; + let fileName = record.fileUrl.split("/").pop(); + link.href = url; + link.download = fileName; + document.body.appendChild(link); + link.click(); + this.$layer.close(loading); + document.body.removeChild(link); + } + }, + reasonCancel() { + this.reasonVisible = false; + }, + reasonOk() { + let { id, lockFlag } = this.currentObj; + let reason = this.reason; + lockFlag = lockFlag == 0 ? 1 : 0; + updateLock({ id, lockFlag, reason }).then((res) => { + const { code } = res.data; + if (code) { + this.$message.success("鎿嶄綔鎴愬姛"); + this.reasonVisible = false; + this.searchData(); + } else { + this.$message.error("鎿嶄綔澶辫触"); + } + }); + }, + lock(record) { + this.reason = ""; + this.currentObj = record; + this.reasonVisible = true; + }, + viewLog(obj) { + // console.log(obj); + const { id } = obj; + getLogs(id).then((res) => { + const { code, data, data2 } = res.data; + if (code) { + this.logList = data2; + this.logVisible = true; + } else { + this.$message.error("鏃ュ織鏌ヨ澶辫触"); + } + }); + }, + logCancel() { + this.logVisible = false; + }, + pdfCancel() { + this.pdfInfo.visible = false; + }, + goHistory(record) { + let { applyMaterialCode, applyModel, applyCustomCode } = record; + this.$router.push({ + path: "/resource/specification-history", + query: { applyMaterialCode, applyModel, applyCustomCode }, + }); + }, + }, + mounted() { + 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; + top: 0; + right: 0; + bottom: 0; + } +} +.img-wraper { + width: 80px; + height: 50px; + display: inline-block; + .image-view { + width: 100%; + height: 100%; + /deep/img { + width: 100%; + height: 100%; + object-fit: contain; + } + } +} +/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; + } +} +.log-content { + max-height: 400px; + overflow-y: auto; + + .user { + color: #23aaf2; + font-weight: 700; + } + + .time { + color: #f9be13; + font-weight: 700; + } + + .version { + color: #0aedb2; + font-weight: 700; + } + + .ant-timeline-item:first-of-type { + padding-top: 6px; + } +} +</style> diff --git a/src/pages/resourceManage/specification/pop.vue b/src/pages/resourceManage/specification/pop.vue new file mode 100644 index 0000000..9d06876 --- /dev/null +++ b/src/pages/resourceManage/specification/pop.vue @@ -0,0 +1,176 @@ +<template> + <div + ref="pop" + :class="['pop', position]" + :style="{ + left: x + 'px', + top: y + 'px', + display: visible ? 'block' : 'none', + }" + > + <div class="inner"> + <desc-res :info="info"></desc-res> + </div> + </div> +</template> + +<script> +import DescRes from "./rowRes"; +export default { + name: "", + components: { + DescRes, + }, + props: { + info: { + type: Object, + default() { + return {}; + }, + }, + x: { + type: Number, + default: 0, + }, + y: { + type: Number, + default: 0, + }, + visible: { + type: Boolean, + default: false, + }, + position: { + type: String, + default: "bottom", + }, + }, + data() { + return {}; + }, + methods: { + onMouseenter() { + this.$emit('update:visible', true); + }, + onMouseleave() { + this.$emit('update:visible', false); + } + }, + + mounted() { + this.$refs.pop.addEventListener('mouseenter', this.onMouseenter); + this.$refs.pop.addEventListener('mouseleave', this.onMouseleave); + }, + beforeDestroy() { + this.$refs.pop.removeEventListener('mouseenter', this.onMouseenter); + this.$refs.pop.removeEventListener('mouseleave', this.onMouseleave); + } +}; +</script> + +<style lang="less" scoped> +.pop { + position: absolute; + z-index: 1; + background: rgba(0, 0, 0, 0.6); + width: 800px; + padding: 10px; + border-radius: 6px; + /deep/ th, + /deep/ td { + border: 1px #fff solid; + color: #fff; + } + &.top { + transform: translate(-50%, -100%); + margin-top: -10px; + &::after { + content: ""; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-5px); + display: inline-block; + width: 0; + height: 0; + border-top: 10px solid rgba(0, 0, 0, 0.6); + border-left: 5px solid transparent; + border-right: 5px solid transparent; + } + &::before { + content: ""; + position: absolute; + top: 100%; + left: 0; + right: 0; + display: inline-block; + height: 10px; + background: transparent; + } + } + &.bottom { + margin-top: 10px; + transform: translate(-50%, 0%); + &::after { + content: ""; + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-5px); + display: inline-block; + width: 0; + height: 0; + border-bottom: 10px solid rgba(0, 0, 0, 0.6); + border-left: 5px solid transparent; + border-right: 5px solid transparent; + } + &::before { + content: ""; + position: absolute; + bottom: 100%; + left: 0; + right: 0; + height: 10px; + background: transparent; + } + } + &.left { + margin-left: -10px; + transform: translate(-100%, -50%); + &::after { + content: ""; + position: absolute; + left: 100%; + top: 50%; + transform: translateY(-5px); + display: inline-block; + width: 0; + height: 0; + border-left: 10px solid rgba(0, 0, 0, 0.6); + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + } + } + &.right { + margin-left: 10px; + transform: translate(0%, -50%); + &::after { + content: ""; + position: absolute; + right: 100%; + top: 50%; + transform: translateY(-5px); + display: inline-block; + width: 0; + height: 0; + border-right: 10px solid rgba(0, 0, 0, 0.6); + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + } + } + .inner { + max-height: 360px; + overflow-y: auto; + } +} +</style> diff --git a/src/pages/resourceManage/specification/rowRes.vue b/src/pages/resourceManage/specification/rowRes.vue new file mode 100644 index 0000000..437467a --- /dev/null +++ b/src/pages/resourceManage/specification/rowRes.vue @@ -0,0 +1,98 @@ +<template> + <div class=""> + <table class="table"> + <tbody> + <tr> + <th class="title" colspan="6">鏂囦欢鍩烘湰淇℃伅</th> + </tr> + <tr> + <th class="col-1">鏂囦欢鍚嶇О</th> + <td colspan="5">{{ info.fileName }}</td> + </tr> + <tr> + <th class="col-1">杞欢绫诲瀷</th> + <td colspan="5">{{ info.type }}</td> + </tr> + <tr> + <th class="col-1">鏂囦欢鐗堟湰</th> + <td colspan="1">{{ info.version }}</td> + <th class="col-1">鍩轰簬鐗堟湰</th> + <td colspan="3">{{ info.basedVersion }}</td> + </tr> + <tr> + <th class="col-1">璐熻矗浜�</th> + <td colspan="1">{{ info.owner }}</td> + <th class="col-1">褰掓。鏃ユ湡</th> + <td colspan="3">{{ info.filingDate }}</td> + </tr> + <tr> + <th class="title" colspan="6">瑙勬牸涔﹂�傜敤鏈哄瀷</th> + </tr> + <tr > + <th class="col-1">鐗╂枡缂栫爜</th> + <td colspan="1">{{ info.applyMaterialCode }}</td> + <th class="col-1">瑙勬牸鍨嬪彿</th> + <td colspan="1">{{ info.applyModel }}</td> + <th class="col-1">瀹氬埗鍗曞彿</th> + <td colspan="1">{{ info.applyCustomCode }}</td> + </tr> + <tr> + <th class="col-1">鍙戝竷璇存槑</th> + <td colspan="5">{{ info.releaseNotes }}</td> + </tr> + </tbody> + </table> + </div> +</template> + +<script> +export default { + name: "", + props: { + info: { + type: Object, + default() { + return {}; + }, + }, + }, + data() { + return { + }; + }, + computed: { + }, + watch: { + }, + methods: { + }, + + mounted() { + }, +}; +</script> + +<style lang="less" scoped> +.table { + width: 100%; + // table-layout: fixed; + border-collapse: collapse; + th, + td { + border: 1px #fff solid; + padding: 4px; + } + td { + color: #fff; + } + .title { + font-weight: 900; + padding-left: 2em; + font-style: italic; + } +} +.col-1 { + // word-break:break-all; + width: 6.4em; +} +</style> \ No newline at end of file diff --git a/src/pages/resourceManage/specification/versionList.vue b/src/pages/resourceManage/specification/versionList.vue new file mode 100644 index 0000000..93c4d11 --- /dev/null +++ b/src/pages/resourceManage/specification/versionList.vue @@ -0,0 +1,130 @@ +<template> + <div class="posR"> + <div class="inner"> + <a-card class="main"> + <!-- 鍒楄〃 --> + <div class="contain"> + <div + :class="['item', { selected: currentV == item.id }]" + v-for="(item, idx) in list" + :key="'item_' + idx" + @click="selectHandle(item)" + > + <span :class="['status', { actived: item.lockFlag == 0 }]"></span> + <div class="version">{{ item.version }}</div> + </div> + </div> + </a-card> + </div> + </div> +</template> + +<script> +export default { + name: "", + props: { + list: { + type: Array, + default() { + return []; + }, + }, + }, + computed: { + // data() { + // return this.list.filter((v) => { + // const reg = new RegExp(this.keyword, "i"); + // return reg.test(v.subModel); + // }); + // }, + }, + watch: { + list(n) { + if (n.length) { + this.selectHandle(this.list[0]); + } + }, + }, + data() { + return { + // keyword: '', + currentV: "-1", + }; + }, + components: {}, + methods: { + selectHandle(item) { + this.currentV = item.id; + this.$emit("select", item); + }, + }, + + mounted() {}, +}; +</script> + +<style scoped lang="less"> +.posR { + position: relative; +} +.inner { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; +} +.main { + height: 100%; + /deep/.ant-card-body { + height: 100%; + display: flex; + flex-direction: column; + } +} +.contain { + margin-top: 8px; + border: 1px solid #e8e8e8; + flex: 1; + overflow: auto; + padding: 0 4px; +} +.item { + cursor: pointer; + box-shadow: 0px 4px 5px -2px #000; + padding: 6px 0; + border-radius: 4px; + display: flex; + flex-direction: row; + align-items: center; + & + .item { + margin-top: 4px; + } + &:hover { + transform: scale(0.98, 0.9); + box-shadow: 0px 2px 5px -2px #000; + background: #f0f0f0; + } + &.selected { + transform: scale(0.98, 0.9); + box-shadow: 0px 2px 5px -2px #000; + color: #13c2c2; + font-weight: bold; + } + .version { + flex: 1; + } + .status { + display: inline-block; + width: 10px; + height: 10px; + background: #aaa; + border-radius: 50%; + margin-left: 10px; + margin-right: 20px; + &.actived { + background: #00ff79; + } + } +} +</style> diff --git a/src/router/config.js b/src/router/config.js index 2da26dc..424bb41 100644 --- a/src/router/config.js +++ b/src/router/config.js @@ -151,10 +151,24 @@ name: 'sop鍘嗗彶鐗堟湰', meta: { invisible: true, - highlight: '/resource/sop-history' + highlight: '/resource/sop-file' }, component: () => import('@/pages/resourceManage/sopFile/sop-history'), }, + { + path: 'specification', + name: '鎶�鏈鏍间功', + component: () => import('@/pages/resourceManage/specification'), + }, + { + path: 'specification-history', + name: '鎶�鏈鏍间功鍘嗗彶鐗堟湰', + meta: { + invisible: true, + highlight: '/resource/specification' + }, + component: () => import('@/pages/resourceManage/specification/history'), + }, ] }, { -- Gitblit v1.9.1