# card_demo 项目指南 > 本文件面向 AI 编程助手。项目主要使用中文进行文档和注释编写,代码标识符采用中文拼音或英文混合风格。 --- ## 项目概述 `card_demo` 是一个面向**甘肃省中医院**的 AI 智慧医疗导诊演示系统,包含: 1. **`medical-card-demo/`** —— 核心 Web 应用,基于 SpringBoot + Vue 的卡片式对话导诊与挂号系统。 2. **`RobotSample-main/`** —— 猎户星空(Orion Star)机器人 Android SDK 示例工程,用于在豹小秘系列机器人上运行原生 APK,实现导航、语音、视觉等硬件能力。 3. **根目录技术文档** —— 包含猎户星空 API 参考手册、仿鸿蒙机器人系统技术方案、合作分析报告等。 项目总体目标是:在机器人终端上部署智慧医疗导诊系统,实现“语音/触屏对话 → AI 导诊推荐 → 机器人带路导航”的完整闭环。 --- ## 技术栈 ### medical-card-demo(Web 应用) | 层级 | 技术 | |------|------| | 后端 | Spring Boot 3.2、Java 17、Maven 3.6+ | | AI 接入 | 阿里云百炼(DashScope)qwen-turbo / qwen-vl-plus | | 前端 | Vue 3.3、Vue CLI 5、Pinia 2、Axios | | 其他 | ZXing(二维码生成)、Lombok、SSE 流式响应 | ### RobotSample-main(机器人 APK) | 层级 | 技术 | |------|------| | 平台 | Android 9.0(API 28)、RobotOS | | 构建 | Gradle 5.6.4、Android Gradle Plugin 3.6.1 | | 语言 | Java 8 | | SDK | 猎户星空 `robotservice.jar` | --- ## 项目结构 ``` card_demo/ ├── medical-card-demo/ # 医疗卡片挂号演示系统 │ ├── backend/ │ │ ├── pom.xml # Maven 构建配置 │ │ ├── startup.sh # 一键构建启动脚本 │ │ ├── src/main/java/com/medical/demo/ │ │ │ ├── MedicalCardDemoApplication.java │ │ │ ├── config/ # WebConfig(CORS 等) │ │ │ ├── controller/ # ChatController、ReportAnalysisController │ │ │ ├── dto/ # 数据传输对象(ChatRequestDTO、DepartmentDTO 等) │ │ │ └── service/ # 业务逻辑层 │ │ │ ├── ChatService.java # 主流程编排 │ │ │ ├── IntentRecognitionService.java # 意图识别 │ │ │ ├── DepartmentRecommendationService.java │ │ │ ├── DoctorScheduleService.java │ │ │ ├── AppointmentService.java │ │ │ ├── IDCardOCRService.java # 身份证 OCR(VL 模型) │ │ │ ├── ReportAnalysisService.java # 检验/检查报告解读 │ │ │ ├── TongueDiagnosisService.java # 中医舌诊 │ │ │ ├── VoiceToTextService.java # 语音转文字 │ │ │ ├── FAQService.java # 常见问题匹配 │ │ │ └── ... │ │ └── src/main/resources/ │ │ ├── application.yml # 服务端配置(含百炼 API Key) │ │ └── static/ # 前端构建产物(由 Maven 自动复制) │ ├── frontend/ │ │ ├── package.json # npm 配置 │ │ ├── vue.config.js # Vue CLI 配置、代理、页面标题 │ │ └── src/ │ │ ├── main.js # Vue 应用入口(Pinia) │ │ ├── App.vue # 根组件(仅挂载 ChatInterface) │ │ ├── api/chat.js # 前端 API 封装(SSE + axios) │ │ └── components/ │ │ ├── ChatInterface.vue │ │ └── cards/ # 各类卡片组件 │ ├── docs/ │ │ └── 省中导诊台.txt # FAQ 问答语料(问题+回答格式) │ ├── CALL_FLOW.md # 完整调用流程与架构图 │ ├── CONVERSATION_UPGRADE.md # 对话式交互改造说明 │ ├── FAQ_TEST_CASES.md # FAQ 批量测试用例 │ └── README.md # 项目主文档 │ ├── RobotSample-main/ # 猎户星空机器人 Android 示例 │ ├── build.gradle # 顶层 Gradle 配置 │ ├── settings.gradle # 仅包含 ':app' │ └── app/ │ ├── build.gradle # App 模块配置(applicationId: com.ainirobot.robotos) │ ├── libs/robotservice.jar # 猎户星空 SDK │ └── src/main/java/com/ainirobot/robotos/ │ ├── MainActivity.java │ ├── application/ # RobotOSApplication、SpeechCallback、ModuleCallback │ ├── fragment/ # 各业务场景 Fragment │ ├── view/ # 公共自定义 View │ └── maputils/ # 地图/定位工具类 │ ├── 仿鸿蒙机器人系统技术方案.md ├── 猎户星空API完整参考手册.md ├── 猎户星空合作分析报告.md └── 猎户星空合作分析报告_详细版.md ``` --- ## 构建与运行 ### 环境要求 - Java 17+ - Maven 3.6+ - Node.js 16+ - Android 开发环境(如需编译 RobotSample) ### medical-card-demo 一键启动(推荐) ```bash cd medical-card-demo/backend ./startup.sh ``` 该脚本会依次完成: 1. 检查 `java`、`mvn`、`node` 环境; 2. 构建后端 `mvn clean package -DskipTests`; 3. 前端 `npm install && npm run build`; 4. 将 `frontend/dist/` 复制到 `backend/src/main/resources/static/`; 5. 重新打包并启动 SpringBoot(端口 `3380`); 6. 最后启动前端开发服务器。 访问地址:`http://localhost:3380` ### 手动启动(前后端分离开发) ```bash # 终端1:后端 cd medical-card-demo/backend mvn spring-boot:run # 默认端口 8080(application.yml) # 生产/一键脚本通常期望 3380 # 终端2:前端 cd medical-card-demo/frontend npm install npm run serve # 端口 8080,代理 /api -> localhost:3380 ``` ### 打包部署 ```bash cd medical-card-demo/frontend npm install && npm run build cd ../backend mvn clean package java -jar target/medical-card-demo-1.0.0.jar ``` ### RobotSample-main 编译 ```bash cd RobotSample-main ./gradlew assembleDebug ``` > **注意**:必须在机器人屏幕上手动点击启动 APK,不能通过 IDE 的 Debug 按钮运行,否则无法获取 API 权限。 --- ## 核心接口与流程 ### REST API(SSE 流式响应) 所有聊天相关接口均返回 `text/event-stream`,前端通过 `handleSSEStream()` 解析。 | 接口 | 路径 | 说明 | |------|------|------| | 发送消息 | `POST /api/v1/chat/messages` | 意图识别 → 功能路由 | | 选择科室 | `POST /api/v1/chat/select-department` | 返回医生排班卡片 | | 选择医生 | `POST /api/v1/chat/select-doctor` | 返回具体排班时段 | | 提交挂号 | `POST /api/v1/chat/appointment` | 返回挂号成功卡片 | | 身份证 OCR | `POST /api/v1/chat/idcard-ocr` | VL 模型识别身份证信息 | | 提交建档 | `POST /api/v1/chat/record` | 保存患者档案 | | 语音转文字 | `POST /api/v1/chat/audio` | 上传音频 Blob | | 舌象校验 | `POST /api/v1/chat/check-tongue-image` | 判断是否为有效舌象照片 | | 舌诊分析 | `POST /api/v1/chat/ai-diagnosis` | 根据舌象+主诉生成报告 | | 报告解读 | `POST /api/v1/chat/report-analysis` | VL 模型解读检验/检查报告 | | 获取日期 | `GET /api/v1/chat/available-dates` | 返回今天/明天/后天 | ### 主业务流程 1. **用户输入** → `KeywordExtractionService.extractKeywords()` 提取意图; 2. **意图路由** → `ChatService` 根据意图分发到挂号/建档/报告解读/舌诊/FAQ; 3. **挂号流程** → 如需建档先引导 `IDCardOCRService` → 推荐科室 → 选择医生/日期/时段 → 生成二维码; 4. **FAQ 流程** → `FAQService` 读取 `docs/省中导诊台.txt`,按关键词覆盖率 / Jaccard 相似度匹配; 5. **报告解读** → `ReportAnalysisService` 调用 `qwen-vl-plus` 分析图片并返回 Markdown; 6. **舌诊** → `TongueDiagnosisService` 校验舌象合法性后生成中医诊断报告。 --- ## 代码风格与约定 ### Java 后端 - 包名:`com.medical.demo` - DTO 使用 Lombok 注解(`@Data` 等),字段命名采用 camelCase; - Service 层以 `*Service.java` 命名,使用 `@Service` + `@Autowired` 注入; - Controller 统一加 `@CrossOrigin(origins = "*")`; - 日志使用 `lombok.extern.slf4j.Slf4j`; - 所有流式输出通过 `SseEmitter` 推送 JSON 事件,格式示例: ```json { "type": "text", "content": "..." } { "type": "card", "cardType": "department-selection", "data": { ... } } { "type": "message_end" } ``` ### Vue 前端 - 单文件组件(SFC),Options API 风格; - API 统一封装在 `src/api/chat.js`; - 组件名采用 PascalCase(如 `DepartmentSelectionCard.vue`); - 静态资源放在 `public/` 或 `src/assets/`; - 页面标题在 `vue.config.js` 的 `chainWebpack` 中配置为 `"甘肃省中医院"`。 --- ## 测试策略 - **单元测试**:后端依赖 `spring-boot-starter-test`,但当前没有大量覆盖的单元测试类; - **集成/手工测试**:以 `FAQ_TEST_CASES.md` 和 `CALL_FLOW.md` 作为测试依据; - **FAQ 批量验证**:文档中提供了 `curl` 示例和 Bash 批量脚本,可直接运行验证; - **前端**:无自动化 E2E 测试,依赖手动在 Chrome 移动端模拟器中演示。 --- ## 安全注意事项 1. **硬编码 API Key**:`medical-card-demo/backend/src/main/resources/application.yml` 中硬编码了阿里云百炼 API Key(`bailian.api-key`)。**严禁提交到公开仓库**,生产环境应改为环境变量或配置中心注入。 2. **CORS 全开放**:`application.yml` 和 `WebConfig` 中 `allowed-origins: "*"`,生产环境需收紧为具体域名。 3. **数据存储**:当前所有会话数据、患者档案均保存在内存 `ConcurrentHashMap` 中,重启后数据丢失,且存在并发安全和数据持久化风险。 4. **二维码为演示用途**:挂号成功页生成的二维码无法真实支付。 --- ## 开发提示 - 如需修改 FAQ 内容,直接编辑 `medical-card-demo/docs/省中导诊台.txt`,格式固定为: ``` 问题:xxx? 回答:xxx。 ``` - 如需调整前端页面标题或代理端口,修改 `medical-card-demo/frontend/vue.config.js`。 - 后端端口在 `application.yml` 中设为 `8080`,但 `startup.sh` 和演示环境通常使用 `3380`,注意保持一致。 - 机器人 APK(RobotSample)与 Web 应用通过 **JSBridge** 方案进行通信(详见 `仿鸿蒙机器人系统技术方案.md`),前端点击“带我去”后触发机器人导航。