FrontTools/DBManager/DBManagerReadme.md
Rain 3ab1f2db24 [入库]初次入库各种工具
- DBManager DB创建管理器
- FormatTimeTool
- ImageViewer工具
- InputArear工具
- OverlayPage工具
- 下拉刷新容器工具
- 视频查看器工具
2026-04-02 16:09:00 +08:00

5.7 KiB
Raw Blame History

DBManager (SQLite 封装工具类)

DBManager 是基于 plus.sqlite 的 Promise 化封装,旨在简化 App 端本地数据库的操作。它支持自动建表、自动创建索引、以及 JSON 字段的自动序列化/反序列化。

# 核心特性

  • 开箱即用open() 时自动检测并创建数据库、表结构和索引。
  • 配置灵活:通过 DBSchema 接口纯配置化定义表结构。
  • JSON 友好:配置 jsonFields 后,无需手动 JSON.stringify/parse,直接存取对象。
  • Promise 封装:支持 async/await,告别回调地狱。
  • 批量操作:内置事务支持,提升批量插入性能。

⚙️ 配置说明 (DBSchema)

在使用前,你需要定义一个 DBSchema 对象。

export interface DBSchema {
  /** 数据库逻辑名称 (如: 'chat_db') */
  dbName: string;
  /** 数据库文件路径 (推荐: '_doc/xxx.db') */
  dbPath: string;
  /** 表名 */
  tableName: string;
  /** 
   * 建表列定义 (标准 SQL 语法)
   * 必须在此处定义 PRIMARY KEY
   */
  columns: string;
  /** 
   * 需要创建索引的字段列表 
   * 支持单字段: ['timestamp']
   * 支持组合索引: ['user_id, timestamp']
   */
  indexes?: string[];
  /** 
   * 需要自动 JSON 序列化的字段名
   * 对应的 columns 类型建议为 TEXT
   */
  jsonFields?: string[];
}

📝 填表案例 (Schema Examples)

以下是几种常见业务场景的配置写法:

场景一:聊天记录表 (标准场景)

  • 需求:使用 UUID 字符串作为主键,存储消息内容,其中 mediaextra 字段存储复杂的 JSON 对象,需要按会话 ID 和时间查询。
const ChatSchema: DBSchema = {
  dbName: 'im_core',
  dbPath: '_doc/im_core.db',
  tableName: 'messages',
  
  // 定义列:注意 media 和 extra 定义为 TEXT 以存储 JSON 字符串
  columns: `
    guid TEXT PRIMARY KEY,
    session_id TEXT,
    sender_id TEXT,
    content TEXT,
    msg_type INTEGER,
    media TEXT,
    extra TEXT,
    is_read INTEGER,
    timestamp INTEGER
  `,
  
  // 定义索引:加快查询速度
  indexes: [
    'timestamp',               // 按时间排序
    'session_id, timestamp'    // 获取某个会话的历史记录 (组合索引)
  ],
  
  // 自动转换:存入时自动 stringify取出时自动 parse
  jsonFields: ['media', 'extra']
};

场景二:待办事项表 (自增主键)

  • 需求简单的任务列表ID 需要自动递增。
const TodoSchema: DBSchema = {
  dbName: 'todo_app',
  dbPath: '_doc/todo.db',
  tableName: 'tasks',
  
  // 使用 SQLite 的自增语法
  columns: `
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT,
    is_completed INTEGER,
    created_at INTEGER
  `,
  
  indexes: ['is_completed']
};

场景三:用户关系表 (联合主键)

  • 需求:存储群组成员关系,一个用户在一个群里只能有一条记录(user_id + group_id 唯一)。
const MemberSchema: DBSchema = {
  dbName: 'relation_db',
  dbPath: '_doc/relation.db',
  tableName: 'group_members',
  
  // 在末尾定义联合主键
  columns: `
    group_id TEXT,
    user_id TEXT,
    nickname TEXT,
    role TEXT,
    join_time INTEGER,
    PRIMARY KEY (group_id, user_id)
  `,
  
  indexes: ['user_id'] // group_id 已经在主键索引里了,不需要单独建
};

🚀 快速开始

1. 初始化

推荐在 Store 或 Service 层创建一个单例实例。

import { DBManager, DBSchema } from './utils/DBManager';

// 1. 定义配置
const config: DBSchema = { /* 参考上面的案例 */ };

// 2. 创建实例
export const ChatDB = new DBManager(config);

// 3. 打开数据库 (通常在 App 启动或登录后调用)
await ChatDB.open();

2. 插入/更新数据 (Upsert)

使用 Upsert 方法,如果主键存在则更新,不存在则插入。 注意:可以直接传入包含对象的 JSON 字段,无需手动转换。

const msg = {
  guid: 'msg_1001',
  session_id: 'sess_a',
  content: 'Hello World',
  timestamp: 1679000000,
  is_read: true, // 会自动转为 1
  // 这里的 media 对象会自动转为字符串存入数据库
  media: { 
    type: 'image', 
    url: 'https://xxx.com/img.png', 
    width: 100 
  }
};

await ChatDB.Upsert(msg);

3. 查询数据 (Find)

支持 whereorderBylimitoffset

const history = await ChatDB.find({
  where: { 
    session_id: 'sess_a',
    // 支持简单的比较操作符 (需在 key 中包含空格)
    'timestamp <': 1679999999 
  },
  orderBy: 'timestamp DESC',
  limit: 20
});

// history[0].media 会自动被还原为对象
console.log(history[0].media.url); 

4. 复杂查询 (Raw SQL)

如果内置方法无法满足需求(如模糊搜索),可执行原生 SQL。

// 模糊搜索示例
const keyword = '测试';
// 注意手动处理 SQL 转义,防止单引号报错
const safeKeyword = keyword.replace(/'/g, "''");

const sql = `
  SELECT * FROM messages 
  WHERE content LIKE '%${safeKeyword}%' 
  ORDER BY timestamp DESC
`;

const res = await ChatDB.queryRaw(sql);

⚠️ 注意事项

  1. 修改表结构SQLite 不支持直接修改列类型或删除列。如果修改了 DBSchemacolumns,通常需要卸载 App 或手动迁移数据(ALTER TABLE ADD COLUMN 可通过 executeSql 手动执行)。
  2. 布尔值SQLite 没有 Boolean 类型,本工具会自动将 true/false 转换为 1/0 存储。
  3. 单引号转义:在使用 queryRaw 手动拼接 SQL 时,务必使用 .replace(/'/g, "''") 处理字符串参数,防止 SQL 报错或注入。