Skip to content

Latest commit

 

History

History
1312 lines (1081 loc) · 41.3 KB

File metadata and controls

1312 lines (1081 loc) · 41.3 KB

安心诊聊平台(AXZL)系统设计文档

1 引言

1.1 编写目的

本文档是安心诊聊平台(AXZL)的系统设计文档,详细描述系统的总体架构、模块设计、数据库设计、接口设计和关键技术实现方案。本文档是开发人员进行编码实现的主要依据,也是后期系统维护和扩展的参考资料。

1.2 设计原则

  1. 模块化原则:采用Maven多模块架构,各模块职责单一,依赖关系清晰。
  2. 分层架构原则:严格遵循Controller → Service → Mapper三层架构,禁止跨层调用。
  3. 开闭原则:AI模型配置存储在数据库中,新增模型无需修改代码。
  4. 安全性原则:无状态认证、密码加密、XSS防护、接口限流等多层安全机制。
  5. 可扩展原则:RAG流程各环节可独立替换(向量库、嵌入模型、大语言模型)。

2 总体架构设计

2.1 系统架构图

graph TB
    subgraph 用户层
        Admin["管理端 (Admin)<br/>Vue3 + Element Plus"]
        Patient["患者端 (Patient)<br/>Vue3 + 自定义UI"]
    end

    subgraph axzl-admin["axzl-admin (Web入口层)"]
        C1["ConsultationController"]
        C2["KnowledgeController"]
        C3["ProfileController"]
        C4["MedicationController"]
        C5["AIModelConfigController"]
        C6["SysLoginController / SysUserController"]
    end

    subgraph axzl-biz["axzl-biz (AI业务层)"]
        S1["AiConsultationService<br/>(RAG Pipeline)"]
        S2["DocumentProcessorService<br/>(异步向量化)"]
        S3["KnowledgeImportService<br/>(批量导入)"]
        S4["SpringAIClientFactory<br/>(模型工厂)"]
        S5["MedicationService"]
        S6["UserProfileService"]
    end

    subgraph axzl-framework["axzl-framework (框架层)"]
        F1["TokenService (JWT管理)"]
        F2["SysLoginService (登录流程)"]
        F3["JwtAuthenticationTokenFilter"]
        F4["PermissionService (权限校验)"]
        F5["LogAspect / DataScopeAspect"]
        F6["RateLimiterAspect / RepeatSubmit"]
    end

    subgraph axzl-system["axzl-system (系统领域层)"]
        SY1["SysUserService / SysRoleService"]
        SY2["SysMenuService / SysDictService"]
        SY3["MyBatis Mapper + XML"]
    end

    subgraph axzl-common["axzl-common (通用层)"]
        CO1["BaseController / AjaxResult"]
        CO2["SecurityUtils / RedisCache"]
        CO3["@Log / @Anonymous / @RateLimiter"]
        CO4["BaseEntity / ExcelUtil"]
    end

    subgraph 外部服务层
        MySQL["MySQL 8<br/>:3306"]
        Redis["Redis 7<br/>:6379"]
        Milvus["Milvus<br/>:19530"]
        DeepSeek["DeepSeek API"]
        BGE["BGE Embedding<br/>:8718"]
    end

    Admin -->|"HTTP/HTTPS + SSE"| C1
    Admin -->|"HTTP/HTTPS"| C2
    Patient -->|"HTTP/HTTPS + SSE"| C1
    Patient -->|"HTTP/HTTPS"| C3

    C1 --> S1
    C2 --> S2
    C3 --> S6
    C4 --> S5
    C5 --> S4

    S1 --> F1
    S2 --> F3
    S5 --> F4

    F1 --> SY1
    F2 --> SY1
    F4 --> SY2

    SY1 --> CO1
    SY2 --> CO2
    SY3 --> CO4

    S1 -->|"向量检索"| Milvus
    S1 -->|"LLM调用"| DeepSeek
    S2 -->|"文本向量化"| BGE
    S2 -->|"向量写入"| Milvus
    axzl-admin --> MySQL
    axzl-admin --> Redis
Loading

2.2 模块依赖关系

graph TD
    A["axzl-admin<br/>Web入口,Controller层"] --> B["axzl-framework<br/>Security, JWT, AOP"]
    A --> D["axzl-biz<br/>AI业务,RAG,知识库"]
    B --> C["axzl-system<br/>User/Role/Menu/Dict"]
    B --> E["axzl-common<br/>工具,基础类,注解"]
    C --> E
    D --> E

    style A fill:#409EFF,color:#fff
    style B fill:#67C23A,color:#fff
    style C fill:#E6A23C,color:#fff
    style D fill:#F56C6C,color:#fff
    style E fill:#909399,color:#fff
Loading

各模块职责:

模块 职责 关键包
axzl-admin Web入口,Controller层,应用启动配置 com.axzl.web.controller
axzl-biz AI业务逻辑,RAG流程,知识库,健康档案 com.axzl.biz.service
axzl-framework Spring Security,JWT,AOP切面,核心服务 com.axzl.framework
axzl-system 系统管理领域(用户/角色/菜单/字典) com.axzl.system
axzl-common 通用工具,基础类,注解,枚举,Redis com.axzl.common

2.3 技术选型

层次 技术 版本 选型理由
后端框架 Spring Boot 4.0.3 Java生态最成熟的Web框架
AI框架 Spring AI 2.0.0-M3 Spring官方AI集成框架,统一API
ORM MyBatis-Plus 3.5.16 兼容MyBatis原生,提供便捷CRUD
连接池 Druid 1.2.28 阿里巴巴开源,支持监控和SQL防火墙
缓存 Redis (Lettuce) 7.x 高性能内存缓存,支持集群
向量库 Milvus 2.x 开源向量数据库,支持多种索引
前端框架 Vue 3 + Vite 6 3.x / 6.x 响应式前端框架,快速构建工具
UI组件库 Element Plus 2.x Vue 3生态最成熟的UI库
API文档 Knife4j (Swagger) 4.4.0 增强版Swagger UI
容器化 Docker Compose - 一键部署所有依赖服务

3 系统功能结构与建模

3.1 系统功能结构图

graph TB
    A["安心诊聊平台 AXZL"] --> B["智能问诊模块"]
    A --> C["知识库管理模块"]
    A --> E["健康档案管理模块"]
    A --> F["AI模型配置模块"]
    A --> M["用药提醒模块"]
    A --> G["系统管理模块"]
    A --> H["系统监控模块"]
    A --> I["通用服务模块"]

    B --> B1["SSE流式对话"]
    B --> B2["同步AI问诊"]
    B --> B3["问诊历史管理"]
    B --> B4["会话管理"]
    B --> B5["满意度评价"]

    C --> C1["知识条目管理"]
    C --> C2["文档上传处理"]
    C --> C3["语义向量检索"]
    C --> C4["异步向量化"]
    C --> C5["文档重新处理"]

    E --> E1["患者档案维护"]
    E --> E2["档案Excel导入导出"]
    E --> E3["我的健康档案"]

    F --> F1["模型CRUD"]
    F --> FM2["默认模型切换"]
    F --> F3["多Provider支持"]

    M --> M1["用药管理"]
    M --> M2["用药打卡"]
    M --> M3["今日提醒"]
    M --> M4["管理端查询"]

    G --> G1["用户管理"]
    G --> G2["角色管理"]
    G --> G3["菜单权限管理"]
    G --> G4["字典管理"]
    G --> G5["参数配置"]
    G --> G6["个人中心"]

    H --> H1["在线用户监控"]
    H --> H2["操作日志"]
    H --> H3["登录日志"]
    H --> H4["缓存监控"]
    H --> H5["服务器监控"]
    H --> H6["SQL监控"]

    I --> I1["验证码生成"]
    I --> I2["文件上传下载"]
Loading

3.2 系统用例图

3.2.1 患者角色用例图

graph LR
    subgraph 患者端
        U(("患者"))

        U --> UC1["用户登录/注册"]
        U --> UC2["AI智能问诊"]
        U --> UC3["查看问诊历史"]
        U --> UC4["管理问诊会话"]
        U --> UC5["评价问诊满意度"]
        U --> UC6["查看健康档案"]
        U --> UC7["编辑健康档案"]
        U --> UC8["修改个人信息"]
        U --> UC9["用药提醒管理"]
    end
Loading

3.2.2 管理员角色用例图

graph LR
    subgraph 管理端
        A(("管理员"))

        A --> AC1["用户管理"]
        A --> AC2["角色权限管理"]
        A --> AC3["菜单管理"]
        A --> AC4["字典管理"]
        A --> AC5["系统参数配置"]
        A --> AC6["问诊会话管理"]
        A --> AC7["知识库管理"]
        A --> AC8["文档管理"]
        A --> AC9["健康档案管理"]
        A --> AC10["AI模型配置"]
        A --> AC11["在线用户监控"]
        A --> AC12["日志查看"]
        A --> AC13["缓存管理"]
        A --> AC14["服务器监控"]
    end
Loading

3.2.3 系统交互用例总图

graph TB
    P(("患者")) --> P1["AI智能问诊"]
    P --> P2["健康档案管理"]
    P --> P3["用药提醒管理"]
    P --> P4["知识文档上传"]

    M(("管理员")) --> M1["系统管理"]
    M --> M2["业务管理"]
    M --> M3["系统监控"]
    M --> M4["AI模型配置"]

    subgraph "核心业务"
        P1 -->|"SSE流式对话"| RAG["RAG检索增强生成"]
        RAG -->|"向量检索"| MV["Milvus向量库"]
        RAG -->|"文本生成"| DS["DeepSeek API"]
        P4 -->|"异步向量化"| MV
    end

    subgraph "系统基础设施"
        M1 --> DB["MySQL数据库"]
        M3 --> RD["Redis缓存"]
    end
Loading

3.3 核心业务流程图

3.3.1 用户登录认证流程

flowchart TD
    A([用户访问系统]) --> B{是否已登录?}
    B -->|是| C[获取Token]
    B -->|否| D[跳转登录页]

    D --> E[输入用户名/密码/验证码]
    E --> F[提交登录请求]
    F --> G{验证码校验}
    G -->|失败| H[提示验证码错误]
    H --> D
    G -->|通过| I{用户存在性检查}
    I -->|不存在| J[提示用户不存在]
    I -->|存在| K{密码校验-BCrypt}
    K -->|失败| L{重试次数>=5?}
    L -->|是| M[锁定账户10分钟]
    L -->|否| N[密码错误计数+1]
    K -->|通过| O{账户状态检查}
    O -->|停用| P[提示账户已停用]
    O -->|正常| Q[生成JWT Token]
    Q --> R[存储Token到Redis]
    R --> S[返回Bearer Token]
    S --> T[前端存储Token到Cookie]
    T --> U[加载动态路由]
    U --> V([进入系统首页])
Loading

3.3.2 AI智能问诊流程(RAG)

flowchart TD
    A([患者输入症状描述]) --> B[创建/获取问诊会话]
    B --> C[保存用户消息到数据库]
    C --> D[文本向量化-Embedding]
    D --> E[Milvus相似度检索Top-5]
    E --> F{相似度>=0.6?}
    F -->|是| G[注入知识库检索结果]
    F -->|否| H[跳过知识库注入]
    G --> I[加载用户健康档案]
    H --> I
    I --> J[加载最近30条对话历史]
    J --> K[组装结构化Prompt]
    K --> L[调用DeepSeek API-SSE流式]
    L --> M[逐字推送SSE事件到前端]
    M --> N{流式输出完成?}
    N -->|否| M
    N -->|是| O[保存AI完整回复到数据库]
    O --> P[更新会话元数据]
    P --> Q([问诊完成])
Loading

3.3.3 文档上传与向量化流程

flowchart TD
    A([管理员/患者上传文档]) --> B{文件格式校验}
    B -->|不支持| C[提示格式错误]
    B -->|支持| D[存储文件到本地]
    D --> E[返回文档记录-状态:待处理]
    E --> F["@Async 异步启动处理"]
    F --> G[更新状态:处理中]
    G --> H[提取文档文本内容]
    H --> I{文本长度<3000字符?}
    I -->|是| J[整体存储为单个知识块]
    I -->|否| K[按800字符分块-50字重叠]
    K --> L[批量向量化-每批20条]
    J --> L
    L --> M[EmbeddingModel.embed]
    M --> N[写入Milvus向量库]
    N --> O[写入MySQL知识元数据表]
    O --> P{处理成功?}
    P -->|是| Q[更新状态:已完成]
    P -->|否| R[更新状态:处理失败]
    Q --> S([文档可被RAG检索])
    R --> T[支持手动重新处理]
Loading

3.3.4 权限控制流程

flowchart TD
    A([HTTP请求到达]) --> B[JwtAuthenticationTokenFilter]
    B --> C{是否匿名接口?}
    C -->|是| D[直接放行]
    C -->|否| E[提取Authorization Header]
    E --> F{Token是否存在?}
    F -->|否| G[返回401未认证]
    F -->|是| H[JWT验签+Redis查询]
    H --> I{Token有效?}
    I -->|否| J[返回401 Token过期/无效]
    I -->|是| K{剩余时间<20分钟?}
    K -->|是| L[自动刷新Token]
    K -->|否| M[设置SecurityContext]
    L --> M
    M --> N[进入Controller方法]
    N --> O{是否有@PreAuthorize?}
    O -->|是| P{权限校验通过?}
    P -->|否| Q[返回403无权限]
    P -->|是| R[执行业务逻辑]
    O -->|否| R
Loading

4 核心模块设计

4.1 RAG智能问诊流程设计

RAG(Retrieval-Augmented Generation)是本系统的核心技术架构,实现了基于知识库检索增强的AI问诊。

4.1.1 流程时序图

sequenceDiagram                                                                                                                  
      actor U as 患者                                                                                                              
      participant FE as 前端                                                                                                       
      participant BE as 后端服务                                                                                                   
      participant Milvus as 向量数据库                                                                                             
      participant DB as MySQL                                                                                                      
      participant AI as DeepSeek大模型                                                                                             
                                                                                                                                   
      U->>FE: 描述症状,点击发送

      alt 新会话
          FE->>BE: 创建新会话
          BE->>DB: 保存会话记录
      end

      BE->>DB: 保存用户消息

      alt 开启知识库
          BE->>Milvus: 症状向量检索(返回Top5相关知识)
          Milvus-->>BE: 返回医学参考知识
      end

      BE->>DB: 查询用户健康档案
      BE->>DB: 查询历史对话(最近30条)

      BE->>BE: 组装提示词(参考知识+健康档案+历史对话+当前症状)

      BE->>AI: 发送提示词请求
      AI-->>BE: 流式返回AI回答

      BE-->>FE: 逐字推送回答(SSE流式)
      FE-->>U: 逐字显示回答(打字机效果)

      BE->>DB: 保存AI回答
      BE->>DB: 更新会话信息

Loading

4.1.2 Prompt组装策略

  flowchart TD
      A([患者发起问诊]) --> B{是否有会话ID?}
      B -- 否 --> C[创建新会话]
      B -- 是 --> D[加载已有会话]
      C --> E[保存用户消息到数据库]
      D --> E

      E --> F{是否开启知识库?}
      F -- 是 --> G[向量检索医学知识库]
      G --> H[获取相关参考知识Top5]
      H --> I[查询用户健康档案]
      F -- 否 --> I

      I --> J[查询历史对话记录]
      J --> K[组装完整提示词]

      K --> L[调用大模型生成回答]
      L --> M[流式返回AI回答]
      M --> N[前端逐字展示]

      N --> O[保存AI回答到数据库]
      O --> P[更新会话]
      P --> Q([问诊完成])

Loading

系统采用结构化Prompt模板,包含以下组成部分:

【系统角色设定】
你是一位专业的医疗健康顾问AI助手...

【知识库检索结果】(当useKnowledgeBase=true时注入)
以下是与患者问题相关的医学知识:
1. [知识标题]:[知识内容片段](相似度:0.92)
2. ...

【用户健康档案】(当用户有健康档案时注入)
患者基本信息:性别[男/女],年龄[X]岁,血型[X]
过敏史:[内容]
既往病史:[内容]
家族病史:[内容]
生活习惯:[内容]

【对话历史】(最近30条消息)
用户:...
AI:...
用户:...

【当前问题】
用户:[当前输入]

【回复要求】
请基于以上信息,给出专业、详细的健康建议...

4.1.3 向量检索参数

参数 值 说明
Top-K 5 返回最相似的5条知识
相似度阈值 0.6 余弦相似度低于0.6的结果不注入
向量维度 1024 BGE-large-zh-v1.5输出维度
索引类型 IVF_FLAT Milvus索引类型
距离度量 COSINE 余弦相似度

4.2 文档处理流程设计

4.2.1 处理流程

flowchart TD
    A["MultipartFile 文件上传"] --> B["存储到本地文件系统"]
    B --> C["@Async 异步启动处理"]
    C --> D["CustomDocumentReader<br/>提取文本内容<br/>(txt/docx/pdf/md/jsonl)"]
    D --> E{"文本长度 < 3000字符?"}
    E -->|是| F["整体存储为单个知识块"]
    E -->|否| G["按段落分块<br/>800字符/块,50字符重叠"]
    F --> H["EmbeddingModel.embed()<br/>批量向量化(每批20条)"]
    G --> H
    H --> I["写入 Milvus 向量库"]
    H --> J["写入 MySQL 元数据表"]
Loading

4.2.2 分块策略

文档大小 策略 块大小 重叠
< 3000字符 整体存储 - -
≥ 3000字符 按段落分块 800字符 50字符

4.3 动态AI模型管理设计

4.3.1 模型配置数据模型

biz_ai_model_config
├── provider (提供商标识: deepseek/openai/anthropic/localhost)
├── model_name (模型名称,唯一)
├── api_base_url (API基础URL)
├── api_key (VARBINARY加密存储)
├── model_type (text/embedding/image/audio)
├── temperature, max_tokens, top_p, top_k (模型参数)
├── frequency_penalty, presence_penalty (采样参数)
├── is_default (是否默认模型)
└── config_extra (JSON扩展配置)

4.3.2 客户端工厂模式

classDiagram
    class SpringAIClientFactory {
        <<interface>>
        +getChatClient(modelName) ChatClient
        +getEmbeddingModel(modelName) EmbeddingModel
        +getDefaultChatClient() ChatClient
        +getDefaultEmbeddingModel() EmbeddingModel
        +refreshCache() void
    }

    class SpringAIClientFactoryImpl {
        -chatClientCache: ConcurrentHashMap~String, ChatClient~
        -embeddingModelCache: ConcurrentHashMap~String, EmbeddingModel~
        +getChatClient(modelName) ChatClient
        +getEmbeddingModel(modelName) EmbeddingModel
        +getDefaultChatClient() ChatClient
        +getDefaultEmbeddingModel() EmbeddingModel
        +refreshCache() void
    }

    class ChatClient {
        <<Spring AI>>
        +prompt() PromptBuilder
    }

    class EmbeddingModel {
        <<Spring AI>>
        +embed(text) float[]
    }

    SpringAIClientFactory <|.. SpringAIClientFactoryImpl
    SpringAIClientFactoryImpl --> ChatClient : 创建/缓存
    SpringAIClientFactoryImpl --> EmbeddingModel : 创建/缓存
Loading

所有AI模型通过OpenAI兼容接口调用,统一使用spring-ai-starter-model-openai,不同Provider通过api_base_url区分:

  • DeepSeek: https://api.deepseek.com
  • OpenAI: https://api.openai.com/v1
  • Anthropic: https://api.anthropic.com/v1(通过OpenAI兼容代理)
  • 本地模型: http://localhost:8718

4.4 安全架构设计

4.4.1 认证流程

sequenceDiagram                                                                                                                  
      actor U as 用户                    
      participant FE as 前端                                                                                                       
      participant BE as 后端服务
      participant Redis as Redis                                                                                                   
      participant DB as 数据库                              

      U->>FE: 输入用户名、密码、验证码
      FE->>BE: 提交登录请求
      BE->>Redis: 校验验证码
      alt 验证码错误或过期
          BE-->>FE: 返回错误提示
          FE-->>U: 显示错误信息
      end

      BE->>DB: 查询用户信息
      DB-->>BE: 返回用户数据
      alt 用户不存在或已停用
          BE-->>FE: 返回错误提示
          FE-->>U: 显示错误信息
      end

      BE->>BE: 校验密码(BCrypt)
      alt 密码错误
          BE->>Redis: 记录失败次数
          alt 连续错误达上限
              BE-->>FE: 返回"账号已锁定"
              FE-->>U: 显示账号锁定
          else 未达上限
              BE-->>FE: 返回"密码错误"
              FE-->>U: 显示密码错误
          end
      end

      BE->>DB: 查询用户权限菜单
      BE->>Redis: 生成并存储登录凭证(TTL=30min)
      BE->>BE: 签发JWT令牌
      BE-->>FE: 返回JWT令牌
      FE->>FE: 保存令牌到Cookie
      FE-->>U: 登录成功,跳转首页

      Note over U,DB: === 后续业务请求 ===

      U->>FE: 访问业务页面
      FE->>BE: 请求携带JWT令牌
      BE->>Redis: 验证令牌有效性
      alt 令牌有效(剩余≤20min自动续期)
          BE-->>FE: 返回业务数据
          FE-->>U: 展示页面
      else 令牌无效或过期
          BE-->>FE: 返回401未授权
          FE-->>U: 跳转登录页
      end

Loading
flowchart TD
    A["用户登录请求"] --> B["CaptchaController<br/>验证码校验(可配置关闭)"]
    B --> C["SysLoginService.login()"]
    C --> D["1. 验证码校验"]
    D --> E["2. 用户存在性检查"]
    E --> F["3. 密码校验 (BCrypt)"]
    F --> F1["SysPasswordService"]
    F1 --> F2["Redis计数器<br/>login_password_limit:{username}"]
    F2 --> F3{"重试次数 >= 5?"}
    F3 -->|是| F4["锁定账户10分钟"]
    F3 -->|否| G["4. 账户状态检查"]
    G --> H["5. TokenService.createToken()"]
    H --> H1["生成UUID loginKey"]
    H1 --> H2["构建loginUser对象<br/>(userId, userName, deptId,<br/>token, loginTime, expireTime)"]
    H2 --> H3["JWT签名 (HS512)"]
    H3 --> H4["Redis存储<br/>login_tokens:{loginKey}"]
    H4 --> H5["返回 Bearer {token}"]
Loading

4.4.2 请求过滤链

flowchart TD
    A["HTTP Request"] --> B["JwtAuthenticationTokenFilter"]
    B --> B1["1. 从Header提取<br/>Authorization: Bearer {token}"]
    B1 --> B2["2. TokenService.parseToken(token)"]
    B2 --> B2a["JWT验签"]
    B2a --> B2b["Redis查询 loginUser"]
    B2b --> B2c["验证过期时间"]
    B2c --> B2d{"剩余 < 20分钟?"}
    B2d -->|是| B2e["自动刷新Token"]
    B2d -->|否| B3["3. 设置SecurityContext"]
    B2e --> B3
    B3 --> B4["4. filterChain.doFilter()"]
    B4 --> C["Spring Security Authorization"]
    C --> C1{"@PreAuthorize?"}
    C1 -->|有| C2{"权限校验通过?"}
    C2 -->|是| D["执行Controller方法"]
    C2 -->|否| E["返回403 无权限"]
    C1 -->|无/Anonymous| D
Loading

4.4.3 权限模型

graph TD
    U["用户 SysUser"] -->|"N:N"| UR["用户角色关联<br/>sys_user_role"]
    UR -->|"N:N"| R["角色 SysRole"]
    R -->|"N:N"| RM["角色菜单关联<br/>sys_role_menu"]
    RM -->|"N:1"| M["菜单 SysMenu"]
    M --> M1["目录 (menuType=M)<br/>一级导航"]
    M --> M2["菜单 (menuType=C)<br/>页面路由"]
    M --> M3["按钮 (menuType=F)<br/>权限标识 (perms)"]

    style U fill:#409EFF,color:#fff
    style R fill:#E6A23C,color:#fff
    style M fill:#67C23A,color:#fff
Loading

权限标识格式:模块:子模块:操作,例如:

  • system:user:list — 用户查询
  • biz:consultation:chat — 流式对话
  • biz:knowledge:add — 知识新增

4.5 双布局架构设计

系统前端采用双布局架构,管理端和患者端使用不同的Layout组件:

graph TB
    subgraph 前端路由
        Router["router/index.ts<br/>静态路由 + 动态路由加载"]
    end

    subgraph 管理端布局
        AdminLayout["layout/index.vue<br/>侧边栏 + 顶部导航 + 面包屑"]
        AdminLayout --> S1["views/system/<br/>用户/角色/菜单/字典管理"]
        AdminLayout --> S2["views/monitor/<br/>缓存/日志/服务器监控"]
        AdminLayout --> S3["views/biz/<br/>问诊/知识/文档/档案管理"]
    end

    subgraph 患者端布局
        PatientLayout["layout/PatientLayout.vue<br/>顶部标题栏 + 底部Tab导航"]
        PatientLayout --> P1["patient/consultation/<br/>智能问诊"]
        PatientLayout --> P2["patient/health/<br/>健康档案"]
        PatientLayout --> P3["patient/medication/<br/>用药提醒"]
        PatientLayout --> P4["patient/profile/<br/>个人信息"]
    end

    Router --> AdminLayout
    Router --> PatientLayout

    style AdminLayout fill:#409EFF,color:#fff
    style PatientLayout fill:#67C23A,color:#fff
Loading

路由分为静态路由(constantRoutes)和动态路由(从后端/getRouters接口获取):

  • 静态路由:登录、注册、401、404、管理端首页、个人中心、患者端所有页面
  • 动态路由:系统管理、系统监控、系统工具、业务管理(根据用户权限动态加载)

5 数据库设计

5.1 ER图(实体关系图)

erDiagram
    sys_user ||--o| biz_user_profile : "1:1 拥有"
    sys_user }|--|{ sys_user_role : "N:N"
    sys_user_role }|--|{ sys_role : "N:N"
    sys_role }|--|{ sys_role_menu : "N:N"
    sys_role_menu }|--|| sys_menu : "N:1"

    biz_chat_session ||--|{ biz_chat_message : "1:N"
    biz_chat_session }o--|| sys_user : "属于用户"

    biz_knowledge_meta }o--|| biz_document : "来源文档"
    biz_document }o--|| sys_user : "上传者"

    biz_medication ||--|{ biz_medication_log : "1:N"
    biz_medication }o--|| sys_user : "属于用户"

    biz_ai_model_config {
        bigint id PK
        varchar provider
        varchar model_name UK
        varchar api_base_url
        varbinary api_key
        varchar model_type
        tinyint is_default
    }

    sys_user {
        bigint user_id PK
        varchar user_name UK
        varchar nick_name
        varchar password
        char status
    }

    sys_role {
        bigint role_id PK
        varchar role_name
        varchar role_key
        char status
    }

    sys_menu {
        bigint menu_id PK
        varchar menu_name
        bigint parent_id
        char menu_type
        varchar perms
    }

    biz_chat_session {
        varchar session_id PK
        bigint user_id FK
        varchar title
        int message_count
        char status
    }

    biz_chat_message {
        bigint message_id PK
        varchar session_id FK
        varchar role
        text content
    }

    biz_user_profile {
        bigint profile_id PK
        bigint user_id FK
        date birthday
        varchar blood_type
        text allergy_history
        text medical_history
    }

    biz_knowledge_meta {
        bigint id PK
        text question
        varchar label
        varchar vector_id
        char vector_status
    }

    biz_document {
        bigint id PK
        varchar file_name
        varchar file_type
        int chunk_count
        char vector_status
    }
Loading

5.2 数据库表设计

5.2.1 系统基础表

用户信息表 (sys_user)

字段 类型 约束 说明
user_id BIGINT(20) PK, AUTO_INCREMENT 用户ID
user_name VARCHAR(30) NOT NULL, UNIQUE 用户账号
nick_name VARCHAR(30) NOT NULL 用户昵称
user_type VARCHAR(2) DEFAULT '00' 用户类型
email VARCHAR(50) DEFAULT '' 邮箱
phonenumber VARCHAR(11) DEFAULT '' 手机号
sex CHAR(1) DEFAULT '0' 性别(0男1女2未知)
avatar VARCHAR(100) DEFAULT '' 头像地址
password VARCHAR(100) NOT NULL BCrypt密码
status CHAR(1) DEFAULT '0' 状态(0正常1停用)
del_flag CHAR(1) DEFAULT '0' 删除标志(0存在2删除)
login_ip VARCHAR(128) DEFAULT '' 最后登录IP
login_date DATETIME 最后登录时间
pwd_update_date DATETIME 密码更新时间
create_by VARCHAR(64) DEFAULT '' 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) DEFAULT '' 更新者
update_time DATETIME 更新时间
remark VARCHAR(500) 备注

角色信息表 (sys_role)

字段 类型 约束 说明
role_id BIGINT(20) PK, AUTO_INCREMENT 角色ID
role_name VARCHAR(30) NOT NULL 角色名称
role_key VARCHAR(100) NOT NULL 角色标识
role_sort INT(4) NOT NULL 显示顺序
data_scope CHAR(1) DEFAULT '2' 数据范围
menu_check_strictly TINYINT(1) DEFAULT 1 菜单树关联显示
status CHAR(1) NOT NULL 状态
del_flag CHAR(1) DEFAULT '0' 删除标志

菜单权限表 (sys_menu)

字段 类型 约束 说明
menu_id BIGINT(20) PK, AUTO_INCREMENT 菜单ID
menu_name VARCHAR(50) NOT NULL 菜单名称
parent_id BIGINT(20) DEFAULT 0 父菜单ID
order_num INT(4) DEFAULT 0 显示顺序
path VARCHAR(200) DEFAULT '' 路由地址
component VARCHAR(255) 组件路径
menu_type CHAR(1) 类型(M目录C菜单F按钮)
perms VARCHAR(100) 权限标识
icon VARCHAR(100) DEFAULT '#' 菜单图标
visible CHAR(1) DEFAULT 0 是否显示
status CHAR(1) DEFAULT 0 状态

5.2.2 业务数据表

问诊会话表 (biz_chat_session)

字段 类型 约束 说明
session_id VARCHAR(64) PK 会话UUID
user_id BIGINT(20) NOT NULL, INDEX 用户ID
title VARCHAR(200) DEFAULT '' 会话标题
symptom_summary TEXT 症状摘要
ai_diagnosis TEXT AI诊断摘要
recommended_label VARCHAR(50) DEFAULT '' 推荐科室
message_count INT(11) DEFAULT 0 消息数量
satisfaction TINYINT(1) 满意度(1-5)
tokens_used INT(11) DEFAULT 0 Token消耗
last_message_time DATETIME 最后消息时间
status CHAR(1) DEFAULT '0' 状态(0进行中1已结束)
is_pinned TINYINT(1) DEFAULT 0 是否置顶
create_time DATETIME INDEX 创建时间
del_flag CHAR(1) DEFAULT '0' 删除标志

对话消息表 (biz_chat_message)

字段 类型 约束 说明
message_id BIGINT(20) PK, AUTO_INCREMENT 消息ID
session_id VARCHAR(64) NOT NULL, INDEX 会话ID
user_id BIGINT(20) NOT NULL 用户ID
role VARCHAR(20) NOT NULL 角色(user/assistant)
content TEXT NOT NULL 消息内容
retrieval_results JSON 向量检索结果(Top5)
create_time DATETIME INDEX 创建时间

用户健康档案表 (biz_user_profile)

字段 类型 约束 说明
profile_id BIGINT(20) PK, AUTO_INCREMENT 档案ID
user_id BIGINT(20) UNIQUE 用户ID
birthday DATE 出生日期
gender CHAR(1) DEFAULT '0' 性别
blood_type VARCHAR(10) DEFAULT '' 血型
height DECIMAL(5,1) 身高(cm)
weight DECIMAL(5,1) 体重(kg)
allergy_history TEXT 过敏史
medical_history TEXT 既往病史
family_history TEXT 家族病史
lifestyle TEXT 生活习惯

知识库元数据表 (biz_knowledge_meta)

字段 类型 约束 说明
id BIGINT(20) PK, AUTO_INCREMENT 知识ID
question TEXT NOT NULL 问题/文本块内容
answer TEXT 答案/补充内容
label VARCHAR(50) DEFAULT '', INDEX 分类标签
score INT(11) DEFAULT 0 评分
related_diseases VARCHAR(500) DEFAULT '' 关联疾病
vector_id VARCHAR(100) DEFAULT '', INDEX Milvus向量ID
vector_status CHAR(1) DEFAULT '0' 向量状态
source_type VARCHAR(20) DEFAULT 'qa', INDEX 来源类型(qa/doc)
source_id BIGINT(20) 来源文档ID
chunk_index INT(11) DEFAULT 0 分块序号

上传文档表 (biz_document)

字段 类型 约束 说明
id BIGINT(20) PK, AUTO_INCREMENT 文档ID
file_name VARCHAR(200) NOT NULL 原始文件名
file_type VARCHAR(20) NOT NULL 文件类型
file_size BIGINT(20) DEFAULT 0 文件大小(字节)
extracted_content LONGTEXT 提取的文本内容
chunk_count INT(11) DEFAULT 0 切分块数
vector_status CHAR(1) DEFAULT '0', INDEX 向量状态
upload_by BIGINT(20) NOT NULL, INDEX 上传用户ID

AI模型配置表 (biz_ai_model_config)

字段 类型 约束 说明
id BIGINT PK, AUTO_INCREMENT 主键ID
provider VARCHAR(50) NOT NULL, INDEX 提供商标识
model_name VARCHAR(150) NOT NULL, UNIQUE 模型名称
api_base_url VARCHAR(500) NOT NULL API基础URL
api_key VARBINARY(2048) NOT NULL API密钥(加密)
model_type VARCHAR(20) NOT NULL, INDEX 模型类型
temperature DECIMAL(3,2) DEFAULT 0.1 温度参数
max_tokens INT DEFAULT 4096 最大Token数
top_p DECIMAL(3,2) DEFAULT 0.3 Top-P参数
is_default TINYINT(1) DEFAULT 0 是否默认
config_extra JSON 扩展配置

用药提醒表 (biz_medication)

字段 类型 约束 说明
id BIGINT(20) PK, AUTO_INCREMENT 主键ID
user_id BIGINT(20) NOT NULL, INDEX 用户ID
drug_name VARCHAR(50) NOT NULL 药品名称
dosage VARCHAR(30) DEFAULT '' 剂量
frequency VARCHAR(20) DEFAULT 'daily' 频次(daily/twice/thrice/weekly/asNeeded)
reminder_times VARCHAR(200) DEFAULT '' 提醒时间(JSON数组)
start_date DATE 开始日期
end_date DATE 结束日期
notes VARCHAR(200) DEFAULT '' 用药备注
status CHAR(1) DEFAULT '0' 状态(0启用1停用)
del_flag CHAR(1) DEFAULT '0' 删除标志
create_time DATETIME 创建时间
update_time DATETIME 更新时间

用药打卡记录表 (biz_medication_log)

字段 类型 约束 说明
id BIGINT(20) PK, AUTO_INCREMENT 主键ID
medication_id BIGINT(20) NOT NULL, INDEX 用药ID
user_id BIGINT(20) NOT NULL, INDEX 用户ID
scheduled_time VARCHAR(10) 计划时间(HH:mm)
taken_time DATETIME 实际服药时间
status CHAR(1) DEFAULT '0' 状态(0已打卡1漏服)
create_time DATETIME 创建时间

5.3 索引设计

表名 索引名 字段 类型 用途
biz_chat_session idx_user_id user_id 普通 按用户查询会话
biz_chat_session idx_create_time create_time 普通 按时间排序
biz_chat_message idx_session_id session_id 普通 按会话查询消息
biz_chat_message idx_create_time create_time 普通 按时间排序
biz_knowledge_meta idx_vector_id vector_id 普通 向量ID查询
biz_knowledge_meta idx_label label 普通 按分类筛选
biz_knowledge_meta idx_source_type source_type 普通 按来源筛选
biz_document idx_upload_by upload_by 普通 按用户查询文档
biz_document idx_vector_status vector_status 普通 按状态筛选
biz_medication idx_user_id user_id 普通 按用户查询用药
biz_medication_log idx_medication_id medication_id 普通 按用药查询记录
biz_medication_log idx_user_date user_id, create_time 普通 按用户和日期查询
biz_ai_model_config uk_model_name model_name 唯一 模型名称唯一

6 接口设计

6.1 RESTful API规范

  • 基础路径:/api(开发环境通过Vite代理/dev-api)
  • 认证方式:Authorization: Bearer {jwt_token}
  • 响应格式:统一使用AjaxResult(HashMap子类)
{
  "code": 200,
  "msg": "操作成功",
  "data": { ... }
}
  • 分页响应:使用TableDataInfo
{
  "code": 200,
  "msg": "查询成功",
  "total": 100,
  "rows": [ ... ]
}

6.2 核心接口列表

6.2.1 认证接口

方法 路径 说明 认证
POST /login 用户登录 否
POST /register 用户注册 否
GET /getInfo 获取当前用户信息 是
GET /getRouters 获取动态路由菜单 是
GET /captchaImage 获取验证码 否

6.2.2 智能问诊接口

方法 路径 说明 认证
POST /biz/consultation/stream SSE流式问诊 是
POST /biz/consultation/chat 同步问诊 是
GET /biz/consultation/history 问诊历史 是
GET /biz/consultation/detail/{sessionId} 会话详情 是
PUT /biz/consultation/satisfaction/{sessionId} 满意度评价 是
PUT /biz/consultation/title/{sessionId} 重命名会话 是
PUT /biz/consultation/pin/{sessionId} 置顶会话 是
DELETE /biz/consultation/remove/{sessionId} 删除会话 是

6.2.3 知识库接口

方法 路径 说明 认证
POST /biz/knowledge/search 语义搜索 是
POST /biz/knowledge/document/upload 上传文档 是
GET /biz/knowledge/document/list 文档列表 是
POST /biz/knowledge/document/reprocess/{id} 重新处理 是

6.2.4 健康档案接口

方法 路径 说明 认证
GET /biz/profile/my 我的档案 是
POST /biz/profile/my 更新我的档案 是
POST /biz/profile/export 导出Excel 是
POST /biz/profile/importData 导入Excel 是

6.2.5 用药提醒接口

方法 路径 说明 认证
GET /biz/medication/my 我的用药列表 是
GET /biz/medication/my/today 今日用药提醒 是
POST /biz/medication/my 新增用药 是
PUT /biz/medication/my 修改用药 是
DELETE /biz/medication/my/{ids} 删除用药 是
POST /biz/medication/my/checkin 用药打卡 是
GET /biz/medication/my/logs 今日打卡记录 是
GET /biz/medication/list 用药列表(管理端) 是
DELETE /biz/medication/{ids} 删除用药(管理端) 是

7 关键技术实现

7.1 SSE流式对话实现

// Controller层
@GetMapping("/stream")
public SseEmitter chatStream(ChatRequest request) {
    SseEmitter emitter = new SseEmitter(0L); // 无超时
    // 委托给Service层处理
    aiConsultationService.chatStream(request, emitter);
    return emitter;
}

// Service层核心逻辑
public void chatStream(ChatRequest request, SseEmitter emitter) {
    Flux<String> flux = chatClient.prompt()
        .user(promptContent)
        .stream()
        .content();

    // 后台订阅者:即使前端断开,也能保存数据
    StringBuilder fullResponse = new StringBuilder();
    flux.subscribe(
        chunk -> {
            try {
                emitter.send(chunk);  // 推送给前端
                fullResponse.append(chunk);
            } catch (IOException e) {
                // 前端断开,继续接收
            }
        },
        error -> emitter.completeWithError(error),
        () -> {
            // 完成后保存AI回复到数据库
            saveAssistantMessage(sessionId, userId, fullResponse.toString());
            emitter.complete();
        }
    );
}

7.2 异步文档处理实现

@Async
public void processDocument(BizDocument document) {
    // 1. 更新状态为"处理中"
    document.setVectorStatus("1");
    documentMapper.updateById(document);

    try {
        // 2. 提取文本内容
        String content = customDocumentReader.read(filePath, fileType);

        // 3. 分块
        List<String> chunks = splitContent(content);

        // 4. 批量向量化
        for (int i = 0; i < chunks.size(); i += BATCH_SIZE) {
            List<String> batch = chunks.subList(i, Math.min(i + BATCH_SIZE, chunks.size()));
            List<float[]> embeddings = embeddingModel.embed(batch);

            // 5. 存入Milvus和MySQL
            for (int j = 0; j < batch.size(); j++) {
                saveToMilvus(embeddings.get(j), batch.get(j));
                saveKnowledgeMeta(batch.get(j), document.getId(), i + j);
            }
        }

        // 6. 更新状态为"已完成"
        document.setVectorStatus("2");
    } catch (Exception e) {
        document.setVectorStatus("3"); // 失败
    }
    documentMapper.updateById(document);
}

7.3 动态路由加载

// 前端路由守卫
router.beforeEach(async (to, from, next) => {
    const userStore = useUserStore();
    const permissionStore = usePermissionStore();

    if (userStore.token) {
        if (!permissionStore.isRoutesLoaded) {
            // 从后端获取动态路由
            const res = await getRouters();
            const asyncRoutes = filterAsyncRoutes(res.data);
            // 动态添加路由
            asyncRoutes.forEach(route => router.addRoute(route));
            permissionStore.setRoutes(asyncRoutes);
            next({ ...to, replace: true });
        } else {
            next();
        }
    } else {
        // 白名单页面直接放行
        if (whiteList.includes(to.path)) next();
        else next('/login');
    }
});

8 部署架构

8.1 Docker Compose部署

services:
  mysql:     # MySQL 8.0, port 3306
  redis:     # Redis 7, port 6379
  milvus:    # Milvus standalone, port 19530
  etcd:      # Milvus依赖
  minio:     # Milvus对象存储依赖
  attu:      # Milvus管理界面, port 8000
  bge-embedding: # BGE嵌入模型服务, port 8718

8.2 服务依赖关系

graph LR
    subgraph 外部API
        DeepSeek["DeepSeek API"]
    end

    subgraph Docker Compose
        MySQL["MySQL 8<br/>:3306"]
        Redis["Redis 7<br/>:6379"]
        Milvus["Milvus<br/>:19530"]
        Etcd["etcd"]
        MinIO["MinIO"]
        Attu["Attu<br/>:8000"]
        BGE["BGE Embedding<br/>:8718"]
    end

    subgraph 应用服务
        Admin["axzl-admin<br/>:8080"]
    end

    Admin -->|"JDBC"| MySQL
    Admin -->|"Lettuce"| Redis
    Admin -->|"gRPC"| Milvus
    Admin -->|"HTTP"| BGE
    Admin -->|"HTTPS"| DeepSeek
    Milvus --> Etcd
    Milvus --> MinIO
    Attu -->|"管理"| Milvus

    style Admin fill:#409EFF,color:#fff
    style DeepSeek fill:#F56C6C,color:#fff
    style Milvus fill:#67C23A,color:#fff
Loading

文档版本:v1.0 编写日期:2026年5月 编写人:项目开发团队