From bfd8748554c675feccc07bb19e894c774f2a7f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=A1=E5=A4=8D=E4=B9=A0?= <2353956224@qq.com> Date: Thu, 12 Mar 2026 09:59:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=9B=BD=E5=AE=B6=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/composables/useCountryInfo.js | 190 ++++++++++++++++++++++++++++++ src/views/tk/FanWorkbench.vue | 28 +++-- src/views/tk/Workbenches.vue | 39 +++--- 3 files changed, 230 insertions(+), 27 deletions(-) create mode 100644 src/composables/useCountryInfo.js diff --git a/src/composables/useCountryInfo.js b/src/composables/useCountryInfo.js new file mode 100644 index 0000000..090a4f7 --- /dev/null +++ b/src/composables/useCountryInfo.js @@ -0,0 +1,190 @@ +import { ref } from 'vue' +import { ElMessage, ElMessageBox } from 'element-plus' +import { getCountryName } from '@/utils/countryUtil' + +/** + * 独立的国家信息管理 composable + * 每次调用都会创建独立的状态,适合需要独立国家设置的页面 + */ +export function useCountryInfo() { + // 状态 - 每次调用都是独立的 + const countryData = ref('') // 中文国家名 + const countryDataEN = ref('') // 英文国家名 + const isLoading = ref(false) // 是否正在获取 + const hasInitialized = ref(false) // 是否已初始化 + + /** + * 获取 IP 国家信息 + * @param {Function} t - 国际化函数 + * @param {boolean} showDialog - 获取失败时是否显示弹窗 + */ + 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) + 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 + 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) + } + + /** + * 手动设置国家信息 + * @param {string} countryName - 国家名称 + * @param {Function} t - 国际化函数(可选) + */ + const setCountryManually = (countryName, t = null) => { + if (!countryName || countryName.trim() === '') { + return false + } + + countryData.value = countryName.trim() + countryDataEN.value = countryName.trim() + hasInitialized.value = true + + if (t) { + ElMessage.success(t('workbenchesSetup.countrySetSuccess') || t('hostsList.countrySetSuccess') || '国家设置成功') + } + + return true + } + + /** + * 显示编辑国家的弹窗 + * @param {Function} t - 国际化函数 + * @returns {Promise} 确认时 resolve 新的国家名称,取消时 reject + */ + const showEditCountryDialog = (t) => { + return ElMessageBox.prompt( + t('workbenchesSetup.editCountryPrompt') || t('hostsList.editCountryPrompt') || '请输入国家名称(中文)', + t('workbenchesSetup.editCountryTitle') || t('hostsList.editCountryTitle') || '编辑国家', + { + confirmButtonText: t('workbenchesSetup.confirm') || t('hostsList.confirm') || '确定', + cancelButtonText: t('workbenchesSetup.cancel') || t('hostsList.cancel') || '取消', + inputPlaceholder: t('workbenchesSetup.countryPlaceholder') || t('hostsList.countryPlaceholder') || '例如:美国、日本、英国', + inputValue: countryData.value, + inputValidator: (value) => { + if (!value || value.trim() === '') { + return t('workbenchesSetup.countryRequired') || t('hostsList.countryRequired') || '请输入国家名称' + } + return true + } + } + ).then(({ value }) => { + setCountryManually(value, t) + return value.trim() + }) + } + + return { + // 状态 + countryData, + countryDataEN, + isLoading, + hasInitialized, + + // 方法 + fetchCountryInfo, + refreshCountry, + showCountryInputDialog, + initCountryInfo, + setCountryManually, + showEditCountryDialog, + } +} diff --git a/src/views/tk/FanWorkbench.vue b/src/views/tk/FanWorkbench.vue index 8242f54..093ed30 100644 --- a/src/views/tk/FanWorkbench.vue +++ b/src/views/tk/FanWorkbench.vue @@ -228,7 +228,7 @@ import { getUser } from "@/utils/storage"; import { getCountryName } from "@/utils/countryUtil"; import { ElMessage, ElMessageBox, ElLoading } from "element-plus"; import { useI18n } from 'vue-i18n'; -import { useCountryStore } from '@/stores/countryStore'; +import { useCountryInfo } from '@/composables/useCountryInfo'; // Mock API calls if not present // Ideally we should import these from api file, but for simplicity I will mock them or use empty callbacks @@ -239,7 +239,14 @@ import { useCountryStore } from '@/stores/countryStore'; import { tkbigdata, getCountryinfo } from "@/api/account"; const { t, locale } = useI18n(); -const countryStore = useCountryStore(); +// 使用独立的国家信息管理(不与其他页面共享) +const { + countryData, + isLoading: isRefreshingCountry, + initCountryInfo, + refreshCountry: refreshCountryInfo, + showEditCountryDialog +} = useCountryInfo(); // Component State const queryFormData = ref({ @@ -275,9 +282,8 @@ const streamdialogVisible = ref(false); const streamdialogVisibletext = ref(false); const filterdialogVisible = ref(false); const textarea = ref(""); -// 使用共享 store 的国家信息 -const countryData = computed(() => countryStore.countryData); -const isRefreshingCountry = computed(() => countryStore.isLoading); +// 使用独立的国家信息 +const countryDataRef = countryData; const userInfo = ref({}); const options = ref([]); @@ -326,8 +332,8 @@ const timerId = ref(null); onMounted(async () => { userInfo.value = getUser() || { tenantId: 0, id: 0 }; - // 使用共享 store 初始化国家信息 - await countryStore.initCountryInfo(t); + // 初始化独立的国家信息 + await initCountryInfo(t); getCountry(); getlist(); @@ -564,14 +570,14 @@ function openTikTok() { loginBigTikTok(); } -// 编辑国家信息 - 使用共享 store +// 编辑国家信息 const editCountry = () => { - countryStore.showEditCountryDialog(t); + showEditCountryDialog(t); }; -// 刷新国家信息 - 使用共享 store +// 刷新国家信息 const refreshCountry = async () => { - await countryStore.refreshCountry(t); + await refreshCountryInfo(t); }; function getCountry() { diff --git a/src/views/tk/Workbenches.vue b/src/views/tk/Workbenches.vue index 9cb4809..fd191e3 100644 --- a/src/views/tk/Workbenches.vue +++ b/src/views/tk/Workbenches.vue @@ -123,7 +123,7 @@ :title="$t('workbenchesSetup.editCountry') || '编辑国家'"> edit -