select-district.vue 5.28 KB
<template>
	<u-popup :show="visible" @close="onClose" :round="10" closeable>
    <view class="select-district__title">{{ title }}</view>
    <view class="select-district__content">
      <view class="select-district__tabs">
        <view class="select-district__tabs-item" :class="{ active: activeTab === 'province' }" @click="province.code ? '' : checkTab('province')">
          <text class="text">{{ t(province, labelKey).input || '请选择' }}</text>
        </view>
        <view v-if="province" class="select-district__tabs-item" :class="{ active: activeTab === 'city' }" @click="city.code ? '' : checkTab('city')">
          <text class="text">{{ t(city, labelKey).input || '请选择' }}</text>
        </view>
        <view v-if="city"  class="select-district__tabs-item" :class="{ active: activeTab === 'area' }" @click="checkTab('area')">
          <text class="text">{{ t(area, labelKey).input || '请选择' }}</text>
        </view>
      </view>
      <scroll-view class="select-district__scroll" scroll-y :scroll-top="scrollTop">
        <view class="select-district__scroll-item" v-for="(item, index) in activeList" :key="index" @click="checkItem(item)">
          <text class="text">{{ item[labelKey] }}</text>
        </view>
      </scroll-view>
    </view>
	</u-popup>
</template>

<script>
import t from 'typy';

export default {
  name: 'select-district',
  props: {
    visible: {
      type: Boolean
    },
    title: {
      type: String,
      default: '选择地址'
    },
    labelKey: {
      type: String,
      default: 'name'
    },
    valueKey: {
      type: String,
      default: 'code'
    },
    childrenKey: {
      type: String,
      default: 'children'
    },
    list: {
      type: Array,
      default: () => []
    },
    value: {
      type: Array,
      default: () => []
    }
  },
  data: function() {
    return {
      activeTab: 'province',
      province: t(this.value, '0').input,
      city: t(this.value, '1').input,
      area: t(this.value, '2').input,
      scrollTop: 0,
    };
  },
  watch: {
    value: function(val) {
      this.province = t(val, '0').input;
      this.city = t(val, '1').input;
      this.area = t(val, '2').input;
      if (this.city) {
        this.activeTab = 'city';
      }
      if (this.area) {
        this.activeTab = 'area';
      }
    }
  },
  computed: {
    activeList: function() {
      if (this.activeTab === 'province') {
        return this.list;
      } else if (this.activeTab === 'city') {
        const currentProvinceKey = t(this.province, this.valueKey).input;
        const match = this.list.find(item => item[this.valueKey] === currentProvinceKey) || {};
        return match[this.childrenKey] || [];
      } else if (this.activeTab === 'area') {
        const currentProvinceKey = t(this.province, this.valueKey).input;
        const currentCityMatch = this.list.find(item => item[this.valueKey] === currentProvinceKey) || {};
        const currentCityList = currentCityMatch[this.childrenKey] || [];
        const currentCityKey = t(this.city, this.valueKey).input;
        const match = currentCityList.find(item => item[this.valueKey] === currentCityKey) || {};
        return match[this.childrenKey] || [];
      }
    }
  },
  methods: {
    t,
    onClose: function() {
      this.$emit('visible', false);
      this.scrollTop = 0;
    },
    checkTab: function(type) {
      this.activeTab = type;
      this[type] = null;
      if (type === 'province') {
        this.city = null;
        this.area = null;
      } else if (type === 'city') {
        this.area = null;
      }
    },
    checkItem: function(item) {
      this[this.activeTab] = { ...item, children: undefined };
      if (this.activeTab === 'province') {
        this.activeTab = 'city';
      } else if (this.activeTab === 'city') {
        this.activeTab = 'area';
      } else if (this.activeTab === 'area') {
        const result = [this.province, this.city, this.area];
        console.log(result,'this.province')
        this.$emit('input', result);
        this.$emit('change', result);
        this.$emit('visible', false);
      }
    },
  }
};
</script>

<style lang="scss">
.select-district {
  &__title {
    padding: $padding-md;
    text-align: center;
    font-size: $font-md;
  }
  &__content {
    background-color: $color-white;
  }
  &__scroll {
    height: ($padding-md * 2 + $font-md) * 8;
    &-item {
      padding: $padding-md;
      font-size: $font-md;
      color: $color-text;
      box-sizing: border-box;
      line-height: 1;
    }
  }
  &__tabs {
    padding-bottom: $padding-md;
    &-item {
      width: 33%;
      max-width: 33%;
      line-height: 1;
      box-sizing: border-box;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: $padding-sm $padding-sm;
      color: $color-black;
      font-size: $font-md;
      font-weight: bold;
      position: relative;
      .text {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      &:after {
        content: '';
        width: 0;
        height: 0;
        border-bottom: 4upx solid $color-primary;
        position: absolute;
        left: 50%;
        bottom: 0;
        transform: translateX(-50%);
        transition: 0.3s;
      }
      &.active {
        &:after {
          width: 50%;
        }
      }
    }
  }
}
</style>