From e3f12e4548cf5b62627312caea1eba602450482d Mon Sep 17 00:00:00 2001 From: lzh Date: Thu, 23 Apr 2026 19:35:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E:=20=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E9=A1=B5=20UI=20=E9=87=8D=E6=9E=84=20+=20=E5=93=81=E7=89=8C=20?= =?UTF-8?q?logo=20=E4=B8=8E=20Lottie=20=E5=90=AF=E5=8A=A8=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 视觉与品牌 - public/logo.svg、public/login-illustration.svg、favicon 替换为 logo.svg。 - preferences.ts 新增 logo.source 指向 /logo.svg。 - packages/effects/layouts 导出 LoginIllustration 共享组件(浮动插画,加载失败自动隐藏)。 Auth 布局重构 - layouts/auth.vue 替换默认 AuthPageLayout:主题色渐变背景 + 左侧浮动插画 + 品牌卡片 + 右上 LanguageToggle + 圆角登录卡片;KeepAlive 仅缓存 Login (CodeLogin/QrCodeLogin 需要每次刷新验证码/二维码)。 - 表单样式通过 :deep(.login-form-container) 覆盖输入框、选择框、主按钮, 全部走 --primary 变量,与主题色联动。 登录组件 - views/_core/authentication/login.vue: 关闭默认 codeLogin/qrcodeLogin/ thirdPartyLogin/register/docLink,改为手机 / 二维码 / 企微三按钮(IconifyIcon); 三方登录前检查租户,缺失时 message.warning + validateField。 - packages/effects/common-ui/authentication/login.vue + types.ts: 新增 showDocLink prop(默认 true),替代原本 HTML 注释掉 DocLink 的做法。 - sso-callback.vue: 等待提示改为 LottieLoading 动画。 Lottie 启动动画 - 新增 loading.html(注入进 index.html)+ public/loading.json + 运行时拷贝的 public/lottie_light.min.js(.gitignore 忽略)。 - 新增 public/lottie-tint.js:共享主题色适配器(LIGHTNESSES / SHADE_MAP / hslToRgb / patchColors / readPrimary),同时被启动白屏脚本与 Vue 组件使用, 消除两份几乎一致的实现。 - 新增 src/components/lottie-loading/LottieLoading.vue:按需加载 lottie-tint.js 并根据 CSS 变量 --primary 重新上色。 - vite.config.mts 新增 copyLottiePlayer 插件:configResolved 时无条件把 node_modules/lottie-web/.../lottie_light.min.js 拷到 public/,避免 mtime 误判。 - package.json 新增 lottie-web ^5.13.0 依赖。 i18n - 新增 otherLoginMethods / contactSupport / weComLogin 三个文案(zh-CN / en-US)。 Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/web-antd/.gitignore | 3 + apps/web-antd/index.html | 2 +- apps/web-antd/loading.html | 77 ++++++++ apps/web-antd/package.json | 1 + apps/web-antd/public/loading.json | 1 + apps/web-antd/public/login-illustration.svg | 1 + apps/web-antd/public/logo.svg | 13 ++ apps/web-antd/public/lottie-tint.js | 158 ++++++++++++++++ .../lottie-loading/LottieLoading.vue | 107 +++++++++++ .../src/components/lottie-loading/index.ts | 1 + apps/web-antd/src/layouts/auth.vue | 174 ++++++++++++++++-- apps/web-antd/src/preferences.ts | 3 + .../src/views/_core/authentication/login.vue | 74 +++++++- .../_core/authentication/sso-callback.vue | 7 +- apps/web-antd/vite.config.mts | 33 ++++ .../common-ui/src/ui/authentication/login.vue | 3 +- .../common-ui/src/ui/authentication/types.ts | 5 + .../icons/login-illustration.vue | 61 ++++++ .../layouts/src/authentication/index.ts | 1 + .../src/langs/en-US/authentication.json | 3 + .../src/langs/zh-CN/authentication.json | 3 + pnpm-lock.yaml | 22 ++- 22 files changed, 727 insertions(+), 26 deletions(-) create mode 100644 apps/web-antd/.gitignore create mode 100644 apps/web-antd/loading.html create mode 100644 apps/web-antd/public/loading.json create mode 100644 apps/web-antd/public/login-illustration.svg create mode 100644 apps/web-antd/public/logo.svg create mode 100644 apps/web-antd/public/lottie-tint.js create mode 100644 apps/web-antd/src/components/lottie-loading/LottieLoading.vue create mode 100644 apps/web-antd/src/components/lottie-loading/index.ts create mode 100644 packages/effects/layouts/src/authentication/icons/login-illustration.vue diff --git a/apps/web-antd/.gitignore b/apps/web-antd/.gitignore new file mode 100644 index 000000000..024a956ab --- /dev/null +++ b/apps/web-antd/.gitignore @@ -0,0 +1,3 @@ +# 由 vite.config.mts 的 copyLottiePlayer 插件在 dev/build 时自动从 +# node_modules/lottie-web 拷贝,不需要进版本控制 +public/lottie_light.min.js diff --git a/apps/web-antd/index.html b/apps/web-antd/index.html index dffc1503a..3451fec2d 100644 --- a/apps/web-antd/index.html +++ b/apps/web-antd/index.html @@ -13,7 +13,7 @@ /> <%= VITE_APP_TITLE %> - + + + diff --git a/apps/web-antd/package.json b/apps/web-antd/package.json index 847d65725..8027ed3df 100644 --- a/apps/web-antd/package.json +++ b/apps/web-antd/package.json @@ -57,6 +57,7 @@ "diagram-js": "catalog:", "fast-xml-parser": "catalog:", "highlight.js": "catalog:", + "lottie-web": "^5.13.0", "pinia": "catalog:", "steady-xml": "catalog:", "tinymce": "catalog:", diff --git a/apps/web-antd/public/loading.json b/apps/web-antd/public/loading.json new file mode 100644 index 000000000..89edde9ea --- /dev/null +++ b/apps/web-antd/public/loading.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":25,"ip":0,"op":101,"w":600,"h":600,"nm":"huakuai","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"five","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":21,"s":[10]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":26,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":51,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":57,"s":[-10]},{"t":62,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.351,"y":1},"o":{"x":0.276,"y":0},"t":15,"s":[520,360,0],"to":[-4.667,-15,0],"ti":[22.917,0,0]},{"i":{"x":0.351,"y":1},"o":{"x":0.276,"y":0},"t":21,"s":[465,250,0],"to":[-22.917,0,0],"ti":[0,0,0]},{"i":{"x":0.416,"y":0.416},"o":{"x":0.317,"y":0.317},"t":26,"s":[410,360,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.467,"y":0.739},"o":{"x":0.225,"y":0},"t":51,"s":[410,360,0],"to":[0,0,0],"ti":[-18.333,0,0]},{"i":{"x":0.579,"y":1},"o":{"x":0.256,"y":0.125},"t":56,"s":[464.291,250,0],"to":[18.333,0,0],"ti":[0,0,0]},{"t":61,"s":[520,360,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-162,-58,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":21,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":25,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":27,"s":[120,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":29,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":51,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":57,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":61,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":63,"s":[120,70,100]},{"t":65,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":10,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[0.623529434204,0.917647063732,0.494117647409,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":26,"s":[0.443137258291,0.737254917622,0.078431375325,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":51,"s":[0.443137258291,0.737254917622,0.078431375325,1]},{"t":61,"s":[0.623529434204,0.917647063732,0.494117647409,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-162,-98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":101,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"four","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[10]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":21,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":56,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":61,"s":[-10]},{"t":66,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.316,"y":1},"o":{"x":0.24,"y":0},"t":11,"s":[410,360,0],"to":[-4.667,-15,0],"ti":[22.917,0,0]},{"i":{"x":0.316,"y":1},"o":{"x":0.24,"y":0},"t":16,"s":[355,250,0],"to":[-22.917,0,0],"ti":[6.307,-19.302,0]},{"i":{"x":0.316,"y":1},"o":{"x":0.167,"y":0},"t":21,"s":[300,360,0],"to":[-0.116,0.355,0],"ti":[0,0,0]},{"i":{"x":0.583,"y":0.775},"o":{"x":0.167,"y":0},"t":56,"s":[300,360,0],"to":[0,0,0],"ti":[-27.317,0.053,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.417,"y":0.224},"t":61,"s":[354.435,250,0],"to":[28.392,-0.055,0],"ti":[-2.765,-8.21,0]},{"t":66,"s":[410,360,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-162,-58,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":16,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":20,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":22,"s":[120,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":24,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":56,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":61,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":65,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":67,"s":[120,70,100]},{"t":69,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":10,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":11,"s":[0.443137258291,0.737254917622,0.078431375325,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":21,"s":[0.298039227724,0.623529434204,0.043137256056,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":56,"s":[0.298039227724,0.623529434204,0.043137256056,1]},{"t":66,"s":[0.443137258291,0.737254917622,0.078431375325,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-162,-98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":101,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"three","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":11,"s":[10]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":16,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":61,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":66,"s":[-10]},{"t":71,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.369,"y":1},"o":{"x":0.258,"y":0},"t":6,"s":[300,360,0],"to":[-5.167,-18.5,0],"ti":[22.917,0,0]},{"i":{"x":0.369,"y":1},"o":{"x":0.258,"y":0},"t":11,"s":[245,250,0],"to":[-22.917,0,0],"ti":[2.434,-10.892,0]},{"i":{"x":0.369,"y":1},"o":{"x":0.167,"y":0},"t":16,"s":[190,360,0],"to":[-0.385,1.723,0],"ti":[0,0,0]},{"i":{"x":0.583,"y":0.776},"o":{"x":0.167,"y":0},"t":61,"s":[190,360,0],"to":[0,0,0],"ti":[-29.055,-0.462,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.417,"y":0.224},"t":66,"s":[245.406,250,0],"to":[28.268,0.45,0],"ti":[-3.029,-9.151,0]},{"t":71,"s":[300,360,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-162,-58,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":11,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":17,"s":[120,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":19,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":61,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":66,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":70,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":72,"s":[120,70,100]},{"t":74,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":10,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[0.298039227724,0.623529434204,0.043137256056,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":16,"s":[0.176470592618,0.474509805441,0.023529412225,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":61,"s":[0.176470592618,0.474509805441,0.023529412225,1]},{"t":71,"s":[0.298039227724,0.623529434204,0.043137256056,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-162,-98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":101,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"two","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[10]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":67,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":73,"s":[-10]},{"t":79,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.458,"y":1},"o":{"x":0.222,"y":0},"t":1,"s":[190,360,0],"to":[-2.417,-11.5,0],"ti":[22.917,0,0]},{"i":{"x":0.458,"y":1},"o":{"x":0.222,"y":0},"t":6,"s":[135,250,0],"to":[-22.917,0,0],"ti":[2.778,-8.535,0]},{"i":{"x":0.458,"y":1},"o":{"x":0.167,"y":0},"t":11,"s":[80,360,0],"to":[-0.664,2.04,0],"ti":[0,0,0]},{"i":{"x":0.583,"y":0.731},"o":{"x":0.167,"y":0},"t":67,"s":[80,360,0],"to":[0,0,0],"ti":[-28.172,-0.208,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.417,"y":0.269},"t":73,"s":[135.986,250,0],"to":[26.782,0.198,0],"ti":[3.225,8.657,0]},{"t":79,"s":[190,360,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-162,-58,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":1,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":6,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":12,"s":[120,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":14,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":67,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":73,"s":[90,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":78,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":80,"s":[120,70,100]},{"t":82,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":10,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[0.176470592618,0.474509805441,0.023529412225,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":11,"s":[0.141176477075,0.388235300779,0.019607843831,1]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":67,"s":[0.141176477075,0.388235300779,0.019607843831,1]},{"t":79,"s":[0.176470592618,0.474509805441,0.023529412225,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-162,-98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":101,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"one","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.111,"y":1},"o":{"x":0.26,"y":0},"t":0,"s":[80,320,0],"to":[73.333,0,0],"ti":[-73.333,0,0]},{"i":{"x":0.082,"y":0.082},"o":{"x":0.213,"y":0.213},"t":39.967,"s":[520,320,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.112,"y":1},"o":{"x":0.26,"y":0},"t":50,"s":[520,320,0],"to":[-73.333,0,0],"ti":[73.333,0,0]},{"t":90,"s":[80,320,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-162,-98,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[80,80],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":10,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.444],"y":[1]},"o":{"x":[0.249],"y":[0]},"t":0,"s":[0.141176477075,0.388235300779,0.019607843831,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":40,"s":[0.623529434204,0.917647063732,0.494117647409,1]},{"i":{"x":[0.444],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":50,"s":[0.623529434204,0.917647063732,0.494117647409,1]},{"t":90,"s":[0.141176477075,0.388235300779,0.019607843831,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-162,-98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":101,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/apps/web-antd/public/login-illustration.svg b/apps/web-antd/public/login-illustration.svg new file mode 100644 index 000000000..44b46c3cb --- /dev/null +++ b/apps/web-antd/public/login-illustration.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/web-antd/public/logo.svg b/apps/web-antd/public/logo.svg new file mode 100644 index 000000000..308ca02b1 --- /dev/null +++ b/apps/web-antd/public/logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/web-antd/public/lottie-tint.js b/apps/web-antd/public/lottie-tint.js new file mode 100644 index 000000000..3613a0d7a --- /dev/null +++ b/apps/web-antd/public/lottie-tint.js @@ -0,0 +1,158 @@ +/** + * Lottie 主题色适配器 + * + * 把 public/loading.json 里硬编码的 5 档绿色替换为当前主题色的 5 档亮度, + * 供 loading.html 的初始白屏动画和 Vue 内的 LottieLoading 组件共用。 + * + * 暴露为 window.__lottieTint,兼容 ES5,可被 + + diff --git a/apps/web-antd/src/components/lottie-loading/index.ts b/apps/web-antd/src/components/lottie-loading/index.ts new file mode 100644 index 000000000..51954f9df --- /dev/null +++ b/apps/web-antd/src/components/lottie-loading/index.ts @@ -0,0 +1 @@ +export { default as LottieLoading } from './LottieLoading.vue'; diff --git a/apps/web-antd/src/layouts/auth.vue b/apps/web-antd/src/layouts/auth.vue index 8ba66e85a..4cfe1eff1 100644 --- a/apps/web-antd/src/layouts/auth.vue +++ b/apps/web-antd/src/layouts/auth.vue @@ -1,25 +1,175 @@ + + diff --git a/apps/web-antd/src/preferences.ts b/apps/web-antd/src/preferences.ts index aeb8ad960..edea6dad2 100644 --- a/apps/web-antd/src/preferences.ts +++ b/apps/web-antd/src/preferences.ts @@ -15,6 +15,9 @@ export const overridesPreferences = defineOverridesPreferences({ /** 首页路径:默认跳转到 IoT 首页(覆盖框架默认的 /analytics) */ defaultHomePath: '/iot/home', }, + logo: { + source: '/logo.svg', + }, footer: { /** 默认关闭 footer 页脚,因为有一定遮挡 */ enable: false, diff --git a/apps/web-antd/src/views/_core/authentication/login.vue b/apps/web-antd/src/views/_core/authentication/login.vue index aa1db4c53..16e2ea971 100644 --- a/apps/web-antd/src/views/_core/authentication/login.vue +++ b/apps/web-antd/src/views/_core/authentication/login.vue @@ -8,9 +8,12 @@ import { useRoute } from 'vue-router'; import { AuthenticationLogin, Verification, z } from '@vben/common-ui'; import { isCaptchaEnable, isTenantEnable } from '@vben/hooks'; +import { IconifyIcon } from '@vben/icons'; import { $t } from '@vben/locales'; import { useAccessStore } from '@vben/stores'; +import { message } from 'ant-design-vue'; + import { checkCaptcha, getCaptcha, @@ -96,6 +99,12 @@ async function handleThirdLogin(type: number) { if (type <= 0) { return; } + // 多租户模式下,必须先选择租户;触发表单校验以提示用户 + if (tenantEnable && !accessStore.tenantId) { + message.warning($t('authentication.tenantTip')); + loginRef.value?.getFormApi().validateField('tenantId'); + return; + } try { // 计算 redirectUri // tricky: type、redirect 需要先 encode 一次,否则钉钉回调会丢失。配合 social-login.vue#getUrlValue() 使用 @@ -170,17 +179,71 @@ const formSchema = computed((): VbenFormSchema[] => { + + diff --git a/apps/web-antd/src/views/_core/authentication/sso-callback.vue b/apps/web-antd/src/views/_core/authentication/sso-callback.vue index c22bbf0de..f9a802cd3 100644 --- a/apps/web-antd/src/views/_core/authentication/sso-callback.vue +++ b/apps/web-antd/src/views/_core/authentication/sso-callback.vue @@ -7,6 +7,7 @@ import { LOGIN_PATH } from '@vben/constants'; import { message } from 'ant-design-vue'; import { ssoCallback } from '#/api/core/sso'; +import { LottieLoading } from '#/components/lottie-loading'; import { IOT_CLIENT_ID, SSO_CALLBACK_PATH, @@ -83,8 +84,8 @@ onMounted(async () => { diff --git a/apps/web-antd/vite.config.mts b/apps/web-antd/vite.config.mts index 92eff85c4..3329a2717 100644 --- a/apps/web-antd/vite.config.mts +++ b/apps/web-antd/vite.config.mts @@ -1,9 +1,42 @@ +import type { Plugin } from 'vite'; + +import { copyFileSync, mkdirSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + import { defineConfig } from '@vben/vite-config'; +/** + * 启动/构建时把 lottie-web 的 light 播放器从 node_modules 拷到 public/ + * 供 loading.html 以 + + + + diff --git a/packages/effects/layouts/src/authentication/index.ts b/packages/effects/layouts/src/authentication/index.ts index d7c1c293a..987d78cd7 100644 --- a/packages/effects/layouts/src/authentication/index.ts +++ b/packages/effects/layouts/src/authentication/index.ts @@ -1,2 +1,3 @@ export { default as AuthPageLayout } from './authentication.vue'; +export { default as LoginIllustration } from './icons/login-illustration.vue'; export * from './types'; diff --git a/packages/locales/src/langs/en-US/authentication.json b/packages/locales/src/langs/en-US/authentication.json index d1fd9b77d..24167d184 100644 --- a/packages/locales/src/langs/en-US/authentication.json +++ b/packages/locales/src/langs/en-US/authentication.json @@ -56,6 +56,9 @@ "sendCode": "Get Security code", "sendText": "Resend in {0}s", "thirdPartyLogin": "Or continue with", + "otherLoginMethods": "Or sign in with", + "contactSupport": "Need help? Contact your administrator.", + "weComLogin": "WeCom QR Login", "weChat": "WeChat", "qq": "QQ", "gitHub": "GitHub", diff --git a/packages/locales/src/langs/zh-CN/authentication.json b/packages/locales/src/langs/zh-CN/authentication.json index 1eb61aed6..873549e25 100644 --- a/packages/locales/src/langs/zh-CN/authentication.json +++ b/packages/locales/src/langs/zh-CN/authentication.json @@ -56,6 +56,9 @@ "sendCode": "获取验证码", "sendText": "{0}秒后重新获取", "thirdPartyLogin": "其他登录方式", + "otherLoginMethods": "或使用以下方式登录", + "contactSupport": "遇到问题?请联系管理员", + "weComLogin": "企业微信扫码登录", "weChat": "微信", "qq": "QQ", "gitHub": "GitHub", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc3dc533b..5ae6ace25 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -815,6 +815,9 @@ importers: highlight.js: specifier: 'catalog:' version: 11.11.1 + lottie-web: + specifier: ^5.13.0 + version: 5.13.0 pinia: specifier: ^3.0.4 version: 3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)) @@ -1170,7 +1173,7 @@ importers: dependencies: '@commitlint/cli': specifier: 'catalog:' - version: 19.8.1(@types/node@24.10.9)(typescript@5.9.3) + version: 19.8.1(@types/node@25.0.10)(typescript@5.9.3) '@commitlint/config-conventional': specifier: 'catalog:' version: 19.8.1 @@ -8580,6 +8583,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lottie-web@5.13.0: + resolution: {integrity: sha512-+gfBXl6sxXMPe8tKQm7qzLnUy5DUPJPKIyRHwtpCpyUEYjHYRJC/5gjUvdkuO2c3JllrPtHXH5UJJK8LRYl5yQ==} + loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} @@ -12991,11 +12997,11 @@ snapshots: style-mod: 4.1.3 w3c-keyname: 2.2.8 - '@commitlint/cli@19.8.1(@types/node@24.10.9)(typescript@5.9.3)': + '@commitlint/cli@19.8.1(@types/node@25.0.10)(typescript@5.9.3)': dependencies: '@commitlint/format': 19.8.1 '@commitlint/lint': 19.8.1 - '@commitlint/load': 19.8.1(@types/node@24.10.9)(typescript@5.9.3) + '@commitlint/load': 19.8.1(@types/node@25.0.10)(typescript@5.9.3) '@commitlint/read': 19.8.1 '@commitlint/types': 19.8.1 tinyexec: 1.0.2 @@ -13042,7 +13048,7 @@ snapshots: '@commitlint/rules': 19.8.1 '@commitlint/types': 19.8.1 - '@commitlint/load@19.8.1(@types/node@24.10.9)(typescript@5.9.3)': + '@commitlint/load@19.8.1(@types/node@25.0.10)(typescript@5.9.3)': dependencies: '@commitlint/config-validator': 19.8.1 '@commitlint/execute-rule': 19.8.1 @@ -13050,7 +13056,7 @@ snapshots: '@commitlint/types': 19.8.1 chalk: 5.6.2 cosmiconfig: 9.0.0(typescript@5.9.3) - cosmiconfig-typescript-loader: 6.2.0(@types/node@24.10.9)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.2.0(@types/node@25.0.10)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 lodash.uniq: 4.5.0 @@ -16618,9 +16624,9 @@ snapshots: core-util-is@1.0.3: {} - cosmiconfig-typescript-loader@6.2.0(@types/node@24.10.9)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): + cosmiconfig-typescript-loader@6.2.0(@types/node@25.0.10)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@types/node': 24.10.9 + '@types/node': 25.0.10 cosmiconfig: 9.0.0(typescript@5.9.3) jiti: 2.6.1 typescript: 5.9.3 @@ -19089,6 +19095,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + lottie-web@5.13.0: {} + loupe@3.2.1: {} lower-case@2.0.2: