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.
git/scr/miniprogram-2/pages/usercenter/components/area-picker-new/index.js

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');
},
},
});