Commit c1a439db49c59ef6b192d71b6d4e794018aa816a

Authored by xp.Huang
2 parents 96e9c22c 5aab4f02

Merge branch 'dev-ft' into 'main'

feat:新增登录接口等

See merge request huang/thingskit-app!12

Too many changes to show.

To preserve performance only 31 of 49 files are displayed.

1   -node_modules/
2 1 .project
3 2 unpackage/
4   -.DS_Store
\ No newline at end of file
  3 +.DS_Store
  4 +dist/
... ...
  1 +<template>
  2 + <view >
  3 + <view class="tab" :style="{'top':gauge+'rpx'}">
  4 + <scroll-view class="tab_scroll" :scroll-x="true" :scroll-into-view="intoindex">
  5 + <view :class="tab_index==index?'tab_scroll_list':'tab_scroll_lists'" :id='"tab"+index'
  6 + :style="{'color':tab_index==index?tab_color:''}" v-for="(item,index) in lists" :key="index"
  7 + @tap="cut(index,item.id)">
  8 + {{item.name}}
  9 + </view>
  10 + <!-- 占位符 -->
  11 + <view class="tab_scroll_list"></view>
  12 + </scroll-view>
  13 + <!-- 多个tab时显示下拉框 -->
  14 + <view class="pull" v-if="lists.length>6" @tap="open">
  15 + <image src="../../static/img/pull.png"></image>
  16 + </view>
  17 + </view>
  18 + <!-- 遮挡弹出 -->
  19 + <view class="popup" v-show="or">
  20 + </view>
  21 + <view :class="or?'popup_list':'popup_lists'" :style="{'top':gauge+100+'rpx'}">
  22 + <view class="label" v-show="or_text">
  23 + <scroll-view class="label_scroll" :scroll-y="true">
  24 + <view class="label_list" v-for="(item,index) in lists" :key="index"
  25 + :style="{'background':tab_index==index?tab_color:''}" @tap="cut(index,item.id)">
  26 + {{item.name}}
  27 + </view>
  28 + </scroll-view>
  29 +
  30 + </view>
  31 + </view>
  32 + </view>
  33 +</template>
  34 +
  35 +<script>
  36 + export default {
  37 + name: "Tab",
  38 + data() {
  39 + return {
  40 + //tab选中的下标
  41 + tab_index: 0,
  42 + //是否开启下拉
  43 + or: false,
  44 + or_text: false,
  45 + intoindex: ''
  46 + };
  47 + },
  48 + props: {
  49 + lists: {
  50 + type: Array,
  51 + default: []
  52 + },
  53 + tab_color: {
  54 + type: String,
  55 + default: ''
  56 + },
  57 + gauge:{
  58 + type:Number,
  59 + default:0
  60 + }
  61 + },
  62 + methods: {
  63 + cut: function(ind,id) {
  64 + var that = this;
  65 + that.tab_index = ind;
  66 + that.or = false;
  67 + that.or_text = false;
  68 + that.$nextTick(() => {
  69 + that.intoindex = "tab" + ind
  70 + });
  71 + that.intoindex = ''
  72 + that.$emit('switchover',id)
  73 + },
  74 + // 打开下拉
  75 + open: function() {
  76 + var that = this;
  77 + that.or = !that.or;
  78 + if (that.or) {
  79 + setTimeout(() => {
  80 + // 这里添加您的逻辑
  81 + that.or_text = true;
  82 + }, 300)
  83 + } else {
  84 + that.or_text = false;
  85 + }
  86 + }
  87 + }
  88 + }
  89 +</script>
  90 +
  91 +<style lang="scss">
  92 + .tab {
  93 + width: 100%;
  94 + padding: 0rpx 30rpx;
  95 + box-sizing: border-box;
  96 + border-bottom: 2rpx solid #e7e7e7;
  97 + position: fixed;
  98 + background: #fff;
  99 + z-index: 99;
  100 + .tab_scroll {
  101 + width: 100%;
  102 + height: 100rpx;
  103 + white-space: nowrap;
  104 + line-height: 100rpx;
  105 +
  106 + .tab_scroll_list {
  107 + display: inline-block;
  108 + font-size: 28rpx;
  109 + margin-right: 40rpx;
  110 + position: relative;
  111 + }
  112 +
  113 + .tab_scroll_lists {
  114 + display: inline-block;
  115 + font-size: 28rpx;
  116 + margin-right: 40rpx;
  117 + position: relative;
  118 + }
  119 +
  120 + .tab_scroll_list:after {
  121 + position: absolute;
  122 + bottom: 0;
  123 + text-align: center;
  124 + left: 46%;
  125 +
  126 + content: "";
  127 + width: 20rpx;
  128 + height: 4rpx;
  129 + border-top: 4rpx solid #3b87f6;
  130 + }
  131 + }
  132 +
  133 + .pull {
  134 + width: 80rpx;
  135 + height: 98rpx;
  136 + position: absolute;
  137 + right: 0rpx;
  138 + top: 0rpx;
  139 + z-index: 999;
  140 + background: #fff;
  141 + box-shadow: #000 -5rpx 0px 5px -5px;
  142 + display: flex;
  143 + justify-content: center;
  144 + align-items: center;
  145 +
  146 + image {
  147 + width: 30rpx;
  148 + height: 30rpx;
  149 + }
  150 + }
  151 +
  152 + }
  153 +
  154 + .popup {
  155 + width: 100%;
  156 + height: 100vh;
  157 + background: rgba(0, 0, 0, .5);
  158 + position: absolute;
  159 + top: 0rpx;
  160 + z-index: 10;
  161 + }
  162 +
  163 + .popup_list {
  164 + width: 100%;
  165 + height: 280rpx;
  166 + background: #fff;
  167 + transition: height .5s;
  168 + padding: 0rpx 30rpx;
  169 + box-sizing: border-box;
  170 + position: fixed;
  171 + z-index: 99;
  172 + .label {
  173 + width: 100%;
  174 +
  175 + .label_scroll {
  176 + width: 100%;
  177 + height: 280rpx;
  178 + padding: 20rpx 0rpx;
  179 + box-sizing: border-box;
  180 +
  181 + .label_list {
  182 + font-size: 28rpx;
  183 + color: #fff;
  184 + padding: 10rpx 10rpx;
  185 + border-radius: 50rpx;
  186 + background: #C0C0C0;
  187 + display: inline-block;
  188 + margin-top: 20rpx;
  189 + margin-right: 20rpx;
  190 + }
  191 + }
  192 +
  193 + }
  194 +
  195 +
  196 + }
  197 +
  198 + .popup_lists {
  199 + width: 100%;
  200 + height: 0rpx;
  201 + background: #fff;
  202 + transition: height .5s;
  203 + padding: 0rpx 30rpx;
  204 + box-sizing: border-box;
  205 + position: fixed;
  206 + z-index: 99;
  207 + }
  208 +</style>
... ...
1   -import { getTabbarHeight } from '@/plugins/utils';
  1 +import {
  2 + getTabbarHeight
  3 +} from '@/plugins/utils';
2 4 let baseUrl = "";
3 5 if (process.env.NODE_ENV === 'development') {
4 6 // 开发环境
5   - baseUrl = 'https://api.yichengshi.cn'
6   - // baseUrl = 'http://192.168.1.228/fan_php/public/index.php'
  7 + baseUrl = 'http://47.99.141.212:8080/api'
  8 + // baseUrl = 'http://192.168.1.228/fan_php/public/index.php'
7 9 } else if (process.env.NODE_ENV === 'production') {
8 10 // 生产环境
9 11 baseUrl = 'https://api.yichengshi.cn'
10 12 }
11 13
12 14 let systemInfo = {
13   - ...getTabbarHeight(),
14   - // #ifdef MP-ALIPAY
15   - navBarH: uni.getSystemInfoSync().statusBarHeight + uni.getSystemInfoSync().titleBarHeight, //菜单栏总高度--单位px
16   - titleBarHeight: uni.getSystemInfoSync().titleBarHeight, //标题栏高度--单位px
17   - // #endif
18   - // #ifndef MP-ALIPAY
19   - navBarH: uni.getSystemInfoSync().statusBarHeight + 44, //菜单栏总高度--单位px
20   - titleBarHeight: 44, //标题栏高度--单位px
21   - // #endif
  15 + ...getTabbarHeight(),
  16 + // #ifdef MP-ALIPAY
  17 + navBarH: uni.getSystemInfoSync().statusBarHeight + uni.getSystemInfoSync().titleBarHeight, //菜单栏总高度--单位px
  18 + titleBarHeight: uni.getSystemInfoSync().titleBarHeight, //标题栏高度--单位px
  19 + // #endif
  20 + // #ifndef MP-ALIPAY
  21 + navBarH: uni.getSystemInfoSync().statusBarHeight + 44, //菜单栏总高度--单位px
  22 + titleBarHeight: 44, //标题栏高度--单位px
  23 + // #endif
22 24 };
23 25 // 平台
24 26 // #ifdef MP-WEIXIN
... ... @@ -33,20 +35,20 @@ systemInfo.platform = 'toutiao'
33 35 // #ifdef APP-PLUS
34 36 systemInfo.platform = 'plus'
35 37 // #endif
36   -console.log(systemInfo,'systemInfo')
  38 +console.log(systemInfo, 'systemInfo')
37 39 const courtConfig = {
38   - publicAppId:'',//公众号appId
39   - baseUrl: baseUrl,//域名
40   - systemInfo:systemInfo,//系统信息
41   - mapData:{
42   - key:'',//地图key
43   - sk:'',
44   - },
45   - share: {
46   - title: '基于uview2.0快速开发框架', //分享标题
47   - desc: "基于uview2.0快速开发框架详情", //分享详情
48   - link: "", // 分享链接
49   - imgUrl: "", // 分享图
50   - }
  40 + publicAppId: '', //公众号appId
  41 + baseUrl: baseUrl, //域名
  42 + systemInfo: systemInfo, //系统信息
  43 + mapData: {
  44 + key: '', //地图key
  45 + sk: '',
  46 + },
  47 + share: {
  48 + title: '基于uview2.0快速开发框架', //分享标题
  49 + desc: "基于uview2.0快速开发框架详情", //分享详情
  50 + link: "", // 分享链接
  51 + imgUrl: "", // 分享图
  52 + }
51 53 };
52 54 export default Object.assign({}, courtConfig);
... ...
1 1 import base from "@/config/baseUrl";
2 2 import store from '@/store';
3   -import { judgeLogin } from '@/config/login';
  3 +import {
  4 + judgeLogin
  5 +} from '@/config/login';
4 6
5 7 // 初始化请求配置
6 8 uni.$u.http.setConfig((config) => {
7   - // var token = store.state.userInfo.token || (uni.getStorageSync('userInfo').token || undefined)
8   - /* config 为默认全局配置*/
9   - config.baseURL = base.baseUrl; /* 根域名 */
10   - config.header = {
11   - 'Content-Type': 'application/x-www-form-urlencoded',
12   - // 'Authorization': 'Bearer ' + token
13   -
14   - }
15   - config.custom = {
16   - load:true,//是否显示加载动画
17   - isFactory: true,//true:返回的数据成功只返回data false:返回response
18   - catch: true,//默认数据返回不成功进入catch返回
19   - // auth: true,//token
20   - }
21   - return config
  9 + let token = store.state.userInfo.isToken || (uni.getStorageSync('userInfo').isToken || undefined)
  10 + //#ifdef MP
  11 + let token = store.state.userInfo.isToken || (wx.getStorageSync('userInfo').isToken || undefined)
  12 + //#endif
  13 + // #ifdef H5
  14 + window.sessionStorage.getItem('userInfo');
  15 + // #endif
  16 + console.log('获取token', token);
  17 + /* config 为默认全局配置*/
  18 + config.baseURL = base.baseUrl; /* 根域名 */
  19 + config.header = {
  20 + 'Content-Type': 'application/json',
  21 + 'Authorization': 'Bearer ' + token
  22 + }
  23 + config.custom = {
  24 + load: true, //是否显示加载动画
  25 + isFactory: true, //true:返回的数据成功只返回data false:返回response
  26 + catch: true, //默认数据返回不成功进入catch返回
  27 + auth: true, //token
  28 + }
  29 + return config
22 30 })
23 31
24 32 // 请求拦截
25 33 uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
26   - // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
27   - config.data = config.data || {}
28   - // 根据custom参数中配置的是否需要token,添加对应的请求头
29   - if(config?.custom?.auth) {
30   - config.header.token = store.state.userInfo.token
31   - }
32   - console.log("请求开始", config);
33   - if (config?.custom?.load) {
34   - //打开加载动画
35   - store.commit("setLoadingShow", true);
36   - }
37   -
38   - return config
  34 + // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
  35 + config.data = config.data || {}
  36 + // 根据custom参数中配置的是否需要token,添加对应的请求头
  37 + if (config?.custom?.auth) {
  38 + config.header.token = store.state.userInfo.token
  39 + }
  40 + // console.log("请求开始", config);
  41 + if (config?.custom?.load) {
  42 + //打开加载动画
  43 + store.commit("setLoadingShow", true);
  44 + }
  45 +
  46 + return config
39 47 }, config => { // 可使用async await 做异步操作
40   - return Promise.reject(config)
  48 + return Promise.reject(config)
41 49 })
42 50
43 51 // 响应拦截
44   -uni.$u.http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/
45   - // 关闭加载动画
46   - store.commit("setLoadingShow", false);
47   - const data = response.data
48   - // 自定义参数
49   - const custom = response.config?.custom
50   - // code: 1、请求成功 -1、请求成功,没有更多参数 2、被迫下线重新登录、
51   - if(data.code == 1 || data.code == -1){
52   - if(data.code == -1){
53   - data.data = []
54   - }
55   - if(!custom.isFactory){
56   - return data
57   - }else{
58   - return data.data === undefined ? {} : data.data
59   - }
60   - }else if(data.code == 2){//被迫下线重新登录
61   - // 清空登录信息
62   - store.commit("emptyUserInfo");
63   - // 20秒节流,弹窗登录
64   - uni.$u.throttle(judgeLogin(), 20000)
65   - return new Promise(() => { })
66   - }else{
67   - // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
68   - if (custom.toast !== false) {
69   - uni.$u.toast(data.message || data.msg)
70   - }
71   - // 如果需要catch返回,则进行reject
72   - if (custom?.catch) {
73   - return Promise.reject(data)
74   - } else {
75   - // 否则返回一个pending中的promise,请求不会进入catch中
76   - return new Promise(() => { })
77   - }
78   - }
  52 +uni.$u.http.interceptors.response.use((response) => {
  53 + /* 对响应成功做点什么 可使用async await 做异步操作*/
  54 + // 关闭加载动画
  55 + store.commit("setLoadingShow", false);
  56 + const data = response.data
  57 + // 自定义参数
  58 + const custom = response.config?.custom
  59 + // code: 200、请求成功 其他,没有更多参数 401、被迫下线重新登录、
  60 + if (response.statusCode == 200) {
  61 + return Promise.resolve(data)
  62 + // if (!custom.isFactory) {
  63 + // return Promise.reject(response.data)
  64 + // } else {
  65 + // return data.data === undefined ? {} : Promise.reject(response.data)
  66 + // }
  67 + } else if (response.statusCode == 401) { //被迫下线重新登录
  68 + // 清空登录信息
  69 + store.commit("emptyUserInfo");
  70 + // 20秒节流,弹窗登录
  71 + uni.$u.throttle(judgeLogin(), 20000)
  72 + return new Promise(() => {})
  73 + } else {
  74 + // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
  75 + if (custom.toast !== false) {
  76 + uni.$u.toast(data.message || data.msg)
  77 + }
  78 + // 如果需要catch返回,则进行reject
  79 + if (custom?.catch) {
  80 + return Promise.reject(data)
  81 + } else {
  82 + // 否则返回一个pending中的promise,请求不会进入catch中
  83 + return new Promise(() => {})
  84 + }
  85 + }
79 86 }, (response) => {
80   - // 关闭加载动画
81   - store.commit("setLoadingShow", false);
82   - // 对响应错误做点什么 (statusCode !== 200)
83   - let errorData = '请检查网络或服务器'
84   - let message = response.message || response.msg
85   - if(message == "request:fail url not in domain list") {
86   - errorData = '检查请求域名是否添加了域名白名单'
87   - }else if (message == 'request:fail timeout') {
88   - errorData = '请求超时:请检查网络'
89   - }else{
90   - errorData = message || '请检查网络或服务器'
91   - }
92   - uni.$u.toast(errorData)
93   - return Promise.reject(response)
94   -})
\ No newline at end of file
  87 + console.log('Error', response);
  88 + // 关闭加载动画
  89 + store.commit("setLoadingShow", false);
  90 + // 对响应错误做点什么 (statusCode !== 200)
  91 + let errorData = '请检查网络或服务器'
  92 + let message = response.errMsg || response.errMsg
  93 + if (message == "request:fail url not in domain list") {
  94 + errorData = '检查请求域名是否添加了域名白名单'
  95 + } else if (message == 'request:fail timeout') {
  96 + errorData = '请求超时:请检查网络'
  97 + } else {
  98 + errorData = message || '请检查网络或服务器'
  99 + }
  100 + uni.$u.toast(errorData)
  101 + return Promise.reject(response)
  102 +})
... ...
... ... @@ -57,7 +57,7 @@
57 57 },
58 58 "quickapp" : {},
59 59 "mp-weixin" : {
60   - "appid" : "wx594747d3848d7a10",
  60 + "appid" : "wx0ad61d7bf6808e02",
61 61 "setting" : {
62 62 "urlCheck" : false,
63 63 "minified" : true,
... ...
... ... @@ -25,34 +25,34 @@
25 25 <image @click="openOrg" style="width: 6px;height: 10px;float: right; margin-right: 34rpx; margin-top: 58rpx;" src="../../static/right-arrow.png" mode=""></image>
26 26 </view>
27 27 </view>
28   - <view class="device-list">
29   - <view @click="openAlertDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
30   - <view class="item">
31   - <view style="margin-top: -3rpx;">
32   - <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
33   - </view>
34   - <view class="u-flex" style="flex-direction: column;margin-top: -1rpx;">
35   - <view style="text-align: left;width: 279rpx;">
36   - <text style="color:#666666;font-size: 14px;">{{ item.name2 }}</text>
  28 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
  29 + <view class="device-list">
  30 + <view @click="openAlertDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
  31 + <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
  32 + <view style="width: 400rpx;text-align: left;">
  33 + <text style="color:#333333;font-size: 15px;">{{ item.deviceName }}</text>
  34 + </view>
  35 + <view style="width: 400rpx;text-align: left;">
  36 + <text style="color:#666666;font-size: 15px;">{{ item.name2 }}</text>
37 37 </view>
38   - <view style="text-align: left;">
39   - <text style="color:#666666;font-size: 14px;">{{ item.name3 }}</text>
  38 + <view style="width: 400rpx;text-align: left;">
  39 + <text style="color:#666666;font-size: 15px;">{{ item.status }}</text>
40 40 </view>
41   - <view style="text-align: left;">
42   - <text style="color:#999999;font-size: 14px;">{{ item.time }}</text>
  41 + <view style="width: 400rpx;text-align: left;">
  42 + <text style="color:#999999;font-size: 15px;">{{ item.createdTime }}</text>
43 43 </view>
44 44 </view>
45   - </view>
46   - <view class="item">
47   - <view class="u-flex" style="flex-direction: row;margin-top: -6rpx;">
48   - <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
49   - <view class="">
50   - <text style="color: #333333;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
  45 + <view class="item">
  46 + <view class="u-flex" style="flex-direction: row;margin-top: -6rpx;">
  47 + <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
  48 + <view class="">
  49 + <text style="color: #333333;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.severity }}</text>
  50 + </view>
51 51 </view>
52 52 </view>
53 53 </view>
54 54 </view>
55   - </view>
  55 + </mescroll-body>
56 56 <view style="height:20rpx"></view>
57 57 <!-- 告警筛选 -->
58 58 <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
... ... @@ -173,20 +173,30 @@
173 173 <script>
174 174 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
175 175 import fNavbar from '@/components/module/f-navbar/f-navbar';
  176 +import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
176 177
177 178 export default {
  179 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
178 180 components: {
179 181 fTabbar,
180 182 fNavbar
181 183 },
182 184 data() {
183 185 return {
  186 + page: {
  187 + num: 1,
  188 + size: 10
  189 + },
  190 + downOption: {
  191 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  192 + },
184 193 timeData: {
185 194 selectTime: '',
186 195 getTimeGap: ''
187 196 },
188 197 showCalendar: false,
189 198 show: false,
  199 + list: [],
190 200 alertStatus: [
191 201 {
192 202 index: 1,
... ... @@ -332,53 +342,6 @@ export default {
332 342 bgColor: '#F6F6F6',
333 343 textColor: '#F6F6F6'
334 344 }
335   - ],
336   - list: [
337   - {
338   - name1: '1号楼1楼三单元水表',
339   - name2: 'CO₂:65.32',
340   - name3: '告警状态:清除已确认',
341   - name4: '../../static/danger.png',
342   - name5: '危险',
343   - time: '2022-04-01 02:12:23',
344   - id: 'xx1'
345   - },
346   - {
347   - name1: '2号楼1楼三单元水表',
348   - name2: 'PH:9.8',
349   - name3: '告警状态:激活未确认',
350   - name4: '../../static/major.png',
351   - name5: '重要',
352   - time: '2022-04-01 02:12:23',
353   - id: 'xx2'
354   - },
355   - {
356   - name1: '3号楼1楼三单元水表',
357   - name2: 'NH3:600',
358   - name3: '告警状态:激活未确认',
359   - name4: '../../static/secondary.png',
360   - name5: '次要',
361   - time: '2022-04-01 02:12:23',
362   - id: 'xx3'
363   - },
364   - {
365   - name1: '4号楼1楼三单元水表',
366   - name2: '水深:1.4',
367   - name3: '告警状态:激活未确认',
368   - name4: '../../static/secondary.png',
369   - name5: '次要',
370   - time: '2022-04-01 02:12:23',
371   - id: 'xx4'
372   - },
373   - {
374   - name1: '5号楼1楼三单元水表',
375   - name2: 'COD:125',
376   - name3: '告警状态:激活未确认',
377   - name4: '../../static/noshue.png',
378   - name5: '不确定',
379   - time: '2022-04-01 02:12:23',
380   - id: 'xx5'
381   - }
382 345 ]
383 346 };
384 347 },
... ... @@ -387,6 +350,44 @@ export default {
387 350 uni.hideTabBar();
388 351 },
389 352 methods: {
  353 + /*下拉刷新的回调 */
  354 + downCallback() {
  355 + //联网加载数据
  356 + this.loadData(1);
  357 + },
  358 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  359 + upCallback() {
  360 + //联网加载数据
  361 + // this.page.num+=10
  362 + this.loadData(this.page.num);
  363 + },
  364 + // 特价商品
  365 + loadData(pageNo) {
  366 + let httpData = {
  367 + page: pageNo,
  368 + pageSize: 10,
  369 + entityType: 'DEVICE',
  370 + entityId: ''
  371 + };
  372 + uni.$u.http
  373 + .get('/yt/alarm', { params: httpData, custom: { load: false } })
  374 + .then(res => {
  375 + uni.stopPullDownRefresh();
  376 + this.mescroll.endByPage(res.items.length, res.total);
  377 + if (pageNo == 1) {
  378 + this.list = res.items;
  379 + console.log(this.list);
  380 + } else {
  381 + this.list = this.list.concat(res.items);
  382 + console.log(this.list);
  383 + }
  384 + })
  385 + .catch(e => {
  386 + console.log(e);
  387 + //联网失败, 结束加载
  388 + this.mescroll.endErr();
  389 + });
  390 + },
390 391 openOrg() {
391 392 uni.navigateTo({
392 393 url: './org/org'
... ... @@ -426,6 +427,7 @@ export default {
426 427 display: flex;
427 428 flex-direction: column;
428 429 padding-left: 18rpx;
  430 + justify-content: flex-start;
429 431 .list-item {
430 432 width: 713rpx;
431 433 height: 233rpx;
... ...
... ... @@ -25,31 +25,31 @@
25 25 <image @click="openOrg" style="width: 6px;height: 10px;float: right; margin-right: 34rpx; margin-top: 58rpx;" src="../../static/right-arrow.png" mode=""></image>
26 26 </view>
27 27 </view>
28   - <view class="device-list">
29   - <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
30   - <view class="item">
31   - <view>
32   - <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
33   - </view>
34   - <view class="u-flex" style="flex-direction: column;justify-content: flex-start;margin-top: 8rpx;">
35   - <view>
36   - <text style="color:#666666;font-size: 14px;">{{ item.name2 }}</text>
  28 + <mescroll-body ref="mescrollRef" @init="mescrollInit" :down="downOption" @down="downCallback" @up="upCallback">
  29 + <view class="device-list">
  30 + <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
  31 + <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
  32 + <view style="width: 450rpx;text-align: left;">
  33 + <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
  34 + </view>
  35 + <view style="width: 450rpx;text-align: left;">
  36 + <text style="color:#666666;font-size: 15px;">{{ item.name2 }}</text>
37 37 </view>
38   - <view style="margin-left: -122rpx;">
39   - <text style="color:#666666;font-size: 14px;">{{ item.name3 }}</text>
  38 + <view style="width: 450rpx;text-align: left;">
  39 + <text style="color:#666666;font-size: 15px;">{{ item.name3 }}</text>
40 40 </view>
41 41 </view>
42   - </view>
43   - <view class="item">
44   - <view class="u-flex" style="flex-direction: row;margin-top: -6rpx;">
45   - <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
46   - <view class="">
47   - <text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
  42 + <view class="item">
  43 + <view class="u-flex" style="flex-direction: row;margin-top: -6rpx;">
  44 + <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
  45 + <view class="">
  46 + <text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
  47 + </view>
48 48 </view>
49 49 </view>
50 50 </view>
51 51 </view>
52   - </view>
  52 + </mescroll-body>
53 53 <view style="height: 30rpx;"></view>
54 54 <!-- 设备筛选 -->
55 55 <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
... ... @@ -125,14 +125,19 @@
125 125 <script>
126 126 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
127 127 import fNavbar from '@/components/module/f-navbar/f-navbar';
  128 +import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
128 129
129 130 export default {
  131 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
130 132 components: {
131 133 fTabbar,
132 134 fNavbar
133 135 },
134 136 data() {
135 137 return {
  138 + downOption: {
  139 + auto: false //是否在初始化后,自动执行downCallback; 默认true
  140 + },
136 141 show: false,
137 142 deviceStatus: [
138 143 {
... ... @@ -263,6 +268,37 @@ export default {
263 268 uni.hideTabBar();
264 269 },
265 270 methods: {
  271 + /*下拉刷新的回调 */
  272 + downCallback() {
  273 + //联网加载数据
  274 + this.loadData(1)
  275 + },
  276 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  277 + upCallback(page) {
  278 + //联网加载数据
  279 + this.loadData(page.num)
  280 + },
  281 + //获取设备
  282 + loadData(pageNo) {
  283 + let httpData = {
  284 + page: pageNo,
  285 + pageSize: 10,
  286 + }
  287 + uni.$u.http.get('/yt/device', {params: httpData, custom: {load:false}}).then(res => {
  288 + uni.stopPullDownRefresh();
  289 + console.log('获取后端数据',res);
  290 + //方法一(推荐): 后台接口有返回列表的总页数 totalPage
  291 + // this.mescroll.endByPage(res.length, res.pages); //必传参数(当前页的数据个数, 总页数)
  292 + // if (pageNo == 1) {
  293 + // this.list = res
  294 + // } else {
  295 + // this.list = this.list.concat(res);
  296 + // }
  297 + }).catch(() => {
  298 + //联网失败, 结束加载
  299 + this.mescroll.endErr();
  300 + });
  301 + },
266 302 openOrg() {
267 303 uni.navigateTo({
268 304 url: './org/org'
... ...
... ... @@ -5,20 +5,18 @@
5 5 <view style="width: 192rpx;margin: 19rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
6 6 <view class="device-list">
7 7 <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
8   - <view class="item">
9   - <view style="margin-top: =13rpx;">
  8 + <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
  9 + <view style="width: 400rpx;text-align: left;">
10 10 <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
11 11 </view>
12   - <view class="u-flex" style="flex-direction: column;justify-content: flex-start;margin-top: -1rpx;">
13   - <view style="text-align: left;width: 279rpx;">
14   - <text style="color:#666666;font-size: 14px;">{{ item.name2 }}</text>
15   - </view>
16   - <view style="text-align: left;">
17   - <text style="color:#666666;font-size: 14px;">{{ item.name3 }}</text>
18   - </view>
19   - <view style="text-align: left">
20   - <text style="color:#666666;font-size: 14px;">{{ item.time }}</text>
21   - </view>
  12 + <view style="width: 400rpx;text-align: left;">
  13 + <text style="color:#666666;font-size: 15px;">{{ item.name2 }}</text>
  14 + </view>
  15 + <view style="width: 400rpx;text-align: left;">
  16 + <text style="color:#666666;font-size: 15px;">{{ item.name3 }}</text>
  17 + </view>
  18 + <view style="width: 400rpx;text-align: left;">
  19 + <text style="color:#999999;font-size: 15px;">{{ item.time }}</text>
22 20 </view>
23 21 </view>
24 22 <view class="item">
... ...
... ... @@ -5,17 +5,15 @@
5 5 <public-module></public-module>
6 6 <view class="device-list">
7 7 <view @click="openAlertDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
8   - <view class="item">
9   - <view style="margin-top: 18rpx;">
  8 + <view class="u-flex item" style="margin-top: 48rpx;justify-content: flex-start;flex-direction: column;align-items: center;">
  9 + <view style="width: 400rpx;text-align: left;">
10 10 <text style="color:#333333;font-size: 15px;">{{ item.name1 }}</text>
11 11 </view>
12   - <view class="u-flex" style="flex-direction: column;margin-top: -1rpx;">
13   - <view style="text-align: left;width: 283rpx;">
14   - <text style="color:#666666;font-size: 14px;">{{ item.name2 }}</text>
15   - </view>
16   - <view style="text-align: left;">
17   - <text style="color:#999999;font-size: 14px;">{{ item.time }}</text>
18   - </view>
  12 + <view style="width: 400rpx;text-align: left;">
  13 + <text style="color:#666666;font-size: 15px;">{{ item.name2 }}</text>
  14 + </view>
  15 + <view style="width: 400rpx;text-align: left;">
  16 + <text style="color:#999999;font-size: 15px;">{{ item.time }}</text>
19 17 </view>
20 18 </view>
21 19 <view class="item">
... ...
... ... @@ -2,10 +2,10 @@
2 2 <view class="history-page">
3 3 <!-- 公共组件-每个页面必须引入 -->
4 4 <public-module></public-module>
5   - <view class="form-style" style="width: 700rpx;height: 800rpx;background-color: #fff;">
  5 + <view class="form-style" style="border-radius: 20px;width: 700rpx;height: 900rpx;background-color: #fff;">
6 6 <u-form :label-style="{ 'font-size': '0rpx' }" style="padding-left: 26rpx;">
7 7 <u-form-item
8   - label="."
  8 + label=""
9 9 prop="selectTime"
10 10 @click="
11 11 showCalendar = true;
... ... @@ -13,28 +13,57 @@
13 13 "
14 14 >
15 15 <view class="u-flex" style="flex-direction: row;">
  16 + <!-- #ifdef MP -->
16 17 <view style="margin-left: -63rpx;"><image style="width: 30rpx;height: 30rpx;" src="../../../static/can-der.png" mode=""></image></view>
17 18 <view style="margin-left: 23rpx;">
18 19 <u--input v-model="timeData.selectTime" disabled disabledColor="#ffffff" placeholder="请选择日期" border="none"></u--input>
19 20 </view>
  21 + <!-- #endif -->
  22 +
  23 + <!-- #ifdef APP -->
  24 + <view style="margin-left: 60rpx;"><image style="width: 30rpx;height: 30rpx;" src="../../../static/can-der.png" mode=""></image></view>
  25 + <view style="margin-left: 46rpx;">
  26 + <u--input v-model="timeData.selectTime" disabled disabledColor="#ffffff" placeholder="请选择日期" border="none"></u--input>
  27 + </view>
  28 + <!-- #endif -->
20 29 </view>
21 30 </u-form-item>
22   - <u-form-item label="." prop="getTimeGap" @click="openTimeGap">
  31 + <u-form-item label="" prop="getTimeGap" @click="openTimeGap">
23 32 <view class="u-flex" style="flex-direction: row;">
  33 + <!-- #ifdef MP -->
24 34 <view style="margin-left: -63rpx;"><image style="width: 30rpx;height: 30rpx;" src="../../../static/time.png" mode=""></image></view>
25 35 <view style="margin-left: 23rpx;">
26 36 <u--input v-model="timeData.getTimeGap" disabled disabledColor="#ffffff" placeholder="请选择时间区间" border="none"></u--input>
27 37 </view>
  38 + <!-- #endif -->
  39 +
  40 + <!-- #ifdef APP -->
  41 + <view style="margin-left: 60rpx;"><image style="width: 30rpx;height: 30rpx;" src="../../../static/time.png" mode=""></image></view>
  42 + <view style="margin-left: 46rpx;">
  43 + <u--input v-model="timeData.getTimeGap" disabled disabledColor="#ffffff" placeholder="请选择时间区间" border="none"></u--input>
  44 + </view>
  45 + <!-- #endif -->
28 46 </view>
29 47 </u-form-item>
30   - <u-form-item label="." prop="getType" @click="openOther">
31   - <u--input v-model="timeData.getType" disabled disabledColor="#ffffff" placeholder="请选择类型" border="none"></u--input>
32   - <!-- <view style="width: 638rpx;height: 50rpx;border-radius: 40px;background-color: #377DFF;border:1px solid #377DFF;margin-left:-60rpx">
33   - <u--input v-model="timeData.getType" disabled disabledColor="#ffffff" placeholder="请选择类型" border="none"></u--input>
34   - </view> -->
  48 + <u-form-item label="" prop="getType" @click="openOther">
  49 + <!-- #ifdef MP -->
  50 + <view style="width: 638rpx;height: 80rpx;border-radius: 40px;background: rgba(55, 125, 255, 0.03);margin-left:-60rpx">
  51 + <u--input shape="circle" v-model="timeData.getType" placeholder="请选择类型"></u--input>
  52 + </view>
  53 + <!-- #endif -->
  54 +
  55 + <!-- #ifdef APP -->
  56 + <view style="width: 638rpx;height: 80rpx;border-radius: 40px;background: rgba(55, 125, 255, 0.03);margin-left:60rpx">
  57 + <u--input shape="circle" v-model="timeData.getType" placeholder="请选择类型"></u--input>
  58 + </view>
  59 + <!-- #endif -->
35 60 </u-form-item>
36 61 </u-form>
37   - <view class="charts-box"><qiun-data-charts type="column" :chartData="chartData" /></view>
  62 + <view style="height: 800rpx;width: 750rpx;margin-left: 20rpx;">
  63 + <!-- 区域折线图 -->
  64 + <view class="charts-box"><qiun-data-charts type="tarea" :chartData="chartData" :echartsH5="true" :echartsApp="true" :canvas2d="true" background="none" /></view>
  65 + <!-- 区域折线图 -->
  66 + </view>
38 67 </view>
39 68 <view style="border-radius: 20px;margin-top: 30rpx;width: 700rpx;height: 700rpx;background-color: #fff;">
40 69 <u-list @scrolltolower="scrolltolower">
... ... @@ -59,12 +88,19 @@
59 88
60 89 <script>
61 90 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  91 +import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
  92 +
62 93 export default {
63 94 components: {
64   - fTabbar
  95 + fTabbar,
  96 + qiunDataCharts
65 97 },
66 98 data() {
67 99 return {
  100 + chartData: {
  101 + categories: [],
  102 + series: []
  103 + },
68 104 indexList: [
69 105 {
70 106 name: '变量值',
... ... @@ -95,19 +131,6 @@ export default {
95 131 value: '2022-03-01 18:16:33'
96 132 }
97 133 ],
98   - chartData: {
99   - categories: ['2016', '2017', '2018', '2019', '2020', '2021'],
100   - series: [
101   - {
102   - name: '目标值',
103   - data: [35, 36, 31, 33, 13, 34]
104   - },
105   - {
106   - name: '完成量',
107   - data: [18, 27, 21, 24, 6, 28]
108   - }
109   - ]
110   - },
111 134 showTimeGap: false,
112 135 showOtherType: false,
113 136 showCalendar: false,
... ... @@ -162,11 +185,25 @@ export default {
162 185 ]
163 186 };
164 187 },
  188 + onReady() {
  189 + setTimeout(() => {
  190 + this.getServerData();
  191 + }, 1000);
  192 + },
165 193 onLoad(e) {
166 194 // 隐藏原生的tabbar
167 195 uni.hideTabBar();
168 196 },
169 197 methods: {
  198 + getServerData() {
  199 + this.chartData.categories = [];
  200 + this.chartData.series = [
  201 + {
  202 + name: '14:52',
  203 + data: [[10000, 55], [30000, 25], [50000, 55], [70000, 25], [90000, 55]]
  204 + }
  205 + ];
  206 + },
170 207 hideKeyboard() {
171 208 uni.hideKeyboard();
172 209 },
... ... @@ -200,10 +237,6 @@ export default {
200 237 padding-top: -12rpx;
201 238 padding-left: 23rpx;
202 239 }
203   -.charts-box {
204   - width: 100%;
205   - height: 600rpx;
206   -}
207 240 .form-style {
208 241 /deep/.u-form {
209 242 .u-form-item {
... ... @@ -211,4 +244,8 @@ export default {
211 244 }
212 245 }
213 246 }
  247 +.charts-box {
  248 + width: 650rpx;
  249 + height: 600rpx;
  250 +}
214 251 </style>
... ...
... ... @@ -19,8 +19,10 @@
19 19 <view class="camera-container">
20 20 <view class="container-item">
21 21 <view @click="openCameraDetail(item.url)" v-for="(item, index) in list" :key="index" class="item">
22   - <view style="width: 320rpx;height: 320rpx"><video style="width: 320rpx;height: 320rpx;" :src="item.url" controls></video></view>
23   - <view style="position: relative;top: 8rpx;text-align: center;">{{ item.name }}</view>
  22 + <video style="border-radius: 20px;width:300rpx ;height: 200rpx;" object-fit="conver" :src="item.url" controls></video>
  23 + <view style="position: relative;top: 8rpx;text-align: center;">
  24 + <text style="color: #333333;font-size: 13px;">{{ item.name }}</text>
  25 + </view>
24 26 </view>
25 27 </view>
26 28 </view>
... ... @@ -79,9 +81,8 @@ export default {
79 81
80 82 <style lang="scss" scoped>
81 83 .camera-page {
82   - padding: 0rpx 15rpx;
83 84 min-height: 100vh;
84   - background-color: #fff;
  85 + background-color: #f0f2f5;
85 86 }
86 87 .org-sty {
87 88 width: 750rpx;
... ... @@ -101,21 +102,22 @@ export default {
101 102 border: 0.1px solid gray;
102 103 }
103 104 .camera-container {
104   - padding: 0 15rpx;
105   - margin-top: 15rpx;
  105 + padding: 0 28rpx;
  106 + margin-top: -27rpx;
106 107 .container-item {
107 108 width: 717rpx;
108 109 display: flex;
109 110 justify-content: space-between;
110 111 flex-direction: row;
111 112 flex-wrap: wrap;
112   - position: relative;
113   - top: -67rpx;
  113 + margin-left: -42rpx;
114 114 .item {
115   - width: 320rpx;
116   - height: 320rpx;
117   - background-color: gray;
118   - margin-top: 70rpx;
  115 + margin-top: 83rpx;
  116 + width: 300rpx;
  117 + height: 200rpx;
  118 + background-color: #fff;
  119 + border-radius: 20px;
  120 + margin-left: 58rpx;
119 121 }
120 122 }
121 123 }
... ...
... ... @@ -30,6 +30,8 @@
30 30 </template>
31 31
32 32 <script>
  33 + var clear;
  34 + import { mapState, mapMutations } from 'vuex';
33 35 export default {
34 36 data() {
35 37 return {
... ... @@ -40,6 +42,7 @@
40 42 }
41 43 },
42 44 methods: {
  45 + ...mapMutations(['setUserInfo']),
43 46 //验证码按钮文字状态
44 47 getCodeState() {
45 48 const _this = this;
... ... @@ -58,7 +61,6 @@
58 61 },
59 62 //获取验证码
60 63 getVcode() {
61   - console.log('getVcode')
62 64 if (this.readonly) {
63 65 uni.showToast({
64 66 title: '验证码已发送~',
... ... @@ -81,13 +83,41 @@
81 83 });
82 84 return;
83 85 }
84   - let httpData = {}
85 86 // 获取验证码接口
86   - // uni.$u.http.post('您的接口', httpData).then(res => {
87   - this.getCodeState(); //开始倒计时
88   - // })
  87 + uni.$u.http.post(`/yt/noauth/sendLoginSmsCode/${this.phone}` ).then(res => {
  88 + this.getCodeState(); //开始倒计时
  89 + })
  90 + },
  91 + onSubmit() {
  92 + if(this.vCode=='')return uni.$u.toast('请输入验证码')
  93 + let httpData = {
  94 + code: this.vCode,
  95 + phoneNumber: this.phone
  96 + }
  97 + uni.$u.http.post('/yt/auth/code/login', httpData).then(res => {
  98 + if (res) {
  99 + // 储存登录信息
  100 + let resObj = {
  101 + refreshToken: res.refreshToken,
  102 + isToken: res.token
  103 + };
  104 + let userInfo = {
  105 + ...resObj,
  106 + token: true //token用于判断是否登录
  107 + };
  108 + this.setUserInfo(userInfo);
  109 + uni.showToast({
  110 + title: '登录成功~',
  111 + icon: 'none'
  112 + });
  113 + setTimeout(() => {
  114 + uni.navigateBack({
  115 + delta:2
  116 + })
  117 + }, 500);
  118 + }
  119 + });
89 120 },
90   - onSubmit() {},
91 121 openAccountFunc(){
92 122 uni.navigateTo({
93 123 url:"./login"
... ...
... ... @@ -42,6 +42,7 @@
42 42 </template>
43 43
44 44 <script>
  45 + var clear;
45 46 export default {
46 47 data() {
47 48 return {
... ... @@ -73,7 +74,6 @@
73 74 },
74 75 //获取验证码
75 76 getVcode() {
76   - console.log('getVcode')
77 77 if (this.readonly) {
78 78 uni.showToast({
79 79 title: '验证码已发送~',
... ... @@ -97,10 +97,10 @@
97 97 return;
98 98 }
99 99 let httpData = {}
100   - // 获取验证码接口
101   - // uni.$u.http.post('您的接口', httpData).then(res => {
102   - this.getCodeState(); //开始倒计时
103   - // })
  100 + // 获取验证码接口
  101 + uni.$u.http.post(`/yt/noauth/sendLoginSmsCode/${this.phone}` ).then(res => {
  102 + this.getCodeState(); //开始倒计时
  103 + })
104 104 },
105 105 onNextSubmit() {
106 106 this.nextStatus = true
... ... @@ -108,7 +108,25 @@
108 108 showPhone(){
109 109 this.nextStatus = false
110 110 },
111   - onSubmit() {}
  111 + onSubmit() {
  112 + if(this.password!==this.rePassword) return uni.$u.toast('两次输入密码不一致');
  113 + let httpData={
  114 + password: this.password,
  115 + phoneNumber: this.phone,
  116 + userId: this.vCode
  117 + }
  118 + uni.$u.http.post(`/yt/noauth/reset/${this.phone}`, httpData).then(res => {
  119 + uni.showToast({
  120 + title: '重置密码成功~',
  121 + icon: 'none'
  122 + });
  123 + setTimeout(() => {
  124 + uni.navigateBack({
  125 + delta:2
  126 + })
  127 + }, 500);
  128 + });
  129 + }
112 130 }
113 131 }
114 132 </script>
... ...
... ... @@ -12,7 +12,7 @@
12 12 <view class="f__login">
13 13 <view class="loginPhone">
14 14 <view class="form-row">
15   - <u--input border="bottom" class="input" prefixIcon="account-fill" type="text" placeholder="登录账号" v-model="loginForm.account"></u--input>
  15 + <u--input border="bottom" class="input" prefixIcon="account-fill" type="text" placeholder="登录账号" v-model="loginForm.username"></u--input>
16 16 </view>
17 17 <view class="form-row">
18 18 <u-input
... ... @@ -47,20 +47,48 @@
47 47 </template>
48 48
49 49 <script>
  50 +import { mapState, mapMutations } from 'vuex';
  51 +
50 52 export default {
51 53 data() {
52 54 return {
53 55 showPasswordIcon: 'eye-off',
54 56 showPasswordOrText: 'password',
55 57 loginForm: {
56   - account: '',
  58 + username: '',
57 59 password: ''
58 60 }
59 61 };
60 62 },
61 63 methods: {
  64 + ...mapMutations(['setUserInfo']),
62 65 passwordChange() {},
63   - onSubmitFunc() {},
  66 + onSubmitFunc() {
  67 + if (this.loginForm.username == '' || this.loginForm.password == '') {
  68 + return uni.$u.toast('请输入用户名或密码');
  69 + }
  70 + uni.$u.http.post('/auth/login', this.loginForm).then(res => {
  71 + if (res) {
  72 + // 储存登录信息
  73 + let resObj = {
  74 + refreshToken: res.refreshToken,
  75 + isToken: res.token
  76 + };
  77 + let userInfo = {
  78 + ...resObj,
  79 + token: true //token用于判断是否登录
  80 + };
  81 + this.setUserInfo(userInfo);
  82 + uni.showToast({
  83 + title: '登录成功~',
  84 + icon: 'none'
  85 + });
  86 + setTimeout(() => {
  87 + uni.navigateBack();
  88 + }, 500);
  89 + }
  90 + });
  91 + },
64 92 openCodeFunc() {
65 93 uni.navigateTo({
66 94 url: './code'
... ...
... ... @@ -151,7 +151,7 @@
151 151 <view style="width:669rpx;height: 100rpx;border-bottom: 1rpx solid #d6d6d6;text-align: center;line-height: 86rpx;">
152 152 <text style="color:#999999">确定要退出当前账号?</text>
153 153 </view>
154   - <view style="width:669rpx;height: 100rpx;border-bottom: 1rpx solid #d6d6d6;text-align: center;line-height: 86rpx;">
  154 + <view @click="logoutBtn" style="width:669rpx;height: 100rpx;border-bottom: 1rpx solid #d6d6d6;text-align: center;line-height: 86rpx;">
155 155 <text style="color:#f95e5a">退出登录</text>
156 156 </view>
157 157 <view style="width:669rpx;height: 100rpx;text-align: center;line-height: 86rpx;"><text @click="closeLogout" style="color:#3478f7">取消</text></view>
... ... @@ -165,7 +165,7 @@
165 165 import base from '@/config/baseUrl';
166 166 import fTabbar from '@/components/module/f-tabbar/f-tabbar';
167 167 import fNavbar from '@/components/module/f-navbar/f-navbar';
168   -import { mapState } from 'vuex';
  168 +import { mapState, mapMutations } from 'vuex';
169 169
170 170 export default {
171 171 components: {
... ... @@ -208,6 +208,7 @@ export default {
208 208 ...mapState(['userInfo'])
209 209 },
210 210 methods: {
  211 + ...mapMutations(['emptyUserInfo']),
211 212 openSysNotify() {
212 213 uni.navigateTo({
213 214 url: '../systemNotify/systemNotify'
... ... @@ -295,6 +296,25 @@ export default {
295 296 },
296 297 closeLogout() {
297 298 this.showLogout = false;
  299 + },
  300 + logoutBtn() {
  301 + let that = this;
  302 + uni.showModal({
  303 + title: '退出登录',
  304 + content: '你确定退出登录吗?',
  305 + success(res) {
  306 + if (res.confirm) {
  307 + that.emptyUserInfo();
  308 + that.showLogout=false
  309 + setTimeout(() => {
  310 + uni.navigateTo({
  311 + url:'./login'
  312 + })
  313 + }, 500);
  314 + } else if (res.cancel) {
  315 + }
  316 + }
  317 + });
298 318 }
299 319 }
300 320 };
... ...
1 1 export const state = {
2   - //用户数据
3   - userInfo: {},
  2 + //用户数据
  3 + userInfo: {},
4 4 };
5 5 export const mutations = {
6   - //储存用户信息
7   - setUserInfo(state, data) {
8   - if (data) {
9   - state.userInfo = Object.assign({}, state.userInfo,data);
10   - // #ifdef H5
11   - window.sessionStorage.setItem('userInfo', JSON.stringify(state.userInfo));
12   - // #endif
13   - // #ifndef H5
14   - uni.setStorageSync('userInfo', state.userInfo);
15   - // #endif
16   - }
17   - },
18   - // 退出APP
19   - emptyUserInfo(state) {
20   - state.userInfo = {};
21   - // #ifdef H5
22   - window.sessionStorage.removeItem("userInfo");
23   - // #endif
24   - // #ifndef H5
25   - uni.removeStorageSync("userInfo");
26   - // #endif
27   - },
  6 + //储存用户信息
  7 + setUserInfo(state, data) {
  8 + if (data) {
  9 + state.userInfo = Object.assign({}, state.userInfo, data);
  10 + // #ifdef H5
  11 + window.sessionStorage.setItem('userInfo', JSON.stringify(state.userInfo));
  12 + // #endif
  13 + // #ifndef MP
  14 + uni.setStorageSync('userInfo', state.userInfo);
  15 + // #endif
  16 + //#ifdef MP
  17 + wx.setStorageSync('userInfo', state.userInfo);
  18 + //#endif
  19 + }
  20 + },
  21 + // 退出APP
  22 + emptyUserInfo(state) {
  23 + state.userInfo = {};
  24 + // #ifdef H5
  25 + window.sessionStorage.removeItem("userInfo");
  26 + // #endif
  27 + // #ifndef MP
  28 + uni.removeStorageSync("userInfo");
  29 + // #endif
  30 + // #ifdef MP
  31 + wx.removeStorageSync("userInfo");
  32 + // #endif
  33 + },
28 34 };
29 35 export const actions = {
30 36
... ...
  1 +## 1.4.11(2021-10-13)
  2 +当前选项是否选中的回显问题。
  3 +## 1.4.10(2021-09-29)
  4 +默认树的显示样式
  5 +## 1.4.9(2021-09-13)
  6 +1. luyj-tree参数中移除props.hasChildren , luyj-tree-item移除参数comparison.hasChilren。
  7 +2. luyj-tree 参数nodes默认值改为false, luyj-tree-item 默认值改为false
  8 +3. luyj-tree-item 修改选中框的默认大小。
  9 +4. 修改luyj-tree-item 插槽 的默认样式
  10 +5. 修改luyj-tree 插槽的默认样式
  11 +6. 修改一些必要的说明
  12 +## 1.4.8(2021-09-09)
  13 +1. 修改了一些说明
  14 +2. 不包含下一级时,点击页面部分,选中当前的项
  15 +3. 修改默认选中事件bug
  16 +4. 自定义slot 默认展示时与 单选框、复选框重叠问题
  17 +## 1.4.7(2021-09-08)
  18 +添加一些必要的说明。
  19 +## 1.4.6(2021-09-03)
  20 +展示和不显示搜索按钮时位置问题。
  21 +## 1.4.5(2021-09-02)
  22 +展示和不显示搜索按钮时位置问题。
  23 +## 1.4.4(2021-09-01)
  24 +区分"选项修改"和"确认"事件,分别对应@change 和 @sendValue。
  25 +## 1.4.3(2021-09-01)
  26 +变量tree_Stack的名称问题
  27 +## 1.4.2(2021-08-27)
  28 +为树添加导航栏事件
  29 +## 1.4.1(2021-08-26)
  30 +一些bug
  31 +懒加载后重新加载数据,显示问题。
  32 +## 1.4.0(2021-08-25)
  33 +添加允许多次渲染item的方法(默认每次50条)。当数据量过大时使用
  34 +## 1.3.2(2021-08-25)
  35 +搜索时,没有显示名称列,中止报错问题。(改为提醒,跳过后继续执行)
  36 +## 1.3.1(2021-08-24)
  37 +添加一些简单的说明
  38 +## 1.3.(2021-08-24)
  39 +更新了一些bug。
  40 +暂时令参数checkStrictly 关联失效。添加了一些参数。文档会后续陆续补充。
  41 +独立出luyj-tree-item项。
  42 +修复了(可能未完全修复)自定义插件的问题。
  43 +移除了一些无效的参数,如max、scrollLeft。
  44 +## 1.2.1(2021-08-20)
  45 +解决。数据不包含数据,点击项报错问题。
  46 +## 1.2.0(2021-08-20)
  47 +将面包屑导航分开
  48 +## 1.1.8(2021-08-19)
  49 +更新不能检测传入数据变动(tree变动)问题
  50 +## 1.1.7(2021-08-14)
  51 +简单整理了一下代码,没有什么实质性的改变。
  52 +## 1.1.6(2021-08-07)
  53 +展示状态下显示确认
  54 +## 1.1.5(2021-07-29)
  55 +更新搜索框在微信开发者工具模拟器不能输入问题
  56 +## 1.1.4(2021-07-27)
  57 +read.md说明
  58 +## 1.1.3(2021-07-27)
  59 +read.md更新
  60 +## 1.1.2(2021-07-27)
  61 +更新说明文档
  62 +## 1.1.1(2021-07-27)
  63 +更新一些插件说明
  64 +## 1.1.0(2021-07-27)
  65 +为树的输入框,添加更多样式参数
  66 +## 1.0.0(2021-07-25)
  67 +无限树形结构组件。支持搜索、面包屑类型导航、选择。
... ...
  1 +@font-face {
  2 + font-family: "iconfont"; /* Project id 2009600 */
  3 + src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
  4 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
  5 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
  6 +}
  7 +
  8 +.iconfont {
  9 + font-family: "iconfont" !important;
  10 + font-size: 16px;
  11 + font-style: normal;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 +}
  15 +
  16 +/* 清除图标 */
  17 +.icon-clear:before{
  18 + content: '\e606';
  19 +}
  20 +
  21 +.icon-banxuanzhongshousuo1-shi:before {
  22 + content: "\e682";
  23 +}
  24 +
  25 +.icon-xuanzhong3:before {
  26 + content: "\e6bb";
  27 +}
  28 +
  29 +.icon-weixuanzhong2:before {
  30 + content: "\e62e";
  31 +}
  32 +
  33 +.icon-danxuanxuanzhong:before {
  34 + content: "\e631";
  35 +}
  36 +
  37 +.icon-xuanzhong4:before {
  38 + content: "\e63e";
  39 +}
  40 +
  41 +.icon-xuanzhong1:before {
  42 + content: "\e62d";
  43 +}
  44 +.icon-xuanzhong2:before {
  45 + content: "\e656";
  46 +}
  47 +
  48 +.icon-selected:before {
  49 + content: "\e615";
  50 +}
  51 +
  52 +.icon-weixuanzhong1:before {
  53 + content: "\e614";
  54 +}
  55 +
  56 +.icon-xingzhuang6kaobei3-copy-copy:before {
  57 + content: "\e613";
  58 +}
  59 +
  60 +.icon-radio-checked:before {
  61 + content: "\e63f";
  62 +}
  63 +
  64 +.icon-huifu:before {
  65 + content: "\e619";
  66 +}
  67 +
  68 +.icon-dizhi:before {
  69 + content: "\e64a";
  70 +}
  71 +
  72 +.icon-kuaijiecaidan:before {
  73 + content: "\e60a";
  74 +}
  75 +
  76 +.icon-z043:before {
  77 + content: "\e62f";
  78 +}
  79 +
  80 +.icon-guanbi:before {
  81 + content: "\e607";
  82 +}
  83 +
  84 +.icon-xuanze:before {
  85 + content: "\e623";
  86 +}
  87 +
  88 +.icon-caidanzhaolinggan:before {
  89 + content: "\e616";
  90 +}
  91 +
  92 +.icon-xitongshezhi:before {
  93 + content: "\e60c";
  94 +}
  95 +
  96 +.icon-xitongshezhi1:before {
  97 + content: "\e633";
  98 +}
  99 +
  100 +.icon-lunbo:before {
  101 + content: "\e692";
  102 +}
  103 +
  104 +.icon-shuping:before {
  105 + content: "\e659";
  106 +}
  107 +
  108 +.icon-tongzhi:before {
  109 + content: "\e641";
  110 +}
  111 +
  112 +.icon-pinglunguanlishezhi:before {
  113 + content: "\e6ac";
  114 +}
  115 +
  116 +.icon-icon:before {
  117 + content: "\e600";
  118 +}
  119 +
  120 +.icon-liuyanguanli:before {
  121 + content: "\e61d";
  122 +}
  123 +
  124 +.icon-xuanzhong:before {
  125 + content: "\e669";
  126 +}
  127 +
  128 +.icon--:before {
  129 + content: "\e622";
  130 +}
  131 +
  132 +.icon-tushu:before {
  133 + content: "\e604";
  134 +}
  135 +
  136 +.icon-huishouzhan:before {
  137 + content: "\e61c";
  138 +}
  139 +
  140 +.icon-yonghutouxiang:before {
  141 + content: "\e617";
  142 +}
  143 +
  144 +.icon-liebiao:before {
  145 + content: "\e630";
  146 +}
  147 +
  148 +.icon-fenlei:before {
  149 + content: "\e621";
  150 +}
  151 +
  152 +.icon-tushu1:before {
  153 + content: "\e605";
  154 +}
  155 +
  156 +.icon-tubiao-:before {
  157 + content: "\e620";
  158 +}
  159 +
  160 +.icon-weixuanze:before {
  161 + content: "\e624";
  162 +}
  163 +
  164 +.icon-tushujieyue:before {
  165 + content: "\e690";
  166 +}
  167 +
  168 +.icon-lunbo1:before {
  169 + content: "\e6c5";
  170 +}
  171 +
  172 +.icon-shanchu:before {
  173 + content: "\e67b";
  174 +}
  175 +
  176 +.icon-lunbo2:before {
  177 + content: "\e61e";
  178 +}
  179 +
  180 +.icon-huaban:before {
  181 + content: "\e663";
  182 +}
  183 +
  184 +.icon-kehuan:before {
  185 + content: "\e608";
  186 +}
  187 +
  188 +.icon-icon02:before {
  189 + content: "\e601";
  190 +}
  191 +
  192 +.icon-huishouzhan1:before {
  193 + content: "\e612";
  194 +}
  195 +
  196 +.icon-huishouzhan2:before {
  197 + content: "\e63d";
  198 +}
  199 +
  200 +.icon-sousuo:before {
  201 + content: "\e62c";
  202 +}
  203 +
  204 +.icon-xingzhuang:before {
  205 + content: "\e625";
  206 +}
  207 +
  208 +.icon-lunbobankuai:before {
  209 + content: "\e61f";
  210 +}
  211 +
  212 +.icon-shangchuan:before {
  213 + content: "\e602";
  214 +}
  215 +
  216 +.icon-yonghu:before {
  217 + content: "\e761";
  218 +}
  219 +
  220 +.icon-tongzhi1:before {
  221 + content: "\e603";
  222 +}
  223 +
  224 +.icon-jingsong:before {
  225 + content: "\e65c";
  226 +}
  227 +
  228 +.icon-fenlei1:before {
  229 + content: "\e6c6";
  230 +}
  231 +
  232 +.icon-xieshupingicon:before {
  233 + content: "\e72d";
  234 +}
  235 +
  236 +.icon-liuyan:before {
  237 + content: "\e626";
  238 +}
  239 +
  240 +.icon-weixuanzhong:before {
  241 + content: "\e627";
  242 +}
  243 +
  244 +.icon-youxiang:before {
  245 + content: "\e646";
  246 +}
  247 +
  248 +.icon-lunboguanggao:before {
  249 + content: "\e6b3";
  250 +}
  251 +
  252 +.icon-xuanze1:before {
  253 + content: "\e60d";
  254 +}
  255 +
  256 +.icon-chushaixuanxiang:before {
  257 + content: "\e606";
  258 +}
  259 +
  260 +.icon-liuyanguanli1:before {
  261 + content: "\e61a";
  262 +}
  263 +
  264 +.icon-shanchu1:before {
  265 + content: "\e609";
  266 +}
  267 +
  268 +.icon-huishouzhan3:before {
  269 + content: "\e642";
  270 +}
  271 +
  272 +.icon-shangchuan1:before {
  273 + content: "\e823";
  274 +}
  275 +
  276 +.icon-huishouzhan4:before {
  277 + content: "\e61b";
  278 +}
  279 +
  280 +.icon-chuangzuo:before {
  281 + content: "\e8ad";
  282 +}
  283 +
  284 +.icon-dianzan:before {
  285 + content: "\e8ae";
  286 +}
  287 +
  288 +.icon-paihangbang:before {
  289 + content: "\e8b3";
  290 +}
  291 +
  292 +.icon-shouye:before {
  293 + content: "\e8b9";
  294 +}
  295 +
  296 +.icon-shoucang:before {
  297 + content: "\e8c6";
  298 +}
  299 +
  300 +.icon-addApp:before {
  301 + content: "\e60b";
  302 +}
  303 +
  304 +.icon-huishouzhan5:before {
  305 + content: "\e63a";
  306 +}
  307 +
  308 +.icon-add1:before {
  309 + content: "\e60e";
  310 +}
  311 +
  312 +.icon-shoucang1:before {
  313 + content: "\e60f";
  314 +}
  315 +
  316 +.icon-canshutongji:before {
  317 + content: "\e618";
  318 +}
  319 +
  320 +.icon-rizhiguanli:before {
  321 + content: "\e628";
  322 +}
  323 +
  324 +.icon-shanchu2:before {
  325 + content: "\e629";
  326 +}
  327 +
  328 +.icon-xinzeng:before {
  329 + content: "\e62a";
  330 +}
  331 +
  332 +.icon-zhankailiebiao:before {
  333 + content: "\e62b";
  334 +}
  335 +
  336 +.icon-xiala-copy:before {
  337 + content: "\e610";
  338 +}
  339 +
  340 +.icon-shangla:before {
  341 + content: "\e64e";
  342 +}
  343 +
  344 +.icon-xianxingshezhi:before {
  345 + content: "\e611";
  346 +}
... ...
  1 +.container-list-item {
  2 + background-color: #fff;
  3 + border-bottom: 1rpx solid #f4f4f4;
  4 + padding-left: 10rpx;
  5 + .content {
  6 + display: flex;
  7 + align-items: center;
  8 + min-height: 60rpx;
  9 + width: 100%;
  10 + padding: 15rpx 0;
  11 + position: relative;
  12 + font-size: 32rpx;
  13 + // 默认文本显示内容(默认的slot)
  14 + .slot {
  15 + position:absolute;
  16 + right: 64rpx;
  17 + font-size: 32rpx;
  18 + color: #5b5757;
  19 + .word {
  20 + width:100%;
  21 + word-break: break-all;
  22 + }
  23 + }
  24 + // 默认箭头显示样式
  25 + .right {
  26 + position: absolute;
  27 + right: 30rpx;
  28 + color: #babdc3;
  29 + font-size: 32rpx;
  30 + }
  31 +
  32 + }
  33 +}
  34 +// 复选框
  35 + .checkbox {
  36 + position: relative;
  37 + height: 36rpx;
  38 + margin-left: 10rpx;
  39 + margin-right: 0px;
  40 + width: 36rpx;
  41 + .txt {
  42 + font-size: 35rpx;
  43 + line-height: 36rpx;
  44 + width: 100%;
  45 + height: 100%;
  46 + display: flex;
  47 + }
  48 + }
  49 +
  50 +.checkBorder {
  51 + border: 1px solid #ecdee4;
  52 +}
  53 +
  54 +.text-cut{
  55 + text-overflow: ellipsis;
  56 + white-space: nowrap;
  57 + overflow: hidden;
  58 +}
... ...
  1 +<template>
  2 + <view class="container-list-item" @click="clickItem($event,item)">
  3 + <label class="content">
  4 + <!-- 复选框 -->
  5 + <view class="checkbox" v-if="isCheckBox" @click.stop="clickBox($event , item)">
  6 + <i v-if="curChecked " :style="{'color' :checkActiveColor}" class="iconfont icon-xuanzhong txt icon-selected"/>
  7 + <i v-else :style="{'color': checkNoneColor}" class="iconfont icon-weixuanzhong txt"/>
  8 + </view>
  9 + <!-- 复选框 -->
  10 + <!-- 单选框 -->
  11 + <view class="checkbox" v-else-if ="isRadio" @click.stop="clickBox($event, item)">
  12 + <i v-if="curChecked" :style="{'color' :checkActiveColor}" class="txt iconfont icon-selected"/>
  13 + <i v-else :style="{'color': checkNoneColor}" class="txt iconfont icon-weixuanzhong1"/>
  14 + </view>
  15 + <!-- 单选框 -->
  16 + <!-- 自定义插槽body -->
  17 + <view :style="isCheck ?'left: 56rpx':'left: 16rpx'" class="slot">
  18 + <slot name="body" >
  19 + <view class="word text-cut" >{{ item[sLabel] }}</view>
  20 + </slot>
  21 + </view>
  22 + <!-- 自定义插槽body -->
  23 + <view v-if="hasChildren" class="right"><i class="iconfont icon-z043"></i></view>
  24 + </label>
  25 + </view>
  26 +</template>
  27 +
  28 +<script>
  29 + /**
  30 + * 无限极树的单项 item
  31 + * @description无限级数的单项item
  32 + * @property {Object} item 单项的值(默认{})
  33 + * @property {Boolean} isCheck 判断是否可选 (默认false)
  34 + * @property {Boolean} 判断是否是否多选(默认false, isCheck为true时有效)。
  35 + * @property {String} checkActiveColor 选中状态下单选框/复选框的颜色 (默认#00AAFF)
  36 + * @property {String} checkNoneColor 未选中状态下单选框/复选框的颜色(默认#B8B8B8)
  37 + * @property {Object} comparison 属性名称对照表
  38 + * @param {String} value 选中值对应列名称(默认value)
  39 + * @param {String} label 显示值对应列名称(默认label)
  40 + * @param {String} children 子级列对应名称(默认children)
  41 + * @return {Function} 点击当前项的执行方法
  42 + * @param {Object} item 当前项的值
  43 + * @return {Function} change 选中值变化时执行方法(event.detail = {value: 是否选中})
  44 + */
  45 + export default {
  46 + name:'luyj-tree-item',
  47 + props:{
  48 + // 传入的数值
  49 + item :{
  50 + type:Object,
  51 + default: {}
  52 + },
  53 + // 判断是否可选
  54 + isCheck : {
  55 + type: Boolean,
  56 + default: false
  57 + },
  58 + // 是否多选
  59 + multiple:{
  60 + type: Boolean,
  61 + default: false
  62 + },
  63 + // 是否选中状态
  64 + checked : {
  65 + type:Boolean,
  66 + default:false
  67 + },
  68 + // 是否只能选择叶子结点
  69 + nodes : {
  70 + type: false,
  71 + default:false
  72 + },
  73 + // 选中状态下单选框/复选框的颜色
  74 + checkActiveColor : {
  75 + type:String,
  76 + default:'#00AAFF'
  77 + },
  78 + // 未选中状态下单选框的颜色
  79 + checkNoneColor : {
  80 + type:String,
  81 + default:'#B8B8B8'
  82 + },
  83 + // 列名称对照表
  84 + comparison :{
  85 + type:Object,
  86 + default: () => {
  87 + return {
  88 + value : 'value', // 选中值
  89 + label : 'label', // 显示名称
  90 + children:'children', // 子级名称
  91 + };
  92 + }
  93 + }
  94 + },
  95 + data() {
  96 + return {
  97 + sLabel: this.comparison.label? this.comparison.label :'label', // label值名称
  98 + sChildren: this.comparison.children ? this.comparison.children : 'children', // children值名称
  99 + curChecked : this.checked, //是否选中状态
  100 + }
  101 + },
  102 + computed:{
  103 + /**
  104 + * 是否包含子级
  105 + */
  106 + hasChildren : function(){
  107 + return Boolean(this.item) ?(Boolean(this.item[this.sChildren]) ? this.item[this.sChildren].length > 0 : false) : false;
  108 + },
  109 + /**
  110 + * 是否单选
  111 + */
  112 + isRadio : function(){
  113 + return this.isCheck && !this.multiple && (!this.nodes || !this.hasChildren);
  114 + },
  115 + /**
  116 + * 是否多选
  117 + */
  118 + isCheckBox :function(){
  119 + return this.isCheck && this.multiple && (!this.nodes || !this.hasChildren);
  120 + },
  121 +
  122 + },
  123 + watch:{
  124 + // 监听列名对照表变化
  125 + comparison :{
  126 + handler: function(val){
  127 + this.sLabel = this.comparison.label? this.comparison.label :'label';
  128 + this.sChildren = this.comparison.children ? this.comparison.children : 'children';
  129 +
  130 + },
  131 + deep: true
  132 + },
  133 + // 是否选中状态
  134 + checked : function(val){
  135 + this.curChecked = val;
  136 + }
  137 + },
  138 + methods:{
  139 + /** 点击当前项的执行方法
  140 + * @param {Object} e
  141 + * @param {Object} item
  142 + */
  143 + clickItem : function (e ,item){
  144 + this.$emit("clickItem" , item , this.hasChildren);
  145 + // 不包含下一级,修改check值事件
  146 + if(!this.hasChildren && this.isCheck){
  147 + this.clickBox(e);
  148 + }
  149 + },
  150 + /**
  151 + * 点击单选框或复选框
  152 + * @param {Object} e 当前选中值
  153 + * @param {Object} item 当前选中的项
  154 + */
  155 + clickBox : function(e , item){
  156 + this.curChecked = !this.curChecked;
  157 + e.detail.value = this.curChecked;
  158 + this.$emit("change" , e); // 切换单选框或复选框
  159 + },
  160 +
  161 + }
  162 + }
  163 +</script>
  164 +
  165 +<style lang="scss" scoped>
  166 + @import 'luyj-tree-item.scss';
  167 + @import "../../lib/css/icon.css";
  168 +</style>
... ...
  1 +@font-face {
  2 + font-family: "iconfont"; /* Project id 2009600 */
  3 + src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
  4 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
  5 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
  6 +}
  7 +
  8 +.iconfont {
  9 + font-family: "iconfont" !important;
  10 + font-size: 16px;
  11 + font-style: normal;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 +}
  15 +
  16 +.icon-banxuanzhongshousuo1-shi:before {
  17 + content: "\e682";
  18 +}
  19 +
  20 +.icon-xuanzhong3:before {
  21 + content: "\e6bb";
  22 +}
  23 +
  24 +.icon-weixuanzhong2:before {
  25 + content: "\e62e";
  26 +}
  27 +
  28 +.icon-danxuanxuanzhong:before {
  29 + content: "\e631";
  30 +}
  31 +
  32 +.icon-xuanzhong4:before {
  33 + content: "\e63e";
  34 +}
  35 +
  36 +.icon-xuanzhong1:before {
  37 + content: "\e62d";
  38 +}
  39 +
  40 +.icon-xuanzhong2:before {
  41 + content: "\e656";
  42 +}
  43 +
  44 +.icon-selected:before {
  45 + content: "\e615";
  46 +}
  47 +
  48 +.icon-weixuanzhong1:before {
  49 + content: "\e614";
  50 +}
  51 +
  52 +.icon-xingzhuang6kaobei3-copy-copy:before {
  53 + content: "\e613";
  54 +}
  55 +
  56 +.icon-radio-checked:before {
  57 + content: "\e63f";
  58 +}
  59 +
  60 +.icon-huifu:before {
  61 + content: "\e619";
  62 +}
  63 +
  64 +.icon-dizhi:before {
  65 + content: "\e64a";
  66 +}
  67 +
  68 +.icon-kuaijiecaidan:before {
  69 + content: "\e60a";
  70 +}
  71 +
  72 +.icon-z043:before {
  73 + content: "\e62f";
  74 +}
  75 +
  76 +.icon-guanbi:before {
  77 + content: "\e607";
  78 +}
  79 +
  80 +.icon-xuanze:before {
  81 + content: "\e623";
  82 +}
  83 +
  84 +.icon-caidanzhaolinggan:before {
  85 + content: "\e616";
  86 +}
  87 +
  88 +.icon-xitongshezhi:before {
  89 + content: "\e60c";
  90 +}
  91 +
  92 +.icon-xitongshezhi1:before {
  93 + content: "\e633";
  94 +}
  95 +
  96 +.icon-lunbo:before {
  97 + content: "\e692";
  98 +}
  99 +
  100 +.icon-shuping:before {
  101 + content: "\e659";
  102 +}
  103 +
  104 +.icon-tongzhi:before {
  105 + content: "\e641";
  106 +}
  107 +
  108 +.icon-pinglunguanlishezhi:before {
  109 + content: "\e6ac";
  110 +}
  111 +
  112 +.icon-icon:before {
  113 + content: "\e600";
  114 +}
  115 +
  116 +.icon-liuyanguanli:before {
  117 + content: "\e61d";
  118 +}
  119 +
  120 +.icon-xuanzhong:before {
  121 + content: "\e669";
  122 +}
  123 +
  124 +.icon--:before {
  125 + content: "\e622";
  126 +}
  127 +
  128 +.icon-tushu:before {
  129 + content: "\e604";
  130 +}
  131 +
  132 +.icon-huishouzhan:before {
  133 + content: "\e61c";
  134 +}
  135 +
  136 +.icon-yonghutouxiang:before {
  137 + content: "\e617";
  138 +}
  139 +
  140 +.icon-liebiao:before {
  141 + content: "\e630";
  142 +}
  143 +
  144 +.icon-fenlei:before {
  145 + content: "\e621";
  146 +}
  147 +
  148 +.icon-tushu1:before {
  149 + content: "\e605";
  150 +}
  151 +
  152 +.icon-tubiao-:before {
  153 + content: "\e620";
  154 +}
  155 +
  156 +.icon-weixuanze:before {
  157 + content: "\e624";
  158 +}
  159 +
  160 +.icon-tushujieyue:before {
  161 + content: "\e690";
  162 +}
  163 +
  164 +.icon-lunbo1:before {
  165 + content: "\e6c5";
  166 +}
  167 +
  168 +.icon-shanchu:before {
  169 + content: "\e67b";
  170 +}
  171 +
  172 +.icon-lunbo2:before {
  173 + content: "\e61e";
  174 +}
  175 +
  176 +.icon-huaban:before {
  177 + content: "\e663";
  178 +}
  179 +
  180 +.icon-kehuan:before {
  181 + content: "\e608";
  182 +}
  183 +
  184 +.icon-icon02:before {
  185 + content: "\e601";
  186 +}
  187 +
  188 +.icon-huishouzhan1:before {
  189 + content: "\e612";
  190 +}
  191 +
  192 +.icon-huishouzhan2:before {
  193 + content: "\e63d";
  194 +}
  195 +
  196 +.icon-sousuo:before {
  197 + content: "\e62c";
  198 +}
  199 +
  200 +.icon-xingzhuang:before {
  201 + content: "\e625";
  202 +}
  203 +
  204 +.icon-lunbobankuai:before {
  205 + content: "\e61f";
  206 +}
  207 +
  208 +.icon-shangchuan:before {
  209 + content: "\e602";
  210 +}
  211 +
  212 +.icon-yonghu:before {
  213 + content: "\e761";
  214 +}
  215 +
  216 +.icon-tongzhi1:before {
  217 + content: "\e603";
  218 +}
  219 +
  220 +.icon-jingsong:before {
  221 + content: "\e65c";
  222 +}
  223 +
  224 +.icon-fenlei1:before {
  225 + content: "\e6c6";
  226 +}
  227 +
  228 +.icon-xieshupingicon:before {
  229 + content: "\e72d";
  230 +}
  231 +
  232 +.icon-liuyan:before {
  233 + content: "\e626";
  234 +}
  235 +
  236 +.icon-weixuanzhong:before {
  237 + content: "\e627";
  238 +}
  239 +
  240 +.icon-youxiang:before {
  241 + content: "\e646";
  242 +}
  243 +
  244 +.icon-lunboguanggao:before {
  245 + content: "\e6b3";
  246 +}
  247 +
  248 +.icon-xuanze1:before {
  249 + content: "\e60d";
  250 +}
  251 +
  252 +.icon-chushaixuanxiang:before {
  253 + content: "\e606";
  254 +}
  255 +
  256 +.icon-liuyanguanli1:before {
  257 + content: "\e61a";
  258 +}
  259 +
  260 +.icon-shanchu1:before {
  261 + content: "\e609";
  262 +}
  263 +
  264 +.icon-huishouzhan3:before {
  265 + content: "\e642";
  266 +}
  267 +
  268 +.icon-shangchuan1:before {
  269 + content: "\e823";
  270 +}
  271 +
  272 +.icon-huishouzhan4:before {
  273 + content: "\e61b";
  274 +}
  275 +
  276 +.icon-chuangzuo:before {
  277 + content: "\e8ad";
  278 +}
  279 +
  280 +.icon-dianzan:before {
  281 + content: "\e8ae";
  282 +}
  283 +
  284 +.icon-paihangbang:before {
  285 + content: "\e8b3";
  286 +}
  287 +
  288 +.icon-shouye:before {
  289 + content: "\e8b9";
  290 +}
  291 +
  292 +.icon-shoucang:before {
  293 + content: "\e8c6";
  294 +}
  295 +
  296 +.icon-addApp:before {
  297 + content: "\e60b";
  298 +}
  299 +
  300 +.icon-huishouzhan5:before {
  301 + content: "\e63a";
  302 +}
  303 +
  304 +.icon-add1:before {
  305 + content: "\e60e";
  306 +}
  307 +
  308 +.icon-shoucang1:before {
  309 + content: "\e60f";
  310 +}
  311 +
  312 +.icon-canshutongji:before {
  313 + content: "\e618";
  314 +}
  315 +
  316 +.icon-rizhiguanli:before {
  317 + content: "\e628";
  318 +}
  319 +
  320 +.icon-shanchu2:before {
  321 + content: "\e629";
  322 +}
  323 +
  324 +.icon-xinzeng:before {
  325 + content: "\e62a";
  326 +}
  327 +
  328 +.icon-zhankailiebiao:before {
  329 + content: "\e62b";
  330 +}
  331 +
  332 +.icon-xiala-copy:before {
  333 + content: "\e610";
  334 +}
  335 +
  336 +.icon-shangla:before {
  337 + content: "\e64e";
  338 +}
  339 +
  340 +.icon-xianxingshezhi:before {
  341 + content: "\e611";
  342 +}
... ...
  1 +// 导航栏标题
  2 +.title {
  3 + height: 90rpx;
  4 + padding: 0 32rpx;
  5 + line-height: 90rpx;
  6 + font-size: 30rpx;
  7 + background-color: #f5f5f5;
  8 + color: #606064;
  9 + // 导航栏图标样式
  10 + .iconclass {
  11 + display: inline-block;
  12 + margin: 0 12rpx;
  13 + color: #D0D4DB;
  14 + font-size: 28rpx;
  15 + }
  16 +}
  17 +// 导航栏项样式
  18 +.inline-item {
  19 + display: inline-block
  20 +}
  21 +// 导航栏项-启用状态
  22 +.active {
  23 + color: #4297ED !important;
  24 +}
  25 +// 导航栏项-无状态
  26 +.none {
  27 + color: #666666;
  28 +}
... ...
  1 +<template>
  2 + <view class="title">
  3 + <scroll-view ref="sea" scroll-x style="width: 100%;white-space: nowrap;">
  4 + <!-- 全部 -->
  5 + <view class="inline-item" @click="clickItem(null,-1)">
  6 + <text v-if="!isre && treeStack.length == 0" class="none">全部</text>
  7 + <text v-else class="active">全部</text>
  8 + </view>
  9 + <!-- 全部 -->
  10 + <!-- 搜索结果 -->
  11 + <view v-if="isre" @click="clickItem(null,-2)"
  12 + :class="activeSearch?'active inline-item':' none inline-item'">
  13 + <i class="iconfont icon-z043 iconclass" />
  14 + 搜索结果
  15 + </view>
  16 + <!-- 搜索结果 -->
  17 + <!-- 当前树的层级值 -->
  18 + <view v-for="(item,index) in treeStack" class="inline-item" :key="index">
  19 + <view class="inline-item" @click="clickItem(item,index)">
  20 + <i class="iconfont icon-z043 iconclass" />
  21 + <text v-if="index== treeStack.length-1" class="none inline-item">
  22 + {{item[slabel]}}
  23 + </text>
  24 + <text v-else class="active">
  25 + {{item[slabel]}}
  26 + </text>
  27 + </view>
  28 + </view>
  29 + <!-- 当前树的层级值 -->
  30 + </scroll-view>
  31 + </view>
  32 +</template>
  33 +
  34 +<script>
  35 + /**
  36 + * 无限级树-面包屑导航
  37 + * @description 无限级树的面包屑导航
  38 + * @property {String} slabel 显示的label值
  39 + * @return {Function} clickItem(item , index) 点击导航栏的索引
  40 + * @item 表示导航项对应的值
  41 + * @index 表示导航项的层级别索引
  42 + * @value -1 全部
  43 + * @value -2 表示层级
  44 + * @value 其他 (从最外层开始,依次0,1,2,3……)
  45 + * @return {Object} inF 导航条内部的方法
  46 + * @param {Function} isIre 设置是否搜索状态
  47 + * @param {Function} setTreeStack 设置导航树的值
  48 + * @param {Function} pushTreeStack 为导航树添加项
  49 + * @param {Function} clearTreeStack 清空导航树
  50 + */
  51 + // scrollLeft : 暂时
  52 + export default {
  53 + name: "luyj-tree-navigation",
  54 + props: {
  55 + // 显示的label值
  56 + slabel: {
  57 + type: String,
  58 + default: 'label'
  59 + },
  60 + },
  61 + data() {
  62 + return {
  63 + isre: false, // 是否进行了搜索(返回是否进行了搜索)
  64 + treeStack: [], // 当前搜索值
  65 + }
  66 + },
  67 + computed: {
  68 + // 是否可点击搜索结果
  69 + activeSearch: function() {
  70 + return this.treeStack.length > 0;
  71 + }
  72 + },
  73 + created: function() {
  74 + // 浅拷贝导航列表的每一个对象(为了不改变item值,也不复制过多的数据)
  75 + this.treeStack.forEach(item => {
  76 + var tempItem = Object.assign(item);
  77 + this.treeStack.push(tempItem);
  78 + });
  79 + var obj = {
  80 + setIsre: this.setIsre,
  81 + getIsre : this.getIsre,
  82 + setTreeStack: this.setTreeStack,
  83 + concatTreeStack : this.concatTreeStack,
  84 + pushTreeStack: this.pushTreeStack,
  85 + clearTreeStack: this.clearTreeStack,
  86 + getTreeStack : this.getTreeStack
  87 + };
  88 + this.$emit("inF", obj); // 导出的导航栏调用方法
  89 + },
  90 + methods: {
  91 + // ================================== 初始化时导出方法(用于外部调用内部结果) =========================================================
  92 + /** 设置isre值(是否搜索)
  93 + * @param {Boolean} isre 设置是否搜索
  94 + */
  95 + setIsre: function(isre) {
  96 + this.isre = isre;
  97 + },
  98 + /**
  99 + * 获取isr值(获取是否搜索中)
  100 + */
  101 + getIsre: function(){
  102 + return this.isre;
  103 + },
  104 + /** 设置导航树
  105 + * @param {Array} treeStack 导航树
  106 + */
  107 + setTreeStack: function(treeStack) {
  108 + this.treeStack = treeStack;
  109 + },
  110 + /** 拼接导航树
  111 + * @param {Object} treeStack 导航树
  112 + */
  113 + concatTreeStack : function(treeStack){
  114 + this.treeStack = this.treeStack.concat(treeStack);
  115 + },
  116 + /** 为导航树添加项
  117 + * @param {Object} item 待添加的对象
  118 + */
  119 + pushTreeStack: function(item) {
  120 + this.treeStack.push(item);
  121 + },
  122 + /**
  123 + * 获取当前导航条
  124 + */
  125 + getTreeStack : function(){
  126 + return this.treeStack;
  127 + },
  128 + /**
  129 + * 清空导航树
  130 + */
  131 + clearTreeStack: function() {
  132 + this.treeStack.splice(0);
  133 + },
  134 + // ================================== 监听事件 ===========================================================
  135 + /** 点击导航栏索引
  136 + * @param {Object} item 当前层的值
  137 + * @param {Number} index 索引值
  138 + */
  139 + clickItem(item, index) {
  140 + if (index == -1) {
  141 + // 点击全部
  142 + this.isre = false;
  143 + this.treeStack.splice(0);
  144 + } else if (index == -2) {
  145 + // 搜索结果
  146 + if (this.activeSearch) {
  147 + this.isre = true;
  148 + this.treeStack.splice(0);
  149 + }
  150 + } else {
  151 + // 点击某一层级树
  152 + this.isre = false;
  153 + if (this.treeStack.length - 1 > index) {
  154 + this.treeStack.splice(index + 1);
  155 + }
  156 + }
  157 + this.$emit("clickItem", item, index);
  158 + },
  159 + },
  160 + // ============================================================================================================
  161 + }
  162 +</script>
  163 +
  164 +<style lang="scss" scoped>
  165 + @import "luyj-tree-navigation.scss";
  166 + @import "icon.css";
  167 +</style>
... ...
  1 +@font-face {
  2 + font-family: "iconfont"; /* Project id 2009600 */
  3 + src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
  4 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
  5 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
  6 +}
  7 +
  8 +.iconfont {
  9 + font-family: "iconfont" !important;
  10 + font-size: 16px;
  11 + font-style: normal;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 +}
  15 +
  16 +/* 清除图标 */
  17 +.icon-clear:before{
  18 + content: '\e606';
  19 +}
  20 +
  21 +.icon-banxuanzhongshousuo1-shi:before {
  22 + content: "\e682";
  23 +}
  24 +
  25 +.icon-xuanzhong3:before {
  26 + content: "\e6bb";
  27 +}
  28 +
  29 +.icon-weixuanzhong2:before {
  30 + content: "\e62e";
  31 +}
  32 +
  33 +.icon-danxuanxuanzhong:before {
  34 + content: "\e631";
  35 +}
  36 +
  37 +.icon-xuanzhong4:before {
  38 + content: "\e63e";
  39 +}
  40 +
  41 +.icon-xuanzhong1:before {
  42 + content: "\e62d";
  43 +}
  44 +.icon-xuanzhong2:before {
  45 + content: "\e656";
  46 +}
  47 +
  48 +.icon-selected:before {
  49 + content: "\e615";
  50 +}
  51 +
  52 +.icon-weixuanzhong1:before {
  53 + content: "\e614";
  54 +}
  55 +
  56 +.icon-xingzhuang6kaobei3-copy-copy:before {
  57 + content: "\e613";
  58 +}
  59 +
  60 +.icon-radio-checked:before {
  61 + content: "\e63f";
  62 +}
  63 +
  64 +.icon-huifu:before {
  65 + content: "\e619";
  66 +}
  67 +
  68 +.icon-dizhi:before {
  69 + content: "\e64a";
  70 +}
  71 +
  72 +.icon-kuaijiecaidan:before {
  73 + content: "\e60a";
  74 +}
  75 +
  76 +.icon-z043:before {
  77 + content: "\e62f";
  78 +}
  79 +
  80 +.icon-guanbi:before {
  81 + content: "\e607";
  82 +}
  83 +
  84 +.icon-xuanze:before {
  85 + content: "\e623";
  86 +}
  87 +
  88 +.icon-caidanzhaolinggan:before {
  89 + content: "\e616";
  90 +}
  91 +
  92 +.icon-xitongshezhi:before {
  93 + content: "\e60c";
  94 +}
  95 +
  96 +.icon-xitongshezhi1:before {
  97 + content: "\e633";
  98 +}
  99 +
  100 +.icon-lunbo:before {
  101 + content: "\e692";
  102 +}
  103 +
  104 +.icon-shuping:before {
  105 + content: "\e659";
  106 +}
  107 +
  108 +.icon-tongzhi:before {
  109 + content: "\e641";
  110 +}
  111 +
  112 +.icon-pinglunguanlishezhi:before {
  113 + content: "\e6ac";
  114 +}
  115 +
  116 +.icon-icon:before {
  117 + content: "\e600";
  118 +}
  119 +
  120 +.icon-liuyanguanli:before {
  121 + content: "\e61d";
  122 +}
  123 +
  124 +.icon-xuanzhong:before {
  125 + content: "\e669";
  126 +}
  127 +
  128 +.icon--:before {
  129 + content: "\e622";
  130 +}
  131 +
  132 +.icon-tushu:before {
  133 + content: "\e604";
  134 +}
  135 +
  136 +.icon-huishouzhan:before {
  137 + content: "\e61c";
  138 +}
  139 +
  140 +.icon-yonghutouxiang:before {
  141 + content: "\e617";
  142 +}
  143 +
  144 +.icon-liebiao:before {
  145 + content: "\e630";
  146 +}
  147 +
  148 +.icon-fenlei:before {
  149 + content: "\e621";
  150 +}
  151 +
  152 +.icon-tushu1:before {
  153 + content: "\e605";
  154 +}
  155 +
  156 +.icon-tubiao-:before {
  157 + content: "\e620";
  158 +}
  159 +
  160 +.icon-weixuanze:before {
  161 + content: "\e624";
  162 +}
  163 +
  164 +.icon-tushujieyue:before {
  165 + content: "\e690";
  166 +}
  167 +
  168 +.icon-lunbo1:before {
  169 + content: "\e6c5";
  170 +}
  171 +
  172 +.icon-shanchu:before {
  173 + content: "\e67b";
  174 +}
  175 +
  176 +.icon-lunbo2:before {
  177 + content: "\e61e";
  178 +}
  179 +
  180 +.icon-huaban:before {
  181 + content: "\e663";
  182 +}
  183 +
  184 +.icon-kehuan:before {
  185 + content: "\e608";
  186 +}
  187 +
  188 +.icon-icon02:before {
  189 + content: "\e601";
  190 +}
  191 +
  192 +.icon-huishouzhan1:before {
  193 + content: "\e612";
  194 +}
  195 +
  196 +.icon-huishouzhan2:before {
  197 + content: "\e63d";
  198 +}
  199 +
  200 +.icon-sousuo:before {
  201 + content: "\e62c";
  202 +}
  203 +
  204 +.icon-xingzhuang:before {
  205 + content: "\e625";
  206 +}
  207 +
  208 +.icon-lunbobankuai:before {
  209 + content: "\e61f";
  210 +}
  211 +
  212 +.icon-shangchuan:before {
  213 + content: "\e602";
  214 +}
  215 +
  216 +.icon-yonghu:before {
  217 + content: "\e761";
  218 +}
  219 +
  220 +.icon-tongzhi1:before {
  221 + content: "\e603";
  222 +}
  223 +
  224 +.icon-jingsong:before {
  225 + content: "\e65c";
  226 +}
  227 +
  228 +.icon-fenlei1:before {
  229 + content: "\e6c6";
  230 +}
  231 +
  232 +.icon-xieshupingicon:before {
  233 + content: "\e72d";
  234 +}
  235 +
  236 +.icon-liuyan:before {
  237 + content: "\e626";
  238 +}
  239 +
  240 +.icon-weixuanzhong:before {
  241 + content: "\e627";
  242 +}
  243 +
  244 +.icon-youxiang:before {
  245 + content: "\e646";
  246 +}
  247 +
  248 +.icon-lunboguanggao:before {
  249 + content: "\e6b3";
  250 +}
  251 +
  252 +.icon-xuanze1:before {
  253 + content: "\e60d";
  254 +}
  255 +
  256 +.icon-chushaixuanxiang:before {
  257 + content: "\e606";
  258 +}
  259 +
  260 +.icon-liuyanguanli1:before {
  261 + content: "\e61a";
  262 +}
  263 +
  264 +.icon-shanchu1:before {
  265 + content: "\e609";
  266 +}
  267 +
  268 +.icon-huishouzhan3:before {
  269 + content: "\e642";
  270 +}
  271 +
  272 +.icon-shangchuan1:before {
  273 + content: "\e823";
  274 +}
  275 +
  276 +.icon-huishouzhan4:before {
  277 + content: "\e61b";
  278 +}
  279 +
  280 +.icon-chuangzuo:before {
  281 + content: "\e8ad";
  282 +}
  283 +
  284 +.icon-dianzan:before {
  285 + content: "\e8ae";
  286 +}
  287 +
  288 +.icon-paihangbang:before {
  289 + content: "\e8b3";
  290 +}
  291 +
  292 +.icon-shouye:before {
  293 + content: "\e8b9";
  294 +}
  295 +
  296 +.icon-shoucang:before {
  297 + content: "\e8c6";
  298 +}
  299 +
  300 +.icon-addApp:before {
  301 + content: "\e60b";
  302 +}
  303 +
  304 +.icon-huishouzhan5:before {
  305 + content: "\e63a";
  306 +}
  307 +
  308 +.icon-add1:before {
  309 + content: "\e60e";
  310 +}
  311 +
  312 +.icon-shoucang1:before {
  313 + content: "\e60f";
  314 +}
  315 +
  316 +.icon-canshutongji:before {
  317 + content: "\e618";
  318 +}
  319 +
  320 +.icon-rizhiguanli:before {
  321 + content: "\e628";
  322 +}
  323 +
  324 +.icon-shanchu2:before {
  325 + content: "\e629";
  326 +}
  327 +
  328 +.icon-xinzeng:before {
  329 + content: "\e62a";
  330 +}
  331 +
  332 +.icon-zhankailiebiao:before {
  333 + content: "\e62b";
  334 +}
  335 +
  336 +.icon-xiala-copy:before {
  337 + content: "\e610";
  338 +}
  339 +
  340 +.icon-shangla:before {
  341 + content: "\e64e";
  342 +}
  343 +
  344 +.icon-xianxingshezhi:before {
  345 + content: "\e611";
  346 +}
... ...
  1 +<template>
  2 + <view>
  3 + <view class='filterBox' :style="{'background-color' : backgroundColor}">
  4 + <view class='filter-input'
  5 + :style="{'background-color' :inputBackgroundColor ,'border-radius':radius + 'rpx'}">
  6 + <!-- 左侧搜索图标 -->
  7 + <text :style="{'color':iconColor}" class="iconfont icon-sousuo filterImg"></text>
  8 + <!-- 输入框内容 -->
  9 + <input class="text" type='text' v-model="inputVal" confirm-type="搜索" :placeholder='placeholder'
  10 + :placeholder-style="placeholderStyle" :maxlength="maxlength" @input="handleInput"
  11 + @focus="handleFocus" @blur="handleBlur" @confirm='handleFllter'></input>
  12 + <!-- 清除按钮 -->
  13 + <view v-if="clearable" class="padding-left-sm" @click="clears">
  14 + <text :style="{'color':iconColor}" class="iconfont icon-clear filterImg"></text>
  15 + </view>
  16 + </view>
  17 + </view>
  18 + </view>
  19 +</template>
  20 +
  21 +<script>
  22 + /**
  23 + * 无限级树的搜索框组件
  24 + * @description 无限级树的搜索框组件
  25 + * @property {String} backgroundColor 背景色(默认#FFFFFF)
  26 + * @property {String} inputBackgroundColor 输入框背景色(默认#EEEFF0)
  27 + * @property {Number} radius 输入框圆角,单位rpx(默认40)
  28 + * @property {String} placeholder 输入框为空时占位符(默认'搜索')
  29 + * @property {String} placeholderStyle placehoder的样式
  30 + * @property {Number} maxlength 最大输入长度 ,设置为 -1 的时候不限制最大长度(默认值140)
  31 + * @property {String} iconColor 图标颜色(默认#B8B8B8)
  32 + * @property {Boolean} clearable 是否显示清除按钮 是否显示清除按钮(默认true)
  33 + * @event {Function()} input 输入框内容编号时触发
  34 + * @event {Function()} focus 输入框获得焦点时触发
  35 + * @event {Function()} blur 输入框失去焦点时触发
  36 + * @event {Function()} confirm 提交输入框内容是触发
  37 + * @event {Function()} clear 清空输入框内容时触发
  38 + */
  39 + export default {
  40 + name: 'luyj-tree-search',
  41 + props: {
  42 + // 背景色
  43 + backgroundColor: {
  44 + type: String,
  45 + default: '#FFFFFF'
  46 + },
  47 + // 输入框背景颜色
  48 + inputBackgroundColor: {
  49 + type: String,
  50 + default: '#EEEFF0'
  51 + },
  52 + // 输入框圆角
  53 + radius: {
  54 + type: Number,
  55 + default: 40
  56 + },
  57 + // 输入框为空时占位符
  58 + placeholder: {
  59 + type: String,
  60 + default: '搜索'
  61 + },
  62 + // placeholder的样式
  63 + placeholderStyle: {
  64 + type: String,
  65 + default: ''
  66 + },
  67 + // 最大输入长度 ,设置为 -1 的时候不限制最大长度
  68 + maxlength: {
  69 + type: Number,
  70 + default: 140
  71 + },
  72 + // 图标的颜色
  73 + iconColor: {
  74 + type: String,
  75 + default: '#B8B8B8'
  76 + },
  77 + // 是否显示清除按钮
  78 + clearable: {
  79 + type: Boolean,
  80 + default: true
  81 + }
  82 + },
  83 + data() {
  84 + return {
  85 + inputVal: "", // 输入内容
  86 + };
  87 + },
  88 + components: {
  89 + test: function() {
  90 + return 120;
  91 + }
  92 + },
  93 + methods: {
  94 + /** 输入框变化时方法
  95 + * @param {Object} e
  96 + */
  97 + handleInput: function(e) {
  98 + this.$emit("input", e)
  99 + },
  100 + /** 输入框聚焦时触发
  101 + * @param {Object} e
  102 + */
  103 + handleFocus: function(e) {
  104 + this.$emit("focus", e)
  105 + },
  106 + /** 输入框失去焦点时触发
  107 + * @param {Object} e
  108 + */
  109 + handleBlur: function(e) {
  110 + this.$emit("blur", e)
  111 + },
  112 + /** 提交内容时触发
  113 + * @param {Object} e
  114 + */
  115 + handleFllter: function(e) {
  116 + this.$emit("confirm", e)
  117 + },
  118 + /**
  119 + * 清空输入框内容
  120 + */
  121 + clears: function() {
  122 + this.inputVal = "";
  123 + this.$emit("clear", this.inputVal)
  124 + }
  125 + },
  126 + }
  127 +</script>
  128 +
  129 +<style lang="scss" scoped>
  130 + .filterBox {
  131 + padding: 15rpx 32rpx;
  132 +
  133 + .filter-input {
  134 + height: 80rpx;
  135 + display: flex;
  136 + align-items: center;
  137 + padding-left: 40rpx;
  138 +
  139 + .filterImg {
  140 + width: 32rpx;
  141 + height: 32rpx;
  142 + margin-right: 20rpx;
  143 + margin-bottom: 5rpx;
  144 + }
  145 +
  146 + .filterImgs {
  147 + width: 32rpx;
  148 + height: 32rpx;
  149 + }
  150 +
  151 + .text {
  152 + width: 100%;
  153 + font-size: 32rpx;
  154 + color: #000;
  155 + }
  156 + }
  157 + }
  158 +
  159 + // 添加左侧padding(用于扩大图标范围)
  160 + .padding-left-sm {
  161 + padding-left: 20rpx;
  162 + }
  163 +
  164 + @import url("icon.css");
  165 +</style>
... ...
  1 +@font-face {
  2 + font-family: "iconfont"; /* Project id 2009600 */
  3 + src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
  4 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
  5 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
  6 +}
  7 +
  8 +.iconfont {
  9 + font-family: "iconfont" !important;
  10 + font-size: 16px;
  11 + font-style: normal;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 +}
  15 +
  16 +.icon-banxuanzhongshousuo1-shi:before {
  17 + content: "\e682";
  18 +}
  19 +
  20 +.icon-xuanzhong3:before {
  21 + content: "\e6bb";
  22 +}
  23 +
  24 +.icon-weixuanzhong2:before {
  25 + content: "\e62e";
  26 +}
  27 +
  28 +.icon-danxuanxuanzhong:before {
  29 + content: "\e631";
  30 +}
  31 +
  32 +.icon-xuanzhong4:before {
  33 + content: "\e63e";
  34 +}
  35 +
  36 +.icon-xuanzhong1:before {
  37 + content: "\e62d";
  38 +}
  39 +
  40 +.icon-xuanzhong2:before {
  41 + content: "\e656";
  42 +}
  43 +
  44 +.icon-selected:before {
  45 + content: "\e615";
  46 +}
  47 +
  48 +.icon-weixuanzhong1:before {
  49 + content: "\e614";
  50 +}
  51 +
  52 +.icon-xingzhuang6kaobei3-copy-copy:before {
  53 + content: "\e613";
  54 +}
  55 +
  56 +.icon-radio-checked:before {
  57 + content: "\e63f";
  58 +}
  59 +
  60 +.icon-huifu:before {
  61 + content: "\e619";
  62 +}
  63 +
  64 +.icon-dizhi:before {
  65 + content: "\e64a";
  66 +}
  67 +
  68 +.icon-kuaijiecaidan:before {
  69 + content: "\e60a";
  70 +}
  71 +
  72 +.icon-z043:before {
  73 + content: "\e62f";
  74 +}
  75 +
  76 +.icon-guanbi:before {
  77 + content: "\e607";
  78 +}
  79 +
  80 +.icon-xuanze:before {
  81 + content: "\e623";
  82 +}
  83 +
  84 +.icon-caidanzhaolinggan:before {
  85 + content: "\e616";
  86 +}
  87 +
  88 +.icon-xitongshezhi:before {
  89 + content: "\e60c";
  90 +}
  91 +
  92 +.icon-xitongshezhi1:before {
  93 + content: "\e633";
  94 +}
  95 +
  96 +.icon-lunbo:before {
  97 + content: "\e692";
  98 +}
  99 +
  100 +.icon-shuping:before {
  101 + content: "\e659";
  102 +}
  103 +
  104 +.icon-tongzhi:before {
  105 + content: "\e641";
  106 +}
  107 +
  108 +.icon-pinglunguanlishezhi:before {
  109 + content: "\e6ac";
  110 +}
  111 +
  112 +.icon-icon:before {
  113 + content: "\e600";
  114 +}
  115 +
  116 +.icon-liuyanguanli:before {
  117 + content: "\e61d";
  118 +}
  119 +
  120 +.icon-xuanzhong:before {
  121 + content: "\e669";
  122 +}
  123 +
  124 +.icon--:before {
  125 + content: "\e622";
  126 +}
  127 +
  128 +.icon-tushu:before {
  129 + content: "\e604";
  130 +}
  131 +
  132 +.icon-huishouzhan:before {
  133 + content: "\e61c";
  134 +}
  135 +
  136 +.icon-yonghutouxiang:before {
  137 + content: "\e617";
  138 +}
  139 +
  140 +.icon-liebiao:before {
  141 + content: "\e630";
  142 +}
  143 +
  144 +.icon-fenlei:before {
  145 + content: "\e621";
  146 +}
  147 +
  148 +.icon-tushu1:before {
  149 + content: "\e605";
  150 +}
  151 +
  152 +.icon-tubiao-:before {
  153 + content: "\e620";
  154 +}
  155 +
  156 +.icon-weixuanze:before {
  157 + content: "\e624";
  158 +}
  159 +
  160 +.icon-tushujieyue:before {
  161 + content: "\e690";
  162 +}
  163 +
  164 +.icon-lunbo1:before {
  165 + content: "\e6c5";
  166 +}
  167 +
  168 +.icon-shanchu:before {
  169 + content: "\e67b";
  170 +}
  171 +
  172 +.icon-lunbo2:before {
  173 + content: "\e61e";
  174 +}
  175 +
  176 +.icon-huaban:before {
  177 + content: "\e663";
  178 +}
  179 +
  180 +.icon-kehuan:before {
  181 + content: "\e608";
  182 +}
  183 +
  184 +.icon-icon02:before {
  185 + content: "\e601";
  186 +}
  187 +
  188 +.icon-huishouzhan1:before {
  189 + content: "\e612";
  190 +}
  191 +
  192 +.icon-huishouzhan2:before {
  193 + content: "\e63d";
  194 +}
  195 +
  196 +.icon-sousuo:before {
  197 + content: "\e62c";
  198 +}
  199 +
  200 +.icon-xingzhuang:before {
  201 + content: "\e625";
  202 +}
  203 +
  204 +.icon-lunbobankuai:before {
  205 + content: "\e61f";
  206 +}
  207 +
  208 +.icon-shangchuan:before {
  209 + content: "\e602";
  210 +}
  211 +
  212 +.icon-yonghu:before {
  213 + content: "\e761";
  214 +}
  215 +
  216 +.icon-tongzhi1:before {
  217 + content: "\e603";
  218 +}
  219 +
  220 +.icon-jingsong:before {
  221 + content: "\e65c";
  222 +}
  223 +
  224 +.icon-fenlei1:before {
  225 + content: "\e6c6";
  226 +}
  227 +
  228 +.icon-xieshupingicon:before {
  229 + content: "\e72d";
  230 +}
  231 +
  232 +.icon-liuyan:before {
  233 + content: "\e626";
  234 +}
  235 +
  236 +.icon-weixuanzhong:before {
  237 + content: "\e627";
  238 +}
  239 +
  240 +.icon-youxiang:before {
  241 + content: "\e646";
  242 +}
  243 +
  244 +.icon-lunboguanggao:before {
  245 + content: "\e6b3";
  246 +}
  247 +
  248 +.icon-xuanze1:before {
  249 + content: "\e60d";
  250 +}
  251 +
  252 +.icon-chushaixuanxiang:before {
  253 + content: "\e606";
  254 +}
  255 +
  256 +.icon-liuyanguanli1:before {
  257 + content: "\e61a";
  258 +}
  259 +
  260 +.icon-shanchu1:before {
  261 + content: "\e609";
  262 +}
  263 +
  264 +.icon-huishouzhan3:before {
  265 + content: "\e642";
  266 +}
  267 +
  268 +.icon-shangchuan1:before {
  269 + content: "\e823";
  270 +}
  271 +
  272 +.icon-huishouzhan4:before {
  273 + content: "\e61b";
  274 +}
  275 +
  276 +.icon-chuangzuo:before {
  277 + content: "\e8ad";
  278 +}
  279 +
  280 +.icon-dianzan:before {
  281 + content: "\e8ae";
  282 +}
  283 +
  284 +.icon-paihangbang:before {
  285 + content: "\e8b3";
  286 +}
  287 +
  288 +.icon-shouye:before {
  289 + content: "\e8b9";
  290 +}
  291 +
  292 +.icon-shoucang:before {
  293 + content: "\e8c6";
  294 +}
  295 +
  296 +.icon-addApp:before {
  297 + content: "\e60b";
  298 +}
  299 +
  300 +.icon-huishouzhan5:before {
  301 + content: "\e63a";
  302 +}
  303 +
  304 +.icon-add1:before {
  305 + content: "\e60e";
  306 +}
  307 +
  308 +.icon-shoucang1:before {
  309 + content: "\e60f";
  310 +}
  311 +
  312 +.icon-canshutongji:before {
  313 + content: "\e618";
  314 +}
  315 +
  316 +.icon-rizhiguanli:before {
  317 + content: "\e628";
  318 +}
  319 +
  320 +.icon-shanchu2:before {
  321 + content: "\e629";
  322 +}
  323 +
  324 +.icon-xinzeng:before {
  325 + content: "\e62a";
  326 +}
  327 +
  328 +.icon-zhankailiebiao:before {
  329 + content: "\e62b";
  330 +}
  331 +
  332 +.icon-xiala-copy:before {
  333 + content: "\e610";
  334 +}
  335 +
  336 +.icon-shangla:before {
  337 + content: "\e64e";
  338 +}
  339 +
  340 +.icon-xianxingshezhi:before {
  341 + content: "\e611";
  342 +}
... ...
  1 +.flex_between_center {
  2 + display: flex;
  3 + justify-content: space-between;
  4 + align-items: center;
  5 + }
  6 +
  7 + .checkbox {
  8 + position: relative;
  9 + height: 36rpx;
  10 + margin-left: 10rpx;
  11 + margin-right: 0px;
  12 + width: 36rpx;
  13 + .color {
  14 + color: #00aaff;
  15 + background-color: #00aaff;
  16 + }
  17 + .txt {
  18 + // font-size: 30rpx;
  19 + line-height: 36rpx;
  20 + width: 100%;
  21 + height: 100%;
  22 + display: flex;
  23 + }
  24 + }
  25 + .checkBorder {
  26 + border: 1px solid #ecdee4;
  27 + }
  28 + .header {
  29 + width: 100%;
  30 + position: fixed;
  31 + background-color: #fff;
  32 + z-index: 9999;
  33 + .title {
  34 + height: 90rpx;
  35 + padding: 0 32rpx;
  36 + line-height: 90rpx;
  37 + font-size: 30rpx;
  38 + background-color: #f5f5f5;
  39 + color: #606064;
  40 + .iconclass {
  41 + display: inline-block;
  42 + margin: 0 12rpx;
  43 + color: #D0D4DB;
  44 + font-size: 28rpx;
  45 + }
  46 + }
  47 + }
  48 + .container-list {
  49 + overflow-y: scroll;
  50 + overflow-x: hidden;
  51 + .common {
  52 + background-color: #fff;
  53 + border-bottom: 1rpx solid #f4f4f4;
  54 + padding-left: 10rpx;
  55 + .content {
  56 + display: flex;
  57 + align-items: center;
  58 + min-height: 60rpx;
  59 + width: 100%;
  60 + padding: 15rpx 0;
  61 + position: relative;
  62 + font-size: 32rpx;
  63 +
  64 + .right {
  65 + position: absolute;
  66 + right: 30rpx;
  67 + color: #babdc3;
  68 + font-size: 32rpx;
  69 + }
  70 + }
  71 + }
  72 + // item的数字样式
  73 + .word {
  74 + font-size: 30rpx;
  75 + color: #5b5757;
  76 + width: 500rpx;
  77 + word-break: break-all;
  78 + }
  79 + }
  80 + .active {
  81 + color: #4297ED !important;
  82 + }
  83 + .none {
  84 + color: #666666;
  85 + }
  86 + .icon-selected{
  87 + color: #0095F2!important;
  88 + font-size: 40rpx!important;
  89 + }
  90 + .icons{
  91 + color: #0095F2!important;
  92 + font-size: 40rpx!important;
  93 + }
  94 + .inline-item {
  95 + display: inline-block
  96 + }
  97 +
  98 + .content-item{
  99 + display: flex;
  100 + position: relative;
  101 + align-items: center;
  102 + }
  103 +
  104 + .box_sizing {
  105 + -webkit-box-sizing: border-box;
  106 + -moz-box-sizing: border-box;
  107 + box-sizing: border-box;
  108 + }
  109 +
  110 + .btn {
  111 + position: fixed;
  112 + bottom: 100rpx;
  113 + padding: 10px;
  114 + background-color: #fff;
  115 + width: 100%;
  116 +
  117 + .sureBtn {
  118 + background-color: #377DFF;
  119 + color: #fff;
  120 + border-radius: 48px;
  121 + width: 500rpx;
  122 + margin-left: 86rpx;
  123 + }
  124 + }
\ No newline at end of file
... ...
  1 +<template>
  2 + <view>
  3 + <!-- 搜索框 -->
  4 + <view class="header">
  5 + <!-- 搜索栏 -->
  6 + <luyj-tree-search v-if="searchIf" :backgroundColor="searchBackgroundColor"
  7 + :inputBackgroundColor="searchInputBackgroundColor" :radius="searchRadius" :iconColor="searchIconColor"
  8 + :placeholder="searchPlaceholder" :placeholderStyle="searchPlaceholderStyle" :maxlength="searchMaxlength"
  9 + :clearable="searchClearable" @confirm="confirmSearch"></luyj-tree-search>
  10 + <!-- 面包屑导航 -->
  11 + <luyj-tree-navigation :slabel="props.label" @inF="navigationInt" @clickItem="backTree">
  12 + </luyj-tree-navigation>
  13 + <!-- 面包屑导航 -->
  14 + </view>
  15 + <!-- 列表 -->
  16 + <view>
  17 + <view class="container-list" :style="{'padding-bottom' : isCheck ? '160rpx' : 0 , 'padding-top' :searchIf ? '200rpx' :'90rpx' }">
  18 + <luyj-tree-item v-for="(item , index) in tree" :key="index" :item="item" :isCheck="isCheck"
  19 + :checkActiveColor="checkActiveColor" :checkNoneColor="checkNoneColor" :multiple="props.multiple" :checked="isChecked(item)"
  20 + :nodes="props.nodes" :comparison="comparison" @clickItem="toChildren"
  21 + @change="checkbox($event , item , index)">
  22 + <template slot="body">
  23 + <slot v-bind:item="item" v-bind:slotObj="slotObj" >
  24 + <view class="word text-cut">{{ item[props.label] }}</view>
  25 + </slot>
  26 + </template>
  27 + </luyj-tree-item>
  28 + </view>
  29 + </view>
  30 +
  31 + <!-- 确定按钮 -->
  32 + <view v-if="isCheck" class="btn box_sizing">
  33 + <button class="sureBtn" type="primary" @click="backConfirm">确认</button>
  34 + </view>
  35 + </view>
  36 +</template>
  37 +
  38 +<script>
  39 + /**
  40 + * luyj-tree 无限树形结构树、支持搜索选择。
  41 + * @description 无限树形结构组件。支持搜索、选择(包括单选、多选)。面包屑类型导航。原插件地址:https://ext.dcloud.net.cn/plugin?id=2423。
  42 + * @tutorial url https://ext.dcloud.net.cn/plugin?name=luyj-tree
  43 + * @property {Boolean} searchIf 是否开启搜索 (默认值true)
  44 + * @property {String} searchBackgroundColor 搜索框背景色(默认#FFFFFF)
  45 + * @property {String} searchInputBackgroundColor 搜索框的输入框背景色(默认#EEEFF0)
  46 + * @property {Number} searchRadius 搜索框的圆角值,单位rpx(默认40)
  47 + * @property {String} searchPlaceholder 搜索框的内容物空时提示内容
  48 + * @property {String} searchPlaceholderStyle 搜索框的placehoder的样式
  49 + * @property {Number} searchMaxlength 搜索框的最大输入长度 ,设置为 -1 的时候不限制最大长度
  50 + * @property {String} searchIconColor 搜索框的图标颜色(默认#B8B8B8)
  51 + * @property {Boolean} searchClearable 搜索框是否显示清除按钮
  52 + * @property {Array} trees 传入的树形结构,每个对象必须包含唯一的id值(默认值【】)
  53 + * @property {Boolean} isCheck 是否开启选择操作(默认值false)
  54 + * @property {Object} slotObj 传入插槽的参数(因为插槽进行了循环,不能直接引用页面的参数,需要传递)
  55 + * @property {Array} checkList 选中列表
  56 + * @property {Boolean} parent 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)(默认值false)
  57 + * @property {Array} parentList 父级列表
  58 + * @property {String} checkActiveColor 选中时单选框的颜色 (默认#00AAFF)
  59 + * @property {String} checkNoneColor 未选中时单选框的颜色(默认#B8B8B8)
  60 + * @property {Object} props 参数配置。
  61 + * @property {String} id id列的属性名称
  62 + * @param {String} label 指定选项标签为选项对象的某个属性值(默认值:name)
  63 + * @param {String} children 指定选项的子选项为选项对象的某个属性名(默认值:children)
  64 + * @param {Boolean} multiple 值为true时为多选,为false时是单选(默认值true)
  65 + * @param {Boolean} checkStrictly(废弃) 需要在多选模式下才传该值,checkStrictly为false时,可让父子节点取消关联,选择任意一级选项。为true时关联子级,可以全选(默认值为false)
  66 + * @param {Boolean} nodes 在单选模式下,nodes为false时,可以选择任意一级选项,nodes为true时,只能选择叶子节点(默认值为true)
  67 + * @property {Boolean} stepReload 是否“分页加载”数据
  68 + * @property {Number} pageSize 分步加载生效时(当条数过大时,反应时间很长)
  69 + * @return {Function} clickItem 点击导航栏事件
  70 + * @value item 当前选中的item值
  71 + * @value realHasChildren 是否包含子级
  72 + * @event {Function()} change 改变选择值时的方法
  73 + * @event {Function()} sendValue 提交选择的方法
  74 + * @event {Function()} backTree 选中导航栏时,返回其他层
  75 + */
  76 + export default {
  77 + name: "luyj-tree",
  78 + props: {
  79 + // 是否开启搜索
  80 + searchIf: {
  81 + type: Boolean,
  82 + default: () => true
  83 + },
  84 + // 搜索框背景色
  85 + searchBackgroundColor: {
  86 + type: String,
  87 + default: '#FFFFFF'
  88 + },
  89 + // 搜索框的输入框内背景颜色
  90 + searchInputBackgroundColor: {
  91 + type: String,
  92 + default: '#EEEFF0'
  93 + },
  94 + // 搜索框的图标的颜色
  95 + searchIconColor: {
  96 + type: String,
  97 + default: '#B8B8B8'
  98 + },
  99 + // 搜索框的圆角值,单位rpx
  100 + searchRadius: {
  101 + type: Number,
  102 + default: 40
  103 + },
  104 + // 搜索框的提示placeholder内容
  105 + searchPlaceholder: {
  106 + type: String,
  107 + default: '搜索'
  108 + },
  109 + // 搜索框的placeholder的样式
  110 + searchPlaceholderStyle: {
  111 + type: String,
  112 + default: ''
  113 + },
  114 + // 搜索框最大输入长度 ,设置为 -1 的时候不限制最大长度
  115 + searchMaxlength: {
  116 + type: Number,
  117 + default: 140
  118 + },
  119 + // 搜索框是否显示清除按钮
  120 + searchClearable: {
  121 + type: Boolean,
  122 + default: true
  123 + },
  124 + // 传入的树形结构数据,每个对象必须包含唯一的id值
  125 + trees: {
  126 + type: Array,
  127 + default: () => {
  128 + return []
  129 + }
  130 + },
  131 + //是否开启选择操作,值为false时仅展示,无操作
  132 + isCheck: {
  133 + type: Boolean,
  134 + default: () => {
  135 + return false
  136 + }
  137 + },
  138 + // 传入插槽的其他参数
  139 + slotObj: {
  140 + type: Object,
  141 + default :() =>{
  142 + return null;
  143 + }
  144 + },
  145 + // 选中列表
  146 + checkList: {
  147 + type: Array,
  148 + default: () => []
  149 + },
  150 + // 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)
  151 + parent: {
  152 + type: Boolean,
  153 + default: () => {
  154 + return false
  155 + }
  156 + },
  157 + // 父级列表
  158 + parentList: {
  159 + type: Array,
  160 + default: () => []
  161 + },
  162 + // 选中时单选框的颜色
  163 + checkActiveColor: {
  164 + type: String,
  165 + default: '#00AAFF'
  166 + },
  167 + // 未选中时单选框的颜色
  168 + checkNoneColor: {
  169 + type: String,
  170 + default: '#B8B8B8'
  171 + },
  172 + // 树的属性参数
  173 + props: {
  174 + type: Object,
  175 + default: () => {
  176 + return {
  177 + id: 'id',
  178 + label: 'name',
  179 + children: 'children',
  180 + multiple: false,
  181 + checkStrictly: false, //不关联
  182 + nodes: false, // nodes为false时,可以选择任意一级选项;nodes为true时只能选择叶子节点
  183 + }
  184 + }
  185 + },
  186 + /**
  187 + * 是否懒加载树的值
  188 + */
  189 + stepReload : {
  190 + type:Boolean,
  191 + default:false
  192 + },
  193 + // 每次循环加载的item的数据量
  194 + pageSize : {
  195 + type : Number,
  196 + default:50
  197 + }
  198 + },
  199 + data() {
  200 + return {
  201 + // 导航条
  202 + setIsre: null, // 导航条方法 - 设置是否搜索中方法
  203 + getIsre : null, // 获取是否搜索中
  204 + setTreeStack: null, // 导航条 - 设置导航
  205 + concatTreeStack: null, // 导航条 - 拼接当前导航对象
  206 + clearTreeStack: null, // 导航条- 清空导航条
  207 + getTreeStack: null, // 导航条 - 获取导航条
  208 +
  209 + itemsLoading : false, // item是否在循环渲染中
  210 + itemsStop : false, // 是否终止其他渲染
  211 + tree: [], // 默认数组
  212 + newNum: 0,
  213 + oldNum: 0,
  214 + allData: this.trees,
  215 + parent_data: this.parentList || [], //选择父辈
  216 + searchResult: [],
  217 + newCheckList: this.checkList,
  218 + nodePathArray: [], // 当前展示的路径
  219 + // item名称对照表
  220 + comparison: {
  221 + value: this.props.id ? this.props.id : 'id', // 选中值名称
  222 + label: this.props.label ? this.props.label : 'name', // 显示名称
  223 + children: this.props.children ? this.props.children : 'children', // 子集名称
  224 + }
  225 + }
  226 + },
  227 + watch: {
  228 + // 监听数据值的变化
  229 + trees: function(val, oldval) {
  230 + if (val != oldval) {
  231 + var tree_stack = this.getTreeStack();
  232 + this.allData = val; // 重新加载所有树
  233 + // 重新加载当前树
  234 + if(!Array.isArray(tree_stack)){
  235 + this.loadTree(val);
  236 + return;
  237 + }
  238 + var length = tree_stack.length;
  239 + if( length === 0){
  240 + if(typeof(this.getIsre) === "function"){
  241 + if(this.getIsre()){
  242 + return;
  243 + }
  244 + }
  245 + this.loadTree(val);
  246 + }else{
  247 + let tempArray = val; // 存储当前值
  248 + let children = this.props.children;
  249 + for(var i = 0 ; i < length ; i ++){
  250 + var tempObject = tempArray.find(item=>{
  251 + return tree_stack[i].Value == item.Value;
  252 + });
  253 + if(Boolean(tempObject)){
  254 + tempArray = tempObject[children];
  255 + }else{
  256 + // 跳转到全部
  257 + break;
  258 + }
  259 + if(i == length -1){
  260 + this.loadTree(tempArray);
  261 + }
  262 + }
  263 + }
  264 + }
  265 + },
  266 + // 树的属性对照参数
  267 + props: {
  268 + handler: function(val) {
  269 + this.comparison.value = this.props.id ? this.props.id : 'id';
  270 + this.comparison.label = this.props.label ? this.props.label : 'name';
  271 + this.comparison.children = this.props.children ? this.props.children : [];
  272 + },
  273 + deep: true
  274 + },
  275 + checkList: function(val , oldVal){
  276 + if(val != oldVal){
  277 + this.newCheckList = JSON.parse(JSON.stringify(val))
  278 + return val;
  279 + }
  280 + }
  281 + },
  282 + created:function(){
  283 + this.loadTree(this.trees);
  284 + },
  285 + // 实例被挂载后调用
  286 + mounted() {
  287 + let id = this.props.id;
  288 + let children = this.props.children;
  289 + // 关联子级的验证,暂时不使用
  290 + // if (this.props.multiple && this.props.checkStrictly) {
  291 + // if (this.newCheckList.length != 0) {
  292 + // this.checkAllChoose();
  293 + // return;
  294 + // }
  295 + // for (let i = 0; i < this.tree.length; i++) {
  296 + // this.$set(this.tree[i], 'bx', 0)
  297 + // this.$set(this.tree[i], 'qx', 0)
  298 + // }
  299 + // }
  300 + // 初始化选中项
  301 + if (!this.props.multiple && this.newCheckList.length > 0) {
  302 + this.getNodeRoute(this.allData, this.newCheckList[0][id]);
  303 + let arr = this.nodePathArray.reverse();
  304 + if (arr.length == 0) {
  305 + return;
  306 + }
  307 +
  308 + this.concatTreeStack(arr); // 获取导航条的值
  309 + // 加载当前列对应的数据
  310 + var tree_stack = this.getTreeStack();
  311 + var data = Boolean(tree_stack[tree_stack.length -1][children]) ? tree_stack[tree_stack.length - 1][
  312 + children
  313 + ] : [];
  314 + this.loadTree(data);
  315 + }
  316 + },
  317 + methods: {
  318 + // ========================================== 添加方法 =====================================================================
  319 + /** 当前选项是否选中
  320 + * @param {Object} item
  321 + */
  322 + isChecked(item){
  323 + if(Array.isArray(this.newCheckList)){
  324 + let id = this.props.id;
  325 + let temp = this.newCheckList.find(chcked=>{
  326 + return chcked[id] == item.id;
  327 + });
  328 + return Boolean(temp);
  329 + }
  330 + return false;
  331 + },
  332 + // =========================================== 初始化方法 ===================================================================
  333 + /** 初始化导航条的方法
  334 + * @param {Object} e
  335 + */
  336 + navigationInt: function(e) {
  337 + this.setIsre = e.setIsre;
  338 + this.getIsre = e.getIsre;
  339 + this.concatTreeStack = e.concatTreeStack;
  340 + this.pushTreeStack = e.pushTreeStack;
  341 + this.clearTreeStack = e.clearTreeStack;
  342 + this.getTreeStack = e.getTreeStack;
  343 + },
  344 + // =========================================== 监听事件 =====================================================================
  345 + /** 选中当前的值
  346 + * @param {Object} e
  347 + * @param {Object} item 当前项
  348 + * @param {Object} index 低昂去索引
  349 + */
  350 + checkbox(e, item, index) {
  351 + var func = this.props.multiple ? this.checkboxChange : this.radioChange;
  352 + func(e,item ,index); // 执行选择操作
  353 + },
  354 + /**单选
  355 + * @param {Object} e 点击事件
  356 + * @param {Object} item 当前项的值
  357 + * @param {Object} index 索引
  358 + */
  359 + radioChange :function( e,item ,index){
  360 + var that = this;
  361 + if(e.detail.value){
  362 + // 选中当前对象
  363 + that.newCheckList = [];
  364 + that.newCheckList.push(that.tree[index]);
  365 + }else{
  366 + // 移除其他对象
  367 + var nIndex = that.newCheckList.indexOf(item);
  368 + that.newCheckList.splice(nIndex , 1);
  369 + }
  370 + that.$emit('change', that.newCheckList);
  371 + },
  372 + /**异步检查复选框值的改变
  373 + * @param {Object} item
  374 + * @param {Object} index
  375 + * @param {Object} bx
  376 + * @param {Object} qx
  377 + */
  378 + async checkboxChange (e,item, index, bx, qx) {
  379 + let that = this;
  380 + let findIdex = that.newCheckList.indexOf(item);
  381 + if(e.detail.value){
  382 + // 点击选中
  383 + if(findIdex == -1){
  384 + that.newCheckList.push(that.tree[index]);
  385 + }
  386 + }else{
  387 + // 点击不选
  388 + that.newCheckList.splice(findIdex , 1);
  389 + }
  390 + that.$emit('change', that.newCheckList);
  391 +
  392 + // if (findIdex > -1) { //反选
  393 + // if (that.props.checkStrictly) { //关联子级
  394 + // if (item[props.hasChilren]) { //用户
  395 + // that.newCheckList.splice(findIdex, 1)
  396 + // } else { //非用户,取消所有下一级
  397 + // if (Boolean(item[props.children])) {
  398 + // that.getIdBydelete(item[props.children]);
  399 + // }
  400 + // }
  401 + // } else {
  402 + // that.newCheckList.splice(findIdex, 1)
  403 + // }
  404 + // } else { //选中
  405 + // if (!item[this.props.hasChilren] && that.props.checkStrictly) { //选中下一级
  406 + // if (qx || bx) { //取消下级
  407 + // if (Boolean(item[props.children])) {
  408 + // await that.getIdBydelete(item[props.children]);
  409 + // }
  410 + // item.qx = 0;
  411 + // item.bx = 0;
  412 + // } else {
  413 + // item.qx = 1;
  414 + // item.bx = 0;
  415 + // if (Boolean(item[props.children])) {
  416 + // await that.chooseChild(item[props.children], item[this.props.id]);
  417 + // }
  418 + // }
  419 + // that.$emit('change', that.newCheckList);
  420 + // // that.$forceUpdate()
  421 + // return;
  422 + // }
  423 + // // if(item[this.props.hasChilren]&&this.props.checkStrictly) this.getNodeRoute(this.allData,item[this.props.id]);
  424 + // that.newCheckList.push({
  425 + // ...item
  426 + // });
  427 + // }
  428 + // that.$emit('change', that.newCheckList)
  429 + },
  430 + // 取消下一级的选中
  431 + getIdBydelete(arr) {
  432 + arr.forEach(e => {
  433 + if (true) {
  434 + for (var i = 0; i < this.newCheckList.length; i++) {
  435 + // 包含下一级
  436 + if (e[this.props.id] == this.newCheckList[i][this.props.id]) {
  437 + this.newCheckList.splice(i, 1)
  438 + break;
  439 + }
  440 + }
  441 + }
  442 + if (false) {
  443 + // 不包含下一级
  444 + if (Boolean(item[props.children])) {
  445 + this.getIdBydelete(e[props.children]);
  446 + }
  447 + }
  448 + })
  449 + },
  450 + // 关联下一级,选中
  451 + chooseChild(arr, pid) {
  452 + let that = this;
  453 + for (var i = 0, len = arr.length; i < len; i++) {
  454 + let item = arr[i];
  455 + if (true) {
  456 + // 包含下一级
  457 + that.newCheckList.push({
  458 + ...item,
  459 + tree_stackId: pid
  460 + })
  461 + }
  462 + if (false) {
  463 + // 不包含下一级
  464 + // !item[that.props.hasChilren]
  465 + if (Boolean(item[props.children])) {
  466 + this.chooseChild(item[props.children], item[this.props.id])
  467 + }
  468 + }
  469 + }
  470 + },
  471 +
  472 + /**
  473 + * @param {Array} tree 目标树
  474 + * @param {Object} targetId 为目标节点id
  475 + */
  476 + getNodeRoute(tree, targetId) {
  477 + let children = this.props.children;
  478 + let id = this.props.id;
  479 + for (let index = 0; index < tree.length; index++) {
  480 + if (Boolean(tree[index][children]) ) {
  481 + if (tree[index][children]) {
  482 + let endRecursiveLoop = this.getNodeRoute(tree[index][children], targetId)
  483 + if (endRecursiveLoop) {
  484 + this.nodePathArray.push(tree[index]);
  485 + return true;
  486 + }
  487 + }
  488 + }
  489 + if (tree[index][id] === targetId) {
  490 + return true;
  491 + }
  492 + }
  493 + },
  494 +
  495 + /**跳转到子级
  496 + * @param {Object} item 选中的项
  497 + * @param {Boolean} realHasChildren 是否包含子级
  498 + */
  499 + toChildren(item, realHasChildren) {
  500 + this.$emit("clickItem" , item , realHasChildren); // 点击导航栏事件
  501 + // 不包含子级,不执行任何操作
  502 + if (!realHasChildren) {
  503 + return;
  504 + }
  505 + // 点击跳转下一级
  506 + let id = this.props.id;
  507 + let children = this.props.children; // 子级名称
  508 +
  509 + // 将当前item加入到导航列表
  510 + if (item[children].length > 0) {
  511 + this.loadTree(item[children]);
  512 + this.pushTreeStack(item); // 添加导航
  513 + }
  514 + // 关联数据 - 暂时不使用
  515 + // if (this.props.checkStrictly) {
  516 + // this.checkAllChoose();
  517 + // }
  518 + },
  519 + /** 搜索提交方法
  520 + * @param {Object} e
  521 + */
  522 + confirmSearch(e) {
  523 + var val = e.detail.value;
  524 + this.searchResult = [];
  525 + // 查找
  526 + uni.showLoading({
  527 + title: '正在查找'
  528 + });
  529 + this.search(this.allData, val);
  530 + // 返回搜索结果
  531 + uni.hideLoading();
  532 + this.setIsre(true); // 设置导航条为搜索状态
  533 + this.clearTreeStack(); // 清空导航条
  534 + this.loadTree(this.searchResult);
  535 + },
  536 + /**搜索方法
  537 + * @param {Object} data 搜索数据
  538 + * @param {Object} keyword 搜索关键字
  539 + */
  540 + search(data, keyword) {
  541 + var that = this;
  542 + let children = that.props.children;
  543 + for (var i = 0, len = data.length; i < len; i++) {
  544 + // try-catch(try-catch) - 没有label列,跳过继续执行
  545 + try{
  546 + if (data[i][that.props.label].indexOf(keyword) >= 0) {
  547 + that.searchResult.push(data[i]);
  548 + }
  549 + if (Boolean(data[i][children])) {
  550 + if (data[i][children].length > 0) {
  551 + that.search(data[i][children], keyword);
  552 + }
  553 + }
  554 + }catch(e){
  555 + console.warn(e);
  556 + }
  557 +
  558 + }
  559 + },
  560 + /**
  561 + * 检查所有的选项
  562 + */
  563 + checkAllChoose() {
  564 + let o = false,
  565 + t = true;
  566 + this.tree.forEach((e, i) => {
  567 + if (true) {
  568 + // 包含下一级 !e[this.props.hasChilren]
  569 + e.qx = o;
  570 + e.bx = o;
  571 + let num2 = this.computAllNumber(e[props.children]);
  572 + // console.log(this.newNum,this.oldNum)
  573 + if (this.newNum != 0 && this.oldNum != 0) {
  574 + if (this.newNum == this.oldNum) {
  575 + e.qx = t;
  576 + e.bx = o;
  577 + } else {
  578 + e.qx = o;
  579 + e.bx = t;
  580 + }
  581 + }
  582 + if (this.newNum != 0 && this.oldNum == 0) {
  583 + this.$set(this.tree[i], 'bx', o);
  584 + this.$set(this.tree[i], 'qx', o);
  585 + }
  586 + // this.$forceUpdate()
  587 + this.newNum = 0
  588 + this.oldNum = 0
  589 + }
  590 + })
  591 + },
  592 +
  593 + // 选中所选值
  594 + computAllNumber(arr) {
  595 + console.log("选中所选值");
  596 + // for (let j = 0; j < arr.length; j++) {
  597 + // var e = arr[j];
  598 + // // if (arr[j][that.props.hasChilren]) {
  599 + // this.newNum++;
  600 + // // }
  601 + // this.checkSum(e.id)
  602 + // if (!e[that.props.hasChilren]) {
  603 + // this.computAllNumber(e[props.children])
  604 + // }
  605 + // }
  606 + },
  607 +
  608 + // 选中事件累计
  609 + checkSum(id) {
  610 + for (let i = 0; i < this.newCheckList.length; i++) {
  611 + if (id == this.newCheckList[i].id) {
  612 + this.oldNum++;
  613 + break
  614 + }
  615 + }
  616 + },
  617 +
  618 + /** 返回到其他树层
  619 + * @param {Object} item 当前item值
  620 + * @param {Object} index 返回到其他索引
  621 + */
  622 + backTree(item, index) {
  623 + this.$emit("backTree", item, index);
  624 + let that = this;
  625 + if (index == -1) {
  626 + // 全部
  627 + that.loadTree(that.allData);
  628 + } else if (index == -2) {
  629 + // 搜索
  630 + that.loadTree(that.searchResult); // 搜索结果
  631 + } else {
  632 + // 其他层级
  633 + that.loadTree(item[that.props.children]); // tree的其他层级
  634 + }
  635 + // 关联数据
  636 + // if (this.props.checkStrictly) {
  637 + // this.checkAllChoose();
  638 + // }
  639 + },
  640 + /**
  641 + * 点击确认按钮执行事件
  642 + */
  643 + backConfirm() {
  644 + this.$emit('sendValue', this.newCheckList, 'back')
  645 + },
  646 + // ======================================== 公共方法 ===============================================================
  647 + /**加载Tree值
  648 + * @param {Array} datas 待复制的数组
  649 + * @param {Number} start 起始位置
  650 + * @description 加载tree值。当数据量大时,子项加载时间很长。可以多次渲染加载
  651 + */
  652 + loadTree : function(datas , start = 0 ){
  653 + let that = this;
  654 + if(!this.stepReload){
  655 + // 不进行多次渲染加载
  656 + that.tree = datas;
  657 + }else{
  658 + // datas为null, 不进行渲染
  659 + if(!Array.isArray(datas)){
  660 + that.tree = datas;
  661 + return;
  662 + }else if(datas.length === 0){
  663 + that.tree = datas;
  664 + return;
  665 + }
  666 + // 进行多次渲染加载
  667 + if(start === 0){
  668 + // 终止其他渲染
  669 + if(that.itemsLoading){
  670 + that.itemsStop = true; //终止其他Item渲染
  671 + }
  672 + // 首次加载提醒
  673 + uni.showLoading();
  674 + that.tree = [];
  675 + that.itemsLoading = true;
  676 + }
  677 + var length = datas.length ;
  678 + var end = Math.min(start + that.pageSize , length);
  679 + var tempArray = datas.slice(start , end);
  680 + that.tree = that.tree.concat(tempArray);
  681 + that.$nextTick(function(){
  682 + if(start == 0){
  683 + uni.hideLoading();
  684 + that.itemsStop = false;
  685 + }
  686 + if(end < length && !that.itemsStop){
  687 + that.loadTree(datas, end);
  688 + }else{
  689 + that.itemsLoading = false;
  690 + }
  691 + });
  692 + }
  693 + },
  694 + // =================================================================================================================
  695 +
  696 + }
  697 + }
  698 +</script>
  699 +<style lang="scss" scoped>
  700 + @import "luyj-tree.scss";
  701 + @import "icon.css";
  702 +</style>
... ...
  1 +@font-face {
  2 + font-family: "iconfont"; /* Project id 2009600 */
  3 + src: url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff2?t=1620633089023') format('woff2'),
  4 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.woff?t=1620633089023') format('woff'),
  5 + url('https://at.alicdn.com/t/font_2009600_gpzp7pxtnw.ttf?t=1620633089023') format('truetype');
  6 +}
  7 +
  8 +.iconfont {
  9 + font-family: "iconfont" !important;
  10 + font-size: 16px;
  11 + font-style: normal;
  12 + -webkit-font-smoothing: antialiased;
  13 + -moz-osx-font-smoothing: grayscale;
  14 +}
  15 +
  16 +/* 清除图标 */
  17 +.icon-clear:before{
  18 + content: '\e606';
  19 +}
  20 +
  21 +.icon-banxuanzhongshousuo1-shi:before {
  22 + content: "\e682";
  23 +}
  24 +
  25 +.icon-xuanzhong3:before {
  26 + content: "\e6bb";
  27 +}
  28 +
  29 +.icon-weixuanzhong2:before {
  30 + content: "\e62e";
  31 +}
  32 +
  33 +.icon-danxuanxuanzhong:before {
  34 + content: "\e631";
  35 +}
  36 +
  37 +.icon-xuanzhong4:before {
  38 + content: "\e63e";
  39 +}
  40 +
  41 +.icon-xuanzhong1:before {
  42 + content: "\e62d";
  43 +}
  44 +.icon-xuanzhong2:before {
  45 + content: "\e656";
  46 +}
  47 +
  48 +.icon-selected:before {
  49 + content: "\e615";
  50 +}
  51 +
  52 +.icon-weixuanzhong1:before {
  53 + content: "\e614";
  54 +}
  55 +
  56 +.icon-xingzhuang6kaobei3-copy-copy:before {
  57 + content: "\e613";
  58 +}
  59 +
  60 +.icon-radio-checked:before {
  61 + content: "\e63f";
  62 +}
  63 +
  64 +.icon-huifu:before {
  65 + content: "\e619";
  66 +}
  67 +
  68 +.icon-dizhi:before {
  69 + content: "\e64a";
  70 +}
  71 +
  72 +.icon-kuaijiecaidan:before {
  73 + content: "\e60a";
  74 +}
  75 +
  76 +.icon-z043:before {
  77 + content: "\e62f";
  78 +}
  79 +
  80 +.icon-guanbi:before {
  81 + content: "\e607";
  82 +}
  83 +
  84 +.icon-xuanze:before {
  85 + content: "\e623";
  86 +}
  87 +
  88 +.icon-caidanzhaolinggan:before {
  89 + content: "\e616";
  90 +}
  91 +
  92 +.icon-xitongshezhi:before {
  93 + content: "\e60c";
  94 +}
  95 +
  96 +.icon-xitongshezhi1:before {
  97 + content: "\e633";
  98 +}
  99 +
  100 +.icon-lunbo:before {
  101 + content: "\e692";
  102 +}
  103 +
  104 +.icon-shuping:before {
  105 + content: "\e659";
  106 +}
  107 +
  108 +.icon-tongzhi:before {
  109 + content: "\e641";
  110 +}
  111 +
  112 +.icon-pinglunguanlishezhi:before {
  113 + content: "\e6ac";
  114 +}
  115 +
  116 +.icon-icon:before {
  117 + content: "\e600";
  118 +}
  119 +
  120 +.icon-liuyanguanli:before {
  121 + content: "\e61d";
  122 +}
  123 +
  124 +.icon-xuanzhong:before {
  125 + content: "\e669";
  126 +}
  127 +
  128 +.icon--:before {
  129 + content: "\e622";
  130 +}
  131 +
  132 +.icon-tushu:before {
  133 + content: "\e604";
  134 +}
  135 +
  136 +.icon-huishouzhan:before {
  137 + content: "\e61c";
  138 +}
  139 +
  140 +.icon-yonghutouxiang:before {
  141 + content: "\e617";
  142 +}
  143 +
  144 +.icon-liebiao:before {
  145 + content: "\e630";
  146 +}
  147 +
  148 +.icon-fenlei:before {
  149 + content: "\e621";
  150 +}
  151 +
  152 +.icon-tushu1:before {
  153 + content: "\e605";
  154 +}
  155 +
  156 +.icon-tubiao-:before {
  157 + content: "\e620";
  158 +}
  159 +
  160 +.icon-weixuanze:before {
  161 + content: "\e624";
  162 +}
  163 +
  164 +.icon-tushujieyue:before {
  165 + content: "\e690";
  166 +}
  167 +
  168 +.icon-lunbo1:before {
  169 + content: "\e6c5";
  170 +}
  171 +
  172 +.icon-shanchu:before {
  173 + content: "\e67b";
  174 +}
  175 +
  176 +.icon-lunbo2:before {
  177 + content: "\e61e";
  178 +}
  179 +
  180 +.icon-huaban:before {
  181 + content: "\e663";
  182 +}
  183 +
  184 +.icon-kehuan:before {
  185 + content: "\e608";
  186 +}
  187 +
  188 +.icon-icon02:before {
  189 + content: "\e601";
  190 +}
  191 +
  192 +.icon-huishouzhan1:before {
  193 + content: "\e612";
  194 +}
  195 +
  196 +.icon-huishouzhan2:before {
  197 + content: "\e63d";
  198 +}
  199 +
  200 +.icon-sousuo:before {
  201 + content: "\e62c";
  202 +}
  203 +
  204 +.icon-xingzhuang:before {
  205 + content: "\e625";
  206 +}
  207 +
  208 +.icon-lunbobankuai:before {
  209 + content: "\e61f";
  210 +}
  211 +
  212 +.icon-shangchuan:before {
  213 + content: "\e602";
  214 +}
  215 +
  216 +.icon-yonghu:before {
  217 + content: "\e761";
  218 +}
  219 +
  220 +.icon-tongzhi1:before {
  221 + content: "\e603";
  222 +}
  223 +
  224 +.icon-jingsong:before {
  225 + content: "\e65c";
  226 +}
  227 +
  228 +.icon-fenlei1:before {
  229 + content: "\e6c6";
  230 +}
  231 +
  232 +.icon-xieshupingicon:before {
  233 + content: "\e72d";
  234 +}
  235 +
  236 +.icon-liuyan:before {
  237 + content: "\e626";
  238 +}
  239 +
  240 +.icon-weixuanzhong:before {
  241 + content: "\e627";
  242 +}
  243 +
  244 +.icon-youxiang:before {
  245 + content: "\e646";
  246 +}
  247 +
  248 +.icon-lunboguanggao:before {
  249 + content: "\e6b3";
  250 +}
  251 +
  252 +.icon-xuanze1:before {
  253 + content: "\e60d";
  254 +}
  255 +
  256 +.icon-chushaixuanxiang:before {
  257 + content: "\e606";
  258 +}
  259 +
  260 +.icon-liuyanguanli1:before {
  261 + content: "\e61a";
  262 +}
  263 +
  264 +.icon-shanchu1:before {
  265 + content: "\e609";
  266 +}
  267 +
  268 +.icon-huishouzhan3:before {
  269 + content: "\e642";
  270 +}
  271 +
  272 +.icon-shangchuan1:before {
  273 + content: "\e823";
  274 +}
  275 +
  276 +.icon-huishouzhan4:before {
  277 + content: "\e61b";
  278 +}
  279 +
  280 +.icon-chuangzuo:before {
  281 + content: "\e8ad";
  282 +}
  283 +
  284 +.icon-dianzan:before {
  285 + content: "\e8ae";
  286 +}
  287 +
  288 +.icon-paihangbang:before {
  289 + content: "\e8b3";
  290 +}
  291 +
  292 +.icon-shouye:before {
  293 + content: "\e8b9";
  294 +}
  295 +
  296 +.icon-shoucang:before {
  297 + content: "\e8c6";
  298 +}
  299 +
  300 +.icon-addApp:before {
  301 + content: "\e60b";
  302 +}
  303 +
  304 +.icon-huishouzhan5:before {
  305 + content: "\e63a";
  306 +}
  307 +
  308 +.icon-add1:before {
  309 + content: "\e60e";
  310 +}
  311 +
  312 +.icon-shoucang1:before {
  313 + content: "\e60f";
  314 +}
  315 +
  316 +.icon-canshutongji:before {
  317 + content: "\e618";
  318 +}
  319 +
  320 +.icon-rizhiguanli:before {
  321 + content: "\e628";
  322 +}
  323 +
  324 +.icon-shanchu2:before {
  325 + content: "\e629";
  326 +}
  327 +
  328 +.icon-xinzeng:before {
  329 + content: "\e62a";
  330 +}
  331 +
  332 +.icon-zhankailiebiao:before {
  333 + content: "\e62b";
  334 +}
  335 +
  336 +.icon-xiala-copy:before {
  337 + content: "\e610";
  338 +}
  339 +
  340 +.icon-shangla:before {
  341 + content: "\e64e";
  342 +}
  343 +
  344 +.icon-xianxingshezhi:before {
  345 + content: "\e611";
  346 +}
... ...
  1 +{
  2 + "id": "luyj-tree",
  3 + "displayName": "luyj-tree 无限级树形结构。",
  4 + "version": "1.4.11",
  5 + "description": "无限极树形结构。支持搜索、面包屑导航、单项选择、多项选择。",
  6 + "keywords": [
  7 + "uni-ui",
  8 + "uniui",
  9 + "",
  10 + "tree",
  11 + ""
  12 +],
  13 + "repository": "https://github.com/luyanjie00436/luyj-tree-app",
  14 + "engines": {
  15 + "HBuilderX": "^3.1.0"
  16 + },
  17 + "dcloudext": {
  18 + "category": [
  19 + "前端组件",
  20 + "通用组件"
  21 + ],
  22 + "sale": {
  23 + "regular": {
  24 + "price": "0.00"
  25 + },
  26 + "sourcecode": {
  27 + "price": "0.00"
  28 + }
  29 + },
  30 + "contact": {
  31 + "qq": ""
  32 + },
  33 + "declaration": {
  34 + "ads": "无",
  35 + "data": "无",
  36 + "permissions": "无"
  37 + },
  38 + "npmurl": ""
  39 + },
  40 + "uni_modules": {
  41 + "dependencies": [],
  42 + "encrypt": [],
  43 + "platforms": {
  44 + "cloud": {
  45 + "tcb": "y",
  46 + "aliyun": "y"
  47 + },
  48 + "client": {
  49 + "App": {
  50 + "app-vue": "y",
  51 + "app-nvue": "y"
  52 + },
  53 + "H5-mobile": {
  54 + "Safari": "u",
  55 + "Android Browser": "u",
  56 + "微信浏览器(Android)": "u",
  57 + "QQ浏览器(Android)": "u"
  58 + },
  59 + "H5-pc": {
  60 + "Chrome": "y",
  61 + "IE": "u",
  62 + "Edge": "u",
  63 + "Firefox": "y",
  64 + "Safari": "u"
  65 + },
  66 + "小程序": {
  67 + "微信": {
  68 + "minVersion": "2.18.1"
  69 + },
  70 + "阿里": "u",
  71 + "百度": "u",
  72 + "字节跳动": "u",
  73 + "QQ": "u"
  74 + },
  75 + "快应用": {
  76 + "华为": "u",
  77 + "联盟": "u"
  78 + },
  79 + "Vue": {
  80 + "vue2": "y",
  81 + "vue3": "u"
  82 + }
  83 + }
  84 + }
  85 + }
  86 +}
\ No newline at end of file
... ...
  1 +# luyj-tree
  2 +> 代码块 `luyj-tree` 内包含`luyj-tree-search`、`luyj-tree-navigation`、`luyj-tree-item`
  3 +
  4 +## 说明
  5 +
  6 +* 本插件是基于[xiaolu-tree](https://ext.dcloud.net.cn/plugin?id=2423)进行了uni_modules模块化。并进行了一些修改。
  7 +* 本人暂时只在微信小程序端和H5 使用Chrome浏览器测试。更改了一些内容,有可能会有一些错误 或说明与实际不一致,介意者慎用。本人会适当的抽出业余时间,把它完善,毕竟有一定的下载量了,而且自己也需要学习,再次感谢原作者。
  8 +* 暂时,使用自定义插件渲染有问题,会出现``duplication is found under a single shadow root. The first one was accepted`` ,还未找到解决方案。
  9 +
  10 +### 安装方式
  11 +
  12 +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`
  13 +
  14 +### 基本用法
  15 +
  16 +``template`` 中使用组件
  17 +
  18 +```html
  19 +<!-- 基础用法 -->
  20 +<luyj-tree v-slot:default="{item}" :max="max" :trees="tree">
  21 + <!-- 内容插槽 -->
  22 + <view>
  23 + <view class="content-item">
  24 + <view class="word">{{item.name}}</view>
  25 + </view>
  26 + </view>
  27 +</luyj-tree>
  28 +```
  29 +
  30 +``` javascript
  31 +import dataList from '@/common/data.js'; // 引用数据
  32 +export default {
  33 + data() {
  34 + return {
  35 + tree: dataList,
  36 + max: 5,
  37 + }
  38 + },
  39 +}
  40 +```
  41 +### 功能说明
  42 +
  43 +1. 树形结构展示。
  44 +2. 包含搜索框。能够自定义搜索框的样式,能够直接搜索树形图、子文件的内容。
  45 +3. 包含面包屑导航。
  46 +4. 可以仅仅展示或选择树形的项内容。
  47 +5. 可以显示选择改变,或确认选择的方法。
  48 +6. 只需传checkList字段就可以回显默认选中。
  49 +7. 支持自定义显示内容的插件(slot)。
  50 +8. 支持懒加载。
  51 +
  52 +### 属性
  53 +
  54 +|属性名 |类型 |默认值 | 说明 |
  55 +|:-: |:-: |:-: | :-: |
  56 +|search-if |Boolean |true | 是否开启搜索 |
  57 +|search-background-color |String |#FFFFFF | 搜索框背景色 |
  58 +|search-input-background-color |String |#EEEFF0 | 搜索框的输入框背景色 |
  59 +|search-radius |Number |40 | 搜索框的圆角值,单位rpx(默认40) |
  60 +|search-placeholder |String |搜索 | 搜索框的内容物空时提示内容 |
  61 +|search-placeholder-style |String | | 搜索框的placehoder的样式 |
  62 +|search-maxlength |Number |140 | 搜索框的最大输入长度 ,设置为 -1 的时候不限制最大长度 |
  63 +|search-iconColor |String | | 搜索框的图标颜色 |
  64 +|search-clearable |Boolean |true | 搜索框是否显示清除按钮 |
  65 +|trees |Array |[] | trees 传入的树形结构,每个对象必须包含唯一的id值 |
  66 +|is-check |Boolean |false | 是否开启选择操作 |
  67 +|slot-obj |Object |null | 传入插槽的参数(自定义的slot中不能引用页面的参数,否则样式会出错)|
  68 +|check-list |Array |[] | 选中的列表 |
  69 +|parent |Boolean |false | 当子级全选时,是否选中父级数据(prop.checkStrictly为true时生效)。此参数占时失效。 |
  70 +|parent-list |Array |[] | 父级列表 |
  71 +|check-active-color |String |#00AAFF | 选中时单选框/复选框的颜色 |
  72 +|check-none-color |String |#B8B8B8 | 未选中时单选框/复选框的颜色 |
  73 +|props |Object |{id: 'id',label:'name',children:'children',hasChilren: 'user',multiple: false,checkStrictly: false ,nodes: false} | 参数配置,详细见下表。 |
  74 +|step-reload |Boolean |false | 是否懒加载数列 |
  75 +|page-size |Number |50 | 每次加载的条数,stepReload = true时生效 |
  76 +
  77 +#### props 参数说明
  78 +|参数 |类型 |默认值 | 说明 |
  79 +|:-: |:-: |:-: | :-: |
  80 +|id |String |id | id列的属性名 |
  81 +|label |String |name | 指定选项标签为选项对象的某个属性值 |
  82 +|children |String |children | 指定选项的子选项为选项对象的某个属性值 |
  83 +|multiple |Boolean |true | 值为true时为多选,为false时是单选 |
  84 +|checkStrictly |Boolean |false | 需要在多选模式下才传该值,checkStrictly为false时,可让父子节点取消关联,选择任意一级选项。为true时关联子级,可以全选(暂时不可用) |
  85 +|nodes |Boolean |true | 在单选模式下,nodes为false时,可以选择任意一级选项,nodes为true时,只能选择叶子节点 |
  86 +
  87 +### 事件
  88 +
  89 +|事件名 |说明 |返回值 |
  90 +|:-: |:-: |:-: |
  91 +|@clickItem |点击Item列事件 |(item : Object ,realHasChildren : Boolean) |
  92 +|@change |选项改变时触发事件 当前选中的值 |
  93 +|@sendValue |点击确认按钮时触发事件 | 参数(选中的项值) |
  94 +
  95 +``@clickItem``,当点击item列时有效。返回值说明如下:
  96 +
  97 +|返回值 |类型 | 说明 |
  98 +|:-: |:-: |:-: |
  99 +|item |Object | 当前选中的值 |
  100 +|realHasChildren |Boolean| 是否包含子级 |
  101 +
  102 +``@change`` ,``is-check``为```true```时,当选中的值改变时触发。返回值说明如下:
  103 +
  104 +|参数 |类型 | 说明 |
  105 +|:-: |:-: | :-: |
  106 +|e.detail.value |Boolean | 当前项是否选中 |
  107 +|item |Object | 当前的Item值 |
  108 +
  109 +# luyj-tree-search
  110 +
  111 +### 说明
  112 +
  113 +``luyj-tree-search`` 是 ``luyj-tree``内的组件,作为搜索框,可以单独引用。
  114 +
  115 +![Image text](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-c07243ab-98a3-4f90-9b4d-2fa60aba2ee9/ba6ace1d-4881-4373-8a8e-b90079d3e290.png)
  116 +
  117 +### 基本用法
  118 +###
  119 +``template`` 中使用组件
  120 +
  121 +``` html
  122 +<luyj-tree-search></luyj-tree-search>
  123 +```
  124 +
  125 +### 属性
  126 +
  127 +|属性名 |类型 |默认值 | 说明 |
  128 +|:-: |:-: |:-: | :-: |
  129 +|background-color |String |#FFFFFF | 背景色 |
  130 +|input-background-color |String |#EEEFF0 | 输入框背景色 |
  131 +|radius |Number |40 | 输入框圆角,单位rpx |
  132 +|icon-color |String |#B8B8B8 | 图标颜色 |
  133 +|placeholder |String |搜索 | 输入框为空时占位符 |
  134 +|placeholder-style |String | | placeholder的样式 |
  135 +|maxlength |Number |140 | 最大输入长度 ,设置为 -1 的时候不限制最大长度 |
  136 +
  137 +### 事件
  138 +
  139 +|事件名 |说明 |返回值 |
  140 +|:-: |:-: |:-: |
  141 +|@input |输入框内容变化时,触发事件 | event |
  142 +|@focus |输入框获得焦点时,触发事件 | event |
  143 +|@blur |输入框失去焦点时,触发事件 | event |
  144 +|@confirm |输入框内容提交时,触发事件 | event |
  145 +|@clear |清空输入框内容时,触发事件 | '' |
  146 +
  147 +# luyj-tree-navigation
  148 +
  149 +``luyj-tree-navigation`` 是 ``luyj-tree``内的组件,作为面包屑导航栏,可以单独引用。
  150 +
  151 +# luyj-tree-item
  152 +
  153 +``luyj-tree-item`` 是 ``luyj-tree``内的组件,是树的选择项。包含单选、多选的样式,可以单独引用。
  154 +
  155 +### 基础用法
  156 +
  157 +``template``中使用组件
  158 +
  159 +``` html
  160 +<!-- 普通使用 -->
  161 +<luyj-tree-item :item="item" :isCheck="ischecked" :multiple="multiple" :checked="ischecked" :comparison="comparison" @change="change" @clickItem="clickItem">
  162 +</luyj-tree-item>
  163 +<!-- 使用插件 -->
  164 +<luyj-tree-item :item="item" :isCheck="isCheck" :multiple="multiple" :checked="ischecked" :comparison="comparison" @change="change" @clickItem="clickItem">
  165 + <!-- 自定义插件内容 -->
  166 + <template slot="body" >
  167 + {{ item.label }}
  168 + </template>
  169 + <!-- 自定义插件内容 -->
  170 +</luyj-tree-item>
  171 +```
  172 +
  173 +对应的数据及方法如下:
  174 +
  175 +``` javascript
  176 +import dataItem from '../../common/item-data.js';
  177 +export default {
  178 + data() {
  179 + return {
  180 + item : dataItem, // 当前item值
  181 + isCheck : true, // 是否可选
  182 + ischecked : true, // 是否选中
  183 + multiple : false, // 是否多选
  184 + comparison :{
  185 + value : 'value', // 选中值
  186 + label : 'label', // 显示名称
  187 + children:'children', // 子级名称
  188 + },
  189 + test :124
  190 + }
  191 + },
  192 + onLoad:function(){
  193 + },
  194 + methods: {
  195 + // 修改change
  196 + change : function(e , item){
  197 + console.log("修改当前值=>" ,e , item);
  198 + },
  199 + // 点击当前项目
  200 + clickItem : function(item , hasChildren){
  201 + console.log("点击当前项目");
  202 + }
  203 + }
  204 +}
  205 +```
  206 +
  207 +### 属性
  208 +
  209 +|属性名 |类型 |默认值 | 说明 |
  210 +|:-: |:-: |:-: | :-: |
  211 +|item |Object |{} | 当前项的值 |
  212 +|is-check |Boolean |false |判断是否可选择,与multiple组合使用。判断显示类型为展示、单选、多选|
  213 +|multiple |Boolean |false |是否多选。当isCheck值为true时有效。multiple=false时为单选,multiple=true时多选|
  214 +|checked |Boolean |false |当前项是否选中状态|
  215 +|nodes |Boolean |false |是否只能选择叶子结点|
  216 +|check-active-color |String |#00AAFF |选中状态下,单选框/复选框的颜色|
  217 +|check-none-color |String |#B8B8B8 |未选中状态下,单选框/复选框的颜色|
  218 +|comparison |Object |{value : 'value',label : 'label',children:'children'}; |当前项的列名称。 |
  219 +
  220 +#### **comparison**的值
  221 +|参数 |类型 |默认值 | 说明 |
  222 +|:-: |:-: |:-: | :-: |
  223 +|value |String |value | value值的列名,即选中时单选按钮或复选按钮的值 |
  224 +|label |String |label | label值的列名,即当前item默认展示的名称 |
  225 +|children |String |children | children对的列名,即当前item的下一级 |
  226 +
  227 +### 事件
  228 +
  229 +|事件名 |说明 |返回值 |
  230 +|:-: |:-: |:-: |
  231 +|@change |单选框/复选框值改变时执行方法 |(e , item) |
  232 +|@clickItem |点击当前选项 |{item , hasChildren} |
  233 +
  234 +#### **change** 的参数说明
  235 +
  236 +|参数 |类型 | 说明 |
  237 +|:-: |:-: | :-: |
  238 +|e.detail.value |Boolean | 当前项是否选中 |
  239 +|item |Object | 当前的Item值 |
  240 +
  241 +#### **clickItem** 的参数说明
  242 +
  243 +|参数 |类型 | 说明 |
  244 +|:-: |:-: | :-: |
  245 +|item |Object | 当前的Item值 |
  246 +|hasChildren |Boolean | 是否包含子级,即children是否包含对象 |
  247 +
  248 +### 源码地址
  249 +
  250 +[代码csdn地址](https://codechina.csdn.net/qq_28624235/luyj-tree-app) <br>
  251 +[代码github地址](https://github.com/luyanjie00436/luyj-tree-app)
\ No newline at end of file
... ...