You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

730 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template xlang="wxml">
<view class="tki-tree">
<view
class="tki-tree-mask"
:class="{ show: showTree }"
@tap="_cancel"
></view>
<view class="tki-tree-cnt" :class="{ show: showTree }">
<view class="tki-tree-bar">
<view
class="tki-tree-bar-cancel"
@tap="_cancel"
:style="{ color: cancelColor }"
hover-class="hover-c"
>
取消
</view>
<view v-if="isSearch" class="tki-tree-bar-title">
<u-search
class="searchinput"
v-model="keyword"
:placeholder="placeholder"
@custom="_searchcustom"
@clear="_searchclear"
:clearabled="true"
:show-action="showAction"
@change="searchchange"
shape="square"
bg-color="#EFF4F9"
input-align="left"
></u-search>
</view>
<view v-else class="tki-tree-bar-title" :style="{ color: titleColor }">
{{ title }}
</view>
<view
class="tki-tree-bar-confirm"
:style="{ color: confirmColor }"
hover-class="hover-c"
@tap="_confirm"
>确定</view
>
</view>
<view class="tki-tree-view">
<scroll-view class="tki-tree-view-sc" :scroll-y="true">
<block v-for="(item, index) in treeList" :key="index">
<view
class="tki-tree-item"
:style="[
{
paddingLeft: item.rank * 15 + 'px',
zIndex: item.rank * -1 + 50,
},
]"
:class="{
border: border === true,
show: item.show,
last: item.lastRank,
showchild: item.showChild,
open: item.open,
}"
>
<view
class="tki-tree-label"
@tap.stop="_treeItemTap(item, index)"
>
<image
class="tki-tree-icon"
:src="
item.lastRank
? lastIcon
: item.showChild
? currentIcon
: defaultIcon
"
></image>
{{ item.name }} {{isCount&&!item.lastRank?'('+item.count+')':''}}
</view>
<view
class="tki-tree-check"
@tap.stop="_treeItemSelect(item, index)"
v-if="
((selectParent ? true : item.lastRank) && (isArea ? item.source[lastNotchoose] == 1 : true)) &&((isLevel && selectLevel && (item.rank + 1) >= selectLevel)||!isLevel)
"
>
<view
class="tki-tree-check-yes"
v-if="item.checked"
:class="{ radio: !multiple }"
:style="{ 'border-color': confirmColor }"
>
<view
class="tki-tree-check-yes-b"
:style="{ 'background-color': confirmColor }"
></view>
</view>
<view
class="tki-tree-check-no"
v-else
:class="{ radio: !multiple }"
:style="{ 'border-color': confirmColor }"
></view>
</view>
</view>
</block>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
export default {
name: "tki-tree",
props: {
range: {
type: Array,
default: function () {
return [];
},
},
idKey: {
type: String,
default: "id",
},
// 用于反显 传字符串格式:'12112121,31313131'
defaultIds: {
// type: String,
default: "",
},
value: {
type: String,
default: "",
},
rangeKey: {
type: String,
default: "label",
},
title: {
type: String,
default: "",
},
multiple: {
// 是否可以多选
type: Boolean,
default: false,
// default: true
},
isArea: {
//是否区域 只有区域可选
type: Boolean,
default: false,
},
selectParent: {
//是否可以选父级
type: Boolean,
default: false,
},
selectThis: {
type: Boolean,
default: false,
},
isLevel: {
// 是否可从第几级别可选
type: Boolean,
default: false,
},
selectLevel: {
// 从第几级可选 根目录是从一级开始赋值1
type: Number,
default: 0, // 从第几级别可选
},
foldAll: {
//折叠时关闭所有已经打开的子集,再次打开时需要一级一级打开
type: Boolean,
default: false,
},
confirmColor: {
// 确定按钮颜色
type: String,
default: "", // #07bb07
},
cancelColor: {
// 取消按钮颜色
type: String,
default: "", // #757575
},
lastNotchoose: {
//判断不同接口最后可选类型
type: String,
default: "", // #757575
},
titleColor: {
// 标题颜色
type: String,
default: "", // #757575
},
currentIcon: {
// 展开时候的ic
type: String,
default: require("@/static/images/arrowx.png"),
},
defaultIcon: {
// 折叠时候的ic
type: String,
default: require("@/static/images/arrowr.png"),
},
lastIcon: {
// 没有子集的ic
type: String,
default: "",
},
border: {
// 是否有分割线
type: Boolean,
default: false,
},
unfold: {
// 是否全部展开
type: Boolean,
default: false,
},
isCount: {
// 是否开启父控件统计模式
type: Boolean,
default: false,
},
isSearch: {
// 是否开启模糊查询
type: Boolean,
default: false,
},
placeholder: {
// 请输入检索关键字
type: String,
default: "请输入检索关键字",
},
searchKey: {
// 筛选关键字键值
type: String,
default: "",
},
},
data() {
return {
showTree: false,
treeListData: [],
treeList: [],
selectIndex: -1,
thisItem: null,
thisIndex: null,
idArr: [],
showAction: false,
keyword: "", //检索关键字
sort:1,
// value :this.localValue
};
},
computed: {},
methods: {
// _handleList(val) {
// this.value =val
// console.log(this.value)
// },
_show() {
this.showTree = true;
},
_hide() {
// this.showTree = false;
// 出发确定事件
this._confirm();
},
_cancel() {
this._hide();
this.$emit("cancel", "");
},
_searchcustom(val) {
// 检索模糊查询事件
if (this.searchKey) {
// 筛选之前先清除选中的数据
this.treeListData.forEach((v, i) => {
this.treeListData[i].checked = false;
});
this.treeList = this.treeListData.filter((p) => {
//filter过滤的意思这个是过滤函数将每一项符合结果的值返回到personList
return (
(p.source &&
p.source[this.searchKey] &&
p.source[this.searchKey].indexOf(val) !== -1) ||
(p.source && p.source.children
? this.isfilter(p.source.children, val)
: false)
);
});
}
// this.$emit("searchDo", val);
},
isfilter(arrs, val) {
var rets = false;
arrs.filter((p) => {
//filter过滤的意思这个是过滤函数将每一项符合结果的值返回到personList
if (
(p[this.searchKey] && p[this.searchKey].indexOf(val) !== -1) ||
(p.children ? this.isfilter(p.children, val) : false)
) {
rets = true;
}
});
return rets;
},
_searchclear() {
// 检索 清除关键字查询全部事件
this.showAction = false;
var inidata = this.treeListData;
this.treeList = [...inidata];
// this.$emit("searchDo", "");
},
searchchange(value) {
if (value) {
this.showAction = true;
}
},
_confirm() {
// 处理所选数据
let rt = [],
treeList = this.treeList,
obj = {};
if (this.selectThis) {
treeList = this.treeList.slice(0, this.thisIndex + 1);
}
treeList.forEach((v, i) => {
if (treeList[i].checked) {
obj = {};
obj.parents = treeList[i].parents;
console.log(obj.sort)
obj = Object.assign(obj, treeList[i].source);
// 移除子元素
delete obj.children
console.log(obj)
obj.sort = treeList[i].sort;
rt.push(obj);
}
});
// this._hide();
this.showTree = false;
this.$emit("confirm", rt);
},
//扁平化树结构
_renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
list.forEach((item) => {
this.treeList.push({
id: item[this.idKey],
name: item[this.rangeKey],
source: item,
parentId, // 父级id数组
parents, // 父级id数组
rank, // 层级
showChild: this.unfold, //false, //子级是否显示
open: this.unfold, //false, //是否打开
show: rank === 0 || this.unfold, // 自身是否显示
hideArr: [],
orChecked: item.checked ? item.checked : false,
checked: item.checked ? item.checked : false,
count:(((this.selectParent ? true : !item.children) && (this.isArea ? this.lastNotchoose&&item[this.lastNotchoose]&&item[this.lastNotchoose] == 1 : true)) ||
(this.isLevel && this.selectLevel && rank + 1 >= this.selectLevel)?1:0)
});
if (Array.isArray(item.children) && item.children.length > 0) {
let parentid = [...parentId],
parentArr = [...parents],
childrenid = [...childrenid];
delete parentArr.children;
parentid.push(item[this.idKey]);
parentArr.push({
[this.idKey]: item[this.idKey],
[this.rangeKey]: item[this.rangeKey],
});
this._renderTreeList(item.children, rank + 1, parentid, parentArr);
} else {
this.treeList[this.treeList.length - 1].lastRank = true;
}
});
},
// 处理默认选择
_defaultSelect(val) {
if (this.defaultIds) {
let defaultIds = this.defaultIds.split(",") || this.defaultIds;
this.treeList.forEach((item) => {
defaultIds.forEach((i) => {
if (item.id == i) {
item.checked = true;
}
});
});
}
this.treeList.forEach((v, i) => {
if (v.checked) {
this.treeList.forEach((v2, i2) => {
if (v.parentId.toString().indexOf(v2.parentId.toString()) >= 0) {
v2.show = true;
if (v.parentId.includes(v2.id)) {
v2.showChild = true;
v2.open = true;
}
}
});
}
});
},
// 点击
_treeItemTap(item, index) {
this.thisItem = item;
this.thisIndex = index;
console.log(item, index, "点击");
if (item.lastRank === true) {
//点击最后一级时触发事件
if (item.source.isArea == 1) {
this.treeList[index].checked = !this.treeList[index].checked;
this._fixMultiple(index);
return;
}
}
let list = this.treeList;
let id = item.id;
item.showChild = !item.showChild;
item.open = item.showChild ? true : !item.open;
list.forEach((childItem, i) => {
if (item.showChild === false) {
//隐藏所有子级
if (!childItem.parentId.includes(id)) {
return;
}
if (!this.foldAll) {
if (childItem.lastRank !== true && !childItem.open) {
childItem.showChild = false;
}
// 为隐藏的内容添加一个标记
if (childItem.show) {
childItem.hideArr[item.rank] = id;
}
} else {
if (childItem.lastRank !== true) {
childItem.showChild = false;
}
}
childItem.show = false;
} else {
// 打开子集
if (childItem.parentId[childItem.parentId.length - 1] === id) {
childItem.show = true;
}
// 打开被隐藏的子集
if (childItem.parentId.includes(id) && !this.foldAll) {
// console.log(childItem.hideArr)
if (childItem.hideArr[item.rank] === id) {
childItem.show = true;
if (childItem.open && childItem.showChild) {
childItem.showChild = true;
} else {
childItem.showChild = false;
}
childItem.hideArr[item.rank] = null;
}
// console.log(childItem.hideArr)
}
}
});
// console.log(this.treeList)
},
_treeItemSelect(item, index) {
item.sort=this.sort
this.sort++;
this.thisItem = item;
this.thisIndex = index;
this.treeList[index].checked = !this.treeList[index].checked;
this._fixMultiple(index);
if (this.selectParent) {
// 可以选择父级时候,单选某个节点自行判断上下节点都选中,否则默认选中用户点击的
this._chenge(item, this.treeList[index].checked);
}
},
_chenge(e, e1) {
console.log(e)
this.idArr.push(e.id);
if (e.source.children == undefined &&this.multiple) {
this.treeList.forEach((k, i) => {
this.idArr.forEach((k1, i1) => {
if (k.id == k1 && e1 == true) {
this.treeList[i].checked = true;
} else if (k.id == k1 && e1 == false) {
this.treeList[i].checked = false;
}
});
});
if (e.checked) {
e.parentId.forEach((k, i) => {
this.treeList.forEach((k1, i1) => {
if (k1.id == k) {
this.treeList[i1].checked = true;
}
});
});
} else {
e.parentId.forEach((k, i) => {
this.treeList.forEach((k1, i1) => {
if (k1.id == k) {
this.treeList[i1].checked = false;
}
});
});
}
this.treeList.forEach((k1, i1) => {
if (k1.checked ) {
k1.parentId.forEach((k2, i2) => {
this.treeList.forEach((k3, i3) => {
if (k3.id == k2) {
this.treeList[i3].checked = true;
}
});
});
}
});
this.idArr = [];
return;
}
if (!this.selectThis) { //增加判断 选择本级的时候 下级不会被选中
this.handkeCheck1(e.source.children);
}
this.treeList.forEach((k, i) => {
this.idArr.forEach((k1, i1) => {
if (k.id == k1 && e1 == true) {
this.treeList[i].checked = true;
} else if (k.id == k1 && e1 == false) {
this.treeList[i].checked = false;
}
});
});
if(this.multiple){
if ( e.checked) {
e.parentId.forEach((k, i) => {
this.treeList.forEach((k1, i1) => {
if (k1.id == k) {
this.treeList[i1].checked = true;
}
});
});
} else {
e.parentId.forEach((k, i) => {
this.treeList.forEach((k1, i1) => {
if (k1.id == k) {
this.treeList[i1].checked = false;
this.treeList[i1].halfchecked = true;
}
});
});
}
this.treeList.forEach((k1, i1) => {
if (k1.checked) {
k1.parentId.forEach((k2, i2) => {
this.treeList.forEach((k3, i3) => {
if (k3.id == k2) {
this.treeList[i3].checked = true;
}
});
});
}
});
}
this.idArr = [];
},
handkeCheck1(list) {
list.forEach((k, i) => {
this.idArr.push(k.id);
if (k.children == undefined) return;
this.handkeCheck1(k.children);
});
},
handkeCheck(list, e, e1) {
// 点击数据权限
list.forEach((k, i) => {
if (k.children != undefined) {
if (k.id == e.id && e.checked == true) {
k.checked = true;
// console.log(k.id,'第一');
this.handkeChecks(k.children, e, e1);
} else if (k.id == e.id && e.checked == false) {
k.checked = false;
this.handkeChecks(k.children, e, e1);
} else {
this.handkeCheck(k.children, e, e1);
}
} else {
// console.log(1);
if (k.id == e.id && e.checked == true) {
k.checked = true;
} else if (k.id == e.id && e.checked == false) {
k.checked = false;
}
}
});
},
handkeChecks(list, e, e1) {
list.forEach((k, i) => {
if (k.children != undefined) {
if (e.checked) {
k.checked = true;
this.handkeChecks(k.children, e, e1);
} else {
k.checked = false;
this.handkeChecks(k.children, e, e1);
}
} else {
// console.log(k, 'else');
if (e.checked) {
k.checked = true;
} else {
k.checked = false;
}
}
});
},
// 处理单选多选
_fixMultiple(index) {
if (!this.multiple) {
// 如果是单选
this.treeList.forEach((v, i) => {
if (i != index) {
this.treeList[i].checked = false;
} else {
// 多余的,点击一下取消选中 否则一直选中不能取消
// this.treeList[i].checked = true;
// console.log(index,'4444');
}
});
}
},
// 重置数据
_reTreeList() {
this.treeList.forEach((v, i) => {
this.treeList[i].checked = v.orChecked;
});
},
_initTree(range = this.range) {
// console.log('接收值的事件');
this.treeList = [];
this._renderTreeList(range);
// console.log(this.treeList)
this.$nextTick(() => {
this._defaultSelect(range);
if (this.treeList.length > 0) {
this.treeList.map((item, index) => {
// if( this.value.indexOf(item.id)>=0){
if (!this.multiple) {
//如果单选
if (this.value === item.id) {
// 键值相等
this.treeList[index].checked = true;
}
} else {
if (("," + this.value + ",").indexOf("," + item.id + ",") >= 0) {
this.treeList[index].checked = true;
}
}
});
}
});
// 循环统计数字
this.treeList.map((item, index) => {
if(item.parentId&&item.parentId.length>0){
item.parentId.forEach(ii => {
this.treeList.filter((p) => {
if (p.id == ii) {
p.count=p.count+item.count;
}
});
});
}
});
var _this = this;
setTimeout(function () {
var inidata = _this.treeList;
_this.treeListData = [...inidata];
}, 800);
},
_initcount(cell){
}
},
watch: {
defaultIds(value) {
this._initTree();
},
range(list) {
// console.log('监视值的改变1');
this._initTree(list);
},
multiple() {
// console.log('监视值的改变2');
if (this.range.length) {
this._reTreeList();
}
},
selectParent() {
// console.log('监视值的改变3');
if (this.range.length) {
this._reTreeList();
}
},
deep: true, // 深度监听
immediate: true, // 初次监听即执行
},
mounted() {
this._initTree();
},
};
</script>
<style scoped>
@import "./style.css";
</style>