diff --git a/src/core/database/TGSqlite.ts b/src/core/database/TGSqlite.ts new file mode 100644 index 00000000..c5303867 --- /dev/null +++ b/src/core/database/TGSqlite.ts @@ -0,0 +1,22 @@ +/** + * @file core database TGSqlite.ts + * @description SQLite 数据库相关 + * @author BTMuli + * @since Alpha v0.1.4 + */ + +import { initDatabase } from "./init"; +import { checkAchievement, checkAchievementSeries } from "./update"; +import { deleteDatabase, checkDatabase } from "./utils"; + +const TGSqlite = { + clearDB: deleteDatabase, + initDB: initDatabase, + checkDB: checkDatabase, + update: { + achievement: checkAchievement, + achievementSeries: checkAchievementSeries, + }, +}; + +export default TGSqlite; diff --git a/src/core/database/init.sql b/src/core/database/init.sql new file mode 100644 index 00000000..22f72a6f --- /dev/null +++ b/src/core/database/init.sql @@ -0,0 +1,142 @@ +/* + * @file core database init.sql + * @description SQLite 初始化 + * @author BTMuli + * @since Alpha v0.1.4 + */ + +-- ///////////////////////////// +-- 创建各种表 +-- ///////////////////////////// +-- ---------------------------- +-- 成就系列表 +-- @table AchievementSeries +-- @field {number} id 成就系列ID,主键 +-- @field {number} order 成就系列排列顺序 +-- @field {string} name 成就系列名称 +-- @field {string} version 成就系列版本 +-- @field {number} totalCount 成就系列总成就数 +-- @field {number} finCount 成就系列已完成成就数 +-- @field {string} icon 成就系列图标 +-- @field {string} nameCard 成就系列名片名称 +-- @field {string} updated 数据更新时间 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS AchievementSeries +( + id INTEGER PRIMARY KEY, + "order" INTEGER, + name TEXT DEFAULT NULL, + version TEXT DEFAULT NULL, + totalCount INTEGER DEFAULT 0, + finCount INTEGER DEFAULT 0, + icon TEXT DEFAULT NULL, + nameCard TEXT DEFAULT NULL, + updated TEXT DEFAULT NULL +); +-- ---------------------------- +-- 成就数据表 +-- @table Achievements +-- @field {number} id 成就ID,主键 +-- @field {number} series 成就系列ID,为成就系列表的主键 +-- @field {number} order 成就排序 +-- @field {string} name 成就名称 +-- @field {string} description 成就描述 +-- @field {number} reward 成就奖励 +-- @field {boolean} isCompleted 成就是否已完成,默认为false +-- @field {string} completedTime 成就完成时间,默认为null +-- @field {number} progress 成就进度,默认为0 +-- @field {string} version 成就版本 +-- @field {string} updated 数据更新时间 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS Achievements +( + id INTEGER PRIMARY KEY, + series INTEGER, + "order" INTEGER, + name TEXT DEFAULT NULL, + description TEXT DEFAULT NULL, + reward INTEGER DEFAULT 0, + isCompleted BOOLEAN DEFAULT 0, + completedTime TEXT DEFAULT NULL, + progress INTEGER DEFAULT 0, + version TEXT DEFAULT NULL, + updated TEXT DEFAULT NULL +); + +-- ///////////////////////////// +-- 创建各种触发器 +-- ///////////////////////////// +-- ---------------------------- +-- 成就系列数据插入触发器 +-- @trigger SeriesInsert +-- @description 当成就系列数据插入时,更新更新时间 +-- ---------------------------- +CREATE TRIGGER IF NOT EXISTS SeriesInsert + AFTER INSERT + ON AchievementSeries + FOR EACH ROW +BEGIN + UPDATE AchievementSeries SET updated = datetime('now') WHERE id = NEW.id; +END; +-- ---------------------------- +-- 成就系列数据更新触发器 +-- @trigger SeriesUpdate +-- @description 当成就系列数据更新时,更新更新时间 +-- ---------------------------- +CREATE TRIGGER IF NOT EXISTS SeriesUpdate + AFTER UPDATE + OF totalCount, finCount, version + ON AchievementSeries + FOR EACH ROW +BEGIN + UPDATE AchievementSeries SET updated = datetime('now') WHERE id = NEW.id; +END; +-- ---------------------------- +-- 成就数据插入触发器 +-- @trigger AchievementInsert +-- @description 当成就数据插入时,更新成就系列表中的数据 +-- ---------------------------- +CREATE TRIGGER IF NOT EXISTS AchievementInsert + AFTER INSERT + ON Achievements + FOR EACH ROW +BEGIN + -- 更新更新时间 + UPDATE Achievements SET updated = datetime('now') WHERE id = NEW.id; + -- 更新成就系列总数 + UPDATE AchievementSeries SET totalCount = AchievementSeries.totalCount + 1 WHERE id = NEW.series; + -- 如果是已完成成就,则更新成就系列完成数 + UPDATE AchievementSeries + SET finCount = AchievementSeries.finCount + 1 + WHERE NEW.isCompleted = 1 AND id = NEW.series; + -- 如果成就系列版本低于成就版本,则更新成就系列版本 + UPDATE AchievementSeries SET version = NEW.version WHERE version < NEW.version AND id = NEW.series; +END; +-- ---------------------------- +-- 成就数据更新触发器 +-- @trigger AchievementUpdate +-- @description 当成就数据更新时,更新成就系列表中的数据 +-- ---------------------------- +CREATE TRIGGER IF NOT EXISTS AchievementUpdate + AFTER UPDATE + OF isCompleted, completedTime, progress + ON Achievements + FOR EACH ROW +BEGIN + -- 更新更新时间 + UPDATE Achievements + SET updated = datetime('now') + WHERE id = NEW.id; + -- 如果是已完成成就,则更新成就系列完成数 + UPDATE AchievementSeries + SET finCount = AchievementSeries.finCount + 1 + WHERE id = NEW.series + AND OLD.isCompleted = 0 + AND NEW.isCompleted = 1; + -- 如果是未完成成就,则更新成就系列完成数 + UPDATE AchievementSeries + SET finCount = AchievementSeries.finCount - 1 + WHERE id = NEW.series + AND OLD.isCompleted = 1 + AND NEW.isCompleted = 0; +END; diff --git a/src/core/database/init.ts b/src/core/database/init.ts new file mode 100644 index 00000000..421f29c3 --- /dev/null +++ b/src/core/database/init.ts @@ -0,0 +1,23 @@ +/** + * @file core database init.ts + * @description SQLite 数据库初始化 + * @author BTMuli + * @since Alpha v0.1.4 + */ + +// tauri +import Database from "tauri-plugin-sql-api"; +// sql +import initSql from "./init.sql?raw"; + +/** + * @description 初始化数据库 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function initDatabase (): Promise { + const db = await Database.load("sqlite:tauri-genshin.db"); + // 执行sql语句 + await db.execute(initSql); + await db.close(); +} diff --git a/src/core/database/update.ts b/src/core/database/update.ts new file mode 100644 index 00000000..00bd7789 --- /dev/null +++ b/src/core/database/update.ts @@ -0,0 +1,63 @@ +/** + * @file core database update.ts + * @description SQLite 数据库更新相关 + * @since Alpha v0.1.4 + */ + +// tauri +import Database from "tauri-plugin-sql-api"; +// local +import { TGAppData } from "../../data"; + +/** + * @description 数据比对-成就系列数据 + * @description 数据只有两种情况:新增、更新 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function checkAchievement (): Promise { + const db = await Database.load("sqlite:tauri-genshin.db"); + Object.values(TGAppData.achievements).map(async (item) => { + // 检测是否存在 + const selectRes: BTMuli.SQLite.Achievements[] = await db.select(`SELECT * FROM achievement WHERE id = ${item.id}`); + if (!selectRes || selectRes.length === 0) { + // 不存在则插入 + const sql = `INSERT INTO Achievements (id, series, \`order\`, name, description, reward, version) VALUES (${item.id}, ${item.series}, ${item.order}, '${item.name}', '${item.description}', ${item.reward}, '${item.version}')`; + await db.execute(sql); + } else { + // 比对两者数据 + const selectItem = selectRes[0]; + if (selectItem.name !== item.name || selectItem.description !== item.description || selectItem.reward !== item.reward) { + // 更新 + const sql = `UPDATE Achievements SET name = '${item.name}', description = '${item.description}', reward = ${item.reward}, version = '${item.version}' WHERE id = ${item.id}`; + await db.execute(sql); + } + } + }); + await db.close(); +} + +/** + * @description 数据比对-成就系列数据 + * @description 只有新增,更新靠触发器解决 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function checkAchievementSeries (): Promise { + const db = await Database.load("sqlite:tauri-genshin.db"); + Object.values(TGAppData.achievementSeries).map(async (item) => { + // 检测是否存在 + const selectRes: BTMuli.SQLite.AchievementSeries[] = await db.select(`SELECT * FROM achievement_series WHERE id = ${item.id}`); + if (!selectRes || selectRes.length === 0) { + // 不存在则插入 + let sql; + if (item.card) { + sql = `INSERT INTO AchievementSeries (id, \`order\`, name, version, icon, nameCard) VALUES (${item.id}, ${item.order}, '${item.name}', '${item.version}', '${item.icon}', '${item.card}')`; + } else { + sql = `INSERT INTO AchievementSeries (id, \`order\`, name, version, icon) VALUES (${item.id}, ${item.order}, '${item.name}', '${item.version}', '${item.icon}')`; + } + await db.execute(sql); + } + }); + await db.close(); +} diff --git a/src/core/database/utils.ts b/src/core/database/utils.ts new file mode 100644 index 00000000..3ab2e893 --- /dev/null +++ b/src/core/database/utils.ts @@ -0,0 +1,28 @@ +/** + * @file core database utils.ts + * @description SQLite 数据库相关工具函数 + * @since Alpha v0.1.4 + */ + +// tauri +import { fs } from "@tauri-apps/api"; + +/** + * @description 检测数据库是否存在 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function checkDatabase (): Promise { + return await fs.exists("tauri-genshin.db", { dir: fs.BaseDirectory.AppConfig }); +} + +/** + * @description 删除数据库 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function deleteDatabase (): Promise { + if (await checkDatabase()) { + await fs.removeFile("tauri-genshin.db", { dir: fs.BaseDirectory.AppConfig }); + } +} diff --git a/src/types/Achievement.d.ts b/src/types/Achievement.d.ts index 4452f08a..c1ef2cf3 100644 --- a/src/types/Achievement.d.ts +++ b/src/types/Achievement.d.ts @@ -109,3 +109,63 @@ declare namespace TGPlugin.UIAF { status: number } } + +declare namespace BTMuli.SQLite { + /** + * @description 数据库-成就表 + * @since Alpha v0.1.4 + * @interface Achievements + * @property {number} id - 成就 ID + * @property {number} series - 成就系列 ID + * @property {number} order - 成就排列顺序,用于展示全部成就 + * @property {string} name - 成就名称 + * @property {string} description - 成就描述 + * @property {number} reward - 成就奖励 + * @property {number} isCompleted - 成就是否完成 + * @property {string} completedTime - 成就完成时间 + * @property {number} progress - 成就进度 + * @property {string} version - 成就版本 + * @property {string} updated - 数据库更新时间 + * @return Achievements + */ + export interface Achievements { + id: number + series: number + order: number + name: string | null + description: string | null + reward: number + isCompleted: 0 | 1 + completedTime: string | null + progress: number + version: string | null + updated: string | null + } + + /** + * @description 数据库-成就系列表 + * @since Alpha v0.1.4 + * @interface AchievementSeries + * @property {number} id - 成就系列 ID + * @property {number} order - 成就系列排列顺序,用于展示全部成就系列 + * @property {string} name - 成就系列名称 + * @property {string} version - 成就系列版本 + * @property {number} totalConut - 成就系列包含的成就数 + * @property {number} finCount - 成就系列已完成的成就数 + * @property {string} icon - 成就系列图标 + * @property {string} nameCard - 成就系列对应名片 + * @property {string} updated - 数据库更新时间 + * @returns AchievementSeries + */ + export interface AchievementSeries { + id: number + order: number + name: string | null + version: string | null + totalCount: number + finCount: number + icon: string | null + nameCard: string | null + updated: string | null + } +}