♻️ 重构用户祈愿数据库相关处理

This commit is contained in:
目棃
2024-05-05 02:46:07 +08:00
parent 6316cc42b2
commit afa0ba190b
5 changed files with 217 additions and 167 deletions

View File

@@ -5,11 +5,11 @@
<v-select v-model="uidCur" class="gacha-top-select" :items="selectItem" variant="outlined" /> <v-select v-model="uidCur" class="gacha-top-select" :items="selectItem" variant="outlined" />
<div class="gacha-top-btns"> <div class="gacha-top-btns">
<v-btn prepend-icon="mdi-refresh" class="gacha-top-btn" @click="confirmRefresh" <v-btn prepend-icon="mdi-refresh" class="gacha-top-btn" @click="confirmRefresh"
>增量刷新</v-btn >增量刷新
> </v-btn>
<v-btn prepend-icon="mdi-refresh" class="gacha-top-btn" @click="confirmRefresh(true)" <v-btn prepend-icon="mdi-refresh" class="gacha-top-btn" @click="confirmRefresh(true)"
>全量刷新</v-btn >全量刷新
> </v-btn>
<v-btn prepend-icon="mdi-import" class="gacha-top-btn" @click="handleImportBtn()">导入</v-btn> <v-btn prepend-icon="mdi-import" class="gacha-top-btn" @click="handleImportBtn()">导入</v-btn>
<v-btn prepend-icon="mdi-export" class="gacha-top-btn" @click="handleExportBtn">导出</v-btn> <v-btn prepend-icon="mdi-export" class="gacha-top-btn" @click="handleExportBtn">导出</v-btn>
<v-btn prepend-icon="mdi-cloud-download" class="gacha-top-btn" @click="backupGacha"> <v-btn prepend-icon="mdi-cloud-download" class="gacha-top-btn" @click="backupGacha">
@@ -52,7 +52,7 @@ import GroHistory from "../../components/gachaRecord/gro-history.vue";
import GroOverview from "../../components/gachaRecord/gro-overview.vue"; import GroOverview from "../../components/gachaRecord/gro-overview.vue";
import ToLoading from "../../components/overlay/to-loading.vue"; import ToLoading from "../../components/overlay/to-loading.vue";
import { AppCharacterData, AppWeaponData } from "../../data"; import { AppCharacterData, AppWeaponData } from "../../data";
import TGSqlite from "../../plugins/Sqlite"; import TSUserGacha from "../../plugins/Sqlite/modules/userGacha";
import { useAppStore } from "../../store/modules/app"; import { useAppStore } from "../../store/modules/app";
import { useUserStore } from "../../store/modules/user"; import { useUserStore } from "../../store/modules/user";
import TGLogger from "../../utils/TGLogger"; import TGLogger from "../../utils/TGLogger";
@@ -79,7 +79,7 @@ const tab = ref<string>("");
onMounted(async () => { onMounted(async () => {
await TGLogger.Info("[UserGacha][onMounted] 进入角色祈愿页面"); await TGLogger.Info("[UserGacha][onMounted] 进入角色祈愿页面");
loadingTitle.value = "正在获取祈愿 UID 列表"; loadingTitle.value = "正在获取祈愿 UID 列表";
selectItem.value = await TGSqlite.getUidList(); selectItem.value = await TSUserGacha.getUidList();
if (selectItem.value.length === 0) { if (selectItem.value.length === 0) {
showSnackbar({ showSnackbar({
color: "error", color: "error",
@@ -91,7 +91,7 @@ onMounted(async () => {
} }
uidCur.value = selectItem.value[0]; uidCur.value = selectItem.value[0];
loadingTitle.value = `正在获取祈愿数据,默认 UID${uidCur.value}`; loadingTitle.value = `正在获取祈愿数据,默认 UID${uidCur.value}`;
gachaListCur.value = await TGSqlite.getGachaRecords(uidCur.value); gachaListCur.value = await TSUserGacha.getGachaRecords(uidCur.value);
await TGLogger.Info( await TGLogger.Info(
`[UserGacha][onMounted] 获取到 ${uidCur.value}${gachaListCur.value.length} 条祈愿数据`, `[UserGacha][onMounted] 获取到 ${uidCur.value}${gachaListCur.value.length} 条祈愿数据`,
); );
@@ -159,11 +159,11 @@ async function confirmRefresh(force: boolean = false): Promise<void> {
]; ];
if (force) { if (force) {
loadingTitle.value = "正在获取数据库祈愿最新 ID"; loadingTitle.value = "正在获取数据库祈愿最新 ID";
checkList[0] = await TGSqlite.getGachaCheck(account.gameUid, "200"); checkList[0] = await TSUserGacha.getGachaCheck(account.gameUid, "200");
checkList[1] = await TGSqlite.getGachaCheck(account.gameUid, "301"); checkList[1] = await TSUserGacha.getGachaCheck(account.gameUid, "301");
checkList[2] = await TGSqlite.getGachaCheck(account.gameUid, "400"); checkList[2] = await TSUserGacha.getGachaCheck(account.gameUid, "400");
checkList[3] = await TGSqlite.getGachaCheck(account.gameUid, "302"); checkList[3] = await TSUserGacha.getGachaCheck(account.gameUid, "302");
checkList[4] = await TGSqlite.getGachaCheck(account.gameUid, "500"); checkList[4] = await TSUserGacha.getGachaCheck(account.gameUid, "500");
} }
console.log(checkList); console.log(checkList);
loadingTitle.value = "正在刷新新手祈愿数据"; loadingTitle.value = "正在刷新新手祈愿数据";
@@ -190,7 +190,7 @@ async function confirmRefresh(force: boolean = false): Promise<void> {
window.location.reload(); window.location.reload();
} }
// 获取祈愿数据并写入数据库 // 获取祈愿数据并写入数据库不用考虑多语言因为从api获取的数据是中文
async function getGachaLogs( async function getGachaLogs(
pool: string, pool: string,
endId: string = "0", endId: string = "0",
@@ -236,7 +236,7 @@ async function getGachaLogs(
} }
uigfList.push(tempItem); uigfList.push(tempItem);
}); });
await TGSqlite.mergeUIGF(account.gameUid, uigfList); await TSUserGacha.mergeUIGF(account.gameUid, uigfList);
if (check !== undefined && gachaRes.some((i) => i.id === check)) { if (check !== undefined && gachaRes.some((i) => i.id === check)) {
await new Promise((resolve) => { await new Promise((resolve) => {
setTimeout(() => { setTimeout(() => {
@@ -334,7 +334,7 @@ async function handleImportBtn(savePath?: string): Promise<void> {
}); });
return; return;
} }
await TGSqlite.mergeUIGF(remoteData.info.uid, remoteData.list); await TSUserGacha.mergeUIGF(remoteData.info.uid, remoteData.list);
loading.value = false; loading.value = false;
showSnackbar({ showSnackbar({
text: `成功导入 ${remoteData.list.length} 条祈愿数据`, text: `成功导入 ${remoteData.list.length} 条祈愿数据`,
@@ -342,14 +342,14 @@ async function handleImportBtn(savePath?: string): Promise<void> {
await TGLogger.Info( await TGLogger.Info(
`[UserGacha][handleImportBtn] 成功导入 ${remoteData.info.uid}${remoteData.list.length} 条祈愿数据`, `[UserGacha][handleImportBtn] 成功导入 ${remoteData.info.uid}${remoteData.list.length} 条祈愿数据`,
); );
setTimeout(() => { // setTimeout(() => {
window.location.reload(); // window.location.reload();
}, 1000); // }, 1000);
} }
// 导出按钮点击事件 // 导出按钮点击事件
async function handleExportBtn(): Promise<void> { async function handleExportBtn(): Promise<void> {
const gachaList = await TGSqlite.getGachaRecords(uidCur.value); const gachaList = await TSUserGacha.getGachaRecords(uidCur.value);
if (gachaList.length === 0) { if (gachaList.length === 0) {
showSnackbar({ showSnackbar({
color: "error", color: "error",
@@ -460,25 +460,25 @@ async function deleteGacha(): Promise<void> {
await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`); await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`);
return; return;
} }
const uidList = await TGSqlite.getUidList(); const uidList = await TSUserGacha.getUidList();
let secondConfirm: string | boolean | undefined; let secondConfirm: string | boolean | undefined;
if (uidList.length <= 1) { if (uidList.length <= 1) {
secondConfirm = await showConfirm({ secondConfirm = await showConfirm({
title: "删除后数据库将为空,确定删除?", title: "删除后数据库将为空,确定删除?",
text: `UID${uidCur.value},共 ${gachaListCur.value.length} 条数据`, text: `UID${uidCur.value},共 ${gachaListCur.value.length} 条数据`,
}); });
} if (!secondConfirm) {
if (!secondConfirm) { showSnackbar({
showSnackbar({ color: "cancel",
color: "cancel", text: "已取消祈愿数据删除",
text: "已取消祈愿数据删除", });
}); await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`);
await TGLogger.Info(`[UserGacha][${uidCur.value}][deleteGacha] 已取消祈愿数据删除`); return;
return; }
} }
loadingTitle.value = `正在删除${uidCur.value}的祈愿数据`; loadingTitle.value = `正在删除${uidCur.value}的祈愿数据`;
loading.value = true; loading.value = true;
await TGSqlite.deleteGachaRecords(uidCur.value); await TSUserGacha.deleteGachaRecords(uidCur.value);
loading.value = false; loading.value = false;
showSnackbar({ showSnackbar({
text: `已成功删除 ${uidCur.value} 的祈愿数据`, text: `已成功删除 ${uidCur.value} 的祈愿数据`,
@@ -493,7 +493,7 @@ async function deleteGacha(): Promise<void> {
// 监听 UID 变化 // 监听 UID 变化
watch(uidCur, async (newUid) => { watch(uidCur, async (newUid) => {
gachaListCur.value = await TGSqlite.getGachaRecords(newUid); gachaListCur.value = await TSUserGacha.getGachaRecords(newUid);
showSnackbar({ showSnackbar({
text: `成功获取 ${gachaListCur.value.length} 条祈愿数据`, text: `成功获取 ${gachaListCur.value.length} 条祈愿数据`,
}); });

View File

@@ -18,7 +18,7 @@ import {
insertRecordData, insertRecordData,
insertRoleData, insertRoleData,
} from "./sql/insertData"; } from "./sql/insertData";
import { importUIAFData, importUIGFData } from "./sql/updateData"; import { importUIAFData } from "./sql/updateData";
class Sqlite { class Sqlite {
/** /**
@@ -115,15 +115,13 @@ class Sqlite {
/** /**
* @description 插入 Account 数据 * @description 插入 Account 数据
* @since Beta v0.4.1 * @since Beta v0.4.7
* @param {TGApp.User.Account.Game[]} accounts * @param {TGApp.User.Account.Game[]} accounts
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
public async saveAccount(accounts: TGApp.User.Account.Game[]): Promise<void> { public async saveAccount(accounts: TGApp.User.Account.Game[]): Promise<void> {
const db = await this.getDB(); const db = await this.getDB();
// 为了防止多账号的情况,先清空数据表 await db.execute("DELETE FROM GameAccount WHERE true;");
const clear = "DELETE FROM GameAccount WHERE 1=1;";
await db.execute(clear);
for (const a of accounts) { for (const a of accounts) {
const sql = insertGameAccountData(a); const sql = insertGameAccountData(a);
await db.execute(sql); await db.execute(sql);
@@ -399,98 +397,6 @@ class Sqlite {
return res; return res;
} }
/**
* @description 获取已有 uid 列表
* @since Beta v0.3.3
* @returns {Promise<string[]>}
*/
public async getUidList(): Promise<string[]> {
const db = await this.getDB();
const sql = "SELECT DISTINCT uid FROM GachaRecords";
const res: Array<{ uid: string }> = await db.select(sql);
return res.map((item) => item.uid);
}
/**
* @description 获取指定 uid 的用户角色数据
* @since Beta v0.3.3
* @param {string} uid 用户 uid
* @returns {Promise<TGApp.Sqlite.GachaRecords.SingleTable[]>}
*/
public async getGachaRecords(uid: string): Promise<TGApp.Sqlite.GachaRecords.SingleTable[]> {
const db = await this.getDB();
const sql = `SELECT *
FROM GachaRecords
WHERE uid = '${uid}'`;
return await db.select(sql);
}
/**
* @description 删除指定 uid 的祈愿数据
* @since Beta v0.3.3
* @param {string} uid 用户 uid
* @returns {Promise<void>}
*/
public async deleteGachaRecords(uid: string): Promise<void> {
const db = await this.getDB();
const sql = `DELETE
FROM GachaRecords
WHERE uid = '${uid}'`;
await db.execute(sql);
}
/**
* @description 合并祈愿数据
* @since Beta v0.3.3
* @param {string} uid UID
* @param {TGApp.Plugins.UIGF.GachaItem[]} data UIGF 数据
* @returns {Promise<void>}
*/
public async mergeUIGF(uid: string, data: TGApp.Plugins.UIGF.GachaItem[]): Promise<void> {
const db = await this.getDB();
const sql = importUIGFData(uid, data);
for (const item of sql) {
await db.execute(item);
}
}
/**
* @description 判断今天是否是某个角色的生日
* @since Beta v0.3.6
* @returns {Promise<false|string>}
*/
public async isBirthday(): Promise<false | string> {
const db = await this.getDB();
const dateNow = new Date();
const date = `${dateNow.getMonth() + 1},${dateNow.getDate()}`;
const sql = `SELECT name
FROM AppCharacters
WHERE birthday = '${date}';`;
const res: Array<{ name: string }> = await db.select(sql);
if (res.length === 0) return false;
return res.map((item) => item.name).join("、");
}
/**
* @description 用于检测祈愿增量更新的 gacha id
* @since Beta v0.4.4
* @param {string} uid 用户 uid
* @param {string} type 卡池类型
* @returns {Promise<string|undefined>}
*/
async getGachaCheck(uid: string, type: string): Promise<string | undefined> {
const db = await this.getDB();
const sql = `SELECT id
FROM GachaRecords
WHERE uid = '${uid}'
AND gachaType = '${type}'
ORDER BY id DESC
LIMIT 1;`;
const res: Array<{ id: string }> = await db.select(sql);
if (res.length === 0) return undefined;
return res[0].id;
}
/** /**
* @description 检测特定表是否存在 * @description 检测特定表是否存在
* @since Beta v0.4.5 * @since Beta v0.4.5

View File

@@ -0,0 +1,147 @@
/**
* @file plugins/Sqlite/modules/userGacha.ts
* @description 用户祈愿模块
* @since Beta v0.4.7
*/
import { AppCharacterData, AppWeaponData } from "../../../data/index";
import TGSqlite from "../index";
import { importUIGFData } from "../sql/updateData";
type gachaItemTypeRes =
| ["角色", TGApp.App.Character.WikiBriefInfo]
| ["武器", TGApp.App.Weapon.WikiBriefInfo]
| ["未知", "未知"];
/**
* @description 根据 item_id 获取角色/武器类型
* @since Beta v0.4.7
* @param {string} item_id - item_id
* @return {gachaItemTypeRes}
*/
function getGachaItemType(item_id: string): gachaItemTypeRes {
const findAvatar = AppCharacterData.find((i) => i.id === item_id);
if (findAvatar !== undefined) return ["角色", findAvatar];
const findWeapon = AppWeaponData.find((i) => i.id === item_id);
if (findWeapon !== undefined) return ["武器", findWeapon];
return ["未知", "未知"];
}
/**
* @description 转换祈愿数据,防止多语言
* @since Beta v0.4.7
* @param {TGApp.Plugins.UIGF.GachaItem} gacha - UIGF数据
* @return {TGApp.Plugins.UIGF.GachaItem} 转换后的数据
*/
function transGacha(gacha: TGApp.Plugins.UIGF.GachaItem): TGApp.Plugins.UIGF.GachaItem {
const type = getGachaItemType(gacha.item_id);
let res = gacha;
res.item_type = type[0];
if (type[0] === "角色") {
const data: TGApp.App.Character.WikiBriefInfo = type[1];
res = {
gacha_type: gacha.gacha_type,
item_id: gacha.item_id,
count: gacha.count ?? "1",
time: gacha.time,
name: data.name,
item_type: "角色",
rank_type: data.star.toString(),
id: gacha.id,
uigf_gacha_type: gacha.uigf_gacha_type,
};
} else if (type[0] === "武器") {
const data: TGApp.App.Weapon.WikiBriefInfo = type[1];
res = {
gacha_type: gacha.gacha_type,
item_id: gacha.item_id,
count: gacha.count ?? "1",
time: gacha.time,
name: data.name,
item_type: "武器",
rank_type: data.star.toString(),
id: gacha.id,
uigf_gacha_type: gacha.uigf_gacha_type,
};
}
return res;
}
/**
* @description 获取数据库的uid列表
* @since Beta v0.4.7
* @return {Promise<string[]>}
*/
async function getUidList(): Promise<string[]> {
const db = await TGSqlite.getDB();
type resType = Array<{ uid: string }>;
const res = await db.select<resType>("SELECT DISTINCT uid FROM GachaRecords;");
return res.map((i) => i.uid);
}
/**
* @description 获取检测增量更新的记录 ID
* @since Beta v0.4.7
* @param {string} uid - UID
* @param {string} type - 类型
* @returns {Promise<string|undefined>}
*/
async function getGachaCheck(uid: string, type: string): Promise<string | undefined> {
const db = await TGSqlite.getDB();
type resType = Array<{ id: string }>;
const res = await db.select<resType>(
"SELECT id FROM GachaRecords WHERE uid = ? AND gachaType = ? ORDER BY id DESC LIMIT 1;",
[uid, type],
);
if (res.length === 0) return undefined;
return res[0].id;
}
/**
* @description 获取用户祈愿记录
* @since Beta v0.4.7
* @param {string} uid - UID
* @return {Promise<TGApp.Sqlite.GachaRecords.SingleTable[]>}
*/
async function getGachaRecords(uid: string): Promise<TGApp.Sqlite.GachaRecords.SingleTable[]> {
const db = await TGSqlite.getDB();
return await db.select("SELECT * FROM GachaRecords WHERE uid = ?;", [uid]);
}
/**
* @description 删除指定UID的祈愿记录
* @since Beta v0.4.7
* @param {string} uid - UID
* @return {Promise<void>}
*/
async function deleteGachaRecords(uid: string): Promise<void> {
const db = await TGSqlite.getDB();
await db.execute("DELETE FROM GachaRecords WHERE uid = ?;", [uid]);
}
/**
* @description 合并祈愿数据
* @since Beta v0.4.7
* @param {string} uid - UID
* @param {TGApp.Plugins.UIGF.GachaItem[]} data - UIGF数据
* @return {Promise<void>}
*/
async function mergeUIGF(uid: string, data: TGApp.Plugins.UIGF.GachaItem[]): Promise<void> {
const db = await TGSqlite.getDB();
for (const gacha of data) {
const trans = transGacha(gacha);
console.log(trans);
const sql = importUIGFData(uid, trans);
await db.execute(sql);
}
}
const TSUserGacha = {
getUidList,
getGachaCheck,
getGachaRecords,
deleteGachaRecords,
mergeUIGF,
};
export default TSUserGacha;

View File

@@ -1,11 +1,9 @@
/** /**
* @file plugins Sqlite sql updateData.ts * @file plugins/Sqlite/sql/updateData.ts
* @description 更新数据 * @description 更新数据
* @author BTMuli <bt-muli@outlook.com> * @since Beta v0.4.7
* @since Alpha v0.2.0
*/ */
// utils
import minifySql from "../../../utils/minifySql"; import minifySql from "../../../utils/minifySql";
/** /**
@@ -26,15 +24,21 @@ export function importUIAFData(data: TGApp.Plugins.UIAF.Achievement[]): string[]
.replace("T", " ") .replace("T", " ")
.slice(0, 19); .slice(0, 19);
sql = ` sql = `
UPDATE Achievements UPDATE Achievements
SET isCompleted = 1, completedTime = '${completedTime}', progress = ${achievement.current}, updated = datetime('now', 'localtime') SET isCompleted = 1,
WHERE id = ${achievement.id} AND (isCompleted = 0 OR completedTime != '${completedTime}' OR progress != ${achievement.current}); completedTime = '${completedTime}',
progress = ${achievement.current},
updated = datetime('now', 'localtime')
WHERE id = ${achievement.id}
AND (isCompleted = 0 OR completedTime != '${completedTime}' OR progress != ${achievement.current});
`; `;
} else { } else {
sql = ` sql = `
UPDATE Achievements UPDATE Achievements
SET progress = ${achievement.current}, updated = datetime('now', 'localtime') SET progress = ${achievement.current},
WHERE id = ${achievement.id} AND progress != ${achievement.current}; updated = datetime('now', 'localtime')
WHERE id = ${achievement.id}
AND progress != ${achievement.current};
`; `;
} }
return sqlRes.push(minifySql(sql)); return sqlRes.push(minifySql(sql));
@@ -43,37 +47,30 @@ export function importUIAFData(data: TGApp.Plugins.UIAF.Achievement[]): string[]
} }
/** /**
* @description 导入UIGF数据 * @description 导入UIGF数据-单项
* @since Alpha v0.2.3 * @since Beta v0.4.7
* @param {string} uid - UID * @param {string} uid - UID
* @param {TGApp.Plugins.UIGF.GachaItem[]} data - UIGF数据 * @param {TGApp.Plugins.UIGF.GachaItem} gacha - UIGF数据
* @returns {string[]} sql * @returns {string} sql
*/ */
export function importUIGFData(uid: string, data: TGApp.Plugins.UIGF.GachaItem[]): string[] { export function importUIGFData(uid: string, gacha: TGApp.Plugins.UIGF.GachaItem): string {
const sqlRes: string[] = []; const sql = `
data.forEach((gacha) => {
const sql = `
INSERT INTO GachaRecords (uid, gachaType, itemId, count, time, name, type, rank, id, uigfType, updated) INSERT INTO GachaRecords (uid, gachaType, itemId, count, time, name, type, rank, id, uigfType, updated)
VALUES ('${uid}', '${gacha.gacha_type}', '${gacha.item_id ?? null}', '${ VALUES ('${uid}', '${gacha.gacha_type}', '${gacha.item_id ?? null}', '${gacha.count ?? null}', '${gacha.time}',
gacha.count ?? null '${gacha.name}', '${gacha.item_type ?? null}', '${gacha.rank_type ?? null}', '${gacha.id}',
}', '${gacha.time}',
'${gacha.name}', '${gacha.item_type ?? null}', '${gacha.rank_type ?? null}', '${
gacha.id
}',
'${gacha.uigf_gacha_type}', datetime('now', 'localtime')) '${gacha.uigf_gacha_type}', datetime('now', 'localtime'))
ON CONFLICT (id) DO UPDATE SET ON CONFLICT (id)
uid = '${uid}', DO UPDATE
gachaType = '${gacha.gacha_type}', SET uid = '${uid}',
uigfType = '${gacha.uigf_gacha_type}', gachaType = '${gacha.gacha_type}',
time = '${gacha.time}', uigfType = '${gacha.uigf_gacha_type}',
itemId = '${gacha.item_id ?? null}', time = '${gacha.time}',
count = '${gacha.count ?? null}', itemId = '${gacha.item_id ?? null}',
name = '${gacha.name}', count = '${gacha.count ?? null}',
type = '${gacha.item_type ?? null}', name = '${gacha.name}',
rank = '${gacha.rank_type ?? null}', type = '${gacha.item_type ?? null}',
updated = datetime('now', 'localtime'); rank = '${gacha.rank_type ?? null}',
`; updated = datetime('now', 'localtime');
sqlRes.push(minifySql(sql)); `;
}); return minifySql(sql);
return sqlRes;
} }

View File

@@ -23,7 +23,7 @@ declare namespace TGApp.Sqlite.GachaRecords {
* @property {string} updated - 数据库更新时间 * @property {string} updated - 数据库更新时间
* @return SingleTable * @return SingleTable
*/ */
export interface SingleTable { interface SingleTable {
id: string; id: string;
uid: string; uid: string;
gachaType: string; gachaType: string;