taro-vue小程序省市搜索类页面

691 阅读1分钟

背景:最近项目中原来多城市选择下拉组件老板嫌找城市麻烦,并且很多区域没有项目。所以新增一个搜索的页面。页面返回多省市区为自己后段返回多有项目的省市。所以自己做了一个切换tab并且可小程序内城市搜索的页面

<template>
  <view class="column-flex-container page-city-select">
    <NavBar
      back-text=""
    >
      <text class="cuIcon-search" />
      <input
        v-model="searchValue"
        class="search-input"
        placeholder="请输入城市或省份"
        type="text"
        :focus="true"
        confirmType="search"
        @input="onInput"
        @blur="onBlur"
        @confirm="onConfirm"
      >
      <text v-show="searchValue.length" @tap="clear" class="cuIcon cuIcon-roundclosefill clear" />
    </NavBar>
    <view v-if="searchValue.length === 0" class="city-nav">
      <view @tap="cityChange(0)" class="city-nav-item" :class="cityIndex===0 ? 'active' : ''">按区域</view>
      <view @tap="cityChange(1)" class="city-nav-item" :class="cityIndex===1 ? 'active' : ''">按城市</view>
    </view>
    <view 
      v-if="searchValue.length === 0"
      class="layout-container city-body"
    >
      <view 
        v-for="(item, index) in (cityIndex ? cityList : provinceList)"
        :key="index"
        class="city-list"
        @tap="areaSelect(item)"
      >
        <view :class="item.place === optinosCity ? 'selected': ''">
          {{ item.place }}
          <text v-if="item.place === optinosCity" @tap="clear" class="cuIcon cuIcon-check" />
        </view>
      </view>
    </view>
    <view 
      v-else
      class="layout-container city-body"
    >
      <view 
        v-for="(item, index) in provinceAndCityList.filter(item => item.place.indexOf(searchValue) !== -1)"
        :key="index"
        class="city-list"
        @tap="areaSelect(item)"
      >
        <view :class="item.place === optinosCity ? 'selected': ''">
          {{ item.place }}
          <text v-if="item.place === optinosCity" class="cuIcon cuIcon-check" />
        </view>
      </view>
    </view>
  </view>
</template>

<script>

import { getAllProvinceAndCities } from '@/api/metadata'
import { mapGetters, mapMutations } from 'vuex'

export default {
  name: 'PageCitySelect',
  
  data () {
    return {
      provinceList: [],
      cityList: [],
      provinceAndCityList: [],
      cityIndex: 0,
      searchValue: '',
      optinosCity: '全国'
    }
  },
  created() {
    this.getProvinceAndCity()
  },
  onLoad(options) {
    // console.log(decodeURI(options.area));
    // if (options.area) {
    //   this.optinosCity = options.area
    // }
  },
  computed: {
    ...mapGetters('areaSelect', ['place']),
  },
  methods: {
    ...mapMutations('areaSelect', ['setPlace']),
    getProvinceAndCity() {
      if (this.place.place) {
        this.optinosCity = this.place.place
      }
      getAllProvinceAndCities().then((data) => {
        console.log(data);
        this.cityList = data.data.cities.map(item => {
          return {
            ...item,
            type: 2
          }
        })
        this.provinceList = data.data.provinces.map(item => {
          return {
            ...item,
            type: 1
          }
        })
        this.provinceAndCityList = [...this.cityList, ...this.provinceList]
      })
    },
    cityChange(i){
      this.cityIndex = i
    },
    onInput () {
      console.log(this.searchValue);
    },
    onBlur () {
      this.searchValue = this.searchValue.trim()
    },
    areaSelect (val) {
      this.setPlace(val)
      this.$navigateTo(1)
    },
    onConfirm () {
      this._getDateList()
    },
    clear() {
      this.searchValue = ''
    }
  }
}
</script>

<style lang="scss">
.page-city-select{
  .search-input {
    width: 220px;
    height: 28px;
    line-height: 28px;
    color: #323232;
    background: #F5F5F5;
    border-radius: 14px;
    text-align: left;
    box-sizing: border-box;
    padding-left: 30px;
    font-weight: 400;
    padding-right: 30px;
  }
  .cu-custom .cu-bar .content {
    width: calc(100% - 180rpx)!important;
    font-weight: 600;
  }
  .cuIcon-search:before {
    content: "";
    width: 10.5px;
    height: 10.5px;
    position: absolute;
    font-size: 10.5px;
    left: 12px;
    color: rgba(111, 111, 111, 1);
  }
  .city-nav {
    display: flex;
    background: #fff;
    border-bottom: 1rpx solid #F5F5F5;
    padding: 16px 0 16px 0;
    color: #999999;
    &-item {
      width: 50%;
      text-align: center;
      position: relative;
    }
  }
  .city-body {
    background: #fff;
    padding-bottom: 60px;
    .city-list {
      padding: 13px 18px;
      color: #323232;
      font-size: 16px;
      position: relative;
    }
  }
  .active {
    color: #323232;
    font-weight: 600;
  }
  .active::after {
    content: '';
    width: 18px;
    height: 3px;
    background: #E64A4A;
    border-radius: 3px;
    position: absolute;
    bottom: -6px;
    left: 50%;
    transform: translateX(-50%);
  }
  .clear {
    color: #C6C6C6;
    position: absolute;
    top: -1px;
    right: 24%;
    padding-right: 6px;
    z-index: 11;
  }
  .selected {
    color: #E64A4A;
  }
  .cuIcon-check{
    position: absolute;
    right: 18px;
    font-weight: 400;
    font-size: 16.5px;
    // font-size: 14px;
  }
}
</style>