本地优先架构实践:SQLite + Repository 模式 + 自动备份
文章目录本地优先架构实践SQLite Repository 模式 自动备份为什么选择本地优先数据库设计Schema7 张表索引策略Repository 模式自动备份5 行代码的数据安全数据导出/导入JSON 导出JSON 导入最复杂的部分CSV 导出局限性总结本地优先架构实践SQLite Repository 模式 自动备份不联网、不注册、不上云。你的财务数据只存在你手机上。为什么选择本地优先做本地优先Local-First不是因为技术限制而是产品定位的刻意选择1. 隐私财务数据是最敏感的个人信息之一。你有多少存款、你的房子值多少、你的信用卡欠多少——这些信息不应该存在于任何第三方服务器上。WorthBase 不主动发起任何网络请求。2. 离线可用地铁里、飞机上、山区旅行——任何地方都能打开 App 查看和更新数据。不依赖网络状态。3. 数据所有权你的数据是你的。不存在服务商停止运营后数据丢失的问题。数据就是一个.db文件你可以随时复制、备份、迁移。数据库设计Schema7 张表-- 账户表8 种类型CREATETABLEaccounts(idTEXTPRIMARYKEY,nameTEXTNOTNULL,typeTEXTNOTNULL,-- wechat/alipay/bank_card/cash/fund/credit_card/loan/othericonTEXT,sort_orderINTEGERDEFAULT0,deleted_atTEXT,-- 软删除不物理删除created_atTEXT,updated_atTEXT);-- 余额快照表追加式不修改历史CREATETABLEbalance_snapshots(idTEXTPRIMARYKEY,account_idTEXTNOTNULLREFERENCESaccounts(id),balanceREALNOTNULL,snapshot_dateTEXTNOTNULL);-- 实物资产表8 种分类4 种分摊方式CREATETABLEassets(idTEXTPRIMARYKEY,nameTEXTNOTNULL,categoryTEXTNOTNULL,-- vehicle/real_estate/electronics/digital/home/luxury/precious_metal/otherpurchase_dateTEXTNOTNULL,purchase_priceREALNOTNULL,amortization_typeTEXTNOTNULL,expected_lifespan_monthsINTEGER,residual_valueREAL,valuation_trackingINTEGERDEFAULT0,current_valuationREAL,statusTEXTDEFAULTactive,-- active/retired/soldsell_dateTEXT,sell_priceREAL,weight_gramsREAL,image_pathTEXT,created_atTEXT,updated_atTEXT);-- 经常性支出保险、停车费等按月生效CREATETABLErecurring_expenses(idTEXTPRIMARYKEY,asset_idTEXTREFERENCESassets(id),nameTEXTNOTNULL,amountREALNOTNULL,effective_fromTEXTNOTNULL,effective_toTEXT,-- null 持续生效ended_reasonTEXT);-- 一次性维护记录维修、保养CREATETABLEmaintenance_records(idTEXTPRIMARYKEY,asset_idTEXTREFERENCESassets(id),nameTEXTNOTNULL,amountREALNOTNULL,dateTEXTNOTNULL,amortizeINTEGERDEFAULT0-- 是否纳入月均分摊);-- 估值历史可选追踪CREATETABLEvaluation_history(idTEXTPRIMARYKEY,asset_idTEXTREFERENCESassets(id),valuationREALNOTNULL,recorded_dateTEXTNOTNULL);-- 应用设置KV 存储CREATETABLEsettings(keyTEXTPRIMARYKEY,valueTEXTNOTNULL);索引策略针对高频查询场景建索引-- 余额快照按账户日期查询最新余额CREATEINDEXidx_snapshots_account_dateONbalance_snapshots(account_id,snapshot_date);-- 余额快照按日期查询趋势图数据CREATEINDEXidx_snapshots_dateONbalance_snapshots(snapshot_date);-- 经常性支出按生效区间查询当月有哪些支出生效CREATEINDEXidx_recurring_effectiveONrecurring_expenses(effective_from,effective_to);Repository 模式每个表对应一个 Repository 对象封装所有 SQL 操作// src/db/account-repository.ts (简化)exportconstAccountRepository{asyncgetAll():PromiseAccount[]{...},asynccreate(account:Account):Promisevoid{...},asyncupdate(id:string,updates:PartialAccount):Promisevoid{...},asyncsoftDelete(id:string):Promisevoid{...},// SET deleted_at now// 聚合查询获取所有账户的最新余额asyncgetAllLatestBalances():PromiseMapstring,number{constresultawaitdb.getAllAsync(SELECT bs.account_id, bs.balance FROM balance_snapshots bs INNER JOIN ( SELECT account_id, MAX(snapshot_date) as max_date FROM balance_snapshots GROUP BY account_id ) latest ON bs.account_id latest.account_id AND bs.snapshot_date latest.max_date INNER JOIN accounts a ON bs.account_id a.id WHERE a.deleted_at IS NULL);returnnewMap(result.map(r[r.account_id,r.balance]));},};没有 ORM没有 query builder纯 SQL。对于 7 张表的项目来说ORM 引入的抽象层比它解决的问题更多。自动备份5 行代码的数据安全本地优先 App 最大的风险是数据丢失——手机丢了、App 被卸载、数据库文件损坏。我的解决方案极其简单// app/_layout.tsx:58-66useEffect((){constsubscriptionAppState.addEventListener(change,(nextAppState){constprevappStateRef.current;appStateRef.currentnextAppState;// App 退到后台 → 自动备份if(prevactive(nextAppStatebackground||nextAppStateinactive)){BackupService.createBackup();}});return()subscription.remove();},[]);BackupService.createBackup()做的事情就是把 SQLite.db文件原封不动地复制到backups/目录文件名带时间戳。最多保留 3 份旧的自动删除。没有后台任务、没有定时器、没有推送通知。App 退后台就备份就这么朴素。数据导出/导入JSON 导出用户手动触发生成结构化 JSON 文件{version:1,exportDate:2026-07-12T08:00:00.000Z,accounts:[...],balanceSnapshots:[...],assets:[...],recurringExpenses:[...],maintenanceRecords:[...],valuationHistory:[...],settings:{...}}从 7 个 Repository 各取全量数据打包成一个 JSON。通过expo-sharing调起系统分享面板用户可以发到微信、邮件、云盘。JSON 导入最复杂的部分导入不是简单的把 JSON 写进数据库。核心挑战是ID 重映射清空所有 7 张表逐条插入 accounts记录oldId → newId映射逐条插入 assets同样记录映射插入子表balance_snapshots、recurring_expenses 等用映射表替换外键如果父记录不存在孤儿记录静默跳过整个过程在一个数据库事务内执行。任何一步失败全部回滚。// src/services/import-service.ts (简化)awaitdb.withTransactionAsync(async(){// 清空所有表for(consttableofTABLES){awaitdb.execAsync(DELETE FROM${table});}// 重建账户记录 ID 映射constaccountIdMapnewMapstring,string();for(constaccountofdata.accounts){constnewIdgenerateId();accountIdMap.set(account.id,newId);awaitAccountRepository.create({...account,id:newId});}// 重建子表替换外键for(constsnapshotofdata.balanceSnapshots){constnewAccountIdaccountIdMap.get(snapshot.accountId);if(!newAccountId)continue;// 孤儿记录跳过awaitBalanceSnapshotRepository.create({...snapshot,accountId:newAccountId,});}// ... 其他表类似});CSV 导出给人看的格式方便在 Excel 里查看日期, 微信零钱, 支付宝余额, 招商储蓄卡, ..., 总计 2025-01-15, 3500, 12000, 45000, ..., 60500 2025-02-15, 4000, 11500, 46000, ..., 61500局限性本地优先不是万能的局限说明缓解方案无多端同步换设备需要手动导出/导入JSON 文件 系统分享设备丢失 数据丢失如果没备份自动备份到本地退后台触发图片未备份资产照片存在文件系统中.db备份不包含图片已知问题计划中无加密SQLite 文件可以被直接读取应用锁保护 App 访问总结本地优先架构的核心原则简单胜过完备。不用云同步用文件导出/导入不用后台任务用 AppState 监听不用 ORM用纯 SQL不用复杂加密用应用锁对于一个个人财务 App 来说这些简单方案已经够用了。源码: github.com/callmebg/worthbase | db/ | services/CSDN 标签:SQLiteReact Native数据安全本地存储架构掘金话题:前端数据库React Native架构

相关新闻

苹果公司技术路线与原则发展史:整合、控制与体验的演进

苹果公司技术路线与原则发展史:整合、控制与体验的演进

苹果公司技术路线与原则发展史:整合、控制与体验的演进摘要本报告旨在深度剖析苹果公司自1976年成立以来,其技术路线与核心原则的演变历程、内在逻辑及得失权衡。报告将苹果的发展划分为五个关键阶段:初创探索期、衰落迷茫期、重塑复兴期、移…

2026/8/10 5:48:19 阅读更多 →
iOS-Tech-Weekly架构设计专题:MVC、MVVM、VIPER等架构模式对比分析

iOS-Tech-Weekly架构设计专题:MVC、MVVM、VIPER等架构模式对比分析

iOS-Tech-Weekly架构设计专题:MVC、MVVM、VIPER等架构模式对比分析 【免费下载链接】iOS-Tech-Weekly 百度Hi团队 iOS 技术周报 项目地址: https://gitcode.com/gh_mirrors/io/iOS-Tech-Weekly iOS-Tech-Weekly作为百度Hi团队的iOS技术周报,涵盖了…

2026/8/10 10:03:36 阅读更多 →
OData.NET实体数据模型(EDM)完全指南:从基础到高级应用

OData.NET实体数据模型(EDM)完全指南:从基础到高级应用

OData.NET实体数据模型(EDM)完全指南:从基础到高级应用 【免费下载链接】odata.net ODataLib: Open Data Protocol - .NET Libraries and Frameworks 项目地址: https://gitcode.com/gh_mirrors/od/odata.net OData.NET实体数据模型(EDM)是构建现代RESTful A…

2026/8/10 3:03:21 阅读更多 →

最新新闻

告别风扇噪音:用FanControl打造你的静音高性能PC

告别风扇噪音:用FanControl打造你的静音高性能PC

告别风扇噪音:用FanControl打造你的静音高性能PC 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/FanC…

2026/8/11 13:02:52 阅读更多 →
3分钟掌握res-downloader:全网资源下载神器,轻松获取视频号、抖音、小红书内容

3分钟掌握res-downloader:全网资源下载神器,轻松获取视频号、抖音、小红书内容

3分钟掌握res-downloader:全网资源下载神器,轻松获取视频号、抖音、小红书内容 【免费下载链接】res-downloader 视频号、小程序、抖音、快手、小红书、直播流、m3u8、酷狗、QQ音乐等常见网络资源下载! 项目地址: https://gitcode.com/GitHub_Trending…

2026/8/11 13:02:52 阅读更多 →
Traymond:Windows桌面整理的终极解决方案,一键隐藏窗口到系统托盘

Traymond:Windows桌面整理的终极解决方案,一键隐藏窗口到系统托盘

Traymond:Windows桌面整理的终极解决方案,一键隐藏窗口到系统托盘 【免费下载链接】traymond A simple Windows app for minimizing windows to tray icons 项目地址: https://gitcode.com/gh_mirrors/tr/traymond Traymond是一款专为Windows用户…

2026/8/11 13:02:52 阅读更多 →
8月深度测评:2026年爆火的10款ai写小说工具(附工具使用避坑指南)

8月深度测评:2026年爆火的10款ai写小说工具(附工具使用避坑指南)

很多新手如何开始写小说总是卡在开头,或者写不出黄金前三章。 这几年测试过不下二十款写小说软件,今天把过去所有的测试笔记总结出来,聊聊那些真正能提升效率的ai写小说工具。 我不讲空话,每款工具我都亲手跑过几十万字废稿&…

2026/8/11 13:02:52 阅读更多 →
2025年网盘文件下载的终极解决方案:多平台直链获取工具详解

2025年网盘文件下载的终极解决方案:多平台直链获取工具详解

2025年网盘文件下载的终极解决方案:多平台直链获取工具详解 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 /…

2026/8/11 13:02:52 阅读更多 →
视频转文字原理是什么?实测4款AI工具后的使用总结

视频转文字原理是什么?实测4款AI工具后的使用总结

摘要: 随着短视频、在线课程、企业会议、访谈内容不断增加,如何快速将视频中的语音转换成可编辑文字,成为很多内容创作者和职场用户的刚需。传统人工听写不仅效率低,而且容易遗漏关键信息。本文从视频转文字技术原理出发&#xff…

2026/8/11 13:01:52 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →