Files
2024-10-31 15:06:02 +08:00

482 lines
13 KiB
Vue

<template>
<div class="tree">
<ai-top-fixed>
<div class="top pad">
<u-search v-if="searchIf" placeholder="搜索" @change="confirmSearch" @search="confirmSearch" :clearabled="true"
v-model="keyword" :show-action="false" @clear="clear"></u-search>
<u-tabs :list="list" :current="current" item-width="50%" height="96" bar-width="192"
@change="tabChange"></u-tabs>
</div>
</ai-top-fixed>
<div class="tree-list">
<scroll-view scroll-x class="scroll pad" style="width:100%" :scroll-left="scrollLeft">
<div v-for="(item,index) in parent" class="inline-item" :key="index">
<div class="inline-item" v-if="index==0" @click.stop="backTree(item,-1)">
<text v-if="index==parent.length-1&&!isSear" class="none">可选范围</text>
<text v-else class="active">可选范围</text>
</div>
<div v-if="index==0 && isSear" @click.stop="backTree(item,-2)"
:class="[index==parent.length-1 && isSear] ? 'none inline-item':'active inline-item'">
<span style="margin: 0 8px">/</span>
搜索结果
</div>
<div class="inline-item" @click.stop="backTree(item,index)" v-if="index!=0">
<span style="margin: 0 8px">/</span>
<text v-if="index==parent.length-1" class="none inline-item">
{{ item[tag] }}
</text>
<text v-else class="active">
{{ item[tag] }}
</text>
</div>
</div>
</scroll-view>
<div class="container-list">
<div class="common" v-for="(item, index) in tree" @click.stop="toNext(item)" :key="index">
<label class="content">
<div class="checkbox" v-if="multiple" @click.stop="checkboxChange(item,index)">
<img :src="$cdn + 'common/xzh.png'" v-if="item.checked" alt="">
<img :src="$cdn + 'common/xzn.png'" v-else alt="">
</div>
<div class="checkbox" v-if="!multiple && (item.type==0 || item.openId)" @click.stop="checkbox(item,index)">
<img :src="$cdn + 'common/xzh.png'" v-if="item.checked" alt="">
<img :src="$cdn + 'common/xzn.png'" v-else alt="">
</div>
<div class="person" v-if="item.type==0">
<u-avatar :src="item.avatar || ($cdn + 'common/xztx.png')" mode="square" :size="37"></u-avatar>
</div>
<u-row justify="between" style="width: 100%;">
<div class="word" v-if="tag=='name'">
<img :src="$cdn + 'common/xzbq.png'" v-if="item.type==1" alt="">
<span class="ellipsis">{{ item[tag] }}</span>
</div>
<div class="word" v-else-if="tag=='tagname'">
<template v-if="!item.openId">
<img :src="$cdn + 'common/xzbqbottom.png'" alt="">
<span class="ellipsis">{{ item[tag] }}</span>
</template>
<template v-else>
<u-avatar :src="item.avatar || ($cdn + 'common/xztx.png')" mode="square" :size="37"
style="margin: 0 17px;"></u-avatar>
<span class="ellipsis">{{ item["name"] }}</span>
</template>
</div>
<div class="right"
v-if="item.type==1 && (item.childrenDept.length || item.childrenUser.length) && tag=='name'"></div>
<div class="right" v-if="tag=='tagname' && !item.openId"></div>
</u-row>
</label>
</div>
</div>
</div>
</div>
</template>
<script>
import AiTopFixed from "../AiTopFixed";
export default {
name: "tree",
components: {AiTopFixed},
props: {
checkList: {
type: Array,
default: () => []
},
searchIf: {
type: Boolean,
default: () => true
},
multiple: {
type: Boolean,
default: true
},
rootId: Object,
},
data() {
return {
isSear: false,
tree: [],
parent: [1],
searchResult: [],
allData: [],
newCheckList: this.checkList,
scrollLeft: Infinity,
keyword: "",
current: 0,
tag: "name",
}
},
methods: {
tabChange(e) {
this.tag = e == 0 ? "name" : "tagname"
this.current = e
this.parent = [1]
// this.newCheckList = []
this.getTree()
},
clear() {
this.keyword = ""
this.tree = this.allData
this.parent = [1]
this.isSear = false
},
checkboxChange(item, index) {
if (item.checked) {
this.$set(this.tree[index], 'checked', false)
this.delChild(item)
for (let index = 0, n = this.newCheckList.length; index < n; index++) {
let temp = this.newCheckList[index];
if (temp.id == item.id) {
this.newCheckList.splice(index, 1)
break
}
}
} else {
(item.type == 0 || item.openId) && this.newCheckList.push(item)
this.$set(this.tree[index], 'checked', true)
this.chooseChild(item)
}
this.$emit('sendValue', this.newCheckList)
},
delUser(id) {
for (let i = 0, len = this.newCheckList.length; i < len; i++) {
if (this.newCheckList[i].id === id) {
return this.newCheckList.splice(i, 1)
}
}
},
chooseChild(arr) {
if (arr.childrenDept?.length) {
for (let i = 0, len = arr.childrenDept.length; i < len; i++) {
let item = arr.childrenDept[i]
item.checked = true
this.newCheckList.push(item)
this.chooseChild(item)
}
}
if (arr.childrenUser?.length) {
for (let i = 0, len = arr.childrenUser.length; i < len; i++) {
let item = arr.childrenUser[i]
item.checked = true
this.newCheckList.push(item)
this.chooseChild(item)
}
}
if (arr.users?.length) {
for (let i = 0, len = arr.users.length; i < len; i++) {
let item = arr.users[i]
item.checked = true
this.newCheckList.push(item)
this.chooseChild(item)
}
}
this.newCheckList = Array.from(new Set(this.newCheckList))
},
delChild(arr) {
if (arr.childrenDept?.length) {
for (let i = 0, len = arr.childrenDept.length; i < len; i++) {
let item = arr.childrenDept[i];
item.checked = false
for (let index = 0, n = this.newCheckList.length; index < n; index++) {
let temp = this.newCheckList[index];
if (temp.id == item.id) {
this.newCheckList.splice(index, 1)
break
}
}
this.delChild(item)
}
}
if (arr.childrenUser?.length) {
for (let i = 0, len = arr.childrenUser.length; i < len; i++) {
let item = arr.childrenUser[i];
item.checked = false
for (let index = 0, n = this.newCheckList.length; index < n; index++) {
let temp = this.newCheckList[index];
if (temp.id == item.id) {
this.newCheckList.splice(index, 1)
break
}
}
this.delChild(item)
}
}
},
//单选
checkbox(item, index) {
let status = !this.tree[index].checked
this.$set(this.tree[index], 'checked', status)
if (this.newCheckList.length <= 0) {
this.newCheckList = [this.tree[index]]
} else if (this.newCheckList.length == 1) {
this.tree.forEach(item => {
if (item.id != this.tree[index].id) {
item.checked = false
}
})
this.newCheckList = []
if (this.tree[index].checked) {
this.newCheckList.push(this.tree[index])
}
}
this.$emit('sendValue', this.newCheckList)
},
toNext(item) {
if (this.tag == "name") {
if (item.type == 1 && (item["childrenDept"].length || item["childrenUser"].length)) {
this.tree = []
if (item["childrenDept"].length) {
this.tree = item["childrenDept"]
}
if (item["childrenUser"].length) {
this.tree = [...this.tree, ...item["childrenUser"]]
}
this.checkIf()
if (this.parent[0].id !== item.id) {
this.parent.push(item)
}
}
} else if (this.tag == "tagname" && !item.openId) {
this.tree = item.users
if (this.parent[0].id !== item.id) {
this.parent.push(item)
}
}
this.$nextTick(() => {
this.scrollLeft += 200
})
},
checkIf() {
for (let i = 0, len = this.tree.length; i < len; i++) {
for (let j = 0, lens = this.newCheckList.length; j < lens; j++) {
if (this.newCheckList[j].id == this.tree[i].id) {
this.$set(this.tree[i], 'checked', true)
break
} else {
this.$set(this.tree[i], 'checked', false)
}
}
}
},
confirmSearch(val) {
this.searchResult = []
this.search(this.tree, val)
this.isSear = true
this.parent.splice(1, Infinity)
this.tree = this.searchResult
if (!val) this.clear()
},
search(data, keyword) {
if (data.length) {
for (let i = 0, len = data.length; i < len; i++) {
if (data[i].name?.indexOf(keyword) != -1) {
this.searchResult.push(data[i])
}
if (data[i]["childrenDept"]?.length || data[i]["childrenUser"]?.length) {
this.search(data[i]["childrenDept"].concat(data[i]["childrenUser"]), keyword)
}
if (data[i]["users"]?.length) {
this.search(data[i]["users"], keyword)
}
}
}
},
backTree(item, index) {
if (index == -1) {
this.tree = this.allData
this.parent.splice(1, Infinity)
this.isSear = false
this.keyword = ""
} else if (index == -2) {
this.tree = this.searchResult
this.parent.splice(1, Infinity)
} else {
if (this.parent.length - index > 2) {
this.parent.forEach((item, i) => {
if (i > index) {
this.parent.splice(i, Infinity)
}
})
} else if (index != this.parent.length - 1) {
this.parent.splice(this.parent.length - 1, 1)
}
this.tree = item["childrenDept"].concat(item["childrenUser"] || [])
}
if (this.multiple) return
this.checkIf()
},
getTree() {
this.$http.post(this.current == 0 ? "/app/wxcp/wxuser/tree" : "/app/wxcp/wxtag/tree", null, {
params: {
rootId: this.rootId
}
}).then(res => {
if (res && res.data) {
let result = this.tag == 'name' ? [res.data] : res.data
this.tree = result
this.allData = result
}
})
},
},
computed: {
list() {
return [
{name: "组织架构"},
{name: "标签"}
]
}
},
created() {
this.getTree()
}
}
</script>
<style lang="scss" scoped>
.tree {
min-height: 100%;
background-color: #F5F5F5;
.top {
background-color: #FFFFFF;
}
.tree-list {
margin-top: 24px;
background-color: #FFFFFF;
.scroll {
white-space: nowrap;
border-bottom: 1px solid #f4f4f4;
.inline-item {
height: 112px;
font-size: 30px;
display: inline-block;
line-height: 112px;
.active {
color: #4297ED !important;
font-weight: 600;
}
.none {
color: #666666;
font-weight: 600;
}
}
}
.container-list {
min-height: 1000px;
overflow-y: scroll;
overflow-x: hidden;
.common {
background-color: #fff;
border-bottom: 1px solid #f4f4f4;
box-sizing: border-box;
padding: 0 30px;
.content {
display: flex;
align-items: center;
height: 100px;
width: 100%;
line-height: 100px;
position: relative;
font-size: 32px;
.right {
width: 16px;
height: 16px;
border-right: 4px solid #CCCCCC;
border-top: 4px solid #CCCCCC;
transform: rotate(45deg);
}
.word {
display: flex;
align-items: center;
& > img {
width: 74px;
height: 74px;
margin: 0 34px;
}
.ellipsis {
width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.checkbox {
position: relative;
display: flex;
align-items: center;
& > img {
width: 48px;
height: 48px;
border-radius: 50%;
}
.color {
color: #00aaff;
background-color: #00aaff;
}
}
.person {
display: flex;
align-items: center;
color: #f57a00;
font-size: 36px;
text-align: center;
margin: 0 34px;
flex-shrink: 0;
}
}
}
}
}
::v-deep .content {
padding: 0 !important;
}
.pad {
box-sizing: border-box;
padding: 20px 32px 0;
}
}
</style>