Files
mes-ui-d2/docs/login-page-migration.md
sheng 8a4511dc36 docs: add i18n spec and login migration docs, fix router trailing char
1. 新增国际化规范文档 `i18n-rules.md`,详细说明项目国际化的规范、key 命名、使用方式等
2. 新增登录页面搬迁文档 `login-page-migration.md`,记录登录页搬迁的步骤、依赖和验证清单
3. 修复生产主数据路由文件中多余的尾随字符
2026-05-27 14:38:53 +08:00

16 KiB
Raw Blame History

登录页面搬迁文档

搬迁源D:\code\company\SCTMES_MES_V5\vue-app
搬迁目标d:\code\mes\mes-ui
状态 待审阅,审阅通过后执行搬迁


一、文件清单与依赖关系

登录页面 index.vue
    │
    ├── ① 页面自身
    ├── ② 依赖的 Store 模块
    ├── ③ 依赖的 API 文件
    ├── ④ 依赖的静态资源(图片)
    ├── ⑤ 依赖的 i18n 语言包
    ├── ⑥ 依赖的 CSS 公共样式(% placeholder
    ├── ⑦ 依赖的工具库
    └── ⑧ 路由中已有框架(无需搬迁本文件)

二、需要搬迁的文件

2.1 页面核心文件

文件 旧路径 新目标路径 说明
登录页面 src/views/system_settings/system_monitoring/system/login/index.vue 覆盖 src/views/system/login/index.vue 新项目已有一个简易占位页面,需用旧项目的完整页面替换

旧路径嵌套很深:system_settings/system_monitoring/system/login/
新项目按对照表命名为简化的 system/login/,保持一致的命名风格。


2.2 Store 模块Vuex

文件 旧路径 新目标路径 说明
account src/store/modules/d2admin/modules/account.js src/store/modules/d2admin/modules/account.js 核心:含 loginlogout action
user src/store/modules/d2admin/modules/user.js src/store/modules/d2admin/modules/user.js account.login 中调用 d2admin/user/set新项目已存在

account.jslogin action 依赖链:
login()loginAdminUser() API → 写 cookie(token/uuid) → dispatch(d2admin/user/set)dispatch(load)
load() → 依次加载 user/theme/transition/page/menu/size/color

account.js 依赖的其它模块(新项目已存在,不需搬迁)

模块 路径 状态
user src/store/modules/d2admin/modules/user.js 已有
theme src/store/modules/d2admin/modules/theme.js 已有
transition src/store/modules/d2admin/modules/transition.js 已有
page src/store/modules/d2admin/modules/page.js 已有
menu src/store/modules/d2admin/modules/menu.js 已有
size src/store/modules/d2admin/modules/size.js 已有
color src/store/modules/d2admin/modules/color.js 已有
db src/store/modules/d2admin/modules/db.js 已有

2.3 API 文件

文件 旧路径 新目标路径 说明
登录/注销 API src/api/login.js src/api/auth.js loginAdminUser()logoutAdminUser()

注意:旧项目 login.js 中 import 了 @/plugin/axios/request,这是旧项目的 axios 封装。
新项目使用 @/api/_service 中的 request,搬迁时需替换 import 路径。


2.4 静态资源(图片)

文件 旧路径 新目标路径 说明
登录页 Logo public/image/logo/sc_logo.png public/image/logo/sc_logo.png 登录表单上方的 Logo

旧项目 public/image/logo/ 目录下共有 9 个文件,但登录页面只用 sc_logo.png
根据需要可按需搬其他 logo 文件。新项目原有 src/views/system/login/image/logo@2x.png,搬迁后可删除。


2.5 i18n 语言包

i18n key 前缀page.system_settings.system_monitoring.system.login

key 中文 英文
time_is_most_precious 时间是一切财富中最宝贵的财富 Time is the most precious of all wealth
username 用户名 Username
password 密码 Password
login 登录 Login
quick_select_user 快速选择用户 Quick Select User
please_enter_username 请输入用户名 Please enter username
please_enter_password 请输入密码 Please enter password
please_enter_code 请输入验证码 Please enter captcha
dev_version 开发版本 Development Version
test_version 测试版本 Test Version
form_validation_failed 表单校验失败,请检查 Form validation failed

搬迁操作

  1. src/locales/zh-chs.jsonpage.system.system_monitoring 下新增:
"login": {
  "time_is_most_precious": "时间是一切财富中最宝贵的财富",
  "username": "用户名",
  "password": "密码",
  "login": "登录",
  "quick_select_user": "快速选择用户",
  "please_enter_username": "请输入用户名",
  "please_enter_password": "请输入密码",
  "please_enter_code": "请输入验证码",
  "dev_version": "开发版本",
  "test_version": "测试版本",
  "form_validation_failed": "表单校验失败,请检查"
}
  1. src/locales/en.json 中对应添加英文翻译。

2.6 CSS 公共样式(依赖但不在页面内)

页面中使用了 SCSS 的 %placeholder 选择器:

placeholder 作用 定义位置
%unable-select 禁止用户选中 + 鼠标变手形 src/assets/style/public.scss
%full 绝对定位填满父元素 src/assets/style/public.scss
%flex-center-col flex 垂直水平居中 src/assets/style/public.scss
$color-text-normal 文字颜色变量 src/assets/style/unit/color.scss
$color-primary 主色变量 src/assets/style/unit/color.scss
$color-bg 背景色变量 src/assets/style/unit/color.scss

这些在新项目中已存在(通过 additionalData 全局注入),不需要额外搬迁。


2.7 工具/插件依赖(新项目已有,不需搬迁)

依赖 旧路径 新项目状态
util.cookies src/libs/util.cookies.jssrc/libs/util.js 已有
localeMixin src/locales/mixin.js 已有
dayjs npm 包 已有(package.json 中)
$baseUrl Vue.prototype.$baseUrl = process.env.BASE_URL 已在 plugin/d2admin/index.js 注册
vuex mapActions npm 包 已有

2.8 路由(新项目已配置,不需搬迁)

旧路由:

{
  path: '/login',
  name: 'login',
  component: _import('system_settings/system_monitoring/system/login')
}

新项目路由已在 routes.jsframeOut 中配置:

{
  path: '/login',
  name: 'login',
  component: _import('system/login')
}

新路由已指向 system/login,对应的 src/views/system/login/index.vue 需要替换为旧页面内容。


三、搬迁执行步骤

步骤 操作 文件
1 拷贝登录 API替换 import 为 @/api/_service src/api/login.jssrc/api/auth.js
2 拷贝 account Store替换 API 引用路径) src/store/modules/d2admin/modules/account.js
3 拷贝 Logo 图片 public/image/logo/sc_logo.png
4 更新登录页面(替换 import 路径 + i18n key + logo 路径) src/views/system/login/index.vue
5 添加 i18n 语言包 src/locales/zh-chs.json / en.json
6 验证:pnpm serve 启动 → 访问 /login 测试登录流程

四、页面中需要修改的内容

登录页面 index.vue 从旧项目拷贝后,需改以下几处:

4.1 import 路径修正

- import { mapActions } from 'vuex'
- import util from '@/libs/util'
- import localeMixin from '@/locales/mixin.js'
+ // 这些在新项目中路径一致,无需修改
+ // util.cookies、localeMixin、mapActions 均同上

注意:旧页面 mixins 中引用了 localeMixin(切换语言),新项目中此 mixin 在 src/locales/mixin.js 已存在,不需动。

4.2 Logo 图片路径

- <img class="page-login--logo" :src="`${$baseUrl}image/logo/sc_logo.png`">
+ <img class="page-login--logo" src="/image/logo/sc_logo.png">

新项目中 $baseUrl 同样已注册,两种写法均可。建议用绝对路径 /image/logo/sc_logo.png 更直观。

4.3 i18n key 修正

旧页面使用的 key 前缀为 page.system_settings.system_monitoring.system.login.xxx,在新项目中统一简化为 page.system.login.xxx,或按新项目目录结构调整。

建议调整为更简洁的 key

旧 key太长 新 key建议
page.system_settings.system_monitoring.system.login.username page.system.login.username
page.system_settings.system_monitoring.system.login.password page.system.login.password

五、不涉及的依赖(记录说明)

依赖 原因
@/libs/websocket.js 登录页面本身不 import websocketaccount.jslogout action 中引用。新项目如不需 websocket注释掉即可
@/api/modules/sys.user.api.js account.login 只调 login.js API不涉及此文件
public/image/logo/ 其他 png 登录页只用 sc_logo.png,其余 logo 按需搬迁

登录流程完整流程图

正向流程:用户登录

sequenceDiagram
    participant User as 用户
    participant LoginPage as Login 页面
    participant VUEX as Store account
    participant API as 后端 POST /login
    participant Cookie as Cookie
    participant Router as router.beforeEach
    participant Home as 首页

    User->>LoginPage: 输入用户名密码,点击登录
    LoginPage->>LoginPage: el-form.validate 校验表单
    alt 校验失败
        LoginPage-->>User: message.error 表单校验失败
    else 校验通过
        LoginPage->>VUEX: dispatch login { username, password }
        VUEX->>API: loginAdminUser
        alt 登录失败 401 或密码错误
            API-->>VUEX: throw Error
            VUEX->>VUEX: remove token 和 uuid
            VUEX-->>LoginPage: Promise rejected
            LoginPage-->>User: message.error
        else 登录成功
            API-->>VUEX: token 和 userInfo
            VUEX->>Cookie: 写入 token / uuid 有效期365天
            VUEX->>VUEX: localStorage.setItem user_id
            VUEX->>VUEX: dispatch user/set
            VUEX->>VUEX: dispatch load 加载持久化配置
            Note over VUEX: load按序加载: user theme transition page menu size color sourceData
            VUEX-->>LoginPage: Promise resolved
            LoginPage->>Router: router.replace redirect or /
            Router->>Router: beforeEach 检查 token
            Router-->>Home: 鉴权通过,跳转目标页
        end
    end

反向流程:用户注销

sequenceDiagram
    participant User as 用户
    participant Header as 顶栏用户菜单
    participant VUEX as Store account
    participant API as 后端 POST /logout
    participant Cookie as Cookie
    participant WS as WebSocket
    participant LoginPage as Login 页面

    User->>Header: 点击注销
    Header->>VUEX: dispatch logout { confirm: true }
    VUEX->>User: confirm 确定要注销吗
    alt 取消
        User-->>VUEX: 取消
    else 确认
        VUEX->>VUEX: Loading 遮罩
        VUEX->>WS: closeSock 断开 WebSocket
        VUEX->>API: logoutAdminUser
        API-->>VUEX: 服务端清除 session
        VUEX->>VUEX: dispatch db/set 清空 sourceData
        VUEX->>VUEX: dispatch user/set 清空用户信息
        VUEX->>Cookie: remove token / uuid / set block true
        VUEX->>VUEX: Loading 关闭
        VUEX->>LoginPage: router.push { name: login }
        LoginPage-->>User: 返回登录页面
    end

路由守卫鉴权流程(分三种情况)

情况 A无 Token → 跳转登录页

flowchart TD
    A["用户访问 URL"] --> B{"路由需要 auth?"}
    B -->|是| C["Cookie.get(token)"]
    C -->|"token 为空"| D["重定向到 /login?redirect=原地址"]
    D --> E["用户在登录页输入账号密码"]
    E --> F["登录成功"]
    F --> G["router.replace 回到目标页"]
    G --> H["进入首页"]

情况 B有 Token → 恢复会话

flowchart TD
    A["用户访问 URLCookie 中已有 token"] --> B{"路由需要 auth?"}
    B -->|是| C["Cookie.get(token)"]
    C -->|"token 有效"| D["next 放行"]
    D --> E["框架渲染 header-aside 布局"]
    E --> F["d2admin/page/isLoaded"]
    F --> G["d2admin/size/isLoaded"]
    G --> H["页面正常加载"]

    style C fill:#f9f,stroke:#333
    style D fill:#9f9,stroke:#333
    style H fill:#9f9,stroke:#333

情况 CToken 有效但后端已过期 → API 层拦截

flowchart TD
    A["页面加载后调用业务 API"] --> B["axios 请求携带 Authorization header"]
    B --> C{"后端 code === 401?"}
    C -->|否| D["正常返回数据"]
    C -->|"是 401"| E["axios 响应拦截器 catch 401"]
    E --> F["清除 Cookie(token / uuid)"]
    F --> G["Message.error 请重新登录"]
    G --> H["router.push /login"]

    style C fill:#f96,stroke:#333
    style H fill:#f96,stroke:#333

已有 Token 时的完整恢复时序

sequenceDiagram
    participant User as 用户
    participant Browser as 浏览器
    participant Router as router.beforeEach
    participant Cookie as Cookie
    participant Store as Vuex Store
    participant DB as Local DB lowdb
    participant Layout as Layout
    participant Page as 目标页面

    User->>Browser: 打开网页
    Browser->>Router: beforeEnter 触发
    Router->>Store: dispatch page/isLoaded
    Router->>Store: dispatch size/isLoaded
    Router->>Cookie: get token
    Cookie-->>Router: token = eyJ...
    Router->>Router: next 放行
    Router->>Layout: 渲染 header-aside
    Layout->>Store: menu 加载侧边栏
    Store->>DB: get sys.menu.asideCollapse
    DB-->>Store: 上次展开收起状态
    Layout->>Store: theme 加载主题
    Store->>DB: get sys.theme.activeName
    DB-->>Store: 上次选择的主题
    Layout->>Store: page 加载多标签页
    Store->>DB: get sys.page.opened
    DB-->>Store: 上次打开的标签页列表
    Layout->>Page: 目标页面渲染完成
    Page-->>User: 首页正常显示,主题侧栏标签页全部恢复

对比:首次登录 vs 已有 Token

维度 首次登录(无 Token 已有 Token 恢复
入口 /login 登录页 任意页面 URL
路由守卫 拦下 → 重定向 /login 放行
用户操作 输入用户名密码 无需操作
account/login 触发 不触发
account/load() 触发(写入 DB 不触发
page/isLoaded 触发(首次无缓存) 触发(从 DB 恢复)
size/isLoaded 触发 触发
主题/侧栏/标签页 从登录后 load() 写入 从 lowdb 读取上次状态
Cookie 新建 token / uuid 复用已有 token

整体状态流转

stateDiagram-v2
    [*] --> 未登录: 首次访问
    [*] --> 已登录: 已有 token恢复会话
    未登录 --> 登录页面: 路由守卫拦下
    登录页面 --> 提交中: 输入账号密码,点击登录
    提交中 --> 登录成功: API 返回 token
    提交中 --> 登录失败: API 报错 / 401
    登录失败 --> 登录页面: 清除 cookie允许重试
    登录成功 --> 已登录: 写入 cookie + load() 加载配置
    已登录 --> 已登录: 页面刷新token 仍有效Router + DB 恢复)
    已登录 --> 未登录: API 返回 401被强制退出
    已登录 --> 注销中: 点击注销
    注销中 --> 已登录: 取消确认
    注销中 --> 未登录: 确认 → logout API → 清 cookie → 跳 /login

六、搬迁后验证清单

  • pnpm lint 无报错
  • pnpm serve 启动成功
  • 访问 http://localhost:8081/login 能看到完整登录页面
  • 输入正确的用户名密码能登录并跳转首页
  • 中文/英文切换按钮文字正确
  • 登录失败有表单校验提示
  • 浏览器 Cookie 中有 tokenuuid