mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-14 09:38:13 +08:00
🌱 初步完成UIGF 导入导出备份恢复,并参照优化UIAF相关代码
This commit is contained in:
@@ -1,5 +1,146 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<ToLoading v-model="loading" :title="loadingTitle" />
|
||||||
<h1>祈愿数据获取、展示、统计</h1>
|
<h1>祈愿数据获取、展示、统计</h1>
|
||||||
|
<v-btn @click="handleImportBtn">导入</v-btn>
|
||||||
|
<v-btn @click="handleExportBtn">导出</v-btn>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
<style lang="css" scoped></style>
|
// vue
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import showSnackbar from "../../components/func/snackbar";
|
||||||
|
import showConfirm from "../../components/func/confirm";
|
||||||
|
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||||
|
// tauri
|
||||||
|
import { dialog } from "@tauri-apps/api";
|
||||||
|
// store
|
||||||
|
import { useUserStore } from "../../store/modules/user";
|
||||||
|
// utils
|
||||||
|
import { exportUigfData, readUigfData, verifyUigfData } from "../../utils/UIGF";
|
||||||
|
import TGSqlite from "../../plugins/Sqlite";
|
||||||
|
|
||||||
|
// store
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// loading
|
||||||
|
const loading = ref<boolean>(true);
|
||||||
|
const loadingTitle = ref<string>();
|
||||||
|
|
||||||
|
// data
|
||||||
|
const user = userStore.getCurAccount();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 导入按钮点击事件
|
||||||
|
async function handleImportBtn(): Promise<void> {
|
||||||
|
const selectedFile = await dialog.open({
|
||||||
|
multiple: false,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: "UIGF",
|
||||||
|
extensions: ["json"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
if (selectedFile) {
|
||||||
|
const check = await verifyUigfData(<string>selectedFile);
|
||||||
|
if (!check) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "error",
|
||||||
|
text: `读取 UIGF 文件失败,请检查文件是否符合规范`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const remoteData = await readUigfData(<string>selectedFile);
|
||||||
|
if (remoteData.info.uid !== user.gameUid) {
|
||||||
|
await showConfirm({
|
||||||
|
title: "UID 不匹配,是否继续导入?",
|
||||||
|
text: `当前 UID:${user.gameUid},导入 UID:${remoteData.info.uid}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const res = await showConfirm({
|
||||||
|
title: "是否导入祈愿数据?",
|
||||||
|
text: `UID:${remoteData.info.uid} 共 ${remoteData.list.length} 条数据`,
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "grey",
|
||||||
|
text: `已取消祈愿数据导入`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadingTitle.value = "正在导入祈愿数据";
|
||||||
|
loading.value = true;
|
||||||
|
await importRemoteData(remoteData);
|
||||||
|
loading.value = false;
|
||||||
|
showSnackbar({
|
||||||
|
text: `成功导入 ${remoteData.list.length} 条祈愿数据`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showSnackbar({
|
||||||
|
color: "grey",
|
||||||
|
text: `已取消文件选择`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导入
|
||||||
|
async function importRemoteData(data: TGApp.Plugins.UIGF.FullData): Promise<void> {
|
||||||
|
if (data.list.length === 0) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "error",
|
||||||
|
text: `导入的祈愿数据为空`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await TGSqlite.mergeUIGF(user.gameUid, data.list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出按钮点击事件
|
||||||
|
async function handleExportBtn(): Promise<void> {
|
||||||
|
const gachaList = await TGSqlite.getGachaRecords(user.gameUid);
|
||||||
|
if (gachaList.length === 0) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "error",
|
||||||
|
text: `用户 ${user.gameUid} 暂无祈愿数据`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await showConfirm({
|
||||||
|
title: `是否导出祈愿数据?`,
|
||||||
|
text: `UID:${user.gameUid},共 ${gachaList.length} 条数据`,
|
||||||
|
});
|
||||||
|
if (!res) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "grey",
|
||||||
|
text: `已取消祈愿数据导出`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = await dialog.save({
|
||||||
|
defaultPath: `UIGF_${user.gameUid}.json`,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: `UIGF`,
|
||||||
|
extensions: ["json"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
if (!file) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "grey",
|
||||||
|
text: `已取消文件保存`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadingTitle.value = "正在导出祈愿数据";
|
||||||
|
loading.value = true;
|
||||||
|
await exportUigfData(user.gameUid, gachaList);
|
||||||
|
loading.value = false;
|
||||||
|
showSnackbar({
|
||||||
|
text: `祈愿数据已成功导出`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -266,25 +266,30 @@ async function importJson(): Promise<void> {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
if (selectedFile && (await verifyUiafData(<string>selectedFile))) {
|
if (!selectedFile) {
|
||||||
const remoteRaw: string | false = await readUiafData(<string>selectedFile);
|
showSnackbar({
|
||||||
if (remoteRaw === false) {
|
color: "grey",
|
||||||
|
text: "已取消文件选择",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!(await verifyUiafData(<string>selectedFile))) {
|
||||||
showSnackbar({
|
showSnackbar({
|
||||||
color: "error",
|
color: "error",
|
||||||
text: "读取 UIAF 数据失败,请检查文件是否符合规范",
|
text: "读取 UIAF 数据失败,请检查文件是否符合规范",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const remoteRaw = await readUiafData(<string>selectedFile);
|
||||||
loadingTitle.value = "正在解析数据";
|
loadingTitle.value = "正在解析数据";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
loadingTitle.value = "正在合并成就数据";
|
loadingTitle.value = "正在合并成就数据";
|
||||||
await TGSqlite.mergeUIAF(JSON.parse(remoteRaw).list);
|
await TGSqlite.mergeUIAF(remoteRaw.list);
|
||||||
loadingTitle.value = "即将刷新页面";
|
loadingTitle.value = "即将刷新页面";
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
async function exportJson(): Promise<void> {
|
async function exportJson(): Promise<void> {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<ToLoading v-model="loading" :title="loadingTitle" />
|
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" />
|
||||||
<v-list class="config-list">
|
<v-list class="config-list">
|
||||||
<v-list-subheader :inset="true" class="config-header"> 应用信息</v-list-subheader>
|
<v-list-subheader :inset="true" class="config-header"> 应用信息</v-list-subheader>
|
||||||
<v-divider :inset="true" class="border-opacity-75" />
|
<v-divider :inset="true" class="border-opacity-75" />
|
||||||
@@ -76,25 +76,25 @@
|
|||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item title="数据库更新时间" prepend-icon="mdi-database">
|
<v-list-item title="数据库更新时间" prepend-icon="mdi-database">
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-list-item-subtitle>{{
|
<v-list-item-subtitle
|
||||||
dbInfo.find((item) => item.key === "dataUpdated")?.value
|
>{{ dbInfo.find((item) => item.key === "dataUpdated")?.value }}
|
||||||
}}</v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
</template>
|
</template>
|
||||||
<v-list-item-subtitle
|
<v-list-item-subtitle
|
||||||
>更新于
|
>更新于
|
||||||
{{ dbInfo.find((item) => item.key === "dataUpdated")?.updated }}</v-list-item-subtitle
|
{{ dbInfo.find((item) => item.key === "dataUpdated")?.updated }}
|
||||||
>
|
</v-list-item-subtitle>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-item title="数据库版本" prepend-icon="mdi-database">
|
<v-list-item title="数据库版本" prepend-icon="mdi-database">
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-list-item-subtitle>{{
|
<v-list-item-subtitle
|
||||||
dbInfo.find((item) => item.key === "appVersion")?.value
|
>{{ dbInfo.find((item) => item.key === "appVersion")?.value }}
|
||||||
}}</v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
</template>
|
</template>
|
||||||
<v-list-item-subtitle
|
<v-list-item-subtitle
|
||||||
>更新于
|
>更新于
|
||||||
{{ dbInfo.find((item) => item.key === "appVersion")?.updated }}</v-list-item-subtitle
|
{{ dbInfo.find((item) => item.key === "appVersion")?.updated }}
|
||||||
>
|
</v-list-item-subtitle>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-list-subheader :inset="true" class="config-header"> 设置</v-list-subheader>
|
<v-list-subheader :inset="true" class="config-header"> 设置</v-list-subheader>
|
||||||
<v-divider :inset="true" class="border-opacity-75" />
|
<v-divider :inset="true" class="border-opacity-75" />
|
||||||
@@ -194,6 +194,7 @@ import { useAchievementsStore } from "../../store/modules/achievements";
|
|||||||
import { useUserStore } from "../../store/modules/user";
|
import { useUserStore } from "../../store/modules/user";
|
||||||
// utils
|
// utils
|
||||||
import { backupUiafData, restoreUiafData } from "../../utils/UIAF";
|
import { backupUiafData, restoreUiafData } from "../../utils/UIAF";
|
||||||
|
import { backupUigfData, restoreUigfData } from "../../utils/UIGF";
|
||||||
import { backupAbyssData, backupCookieData } from "../../web/utils/backupData";
|
import { backupAbyssData, backupCookieData } from "../../web/utils/backupData";
|
||||||
import { restoreAbyssData, restoreCookieData } from "../../web/utils/restoreData";
|
import { restoreAbyssData, restoreCookieData } from "../../web/utils/restoreData";
|
||||||
import TGSqlite from "../../plugins/Sqlite";
|
import TGSqlite from "../../plugins/Sqlite";
|
||||||
@@ -218,6 +219,7 @@ const dbInfo = ref<Array<{ key: string; value: string; updated: string }>>([]);
|
|||||||
// loading
|
// loading
|
||||||
const loading = ref<boolean>(true);
|
const loading = ref<boolean>(true);
|
||||||
const loadingTitle = ref<string>("正在加载...");
|
const loadingTitle = ref<string>("正在加载...");
|
||||||
|
const loadingSub = ref<string>("");
|
||||||
|
|
||||||
// data
|
// data
|
||||||
const showHome = ref<string[]>(homeStore.getShowValue());
|
const showHome = ref<string[]>(homeStore.getShowValue());
|
||||||
@@ -233,10 +235,15 @@ const userInfo = computed(() => {
|
|||||||
|
|
||||||
// load version
|
// load version
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
loadingSub.value = "正在获取应用版本";
|
||||||
versionApp.value = await app.getVersion();
|
versionApp.value = await app.getVersion();
|
||||||
|
loadingSub.value = "正在获取 Tauri 版本";
|
||||||
versionTauri.value = await app.getTauriVersion();
|
versionTauri.value = await app.getTauriVersion();
|
||||||
|
loadingSub.value = "正在获取系统信息";
|
||||||
osPlatform.value = `${await os.platform()}`;
|
osPlatform.value = `${await os.platform()}`;
|
||||||
|
loadingSub.value = "正在获取系统版本";
|
||||||
osVersion.value = await os.version();
|
osVersion.value = await os.version();
|
||||||
|
loadingSub.value = "正在获取数据库信息";
|
||||||
try {
|
try {
|
||||||
dbInfo.value = await TGSqlite.getAppData();
|
dbInfo.value = await TGSqlite.getAppData();
|
||||||
const ck = dbInfo.value.find((v) => v.key === "cookie");
|
const ck = dbInfo.value.find((v) => v.key === "cookie");
|
||||||
@@ -249,6 +256,7 @@ onMounted(async () => {
|
|||||||
text: "读取数据库失败!",
|
text: "读取数据库失败!",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
loadingSub.value = "";
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -264,7 +272,7 @@ async function confirmRefreshUser(): Promise<void> {
|
|||||||
text: "将会重新获取用户信息",
|
text: "将会重新获取用户信息",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消刷新",
|
text: "已取消刷新",
|
||||||
});
|
});
|
||||||
@@ -347,7 +355,7 @@ async function confirmBackup(): Promise<void> {
|
|||||||
text: "若已备份将会被覆盖",
|
text: "若已备份将会被覆盖",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消备份",
|
text: "已取消备份",
|
||||||
});
|
});
|
||||||
@@ -355,12 +363,28 @@ async function confirmBackup(): Promise<void> {
|
|||||||
}
|
}
|
||||||
loadingTitle.value = "正在备份数据...";
|
loadingTitle.value = "正在备份数据...";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
loadingSub.value = "正在获取成就数据";
|
||||||
const achievements = await TGSqlite.getUIAF();
|
const achievements = await TGSqlite.getUIAF();
|
||||||
|
loadingSub.value = "正在备份成就数据";
|
||||||
await backupUiafData(achievements);
|
await backupUiafData(achievements);
|
||||||
|
loadingSub.value = "正在获取 Cookie";
|
||||||
const cookie = await TGSqlite.getCookie();
|
const cookie = await TGSqlite.getCookie();
|
||||||
|
loadingSub.value = "正在备份 Cookie";
|
||||||
await backupCookieData(cookie);
|
await backupCookieData(cookie);
|
||||||
|
loadingSub.value = "正在获取深渊数据";
|
||||||
const abyss = await TGSqlite.getAbyss();
|
const abyss = await TGSqlite.getAbyss();
|
||||||
|
loadingSub.value = "正在备份深渊数据";
|
||||||
await backupAbyssData(abyss);
|
await backupAbyssData(abyss);
|
||||||
|
if (userInfo.value.uid === "-1") {
|
||||||
|
loadingSub.value = "用户未登录,跳过祈愿数据备份";
|
||||||
|
} else {
|
||||||
|
loadingSub.value = "正在获取祈愿数据";
|
||||||
|
const gameUid = userStore.getCurAccount().gameUid;
|
||||||
|
const gacha = await TGSqlite.getGachaRecords(gameUid);
|
||||||
|
loadingSub.value = "正在备份祈愿数据";
|
||||||
|
await backupUigfData(gameUid, gacha);
|
||||||
|
}
|
||||||
|
loadingSub.value = "";
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
showSnackbar({ text: "数据已备份!" });
|
showSnackbar({ text: "数据已备份!" });
|
||||||
}
|
}
|
||||||
@@ -372,7 +396,7 @@ async function confirmRestore(): Promise<void> {
|
|||||||
text: "请确保存在备份数据",
|
text: "请确保存在备份数据",
|
||||||
});
|
});
|
||||||
if (!resConfirm) {
|
if (!resConfirm) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消恢复",
|
text: "已取消恢复",
|
||||||
});
|
});
|
||||||
@@ -380,19 +404,39 @@ async function confirmRestore(): Promise<void> {
|
|||||||
}
|
}
|
||||||
loadingTitle.value = "正在恢复数据...";
|
loadingTitle.value = "正在恢复数据...";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const fail = [];
|
const fail: string[] = [];
|
||||||
let res = await restoreUiafData();
|
let res: boolean;
|
||||||
|
loadingSub.value = "正在恢复成就数据";
|
||||||
|
res = await restoreUiafData();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
fail.push("成就数据");
|
fail.push("成就数据");
|
||||||
}
|
}
|
||||||
|
loadingSub.value = "正在恢复祈愿数据";
|
||||||
res = await restoreCookieData();
|
res = await restoreCookieData();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
fail.push("Cookie");
|
fail.push("Cookie");
|
||||||
}
|
}
|
||||||
|
loadingSub.value = "正在恢复深渊数据";
|
||||||
res = await restoreAbyssData();
|
res = await restoreAbyssData();
|
||||||
if (!res) {
|
if (!res) {
|
||||||
fail.push("深渊数据");
|
fail.push("深渊数据");
|
||||||
}
|
}
|
||||||
|
if (userInfo.value.uid === "-1") {
|
||||||
|
showSnackbar({
|
||||||
|
color: "grey",
|
||||||
|
text: "用户未登录,跳过祈愿数据恢复",
|
||||||
|
});
|
||||||
|
await new Promise(() => {
|
||||||
|
setTimeout(() => {}, 1500);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
loadingSub.value = "正在恢复祈愿数据";
|
||||||
|
const gameUid = userStore.getCurAccount().gameUid;
|
||||||
|
res = await restoreUigfData(gameUid);
|
||||||
|
if (!res) {
|
||||||
|
fail.push("祈愿数据");
|
||||||
|
}
|
||||||
|
}
|
||||||
fail.length > 0
|
fail.length > 0
|
||||||
? showSnackbar({ text: `${fail.join("、")} 恢复失败!`, color: "error" })
|
? showSnackbar({ text: `${fail.join("、")} 恢复失败!`, color: "error" })
|
||||||
: showSnackbar({ text: "数据已恢复!" });
|
: showSnackbar({ text: "数据已恢复!" });
|
||||||
@@ -408,7 +452,7 @@ async function confirmUpdate(title?: string): Promise<void> {
|
|||||||
text: "请确保存在备份数据",
|
text: "请确保存在备份数据",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消更新数据库",
|
text: "已取消更新数据库",
|
||||||
});
|
});
|
||||||
@@ -433,9 +477,9 @@ async function confirmDelUC(): Promise<void> {
|
|||||||
text: "备份数据也将被清除",
|
text: "备份数据也将被清除",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消清除",
|
text: "已取消清除用户缓存",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -454,9 +498,9 @@ async function confirmDelTemp(): Promise<void> {
|
|||||||
title: "确认清除临时数据吗?",
|
title: "确认清除临时数据吗?",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消清除",
|
text: "已取消清除临时数据",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -474,9 +518,9 @@ async function confirmResetApp(): Promise<void> {
|
|||||||
title: "确认恢复默认设置吗?",
|
title: "确认恢复默认设置吗?",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消恢复",
|
text: "已取消恢复默认设置",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -495,16 +539,16 @@ async function confirmInputCK(): Promise<void> {
|
|||||||
title: "确认手动输入 Cookie 吗?",
|
title: "确认手动输入 Cookie 吗?",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消输入",
|
text: "已取消输入Cookie",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (typeof res !== "string") {
|
if (typeof res !== "string") {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "error",
|
color: "error",
|
||||||
text: "参数错误!",
|
text: "Confirm组件类型错误!",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -566,7 +610,7 @@ async function confirmResetDB(title?: string): Promise<void> {
|
|||||||
text: "请确认已经备份关键数据",
|
text: "请确认已经备份关键数据",
|
||||||
});
|
});
|
||||||
if (!res) {
|
if (!res) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消重置数据库",
|
text: "已取消重置数据库",
|
||||||
});
|
});
|
||||||
@@ -590,7 +634,7 @@ async function confirmCheckDB(): Promise<void> {
|
|||||||
title: "确认检测数据库完整性吗?",
|
title: "确认检测数据库完整性吗?",
|
||||||
});
|
});
|
||||||
if (!resConfirm) {
|
if (!resConfirm) {
|
||||||
snackbar({
|
showSnackbar({
|
||||||
color: "grey",
|
color: "grey",
|
||||||
text: "已取消检测",
|
text: "已取消检测",
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -488,13 +488,12 @@ class Sqlite {
|
|||||||
* @description 合并祈愿数据
|
* @description 合并祈愿数据
|
||||||
* @since Alpha v0.2.3
|
* @since Alpha v0.2.3
|
||||||
* @param {string} uid UID
|
* @param {string} uid UID
|
||||||
* @param {string} data UIGF 数据
|
* @param {TGApp.Plugins.UIGF.GachaItem[]} data UIGF 数据
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
public async mergeUIGF(uid: string, data: string): Promise<void> {
|
public async mergeUIGF(uid: string, data: TGApp.Plugins.UIGF.GachaItem[]): Promise<void> {
|
||||||
const db = await Database.load(this.dbPath);
|
const db = await Database.load(this.dbPath);
|
||||||
const gachaList: TGApp.Plugins.UIGF.GachaItem[] = JSON.parse(data);
|
const sql = importUIGFData(uid, data);
|
||||||
const sql = importUIGFData(uid, gachaList);
|
|
||||||
for (const item of sql) {
|
for (const item of sql) {
|
||||||
await db.execute(item);
|
await db.execute(item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,55 +46,47 @@ export async function getUiafHeader(): Promise<TGApp.Plugins.UIAF.Export> {
|
|||||||
/**
|
/**
|
||||||
* @description 检测是否存在 UIAF 数据
|
* @description 检测是否存在 UIAF 数据
|
||||||
* @description 粗略检测,不保证数据完整性
|
* @description 粗略检测,不保证数据完整性
|
||||||
* @since Alpha v0.1.3
|
* @since Alpha v0.2.3
|
||||||
* @param {string} path - UIAF 数据路径
|
* @param {string} path - UIAF 数据路径
|
||||||
* @returns {Promise<boolean>} 是否存在 UIAF 数据
|
* @returns {Promise<boolean>} 是否存在 UIAF 数据
|
||||||
*/
|
*/
|
||||||
export async function verifyUiafData(path: string): Promise<boolean> {
|
export async function verifyUiafData(path: string): Promise<boolean> {
|
||||||
const fileData: string = await fs.readTextFile(path);
|
const fileData: string = await fs.readTextFile(path);
|
||||||
const UiafData: TGApp.Plugins.UIAF.Export = JSON.parse(fileData).info;
|
const UiafData: TGApp.Plugins.UIAF.Export = JSON.parse(fileData)?.info;
|
||||||
return UiafData.uiaf_version !== undefined;
|
return UiafData?.uiaf_version !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 读取 UIAF 数据
|
* @description 读取 UIAF 数据
|
||||||
* @since Alpha v0.1.3
|
* @since Alpha v0.2.3
|
||||||
* @param {string} userPath - UIAF 数据路径
|
* @param {string} userPath - UIAF 数据路径
|
||||||
* @returns {Promise<string|false>} UIAF 数据
|
* @returns {Promise<TGApp.Plugins.UIAF.Data>} UIAF 数据
|
||||||
*/
|
*/
|
||||||
export async function readUiafData(userPath: string): Promise<string | false> {
|
export async function readUiafData(userPath: string): Promise<TGApp.Plugins.UIAF.Data> {
|
||||||
if (await fs.exists(userPath)) {
|
|
||||||
const fileData = await fs.readTextFile(userPath);
|
const fileData = await fs.readTextFile(userPath);
|
||||||
if (fileData !== undefined && fileData !== null && fileData !== "" && fileData !== "{}") {
|
return <TGApp.Plugins.UIAF.Data>JSON.parse(fileData);
|
||||||
return fileData;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 根据成就数据导出 UIAF 数据
|
* @description 根据成就数据导出 UIAF 数据
|
||||||
* @since Alpha v0.1.4
|
* @since Alpha v0.2.3
|
||||||
* @param {TGApp.Plugins.UIAF.Achievement[]} achievementData - 成就数据
|
* @param {TGApp.Plugins.UIAF.Achievement[]} achievementData - 成就数据
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function backupUiafData(
|
export async function backupUiafData(
|
||||||
achievementData: TGApp.Plugins.UIAF.Achievement[],
|
achievementData: TGApp.Plugins.UIAF.Achievement[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const savePath = `${await path.appLocalDataDir()}\\userData\\UIAF.json`;
|
const savePath = `${await path.appLocalDataDir()}userData\\UIAF.json`;
|
||||||
await fs.writeTextFile(savePath, JSON.stringify(achievementData, null, 2));
|
await fs.writeTextFile(savePath, JSON.stringify(achievementData, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 根据 UIAF 数据恢复成就数据
|
* @description 根据 UIAF 数据恢复成就数据
|
||||||
* @since Alpha v0.1.4
|
* @since Alpha v0.2.3
|
||||||
* @returns {Promise<boolean>} 恢复的成就数量
|
* @returns {Promise<boolean>} 恢复的成就数量
|
||||||
*/
|
*/
|
||||||
export async function restoreUiafData(): Promise<boolean> {
|
export async function restoreUiafData(): Promise<boolean> {
|
||||||
const uiafPath = `${await path.appLocalDataDir()}\\userData\\UIAF.json`;
|
const uiafPath = `${await path.appLocalDataDir()}userData\\UIAF.json`;
|
||||||
// 检测是否存在 UIAF 数据
|
// 检测是否存在 UIAF 数据
|
||||||
if (!(await fs.exists(uiafPath))) {
|
if (!(await fs.exists(uiafPath))) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -30,6 +30,30 @@ export async function getUigfHeader(uid: string): Promise<TGApp.Plugins.UIGF.Exp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 数据转换-数据库到 UIGF
|
||||||
|
* @since Alpha v0.2.3
|
||||||
|
* @param {TGApp.Sqlite.GachaRecords.SingleTable[]} data - 数据库数据
|
||||||
|
* @returns {TGApp.Plugins.UIGF.GachaItem[]} UIGF 数据
|
||||||
|
*/
|
||||||
|
export function convertDataToUigf(
|
||||||
|
data: TGApp.Sqlite.GachaRecords.SingleTable[],
|
||||||
|
): TGApp.Plugins.UIGF.GachaItem[] {
|
||||||
|
return data.map((gacha) => {
|
||||||
|
return {
|
||||||
|
gacha_type: gacha.gachaType,
|
||||||
|
item_id: gacha.itemId,
|
||||||
|
count: gacha.count,
|
||||||
|
time: gacha.time,
|
||||||
|
name: gacha.name,
|
||||||
|
item_type: gacha.type,
|
||||||
|
rank_type: gacha.rank,
|
||||||
|
id: gacha.id,
|
||||||
|
uigf_gacha_type: gacha.uigfType,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 检测是否存在 UIGF 数据
|
* @description 检测是否存在 UIGF 数据
|
||||||
* @description 粗略检测,不保证数据完整性
|
* @description 粗略检测,不保证数据完整性
|
||||||
@@ -39,42 +63,55 @@ export async function getUigfHeader(uid: string): Promise<TGApp.Plugins.UIGF.Exp
|
|||||||
*/
|
*/
|
||||||
export async function verifyUigfData(path: string): Promise<boolean> {
|
export async function verifyUigfData(path: string): Promise<boolean> {
|
||||||
const fileData: string = await fs.readTextFile(path);
|
const fileData: string = await fs.readTextFile(path);
|
||||||
const UigfData: TGApp.Plugins.UIGF.Export = JSON.parse(fileData).info;
|
const UigfData: TGApp.Plugins.UIGF.Export = JSON.parse(fileData)?.info;
|
||||||
return UigfData.uigf_version !== undefined;
|
return UigfData?.uigf_version !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 读取 UIGF 数据
|
* @description 读取 UIGF 数据
|
||||||
* @since Alpha v0.2.3
|
* @since Alpha v0.2.3
|
||||||
* @param {string} userPath - UIGF 数据路径
|
* @param {string} userPath - UIGF 数据路径
|
||||||
* @returns {Promise<string|false>} UIGF 数据
|
* @returns {Promise<TGApp.Plugins.UIGF.FullData>} UIGF 数据
|
||||||
*/
|
*/
|
||||||
export async function readUigfData(userPath: string): Promise<string | false> {
|
export async function readUigfData(userPath: string): Promise<TGApp.Plugins.UIGF.FullData> {
|
||||||
if (await fs.exists(userPath)) {
|
|
||||||
const fileData = await fs.readTextFile(userPath);
|
const fileData = await fs.readTextFile(userPath);
|
||||||
if (fileData !== undefined && fileData !== null && fileData !== "" && fileData !== "{}") {
|
return <TGApp.Plugins.UIGF.FullData>JSON.parse(fileData);
|
||||||
return fileData;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 导出 UIGF 数据
|
||||||
|
* @since Alpha v0.2.3
|
||||||
|
* @param {string} uid - UID
|
||||||
|
* @param {TGApp.Sqlite.GachaRecords.SingleTable[]} gachaList - 祈愿列表
|
||||||
|
* @param {string} savePath - 保存路径
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function exportUigfData(
|
||||||
|
uid: string,
|
||||||
|
gachaList: TGApp.Sqlite.GachaRecords.SingleTable[],
|
||||||
|
savePath?: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const UigfData = {
|
||||||
|
info: await getUigfHeader(uid),
|
||||||
|
list: convertDataToUigf(gachaList),
|
||||||
|
};
|
||||||
|
const filePath = savePath ?? `${await path.appLocalDataDir()}userData\\UIGF_${uid}.json`;
|
||||||
|
await fs.writeTextFile(filePath, JSON.stringify(UigfData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 备份 UIGF 数据
|
* @description 备份 UIGF 数据
|
||||||
* @since Alpha v0.2.3
|
* @since Alpha v0.2.3
|
||||||
* @param {TGApp.Plugins.UIAF.GachaItem[]} gachaList - 祈愿列表
|
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
|
* @param {TGApp.Sqlite.GachaRecords.SingleTable[]} gachaList - 祈愿列表
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function backupUigfData(
|
export async function backupUigfData(
|
||||||
gachaList: TGApp.Plugins.UIGF.GachaItem[],
|
|
||||||
uid: string,
|
uid: string,
|
||||||
|
gachaList: TGApp.Sqlite.GachaRecords.SingleTable[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const savePath = `${await path.appLocalDataDir()}\\userData\\UIGF_${uid}.json`;
|
const savePath = `${await path.appLocalDataDir()}userData\\UIGF_${uid}.json`;
|
||||||
await fs.writeTextFile(savePath, JSON.stringify(gachaList, null, 2));
|
await exportUigfData(uid, gachaList, savePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,9 +121,11 @@ export async function backupUigfData(
|
|||||||
* @returns {Promise<boolean>} UIGF 数据
|
* @returns {Promise<boolean>} UIGF 数据
|
||||||
*/
|
*/
|
||||||
export async function restoreUigfData(uid: string): Promise<boolean> {
|
export async function restoreUigfData(uid: string): Promise<boolean> {
|
||||||
const uigfPath = `${await path.appLocalDataDir()}\\userData\\UIGF_${uid}.json`;
|
const uigfPath = `${await path.appLocalDataDir()}userData\\UIGF_${uid}.json`;
|
||||||
|
if (!(await fs.exists(uigfPath))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const uigfData = await readUigfData(uigfPath);
|
const uigfData = await readUigfData(uigfPath);
|
||||||
if (uigfData === false) return false;
|
await TGSqlite.mergeUIGF(uid, uigfData.list);
|
||||||
await TGSqlite.mergeUIGF(uid, uigfData);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user