asd/asd-pc/components/xiaolu-tree/tree.vue
愉快的大福 eb8378e551 init
2024-11-21 11:06:22 +08:00

655 lines
17 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view>
<view class="header">
<search v-if="searchIf" ref="sea" @confirm="confirmSearch" @add="addGroup" />
<view class="title">
<scroll-view scroll-x style="width: 100%;white-space: nowrap;" :scroll-left="scrollLeft">
<view v-for="(item,index) in tree_stack" class="inline-item" :key="index">
<view class="inline-item" v-if="index==0" @click="backTree(item,-1)">
<text :class="[(index==tree_stack.length-1&&!isre)?'none':'active']">全部</text>
</view>
<view v-if="index==0&&isre" @click="backTree(item,-2)"
:class="[index==tree_stack.length-1&&isre]?'none inline-item':'active inline-item'">
<!-- <i class="iconfont icon-z043 iconclass" />-->
<view style="display: inline-block;">
<u-icon name="arrow-right" color="#D0D4DB" size="14"></u-icon>
</view>
搜索结果
</view>
<view class="inline-item" @click="backTree(item,index)" v-if="index!=0">
<!-- <i class="iconfont icon-z043 iconclass" /> -->
<view style="display: inline-block;">
<u-icon name="arrow-right" color="#D0D4DB" size="14"></u-icon>
</view>
<text :class="index==tree_stack.length-1?'none inline-ite':'active'">
{{item[props.label]}}
</text>
</view>
</view>
</scroll-view>
</view>
</view>
<view>
<view class="container-list">
<u-swipe-action>
<template v-for="(item, index) in tree">
<u-swipe-action-item v-if="item.type=='user'" :options="options2"
:disabled="item.type=='system'?true:false" :key="item.id" @click="operateClick"
:name="item.type+item.id">
<view class="common" @click="handleClick(item,index)">
<label class="content">
<view class="list-item" v-show="isCheck">
<!-- 多选 -->
<view class="checkbox" v-if="props.multiple" @click.stop="handleClick(item,-1)">
<span v-if="isSelect(item)">
<i v-if="item.bx&&newCheckList.length!=0"
class="iconfont icon-banxuanzhongshousuo1-shi icons" />
<i v-else class="iconfont icon-xuanzhong txt icon-selected" />
</span>
<i v-else-if="item.qx" class="iconfont icon-xuanzhong txt icon-selected" />
<i v-else-if="item.bx"
class="iconfont icon-banxuanzhongshousuo1-shi icons" />
<i style="color: #b8b8b8;" v-else class="iconfont icon-weixuanzhong txt" />
</view>
<!-- 单选 -->
<view class="checkbox" v-else-if="(props.nodes?item.user?true:false:true)"
@click.stop="handleClick(item,-1)">
<i v-if="radioSelect(item)" class="txt iconfont icon-selected" />
<i style="color: #b8b8b8;" v-else class="txt iconfont icon-weixuanzhong1" />
</view>
</view>
<view class="avator" v-if="isAvator&&item.user" @click.stop="goDetails(item)">
<img
:src="item.avatar?(item.avatar.indexOf('http')!=-1?item.avatar:basePicUrl+item.avatar):avatorUrl">
</view>
<view class="lable-text">{{item[props.label]}}</view>
<view class="right">
<!-- <i v-if="!item.user&&item.children.length>0"
class="iconfont icon-z043 iconclass"></i> -->
<u-icon v-if="!item.user&&item.children.length>0" name="arrow-right"></u-icon>
</view>
</label>
</view>
</u-swipe-action-item>
<u-swipe-action-item v-else :options="options1"
:disabled="item.type=='system'?true:false" :key="item.id" @click="operateClick"
:name="item.type+item.id">
<view class="common" @click="handleClick(item,index)">
<label class="content">
<view class="list-item" v-show="isCheck">
<!-- 多选 -->
<view class="checkbox" v-if="props.multiple" @click.stop="handleClick(item,-1)">
<span v-if="isSelect(item)">
<i v-if="item.bx&&newCheckList.length!=0"
class="iconfont icon-banxuanzhongshousuo1-shi icons" />
<i v-else class="iconfont icon-xuanzhong txt icon-selected" />
</span>
<i v-else-if="item.qx" class="iconfont icon-xuanzhong txt icon-selected" />
<i v-else-if="item.bx"
class="iconfont icon-banxuanzhongshousuo1-shi icons" />
<i style="color: #b8b8b8;" v-else class="iconfont icon-weixuanzhong txt" />
</view>
<!-- 单选 -->
<view class="checkbox" v-else-if="(props.nodes?item.user?true:false:true)"
@click.stop="handleClick(item,-1)">
<i v-if="radioSelect(item)" class="txt iconfont icon-selected" />
<i style="color: #b8b8b8;" v-else class="txt iconfont icon-weixuanzhong1" />
</view>
</view>
<view class="avator" v-if="isAvator&&item.user" @click.stop="goDetails(item)">
<img
:src="item.avatar?(item.avatar.indexOf('http')!=-1?item.avatar:basePicUrl+item.avatar):avatorUrl">
</view>
<view class="lable-text">{{item[props.label]}}</view>
<view class="right">
<!-- <i v-if="!item.user&&item.children.length>0"
class="iconfont icon-z043 iconclass"></i> -->
<u-icon v-if="!item.user&&item.children.length>0" name="arrow-right"></u-icon>
</view>
</label>
</view>
</u-swipe-action-item>
</template>
</u-swipe-action>
</view>
</view>
<u-picker :show="isShow" :columns="columns" keyName="groupName" title="将联系人添加至" closeOnClickOverlay
@confirm="removeSure" @cancel="isShow=false" @close="isShow=false"></u-picker>
<u-modal :show="isShow1" :content='content' showCancelButton closeOnClickOverlay @confirm="deleteSure"
@cancel="isShow1=false" @close="isShow1=false"></u-modal>
<!-- <view class="btn box_sizing">
<button class="sureBtn" type="primary" @click="backConfirm">确认</button>
</view> -->
</view>
</template>
<script>
import search from './search/index.vue'
import {
deleteAddress,
myAddressList,
addAddressBook
} from "@/common/api/api.js"
export default {
name: "treeComponent",
data() {
return {
basePicUrl: this.$basePicUrl,
content: "",
value: "",
isShow1: false,
isShow: false,
isre: false,
tree: Object.freeze(this.treeNone),
newNum: 0,
oldNum: 0,
catchTreeNone: [...this.treeNone],
tree_stack: [1],
searchResult: [],
newCheckList: this.checkList,
scrollLeft: 999,
nodePathArray: [],
options1: [{
text: '删除',
style: {
backgroundColor: '#f56c6c',
}
}],
options2: [{
text: '添加至',
style: {
backgroundColor: '#3c9cff',
}
}, {
text: '删除',
style: {
backgroundColor: '#f56c6c',
}
}],
columns: [],
}
},
components: {
search
},
computed: {
isSelect() {
return (item) => {
const checkList = this.newCheckList
if (checkList.length == 0) {
this.props.checkStrictly ? (item.bx = 0, item.qx = 0) : ''
return false
}
const i = checkList.findIndex(e => {
return item[this.keyCode] == e[this.keyCode]
}) > -1
return i && !item.qx
}
},
radioSelect() {
const list = this.newCheckList
return (item) => {
return list.length > 0 && item[this.keyCode] == list[0][this.keyCode]
}
},
keyCode() {
return this.keyValue
}
},
created() {
this.Init()
},
methods: {
goDetails(item) {
this.$emit("toPerson", item);
},
// 移动联系人
removeSure(data) {
console.log(data.value[0]);
let params = {
"addressUserId": this.personId,
"createBy": "",
"createTime": "",
"groupName": "",
"gruopId": data.value[0].id,
"id": "",
"type": "1",
"updateBy": "",
"updateTime": "",
"userId": ""
}
addAddressBook(params).then(res => {
if (res.code == 200) {
uni.showToast({
title: "添加成功",
icon: "success",
duration: 2000
})
this.isShow = false;
this.$emit("reload")
} else {
uni.showToast({
title: "添加失败",
icon: "none",
duration: 2000
})
}
})
},
//删除联系人
deleteSure() {
deleteAddress(null, "?id=" + this.personId).then(res => {
if (res.code == 200) {
uni.showToast({
title: "删除成功",
icon: "success",
duration: 2000
})
this.isShow1 = false;
this.$emit("reload")
} else {
uni.showToast({
title: "删除失败",
icon: "none",
duration: 2000
})
}
})
},
sure() {
this.show = false;
},
operateClick(data) {
if (data.name.indexOf('user') != -1) {
this.personId = data.name.replace("user", "");
if (data.index == 0) {
//移动 联系人
//请求自建分组列表
myAddressList().then(res => {
if (res.code == 200) {
this.columns = [
[...res.result.records]
];
this.isShow = true;
} else {
uni.showToast({
title: "获取自建分组失败",
icon: "none",
duration: 2000
})
}
})
} else {
//删除联系人
this.content = "是否要删除该联系人"
this.isShow1 = true;
}
}
if (data.name.indexOf('my') != -1) {
//删除自建分组
this.personId = data.name.replace("my", "");
this.content = "是否要删除该分组"
this.isShow1 = true;
}
},
addGroup(value) {
this.$emit("add", value)
},
// 初始化
Init() {
if (this.newCheckList.length !== 0) {
let {
tree_stack,
props,
catchTreeNone,
newCheckList
} = this
if (props.multiple) {
if (props.checkStrictly) {
this.checkAllChoose();
}
} else {
this.getNodeRoute(catchTreeNone, newCheckList[0][this.keyCode])
let arr = this.nodePathArray.reverse()
console.log(arr)
if (arr.length == 0) return
this.tree_stack = tree_stack.concat(arr);
this.tree = this.tree_stack[this.tree_stack.length - 1].children;
}
}
},
// 点击项目处理
handleClick(item, index) {
console.log(item);
let children = item[this.props.children]
if (index > -1 && children && children.length > 0) {
console.log(index)
this.toChildren(item)
} else if (this.props.multiple) {
this.checkboxChange(item, index, item.bx, item.qx)
} else {
this.checkbox(item, index)
}
},
// 获取路径
getPath() {
const {
keyCode,
tree_stack,
props
} = this
const path = [...tree_stack].map(e => {
const item = Object.assign({}, e)
delete item[props.children]
return item
})
return path.slice(1, path.length) || []
},
//多选
async checkboxChange(item, index, bx, qx) {
let that = this;
const {
props
} = that
if (!props.multiple) return;
let findIdex = that.newCheckList.findIndex(e => item[this.keyCode] == e[this.keyCode]);
const path = this.getPath()
if (findIdex > -1) { //反选
if (props.checkStrictly) { //关联子级
if (item.user) { //用户
that.newCheckList.splice(findIdex, 1)
} else { //非用户,取消所有下一级
that.getIdBydelete(item.children)
}
} else {
that.newCheckList.splice(findIdex, 1)
}
} else { //选中
if (!item.user && props.checkStrictly) { //选中下一级
if (qx || bx) { //取消下级
await that.getIdBydelete(item.children);
item.qx = 0;
item.bx = 0;
} else {
item.qx = 1;
item.bx = 0;
const {
id,
name,
user
} = item
const newObj = {
id,
name,
user
}
const pathList = this.tree_stack.length === 1 ? [newObj, ...path] : [...path, newObj]
await that.chooseChild(item.children, pathList);
}
this.$forceUpdate()
return
}
that.newCheckList.push({
...item,
path
});
}
},
// 取消下一级的选中
getIdBydelete(arr) {
arr.forEach(e => {
if (e.user) {
for (var i = 0; i < this.newCheckList.length; i++) {
if (e[this.keyCode] == this.newCheckList[i][this.keyCode]) {
this.newCheckList.splice(i, 1)
break;
}
}
} else {
this.getIdBydelete(e.children)
}
})
},
// 关联下一级,选中
chooseChild(arr, path) {
let that = this;
const oldPath = [...path]
for (var i = 0, len = arr.length; i < len; i++) {
let item = arr[i];
if (item.user) {
that.newCheckList.push({
...item,
path: oldPath
})
} else {
const newItem = {
...item
}
delete newItem[that.props.children]
const newPath = [...oldPath, newItem]
that.chooseChild(item.children, newPath)
}
}
},
// (tree为目标树targetId为目标节点id)
getNodeRoute(tree, targetId) {
for (let index = 0; index < tree.length; index++) {
if (tree[index].children) {
let endRecursiveLoop = this.getNodeRoute(tree[index].children, targetId)
if (endRecursiveLoop) {
this.nodePathArray.push(tree[index])
return true
}
}
if (tree[index][this.keyCode] === targetId) {
return true
}
}
},
//单选
checkbox(item, index) {
const path = this.getPath()
this.$set(this, 'newCheckList', [{
...item,
path
}])
if (item.user) {
//直接发起聊天
console.log("12432");
this.$emit("toChat", item)
}
},
//到下一级
toChildren(item) {
if (item.user) return
var that = this;
uni.showLoading({
title: '加载中'
})
let children = that.props.children;
if (!item.user && item[children].length > 0 && !(that.tree_stack[0][this.keyCode] == item[this.keyCode])) {
that.tree = item[children];
that.tree_stack.push(item);
}
this.$nextTick(() => {
uni.hideLoading()
this.scrollLeft += 200;
})
if (this.props.checkStrictly) this.checkAllChoose();
},
//搜索
confirmSearch(val) {
this.searchResult = []
this.search(this.catchTreeNone, val)
this.isre = true
this.tree_stack.splice(1, 1000)
uni.showLoading({
title: '正在查找'
})
setTimeout(() => {
this.tree = this.searchResult
uni.hideLoading()
}, 300)
},
search(data, keyword) {
var that = this
let children = that.props.children
for (var i = 0, len = data.length; i < len; i++) {
if (data[i].name.indexOf(keyword) >= 0) {
that.searchResult.push(data[i])
}
if (!data[i].user && data[i][children].length > 0) {
that.search(data[i][children], keyword)
}
}
},
checkAllChoose() {
let o = false,
t = true;
this.tree.forEach((e, i) => {
if (!e.user) {
e.qx = o;
e.bx = o;
this.computAllNumber(e.children);
// console.log(this.newNum,this.oldNum)
if (this.newNum != 0 && this.oldNum != 0) {
if (this.newNum == this.oldNum) {
e.qx = t;
e.bx = o;
} else {
e.qx = o;
e.bx = t;
}
}
if (this.newNum != 0 && this.oldNum == 0) {
this.$set(this.tree[i], 'bx', o);
this.$set(this.tree[i], 'qx', o);
}
this.$forceUpdate()
this.newNum = 0
this.oldNum = 0
}
})
},
computAllNumber(arr) {
for (let j = 0; j < arr.length; j++) {
var e = arr[j];
this.checkSum(e[this.keyCode])
if (e.user) {
this.newNum++;
} else {
this.computAllNumber(e.children)
}
}
},
checkSum(id) {
for (let i = 0; i < this.newCheckList.length; i++) {
if (id == this.newCheckList[i][this.keyCode]) {
this.oldNum++;
break
}
}
},
//返回其它层
backTree(item, index) {
console.log(index);
let that = this,
tree_stack = that.tree_stack,
max = 10000;
if (index === -1) {
that.tree = that.catchTreeNone
that.tree_stack.splice(1, max)
that.isre = false
that.$refs.sea.clears()
} else if (index === -2) {
that.tree = that.searchResult
that.tree_stack.splice(1, max)
} else {
if (tree_stack.length - index > 2) {
tree_stack.forEach((item, i) => {
if (i > index) {
that.tree_stack.splice(i, max)
}
})
} else if (index !== tree_stack.length - 1) {
that.tree_stack.splice(tree_stack.length - 1, 1)
}
that.tree = item[that.props.children]
}
if (this.props.checkStrictly) this.checkAllChoose();
this.$forceUpdate()
},
backConfirm() {
this.$emit('sendValue', this.newCheckList, 'back')
}
},
props: {
treeNone: {
type: Array,
default: () => {
return []
}
},
//是否开启选中
isCheck: {
type: Boolean,
default: () => {
return false
}
},
isAvator: {
type: Boolean,
default: () => {
return false
}
},
checkList: {
type: Array,
default: () => []
},
parentList: {
type: Array,
default: () => []
},
searchIf: {
type: Boolean,
default: () => true
},
keyValue: {
type: String,
default: 'id',
},
avatorUrl: {
type: String,
default: '',
},
props: {
type: Object,
default: () => {
return {
label: 'name',
children: 'children',
multiple: false,
checkStrictly: false, //不关联
}
}
}
},
}
</script>
<style lang="scss" scoped>
@import './css/style.scss';
@import url("./css/icon.css");
</style>