架构设计
爱生活 的分层架构、技术决策、离线优先策略与模块化设计
总体架构
爱生活 采用 Page → Store → Module (Repository) → Database Engine 的四层单向数据流。每一层只依赖下一层,上层完全不感知底层的存储引擎差异(SQLite / IndexedDB)和加解密逻辑。
┌─────────────────────────────────────────────────────────┐
│ Pages (60+) │
│ 页面视图层:任务列表、日历、财务仪表盘、AI对话…… │
│ 只调用 Store 的方法,不直接操作数据库 │
├─────────────────────────────────────────────────────────┤
│ Stores (Pinia) │
│ 状态管理层:任务、日历、习惯、番茄钟、笔记、模式…… │
│ 持有 Repository 引用,管理 UI 状态和业务逻辑 │
├─────────────────────────────────────────────────────────┤
│ Modules (Repository + Types) │
│ 数据持久层:每个模块 = types.ts + repository.ts │
│ 继承 BaseRepository,自动获得 CRUD 全套能力 │
├─────────────────────────────────────────────────────────┤
│ Database Engine │
│ 存储引擎:DexieStore (H5) / SqliteStore (App) │
│ 透明加密:EncryptedStore 包装层 │
└─────────────────────────────────────────────────────────┘数据流严格单向:用户操作 → Page 调用 Store → Store 调用 Repository → Repository 写入 Engine → Engine 返回结果 → Store 更新状态 → Page 响应式更新。
目录结构
src/
├── ai/ # AI 子系统
│ ├── pipeline.ts # 端侧模型加载与推理(H5: Transformers.js)
│ ├── edge-stream.ts # 端侧流式推理输出
│ ├── agent-prompt.ts # Agent 系统提示词模板
│ ├── model-manager.ts # 模型下载、缓存、切换管理
│ └── actions.ts # AI 操作路由(20+ 动作 Schema + 执行函数)
│
├── database/ # 数据库层(多引擎适配)
│ ├── index.ts # 表结构定义、字段 Schema、索引声明
│ ├── schema.ts # 数据库版本管理
│ ├── base-repository.ts # 通用 Repository 基类
│ ├── storage-store.ts # uni.storage 兼容层(小程序降级)
│ ├── migration.ts # v1→v2 加密数据迁移
│ └── engines/
│ ├── types.ts # IStore<T> 统一接口
│ ├── dexie-store.ts # H5 引擎(IndexedDB via Dexie.js)
│ ├── encrypted-store.ts # 透明加密包装器
│ └── ... # SqliteStore 等
│
├── modules/ # 业务模块(60+ 模块目录)
│ ├── task/ # 任务管理
│ │ ├── types.ts # Task, TaskStatus, TaskPriority 等类型
│ │ └── repository.ts # TaskRepository extends BaseRepository
│ ├── calendar/ # 日历
│ ├── habit/ # 习惯
│ ├── finance/ # 财务
│ ├── health/ # 健康
│ ├── knowledge/ # 知识库
│ ├── pomodoro/ # 番茄钟
│ ├── inventory/ # 库存
│ └── ... # 其余 50+ 模块
│
├── stores/ # Pinia 状态管理
│ ├── task.store.ts # 任务 Store
│ ├── calendar.store.ts # 日历 Store
│ ├── habit.store.ts # 习惯 Store
│ ├── note.store.ts # 知识库/便签 Store
│ ├── pomodoro.store.ts # 番茄钟 Store
│ ├── channel.store.ts # 渠道 Store
│ └── mode.store.ts # 生活模式 Store
│
├── sync/ # 同步引擎
│ └── sync-manager.ts # 可插拔 Provider 架构的同步管理器
│
├── services/ # 全局服务层
│ ├── event.service.ts # 事件发射服务(跨模块联动)
│ ├── ai-agent.service.ts # AI Agent 编排服务
│ ├── ai-insight.service.ts # AI 洞察生成服务
│ └── reminder.service.ts # 提醒服务
│
├── pages/ # 页面视图(60+ 页面目录)
│ ├── task/ # 任务页面
│ ├── calendar/ # 日历页面
│ └── ... # 其余页面
│
├── components/ # 通用组件库
│ ├── Layout.vue # 应用主布局
│ ├── TabBar.vue # 底部导航栏
│ ├── default-layout/ # 默认布局组件
│ └── ... # 通用 UI 组件
│
├── hooks/ # 通用 Hooks
│ ├── useSafeArea.ts # 安全区域适配
│ └── useTimePhase.ts # 时间段判断(早/中/晚)
│
├── types/ # 全局类型定义
│ ├── index.ts # 基础类型
│ ├── life-event.ts # 生活事件类型
│ └── entity-relation.ts # 实体关系类型
│
├── data/ # 静态数据
│ └── features.json # 功能模块注册表(62 条目)
│
└── uni_modules/ # uni-app 原生模块
├── biometric-auth2/ # 生物认证(Face ID / 指纹)
└── llama-ai3/ # Llama.cpp 原生 AI 引擎分层设计
Page 层
页面组件只负责两件事:渲染 UI、调用 Store 方法。页面内不应出现直接操作数据库的代码。所有数据读取通过 Store 的 computed/getter,所有数据写入通过 Store 的 action。
// 典型页面组件的交互模式
const taskStore = useTaskStore()
// 读:computed 自动响应
const tasks = computed(() => taskStore.tasks)
// 写:调用 action
await taskStore.addTask({ title: '新任务', priority: 'HIGH' })Store 层
Pinia Store 是业务逻辑的集中点。每个核心模块有一个对应的 Store,持有 Repository 实例,负责:
- 缓存数据到响应式状态(减少数据库读取)
- 提供 action 方法封装复杂业务流程
- 管理 UI 状态(排序方式、筛选条件、当前选中项)
// Store 模式示例
export const useTaskStore = defineStore('task', () => {
const repo = new TaskRepository(getDatabase().tasks)
const tasks = ref([])
async function loadTasks() {
tasks.value = await repo.findAll()
}
// data 类型: Omit Task, keyof BaseEntity
async function addTask(data) {
const task = await repo.create(data)
tasks.value.unshift(task)
emitEvent({
type: 'task_created',
module: 'task',
sourceId: task.id,
title: task.title,
})
return task
}
return { tasks, loadTasks, addTask }
})关键约定:所有成功的写操作(create/update/delete)都应调用 emitEvent 发射生活事件,供全局事件系统消费。
Module 层
每个模块独立一个目录,包含 types.ts 和 repository.ts。模块之间完全解耦——它们共享 BaseEntity 基类和 IStore<T> 接口,但彼此的 Repository 实例互不依赖。
添加新模块的成本
在 features.json 注册 → 创建页面组件 → 创建 src/modules/{name}/ 目录 → 定义 types 和 repository → 创建 Store。无需修改任何已有模块的代码。
Database 层
详细设计见 数据库 Schema 设计。关键架构点:
- IStore<T> 接口统一了 DexieStore / SqliteStore / EncryptedStore 的 API
- BaseRepository<T> 提供了开箱即用的 CRUD + 软删除 + 分页 + 批量操作
- EncryptedStore 通过装饰器模式包装底层引擎,透明加解密
平台适配
uni-app 的条件编译指令是跨平台适配的核心机制。关键适配点:
| 场景 | 策略 | 实现方式 |
|---|---|---|
| 数据库引擎 | App→SQLite,H5→Dexie | #ifdef APP-PLUS / #ifdef H5 条件编译 |
| 端侧 AI | App→Llama.cpp,H5→Transformers.js | uni_modules 条件编译 |
| 生物认证 | App→uni.指纹/面容,H5→降级密码 | Feature detection |
| 文件系统 | App→plus.io,H5→File API | 条件编译 |
| 推送通知 | App→厂商推送,H5→不支持 | 平台预判 |
条件编译发生在构建阶段,编译产物中不包含其他平台的代码,保证包体积最优。
AI 子系统
AI 子系统采用双引擎 + Agent 中间层架构,如下图所示:
用户输入
│
▼
┌──────────────┐ 端侧可用?
│ ai-agent │────yes──▶ pipeline.ts ──▶ Llama.cpp / Transformers.js
│ service.ts │ │
│ (编排层) │ 边缘流式输出
└──────────────┘
│ 端侧不可用
▼
SSE Stream ──▶ 云端 AI API ──▶ 流式响应端侧 AI 引擎
| 平台 | 引擎 | 推理方式 | 模型缓存 |
|---|---|---|---|
| Android / iOS | llama.cpp 原生库 | GPU/NPU 加速 | 本地文件系统 |
| H5 | Transformers.js (ONNX Runtime Web) | WebAssembly + WebGPU | IndexedDB 缓存 |
模型管理:model-manager.ts 负责从 HuggingFace 下载模型文件、校验完整性、维护缓存索引。端侧模型仅首次使用需下载(几百 MB),后续从本地缓存秒开。
云端 AI Agent
ai-agent.service.ts 是 Agent 编排层,负责:
- 接收用户自然语言输入
- 决定路由到端侧 AI 还是云端 AI
- 若路由到云端,发起 SSE 流式请求
- 解析响应中的
[ACTION]标签,提取 JSON 操作指令 - 调用
actions.ts中注册的执行函数,将 AI 意图转化为实际数据操作
Actions 注册表
actions.ts 定义了 20+ 个动作 Schema,每个动作包含:
- name:动作唯一标识(如
record_transaction、create_event) - description:供 AI 理解的描述
- params:参数 Schema(名称、类型、是否必填、枚举值)
- execute:执行函数,调用对应 Store 完成数据操作
// 示例:记账动作
{
name: 'record_transaction',
description: '记录收支',
params: [
{ name: 'type', type: 'string', description: '类型', required: true, enum: ['income', 'expense'] },
{ name: 'amount', type: 'number', description: '金额(元)', required: true },
{ name: 'remark', type: 'string', description: '备注', required: false },
{ name: 'category', type: 'string', description: '分类', required: false },
],
execute: async (payload) => {
return await useFinanceStore().addTransaction({
type: payload.type as TransactionType,
amount: Math.round((payload.amount as number) * 100), // 元→分
remark: payload.remark as string || '',
category: payload.category as string || '其他',
})
},
}Agent Prompt
agent-prompt.ts 构建 System Prompt,包含当前日期、动作 Schema 速查表、使用示范。Prompt 只展示一种 [ACTION] JSON 格式做示例,避免端侧小模型混淆。
同步系统
整体架构
Repositories ──▶ SyncQueue (syncQueue 表)
│
▼
SyncManager
│
▼
SyncProvider (可插拔)
│
┌────┼────┐
▼ ▼ ▼
Gist S3 WebDAV 未来扩展同步队列
每个写操作完成后,Repository 将变更记录写入 syncQueue 表,字段包括 tableName、recordId、operation(create/update/delete)、data(变更数据快照)。
SyncManager
sync-manager.ts 是同步流程的总调度器:
push()— 从syncQueue取待同步记录,批量推送到远端 Providerpull()— 从远端 Provider 拉取变更,merge 到本地resolveConflict()— 基于version字段的乐观锁检测冲突
Provider 架构
同步后端通过 SyncProvider 接口抽象。当前实现为 Local Provider(无远端同步),但接口已预留 push、pull、resolve 三个方法。未来接入 Gist / WebDAV / S3 等后端只需实现此接口即可。
冲突解决
采用乐观锁策略:每条记录有 version 字段。执行 update 时 Repository 自动将 version + 1。同步时若远端版本 > 本地版本,说明有冲突,执行合并策略(最后写入者胜出,保存冲突副本供用户手动选择)。
事件系统
services/event.service.ts 提供全局事件发射能力。任何模块的写操作在完成后都应调用 emitEvent 发射一个 LifeEvent,包含:
| 字段 | 说明 |
|---|---|
type | 事件类型(如 task_created、mood_recorded) |
module | 来源模块 |
sourceId | 源记录 ID |
title | 事件标题 |
description | 事件描述(可选) |
timestamp | 事件时间 |
metadata | 扩展数据(可选) |
事件写入 lifeEvents 表,可供 AI 洞察、统计面板、时间线等模块消费。例如,AI 洞察服务可以通过分析近一周的 task_completed 和 mood_recorded 事件,生成"本周任务完成率 85%,心情指数平均 4.2"的自动摘要。
状态管理
使用 Pinia 做状态管理,采用 Setup Store 语法(Composition API 风格)。当前 7 个 Store 覆盖核心模块:
| Store | 管理范围 | 关键功能 |
|---|---|---|
task.store | 任务管理 | CRUD、分类筛选、拖拽排序 |
calendar.store | 日历事件 | 事件 CRUD、时间范围查询 |
habit.store | 习惯打卡 | 习惯定义、每日打卡、统计 |
note.store | 知识库/便签 | 笔记 CRUD、笔记本管理 |
pomodoro.store | 番茄钟 | 计时器、历史统计、设置 |
channel.store | 渠道管理 | 渠道 CRUD |
mode.store | 生活模式 | 模式切换、预设管理 |
Store 之间通过 Pinia 的 useXxxStore() 互相引用,而非依赖注入。每个 Store 持有对应 Repository 的实例,所有写操作自动触发 emitEvent。
离线优先数据流
爱生活 的核心设计哲学:网络是可选的增强,而非必需品。具体体现:
- 本地优先写入 — 用户操作立即写入本地数据库(SQLite/IndexedDB),同步到远端是异步的后台任务
- 本地优先读取 — 所有页面展示的数据来自本地数据库,不依赖网络请求
- AI 离线可用 — 端侧 AI 引擎在无网络时照常工作,云端 AI 仅在用户主动调用且网络可用时使用
- 同步滞后可接受 — 离线期间积累的变更在恢复网络后批量同步
用户操作
│
▼
Store action ──▶ Repository.create/update/delete()
│
┌───┴───┐
▼ ▼
本地写入 push 到 syncQueue
(即时完成) (异步后台)
│
▼
SyncManager
│
(有网络时)
▼
远端同步这种设计意味着飞机上、地铁里、信号盲区——所有核心功能依然可用。唯一的区别是同步队列中的记录数会增长,恢复网络后自动清空。