个人基于vue3+TS+ant 实现城市三字码选择小组件

页面效果图

在这里插入图片描述
在这里插入图片描述

核心代码

<template>
  <a-popover
    v-model:open="visible"
    class="city-popover"
    title="支持城市检索"
    trigger="click"
    :destroyTooltipOnHide="true"
    placement="bottomLeft"
  >
    <template #content>
      <div class="city-main-box">
        <!-- 输入检索 -->
        <a-input v-model:value="searchValue" placeholder="输入城市名称检索" />
        <!-- 输入检索列表 -->
        <div class="search-value-list" v-if="searchList?.length > 0">
          <a-list :data-source="searchList">
            <template #renderItem="{ item }">
              <a-list-item class="pointer" @click="choseCity(item)">
                <div>{{ item.name }}</div>
                <div>{{ item.provinceName }}</div>
              </a-list-item>
            </template>
          </a-list>
          <a-pagination size="small" @change="listDistrictBySyRun" v-model:current="current" :total="total" show-less-items />
        </div>
        <!-- 默认城市三字码 -->
        <a-tabs v-model:activeKey="activeKey" v-else>
          <a-tab-pane v-for="tab in cityOptions" :key="tab.key" :tab="tab.label">
            <div class="city-list">
              <div class="city-box" v-for="(city, index) in tab?.children" :key="index">
                <div class="box-left">{{ city.label }}</div>
                <div class="box-right">
                  <a-button v-for="(item, index) in city?.children" :key="index" @click="choseCity(item)" type="text">{{
                    item.name
                  }}</a-button>
                </div>
              </div>
            </div>
          </a-tab-pane>
        </a-tabs>
      </div>
    </template>
    <a-input class="city-chose-input" readonly :bordered="props.bordered" v-model:value="props.value" placeholder="选择城市" />
  </a-popover>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch, watchEffect, toRefs, createVNode } from 'vue';
import { DataType, usePagination, useRequest } from 'vue-request';

const emit = defineEmits(['chosedCity']);
interface Props {
    value: string
    placeholder?: string
    bordered?: boolean
    index?: number
    i?: number
}

const props = withDefaults(defineProps<Props>(), {
    value: '',
    bordered: true,
    placeholder: '请选择',
});

const searchValue = ref<string>('');
const visible = ref<boolean>(false);
const activeKey = ref<number>(0);
const current = ref(1);
const total = ref<number>(0);

// const searchList = ref<Array<object>>([]);

const {
  data: cityOptions,
  run: getInitialGroupingCityRun,
  loading: getInitialGroupingCityLoading,
} = useRequest(cityApi.getInitialGroupingCity, {
  defaultParams: [],
  onSuccess: () => {
    // detailsApiRun({ todoId: todoId.value, code: code.value })
  },
  manual: false,
});


const searchList = ref<Array<CityResponse>>([])

const listDistrictBySyRun = () => {
  cityApi.listDistrictBySy(searchValue.value, 8, current.value).then(res => {
    total.value = res.total 
    searchList.value = res.records
  })
}



const choseCity = (city: CityItem) => {
  debugger
  searchList.value = [];
  visible.value = false;
  searchValue.value = '';
  emit('chosedCity', city);
};
watch(
  searchValue,
  (newVal) => {
    if (!newVal) {
      searchList.value = [];
      return;
    }
    current.value = 1
    listDistrictBySyRun();
  },
  {
    deep: true,
  },
);
</script>

<style scoped lang="less">
.city-main-box {
  width: 600px;
  .pointer{
    cursor: pointer;
  }
}
.city-list {
  .city-box {
    display: flex;
    border-bottom: 1px solid #eee;
    .box-left {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 10%;
      color: orange;
      font-size: 20px;
    }
    .box-right {
      display: flex;
      flex-wrap: wrap;
      flex: 1;
    }
  }
}
</style>

城市数据太大无法贴过来,如果有需要可以私聊看见就发

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值