elder 项目功能笔记(分模块)

elder 项目功能笔记(分模块)

技术栈:Spring Boot 3.4.5 + MyBatis-Plus + MySQL + JWT + 阿里云 OSS + Spring AI(DeepSeek) + EasyExcel
前端:ui-admin 管理后台(Vue3 + Element Plus)、ui-app 手机端(Vue3 + Vant)


一、登录模块(全项目的参照模板)

流程:

  1. 前端输入姓名和密码,POST /admin/users/login 提交 {name, password}
  2. 后端 getOne(new QueryWrapper<User>().eq("name", user.getName())) 判断是否有数据,没有返回”用户名不存在”
  3. 有就对比密码,再依次校验注销(deleted)、禁用(status)状态
  4. 校验通过后,map 存储 id 和 name,通过 String token = JwtUtil.createToken(map) 创建 token(HMAC256 签名,1 小时过期)
  5. token 传到前端,tokenStore.setToken(result.data) 存入 Pinia(并持久化到 localStorage,key 为 elder-admin-token),然后 router.push('/') 跳转首页
  6. 首页路由守卫拦截 → 请求 userInfo 接口 → 后端从 token 解析出 id 查库,返回用户信息 + 菜单树 + 按钮权限
  7. 之后每次请求,axios 请求拦截器自动在 Authorization 头带上 token;后端 LoginInterceptor 验签,失败返回 401,前端收到 401 清 token 踢回登录页

token 校验链路:

登录成功拿 token → Pinia + localStorage 持久化(刷新不丢失)
     ↓
axios 请求拦截器:headers.Authorization = token
     ↓
后端 LoginInterceptor:JwtUtil.parseToken 验签验过期
     ↓                       ↓
   通过→放行 Controller    失败→401→前端踢回 /login

手机端登录(/app/elders/login)流程完全相同,只是查的是 Elder 表(老人姓名即账号),登录成功当场调 userInfo() 拉老人信息再跳转。两端 token store 用不同 localStorage key,防止同域名下互相覆盖。

注册/找回密码:注册校验用户名、手机号唯一后创建账号;忘记密码按手机号找到用户直接改密(TODO:后期改邮箱验证)。


二、权限模块(RBAC)

功能:角色管理、权限(菜单/按钮)管理、给角色分配权限、给用户分配角色。

五张表:user → user_role → role → role_permission → permission(permission 分三类:0 目录 / 1 菜单带路由 / 2 按钮带权限值如 user:add)。

实现流程:

  1. 登录后 userInfo 接口按 userId 三表关联查出全部权限
  2. type=2 的权限值进 btnList → 前端 hasBtnPermission('user:add') 控制按钮显隐
  3. type=0/1 递归组装成菜单树 routerList → 前端动态生成左侧菜单,并做路径级鉴权(手输 URL 无权限会被拦回首页)
  4. 分配权限/角色的接口统一”先删旧关联再插新关联“全量覆盖

三、用户管理(后台)

功能:用户增删改查、条件分页、批量删除、Excel 导入导出、分配角色、重置密码。

实现流程:

  • 列表:?page=&limit= + Query 对象(name/email 模糊、时间区间)走 MyBatis-Plus 分页插件
  • Excel 导出:EasyExcel 写响应流,前端 blob 接收下载;导入:监听器逐行读逐行入库
  • 重置密码:从 token 解析本人 id → 校验旧密码 → 更新新密码
  • 分配护工下拉:listByRole?roleCode=HUGONG 按角色编码查该角色下的用户

四、老人管理

功能:老人档案增删改查(照片、富文本备注、Excel 导入导出)、标签管理、给老人打标签。老人同时是手机端登录账号。

实现流程:

  • 状态:0禁用/1启用/2请假/3退住中/4入住中/5已退住
  • 标签分配:先删后插全量覆盖;列表支持多标签 AND 筛选(老人必须同时拥有所选全部标签)
  • 查询结果批量回填每条老人的 tagList,避免循环查库(N+1 问题)
  • 标签编码唯一,冲突捕获 DuplicateKeyException 返回友好提示

五、客户管理(客户/合同/附件)

业务主线:录入客户(意向) → 关联老人 → 签订合同 → 合同生效(入住)。

功能:客户列表(来源、状态字典)、客户分配老人、合同管理、合同附件上传预览。

实现流程:

  • 绑定方向是老人挂客户:分配老人 = 事务里先清掉未勾选老人的 customer_id,再给勾选的老人设置,全量替换
  • 合同自动回填客户:保存合同时强制 customerId = elder.customerId,客户由老人唯一确定,不信任前端传值
  • 级联保护:客户名下还有老人或合同时拒绝删除,防孤儿数据
  • 合同状态:1草稿/2待签署/3生效中/4到期/5终止/6作废
  • 附件传 OSS 存 URL;预览走后端代理(见公共功能)

六、护理管理(等级/项目/计划/任务)

功能:护理等级、护理项目、护理计划(给老人定周期性护理方案)、护理任务(护工执行打卡)。

实现流程(计划→任务引擎):

  1. 计划明细指定每个项目的时间、周期(0每天/1每周/2每月)、频次
  2. 保存计划时一次性物化生成任务:遍历起止日期,按周期判定执行日(每周=距开始日%7==0,每月=同日号),每个执行日按频次生成 N 条任务;不是定时任务
  3. 任务快照项目名、护工、时间,状态 0待执行/1已完成/2已跳过
  4. 删除计划级联删明细和任务
  5. 护工在任务页打卡执行:填实际时间、结果(如”血压120/80″)、传打卡照片

护工数据隔离:任务列表接口解析 token,判断角色是护工(HUGONG)就服务端强制覆盖查询条件为只看自己的任务,前端传什么都无效。


七、预约管理(项目/计划/任务)

功能:预约项目维护、预约计划(管理员创建 + 公开页免登录自助提交)、分配护工、任务执行打卡。

实现流程:

  • 状态机:自助提交强制 status=0待确认, source=1自助 → 待确认不生成任务 → 管理员 assign/{id} 分配护工,0→1 进行中时才生成任务 → 取消则删任务
  • 管理员直接创建计划时若选了护工则直接确认并生成任务
  • 修改计划:删旧明细和旧任务后重建
  • 公开接口 submit、public-list 在拦截器白名单里,免登录可访问
  • 其余与护理模块的任务引擎完全同构

八、体检管理(项目/套餐/记录)

功能:体检项目维护、体检套餐(穿梭框分配项目)、手机端预约套餐、后台到检签到、逐项录结果、完成出报告。

实现流程:

  • 套餐价格 = 所含项目价格之和,分配项目时自动重算
  • 状态机:手机端提交 0待体检 → 到检签到 1体检中 → 完成体检 2已完成;取消 3已取消
  • 提交时做价格快照(套餐后改价不影响历史订单);明细做 itemName 快照(项目改名不污染历史)
  • 录结果时数值型项目按参考范围自动判定异常,覆盖前端选择;完成时未录的明细统一标”未完成”
  • 手机端报告:本人 + 已完成双重校验后才返回

九、手机端功能(ui-app,老人使用)

功能:登录、首页健康数据、浏览体检套餐并预约、上门服务目录与预约、我的预约(体检+服务合并列表,可取消)、我的合同及附件预览、体检报告、AI 助手、个人中心(资料/改密/头像)。

实现流程:

  • Controller 层独立(/app/),Service 层完全复用后台的**
  • 所有数据隔离靠”从 token 解析 elderId + 只操作本人数据”:查合同先验合同属于本人,查报告验本人+已完成
  • 我的预约是三源合并:体检记录 + 已确认服务任务 + 待确认服务计划(用 5 表示待确认),按日期倒序展示
  • 取消预约按 type 区分:体检取消体检记录,服务仅可取消本人待确认计划
  • 预约提交/取消后置 store 里的 dirty 脏标记,列表页据此重新拉数据

十、AI 助手(康养小智)

功能:手机端聊天窗口,健康咨询,可查老人自己的体检报告。

实现流程:

  1. DeepSeek ChatClient + 系统提示词(紧急情况提示就医、不替代医生等规则)
  2. 会话记忆以 token 里的老人 id 作为 conversationId,按老人隔离
  3. 挂了三个工具(Function Calling):查本人档案、最近报告、历史报告——工具底层复用”本人+已完成”校验过的接口,AI 也越不了权
  4. 回复走 SSE 流式:后端返回 Flux 流,前端用原生 fetch 逐块读取渲染打字机效果,[END] 为结束标记,Markdown 渲染 + DOMPurify 防注入
  5. 离开页面自动中断未完成的请求

十一、公共功能

文件上传:统一 POST /upload,UUID 重命名后传阿里云 OSS,返回 URL 由前端存库。admin 用 el-upload(手动带 Authorization 头),app 用 van-uploader。

OSS 读取代理:GET /oss/get?url= 后端读取 OSS 对象流式回写(inline 内联预览),绕过匿名直链强制下载的问题,也不暴露 OSS 地址。admin 和 app 各有一个代理 Controller。

首页图表(后台):4 张统计卡片(老人/计划/待执行/已完成)+ 近 7 日新增面积图、完成柱状图、状态环形图,数据通过多次分页查询取 total 聚合。

Excel 导入导出:用户、老人两个模块支持,导出 blob 下载,导入逐行读逐行入库。


十二、横切机制速查

机制 做法
统一响应 Result:code(1成功/0失败) + msg + data,前端拦截器统一判
全局异常 业务异常 ServiceException 抛出 → 全局处理器转 Result.error(msg)
登录校验 LoginInterceptor 拦 /**,白名单放行:两个 login、register、forgetPassword、公开预约 2 个、公开体检套餐 2 个
分页 ?page=&limit= 统一入参,MyBatis-Plus 分页插件;复杂 join 写 XML
逻辑删除 deleted 字段 @TableLogic,查询自动过滤
自动填充 createTime/updateTime 由 MetaObjectHandler 自动写
Long 精度 全局 Long→String 序列化,防前端 JS 丢精度

十三、通用设计套路(各模块反复出现)

  1. 不信任前端:自助提交强制覆盖 status/source/elderId,更新只接受白名单字段
  2. 关联分配先删后插全量覆盖(角色/权限/标签/老人/套餐项目五处同款)
  3. 快照设计:价格快照、项目名快照,历史数据不受主数据修改影响
  4. 主子表级联:删计划级联删明细+任务;客户反向禁止删除
  5. 登录定义的三种模式贯穿全项目:先查后比、不信任前端、token 里的 id 是唯一身份凭证

十四、已知问题

  1. ui-admin/src/utils/request.js:35:401 分支用了未 import 的 router,token 过期时会报错而非跳转(ui-app 版本正常)
  2. Authorization 头为裸 token,无 Bearer 前缀
  3. 两端登录页预填了测试账号密码,上线前需删除
  4. JWT 密钥硬编码 "dxk",密码明文存储,生产环境需改为环境变量 + 哈希
  5. 后端接口层无 RBAC 校验,权限只在前端菜单/按钮层面
上一篇
下一篇