forked from dyf/dyf-vue-ui
Compare commits
4 Commits
8753b8c251
...
1cfb5581c8
Author | SHA1 | Date | |
---|---|---|---|
1cfb5581c8 | |||
d96b28a0b9 | |||
0d8f101582 | |||
e4eace467f |
@ -1,5 +1,5 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 星汉研创科技
|
VITE_APP_TITLE = 云平台管理系统
|
||||||
|
|
||||||
# 开发环境配置
|
# 开发环境配置
|
||||||
VITE_APP_ENV = 'development'
|
VITE_APP_ENV = 'development'
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 星汉研创科技
|
VITE_APP_TITLE = 云平台管理系统
|
||||||
|
|
||||||
# 生产环境配置 晶全1
|
# 生产环境配置 晶全1
|
||||||
VITE_APP_ENV = 'https://fuyuanshen.com/backend'
|
VITE_APP_ENV = 'https://fuyuanshen.com/backend'
|
||||||
|
17
src/App.vue
17
src/App.vue
@ -8,8 +8,10 @@
|
|||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
import { handleThemeStyle } from '@/utils/theme';
|
import { handleThemeStyle } from '@/utils/theme';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
|
import { useUserStore } from '@/store/modules/user';
|
||||||
|
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -17,4 +19,19 @@ onMounted(() => {
|
|||||||
handleThemeStyle(useSettingsStore().theme);
|
handleThemeStyle(useSettingsStore().theme);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 监听租户名称变化,动态更新页面标题
|
||||||
|
watch(
|
||||||
|
() => userStore.tenantName,
|
||||||
|
(value) => {
|
||||||
|
if (value) {
|
||||||
|
document.title = userStore.tenantName;
|
||||||
|
} else {
|
||||||
|
document.title = import.meta.env.VITE_APP_TITLE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
@ -16,6 +16,7 @@ export type RegisterForm = {
|
|||||||
*/
|
*/
|
||||||
export interface LoginData {
|
export interface LoginData {
|
||||||
tenantId?: string;
|
tenantId?: string;
|
||||||
|
tenantName?: string;
|
||||||
username?: string;
|
username?: string;
|
||||||
password?: string;
|
password?: string;
|
||||||
rememberMe?: boolean;
|
rememberMe?: boolean;
|
||||||
|
@ -130,7 +130,7 @@ $--color-warning: #e6a23c;
|
|||||||
$--color-danger: #f56c6c;
|
$--color-danger: #f56c6c;
|
||||||
$--color-info: #909399;
|
$--color-info: #909399;
|
||||||
|
|
||||||
$base-sidebar-width: 200px;
|
$base-sidebar-width: 280px;
|
||||||
|
|
||||||
// the :export directive is the magic sauce for webpack
|
// the :export directive is the magic sauce for webpack
|
||||||
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
||||||
|
@ -5,14 +5,7 @@
|
|||||||
:style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"
|
:style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"
|
||||||
>
|
>
|
||||||
<transition :enter-active-class="proxy?.animate.logoAnimate.enter" mode="out-in">
|
<transition :enter-active-class="proxy?.animate.logoAnimate.enter" mode="out-in">
|
||||||
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
|
<router-link class="sidebar-logo-link" to="/">
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
|
||||||
<h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
|
|
||||||
{{ title }}
|
|
||||||
</h1>
|
|
||||||
</router-link>
|
|
||||||
<router-link v-else key="expand" class="sidebar-logo-link" to="/">
|
|
||||||
<img v-if="logo" :src="logo" class="sidebar-logo" />
|
|
||||||
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
|
<h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</h1>
|
</h1>
|
||||||
@ -23,8 +16,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import variables from '@/assets/styles/variables.module.scss';
|
import variables from '@/assets/styles/variables.module.scss';
|
||||||
import logo from '@/assets/logo/logo.png';
|
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
|
import { useUserStore } from '@/store/modules/user';
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
@ -34,8 +27,14 @@ defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const title = ref('星汉研创科技');
|
const userStore = useUserStore();
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
|
|
||||||
|
// 使用计算属性动态获取标题
|
||||||
|
const title = computed(() => {
|
||||||
|
return userStore.tenantName || import.meta.env.VITE_APP_TITLE || '云平台管理系统';
|
||||||
|
});
|
||||||
|
|
||||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -62,33 +61,25 @@ const sideTheme = computed(() => settingsStore.sideTheme);
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
& .sidebar-logo {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .sidebar-title {
|
& .sidebar-title {
|
||||||
display: inline-block;
|
display: block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
padding: 0 15px; // 增加左右内边距
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
font-size: 16px; // 匹配设计UI的字体大小
|
font-size: 16px; // 恢复正常字体大小
|
||||||
font-family:
|
font-family:
|
||||||
Avenir,
|
Avenir,
|
||||||
Helvetica Neue,
|
Helvetica Neue,
|
||||||
Arial,
|
Arial,
|
||||||
Helvetica,
|
Helvetica,
|
||||||
sans-serif;
|
sans-serif;
|
||||||
vertical-align: middle;
|
width: 100%; // 使用全宽
|
||||||
}
|
white-space: nowrap;
|
||||||
}
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
&.collapse {
|
text-align: center; // 居中显示
|
||||||
.sidebar-logo {
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const nickname = ref('');
|
const nickname = ref('');
|
||||||
const userId = ref<string | number>('');
|
const userId = ref<string | number>('');
|
||||||
const tenantId = ref<string>('');
|
const tenantId = ref<string>('');
|
||||||
|
// 从 localStorage 恢复租户名称
|
||||||
|
const tenantName = ref<string>(localStorage.getItem('currentTenantName') || '');
|
||||||
const avatar = ref('');
|
const avatar = ref('');
|
||||||
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
|
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
|
||||||
const permissions = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
|
const permissions = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
|
||||||
@ -27,6 +29,10 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const data = res.data;
|
const data = res.data;
|
||||||
setToken(data.access_token);
|
setToken(data.access_token);
|
||||||
token.value = data.access_token;
|
token.value = data.access_token;
|
||||||
|
// 设置租户名称
|
||||||
|
if (userInfo.tenantName) {
|
||||||
|
tenantName.value = userInfo.tenantName;
|
||||||
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
@ -61,9 +67,12 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
const logout = async (): Promise<void> => {
|
const logout = async (): Promise<void> => {
|
||||||
await logoutApi();
|
await logoutApi();
|
||||||
token.value = '';
|
token.value = '';
|
||||||
|
tenantName.value = '';
|
||||||
roles.value = [];
|
roles.value = [];
|
||||||
permissions.value = [];
|
permissions.value = [];
|
||||||
removeToken();
|
removeToken();
|
||||||
|
// 清除保存的租户名称
|
||||||
|
localStorage.removeItem('currentTenantName');
|
||||||
};
|
};
|
||||||
|
|
||||||
const setAvatar = (value: string) => {
|
const setAvatar = (value: string) => {
|
||||||
@ -73,6 +82,7 @@ export const useUserStore = defineStore('user', () => {
|
|||||||
return {
|
return {
|
||||||
userId,
|
userId,
|
||||||
tenantId,
|
tenantId,
|
||||||
|
tenantName,
|
||||||
token,
|
token,
|
||||||
nickname,
|
nickname,
|
||||||
avatar,
|
avatar,
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import defaultSettings from '@/settings';
|
import defaultSettings from '@/settings';
|
||||||
import { useSettingsStore } from '@/store/modules/settings';
|
import { useSettingsStore } from '@/store/modules/settings';
|
||||||
|
import { useUserStore } from '@/store/modules/user';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 动态修改标题
|
* 动态修改标题
|
||||||
*/
|
*/
|
||||||
export const useDynamicTitle = () => {
|
export const useDynamicTitle = () => {
|
||||||
const settingsStore = useSettingsStore();
|
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;
|
document.title = settingsStore.title + ' - ' + import.meta.env.VITE_APP_TITLE;
|
||||||
} else {
|
} else {
|
||||||
document.title = defaultSettings.title as string;
|
document.title = defaultSettings.title as string;
|
||||||
|
@ -40,6 +40,11 @@
|
|||||||
<el-table v-loading="loading" border :data="deviceTypeList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" border :data="deviceTypeList" @selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="50" align="center" />
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
<el-table-column label="型号名称" align="center" prop="typeName" />
|
<el-table-column label="型号名称" align="center" prop="typeName" />
|
||||||
|
<el-table-column label="类型code" align="center" prop="modelDictionary">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ modelDictionaryOptions.find(item => item.dictValue === String(scope.row.modelDictionary))?.dictLabel }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="是否支持蓝牙" align="center" prop="isSupportBle">
|
<el-table-column label="是否支持蓝牙" align="center" prop="isSupportBle">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.isSupportBle ? '是' : '否' }}
|
{{ scope.row.isSupportBle ? '是' : '否' }}
|
||||||
@ -90,6 +95,16 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item label="类型code" prop="modelDictionary">
|
||||||
|
<el-select v-model="form.modelDictionary" placeholder="请选择">
|
||||||
|
<el-option v-for="item in modelDictionaryOptions" :key="item.dictValue" :label="item.dictLabel"
|
||||||
|
:value="item.dictValue" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="是否支持蓝牙" prop="isSupportBle">
|
<el-form-item label="是否支持蓝牙" prop="isSupportBle">
|
||||||
@ -104,11 +119,11 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="定位方式" prop="locateMode">
|
<el-form-item label="定位方式" prop="locateMode">
|
||||||
<el-select v-model="form.locateMode" placeholder="请选择">
|
<el-select v-model="form.locateMode" placeholder="请选择">
|
||||||
<el-option label="无" value="0" />
|
<el-option label="无" :value="0" />
|
||||||
<el-option label="GPS" value="1" />
|
<el-option label="GPS" :value="1" />
|
||||||
<el-option label="基站" value="2" />
|
<el-option label="基站" :value="2" />
|
||||||
<el-option label="wifi" value="3" />
|
<el-option label="wifi" :value="3" />
|
||||||
<el-option label="北斗" value="4" />
|
<el-option label="北斗" :value="4" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -117,8 +132,8 @@
|
|||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-form-item label="通讯方式" prop="communicationMode">
|
<el-form-item label="通讯方式" prop="communicationMode">
|
||||||
<el-select v-model="form.communicationMode" placeholder="请选择">
|
<el-select v-model="form.communicationMode" placeholder="请选择">
|
||||||
<el-option label="4G" value="0" />
|
<el-option label="4G" :value="0" />
|
||||||
<el-option label="蓝牙" value="1" />
|
<el-option label="蓝牙" :value="1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -137,24 +152,22 @@
|
|||||||
<script setup name="User" lang="ts">
|
<script setup name="User" lang="ts">
|
||||||
import api from '@/api/equipmentManagement/deviceType/index';
|
import api from '@/api/equipmentManagement/deviceType/index';
|
||||||
import { deviceTypeQuery } from '@/api/equipmentManagement/deviceType/types';
|
import { deviceTypeQuery } from '@/api/equipmentManagement/deviceType/types';
|
||||||
|
import { getDicts } from '@/api/system/dict/data';
|
||||||
import { to } from 'await-to-js';
|
import { to } from 'await-to-js';
|
||||||
import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
|
import { ComponentInternalInstance, getCurrentInstance, onMounted, reactive, ref, toRefs } from 'vue';
|
||||||
import { ElDialog, ElForm, ElFormItem, ElInput, ElRow, ElCol, ElButton, ElCard, ElSelect, ElOption, ElDatePicker, ElTable, ElTableColumn, ElTooltip, ElSwitch } from 'element-plus';
|
import { ElDialog, ElForm, ElFormItem, ElInput, ElRow, ElCol, ElButton, ElCard, ElSelect, ElOption, ElDatePicker, ElTable, ElTableColumn, ElTooltip, ElSwitch } from 'element-plus';
|
||||||
|
|
||||||
interface deviceTypeVO {
|
interface deviceTypeVO {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
typeName: string;
|
typeName: string;
|
||||||
isSupportBle: boolean;
|
isSupportBle: boolean;
|
||||||
locateMode: string;
|
locateMode: number;
|
||||||
communicationMode: string;
|
modelDictionary: string;
|
||||||
|
communicationMode: number;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
createByName: string;
|
createByName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DeviceTypeForm extends deviceTypeVO {
|
interface DeviceTypeForm extends deviceTypeVO {
|
||||||
// 可能有其他字段
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const deviceTypeList = ref<deviceTypeVO[]>();
|
const deviceTypeList = ref<deviceTypeVO[]>();
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@ -167,16 +180,17 @@ const queryFormRef = ref<InstanceType<typeof ElForm>>();
|
|||||||
const userFormRef = ref<InstanceType<typeof ElForm>>();
|
const userFormRef = ref<InstanceType<typeof ElForm>>();
|
||||||
const formDialogRef = ref<InstanceType<typeof ElDialog>>();
|
const formDialogRef = ref<InstanceType<typeof ElDialog>>();
|
||||||
const loadingIng = ref(false)
|
const loadingIng = ref(false)
|
||||||
|
const modelDictionaryOptions = ref<any[]>([]);
|
||||||
const dialog = reactive<DialogOption>({
|
const dialog = reactive<DialogOption>({
|
||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const initFormData: DeviceTypeForm = {
|
const initFormData: DeviceTypeForm = {
|
||||||
typeName: '',
|
typeName: '',
|
||||||
isSupportBle: false,
|
isSupportBle: false,
|
||||||
locateMode: '',
|
locateMode: 0,
|
||||||
communicationMode: '',
|
modelDictionary: '',
|
||||||
|
communicationMode: 0,
|
||||||
id: '',
|
id: '',
|
||||||
createTime: '',
|
createTime: '',
|
||||||
createByName: '',
|
createByName: '',
|
||||||
@ -193,6 +207,9 @@ const initData = {
|
|||||||
typeName: [
|
typeName: [
|
||||||
{ required: true, message: '请输入设备类型名称', trigger: 'blur' },
|
{ required: true, message: '请输入设备类型名称', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
|
modelDictionary: [
|
||||||
|
{ required: true, message: '请选择类型code', trigger: 'blur' },
|
||||||
|
],
|
||||||
locateMode: [
|
locateMode: [
|
||||||
{ required: true, message: '请选择定位方式', trigger: 'blur' },
|
{ required: true, message: '请选择定位方式', trigger: 'blur' },
|
||||||
],
|
],
|
||||||
@ -218,7 +235,10 @@ const getList = async () => {
|
|||||||
deviceTypeList.value = res.rows;
|
deviceTypeList.value = res.rows;
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
};
|
};
|
||||||
|
const getDict = async () => {
|
||||||
|
const res = await getDicts('model_dictionary');
|
||||||
|
modelDictionaryOptions.value = res.data;
|
||||||
|
}
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
@ -278,12 +298,12 @@ const handleUpdate = async (row?: DeviceTypeForm) => {
|
|||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = '修改设备类型';
|
dialog.title = '修改设备类型';
|
||||||
try {
|
try {
|
||||||
if (row) {
|
const deviceData = row || ids.value[0];
|
||||||
Object.assign(form.value, row);
|
Object.assign(form.value, deviceData);
|
||||||
} else {
|
// 确保数据类型正确
|
||||||
const selectedId = ids.value[0];
|
form.value.modelDictionary = String(form.value.modelDictionary || '');
|
||||||
Object.assign(form.value, selectedId);
|
form.value.locateMode = Number(form.value.locateMode) || 0;
|
||||||
}
|
form.value.communicationMode = Number(form.value.communicationMode) || 0;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
}
|
}
|
||||||
@ -295,7 +315,13 @@ const submitForm = () => {
|
|||||||
if (valid) {
|
if (valid) {
|
||||||
loadingIng.value = true;
|
loadingIng.value = true;
|
||||||
try {
|
try {
|
||||||
form.value.id ? await api.updateDeviceType(form.value) : await api.addDeviceType(form.value);
|
const payload = {
|
||||||
|
...form.value,
|
||||||
|
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('操作成功');
|
proxy?.$modal.msgSuccess('操作成功');
|
||||||
dialog.visible = false;
|
dialog.visible = false;
|
||||||
await getList();
|
await getList();
|
||||||
@ -325,6 +351,7 @@ const resetForm = () => {
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList(); // 初始化列表数据
|
getList(); // 初始化列表数据
|
||||||
|
getDict();
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -277,7 +277,8 @@
|
|||||||
<!-- IMEI 二维码弹窗 -->
|
<!-- IMEI 二维码弹窗 -->
|
||||||
<el-dialog v-model="qrCodeDialogVisible" title="设备IMEI二维码" width="20%" append-to-body>
|
<el-dialog v-model="qrCodeDialogVisible" title="设备IMEI二维码" width="20%" append-to-body>
|
||||||
<div style="text-align: center;">
|
<div style="text-align: center;">
|
||||||
<QRCodeVue3 :value="qrCodeValue" :size="100" />
|
<!-- 使用 v-if 强制重新渲染 -->
|
||||||
|
<QRCodeVue3 v-if="qrCodeDialogVisible" :value="qrCodeValue" :size="100" />
|
||||||
<p style="margin-top: 10px;">{{ qrCodeValue }}</p>
|
<p style="margin-top: 10px;">{{ qrCodeValue }}</p>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-form-item v-if="tenantEnabled" prop="tenantId">
|
<el-form-item v-if="tenantEnabled" prop="tenantId">
|
||||||
<el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')"
|
<el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')"
|
||||||
style="width: 100%">
|
style="width: 100%" @change="onTenantChange">
|
||||||
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName"
|
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName"
|
||||||
:value="item.tenantId"></el-option>
|
:value="item.tenantId"></el-option>
|
||||||
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
||||||
@ -56,7 +56,7 @@ import { HttpStatus } from '@/enums/RespEnum';
|
|||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
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 userStore = useUserStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -102,19 +102,30 @@ const handleLogin = () => {
|
|||||||
loginRef.value?.validate(async (valid: boolean, fields: any) => {
|
loginRef.value?.validate(async (valid: boolean, fields: any) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
// 获取选中租户的名称并设置到登录表单中
|
||||||
|
const tenantName = tenantList.value.find(item => item.tenantId === loginForm.value.tenantId)?.companyName;
|
||||||
|
loginForm.value.tenantName = tenantName;
|
||||||
|
|
||||||
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
// 勾选了需要记住密码设置在 localStorage 中设置记住用户名和密码
|
||||||
if (loginForm.value.rememberMe) {
|
if (loginForm.value.rememberMe) {
|
||||||
localStorage.setItem('tenantId', String(loginForm.value.tenantId));
|
localStorage.setItem('tenantId', String(loginForm.value.tenantId));
|
||||||
|
localStorage.setItem('tenantName', String(tenantName || ''));
|
||||||
localStorage.setItem('username', String(loginForm.value.username));
|
localStorage.setItem('username', String(loginForm.value.username));
|
||||||
localStorage.setItem('password', String(loginForm.value.password));
|
localStorage.setItem('password', String(loginForm.value.password));
|
||||||
localStorage.setItem('rememberMe', String(loginForm.value.rememberMe));
|
localStorage.setItem('rememberMe', String(loginForm.value.rememberMe));
|
||||||
} else {
|
} else {
|
||||||
// 否则移除
|
// 否则移除
|
||||||
localStorage.removeItem('tenantId');
|
localStorage.removeItem('tenantId');
|
||||||
|
localStorage.removeItem('tenantName');
|
||||||
localStorage.removeItem('username');
|
localStorage.removeItem('username');
|
||||||
localStorage.removeItem('password');
|
localStorage.removeItem('password');
|
||||||
localStorage.removeItem('rememberMe');
|
localStorage.removeItem('rememberMe');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 无论是否记住密码,都保存租户名称用于页面刷新时恢复
|
||||||
|
if (tenantName) {
|
||||||
|
localStorage.setItem('currentTenantName', tenantName);
|
||||||
|
}
|
||||||
// 调用action的登录方法
|
// 调用action的登录方法
|
||||||
const [err] = await to(userStore.login(loginForm.value));
|
const [err] = await to(userStore.login(loginForm.value));
|
||||||
if (!err) {
|
if (!err) {
|
||||||
@ -170,6 +181,8 @@ const initTenantList = async () => {
|
|||||||
tenantList.value = data.voList;
|
tenantList.value = data.voList;
|
||||||
if (tenantList.value != null && tenantList.value.length !== 0) {
|
if (tenantList.value != null && tenantList.value.length !== 0) {
|
||||||
loginForm.value.tenantId = tenantList.value[0].tenantId;
|
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(() => {
|
onMounted(() => {
|
||||||
getCode();
|
getCode();
|
||||||
initTenantList();
|
initTenantList();
|
||||||
|
Reference in New Issue
Block a user