docs: add i18n spec and login migration docs, fix router trailing char

1. 新增国际化规范文档 `i18n-rules.md`,详细说明项目国际化的规范、key 命名、使用方式等
2. 新增登录页面搬迁文档 `login-page-migration.md`,记录登录页搬迁的步骤、依赖和验证清单
3. 修复生产主数据路由文件中多余的尾随字符
This commit is contained in:
sheng
2026-05-27 14:38:53 +08:00
parent 3eaea3116d
commit 8a4511dc36
3 changed files with 887 additions and 1 deletions

445
docs/i18n-rules.md Normal file
View File

@@ -0,0 +1,445 @@
# i18n 国际化规范文档
> **版本**v1.0
> **适用项目**`mes-ui`
> **语言包文件**`src/locales/zh-chs.json` / `src/locales/en.json` / `src/locales/zh-cht.json` / `src/locales/ja.json`
> **配合使用**`src/composables/useI18n.js``i18nMixin`
---
## 目录
1. [语言包文件规范](#1-语言包文件规范)
2. [Key 命名规范(三层层级)](#2-key-命名规范三层层级)
3. [公共 Key 规范page.common](#3-公共-key-规范pagecommon)
4. [页面中如何使用i18nMixin](#4-页面中如何使用i18nmixin)
5. [常见场景 Key 模板](#5-常见场景-key-模板)
6. [旧项目 Key 迁移对照](#6-旧项目-key-迁移对照)
7. [翻译格式规范](#7-翻译格式规范)
8. [新增页面 Checklist](#8-新增页面-checklist)
---
## 1. 语言包文件规范
### 1.1 文件清单
| 文件 | 语言 | `_element` 值 |
|------|------|--------------|
| `src/locales/zh-chs.json` | 简体中文 | `"zh-CN"` |
| `src/locales/zh-cht.json` | 繁体中文 | `"zh-TW"` |
| `src/locales/en.json` | 英文 | `"en"` |
| `src/locales/ja.json` | 日文 | `"ja"` |
### 1.2 文件格式
- **编码**UTF-8
- **格式**:标准 JSON不允许尾逗号不允许注释
- **顶层结构**
```json
{
"_element": "zh-CN",
"_name": "简体中文",
"page": { ... }
}
```
- `_element`:对应 `element-ui/lib/locale/lang/` 的语言包文件名
- `_name`:语言切换下拉菜单中的显示名
- `page`:所有业务翻译的根节点,之下按模块层级嵌套
### 1.3 维护原则
- 中文和英文文件**必须保持 key 结构完全一致**,不允许一边有 key 而另一边没有
- 新增页面时**中英文同步添加**
- 每次新增后用 `node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"` 验证 JSON 合法性
---
## 2. Key 命名规范(三层层级)
### 2.1 核心规则
```
page.{一级模块英文} .{二级模块英文} .{三级模块英文} .{具体key}
└─ snake_case ─┘└─ snake_case ─┘└─ snake_case ─┘
```
**英文来源**[后台Webman界面截图对照表](./后台Webman界面截图对照表.md) 中的英文列。
**格式转换**:对照表英文 → 全小写 + 空格替换为下划线 + `&` 替换为下划线。
### 2.2 对照表 → i18n Key 映射表
| 对照表英文名 | snake_case用于 i18n key | kebab-case用于目录名 |
|-------------|---------------------------|------------------------|
| System Administration | `system_administration` | `system-administration` |
| Production Master Data | `production_master_data` | `production-master-data` |
| Equipment Management | `equipment_management` | `equipment-management` |
| Planning & Production | `planning_production` | `planning-production` |
| Quality Management | `quality_management` | `quality-management` |
| Data Platform | `data_platform` | `data-platform` |
| Factory Model | `factory_model` | `factory-model` |
| Process Model | `process_model` | `process-model` |
| Product Management | `product_management` | `product-management` |
| Material Model | `material_model` | `material-model` |
| SPC Configuration | `spc_configuration` | `spc-configuration` |
| Team Model | `team_model` | `team-model` |
| User Management | `user_management` | `user-management` |
| Menu Management | `menu_management` | `menu-management` |
| System Utilities | `system_utilities` | `system-utilities` |
| System Monitoring | `system_monitoring` | `system-monitoring` |
| Batch Management | `batch_management` | `batch-management` |
| Production Monitoring | `production_monitoring` | `production-monitoring` |
| Process Control | `process_control` | `process-control` |
| Inspection Management | `inspection_management` | `inspection-management` |
| Traceability | `traceability` | `traceability` |
| Production Reports | `production_reports` | `production-reports` |
| Correlation Analysis | `correlation_analysis` | `correlation-analysis` |
| Factory Area | `factory_area` | `factory-area` |
| Production Line | `production_line` | `production-line` |
> **完整映射表**见本文档末尾附录 A。
### 2.3 完整示例
以「生产配置 → 工厂模型 → 工厂区域」页面为例:
```json
{
"page": {
"production_master_data": {
"factory_model": {
"factory_area": {
"search": "查询",
"reset": "重置",
"code": "所区编码",
"name": "所区名称",
"add": "新 增",
"edit": "编 辑",
"delete": "删 除"
}
}
}
}
}
```
对应的 `i18nMixin` 前缀:
```js
mixins: [i18nMixin('page.production_master_data.factory_model.factory_area')]
```
---
## 3. 公共 Key 规范page.common
### 3.1 什么应该放公共
跨页面、跨模块重复出现的文案,提取到 `page.common` 下:
```json
{
"page": {
"common": {
"help": "帮 助",
"confirm": "确定",
"cancel": "取消",
"save": "保存",
"delete": "删除",
"edit": "编辑",
"add": "新增",
"search": "查询",
"reset": "重置",
"operation": "操作",
"tip": "提示",
"confirm_delete": "确定要执行该操作吗?",
"operation_success": "操作成功",
"no_data": "暂无数据",
"loading": "加载中..."
}
}
}
```
### 3.2 已有公共 Key 清单
| key | 中文 | 英文 | 用途 |
|-----|------|------|------|
| `page.common.help` | 帮 助 | Help | 表格工具栏右侧帮助按钮 |
> 后续发现跨页面共用 key 时,持续往 `page.common` 中补充。
### 3.3 如何使用
```vue
<page-table :help-text="$t(ckey('help'))" />
```
`ckey('help')``'page.common.help'`,由 `i18nMixin` 自动注入。
### 3.4 判断标准:该不该放 common
| 情况 | 放哪里 | 示例 |
|------|--------|------|
| 多个一级模块都出现 | `page.common` | 帮助、确定、取消 |
| 只在本模块内出现 | 模块自己的 key | 所区编码、产线编码 |
| 不确定 | 先放在模块内,等第二次出现时提取 | — |
---
## 4. 页面中如何使用i18nMixin
### 4.1 页面 Script 部分
```js
import { i18nMixin } from '@/composables/useI18n'
export default {
mixins: [i18nMixin('page.production_master_data.factory_model.factory_area')],
data () {
const t = this.$t.bind(this)
const k = (s) => t(this.key(s)) // 当前页面翻译
const ck = (s) => t(this.ckey(s)) // 公共翻译
return {
formCols: [
[{ label: k('code'), placeholder: k('enter_code') }]
],
rules: {
code: [{ required: true, message: k('enter_code'), trigger: 'blur' }]
}
}
},
created () {
this.columns = useTableColumns([
{ prop: 'code', label: this.key('code') }
])
}
}
```
### 4.2 页面 Template 部分
```vue
<template>
<!-- 当前页面翻译 -->
<el-form-item :label="$t(key('code'))">
<el-input :placeholder="$t(key('enter_code'))" />
</el-form-item>
<el-button>{{ $t(key('search')) }}</el-button>
<!-- 公共翻译 -->
<page-table :help-text="$t(ckey('help'))" />
</template>
```
### 4.3 data() 中翻译的时机说明
`data()``created` 之前执行,此时 `this` 已经可用。因此:
- **column label / formCols / rules.message**:在 `data()` 中或 `created()``this.key()` 都可以
- **推荐在 `data()` 中用 `k()` 提前翻译**,避免子组件 `$t()` 的 webpack HMR 缓存问题
---
## 5. 常见场景 Key 模板
### 5.1 标准 CRUD 页面(每个页面必有的 key
```json
{
"search": "查询",
"reset": "重置",
"add": "新 增",
"edit": "编 辑",
"delete": "删 除",
"operation": "操作",
"add_title": "新增{模块名}",
"edit_title": "编辑{模块名}",
"operation_success": "操作成功",
"confirm_delete": "确定要执行该操作吗?",
"enter_xxx": "请输入{字段名}",
"select_xxx": "请选择{字段名}"
}
```
### 5.2 列表页字段 Key
```json
{
"sort": "序号",
"code": "{实体}编码",
"name": "{实体}名称",
"remark": "备注"
}
```
### 5.3 表单校验 Key
```json
{
"enter_code": "请输入{实体}编码",
"enter_name": "请输入{实体}名称",
"remark_length": "长度在 1 到 100 个字符",
"validation_fail": "校验失败"
}
```
### 5.4 登录页 Key
```json
{
"username": "用户名",
"password": "密码",
"login": "登录",
"please_enter_username": "请输入用户名",
"please_enter_password": "请输入密码",
"form_validation_failed": "表单校验失败,请检查"
}
```
---
## 6. 旧项目 Key 迁移对照
### 6.1 旧 Key 结构 vs 新 Key 结构
旧项目 key 路径深且命名不统一:
| 旧 key 前缀 | 新 key 前缀 |
|-----------|-----------|
| `page.system_settings.user_management.role` | `page.system_administration.user_management.role` |
| `page.system_settings.user_management.user` | `page.system_administration.user_management.user` |
| `page.system_settings.menu_configuration.menu` | `page.system_administration.menu_management.menu_configuration` |
| `page.system_settings.system_assistant.operate_log` | `page.system_administration.system_utilities.operation_logs` |
| `page.system_settings.system_monitoring.system.login` | `page.system_administration.system_monitoring.login` |
| `page.production_configuration.factory_model.factory_area` | `page.production_master_data.factory_model.factory_area` |
| `page.production_configuration.matetial_model.*` | `page.production_master_data.material_model.*` |
| `page.planning_production.production_batch_management.batch` | `page.planning_production.batch_management.batch_list` |
| `page.data_middleground.basic_traceability.*` | `page.data_platform.traceability.*` |
| `page.warehouse.*` | `page.warehouse.*`(待确定对照表英文名) |
### 6.2 搬迁时的操作步序
1. 确定页面对应的对照表三级模块英文名
2.`page.{一级}.{二级}.{三级}` 组装新 key 前缀
3.`zh-chs.json` 中按三层嵌套创建节点
4.`en.json` 中创建相同结构
5. 将旧 key 的翻译值复制到新 key 下
6. 页面代码中 `i18nMixin` 参数改为新前缀
7. 模板中 `$t('旧key')` 全部改为 `$t(key('新suffix'))`
---
## 7. 翻译格式规范
### 7.1 中文规范
| 场景 | 格式 | 示例 |
|------|------|------|
| 按钮文字 | 字间加空格(两字不加) | `"查询"``"新 增"``"批量删除"` |
| 占位提示 | `请输入{名称}` | `"请输入所区编码"` |
| 校验消息 | 完整句,不加句号 | `"长度在 1 到 100 个字符"` |
| 提示弹框 | 加问号 | `"确定要执行该操作吗?"` |
| 操作成功消息 | 不加"成功"后缀的冗余 | `"操作成功"`(而非"保存成功"、"编辑成功"各自定义) |
### 7.2 英文规范
| 场景 | 格式 | 示例 |
|------|------|------|
| 按钮文字 | 首字母大写 | `"Search"``"Add"``"Edit"` |
| 占位提示 | `Please enter {name}` | `"Please enter area code"` |
| 校验消息 | 完整句 | `"Length should be 1 to 100 characters"` |
| 提示弹框 | 问句 | `"Are you sure to delete?"` |
| 操作成功消息 | 过去式或名词 | `"Operation succeeded"` |
### 7.3 占位符
使用 `{name}` 格式,不使用 `%s` / `{0}`
```json
"please_enter": "请输入{name}"
```
```js
this.$t('please_enter', { name: '所区编码' })
// → "请输入所区编码"
```
---
## 8. 新增页面 Checklist
新增一个 CRUD 页面时,按以下顺序操作:
- [ ] 1. 在 [后台Webman界面截图对照表](./后台Webman界面截图对照表.md) 中找到该页面的三级英文名
- [ ] 2. 确定 i18n key 前缀:`page.{一级snake_case}.{二级snake_case}.{三级snake_case}`
- [ ] 3. 在 `zh-chs.json` 的对应节点下添加本页面全部 key
- [ ] 4. 在 `en.json` 的相同节点下添加对应英文翻译
- [ ] 5. 验证 JSON 合法性:`node -e "JSON.parse(require('fs').readFileSync('src/locales/zh-chs.json','utf8'))"`
- [ ] 6. 页面中使用 `mixins: [i18nMixin('key前缀')]`
- [ ] 7. 模板中用 `$t(key('xxx'))` 替代硬编码文字
- [ ] 8. data() 中用 `k('xxx')` 提前翻译 formCols / rules
- [ ] 9. 公共文案(帮助、确定、取消等)用 `ckey('xxx')` 引用
- [ ] 10. `pnpm lint` 无报错
---
## 附录 A对照表 → i18n Key 完整映射
### 一级模块
| 对照表英文 | snake_casei18n | kebab-case目录 |
|-----------|-------------------|-------------------|
| System Administration | `system_administration` | `system-administration` |
| Production Master Data | `production_master_data` | `production-master-data` |
| Equipment Management | `equipment_management` | `equipment-management` |
| Planning & Production | `planning_production` | `planning-production` |
| Quality Management | `quality_management` | `quality-management` |
| Data Platform | `data_platform` | `data-platform` |
| Warehouse | `warehouse` | `warehouse` |
| SCADA Management | `scada_management` | `scada-management` |
### 生产配置 → 二级模块
| 二级(对照表) | snake_case | 三级页面数 |
|---------------|-----------|:--:|
| Factory Model | `factory_model` | 2 |
| Process Model | `process_model` | 3 |
| Product Management | `product_management` | 2 |
| Material Model | `material_model` | 4 |
| SPC Configuration | `spc_configuration` | 1 |
| Team Model | `team_model` | 3 |
### 设备模型 → 二级模块
| 二级(对照表) | snake_case |
|---------------|-----------|
| Equipment Category | `equipment_category` |
| Equipment Management | `equipment_management` |
| Inspection Management | `inspection_management` |
| Maintenance Management | `maintenance_management` |
| Repair Management | `repair_management` |
| Consumables Management | `consumables_management` |
### 系统设置 → 二级/三级
| 二级(对照表) | snake_case | 三级 snake_case |
|---------------|-----------|----------------|
| User Management | `user_management` | `role` / `user` |
| Menu Management | `menu_management` | `menu_configuration` |
| System Utilities | `system_utilities` | `operation_logs` / `api_logs` |
| System Monitoring | `system_monitoring` | `monitoring_configuration` |
| Organization | `organization` | `production_team_manage` / `production_shift_management` / `production_shift_calender` |
| OCR | `ocr` | `config` / `log` |
---
## 附录 B当前已实施页面
| 页面 | i18nMixin 前缀 | 语言包节点 |
|------|---------------|----------|
| 工厂区域 | `page.production_master_data.factory_model.factory_area` | `zh-chs.json` / `en.json` ✅ |

View File

@@ -0,0 +1,441 @@
# 登录页面搬迁文档
> **搬迁源**`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` | **核心**:含 `login``logout` action |
| user | `src/store/modules/d2admin/modules/user.js` | `src/store/modules/d2admin/modules/user.js` | account.login 中调用 `d2admin/user/set`**新项目已存在** |
> `account.js` 的 `login` 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.json``page.system.system_monitoring` 下新增:
```json
"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": "表单校验失败,请检查"
}
```
2.`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.js``src/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 路由(新项目已配置,不需搬迁)
旧路由:
```js
{
path: '/login',
name: 'login',
component: _import('system_settings/system_monitoring/system/login')
}
```
新项目路由已在 `routes.js``frameOut` 中配置:
```js
{
path: '/login',
name: 'login',
component: _import('system/login')
}
```
> ✅ 新路由已指向 `system/login`,对应的 `src/views/system/login/index.vue` 需要替换为旧页面内容。
---
## 三、搬迁执行步骤
| 步骤 | 操作 | 文件 |
|:--:|------|------|
| 1 | 拷贝登录 API替换 import 为 `@/api/_service` | `src/api/login.js``src/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 路径修正
```diff
- 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 图片路径
```diff
- <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 websocket`account.js``logout` action 中引用。新项目如不需 websocket注释掉即可 |
| `@/api/modules/sys.user.api.js` | 旧 `account.login` 只调 `login.js` API不涉及此文件 |
| `public/image/logo/` 其他 png | 登录页只用 `sc_logo.png`,其余 logo 按需搬迁 |
---
## 登录流程完整流程图
### 正向流程:用户登录
```mermaid
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
```
### 反向流程:用户注销
```mermaid
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 → 跳转登录页
```mermaid
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 → 恢复会话
```mermaid
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 层拦截
```mermaid
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 时的完整恢复时序
```mermaid
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 |
---
### 整体状态流转
```mermaid
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 中有 `token``uuid`

View File

@@ -14,5 +14,5 @@ export default {
meta: { ...meta, cache: true, title: '工厂区域' },
component: _import('production-master-data/factory-model/factory-area')
}
])('production_master_data-')
])('production_master_data-')
}