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

539 lines
14 KiB
Vue

1 year ago
<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>