初次提交

This commit is contained in:
2025-06-30 10:21:25 +08:00
commit 150b39dfea
396 changed files with 80277 additions and 0 deletions

View File

@ -0,0 +1,67 @@
## 1.4.112021-10-13
当前选项是否选中的回显问题。
## 1.4.102021-09-29
默认树的显示样式
## 1.4.92021-09-13
1. luyj-tree参数中移除props.hasChildren , luyj-tree-item移除参数comparison.hasChilren。
2. luyj-tree 参数nodes默认值改为false, luyj-tree-item 默认值改为false
3. luyj-tree-item 修改选中框的默认大小。
4. 修改luyj-tree-item 插槽 的默认样式
5. 修改luyj-tree 插槽的默认样式
6. 修改一些必要的说明
## 1.4.82021-09-09
1. 修改了一些说明
2. 不包含下一级时,点击页面部分,选中当前的项
3. 修改默认选中事件bug
4. 自定义slot 默认展示时与 单选框、复选框重叠问题
## 1.4.72021-09-08
添加一些必要的说明。
## 1.4.62021-09-03
展示和不显示搜索按钮时位置问题。
## 1.4.52021-09-02
展示和不显示搜索按钮时位置问题。
## 1.4.42021-09-01
区分"选项修改"和"确认"事件,分别对应@change@sendValue
## 1.4.32021-09-01
变量tree_Stack的名称问题
## 1.4.22021-08-27
为树添加导航栏事件
## 1.4.12021-08-26
一些bug
懒加载后重新加载数据,显示问题。
## 1.4.02021-08-25
添加允许多次渲染item的方法默认每次50条。当数据量过大时使用
## 1.3.22021-08-25
搜索时,没有显示名称列,中止报错问题。(改为提醒,跳过后继续执行)
## 1.3.12021-08-24
添加一些简单的说明
## 1.3.2021-08-24
更新了一些bug。
暂时令参数checkStrictly 关联失效。添加了一些参数。文档会后续陆续补充。
独立出luyj-tree-item项。
修复了(可能未完全修复)自定义插件的问题。
移除了一些无效的参数如max、scrollLeft。
## 1.2.12021-08-20
解决。数据不包含数据,点击项报错问题。
## 1.2.02021-08-20
将面包屑导航分开
## 1.1.82021-08-19
更新不能检测传入数据变动tree变动问题
## 1.1.72021-08-14
简单整理了一下代码,没有什么实质性的改变。
## 1.1.62021-08-07
展示状态下显示确认
## 1.1.52021-07-29
更新搜索框在微信开发者工具模拟器不能输入问题
## 1.1.42021-07-27
read.md说明
## 1.1.32021-07-27
read.md更新
## 1.1.22021-07-27
更新说明文档
## 1.1.12021-07-27
更新一些插件说明
## 1.1.02021-07-27
为树的输入框,添加更多样式参数
## 1.0.02021-07-25
无限树形结构组件。支持搜索、面包屑类型导航、选择。

View File

@ -0,0 +1,346 @@
@font-face {
font-family: "iconfont"; /* Project id 2009600 */
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* 清除图标 */
.icon-clear:before{
content: '\e606';
}
.icon-banxuanzhongshousuo1-shi:before {
content: "\e682";
}
.icon-xuanzhong3:before {
content: "\e6bb";
}
.icon-weixuanzhong2:before {
content: "\e62e";
}
.icon-danxuanxuanzhong:before {
content: "\e631";
}
.icon-xuanzhong4:before {
content: "\e63e";
}
.icon-xuanzhong1:before {
content: "\e62d";
}
.icon-xuanzhong2:before {
content: "\e656";
}
.icon-selected:before {
content: "\e615";
}
.icon-weixuanzhong1:before {
content: "\e614";
}
.icon-xingzhuang6kaobei3-copy-copy:before {
content: "\e613";
}
.icon-radio-checked:before {
content: "\e63f";
}
.icon-huifu:before {
content: "\e619";
}
.icon-dizhi:before {
content: "\e64a";
}
.icon-kuaijiecaidan:before {
content: "\e60a";
}
.icon-z043:before {
content: "\e62f";
}
.icon-guanbi:before {
content: "\e607";
}
.icon-xuanze:before {
content: "\e623";
}
.icon-caidanzhaolinggan:before {
content: "\e616";
}
.icon-xitongshezhi:before {
content: "\e60c";
}
.icon-xitongshezhi1:before {
content: "\e633";
}
.icon-lunbo:before {
content: "\e692";
}
.icon-shuping:before {
content: "\e659";
}
.icon-tongzhi:before {
content: "\e641";
}
.icon-pinglunguanlishezhi:before {
content: "\e6ac";
}
.icon-icon:before {
content: "\e600";
}
.icon-liuyanguanli:before {
content: "\e61d";
}
.icon-xuanzhong:before {
content: "\e669";
}
.icon--:before {
content: "\e622";
}
.icon-tushu:before {
content: "\e604";
}
.icon-huishouzhan:before {
content: "\e61c";
}
.icon-yonghutouxiang:before {
content: "\e617";
}
.icon-liebiao:before {
content: "\e630";
}
.icon-fenlei:before {
content: "\e621";
}
.icon-tushu1:before {
content: "\e605";
}
.icon-tubiao-:before {
content: "\e620";
}
.icon-weixuanze:before {
content: "\e624";
}
.icon-tushujieyue:before {
content: "\e690";
}
.icon-lunbo1:before {
content: "\e6c5";
}
.icon-shanchu:before {
content: "\e67b";
}
.icon-lunbo2:before {
content: "\e61e";
}
.icon-huaban:before {
content: "\e663";
}
.icon-kehuan:before {
content: "\e608";
}
.icon-icon02:before {
content: "\e601";
}
.icon-huishouzhan1:before {
content: "\e612";
}
.icon-huishouzhan2:before {
content: "\e63d";
}
.icon-sousuo:before {
content: "\e62c";
}
.icon-xingzhuang:before {
content: "\e625";
}
.icon-lunbobankuai:before {
content: "\e61f";
}
.icon-shangchuan:before {
content: "\e602";
}
.icon-yonghu:before {
content: "\e761";
}
.icon-tongzhi1:before {
content: "\e603";
}
.icon-jingsong:before {
content: "\e65c";
}
.icon-fenlei1:before {
content: "\e6c6";
}
.icon-xieshupingicon:before {
content: "\e72d";
}
.icon-liuyan:before {
content: "\e626";
}
.icon-weixuanzhong:before {
content: "\e627";
}
.icon-youxiang:before {
content: "\e646";
}
.icon-lunboguanggao:before {
content: "\e6b3";
}
.icon-xuanze1:before {
content: "\e60d";
}
.icon-chushaixuanxiang:before {
content: "\e606";
}
.icon-liuyanguanli1:before {
content: "\e61a";
}
.icon-shanchu1:before {
content: "\e609";
}
.icon-huishouzhan3:before {
content: "\e642";
}
.icon-shangchuan1:before {
content: "\e823";
}
.icon-huishouzhan4:before {
content: "\e61b";
}
.icon-chuangzuo:before {
content: "\e8ad";
}
.icon-dianzan:before {
content: "\e8ae";
}
.icon-paihangbang:before {
content: "\e8b3";
}
.icon-shouye:before {
content: "\e8b9";
}
.icon-shoucang:before {
content: "\e8c6";
}
.icon-addApp:before {
content: "\e60b";
}
.icon-huishouzhan5:before {
content: "\e63a";
}
.icon-add1:before {
content: "\e60e";
}
.icon-shoucang1:before {
content: "\e60f";
}
.icon-canshutongji:before {
content: "\e618";
}
.icon-rizhiguanli:before {
content: "\e628";
}
.icon-shanchu2:before {
content: "\e629";
}
.icon-xinzeng:before {
content: "\e62a";
}
.icon-zhankailiebiao:before {
content: "\e62b";
}
.icon-xiala-copy:before {
content: "\e610";
}
.icon-shangla:before {
content: "\e64e";
}
.icon-xianxingshezhi:before {
content: "\e611";
}

View File

@ -0,0 +1,76 @@
.container-list-item {
background-color: #fff;
border-bottom: 1rpx solid #f4f4f4;
border-radius: 20rpx;
margin:0 30rpx 20rpx 30rpx;
.content
{
display: flex;
align-items: center;
// min-height: 60rpx;
width: 100%;
padding:30rpx 15rpx ;
position: relative;
font-size: 32rpx;
// 默认文本显示内容默认的slot
.slot {
// position:absolute;
right: 64rpx;
font-size: 32rpx;
color: #5b5757;
.word {
width:100%;
word-break: break-all;
}
}
// 默认箭头显示样式
.right {
position: absolute;
text-align: center;
width: 80rpx;
right: 30rpx;
color: #babdc3;
font-size: 32rpx;
}
}
}
// 复选框
.checkbox {
position: relative;
height: 36rpx;
margin-left: 10rpx;
margin-right: 0px;
width: 36rpx;
.txt {
font-size: 35rpx;
line-height: 36rpx;
width: 100%;
height: 100%;
display: flex;
}
}
.checkBorder {
border: 1px solid #ecdee4;
}
.text-cut{
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.value_box{
display: flex;
height: 100%;
.index{
color: #009C77;
width: 70rpx;
text-align: center;
border-right: 1rpx solid #eeeeee;
}
.value{
padding-left: 20rpx;
}
}

View File

@ -0,0 +1,312 @@
<template>
<view class="container-list-item" >
<view class="content" @click="clickItem($event, item)">
<!-- 复选框 -->
<view class="checkbox" v-if="isCheckBox" @click.stop="clickBox($event , item)">
<i v-if="curChecked " :style="{'color' :checkActiveColor}"
class="iconfont icon-xuanzhong txt icon-selected" />
<i v-else :style="{'color': checkNoneColor}" class="iconfont icon-weixuanzhong txt" />
</view>
<!-- 复选框 -->
<!-- 单选框 -->
<view class="checkbox" v-else-if="isRadio" @click.stop="clickBox($event, item)">
<i v-if="curChecked" :style="{'color' :checkActiveColor}" class="txt iconfont icon-selected" />
<i v-else :style="{'color': checkNoneColor}" class="txt iconfont icon-weixuanzhong1" />
</view>
<!-- 单选框 -->
<!-- 自定义插槽body -->
<view :style="isCheck ?'left: 56rpx':'left: 16rpx'" class="slot">
<view v-if="item.name" class="value_box" style="height: 50rpx!important;display: flex;align-items: center;">
<view class="index" style="height: 50rpx;">
<image v-if="item.deviceType? item.deviceType.includes('pcs') : ''" :src="pcs" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('bms') : ''" :src="bms" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('stack') : ''" :src="cluster" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('storage_fire') : ''" :src="fire" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('pack') : ''" :src="pack" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('air_condition') : ''" :src="air" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('ele_meter') : ''" :src="unit" class="device-img"></image>
<image v-else-if="item.deviceType? item.deviceType.includes('emu') : ''" :src="emu" class="device-img"></image>
<image v-else :src="other" style="width: 50rpx;height: 50rpx;"></image>
<!-- {{item.deviceType}} -->
</view>
<view class="value">
{{item[sLabel]}}
</view>
</view>
</view>
<!-- 自定义插槽body -->
<view v-if="hasChildren" class="right" @click.stop="clickItemRight($event,item)"><i class="iconfont icon-z043" ></i></view>
</view>
</view>
</template>
<script>
import pcs from '@/static/aidex/device/pcs.png'
import bms from '@/static/aidex/device/bms.png'
import cluster from '@/static/aidex/device/cluster.png'
import air from '@/static/aidex/device/air.png'
import fire from '@/static/aidex/device/fire.png'
import emu from '@/static/aidex/device/emu.png'
import pack from '@/static/aidex/device/pack.png'
import unit from '@/static/aidex/device/unit.png'
import other from '@/static/aidex/device/other.png'
/**
* 无限极树的单项 item
* @description无限级数的单项item
* @property {Object} item 单项的值(默认{}
* @property {Boolean} isCheck 判断是否可选 (默认false)
* @property {Boolean} 判断是否是否多选默认false isCheck为true时有效
* @property {String} checkActiveColor 选中状态下单选框/复选框的颜色 (默认#00AAFF)
* @property {String} checkNoneColor 未选中状态下单选框/复选框的颜色(默认#B8B8B8)
* @property {Object} comparison 属性名称对照表
* @param {String} value 选中值对应列名称(默认value)
* @param {String} label 显示值对应列名称默认label
* @param {String} children 子级列对应名称默认children
* @return {Function} 点击当前项的执行方法
* @param {Object} item 当前项的值
* @return {Function} change 选中值变化时执行方法event.detail = {value: 是否选中}
*/
export default {
name: 'luyj-tree-item',
props: {
// 传入的数值
item: {
type: Object,
default: {}
},
index: {
type: Number,
default: 0
},
// 判断是否可选
isCheck: {
type: Boolean,
default: false
},
// 是否多选
multiple: {
type: Boolean,
default: false
},
// 是否选中状态
checked: {
type: Boolean,
default: false
},
// 是否只能选择叶子结点
nodes: {
type: false,
default: false
},
// 选中状态下单选框/复选框的颜色
checkActiveColor: {
type: String,
default: '#00AAFF'
},
// 未选中状态下单选框的颜色
checkNoneColor: {
type: String,
default: '#B8B8B8'
},
// 列名称对照表
comparison: {
type: Object,
default: () => {
return {
value: 'value', // 选中值
label: 'label', // 显示名称
children: 'children', // 子级名称
};
}
}
},
data() {
return {
sLabel: this.comparison.label ? this.comparison.label : 'label', // label值名称
sChildren: this.comparison.children ? this.comparison.children : 'children', // children值名称
curChecked: this.checked, //是否选中状态
formModel: undefined,
singleMinVolData: undefined,
singleMaxVolData: undefined,
pcs,
bms,
cluster,
air,
fire,emu,other,pack,unit
}
},
computed: {
/**
* 是否包含子级
*/
hasChildren: function() {
return Boolean(this.item) ? (Boolean(this.item[this.sChildren]) ? this.item[this.sChildren].length >
0 : false) : false;
},
/**
* 是否单选
*/
isRadio: function() {
return this.isCheck && !this.multiple && (!this.nodes || !this.hasChildren);
},
/**
* 是否多选
*/
isCheckBox: function() {
return this.isCheck && this.multiple && (!this.nodes || !this.hasChildren);
},
},
watch: {
// 监听列名对照表变化
comparison: {
handler: function(val) {
this.sLabel = this.comparison.label ? this.comparison.label : 'label';
this.sChildren = this.comparison.children ? this.comparison.children : 'children';
},
deep: true
},
// 是否选中状态
checked: function(val) {
this.curChecked = val;
},
item: {
handler(val) {
if (val) {
// this.getStatus()
this.$forceUpdate()
}
},
deep: true,
immediate: true
}
},
created() {
// this.getStatus()
},
methods: {
//获取状态
getStatus() {
if (this.item.deviceType) {
let params = {
colList: [],
srcId: this.item.srcId,
stationId: this.item.stationId
}
if (this.item.deviceType.includes('pcs')) { //舱
params.colList = ['runState']
} else if (this.item.deviceType.includes('emu')) {
//emu 总有功功率 总无功功率
params.colList = ['EMUPTotal', 'EMUQTotal']
} else if (this.item.deviceType.includes('stack')) {
// <!-- 簇 -->累计充电量,累计放电量
params.colList = ['cTotalChargePower', 'cTotalDisChargePower']
} else if (this.item.deviceType.includes('bms')) {
// 堆 累计充电量,累计放电量
params.colList = ['totalCharge', 'totalDischarge']
} else if (this.item.deviceType.includes('ele_meter')) {
// 电表 正向有功总电量 反向有功总电量
params.colList = ['totalCharge', 'totalDisCharge']
} else if (this.item.deviceType.includes('air_condition')) {
//空调 空调开关机:
params.colList = ['airconditionSwitchYX']
} else if (this.item.deviceType.includes('storage_fire')) {
//消防
} else if (this.item.deviceType.includes('pack')) { //组
//组 最高电压 最低电压
params.colList = ['singleMaxVolData', 'singleMinVolData']
}
if (params.colList.length > 0) {
if (this.item.deviceType.includes('pack')) {
this.GetPackTemperatureVoltageData(params)
} else {
this.GetNewValue(params)
}
}
}
},
GetPackTemperatureVoltageData(params) {
this.$u.api.deviceList.GetPackTemperatureVoltageData(params).then(res => {
this.singleMaxVolData = res.data.packData.csingleMaxVolData
this.singleMinVolData = res.data.packData.csingleMinVolData
this.$forceUpdate()
})
},
GetNewValue(params) {
this.$u.api.deviceList.GetNewValue(params).then(res => {
this.formModel = res.data
this.$forceUpdate()
})
},
/** 点击当前项右侧的执行方法
* @param {Object} e
* @param {Object} item
*/
clickItemRight: function(e, item) {
this.$emit("clickItemRight", item, this.hasChildren);
// 不包含下一级修改check值事件
if (!this.hasChildren && this.isCheck) {
this.clickBox(e);
}
},
/** 点击当前项的执行方法
* @param {Object} e
* @param {Object} item
*/
clickItem: function(e, item) {
this.$emit("clickItem", item);
},
/**
* 点击单选框或复选框
* @param {Object} e 当前选中值
* @param {Object} item 当前选中的项
*/
clickBox: function(e, item) {
this.curChecked = !this.curChecked;
e.detail.value = this.curChecked;
this.$emit("change", e); // 切换单选框或复选框
},
}
}
</script>
<style lang="scss" scoped>
@import 'luyj-tree-item.scss';
@import "../../lib/css/icon.css";
.device-box {
display: flex;
flex-direction: row;
align-items: center;
margin-top: 20rpx;
.device-img {
width: 100rpx;
height: 100rpx;
background: #f8f8f8;
flex-shrink: 0;
margin-right: 20rpx;
}
}
.device-img{
width: 50rpx;
height: 50rpx;
}
.runValue {
flex: 1;
color: #12ec0a;
font-size: 28rpx;
}
.stopValue {
flex: 1;
color: #FFB800;
font-size: 28rpx;
}
</style>

View File

@ -0,0 +1,342 @@
@font-face {
font-family: "iconfont"; /* Project id 2009600 */
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-banxuanzhongshousuo1-shi:before {
content: "\e682";
}
.icon-xuanzhong3:before {
content: "\e6bb";
}
.icon-weixuanzhong2:before {
content: "\e62e";
}
.icon-danxuanxuanzhong:before {
content: "\e631";
}
.icon-xuanzhong4:before {
content: "\e63e";
}
.icon-xuanzhong1:before {
content: "\e62d";
}
.icon-xuanzhong2:before {
content: "\e656";
}
.icon-selected:before {
content: "\e615";
}
.icon-weixuanzhong1:before {
content: "\e614";
}
.icon-xingzhuang6kaobei3-copy-copy:before {
content: "\e613";
}
.icon-radio-checked:before {
content: "\e63f";
}
.icon-huifu:before {
content: "\e619";
}
.icon-dizhi:before {
content: "\e64a";
}
.icon-kuaijiecaidan:before {
content: "\e60a";
}
.icon-z043:before {
content: "\e62f";
}
.icon-guanbi:before {
content: "\e607";
}
.icon-xuanze:before {
content: "\e623";
}
.icon-caidanzhaolinggan:before {
content: "\e616";
}
.icon-xitongshezhi:before {
content: "\e60c";
}
.icon-xitongshezhi1:before {
content: "\e633";
}
.icon-lunbo:before {
content: "\e692";
}
.icon-shuping:before {
content: "\e659";
}
.icon-tongzhi:before {
content: "\e641";
}
.icon-pinglunguanlishezhi:before {
content: "\e6ac";
}
.icon-icon:before {
content: "\e600";
}
.icon-liuyanguanli:before {
content: "\e61d";
}
.icon-xuanzhong:before {
content: "\e669";
}
.icon--:before {
content: "\e622";
}
.icon-tushu:before {
content: "\e604";
}
.icon-huishouzhan:before {
content: "\e61c";
}
.icon-yonghutouxiang:before {
content: "\e617";
}
.icon-liebiao:before {
content: "\e630";
}
.icon-fenlei:before {
content: "\e621";
}
.icon-tushu1:before {
content: "\e605";
}
.icon-tubiao-:before {
content: "\e620";
}
.icon-weixuanze:before {
content: "\e624";
}
.icon-tushujieyue:before {
content: "\e690";
}
.icon-lunbo1:before {
content: "\e6c5";
}
.icon-shanchu:before {
content: "\e67b";
}
.icon-lunbo2:before {
content: "\e61e";
}
.icon-huaban:before {
content: "\e663";
}
.icon-kehuan:before {
content: "\e608";
}
.icon-icon02:before {
content: "\e601";
}
.icon-huishouzhan1:before {
content: "\e612";
}
.icon-huishouzhan2:before {
content: "\e63d";
}
.icon-sousuo:before {
content: "\e62c";
}
.icon-xingzhuang:before {
content: "\e625";
}
.icon-lunbobankuai:before {
content: "\e61f";
}
.icon-shangchuan:before {
content: "\e602";
}
.icon-yonghu:before {
content: "\e761";
}
.icon-tongzhi1:before {
content: "\e603";
}
.icon-jingsong:before {
content: "\e65c";
}
.icon-fenlei1:before {
content: "\e6c6";
}
.icon-xieshupingicon:before {
content: "\e72d";
}
.icon-liuyan:before {
content: "\e626";
}
.icon-weixuanzhong:before {
content: "\e627";
}
.icon-youxiang:before {
content: "\e646";
}
.icon-lunboguanggao:before {
content: "\e6b3";
}
.icon-xuanze1:before {
content: "\e60d";
}
.icon-chushaixuanxiang:before {
content: "\e606";
}
.icon-liuyanguanli1:before {
content: "\e61a";
}
.icon-shanchu1:before {
content: "\e609";
}
.icon-huishouzhan3:before {
content: "\e642";
}
.icon-shangchuan1:before {
content: "\e823";
}
.icon-huishouzhan4:before {
content: "\e61b";
}
.icon-chuangzuo:before {
content: "\e8ad";
}
.icon-dianzan:before {
content: "\e8ae";
}
.icon-paihangbang:before {
content: "\e8b3";
}
.icon-shouye:before {
content: "\e8b9";
}
.icon-shoucang:before {
content: "\e8c6";
}
.icon-addApp:before {
content: "\e60b";
}
.icon-huishouzhan5:before {
content: "\e63a";
}
.icon-add1:before {
content: "\e60e";
}
.icon-shoucang1:before {
content: "\e60f";
}
.icon-canshutongji:before {
content: "\e618";
}
.icon-rizhiguanli:before {
content: "\e628";
}
.icon-shanchu2:before {
content: "\e629";
}
.icon-xinzeng:before {
content: "\e62a";
}
.icon-zhankailiebiao:before {
content: "\e62b";
}
.icon-xiala-copy:before {
content: "\e610";
}
.icon-shangla:before {
content: "\e64e";
}
.icon-xianxingshezhi:before {
content: "\e611";
}

View File

@ -0,0 +1,28 @@
// 导航栏标题
.title {
height: 90rpx;
padding: 0 32rpx;
line-height: 90rpx;
font-size: 30rpx;
background-color: #f5f5f5;
color: #606064;
// 导航栏图标样式
.iconclass {
display: inline-block;
margin: 0 12rpx;
color: #D0D4DB;
font-size: 28rpx;
}
}
// 导航栏项样式
.inline-item {
display: inline-block
}
// 导航栏项-启用状态
.active {
color: #666666 !important;
}
// 导航栏项-无状态
.none {
color: #009C77;
}

View File

@ -0,0 +1,182 @@
<template>
<view class="title">
<scroll-view ref="sea" scroll-x style="width: 100%;white-space: nowrap;">
<!-- 全部 -->
<view class="inline-item" @click="clickItem(null,-1)">
<text v-if="!isre && treeStack.length == 0" class="none">{{ this.$t('homePage.device.all') }}</text>
<text v-else class="active">{{ this.$t('homePage.device.all') }}</text>
</view>
<!-- 全部 -->
<!-- 搜索结果 -->
<view v-if="isre" @click="clickItem(null,-2)"
:class="activeSearch?'active inline-item':' none inline-item'">
<i class="iconfont icon-z043 iconclass" />
{{ this.$t('homePage.device.queryResult') }}
</view>
<!-- 搜索结果 -->
<!-- 当前树的层级值 -->
<view v-for="(item,index) in treeStack" class="inline-item" :key="index">
<view class="inline-item" @click="clickItem(item,index)">
<i class="iconfont icon-z043 iconclass" />
<text v-if="index== treeStack.length-1" class="none inline-item" style="color: #009C77;">
{{item[slabel]}}
</text>
<text v-else class="active" >
{{item[slabel]}}
</text>
</view>
</view>
<!-- 当前树的层级值 -->
</scroll-view>
</view>
</template>
<script>
/**
* 无限级树-面包屑导航
* @description 无限级树的面包屑导航
* @property {String} slabel 显示的label值
* @return {Function} clickItemitem , index 点击导航栏的索引
* @item 表示导航项对应的值
* @index 表示导航项的层级别索引
* @value -1 全部
* @value -2 表示层级
* @value 其他 从最外层开始依次0,1,2,3……
* @return {Object} inF 导航条内部的方法
* @param {Function} isIre 设置是否搜索状态
* @param {Function} setTreeStack 设置导航树的值
* @param {Function} pushTreeStack 为导航树添加项
* @param {Function} clearTreeStack 清空导航树
*/
// scrollLeft : 暂时
export default {
name: "luyj-tree-navigation",
props: {
// 显示的label值
slabel: {
type: String,
default: 'label'
},
},
watch:{
treeStack:{
handler(val){
uni.setStorage({
key: 'deviceNavArr',//本地缓存中的指定的 key
data: val
})
}
},
deep:true,
immediate:true
},
data() {
return {
isre: false, // 是否进行了搜索(返回是否进行了搜索)
treeStack: [], // 当前搜索值
}
},
mounted() {
this.clearTreeStack()
},
computed: {
// 是否可点击搜索结果
activeSearch: function() {
return this.treeStack.length > 0;
}
},
created: function() {
// 浅拷贝导航列表的每一个对象为了不改变item值也不复制过多的数据
this.treeStack.forEach(item => {
var tempItem = Object.assign(item);
this.treeStack.push(tempItem);
});
var obj = {
setIsre: this.setIsre,
getIsre : this.getIsre,
setTreeStack: this.setTreeStack,
concatTreeStack : this.concatTreeStack,
pushTreeStack: this.pushTreeStack,
clearTreeStack: this.clearTreeStack,
getTreeStack : this.getTreeStack
};
this.$emit("inF", obj); // 导出的导航栏调用方法
},
methods: {
// ================================== 初始化时导出方法(用于外部调用内部结果) =========================================================
/** 设置isre值(是否搜索)
* @param {Boolean} isre 设置是否搜索
*/
setIsre: function(isre) {
this.isre = isre;
},
/**
* 获取isr值获取是否搜索中
*/
getIsre: function(){
return this.isre;
},
/** 设置导航树
* @param {Array} treeStack 导航树
*/
setTreeStack: function(treeStack) {
this.treeStack = treeStack;
},
/** 拼接导航树
* @param {Object} treeStack 导航树
*/
concatTreeStack : function(treeStack){
this.treeStack = this.treeStack.concat(treeStack);
},
/** 为导航树添加项
* @param {Object} item 待添加的对象
*/
pushTreeStack: function(item) {
this.treeStack.push(item);
},
/**
* 获取当前导航条
*/
getTreeStack : function(){
return this.treeStack;
},
/**
* 清空导航树
*/
clearTreeStack: function() {
this.treeStack.splice(0);
},
// ================================== 监听事件 ===========================================================
/** 点击导航栏索引
* @param {Object} item 当前层的值
* @param {Number} index 索引值
*/
clickItem(item, index) {
if (index == -1) {
// 点击全部
this.isre = false;
this.treeStack.splice(0);
} else if (index == -2) {
// 搜索结果
if (this.activeSearch) {
this.isre = true;
this.treeStack.splice(0);
}
} else {
// 点击某一层级树
this.isre = false;
if (this.treeStack.length - 1 > index) {
this.treeStack.splice(index + 1);
}
}
this.$emit("clickItem", item, index);
},
},
// ============================================================================================================
}
</script>
<style lang="scss" scoped>
@import "luyj-tree-navigation.scss";
@import "icon.css";
</style>

View File

@ -0,0 +1,346 @@
@font-face {
font-family: "iconfont"; /* Project id 2009600 */
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* 清除图标 */
.icon-clear:before{
content: '\e606';
}
.icon-banxuanzhongshousuo1-shi:before {
content: "\e682";
}
.icon-xuanzhong3:before {
content: "\e6bb";
}
.icon-weixuanzhong2:before {
content: "\e62e";
}
.icon-danxuanxuanzhong:before {
content: "\e631";
}
.icon-xuanzhong4:before {
content: "\e63e";
}
.icon-xuanzhong1:before {
content: "\e62d";
}
.icon-xuanzhong2:before {
content: "\e656";
}
.icon-selected:before {
content: "\e615";
}
.icon-weixuanzhong1:before {
content: "\e614";
}
.icon-xingzhuang6kaobei3-copy-copy:before {
content: "\e613";
}
.icon-radio-checked:before {
content: "\e63f";
}
.icon-huifu:before {
content: "\e619";
}
.icon-dizhi:before {
content: "\e64a";
}
.icon-kuaijiecaidan:before {
content: "\e60a";
}
.icon-z043:before {
content: "\e62f";
}
.icon-guanbi:before {
content: "\e607";
}
.icon-xuanze:before {
content: "\e623";
}
.icon-caidanzhaolinggan:before {
content: "\e616";
}
.icon-xitongshezhi:before {
content: "\e60c";
}
.icon-xitongshezhi1:before {
content: "\e633";
}
.icon-lunbo:before {
content: "\e692";
}
.icon-shuping:before {
content: "\e659";
}
.icon-tongzhi:before {
content: "\e641";
}
.icon-pinglunguanlishezhi:before {
content: "\e6ac";
}
.icon-icon:before {
content: "\e600";
}
.icon-liuyanguanli:before {
content: "\e61d";
}
.icon-xuanzhong:before {
content: "\e669";
}
.icon--:before {
content: "\e622";
}
.icon-tushu:before {
content: "\e604";
}
.icon-huishouzhan:before {
content: "\e61c";
}
.icon-yonghutouxiang:before {
content: "\e617";
}
.icon-liebiao:before {
content: "\e630";
}
.icon-fenlei:before {
content: "\e621";
}
.icon-tushu1:before {
content: "\e605";
}
.icon-tubiao-:before {
content: "\e620";
}
.icon-weixuanze:before {
content: "\e624";
}
.icon-tushujieyue:before {
content: "\e690";
}
.icon-lunbo1:before {
content: "\e6c5";
}
.icon-shanchu:before {
content: "\e67b";
}
.icon-lunbo2:before {
content: "\e61e";
}
.icon-huaban:before {
content: "\e663";
}
.icon-kehuan:before {
content: "\e608";
}
.icon-icon02:before {
content: "\e601";
}
.icon-huishouzhan1:before {
content: "\e612";
}
.icon-huishouzhan2:before {
content: "\e63d";
}
.icon-sousuo:before {
content: "\e62c";
}
.icon-xingzhuang:before {
content: "\e625";
}
.icon-lunbobankuai:before {
content: "\e61f";
}
.icon-shangchuan:before {
content: "\e602";
}
.icon-yonghu:before {
content: "\e761";
}
.icon-tongzhi1:before {
content: "\e603";
}
.icon-jingsong:before {
content: "\e65c";
}
.icon-fenlei1:before {
content: "\e6c6";
}
.icon-xieshupingicon:before {
content: "\e72d";
}
.icon-liuyan:before {
content: "\e626";
}
.icon-weixuanzhong:before {
content: "\e627";
}
.icon-youxiang:before {
content: "\e646";
}
.icon-lunboguanggao:before {
content: "\e6b3";
}
.icon-xuanze1:before {
content: "\e60d";
}
.icon-chushaixuanxiang:before {
content: "\e606";
}
.icon-liuyanguanli1:before {
content: "\e61a";
}
.icon-shanchu1:before {
content: "\e609";
}
.icon-huishouzhan3:before {
content: "\e642";
}
.icon-shangchuan1:before {
content: "\e823";
}
.icon-huishouzhan4:before {
content: "\e61b";
}
.icon-chuangzuo:before {
content: "\e8ad";
}
.icon-dianzan:before {
content: "\e8ae";
}
.icon-paihangbang:before {
content: "\e8b3";
}
.icon-shouye:before {
content: "\e8b9";
}
.icon-shoucang:before {
content: "\e8c6";
}
.icon-addApp:before {
content: "\e60b";
}
.icon-huishouzhan5:before {
content: "\e63a";
}
.icon-add1:before {
content: "\e60e";
}
.icon-shoucang1:before {
content: "\e60f";
}
.icon-canshutongji:before {
content: "\e618";
}
.icon-rizhiguanli:before {
content: "\e628";
}
.icon-shanchu2:before {
content: "\e629";
}
.icon-xinzeng:before {
content: "\e62a";
}
.icon-zhankailiebiao:before {
content: "\e62b";
}
.icon-xiala-copy:before {
content: "\e610";
}
.icon-shangla:before {
content: "\e64e";
}
.icon-xianxingshezhi:before {
content: "\e611";
}

View File

@ -0,0 +1,165 @@
<template>
<view>
<view class='filterBox' :style="{'background-color' : backgroundColor}">
<view class='filter-input'
:style="{'background-color' :inputBackgroundColor ,'border-radius':radius + 'rpx'}">
<!-- 左侧搜索图标 -->
<u-icon name="search" color="#009C77!important" size="40"></u-icon>
<!-- 输入框内容 -->
<input class="text" type='text' v-model="inputVal" confirm-type="搜索" :placeholder='placeholder'
:placeholder-style="placeholderStyle" :maxlength="maxlength" @input="handleInput"
@focus="handleFocus" @blur="handleBlur" @confirm='handleFllter'/>
<!-- 清除按钮 -->
<view v-if="clearable" class="padding-left-sm" @click="clears">
<text :style="{'color':iconColor}" class="iconfont icon-clear filterImg"></text>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* 无限级树的搜索框组件
* @description 无限级树的搜索框组件
* @property {String} backgroundColor 背景色(默认#FFFFFF)
* @property {String} inputBackgroundColor 输入框背景色(默认#EEEFF0)
* @property {Number} radius 输入框圆角单位rpx(默认40)
* @property {String} placeholder 输入框为空时占位符(默认'搜索')
* @property {String} placeholderStyle placehoder的样式
* @property {Number} maxlength 最大输入长度 ,设置为 -1 的时候不限制最大长度(默认值140)
* @property {String} iconColor 图标颜色(默认#B8B8B8
* @property {Boolean} clearable 是否显示清除按钮 是否显示清除按钮默认true
* @event {Function()} input 输入框内容编号时触发
* @event {Function()} focus 输入框获得焦点时触发
* @event {Function()} blur 输入框失去焦点时触发
* @event {Function()} confirm 提交输入框内容是触发
* @event {Function()} clear 清空输入框内容时触发
*/
export default {
name: 'luyj-tree-search',
props: {
// 背景色
backgroundColor: {
type: String,
default: '#FFFFFF'
},
// 输入框背景颜色
inputBackgroundColor: {
type: String,
default: '#EEEFF0'
},
// 输入框圆角
radius: {
type: Number,
default: 40
},
// 输入框为空时占位符
placeholder: {
type: String,
default: '输入名称搜索'
},
// placeholder的样式
placeholderStyle: {
type: String,
default: ''
},
// 最大输入长度 ,设置为 -1 的时候不限制最大长度
maxlength: {
type: Number,
default: 140
},
// 图标的颜色
iconColor: {
type: String,
default: '#009C77'
},
// 是否显示清除按钮
clearable: {
type: Boolean,
default: true
}
},
data() {
return {
inputVal: "", // 输入内容
};
},
components: {
test: function() {
return 120;
}
},
methods: {
/** 输入框变化时方法
* @param {Object} e
*/
handleInput: function(e) {
this.$emit("input", e)
},
/** 输入框聚焦时触发
* @param {Object} e
*/
handleFocus: function(e) {
this.$emit("focus", e)
},
/** 输入框失去焦点时触发
* @param {Object} e
*/
handleBlur: function(e) {
this.$emit("blur", e)
},
/** 提交内容时触发
* @param {Object} e
*/
handleFllter: function(e) {
this.$emit("confirm", e)
},
/**
* 清空输入框内容
*/
clears: function() {
this.inputVal = "";
this.$emit("clear", this.inputVal)
}
},
}
</script>
<style lang="scss" scoped>
.filterBox {
padding: 15rpx 32rpx;
.filter-input {
height: 80rpx;
display: flex;
align-items: center;
padding-left: 40rpx;
.filterImg {
width: 32rpx;
height: 32rpx;
margin-right: 20rpx;
margin-bottom: 5rpx;
}
.filterImgs {
width: 32rpx;
height: 32rpx;
}
.text {
width: 100%;
font-size: 32rpx;
color: #000;
}
}
}
// 添加左侧padding(用于扩大图标范围)
.padding-left-sm {
padding-left: 20rpx;
}
@import url("icon.css");
</style>

View File

@ -0,0 +1,342 @@
@font-face {
font-family: "iconfont"; /* Project id 2009600 */
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-banxuanzhongshousuo1-shi:before {
content: "\e682";
}
.icon-xuanzhong3:before {
content: "\e6bb";
}
.icon-weixuanzhong2:before {
content: "\e62e";
}
.icon-danxuanxuanzhong:before {
content: "\e631";
}
.icon-xuanzhong4:before {
content: "\e63e";
}
.icon-xuanzhong1:before {
content: "\e62d";
}
.icon-xuanzhong2:before {
content: "\e656";
}
.icon-selected:before {
content: "\e615";
}
.icon-weixuanzhong1:before {
content: "\e614";
}
.icon-xingzhuang6kaobei3-copy-copy:before {
content: "\e613";
}
.icon-radio-checked:before {
content: "\e63f";
}
.icon-huifu:before {
content: "\e619";
}
.icon-dizhi:before {
content: "\e64a";
}
.icon-kuaijiecaidan:before {
content: "\e60a";
}
.icon-z043:before {
content: "\e62f";
}
.icon-guanbi:before {
content: "\e607";
}
.icon-xuanze:before {
content: "\e623";
}
.icon-caidanzhaolinggan:before {
content: "\e616";
}
.icon-xitongshezhi:before {
content: "\e60c";
}
.icon-xitongshezhi1:before {
content: "\e633";
}
.icon-lunbo:before {
content: "\e692";
}
.icon-shuping:before {
content: "\e659";
}
.icon-tongzhi:before {
content: "\e641";
}
.icon-pinglunguanlishezhi:before {
content: "\e6ac";
}
.icon-icon:before {
content: "\e600";
}
.icon-liuyanguanli:before {
content: "\e61d";
}
.icon-xuanzhong:before {
content: "\e669";
}
.icon--:before {
content: "\e622";
}
.icon-tushu:before {
content: "\e604";
}
.icon-huishouzhan:before {
content: "\e61c";
}
.icon-yonghutouxiang:before {
content: "\e617";
}
.icon-liebiao:before {
content: "\e630";
}
.icon-fenlei:before {
content: "\e621";
}
.icon-tushu1:before {
content: "\e605";
}
.icon-tubiao-:before {
content: "\e620";
}
.icon-weixuanze:before {
content: "\e624";
}
.icon-tushujieyue:before {
content: "\e690";
}
.icon-lunbo1:before {
content: "\e6c5";
}
.icon-shanchu:before {
content: "\e67b";
}
.icon-lunbo2:before {
content: "\e61e";
}
.icon-huaban:before {
content: "\e663";
}
.icon-kehuan:before {
content: "\e608";
}
.icon-icon02:before {
content: "\e601";
}
.icon-huishouzhan1:before {
content: "\e612";
}
.icon-huishouzhan2:before {
content: "\e63d";
}
.icon-sousuo:before {
content: "\e62c";
}
.icon-xingzhuang:before {
content: "\e625";
}
.icon-lunbobankuai:before {
content: "\e61f";
}
.icon-shangchuan:before {
content: "\e602";
}
.icon-yonghu:before {
content: "\e761";
}
.icon-tongzhi1:before {
content: "\e603";
}
.icon-jingsong:before {
content: "\e65c";
}
.icon-fenlei1:before {
content: "\e6c6";
}
.icon-xieshupingicon:before {
content: "\e72d";
}
.icon-liuyan:before {
content: "\e626";
}
.icon-weixuanzhong:before {
content: "\e627";
}
.icon-youxiang:before {
content: "\e646";
}
.icon-lunboguanggao:before {
content: "\e6b3";
}
.icon-xuanze1:before {
content: "\e60d";
}
.icon-chushaixuanxiang:before {
content: "\e606";
}
.icon-liuyanguanli1:before {
content: "\e61a";
}
.icon-shanchu1:before {
content: "\e609";
}
.icon-huishouzhan3:before {
content: "\e642";
}
.icon-shangchuan1:before {
content: "\e823";
}
.icon-huishouzhan4:before {
content: "\e61b";
}
.icon-chuangzuo:before {
content: "\e8ad";
}
.icon-dianzan:before {
content: "\e8ae";
}
.icon-paihangbang:before {
content: "\e8b3";
}
.icon-shouye:before {
content: "\e8b9";
}
.icon-shoucang:before {
content: "\e8c6";
}
.icon-addApp:before {
content: "\e60b";
}
.icon-huishouzhan5:before {
content: "\e63a";
}
.icon-add1:before {
content: "\e60e";
}
.icon-shoucang1:before {
content: "\e60f";
}
.icon-canshutongji:before {
content: "\e618";
}
.icon-rizhiguanli:before {
content: "\e628";
}
.icon-shanchu2:before {
content: "\e629";
}
.icon-xinzeng:before {
content: "\e62a";
}
.icon-zhankailiebiao:before {
content: "\e62b";
}
.icon-xiala-copy:before {
content: "\e610";
}
.icon-shangla:before {
content: "\e64e";
}
.icon-xianxingshezhi:before {
content: "\e611";
}

View File

@ -0,0 +1,121 @@
.flex_between_center {
display: flex;
justify-content: space-between;
align-items: center;
}
.checkbox {
position: relative;
height: 36rpx;
margin-left: 10rpx;
margin-right: 0px;
width: 36rpx;
.color {
color: #00aaff;
background-color: #00aaff;
}
.txt {
// font-size: 30rpx;
line-height: 36rpx;
width: 100%;
height: 100%;
display: flex;
}
}
.checkBorder {
border: 1px solid #ecdee4;
}
.header {
width: 100%;
position: fixed;
background-color: #fff;
z-index: 99;
.title {
height: 90rpx;
padding: 0 32rpx;
line-height: 90rpx;
font-size: 30rpx;
background-color: #f5f5f5;
color: #606064;
.iconclass {
display: inline-block;
margin: 0 12rpx;
color: #D0D4DB;
font-size: 28rpx;
}
}
}
.container-list {
overflow-y: scroll;
overflow-x: hidden;
.common {
background-color: #fff;
border-bottom: 1rpx solid #f4f4f4;
padding-left: 10rpx;
.content {
display: flex;
align-items: center;
min-height: 60rpx;
width: 100%;
padding: 15rpx 0;
position: relative;
font-size: 32rpx;
.right {
position: absolute;
right: 30rpx;
color: #babdc3;
font-size: 32rpx;
}
}
}
// item的数字样式
.word {
font-size: 30rpx;
color: #5b5757;
width: 500rpx;
word-break: break-all;
}
}
.active {
color: #4297ED !important;
}
.none {
color: #666666;
}
.icon-selected{
color: #0095F2!important;
font-size: 40rpx!important;
}
.icons{
color: #0095F2!important;
font-size: 40rpx!important;
}
.inline-item {
display: inline-block
}
.content-item{
display: flex;
position: relative;
align-items: center;
}
.box_sizing {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.btn {
position: fixed;
bottom: 0;
padding: 10px;
background-color: #fff;
width: 100%;
.sureBtn {
background-color: #0095F2;
color: #fff;
}
}

View File

@ -0,0 +1,709 @@
<template>
<view style="width: 100%;height: 100%;">
<!-- 搜索框 -->
<view class="header">
<!-- 搜索栏 -->
<luyj-tree-search v-if="searchIf" :backgroundColor="searchBackgroundColor"
:inputBackgroundColor="searchInputBackgroundColor" :radius="searchRadius" :iconColor="searchIconColor"
:placeholder="searchPlaceholder" :placeholderStyle="searchPlaceholderStyle" :maxlength="searchMaxlength"
:clearable="searchClearable" @confirm="confirmSearch"></luyj-tree-search>
<!-- 面包屑导航 -->
<luyj-tree-navigation :slabel="props.label" @inF="navigationInt" @clickItem="backTree" ref="treeNavigation">
</luyj-tree-navigation>
<!-- 面包屑导航 -->
</view>
<!-- 列表 -->
<view style="height: 100%;">
<view class="container-list" :style="{'padding-bottom' : isCheck ? '160rpx' : 0 , 'padding-top' :searchIf ? '200rpx' :'90rpx', height:'calc(100% - 90rpx)'}">
<block v-for="(item , index) in tree" :key="index">
<luyj-tree-item :item="item" :index='index' :isCheck="isCheck"
:checkActiveColor="checkActiveColor" :checkNoneColor="checkNoneColor" :multiple="props.multiple" :checked="isChecked(item)"
:nodes="props.nodes" :comparison="comparison" @clickItemRight="toChildren" @clickItem="toLookDetail"
@change="checkbox($event , item , index)">
</luyj-tree-item>
</block>
</view>
</view>
<!-- 确定按钮 -->
<view v-if="isCheck" class="btn box_sizing">
<button class="sureBtn" type="primary" @click="backConfirm">确认</button>
</view>
</view>
</template>
<script>
/**
* luyj-tree 无限树形结构树、支持搜索选择。
* @description 无限树形结构组件。支持搜索、选择(包括单选、多选)。面包屑类型导航。原插件地址https://ext.dcloud.net.cn/plugin?id=2423。
* @tutorial url https://ext.dcloud.net.cn/plugin?name=luyj-tree
* @property {Boolean} searchIf 是否开启搜索 默认值true
* @property {String} searchBackgroundColor 搜索框背景色(默认#FFFFFF)
* @property {String} searchInputBackgroundColor 搜索框的输入框背景色(默认#EEEFF0)
* @property {Number} searchRadius 搜索框的圆角值单位rpx默认40
* @property {String} searchPlaceholder 搜索框的内容物空时提示内容
* @property {String} searchPlaceholderStyle 搜索框的placehoder的样式
* @property {Number} searchMaxlength 搜索框的最大输入长度 ,设置为 -1 的时候不限制最大长度
* @property {String} searchIconColor 搜索框的图标颜色(默认#B8B8B8
* @property {Boolean} searchClearable 搜索框是否显示清除按钮
* @property {Array} trees 传入的树形结构每个对象必须包含唯一的id值(默认值【】)
* @property {Boolean} isCheck 是否开启选择操作默认值false
* @property {Object} slotObj 传入插槽的参数(因为插槽进行了循环,不能直接引用页面的参数,需要传递)
* @property {Array} checkList 选中列表
* @property {Boolean} parent 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)(默认值false)
* @property {Array} parentList 父级列表
* @property {String} checkActiveColor 选中时单选框的颜色 (默认#00AAFF)
* @property {String} checkNoneColor 未选中时单选框的颜色(默认#B8B8B8)
* @property {Object} props 参数配置。
* @property {String} id id列的属性名称
* @param {String} label 指定选项标签为选项对象的某个属性值(默认值:name)
* @param {String} children 指定选项的子选项为选项对象的某个属性名(默认值children)
* @param {Boolean} multiple 值为true时为多选为false时是单选(默认值true)
* @param {Boolean} checkStrictly(废弃) 需要在多选模式下才传该值checkStrictly为false时可让父子节点取消关联选择任意一级选项。为true时关联子级可以全选(默认值为false)
* @param {Boolean} nodes 在单选模式下nodes为false时可以选择任意一级选项nodes为true时只能选择叶子节点(默认值为true)
* @property {Boolean} stepReload 是否“分页加载”数据
* @property {Number} pageSize 分步加载生效时(当条数过大时,反应时间很长)
* @return {Function} clickItem 点击导航栏事件
* @value item 当前选中的item值
* @value realHasChildren 是否包含子级
* @event {Function()} change 改变选择值时的方法
* @event {Function()} sendValue 提交选择的方法
* @event {Function()} backTree 选中导航栏时,返回其他层
*/
export default {
name: "luyj-tree",
props: {
// 是否开启搜索
searchIf: {
type: Boolean,
default: () => true
},
// 搜索框背景色
searchBackgroundColor: {
type: String,
default: '#FFFFFF'
},
// 搜索框的输入框内背景颜色
searchInputBackgroundColor: {
type: String,
default: '#EEEFF0'
},
// 搜索框的图标的颜色
searchIconColor: {
type: String,
default: '#B8B8B8'
},
// 搜索框的圆角值单位rpx
searchRadius: {
type: Number,
default: 40
},
// 搜索框的提示placeholder内容
searchPlaceholder: {
type: String,
default: '搜索'
},
// 搜索框的placeholder的样式
searchPlaceholderStyle: {
type: String,
default: ''
},
// 搜索框最大输入长度 ,设置为 -1 的时候不限制最大长度
searchMaxlength: {
type: Number,
default: 140
},
// 搜索框是否显示清除按钮
searchClearable: {
type: Boolean,
default: true
},
// 传入的树形结构数据每个对象必须包含唯一的id值
trees: {
type: Array,
default: () => {
return []
}
},
//是否开启选择操作值为false时仅展示无操作
isCheck: {
type: Boolean,
default: () => {
return false
}
},
// 传入插槽的其他参数
slotObj: {
type: Object,
default :() =>{
return null;
}
},
// 选中列表
checkList: {
type: Array,
default: () => []
},
// 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)
parent: {
type: Boolean,
default: () => {
return false
}
},
// 父级列表
parentList: {
type: Array,
default: () => []
},
// 选中时单选框的颜色
checkActiveColor: {
type: String,
default: '#00AAFF'
},
// 未选中时单选框的颜色
checkNoneColor: {
type: String,
default: '#B8B8B8'
},
// 树的属性参数
props: {
type: Object,
default: () => {
return {
id: 'id',
label: 'name',
children: 'children',
multiple: false,
checkStrictly: false, //不关联
nodes: false, // nodes为false时可以选择任意一级选项nodes为true时只能选择叶子节点
}
}
},
/**
* 是否懒加载树的值
*/
stepReload : {
type:Boolean,
default:false
},
// 每次循环加载的item的数据量
pageSize : {
type : Number,
default:50
}
},
data() {
return {
// 导航条
setIsre: null, // 导航条方法 - 设置是否搜索中方法
getIsre : null, // 获取是否搜索中
setTreeStack: null, // 导航条 - 设置导航
concatTreeStack: null, // 导航条 - 拼接当前导航对象
clearTreeStack: null, // 导航条- 清空导航条
getTreeStack: null, // 导航条 - 获取导航条
itemsLoading : false, // item是否在循环渲染中
itemsStop : false, // 是否终止其他渲染
tree: [], // 默认数组
newNum: 0,
oldNum: 0,
allData: this.trees,
storeData:undefined,
parent_data: this.parentList || [], //选择父辈
searchResult: [],
newCheckList: this.checkList,
nodePathArray: [], // 当前展示的路径
// item名称对照表
comparison: {
value: this.props.id ? this.props.id : 'id', // 选中值名称
label: this.props.label ? this.props.label : 'name', // 显示名称
children: this.props.children ? this.props.children : 'children', // 子集名称
}
}
},
watch: {
// 监听数据值的变化
trees: function(val, oldval) {
if (val != oldval) {
var tree_stack = val;
this.allData = val; // 重新加载所有树
this.storeData = JSON.parse(JSON.stringify(val))
// 重新加载当前树
this.$refs.treeNavigation.treeStack = val
var length = tree_stack.length;
if( length === 0){
if(typeof(this.getIsre) === "function"){
if(this.getIsre()){
return;
}
}
this.loadTree(val);
}else{
let tempArray = val; // 存储当前值
let children = this.props.children;
for(var i = 0 ; i < length ; i ++){
var tempObject = tempArray.find(item=>{
return tree_stack[i].Value == item.Value;
});
if(Boolean(tempObject)){
tempArray = tempObject[children];
}else{
// 跳转到全部
break;
}
if(i == length -1){
this.loadTree(tempArray);
}
}
}
}
},
// 树的属性对照参数
props: {
handler: function(val) {
this.comparison.value = this.props.id ? this.props.id : 'id';
this.comparison.label = this.props.label ? this.props.label : 'name';
this.comparison.children = this.props.children ? this.props.children : [];
},
deep: true
},
checkList: function(val , oldVal){
if(val != oldVal){
this.newCheckList = JSON.parse(JSON.stringify(val))
return val;
}
}
},
created:function(){
this.loadTree(this.trees);
this.storeData = JSON.parse(JSON.stringify(this.trees))
},
// 实例被挂载后调用
mounted() {
let id = this.props.id;
let children = this.props.children;
// 关联子级的验证,暂时不使用
// if (this.props.multiple && this.props.checkStrictly) {
// if (this.newCheckList.length != 0) {
// this.checkAllChoose();
// return;
// }
// for (let i = 0; i < this.tree.length; i++) {
// this.$set(this.tree[i], 'bx', 0)
// this.$set(this.tree[i], 'qx', 0)
// }
// }
// 初始化选中项
if (!this.props.multiple && this.newCheckList.length > 0) {
this.getNodeRoute(this.allData, this.newCheckList[0][id]);
let arr = this.nodePathArray.reverse();
if (arr.length == 0) {
return;
}
this.concatTreeStack(arr); // 获取导航条的值
// 加载当前列对应的数据
var tree_stack = this.trees;
var data = Boolean(tree_stack[tree_stack.length -1][children]) ? tree_stack[tree_stack.length - 1][
children
] : [];
this.loadTree(data);
}
},
methods: {
// ========================================== 添加方法 =====================================================================
/** 当前选项是否选中
* @param {Object} item
*/
isChecked(item){
if(Array.isArray(this.newCheckList)){
let id = this.props.id;
let temp = this.newCheckList.find(chcked=>{
return chcked[id] == item.id;
});
return Boolean(temp);
}
return false;
},
// =========================================== 初始化方法 ===================================================================
/** 初始化导航条的方法
* @param {Object} e
*/
navigationInt: function(e) {
this.setIsre = e.setIsre;
this.getIsre = e.getIsre;
this.concatTreeStack = e.concatTreeStack;
this.pushTreeStack = e.pushTreeStack;
this.clearTreeStack = e.clearTreeStack;
this.getTreeStack = e.getTreeStack;
},
// =========================================== 监听事件 =====================================================================
/** 选中当前的值
* @param {Object} e
* @param {Object} item 当前项
* @param {Object} index 低昂去索引
*/
checkbox(e, item, index) {
var func = this.props.multiple ? this.checkboxChange : this.radioChange;
func(e,item ,index); // 执行选择操作
},
/**单选
* @param {Object} e 点击事件
* @param {Object} item 当前项的值
* @param {Object} index 索引
*/
radioChange :function( e,item ,index){
var that = this;
if(e.detail.value){
// 选中当前对象
that.newCheckList = [];
that.newCheckList.push(that.tree[index]);
}else{
// 移除其他对象
var nIndex = that.newCheckList.indexOf(item);
that.newCheckList.splice(nIndex , 1);
}
that.$emit('change', that.newCheckList);
},
/**异步检查复选框值的改变
* @param {Object} item
* @param {Object} index
* @param {Object} bx
* @param {Object} qx
*/
async checkboxChange (e,item, index, bx, qx) {
let that = this;
let findIdex = that.newCheckList.indexOf(item);
if(e.detail.value){
// 点击选中
if(findIdex == -1){
that.newCheckList.push(that.tree[index]);
}
}else{
// 点击不选
that.newCheckList.splice(findIdex , 1);
}
that.$emit('change', that.newCheckList);
// if (findIdex > -1) { //反选
// if (that.props.checkStrictly) { //关联子级
// if (item[props.hasChilren]) { //用户
// that.newCheckList.splice(findIdex, 1)
// } else { //非用户,取消所有下一级
// if (Boolean(item[props.children])) {
// that.getIdBydelete(item[props.children]);
// }
// }
// } else {
// that.newCheckList.splice(findIdex, 1)
// }
// } else { //选中
// if (!item[this.props.hasChilren] && that.props.checkStrictly) { //选中下一级
// if (qx || bx) { //取消下级
// if (Boolean(item[props.children])) {
// await that.getIdBydelete(item[props.children]);
// }
// item.qx = 0;
// item.bx = 0;
// } else {
// item.qx = 1;
// item.bx = 0;
// if (Boolean(item[props.children])) {
// await that.chooseChild(item[props.children], item[this.props.id]);
// }
// }
// that.$emit('change', that.newCheckList);
// // that.$forceUpdate()
// return;
// }
// // if(item[this.props.hasChilren]&&this.props.checkStrictly) this.getNodeRoute(this.allData,item[this.props.id]);
// that.newCheckList.push({
// ...item
// });
// }
// that.$emit('change', that.newCheckList)
},
// 取消下一级的选中
getIdBydelete(arr) {
arr.forEach(e => {
if (true) {
for (var i = 0; i < this.newCheckList.length; i++) {
// 包含下一级
if (e[this.props.id] == this.newCheckList[i][this.props.id]) {
this.newCheckList.splice(i, 1)
break;
}
}
}
})
},
// 关联下一级,选中
chooseChild(arr, pid) {
let that = this;
for (var i = 0, len = arr.length; i < len; i++) {
let item = arr[i];
if (true) {
// 包含下一级
that.newCheckList.push({
...item,
tree_stackId: pid
})
}
}
},
/**
* @param {Array} tree 目标树
* @param {Object} targetId 为目标节点id
*/
getNodeRoute(tree, targetId) {
let children = this.props.children;
let id = this.props.id;
for (let index = 0; index < tree.length; index++) {
if (Boolean(tree[index][children]) ) {
if (tree[index][children]) {
let endRecursiveLoop = this.getNodeRoute(tree[index][children], targetId)
if (endRecursiveLoop) {
this.nodePathArray.push(tree[index]);
return true;
}
}
}
if (tree[index][id] === targetId) {
return true;
}
}
},
/**跳转到子级
* @param {Object} item 选中的项
* @param {Boolean} realHasChildren 是否包含子级
*/
toChildren(item, realHasChildren) {
this.$emit("clickItem" , item , realHasChildren); // 点击导航栏事件
// 不包含子级,不执行任何操作
if (!realHasChildren) {
return;
}
// 点击跳转下一级
let id = this.props.id;
let children = this.props.children; // 子级名称
// 将当前item加入到导航列表
if (item[children].length > 0) {
this.loadTree(item[children]);
this.pushTreeStack(item); // 添加导航
}
// 关联数据 - 暂时不使用
// if (this.props.checkStrictly) {
// this.checkAllChoose();
// }
},
/**查看详情 */
toLookDetail(item, realHasChildren){
this.$emit('lookDetail',item)
},
/** 搜索提交方法
* @param {Object} e
*/
confirmSearch(e) {
var val = e.detail.value;
this.searchResult = [];
if(val){
// 查找
uni.showLoading({
title: '正在查找'
});
this.search(this.allData, val);
}else{
return
}
// 返回搜索结果
uni.hideLoading();
this.setIsre(true); // 设置导航条为搜索状态
this.clearTreeStack(); // 清空导航条
this.loadTree(this.searchResult);
},
/**搜索方法
* @param {Object} data 搜索数据
* @param {Object} keyword 搜索关键字
*/
search(data, keyword) {
var that = this;
let children = that.props.children;
for (var i = 0, len = data.length; i < len; i++) {
// try-catch(try-catch) - 没有label列跳过继续执行
try{
if ((data[i][that.props.label].toLowerCase()).indexOf(keyword.toLowerCase()) >= 0) {
that.searchResult.push(data[i]);
}
if (Boolean(data[i][children])) {
if (data[i][children].length > 0) {
that.search(data[i][children], keyword);
}
}
}catch(e){
console.warn(e);
}
}
},
/**
* 检查所有的选项
*/
checkAllChoose() {
let o = false,
t = true;
this.tree.forEach((e, i) => {
if (true) {
// 包含下一级 !e[this.props.hasChilren]
e.qx = o;
e.bx = o;
let num2 = this.computAllNumber(e[props.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) {
console.log("选中所选值");
// for (let j = 0; j < arr.length; j++) {
// var e = arr[j];
// // if (arr[j][that.props.hasChilren]) {
// this.newNum++;
// // }
// this.checkSum(e.id)
// if (!e[that.props.hasChilren]) {
// this.computAllNumber(e[props.children])
// }
// }
},
// 选中事件累计
checkSum(id) {
for (let i = 0; i < this.newCheckList.length; i++) {
if (id == this.newCheckList[i].id) {
this.oldNum++;
break
}
}
},
/** 返回到其他树层
* @param {Object} item 当前item值
* @param {Object} index 返回到其他索引
*/
backTree(item, index) {
this.$emit("backTree", item, index);
let that = this;
if (index == -1) {
// 全部
that.loadTree(that.storeData);
} else if (index == -2) {
// 搜索
that.loadTree(that.searchResult); // 搜索结果
} else {
// 其他层级
that.loadTree(item[that.props.children]); // tree的其他层级
}
// 关联数据
// if (this.props.checkStrictly) {
// this.checkAllChoose();
// }
},
/**
* 点击确认按钮执行事件
*/
backConfirm() {
this.$emit('sendValue', this.newCheckList, 'back')
},
// ======================================== 公共方法 ===============================================================
/**加载Tree值
* @param {Array} datas 待复制的数组
* @param {Number} start 起始位置
* @description 加载tree值。当数据量大时子项加载时间很长。可以多次渲染加载
*/
loadTree : function(datas , start = 0 ){
let that = this;
if(!this.stepReload){
// 不进行多次渲染加载
that.tree = datas;
}else{
// datas为null, 不进行渲染
if(!Array.isArray(datas)){
that.tree = datas;
return;
}else if(datas.length === 0){
that.tree = datas;
return;
}
// 进行多次渲染加载
if(start === 0){
// 终止其他渲染
if(that.itemsLoading){
that.itemsStop = true; //终止其他Item渲染
}
// 首次加载提醒
uni.showLoading();
that.tree = [];
that.itemsLoading = true;
}
var length = datas.length ;
var end = Math.min(start + that.pageSize , length);
var tempArray = datas.slice(start , end);
that.tree = that.tree.concat(tempArray);
that.$nextTick(function(){
if(start == 0){
uni.hideLoading();
that.itemsStop = false;
}
if(end < length && !that.itemsStop){
that.loadTree(datas, end);
}else{
that.itemsLoading = false;
}
});
}
},
// =================================================================================================================
}
}
</script>
<style lang="scss" scoped>
@import "luyj-tree.scss";
@import "icon.css";
.device-box{
display: flex;
flex-direction: row;
align-items: center;
.device-img{
width: 80rpx;
height: 80rpx;
background: #f8f8f8;
flex-shrink: 0;
margin-right: 10rpx;
}
}
</style>

View File

@ -0,0 +1,346 @@
@font-face {
font-family: "iconfont"; /* Project id 2009600 */
src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* 清除图标 */
.icon-clear:before{
content: '\e606';
}
.icon-banxuanzhongshousuo1-shi:before {
content: "\e682";
}
.icon-xuanzhong3:before {
content: "\e6bb";
}
.icon-weixuanzhong2:before {
content: "\e62e";
}
.icon-danxuanxuanzhong:before {
content: "\e631";
}
.icon-xuanzhong4:before {
content: "\e63e";
}
.icon-xuanzhong1:before {
content: "\e62d";
}
.icon-xuanzhong2:before {
content: "\e656";
}
.icon-selected:before {
content: "\e615";
}
.icon-weixuanzhong1:before {
content: "\e614";
}
.icon-xingzhuang6kaobei3-copy-copy:before {
content: "\e613";
}
.icon-radio-checked:before {
content: "\e63f";
}
.icon-huifu:before {
content: "\e619";
}
.icon-dizhi:before {
content: "\e64a";
}
.icon-kuaijiecaidan:before {
content: "\e60a";
}
.icon-z043:before {
content: "\e62f";
}
.icon-guanbi:before {
content: "\e607";
}
.icon-xuanze:before {
content: "\e623";
}
.icon-caidanzhaolinggan:before {
content: "\e616";
}
.icon-xitongshezhi:before {
content: "\e60c";
}
.icon-xitongshezhi1:before {
content: "\e633";
}
.icon-lunbo:before {
content: "\e692";
}
.icon-shuping:before {
content: "\e659";
}
.icon-tongzhi:before {
content: "\e641";
}
.icon-pinglunguanlishezhi:before {
content: "\e6ac";
}
.icon-icon:before {
content: "\e600";
}
.icon-liuyanguanli:before {
content: "\e61d";
}
.icon-xuanzhong:before {
content: "\e669";
}
.icon--:before {
content: "\e622";
}
.icon-tushu:before {
content: "\e604";
}
.icon-huishouzhan:before {
content: "\e61c";
}
.icon-yonghutouxiang:before {
content: "\e617";
}
.icon-liebiao:before {
content: "\e630";
}
.icon-fenlei:before {
content: "\e621";
}
.icon-tushu1:before {
content: "\e605";
}
.icon-tubiao-:before {
content: "\e620";
}
.icon-weixuanze:before {
content: "\e624";
}
.icon-tushujieyue:before {
content: "\e690";
}
.icon-lunbo1:before {
content: "\e6c5";
}
.icon-shanchu:before {
content: "\e67b";
}
.icon-lunbo2:before {
content: "\e61e";
}
.icon-huaban:before {
content: "\e663";
}
.icon-kehuan:before {
content: "\e608";
}
.icon-icon02:before {
content: "\e601";
}
.icon-huishouzhan1:before {
content: "\e612";
}
.icon-huishouzhan2:before {
content: "\e63d";
}
.icon-sousuo:before {
content: "\e62c";
}
.icon-xingzhuang:before {
content: "\e625";
}
.icon-lunbobankuai:before {
content: "\e61f";
}
.icon-shangchuan:before {
content: "\e602";
}
.icon-yonghu:before {
content: "\e761";
}
.icon-tongzhi1:before {
content: "\e603";
}
.icon-jingsong:before {
content: "\e65c";
}
.icon-fenlei1:before {
content: "\e6c6";
}
.icon-xieshupingicon:before {
content: "\e72d";
}
.icon-liuyan:before {
content: "\e626";
}
.icon-weixuanzhong:before {
content: "\e627";
}
.icon-youxiang:before {
content: "\e646";
}
.icon-lunboguanggao:before {
content: "\e6b3";
}
.icon-xuanze1:before {
content: "\e60d";
}
.icon-chushaixuanxiang:before {
content: "\e606";
}
.icon-liuyanguanli1:before {
content: "\e61a";
}
.icon-shanchu1:before {
content: "\e609";
}
.icon-huishouzhan3:before {
content: "\e642";
}
.icon-shangchuan1:before {
content: "\e823";
}
.icon-huishouzhan4:before {
content: "\e61b";
}
.icon-chuangzuo:before {
content: "\e8ad";
}
.icon-dianzan:before {
content: "\e8ae";
}
.icon-paihangbang:before {
content: "\e8b3";
}
.icon-shouye:before {
content: "\e8b9";
}
.icon-shoucang:before {
content: "\e8c6";
}
.icon-addApp:before {
content: "\e60b";
}
.icon-huishouzhan5:before {
content: "\e63a";
}
.icon-add1:before {
content: "\e60e";
}
.icon-shoucang1:before {
content: "\e60f";
}
.icon-canshutongji:before {
content: "\e618";
}
.icon-rizhiguanli:before {
content: "\e628";
}
.icon-shanchu2:before {
content: "\e629";
}
.icon-xinzeng:before {
content: "\e62a";
}
.icon-zhankailiebiao:before {
content: "\e62b";
}
.icon-xiala-copy:before {
content: "\e610";
}
.icon-shangla:before {
content: "\e64e";
}
.icon-xianxingshezhi:before {
content: "\e611";
}

View File

@ -0,0 +1,86 @@
{
"id": "luyj-tree",
"displayName": "luyj-tree 无限级树形结构。",
"version": "1.4.11",
"description": "无限极树形结构。支持搜索、面包屑导航、单项选择、多项选择。",
"keywords": [
"uni-ui",
"uniui",
"",
"tree",
""
],
"repository": "https://github.com/luyanjie00436/luyj-tree-app",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"前端组件",
"通用组件"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "y",
"IE": "u",
"Edge": "u",
"Firefox": "y",
"Safari": "u"
},
"小程序": {
"微信": {
"minVersion": "2.18.1"
},
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
}
}

View File

@ -0,0 +1,251 @@
# luyj-tree
> 代码块 `luyj-tree` 内包含`luyj-tree-search`、`luyj-tree-navigation`、`luyj-tree-item`
## 说明
* 本插件是基于[xiaolu-tree](https://ext.dcloud.net.cn/plugin?id=2423)进行了uni_modules模块化。并进行了一些修改。
* 本人暂时只在微信小程序端和H5 使用Chrome浏览器测试。更改了一些内容有可能会有一些错误 或说明与实际不一致,介意者慎用。本人会适当的抽出业余时间,把它完善,毕竟有一定的下载量了,而且自己也需要学习,再次感谢原作者。
* 暂时,使用自定义插件渲染有问题,会出现``duplication is found under a single shadow root. The first one was accepted`` ,还未找到解决方案。
### 安装方式
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`
### 基本用法
在 ``template`` 中使用组件
```html
<!-- 基础用法 -->
<luyj-tree v-slot:default="{item}" :max="max" :trees="tree">
<!-- 内容插槽 -->
<view>
<view class="content-item">
<view class="word">{{item.name}}</view>
</view>
</view>
</luyj-tree>
```
``` javascript
import dataList from '@/common/data.js'; // 引用数据
export default {
data() {
return {
tree: dataList,
max: 5,
}
},
}
```
### 功能说明
1. 树形结构展示。
2. 包含搜索框。能够自定义搜索框的样式,能够直接搜索树形图、子文件的内容。
3. 包含面包屑导航。
4. 可以仅仅展示或选择树形的项内容。
5. 可以显示选择改变,或确认选择的方法。
6. 只需传checkList字段就可以回显默认选中。
7. 支持自定义显示内容的插件slot)。
8. 支持懒加载。
### 属性
|属性名 |类型 |默认值 | 说明 |
|:-: |:-: |:-: | :-: |
|search-if |Boolean |true | 是否开启搜索 |
|search-background-color |String |#FFFFFF | 搜索框背景色 |
|search-input-background-color |String |#EEEFF0 | 搜索框的输入框背景色 |
|search-radius |Number |40 | 搜索框的圆角值单位rpx默认40 |
|search-placeholder |String |搜索 | 搜索框的内容物空时提示内容 |
|search-placeholder-style |String | | 搜索框的placehoder的样式 |
|search-maxlength |Number |140 | 搜索框的最大输入长度 ,设置为 -1 的时候不限制最大长度 |
|search-iconColor |String | | 搜索框的图标颜色 |
|search-clearable |Boolean |true | 搜索框是否显示清除按钮 |
|trees |Array |[] | trees 传入的树形结构每个对象必须包含唯一的id值 |
|is-check |Boolean |false | 是否开启选择操作 |
|slot-obj |Object |null | 传入插槽的参数自定义的slot中不能引用页面的参数否则样式会出错|
|check-list |Array |[] | 选中的列表 |
|parent |Boolean |false | 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)。此参数占时失效。 |
|parent-list |Array |[] | 父级列表 |
|check-active-color |String |#00AAFF | 选中时单选框/复选框的颜色 |
|check-none-color |String |#B8B8B8 | 未选中时单选框/复选框的颜色 |
|props |Object |{id: 'id',label:'name',children:'children'hasChilren: 'user',multiple: false,checkStrictly: false nodes: false} | 参数配置,详细见下表。 |
|step-reload |Boolean |false | 是否懒加载数列 |
|page-size |Number |50 | 每次加载的条数stepReload = true时生效 |
#### props 参数说明
|参数 |类型 |默认值 | 说明 |
|:-: |:-: |:-: | :-: |
|id |String |id | id列的属性名 |
|label |String |name | 指定选项标签为选项对象的某个属性值 |
|children |String |children | 指定选项的子选项为选项对象的某个属性值 |
|multiple |Boolean |true | 值为true时为多选为false时是单选 |
|checkStrictly |Boolean |false | 需要在多选模式下才传该值checkStrictly为false时可让父子节点取消关联选择任意一级选项。为true时关联子级可以全选暂时不可用 |
|nodes |Boolean |true | 在单选模式下nodes为false时可以选择任意一级选项nodes为true时只能选择叶子节点 |
### 事件
|事件名 |说明 |返回值 |
|:-: |:-: |:-: |
|@clickItem |点击Item列事件 |(item : Object ,realHasChildren : Boolean) |
|@change |选项改变时触发事件 当前选中的值 |
|@sendValue |点击确认按钮时触发事件 | 参数(选中的项值) |
``@clickItem``,当点击item列时有效。返回值说明如下
|返回值 |类型 | 说明 |
|:-: |:-: |:-: |
|item |Object | 当前选中的值 |
|realHasChildren |Boolean| 是否包含子级 |
``@change`` ,``is-check``为```true```时,当选中的值改变时触发。返回值说明如下:
|参数 |类型 | 说明 |
|:-: |:-: | :-: |
|e.detail.value |Boolean | 当前项是否选中 |
|item |Object | 当前的Item值 |
# luyj-tree-search
### 说明
``luyj-tree-search`` 是 ``luyj-tree``内的组件,作为搜索框,可以单独引用。
![Image text](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-c07243ab-98a3-4f90-9b4d-2fa60aba2ee9/ba6ace1d-4881-4373-8a8e-b90079d3e290.png)
### 基本用法
###
在 ``template`` 中使用组件
``` html
<luyj-tree-search></luyj-tree-search>
```
### 属性
|属性名 |类型 |默认值 | 说明 |
|:-: |:-: |:-: | :-: |
|background-color |String |#FFFFFF | 背景色 |
|input-background-color |String |#EEEFF0 | 输入框背景色 |
|radius |Number |40 | 输入框圆角单位rpx |
|icon-color |String |#B8B8B8 | 图标颜色 |
|placeholder |String |搜索 | 输入框为空时占位符 |
|placeholder-style |String | | placeholder的样式 |
|maxlength |Number |140 | 最大输入长度 ,设置为 -1 的时候不限制最大长度 |
### 事件
|事件名 |说明 |返回值 |
|:-: |:-: |:-: |
|@input |输入框内容变化时,触发事件 | event |
|@focus |输入框获得焦点时,触发事件 | event |
|@blur |输入框失去焦点时,触发事件 | event |
|@confirm |输入框内容提交时,触发事件 | event |
|@clear |清空输入框内容时,触发事件 | '' |
# luyj-tree-navigation
``luyj-tree-navigation`` 是 ``luyj-tree``内的组件,作为面包屑导航栏,可以单独引用。
# luyj-tree-item
``luyj-tree-item`` 是 ``luyj-tree``内的组件,是树的选择项。包含单选、多选的样式,可以单独引用。
### 基础用法
在``template``中使用组件
``` html
<!-- 普通使用 -->
<luyj-tree-item :item="item" :isCheck="ischecked" :multiple="multiple" :checked="ischecked" :comparison="comparison" @change="change" @clickItem="clickItem">
</luyj-tree-item>
<!-- 使用插件 -->
<luyj-tree-item :item="item" :isCheck="isCheck" :multiple="multiple" :checked="ischecked" :comparison="comparison" @change="change" @clickItem="clickItem">
<!-- 自定义插件内容 -->
<template slot="body" >
{{ item.label }}
</template>
<!-- 自定义插件内容 -->
</luyj-tree-item>
```
对应的数据及方法如下:
``` javascript
import dataItem from '../../common/item-data.js';
export default {
data() {
return {
item : dataItem, // 当前item值
isCheck : true, // 是否可选
ischecked : true, // 是否选中
multiple : false, // 是否多选
comparison :{
value : 'value', // 选中值
label : 'label', // 显示名称
children:'children', // 子级名称
},
test :124
}
},
onLoad:function(){
},
methods: {
// 修改change
change : function(e , item){
console.log("修改当前值=>" ,e , item);
},
// 点击当前项目
clickItem : function(item , hasChildren){
console.log("点击当前项目");
}
}
}
```
### 属性
|属性名 |类型 |默认值 | 说明 |
|:-: |:-: |:-: | :-: |
|item |Object |{} | 当前项的值 |
|is-check |Boolean |false |判断是否可选择与multiple组合使用。判断显示类型为展示、单选、多选|
|multiple |Boolean |false |是否多选。当isCheck值为true时有效。multiple=false时为单选multiple=true时多选|
|checked |Boolean |false |当前项是否选中状态|
|nodes |Boolean |false |是否只能选择叶子结点|
|check-active-color |String |#00AAFF |选中状态下,单选框/复选框的颜色|
|check-none-color |String |#B8B8B8 |未选中状态下,单选框/复选框的颜色|
|comparison |Object |{value : 'value',label : 'label',children:'children'}; |当前项的列名称。 |
#### **comparison**的值
|参数 |类型 |默认值 | 说明 |
|:-: |:-: |:-: | :-: |
|value |String |value | value值的列名即选中时单选按钮或复选按钮的值 |
|label |String |label | label值的列名即当前item默认展示的名称 |
|children |String |children | children对的列名即当前item的下一级 |
### 事件
|事件名 |说明 |返回值 |
|:-: |:-: |:-: |
|@change |单选框/复选框值改变时执行方法 |(e , item) |
|@clickItem |点击当前选项 |{item , hasChildren} |
#### **change** 的参数说明
|参数 |类型 | 说明 |
|:-: |:-: | :-: |
|e.detail.value |Boolean | 当前项是否选中 |
|item |Object | 当前的Item值 |
#### **clickItem** 的参数说明
|参数 |类型 | 说明 |
|:-: |:-: | :-: |
|item |Object | 当前的Item值 |
|hasChildren |Boolean | 是否包含子级即children是否包含对象 |
### 源码地址
[代码csdn地址](https://codechina.csdn.net/qq_28624235/luyj-tree-app) <br>
[代码github地址](https://github.com/luyanjie00436/luyj-tree-app)