diff --git a/src/core/database/TGSqlite.ts b/src/core/database/TGSqlite.ts index c5303867..45dd6ec5 100644 --- a/src/core/database/TGSqlite.ts +++ b/src/core/database/TGSqlite.ts @@ -5,18 +5,18 @@ * @since Alpha v0.1.4 */ -import { initDatabase } from "./init"; +import { initDatabase, resetDatabase, checkDatabase, sqlitePath } from "./init"; import { checkAchievement, checkAchievementSeries } from "./update"; -import { deleteDatabase, checkDatabase } from "./utils"; const TGSqlite = { - clearDB: deleteDatabase, initDB: initDatabase, + resetDB: resetDatabase, checkDB: checkDatabase, update: { achievement: checkAchievement, achievementSeries: checkAchievementSeries, }, + dbPath: sqlitePath, }; export default TGSqlite; diff --git a/src/core/database/init.ts b/src/core/database/init.ts index 421f29c3..525c38f9 100644 --- a/src/core/database/init.ts +++ b/src/core/database/init.ts @@ -9,6 +9,12 @@ import Database from "tauri-plugin-sql-api"; // sql import initSql from "./init.sql?raw"; +// local +import { TGAppData } from "../../data"; + +export const sqlitePath = "sqlite:tauri-genshin.db"; +export const sqliteTBList = ["Achievements", "AchievementSeries"]; +export const sqliteTGList = ["SeriesInsert", "SeriesUpdate", "AchievementInsert", "AchievementUpdate"]; /** * @description 初始化数据库 @@ -16,8 +22,78 @@ import initSql from "./init.sql?raw"; * @returns {Promise} */ export async function initDatabase (): Promise { - const db = await Database.load("sqlite:tauri-genshin.db"); - // 执行sql语句 + const db = await Database.load(sqlitePath); + // 初始化表格、触发器 await db.execute(initSql); + // 初始化数据 + await insertData(db); await db.close(); } + +/** + * @description 初始化数据 + * @since Alpha v0.1.4 + * @param {Database} db + * @returns {Promise} + */ +async function insertData (db: Database): Promise { + // 插入成就系列数据 + await Promise.all(Object.values(TGAppData.achievementSeries).map(async (item) => { + 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, nameCard) VALUES (${item.id}, ${item.order}, '${item.name}', '${item.version}', '${item.icon}', NULL)`; + } + await db.execute(sql); + }, + )); + // 插入成就数据 + await Promise.all(Object.values(TGAppData.achievements).map(async (item) => { + 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); + }, + )); +}; + +/** + * @description 删除所有数据,重新创建数据 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function resetDatabase (): Promise { + const db = await Database.load(sqlitePath); + // 删除所有触发器 + await Promise.all(sqliteTGList.map(async (trigger) => { + await db.execute(`DROP TRIGGER IF EXISTS ${trigger}`); + })); + // 删除所有表格 + await Promise.all(sqliteTBList.map(async (table) => { + await db.execute(`DROP TABLE IF EXISTS ${table}`); + })); + await db.close(); + await initDatabase(); +} + +/** + * @description 检测表单是否完整 + * @since Alpha v0.1.4 + * @returns {Promise} + */ +export async function checkDatabase (): Promise { + const db = await Database.load(sqlitePath); + // 获取所有表格 + const tables: Array<{ name: string }> = await db.select("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"); + // 获取所有触发器 + const triggers: Array<{ name: string }> = await db.select("SELECT name FROM sqlite_master WHERE type='trigger' ORDER BY name"); + await db.close(); + let res; + if (tables.length !== sqliteTBList.length || triggers.length !== sqliteTGList.length) { + res = false; + } else if (tables.every((item) => sqliteTBList.includes(item.name)) && triggers.every((item) => sqliteTGList.includes(item.name))) { + res = true; + } else { + res = false; + } + return res; +} diff --git a/src/core/database/update.ts b/src/core/database/update.ts index 00bd7789..82d88db1 100644 --- a/src/core/database/update.ts +++ b/src/core/database/update.ts @@ -8,6 +8,7 @@ import Database from "tauri-plugin-sql-api"; // local import { TGAppData } from "../../data"; +import { sqlitePath } from "./init"; /** * @description 数据比对-成就系列数据 @@ -16,10 +17,10 @@ import { TGAppData } from "../../data"; * @returns {Promise} */ export async function checkAchievement (): Promise { - const db = await Database.load("sqlite:tauri-genshin.db"); - Object.values(TGAppData.achievements).map(async (item) => { + const db = await Database.load(sqlitePath); + await Promise.all(Object.values(TGAppData.achievements).map(async (item) => { // 检测是否存在 - const selectRes: BTMuli.SQLite.Achievements[] = await db.select(`SELECT * FROM achievement WHERE id = ${item.id}`); + const selectRes: BTMuli.SQLite.Achievements[] = await db.select(`SELECT * FROM Achievements 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}')`; @@ -33,7 +34,7 @@ export async function checkAchievement (): Promise { await db.execute(sql); } } - }); + })); await db.close(); } @@ -44,20 +45,20 @@ export async function checkAchievement (): Promise { * @returns {Promise} */ export async function checkAchievementSeries (): Promise { - const db = await Database.load("sqlite:tauri-genshin.db"); - Object.values(TGAppData.achievementSeries).map(async (item) => { + const db = await Database.load(sqlitePath); + await Promise.all(Object.values(TGAppData.achievementSeries).map(async (item) => { // 检测是否存在 - const selectRes: BTMuli.SQLite.AchievementSeries[] = await db.select(`SELECT * FROM achievement_series WHERE id = ${item.id}`); + const selectRes: BTMuli.SQLite.AchievementSeries[] = await db.select(`SELECT * FROM AchievementSeries 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}')`; + sql = `INSERT INTO AchievementSeries (id, \`order\`, name, version, icon, nameCard) VALUES (${item.id}, ${item.order}, '${item.name}', '${item.version}', '${item.icon}', NULL)`; } await db.execute(sql); } - }); + })); await db.close(); } diff --git a/src/core/database/utils.ts b/src/core/database/utils.ts deleted file mode 100644 index 3ab2e893..00000000 --- a/src/core/database/utils.ts +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @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/pages/Config.vue b/src/pages/Config.vue index da85c16a..0dc4360d 100644 --- a/src/pages/Config.vue +++ b/src/pages/Config.vue @@ -1,6 +1,6 @@ + 路径 @@ -146,7 +147,6 @@ // vue import { onMounted, ref } from "vue"; import { getBuildTime } from "../utils/TGBuild"; - import TLoading from "../components/t-loading.vue"; import TConfirm from "../components/t-confirm.vue"; // tauri @@ -159,8 +159,11 @@ import { useAchievementsStore } from "../store/modules/achievements"; // utils import { WriteTGData, DeleteTGData, ReadAllTGData } from "../utils/TGIndex"; import { backupUiafData, restoreUiafData } from "../utils/UIAF"; +import TGSqlite from "../core/database/TGSqlite"; // data import { getDataList } from "../data/init"; +import Database from "tauri-plugin-sql-api"; +import { onUnmounted } from "vue"; // Store const appStore = useAppStore(); @@ -178,6 +181,7 @@ const osVersion = ref("" as string); // loading const loading = ref(true as boolean); +const loadingTitle = ref("正在加载..." as string); // data const showHome = ref(homeStore.getShowValue() as string[]); @@ -252,6 +256,11 @@ function tryConfirm (oper: string) { confirmOper.value = "delDB"; confirmShow.value = true; break; + case "checkDB": + confirmText.value = "请确认已经备份关键数据。"; + confirmOper.value = "checkDB"; + confirmShow.value = true; + break; } } @@ -283,6 +292,9 @@ async function doConfirm (oper: string) { case "delDB": delDB(); break; + case "checkDB": + await checkDB(); + break; default: break; } @@ -400,6 +412,28 @@ function delDB () { snackbarColor.value = "success"; snackbar.value = true; } + +// 检查 SQLite 数据库 +async function checkDB () { + loadingTitle.value = "正在检查数据库表单完整性..."; + const res = await TGSqlite.checkDB(); + if (!res) { + loadingTitle.value = "检测到表单不完整,正在重置数据库..."; + await TGSqlite.resetDB(); + loading.value = false; + snackbarText.value = "数据库已重置!请载入备份数据。"; + snackbarColor.value = "success"; + snackbar.value = true; + } else { + loadingTitle.value = "正在检查数据库数据完整性..."; + await TGSqlite.update.achievement(); + await TGSqlite.update.achievementSeries(); + loading.value = false; + snackbarText.value = "数据库检查完毕!"; + snackbarColor.value = "success"; + snackbar.value = true; + } +}