🌱 幽境危战数据库操作

#157
This commit is contained in:
BTMuli
2025-07-01 16:21:13 +08:00
parent 8f4d3d2285
commit 1718b87adf
11 changed files with 754 additions and 86 deletions

View File

@@ -1,7 +1,7 @@
/**
* @file plugins/Sqlite/index.ts
* @description Sqlite 数据库操作类
* @since Beta v0.6.1
* @since Beta v0.8.0
*/
import { app } from "@tauri-apps/api";
@@ -19,6 +19,8 @@ class Sqlite {
"GachaRecords",
"GameAccount",
"SpiralAbyss",
"RoleCombat",
"HardChallenge",
"UFCollection",
"UFMap",
"UFPost",

View File

@@ -0,0 +1,177 @@
/**
* @file sqlite/modules/userChallenge.ts
* @description 幽境危战模块
* @since Beta v0.8.0
*/
import { path } from "@tauri-apps/api";
import { exists, mkdir, readTextFile, writeTextFile } from "@tauri-apps/plugin-fs";
import TGLogger from "@utils/TGLogger.js";
import { timestampToDate } from "@utils/toolFunc.js";
import TGSqlite from "../index.js";
/**
* @description 将通过 api 获取到的数据转换为数据库中的数据
* @since Beta v0.8.0
* @param {TGApp.Game.Challenge.ChallengeItem} data - 挑战数据
* @returns {TGApp.Sqlite.Challenge.SingleTable} 转换后的数据
*/
function transUserChallenge(
data: TGApp.Game.Challenge.ChallengeItem,
): TGApp.Sqlite.Challenge.SingleTable {
return {
uid: "",
id: Number(data.schedule.schedule_id),
startTime: timestampToDate(Number(data.schedule.start_time) * 1000),
endTime: timestampToDate(Number(data.schedule.end_time) * 1000),
name: data.schedule.name,
single: data.single,
mp: data.mp,
updated: timestampToDate(new Date().getTime()),
};
}
/**
* @description 直接插入数据
* @since Beta v0.8.0
* @param {TGApp.Sqlite.Challenge.SingleTable} data - 挑战数据
* @param {string} [uid] - 用户UID
* @returns {string} - 插入 SQL 语句
*/
function getInsertSql(data: TGApp.Sqlite.Challenge.SingleTable, uid?: string): string {
const timeNow = timestampToDate(new Date().getTime());
return `
INSERT INTO HardChallenge(uid, id, startTime, endTime, name, single, mp, updated)
VALUES ('${uid ?? data.uid}', ${data.id}, '${data.startTime}', '${data.endTime}', '${data.name}',
'${JSON.stringify(data.single)}', '${JSON.stringify(data.mp)}', '${timeNow}') ON CONFLICT(uid,id) DO
UPDATE
SET startTime = '${data.startTime}',
endTime = '${data.endTime}',
name = '${data.name}',
single = '${JSON.stringify(data.single)}',
mp = '${JSON.stringify(data.mp)}',
updated = '${timeNow}'
`;
}
/**
* @description 获取所有数据的UID
* @since Beta v0.8.0
* @return {Promise<Array<string>} - 所有数据的UID
*/
async function getAllUid(): Promise<Array<string>> {
const db = await TGSqlite.getDB();
type resType = Array<{ uid: string }>;
const res = await db.select<resType>("SELECT DISTINCT uid FROM HardChallenge;");
return res.map((i) => i.uid);
}
/**
* @description 获取挑战数据
* @since Beta v0.8.0
* @param {string} [uid] - 游戏UID
* @return {Promise<Array<TGApp.Sqlite.Challenge.SingleTable>>} - 挑战数据
*/
async function getChallenge(uid?: string): Promise<Array<TGApp.Sqlite.Challenge.SingleTable>> {
const db = await TGSqlite.getDB();
let resR: Array<TGApp.Sqlite.Challenge.RawTable>;
if (uid === undefined) {
resR = await db.select<Array<TGApp.Sqlite.Challenge.RawTable>>(
"SELECT * FROM HardChallenge ORDER BY id DESC;",
);
} else {
resR = await db.select<Array<TGApp.Sqlite.Challenge.RawTable>>(
`SELECT *
FROM HardChallenge
WHERE uid = ?;`,
[uid],
);
}
const res: Array<TGApp.Sqlite.Challenge.SingleTable> = [];
for (const raw of resR) {
res.push({
uid: raw.uid,
id: raw.id,
startTime: raw.startTime,
endTime: raw.endTime,
name: raw.name,
single: JSON.parse(raw.single),
mp: JSON.parse(raw.mp),
updated: raw.updated,
});
}
return res;
}
/**
* @description 保存挑战数据
* @since Beta v0.8.0
* @param {string} uid - 游戏UID
* @param {TGApp.Game.Challenge.ChallengeItem} data - 挑战数据
* @return {Promise<void>}
*/
async function saveChallenge(uid: string, data: TGApp.Game.Challenge.ChallengeItem): Promise<void> {
const db = await TGSqlite.getDB();
await db.execute(getInsertSql(transUserChallenge(data), uid));
}
/**
* @description 删除指定UID的挑战数据
* @since Beta v0.8.0
* @param {string} uid - 游戏UID
* @return {Promise<void>}
*/
async function delChallenge(uid: string): Promise<void> {
const db = await TGSqlite.getDB();
await db.execute("DELETE FROM HardChallenge WHERE uid = ?;", [uid]);
}
/**
* @description 备份挑战数据
* @since Beta v0.8.0
* @param {string} dir - 备份目录
* @return {Promise<void>}
*/
async function backupChallenge(dir: string): Promise<void> {
if (!(await exists(dir))) {
await mkdir(dir, { recursive: true });
await TGLogger.Warn(`[TSUserChallenge][Backup] 未检测到备份目录,已创建`);
}
const data = await getChallenge();
await writeTextFile(`${dir}${path.sep()}challenge.json`, JSON.stringify(data));
}
/**
* @description 恢复挑战数据
* @since Beta v0.8.0
* @param {string} dir - 备份目录
* @return {Promise<boolean>}
*/
async function restoreChallenge(dir: string): Promise<boolean> {
const filePath = `${dir}${path.sep()}challenge.json`;
if (!(await exists(filePath))) return false;
try {
const data: Array<TGApp.Sqlite.Challenge.SingleTable> = JSON.parse(
await readTextFile(filePath),
);
const db = await TGSqlite.getDB();
for (const challenge of data) await db.execute(getInsertSql(challenge));
return true;
} catch (e) {
await TGLogger.Error(`[TSUserChallenge][Restore] 恢复挑战数据失败: `);
await TGLogger.Error(`${e}`);
return false;
}
}
const TSUserChallenge = {
getAllUid,
getChallenge,
saveChallenge,
delChallenge,
backupChallenge,
restoreChallenge,
};
export default TSUserChallenge;

View File

@@ -1,7 +1,7 @@
/**
* @file plugins/Sqlite/modules/userCombat.ts
* @description Sqlite-幻想真境剧诗模块
* @since Beta v0.6.3
* @since Beta v0.8.0
*/
import { path } from "@tauri-apps/api";
@@ -10,13 +10,32 @@ import TGLogger from "@utils/TGLogger.js";
import { timestampToDate } from "@utils/toolFunc.js";
import TGSqlite from "../index.js";
import { transUserCombat } from "../utils/transUserCombat.js";
/**
* @description 将通过 api 获取到的数据转换为数据库中的数据
* @since Beta v0.8.0
* @param {TGApp.Game.Combat.Combat} data - 剧诗数据
* @returns {TGApp.Sqlite.Combat.SingleTable} 转换后端数据
*/
function transUserCombat(data: TGApp.Game.Combat.Combat): TGApp.Sqlite.Combat.SingleTable {
return {
uid: "",
detail: data.detail,
endTime: timestampToDate(Number(data.schedule.end_time) * 1000),
hasData: data.has_data,
hasDetailData: data.has_detail_data,
id: data.schedule.schedule_id,
startTime: timestampToDate(Number(data.schedule.start_time) * 1000),
stat: data.stat,
updated: timestampToDate(new Date().getTime()),
};
}
/**
* @description 直接插入数据
* @since Beta v0.6.3
* @param {string} uid 用户UID
* @param {TGApp.Sqlite.Combat.SingleTable} data 剧诗数据
* @param {string} [uid] 用户UID
* @returns {string}
*/
function getInsertSql(data: TGApp.Sqlite.Combat.SingleTable, uid?: string): string {
@@ -41,7 +60,7 @@ function getInsertSql(data: TGApp.Sqlite.Combat.SingleTable, uid?: string): stri
/**
* @description 获取所有有数据的UID
* @since Beta v0.6.3
* @returns {Promise<void>}
* @returns {Promise<Array<string>>}
*/
async function getAllUid(): Promise<Array<string>> {
const db = await TGSqlite.getDB();
@@ -52,20 +71,20 @@ async function getAllUid(): Promise<Array<string>> {
/**
* @description 获取剧诗数据
* @since Beta v0.6.3
* @param {string} uid - 游戏UID
* @since Beta v0.8.0
* @param {string} [uid] - 游戏UID
* @returns {Promise<TGApp.Sqlite.Abyss.TableRaw[]>}
*/
async function getCombat(uid?: string): Promise<TGApp.Sqlite.Combat.SingleTable[]> {
const db = await TGSqlite.getDB();
let resR: TGApp.Sqlite.Combat.RawTable[];
let resR: Array<TGApp.Sqlite.Combat.RawTable>;
if (uid === undefined) {
resR = await db.select<TGApp.Sqlite.Combat.RawTable[]>(
"SELECT * FROM RoleCombat order by id DESC;",
resR = await db.select<Array<TGApp.Sqlite.Combat.RawTable>>(
"SELECT * FROM RoleCombat ORDER BY id DESC;",
);
} else {
resR = await db.select<TGApp.Sqlite.Combat.RawTable[]>(
"SELECT * FROM RoleCombat WHERE uid = ? order by id DESC;",
resR = await db.select<Array<TGApp.Sqlite.Combat.RawTable>>(
"SELECT * FROM RoleCombat WHERE uid = ?;",
[uid],
);
}
@@ -118,7 +137,7 @@ async function delCombat(uid: string): Promise<void> {
async function backupCombat(dir: string): Promise<void> {
if (!(await exists(dir))) {
await mkdir(dir, { recursive: true });
await TGLogger.Warn(`未检测到备份目录,已创建`);
await TGLogger.Warn(`[TSUserCombat][Backup] 未检测到备份目录,已创建`);
}
const data = await getCombat();
await writeTextFile(`${dir}${path.sep()}combat.json`, JSON.stringify(data));
@@ -126,7 +145,7 @@ async function backupCombat(dir: string): Promise<void> {
/**
* @description 恢复剧诗数据
* @since Beta v0.6.3
* @since Beta v0.8.0
* @param {string} dir - 备份文件目录
* @returns {Promise<boolean>}
*/
@@ -134,12 +153,12 @@ async function restoreCombat(dir: string): Promise<boolean> {
const filePath = `${dir}${path.sep()}combat.json`;
if (!(await exists(filePath))) return false;
try {
const data: TGApp.Sqlite.Combat.SingleTable[] = JSON.parse(await readTextFile(filePath));
const data: Array<TGApp.Sqlite.Combat.SingleTable> = JSON.parse(await readTextFile(filePath));
const db = await TGSqlite.getDB();
for (const abyss of data) await db.execute(getInsertSql(abyss));
return true;
} catch (e) {
await TGLogger.Error(`恢复剧诗数据失败${filePath}`);
await TGLogger.Error(`[TSUserCombat][Restore] 恢复剧诗数据失败${filePath}`);
await TGLogger.Error(`${e}`);
return false;
}

View File

@@ -1,6 +1,6 @@
-- @file plugins/Sqlite/sql/createTable.sql
-- @brief sqlite数据库创建表语句
-- @since Beta v0.7.2
-- @since Beta v0.8.0
-- @brief 创建成就数据表
create table if not exists Achievements
@@ -47,27 +47,6 @@ create table if not exists GameAccount
primary key (uid, gameBiz, gameUid)
);
-- @brief 创建临时游戏账号数据表用于迁移数据
create table GameAccountTemp
(
uid text,
gameBiz text,
gameUid text,
isChosen boolean,
isOfficial boolean,
level integer,
nickname text,
region text,
regionName text,
updated text,
primary key (uid, gameBiz, gameUid)
);
--- @brief 迁移数据
insert into GameAccountTemp select * from GameAccount;
drop table GameAccount;
alter table GameAccountTemp rename to GameAccount;
-- @brief 创建深渊数据表
create table if not exists SpiralAbyss
(
@@ -107,6 +86,20 @@ create table if not exists RoleCombat
primary key (uid, id)
);
-- @brief 创建幽境危战数据表
create table if not exists HardChallenge
(
uid text,
id integer,
startTime text,
endTime text,
name text,
single text,
mp text,
updated text,
primary key (uid, id)
);
-- @brief 创建战绩数据表
create table if not exists UserRecord
(

View File

@@ -1,27 +0,0 @@
/**
* @file plugins/Sqlite/utils/transUserCombat.ts
* @description Sqlite 数据转换-幻想真境剧诗
* @since Beta v0.6.3
*/
import { timestampToDate } from "@utils/toolFunc.js";
/**
* @description 将通过 api 获取到的数据转换为数据库中的数据
* @since Beta v0.6.3
* @param {TGApp.Game.Combat.Combat} data - 剧诗数据
* @returns {TGApp.Sqlite.Combat.SingleTable} 转换后端数据
*/
export function transUserCombat(data: TGApp.Game.Combat.Combat): TGApp.Sqlite.Combat.SingleTable {
return {
uid: "",
detail: data.detail,
endTime: timestampToDate(Number(data.schedule.end_time) * 1000),
hasData: data.has_data,
hasDetailData: data.has_detail_data,
id: data.schedule.schedule_id,
startTime: timestampToDate(Number(data.schedule.start_time) * 1000),
stat: data.stat,
updated: timestampToDate(new Date().getTime()),
};
}