You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.7 KiB
193 lines
5.7 KiB
Component({
|
|
codeList: [],
|
|
options: {
|
|
multipleSlots: true,
|
|
},
|
|
properties: {
|
|
show: {
|
|
type: Boolean,
|
|
observer(show) {
|
|
if (!show) return;
|
|
this.setData({ pickerValue: [] }, () => {
|
|
this.codeList = this.splitCode(this.data.value);
|
|
this.updateDivisions();
|
|
});
|
|
},
|
|
},
|
|
title: {
|
|
type: String,
|
|
value: '选择地区',
|
|
},
|
|
value: {
|
|
type: String,
|
|
value: '',
|
|
},
|
|
areaData: {
|
|
type: Array,
|
|
value: [],
|
|
observer() {
|
|
if (!this.data.show) return;
|
|
this.updateDivisions();
|
|
},
|
|
},
|
|
columns: {
|
|
type: Number,
|
|
value: 3,
|
|
},
|
|
columnsName: {
|
|
type: Array,
|
|
value: ['省市/地区', '城市', '区'],
|
|
},
|
|
useLoadingSlot: Boolean,
|
|
},
|
|
data: {
|
|
pickerValue: [],
|
|
pickerColumnData: [],
|
|
hightLightIndex: [],
|
|
loading: false,
|
|
scrollTop: 0,
|
|
},
|
|
methods: {
|
|
splitCode(value) {
|
|
const codeList = [];
|
|
for (let i = 1; i <= this.data.columns; i++) {
|
|
let code = value.slice(0, i * 2);
|
|
if (code.length < i * 2) {
|
|
code = `${value.slice(0, (i - 1) * 2)}00`;
|
|
}
|
|
while (code.length < this.data.value.length) {
|
|
code += '0';
|
|
}
|
|
codeList.push(code);
|
|
}
|
|
return codeList;
|
|
},
|
|
updateDivisions() {
|
|
const { pickerValue } = this.data;
|
|
const area = pickerValue[pickerValue.length - 1];
|
|
let currentAreaData = [];
|
|
if (pickerValue.length === 0) {
|
|
currentAreaData = this.data.areaData;
|
|
} else {
|
|
if (area && area.children && area.children.length > 0) {
|
|
currentAreaData = [...area.children];
|
|
} else if (area && !area.children) {
|
|
const newArea = this.getNewAreaByPickerValue(pickerValue).area;
|
|
if (newArea && newArea.children) {
|
|
area.children = newArea.children;
|
|
currentAreaData = [...area.children];
|
|
}
|
|
}
|
|
}
|
|
if (currentAreaData.length > 0) {
|
|
const pickerColumnData = currentAreaData[0].code
|
|
? [{ name: '', children: currentAreaData }]
|
|
: currentAreaData;
|
|
let oldPickedIndexes = [-1, -1];
|
|
if (this.codeList.length > pickerValue.length) {
|
|
for (const gi in pickerColumnData) {
|
|
for (const ai in pickerColumnData[gi].children) {
|
|
if (
|
|
pickerColumnData[gi].children[ai].code ===
|
|
this.codeList[pickerValue.length]
|
|
) {
|
|
oldPickedIndexes = [+gi, +ai];
|
|
break;
|
|
}
|
|
}
|
|
if (oldPickedIndexes[0] > -1) break;
|
|
}
|
|
}
|
|
this.setData({ loading: false, pickerColumnData }, () => {
|
|
return new Promise((resolve) => {
|
|
if (oldPickedIndexes[0] > -1) {
|
|
this.createSelectorQuery()
|
|
.select('#area-item-0-0')
|
|
.boundingClientRect()
|
|
.select(`#area-item-${oldPickedIndexes.join('-')}`)
|
|
.boundingClientRect()
|
|
.exec((res) => {
|
|
if (res[0] && res[1]) {
|
|
const offsetTop = res[1].top - res[0].top;
|
|
const diff = res[1].height;
|
|
resolve(offsetTop > diff ? offsetTop - diff : 0);
|
|
} else {
|
|
resolve(0);
|
|
}
|
|
});
|
|
} else resolve(0);
|
|
}).then((scrollTop) => {
|
|
this.setData({
|
|
hightLightIndex: oldPickedIndexes,
|
|
scrollTop,
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
this.setData({ loading: true, pickerColumnData: [] }, () => {
|
|
if (area && area.code) {
|
|
this.triggerEvent('pullchildren', { parentCode: area.code });
|
|
} else {
|
|
this.triggerEvent('pullchildren', {});
|
|
}
|
|
});
|
|
}
|
|
},
|
|
getNewAreaByPickerValue(pickerValue) {
|
|
let { areaData } = this.data;
|
|
const areas = [];
|
|
for (const pickedArea of pickerValue) {
|
|
const _areaData =
|
|
areaData.length > 0 && areaData[0].code
|
|
? [{ name: '', children: areaData }]
|
|
: areaData;
|
|
let newArea;
|
|
for (const gi in _areaData) {
|
|
for (const ai in _areaData[gi].children) {
|
|
if (_areaData[gi].children[ai].code === pickedArea.code) {
|
|
newArea = _areaData[gi].children[ai];
|
|
break;
|
|
}
|
|
}
|
|
if (newArea) break;
|
|
}
|
|
if (!newArea) break;
|
|
areaData = newArea.children || [];
|
|
areas.push(newArea);
|
|
}
|
|
return { area: areas[areas.length - 1], areas };
|
|
},
|
|
onChange(e) {
|
|
const { gi, ai } = e.currentTarget.dataset;
|
|
const area = this.data.pickerColumnData[gi].children[ai];
|
|
const pickerValue = this.data.pickerValue.concat(area);
|
|
if (pickerValue.length < this.data.columns) {
|
|
this.setData({ pickerValue }, () => {
|
|
this.updateDivisions();
|
|
});
|
|
this.triggerEvent('change', { value: area.code, areas: pickerValue });
|
|
} else {
|
|
this.setData({ show: false });
|
|
this.triggerEvent('confirm', { value: area.code, areas: pickerValue });
|
|
}
|
|
},
|
|
onPickerClick(e) {
|
|
const { index } = e.currentTarget.dataset;
|
|
if (index > this.data.pickerValue.length - 1) return;
|
|
const pickerValue = this.data.pickerValue.slice(0, index);
|
|
this.setData({ pickerValue }, () => {
|
|
this.updateDivisions();
|
|
});
|
|
this.triggerEvent('change', {
|
|
value: pickerValue[pickerValue.length - 1]?.code,
|
|
areas: pickerValue,
|
|
});
|
|
},
|
|
|
|
onClose() {
|
|
this.setData({ show: false });
|
|
this.triggerEvent('close');
|
|
},
|
|
},
|
|
});
|