754 lines
22 KiB
Plaintext
754 lines
22 KiB
Plaintext
<script lang="ts">
|
|
import { PropType, toRaw } from "vue"
|
|
import { getUid } from "../../core/util/xCoreUtil.uts"
|
|
import { getDefaultColor } from "../../core/util/xCoreColorUtil.uts"
|
|
import { checkIsCssUnit, getUnit } from "../../core/util/xCoreUtil.uts"
|
|
import { xConfig } from "../../config/xConfig.uts"
|
|
import { CASCADER_ITEM_INFO,CASCADER_TREE_ITEM } from "../../interface.uts"
|
|
import { isParent, getTreeNodesPath, getTreeSelectedNum } from "./util.uts"
|
|
|
|
|
|
|
|
/**
|
|
* @name 极联器 xCascader
|
|
* @page /pages/index/cascader
|
|
* @category 表单组件
|
|
* @description 极联选择器,单选模式。
|
|
* @constant 平台兼容
|
|
* | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
| ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.44+ | 1.1.9 |
|
|
*/
|
|
export default {
|
|
data() {
|
|
return {
|
|
//当前的层级
|
|
activeId: "",
|
|
selectedsIds: [] as string[],
|
|
//当前的层级索引
|
|
selectedsIdsItem: [] as CASCADER_TREE_ITEM[],
|
|
menuBarList: [] as CASCADER_TREE_ITEM[],
|
|
activeIndex: [] as number[],
|
|
changshowpenl: "0",
|
|
showCchangshowpenl: true,
|
|
swiperIndex: 0,
|
|
_nowListSwiper:[] as CASCADER_TREE_ITEM[][],
|
|
isAndriod:(uni.getSystemInfoSync().platform == 'android') as boolean,
|
|
// 添加切换状态管理,防止闪烁
|
|
isTransitioning: false,
|
|
nextSwiperIndex: 0,
|
|
tid:20
|
|
}
|
|
},
|
|
emits: [
|
|
|
|
/**
|
|
* 选中触发时变化,只要路径变化了就会触发
|
|
* @param {String[]} ids - 当前id路径值
|
|
*/
|
|
'change',
|
|
/**
|
|
* 点击项目时触发
|
|
* @param {CASCADER_TREE_ITEM} item - 项目数据
|
|
* @param {number} parentIndex - 父index
|
|
* @param {number} childrenIndex - 当前子index
|
|
*/
|
|
'cellClick',
|
|
/**
|
|
* 最后一项时触发,或者选择本级时触发
|
|
* @param {String} id - 最后一级选中的值
|
|
* @param {String[]} ids - 完整的路径id值
|
|
*/
|
|
'confirm',
|
|
/**
|
|
* 等同v-model,或者选择本级时触发
|
|
* @param {String} id - 当前id
|
|
*/
|
|
'update:modelValue'
|
|
],
|
|
props: {
|
|
/**
|
|
* 宽,不可为auto。
|
|
*/
|
|
width: {
|
|
type: String,
|
|
default: "100%"
|
|
},
|
|
/**
|
|
* 高是必填,不可为auto。
|
|
*/
|
|
height: {
|
|
type: String,
|
|
default: "150"
|
|
},
|
|
|
|
/**
|
|
* 选项项目未选中的文字颜色
|
|
*/
|
|
itemTextColor: {
|
|
type: String,
|
|
default: "#333333"
|
|
},
|
|
/**
|
|
* 选项项目未选中的暗黑文字颜色,空值是取白色
|
|
*/
|
|
darkItemTextColor: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
/**
|
|
* 选项项目选中的文字颜色,空值取全局主题
|
|
*/
|
|
itemActiveColor: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
|
|
/**
|
|
* 内容区域背景颜色
|
|
*/
|
|
sliderContentBgColor: {
|
|
type: String,
|
|
default: "transparent"
|
|
},
|
|
/**
|
|
* 提供的数据结构
|
|
*/
|
|
list: {
|
|
type: Array as PropType<CASCADER_ITEM_INFO[]>,
|
|
default: () : CASCADER_ITEM_INFO[] => [] as CASCADER_ITEM_INFO[]
|
|
},
|
|
/**
|
|
* 当前选中项的id
|
|
*/
|
|
modelValue: {
|
|
type: String,
|
|
default: ""
|
|
},
|
|
/**
|
|
* 每级是否允许多选
|
|
* 暂不开放,如需多选请参考组件slider-tree。
|
|
*/
|
|
multiple: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* 项目文字大小
|
|
*/
|
|
fontSize: {
|
|
type: String,
|
|
default: "18"
|
|
},
|
|
/**
|
|
* 是否在有下级的项目上显示选择本级按钮.
|
|
* 当用户选中了本级时就同选择最后一项一样会触发confirm及同步vmodel值
|
|
*/
|
|
showCurrentBtn: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
},
|
|
computed: {
|
|
_showCurrentBtn() : boolean {
|
|
return this.showCurrentBtn
|
|
},
|
|
|
|
_width() : string {
|
|
return checkIsCssUnit(this.width, xConfig.unit);
|
|
},
|
|
_height() : string {
|
|
return checkIsCssUnit(this.height, xConfig.unit);
|
|
},
|
|
_fontSize() : string {
|
|
let fontSize = checkIsCssUnit(this.fontSize, xConfig.unit);
|
|
if (xConfig.fontScale == 1) return fontSize;
|
|
let sizeNumber = parseInt(fontSize)
|
|
if (isNaN(sizeNumber)) {
|
|
sizeNumber = 16
|
|
}
|
|
return (sizeNumber * xConfig.fontScale).toString() + getUnit(fontSize)
|
|
},
|
|
|
|
_itemTextColor() : string {
|
|
let color = this.itemTextColor;
|
|
if (xConfig.dark == 'dark') {
|
|
color = this.darkItemTextColor != "" ? this.darkItemTextColor : "#ffffff"
|
|
}
|
|
return getDefaultColor(color);
|
|
},
|
|
_itemActiveColor() : string {
|
|
return this.itemActiveColor != "" ? getDefaultColor(this.itemActiveColor) : getDefaultColor(xConfig.color);
|
|
},
|
|
|
|
_sliderContentBgColor() : string {
|
|
return getDefaultColor(this.sliderContentBgColor);
|
|
},
|
|
_multiple() : boolean {
|
|
return this.multiple
|
|
},
|
|
_list() : CASCADER_TREE_ITEM[] {
|
|
let list = this.list as CASCADER_ITEM_INFO[];
|
|
function addOptionalFieldsToTree(tree : CASCADER_ITEM_INFO[]) : void {
|
|
for (let i = 0; i < tree.length; i++) {
|
|
const node = tree[i];
|
|
node.disabled = node.disabled == null ? false : node.disabled! as boolean;
|
|
node.selected = node.selected == null ? [] : node.selected! as string[];
|
|
node.children = node.children == null ? ([] as CASCADER_ITEM_INFO[]) : node.children! as CASCADER_ITEM_INFO[];
|
|
if ((node.children!).length > 0) {
|
|
addOptionalFieldsToTree(node.children! as CASCADER_ITEM_INFO[]);
|
|
}
|
|
}
|
|
}
|
|
function addOptionalFieldsToTreeClolone(tree : CASCADER_ITEM_INFO[]) : CASCADER_TREE_ITEM[] {
|
|
let nowlist = [] as CASCADER_TREE_ITEM[]
|
|
for (let i = 0; i < tree.length; i++) {
|
|
const node = tree[i];
|
|
node.disabled = node.disabled == null ? false : node.disabled! as boolean;
|
|
node.selected = node.selected == null ? [] : node.selected! as string[];
|
|
node.children = node.children == null ? ([] as CASCADER_ITEM_INFO[]) : node.children! as CASCADER_ITEM_INFO[];
|
|
let item = {
|
|
id: node.id,
|
|
title: node.title,
|
|
disabled: node.disabled!,
|
|
selected: node.selected!,
|
|
children: [] as CASCADER_TREE_ITEM[],
|
|
checked: false
|
|
} as CASCADER_TREE_ITEM
|
|
if ((node.children!).length > 0) {
|
|
item.children = addOptionalFieldsToTreeClolone(node.children! as CASCADER_ITEM_INFO[]);
|
|
}
|
|
nowlist.push(item)
|
|
}
|
|
|
|
return nowlist
|
|
}
|
|
|
|
addOptionalFieldsToTree(list as CASCADER_ITEM_INFO[]);
|
|
|
|
return addOptionalFieldsToTreeClolone(list)
|
|
},
|
|
_borderColor() : string {
|
|
if (xConfig.dark == 'dark') return xConfig.borderDarkColor
|
|
return '#f5f5f5'
|
|
},
|
|
_nextChildren() : CASCADER_TREE_ITEM[] {
|
|
if (this.menuBarList.length == 0) return this._list
|
|
let lastChildren = this.menuBarList[this.menuBarList.length -1]
|
|
if(lastChildren.children.length==0) return [] as CASCADER_TREE_ITEM[];
|
|
return lastChildren.children
|
|
},
|
|
|
|
},
|
|
mounted() {
|
|
this.oninit();
|
|
},
|
|
beforeUnmount() {
|
|
clearTimeout(this.tid)
|
|
},
|
|
watch: {
|
|
modelValue(newval : string) {
|
|
let nowid = ""
|
|
if (this.selectedsIds.length > 0) {
|
|
nowid = this.selectedsIds[this.selectedsIds.length - 1]
|
|
}
|
|
if (nowid == newval) return;
|
|
this.oninit();
|
|
}
|
|
},
|
|
methods: {
|
|
getFontSize(k:string):string{
|
|
return checkIsCssUnit(k,xConfig.unit)
|
|
},
|
|
getNowListSwiper(){
|
|
if (this.menuBarList.length == 0){
|
|
// 当菜单为空时,显示根级数据
|
|
this._nowListSwiper = [this._list]
|
|
return
|
|
}
|
|
let lastId = this.menuBarList[this.menuBarList.length -1].id;
|
|
let temlist = [] as CASCADER_TREE_ITEM[][]
|
|
try {
|
|
temlist = this.findIdToMenuAry(lastId,this._list)
|
|
} catch (error) {
|
|
//TODO handle the exception
|
|
console.error(error)
|
|
// 出错时回退到根级数据
|
|
temlist = [this._list]
|
|
}
|
|
this._nowListSwiper = temlist
|
|
},
|
|
// 根据id返回第一级到当前id级的数据列表
|
|
findIdToMenuAry(id: string | number, trees: CASCADER_TREE_ITEM[]): CASCADER_TREE_ITEM[][] {
|
|
// 存储最终结果:每个层级的所有节点(带checked状态)
|
|
const result: CASCADER_TREE_ITEM[][] = [];
|
|
// 存储从根到目标节点的路径
|
|
const selectedPath: CASCADER_TREE_ITEM[] = [];
|
|
// 标记是否找到目标节点
|
|
let found = false;
|
|
|
|
// 递归查找目标节点并构建路径
|
|
function findPath(node: CASCADER_TREE_ITEM, path: CASCADER_TREE_ITEM[] = []): boolean {
|
|
// 当前节点加入临时路径
|
|
const currentPath = [...path, node] as CASCADER_TREE_ITEM[];
|
|
|
|
// 找到目标节点
|
|
if (node.id == id) {
|
|
// 复制路径到selectedPath
|
|
selectedPath.push(...currentPath);
|
|
found = true;
|
|
return true;
|
|
}
|
|
|
|
// 递归搜索子节点
|
|
if (node.children.length>0) {
|
|
for (let i = 0; i < node.children.length; i++) {
|
|
const child = node.children[i]
|
|
if (findPath(child, currentPath)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
for (let i = 0; i < trees.length; i++) {
|
|
const tree = trees[i]
|
|
// 直接检查第一级节点
|
|
if (tree.id == id) {
|
|
selectedPath.push(tree);
|
|
found = true;
|
|
break;
|
|
}
|
|
// 如果第一级不匹配,继续递归查找
|
|
else if (findPath(tree)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// 如果找到目标节点,构建结果数组
|
|
if (found) {
|
|
// 构建每一层级的节点列表
|
|
let currentLevel = trees;
|
|
let currentParent = null as null|CASCADER_TREE_ITEM;
|
|
|
|
// 遍历路径中的每个节点
|
|
for (let i = 0; i < selectedPath.length; i++) {
|
|
const pathNode = selectedPath[i];
|
|
|
|
// 为当前层级的所有节点添加checked状态
|
|
const levelWithChecked = currentLevel
|
|
|
|
// 添加到结果数组
|
|
result.push(levelWithChecked);
|
|
|
|
// 更新下一层级的父节点和子节点列表
|
|
if (i < selectedPath.length - 1) {
|
|
currentParent = currentLevel.find((node:CASCADER_TREE_ITEM):boolean => node.id == pathNode.id);
|
|
|
|
currentLevel = currentParent?.children??[]
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
return [trees];
|
|
},
|
|
//初始默认选中一个id值。如果为空的话。
|
|
oninit() {
|
|
const trees = toRaw(this._list) as CASCADER_TREE_ITEM[]
|
|
let rulst = getTreeNodesPath(trees, this.modelValue)
|
|
if (rulst != null) {
|
|
let indexpath = rulst.indexPath!
|
|
this.menuBarList = rulst.pathData
|
|
this.selectedsIds = rulst.ids
|
|
this.activeIndex = indexpath
|
|
this.changshowpenl = getUid() as string;
|
|
this.swiperIndex = this.menuBarList.length - 1
|
|
}
|
|
this.getNowListSwiper()
|
|
},
|
|
change(isCurrent:boolean) {
|
|
let idis = this.selectedsIds.slice(0);
|
|
let empty = ""
|
|
// 单项模式下,父节点不更新对外更新值,只取最后一个确定的值。
|
|
if (idis.length > 0) {
|
|
empty = idis[idis.length - 1]
|
|
}
|
|
if (empty != "" && (this._nextChildren.length==0||isCurrent)) {
|
|
/**
|
|
* 更新当前的值,等同v-model
|
|
*/
|
|
this.$emit('update:modelValue', empty)
|
|
/**
|
|
* 最后一项时触发.
|
|
*/
|
|
this.$emit('confirm',empty,idis)
|
|
|
|
}
|
|
this.$emit('change', idis)
|
|
},
|
|
|
|
swiperChange(detail:UniSwiperChangeEvent){
|
|
this.swiperIndex = detail.detail.current;
|
|
},
|
|
/**
|
|
* isCurrent:是否选中本级,不进行下级跳转
|
|
*/
|
|
nextOnClick(item : CASCADER_TREE_ITEM, parentIndex : number,childrenIndex:number, isNext : boolean,isCurrent:boolean) {
|
|
if (item.disabled || this.isTransitioning) return;
|
|
|
|
// 设置过渡状态,防止快速点击造成的闪烁
|
|
this.isTransitioning = true;
|
|
|
|
if(isNext){
|
|
this.menuBarList.push(item)
|
|
this.selectedsIds = this.menuBarList.map((el:CASCADER_TREE_ITEM):string => el.id)
|
|
|
|
// 先更新数据,再切换swiper
|
|
this.getNowListSwiper()
|
|
|
|
if(item.children.length>0 && !isCurrent){
|
|
// 使用nextTick确保数据更新完成后再切换
|
|
this.$nextTick(() => {
|
|
this.swiperIndex += 1
|
|
// 延迟重置过渡状态
|
|
const _this =this;
|
|
this.tid = setTimeout(() => {
|
|
_this.isTransitioning = false
|
|
}, 200)
|
|
})
|
|
}else{
|
|
if(!isCurrent){
|
|
// #ifdef APP-IOS
|
|
this.swiperIndex = parentIndex
|
|
// #endif
|
|
}
|
|
this.isTransitioning = false
|
|
}
|
|
this.$emit("cellClick",item,parentIndex-1,childrenIndex)
|
|
this.change(isCurrent)
|
|
|
|
return;
|
|
}
|
|
|
|
this.menuBarList = this.menuBarList.slice(0,this.swiperIndex+1)
|
|
|
|
if(item.children.length>0){
|
|
if(this.swiperIndex == this.menuBarList.length-1){
|
|
this.menuBarList.splice(this.menuBarList.length-1,1,item)
|
|
}else{
|
|
this.menuBarList.push(item)
|
|
}
|
|
|
|
// 先更新数据
|
|
this.getNowListSwiper()
|
|
|
|
if(!isCurrent){
|
|
// 使用nextTick确保数据更新完成
|
|
this.$nextTick(() => {
|
|
this.swiperIndex += 1
|
|
const _this =this;
|
|
this.tid = setTimeout(() => {
|
|
_this.isTransitioning = false
|
|
}, 200)
|
|
})
|
|
} else {
|
|
this.isTransitioning = false
|
|
}
|
|
}else{
|
|
if(parentIndex>this.menuBarList.length-1){
|
|
this.menuBarList.push(item)
|
|
}else{
|
|
this.menuBarList.splice(this.menuBarList.length-1,1,item)
|
|
}
|
|
this.isTransitioning = false
|
|
}
|
|
|
|
this.selectedsIds = this.menuBarList.map((el:CASCADER_TREE_ITEM):string => el.id)
|
|
this.$emit("cellClick",item,parentIndex,childrenIndex)
|
|
this.change(isCurrent)
|
|
},
|
|
menuBarClick(index : number) {
|
|
if(index==-1 || this.isTransitioning) return;
|
|
|
|
// 设置过渡状态
|
|
this.isTransitioning = true;
|
|
|
|
if(index==0){
|
|
this.menuBarList = [] as CASCADER_TREE_ITEM[]
|
|
}else{
|
|
this.menuBarList = this.menuBarList.slice(0,index)
|
|
}
|
|
|
|
// 先更新数据,再切换swiper
|
|
this.getNowListSwiper()
|
|
|
|
// 使用nextTick确保数据更新完成
|
|
this.$nextTick(() => {
|
|
this.swiperIndex = index
|
|
this.selectedsIds = this.menuBarList.map((el:CASCADER_TREE_ITEM):string => el.id)
|
|
this.change(false)
|
|
|
|
// 延迟重置过渡状态
|
|
const _this =this;
|
|
this.tid = setTimeout(() => {
|
|
_this.isTransitioning = false
|
|
}, 200)
|
|
})
|
|
},
|
|
elitext(text : string) : string {
|
|
let len = text.length;
|
|
return len <= 7 ? text : (text.substring(0, 7) + '..')
|
|
},
|
|
/**
|
|
* 当前是否选中
|
|
*/
|
|
isSelected(item : CASCADER_TREE_ITEM) : boolean {
|
|
return (this.selectedsIds.includes(item.id)) && item.children.length == 0
|
|
},
|
|
/**
|
|
* 本下级选了几个
|
|
*/
|
|
isSelectedNum(item : CASCADER_TREE_ITEM) : number {
|
|
let ps = new Set(this.selectedsIds)
|
|
return getTreeSelectedNum(item.children, ps);
|
|
},
|
|
|
|
},
|
|
}
|
|
</script>
|
|
<template>
|
|
<view class="xCascaderTree" :style="{width:_width,minHeight:`calc(${_height} + 50px)`}">
|
|
<scroll-view direction="horizontal" class="xCascaderTreeBar">
|
|
|
|
<!--
|
|
@slot 顶部头菜单导航插槽,你可以完全写自己的导航样式
|
|
@prop {CASCADER_TREE_ITEM[]} menus - 菜单导航,注意,可能为空
|
|
-->
|
|
<slot name="header" :menus="menuBarList" >
|
|
|
|
<view @click="menuBarClick(index)" v-if="menuBarList.length>0" class="xCascaderBarTreeItem"
|
|
v-for="(item,index) in menuBarList" :key="index">
|
|
<text class="xCascaderTreeItemBarText"
|
|
:style="{
|
|
color:_itemActiveColor,
|
|
fontSize:_fontSize,
|
|
whiteSpace:'nowrap',
|
|
border:`1px solid ${_itemActiveColor}`
|
|
}
|
|
">
|
|
{{elitext(item.title)}}
|
|
</text>
|
|
<x-icon
|
|
v-if="index<menuBarList.length-1||(index==0&&_nextChildren.length>0)||_nextChildren.length>0"
|
|
class="xCascaderBarTreeItemRight" :font-size="_fontSize"
|
|
name="arrow-right-s-line" :color="_itemActiveColor"></x-icon>
|
|
</view>
|
|
|
|
<view v-if="_nextChildren.length>0||(menuBarList.length==0&&_list.length>0)" @click="menuBarClick(-1)" class="xCascaderBarTreeItem">
|
|
<text :style="{color:_itemTextColor,fontSize:_fontSize,whiteSpace:'nowrap'}">
|
|
<!-- 请选择 -->
|
|
{{i18n!.t('tmui4x.cascader.placeholder')}}
|
|
</text>
|
|
<x-icon class="xCascaderBarTreeItemRight" font-size="14" name="arrow-right-s-line"
|
|
:color="_itemActiveColor"></x-icon>
|
|
</view>
|
|
|
|
|
|
</slot>
|
|
</scroll-view>
|
|
<view :style="{height:'1px',borderBottom:`1px solid ${_borderColor}`}"></view>
|
|
<swiper :disable-touch="true" :duration="200" @change="swiperChange" :style="{height:_height}" :current="swiperIndex">
|
|
<swiper-item v-for="(children,childrenIndex) in _nowListSwiper" :key="childrenIndex" class="xCascaderTreeSwiperItem"
|
|
:style="{height:_height}">
|
|
<list-view style="width: 100%;height: 100%;" direction="vertical">
|
|
<list-item v-for="(item,index) in children" :key="index" :style="{height:getFontSize('50')}">
|
|
<view :hover-start-time="10" :hover-stay-time="100"
|
|
:hover-class="item.disabled?'':'xCascaderTreeItemHover'"
|
|
@click="nextOnClick(item,childrenIndex,index,false,false)" class="xCascaderTreeItemRight"
|
|
:style="{backgroundColor:_sliderContentBgColor,opacity:item.disabled?'0.5':1}">
|
|
<view style="flex: 1;">
|
|
<text class="xCascaderTreeItemRightText"
|
|
:style="{fontSize:_fontSize,color:isSelected(item)?_itemActiveColor : _itemTextColor}">
|
|
{{item.title}}
|
|
</text>
|
|
</view>
|
|
<view
|
|
style="display: flex;flex-direction: row;justify-content: flex-end;align-items: center;">
|
|
<text class="xCascaderTreeItemRightTextBtns" :style="{color:_itemActiveColor,border:`1px solid ${_itemActiveColor}`}"
|
|
v-if="item.children.length>0&&_showCurrentBtn" @click.stop="nextOnClick(item,swiperIndex+1,index,false,true)">
|
|
<!-- 选择本级 -->
|
|
{{i18n!.t('tmui4x.cascader.currentPlaceholder')}}
|
|
|
|
</text>
|
|
<text :style="{fontSize:_fontSize,color:_itemActiveColor,marginRight:'8px'}"
|
|
v-if="item.children.length>0&&isSelectedNum(item)>0">已选({{isSelectedNum(item)}})</text>
|
|
<x-icon v-if="isSelected(item)" :color="_itemActiveColor"
|
|
name="check-line"></x-icon>
|
|
<x-icon v-if="item.children.length>0" :color="_itemTextColor"
|
|
name="arrow-right-s-line"></x-icon>
|
|
</view>
|
|
</view>
|
|
</list-item>
|
|
|
|
</list-view>
|
|
</swiper-item>
|
|
|
|
<swiper-item v-if="_nextChildren.length>0||isAndriod" class="xCascaderTreeSwiperItem" :style="{height:_height}">
|
|
|
|
|
|
<list-view style="width: 100%;height: 100%;" direction="vertical">
|
|
<list-item v-for="(item,index) in _nextChildren" :key="index" :style="{height:getFontSize('50')}">
|
|
<view :hover-start-time="10" :hover-stay-time="100"
|
|
:hover-class="item.disabled?'':'xCascaderTreeItemHover'"
|
|
@click="nextOnClick(item,swiperIndex+1,index,true,false)" class="xCascaderTreeItemRight"
|
|
:style="{backgroundColor:_sliderContentBgColor,opacity:item.disabled?'0.5':1}">
|
|
<view style="flex: 1;">
|
|
<text class="xCascaderTreeItemRightText"
|
|
:style="{fontSize:_fontSize,color:isSelected(item)?_itemActiveColor : _itemTextColor}">
|
|
{{item.title}}
|
|
</text>
|
|
</view>
|
|
<view
|
|
style="display: flex;flex-direction: row;justify-content: flex-end;align-items: center;">
|
|
|
|
<text class="xCascaderTreeItemRightTextBtns" :style="{color:_itemActiveColor,border:`1px solid ${_itemActiveColor}`}"
|
|
v-if="item.children.length>0&&_showCurrentBtn" @click.stop="nextOnClick(item,swiperIndex+1,index,true,true)">
|
|
<!-- 选择本级 -->
|
|
{{i18n!.t('tmui4x.cascader.currentPlaceholder')}}
|
|
</text>
|
|
|
|
<text :style="{fontSize:_fontSize,color:_itemActiveColor,marginRight:'8px'}"
|
|
v-if="item.children.length>0&&isSelectedNum(item)>0">已选({{isSelectedNum(item)}})</text>
|
|
<x-icon v-if="isSelected(item)" :color="_itemActiveColor"
|
|
name="check-line"></x-icon>
|
|
<x-icon v-if="item.children.length>0" :color="_itemTextColor"
|
|
name="arrow-right-s-line"></x-icon>
|
|
</view>
|
|
</view>
|
|
</list-item>
|
|
</list-view>
|
|
</swiper-item>
|
|
|
|
</swiper>
|
|
|
|
</view>
|
|
</template>
|
|
<style scoped>
|
|
.xCascaderTreeItemRightTextBtns{
|
|
font-size: 12px;
|
|
border-radius: 3px;
|
|
/* #ifdef APP-ANDROID */
|
|
padding: 0px 8px;
|
|
line-height:1.5;
|
|
/* #endif */
|
|
/* #ifndef APP-ANDROID */
|
|
padding: 4px 8px;
|
|
line-height:1;
|
|
/* #endif */
|
|
}
|
|
.xCascaderTreeItemBarText {
|
|
text-overflow: ellipsis;
|
|
lines: 1;
|
|
border-radius: 3px;
|
|
/* #ifdef APP */
|
|
padding: 0px 8px;
|
|
line-height:1.5;
|
|
/* #endif */
|
|
/* #ifndef APP */
|
|
padding: 4px 8px;
|
|
line-height:1;
|
|
/* #endif */
|
|
|
|
/* #ifndef APP */
|
|
display: -webkit-box;
|
|
-webkit-box-orient: vertical;
|
|
-webkit-line-clamp: 1;
|
|
/* 限定为3行 */
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
/* #endif */
|
|
}
|
|
|
|
.xCascaderTreeBar {
|
|
display: flex;
|
|
flex-direction: row;
|
|
|
|
height: 50px;
|
|
|
|
}
|
|
|
|
.xCascaderBarTreeItem {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
}
|
|
|
|
.xCascaderBarTreeItemRight {
|
|
margin: 0px 0px;
|
|
}
|
|
|
|
|
|
|
|
.xCascaderTreeSwiperItem {
|
|
/* #ifdef WEB */
|
|
cursor: default;
|
|
/* #endif */
|
|
}
|
|
|
|
|
|
|
|
|
|
.xCascaderTreeItemHover {
|
|
background-color: rgba(155, 155, 155, 0.1);
|
|
}
|
|
|
|
.xCascaderTreeItemMoreHeader {
|
|
padding: 12px;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.xCascaderTreeItemMore {
|
|
position: absolute;
|
|
left: 0px;
|
|
top: 0px;
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 10;
|
|
|
|
}
|
|
|
|
.xCascaderTreeItem {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.xCascaderTreeItemRight {
|
|
/* padding:0 24rpx; */
|
|
height: 50px;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.xCascaderTreeItemRightText {
|
|
text-align: left;
|
|
lines: 1;
|
|
text-overflow: ellipsis;
|
|
/* #ifndef APP */
|
|
white-space: nowrap;
|
|
/* 禁止换行 */
|
|
overflow: hidden;
|
|
width: 100%;
|
|
/* #endif */
|
|
}
|
|
</style> |