| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- <template>
- <view class="addressPicker">
- <u-picker :show="shows" ref="uPicker" :defaultIndex="defaultIndex" :columns="columns" keyName="name"
- @change="changeHandler" @cancel="cancel" @confirm="confirm" @close="close"
- :closeOnClickOverlay="true"></u-picker>
- </view>
- </template>
- <script>
- import address from '@/utils/address.json'
- export default {
- props: {
- show: Boolean,
- defaultIndex: {
- type: Array,
- default: () => {
- return [0, 0, 0]
- },
- },
- defaultCodes: { // 改为接收标准6位码数组
- type: Array,
- default: () => ['110000', '110100', '110101'] // 默认北京东城区
- }
- },
- data() {
- return {
- shows: this.show,
- columns: [
- [],
- [],
- []
- ], // 省/市/区三级数据
- fullData: [] // 包含完整结构的缓存数据
- }
- },
- watch: {
- show(val) {
- this.shows = val
- if (val) this.initByCodes(this.defaultCodes)
- },
- defaultCodes: {
- immediate: true,
- handler(codes) {
- this.initByCodes(codes)
- }
- }
- },
- async created() {
- await this.initData()
- },
- methods: {
- // 初始化数据结构(含6位码处理)
- initData() {
- this.fullData = address.map(province => ({
- ...province,
- code: this.ensure6DigitCode(province.code),
- children: province.children.map(city => ({
- ...city,
- code: this.ensure6DigitCode(city.code),
- children: (city.children || []).map(area => ({
- ...area,
- code: this.ensure6DigitCode(area.code)
- }))
- }))
- }))
- // 初始化省级选项
- this.columns[0] = this.fullData.map(p => ({
- name: p.name,
- code: p.code
- }))
- this.initDefaultSelection();
- },
- initDefaultSelection() {
- if (this.defaultCodes && this.defaultCodes.length >= 3) {
- // 如果传入了defaultCodes,优先使用
- this.initByCodes(this.defaultCodes);
- } else {
- // 否则自动选择第一个省+第一个市+第一个区
- const firstProvince = this.fullData[0];
- const firstCity = firstProvince.children?.[0];
- const firstArea = firstCity?.children?.[0];
- this.columns[1] = firstProvince.children?.map(c => ({
- name: c.name,
- code: c.code
- })) || [];
- this.columns[2] = firstCity?.children?.map(a => ({
- name: a.name,
- code: a.code
- })) || [];
- // 设置Picker选中状态
- this.$nextTick(() => {
- this.$refs.uPicker?.setIndexs([0, 0, 0]);
- });
- }
- },
- // 根据6位码初始化选中状态
- initByCodes(codes) {
- if (!codes || codes.length < 3) return
- // 1. 查找省级索引
- const provIndex = this.fullData.findIndex(
- p => p.code === codes[0]
- )
- if (provIndex === -1) return
- // 2. 设置市级数据
- const cities = this.fullData[provIndex].children
- this.columns[1] = cities.map(c => ({
- name: c.name,
- code: c.code
- }))
- // 3. 查找市级索引
- const cityIndex = cities.findIndex(
- c => c.code === codes[1]
- )
- if (cityIndex === -1) return
- // 4. 设置区级数据
- const areas = cities[cityIndex].children
- this.columns[2] = areas.map(a => ({
- name: a.name,
- code: a.code
- }))
- },
- // 确保6位行政区划码
- ensure6DigitCode(code) {
- if (!code) return ''
- if (code.length === 2) return code + '0000'
- if (code.length === 4) return code + '00'
- return code // 6位或9位码保持不变
- },
- // 选择变化事件(适配6位码)
- changeHandler(e) {
- const {
- columnIndex,
- index
- } = e
- if (columnIndex === 0) {
- // 省份变化
- const cities = this.fullData[index].children
- this.columns[1] = cities.map(c => ({
- name: c.name,
- code: c.code
- }))
- this.columns[2] = cities[0]?.children.map(a => ({
- name: a.name,
- code: a.code
- })) || []
- this.$refs.uPicker.setColumnValues(1, this.columns[1])
- this.$refs.uPicker.setColumnValues(2, this.columns[2])
- } else if (columnIndex === 1) {
- // 城市变化
- const areas = this.fullData[e.indexs[0]].children[index].children
- this.columns[2] = areas.map(a => ({
- name: a.name,
- code: a.code
- }))
- this.$refs.uPicker.setColumnValues(2, this.columns[2])
- }
- },
- cancel() {
- this.$emit('cancel')
- },
- close() {
- this.$emit('close')
- },
- confirm(e) {
- const selected = e.value
- this.$emit('confirm', {
- names: selected.map(i => i.name),
- codes: selected.map(i => i.code), // 标准6位码
- fullAddress: selected.map(i => i.name).join('-')
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- </style>
|