部门调整为树结构

This commit is contained in:
aixianling
2023-05-25 14:54:46 +08:00
parent 773913ef89
commit 5f8850dc00
6 changed files with 165 additions and 40 deletions

View File

@@ -20,6 +20,7 @@
"src/common/http.js",
"src/common/crypto-js.js",
"src/common/observer.js",
"src/common/tree.js",
"src/apps",
"src/styles"
],

57
src/common/tree.js Normal file
View File

@@ -0,0 +1,57 @@
class Tree {
constructor(list = [], config) {
this.config = {
key: 'id', parent: 'parentId', children: 'children',
...config
}
this.list = list
if (Array.isArray(list)) this.tree = this.arr2tree(list)
}
arr2tree(list) {
const {key, parent, children} = this.config
const result = []
this.map = {}
const ids = list?.map(e => `#${e[key]}#`)?.toString()
for (const e of list) {
const id = e[key], pid = e[parent]
this.map[id] = {...e, [children]: [this.map[id]?.[children]].flat().filter(Boolean)}
const treeItem = this.map[id]
if (!!pid && ids.indexOf(`#${pid}#`) > -1) {
if (!this.map[pid]) {
this.map[pid] = {
children: []
}
}
this.map[pid].children.push(treeItem)
} else result.push(treeItem)
}
const removeNullChildren = node => {
if (node[children] && node[children].length > 0) {
node[children].map(c => removeNullChildren(c))
} else delete node[children]
}
result.forEach(removeNullChildren)
return result
}
root(id) {
return this.map[id]
}
find(id) {
return this.map[id]
}
every(cb) {
const iterate = list => {
list?.map(e => {
cb(e)
iterate(e.children)
})
}
iterate(this.tree)
}
}
export default Tree

View File

@@ -308,5 +308,31 @@ export default {
qs,
permissions,
copy,
reg
reg,
arr2tree(list, config = {}) {
const {key = 'id', parent = 'parentId', children = 'children'} = config
const result = []
const itemMap = {}
const ids = list?.map(e => `#${e[key]}#`)?.toString()
for (const e of list) {
const id = e[key], pid = e[parent]
itemMap[id] = {...e, [children]: [itemMap[id]?.[children]].flat().filter(Boolean)}
const treeItem = itemMap[id]
if (!!pid && ids.indexOf(`#${pid}#`) > -1) {
if (!itemMap[pid]) {
itemMap[pid] = {
children: []
}
}
itemMap[pid].children.push(treeItem)
} else result.push(treeItem)
}
const removeNullChildren = node => {
if (node[children] && node[children].length > 0) {
node[children].map(c => removeNullChildren(c))
} else delete node[children]
}
result.forEach(removeNullChildren)
return result
}
}

View File

@@ -0,0 +1,38 @@
<template>
<section class="AiTreePath">
<AiTreePath v-if="parent" v-bind="$props" :current="parent" v-on="$listeners"/>
<div v-else v-text="`全部`" @click="$emit('click','all')"/>
<u-icon v-if="label" name="arrow-right" size="32" color="#ccc"/>
<div v-text="label" @click="$emit('click',current)"/>
</section>
</template>
<script>
export default {
name: "AiTreePath",
props: {
current: {default: null},
prop: {default: () => ({})},
paths: {default: () => []}
},
computed: {
options: v => ({
id: 'id',
label: 'name',
parent: 'parentId',
...v.prop
}),
label: v => v.current?.[v.options.label] || "",
parent: v => v.paths?.[v.current?.[v.options.parent]]
}
}
</script>
<style scoped lang="scss">
.AiTreePath {
display: flex;
align-items: center;
gap: 8px;
font-size: 36px;
line-height: 40px;
font-family: PingFang-SC;
}
</style>

View File

@@ -1,15 +1,18 @@
<template>
<div class="selectDept">
<AiTopFixed>
<u-search placeholder="搜索" v-model="name" :show-action="false" @change="getList()"/>
<AiTreePath :current="cursor" :paths="depts.map" :prop="{parent:'parentid'}" @click="changeList"/>
</AiTopFixed>
<div class="user-list">
<template v-if="list.length>0">
<div class="item" v-for="(item, index) in list" :key="index">
<div class="select-img" @click="checkClick(index)">
<div class="item" v-for="(item, index) in list" :key="index" flex>
<div class="select-img" @click="checkClick(item)">
<img :src="item.isCheck ? checkIcon : cirIcon" alt="">
</div>
<div class="user-info">{{ item.name }}</div>
<div class="user-info fill" flex @click="getCursor(item)">
<div class="fill" v-text="item.name"/>
<u-icon v-if="Array.isArray(item.children)" class="mar-r16" name="arrow-right" size="40" color="#999"/>
</div>
</div>
</template>
<template v-else>
@@ -26,6 +29,7 @@
<script>
import {mapState} from 'vuex'
import Tree from "../../common/tree";
export default {
name: "selectDept",
@@ -36,55 +40,46 @@ export default {
total: 0,
name: '',
list: [],
depts: [],
cirIcon: require('./img/xz.png'),
checkIcon: require('./img/xzh.png'),
selected: []
selected: [],
cursor: null
}
},
computed: {
...mapState(['user']),
isSingle() {
return this.$route.query.single
},
nodeKey() {
return this.$route.query.nodeKey || "idNumber"
},
isRequire() {
return this.$route.query.isRequire || 1
}
isSingle: v => !!v.$route.query.single,
nodeKey: v => v.$route.query.nodeKey || "idNumber",
isRequire: v => v.$route.query.isRequire || 1
},
onLoad(query) {
console.log(query)
if (query.selected) {
this.selected = query.selected?.split(",") || []
this.selected = query.selected?.split(",").map(e => Number(e)) || []
}
this.selected.map((item, index) => {
this.selected[index] = parseInt(item)
})
this.getList()
},
methods: {
getList() {
this.$http.post(`/app/wxcp/wxdepartment/listAll?name=${this.name}`).then(res => {
if (res?.data) {
res.data.forEach(e => {
e.isCheck = this.selected.includes(e[this.nodeKey])
})
this.list = res.data
res.data.forEach(e => e.isCheck = this.selected.includes(e[this.nodeKey]))
this.depts = new Tree(res.data, {parent: 'parentid'})
this.list = this.depts.tree
}
})
},
checkClick(index) {
checkClick(item) {
if (this.isSingle && this.isRequire == 1) {
this.list.map((e, i) => {
e.isCheck = i == index;
this.depts.every(e => {
e.isCheck = item.id == e.id
})
} else this.list[index].isCheck = !this.list[index].isCheck
} else item.isCheck = !item.isCheck
},
confirm() {
let checkList = []
this.list.map((item) => {
this.depts.every((item) => {
if (item.isCheck) {
checkList.push(item)
}
@@ -98,6 +93,21 @@ export default {
}
})
}
},
changeList(item) {
if (item == "all") {
this.list = this.depts.tree
this.cursor = null
} else {
this.cursor = item
this.list = item.children
}
},
getCursor(item) {
if (item.children?.length > 0) {
this.cursor = item
this.list = item.children
}
}
},
}
@@ -117,6 +127,8 @@ export default {
background-color: #fff;
.item {
width: 100vw;
.select-img {
display: inline-block;
@@ -129,9 +141,7 @@ export default {
}
.user-info {
display: inline-block;
padding: 20px 0 20px 0;
width: calc(100% - 114px);
height: 100%;
border-bottom: 1px solid #E4E5E6;
font-size: 36px;
@@ -139,14 +149,6 @@ export default {
font-weight: 500;
color: #333;
line-height: 74px;
img {
width: 74px;
height: 74px;
border-radius: 8px;
margin-right: 34px;
vertical-align: bottom;
}
}
}
}

View File

@@ -14,7 +14,8 @@
"common/http.js",
"common/crypto-js.js",
"common/regular.js",
"common/observer.js"
"common/observer.js",
"common/tree.js"
],
"dependencies": {
}