<template> <view class="tm-pickersView flex-start px-24" :class="[black_tmeme?'grey-darken-5':bgColor]"> <!-- @change="bindChange" --> <picker-view @change="change" @pickstart='$emit("aniStart")' @pickend='$emit("aniEnd")' v-if="listData.length>0" :value="value_default" :mask-style='black_tmeme?"opacity:0;":""' indicator-style='height:50px;' indicator-class="tm-pickersBView-item-h" class="tm-pickersBView-wk"> <picker-view-column v-for="(item,index) in listData" :key="index"> <view class="tm-pickersBView-item fulled-height flex-center " style="margin: 0 5px;" :class="[value_default[index]==index_pub?'text-size-n text-weight-b active':'',black_tmeme?'bk':'']" v-for="(item_data,index_pub) in listData[index]" :key="index_pub"> <text v-if="dataType == 'string'" >{{item_data}}</text> <text v-if="dataType == 'object'">{{item_data[rangKey]}}</text> </view> </picker-view-column> </picker-view> </view> </template> <script> /** * 普通级联拉选择器(嵌入式) * @description 多级关联,单级关联选择 * @property {Array} default-value = [] 默认:[],默认赋值项。可选三种赋值方式,名称赋值,对象赋值,数字序列赋值 * @property {String|Number} item-height = [34|42|50|58|62] 项目的高度单位px * @property {Array} list = [] 选择器的数据,可选格式:Array<string>,Array<object>.如果为object格式需要提供rangKey.如果为多级需要提供children.key值 * @property {String} rang-key = [text|title] 默认:text,如果List格式为对象数组,需要提供此值 * @property {String} children-key = [children] 默认:children,如果List格式为对象数组且为多级联选择,需要提供此值,理论上无限级联数据 * @property {String|Boolean} black = [true|false] 是否开启暗黑模式。 * @property {String|Boolean} disabled = [true|false] 是否禁用 * @property {String} bg-color = [white|blue] 默认:white,白色背景;请填写背景的主题色名称。 * @property {Function} change 列数被选中改变时触发。 * */ export default { name: "tm-pickersView", props: { // 默认选中的项 // 格式有三种分别是[string,string...] // [数字序列,数字序列....] // 和list同等对象结构[{},{},...],此格式需要提供rangKey字段否则报错。 defaultValue:{ type:Array, default:()=>{return []} }, // 行高。 itemHeight: { type: String | Number, default: 40 }, list: { type: Array, default: () => { return [] } }, // 如果数据是对象,则需要提供key值。 rangKey: { type: String, default: "text" }, rangKeyId: { type: String, default: "id" }, // 如果是联级,则需要提供子集key值。 childrenKey: { type: String, default: "children" }, black:{ type:String|Boolean, default:null }, // 是否禁用 disabled:{ type:String|Boolean, default:false }, // 背景颜色,主题色名称。 bgColor:{ type:String, default:'white' } }, data() { return { value_default:[], pre_value:[], scrollEvent: 0, childrenIndex: 0, listIndex: [], listData: [], idx:9123 }; }, mounted() { this.$nextTick(function(){ this.chulisdata() this.setDefaultValue(); }) }, watch:{ defaultValue:{ deep:true, handler: function(newV,oldV){ this.chulisdata() this.$nextTick(function(){ this.inits(); }) } }, list:{ deep:true, handler:async function(newV,oldV){ this.chulisdata() this.$nextTick(async function(){ await this.inits(); }) } }, }, computed: { black_tmeme: function() { if (this.black !== null) return this.black; return this.$tm.vx.state().tmVuetify.black; }, dataType: function() { // 数据有误 if (typeof this.list !== 'object' && !Array.isArray(this.list) && !this.list.length) return null; if (typeof this.list[0] === 'string') return 'string'; if (typeof this.list[0] === 'object') return 'object'; }, gridNum: function() { let t = this; if ( (typeof this.list !== 'object' && !Array.isArray(this.list) && this.list.length==0)|| typeof this.list[0] === 'undefined' ) { this.listIndex = [{ itemIndex: 0, childrenIndex: 0, wz: 0 }] return 0 }; if (typeof this.list[0] === 'string') { this.listIndex = [{ itemIndex: 0, childrenIndex: 0, wz: 0 }] return 1 } if (typeof this.list[0] === 'object') { let index = 0; let cindex = 1; let pds = [] function tests(obj) { if(!obj||obj?.length==0){ return; } cindex = cindex+1; index +=1; pds.push({ itemIndex: 0, childrenIndex: index, wz: 0 }) if (obj && typeof obj === 'object' && Array.isArray(obj)) { if (obj[0][t.childrenKey]) { tests(obj[0][t.childrenKey]); } } } pds.push({ itemIndex: 0, childrenIndex: index, wz: 0 }) tests(this.list[0][this.childrenKey]) t.listIndex = pds; return cindex; } }, }, methods: { SeletecdeIndexdefault(){ let d = [] for(let i=0;i<this.gridNum;i++){ d.push(this.listIndex[i].itemIndex) } this.value_default = d; }, // 获取当前选中的数据。 getSelectedValue(){ let t = this; // 总的级联数。 let dNum = this.gridNum; let pd = this.listIndex; if(this.dataType === 'string'){ return [{ index:this.listIndex[0].itemIndex, data:this.listData[0][this.listIndex[0].itemIndex] }] }else if(this.dataType === 'object'){ if(dNum===1){ let ps = {...this.listData[0][this.listIndex[0].itemIndex]}; delete ps.children; return [{ index:this.listIndex[0].itemIndex, data:ps }] }else if(dNum>1){ let p = []; this.listIndex.forEach((item,index)=>{ if(t.listData[index]){ let ps = {...t.listData[index][item.itemIndex]}; delete ps.children; p.push({ index:item.itemIndex, data:ps }) } }) return p; } } return []; }, chulisdata() { // 总的级联数。 let dNum = this.gridNum; let t = this; if (dNum === 0) { this.listData = []; this.$forceUpdate() return this.listData; } if (dNum === 1) { this.listData = [this.list]; // this.listData.push([...this.list]); this.$forceUpdate() return this.listData; } if (dNum > 1) { let index = 1; let list = []; let p = []; function tests(obj) { if(index > dNum) return; list.push([...obj]) if(obj[t.listIndex[index]?.itemIndex]){ let cl = obj[t.listIndex[index].itemIndex][t.childrenKey]; if (cl && typeof cl === 'object' && Array.isArray(cl)) { index++; tests(cl); } } } p.push([...this.list]) if(this.list[t.listIndex[0].itemIndex][this.childrenKey]){ tests(this.list[t.listIndex[0].itemIndex][this.childrenKey]) } p.push(...list); this.$forceUpdate() this.listData = p; } return this.listData; }, setDefaultValue(objSelected){ let t = this; uni.$tm.sleep(50).then(()=>t.inits(objSelected)) .then(()=>uni.$tm.sleep(50)) .then(()=>t.SeletecdeIndexdefault()) }, async inits(objSelected){ // 总的级联数。 let dNum = this.gridNum; let t = this; var sjd = null; if(typeof objSelected ==='object' && Array.isArray(objSelected)){ sjd = objSelected; }else{ if(!this.defaultValue||this.defaultValue.length==0) return; sjd = this.defaultValue; } let typeindex = typeof sjd[0]; if(dNum===0) return; if(typeindex === 'number'){ if (dNum === 1) { let itemIndex = sjd[0]; if(typeof itemIndex === 'number' && !isNaN(itemIndex) ){ this.$set(this.listIndex[0], 'itemIndex', itemIndex); } return }else if(dNum > 1){ let index = 1; async function tests() { if(index > dNum) return; let itemIndex = t.defaultValue[index]; if(typeof itemIndex === 'number' && !isNaN(itemIndex) &&typeof t.listIndex[index] === 'object' && typeof t.listIndex[index] !=='undefined'){ await uni.$tm.sleep(30) t.$set(t.listIndex[index], 'itemIndex', itemIndex); t.chulisdata(); index++; await tests(); } } let itemIndex = sjd[0]; this.$set(this.listIndex[0], 'itemIndex', itemIndex); this.chulisdata(); await tests() } }else if(typeindex === 'string'){ if(this.dataType==='string'){ if (dNum === 1) { let valueStr = sjd[0]; if(typeof valueStr !=='string' || typeof valueStr ==='undefined' || valueStr ==null){ return; } let itemIndex = this.listData[0].indexOf(valueStr) if(itemIndex>-1){ this.$set(this.listIndex[0], 'itemIndex', itemIndex); } return } }else if(this.dataType === 'object'){ if (dNum === 1) { let valueStr = sjd[0]; if(typeof valueStr !=='string' || typeof valueStr ==='undefined' || valueStr ==null){ return; } let itemIndex = this.listData[0].findIndex(item=>{ return item[t.rangKey] == valueStr; }) if(itemIndex>-1){ this.$set(this.listIndex[0], 'itemIndex', itemIndex); } return }else if(dNum>1){ let index = 0; async function tests() { if(index > dNum) return; if(typeof t.listIndex[index] === 'object' && typeof t.listIndex[index] !=='undefined'){ let valueStr = t.defaultValue[index]; if(typeof valueStr !=='string' || typeof valueStr ==='undefined' || valueStr ==null){ return; } let itemIndex = t.listData[index].findIndex(item=>{ return item[t.rangKey] == valueStr; }) if(itemIndex>-1){ await uni.$tm.sleep(30) t.$set(t.listIndex[index], 'itemIndex', itemIndex); t.chulisdata(); } index++; await tests(); } } await tests() } } }else if(typeindex === 'object'){ if (dNum === 1) { let valueStr = sjd[0]; if(typeof valueStr[t.rangKey] ==='undefined' || typeof valueStr !=='object' || typeof valueStr ==='undefined' || valueStr ==null){ return; } let itemIndex = this.listData[0].findIndex(item=>{ return (item[t.rangKey] == valueStr[t.rangKey])||(parseInt(item[t.rangKeyId]) == parseInt(valueStr[t.rangKeyId]));; }) if(itemIndex>-1){ this.$set(this.listIndex[0], 'itemIndex', itemIndex); } return }else if(dNum>1){ let index = 0; async function tests() { if(index > dNum) return; if(typeof t.listIndex[index] === 'object' && typeof t.listIndex[index] !=='undefined'){ let valueStr = t.defaultValue[index]; if(typeof valueStr[t.rangKey] ==='undefined' || typeof valueStr !=='object' || typeof valueStr ==='undefined' || valueStr ==null){ return; } let itemIndex = t.listData[index].findIndex(item=>{ return (item[t.rangKey] == valueStr[t.rangKey])||(parseInt(item[t.rangKeyId]) == parseInt(valueStr[t.rangKeyId])); }) if(itemIndex>-1){ await uni.$tm.sleep(30) t.$set(t.listIndex[index], 'itemIndex', itemIndex); t.$set(t.listIndex[index], 'wz', itemIndex * t.itemHeight); t.chulisdata(); } index++; await tests(); } } await tests() } } }, change(e) { let pl = [...e.detail.value]; this.pre_value =[...this.value_default]; if(this.disabled){ this.value_default = this.pre_value; return; } let childrenIndex = 0; for(let i=0;i<pl.length;i++){ if(this.listIndex[i].itemIndex !== pl[i]){ childrenIndex = this.listIndex[i].childrenIndex; break; } } this.childrenIndex = childrenIndex; for(let i=childrenIndex;i<pl.length;i++){ if(this.listIndex[i]?.itemIndex !== pl[i]){ this.$set(this.listIndex[i],'itemIndex',pl[i]) }else{ this.$set(this.listIndex[i],'itemIndex',0) pl[i] = 0; } } this.chulisdata() this.$nextTick(function(){ this.value_default = pl; this.$emit("change",pl) }) }, }, } </script> <style > .tm-pickersView .tm-pickersBView-item-h{ height: 50px; background-color: rgba(0,0,0,0.03); width: calc(100% - 10px); margin-left: 5px; border-radius: 20rpx; border: none; } .tm-pickersView .tm-pickersBView-item-h::after,.tm-pickersView .tm-pickersBView-item-h::before{ border: none; } .tm-pickersView .tm-pickersBView-wk{ position: relative; width: 750rpx; height: 500rpx; } .tm-pickersView .tm-pickersBView-wk .tm-pickersBView-item.bk{ opacity: 0.4; } .tm-pickersView .tm-pickersBView-wk .tm-pickersBView-item.active{ opacity: 1; border-radius: 20rpx; border: none; background-color: rgba(0,0,0,0.06); } .tm-pickersView .tm-pickersBView-wk .tm-pickersBView-item.active.bk{ background-color: rgba(255,255,255,0.06); } </style>