123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- import type { Area } from '../../../../utils/area'
- Component({
- //@ts-ignore
- 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: [] as Area[],
- pickerColumnData: [] as Area[],
- hightLightIndex: [] as number[],
- loading: false,
- scrollTop: 0,
- },
- methods: {
- splitCode(value: string) {
- 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) {
- //@ts-ignore
- 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<number>((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: Area[]) {
- let { areaData } = this.data as any
- 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: WechatMiniprogram.CustomEvent<{}, {}, { gi: number; ai: number }>) {
- 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: WechatMiniprogram.CustomEvent<{}, {}, { index: number }>) {
- 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')
- },
- },
- })
|