鸿蒙app 急救知识库(症状自检/紧急联系人设置)【华为云根技术】

举报
鱼弦 发表于 2025/12/26 11:07:54 2025/12/26
【摘要】 引言突发疾病或意外时,快速获取急救知识与联系紧急联系人至关重要。鸿蒙系统的分布式能力与实时响应特性,为急救知识库App提供了高效、可靠的开发基础,支持症状自检引导与紧急联系人快速触达,助力用户在危急时刻争取黄金救援时间。技术背景鸿蒙框架:基于Stage模型,@Entry/@Component构建UI,Ability管理生命周期,支持后台任务与通知推送。数据管理:急救知识以JSON文件预置,P...

引言

突发疾病或意外时,快速获取急救知识与联系紧急联系人至关重要。鸿蒙系统的分布式能力与实时响应特性,为急救知识库App提供了高效、可靠的开发基础,支持症状自检引导与紧急联系人快速触达,助力用户在危急时刻争取黄金救援时间。

技术背景

  • 鸿蒙框架:基于Stage模型,@Entry/@Component构建UI,Ability管理生命周期,支持后台任务与通知推送。
  • 数据管理:急救知识以JSON文件预置,Preferences存储紧急联系人,关系型数据库缓存用户搜索记录。
  • 交互能力:通过弹窗展示自检流程,电话拨打接口实现一键呼叫,语音播报增强盲操作友好性。

应用使用场景

  1. 日常学习:用户浏览常见急症(如中暑、烫伤)处理步骤,提前储备知识。
  2. 症状自检:出现不适时,按引导回答问题(如“是否发热?”“有无呕吐?”),获取疑似病症及急救建议。
  3. 紧急求助:一键触发预设联系人呼叫,或快速拨打120并发送位置信息。

核心特性

  • 智能症状自检:基于决策树算法,通过问答逐步缩小病症范围。
  • 紧急联系人管理:支持增删改查,一键拨号与短信通知。
  • 离线可用:急救知识本地存储,无网络时仍可访问。
  • 多模态交互:图文指引+语音播报,适配不同用户习惯。

原理流程图与原理解释

流程图

graph TD  
    A[用户打开App] --> B[首页:知识库/自检/联系人]  
    B --> C[症状自检:选择部位/输入症状]  
    C --> D[决策树问答引导]  
    D --> E[输出疑似病症与急救步骤]  
    B --> F[紧急联系人:设置/呼叫]  
    F --> G[调用电话API拨打/发短信]

原理解释

  1. 症状自检:预定义决策树(如“头痛”分支包含“伴随发热→感冒/脑炎”“伴呕吐→颅内压增高”),用户每回答一个问题,系统跳转至对应子节点,直至匹配病症。
  2. 联系人管理:通过Preferences存储联系人姓名与电话(键值对:contact_${index}{"name":"张三","phone":"138xxx"}),调用@ohos.telephony.call发起呼叫。

环境准备

  • 开发工具:DevEco Studio 4.0+
  • SDK版本:API 9+(支持电话、弹窗、文件读取)
  • 权限配置:在module.json5中声明权限:
    "requestPermissions": [  
      { "name": "ohos.permission.PLACE_CALL" },  
      { "name": "ohos.permission.SEND_MESSAGES" },  
      { "name": "ohos.permission.READ_MEDIA" } // 读取本地知识库文件  
    ]

代码实现(完整示例)

1. 数据结构定义(Model/SymptomTree.ts)

// 决策树节点  
export interface TreeNode {  
  question?: string; // 问题(如“是否发热?”)  
  options?: { text: string; nextNode: string }[]; // 选项与下一节点ID  
  disease?: string; // 最终病症(叶子节点)  
  advice?: string; // 急救建议  
}  

// 急救知识库(预置JSON转换)  
export const symptomTree: Record<string, TreeNode> = {  
  root: {  
    question: "请选择不适部位",  
    options: [  
      { text: "头部", nextNode: "head" },  
      { text: "躯干", nextNode: "trunk" }  
    ]  
  },  
  head: {  
    question: "是否头痛?",  
    options: [  
      { text: "是", nextNode: "headache" },  
      { text: "否", nextNode: "head_other" }  
    ]  
  },  
  headache: {  
    question: "是否伴随发热?",  
    options: [  
      { text: "是", nextNode: "cold" },  
      { text: "否", nextNode: "migraine" }  
    ]  
  },  
  cold: {  
    disease: "普通感冒",  
    advice: "1. 休息保暖;2. 温水擦浴降温;3. 体温>38.5℃可服退烧药。"  
  },  
  migraine: {  
    disease: "偏头痛",  
    advice: "1. 安静避光环境休息;2. 冷敷额头;3. 严重时就医。"  
  }  
};

2. 紧急联系人管理(ViewModel/ContactManager.ts)

import preferences from '@ohos.data.preferences';  

export class ContactManager {  
  private pref: preferences.Preferences | null = null;  

  async init(context: Context) {  
    this.pref = await preferences.getPreferences(context, 'contacts');  
  }  

  // 保存联系人(最多5个)  
  async saveContact(index: number, name: string, phone: string): Promise<boolean> {  
    if (!this.pref || index < 0 || index > 4) return false;  
    try {  
      await this.pref.put(`contact_${index}`, JSON.stringify({ name, phone }));  
      await this.pref.flush();  
      return true;  
    } catch (err) {  
      console.error(`Save contact failed: ${err}`);  
      return false;  
    }  
  }  

  // 获取所有联系人  
  async getContacts(): Promise<Array<{ name: string; phone: string }>> {  
    if (!this.pref) return [];  
    const contacts: Array<{ name: string; phone: string }> = [];  
    for (let i = 0; i < 5; i++) {  
      const data = await this.pref.get(`contact_${i}`, '{}');  
      const contact = JSON.parse(data as string);  
      if (contact.name) contacts.push(contact);  
    }  
    return contacts;  
  }  

  // 删除联系人  
  async deleteContact(index: number): Promise<boolean> {  
    if (!this.pref) return false;  
    await this.pref.delete(`contact_${index}`);  
    await this.pref.flush();  
    return true;  
  }  
}

3. UI界面(pages/Index.ets)

import { symptomTree } from '../Model/SymptomTree';  
import { ContactManager } from '../ViewModel/ContactManager';  
import call from '@ohos.telephony.call';  

@Entry  
@Component  
struct FirstAidPage {  
  @State currentNodeId: string = 'root'; // 当前决策树节点ID  
  @State selfCheckStep: string = ''; // 当前问题/结果  
  @State selfCheckOptions: { text: string; nextNode: string }[] = [];  
  @State result: { disease?: string; advice?: string } = {};  
  @State contacts: Array<{ name: string; phone: string }> = [];  
  @State showAddDialog: boolean = false;  
  @State inputName: string = '';  
  @State inputPhone: string = '';  

  private contactManager: ContactManager = new ContactManager();  

  aboutToAppear() {  
    this.loadSelfCheckNode('root');  
    this.loadContacts();  
  }  

  loadSelfCheckNode(nodeId: string) {  
    const node = symptomTree[nodeId];  
    if (node.disease) {  
      this.result = { disease: node.disease, advice: node.advice };  
      this.selfCheckStep = '';  
      this.selfCheckOptions = [];  
    } else {  
      this.selfCheckStep = node.question!;  
      this.selfCheckOptions = node.options!;  
      this.result = {};  
    }  
  }  

  async loadContacts() {  
    await this.contactManager.init(getContext());  
    this.contacts = await this.contactManager.getContacts();  
  }  

  build() {  
    Column({ space: 20 }) {  
      // 标题  
      Text("急救知识库").fontSize(24).fontWeight(FontWeight.Bold).margin(16);  

      // 标签页  
      Tabs({ barPosition: BarPosition.Start }) {  
        // 症状自检  
        TabContent() {  
          Column({ space: 15 }) {  
            if (this.result.disease) {  
              Text(`疑似病症:${this.result.disease}`).fontSize(18).fontColor(Color.Red);  
              Text(this.result.advice!).fontSize(16).padding(10).backgroundColor('#F5F5F5');  
              Button("重新自检").onClick(() => this.loadSelfCheckNode('root'));  
            } else {  
              Text(this.selfCheckStep).fontSize(18);  
              ForEach(this.selfCheckOptions, (option) => {  
                Button(option.text)  
                  .width('80%')  
                  .onClick(() => this.loadSelfCheckNode(option.nextNode));  
              })  
            }  
          }  
        }.tabBar("症状自检")  

        // 紧急联系人  
        TabContent() {  
          Column({ space: 10 }) {  
            List() {  
              ForEach(this.contacts, (item, index) => {  
                ListItem() {  
                  Row() {  
                    Column() {  
                      Text(item.name).fontSize(16);  
                      Text(item.phone).fontSize(14).fontColor(Color.Gray);  
                    }.alignItems(HorizontalAlign.Start).layoutWeight(1)  
                    Button("呼叫").onClick(() => call.makeCall(item.phone));  
                  }.width('100%').padding(10)  
                }  
              })  
            }.width('100%').height(300)  
            Button("添加联系人").onClick(() => this.showAddDialog = true);  
          }  
        }.tabBar("紧急联系人")  
      }.width('100%').height('85%')  
    }  
    .width('100%').height('100%')  
    .bindSheet(this.showAddDialog, this.buildAddDialog(), { height: 300 })  
  }  

  @Builder buildAddDialog() {  
    Column({ space: 15 }) {  
      Text("添加联系人").fontSize(20).fontWeight(FontWeight.Bold);  
      TextInput({ placeholder: "姓名" }).onChange(val => this.inputName = val);  
      TextInput({ placeholder: "电话" }).type(InputType.PhoneNumber).onChange(val => this.inputPhone = val);  
      Row() {  
        Button("取消").onClick(() => this.showAddDialog = false);  
        Button("保存").onClick(async () => {  
          if (this.inputName && this.inputPhone) {  
            const index = this.contacts.length;  
            await this.contactManager.saveContact(index, this.inputName, this.inputPhone);  
            this.loadContacts();  
            this.showAddDialog = false;  
            this.inputName = '';  
            this.inputPhone = '';  
          }  
        });  
      }.justifyContent(FlexAlign.SpaceAround)  
    }.padding(20)  
  }  
}

运行结果与测试步骤

运行结果

  • 症状自检:从“选择部位”开始,依次回答问题,最终显示病症与急救建议(如“普通感冒”及处理步骤)。
  • 紧急联系人:列表展示已保存联系人,点击“呼叫”直接拨号,点击“添加联系人”弹出输入框完成新增。

测试步骤

  1. 环境配置:创建鸿蒙工程,添加权限与代码文件,导入symptomTree数据与ContactManager
  2. 模拟器运行:使用API 9+模拟器,运行App,验证首页标签切换正常。
  3. 自检流程:依次点击“头部→是→是”,确认显示“普通感冒”及建议。
  4. 联系人操作:添加联系人“李四 139xxxx1234”,验证列表中显示并可呼叫。

部署场景

  • 个人手机:作为独立App安装,适合日常携带与紧急使用。
  • 社区终端:部署于社区服务中心大屏,居民可通过触控操作学习与求助。
  • 车载系统:集成至鸿蒙车机,驾驶途中突发不适时快速呼救。

疑难解答

  • 决策树跳转错误:检查symptomTreenextNode字段是否与节点ID一致。
  • 呼叫失败:确认已申请PLACE_CALL权限,且模拟器/真机开启电话功能。
  • 联系人保存无效:验证Preferences初始化是否成功(aboutToAppear中调用init)。

未来展望与技术趋势与挑战

未来展望

  • AI辅助诊断:接入大模型分析症状描述文本,提升自检准确率。
  • 位置联动:呼叫120时自动发送实时位置至急救中心。
  • 多语言支持:适配方言与外语,覆盖更广泛人群。

技术挑战

  • 复杂病症覆盖:决策树难以穷举所有病症,需结合知识图谱扩展。
  • 低网速优化:离线知识库体积较大时,需压缩存储与增量更新。

总结

本文基于鸿蒙系统实现急救知识库App,涵盖症状自检的决策树引导与紧急联系人的快速管理,通过本地化数据与简洁交互,为用户提供危急时刻的关键支持,具备高实用性与可扩展性。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。