Files
web-fusion/src/stores/countryStore.js
2026-02-09 21:04:09 +08:00

144 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getCountryName } from '@/utils/countryUtil'
export const useCountryStore = defineStore('country', () => {
// 状态
const countryData = ref('') // 中文国家名
const countryDataEN = ref('') // 英文国家名
const isLoading = ref(false) // 是否正在获取
const hasInitialized = ref(false) // 是否已初始化
const lastFetchTime = ref(null) // 上次获取时间
/**
* 获取 IP 国家信息
* @param {Function} t - 国际化函数
* @param {boolean} showDialog - 获取失败时是否显示弹窗(默认 true只在第一次获取时显示
*/
const fetchCountryInfo = async (t, showDialog = true) => {
if (isLoading.value) return
isLoading.value = true
try {
const response = await fetch('https://ipapi.co/json/')
if (!response.ok) {
throw new Error('请求失败')
}
const data = await response.json()
countryDataEN.value = data.country_name
countryData.value = getCountryName(data.country)
lastFetchTime.value = Date.now()
hasInitialized.value = true
return { success: true }
} catch (error) {
console.error('获取国家信息失败:', error)
// 只在允许显示弹窗且未初始化时才显示
if (showDialog && !hasInitialized.value) {
showCountryInputDialog(t)
}
return { success: false, error }
} finally {
isLoading.value = false
}
}
/**
* 刷新国家信息
* @param {Function} t - 国际化函数
*/
const refreshCountry = async (t) => {
if (isLoading.value) return
try {
const result = await fetchCountryInfo(t, false) // 刷新时不自动弹窗
if (result.success) {
ElMessage.success(t('workbenchesSetup.refreshSuccess') || t('hostsList.refreshSuccess') || '刷新成功')
} else {
// 刷新失败时,给用户选择是否手动输入
ElMessageBox.confirm(
t('workbenchesSetup.refreshFailed') || t('hostsList.refreshFailed') || '刷新失败,是否手动输入国家?',
t('workbenchesSetup.enterCountryTitle') || t('hostsList.enterCountryTitle') || '提示',
{
confirmButtonText: t('workbenchesSetup.confirm') || t('hostsList.confirm') || '手动输入',
cancelButtonText: t('workbenchesSetup.cancel') || t('hostsList.cancel') || '取消',
type: 'warning',
}
).then(() => {
showCountryInputDialog(t)
}).catch(() => {
// 用户取消
})
}
} catch (error) {
ElMessage.error(t('workbenchesSetup.refreshFailed') || t('hostsList.refreshFailed') || '刷新失败')
}
}
/**
* 显示手动输入国家的弹窗
* @param {Function} t - 国际化函数
*/
const showCountryInputDialog = (t) => {
ElMessageBox.prompt(
t('workbenchesSetup.enterCountryPrompt') || t('hostsList.enterCountryPrompt') || '由于网络原因无法自动获取国家信息,请手动输入当前网络所在国家(中文名)',
t('workbenchesSetup.enterCountryTitle') || t('hostsList.enterCountryTitle') || '获取国家失败',
{
confirmButtonText: t('workbenchesSetup.confirm') || t('hostsList.confirm') || '确定',
cancelButtonText: t('workbenchesSetup.cancel') || t('hostsList.cancel') || '取消',
inputPlaceholder: t('workbenchesSetup.countryPlaceholder') || t('hostsList.countryPlaceholder') || '例如:美国、日本、英国',
inputValidator: (value) => {
if (!value || value.trim() === '') {
return t('workbenchesSetup.countryRequired') || t('hostsList.countryRequired') || '请输入国家名称'
}
return true
}
}
).then(({ value }) => {
countryData.value = value.trim()
countryDataEN.value = value.trim()
hasInitialized.value = true
lastFetchTime.value = Date.now()
ElMessage.success(t('workbenchesSetup.countrySetSuccess') || t('hostsList.countrySetSuccess') || '国家设置成功')
}).catch(() => {
// 用户取消输入
if (!hasInitialized.value) {
countryData.value = t('workbenchesSetup.unknown') || t('hostsList.unknown') || '未知'
countryDataEN.value = 'Unknown'
hasInitialized.value = true
}
})
}
/**
* 初始化国家信息(只在第一次调用时获取)
* @param {Function} t - 国际化函数
*/
const initCountryInfo = async (t) => {
if (hasInitialized.value) {
return // 已经初始化过,不再重复获取
}
await fetchCountryInfo(t, true)
}
return {
// 状态
countryData,
countryDataEN,
isLoading,
hasInitialized,
lastFetchTime,
// 方法
fetchCountryInfo,
refreshCountry,
showCountryInputDialog,
initCountryInfo,
}
})