mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-14 09:38:13 +08:00
10
src/App.vue
10
src/App.vue
@@ -182,6 +182,16 @@ async function checkUserLoad(): Promise<void> {
|
|||||||
} else {
|
} else {
|
||||||
console.info("curAccount 数据已加载!");
|
console.info("curAccount 数据已加载!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const userDir = appData.find((item) => item.key === "userDir")?.value;
|
||||||
|
if (userDir === undefined) {
|
||||||
|
await TGSqlite.saveAppData("userDir", appStore.userDir);
|
||||||
|
} else if (userDir !== appStore.userDir) {
|
||||||
|
appStore.userDir = userDir;
|
||||||
|
console.info("userDir 数据已更新!");
|
||||||
|
} else {
|
||||||
|
console.info("userDir 数据已加载!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建数据文件夹
|
// 创建数据文件夹
|
||||||
|
|||||||
@@ -52,11 +52,13 @@ 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 TGSqlite from "../../plugins/Sqlite";
|
||||||
|
import { useAppStore } from "../../store/modules/app";
|
||||||
import { useUserStore } from "../../store/modules/user";
|
import { useUserStore } from "../../store/modules/user";
|
||||||
import { backupUigfData, exportUigfData, readUigfData, verifyUigfData } from "../../utils/UIGF";
|
import { backupUigfData, exportUigfData, readUigfData, verifyUigfData } from "../../utils/UIGF";
|
||||||
import TGRequest from "../../web/request/TGRequest";
|
import TGRequest from "../../web/request/TGRequest";
|
||||||
|
|
||||||
// store
|
// store
|
||||||
|
const appStore = useAppStore();
|
||||||
const userStore = storeToRefs(useUserStore());
|
const userStore = storeToRefs(useUserStore());
|
||||||
const account = userStore.account.value;
|
const account = userStore.account.value;
|
||||||
const authkey = ref<string>("");
|
const authkey = ref<string>("");
|
||||||
@@ -324,8 +326,7 @@ async function handleExportBtn(): Promise<void> {
|
|||||||
|
|
||||||
// 恢复UID祈愿数据,相当于导入祈愿数据,不过目录固定
|
// 恢复UID祈愿数据,相当于导入祈愿数据,不过目录固定
|
||||||
async function restoreGacha(): Promise<void> {
|
async function restoreGacha(): Promise<void> {
|
||||||
const backupPath = `${await path.appLocalDataDir()}userData`;
|
await handleImportBtn(appStore.userDir);
|
||||||
await handleImportBtn(backupPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 备份当前 UID 的祈愿数据
|
// 备份当前 UID 的祈愿数据
|
||||||
@@ -350,10 +351,7 @@ async function backupGacha(): Promise<void> {
|
|||||||
}
|
}
|
||||||
loadingTitle.value = "正在备份祈愿数据";
|
loadingTitle.value = "正在备份祈愿数据";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (!(await fs.exists("userData", { dir: fs.BaseDirectory.AppLocalData }))) {
|
await backupUigfData(appStore.userDir, uidCur.value, gachaListCur.value);
|
||||||
await fs.createDir("userData", { dir: fs.BaseDirectory.AppLocalData, recursive: true });
|
|
||||||
}
|
|
||||||
await backupUigfData(uidCur.value, gachaListCur.value);
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
showSnackbar({
|
showSnackbar({
|
||||||
text: `已成功备份 ${uidCur.value} 的祈愿数据`,
|
text: `已成功备份 ${uidCur.value} 的祈愿数据`,
|
||||||
|
|||||||
@@ -121,11 +121,11 @@
|
|||||||
<v-list-item prepend-icon="mdi-cog-sync" title="恢复默认设置" @click="confirmResetApp" />
|
<v-list-item prepend-icon="mdi-cog-sync" title="恢复默认设置" @click="confirmResetApp" />
|
||||||
<v-list-subheader :inset="true" class="config-header" title="路径" />
|
<v-list-subheader :inset="true" class="config-header" title="路径" />
|
||||||
<v-divider :inset="true" class="border-opacity-75" />
|
<v-divider :inset="true" class="border-opacity-75" />
|
||||||
<v-list-item
|
<v-list-item prepend-icon="mdi-folder-key">
|
||||||
prepend-icon="mdi-folder-key"
|
<v-list-item-title style="cursor: pointer" @click="confirmCUD"
|
||||||
title="本地数据库路径"
|
>本地数据库路径</v-list-item-title
|
||||||
:subtitle="appStore.dataPath.dbDataPath"
|
|
||||||
>
|
>
|
||||||
|
<v-list-item-subtitle>{{ appStore.userDir }}</v-list-item-subtitle>
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-icon @click="copyPath('db')">mdi-content-copy</v-icon>
|
<v-icon @click="copyPath('db')">mdi-content-copy</v-icon>
|
||||||
</template>
|
</template>
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
<v-list-item
|
<v-list-item
|
||||||
prepend-icon="mdi-folder-account"
|
prepend-icon="mdi-folder-account"
|
||||||
title="本地用户数据路径"
|
title="本地用户数据路径"
|
||||||
:subtitle="appStore.dataPath.userDataDir"
|
:subtitle="appStore.dbPath"
|
||||||
>
|
>
|
||||||
<template #append>
|
<template #append>
|
||||||
<v-icon @click="copyPath('user')">mdi-content-copy</v-icon>
|
<v-icon @click="copyPath('user')">mdi-content-copy</v-icon>
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { app, fs, invoke, os, process as TauriProcess } from "@tauri-apps/api";
|
import { app, dialog, fs, invoke, os, process as TauriProcess } from "@tauri-apps/api";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { computed, onMounted, ref } from "vue";
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
|
||||||
@@ -159,13 +159,11 @@ import { useAchievementsStore } from "../../store/modules/achievements";
|
|||||||
import { useAppStore } from "../../store/modules/app";
|
import { useAppStore } from "../../store/modules/app";
|
||||||
import { useHomeStore } from "../../store/modules/home";
|
import { useHomeStore } from "../../store/modules/home";
|
||||||
import { useUserStore } from "../../store/modules/user";
|
import { useUserStore } from "../../store/modules/user";
|
||||||
|
import { backUpUserData, restoreUserData } from "../../utils/dataBS";
|
||||||
import { getBuildTime } from "../../utils/TGBuild";
|
import { getBuildTime } from "../../utils/TGBuild";
|
||||||
import { bytesToSize, getCacheDir, getDeviceInfo, getRandomString } from "../../utils/toolFunc";
|
import { bytesToSize, getCacheDir, getDeviceInfo, getRandomString } from "../../utils/toolFunc";
|
||||||
import { backupUiafData, restoreUiafData } from "../../utils/UIAF";
|
|
||||||
import { getDeviceFp } from "../../web/request/getDeviceFp";
|
import { getDeviceFp } from "../../web/request/getDeviceFp";
|
||||||
import TGRequest from "../../web/request/TGRequest";
|
import TGRequest from "../../web/request/TGRequest";
|
||||||
import { backupAbyssData, backupCookieData } from "../../web/utils/backupData";
|
|
||||||
import { restoreAbyssData, restoreCookieData } from "../../web/utils/restoreData";
|
|
||||||
|
|
||||||
// Store
|
// Store
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
@@ -367,28 +365,9 @@ async function confirmBackup(): Promise<void> {
|
|||||||
}
|
}
|
||||||
loadingTitle.value = "正在备份数据...";
|
loadingTitle.value = "正在备份数据...";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
// todo 这边采用自定义路径
|
const saveDir = appStore.userDir;
|
||||||
if (!(await fs.exists("userData", { dir: fs.BaseDirectory.AppLocalData }))) {
|
loadingSub.value = "祈愿数据需单独备份";
|
||||||
await fs.createDir("userData", { dir: fs.BaseDirectory.AppLocalData, recursive: true });
|
await backUpUserData(saveDir);
|
||||||
}
|
|
||||||
console.info("数据文件夹创建完成!");
|
|
||||||
loadingSub.value = "正在获取成就数据";
|
|
||||||
const achievements = await TGSqlite.getUIAF();
|
|
||||||
loadingSub.value = "正在备份成就数据";
|
|
||||||
// todo 自定义路径
|
|
||||||
await backupUiafData(achievements);
|
|
||||||
loadingSub.value = "正在获取 Cookie";
|
|
||||||
const cookie = await TGSqlite.getCookie();
|
|
||||||
loadingSub.value = "正在备份 Cookie";
|
|
||||||
// todo 自定义路径
|
|
||||||
await backupCookieData(cookie);
|
|
||||||
loadingSub.value = "正在获取深渊数据";
|
|
||||||
const abyss = await TGSqlite.getAbyss();
|
|
||||||
loadingSub.value = "正在备份深渊数据";
|
|
||||||
// todo 自定义路径
|
|
||||||
await backupAbyssData(abyss);
|
|
||||||
// todo 其他数据备份?
|
|
||||||
loadingSub.value = "";
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
showSnackbar({ text: "数据已备份!" });
|
showSnackbar({ text: "数据已备份!" });
|
||||||
}
|
}
|
||||||
@@ -409,37 +388,9 @@ async function confirmRestore(): Promise<void> {
|
|||||||
// todo 自定义路径
|
// todo 自定义路径
|
||||||
loadingTitle.value = "正在恢复数据...";
|
loadingTitle.value = "正在恢复数据...";
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
if (!(await fs.exists("userData", { dir: fs.BaseDirectory.AppLocalData }))) {
|
loadingSub.value = "祈愿数据需单独恢复";
|
||||||
showSnackbar({
|
const saveDir = appStore.userDir;
|
||||||
color: "error",
|
await restoreUserData(saveDir);
|
||||||
text: "数据文件夹不存在!",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const fail: string[] = [];
|
|
||||||
let res: boolean;
|
|
||||||
loadingSub.value = "正在恢复成就数据";
|
|
||||||
// todo 自定义路径
|
|
||||||
res = await restoreUiafData();
|
|
||||||
if (!res) {
|
|
||||||
fail.push("成就数据");
|
|
||||||
}
|
|
||||||
loadingSub.value = "正在恢复祈愿数据";
|
|
||||||
// todo 自定义路径
|
|
||||||
res = await restoreCookieData();
|
|
||||||
userStore.cookie.value = await TGSqlite.getCookie();
|
|
||||||
if (!res) {
|
|
||||||
fail.push("Cookie");
|
|
||||||
}
|
|
||||||
loadingSub.value = "正在恢复深渊数据";
|
|
||||||
// todo 自定义路径
|
|
||||||
res = await restoreAbyssData();
|
|
||||||
if (!res) {
|
|
||||||
fail.push("深渊数据");
|
|
||||||
}
|
|
||||||
fail.length > 0
|
|
||||||
? showSnackbar({ text: `${fail.join("、")} 恢复失败!`, color: "error" })
|
|
||||||
: showSnackbar({ text: "数据已恢复!" });
|
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,13 +626,65 @@ function submitHome(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function copyPath(type: "db" | "user"): void {
|
function copyPath(type: "db" | "user"): void {
|
||||||
const path = type === "db" ? appStore.dataPath.dbDataPath : appStore.dataPath.userDataDir;
|
const path = type === "db" ? appStore.dbPath : appStore.userDir;
|
||||||
navigator.clipboard.writeText(path);
|
navigator.clipboard.writeText(path);
|
||||||
const content = type === "db" ? "数据库" : "用户数据";
|
const content = type === "db" ? "数据库" : "用户数据";
|
||||||
showSnackbar({
|
showSnackbar({
|
||||||
text: `${content}路径已复制!`,
|
text: `${content}路径已复制!`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function confirmCUD(): Promise<void> {
|
||||||
|
const oriDir = appStore.userDir;
|
||||||
|
const check = await showConfirm({
|
||||||
|
title: "确认修改用户数据路径吗?",
|
||||||
|
text: "祈愿数据需修改后重新手动备份!",
|
||||||
|
});
|
||||||
|
if (!check) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "cancel",
|
||||||
|
text: "已取消修改",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dir = await dialog.open({
|
||||||
|
directory: true,
|
||||||
|
defaultPath: oriDir,
|
||||||
|
multiple: false,
|
||||||
|
});
|
||||||
|
if (dir === null) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "error",
|
||||||
|
text: "路径不能为空!",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof dir !== "string") {
|
||||||
|
showSnackbar({
|
||||||
|
color: "error",
|
||||||
|
text: "路径错误!",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dir === oriDir) {
|
||||||
|
showSnackbar({
|
||||||
|
color: "warn",
|
||||||
|
text: "路径未修改!",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
appStore.userDir = dir;
|
||||||
|
await TGSqlite.saveAppData("userDir", dir);
|
||||||
|
await backUpUserData(dir);
|
||||||
|
await fs.removeDir(oriDir, { recursive: true });
|
||||||
|
showSnackbar({
|
||||||
|
text: "已重新备份数据!即将刷新页面!",
|
||||||
|
timeout: 3000,
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 4000);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="css" scoped>
|
<style lang="css" scoped>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file store/modules/app.ts
|
* @file store/modules/app.ts
|
||||||
* @description App store module
|
* @description App store module
|
||||||
* @since Beta v0.3.9
|
* @since Beta v0.4.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { path } from "@tauri-apps/api";
|
import { path } from "@tauri-apps/api";
|
||||||
@@ -33,15 +33,10 @@ export const useAppStore = defineStore(
|
|||||||
const theme = ref("default");
|
const theme = ref("default");
|
||||||
// 是否登录
|
// 是否登录
|
||||||
const isLogin = ref(false);
|
const isLogin = ref(false);
|
||||||
|
// 用户数据目录
|
||||||
const dataPath = reactive({
|
const userDir = ref(userDataDir);
|
||||||
userDataDir,
|
// 数据库路径
|
||||||
dbDataPath,
|
const dbPath = ref(dbDataPath);
|
||||||
});
|
|
||||||
// 用户数据路径
|
|
||||||
const userPath = ref({
|
|
||||||
UIAF: `${dataPath.userDataDir}/UIAF.json`,
|
|
||||||
});
|
|
||||||
// 设备信息
|
// 设备信息
|
||||||
const deviceInfo = ref<TGApp.App.Device.DeviceInfo>(getInitDeviceInfo());
|
const deviceInfo = ref<TGApp.App.Device.DeviceInfo>(getInitDeviceInfo());
|
||||||
|
|
||||||
@@ -69,10 +64,10 @@ export const useAppStore = defineStore(
|
|||||||
buildTime,
|
buildTime,
|
||||||
sidebar,
|
sidebar,
|
||||||
devMode,
|
devMode,
|
||||||
dataPath,
|
|
||||||
userPath,
|
|
||||||
deviceInfo,
|
deviceInfo,
|
||||||
isLogin,
|
isLogin,
|
||||||
|
userDir,
|
||||||
|
dbPath,
|
||||||
init,
|
init,
|
||||||
changeTheme,
|
changeTheme,
|
||||||
};
|
};
|
||||||
@@ -82,7 +77,7 @@ export const useAppStore = defineStore(
|
|||||||
{
|
{
|
||||||
key: "appPath",
|
key: "appPath",
|
||||||
storage: window.localStorage,
|
storage: window.localStorage,
|
||||||
paths: ["dataPath", "userPath"],
|
paths: ["userDir", "dbPath"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "app",
|
key: "app",
|
||||||
|
|||||||
6
src/types/Sqlite/AppData.d.ts
vendored
6
src/types/Sqlite/AppData.d.ts
vendored
@@ -1,19 +1,20 @@
|
|||||||
/**
|
/**
|
||||||
* @file types/Sqlite/AppData.d.ts
|
* @file types/Sqlite/AppData.d.ts
|
||||||
* @description Sqlite AppData 类型定义文件
|
* @description Sqlite AppData 类型定义文件
|
||||||
* @since Beta v0.3.8
|
* @since Beta v0.4.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare namespace TGApp.Sqlite.AppData {
|
declare namespace TGApp.Sqlite.AppData {
|
||||||
/**
|
/**
|
||||||
* @description AppData 数据库 - key 枚举
|
* @description AppData 数据库 - key 枚举
|
||||||
* @since Beta v0.3.8
|
* @since Beta v0.4.1
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
* @property {string} APP_VERSION - App 版本
|
* @property {string} APP_VERSION - App 版本
|
||||||
* @property {string} DATA_UPDATED - 数据库更新时间
|
* @property {string} DATA_UPDATED - 数据库更新时间
|
||||||
* @property {string} COOKIE - Cookie
|
* @property {string} COOKIE - Cookie
|
||||||
* @property {string} USER_INFO - 用户信息
|
* @property {string} USER_INFO - 用户信息
|
||||||
* @property {string} DEVICE_INFO - 设备信息
|
* @property {string} DEVICE_INFO - 设备信息
|
||||||
|
* @property {string} USER_DIR - 用户数据目录
|
||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
enum DBKey {
|
enum DBKey {
|
||||||
@@ -22,6 +23,7 @@ declare namespace TGApp.Sqlite.AppData {
|
|||||||
COOKIE = "cookie",
|
COOKIE = "cookie",
|
||||||
USER_INFO = "userInfo",
|
USER_INFO = "userInfo",
|
||||||
DEVICE_INFO = "deviceInfo",
|
DEVICE_INFO = "deviceInfo",
|
||||||
|
USER_DIR = "userDir",
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
* @file utils/UIAF.ts
|
* @file utils/UIAF.ts
|
||||||
* @description UIAF工具类
|
* @description UIAF工具类
|
||||||
* @since Beta v0.3.4
|
* @since Beta v0.4.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { app, fs, path } from "@tauri-apps/api";
|
import { app, fs } from "@tauri-apps/api";
|
||||||
|
|
||||||
import TGSqlite from "../plugins/Sqlite";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 根据 completed 跟 progress 获取 status
|
* @description 根据 completed 跟 progress 获取 status
|
||||||
@@ -64,32 +62,3 @@ export async function readUiafData(userPath: string): Promise<TGApp.Plugins.UIAF
|
|||||||
const fileData = await fs.readTextFile(userPath);
|
const fileData = await fs.readTextFile(userPath);
|
||||||
return <TGApp.Plugins.UIAF.Data>JSON.parse(fileData);
|
return <TGApp.Plugins.UIAF.Data>JSON.parse(fileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 根据成就数据导出 UIAF 数据
|
|
||||||
* @since Alpha v0.2.3
|
|
||||||
* @param {TGApp.Plugins.UIAF.Achievement[]} achievementData - 成就数据
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
export async function backupUiafData(
|
|
||||||
achievementData: TGApp.Plugins.UIAF.Achievement[],
|
|
||||||
): Promise<void> {
|
|
||||||
const savePath = `${await path.appLocalDataDir()}userData\\UIAF.json`;
|
|
||||||
await fs.writeTextFile(savePath, JSON.stringify(achievementData, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 根据 UIAF 数据恢复成就数据
|
|
||||||
* @since Alpha v0.2.3
|
|
||||||
* @returns {Promise<boolean>} 恢复的成就数量
|
|
||||||
*/
|
|
||||||
export async function restoreUiafData(): Promise<boolean> {
|
|
||||||
const uiafPath = `${await path.appLocalDataDir()}userData\\UIAF.json`;
|
|
||||||
// 检测是否存在 UIAF 数据
|
|
||||||
if (!(await fs.exists(uiafPath))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const uiafData: TGApp.Plugins.UIAF.Achievement[] = JSON.parse(await fs.readTextFile(uiafPath));
|
|
||||||
await TGSqlite.mergeUIAF(uiafData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @file utils/UIGF.ts
|
* @file utils/UIGF.ts
|
||||||
* @description UIGF工具类
|
* @description UIGF工具类
|
||||||
* @since Beta v0.3.8
|
* @since Beta v0.4.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { app, fs, path } from "@tauri-apps/api";
|
import { app, fs, path } from "@tauri-apps/api";
|
||||||
@@ -111,15 +111,17 @@ export async function exportUigfData(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 备份 UIGF 数据
|
* @description 备份 UIGF 数据
|
||||||
* @since Alpha v0.2.3
|
* @since Beta v0.4.1
|
||||||
|
* @param {string} dirPath - 备份路径
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
* @param {TGApp.Sqlite.GachaRecords.SingleTable[]} gachaList - 祈愿列表
|
* @param {TGApp.Sqlite.GachaRecords.SingleTable[]} gachaList - 祈愿列表
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function backupUigfData(
|
export async function backupUigfData(
|
||||||
|
dirPath: string,
|
||||||
uid: string,
|
uid: string,
|
||||||
gachaList: TGApp.Sqlite.GachaRecords.SingleTable[],
|
gachaList: TGApp.Sqlite.GachaRecords.SingleTable[],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const savePath = `${await path.appLocalDataDir()}userData\\UIGF_${uid}.json`;
|
if (!(await fs.exists(dirPath))) await fs.createDir(dirPath, { recursive: true });
|
||||||
await exportUigfData(uid, gachaList, savePath);
|
await exportUigfData(uid, gachaList, `${dirPath}${path.sep}UIGF_${uid}.json`);
|
||||||
}
|
}
|
||||||
|
|||||||
122
src/utils/dataBS.ts
Normal file
122
src/utils/dataBS.ts
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
* @file utils/dataBS.ts
|
||||||
|
* @description 用户数据的备份、恢复、迁移
|
||||||
|
* @since Beta v0.4.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fs, path } from "@tauri-apps/api";
|
||||||
|
|
||||||
|
import showSnackbar from "../components/func/snackbar";
|
||||||
|
import TGSqlite from "../plugins/Sqlite";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 备份用户数据
|
||||||
|
* @since Beta v0.4.1
|
||||||
|
* @param {string} dir 备份目录路径
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function backUpUserData(dir: string): Promise<void> {
|
||||||
|
if (!(await fs.exists(dir))) {
|
||||||
|
console.log("备份目录不存在,创建备份目录");
|
||||||
|
await fs.createDir(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
// 备份成就数据
|
||||||
|
const dataAchi = await TGSqlite.getUIAF();
|
||||||
|
await fs.writeTextFile(`${dir}${path.sep}UIAF.json`, JSON.stringify(dataAchi));
|
||||||
|
// 备份 ck
|
||||||
|
const dataCK = await TGSqlite.getCookie();
|
||||||
|
await fs.writeTextFile(`${dir}${path.sep}cookie.json`, JSON.stringify(dataCK));
|
||||||
|
// 备份深渊数据
|
||||||
|
const dataAbyss = await TGSqlite.getAbyss();
|
||||||
|
await fs.writeTextFile(`${dir}${path.sep}abyss.json`, JSON.stringify(dataAbyss));
|
||||||
|
// todo 添加祈愿数据备份支持
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 恢复用户数据
|
||||||
|
* @since Beta v0.4.1
|
||||||
|
* @param {string} dir 备份目录路径
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
export async function restoreUserData(dir: string): Promise<void> {
|
||||||
|
let errNum = 0;
|
||||||
|
if (!(await fs.exists(dir))) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "备份目录不存在",
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 恢复成就数据
|
||||||
|
const dataAchiPath = `${dir}${path.sep}UIAF.json`;
|
||||||
|
if (await fs.exists(dataAchiPath)) {
|
||||||
|
try {
|
||||||
|
const dataAchi: TGApp.Plugins.UIAF.Achievement[] = JSON.parse(
|
||||||
|
await fs.readTextFile(dataAchiPath),
|
||||||
|
);
|
||||||
|
await TGSqlite.mergeUIAF(dataAchi);
|
||||||
|
} catch (e) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "成就数据恢复失败",
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
errNum++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showSnackbar({
|
||||||
|
text: "成就数据恢复失败,备份文件不存在",
|
||||||
|
color: "warn",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 恢复 ck
|
||||||
|
const dataCKPath = `${dir}${path.sep}cookie.json`;
|
||||||
|
if (await fs.exists(dataCKPath)) {
|
||||||
|
try {
|
||||||
|
const dataCK = await fs.readTextFile(dataCKPath);
|
||||||
|
await TGSqlite.saveAppData("cookie", JSON.stringify(JSON.parse(dataCK)));
|
||||||
|
} catch (e) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "Cookie 数据恢复失败",
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
errNum++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showSnackbar({
|
||||||
|
text: "Cookie 数据恢复失败,备份文件不存在",
|
||||||
|
color: "warn",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 恢复深渊数据
|
||||||
|
const dataAbyssPath = `${dir}${path.sep}abyss.json`;
|
||||||
|
if (await fs.exists(dataAbyssPath)) {
|
||||||
|
try {
|
||||||
|
const dataAbyss: TGApp.Sqlite.Abyss.SingleTable[] = JSON.parse(
|
||||||
|
await fs.readTextFile(dataAbyssPath),
|
||||||
|
);
|
||||||
|
await TGSqlite.restoreAbyss(dataAbyss);
|
||||||
|
} catch (e) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "深渊数据恢复失败",
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
errNum++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showSnackbar({
|
||||||
|
text: "深渊数据恢复失败,备份文件不存在",
|
||||||
|
color: "warn",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (errNum === 0) {
|
||||||
|
showSnackbar({
|
||||||
|
text: "数据恢复成功",
|
||||||
|
color: "success",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
showSnackbar({
|
||||||
|
text: `数据恢复失败,失败数量:${errNum}`,
|
||||||
|
color: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file web/utils/backupData.ts
|
|
||||||
* @description 数据备份
|
|
||||||
* @since Alpha v0.1.5
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { fs, path } from "@tauri-apps/api";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 备份 Cookie 数据
|
|
||||||
* @since Alpha v0.2.0
|
|
||||||
* @param {TGApp.User.Account.Cookie} cookie cookie
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
export async function backupCookieData(cookie: TGApp.User.Account.Cookie): Promise<void> {
|
|
||||||
const savePath = `${await path.appLocalDataDir()}\\userData\\cookie.json`;
|
|
||||||
await fs.writeTextFile(savePath, JSON.stringify(cookie, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 备份深渊数据
|
|
||||||
* @since Alpha v0.2.0
|
|
||||||
* @param {TGApp.Sqlite.Abyss.SingleTable[]} abyssData 深渊数据
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
export async function backupAbyssData(abyssData: TGApp.Sqlite.Abyss.SingleTable[]): Promise<void> {
|
|
||||||
const savePath = `${await path.appLocalDataDir()}\\userData\\abyss.json`;
|
|
||||||
await fs.writeTextFile(savePath, JSON.stringify(abyssData, null, 2));
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file web/utils/restoreData.ts
|
|
||||||
* @description 数据恢复
|
|
||||||
* @since Beta v0.3.9
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { fs, path } from "@tauri-apps/api";
|
|
||||||
|
|
||||||
import TGSqlite from "../../plugins/Sqlite";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 恢复 Cookie 数据
|
|
||||||
* @since Alpha v0.2.0
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
export async function restoreCookieData(): Promise<boolean> {
|
|
||||||
const cookiePath = `${await path.appLocalDataDir()}\\userData\\cookie.json`;
|
|
||||||
if (!(await fs.exists(cookiePath))) return false;
|
|
||||||
const cookieData = await fs.readTextFile(cookiePath);
|
|
||||||
await TGSqlite.saveAppData("cookie", JSON.stringify(JSON.parse(cookieData)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 恢复深渊数据
|
|
||||||
* @since Beta v0.3.9
|
|
||||||
* @returns {Promise<boolean>}
|
|
||||||
*/
|
|
||||||
export async function restoreAbyssData(): Promise<boolean> {
|
|
||||||
const abyssPath = `${await path.appLocalDataDir()}\\userData\\abyss.json`;
|
|
||||||
if (!(await fs.exists(abyssPath))) return false;
|
|
||||||
const abyssData = await fs.readTextFile(abyssPath);
|
|
||||||
const parseData = JSON.parse(abyssData);
|
|
||||||
if (!parseData || !Array.isArray(parseData)) return false;
|
|
||||||
await TGSqlite.restoreAbyss(<TGApp.Sqlite.Abyss.SingleTable[]>parseData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user