👌 del(db): indexedDB 已经是过去式了

This commit is contained in:
BTMuli
2023-04-25 00:29:38 +08:00
parent 4c8cb39bf6
commit d6e60ee264
10 changed files with 25 additions and 432 deletions

View File

@@ -35,11 +35,10 @@ import { fs, window, app, event } from "@tauri-apps/api";
import { useAppStore } from "./store/modules/app"; import { useAppStore } from "./store/modules/app";
import { useAchievementsStore } from "./store/modules/achievements"; import { useAchievementsStore } from "./store/modules/achievements";
// utils // utils
import { InitTGData, DeleteTGData, WriteTGData } from "./utils/TGIndex";
import { getBuildTime } from "./utils/TGBuild"; import { getBuildTime } from "./utils/TGBuild";
// data // data
import { TGGetDataList, TGInitDBT } from "./data";
import { restoreUiafData } from "./utils/UIAF"; import { restoreUiafData } from "./utils/UIAF";
import TGSqlite from "./core/database/TGSqlite";
const appStore = useAppStore(); const appStore = useAppStore();
const isMain = ref(true as boolean); const isMain = ref(true as boolean);
@@ -84,9 +83,8 @@ async function checkLoad () {
console.info("数据已加载!"); console.info("数据已加载!");
return; return;
} }
DeleteTGData();
await createDataDir(); await createDataDir();
await writeIndex(); await writeDB();
await writeData(); await writeData();
appStore.loading = true; appStore.loading = true;
console.info("数据加载完成!"); console.info("数据加载完成!");
@@ -100,16 +98,17 @@ async function createDataDir () {
console.info("数据文件夹创建完成!"); console.info("数据文件夹创建完成!");
} }
// 写入 IndexedDB // 写入 IndexedDB
async function writeIndex () { async function writeDB () {
console.info("开始写入 IndexedDB..."); const res = await TGSqlite.checkDB();
await InitTGData(); if (!res) {
TGGetDataList.map(async (item) => { console.info("检测到数据库不完整,正在重置数据库...");
await WriteTGData(item.name, item.data); await TGSqlite.resetDB();
}); } else {
console.info("IndexedDB 写入完成!"); console.info("正在更新成就系列数据...");
console.info("开始写入 SQLite..."); await TGSqlite.update.achievementSeries();
await TGInitDBT(); console.info("正在更新成就数据...");
console.info("SQLite 写入完成!"); await TGSqlite.update.achievement();
}
} }
// 恢复数据 // 恢复数据
async function writeData () { async function writeData () {

View File

@@ -103,7 +103,6 @@
<div <div
v-for="item of weapon.contents" v-for="item of weapon.contents"
:key="item.id" :key="item.id"
alt="content.content_id"
class="card-box" class="card-box"
@click="showContent(item)" @click="showContent(item)"
> >
@@ -139,7 +138,7 @@
// vue // vue
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
// data // data
import { TGAppData } from "../data/index"; import { TGAppData } from "../data";
// interface // interface
import { OBC_CONTENT_API } from "../plugins/Mys/interface/utils"; import { OBC_CONTENT_API } from "../plugins/Mys/interface/utils";
import { createTGWindow } from "../utils/TGWindow"; import { createTGWindow } from "../utils/TGWindow";

View File

@@ -2,7 +2,7 @@
<v-navigation-drawer permanent :rail="rail" style="background: var(--sidebar-bg); color: #faf7e8"> <v-navigation-drawer permanent :rail="rail" style="background: var(--sidebar-bg); color: #faf7e8">
<v-list v-model:opened="open" class="side-list" density="compact" nav> <v-list v-model:opened="open" class="side-list" density="compact" nav>
<!-- 负责收缩侧边栏 --> <!-- 负责收缩侧边栏 -->
<v-list-item @click="collapse"> <v-list-item @click="collapse()">
<template v-if="rail" #prepend> <template v-if="rail" #prepend>
<v-list-item-action> <v-list-item-action>
<v-icon style="color:var(--sidebar-icon)"> <v-icon style="color:var(--sidebar-icon)">
@@ -120,7 +120,7 @@
<img :src="userInfo.avatar" alt="userIcon" class="side-icon"> <img :src="userInfo.avatar" alt="userIcon" class="side-icon">
</template> </template>
</v-list-item> --> </v-list-item> -->
<v-list-item :title="themeTitle" value="theme" @click="switchTheme"> <v-list-item :title="themeTitle" value="theme" @click="switchTheme()">
<template #prepend> <template #prepend>
<v-icon style="color:var(--sidebar-icon)"> <v-icon style="color:var(--sidebar-icon)">
{{ themeGet === 'default' ? 'mdi-weather-night' : 'mdi-weather-sunny' }} {{ themeGet === 'default' ? 'mdi-weather-night' : 'mdi-weather-sunny' }}

View File

@@ -5,11 +5,6 @@
* @since Alpha v0.1.4 * @since Alpha v0.1.4
*/ */
import { AppData, AppDataList } from "./app"; import { AppData } from "./app";
import { ConfigList, getDataList, initDBT } from "./init";
export const TGAppData = AppData; export const TGAppData = AppData;
export const TGAppDataList = AppDataList;
export const TGConfigList = ConfigList;
export const TGGetDataList = getDataList;
export const TGInitDBT = initDBT;

View File

@@ -1,73 +0,0 @@
/**
* @file data init achievementSeries
* @description data init achievementSeries
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.2
*/
import { AppData } from "../app";
/**
* @description 成就系列表参数
* @since Alpha v0.1.2
* @returns {BTMuli.Genshin.Base.DBConfig}
*/
export const Config: BTMuli.Genshin.Base.DBConfig = {
storeName: "AchievementSeries",
keyPath: "id",
indexes: ["order", "name", "card"],
};
/**
* @description 成就系列数据
* @since Alpha v0.1.2
* @return {BTMuli.Genshin.AchievementSeries[]}
*/
export function getData (): BTMuli.Genshin.AchievementSeries[] {
const data: Record<number, BTMuli.Genshin.AchievementSeries> = AppData.achievementSeries;
return Object.keys(data).map((key) => {
return data[Number(key)];
});
}
/**
* @description 创建表的 SQL 语句
* @since Alpha v0.1.4
* @see BTMuli.Genshin.AchievementSeries
* @returns {string}
*/
export const CTS = `CREATE TABLE IF NOT EXISTS ${Config.storeName} (
id INTEGER PRIMARY KEY,
'order' INTEGER NOT NULL,
name TEXT NOT NULL,
version TEXT NOT NULL,
total INTEGER NOT NULL,
finished INTEGER NOT NULL,
card TEXT NOT NULL,
icon TEXT NOT NULL
);`;
/**
* @description 初始化数据的 SQL 语句
* @since Alpha v0.1.4
* @see BTMuli.Genshin.AchievementSeries
* @returns {string[]}
*/
export function getInsertSqls (): string[] {
const data = getData();
const sql: string[] = [];
data.forEach((item) => {
const card = item.card ? item.card : "";
sql.push(`INSERT INTO ${Config.storeName} VALUES (
${item.id},
${item.order},
"${item.name}",
"${item.version}",
${item.total_count},
${item.completed_count},
"${card}",
"${item.icon}"
)`);
});
return sql;
}

View File

@@ -1,77 +0,0 @@
/**
* @file data init achievement
* @description data init achievement
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.2
*/
import { AppData } from "../app";
/**
* @description 成就表参数
* @since Alpha v0.1.2
* @returns {BTMuli.Genshin.Base.DBConfig}
*/
export const Config: BTMuli.Genshin.Base.DBConfig = {
storeName: "Achievements",
keyPath: "id",
indexes: ["name", "description", "series", "order", "reward", "version"],
};
/**
* @description 成就数据
* @since Alpha v0.1.2
* @return {BTMuli.Genshin.Achievement[]}
*/
export function getData (): BTMuli.Genshin.Achievement[] {
const data: Record<number, BTMuli.Genshin.Achievement> = AppData.achievements;
return Object.keys(data).map((key) => {
return data[Number(key)];
});
}
/**
* @description 创建表的 SQLite 语句
* @since Alpha v0.1.4
* @todo 外键约束
* @see BTMuli.Genshin.Achievement
*/
export const CTS: string = `CREATE TABLE IF NOT EXISTS ${Config.storeName} (
id INTEGER PRIMARY KEY,
series INTEGER NOT NULL,
'order' INTEGER NOT NULL,
name TEXT NOT NULL,
description TEXT NOT NULL,
reward INTEGER NOT NULL,
completed INTEGER NOT NULL,
completed_time TEXT NOT NULL,
progress INTEGER NOT NULL,
version TEXT NOT NULL
);`;
/**
* @description 初始化数据的 SQL 语句
* @since Alpha v0.1.4
* @see BTMuli.Genshin.Achievement
* @returns {string[]}
*/
export function getInsertSqls (): string[] {
const data = getData();
const sql: string[] = [];
data.forEach((item) => {
const completedTime = item.completed_time ? item.completed_time : "";
const completed = item.completed ? 1 : 0;
sql.push(`INSERT INTO ${Config.storeName} VALUES (
${item.id},
${item.series},
${item.order},
'${item.name}',
'${item.description}',
${item.reward},
${completed},
'${completedTime}',
${item.progress},
'${item.version}'
)`);
});
return sql;
}

View File

@@ -1,48 +0,0 @@
/**
* @file data init index
* @description data init index
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.4
*/
// tauri-pligin
import Database from "tauri-plugin-sql-api";
// local-data
import { Config as AchievementsConfig, getData as getAchievementsData, CTS as ctsAchievement, getInsertSqls as gisAchievement } from "./achievements";
import { Config as SeriesConfig, getData as getSeriesData, CTS as ctsSeries, getInsertSqls as gisSeries } from "./achievementSeries";
export const SqlitePath = "sqlite:tauri-genshin.db";
export const ConfigList = [AchievementsConfig, SeriesConfig];
export const getDataList = [
{
name: "Achievements",
data: getAchievementsData(),
},
{
name: "AchievementSeries",
data: getSeriesData(),
},
];
/**
* @description 初始化数据表
* @since Alpha v0.1.4
* @returns {Promise<void>}
*/
export async function initDBT (): Promise<void> {
const SQlite = await Database.load(SqlitePath);
// 创建表
await SQlite.execute(ctsSeries);
console.log("AchievementSeries 表创建成功");
await SQlite.execute(ctsAchievement);
console.log("Achievements 表创建成功");
// 初始化数据
const sqls = gisAchievement().concat(gisSeries());
sqls.map(async (sql) => {
console.log(sql);
await SQlite.execute(sql);
});
await SQlite.close();
}

View File

@@ -158,13 +158,8 @@ import { useHomeStore } from "../store/modules/home";
import { useHk4eStore } from "../store/modules/hk4e"; import { useHk4eStore } from "../store/modules/hk4e";
import { useAchievementsStore } from "../store/modules/achievements"; import { useAchievementsStore } from "../store/modules/achievements";
// utils // utils
import { WriteTGData, DeleteTGData, ReadAllTGData } from "../utils/TGIndex";
import { backupUiafData, restoreUiafData } from "../utils/UIAF"; import { backupUiafData, restoreUiafData } from "../utils/UIAF";
import TGSqlite from "../core/database/TGSqlite"; import TGSqlite from "../core/database/TGSqlite";
// data
import { getDataList } from "../data/init";
import Database from "tauri-plugin-sql-api";
import { onUnmounted } from "vue";
// Store // Store
const appStore = useAppStore(); const appStore = useAppStore();
@@ -311,8 +306,11 @@ async function doConfirm (oper: string) {
// confirmOper // confirmOper
async function backupData () { async function backupData () {
const achievements = await ReadAllTGData("achievements"); loadingTitle.value = "正在备份数据...";
loading.value = true;
const achievements = await TGSqlite.UIAF.export();
await backupUiafData(achievements); await backupUiafData(achievements);
loading.value = false;
snackbarText.value = "数据已备份!"; snackbarText.value = "数据已备份!";
snackbarColor.value = "success"; snackbarColor.value = "success";
snackbar.value = true; snackbar.value = true;
@@ -321,7 +319,7 @@ async function backupData () {
async function restoreData () { async function restoreData () {
const res = await restoreUiafData(); const res = await restoreUiafData();
if (res !== false) { if (res !== false) {
achievementsStore.flushData(res.total, res.completed); achievementsStore.flushData(res.total, res.fin);
snackbarText.value = "数据已恢复!"; snackbarText.value = "数据已恢复!";
snackbarColor.value = "success"; snackbarColor.value = "success";
snackbar.value = true; snackbar.value = true;
@@ -347,9 +345,6 @@ async function delUserData () {
dir: fs.BaseDirectory.AppLocalData, dir: fs.BaseDirectory.AppLocalData,
recursive: true, recursive: true,
}); });
getDataList.map(async (item) => {
await WriteTGData(item.name, item.data);
});
snackbarText.value = "用户数据已删除!"; snackbarText.value = "用户数据已删除!";
snackbar.value = true; snackbar.value = true;
achievementsStore.init(); achievementsStore.init();
@@ -416,7 +411,7 @@ async function readCookie () {
// 删除 IndexedDB // 删除 IndexedDB
function delDB () { function delDB () {
DeleteTGData(); window.indexedDB.deleteDatabase("TGData");
snackbarText.value = "IndexedDB 已清除!若无法正常使用,请初始化配置。"; snackbarText.value = "IndexedDB 已清除!若无法正常使用,请初始化配置。";
snackbarColor.value = "success"; snackbarColor.value = "success";
snackbar.value = true; snackbar.value = true;
@@ -433,8 +428,8 @@ async function checkDB () {
confirmShow.value = true; confirmShow.value = true;
} else { } else {
loadingTitle.value = "正在检查数据库数据完整性..."; loadingTitle.value = "正在检查数据库数据完整性...";
await TGSqlite.update.achievement();
await TGSqlite.update.achievementSeries(); await TGSqlite.update.achievementSeries();
await TGSqlite.update.achievement();
loading.value = false; loading.value = false;
snackbarText.value = "数据库检查完毕!"; snackbarText.value = "数据库检查完毕!";
snackbarColor.value = "success"; snackbarColor.value = "success";

View File

@@ -1,197 +0,0 @@
/**
* @file utils TGIndex.ts
* @description IndexedDB utils
* @author BTMuli<bt-muli@outlook.com>
* @since Alpha v0.1.2
*/
import { TGConfigList } from "../data";
// 数据库参数
export const DB_NAME = "TGData";
export const DB_VERSION = 1;
/**
* @description 初始化数据库
* @description 只会在第一次打开游戏时执行
* @since Alpha v0.1.2
* @returns {Promise<void>}
*/
export async function InitTGData (): Promise<void> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
request.onupgradeneeded = () => {
const db = request.result;
// 创建表
TGConfigList.forEach((config) => {
const store = db.createObjectStore(config.storeName, {
keyPath: config.keyPath,
});
config.indexes.forEach((index) => {
store.createIndex(index, index, { unique: false });
});
});
};
}
/**
* @description 删除数据库
* @since Alpha
* @returns {void}
*/
export function DeleteTGData (): void {
window.indexedDB.deleteDatabase(DB_NAME);
}
/**
* @description 向数据库中写入数据
* @since Alpha
* @param {string} storeName 表名
* @param {any[]} data 数据
* @returns {Promise<void>}
*/
export async function WriteTGData (storeName: string, data: any[]): Promise<void> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
data.forEach((item) => {
store.put(item);
});
};
}
/**
* @description 更新数据库中的单条数据-根据主键
* @since Alpha
* @param {string} storeName 表名
* @param {any} data 数据
* @returns {Promise<void>}
*/
export async function UpdateTGDataByKey (storeName: string, data: any): Promise<void> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
store.put(data);
};
}
/**
* @description 更新数据库中的单条数据-根据索引
* @since Alpha
* @param {string} storeName 表名
* @param {string} indexName 索引名
* @param {any} key 索引值
* @param {any} data 数据
* @returns {Promise<void>}
*/
export async function UpdateTGDataByIndex (storeName: string, indexName: string, key: any, data: any): Promise<void> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readwrite");
const store = transaction.objectStore(storeName);
const index = store.index(indexName);
const requestData = index.getAll(key);
requestData.onsuccess = () => {
const result = requestData.result;
result.forEach((item) => {
Object.keys(data).forEach((key) => {
item[key] = data[key];
});
store.put(item);
});
};
};
}
/**
* @description 从数据库中读取某些数据-按照主键
* @since Alpha
* @param {string} storeName 表名
* @param {any[]} keys 主键值
* @returns {Promise<any[]>}
*/
export async function ReadTGDataByKey (storeName: string, keys: any[]): Promise<any[]> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
return await new Promise((resolve, reject) => {
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readonly");
const store = transaction.objectStore(storeName);
const requestData = store.getAll();
requestData.onsuccess = () => {
const result = requestData.result;
const data = result.filter((item) => {
return keys.includes(item.id);
});
resolve(data);
};
requestData.onerror = () => {
reject(requestData.error);
};
};
request.onerror = () => {
reject(request.error);
};
});
}
/**
* @description 从数据库中读取某些数据-按照索引
* @since Alpha
* @param {string} storeName 表名
* @param {string} indexName 索引名
* @param {any} key 索引值
* @returns {Promise<any[]>}
*/
export async function ReadTGDataByIndex (storeName: string, indexName: string, key: any): Promise<any[]> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
return await new Promise((resolve, reject) => {
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readonly");
const store = transaction.objectStore(storeName);
const index = store.index(indexName);
const requestData = index.getAll(key);
requestData.onsuccess = () => {
resolve(requestData.result);
};
requestData.onerror = () => {
reject(requestData.error);
};
};
request.onerror = () => {
reject(request.error);
};
});
}
/**
* @description 从数据库中读取所有数据
* @since Alpha
* @param {string} storeName 表名
* @returns {Promise<any[]>}
*/
export async function ReadAllTGData (storeName: string): Promise<any[]> {
const request = window.indexedDB.open(DB_NAME, DB_VERSION);
return await new Promise((resolve, reject) => {
request.onsuccess = () => {
const db = request.result;
const transaction = db.transaction(storeName, "readonly");
const store = transaction.objectStore(storeName);
const requestData = store.getAll();
requestData.onsuccess = () => {
resolve(requestData.result);
};
requestData.onerror = () => {
reject(requestData.error);
};
};
request.onerror = () => {
reject(request.error);
};
});
}

View File

@@ -266,7 +266,7 @@ onUpdated(() => {
.lottery-user-nickname { .lottery-user-nickname {
display: inline-block; display: inline-block;
font-size: 14px; font-size: 14px;
font-family: Genshin-Light, "仿宋"; font-family: Genshin-Light, "仿宋", serif;
color: var(--content-text-3); color: var(--content-text-3);
overflow: hidden; overflow: hidden;
} }