From 26048dc12ef957b503ea97dc76aff98afb50f1e9 Mon Sep 17 00:00:00 2001 From: BTMuli Date: Mon, 24 Apr 2023 21:50:58 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(db):=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=BA=90=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/database/TGSqlite.ts | 14 ++++ src/core/database/UIAF.ts | 86 ++++++++++++++++++++++++ src/core/database/init.sql | 2 +- src/core/database/select.ts | 71 ++++++++++++++++++++ src/pages/Achievements.vue | 119 ++++++++-------------------------- src/pages/Config.vue | 25 +++++-- src/types/Achievement.d.ts | 2 +- src/utils/UIAF.ts | 59 +++-------------- 8 files changed, 229 insertions(+), 149 deletions(-) create mode 100644 src/core/database/UIAF.ts create mode 100644 src/core/database/select.ts diff --git a/src/core/database/TGSqlite.ts b/src/core/database/TGSqlite.ts index 45dd6ec5..a5f447a9 100644 --- a/src/core/database/TGSqlite.ts +++ b/src/core/database/TGSqlite.ts @@ -6,12 +6,26 @@ */ import { initDatabase, resetDatabase, checkDatabase, sqlitePath } from "./init"; +import { getAllSeries, getAchievementsBySeries, searchAchievement, getAchievementOverview } from "./select"; +import { importUIAFData, exportUIAFData } from "./UIAF"; import { checkAchievement, checkAchievementSeries } from "./update"; const TGSqlite = { initDB: initDatabase, resetDB: resetDatabase, checkDB: checkDatabase, + search: { + achievement: { + bySeries: getAchievementsBySeries, + bySearch: searchAchievement, + }, + achievementSeries: getAllSeries, + overview: getAchievementOverview, + }, + UIAF: { + import: importUIAFData, + export: exportUIAFData, + }, update: { achievement: checkAchievement, achievementSeries: checkAchievementSeries, diff --git a/src/core/database/UIAF.ts b/src/core/database/UIAF.ts new file mode 100644 index 00000000..6cf81b44 --- /dev/null +++ b/src/core/database/UIAF.ts @@ -0,0 +1,86 @@ +/** + * @file core database UIAF.ts + * @description UIAF 数据导入导出 + * @author BTMuli + * @since Alpha v0.1.4 + */ + +// tauri +import Database from "tauri-plugin-sql-api"; +// local +import { sqlitePath } from "./init"; +// utils +import { timestampToDate, getUiafStatus } from "../../utils/UIAF"; + +/** + * @description 根据本地数据跟导入数据获取更新 SQL + * @since Alpha v0.1.4 + * @param {TGPlugin.UIAF.Achievement} importData - 导入数据 + * @param {BTMuli.SQLite.Achievements} localData - 本地数据 + * @returns {string} SQL + */ +function getUpdateSql (importData: TGPlugin.UIAF.Achievement, localData: BTMuli.SQLite.Achievements): string { + // 如果本地为未完成状态,直接更新 + if (localData.isCompleted === 0) { + // 已完成 + if (importData.status === 2 || importData.status === 3) { + const completedTime = timestampToDate(importData.timestamp); + return `UPDATE Achievements SET isCompleted = 1, progress = ${importData.current}, completedTime = '${completedTime}' WHERE id = ${importData.id}`; + } else if (importData.current > localData.progress) { + return `UPDATE Achievements SET progress = ${importData.current} WHERE id = ${importData.id}`; + } else { + return ""; + } + } else { + // 本地为已完成状态,判断进度 + if (importData.current > localData.progress) { + // 进度大于本地进度,更新 + return `UPDATE Achievements SET progress = ${importData.current} WHERE id = ${importData.id}`; + } else { + return ""; + } + } +} + +/** + * @description 导入 UIAF 数据,更新数据库 + * @since Alpha v0.1.4 + * @param {TGPlugin.UIAF.Achievement[]} achievements - 成就列表 + * @returns {Promise} + */ +export async function importUIAFData (achievements: TGPlugin.UIAF.Achievement[]): Promise { + const db = await Database.load(sqlitePath); + for (const achievement of achievements) { + const id = achievement.id; + const selects: BTMuli.SQLite.Achievements[] = await db.select(`SELECT * FROM Achievements WHERE id = ${id}`); + if (selects.length === 1) { + const sql = getUpdateSql(achievement, selects[0]); + if (sql !== "") await db.execute(sql); + } + } + await db.close(); +} + +/** + * @description 导出 UIAF 数据 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function exportUIAFData (): Promise { + const db = await Database.load(sqlitePath); + const sql = "SELECT * FROM Achievements WHERE isCompleted = 1 OR progress > 0"; + const selects: BTMuli.SQLite.Achievements[] = await db.select(sql); + await db.close(); + const achievements: TGPlugin.UIAF.Achievement[] = []; + for (const select of selects) { + const completed = select.isCompleted === 1; + const status = getUiafStatus(completed, select.progress); + achievements.push({ + id: select.id, + status, + timestamp: completed && select.completedTime ? Math.round(new Date(select.completedTime).getTime() / 1000) : 0, + current: select.progress, + }); + } + return achievements; +} diff --git a/src/core/database/init.sql b/src/core/database/init.sql index 22f72a6f..b73014ae 100644 --- a/src/core/database/init.sql +++ b/src/core/database/init.sql @@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS AchievementSeries version TEXT DEFAULT NULL, totalCount INTEGER DEFAULT 0, finCount INTEGER DEFAULT 0, - icon TEXT DEFAULT NULL, + icon TEXT NOT NULL, nameCard TEXT DEFAULT NULL, updated TEXT DEFAULT NULL ); diff --git a/src/core/database/select.ts b/src/core/database/select.ts new file mode 100644 index 00000000..b8754a39 --- /dev/null +++ b/src/core/database/select.ts @@ -0,0 +1,71 @@ +/** + * @file core database select.ts + * @description SQLite 数据库查询操作封装模块 + * @author BTMuli + * @since Alpha v0.1.4 + */ + +// tauri +import Database from "tauri-plugin-sql-api"; +// local +import { sqlitePath } from "./init"; + +/** + * @description 返回所有成就系列数据 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function getAllSeries (): Promise { + const db = await Database.load(sqlitePath); + const sql = "SELECT * FROM AchievementSeries ORDER BY `order` ASC"; + const result = await db.select(sql); + await db.close(); + return result as BTMuli.SQLite.AchievementSeries[]; +} + +/** + * @description 查询成就数据,无参默认查询所有成就 + * @since Alpha v0.1.4 + * @param {number} series + * @returns {Promise} + */ +export async function getAchievementsBySeries (series?: number): Promise { + const db = await Database.load(sqlitePath); + let sql; + // 无参默认查询所有成就 + if (!series) { + sql = "SELECT * FROM Achievements"; + } else { + sql = `SELECT * FROM Achievements WHERE series = ${series}`; + } + const result = await db.select(sql); + await db.close(); + return result as BTMuli.SQLite.Achievements[]; +} + +/** + * @description 条件查询 + * @since Alpha v0.1.4 + * @param {string} search + * @returns {Promise} + */ +export async function searchAchievement (search: string): Promise { + const db = await Database.load(sqlitePath); + const sql = `SELECT * FROM Achievements WHERE name LIKE '%${search}%' AND description LIKE '%${search}%'`; + const result = await db.select(sql); + await db.close(); + return result as BTMuli.SQLite.Achievements[]; +} + +/** + * @description 返回成就概况 + * @since Alpha v0.1.4 + * @returns {Promise<{total: number, fin:number}>} + */ +export async function getAchievementOverview (): Promise<{ total: number, fin: number }> { + const db = await Database.load(sqlitePath); + const sql = "SELECT COUNT(*) AS total, SUM(isCompleted) AS fin FROM Achievements"; + const res: Array<{ total: number, fin: number }> = await db.select(sql); + await db.close(); + return res[0]; +} diff --git a/src/pages/Achievements.vue b/src/pages/Achievements.vue index c5afd896..d0445041 100644 --- a/src/pages/Achievements.vue +++ b/src/pages/Achievements.vue @@ -39,7 +39,7 @@ {{ series.name }} - {{ series.completed_count }} / {{ series.total_count }} + {{ series.finCount }} / {{ series.totalCount }} @@ -72,9 +72,9 @@ @@ -83,7 +83,7 @@ {{ achievement.description }}