From eff4f8b3140154ec445cbf6638b70f625511ea6a Mon Sep 17 00:00:00 2001 From: liuyun Date: Sun, 11 Oct 2026 17:22:16 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=AC=AC=E4=BA=8C=E8=BD=AE=E6=AE=8B?= =?UTF-8?q?=E7=95=99=EF=BC=88=E5=89=8D=E7=AB=AF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 config.tenantCode 死配置,注册页加租户输入 - 全局 errorHandler + unhandledrejection 兜底错误提示 - selectTenant 二次登录加 loading - 路由守卫支持 meta.freeAccess 白名单 Co-Authored-By: Claude Opus 4.8 --- components.d.ts | 2 ++ src/config/login.ts | 3 --- src/main.ts | 10 ++++++++++ src/pages/login/index.vue | 3 +++ src/pages/register.vue | 10 ++++++++-- src/router/index.ts | 4 ++-- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/components.d.ts b/components.d.ts index 690c297..3b15375 100644 --- a/components.d.ts +++ b/components.d.ts @@ -18,6 +18,7 @@ declare module 'vue' { ElButton: typeof import('element-plus/es')['ElButton'] ElCard: typeof import('element-plus/es')['ElCard'] ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] ElDialog: typeof import('element-plus/es')['ElDialog'] @@ -77,6 +78,7 @@ declare global { const ElButton: typeof import('element-plus/es')['ElButton'] const ElCard: typeof import('element-plus/es')['ElCard'] const ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] + const ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] const ElColorPicker: typeof import('element-plus/es')['ElColorPicker'] const ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider'] const ElDialog: typeof import('element-plus/es')['ElDialog'] diff --git a/src/config/login.ts b/src/config/login.ts index 8c08ce7..1ca9db0 100644 --- a/src/config/login.ts +++ b/src/config/login.ts @@ -18,8 +18,6 @@ export interface LoginConfig { layout: LoginLayout /** 背景(图 URL 或 CSS 渐变/颜色)。 */ background?: string - /** 登录提交的租户编码(页面不展示租户输入框,统一用此默认租户)。 */ - tenantCode: string /** 登录字段(JSON Schema,字段名须与后端 DTO 一致)。 */ fields: JsonSchema /** 是否显示「记住我」。 */ @@ -40,7 +38,6 @@ export const defaultLoginConfig: LoginConfig = { subtitle: '通用系统管理脚手架', copyright: '云南投云科技有限公司', layout: 'split', - tenantCode: 'touyun', fields: { type: 'object', properties: { diff --git a/src/main.ts b/src/main.ts index 1b200ba..7b20ec2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,5 @@ import { createApp } from 'vue' +import { ElMessage } from 'element-plus' import 'element-plus/theme-chalk/dark/css-vars.css' import App from './App.vue' @@ -36,4 +37,13 @@ setAuthExpiredHandler(() => { installI18n(app) installAssets() +// 全局兜底:未捕获的组件错误 / Promise 拒绝,统一弹出错误提示(避免静默失败) +app.config.errorHandler = (err) => { + ElMessage.error(err instanceof Error ? err.message : String(err)) +} +window.addEventListener('unhandledrejection', (e) => { + const reason = e.reason + ElMessage.error(reason instanceof Error ? reason.message : String(reason)) +}) + app.mount('#app') diff --git a/src/pages/login/index.vue b/src/pages/login/index.vue index 666fefd..33631e7 100644 --- a/src/pages/login/index.vue +++ b/src/pages/login/index.vue @@ -208,11 +208,14 @@ const { loading, run: doLogin } = useRequest( async function selectTenant(tenantCode: string): Promise { tenantDialogVisible.value = false + loading.value = true try { await auth.login(model.username, model.password, tenantCode) router.push(config.homePath) } catch (e) { error.value = (e as Error).message + } finally { + loading.value = false } } diff --git a/src/pages/register.vue b/src/pages/register.vue index 4e09476..5c94ce4 100644 --- a/src/pages/register.vue +++ b/src/pages/register.vue @@ -14,6 +14,11 @@ meta: + + + + + @@ -71,9 +76,10 @@ applyTheme(app.themeColor, app.isDark) const formRef = ref() const loading = ref(false) -const model = reactive({ username: '', password: '', confirmPassword: '', email: '', phone: '' }) +const model = reactive({ tenantCode: '', username: '', password: '', confirmPassword: '', email: '', phone: '' }) const rules: FormRules = { + tenantCode: [{ required: true, message: '请输入租户编码', trigger: 'blur' }], username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, @@ -105,7 +111,7 @@ async function onSubmit(): Promise { loading.value = true try { await register({ - tenantCode: config.tenantCode, + tenantCode: model.tenantCode, username: model.username, password: model.password, email: model.email, diff --git a/src/router/index.ts b/src/router/index.ts index 9d82cd2..ccb08a7 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -66,8 +66,8 @@ router.beforeEach(async (to, from, next) => { next('/login') return } - // 路由级权限:自由路径放行,其余须在可访问菜单中 - if (FREE_PATHS.has(to.path)) { + // 路由级权限:自由路径或 meta.freeAccess 放行,其余须在可访问菜单中 + if (FREE_PATHS.has(to.path) || to.meta.freeAccess === true) { next() return }