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
-