Newer
Older
xc-metering-front / src / components / AddressSelect / AddressSelect.vue
liyaguang on 19 Jul 2023 6 KB first commit
<script lang="ts" setup name="AddressSelect">
import countries from './country-code.json'
import type { IAddress } from './address-interface'
import { getAreaByPid } from '@/api/system/area'
const props = defineProps({
  /**
   * 数据列表: ['国家','省','市','区','详细地址']
   */
  data: {
    type: Array,
    default: () => [],
  },
  /**
   * 是否显示详细地址
   */
  isShowDetailedAddress: {
    type: Boolean,
    default: true,
  },
  /**
   * 是否可编辑
   */
  disabled: {
    type: Boolean,
    default: false,
  },
  /**
   * 是否是详情展示
   */
  detail: {
    type: Boolean,
    default: false,
  },
})
const emit = defineEmits(['onChange'])
// 下拉区域对象
interface IArea {
  id: string
  areaName: string
}
const countryList = ref(countries)
const provinceList = ref<IArea[]>([]) // 省列表
const cityList = ref<IArea[]>([]) // 市列表
const areaList = ref<IArea[]>([]) // 区列表
// 地址对象
const addressObj: IAddress = reactive({
  country: '',
  countryName: '',
  province: '',
  provinceName: '',
  city: '',
  cityName: '',
  area: '',
  areaName: '',
  address: '',
})
function countryChange(countryCode: string, clear = true) {
  if (clear) {
    addressObj.province = ''
    addressObj.provinceName = ''
    addressObj.city = ''
    addressObj.cityName = ''
    addressObj.area = ''
    addressObj.areaName = ''
  }
  if (countryCode === 'CN') {
    getAreaByPid('0').then((res) => {
      provinceList.value = res.data
    })
  }
}
// 省份变化
function provinceChange(provinceId: string, clear = true) {
  if (clear) {
    addressObj.city = ''
    addressObj.cityName = ''
    addressObj.area = ''
    addressObj.areaName = ''
  }
  getAreaByPid(provinceId).then((res) => {
    cityList.value = res.data
  })
  // emit('onChange', addressObj)
}

// 城市变化
function cityChange(cityId: string, clear = true) {
  if (clear) {
    addressObj.area = ''
    addressObj.areaName = ''
  }

  getAreaByPid(cityId).then((res) => {
    areaList.value = res.data
  })
  // emit('onChange', addressObj)
}
// 区域变化
function areaChange(areaId: string) {
}
// 监听参数变化
watch(() => props.data, (val) => {
  if (Array.isArray(val) && val.length == 5) {
    if (!props.detail) {
      addressObj.country = val[0]
      addressObj.province = val[1]
      addressObj.city = val[2]
      addressObj.area = val[3]
      addressObj.address = val[4]
      if (addressObj.country) { countryChange(addressObj.country, false) }
      if (addressObj.province) { provinceChange(addressObj.province, false) }
      if (addressObj.city) { cityChange(addressObj.city, false) }
    }
    else { // 详情,只给输入框复制
      addressObj.countryName = val[0]
      addressObj.provinceName = val[1]
      addressObj.cityName = val[2]
      addressObj.areaName = val[3]
      addressObj.address = val[4]
    }
  }
})

watch(
  () => addressObj,
  (val) => {
    // 如果无中文的,查找中文
    if (addressObj.countryName == '') {
      addressObj.countryName = countryList.value.find(item => item.code == addressObj.country)?.CNName || ''
    }
    if (addressObj.provinceName == '') {
      addressObj.provinceName = provinceList.value.find(item => item.id == addressObj.province)?.areaName || ''
    }
    if (addressObj.cityName == '') {
      addressObj.cityName = cityList.value.find(item => item.id == addressObj.city)?.areaName || ''
    }
    if (addressObj.areaName == '') {
      addressObj.areaName = areaList.value.find(item => item.id == addressObj.area)?.areaName || ''
    }
    emit('onChange', addressObj)
  },
  { immediate: false, deep: true })
</script>

<template>
  <div>
    <!-- 国家 -->
    <el-select
      v-if="!detail"
      v-model="addressObj.country"
      class="address-select"
      placeholder="国家"
      @change="countryChange"
    >
      <el-option v-for="country of countryList" :key="country.code" :label="country.CNName" :value="country.code" />
    </el-select>
    <el-input
      v-else
      v-model="addressObj.countryName"
      placeholder=""
      class="address-select"
      :class="{ 'detail-input': detail }"
      :disabled="detail"
    />
    <!-- 省 -->
    <el-select
      v-if="!detail && (addressObj.country === '' || addressObj.country === 'CN')"
      v-model="addressObj.province"
      placeholder="省"
      :disabled="detail || !addressObj.country"
      class="address-select"
      @change="provinceChange"
    >
      <el-option
        v-for="province in provinceList"
        :key="province.id"
        :label="province.areaName"
        :value="province.id"
      />
    </el-select>
    <el-input
      v-else-if="detail && addressObj.countryName === '中国'"
      v-model="addressObj.provinceName"
      placeholder=""
      class="address-select"
      :class="{ 'detail-input': detail }"
      :disabled="detail"
    />
    <!-- 市 -->
    <el-select
      v-if="!detail && (addressObj.country === '' || addressObj.country === 'CN')"
      v-model="addressObj.city"
      placeholder="市"
      :disabled="detail || !addressObj.province"
      class="address-select"
      @change="cityChange"
    >
      <el-option
        v-for="city in cityList"
        :key="city.id"
        :label="city.areaName"
        :value="city.id"
      />
    </el-select>
    <el-input
      v-else-if="detail && addressObj.countryName === '中国'"
      v-model="addressObj.cityName"
      placeholder=""
      class="address-select"
      :class="{ 'detail-input': detail }"
      :disabled="detail"
    />
    <!-- 区 -->
    <el-select
      v-if="!detail && (addressObj.country === '' || addressObj.country === 'CN')"
      v-model="addressObj.area"
      placeholder="区/县"
      class="address-select"
      :disabled="detail || !addressObj.city"
      @change="areaChange"
    >
      <el-option
        v-for="area in areaList"
        :key="area.id"
        :label="area.areaName"
        :value="area.id"
      />
    </el-select>
    <el-input
      v-else-if="detail && addressObj.countryName === '中国'"
      v-model="addressObj.areaName"
      placeholder=""
      class="address-select"
      :class="{ 'detail-input': detail }"
      :disabled="detail"
    />
    <!-- 详细地址 -->
    <el-input
      v-if="isShowDetailedAddress"
      v-model="addressObj.address"
      :placeholder="detail ? '' : '详细地址'"
      :disabled="detail"
      class="address-input"
      :class="{ 'detail-input': detail }"
    />
  </div>
</template>

<style lang="scss" scoped>
.address-select {
  width: 160px;
  margin-right: 5px;
}

.address-input {
  width: 280px;
}
</style>