tasks.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // 任务数据访问层
  2. //
  3. // 替代之前的 src/mocks/tasks.ts,所有数据落 SQLite(@tauri-apps/plugin-sql)。
  4. // 数据库名与 src-tauri/src/lib.rs 中的 migration 一致:sqlite:autorecord.db
  5. //
  6. // 表结构(migration v1):
  7. // id TEXT PRIMARY KEY -- uuid 缩短到 12 位
  8. // url TEXT NOT NULL
  9. // status INT NOT NULL DEFAULT 0 -- 0=待处理, 1=已完成
  10. // "desc" TEXT NOT NULL DEFAULT '' -- DESC 是 SQLite 关键字,列名要带引号
  11. import Database from "@tauri-apps/plugin-sql";
  12. const DB_URI = "sqlite:autorecord.db";
  13. /** 任务行结构(与 SQLite 表一一对应) */
  14. export interface Task {
  15. /** 任务唯一标识(uuid 截短 12 位) */
  16. id: string;
  17. /** 目标网页 url */
  18. url: string;
  19. /** 0=待处理(出现在主列表),1=已完成(隐藏) */
  20. status: number;
  21. /** 备注(当前导入流程统一留空,后续可补) */
  22. desc: string;
  23. }
  24. let _dbPromise: Promise<Database> | null = null;
  25. /** 单例:第一次调用时打开 DB,后续复用同一个连接 */
  26. function getDb(): Promise<Database> {
  27. if (!_dbPromise) {
  28. _dbPromise = Database.load(DB_URI);
  29. }
  30. return _dbPromise;
  31. }
  32. /** 生成 12 位的短 uuid(去掉连字符后取前 12 位) */
  33. export function genTaskId(): string {
  34. // crypto.randomUUID 在所有现代 WebView2/WKWebView 上都可用
  35. return crypto.randomUUID().replace(/-/g, "").slice(0, 12);
  36. }
  37. /** 列出所有 status=0 的待处理任务,按 rowid 升序(= 插入顺序) */
  38. export async function listPendingTasks(): Promise<Task[]> {
  39. const db = await getDb();
  40. return await db.select<Task[]>(
  41. 'SELECT id, url, status, "desc" FROM tasks WHERE status = 0 ORDER BY rowid ASC',
  42. );
  43. }
  44. /** 统计 status=0 的任务数量,供「空表 → 拉起导入窗口」判断 */
  45. export async function countPendingTasks(): Promise<number> {
  46. const db = await getDb();
  47. const rows = await db.select<{ n: number }[]>(
  48. "SELECT COUNT(*) AS n FROM tasks WHERE status = 0",
  49. );
  50. return rows[0]?.n ?? 0;
  51. }
  52. /**
  53. * 批量插入 url(desc 全部留空)。
  54. * - 自动去除空白行
  55. * - 自动去除 url 两端空白
  56. * - id 用 12 位短 uuid
  57. * 返回实际插入的条数。
  58. */
  59. export async function insertTasksFromUrls(rawUrls: string[]): Promise<number> {
  60. const urls = rawUrls.map((s) => s.trim()).filter((s) => s.length > 0);
  61. if (urls.length === 0) return 0;
  62. const db = await getDb();
  63. // plugin-sql 不直接暴露事务,循环 execute 即可。批量量不大,性能足够。
  64. for (const url of urls) {
  65. await db.execute(
  66. 'INSERT INTO tasks (id, url, status, "desc") VALUES ($1, $2, 0, \'\')',
  67. [genTaskId(), url],
  68. );
  69. }
  70. return urls.length;
  71. }
  72. /** 把指定任务标记为完成(status=1),不再出现在主列表 */
  73. export async function markTaskDone(id: string): Promise<void> {
  74. const db = await getDb();
  75. await db.execute("UPDATE tasks SET status = 1 WHERE id = $1", [id]);
  76. }