初始化
This commit is contained in:
1
memory/.session-last
Normal file
1
memory/.session-last
Normal file
@@ -0,0 +1 @@
|
||||
{"projectPath":"E:\\AI\\claude\\new\\mokeeGateway","endedAt":"2026-06-20T10:55:00+08:00","sessionId":"session-20260620-2"}
|
||||
24
memory/MEMORY.md
Normal file
24
memory/MEMORY.md
Normal file
@@ -0,0 +1,24 @@
|
||||
- [项目概览](project-overview.md) — 统一登录网关平台完整信息、架构、状态、已知问题
|
||||
- [2026-06-28 会话-1](session-20260628-1.md) — 修复登录后 /open/token 和文件下载接口重复调用
|
||||
- [2026-06-09 会话](session-log.md) — 完整开发过程、决策、Bug修复、待办
|
||||
- [2026-06-10 会话-1](session-20260610-1.md) — 数据库地址变更、前端环境变量整理
|
||||
- [2026-06-10 会话-2](session-20260610-2.md) — UUID迁移、权限系统、UI翻新、数据库对齐、Cookie跨域修复
|
||||
- [2026-06-11 会话-1](session-20260611-1.md) — 头像上传修复、用户信息显示修复、文件存DB、系统Bug全面检查
|
||||
- [2026-06-12 会话-1](session-20260612-1.md) — 域名迁移zgitm.com、对外开放API、邮件服务、Token一次消费、移动端适配
|
||||
- [2026-06-12 会话-2](session-20260612-2.md) — VPN网络带宽诊断、前端加载慢根因定位(Nginx代理丢失gzip)
|
||||
- [2026-06-13 会话-1](session-20260613-1.md) — 数据库IP切换、11个bug修复、42文件加注释、assignRoles session修复
|
||||
- [2026-06-13 会话-2](session-20260613-2.md) — UI移动端优化、登录跳转、操作人乱码修复、文件存储迁移磁盘、系统配置页、开放文件API
|
||||
- [2026-06-13 会话-3](session-20260613-3.md) — 头像401、菜单check-strictly、移动端全面优化、token/info接口、唯一键校验、数据权限
|
||||
- [2026-06-13 会话-4](session-20260613-4.md) — Widget实施 + 10+Bug修复(菜单动态化/数据权限/ApiFilter/网关转发/ElMessage等)+ 接入文档完善
|
||||
- [2026-06-13 会话-5](session-20260613-5.md) — 5个前端修复(ElMessage弹窗/双首页/服务器卡片/图表数据/头像上传)
|
||||
- [2026-06-15 会话-1](session-20260615-1.md) — 前端UI统一优化:分页/布局/CSS变量/下载修复,12文件改动
|
||||
- [2026-06-15 会话-2](session-20260615-2.md) — sys_user唯一索引删除,修复逻辑删除与uk_username冲突
|
||||
- [2026-06-17 会话-1](session-20260617-1.md) — 前端日期时间格式统一为 yyyy-MM-dd HH:mm:ss
|
||||
- [2026-06-18 会话-1](session-20260618-1.md) — 网关SocketTimeout日志分析 + Widget接入指南补全(后端文档+前端页面)
|
||||
- [2026-06-18 会话-2](session-20260618-2.md) — SQL执行26权限 + 7页面查看按钮 + 3页面列宽填满 + 个人中心权限 + ICP备案号
|
||||
- [2026-06-19 会话-1](session-20260619-1.md) — 接入文档全面审查修复:permission字段、字段说明表、v-permission指令、Widget修复、废弃放行API、删除登录API
|
||||
- [2026-06-20 会话-1](session-20260620-1.md) — menu/router接口改造、user/info权限过滤、文档清理、数据库IP迁移域名、Redis Key前缀
|
||||
- [2026-06-20 会话-2](session-20260620-2.md) — 修复TokenAuthFilter Redis Key前缀遗漏导致登录后Token找不到会话
|
||||
- [2026-06-21 会话-1](session-20260621-1.md) — 接口性能排查(/auth/system/list + /open/token) + sys_system.system_code加索引
|
||||
- [2026-06-23 会话-1](session-20260623-1.md) — Cookie Token兜底确认 + API白名单跳过鉴权方案设计(待实施)
|
||||
- [部署审批](deploy-approval-required.md) — 部署 10.1.1.170 必须经用户明确授权
|
||||
102
memory/session-20260611-1.md
Normal file
102
memory/session-20260611-1.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
name: session-20260611-1
|
||||
description: 2026-06-11 会话 — 头像上传修复、用户信息显示修复、文件存DB、系统Bug全面检查
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-11
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-11T01:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-11 会话
|
||||
|
||||
## 会话摘要
|
||||
修复了上次会话遗留的2个已知问题(头像上传、用户信息不显示),将文件存储从磁盘改为数据库,并对整个系统进行了全面Bug检查,修复了8个高/中优先级问题。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、sys_file 表重构(文件存数据库)
|
||||
- **做了什么**:
|
||||
- 重新设计 sys_file 表,添加 `file_data LONGBLOB` 字段存储二进制
|
||||
- 统一 Entity 和 DDL:新增 `system_id`, `mime_type`, `upload_user_id`, `md5` 字段
|
||||
- 删除旧磁盘存储字段 `file_path`(→file_data), `upload_by`(→upload_user_id)
|
||||
- **原因**: 用户要求图片文件存入数据库而非磁盘
|
||||
- **结果**: QA 数据库已更新,PROD 迁移脚本已准备(`sql/prod_migrate_sys_file.sql`)
|
||||
|
||||
### 二、FileServiceImpl 重写
|
||||
- **做了什么**: upload()改为读取文件字节存入DB;page()/list()排除file_data字段;新增getMetaById();新增文件输出流
|
||||
- **原因**: 配合数据库存储方案
|
||||
- **结果**: 编译通过
|
||||
|
||||
### 三、FileController 更新
|
||||
- **做了什么**: upload返回时清除fileData;新增 `GET /{id}/view` 端点直接输出文件流(支持浏览器 `<img>` 标签加载)
|
||||
- **原因**: 文件存DB后需要HTTP接口访问
|
||||
|
||||
### 四、PersonalView 头像上传修复
|
||||
- **做了什么**:
|
||||
- 修正 `res.data?.url` → 通过 `res.data?.id` 构建访问URL
|
||||
- 上传时添加 `fd.append('fileType', 'avatar')`
|
||||
- 头像地址格式: `{VITE_GATEWAY_URL}/zgapi/v1/admin/file/{id}/view`
|
||||
- 更新后调用 `authStore.fetchUserInfo()` 刷新store
|
||||
- **原因**: Entity字段名不匹配+文件访问方式变更
|
||||
|
||||
### 五、AdminLayout 用户信息修复
|
||||
- **做了什么**: onMounted中调用 `authStore.fetchUserInfo()`
|
||||
- **原因**: 跨域名跳转(login.user.mokee.com→web.gw.mokee.com)后Pinia状态丢失,需要重新加载
|
||||
- **结果**: 顶栏头像和用户名正确显示
|
||||
|
||||
### 六、Redis TokenInfo 同步机制
|
||||
- **做了什么**:
|
||||
- 登录时建立反向索引 `auth:user_session:{userId}` → tokenId
|
||||
- 登出时清除反向索引
|
||||
- UserServiceImpl.update()后同步更新Redis中的TokenInfo(username/realName/email/phone/avatar/post)
|
||||
- UserServiceImpl.assignRoles()后清除用户Redis会话强制重新登录
|
||||
- RoleServiceImpl.assignMenus()后清除所有受影响用户的Redis会话
|
||||
- **原因**: 用户信息/角色/权限变更后前端fetchUserInfo读到过期数据
|
||||
|
||||
### 七、SysSystem 实体补充
|
||||
- **做了什么**: 添加 `gatewayUrl` 字段映射 `gateway_url` 列
|
||||
- **原因**: DDL中有此列但Entity缺少映射,INSERT可能失败
|
||||
|
||||
### 八、前端错误处理修复
|
||||
- **做了什么**: LoginView和UserForm的catch块添加具体错误提示
|
||||
- **原因**: 登录失败/保存失败时用户看不到任何反馈
|
||||
|
||||
### 九、系统全面检查发现(已记录,部分待处理)
|
||||
- A-2: SysMenu.menuType注释错误(0-based vs 1-based) — LOW
|
||||
- D-3~D-6: 多处catch块无用户反馈 — MEDIUM(拦截器已提供基线处理)
|
||||
- E-1: Cookie domain硬编码.mokee.com导致localhost开发不可用 — HIGH(已知限制)
|
||||
- E-2: auth.ts和request.ts重复实现Token Cookie操作 — MEDIUM
|
||||
- F-3: bindSystems/unbindSystems不同步Redis — MEDIUM
|
||||
- F-5: RoleServiceImpl.update不同步Redis — LOW
|
||||
|
||||
## 修改文件清单
|
||||
**后端 (7个文件)**:
|
||||
- `mokee-gateway-common/.../entity/SysFile.java` — 重构字段
|
||||
- `mokee-gateway-common/.../entity/SysSystem.java` — 添加gatewayUrl
|
||||
- `mokee-gateway-admin/.../service/FileService.java` — 新增getMetaById
|
||||
- `mokee-gateway-admin/.../service/impl/FileServiceImpl.java` — 完全重写(DB存储)
|
||||
- `mokee-gateway-admin/.../controller/FileController.java` — 新增view端点
|
||||
- `mokee-gateway-admin/.../service/impl/UserServiceImpl.java` — Redis同步+会话失效
|
||||
- `mokee-gateway-admin/.../service/impl/RoleServiceImpl.java` — 角色变更会话失效
|
||||
- `mokee-gateway-auth/.../service/impl/AuthServiceImpl.java` — 反向索引
|
||||
|
||||
**前端 (3个文件)**:
|
||||
- `mokee-gateway-web/src/views/admin/PersonalView.vue` — 头像上传修复
|
||||
- `mokee-gateway-web/src/views/admin/AdminLayout.vue` — fetchUserInfo onMount
|
||||
- `mokee-gateway-web/src/views/login/LoginView.vue` — 错误提示
|
||||
- `mokee-gateway-web/src/views/admin/user/UserForm.vue` — 错误提示
|
||||
|
||||
**SQL (4个文件)**:
|
||||
- `sql/qa_ddl.sql` — sys_file新结构
|
||||
- `sql/prod_align_qa.sql` — sys_file新结构
|
||||
- `sql/prod_migrate_sys_file.sql` — PROD迁移(新建)
|
||||
- `init_qa_database.py` — sys_file新结构
|
||||
|
||||
## 待处理
|
||||
- [x] **PROD 数据库 sys_file 表迁移** — 已完成,QA和PROD结构一致
|
||||
- [ ] 部署前端到PROD(Nginx 10.10.1.160)
|
||||
- [ ] 部署后端到PROD(10.10.1.170)
|
||||
- [ ] 验证头像上传端到端流程
|
||||
- [ ] E-1 Cookie域localhost问题(开发环境限制,暂不处理)
|
||||
- [ ] F-3 bindSystems/unbindSystems Redis同步(低优先级)
|
||||
133
memory/session-20260612-1.md
Normal file
133
memory/session-20260612-1.md
Normal file
@@ -0,0 +1,133 @@
|
||||
---
|
||||
name: session-20260612-1
|
||||
description: 2026-06-12 会话 — 域名迁移mokee.com→zgitm.com、对外开放API、邮件服务、Token一次消费、文件管理、移动端适配
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-12
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-12T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-12 会话
|
||||
|
||||
## 会话摘要
|
||||
域名从 mokee.com 迁移到 zgitm.com,新增对外开放API(Token获取+邮件发送+一次消费),新增邮件服务(阿里企业邮箱),新增Token日志和文件管理页面,全员移动端适配,修复多个关键Bug。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、域名迁移 mokee.com → zgitm.com
|
||||
- `.env.production` 所有 URL 改为 `zgitm.com`
|
||||
- `auth.ts` Cookie domain `.zgitm.com`(环境变量 `VITE_COOKIE_DOMAIN`)
|
||||
- `request.ts` Cookie domain 环境变量化
|
||||
- `IntegrationDoc.vue` 备用 URL 更新
|
||||
- **Bug**: Cookie domain 拼写错误 `.zgtim.com` → 修正为 `.zgitm.com`
|
||||
- **Bug**: 登录不跳转 → Cookie domain 不匹配导致跨子域丢失
|
||||
- Nginx 需要配置 `zgitm.com` 域名
|
||||
|
||||
### 二、对外开放 API
|
||||
- **获取Token**: `POST /zgapi/v1/open/token` 只需传 `systemCode`
|
||||
- **发送邮件**: `POST /zgapi/v1/open/email/send` 带 Bearer Token
|
||||
- **一次消费**: 每个 Token 只能用一次,Redis `open:token:{id}:consumed` 标记
|
||||
- **30分钟有效期**
|
||||
- 网关路由 `/zgapi/v1/open/` → admin
|
||||
- TokenAuthFilter 放行 `/zgapi/v1/open/token`,其他 open 路径验证 open token
|
||||
|
||||
### 三、邮件服务
|
||||
- SMTP: `smtp.qiye.aliyun.com:465` SSL, `admin@zgitm.com` / `mokee2016.`
|
||||
- `EmailService.java` — 支持纯文本/HTML/附件,自动加 `[QA]`/`[PROD]` 前缀
|
||||
- `EmailService.setFrom()` 设发件人(阿里企业邮箱要求发件人=认证账号)
|
||||
- `EmailController.java` — 后台发送+记录+分页查询+Token日志
|
||||
- `sys_email_log` 表 — 发送记录
|
||||
- `@ConditionalOnBean` 问题 → 改为 `@Autowired(required = false)` + null检查
|
||||
- **Bug**: 网关模块无 mail 配置导致 `@Value("${spring.mail.username}")` 启动失败 → 加默认值 `:}`
|
||||
|
||||
### 四、编码兼容
|
||||
- **Bug**: 外部系统发 GBK 编码 JSON → Jackson 按 UTF-8 解析失败 `Invalid UTF-8 start byte 0xb2`
|
||||
- 网关方案被拒绝 → 在 `OpenApiController` 手动读字节流,检测 GBK→UTF-8 转换
|
||||
- API 文档要求 `Content-Type: application/json; charset=UTF-8`
|
||||
|
||||
### 五、文件管理
|
||||
- 文件二进制存入数据库 `file_data LONGBLOB`
|
||||
- `sys_file` 表结构调整(QA+PROD)
|
||||
- `FileController.{id}/view` 端点输出图片流
|
||||
- `FileList.vue` — 文件列表+上传+预览
|
||||
- **Bug**: 图片显示 `ERR_BLOCKED_BY_ORB` → view 端点加 CORS 头
|
||||
- **Bug**: 上传报 `MissingServletRequestPartException` → 网关 `spring.servlet.multipart.enabled=false`
|
||||
- **Bug**: 图片 `<img>` 不带 Authorization 头 → TokenAuthFilter 支持 Cookie 读取 token
|
||||
|
||||
### 六、系统Bug全面检查
|
||||
- A-1: `SysSystem` 缺 `gatewayUrl` 字段 → 已添加
|
||||
- D-1/D-2: LoginView/UserForm 错误静默吞没 → 加错误提示
|
||||
- E-1: Cookie domain 硬编码 → 改为环境变量 `VITE_COOKIE_DOMAIN`
|
||||
- F-1/F-2: assignRoles/assignMenus 不同步 Redis → 清除会话强制重登
|
||||
- F-4: username 不同步 Redis → 已加同步
|
||||
|
||||
### 七、移动端适配(全部22个Vue页面)
|
||||
- AdminLayout: 汉堡菜单 + 侧边栏滑出 + 遮罩
|
||||
- 全局: 表格横向滚动、弹窗95vw、按钮缩小
|
||||
- 所有列表页: 工具栏垂直排列、select/input 100%宽
|
||||
- 所有表单页: max-width→100%、label缩到70px、按钮全宽
|
||||
- 操作列: 去掉 `fixed="right"`,手机端只显示图标
|
||||
|
||||
### 八、Token日志
|
||||
- `sys_open_token_log` 表(QA+PROD)
|
||||
- `OpenTokenLogList.vue` — Token日志页面
|
||||
- 菜单 "Token日志" 在日志审计下
|
||||
- **Bug**: Token日志跳转登录 → 接口路径从 `/zgapi/v1/open/` 移到 `/zgapi/v1/admin/email/token-log/page`
|
||||
|
||||
### 九、API文档
|
||||
- `docs/open-api-doc.md` — 独立API文档,使用生产地址 `gw.server.zgitm.com`
|
||||
- Java(Hutool)调用示例
|
||||
- UTF-8 编码要求醒目提示
|
||||
|
||||
### 十、数据库变更(QA+PROD均已执行)
|
||||
- `sys_file` 表重建(file_data LONGBLOB + 新结构)
|
||||
- `sys_file` 添加 `file_url` 兼容列
|
||||
- `sys_open_token_log` 表创建
|
||||
- `sys_email_log` 表创建
|
||||
- 文件管理菜单+权限 `system:file:*`
|
||||
- 邮件管理菜单+权限 `system:email:*`
|
||||
- Token日志菜单+权限 `system:token:list`
|
||||
|
||||
## 修改文件清单
|
||||
**后端**:
|
||||
- `SysSystem.java` — 添加 gatewayUrl
|
||||
- `SysFile.java` — 重构(file_data)
|
||||
- `SysEmailLog.java` — 新建
|
||||
- `SysOpenTokenLog.java` — 新建
|
||||
- `EmailService.java` — 新建(setFrom修复)
|
||||
- `JwtUtil.java` — generateOpenToken()
|
||||
- `FileService.java` / `FileServiceImpl.java` — DB存储重写
|
||||
- `FileController.java` — view端点+CORS
|
||||
- `EmailController.java` — 发送+记录+Token日志
|
||||
- `OpenApiController.java` — Token获取+邮件发送+编码兼容+自主解析tokenId
|
||||
- `UserServiceImpl.java` — Redis同步+会话失效
|
||||
- `RoleServiceImpl.java` — 角色变更会话失效
|
||||
- `AuthServiceImpl.java` — 反向索引
|
||||
- `TokenAuthFilter.java` — Cookie token + Open API认证
|
||||
- `GatewayController.java` — open路由+multipart修复
|
||||
- 8个 application-*.yml — 日志级别+邮件配置+multipart禁用
|
||||
|
||||
**前端**:
|
||||
- `.env.production` / `.env.development` — VITE_COOKIE_DOMAIN
|
||||
- `auth.ts` — Cookie domain环境变量化
|
||||
- `request.ts` — Cookie domain环境变量化
|
||||
- `LoginView.vue` — 错误提示+移动端
|
||||
- `AdminLayout.vue` — fetchUserInfo+汉堡菜单+移动端+文件/邮件/Token菜单
|
||||
- `PersonalView.vue` — 头像上传修复+移动端
|
||||
- `FileList.vue` — 新建(上传+预览+移动端)
|
||||
- `EmailList.vue` — 新建(发送+记录+移动端)
|
||||
- `OpenTokenLogList.vue` — 新建(移动端)
|
||||
- `IconPicker.vue` — 已上传图标标签页
|
||||
- 15个页面 — 移动端@media适配
|
||||
- 7个表格 — 去掉fixed="right"
|
||||
- `router/index.ts` — 路由+标题favicon
|
||||
- `global.css` — 全局移动端CSS
|
||||
|
||||
**文档**:
|
||||
- `docs/open-api-doc.md` — 对外开放API文档
|
||||
|
||||
## 已知问题
|
||||
- E-1: Cookie domain localhost开发不可用(开发环境VITE_COOKIE_DOMAIN为空)
|
||||
- PROD Nginx 需要配 `zgitm.com` 域名
|
||||
- Docker部署需要重新构建镜像
|
||||
57
memory/session-20260612-2.md
Normal file
57
memory/session-20260612-2.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
name: session-20260612-2
|
||||
description: 2026-06-12 第2次会话 — VPN网络带宽诊断、Nginx代理丢失gzip修复、共享静态资源域名解决双域重复加载
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-12
|
||||
sessionNumber: 2
|
||||
startTime: 2026-06-12T19:30:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-12 第2次会话
|
||||
|
||||
## 会话摘要
|
||||
用户反馈 Vue 前端通过 VPN 访问非常慢(JS/CSS 加载要 1 分钟)。诊断发现根因是 Nginx 代理层(10.10.1.160)丢失了 gzip 压缩,导致 1MB+ 的文件通过 VPN 窄带宽原样传输。用户自行修复。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### VPN 网络诊断 — 前端加载慢
|
||||
- **问题现象**: 通过域名 `web.gw.zgitm.com` 访问前端,JS/CSS 加载要 40 秒~1 分钟
|
||||
- **网络拓扑**: 用户电脑(10.10.1.5) → 公网VPN → 阿里云VPN(10.10.1.1) → Nginx代理(10.10.1.160) → 前端服务(10.10.1.170:5001)
|
||||
- **域名解析**: `web.gw.zgitm.com` 和 `login.user.zgitm.com` 均解析到 10.10.1.160
|
||||
- **实测数据**:
|
||||
|
||||
| 路径 | el.js (1.08MB) 耗时 | gzip |
|
||||
|------|---------------------|------|
|
||||
| 内网 10.1.1.170:5001 | 19ms | ✅ |
|
||||
| VPN直连 10.10.1.170:5001 | 3-10秒 | ✅ |
|
||||
| Nginx代理 web.gw.zgitm.com | 20-40秒 | ❌ 丢失 |
|
||||
|
||||
- **根因**: 10.10.1.170 上的 Nginx 返回 gzip 压缩内容,但 10.10.1.160 Nginx 代理时丢失了 gzip 压缩,导致 1MB+ 文件通过窄带宽 VPN 原样传输
|
||||
- **Ping延迟**: 5-15ms(正常),**不是延迟问题是带宽+压缩问题**
|
||||
- **修复方案**: 在 10.10.1.160 Nginx 配置中添加 `proxy_set_header Accept-Encoding "gzip"` 和/或开启本地 gzip — 用户自行修复
|
||||
|
||||
## 重要信息
|
||||
- VPN 网关: 10.10.1.1(阿里云)
|
||||
- VPN 子网: 10.10.1.x
|
||||
- 前端服务: 10.10.1.170:5001(内网 10.1.1.170:5001)
|
||||
- Nginx 代理: 10.10.1.160
|
||||
- DNS 服务器: 10.10.1.150
|
||||
- 公网 IP: zgitm.com → 8.133.197.85
|
||||
- 生产前端域名: web.gw.zgitm.com, login.user.zgitm.com
|
||||
- Nginx 版本: 160 上是 1.14.1,170 上是 1.30.2
|
||||
|
||||
### 共享静态资源域名 — 解决 login/web 双域名重复加载
|
||||
- **问题**: login.user.zgitm.com 登录后跳转 web.gw.zgitm.com,同一份 JS/CSS 被两个域名各自下载一次
|
||||
- **方案**: Vite 构建设置 `base` 为统一静态域名,HTML 中资源 URL 用绝对路径
|
||||
- **第一版**: `http://web.wg.static.zgitm.com:5001/` — 遇到 Mixed Content 问题(HTTPS 页面加载 HTTP 资源被浏览器拦截)
|
||||
- **最终版**: `https://web.gw.zgitm.com/` — 复用已有 HTTPS 域名,零额外配置
|
||||
- **改动文件**:
|
||||
- `vite.config.ts` — 引入 loadEnv,build 时 base 读取 VITE_STATIC_URL,dev 回退 '/'
|
||||
- `.env.production` — 新增 `VITE_STATIC_URL=https://web.gw.zgitm.com/`
|
||||
- **效果**: login 域名首次下载资源后,跳转到 web 域名时浏览器缓存直接命中,0 网络请求
|
||||
|
||||
## 待处理
|
||||
- [ ] 重新 `npm run build` + 部署后验证效果
|
||||
- [ ] 如果后续还慢,考虑 Vite 拆包 Element Plus 按需加载
|
||||
- [ ] 考虑 160 Nginx 升级 gzip 压缩级别
|
||||
73
memory/session-20260613-1.md
Normal file
73
memory/session-20260613-1.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
name: session-20260613-1
|
||||
description: 2026-06-13 会话 — 数据库地址变更、11个前后端字段不匹配bug修复、42个文件加注释、5个新bug修复(图标/操作日志/登录日志/选择系统/用户编辑跳登录)
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-13
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-13T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-13 会话
|
||||
|
||||
## 会话摘要
|
||||
数据库地址从VPN网段切换到内网,全项目前后端字段匹配审计修复11个bug,42个Java/Vue文件加中文注释,修复5个功能bug(图标不显示、操作日志缺报文、登录日志缺字段、选择系统未记录、用户编辑跳登录)。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、数据库地址变更
|
||||
- MySQL + Redis 地址: `10.10.1.122` → `10.1.1.122`
|
||||
- 14个文件全局替换(yml/py/md)
|
||||
|
||||
### 二、前后端字段匹配审计 + Bug修复
|
||||
共发现11个问题,修复了9个:
|
||||
- BUG1: ApiList/ApiForm `s.id` → `s.systemId` (SystemVO无id字段)
|
||||
- BUG2: OperationLogList `operateTime` → `createdAt`
|
||||
- BUG3: MenuRouterVO 加 `sortOrder`/`status`
|
||||
- BUG4: UserController加email过滤
|
||||
- BUG5: RoleServiceImpl联表填充systemName + SysRole加transient systemName
|
||||
- BUG6: ApiForm编辑补apiDesc
|
||||
- BUG7: LoginLogList接口 `loginTime` → `createdAt`
|
||||
- BUG9: DictController补全CRUD (listTypes/add/update/delete/getById)
|
||||
- 登录日志systemName: `WHERE system_id=?` → `WHERE id=?`
|
||||
|
||||
### 三、PUT路由405修复
|
||||
前端 `PUT /admin/role/{id}` 后端 `@PutMapping` 不匹配。
|
||||
SystemController/UserController: `@PutMapping` (id在body)
|
||||
RoleController/MenuController/SystemApiController: `@PutMapping("/{id}")` (id在URL)
|
||||
MenuList.vue统一用URL传id
|
||||
|
||||
### 四、42个文件加中文注释
|
||||
- 后端23个: 10 Controller + 10 Service + 3 Entity/VO
|
||||
- 前端19个: 4配置 + 15页面
|
||||
|
||||
### 五、5个新Bug修复
|
||||
1. **图标不显示**: icons.ts改 `import * as Icons` 全量支持动态图标
|
||||
2. **用户编辑跳登录**: `assignRoles` 的 `invalidateUserSession` 删除Redis会话,admin编辑自己时自己的token被清理。改为同步角色到Redis不删session
|
||||
3. **操作日志**: actionTag加中文映射(新增/编辑/删除), 加"查看"弹窗显示传入/返回报文, 加responseBody字段
|
||||
4. **登录日志**: 加realName字段 (实体+DDL+AuthService+前端)
|
||||
5. **选择系统**: selectSystem更新最近登录日志的systemId
|
||||
|
||||
### 六、服务器状态
|
||||
- TCP端口检测改为HTTP健康检查
|
||||
- 每个微服务独立JVM信息
|
||||
|
||||
### 七、前端拦截器
|
||||
- request.ts 401还原直接跳登录
|
||||
|
||||
### 八、系统列表权限
|
||||
- 新增 `GET /zgapi/v1/admin/system/list`
|
||||
- super_admin@gateway → 全部系统
|
||||
- 其他 → 仅绑定的系统 (JOIN sys_user_system)
|
||||
|
||||
### 九、数据库
|
||||
- QA+PROD执行: sys_login_log加real_name, sys_operation_log加response_body
|
||||
|
||||
## 修改文件清单
|
||||
详见会话日志中各Bug修复记录
|
||||
|
||||
## 重要信息
|
||||
- 数据库: 10.1.1.122:3306
|
||||
- 微服务端口: gateway:9000, auth:9001, admin:9002
|
||||
- 前端构建: `npm run build:prod` (跳过vue-tsc类型检查)
|
||||
- Node版本: 服务器Node 18,Vite 5.4兼容
|
||||
138
memory/session-20260613-2.md
Normal file
138
memory/session-20260613-2.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
name: session-20260613-2
|
||||
description: 2026-06-13 第2次会话 — UI移动端优化、登录跳转修复、操作人乱码修复、操作详情弹窗重设计、文件对象存储从DB迁移到磁盘、系统配置页、开放文件API
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-13
|
||||
sessionNumber: 2
|
||||
startTime: 2026-06-13T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-13 第2次会话
|
||||
|
||||
## 会话摘要
|
||||
|
||||
完成前两轮累积的全部需求:UI移动端适配、登录页跳转优化、操作人乱码BUG修复(Header URL编解码)、操作日志查看弹窗重新设计、文件存储从MySQL BLOB迁移到本地磁盘、系统配置管理页、文件对象储存列表重设计、开放API文件上传/下载接口、open-api-doc.md文档更新。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、前端UI优化
|
||||
|
||||
**登录页 (LoginView.vue)**:
|
||||
- 登录成功后按钮持续转圈(loading不关闭),显示"正在跳转..."
|
||||
- `navigating` 标志防重复跳转
|
||||
- 支持二次点击(已登录成功卡住时重新触发跳转)
|
||||
- 8秒超时自动提示"网络较慢"
|
||||
|
||||
**操作日志 (OperationLogList.vue)**:
|
||||
- 查看弹窗完全重设计:el-descriptions 展示操作人/时间/接口/方法/成功/耗时
|
||||
- 深色代码块 + 折叠面板展示传入/返回报文
|
||||
- 一键复制按钮
|
||||
|
||||
**移动端全局适配 (global.css)**:
|
||||
- 操作列按钮 480px 以上保留文字,480px 以下只显示图标
|
||||
- 搜索卡片 inline 表单移动端垂直排列
|
||||
- 分页移动端隐藏 sizes 和 jumper
|
||||
- 弹窗移动端 95vw
|
||||
|
||||
**列表页移动端适配**: SystemList/UserList/RoleList/DictList/LoginLogList 全部更新
|
||||
|
||||
### 二、操作人乱码BUG修复
|
||||
|
||||
**根因**: HeaderInjectFilter 将中文 realName(如"张三")注入 HTTP 头 `X-User-Name`。HTTP 头只支持 ASCII,跨服务转发时中文字符损坏。
|
||||
|
||||
**修复**:
|
||||
- `HeaderInjectFilter.java`: `X-User-Name` 值写入前 `URLEncoder.encode(realName, UTF_8)`
|
||||
- `OperationLogAspect.java`: 读取后 `URLDecoder.decode(value, UTF_8)` 还原
|
||||
- 新增 `decodeHeader()` 辅助方法
|
||||
|
||||
### 三、文件对象存储(DB BLOB → 本地磁盘)
|
||||
|
||||
**核心原则**: 文件二进制数据一律存磁盘,sys_file 表只存元信息。
|
||||
|
||||
**数据库变更**:
|
||||
- 新建 `sys_config` 表(系统配置键值对)
|
||||
- `sys_file` 加 `storage_file_name`、`upload_user_name` 字段
|
||||
- 保留 `file_data` 列用于存量 BLOB 向后兼容
|
||||
|
||||
**后端新增**:
|
||||
- `SysConfig.java` 实体 + `SysConfigMapper` + `ConfigService`(含 ConcurrentHashMap 缓存) + `ConfigController`
|
||||
- `FileServiceImpl.upload()` 改为写磁盘:`{basePath}/{yyyy-MM}/{uuid}.{ext}`
|
||||
- `FileController.view()` 优先读磁盘,兜底读 BLOB(存量兼容)
|
||||
- `FileController.download()` 新增下载端点(Content-Disposition: attachment)
|
||||
- `uploadUserName` 逻辑:管理后台上传→用户姓名,API上传→系统名称
|
||||
|
||||
**开放 API(OpenApiController)**:
|
||||
- `POST /zgapi/v1/open/file/upload` — form 字段传 token,上传成功消费
|
||||
- `GET /zgapi/v1/open/file/{id}/download?token=xxx` — query 参数传 token,下载成功消费
|
||||
- 新增 `validateOpenTokenFromValue(String)` 支持非 Header 传 token
|
||||
|
||||
**网关 (TokenAuthFilter)**:
|
||||
- `authenticateOpenApi()` 无 Bearer Header 时从 `request.getParameter("token")` 兜底
|
||||
|
||||
**前端**:
|
||||
- `SystemConfig.vue` — 系统配置页(存储磁盘路径输入框 + 保存)
|
||||
- `FileList.vue` — 完全重写:卡片网格、缩略图点击预览、储存文件名、上传者、下载/复制链接/删除
|
||||
- 菜单"文件管理"→"文件对象储存"
|
||||
- 新增"系统配置"菜单(Setting 图标)
|
||||
|
||||
**菜单 SQL**:
|
||||
- `add_file_storage.sql`: sys_config DDL + sys_file ALTER + 菜单改名+新增
|
||||
- `add_file_menu.sql`: 菜单名更新
|
||||
|
||||
### 四、文档更新
|
||||
|
||||
`docs/open-api-doc.md` 新增:
|
||||
- §4 上传文件(multipart/form-data 示例、响应字段说明)
|
||||
- §5 下载文件(query param token 示例)
|
||||
- Java 调用示例增加文件上传
|
||||
- 附录重新编号为 §7
|
||||
|
||||
## 修改文件清单
|
||||
|
||||
| 文件 | 操作 |
|
||||
|------|------|
|
||||
| `LoginView.vue` | 修改 |
|
||||
| `OperationLogList.vue` | 修改 |
|
||||
| `global.css` | 修改 |
|
||||
| `SystemList.vue` | 修改 |
|
||||
| `UserList.vue` | 修改 |
|
||||
| `RoleList.vue` | 修改 |
|
||||
| `DictList.vue` | 修改 |
|
||||
| `LoginLogList.vue` | 修改 |
|
||||
| `HeaderInjectFilter.java` | 修改(URL编码) |
|
||||
| `OperationLogAspect.java` | 修改(URL解码) |
|
||||
| `SysConfig.java` | **新增** |
|
||||
| `SysConfigMapper.java` | **新增** |
|
||||
| `ConfigService.java` | **新增** |
|
||||
| `ConfigServiceImpl.java` | **新增** |
|
||||
| `ConfigController.java` | **新增** |
|
||||
| `SysFile.java` | 修改(+2字段) |
|
||||
| `FileService.java` | 修改(接口更新) |
|
||||
| `FileServiceImpl.java` | 重写(磁盘存储) |
|
||||
| `FileController.java` | 重写(+download,view改磁盘优先) |
|
||||
| `OpenApiController.java` | 修改(+2文件端点) |
|
||||
| `TokenAuthFilter.java` | 修改(query param token) |
|
||||
| `SystemConfig.vue` | **新增** |
|
||||
| `FileList.vue` | 重写 |
|
||||
| `router/index.ts` | 修改 |
|
||||
| `AdminLayout.vue` | 修改 |
|
||||
| `open-api-doc.md` | 修改 |
|
||||
| `add_file_storage.sql` | **新增** |
|
||||
| `add_file_menu.sql` | 修改 |
|
||||
|
||||
## 重要信息
|
||||
|
||||
- 文件存储路径: 默认 `/data/mokee/gw/file`,可在系统配置页修改
|
||||
- 磁盘文件结构: `{basePath}/{yyyy-MM}/{uuid}.{ext}`
|
||||
- 存量 BLOB 文件仍可正常读取(view/download 兜底逻辑)
|
||||
- 开放 API Token 消费规则: 上传/下载成功后消费,失败不消费
|
||||
- Token 在 download 通过 query 参数传递(浏览器 `<a>` 标签无法设 Header)
|
||||
|
||||
## 待处理
|
||||
|
||||
- [ ] 执行 `add_file_storage.sql` 到 QA/PROD 数据库
|
||||
- [ ] 服务器上创建存储目录 `/data/mokee/gw/file` 并设置写权限
|
||||
- [ ] 执行 QA/PROD 菜单更新(文件管理→文件对象储存 + 系统配置菜单)
|
||||
- [ ] 构建部署:`mvn clean package` + `npm run build:prod`
|
||||
- [ ] 原有迁移建议:现有文件数据过大时,可编写迁移脚本将 `file_data` BLOB 导出到磁盘
|
||||
142
memory/session-20260613-3.md
Normal file
142
memory/session-20260613-3.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
name: session-20260613-3
|
||||
description: 2026-06-13 第3次会话 — 头像401、菜单check-strictly、移动端全面优化、token/info接口、唯一键校验、数据权限、文档更新
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-13
|
||||
sessionNumber: 3
|
||||
startTime: 2026-06-13T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-13 第3次会话 — 完整记录
|
||||
|
||||
## 一、头像 401 修复
|
||||
|
||||
**根因**:文件服务 Token 一次一密,PersonalView.vue 上传和下载共用一个 Token,带 Token 的 URL 存入数据库 → 永久 401。
|
||||
|
||||
**修复**:
|
||||
- `auth.ts`:fetchUserInfo() 和 login() 先刷新 Token 再设 userInfo
|
||||
- `PersonalView.vue`:上传用 Token1(消费),下载用 Token2(新获取),DB 只存基础 URL
|
||||
|
||||
## 二、分配菜单 check-strictly
|
||||
|
||||
**RoleList.vue**:el-tree 加 `check-strictly`,节点独立勾选,父子不联动。
|
||||
- 可以只勾"系统列表"不给新增/编辑/删除
|
||||
|
||||
## 三、移动端全面优化
|
||||
|
||||
### 3.1 操作列 → 桌面按钮行 / 手机卡片按钮
|
||||
不再使用 CSS dropdown hack,改用 `useIsMobile()` composable + `v-if`
|
||||
|
||||
**composable**: `src/composables/useIsMobile.ts` — 响应式检测屏幕 ≤768px
|
||||
|
||||
**已改造**:RoleList, UserList, SystemList, MenuList, DictList, ApiList, FileList, EmailList, LoginLogList, OperationLogList, OpenTokenLogList
|
||||
|
||||
### 3.2 表单按钮全局统一
|
||||
`global.css`:移动端 `.form-footer { flex-direction: column }` 取消/保存按钮等宽上下排列
|
||||
|
||||
### 3.3 分页滚动
|
||||
`main.ts`:监听分页点击 → `window.scrollTo({ top: 0, behavior: 'smooth' })`
|
||||
|
||||
### 3.4 卡片样式
|
||||
`global.css`:`.mobile-cards` / `.mobile-card` / `.card-field` / `.card-actions`
|
||||
|
||||
## 四、新增 GET /token/info 接口
|
||||
|
||||
- `OpenApiController.java`:`GET /zgapi/v1/open/token/info?token=xxx`
|
||||
- 不消费 Token,从 JWT 解析 systemId/systemCode/systemName
|
||||
- `TokenAuthFilter.java`:放行 `/zgapi/v1/open/token/info`
|
||||
- `open-api-doc.md`:新增 §4
|
||||
|
||||
## 五、所有新增接口唯一键校验
|
||||
|
||||
| 接口 | 唯一约束 | 修复 |
|
||||
|------|----------|------|
|
||||
| 新增系统 | uk_system_code + uk_gateway_url | ✅ gatewayUrl 自动生成唯一值 |
|
||||
| 新增用户 | uk_username + uk_email | ✅ 空邮箱→null,重复提示中文 |
|
||||
| 新增角色 | uk_system_role_code | ✅ 系统+编码重复提示 |
|
||||
| 新增字典 | uk_type_value | ✅ 类型+值重复提示 |
|
||||
| 新增接口 | uk_system_path_method | ✅ 系统+路径+方法重复提示 |
|
||||
|
||||
## 六、全局数据权限
|
||||
|
||||
**架构**:`UserContextInterceptor` → `UserContextHolder`(ThreadLocal) → Service 层过滤
|
||||
|
||||
**规则**:roleCode=super_admin 看全部;其他角色只看绑定系统(sys_user_system)的数据
|
||||
|
||||
**新增文件**:
|
||||
- `config/UserContextHolder.java` — ThreadLocal
|
||||
- `config/UserContextInterceptor.java` — 拦截器,读 X-User-Roles 头
|
||||
- `config/WebMvcConfig.java` — 注册拦截器
|
||||
|
||||
**修改的 Service**:
|
||||
- RoleServiceImpl.page() — in(systemIds)
|
||||
- SystemApiServiceImpl.page() — in(systemIds)
|
||||
- LogServiceImpl.loginLogPage() — in(systemIds)
|
||||
- UserServiceImpl.page() — 通过 sys_user_system 关联过滤
|
||||
- SystemServiceImpl.page() — in(systemIds)
|
||||
- SystemServiceImpl.add() — gatewayUrl 唯一值
|
||||
|
||||
**不做过滤**:
|
||||
- 操作日志、Token日志(用户指定不要)
|
||||
- 字典、邮件(无 system_id)
|
||||
|
||||
## 七、FileList 系统筛选
|
||||
|
||||
- 搜索栏新增"所属系统"下拉(systemCode / systemName)
|
||||
- 表格新增"所属系统"列
|
||||
- systemId 传给后端过滤
|
||||
|
||||
## 八、接入文档更新
|
||||
|
||||
### IntegrationDoc.vue(页面内文档)
|
||||
- **§9.3** 下载文件:Token 支持 Header 和 Query 参数两种方式
|
||||
- **§10** 新增对外开放 API 章节(Token 获取 + 邮件发送)
|
||||
- **§3** 前端接入:localStorage → Cookie 读取 Token,说明跨域 Cookie 机制
|
||||
- **§3.5** 登录回调:完整说明 Cookie Token 流程
|
||||
|
||||
### open-api-doc.md(独立文档)
|
||||
- 下载文件 curl 示例增加 Query 参数方式
|
||||
- 所有文档章节重新编号
|
||||
|
||||
## 修改文件总清单
|
||||
|
||||
**后端新增**:
|
||||
- `config/UserContextHolder.java`
|
||||
- `config/UserContextInterceptor.java`
|
||||
- `config/WebMvcConfig.java`
|
||||
|
||||
**后端修改**:
|
||||
- `OpenApiController.java` — +GET /token/info
|
||||
- `TokenAuthFilter.java` — 放行 /token/info
|
||||
- `UserServiceImpl.java` — 重复校验 + 数据权限 + 空邮箱→null
|
||||
- `SystemServiceImpl.java` — systemCode/gatewayUrl 唯一性 + 数据权限
|
||||
- `RoleServiceImpl.java` — 角色编码唯一性 + 数据权限
|
||||
- `DictServiceImpl.java` — 字典值唯一性
|
||||
- `SystemApiServiceImpl.java` — 接口唯一性 + 数据权限
|
||||
- `LogServiceImpl.java` — 登录日志数据权限(操作日志不过滤)
|
||||
- `FileController.java` — systemId 过滤已支持
|
||||
|
||||
**前端新增**:
|
||||
- `composables/useIsMobile.ts`
|
||||
|
||||
**前端修改**:
|
||||
- `auth.ts` — 头像 Token 刷新
|
||||
- `PersonalView.vue` — 头像双 Token
|
||||
- `global.css` — 移动端卡片 + 表单按钮
|
||||
- `main.ts` — 分页滚动
|
||||
- `RoleList.vue` — check-strictly + 手机卡片
|
||||
- `UserList.vue` — 手机卡片
|
||||
- `SystemList.vue` — 手机卡片
|
||||
- `MenuList.vue` — 手机卡片
|
||||
- `DictList.vue` — 手机卡片
|
||||
- `ApiList.vue` — 手机卡片
|
||||
- `FileList.vue` — 系统下拉过滤
|
||||
- `EmailList.vue` — 手机卡片 + confirmDel
|
||||
- `LoginLogList.vue` — 手机卡片
|
||||
- `OperationLogList.vue` — 手机卡片
|
||||
- `OpenTokenLogList.vue` — 手机卡片
|
||||
|
||||
**文档修改**:
|
||||
- `docs/open-api-doc.md` — +token/info,下载 Query 参数
|
||||
- `IntegrationDoc.vue` — Cookie Token + 邮件发送 + 下载方式
|
||||
137
memory/session-20260613-4.md
Normal file
137
memory/session-20260613-4.md
Normal file
@@ -0,0 +1,137 @@
|
||||
---
|
||||
name: session-20260613-4
|
||||
description: 2026-06-13 第4次会话 — Widget实施 + 大量Bug修复 + 接入文档完善
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-13
|
||||
sessionNumber: 4
|
||||
startTime: 2026-06-13
|
||||
endTime: 2026-06-13
|
||||
---
|
||||
|
||||
# 2026-06-13 第4次会话 — 完整记录
|
||||
|
||||
## 会话摘要
|
||||
实施了用户头像下拉 Widget,修复了 10+ 个 Bug(菜单权限、数据过滤、API转发、错误提示、SQL修复等),完善了接入文档。
|
||||
|
||||
## 一、UserChip Widget 实施
|
||||
|
||||
### 新建文件(6个)
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `src/widgets/user-chip/cookie.ts` | Cookie Token 读写 |
|
||||
| `src/widgets/user-chip/api.ts` | API 调用层(fetch/原生) |
|
||||
| `src/widgets/user-chip/UserChip.vue` | 核心组件(BEM 命名空间) |
|
||||
| `src/widgets/user-chip/main.ts` | 自动扫描 #mokee-user-chip 挂载 |
|
||||
| `vite.widget.config.ts` | 独立 IIFE 构建(→ dist-widget/) |
|
||||
| `public/demo-widget.html` | 接入演示 |
|
||||
|
||||
### 修改文件
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `package.json` | +build:widget + build:prod 合并 |
|
||||
| `IntegrationDoc.vue` | §3.6 Widget 一键接入 + widgetConfigTable |
|
||||
|
||||
### 关键设计
|
||||
- loginUrl/selectUrl 从脚本自身 URL 推断(不用 window.location.origin)
|
||||
- 登录页: https://web.gw.zgitm.com/login
|
||||
- 切换系统: https://web.gw.zgitm.com/select
|
||||
- API 网关: https://gw.server.zgitm.com
|
||||
|
||||
## 二、重要 Bug 修复
|
||||
|
||||
### 2.1 AdminLayout 菜单动态化(硬编码→API 加载)
|
||||
- **原因**: 硬编码 HTML,所有用户看到全部菜单
|
||||
- **修复**: 改为 `fetchMenuRouter('gateway')` 动态加载,按角色过滤
|
||||
- **问题**: API 返回字段和前端预期不一致 → MenuRouterVO 缺少字段
|
||||
- **修复**: buildMenuTree 补填 id/menuName/menuType/icon/permission/sortOrder/status
|
||||
|
||||
### 2.2 ApiPermissionFilter 过于严格
|
||||
- **问题**: 业务系统选系统后调 /zgapi/v1/auth/menu/router 被 403
|
||||
- **修复**: `/zgapi/v1/auth/*` 和 `/zgapi/v1/admin/*` 全部放行,不查 sys_api 白名单
|
||||
|
||||
### 2.3 网关不转发非 /zgapi/ 路径
|
||||
- **问题**: 业务系统请求 /api/rules 带 X-System-Code,网关返回 200 空响应
|
||||
- **修复**: 非 /zgapi/ 路径有 X-System-Code 头 → 转发到业务后端
|
||||
|
||||
### 2.4 RestTemplate 吞业务后端错误
|
||||
- **问题**: RestTemplate 默认对 4xx/5xx 抛异常,网关 catch 后返回 502 吞掉真实错误
|
||||
- **修复**: 设置自定义 ResponseErrorHandler,hasError() 永远返回 false
|
||||
|
||||
### 2.5 assignRoles 角色覆盖
|
||||
- **问题**: tokenInfo.setRoles(当前系统角色) 覆盖掉其他系统角色 → super_admin 丢失 → 403
|
||||
- **修复**: 改为从 DB 重新查询用户全部角色再写入 Redis
|
||||
|
||||
### 2.6 选择系统页不应该隐藏 gateway
|
||||
- **初始修复(错误)**: AuthServiceImpl 过滤 gateway,导致用户无法进入管理后台
|
||||
- **正确的修复**: 还原 AuthServiceImpl,选择系统页显示 gateway 卡片(入口),数据层面由 UserContextInterceptor 过滤 gateway 数据
|
||||
|
||||
### 2.7 非 super_admin 看到 gateway 数据
|
||||
- **问题**: adminnginxserver 绑定 gateway+nginxServer,数据权限范围包含 gateway
|
||||
- **修复**: UserContextInterceptor 加 isGatewaySystem() 过滤,排除 gateway 系统 ID
|
||||
|
||||
### 2.8 MenuServiceImpl 无权限校验
|
||||
- **问题**: getMenuTree/add/update/delete 都不检查 UserContextHolder
|
||||
- **修复**: 新增 checkSystemScope(),所有方法校验 systemId 是否在绑定范围内
|
||||
|
||||
### 2.9 两个首页菜单
|
||||
- **问题**: 过滤逻辑只查顶级节点,子节点中的首页漏网
|
||||
- **修复**: 递归 removeDashboard() 函数,过滤所有层级
|
||||
|
||||
### 2.10 ElMessage 弹窗位置错误
|
||||
- **问题**: CSS 导入路径不对,el-message.css 未加载 → 消息显示在底部
|
||||
- **修复**: main.ts 显式 import 'element-plus/theme-chalk/el-message.css',global.css 去冲突 !important
|
||||
|
||||
### 2.11 登录错误双重弹窗
|
||||
- **修复**: LoginView.vue catch 块去掉重复的 ElMessage.error
|
||||
|
||||
### 2.12 SystemServiceImpl 排除 gateway
|
||||
- **修复**: 非 super_admin 时 wrapper.ne(SysSystem::getSystemCode, "gateway")
|
||||
|
||||
### 2.13 接入文档 SQL 修复
|
||||
- 所有 INSERT 加 id 列 + REPLACE(UUID(),'-','')
|
||||
- 用户创建 SQL 加步骤 4(绑定自己系统)+ 步骤 5(分配自己系统 admin 角色)
|
||||
- 菜单初始化 SQL 改用 MySQL 变量显式持有 UUID
|
||||
|
||||
### 2.14 RestTemplate 吞业务后端错误
|
||||
- **问题**: RestTemplate 默认对 4xx/5xx 抛异常,网关 catch 返回 502 吞掉真实错误
|
||||
- **修复**: RestTemplateConfig 设置自定义 ResponseErrorHandler,hasError() 永远返回 false
|
||||
|
||||
### 2.15 FileServiceImpl 无数据权限
|
||||
- **问题**: 文件对象储存页能看到 gateway 系统的文件
|
||||
- **修复**: FileServiceImpl.page() 加 UserContextHolder 检查
|
||||
|
||||
### 2.16 用户列表排除 super_admin 账号
|
||||
- **问题**: 非 super_admin 用户能看到 admin 等超管账号
|
||||
- **修复**: UserServiceImpl.page() 加 NOT IN (拥有 super_admin 角色的用户ID)
|
||||
|
||||
## 三、接入文档完善
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| `IntegrationDoc.vue` §5 | 重写 API 章节:7 个接口 + 速查表 + 完整请求/响应 JSON |
|
||||
| `docs/integration-guide.md` | 新建独立的完整 Markdown 接入文档 |
|
||||
|
||||
## 四、所有修改文件清单
|
||||
|
||||
**后端修改**:
|
||||
- gateway-auth: AuthServiceImpl.java (systemList过滤 + buildMenuTree补字段)
|
||||
- gateway-admin: UserContextInterceptor.java (排除gateway), MenuServiceImpl.java (权限校验), SystemServiceImpl.java (排除gateway), UserServiceImpl.java (assignRoles修复 + resetPassword新增)
|
||||
- gateway-gateway: ApiPermissionFilter.java (放行auth/admin), GatewayController.java (转发非zgapi路径), RestTemplateConfig.java (不吞错误)
|
||||
|
||||
**前端修改**:
|
||||
- AdminLayout.vue (动态菜单 + 递归过滤首页)
|
||||
- LoginView.vue (去掉重复ElMessage)
|
||||
- UserForm.vue (super_admin重置密码)
|
||||
- IntegrationDoc.vue (§3.6 Widget + §5 API完善 + SQL修复)
|
||||
- main.ts (ElMessage CSS显式引入)
|
||||
- global.css (ElMessage样式修复)
|
||||
- package.json (build:widget脚本)
|
||||
|
||||
**新建文件**:
|
||||
- 6个Widget文件 + 1个文档
|
||||
|
||||
## 待处理
|
||||
- [ ] 部署到 web.gw.zgitm.com(Nginx /widgets/ location)
|
||||
- [ ] 给 gateway-app-admin/gateway-app-user 角色分配菜单
|
||||
- [ ] 生产环境验证
|
||||
90
memory/session-20260613-5.md
Normal file
90
memory/session-20260613-5.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: session-20260613-5
|
||||
description: 2026-06-13 第5次会话 — 前端5问题 + 系统下拉框过滤 + Token失效 + ECharts修复 + Token日志复制
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-13
|
||||
sessionNumber: 5
|
||||
startTime: 2026-06-13
|
||||
---
|
||||
|
||||
# 2026-06-13 第5次会话 — 完整记录
|
||||
|
||||
## 会话摘要
|
||||
修复了前端 5 个问题 + 系统下拉框 gateway 过滤 + 角色菜单保存后 token 失效 + ECharts 图表空指针 + Token 日志列点击复制。
|
||||
|
||||
---
|
||||
|
||||
## 1. ElMessage 错误提示显示在左下角(非弹窗)
|
||||
- **尝试**: 改为全量 `element-plus/dist/index.css` → 与 unplugin-vue-components 按需加载冲突导致首页空白
|
||||
- **回退**: 保持 3 个独立 CSS 引入(el-message.css/message-box.css/notification.css)
|
||||
- **文件**: `mokee-gateway-web/src/main.ts`
|
||||
|
||||
## 2. 登录后显示两个首页
|
||||
- **修复**: 删除 AdminLayout 侧边栏硬编码"首页"菜单项 + 删除 `removeDashboard()` 函数
|
||||
- 菜单完全由 API 动态提供,需确保 DB 中"首页"菜单已分配角色
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/AdminLayout.vue`
|
||||
|
||||
## 3. 去掉首页服务器状态卡片
|
||||
- 删除 server-panel 块(微服务状态 + JVM 信息)及关联 CSS
|
||||
- 布局简化:统计卡片 + 登录趋势图表全宽
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/Dashboard.vue`
|
||||
|
||||
## 4. 近30天登录趋势图表 — 两次修复
|
||||
### 4a. 执行顺序 bug
|
||||
- `chartLoading=false` 原在 finally 块,renderChart() 在 try 块 → chartRef 未挂载
|
||||
- 修复: chartLoading=false 移到 nextTick 前
|
||||
### 4b. ECharts init(null) 崩溃
|
||||
- 根因: `v-if/v-else` 导致 ref div 按需创建/销毁,nextTick 后 chartRef.value 仍为 null
|
||||
- 修复: 改为 `v-show`,div 始终在 DOM 中。renderChart 增加动态 import 前后双重 null 检查
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/Dashboard.vue`
|
||||
|
||||
## 5. 用户编辑页添加头像上传
|
||||
- `v-if="isSelf"` — 仅 `authStore.userInfo.userId === editId` 时显示
|
||||
- 复用 PersonalView 上传逻辑: 获取Token → 上传 → 保存baseUrl
|
||||
- loadData 时自动刷新文件服务 Token(避免 401)
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/user/UserForm.vue`
|
||||
|
||||
## 6. Token日志菜单后端不返回
|
||||
- 根因: 初始化脚本是破坏性的(DELETE+重建),Token日志菜单从未被加入
|
||||
- 修复: 3 个脚本补充 Token日志菜单 INSERT
|
||||
- **文件**: `init_gateway_system.py`, `sql/init_qa.py`, `sql/qa_data.sql`
|
||||
|
||||
## 7. 系统下拉框过滤 gateway(非 super_admin)
|
||||
- 需求: admin 页面系统下拉框不显示"网关管理平台"
|
||||
- 初次方案: `listByUserId()` SQL 加 `AND system_code != 'gateway'` → 用户指出会误伤 super_admin
|
||||
- 最终方案: 过滤移到 `SystemController.listAll()`,Stream 加 `.filter(s -> isSuperAdmin || !"gateway".equals(s.getSystemCode()))`
|
||||
- 编译错误修复: `isSuperAdmin` 需声明 `final`
|
||||
- **文件**: `mokee-gateway-admin/.../controller/SystemController.java`
|
||||
|
||||
## 8. 编辑角色菜单保存后 token 失效跳登录
|
||||
- 根因: `RoleServiceImpl.invalidateSessionsForRole()` 删除所有拥有该角色的用户的 Redis 会话,包括操作者自己
|
||||
- 修复: 加 `.filter(uid -> !uid.equals(currentUserId))` 跳过当前操作用户
|
||||
- **文件**: `mokee-gateway-admin/.../service/impl/RoleServiceImpl.java`
|
||||
|
||||
## 9. Token日志列点击复制
|
||||
- 显示: `tokenSuffix()` 只显示 `...` 后缀部分(如 `...dQwNJ9HG0E`)
|
||||
- 点击: `navigator.clipboard.writeText()` 复制完整 tokenPreview
|
||||
- 注意: 完整 JWT token 不存库,只有 tokenPreview(前20+...+后10字符)
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/log/OpenTokenLogList.vue`
|
||||
|
||||
---
|
||||
|
||||
## 涉及文件清单
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `mokee-gateway-web/src/main.ts` | CSS 引入(保持 3 个独立引入) |
|
||||
| `mokee-gateway-web/src/views/admin/AdminLayout.vue` | 去硬编码首页 + removeDashboard |
|
||||
| `mokee-gateway-web/src/views/admin/Dashboard.vue` | 去服务器卡片 + 图表v-show + 双重null检查 |
|
||||
| `mokee-gateway-web/src/views/admin/user/UserForm.vue` | 新增头像上传(仅编辑自己) |
|
||||
| `mokee-gateway-web/src/views/admin/log/OpenTokenLogList.vue` | Token列点击复制 + 后缀展示 |
|
||||
| `init_gateway_system.py` | 新增 Token日志菜单 |
|
||||
| `sql/init_qa.py` | 新增 Token日志菜单 |
|
||||
| `sql/qa_data.sql` | 新增 Token日志菜单 |
|
||||
| `mokee-gateway-admin/.../controller/SystemController.java` | 非super_admin过滤gateway |
|
||||
| `mokee-gateway-admin/.../service/impl/RoleServiceImpl.java` | invalidateSessions跳过当前用户 |
|
||||
|
||||
## 待处理
|
||||
- [ ] 重新构建部署前后端验证所有修复
|
||||
- [ ] 问题1(ElMessage 左下角)需进一步排查 — CSS 引入正确但可能浏览器缓存
|
||||
89
memory/session-20260615-1.md
Normal file
89
memory/session-20260615-1.md
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
name: session-20260615-1
|
||||
description: 2026-06-15 第1次会话 — 前端UI统一优化:分页/布局/CSS变量/下载修复,12文件改动
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-15
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-15
|
||||
---
|
||||
|
||||
# 2026-06-15 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
全面统一了前端 11 个列表页面的 UI 风格。核心工作:提取 4 个公共 CSS 类到 global.css,修复 3 个不规范的页面(EmailList、OpenTokenLogList、FileList),清理 7 个标准页面的重复样式。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 1. global.css 添加公共布局类
|
||||
- **做了什么**: 在 global.css 新增 `.page-wrapper`、`.card-header-title`、`.toolbar`、`.pagination-wrapper` 四个全局类,统一所有列表页的布局结构
|
||||
- **原因**: 8+ 个文件各自重复定义相同的 CSS 规则,维护困难且容易产生不一致
|
||||
- **结果**: 一处定义,处处使用;同时统一了 `card-header-title` 的 `color` 为 `var(--text-primary)`(之前大部分页面用硬编码 `#303133`)
|
||||
|
||||
### 2. EmailList.vue 全面翻新
|
||||
- **做了什么**: 根类名 email-page→page-wrapper,分页改为标准配置(background + 完整 layout),新增 v-if/v-else 移动端卡片列表,搜索卡片加 search-card 类,操作栏简化,删除了大量冗余 CSS
|
||||
- **原因**: 分页只有 prev/pager/next 且 small 模式,无移动端适配,结构与其他页面完全不同
|
||||
- **结果**: 与其他列表页样式完全统一
|
||||
|
||||
### 3. OpenTokenLogList.vue 统一
|
||||
- **做了什么**: 根类名 tokenlog-page→page-wrapper,page-footer→pagination-wrapper,分页改为标准配置,el-card 包裹表格
|
||||
- **原因**: 分页居中且不完整,容器类名不标准
|
||||
- **结果**: 与其他列表页样式完全统一
|
||||
|
||||
### 4. FileList.vue 结构调整
|
||||
- **做了什么**: 搜索卡片加 search-card 类,上传按钮从搜索卡片内移出到独立 toolbar,去掉分页 v-if="total>0",删除重复 CSS 规则
|
||||
- **原因**: 搜索+操作栏混在同一卡片不符合标准模式
|
||||
- **结果**: 结构对齐标准模式
|
||||
|
||||
### 5. 7 个标准页面清理
|
||||
- **做了什么**: UserList, RoleList, SystemList, ApiList, LoginLogList, OperationLogList, DictList 删除已全局化的 4 个 CSS 规则
|
||||
- **额外**: UserList 还删除了 .search-card scoped 规则(全局 el-card 规则已覆盖);DictList 保留 `.toolbar { gap: 8px }` 特有样式
|
||||
- **结果**: 每个文件平均减少 ~20 行冗余 CSS
|
||||
|
||||
## 6. 文件对象存储下载修复
|
||||
- **做了什么**: 将 `downloadFile()` 从 `fetch blob → createObjectURL → <a> click` 改为 `隐藏 iframe 直接加载下载 URL`
|
||||
- **原因**: 旧方式先把文件全量下载到浏览器内存,等全部下完才弹保存对话框,大文件体验极差。新方式浏览器直接接管下载,立即弹出保存对话框,后台下载有进度条
|
||||
- **结果**: FileList.vue 的 `downloadFile` 函数重写,用户体验显著提升
|
||||
- **文件**: `mokee-gateway-web/src/views/admin/file/FileList.vue`
|
||||
|
||||
## 涉及文件清单
|
||||
|
||||
| 文件 | 改动类型 |
|
||||
|------|---------|
|
||||
| `src/styles/global.css` | 新增 4 个公共类 + 移动端适配 |
|
||||
| `src/views/admin/email/EmailList.vue` | 模板+脚本+样式全面翻新 |
|
||||
| `src/views/admin/log/OpenTokenLogList.vue` | 模板+样式翻新 |
|
||||
| `src/views/admin/file/FileList.vue` | 结构调整 + 样式清理 |
|
||||
| `src/views/admin/user/UserList.vue` | 样式清理 |
|
||||
| `src/views/admin/role/RoleList.vue` | 样式清理 |
|
||||
| `src/views/admin/system/SystemList.vue` | 样式清理 |
|
||||
| `src/views/admin/system/ApiList.vue` | 样式清理 |
|
||||
| `src/views/admin/log/LoginLogList.vue` | 样式清理 |
|
||||
| `src/views/admin/log/OperationLogList.vue` | 样式清理 |
|
||||
| `src/views/admin/dict/DictList.vue` | 样式清理 |
|
||||
|
||||
## 统一后的分页组件标准
|
||||
```html
|
||||
<el-pagination
|
||||
v-model:current-page="page"
|
||||
v-model:page-size="pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
background
|
||||
@current-change="fetchData"
|
||||
@size-change="fetchData"
|
||||
/>
|
||||
```
|
||||
|
||||
## 统一后的页面结构标准
|
||||
```
|
||||
.page-wrapper
|
||||
├── el-card.search-card → 搜索条件
|
||||
├── div.toolbar → 操作按钮
|
||||
└── el-card → 表格(v-if=!isMobile) + 卡片(v-else) + 分页
|
||||
```
|
||||
|
||||
## 待处理
|
||||
- [ ] 启动 dev server 手动验证所有页面的分页和移动端效果
|
||||
- [ ] 如有需要,部署到测试环境验证
|
||||
56
memory/session-20260615-2.md
Normal file
56
memory/session-20260615-2.md
Normal file
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: session-20260615-2
|
||||
description: 2026-06-15 第2次会话 — sys_user唯一索引删除,修复逻辑删除与uk_username冲突
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-15
|
||||
sessionNumber: 2
|
||||
startTime: 2026-06-15
|
||||
---
|
||||
|
||||
# 2026-06-15 第2次会话
|
||||
|
||||
## 会话摘要
|
||||
修复了 `sys_user` 表逻辑删除(`is_deleted`)与唯一索引 `uk_username`/`uk_email` 冲突的问题。删除了数据库唯一索引,改为应用层代码校验。
|
||||
|
||||
## 问题描述
|
||||
- **现象**:创建用户时报 `Duplicate entry 'nginxadmin' for key 'sys_user.uk_username'`
|
||||
- **根因**:MyBatis-Plus `@TableLogic` 自动在查询时过滤 `is_deleted=1`,但数据库唯一索引不区分逻辑删除标记。已删用户仍占着 username → 新用户无法创建同名 → 插入时索引冲突
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 删除唯一索引,改应用层校验
|
||||
- **做了什么**:从 `sys_user` 表删除 `uk_username` 和 `uk_email` 两个唯一索引,用户名/邮箱唯一性交给 `UserServiceImpl.add()` 中的 `selectCount` 校验
|
||||
- **原因**:唯一索引不区分 `is_deleted`,逻辑删除的记录仍阻塞同名用户创建
|
||||
- **结果**:已删除的用户不再占坑,可创建同名新用户;活跃用户的唯一性由应用层保证
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `sql/qa_ddl.sql` | 删除 uk_username、uk_email 索引定义 |
|
||||
| `init_database.py` | 同上 |
|
||||
| `init_qa_database.py` | 同上 |
|
||||
| QA 数据库 `mokeegatewayqa` | DROP INDEX uk_username, uk_email |
|
||||
| PROD 数据库 `mokeegateway` | DROP INDEX uk_username, uk_email |
|
||||
|
||||
## 代码层无需改动
|
||||
`UserServiceImpl.add()` 已有校验:`selectCount` + MyBatis-Plus `@TableLogic` 自动过滤已删除记录,重复用户名会提示"用户名已存在"。
|
||||
|
||||
## 待处理
|
||||
- [ ] 验证:创建一个用户 → 删除 → 再创建同名用户,确认不再报错
|
||||
|
||||
### 2. 首页仪表盘数据权限
|
||||
- **做了什么**:DashboardController.stats() 增加数据权限过滤。非 super_admin 用户首页统计卡片和登录趋势图只看自己绑定系统的数据(排除网关平台)
|
||||
- **原因**:之前首页显示全部系统/全部用户的全局统计数据,业务管理员不应看到平台全局数据
|
||||
- **结果**:
|
||||
- 系统总数 → 用户绑定系统数(拦截器已排除网关)
|
||||
- 用户总数 → JOIN sys_user_system 统计绑定系统下的用户
|
||||
- 今日登录/在线/30天趋势 → system_id IN (用户绑定系统) 过滤
|
||||
- super_admin 行为不变
|
||||
- 复用 UserContextInterceptor 已有的 systemIds(已排除网关),不重复查库
|
||||
- **涉及文件**: `DashboardController.java`
|
||||
|
||||
## 待处理
|
||||
- [ ] 验证:创建一个用户 → 删除 → 再创建同名用户,确认不再报错
|
||||
- [ ] 部署后验证首页数据权限:用非 super_admin 账号登录,确认统计数据只显示绑定系统范围内
|
||||
79
memory/session-20260617-1.md
Normal file
79
memory/session-20260617-1.md
Normal file
@@ -0,0 +1,79 @@
|
||||
---
|
||||
name: session-20260617-1
|
||||
description: 2026-06-17 第1次会话 — 前端日期时间格式统一 + 全局权限控制修复 + DB权限条目补全
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-17
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-17
|
||||
---
|
||||
|
||||
# 2026-06-17 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
1. 前端日期时间格式统一为 `yyyy-MM-dd HH:mm:ss`
|
||||
2. 全局排查并修复了前端 v-permission 权限控制缺失问题(9个页面少了几十个权限指令)
|
||||
3. 补充了数据库初始化脚本中缺失的权限条目(menu/delete, api/add/edit/delete, dict/add/edit/delete)
|
||||
4. 重写了日期工具函数,用手动解析替代 `new Date()` 避免跨浏览器兼容问题
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、创建/重写日期格式化工具
|
||||
- **做了什么**: 创建 `src/utils/date.ts`,导出 `formatDateTime()` 和 `formatDate()`
|
||||
- **原因**: 统一格式 + 解决 `new Date("yyyy-MM-dd HH:mm:ss")` 在 Firefox/Safari 中返回 Invalid Date 的浏览器兼容问题
|
||||
- **结果**: 使用手动正则解析替代 `new Date()` 解析字符串,兼容 ISO 8601、时间戳、后端标准格式
|
||||
- **涉及文件**: `src/utils/date.ts`(新建)
|
||||
|
||||
### 二、替换所有日期格式化调用
|
||||
- **做了什么**: 将7个Vue文件中所有 `toLocaleString('zh-CN')` 替换为 `formatDateTime()`,并为之前裸字符串显示日期的页面添加格式化
|
||||
- **涉及文件**: PersonalView, FileList, UserList, OperationLogList, LoginLogList, EmailList, OpenTokenLogList
|
||||
|
||||
### 三、全局修复 v-permission 权限控制
|
||||
- **问题根因**: 之前 90% 的操作按钮没有 `v-permission` 指令,导致即使用户没有勾选编辑/删除权限按钮,按钮仍然显示并可操作
|
||||
- **做了什么**: 为所有列表页的操作按钮添加了完整的 `v-permission` 指令
|
||||
|
||||
**前端修改(9个文件):**
|
||||
|
||||
| 文件 | 新增按钮 | 编辑按钮 | 删除按钮 | 其他 |
|
||||
|------|:--:|:--:|:--:|------|
|
||||
| SystemList.vue | ✅已有 | ✅新增 | ✅新增 | |
|
||||
| UserList.vue | ✅新增 | ✅新增 | ✅新增 | |
|
||||
| RoleList.vue | ✅新增 | ✅新增 | ✅新增 | 分配菜单 ✅新增 |
|
||||
| MenuList.vue | ✅新增 | ✅新增 | ✅新增 | 新增子级 ✅新增 |
|
||||
| DictList.vue | ✅新增 | ✅新增 | ✅新增 | 新增类型 ✅新增 |
|
||||
| ApiList.vue | ✅新增 | ✅新增 | ✅新增 | |
|
||||
| FileList.vue | N/A | N/A | ✅新增 | 上传 ✅新增 |
|
||||
| EmailList.vue | ✅已有 | N/A | ✅新增 | |
|
||||
| SystemConfig.vue | N/A | N/A | N/A | 保存 ✅新增 |
|
||||
|
||||
### 四、补充数据库权限条目
|
||||
- **做了什么**: 在 DB 初始化脚本中新增以下权限按钮(之前 DB 中没有这些记录,即使前端加了 v-permission,super_admin 也会因权限列表不含该字符串而看不到按钮)
|
||||
- **新增权限**: `system:menu:delete`, `system:api:add/edit/delete`, `system:dict:add/edit/delete`
|
||||
- **涉及文件**: `sql/qa_data.sql`, `sql/init_qa.py`, `sql/prod_add_permissions.sql`, `sql/prod_fix_data.sql`
|
||||
|
||||
### 权限字符串对照表
|
||||
|
||||
| 模块 | 列表权限 | 新增 | 编辑 | 删除 | 其他 |
|
||||
|------|---------|------|------|------|------|
|
||||
| 系统管理 | system:system:list | system:system:add | system:system:edit | system:system:delete | |
|
||||
| 用户管理 | system:user:list | system:user:add | system:user:edit | system:user:delete | |
|
||||
| 角色管理 | system:role:list | system:role:add | system:role:edit | system:role:delete | system:role:assignMenu |
|
||||
| 菜单管理 | system:menu:list | system:menu:add | system:menu:edit | system:menu:delete | |
|
||||
| 接口管理 | system:api:list | system:api:add | system:api:edit | system:api:delete | |
|
||||
| 数据字典 | system:dict:list | system:dict:add | system:dict:edit | system:dict:delete | |
|
||||
| 文件管理 | system:file:list | system:file:upload | | system:file:delete | |
|
||||
| 邮件管理 | system:email:list | system:email:send | | system:email:delete | |
|
||||
| 系统配置 | | system:config:save | | | |
|
||||
|
||||
### 五、网关转发注入用户信息头
|
||||
- **问题根因**: 非 `/zgapi/` 路径的请求(如 `/dashboard/stats`),TokenAuthFilter 直接放行不解析 token → HeaderInjectFilter 拿不到 tokenInfo → 转发到业务系统后端时请求头中没有 X-User-Id/Name 等用户信息
|
||||
- **做了什么**:
|
||||
1. `TokenAuthFilter.java`: 非 `/zgapi/` 路径也尝试解析 token(Cookie / Authorization 头),有则设置 tokenInfo,无/过期则放行不阻塞。`/zgapi/` 路径行为不变
|
||||
2. `HeaderInjectFilter.java`: 系统信息头(X-System-Id/Code/Name)原始请求已有则保留原始值,避免用 tokenInfo.currentSystemCode 覆盖业务系统前端设的 `x-system-code`
|
||||
- **涉及文件**: `TokenAuthFilter.java`, `HeaderInjectFilter.java`
|
||||
|
||||
## 待处理
|
||||
- [ ] 部署后验证:用非 super_admin 角色登录,确认未授权的按钮不显示
|
||||
- [ ] 在生产数据库执行 `prod_add_permissions.sql`(INSERT IGNORE 安全幂等)
|
||||
- [ ] 验证日期时间显示格式在各个浏览器中一致
|
||||
- [ ] 部署网关后验证:非 `/zgapi/` 业务系统请求能正确转发并携带用户信息头
|
||||
55
memory/session-20260618-1.md
Normal file
55
memory/session-20260618-1.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
name: session-20260618-1
|
||||
description: 2026-06-18 第1次会话 — 网关SocketTimeout日志分析 + Widget接入指南补全(后端文档+前端页面)
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-18
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-18T01:18:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-18 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
1. 分析网关日志中频繁出现的 `SocketTimeoutException` / `Broken pipe` 错误,确认是下游 `devops.server.zgitm.com` 响应太慢导致客户端超时断开,不是网关 Bug
|
||||
2. 将 Widget 接入详细指南补充到 deployServer 文档体系(新建 `06-gateway-widget.md`)
|
||||
3. 将 Widget 接入详细内容更新到网关前端公网文档页面 `IntegrationDoc.vue`(`https://web.gw.zgitm.com/docs/:token`)
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、网关 SocketTimeout/Broken pipe 日志分析
|
||||
- **做了什么**: 分析了 `mokee-gateway-gateway` 服务日志中大量 `AsyncRequestNotUsableException` → `ClientAbortException` → `SocketTimeoutException` / `Broken pipe` 异常栈
|
||||
- **根因**: 下游 `devops.server.zgitm.com` 的 `/api/apps/{8,9,10}/builds` 接口响应时间 >3秒,浏览器/前端超时主动断开连接,网关尝试写响应时发现 socket 已关闭
|
||||
- **结论**:
|
||||
- 🔴 主要问题:下游 devops 服务响应太慢
|
||||
- ⚠️ 网关问题:GlobalExceptionHandler 把客户端断开当成 ERROR 记录,应降级为 WARN 或静默忽略
|
||||
- 🟡 前端问题:超时设置过短(~3秒),并发请求多导致日志刷屏
|
||||
|
||||
### 二、deployServer 文档体系补充 Widget 接入指南
|
||||
- **做了什么**: 将 `mokee-gateway-widget-integration.md` 内容格式化后新建为编号文档 `docs/06-gateway-widget.md`
|
||||
- **原因**: 文档目录中原只有 01-05 号文档,Widget 接入指南是独立的未编号文件,需要纳入体系
|
||||
- **涉及文件**:
|
||||
- 新建:`deployServer/docs/06-gateway-widget.md`
|
||||
- 更新:`deployServer/README.md`(文档导航新增链接)
|
||||
- 更新:`deployServer/docs/05-implementation-plan.md`(文件清单树形图)
|
||||
|
||||
### 三、IntegrationDoc.vue 第 3.6 节 Widget 接入大幅扩展
|
||||
- **做了什么**: 将原来 3 行简略 HTML 代码替换为完整接入指南
|
||||
- **新增内容**:
|
||||
- 🚫 常见错误说明:`process is not defined` 的原因(Vue 3.x 打包引用 process.env,浏览器无此全局变量)
|
||||
- 步骤 1:index.html 引入 CSS(不引入 JS、不放占位 div)
|
||||
- 步骤 2:TopBar.vue 中放置占位 div(必须在 Vue 模板中,不在 index.html)
|
||||
- 步骤 3:main.js 中 mount 后动态加载脚本 + `window.process = { env: {} }` polyfill
|
||||
- 原理说明:ASCII 流程图展示加载时序
|
||||
- 排查清单:5 项常见问题对照表(Widget 不显示 / process 报错 / 登录不识别 / 样式错乱 / 跨域报错)
|
||||
- CDN 资源地址
|
||||
- **涉及文件**: `mokee-gateway-web/src/views/docs/IntegrationDoc.vue`
|
||||
- 注释头更新:8 个章节 → 10 个章节
|
||||
- 模板:第 3.6 节完全重写
|
||||
- Script:新增 `widgetTroubleshooting` 数据
|
||||
|
||||
## 待处理
|
||||
- [ ] `IntegrationDoc.vue` 修改需要重新构建部署 `mokee-gateway-web` 前端才能在 `https://web.gw.zgitm.com/docs/:token` 看到更新
|
||||
- [ ] 网关 `GlobalExceptionHandler` 需要优化:`ClientAbortException` / `AsyncRequestNotUsableException` 降级为 WARN 或静默处理
|
||||
- [ ] 排查 `devops.server.zgitm.com` 的 `/api/apps/{8,9,10}/builds` 接口性能,优化响应时间
|
||||
- [ ] 前端可考虑增加超时时间或减少并发请求数
|
||||
72
memory/session-20260618-2.md
Normal file
72
memory/session-20260618-2.md
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
name: session-20260618-2
|
||||
description: 2026-06-18 第2次会话 — 权限修复SQL执行 + 7页面查看按钮 + 3页面列宽填满 + 个人中心权限 + ICP备案号
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-18
|
||||
sessionNumber: 2
|
||||
startTime: 2026-06-18T02:00:00+08:00
|
||||
endTime: 2026-06-18T05:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-18 第2次会话
|
||||
|
||||
## 会话摘要
|
||||
1. 数据库权限修复:发现 PROD 缺失 10 条按钮权限(接口管理/数据字典/菜单删除/个人中心),已执行 SQL 补充并绑定 super_admin
|
||||
2. 7个列表页新增查看按钮(无需权限),含详情弹窗
|
||||
3. 修复 DictList/MenuList/TokenLog 表格列宽不填满屏幕的问题(width → min-width)
|
||||
4. 个人中心 3 个按钮绑定 v-permission
|
||||
5. 所有页面底部添加 ICP备案号 湘ICP备19021539号
|
||||
6. 纠正了之前的"全屏按钮"错误理解,删除 useFullscreen composable
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、数据库权限诊断与修复
|
||||
- **做了什么**: 连接 PROD 数据库 10.1.1.122,查询发现缺少 10 条按钮权限:
|
||||
- `system:api:add/edit/delete`(接口管理)← 导致超级管理员看不到新增接口按钮
|
||||
- `system:dict:add/edit/delete`(数据字典)
|
||||
- `system:menu:delete`(菜单管理缺少删除)
|
||||
- `system:profile:edit/password/avatar`(个人中心)
|
||||
- **执行方式**: Python pymysql 逐条 INSERT IGNORE + 全量 super_admin 绑定
|
||||
- **结果**: 26 个按钮权限全部绑定到 super_admin,需重新登录刷新 Redis TokenInfo
|
||||
- **涉及文件**: `sql/fix_all_permissions.sql`, 数据库 `mokeegateway@10.1.1.122`
|
||||
- **数据库账号**: mokeegateway / mokee.
|
||||
|
||||
### 二、查看按钮 — 6个页面新增
|
||||
- **做了什么**: 在 ApiList/UserList/SystemList/RoleList/DictList/OpenTokenLogList 添加"查看"按钮
|
||||
- **查看按钮无 v-permission**,所有人可见,点击弹出 el-descriptions 详情弹窗
|
||||
- **Token日志特别处理**: 弹窗展示完整 Token(可复制)、消费状态、所有时间字段
|
||||
- **涉及文件**: 6 个 list Vue 文件
|
||||
|
||||
### 三、表格列宽填满屏幕修复
|
||||
- **问题**: DictList/ MenuList/ OpenTokenLogList 表格列使用固定 width,不能填满屏幕
|
||||
- **修复**: 文本列 width="xxx" → min-width="xxx",固定宽度列(排序/状态/操作)保持不变
|
||||
- **清理**: 删除了之前错误添加的 useFullscreen composable、全屏按钮、card-fullscreen CSS
|
||||
- **涉及文件**: DictList.vue, MenuList.vue, OpenTokenLogList.vue
|
||||
|
||||
### 四、个人中心权限绑定
|
||||
- **做了什么**: PersonalView.vue 三个按钮添加 v-permission:
|
||||
- "保存信息" → `system:profile:edit`
|
||||
- "修改密码" → `system:profile:password`
|
||||
- "更换头像" → `system:profile:avatar`
|
||||
- **SQL**: 3 条独立权限条目(parent_id='0'),已执行到 PROD
|
||||
|
||||
### 五、ICP备案号
|
||||
- **做了什么**: 所有页面底部添加 `湘ICP备19021539号`,链接到 `https://beian.miit.gov.cn/`
|
||||
- **涉及页面**: AdminLayout.vue(footer-icp)、LoginView.vue(login-footer 追加)、SystemSelectView.vue(select-footer)、IntegrationDoc.vue(doc-footer)
|
||||
- **样式**: 灰色小字、居中、hover 变主题色
|
||||
|
||||
### 六、构建部署
|
||||
- **构建命令**: `npm run build:prod`(跳过 vue-tsc 类型检查,避免 pre-existing TS 错误)
|
||||
- **构建结果**: 成功,2437 + 1581 modules transformed
|
||||
|
||||
## 重要信息
|
||||
- 数据库: 10.1.1.122:3306, db=mokeegateway, user=mokeegateway, pass=mokee.
|
||||
- 查看按钮无需 v-permission,不入 sys_menu
|
||||
- 表格列宽用 min-width 替代 width 可自动填满屏幕
|
||||
- build:prod 跳过 vue-tsc,pre-existing TS 类型错误不影响部署
|
||||
|
||||
## 待处理
|
||||
- [ ] super_admin 重新登录验证所有 26 个按钮权限可见
|
||||
- [ ] 网关 `GlobalExceptionHandler` 优化(ClientAbortException 降级为 WARN)
|
||||
- [ ] 排查 `devops.server.zgitm.com` 接口性能
|
||||
59
memory/session-20260619-1.md
Normal file
59
memory/session-20260619-1.md
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
name: session-20260619-1
|
||||
description: 2026-06-19 第1次会话 — 接入文档全面审查和修复:permission字段补充、字段说明表、v-permission指令、Widget修复、废弃放行API、删除登录API
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-19
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-19T14:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-19 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
用户指出的接入文档(`docs/integration-guide.md` 和 `IntegrationDoc.vue`)中 INSERT SQL 缺少 `permission` 字段、字段含义未解释等问题,要求以"接入方开发者"视角全面审查文档,确保人家(非AI)能看懂并照着接入。进行了大范围审查和修复。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 1. 初始化SQL补充 permission 字段 + 按钮权限示例
|
||||
- **做了什么**:两个文件的菜单初始化 INSERT SQL 加上 `permission` 列,目录=NULL、菜单=页面权限标识、新增按钮(menu_type=3)示例(新增/编辑/删除)
|
||||
- **原因**:接入系统需要知道怎么创建按钮权限
|
||||
- **结果**:SQL 完整覆盖目录→菜单→按钮三级结构,含注释说明
|
||||
|
||||
### 2. 新增字段说明表
|
||||
- **做了什么**:第六章新增 6.1 节,含 sys_menu / sys_role / sys_role_menu 三张表的字段说明表格 + permission 命名规范示例表
|
||||
- **原因**:用户指出"字段意思没解释,人家一脸懵"
|
||||
- **结果**:每个字段的类型、必填、不同 menu_type 下填什么都写清楚了
|
||||
|
||||
### 3. 新增 v-permission 指令章节
|
||||
- **做了什么**:Markdown 3.6 / Vue 3.7 新增按钮权限控制章节,含 directive 代码、全局注册、模板用法
|
||||
- **原因**:接入方不知道怎么用 permissions 控制前端按钮显隐
|
||||
- **结果**:完整可复制的代码示例
|
||||
|
||||
### 4. Widget 接入章节大修
|
||||
- **做了什么**:从简单三行 HTML 改为正确的 polyfill 三步接入(process polyfill + mount后动态加载),加了排查清单
|
||||
- **原因**:原方式在浏览器会报 `process is not defined`,且说"如果不想手写代码"语气不对——这是必须这样做的步骤
|
||||
- **结果**:与 Vue 组件中 3.6 节一致,接入方不会踩坑
|
||||
|
||||
### 5. 废弃放行 API 章节
|
||||
- **做了什么**:新增 sys_api 章节后又根据用户指示完全移除(该功能已废弃)
|
||||
- **原因**:用户说"放行 API 配置废弃了,可以去掉"
|
||||
|
||||
### 6. 删除登录 API 章节
|
||||
- **做了什么**:删除 Markdown 5.1 / Vue 5.1 登录接口章节(请求体/响应体/字段说明全移除),API 章节重新编号
|
||||
- **原因**:用户指出"登录是网关的登录页面,业务系统没有登录页",所以不应该文档里出现登录API
|
||||
|
||||
### 7. 其他修复
|
||||
- 3.2 环境变量加说明表(各变量从哪获取)
|
||||
- 3.5 多系统场景改为跳转URL带 systemCode 参数(不再调用登录API)
|
||||
- 5.0 新增错误码表(200/401/403/500)
|
||||
- 管理员BCrypt改为 Python/Java/在线工具三种具体方式
|
||||
- 普通用户角色说明(为何初始化不给菜单、怎么手动分配)
|
||||
- 测试清单移除"未放行API"项
|
||||
|
||||
## 修改文件
|
||||
- `docs/integration-guide.md`
|
||||
- `mokee-gateway-web/src/views/docs/IntegrationDoc.vue`
|
||||
|
||||
## 待处理
|
||||
- [ ] 部署前端到服务器使线上文档页生效
|
||||
71
memory/session-20260620-1.md
Normal file
71
memory/session-20260620-1.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
name: session-20260620-1
|
||||
description: 2026-06-20 第1次会话 — menu/router接口改造、user/info权限过滤、文档清理、数据库IP迁移域名、Redis Key加前缀
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-20
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-20T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-20 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
本次会话主要做了5件事:1) `/menu/router` 接口响应结构调整,新增 `permission` 字段;2) `/user/info` 的 `permissions` 仅 gateway 系统返回;3) 接入文档清理删除冗余接口章节;4) 数据库/Redis IP 全部迁移到域名;5) Redis Key 加统一前缀 `GATEWAY:`。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 1. /menu/router 接口返回结构调整
|
||||
- **做了什么**: 新建 `MenuRouterResponse` DTO(含 `menu` + `permission` 字段),修改 AuthService/AuthServiceImpl/AuthController 返回新结构,前端 auth.ts 和 AdminLayout.vue 适配新结构
|
||||
- **原因**: 业务系统需要一次性获取菜单路由树 + 该系统所有权限标识,用于前端 v-permission 指令
|
||||
- **结果**: 返回从 `[{...}]` 变为 `{"menu":[{...}], "permission":["...","..."]}`
|
||||
- **涉及文件**: `MenuRouterResponse.java`(新建), `AuthService.java`, `AuthServiceImpl.java`, `AuthController.java`, `auth.ts`, `AdminLayout.vue`, `integration-guide.md`, `IntegrationDoc.vue`
|
||||
|
||||
### 2. /user/info 的 permissions 条件返回
|
||||
- **做了什么**: `getUserInfo()` 中判断 `currentSystemCode`,仅 gateway 系统返回 permissions,业务系统返回 null
|
||||
- **原因**: user/info 的 permissions 是网关平台权限,业务系统用不到,应通过 /menu/router 获取自身权限
|
||||
- **结果**: 文档 5.1 节完全去掉 permissions 字段
|
||||
|
||||
### 3. 接入文档删除 system/select 和 logout 接口
|
||||
- **做了什么**: 删除 Markdown 和 Vue 文档中 5.4 (system/select) 和 5.5 (logout) 章节,5.6→5.4 重新编号,API 速查表同步更新
|
||||
- **原因**: 这两个接口 Widget 已内置(切换系统→跳转系统选择页,退出登录→Widget 内部处理),接入系统不需要自己调
|
||||
- **涉及文件**: `integration-guide.md`, `IntegrationDoc.vue`
|
||||
|
||||
### 4. 数据库/Redis IP 迁移域名
|
||||
- **做了什么**: 全项目 `10.1.1.122` → 域名,区分 PROD/QA 环境
|
||||
- **原因**: 统一使用域名方便运维,IP 变更不用改代码
|
||||
- **结果**:
|
||||
- PROD: MySQL=`db1.prod.zgitm.com`, Redis=`redis.db1.zgitm.com`
|
||||
- QA: MySQL=`db1.qa.zgitm.com`, Redis=`redis.db2.zgitm.com`
|
||||
- **涉及文件**: 21个文件(yml src×6 + yml target×6 + py×7 + 需求文档×1 + ...)
|
||||
|
||||
### 5. Redis Key 加统一前缀 GATEWAY:
|
||||
- **做了什么**: `RedisUtil` 新增 `KEY_PREFIX = "GATEWAY:"` 常量和 `key()` 静态方法,所有 Redis key 改为 `RedisUtil.key("xxx")`
|
||||
- **原因**: 以后改前缀只改一处
|
||||
- **结果**: 所有 key 变为 `GATEWAY:rate:login:...` / `GATEWAY:auth:token:...` / `GATEWAY:open:token:...` 等
|
||||
- **涉及文件**: `RedisUtil.java`, `AuthServiceImpl.java`, `UserServiceImpl.java`, `RoleServiceImpl.java`, `OpenApiController.java`
|
||||
|
||||
## 重要信息
|
||||
|
||||
### 数据库连接
|
||||
| 环境 | MySQL | Redis |
|
||||
|------|-------|-------|
|
||||
| PROD | db1.prod.zgitm.com:3306 | redis.db1.zgitm.com:6379 |
|
||||
| QA | db1.qa.zgitm.com:3306 | redis.db2.zgitm.com:6379 |
|
||||
|
||||
### API 接口清单(接入系统用)
|
||||
| 章节 | 接口 | 说明 |
|
||||
|------|------|------|
|
||||
| 5.1 | GET /user/info | 用户信息(无 permissions) |
|
||||
| 5.2 | GET /menu/router | 菜单树 + 权限列表 |
|
||||
| 5.3 | GET /system/list | 可切换系统列表 |
|
||||
| 5.4 | PUT /password/update | 修改密码 |
|
||||
|
||||
### Redis Key 前缀
|
||||
- 统一前缀: `GATEWAY:`
|
||||
- 改法: `RedisUtil.key("auth:token:" + tokenId)`
|
||||
|
||||
## 待处理
|
||||
- [ ] 部署后端到服务器使接口变更生效
|
||||
- [ ] 部署前端到服务器使文档页生效
|
||||
- [ ] 确认 DNS 解析 `db1.prod.zgitm.com` / `db1.qa.zgitm.com` / `redis.db1.zgitm.com` / `redis.db2.zgitm.com` 已配置
|
||||
51
memory/session-20260620-2.md
Normal file
51
memory/session-20260620-2.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
name: session-20260620-2
|
||||
description: 2026-06-20 第2次会话 — 修复TokenAuthFilter Redis Key前缀遗漏导致登录后Token找不到会话
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-20
|
||||
sessionNumber: 2
|
||||
startTime: 2026-06-20T10:45:00+08:00
|
||||
endTime: 2026-06-20T10:55:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-20 第2次会话
|
||||
|
||||
## 会话摘要
|
||||
修复 TokenAuthFilter 中 Redis Key 缺少 `GATEWAY:` 前缀的 bug。上次会话给 RedisUtil 加了统一前缀机制后,Auth/Admin 服务都改为使用 `RedisUtil.key()` 生成 key,但 Gateway 的 TokenAuthFilter 被遗漏,导致登录后 Token 校验时找不到 Redis 会话。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### TokenAuthFilter Redis Key 前缀修复
|
||||
- **做了什么**: `TokenAuthFilter.java` 中两处 Redis key 改为 `RedisUtil.key("auth:token:" + tokenId)` 和 `RedisUtil.key("open:token:" + tokenId)`
|
||||
- **原因**: 上次会话(session-1)引入 `RedisUtil.KEY_PREFIX = "GATEWAY:"` 和 `key()` 方法后,Auth 服务写入 key 是 `GATEWAY:auth:token:xxx`,但 Gateway 读取时直接拼 `"auth:token:" + tokenId`(无前缀),导致永远找不到。这是一个重构遗漏 bug。
|
||||
- **结果**: 修复后 Gateway 正确使用 `RedisUtil.key()` 生成带前缀的 key,与 Auth/Admin 服务写入的 key 一致
|
||||
- **涉及文件**: `TokenAuthFilter.java` (第115行和第183行)
|
||||
|
||||
### 问题诊断过程
|
||||
- **日志现象**: `Token 对应 Redis 会话不存在 - tokenId: 43a705df-fdc7-4b97-b5eb-605d3c081897`
|
||||
- **数据流追踪**:
|
||||
1. 登录 → Auth 服务写入 `GATEWAY:auth:token:43a705df-...` ✓
|
||||
2. 校验 → Gateway 查找 `auth:token:43a705df-...` ✗ (缺少 GATEWAY: 前缀)
|
||||
- **根因**: `RedisUtil.key()` 自动添加 `GATEWAY:` 前缀,但 TokenAuthFilter 没使用此方法
|
||||
|
||||
## 重要信息
|
||||
- Redis 前缀机制详情见 [[session-20260620-1]] 的 "Redis Key 加统一前缀 GATEWAY:" 章节
|
||||
- Auth 服务(9001)、Admin 服务(9002)、Gateway(9000) 三个服务共享同一个 Redis 实例
|
||||
- 所有 Redis key 操作都必须通过 `RedisUtil.key()` 方法,不能直接拼字符串
|
||||
|
||||
## 待处理
|
||||
- [x] 重新编译部署 Gateway 服务使修复生效 (10:54 已部署到 10.1.1.170 Docker 容器 mokeegateway-mokee-gateway-gateway)
|
||||
- [ ] 验证登录后 Token 校验正常通过(用户自行测试)
|
||||
|
||||
## 部署记录
|
||||
- **服务器**: 10.1.1.170(内网)
|
||||
- **容器名**: mokeegateway-mokee-gateway-gateway
|
||||
- **容器 ID**: 09bc559da896
|
||||
- **镜像**: harbor.zgitm.com/mokee/mokee-mokeegateway-mokee-gateway-gateway:v78.20260620102948
|
||||
- **部署方式**: SCP JAR → docker cp 替换 /app/app.jar → docker restart
|
||||
- **启动耗时**: 约 5.5 秒
|
||||
- **部署时间**: 2026-06-20 10:54
|
||||
|
||||
## 新规则
|
||||
- **部署 170 须用户授权**: 后续没有用户明确要求,不能擅自部署到 10.1.1.170(生产环境)。[[deploy-approval-required]]
|
||||
50
memory/session-20260621-1.md
Normal file
50
memory/session-20260621-1.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
name: session-20260621-1
|
||||
description: 2026-06-21 第1次会话 — 接口性能排查 + sys_system.system_code 加索引
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-21
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-21T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-21 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
用户反馈两个接口响应慢,排查了全链路耗时分布。最终在 QA/Prod 数据库 `sys_system` 表 `system_code` 列加了普通索引。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### /zgapi/v1/auth/system/list 性能排查
|
||||
- **做了什么**: 完整追踪请求链路:Nginx → Gateway(9000) → TokenAuthFilter → RateLimitFilter → HeaderInjectFilter → ApiPermissionFilter → GatewayController → [HTTP转发] → Auth(9001) → DB/Redis
|
||||
- **发现的浪费**:
|
||||
1. JWT 签名验证执行了 3 次(TokenAuthFilter + RateLimitFilter + AuthServiceImpl)
|
||||
2. 同一个 Redis key 被查询了 4 次(TokenAuthFilter GET+GETEXPIRE + AuthServiceImpl GET+GETEXPIRE)
|
||||
3. Gateway→Auth HTTP 转发无连接池(SimpleClientHttpRequestFactory)
|
||||
- **原因**: Gateway 和 Auth 服务各自独立认证,互不复用结果
|
||||
- **结论**: 架构设计上的"层层设防"必然代价,不是 bug。未改代码
|
||||
|
||||
### /zgapi/v1/open/token 性能排查
|
||||
- **做了什么**: 追踪 `/zgapi/v1/open/token` 全链路
|
||||
- **发现的问题**:
|
||||
1. `sys_system.system_code` 列没有索引 → 每次查询都是全表扫描
|
||||
2. `sys_open_token_log` 用 UUID 主键,日志量上去后 INSERT 引发页分裂
|
||||
3. RateLimitFilter 对所有 /open/token 请求共用一个 anonymous 限流 key
|
||||
4. 同上:Gateway→Admin HTTP 转发无连接池
|
||||
|
||||
### sys_system.system_code 加索引
|
||||
- **做了什么**: 在 QA (`mokeegatewayqa`) 和 Prod (`mokeegateway`) 的 `sys_system` 表 `system_code` 列创建普通索引 `idx_system_code`
|
||||
- **SQL**: `CREATE INDEX idx_system_code ON sys_system (system_code)`
|
||||
- **原因**: DDL 仅指定了 PRIMARY KEY (id),system_code 的索引被遗漏,所有按 system_code 查询的场景都在全表扫描(/open/token、ApiPermissionFilter、GatewayController 业务系统转发等)
|
||||
- **验证结果**: QA 和 Prod 均已确认 `idx_system_code` 存在
|
||||
|
||||
## 重要信息
|
||||
- QA MySQL: db1.qa.zgitm.com / mokeegatewayqa
|
||||
- Prod MySQL: db1.prod.zgitm.com / mokeegateway
|
||||
- DDL `sys_system` 注释 "uk_system_code/uk_gateway_url 唯一性由应用层代码校验" 说明当时故意没建唯一约束,但普通索引也没有是遗漏
|
||||
|
||||
## 待处理
|
||||
- [ ] 可以考虑给 `sys_system.gateway_url` 也加个索引(但使用频率低,优先级不高)
|
||||
- [ ] `RestTemplateConfig` 改用连接池(HttpComponentsClientHttpRequestFactory),省掉每次转发的 TCP 握手
|
||||
- [ ] `RateLimitFilter` 可以跳过 `/zgapi/v1/open/token`(获取 token 本身不应限流,且 anonymous key 是热点)
|
||||
- [ ] Auth 服务 getTokenInfoFromRedis 中 JWT validateToken 可以改为只解析 payload 不验签(Gateway 已验证过)
|
||||
38
memory/session-20260623-1.md
Normal file
38
memory/session-20260623-1.md
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: session-20260623-1
|
||||
description: 2026-06-23 第1次会话 — Cookie Token 兜底确认 + API 白名单跳过鉴权方案设计
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-23
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-23T00:00:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-23 第1次会话
|
||||
|
||||
## 会话摘要
|
||||
1. 用户询问网关是否支持从 Cookie 读取 Token 兜底,确认已有实现,无需改动
|
||||
2. 用户提出新增"API 白名单跳过鉴权"需求,完成方案设计,计划已保存待后续实施
|
||||
|
||||
## 关键操作
|
||||
|
||||
### Cookie Token 兜底确认
|
||||
- **做了什么**: 检查了 TokenAuthFilter.java、前端 auth.ts/request.ts 的完整链路
|
||||
- **结论**:
|
||||
- `/zgapi/*` 路径:Authorization 头 → Cookie 兜底 ✅ 已有
|
||||
- `/zgapi/v1/open/*` 路径:Authorization 头 → query 参数兜底 ✅ 已有,用 Cookie
|
||||
- Cookie 由前端登录后写入(domain=.zgitm.com, max-age=7200, SameSite=Lax)
|
||||
- **用户确认**: Open API 绝不用 Cookie,保持现状
|
||||
|
||||
### API 白名单跳过鉴权方案设计
|
||||
- **做了什么**: 完整调研了 TokenAuthFilter、ApiPermissionFilter、sys_api 表、SysApi 实体、前端 ApiForm/ApiList
|
||||
- **方案**: 扩展 `sys_api` 表新增 `skip_auth` 字段(TINYINT, 0=需鉴权/1=跳过),在 TokenAuthFilter 中增加 Caffeine 缓存查询
|
||||
- **计划文件**: `C:\Users\Administrator\.claude\plans\valiant-nibbling-lake.md`
|
||||
|
||||
## 重要信息
|
||||
- 方案涉及 8 个文件(2 新建 + 6 修改)
|
||||
- 核心逻辑:TokenAuthFilter 在返回 401 之前,先查 SkipAuthCacheService(Caffeine 5min TTL),匹配则放行
|
||||
- 不改动 `/zgapi/v1/open/*` 路径
|
||||
|
||||
## 待处理
|
||||
- [ ] 执行 API 白名单跳过鉴权方案实施(计划已就绪,下次会话继续)
|
||||
82
memory/session-20260628-1.md
Normal file
82
memory/session-20260628-1.md
Normal file
@@ -0,0 +1,82 @@
|
||||
---
|
||||
name: session-20260628-1
|
||||
description: 2026-06-28 第1次会话 — 登录后头像下载接口重复调用三轮排查修复
|
||||
metadata:
|
||||
type: session
|
||||
date: 2026-06-28
|
||||
sessionNumber: 1
|
||||
startTime: 2026-06-28T05:00:00+08:00
|
||||
endTime: 2026-06-28T05:30:00+08:00
|
||||
---
|
||||
|
||||
# 2026-06-28 会话
|
||||
|
||||
## 会话摘要
|
||||
|
||||
用户反馈登录成功后 `/open/token` 和 `https://file.wg.zgitm.com/api/download` 接口被重复调用。经过三轮排查,发现根因是 `login()` + `fetchUserInfo()`(SystemSelectView/AdminLayout)重复刷新头像 Token。最终方案:`login()` 刷新头像(确保 `<el-avatar>` 加载时 URL 已有 Token),`fetchUserInfo()` 增加去重逻辑(同一文件复用已有 URL),共 3 次部署到生产环境。
|
||||
|
||||
## 关键操作
|
||||
|
||||
### 一、第一轮修复 — 删除 login() 中的头像刷新
|
||||
|
||||
- **做了什么**: 删除 `auth.ts` login() 中的 `refreshFileServiceUrl()` 调用
|
||||
- **原因**: login() 和 fetchUserInfo() 各刷新一次,导致 2 次 /open/token + 2 次 download
|
||||
- **结果**: ❌ 引入新问题——login() 不刷新后,`<el-avatar>` 先用无 Token 的 URL 发起失败请求,fetchUserInfo() 再发一次成功请求
|
||||
|
||||
### 二、第二轮修复 — fetchUserInfo() 增加去重 + 恢复 login() 刷新
|
||||
|
||||
- **做了什么**:
|
||||
1. `fetchUserInfo()` 中比较当前 store 中的 avatar(去 Token)和新获取的 avatar(去 Token),相同文件则复用已有 URL
|
||||
2. 恢复 `login()` 中的头像刷新
|
||||
- **原因**: 用户发现 admin 登录后 download 接口仍被调用 2 次:SystemSelectView 一次 → AdminLayout 又一次
|
||||
- **结果**: ✅ 达到 1 次 /open/token + 1 次 download
|
||||
|
||||
### 三、最终代码改动
|
||||
|
||||
**文件**: `mokee-gateway-web/src/stores/auth.ts`
|
||||
|
||||
**login() 最终版** — 保留头像刷新:
|
||||
```typescript
|
||||
// 立即刷新头像 Token — 否则跳转后 <el-avatar> 先用无 Token 的 URL
|
||||
// 发起一次失败请求,等 fetchUserInfo() 拿到 Token 后又发起第二次
|
||||
// fetchUserInfo() 中有去重逻辑,不会重复刷新同一文件
|
||||
let userInfoData = data.userInfo
|
||||
if (userInfoData?.avatar && isFileServiceUrl(userInfoData.avatar)) {
|
||||
userInfoData = { ...userInfoData, avatar: await refreshFileServiceUrl(userInfoData.avatar) }
|
||||
}
|
||||
userInfo.value = userInfoData
|
||||
```
|
||||
|
||||
**fetchUserInfo() 最终版** — 增加去重:
|
||||
```typescript
|
||||
const prevBase = stripToken(userInfo.value?.avatar || '')
|
||||
const newBase = stripToken(data?.avatar || '')
|
||||
if (data?.avatar && isFileServiceUrl(data.avatar) && prevBase !== newBase) {
|
||||
data = { ...data, avatar: await refreshFileServiceUrl(data.avatar) }
|
||||
} else if (data?.avatar && isFileServiceUrl(data.avatar) && prevBase === newBase) {
|
||||
// 同一文件,复用已有的带 Token 的 URL
|
||||
data = { ...data, avatar: userInfo.value?.avatar || data.avatar }
|
||||
}
|
||||
```
|
||||
|
||||
## 部署记录
|
||||
|
||||
- **服务器**: 10.1.1.170(内网)
|
||||
- **前端容器**: `mokeegateway-web-mokee-gateway-web`(nginx:stable-alpine,端口 80→5001)
|
||||
- **部署方式**: `npm run build:prod` → SFTP 上传 dist → `docker cp` 替换容器内 `/usr/share/nginx/html/` → `docker exec nginx -s reload`
|
||||
- **共部署 3 次**,最终版本已验证 HTTP 200
|
||||
|
||||
## 重要信息
|
||||
|
||||
- 生产 Docker 容器列表(10.1.1.170):
|
||||
- `mokeegateway-web-mokee-gateway-web` — 前端
|
||||
- `mokeegateway-mokee-gateway-gateway` — 网关
|
||||
- `mokeegateway-mokee-gateway-auth` — 认证
|
||||
- `mokeegateway-mokee-gateway-admin` — 管理
|
||||
- 文件服务域名: `file.wg.zgitm.com`,下载 Token 一次性消费
|
||||
- 头像存储在文件服务中,DB 只存基础路径,每次加载页面需获取 Token 并拼接完整 URL
|
||||
|
||||
## 待处理
|
||||
|
||||
- [ ] 生产环境验证:用 admin 用户登录,确认只调用 1 次 /open/token 和 1 次 download
|
||||
- [ ] 容器内旧 JS chunk 文件会累积(docker cp 不删除旧文件),长期需增加清理步骤
|
||||
Reference in New Issue
Block a user