|
@@ -14,19 +14,18 @@
|
|
|
:class="{ 'transparent-header': isSpecialBg }"
|
|
:class="{ 'transparent-header': isSpecialBg }"
|
|
|
>
|
|
>
|
|
|
<div class="logo-title-row">
|
|
<div class="logo-title-row">
|
|
|
- <!-- 左侧:Logo和标题 -->
|
|
|
|
|
|
|
+ <!-- 左侧:Logo 和标题 -->
|
|
|
<div class="left-section">
|
|
<div class="left-section">
|
|
|
<img src="@/assets/logo.png" alt="Logo" class="logo" />
|
|
<img src="@/assets/logo.png" alt="Logo" class="logo" />
|
|
|
<span class="project-name" :class="{ 'light-text': isSpecialBg }">
|
|
<span class="project-name" :class="{ 'light-text': isSpecialBg }">
|
|
|
- <!-- 土壤酸化智能预测专家系统 -->
|
|
|
|
|
- {{ t('Header.title') }}
|
|
|
|
|
|
|
+ {{ t('Header.title') }}
|
|
|
</span>
|
|
</span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 右侧:用户信息 -->
|
|
<!-- 右侧:用户信息 -->
|
|
|
<div class="right-section" v-if="!isSelectCity">
|
|
<div class="right-section" v-if="!isSelectCity">
|
|
|
<div class="user-info-row">
|
|
<div class="user-info-row">
|
|
|
- <div class="lang-buttons" v-if="true"> <!-- 设为false隐藏,选择一种方式即可 -->
|
|
|
|
|
|
|
+ <div class="lang-buttons">
|
|
|
<!-- 语言切换按钮 -->
|
|
<!-- 语言切换按钮 -->
|
|
|
<button
|
|
<button
|
|
|
class="lang-toggle-btn"
|
|
class="lang-toggle-btn"
|
|
@@ -52,12 +51,12 @@
|
|
|
</span>
|
|
</span>
|
|
|
<template #dropdown>
|
|
<template #dropdown>
|
|
|
<el-dropdown-menu>
|
|
<el-dropdown-menu>
|
|
|
- <el-dropdown-item disabled
|
|
|
|
|
- > {{ t('Header.username') }} :{{ userInfo.name }}</el-dropdown-item
|
|
|
|
|
- >
|
|
|
|
|
- <el-dropdown-item divided @click="handleLogout"
|
|
|
|
|
- > {{ t('Header.logout') }} </el-dropdown-item
|
|
|
|
|
- >
|
|
|
|
|
|
|
+ <el-dropdown-item disabled>
|
|
|
|
|
+ {{ t('Header.username') }}: {{ userInfo.name }}
|
|
|
|
|
+ </el-dropdown-item>
|
|
|
|
|
+ <el-dropdown-item divided @click="handleLogout">
|
|
|
|
|
+ {{ t('Header.logout') }}
|
|
|
|
|
+ </el-dropdown-item>
|
|
|
</el-dropdown-menu>
|
|
</el-dropdown-menu>
|
|
|
</template>
|
|
</template>
|
|
|
</el-dropdown>
|
|
</el-dropdown>
|
|
@@ -122,12 +121,11 @@
|
|
|
import { ref, reactive, computed, watch, defineAsyncComponent } from "vue";
|
|
import { ref, reactive, computed, watch, defineAsyncComponent } from "vue";
|
|
|
import { useRouter, useRoute } from "vue-router";
|
|
import { useRouter, useRoute } from "vue-router";
|
|
|
import { useTokenStore } from "@/stores/mytoken";
|
|
import { useTokenStore } from "@/stores/mytoken";
|
|
|
-import { ElMessageBox, ElMessage } from "element-plus"; // 确保导入ElMessage
|
|
|
|
|
|
|
+import { ElMessageBox, ElMessage } from "element-plus";
|
|
|
import { logout } from "@/API/users";
|
|
import { logout } from "@/API/users";
|
|
|
import { useI18n } from 'vue-i18n'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-const { t,locale } =useI18n()
|
|
|
|
|
|
|
+const { t, locale } = useI18n()
|
|
|
const currentLang = ref(locale.value || 'zh')
|
|
const currentLang = ref(locale.value || 'zh')
|
|
|
|
|
|
|
|
// 切换语言
|
|
// 切换语言
|
|
@@ -143,7 +141,7 @@ const changeLanguage = () => {
|
|
|
|
|
|
|
|
// 按钮点击切换
|
|
// 按钮点击切换
|
|
|
const toggleLanguage = () => {
|
|
const toggleLanguage = () => {
|
|
|
- currentLang.value = currentLang.value === 'zh' ?'en':'zh'
|
|
|
|
|
|
|
+ currentLang.value = currentLang.value === 'zh' ? 'en' : 'zh'
|
|
|
changeLanguage()
|
|
changeLanguage()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -152,7 +150,6 @@ watch(locale, (newVal) => {
|
|
|
currentLang.value = newVal
|
|
currentLang.value = newVal
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-
|
|
|
|
|
const router = useRouter();
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
const route = useRoute();
|
|
|
const tokenStore = useTokenStore();
|
|
const tokenStore = useTokenStore();
|
|
@@ -161,11 +158,10 @@ const currentBgImage = ref("");
|
|
|
// ============ 新增状态 ============
|
|
// ============ 新增状态 ============
|
|
|
const showGlobalMessage = ref(false);
|
|
const showGlobalMessage = ref(false);
|
|
|
const globalMessage = ref("");
|
|
const globalMessage = ref("");
|
|
|
-const messageType = ref("success"); // 消息类型: success/error
|
|
|
|
|
|
|
+const messageType = ref("success");
|
|
|
|
|
|
|
|
currentBgImage.value = `url(${new URL('../../assets/bg/background.jpg', import.meta.url).href})`;
|
|
currentBgImage.value = `url(${new URL('../../assets/bg/background.jpg', import.meta.url).href})`;
|
|
|
|
|
|
|
|
-// 是否特殊背景(始终返回true → 所有页面应用特殊背景样式)
|
|
|
|
|
const isSpecialBg = computed(() => true);
|
|
const isSpecialBg = computed(() => true);
|
|
|
|
|
|
|
|
const backgroundStyle = computed(() => ({
|
|
const backgroundStyle = computed(() => ({
|
|
@@ -186,152 +182,79 @@ const userInfo = reactive({
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const tabs = computed(() => {
|
|
const tabs = computed(() => {
|
|
|
-
|
|
|
|
|
- if (userInfo.type === "admin") {
|
|
|
|
|
-
|
|
|
|
|
- return [
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "dataManagement",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.dataManagement'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-folder",
|
|
|
|
|
-
|
|
|
|
|
- routes: [
|
|
|
|
|
-
|
|
|
|
|
- "/soilAcidReductionData",
|
|
|
|
|
-
|
|
|
|
|
- "/soilAcidificationData",
|
|
|
|
|
-
|
|
|
|
|
- "/crossSectionSampleData",
|
|
|
|
|
-
|
|
|
|
|
- "/irrigationWaterInputFluxData",
|
|
|
|
|
-
|
|
|
|
|
- "/heavyMetalEnterpriseData",
|
|
|
|
|
-
|
|
|
|
|
- "/atmosphericSampleData",
|
|
|
|
|
-
|
|
|
|
|
- ],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "infoManagement",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.infoManagement'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-document",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/IntroductionUpdate"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "modelManagement",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.modelManagement'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-cpu",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/ModelSelection", "/thres", "/ModelTrain"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "userManagement",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.userManagement'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-user",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/UserManagement"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- } else {
|
|
|
|
|
-
|
|
|
|
|
- return [
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "introduction",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.swIntroduce'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-info-filled",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/SoilPro", "/Overview", "/ResearchFindings", "/Unit"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
- name: "acidmodelmap",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.mapcalulate'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-data-analysis",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/shaoguan_acidmodelmap","nanxiong_acidmodelmap"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "Calculation",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.reversionmodel'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-data-analysis",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/Calculation", "/SoilAcidReductionIterativeEvolution"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "AcidNeutralizationModel",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.reducemodel'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-data-analysis",
|
|
|
|
|
-
|
|
|
|
|
- routes: ["/AcidNeutralizationModel", "/SoilAcidificationIterativeEvolution"],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- {
|
|
|
|
|
-
|
|
|
|
|
- name: "dataStatistics",
|
|
|
|
|
-
|
|
|
|
|
- label: t('Menu.dataStatistics'),
|
|
|
|
|
-
|
|
|
|
|
- icon: "el-icon-pie-chart",
|
|
|
|
|
-
|
|
|
|
|
- routes: [
|
|
|
|
|
-
|
|
|
|
|
- "/DetectionStatistics",
|
|
|
|
|
-
|
|
|
|
|
- "/FarmlandPollutionStatistics",
|
|
|
|
|
-
|
|
|
|
|
- "/LandClutivatesStatistics",
|
|
|
|
|
-
|
|
|
|
|
- "/SoilacidificationStatistics",
|
|
|
|
|
-
|
|
|
|
|
- ],
|
|
|
|
|
-
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- ];
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if (userInfo.type === "admin") {
|
|
|
|
|
+ return [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "dataManagement",
|
|
|
|
|
+ label: t('Menu.dataManagement'),
|
|
|
|
|
+ icon: "el-icon-folder",
|
|
|
|
|
+ routes: [
|
|
|
|
|
+ "/soilAcidReductionData",
|
|
|
|
|
+ "/soilAcidificationData",
|
|
|
|
|
+ "/crossSectionSampleData",
|
|
|
|
|
+ "/irrigationWaterInputFluxData",
|
|
|
|
|
+ "/heavyMetalEnterpriseData",
|
|
|
|
|
+ "/atmosphericSampleData",
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "infoManagement",
|
|
|
|
|
+ label: t('Menu.infoManagement'),
|
|
|
|
|
+ icon: "el-icon-document",
|
|
|
|
|
+ routes: ["/IntroductionUpdate"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "modelManagement",
|
|
|
|
|
+ label: t('Menu.modelManagement'),
|
|
|
|
|
+ icon: "el-icon-cpu",
|
|
|
|
|
+ routes: ["/ModelSelection", "/thres", "/ModelTrain"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "userManagement",
|
|
|
|
|
+ label: t('Menu.userManagement'),
|
|
|
|
|
+ icon: "el-icon-user",
|
|
|
|
|
+ routes: ["/UserManagement"],
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "introduction",
|
|
|
|
|
+ label: t('Menu.swIntroduce'),
|
|
|
|
|
+ icon: "el-icon-info-filled",
|
|
|
|
|
+ routes: ["/SoilPro", "/Overview", "/ResearchFindings", "/Unit"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "acidmodelmap",
|
|
|
|
|
+ label: t('Menu.mapcalulate'),
|
|
|
|
|
+ icon: "el-icon-data-analysis",
|
|
|
|
|
+ routes: ["/shaoguan_acidmodelmap","nanxiong_acidmodelmap"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "Calculation",
|
|
|
|
|
+ label: t('Menu.reversionmodel'),
|
|
|
|
|
+ icon: "el-icon-data-analysis",
|
|
|
|
|
+ routes: ["/Calculation", "/SoilAcidReductionIterativeEvolution"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "AcidNeutralizationModel",
|
|
|
|
|
+ label: t('Menu.reducemodel'),
|
|
|
|
|
+ icon: "el-icon-data-analysis",
|
|
|
|
|
+ routes: ["/AcidNeutralizationModel", "/SoilAcidificationIterativeEvolution"],
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ name: "dataStatistics",
|
|
|
|
|
+ label: t('Menu.dataStatistics'),
|
|
|
|
|
+ icon: "el-icon-pie-chart",
|
|
|
|
|
+ routes: [
|
|
|
|
|
+ "/DetectionStatistics",
|
|
|
|
|
+ "/FarmlandPollutionStatistics",
|
|
|
|
|
+ "/LandClutivatesStatistics",
|
|
|
|
|
+ "/SoilacidificationStatistics",
|
|
|
|
|
+ ],
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const activeName = ref(tabs.value[0]?.name || "");
|
|
const activeName = ref(tabs.value[0]?.name || "");
|
|
@@ -356,13 +279,11 @@ watch(
|
|
|
{ immediate: true }
|
|
{ immediate: true }
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
-// 点击 tab
|
|
|
|
|
const activeAsideTab = ref(activeName.value || "");
|
|
const activeAsideTab = ref(activeName.value || "");
|
|
|
const handleClick = (tab: any, _event?: Event) => {
|
|
const handleClick = (tab: any, _event?: Event) => {
|
|
|
activeAsideTab.value = tab.name || tab.props?.name;
|
|
activeAsideTab.value = tab.name || tab.props?.name;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-// 动态加载侧边栏
|
|
|
|
|
const AsideComponent = computed(() => {
|
|
const AsideComponent = computed(() => {
|
|
|
return [
|
|
return [
|
|
|
"dataManagement",
|
|
"dataManagement",
|
|
@@ -374,50 +295,47 @@ const AsideComponent = computed(() => {
|
|
|
: defineAsyncComponent(() => import("./AppAside.vue"));
|
|
: defineAsyncComponent(() => import("./AppAside.vue"));
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
-// 是否显示侧边栏
|
|
|
|
|
const showAside = computed(
|
|
const showAside = computed(
|
|
|
() =>
|
|
() =>
|
|
|
!isFullScreen.value && !["cropRiskAssessment"].includes(activeName.value)
|
|
!isFullScreen.value && !["cropRiskAssessment"].includes(activeName.value)
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
-// ============ 显示全局消息 ============
|
|
|
|
|
|
|
+const mainStyle = computed(() => ({
|
|
|
|
|
+ padding: ["mapView", "infoManagement"].includes(activeName.value)
|
|
|
|
|
+ ? "0"
|
|
|
|
|
+ : "20px",
|
|
|
|
|
+ overflow: "hidden",
|
|
|
|
|
+}));
|
|
|
|
|
|
|
|
-// 登出逻辑
|
|
|
|
|
|
|
+// 登出逻辑 - 支持多语言
|
|
|
const handleLogout = async () => {
|
|
const handleLogout = async () => {
|
|
|
try {
|
|
try {
|
|
|
- await ElMessageBox.confirm("确定要退出登录吗?", "提示", {
|
|
|
|
|
- confirmButtonText: "确定",
|
|
|
|
|
- cancelButtonText: "取消",
|
|
|
|
|
- type: "warning",
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ await ElMessageBox.confirm(
|
|
|
|
|
+ t('logout.confirmMessage'),
|
|
|
|
|
+ t('logout.confirmTitle'),
|
|
|
|
|
+ {
|
|
|
|
|
+ confirmButtonText: t('logout.confirmButton'),
|
|
|
|
|
+ cancelButtonText: t('logout.cancelButton'),
|
|
|
|
|
+ type: "warning",
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
await logout();
|
|
await logout();
|
|
|
tokenStore.clearToken();
|
|
tokenStore.clearToken();
|
|
|
|
|
|
|
|
- // 使用ElMessage而不是全局消息提示
|
|
|
|
|
- ElMessage.success("退出登录成功");
|
|
|
|
|
|
|
+ ElMessage.success(t('logout.logoutSuccess'));
|
|
|
|
|
|
|
|
- // 延迟跳转,让用户看到提示消息
|
|
|
|
|
setTimeout(() => {
|
|
setTimeout(() => {
|
|
|
router.push("/login");
|
|
router.push("/login");
|
|
|
}, 1000);
|
|
}, 1000);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
- // 区分用户取消操作和真正的错误
|
|
|
|
|
if (error === 'cancel' || error?.toString().includes('cancel')) {
|
|
if (error === 'cancel' || error?.toString().includes('cancel')) {
|
|
|
- // console.log("用户取消退出登录");
|
|
|
|
|
|
|
+ // 用户取消操作
|
|
|
} else {
|
|
} else {
|
|
|
- ElMessage.error("退出失败,请重试");
|
|
|
|
|
|
|
+ ElMessage.error(t('logout.logoutFailed'));
|
|
|
console.error("退出登录错误:", error);
|
|
console.error("退出登录错误:", error);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
-
|
|
|
|
|
-// 内容区样式
|
|
|
|
|
-const mainStyle = computed(() => ({
|
|
|
|
|
- padding: ["mapView", "infoManagement"].includes(activeName.value)
|
|
|
|
|
- ? "0"
|
|
|
|
|
- : "20px",
|
|
|
|
|
- overflow: "hidden",
|
|
|
|
|
-}));
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style>
|
|
<style>
|