From dbbfad10dab14ae84746a01f2b676caeec80b88a Mon Sep 17 00:00:00 2001 From: licp <lichunping@guanfang.com.cn> Date: 星期一, 15 四月 2024 18:10:38 +0800 Subject: [PATCH] 完成人员总览n功能 --- src/components/tool/value-table.vue | 2 static/js/menu.js | 4 src/components/view/a6-personnel-detail.vue | 355 ++++++++++++++++++++++++++++++++ src/components/view/a6-personnel-overview.vue | 252 ++++++++++++++++++++++ static/img/renyuan-title.svg | 11 + src/assets/api/controller.js | 9 6 files changed, 629 insertions(+), 4 deletions(-) diff --git a/src/assets/api/controller.js b/src/assets/api/controller.js index 3d74343..a4c5979 100644 --- a/src/assets/api/controller.js +++ b/src/assets/api/controller.js @@ -16,7 +16,8 @@ sampleOrder, insOrderPlan, insReport, - warehouse + warehouse, + department, } } @@ -203,3 +204,9 @@ getSampleRecord: "/warehouse/getSampleRecord", //鏌ヨ鏍峰搧璇︾粏璁板綍 searchSampleId: "/warehouse/searchSampleId", //閫氳繃鏍峰搧缂栧彿杩涜妫�绱� } + +const department = { + selectDepartment: "/department/selectDepartment", //浜哄憳鏋舵瀯鏍� + addDepartment: "/department/addDepartment", //娣诲姞閮ㄩ棬 + delDepartment: "/department/delDepartment", //鍒犻櫎閮ㄩ棬 +} diff --git a/src/components/tool/value-table.vue b/src/components/tool/value-table.vue index 0c7ee99..58466cf 100644 --- a/src/components/tool/value-table.vue +++ b/src/components/tool/value-table.vue @@ -684,7 +684,7 @@ return false }, showUpload(label){ - if(this.data.addUpload.find(m=>m==label)){ + if(this.data.addUpload&&this.data.addUpload.find(m=>m==label)){ return true; }else{ return false; diff --git a/src/components/view/a6-personnel-detail.vue b/src/components/view/a6-personnel-detail.vue new file mode 100644 index 0000000..b96ad20 --- /dev/null +++ b/src/components/view/a6-personnel-detail.vue @@ -0,0 +1,355 @@ +<style scoped> + .standard { + padding: 20px 0; + display: flex; + } + + .left { + width: 270px; + height: calc(100% - 40px - 25px); + background-color: white; + padding: 15px; + } + .el-tree{ + height: calc(100% - 37px); + overflow-y: auto; + } + + .custom-tree-node { + width: 100%; + line-height: 32px; + } + + .custom-tree-node .el-icon-delete { + color: #3A7BFA; + opacity: 0; + font-size: 18px; + } + + .custom-tree-node:hover .el-icon-delete { + opacity: 1; + } + + .node_i { + color: orange; + font-size: 18px; + } + + .right { + margin-left: 5px; + width: calc(100% - 305px); + height: calc(100% - 40px); + } + + .right .title { + height: 50px; + line-height: 50px; + padding: 0 10px; + background-color: white; + } + + .standard_table { + border-top: 1px solid #ebeef5; + height: calc(100% - 50px); + margin-top: 5px; + background-color: white; + user-select: none; + overflow-y: auto; + } + .sort{ + width: 80% !important; + overflow: hidden; + } + + .search { + background-color: #fff; + height: 100%; + display: flex; + align-items: center; + justify-content: end; + } + + .search_thing { + width: 350px; + display: flex; + align-items: center; + } + + .search_label { + width: 110px; + font-size: 14px; + text-align: right; + } + + .search_input { + width: calc(100% - 110px); + } +</style> +<style> + .standard .el-tree-node__content { + height: 32px; + font-size: 14px; + border-radius: 2px; + } + + .standard .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content { + color: #3A7BFA; + } +</style> + +<template> + <div class="standard"> + <div class="left"> + <el-row> + <el-col :span="20"> + <el-input placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�" suffix-icon="el-icon-search" v-model="search" size="small" + style="margin-bottom: 5px;" clearable @blur="searchFilter" @clear="searchFilter"></el-input> + </el-col> + <el-col :span="4" style="text-align: center;line-height: 30px;" v-if="addPower"> + <el-button type="primary" icon="el-icon-plus" size="mini" circle @click="handleAdd"></el-button> + </el-col> + </el-row> + <el-tree :data="list" ref="tree" :props="{ children: 'children', label: 'name' }" node-key="id" + :filter-node-method="filterNode" @node-click="handleNodeClick" highlight-current @node-expand="nodeOpen" + @node-collapse="nodeClose" v-loading="treeLoad" :expand-on-click-node="false" + :default-expanded-keys="expandedKeys"> + <div class="custom-tree-node" slot-scope="{ node, data }"> + <el-row style="width: 100%;"> + <el-col :span="21" :class="{sort:node.level>3}"> + <span><i + :class="`node_i ${data.children != undefined&&data.children.length>0 ? 'el-icon-folder-opened' : 'el-icon-tickets'}`"></i> + [{{ node.level-1 }}] {{ data.name }}</span> + </el-col> + <el-col :span="2" style="text-align: right;" v-if="delStandardTree"> + <el-button type="text" size="mini" @click.stop="remove(node, data)"> + <i class="el-icon-delete"></i> + </el-button> + </el-col> + </el-row> + </div> + </el-tree> + </div> + <div class="right"> + <el-row class="title"> + <el-col :span="14" style="font-size: 14px;color: #999;">{{selectTree}}</el-col> + <el-col :span="selectTree==''?24:10" style="text-align: right;" v-if="selectTree!=''"> + <div class="search"> + <div class="search_thing"> + <div class="search_label">浜哄憳鍚嶇О锛�</div> + <div class="search_input"><el-input size="small" placeholder="璇疯緭鍏�" clearable v-model="componentData.entity.name"></el-input></div> + </div> + <div class="search_thing" style="padding-left: 30px;width: 120px;"> + <el-button size="small" @click="refresh()">閲� 缃�</el-button> + <el-button size="small" type="primary" @click="refreshTable()">鏌� 璇�</el-button> + </div> + </div> + </el-col> + </el-row> + <el-row class="standard_table" v-loading="tableLoad"> + <ValueTable ref="ValueTable" :url="$api.capacityScope.selectItemParameterList" :componentData="componentData" /> + </el-row> + </div> + <el-dialog title="鏋舵瀯鏂板" :visible.sync="addDia" width="400px"> + <div class="body"> + <el-row style="line-height: 50px;"> + <el-col :span="6" style="text-align: right;"> + <span class="required-span">* </span>鏋舵瀯鍚嶇О锛� + </el-col> + <el-col :span="16" :offset="1"> + <el-input v-model="addOb.name" placeholder="璇疯緭鍏ユ灦鏋勫悕绉�" clearable size="small"></el-input> + </el-col> + </el-row> + </div> + <span slot="footer" class="dialog-footer"> + <el-button @click="addDia = false">鍙� 娑�</el-button> + <el-button type="primary" @click="addStandardTree" :loading="addLoad">纭� 瀹�</el-button> + </span> + </el-dialog> + </div> +</template> + +<script> + import ValueTable from '../tool/value-table.vue' + export default { + components: { + ValueTable + }, + data() { + return { + search: null, + list: [], + selectTree: '', + addDia: false, + addOb: { + name:'', + fatherId:'' + }, + addLoad: false, + treeLoad: false, + addPower: false, + tableLoad: false, + delStandardProduct: false, + addStandardProduct: false, + componentData: { + entity: { + orderBy: { + field: 'id', + order: 'asc' + } + }, + init:false, + isIndex: true, + showSelect: true, + select: true, + do: [], + isPage: false, + tagField: { + }, + selectField: {}, + }, + expandedKeys: [] + } + }, + mounted() { + this.getPower() + this.selectTreeList() + }, + methods: { + filterNode(value, data) { + if (!value) return true; + return data.name.indexOf(value) !== -1; + }, + searchFilter() { + this.$refs.tree.filter(this.search) + }, + refreshTable() { + this.$refs.ValueTable.selectList() + }, + refresh() { + this.upIndex++ + this.refreshTable() + }, + handleNodeClick(val, node, el) { //鏍戠殑鍊� + this.selectTree = '' + this.getNodeParent(node) + this.selectTree = this.selectTree.replace(' - ', '') + let data = this.selectTree.split(' - ') + let data2 = '' + for (let index = data.length - 1; index >= 0; index--) { + data2 += " - " + data[index] + } + this.selectTree = data2.replace(' - ', '') + this.addOb.fatherId = val.id; + }, + getNodeParent(val) { + if (val.parent != null) { + this.selectTree += ' - ' + val.label + this.getNodeParent(val.parent) + } + }, + remove(node, data) { + this.$confirm("鏄惁鍒犻櫎璇ュ眰绾�", "鎻愮ず", { + type: "error" + }).then(() => { + this.treeLoad = true + this.$axios.post(this.$api.department.delDepartment, { + id: data.id + }).then(res => { + if (res.code == 201) return + this.$message.success('宸插垹闄�') + this.selectTreeList() + }) + }).catch(e => {}) + }, + nodeOpen(data, node, el) { + $($(el.$el).find('.node_i')[0]).attr('class', 'node_i el-icon-folder-opened') + }, + nodeClose(data, node, el) { + $($(el.$el).find('.node_i')[0]).attr('class', 'node_i el-icon-folder') + }, + selectTreeList() { + this.treeLoad = true + this.$axios.get(this.$api.department.selectDepartment).then(res => { + this.list = res.data + this.list.forEach(a => { + a.children.forEach(b => { + b.children.forEach(c => { + this.expandedKeys.push(c.name) + }) + // this.expandedKeys.push(b.label) + }) + }) + this.treeLoad = false + }) + }, + addStandardTree() { + if (this.addOb.name == null || this.addOb.factory == '') { + this.$message.error('鏋勬灦鍚嶇О鏄繀濉」') + return + } + this.addLoad = true + this.$axios.post(this.$api.department.addDepartment, this.addOb, { + headers: { + 'Content-Type': 'application/json' + } + }).then(res => { + if (res.code === 201) { + this.addLoad = false + return + } + this.$message.success('娣诲姞鎴愬姛') + this.addDia = false + this.selectTreeList() + this.addLoad = false + this.addOb.name = '' + this.addOb.fatherId = '' + }).catch(e => { + this.addDia = false + this.addLoad = false + }) + }, + handleAdd(){ + if(this.addOb.fatherId){ + this.addDia = true; + }else{ + this.$message.error('璇烽�夋嫨涓�涓灦鏋勫眰绾�') + } + }, + getPower() { + let power = JSON.parse(sessionStorage.getItem('power')) + let add = false + let upStandardProduct = false + let delStandardMethod = false + let delStandardProduct = false + let addStandardProduct = false + let delStandardTree = false + for (var i = 0; i < power.length; i++) { + if (power[i].menuMethod == 'addStandardTree') { + add = true + } + if (power[i].menuMethod == 'upStandardProductList') { + upStandardProduct = true + } + if (power[i].menuMethod == 'delStandardMethodByFLSSM') { + delStandardMethod = true + } + if (power[i].menuMethod == 'delStandardProductByIds') { + delStandardProduct = true + } + if (power[i].menuMethod == 'addStandardProduct') { + addStandardProduct = true + } + if (power[i].menuMethod == 'delStandardTree') { + delStandardTree = true + } + } + this.addPower = add + this.upStandardProduct = upStandardProduct + this.delStandardMethod = delStandardMethod + this.delStandardProduct = delStandardProduct + this.addStandardProduct = addStandardProduct + this.delStandardTree = delStandardTree + }, + } + } +</script> diff --git a/src/components/view/a6-personnel-overview.vue b/src/components/view/a6-personnel-overview.vue new file mode 100644 index 0000000..bf88add --- /dev/null +++ b/src/components/view/a6-personnel-overview.vue @@ -0,0 +1,252 @@ +<style scoped> + .title { + height: 60px; + line-height: 60px; + } + + .search { + background-color: #fff; + height: 80px; + display: flex; + align-items: center; + } + + .search_thing { + width: 350px; + display: flex; + align-items: center; + } + + .search_label { + width: 110px; + font-size: 14px; + text-align: right; + } + + .search_input { + width: calc(100% - 110px); + } + + .table { + margin-top: 10px; + background-color: #fff; + width: calc(100% - 40px); + height: calc(100% - 60px - 80px - 10px - 40px); + padding: 20px; + overflow-y: auto; + } + + .card { + list-style-type: none; + display: grid; + grid-template-columns: repeat(auto-fit, 320px); + /* justify-content: center; */ + grid-gap: 16px; + min-height: 200px; + } + .card li{ + width: 320px; + /* height: 170px; */ + border-radius: 8px 8px 8px 8px; + box-shadow: 4px 4px 8px 0px rgba(51,51,51,0.04); + border: 1px solid #EEEEEE; + margin: 0 !important; + display: flex; + align-items: center; + justify-content: space-between; + box-sizing: border-box; + padding: 26px 16px 16px; + font-size: 14px; + position: relative; + overflow: show; + } + li .title{ + width: 147px; + height: 20px; + background: url(../../../static/img/renyuan-title.svg) no-repeat; + position: absolute; + top: -6px; + left: 50%; + transform: translateX(-50%); + text-align: center; + line-height: 20px; + color: #fff; + } +</style> + +<template> + <div class="role_manage"> + <div> + <el-row class="title"> + <el-col :span="12" style="padding-left: 20px;">浜哄憳鎬昏</el-col> + </el-row> + </div> + <div class="search"> + <div class="search_thing"> + <div class="search_label">浜哄憳鍚嶇О锛�</div> + <div class="search_input"><el-input size="small" placeholder="璇疯緭鍏�" clearable v-model="entity.name"></el-input></div> + </div> + <div class="search_thing" style="padding-left: 30px;"> + <el-button size="small" @click="refresh()">閲� 缃�</el-button> + <el-button size="small" type="primary" @click="currentPage= 1,list=[],finishLoding = false,refreshTable()">鏌� 璇�</el-button> + </div> + </div> + <div class="table" @scroll="scrollFn"> + <ul v-loading="loading" class="card"> + <li v-for="(m,i) in list" :key="i"> + <el-image style="width: 80px; + height: 112px;" :src="javaApi+'/img/'+m.pictureUrl"> + <div slot="error" class="image-error" style="width: 79px; + height: 110px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #EEEEEE;"> + <i class="el-icon-picture-outline" style="font-size:30px;color:#666666;"></i> + </div> + </el-image> + <el-image style="width: 195px; + height: 112px;" :src="javaApi+'/img/'+m.signatureUrl"> + <div slot="error" class="image-error" style="width: 194px; + height: 110px; + display: flex; + align-items: center; + justify-content: center; + border: 1px solid #EEEEEE;"> + <i class="el-icon-picture-outline" style="font-size:30px;color:#666666;"></i> + </div> + </el-image> + <div class="title">{{ m.name }}</div> + </li> + </ul> + <div v-if="list.length<1&&!loading&&!isLoding" style="color:#909399;font-size:14px;text-align: center;margin-top:200px" >鏆傛棤鏁版嵁</div> + <div v-if="list.length>0"> + <el-button + v-if="isLoding" + type="text" + style="display: flex; margin: 0 auto; color: #909399" + ><i class="el-icon-loading" style="font-size:20px"></i + ></el-button> + <el-button + type="text" + v-if="finishLoding" + style="display: flex; margin: 0 auto; color: #909399" + >宸茬粡娌℃湁鏇村鍟</el-button + > + </div> + </div> + </div> +</template> + +<script> + export default { + data() { + return { + entity:{ + name: null, + state:1, + orderBy: {field: "id", order: "asc"} + }, + list:[], + currentPage: 1, // 褰撳墠椤� + pageSize: 16, // 涓�椤�16鏉� + total: '', + loading: true, // 缁勪欢loading鐨勫睍绀�,榛樿涓簍rue + isLoding: false, // 鍔犺浇涓紝loading鍥炬爣,榛樿涓簍rue + finishLoding: false // 鍔犺浇瀹屾垚锛屾樉绀哄凡缁忔病鏈夋洿澶氫簡 + } + }, + created() { + this.currentPage = 1; + this.list = []; + this.refreshTable(); + }, + methods: { + refreshTable() { + if(this.currentPage>1){ + this.isLoding = true + }else{ + this.loading = true + } + if(this.list.length==0){ + window.addEventListener("scroll", this.throttle(this.scrollFn, 20000)); + } + this.$axios.post(this.$api.user.selectUserList,{ + page: { + current: this.currentPage, + size: this.pageSize + }, + entity: this.entity + }, { + headers: { + 'Content-Type': 'application/json' + } + }).then(res => { + if(res.code==200){ + this.total = res.data.body.total + let list = res.data.body.records; + if(list.length==0){ + this.finishLoding = true; + }else{ + if(list.length<this.pageSize){ + this.finishLoding = true; + } + this.list = this.list.concat(list) + if(this.total==this.list.length){ + this.finishLoding = true; + } + } + } + this.loading = false + this.isLoding = false; + }) + }, + refresh() { + this.currentPage= 1; + this.list=[]; + this.finishLoding = false; + this.entity={ + name: null, + state:1, + orderBy: {field: "id", order: "asc"} + }; + this.refreshTable() + }, + // 婊氬姩瑙﹀簳鍔犺浇 + scrollFn() { + let clientHeight = document.documentElement.clientHeight - 18; //鍙鍖哄煙 + let scrollHeight = document.body.scrollHeight; // 婊氬姩鏂囨。楂樺害 + let scrollTop = parseInt(document.documentElement.scrollTop); // 宸叉粴鍔ㄧ殑楂樺害 + let height = 300; + if ( + scrollTop + clientHeight >= scrollHeight - height && + scrollHeight != 0 + ) { + if (!this.finishLoding&&this.currentPage*this.pageSize<this.total) { + this.currentPage = this.currentPage + 1; + this.refreshTable(); + } + } else { + return false; + } + }, + throttle(fn, wait) { + // 灏佽鍑芥暟杩涜鑺傛祦 + var timer = null; + return function () { + var context = this; + var args = arguments; + if (!timer) { + timer = setTimeout(function () { + fn.apply(context, args); + timer = null; + }, wait); + } + }; + }, + }, + destroyed() { + window.removeEventListener("scroll", this.throttle(), false); + }, + } +</script> diff --git a/static/img/renyuan-title.svg b/static/img/renyuan-title.svg new file mode 100644 index 0000000..c69691f --- /dev/null +++ b/static/img/renyuan-title.svg @@ -0,0 +1,11 @@ +<svg width="148" height="21" viewBox="0 0 148 21" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00437 5.75531V0.0625L0.772461 5.75531H7.00437Z" fill="#B26F00"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M141.709 5.75531V0.0625L147.941 5.75531H141.709Z" fill="#B26F00"/> +<path d="M6.97192 2.0625C6.97192 0.957931 7.86735 0.0625 8.97192 0.0625H139.676C140.781 0.0625 141.676 0.957931 141.676 2.0625V12.0625C141.676 16.4808 138.095 20.0625 133.676 20.0625H14.9719C10.5537 20.0625 6.97192 16.4808 6.97192 12.0625V2.0625Z" fill="url(#paint0_linear_2026_4)"/> +<defs> +<linearGradient id="paint0_linear_2026_4" x1="6.97192" y1="0.0625" x2="6.97192" y2="20.0625" gradientUnits="userSpaceOnUse"> +<stop stop-color="#F9C76F"/> +<stop offset="1" stop-color="#FEB42F"/> +</linearGradient> +</defs> +</svg> diff --git a/static/js/menu.js b/static/js/menu.js index 4de375e..d34f6ff 100644 --- a/static/js/menu.js +++ b/static/js/menu.js @@ -279,13 +279,13 @@ }, { v: "浜哄憳鎬昏", i: "font icon-erjidaohang", - u: "", + u: "a6-personnel-overview", g: "6.2 浜哄憳", p: "" }, { v: "浜哄憳鏄庣粏", i: "font icon-erjidaohang", - u: "", + u: "a6-personnel-detail", g: "6.2 浜哄憳", p: "" }, { -- Gitblit v1.9.3