feat(country): 新增国家地区选择功能,支持常用国家快速选择
This commit is contained in:
parent
00188a9d48
commit
d27e5268f3
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user