charging-cabinet/tasks/review-full-codebase-report.md
2026-07-02 05:38:01 +08:00

13 KiB
Raw Blame History

全面代码审查报告

总体评价

评分7.5 / 10

项目整体代码质量良好,架构清晰,模块职责分明。后端 Rust 代码规范,通过了 cargo clippy 零警告检查;前端 TypeScript 代码通过 tsc --noEmit 零错误,vite build 构建成功。RBAC 权限模型完整TCP 协议处理健壮。主要不足集中在安全细节、性能优化和部分功能未完成方面。

统计

  • 后端文件数29Rust
  • 前端文件数35TypeScript/TSX
  • 后端代码行数5,162
  • 前端代码行数5,282
  • 总代码行数10,444
  • 问题总数19严重 5 / 警告 8 / 建议 6

静态检查结果

检查项 结果
cargo check 通过
cargo clippy 通过(零警告)
tsc --noEmit 通过(零错误)
vite build 通过(有 chunk 大小警告)

严重问题(必须修复)

问题1设备指令下发接口缺少权限校验

  • 位置software/server/src/tcp/commands.rs:36-61
  • 描述send_command 端点(POST /api/devices/:dev_id/command)虽然经过认证中间件,但未调用 check_permission 进行 RBAC 权限校验。任何已登录用户均可向设备下发任意指令(包括开门、供电等危险操作)。
  • 风险:未授权用户可操控设备,造成安全隐患。
  • 建议:在 send_command 函数开头添加权限校验,根据 act 字段判断所需权限码(如 device:operate、charge:open_door` 等)。

问题2组织树接口缺少权限校验和数据隔离

  • 位置software/server/src/routes/cabinet_tree.rs:14-92
  • 描述organization_tree 端点未提取 CurrentUser,无权限校验,也无组织级数据隔离。企业管理员可通过此接口看到所有组织的数据。
  • 风险:数据泄露,违反多租户隔离原则。
  • 建议:添加 CurrentUser 提取器,校验 device:view 权限,并根据 role_levelorganization_id 过滤返回数据。

问题3默认密码 "123456" 硬编码

  • 位置software/server/src/routes/users.rs:302software/server/src/routes/users.rs:437
  • 描述:创建用户和重置密码时,默认密码硬编码为 "123456"。此密码过于简单,且散落在代码中。
  • 风险:安全风险,弱密码可能被暴力破解。
  • 建议:将默认密码抽离为配置常量,并强制用户首次登录时修改密码。至少应使用随机生成的初始密码。

问题4auth_str 安全码明文打印到日志

  • 位置software/server/src/tcp/handler.rs:61
  • 描述handle_auth_str 函数将生成的安全码以明文写入日志:tracing::info!("[auth_str] dev_id={} auth_str={}", dev_id, auth_str)
  • 风险:安全码泄露,攻击者可通过日志获取签名密钥。
  • 建议:移除日志中的 auth_str 值,仅记录 dev_id或使用脱敏处理如仅打印前2位

问题5前端刷新后用户信息丢失

  • 位置software/web/src/stores/auth.ts:71-76
  • 描述restore 函数仅从 localStorage 恢复 token但未调用 /api/auth/me 获取用户信息和权限码。刷新页面后,虽然 token 存在,但 user 为 null导致前端权限判断hasPermission)始终返回 false所有权限按钮消失。
  • 风险:用户体验严重受损,刷新后所有权限控制按钮消失。
  • 建议:在 restore 中检测到 token 后,异步调用 /api/auth/me 恢复完整用户信息。

警告(建议修复)

警告1前端打包体积过大

  • 位置software/web/ 构建配置
  • 描述vite build 产物 JS 文件 1,314 KBgzip 后 374 KB超过 500 KB 警告阈值。未做代码分割。
  • 建议:使用 React.lazy() + 动态 import() 对路由级组件进行代码分割,尤其是 H5 端和后台管理端应分离打包。

警告2柜子详情接口存在 N+1 查询

  • 位置software/server/src/routes/cabinets.rs:284-308
  • 描述get_cabinet_detail 先查询仓控板列表,然后对每个仓控板单独查询仓体。若柜子有 N 块仓控板,则产生 N+1 次数据库查询。
  • 建议:使用一条 SQL 通过 JOIN 查询所有仓控板和仓体,或在应用层批量查询。

警告3角色列表接口存在 N+1 查询

  • 位置software/server/src/routes/roles.rs:42-69
  • 描述list_roles 对每个角色单独查询权限码,产生 N+1 次查询。
  • 建议:使用一条 SQL 通过 JOIN 查询所有角色及其权限码。

警告4多处使用 as unknown as 类型断言

  • 位置software/web/src/pages/devices/index.tsx:81,103OrganizationTree.tsx:169,171
  • 描述:前端代码中多处使用 as unknown as 进行类型强转,绕过了 TypeScript 类型检查。
  • 建议:修正 API 响应类型定义,使其与实际返回数据结构一致,消除不必要的类型断言。

警告5下载文件端点未实现

  • 位置software/server/src/routes/downloads.rs:162
  • 描述get_download 返回 download_url: "/api/downloads/{id}/file",但此路由未在 routes/mod.rs 中注册,实际下载功能不可用。
  • 建议:实现文件下载端点,使用 axum::response::Filetower-httpServeDir 提供文件服务。

警告6org_condition 辅助函数未被充分使用

  • 位置software/server/src/middleware/auth.rs:255-270
  • 描述org_condition 函数已定义但仅在 charge_records.rsdevice_logs.rs 中使用。cabinet_tree.rsenergy_stats.rs 等模块自行实现了类似的组织过滤逻辑,代码重复。
  • 建议:统一使用 org_conditionorg_condition_for_logs 进行组织数据隔离,减少重复代码。

警告7H5 用户端 API 端点后端未实现

  • 位置software/web/src/h5/api.ts
  • 描述H5 API 调用了 /h5/auth/login/h5/dashboard/h5/projects 等端点但后端路由中未注册这些路径。H5 用户端目前无法正常工作。
  • 建议:明确 H5 后端 API 的开发计划,或在 H5 代码中标注为 WIPWork In Progress

警告8Dashboard 页面为占位符

  • 位置software/web/src/pages/Dashboard.tsx
  • 描述后台管理首页仅显示欢迎文字无任何数据展示。能耗管理页面已有总览数据Dashboard 应复用或引用。
  • 建议:实现 Dashboard 数据展示(如今日充电次数、在线设备数、告警数等),可复用 energy-stats/summary 接口。

建议(可优化)

建议1LIKE 查询中 % 通配符未转义

  • 位置software/server/src/routes/users.rs:111
  • 描述let like_pattern = format!("%{}%", keyword) 未对关键字中的 %_ 进行转义,用户输入这些字符时可能产生非预期的模糊匹配。
  • 建议:对 keyword 中的 %_ 进行转义后再拼接 LIKE 模式。

建议2连接池最大连接数可配置化

  • 位置software/server/src/db/mod.rs:11
  • 描述MySQL 连接池 max_connections(20) 硬编码。
  • 建议:通过环境变量 DB_MAX_CONNECTIONS 配置,便于不同环境调整。

建议3充电曲线使用静态模拟数据

  • 位置software/web/src/h5/pages/compartment-detail.tsx:174
  • 描述:通道详情页的充电曲线使用硬编码数据 [30, 45, 55, ...] 展示,非真实数据。
  • 建议:标注为 TODO 或待后端提供充电曲线 API 后替换,当前可接受。

建议4log_operation 函数可抽取为公共模块

  • 位置software/server/src/routes/users.rs:63-85
  • 描述:操作日志记录函数 log_operation 定义在 users.rs 中,但其他模块(如 roles.rscabinets.rs)也需要记录操作日志。
  • 建议:将 log_operation 抽取到公共模块(如 middleware/auth.rs 或新建 utils/log.rs),供所有路由模块复用。

建议5前端 eslint-disable 注释

  • 位置software/web/src/h5/pages/devices.tsx:62device-detail.tsx:37compartment-detail.tsx:43
  • 描述H5 页面中有多处 eslint-disable-next-line react-hooks/exhaustive-deps,跳过了 Hook 依赖检查。
  • 建议:补充正确的依赖项,或使用 useCallback 包裹函数以明确依赖关系。

建议6数据库迁移缺少索引定义

  • 位置software/server/src/db/migrate.rs
  • 描述:建表语句中未创建索引(除 energy_stats 的联合唯一键外)。charge_recordsdevice_logsoperation_logs 等高频查询表缺少对 cabinet_idcreated_at 等常用过滤字段的索引。
  • 建议:在迁移脚本中添加索引,如:
    • charge_records: cabinet_id, start_time
    • device_logs: cabinet_id, created_at
    • operation_logs: user_id, created_at
    • cabinets: project_id

审查清单完成情况

1. 编译与类型检查

  • cargo check 零报错零警告
  • cargo clippy 零报错零警告
  • tsc --noEmit 零报错零警告
  • vite build 成功(有 chunk 大小警告)

2. 代码规范

  • 单函数基本 <=80 行(少数函数略超,如 list_users 约 160 行,可拆分)
  • 命名语义化,无无意义缩写
  • 完整注释(模块级文档注释 + 函数文档注释)
  • 常量抽离(如 COST_PER_KWHSIGN_STARTTIMESTAMP_TOLERANCE_SECS
  • 无废弃 API 使用

3. 错误处理

  • 所有外部 IO/网络请求有异常捕获
  • 无裸 panic!expect 仅用于启动阶段的致命错误,如数据库连接失败)
  • 分支逻辑基本全覆盖
  • 错误信息有意义(使用中文描述,含上下文)

4. Rust 专项

  • 内存安全,使用 sqlx 连接池无冗余拷贝
  • unsafe
  • 所有权管理合理(ConnectionPool 使用 Arc<RwLock<>> 共享)
  • 异步代码无阻塞操作

5. React 专项

  • 函数式组件 + Hooks无 Class 组件
  • 状态管理使用 Zustand分层清晰
  • useEffect 有清理函数(如 DownloadCenter 的 setInterval
  • 少量 as unknown as 类型断言见警告4

6. 安全

  • SQL 注入防护(全部使用 ? 参数化查询)
  • 密码哈希使用 argon2
  • JWT 密钥有环境变量覆盖机制 + 警告
  • 输入参数校验(手机号 11 位、IMEI 15 位等)
  • 权限校验未覆盖所有 API 接口(见严重问题 1、2
  • 数据隔离部分缺失(见严重问题 2
  • 敏感参数脱敏不足(见严重问题 4

7. 业务逻辑

  • TCP 协议解析正确签名验证、LF 粘包处理、超时清理)
  • 权限模型正确(总管理员/企业管理员/普通用户三级)
  • 异步导出流程完整(任务创建 -> 后台处理 -> 下载中心)
  • 前端权限组件正确隐藏/禁用按钮

8. 架构

  • 接口层、业务逻辑层、数据模型层分离
  • 无循环依赖
  • 模块职责清晰
  • 路由注册完整

9. 性能

  • 数据库查询缺少索引(见建议 6
  • 存在 N+1 查询(见警告 2、3
  • 前端列表有分页
  • 大数据量导出异步处理

10. 可维护性

  • 文件长度合理(最长 467 行 energy/index.tsx
  • 组件拆分合理
  • 代码重复度低(组织过滤逻辑有重复,见警告 6
  • 配置外部化(环境变量 + dotenvy

优点

  1. 架构清晰后端按功能域拆分模块auth、organizations、cabinets、users 等),每个文件职责单一,不超过 500 行。
  2. 安全性基础扎实:密码使用 argon2 哈希、JWT 有过期时间、SQL 全部参数化、TCP 签名验证含时间窗口校验。
  3. RBAC 权限模型完整:权限码精确到按钮级别,前端 Permission 组件支持 hidden/disabled 两种模式,总管理员自动拥有全部权限。
  4. TCP 协议处理健壮:使用 LinesCodec 处理粘包、mpsc 通道分离读写、心跳超时自动清理、连接池 Arc<RwLock> 支持并发。
  5. 异步导出设计合理download_tasks 表管理任务状态、tokio::spawn 后台生成 Excel、前端轮询刷新、过期文件清理。
  6. 前端工程化规范Zustand 状态管理简洁、API 层统一封装、路由守卫完善、H5 端与后台管理端独立认证。
  7. 代码注释充分:每个模块有模块级文档注释,关键函数有入参/返回值说明,复杂逻辑有行内注释。
  8. 数据库迁移自动化:启动时自动建表 + 初始化权限码和角色,部署友好。

总结

项目整体质量良好,代码规范、架构清晰、安全基础扎实。优先修复建议

  1. P0立即修复:设备指令下发接口添加权限校验(严重问题 1、组织树接口添加权限校验和数据隔离严重问题 2
  2. P1尽快修复:前端 restore 后加载用户信息(严重问题 5、auth_str 日志脱敏(严重问题 4、默认密码安全化严重问题 3
  3. P2迭代优化N+1 查询优化、数据库索引添加、前端代码分割、下载文件端点实现、Dashboard 数据填充。
  4. P3后续完善H5 后端 API 开发、操作日志函数抽取公共模块、LIKE 通配符转义。