资讯动态

Flutter适配OpenHarmony:家庭药箱与血糖记录App开发实战

发布时间:2026/10/22 8:00:52 来源:尧图企业网站定制
1. 先从基本面拆需求药箱管理加血糖记录到底要做什么我最近做了一个跑在 OpenHarmony 设备上的家庭药箱管理 App项目代号就叫 flutter_for_openharmony。起因很简单家里药抽屉乱成一团过期的药不敢扔又怕误吃长辈每天测血糖结果全记在纸上偶尔想翻一下过去一周的趋势根本翻不到。这个项目把两件事做成一个应用药品信息录入和效期余量管理以及血糖记录和趋势统计。这里我把从需求拆解到 Flutter 适配 OpenHarmony 的完整思路写下来给正在做健康类跨平台应用的朋友做个参考。先说结论这类项目最难的不是界面也不是图表而是把数据模型想清楚再把平台差异控制住。1.1 从一个使用场景推导功能边界我不建议上来就设计云同步、多家庭、医生随访那种大而全的功能。先想清楚最真实的场景某天早晨老人打开药箱找不到药打开手机能看到“阿托伐他汀还剩两片3天后过期”中午测完血糖顺手输入一个数值晚上能看到一周的趋势曲线。围绕这两个高频动作往下拆功能清单。功能清单大致包括药品录入、编辑、删除、搜索药品规格、剂量、库存数量、生产批次、有效期、分类临期和低库存标记用药提醒本地通知血糖记录和修改按时间展示历史列表用折线图看血糖趋势并对空腹和餐后数据分别统计。这是我第一版全部功能够用而且没有盲目扩大。很多健康类 App 一上来就搞登录账号、云端病历夹实际使用率并不高家庭场景里“打开即记、本地优先”反而是最舒服的。1.2 先做 MVP功能优先级怎么排如果一个人第一次接触 Flutter 和 OpenHarmony建议把项目缩成一个最小可运行版本。我把功能分为三档优先级功能说明P0药箱增删改查、血糖记录增删改查、本地持久化没有这些应用没有使用价值P1临期提醒、低库存提示、血糖趋势图让数据产生决策价值P2用药提醒通知、导出 CSV、备份恢复后期体验增强可迭代上线这种排序有实际考虑。药箱和血糖记录的核心是“不丢数据”所以持久化一定放在第一版提醒和图表属于交互增强可以放到第二个版本备份导出属于数据归属安全等基础功能稳定再做。后面做的时候我也是按这个节奏交付的每个版本都能独立跑通测试。先能查、能记、能存再去做提醒和图表这样开发过程中每个里程碑都有可用产物。2. 技术选型复盘为什么 Flutter 能跑在 OpenHarmony 上2.1 Flutter 在 OpenHarmony 上运行的基本原理OpenHarmony 虽然有自己的应用开发框架但 Flutter 这类跨平台方案也能直接落地。背后原理不复杂Flutter 的 Dart VM 加载业务代码UI 通过自绘引擎直接渲染到 OpenHarmony 提供的显示 Surface 上不依赖系统原生控件需要调用系统能力时再通过 MethodChannel 走平台通道让原生侧完成通知、存储、权限等动作。这就意味着大多数界面和业务逻辑代码可以跨平台复用需要单独适配的主要是平台相关接口。实际体验下来这个方案在 UI 一致性上有天然优势。同一个页面在 OpenHarmony 设备上和其他平台测试机上几乎长一个样没有各端一到两像素偏差的问题。对我这种要同时维护多个目标的开发者来说节省的时间非常明显。Flutter 的布局和渲染模型本身是自包含的页面不会因为系统控件的风格变化而变形这对健康数据展示类页面尤其重要掉点、对齐、字体大小都要稳定可控。2.2 原生方案与其他跨端方案的取舍简单对比一下几类选择ArkUI 原生对系统能力支持最直接但需要重新学习方舟应用开发语言和布局体系如果团队里已经有不少 Dart 代码迁移成本偏高。OpenHarmony 原生生态在快速完善组件质量和文档量都还不错但要做出同样复杂度的血糖趋势图表和列表动效成本并不低。Web/H5 混合开发快但在复杂交互和大量数据渲染时会有卡顿而且离线能力和系统通知接入流畅度都弱一些。药箱数据属于本地高频操作一旦断网导致页面不可用体验会非常差。Flutter 自绘学习曲线存在但如果你熟悉 Dart开发效率很高缺点是插件生态在 OpenHarmony 上还不够全个别三方库要自己封装。我更倾向 Flutter 的理由还有一个它的状态管理和组件化方式很适合“药箱列表 血糖趋势图”这种页面结构。同一个列表模型可以通过一个 ChangeNotifier 让多组件联动刷新减少手工 setState 带来的状态散乱。本身药箱页面同时要显示列表、搜索、预警卡片如果靠一层层回调传递状态后面维护起来会很痛苦。2.3 标题里的 flutter_for_openharmony 是什么这个代号是我给项目里那层 Flutter 与 OpenHarmony 桥接适配起的名字不是官方 SDK。它封装了引擎初始化、Surface 接入、平台通道注册等步骤让我在 Dart 侧可以用标准 Flutter API 写代码。实际工程中这层适配的工作量也比较集中要处理系统差异的主要是权限、存储目录、通知服务、日志输出和文件选择这些点。把这层做好后面的业务开发才会顺畅。项目取这个代号也是为了提醒自己不要忘记平台差异问题所有涉及系统能力的代码都要先经过这一层而不是直接到处写平台判断。3. 数据模型和项目结构先建两张表再谈界面3.1 药箱表和血糖记录表怎么设计药箱管理用一张 medicine 表就够了字段包括名称、规格、剂量、分类、批号、库存数量、单位、有效期、生产日期、备注、创建时间和更新时间。其中“分类”字段用来做慢性病药品、外用药、急救药等分组筛选“有效截止日期”和“库存数量”是后面预警逻辑的关键。如果后续要加家庭成员维度也可以再补一个 owner_id 字段不同成员之间做数据隔离。血糖记录单独建一张 glucose_record 表。字段有测量时间、血糖数值、单位、时段标签空腹/餐后/随机、备注、创建时间。为什么不把血糖数据塞进药箱表因为维度完全不同药品关心的是“还剩多少、是否过期”血糖关心的是“何时测的、是否空腹、趋势怎样”分开建表更符合查询场景。两表之间目前没有外键关联业务上也不需要保持简单即可。数据库我用的是基于 sqlite 的适配方案在 OpenHarmony 上通过插件能力访问本地文件。初始化代码大致如下class AppDatabase { static const _dbName family_medicine_box.db; static const _dbVersion 1; Database? _db; FutureDatabase get database async { if (_db ! null) return _db!; _db await _open(); return _db!; } FutureDatabase _open() async { final dir await getApplicationSupportDirectory(); final path ${dir.path}/$_dbName; return openDatabase(path, version: _dbVersion, onCreate: (db, version) async { await db.execute( CREATE TABLE medicine ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, spec TEXT, dosage TEXT, category TEXT, stock INTEGER DEFAULT 0, unit TEXT DEFAULT 盒, expire_date TEXT, manufacturer TEXT, note TEXT, created_at TEXT, updated_at TEXT ) ); await db.execute( CREATE TABLE glucose_record ( id INTEGER PRIMARY KEY AUTOINCREMENT, value REAL NOT NULL, unit TEXT DEFAULT mmol/L, period TEXT, measure_time TEXT, note TEXT, created_at TEXT ) ); }); } }注意这里我用了 getApplicationSupportDirectory 获取目录这个 API 在 Android 上返回应用私有目录在 OpenHarmony 上则需要通过平台通道做一层转换。如果直接沿用旧平台写死的路径很可能出现目录不存在或权限不足的问题。所以我在适配层单独封装了一个路径获取函数确保所有数据库文件、导出文件的读写都落在同一个沙箱目录下避免因为路径不一致导致升级后数据丢失。3.2 目录结构和状态管理选型项目代码我按数据层、页面层、组件层拆开没有把逻辑全塞进 Widget 里。目录大概是lib/ main.dart models/ medicine.dart glucose_record.dart repositories/ medicine_repository.dart glucose_repository.dart pages/ medicine/ medicine_list_page.dart medicine_edit_page.dart glucose/ glucose_list_page.dart glucose_record_page.dart home_page.dart widgets/ medicine_card.dart glucose_trend_chart.dart stat_card.dart utils/ date_helper.dart db_helper.dart状态管理选的是 Provider 加 ChangeNotifier。操作逻辑很简单药品列表页加载数据后放入 MedicineModel页面用 Consumer 订阅编辑器填写完成后调用 repository 保存再触发 model 刷新。这样列表、搜索、详情卡片能同步更新。血糖页面则按时间范围加载记录用一个独立的 GlucoseModel 管理。选择 Provider 而不是更重的状态管理框架是因为这个项目里的共享状态不多主要就是列表数据和当前筛选条件Provider 的轻量特点刚好匹配调试也比较直观。3.3 数据版本升级的坑第一次建表后如果后面改动字段不能直接删掉重建。我在数据库版本号上做了递增并在 onUpgrade 里用 ALTER TABLE 补充字段。比如想给血糖表加一个“是否服药记录”字段就把版本从 1 改成 2执行类似下面的语句await db.execute(ALTER TABLE glucose_record ADD COLUMN medication_tag TEXT);这条没提前规划很容易出现在真机上更新后闪退的情况。数据库升级的测试一定要做“旧表 - 新表”的迁移验证而不是每次卸载重装。因为用户已经积累了几百条记录卸载重装等于数据全丢这个体验对家庭健康场景来说是不可接受的。我把数据库迁移逻辑单独写在 MigrationManager 里每次升级前先检查当前版本按版本号顺序执行迁移语句并把迁移过程包在事务里任一语句失败就回滚保证数据完整性。4. 药箱管理核心功能实现从表单到预警提醒4.1 药品录入表单和校验逻辑药品录入页主要包含名称、规格、剂量、分类、库存、单位、有效期、厂家、备注。名称是必填字段库存我限定为整数且不能为负数。有效期需要用日期选择器选择不能直接让用户随意输入字符串否则后面的临期计算会出问题。提交前做一个轻量校验String? validate() { if (name.trim().isEmpty) return 药品名称不能为空; if (stock 0) return 库存不能是负数; if (expireDate null) return 请选择有效期; if (DateTime.parse(expireDate!).isBefore(DateTime.now())) return 有效期不能早于今天; return null; }严格限制日期后药品列表、临期预警和血糖记录的时间维度才有一致性。所有日期在写入数据库前统一转成 yyyy-MM-dd 或毫秒时间戳展示层再做格式化这样后面无论是排序还是统计都不会因为格式不一致出偏差。这里还要注意时区问题日期选择器拿到的本地日期直接格式化保存即可不要二次转时区否则容易出现“今天选的有效期存入后变成昨天”的诡异情况。4.2 列表展示与状态标签药品列表我用 ListView.builder 渲染卡片。每张卡片显示药品名称、规格、剩余数量以及一个根据有效期计算出来的状态标签。状态分三种正常、即将过期、已过期。判断逻辑写成一个独立函数方便单元测试String expiryStatus(String expireDate) { final now DateTime.now(); final date DateTime.parse(expireDate); final days date.difference(now).inDays; if (days 0) return 已过期; if (days 30) return 临期; return 正常; }注意 date.difference 的结果要按天数归一化不能直接拿毫秒转数字去比较否则会受当天时分秒影响。我建议把所有日期都先规范成零点再比较也就是用 DateTime(year, month, day) 构造一个日期对象再计算差值。这样今天到明天永远是 1 天不会因为当前时间是下午一点还是晚上八点产生偏差。卡片布局上我用了 Stack 在右上角放状态标签过期标红、临期标黄正常标绿颜色信息配合文字避免单纯靠颜色无法区分。4.3 临期和低库存提醒怎么触发预警最好的触发时机是首页刷新。每次进入首页时我会遍历药品列表找出已过期、未来 30 天内过期、库存低于设定阈值的药品把它们统一显示在“需要关注”区域。这个方案简单可靠不需要额外写复杂的调度器。阈值在设置里可配置默认库存低于 3 盒或 3 片时标红。如果药品数量比较多也可以把这部分查询交给 SQL用 WHERE expire_date BETWEEN 和 stock 条件控制返回速度很快而且只查需要的字段内存占用小。用药提醒依赖本地通知。OpenHarmony 的通知能力和其他平台不完全一样我在 Dart 侧定义一个 NotificationService底层用 MethodChannel 调用原生接口。发送提醒前需要先检查是否已经授权未授权则引导用户在设置里打开。通知内容会带上药品名称和剩余数量提醒文案写得具体一点比如“阿托伐他汀还剩 2 片请记得服用并补药”比一句“你有用药提醒”有用得多。5. 血糖记录功能实现从输入到趋势图5.1 记录表单和数据校验血糖记录页面里的核心字段是血糖值、测量时间和时段标签。血糖值我用数字键盘输入范围限制在 2.0 ~ 25.0 mmol/L 之间过高的异常值会弹提示建议复核或去医院检查。这里要特别说明App 只做记录和趋势参考不能替代专业血糖仪和医生诊断所以页面上我还加了一行小字备注提醒用户如果连续出现异常值应该尽快咨询专业人员。时段标签分为空腹、早餐后、午餐后、晚餐后、睡前、随机。同样的血糖值空腹和餐后的意义完全不同统计时不能混在一起看。我在模型里用一个字符串字段保存而不是用一个整数枚举原因是后续要扩展中国式餐后两小时等场景字符串字段的兼容性更好查询时直接按字符串过滤即可。表单提交前会校验数值是否在范围内测量时间是否晚于创建时间以及备注长度是否合理所有校验通过后才写数据库。5.2 历史记录列表如何组织记录列表按时间倒序展示每一项显示测量时间、血糖值和时段标签。为了缩短每天看到的列表长度我做了按天分组每天显示一条日期头底下是该天的多条记录。分组逻辑不复杂从查询结果里按日期字符串切分即可。编辑可以长按记录弹出操作菜单或者右滑出现编辑、删除按钮点击后进入原表单回填数据。删除前弹确认框避免误触。列表项里还加了一个平均值小组件当某一天的记录超过一条时会自动算当天平均显示在日期头右侧。这个细节看着小但对老人和子女都很有用因为一天多次测量的情况并不少只看单点容易产生误判。按天分组后列表长度也被控制住了不会因为一个月几百条记录导致 ListView 一次性渲染太多节点性能问题在数据量变大之前就被提前规避了。5.3 用 CustomPaint 自己画趋势折线图本来想直接引用第三方的图表库但在 OpenHarmony 适配过程中发现有两个问题一是包体积增加明显二是部分图表库依赖的轻量级手势组件在目标设备上会有兼容问题。于是血糖趋势图我直接用 CustomPaint 实现效果完全够用。绘制思路分三步计算数据范围绘制坐标轴和辅助线绘制折线和数据点。x 轴是测量时间点y 轴是血糖值。为了让图表有实际参考意义我额外画了两条浅色横向参考线分别对应 3.9 mmol/L 和 6.1 mmol/L这是常见的空腹血糖参考范围。Painter 核心代码如下class GlucoseChartPainter extends CustomPainter { final ListGlucoseRecord records; final double normalLow; final double normalHigh; GlucoseChartPainter({required this.records, this.normalLow 3.9, this.normalHigh 6.1}); override void paint(Canvas canvas, Size size) { if (records.length 2) return; final minY (records.map((r) r.value).reduce(min) - 0.5).clamp(0, 30); final maxY (records.map((r) r.value).reduce(max) 0.5).clamp(0, 30); // 画正常范围背景 final bgPaint Paint()..color Color(0x1A4CAF50); final lowY size.height - (normalLow - minY) / (maxY - minY) * size.height; final highY size.height - (normalHigh - minY) / (maxY - minY) * size.height; canvas.drawRect(Rect.fromLTRB(0, highY, size.width, lowY), bgPaint); // 画折线 final linePaint Paint() ..color Color(0xFF2E7D32) ..style PaintingStyle.stroke ..strokeWidth 2.5 ..strokeCap StrokeCap.round; final path Path(); for (var i 0; i records.length; i) { final dx i / (records.length - 1) * size.width; final dy size.height - (records[i].value - minY) / (maxY - minY) * size.height; if (i 0) { path.moveTo(dx, dy); } else { path.lineTo(dx, dy); } } canvas.drawPath(path, linePaint); // 画数据点 final pointPaint Paint()..color Color(0xFF1B5E20); for (var i 0; i records.length; i) { final dx i / (records.length - 1) * size.width; final dy size.height - (records[i].value - minY) / (maxY - minY) * size.height; canvas.drawCircle(Offset(dx, dy), 3, pointPaint); } } override bool shouldRepaint(covariant GlucoseChartPainter oldDelegate) { return oldDelegate.records ! records; } }正常范围背景色我用了透明度很低的安全绿既不影响数据点阅读又能一眼看出血糖是否高出正常区域。记录少于两个点时直接不绘制避免除以零。这里有个小细节x 轴并不是按真实时间等距排列而是按记录序号均匀排列。这样做的原因是血糖测量时间并不规律有时候一天测五次有时候三天测一次如果严格按时间比例绘制数据点会挤在一团根本看不清。治疗趋势本身更关心顺序和方向所以按记录序号排列是一个更实用的折中方案。图表下方再放三个统计卡片平均血糖、最高血糖、最低血糖和达标率。达标率定义为数据值落在 3.9~6.1 或目标区间内的比例计算时要去掉空值随机时段的记录不参与空腹达标判断。统计卡片我用一个横向 Row 排列视觉上清爽而且不占太多垂直空间。对于家庭使用者来说一个“最近 14 天空腹平均水平”的总结往往比几十个原始数据点更有指导意义。6. OpenHarmony 适配全程复盘权限、存储、通知和打包6.1 权限与沙箱目录的区别Flutter 项目跑在 OpenHarmony 上不要默认所有参考其他平台的权限配置都有效。OpenHarmony 的应用配置文件通常是 module.json5需要在这里声明要访问的权限例如读取存储、通知、网络访问等。声明完成后部分权限还需要在运行时动态向用户申请。否则你会发现在参考其他平台时很正常的数据导入流程在 OpenHarmony 上会静默失败甚至完全无回调。本地数据库路径不要写死成常见移动系统里的 data/data 路径。OpenHarmony 对应用沙箱目录有自己的一套规则最靠谱的做法是通过平台通道向原生侧拿到系统返回的应用支持目录再拼上数据库文件名。我在前面的 AppDatabase 里就是用 getApplicationSupportDirectory 而不是硬编码路径。目录相关代码在适配层统一处理业务层完全感知不到路径差异后面如果要迁移到新的系统版本也只需要改适配层。6.2 通知服务的平台通道示例用药提醒和血糖测量提醒都需要系统通知。Dart 侧定义一个 MethodChannel 服务调用原生方法发送通知class LocalNotificationService { static const channel MethodChannel(family_medicine/notification); Futurevoid showMedicineReminder(String title, String body) async { await channel.invokeMethod(showReminder, { title: title, body: body, triggerTime: DateTime.now().add(Duration(minutes: 1)).millisecondsSinceEpoch, }); } }原生侧收到消息后通过 OpenHarmony 的通知接口创建通知。这里重点是一个容易踩的坑通知的触发时间一般要求是时间戳时区要统一使用本地时区不要内部转成 UTC 再传回去否则会发现通知提前或延后一个小时。我就在这上面调了整整一个晚上。建议所有时间字段都用毫秒时间戳传展示层再做格式化避免跨平台时 DateTime 序列化和反序列化出现时区错位。通知功能除了提醒本身还要处理重复点击的问题。用户在药箱页面点了“已服用”按钮后我通过另一个接口取消尚未触发的通知避免老人已经吃完药却再次收到提醒。这个交互虽然是边缘场景但直接影响信任度如果总是误报家人很快就不再依赖这个提醒功能了。6.3 字体、体积和调试注意事项OpenHarmony 设备的中文字体渲染并不是每个版本都一致个别系统裁剪版本缺省字体文件会造成 Text 显示为方框。解决办法是在 Flutter 侧为 MaterialApp 统一配置 fallback 字体把常用的开源中文字体打包进 assets或者至少设置 fontFamilyFallback 列表指定一个系统支持的字体名。我在项目里选择直接打包一款字体文件虽然增加了一点应用体积但换来了稳定一致的渲染效果尤其在药品名称这类关键信息上不能出现乱码。包体积方面Flutter 产物本身比小型原生应用大不少如果项目对包体敏感需要裁剪未使用的 native library并在 release 构建时开启 tree shake icons同时检查 assets 里是否混进了不必要的测试资源。调试上不要完全依赖热重载。我在一些开发板上测试时热重载偶尔会失效页面状态停留在旧代码这时先停掉应用再重新构建即可别浪费时间去猜环境问题。真机日志输出也可能缺失我习惯在关键操作里主动加日志并统一输出带时间戳的信息方便回溯。6.4 分发和真机安装的注意事项OpenHarmony 设备安装 App 的签名要求与常见移动系统类似但不完全相同需要在工程里配置好签名能力。首次安装到开发板时如果签名不匹配应用能装上但无法访问部分敏感权限。我建议准备一台专用测试设备反复测试“全新安装、升级安装、覆盖安装”三种方式重点看数据库迁移和权限授权是否会丢失。升级安装尤其重要因为正式使用后家人不会每次点“卸载重装”他们只会点“更新”如果升级路径没测好所有积累的药箱数据和血糖记录都可能消失。另外OpenHarmony 不同设备的内存和性能差异比想象中大。有的开发板内存不到 2GB跑完整 Flutter 应用虽然能进界面但列表滑动时会明显掉帧。我在最终版本里把列表项图标全部简化为线条风格并把阴影改为轻量边框就是为了在低端设备上也能顺畅操作。这个优化不会影响功能但对实际体验影响很大。7. 问题排查与优化建议速查7.1 实际运行中的典型问题把我在开发过程中遇到比较典型的几个问题列成表方便直接对照现象可能原因解决思路数据库打开失败沙箱目录不对或首次初始化权限未授予用平台通道获取真实支持目录申请存储权限药品列表滚动卡顿list item 有重型布局或频繁 setState缩小卡片布局层级列表项用 const 构造局部刷新血糖图不显示记录少于两个或 y 轴范围计算除零Painter 判空范围做 clamp本地通知不触发权限未申请或时间戳时区不对检查通知授权统一用本地毫秒时间戳升级后闪退数据库表结构没迁移递增版本号写 onUpgrade覆盖旧数据测试每一个问题我都实际撞过。尤其是数据库迁移表面上只是加了一列但如果用户手机上已经存在旧版本直接跑新代码就会报 no such column。后来我把 onUpgrade 的语句统一放到事务里执行并把所有迁移操作都写进 MigrationManager再在每个版本升级前做自动备份这样出问题时还能从备份恢复。迁移脚本不是一次性写完就不管只要后续加字段、加表、改索引都要在这里补一条迁移记录。7.2 性能优化建议数据量大了以后最明显的瓶颈是列表重建。建议使用 ListView.builder 加分页一次只加载当前屏幕需要的记录数据库查询不要把所有字段都取回来只取展示需要的字段如果同一页面有多个子 widget 依赖同一个 model可以拆成多个 Consumer 而不是一个大的 provider 包裹这样局部刷新更高效。图表部分如果记录超过几百条可以在 Painter 里做数据降采样比如每隔 3 个点取一个极值点曲线形状影响不大CPU 占用能降一半。本地数据库还有一个容易忽略的优化点索引。血糖表如果经常按 measure_time 排序就给 measure_time 建一个普通索引药箱表如果经常按 expire_date 筛选今天到期或近期到期的药品也给 expire_date 建索引。加了索引之后数据量到几千条时查询速度依然能保持在毫秒级列表滚动也不会因为等待数据库查询而卡住。7.3 后面还能怎么做这个项目做下来我发现家庭药箱和血糖记录还有很多可扩展空间。比如为每一位家庭成员建立独立数据空间记录各自的药品和血糖数据增加 CSV 导出方便去医院时直接给医护人员看趋势后续可以做用药依从性分析统计按时服药比例和漏服率。对那些已经有数据积累的家庭来说这些功能能带来的实际帮助比又一个购物式应用更有价值。还有一个很实用的方向把药箱和血糖联动起来。比如记录血糖的时候可以顺手标记“是否已服降糖药”当血糖趋势持续异常时能辅助观察用药和血糖之间的关系。这个功能不需要复杂的算法只是在血糖记录表里多一个字段然后增加一个筛选维度即可。但跨表的数据联动对数据模型和查询设计有要求所以我建议在基础版本稳定后再加一步一步来。我个人在这个项目里最深的体会是技术选型再花哨也不如先把核心流程跑通。flutter_for_openharmony 这个项目最值的部分不是把界面做得好看而是把药箱数据和血糖数据从纸质记录盘活成了可查询、可预警、可看趋势的本地数据库。如果你也想做类似的东西我的建议是从一张药箱表和一张血糖表开始先让家人真正用起来再慢慢加功能。数据一旦积累起来应用的不可替代性就出现了。最后再分享一个小技巧开发这类健康管理工具一定要留好数据导出入口无论用 CSV 还是 JSON至少要让用户能把数据拿走。这不只是为了合规更是对用户信任的基本尊重。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑