feat(country): 新增国家地区选择功能,支持常用国家快速选择

This commit is contained in:
scout 2025-01-15 13:05:07 +08:00
parent 00188a9d48
commit d27e5268f3

View File

@ -3,37 +3,69 @@ import {ref, computed, watch} from 'vue';
import pinyin from 'pinyin'; import pinyin from 'pinyin';
import countryCode from './data/index.js'; import countryCode from './data/index.js';
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
definePageMeta({
title: '国家地区',
i18n: 'countryRegion.title',
})
const router = useRouter()
const { t, locale } = useI18n() const { t, locale } = useI18n()
const value = ref(''); const value = ref('');
const alphabet = [ const alphabet = [
'#',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]; ];
//
const frequentCountryCodes = ['CN', 'TW', 'JP', 'US'];
function groupByPinyinInitial(data) { function groupByPinyinInitial(data) {
const grouped = {}; const grouped = {};
//
grouped['#'] = [];
data.forEach(country => { data.forEach(country => {
// if (frequentCountryCodes.includes(country.code)) {
const countryName = locale.value === 'zh-CN' ? country.cn : const countryName = locale.value === 'zh-CN' ? country.cn :
locale.value === 'zh-TW' ? country.tw : locale.value === 'zh-TW' ? country.tw :
locale.value === 'ja-JP' ? country.ja : locale.value === 'ja-JP' ? country.ja :
country.en; country.en;
grouped['#'].push({
const initial = locale.value === 'ja-JP' ? '' : ...country,
locale.value === 'zh-CN' || locale.value === 'zh-TW' ? displayName: countryName
pinyin(countryName, {style: pinyin.STYLE_FIRST_LETTER})[0][0].toUpperCase() : });
countryName.charAt(0).toUpperCase();
if (!grouped[initial]) {
grouped[initial] = [];
} }
grouped[initial].push({
...country,
displayName: countryName
});
}); });
//
data.forEach(country => {
if (!frequentCountryCodes.includes(country.code)) {
const countryName = locale.value === 'zh-CN' ? country.cn :
locale.value === 'zh-TW' ? country.tw :
locale.value === 'ja-JP' ? country.ja :
country.en;
const initial = locale.value === 'ja-JP' ? '' :
locale.value === 'zh-CN' || locale.value === 'zh-TW' ?
pinyin(countryName, {style: pinyin.STYLE_FIRST_LETTER})[0][0].toUpperCase() :
countryName.charAt(0).toUpperCase();
if (!grouped[initial]) {
grouped[initial] = [];
}
grouped[initial].push({
...country,
displayName: countryName
});
}
});
if (locale.value === 'ja-JP') {
//
grouped[''] = grouped[''].sort((a, b) => a.displayName.localeCompare(b.displayName, 'ja-JP'));
}
return grouped; return grouped;
} }
@ -59,6 +91,16 @@ const searchCountry = computed(() => {
const showIndexBar = computed(() => locale.value !== 'ja-JP') const showIndexBar = computed(() => locale.value !== 'ja-JP')
const handleCountrySelect = (country) => {
router.push({
path: '/login',
query: {
zone: country.zone,
countryName: country.displayName
}
})
}
initData() initData()
// //
@ -78,20 +120,58 @@ watch(locale, () => {
:sticky-offset-top="55" :sticky-offset-top="55"
:index-list="alphabet" :index-list="alphabet"
> >
<!-- 常用国家分类 -->
<van-index-anchor index="#">{{ t('countryRegion.frequentCountry') }}</van-index-anchor>
<van-cell
v-for="country in searchCountry['#']"
:key="country.code"
:title="country.displayName"
@click="handleCountrySelect(country)"
clickable
>
<div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell>
<!-- 其他国家按字母分类 -->
<template v-for="(countries, index) in searchCountry" :key="index"> <template v-for="(countries, index) in searchCountry" :key="index">
<van-index-anchor <template v-if="index !== '#'">
:index="index" <van-index-anchor
></van-index-anchor> :index="index"
<van-cell v-for="country in countries" :key="country.code" :title="country.displayName"> ></van-index-anchor>
<div class="pr-[25px]"> +{{ country.zone }}</div> <van-cell
</van-cell> v-for="country in countries"
:key="country.code"
:title="country.displayName"
@click="handleCountrySelect(country)"
clickable
>
<div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell>
</template>
</template> </template>
</van-index-bar> </van-index-bar>
<div v-else> <div v-else>
<van-cell v-for="country in Object.values(searchCountry).flat()" <div class="mb-4">
:key="country.code" <div class="px-4 py-2 text-gray-600">{{ t('countryRegion.frequentCountry') }}</div>
:title="country.displayName"> <van-cell
v-for="country in searchCountry['#']"
:key="country.code"
:title="country.displayName"
@click="handleCountrySelect(country)"
clickable
>
<div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell>
</div>
<van-cell
v-for="country in Object.values(searchCountry).flat().filter(c => !frequentCountryCodes.includes(c.code))"
:key="country.code"
:title="country.displayName"
@click="handleCountrySelect(country)"
clickable
>
<div class="pr-[25px]"> +{{ country.zone }}</div> <div class="pr-[25px]"> +{{ country.zone }}</div>
</van-cell> </van-cell>
</div> </div>