diff --git a/.env.development b/.env.development index 399bf06..ccc0503 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,5 @@ # 页面标题 -VITE_APP_TITLE = 星汉研创科技 +VITE_APP_TITLE = 云平台管理系统 # 开发环境配置 VITE_APP_ENV = 'development' diff --git a/.env.production b/.env.production index 8ef038f..cb8d349 100644 --- a/.env.production +++ b/.env.production @@ -1,5 +1,5 @@ # 页面标题 -VITE_APP_TITLE = 星汉研创科技 +VITE_APP_TITLE = 云平台管理系统 # 生产环境配置 晶全1 VITE_APP_ENV = 'https://fuyuanshen.com/backend' diff --git a/src/App.vue b/src/App.vue index 617a10e..8edf94e 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,8 +8,10 @@ import { useSettingsStore } from '@/store/modules/settings'; import { handleThemeStyle } from '@/utils/theme'; import { useAppStore } from '@/store/modules/app'; +import { useUserStore } from '@/store/modules/user'; const appStore = useAppStore(); +const userStore = useUserStore(); onMounted(() => { nextTick(() => { @@ -17,4 +19,19 @@ onMounted(() => { handleThemeStyle(useSettingsStore().theme); }); }); + +// 监听租户名称变化,动态更新页面标题 +watch( + () => userStore.tenantName, + (value) => { + if (value) { + document.title = userStore.tenantName; + } else { + document.title = import.meta.env.VITE_APP_TITLE; + } + }, + { + immediate: true, + } +); diff --git a/src/api/types.ts b/src/api/types.ts index 617286c..39695a5 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -16,6 +16,7 @@ export type RegisterForm = { */ export interface LoginData { tenantId?: string; + tenantName?: string; username?: string; password?: string; rememberMe?: boolean; diff --git a/src/assets/styles/variables.module.scss b/src/assets/styles/variables.module.scss index a7959e1..b06082e 100644 --- a/src/assets/styles/variables.module.scss +++ b/src/assets/styles/variables.module.scss @@ -130,7 +130,7 @@ $--color-warning: #e6a23c; $--color-danger: #f56c6c; $--color-info: #909399; -$base-sidebar-width: 200px; +$base-sidebar-width: 280px; // the :export directive is the magic sauce for webpack // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue index cbc5048..4a4d2d7 100644 --- a/src/layout/components/Sidebar/Logo.vue +++ b/src/layout/components/Sidebar/Logo.vue @@ -5,14 +5,7 @@ :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }" > - - -

- {{ title }} -

-
- - +

{{ title }}

@@ -23,8 +16,8 @@ @@ -62,33 +61,25 @@ const sideTheme = computed(() => settingsStore.sideTheme); height: 100%; width: 100%; - & .sidebar-logo { - width: 32px; - height: 32px; - vertical-align: middle; - margin-right: 12px; - } - & .sidebar-title { - display: inline-block; + display: block; margin: 0; + padding: 0 15px; // 增加左右内边距 color: #fff; font-weight: 600; line-height: 50px; - font-size: 16px; // 匹配设计UI的字体大小 + font-size: 16px; // 恢复正常字体大小 font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; - vertical-align: middle; - } - } - - &.collapse { - .sidebar-logo { - margin-right: 0px; + width: 100%; // 使用全宽 + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + text-align: center; // 居中显示 } } } diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index b714d03..2540cb0 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -12,6 +12,8 @@ export const useUserStore = defineStore('user', () => { const nickname = ref(''); const userId = ref(''); const tenantId = ref(''); + // 从 localStorage 恢复租户名称 + const tenantName = ref(localStorage.getItem('currentTenantName') || ''); const avatar = ref(''); const roles = ref>([]); // 用户角色编码集合 → 判断路由权限 const permissions = ref>([]); // 用户权限编码集合 → 判断按钮权限 @@ -27,6 +29,10 @@ export const useUserStore = defineStore('user', () => { const data = res.data; setToken(data.access_token); token.value = data.access_token; + // 设置租户名称 + if (userInfo.tenantName) { + tenantName.value = userInfo.tenantName; + } return Promise.resolve(); } return Promise.reject(err); @@ -61,9 +67,12 @@ export const useUserStore = defineStore('user', () => { const logout = async (): Promise => { await logoutApi(); token.value = ''; + tenantName.value = ''; roles.value = []; permissions.value = []; removeToken(); + // 清除保存的租户名称 + localStorage.removeItem('currentTenantName'); }; const setAvatar = (value: string) => { @@ -73,6 +82,7 @@ export const useUserStore = defineStore('user', () => { return { userId, tenantId, + tenantName, token, nickname, avatar, diff --git a/src/utils/dynamicTitle.ts b/src/utils/dynamicTitle.ts index 8e23ef8..bdcf0ab 100644 --- a/src/utils/dynamicTitle.ts +++ b/src/utils/dynamicTitle.ts @@ -1,12 +1,18 @@ import defaultSettings from '@/settings'; import { useSettingsStore } from '@/store/modules/settings'; +import { useUserStore } from '@/store/modules/user'; /** * 动态修改标题 */ export const useDynamicTitle = () => { const settingsStore = useSettingsStore(); - if (settingsStore.dynamicTitle) { + const userStore = useUserStore(); + + // 优先使用租户名称 + if (userStore.tenantName) { + document.title = userStore.tenantName; + } else if (settingsStore.dynamicTitle) { document.title = settingsStore.title + ' - ' + import.meta.env.VITE_APP_TITLE; } else { document.title = defaultSettings.title as string; diff --git a/src/views/equipmentManagement/deviceType/index.vue b/src/views/equipmentManagement/deviceType/index.vue index f8d8a64..6bbc86a 100644 --- a/src/views/equipmentManagement/deviceType/index.vue +++ b/src/views/equipmentManagement/deviceType/index.vue @@ -42,7 +42,7 @@ @@ -119,11 +119,11 @@ - - - - - + + + + + @@ -132,8 +132,8 @@ - - + + @@ -160,9 +160,9 @@ interface deviceTypeVO { id: string | number; typeName: string; isSupportBle: boolean; - locateMode: string; + locateMode: number; modelDictionary: string; - communicationMode: string; + communicationMode: number; createTime: string; createByName: string; } @@ -188,9 +188,9 @@ const dialog = reactive({ const initFormData: DeviceTypeForm = { typeName: '', isSupportBle: false, - locateMode: '', + locateMode: 0, modelDictionary: '', - communicationMode: '', + communicationMode: 0, id: '', createTime: '', createByName: '', @@ -300,9 +300,10 @@ const handleUpdate = async (row?: DeviceTypeForm) => { try { const deviceData = row || ids.value[0]; Object.assign(form.value, deviceData); - if (form.value.modelDictionary) { - form.value.modelDictionary = String(form.value.modelDictionary); - } + // 确保数据类型正确 + form.value.modelDictionary = String(form.value.modelDictionary || ''); + form.value.locateMode = Number(form.value.locateMode) || 0; + form.value.communicationMode = Number(form.value.communicationMode) || 0; } catch (error) { dialog.visible = false; } @@ -316,7 +317,9 @@ const submitForm = () => { try { const payload = { ...form.value, - modelDictionary: Number(form.value.modelDictionary) + modelDictionary: form.value.modelDictionary, + locateMode: Number(form.value.locateMode), + communicationMode: Number(form.value.communicationMode) }; form.value.id ? await api.updateDeviceType(payload) : await api.addDeviceType(payload); proxy?.$modal.msgSuccess('操作成功'); diff --git a/src/views/login.vue b/src/views/login.vue index 2943f0a..ea0a28b 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -6,7 +6,7 @@ + style="width: 100%" @change="onTenantChange"> @@ -56,7 +56,7 @@ import { HttpStatus } from '@/enums/RespEnum'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const title = import.meta.env.VITE_APP_TITLE; +const title = ref(import.meta.env.VITE_APP_TITLE); const userStore = useUserStore(); const router = useRouter(); @@ -102,19 +102,30 @@ const handleLogin = () => { loginRef.value?.validate(async (valid: boolean, fields: any) => { if (valid) { loading.value = true; + // 获取选中租户的名称并设置到登录表单中 + const tenantName = tenantList.value.find(item => item.tenantId === loginForm.value.tenantId)?.companyName; + loginForm.value.tenantName = tenantName; + // 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码 if (loginForm.value.rememberMe) { localStorage.setItem('tenantId', String(loginForm.value.tenantId)); + localStorage.setItem('tenantName', String(tenantName || '')); localStorage.setItem('username', String(loginForm.value.username)); localStorage.setItem('password', String(loginForm.value.password)); localStorage.setItem('rememberMe', String(loginForm.value.rememberMe)); } else { // 否则移除 localStorage.removeItem('tenantId'); + localStorage.removeItem('tenantName'); localStorage.removeItem('username'); localStorage.removeItem('password'); localStorage.removeItem('rememberMe'); } + + // 无论是否记住密码,都保存租户名称用于页面刷新时恢复 + if (tenantName) { + localStorage.setItem('currentTenantName', tenantName); + } // 调用action的登录方法 const [err] = await to(userStore.login(loginForm.value)); if (!err) { @@ -170,6 +181,8 @@ const initTenantList = async () => { tenantList.value = data.voList; if (tenantList.value != null && tenantList.value.length !== 0) { loginForm.value.tenantId = tenantList.value[0].tenantId; + // 初始化标题为第一个租户的名称 + onTenantChange(tenantList.value[0].tenantId); } } }; @@ -189,6 +202,21 @@ const doSocialLogin = (type: string) => { }); }; +/** + * 租户变化时更新标题 + */ +const onTenantChange = (tenantId: string) => { + const selectedTenant = tenantList.value.find(item => item.tenantId === tenantId); + if (selectedTenant) { + title.value = selectedTenant.companyName; + // 同时更新页面标题 + document.title = selectedTenant.companyName; + } else { + title.value = import.meta.env.VITE_APP_TITLE; + document.title = import.meta.env.VITE_APP_TITLE; + } +}; + onMounted(() => { getCode(); initTenantList();