mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-04-03 06:55:06 +08:00
♻️ 祈愿数据备份迭代,采用UIGF4,调整导入进度更新逻辑
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
<div class="ugo-title">{{ title }}</div>
|
<div class="ugo-title">{{ title }}</div>
|
||||||
<div class="ugo-fp" title="点击选择文件路径" @click="selectFile()">文件路径:{{ fp }}</div>
|
<div class="ugo-fp" title="点击选择文件路径" @click="selectFile()">文件路径:{{ fp }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ugo-header" v-if="props.mode === 'import' && dataRaw">
|
<div v-if="props.mode === 'import' && dataRaw" class="ugo-header">
|
||||||
<div class="ugo-header-item">
|
<div class="ugo-header-item">
|
||||||
<div>应用信息:</div>
|
<div>应用信息:</div>
|
||||||
<div>{{ dataRaw.info.export_app }} {{ dataRaw.info.export_app_version }}</div>
|
<div>{{ dataRaw.info.export_app }} {{ dataRaw.info.export_app_version }}</div>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<div>{{ timestampToDate(Number(dataRaw.info.export_timestamp) * 1000) }}</div>
|
<div>{{ timestampToDate(Number(dataRaw.info.export_timestamp) * 1000) }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<v-item-group multiple v-model="selectedData" class="ugo-content">
|
<v-item-group v-model="selectedData" class="ugo-content" multiple>
|
||||||
<v-item
|
<v-item
|
||||||
v-for="(item, index) in data"
|
v-for="(item, index) in data"
|
||||||
:key="index"
|
:key="index"
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
</v-item>
|
</v-item>
|
||||||
</v-item-group>
|
</v-item-group>
|
||||||
<div class="ugo-bottom">
|
<div class="ugo-bottom">
|
||||||
<v-btn class="ugo-item-btn" @click="visible = false" :rounded="true">取消</v-btn>
|
<v-btn :rounded="true" class="ugo-item-btn" @click="visible = false">取消</v-btn>
|
||||||
<v-btn class="ugo-item-btn" @click="handleSelected()" :rounded="true">确定</v-btn>
|
<v-btn :rounded="true" class="ugo-item-btn" @click="handleSelected()">确定</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</TOverlay>
|
</TOverlay>
|
||||||
@@ -53,10 +53,9 @@ import showSnackbar from "@comp/func/snackbar.js";
|
|||||||
import TSUserGacha from "@Sqlm/userGacha.js";
|
import TSUserGacha from "@Sqlm/userGacha.js";
|
||||||
import { path } from "@tauri-apps/api";
|
import { path } from "@tauri-apps/api";
|
||||||
import { open } from "@tauri-apps/plugin-dialog";
|
import { open } from "@tauri-apps/plugin-dialog";
|
||||||
import { writeTextFile } from "@tauri-apps/plugin-fs";
|
|
||||||
import TGLogger from "@utils/TGLogger.js";
|
import TGLogger from "@utils/TGLogger.js";
|
||||||
import { timestampToDate } from "@utils/toolFunc.js";
|
import { timestampToDate } from "@utils/toolFunc.js";
|
||||||
import { getUigf4Header, getUigf4Item, readUigf4Data, verifyUigfData } from "@utils/UIGF.js";
|
import { exportUigf4Data, readUigf4Data, verifyUigfData } from "@utils/UIGF.js";
|
||||||
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
import { computed, onMounted, ref, shallowRef, watch } from "vue";
|
||||||
|
|
||||||
type UgoUidProps = { mode: "import" | "export" };
|
type UgoUidProps = { mode: "import" | "export" };
|
||||||
@@ -77,14 +76,14 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => visible.value,
|
() => [visible.value, props.mode],
|
||||||
async () => {
|
async () => {
|
||||||
if (visible.value) await refreshData();
|
if (visible.value) await refreshData();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
async function getDefaultSavePath(): Promise<string> {
|
async function getDefaultSavePath(): Promise<string> {
|
||||||
const tsNow = new Date().getTime();
|
const tsNow = Math.floor(Date.now() / 1000);
|
||||||
return `${await path.downloadDir()}${path.sep()}UIGFv4.1_${tsNow}.json`;
|
return `${await path.downloadDir()}${path.sep()}UIGFv4.1_${tsNow}.json`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,22 +207,21 @@ async function handleExport(): Promise<void> {
|
|||||||
showSnackbar.warn("请至少选择一个!");
|
showSnackbar.warn("请至少选择一个!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await showLoading.start("正在导出数据...", "正在生成文件头");
|
const totalCnt = selectedData.value.map((s) => s.length).reduce((a, b) => a + b, 0);
|
||||||
const header = await getUigf4Header();
|
await showLoading.start(
|
||||||
const data: TGApp.Plugins.UIGF.GachaHk4e[] = [];
|
"正在导出数据...",
|
||||||
for (const item of selectedData.value) {
|
`${selectedData.value.length}条UID - ${totalCnt}条记录`,
|
||||||
await showLoading.update(`正在导出UID: ${item.uid}`);
|
);
|
||||||
const dataItem = await getUigf4Item(item.uid);
|
await exportUigf4Data(
|
||||||
data.push(dataItem);
|
selectedData.value.map((s) => s.uid.toString()),
|
||||||
}
|
fp.value,
|
||||||
await showLoading.update("正在写入文件...");
|
);
|
||||||
await writeTextFile(fp.value, JSON.stringify({ info: header, hk4e: data }));
|
|
||||||
await showLoading.end();
|
await showLoading.end();
|
||||||
showSnackbar.success(`导出成功! 文件路径: ${fp.value}`);
|
showSnackbar.success(`导出成功! 文件路径: ${fp.value}`);
|
||||||
fp.value = await getDefaultSavePath();
|
fp.value = await getDefaultSavePath();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="css" scoped>
|
<style lang="scss" scoped>
|
||||||
.ugo-box {
|
.ugo-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { path } from "@tauri-apps/api";
|
|||||||
import { exists, mkdir, readDir } from "@tauri-apps/plugin-fs";
|
import { exists, mkdir, readDir } from "@tauri-apps/plugin-fs";
|
||||||
import TGLogger from "@utils/TGLogger.js";
|
import TGLogger from "@utils/TGLogger.js";
|
||||||
import { getWikiBrief, timestampToDate } from "@utils/toolFunc.js";
|
import { getWikiBrief, timestampToDate } from "@utils/toolFunc.js";
|
||||||
import { exportUigfData, readUigfData, verifyUigfData } from "@utils/UIGF.js";
|
import { exportUigf4Data, readUigf4Data, readUigfData, verifyUigfData } from "@utils/UIGF.js";
|
||||||
|
|
||||||
import TGSqlite from "../index.js";
|
import TGSqlite from "../index.js";
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ async function cleanGachaRecords(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 合并祈愿数据
|
* 合并祈愿数据
|
||||||
* @since Beta v0.8.7
|
* @since Beta v0.9.0
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
* @param {Array<TGApp.Plugins.UIGF.GachaItem>} data - UIGF数据
|
* @param {Array<TGApp.Plugins.UIGF.GachaItem>} data - UIGF数据
|
||||||
* @param {boolean} showProgress - 是否显示进度
|
* @param {boolean} showProgress - 是否显示进度
|
||||||
@@ -214,25 +214,32 @@ async function mergeUIGF(
|
|||||||
let cnt = 0;
|
let cnt = 0;
|
||||||
const len = data.length;
|
const len = data.length;
|
||||||
let progress = 0;
|
let progress = 0;
|
||||||
|
let timer: NodeJS.Timeout | null = null;
|
||||||
|
if (showProgress) {
|
||||||
|
timer = setInterval(async () => {
|
||||||
|
progress = Math.round((cnt / len) * 100 * 100) / 100;
|
||||||
|
const current = data[cnt]?.time ?? "";
|
||||||
|
const name = data[cnt]?.name ?? "";
|
||||||
|
const rank = data[cnt]?.rank_type ?? "0";
|
||||||
|
await showLoading.update(`[${progress}%][${current}] ${"⭐".repeat(Number(rank))}-${name}`);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
for (const gacha of data) {
|
for (const gacha of data) {
|
||||||
const trans = transGacha(gacha);
|
const trans = transGacha(gacha);
|
||||||
if (cnt % 20 === 0) {
|
|
||||||
progress = Math.round((cnt / len) * 100 * 100) / 100;
|
|
||||||
if (showProgress) {
|
|
||||||
await showLoading.update(
|
|
||||||
`[${progress}%][${trans.time}] ${"⭐".repeat(Number(trans.rank_type))}-${trans.name}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
const sql = getInsertSql(uid, trans);
|
const sql = getInsertSql(uid, trans);
|
||||||
await db.execute(sql);
|
await db.execute(sql);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
if (timer) {
|
||||||
|
clearInterval(timer);
|
||||||
|
progress = 100;
|
||||||
|
await showLoading.update(`[${progress}%] 完成`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合并祈愿数据(v4.0)
|
* 合并祈愿数据(v4.0)
|
||||||
* @since Beta v0.8.7
|
* @since Beta v0.9.0
|
||||||
* @param {TGApp.Plugins.UIGF.GachaHk4e} data - UIGF数据
|
* @param {TGApp.Plugins.UIGF.GachaHk4e} data - UIGF数据
|
||||||
* @param {boolean} showProgress - 是否显示进度
|
* @param {boolean} showProgress - 是否显示进度
|
||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
@@ -245,25 +252,32 @@ async function mergeUIGF4(
|
|||||||
let cnt: number = 0;
|
let cnt: number = 0;
|
||||||
const len = data.list.length;
|
const len = data.list.length;
|
||||||
let progress: number = 0;
|
let progress: number = 0;
|
||||||
|
let timer: NodeJS.Timeout | null = null;
|
||||||
|
if (showProgress) {
|
||||||
|
timer = setInterval(async () => {
|
||||||
|
progress = Math.round((cnt / len) * 100 * 100) / 100;
|
||||||
|
const current = data.list[cnt]?.time ?? "";
|
||||||
|
const name = data.list[cnt]?.name ?? "";
|
||||||
|
const rank = data.list[cnt]?.rank_type ?? "0";
|
||||||
|
await showLoading.update(`[${progress}%][${current}] ${"⭐".repeat(Number(rank))}-${name}`);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
for (const gacha of data.list) {
|
for (const gacha of data.list) {
|
||||||
const trans = transGacha(gacha, data.timezone);
|
const trans = transGacha(gacha, data.timezone);
|
||||||
if (cnt % 20 === 0) {
|
|
||||||
progress = Math.round((cnt / len) * 100 * 100) / 100;
|
|
||||||
if (showProgress) {
|
|
||||||
await showLoading.update(
|
|
||||||
`[${progress}%][${trans.time}] ${"⭐".repeat(Number(trans.rank_type))}-${trans.name}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const sql = getInsertSql(data.uid.toString(), trans);
|
const sql = getInsertSql(data.uid.toString(), trans);
|
||||||
await db.execute(sql);
|
await db.execute(sql);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
if (timer) {
|
||||||
|
clearInterval(timer);
|
||||||
|
progress = 100;
|
||||||
|
await showLoading.update(`[${progress}%] 完成`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 备份祈愿数据
|
* 备份祈愿数据
|
||||||
* @since Beta v0.6.0
|
* @since Beta v0.9.0
|
||||||
* @param {string} dir - 备份目录
|
* @param {string} dir - 备份目录
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
@@ -273,17 +287,14 @@ async function backUpUigf(dir: string): Promise<void> {
|
|||||||
await mkdir(dir, { recursive: true });
|
await mkdir(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
const uidList = await getUidList();
|
const uidList = await getUidList();
|
||||||
for (const uid of uidList) {
|
const savePath = `${dir}${path.sep()}UIGF4.json`;
|
||||||
const dataGacha = await getGachaRecords(uid);
|
await exportUigf4Data(uidList, savePath);
|
||||||
const savePath = `${dir}${path.sep()}UIGF_${uid}.json`;
|
|
||||||
await exportUigfData(uid, dataGacha, savePath);
|
|
||||||
}
|
|
||||||
await TGLogger.Info("祈愿数据备份完成");
|
await TGLogger.Info("祈愿数据备份完成");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 恢复祈愿数据
|
* 恢复祈愿数据
|
||||||
* @since Beta v0.6.0
|
* @since Beta v0.9.0
|
||||||
* @param {string} dir - 备份目录
|
* @param {string} dir - 备份目录
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
@@ -292,29 +303,55 @@ async function restoreUigf(dir: string): Promise<boolean> {
|
|||||||
await TGLogger.Warn("不存在指定的祈愿备份目录");
|
await TGLogger.Warn("不存在指定的祈愿备份目录");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const filesRead = await readDir(dir);
|
let cnt = 0;
|
||||||
// 校验 UIGF_xxx.json 文件
|
// 旧版备份文件 UIGF_{{uid}}
|
||||||
const fileRegex = /^UIGF_\d+\.json$/;
|
const legacyReg = /^UIGF_\d+\.json$/;
|
||||||
const files = filesRead.filter((item) => item.isFile && fileRegex.test(item.name));
|
const legacyFiles = (await readDir(dir)).filter(
|
||||||
if (files.length === 0) return false;
|
(item) => item.isFile && legacyReg.test(item.name),
|
||||||
try {
|
);
|
||||||
for (const file of files) {
|
if (legacyFiles.length > 0) {
|
||||||
const filePath = `${dir}${path.sep()}${file.name}`;
|
try {
|
||||||
const check = await verifyUigfData(filePath);
|
for (const file of legacyFiles) {
|
||||||
|
await showLoading.update(`祈愿文件:${file.name}`);
|
||||||
|
const filePath = `${dir}${path.sep()}${file.name}`;
|
||||||
|
const check = await verifyUigfData(filePath);
|
||||||
|
if (!check) {
|
||||||
|
await showLoading.update(`UIGF数据校验失败`);
|
||||||
|
await TGLogger.Warn(`UIGF数据校验失败${filePath}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const data = await readUigfData(filePath);
|
||||||
|
const uid = data.info.uid;
|
||||||
|
await showLoading.update(`正在导入${data.info.uid}的${data.list.length}条祈愿数据`);
|
||||||
|
await mergeUIGF(uid, data.list, true);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
await TGLogger.Error(`恢复祈愿数据失败${dir}`);
|
||||||
|
await TGLogger.Error(typeof e === "string" ? e : JSON.stringify(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const filePath = `${dir}${path.sep()}UIGF4.json`;
|
||||||
|
if (!(await exists(filePath))) {
|
||||||
|
await TGLogger.Warn(`未检测到UIGF4备份文件`);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const check = await verifyUigfData(filePath, true);
|
||||||
if (!check) {
|
if (!check) {
|
||||||
await TGLogger.Warn(`UIGF数据校验失败${filePath}`);
|
await TGLogger.Warn(`UIGF数据校验失败${filePath}`);
|
||||||
continue;
|
} else {
|
||||||
|
const data = await readUigf4Data(filePath);
|
||||||
|
for (const uidData of data.hk4e) {
|
||||||
|
await showLoading.update(`正在导入${uidData.uid}的${uidData.list.length}条祈愿记录`);
|
||||||
|
await mergeUIGF4(uidData, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const data = await readUigfData(filePath);
|
} catch (e) {
|
||||||
const uid = data.info.uid;
|
await TGLogger.Error(`恢复祈愿数据失败${dir}`);
|
||||||
await mergeUIGF(uid, data.list);
|
await TGLogger.Error(typeof e === "string" ? e : JSON.stringify(e));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
await TGLogger.Error(`恢复祈愿数据失败${dir}`);
|
|
||||||
await TGLogger.Error(typeof e === "string" ? e : JSON.stringify(e));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return cnt > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* @file utils/UIGF.ts
|
* UIGF工具类
|
||||||
* @description UIGF工具类
|
* @since Beta v0.9.0
|
||||||
* @since Beta v0.7.10
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import showLoading from "@comp/func/loading.js";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
import TSUserGacha from "@Sqlm/userGacha.js";
|
import TSUserGacha from "@Sqlm/userGacha.js";
|
||||||
import { app, path } from "@tauri-apps/api";
|
import { app, path } from "@tauri-apps/api";
|
||||||
@@ -17,7 +17,7 @@ import { timestampToDate } from "./toolFunc.js";
|
|||||||
import { Uigf4Schema, UigfSchema } from "@/data/index.js";
|
import { Uigf4Schema, UigfSchema } from "@/data/index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取 UIGF 时区
|
* 获取 UIGF 时区
|
||||||
* @since Beta v0.3.5
|
* @since Beta v0.3.5
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
* @returns {number} 时区
|
* @returns {number} 时区
|
||||||
@@ -29,7 +29,7 @@ function getUigfTimeZone(uid: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 传入utc8时间字符串跟目标时区,转成目标时区时间字符串
|
* 传入utc8时间字符串跟目标时区,转成目标时区时间字符串
|
||||||
* @since Beta v0.7.5
|
* @since Beta v0.7.5
|
||||||
* @param {string} time - 时间字符串
|
* @param {string} time - 时间字符串
|
||||||
* @param {number} timezone - 时区
|
* @param {number} timezone - 时区
|
||||||
@@ -43,7 +43,7 @@ function getExportTime(time: string, timezone: number): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取 UIGF 头部信息
|
* 获取 UIGF 头部信息
|
||||||
* @since Beta v0.7.5
|
* @since Beta v0.7.5
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
* @param {number} timezone - 时区
|
* @param {number} timezone - 时区
|
||||||
@@ -64,7 +64,7 @@ async function getUigfHeader(uid: string, timezone: number): Promise<TGApp.Plugi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取 UIGF v4.1 头部信息
|
* 获取 UIGF v4.1 头部信息
|
||||||
* @since Beta v0.7.10
|
* @since Beta v0.7.10
|
||||||
* @returns {TGApp.Plugins.UIGF.Info4} UIGF v4.1 头部信息
|
* @returns {TGApp.Plugins.UIGF.Info4} UIGF v4.1 头部信息
|
||||||
*/
|
*/
|
||||||
@@ -80,7 +80,7 @@ export async function getUigf4Header(): Promise<TGApp.Plugins.UIGF.Info4> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 数据转换-数据库到 UIGF
|
* 数据转换-数据库到 UIGF
|
||||||
* @since Beta v0.7.5
|
* @since Beta v0.7.5
|
||||||
* @param {TGApp.Sqlite.GachaRecords.TableGacha[]} data - 数据库数据
|
* @param {TGApp.Sqlite.GachaRecords.TableGacha[]} data - 数据库数据
|
||||||
* @param {number} timezone - 时区
|
* @param {number} timezone - 时区
|
||||||
@@ -106,7 +106,7 @@ function convertDataToUigf(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 检测是否存在 UIGF 数据,采用 ajv 验证 schema
|
* 检测是否存在 UIGF 数据,采用 ajv 验证 schema
|
||||||
* @since Beta v0.6.5
|
* @since Beta v0.6.5
|
||||||
* @param {string} path - UIGF 数据路径
|
* @param {string} path - UIGF 数据路径
|
||||||
* @param {boolean} isVersion4 - 是否为 UIGF v4.0
|
* @param {boolean} isVersion4 - 是否为 UIGF v4.0
|
||||||
@@ -127,7 +127,7 @@ export async function verifyUigfData(path: string, isVersion4: boolean = false):
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 验证 UIGF 数据
|
* 验证 UIGF 数据
|
||||||
* @since Beta v0.5.1
|
* @since Beta v0.5.1
|
||||||
* @param {object} data - UIGF 数据
|
* @param {object} data - UIGF 数据
|
||||||
* @returns {boolean} 是否验证通过
|
* @returns {boolean} 是否验证通过
|
||||||
@@ -150,7 +150,7 @@ function validateUigfData(data: object): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 验证 UIGF v4.0 数据
|
* 验证 UIGF v4.0 数据
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.0
|
||||||
* @param {object} data - UIGF 数据
|
* @param {object} data - UIGF 数据
|
||||||
* @returns {boolean} 是否验证通过
|
* @returns {boolean} 是否验证通过
|
||||||
@@ -166,7 +166,7 @@ function validateUigf4Data(data: object): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 读取 UIGF 数据
|
* 读取 UIGF 数据
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.0
|
||||||
* @param {string} userPath - UIGF 数据路径
|
* @param {string} userPath - UIGF 数据路径
|
||||||
* @returns {Promise<TGApp.Plugins.UIGF.Schema>} UIGF 数据
|
* @returns {Promise<TGApp.Plugins.UIGF.Schema>} UIGF 数据
|
||||||
@@ -177,7 +177,7 @@ export async function readUigfData(userPath: string): Promise<TGApp.Plugins.UIGF
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 读取 UIGF 4.0 数据
|
* 读取 UIGF 4.0 数据
|
||||||
* @since Beta v0.5.0
|
* @since Beta v0.5.0
|
||||||
* @param {string} userPath - UIGF 数据路径
|
* @param {string} userPath - UIGF 数据路径
|
||||||
* @returns {Promise<TGApp.Plugins.UIGF.Schema4>} UIGF 数据
|
* @returns {Promise<TGApp.Plugins.UIGF.Schema4>} UIGF 数据
|
||||||
@@ -188,7 +188,7 @@ export async function readUigf4Data(userPath: string): Promise<TGApp.Plugins.UIG
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 导出 UIGF 数据
|
* 导出 UIGF 数据
|
||||||
* @since Beta v0.7.5
|
* @since Beta v0.7.5
|
||||||
* @param {string} uid - UID
|
* @param {string} uid - UID
|
||||||
* @param {TGApp.Sqlite.GachaRecords.TableGacha[]} gachaList - 祈愿列表
|
* @param {TGApp.Sqlite.GachaRecords.TableGacha[]} gachaList - 祈愿列表
|
||||||
@@ -210,13 +210,22 @@ export async function exportUigfData(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 获取单项UID的UIGF4.0数据
|
* 导出UIGF4数据
|
||||||
* @since Beta v0.7.5
|
* @since Beta v0.9.0
|
||||||
* @param {string} uid - UID
|
* @param {Array<string>} uids - UID列表
|
||||||
* @returns {Promise<TGApp.Plugins.UIGF.GachaHk4e>}
|
* @param {string} [savePath] - 保存路径
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function getUigf4Item(uid: string): Promise<TGApp.Plugins.UIGF.GachaHk4e> {
|
export async function exportUigf4Data(uids: Array<string> = [], savePath?: string): Promise<void> {
|
||||||
const gachaList = await TSUserGacha.getGachaRecords(uid);
|
const header = await getUigf4Header();
|
||||||
const timezone = getUigfTimeZone(uid);
|
const filePath = savePath ?? `${await path.appLocalDataDir()}userData\\UIGF4.json`;
|
||||||
return { uid: uid, timezone: timezone, list: convertDataToUigf(gachaList, timezone) };
|
const data: Array<TGApp.Plugins.UIGF.GachaHk4e> = [];
|
||||||
|
for (const uid of uids) {
|
||||||
|
const gachaList = await TSUserGacha.getGachaRecords(uid);
|
||||||
|
await showLoading.update(`正在导出${uid}的${gachaList.length}条祈愿记录`);
|
||||||
|
const timezone = getUigfTimeZone(uid);
|
||||||
|
data.push({ uid: uid, timezone: timezone, list: convertDataToUigf(gachaList, timezone) });
|
||||||
|
}
|
||||||
|
const uigf4Data: TGApp.Plugins.UIGF.Schema4 = { info: header, hk4e: data };
|
||||||
|
await writeTextFile(filePath, JSON.stringify(uigf4Data, null, 2));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file utils/dataBS.ts
|
* 用户数据的备份、恢复、迁移
|
||||||
* @description 用户数据的备份、恢复、迁移
|
* @since Beta v0.9.0
|
||||||
* @since Beta v0.8.0
|
|
||||||
*/
|
*/
|
||||||
import showLoading from "@comp/func/loading.js";
|
import showLoading from "@comp/func/loading.js";
|
||||||
import showSnackbar from "@comp/func/snackbar.js";
|
import showSnackbar from "@comp/func/snackbar.js";
|
||||||
@@ -16,8 +15,9 @@ import { exists, mkdir } from "@tauri-apps/plugin-fs";
|
|||||||
import TGLogger from "./TGLogger.js";
|
import TGLogger from "./TGLogger.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 备份用户数据
|
* 备份用户数据
|
||||||
* @since Beta v0.8.0
|
* @since Beta v0.9.0
|
||||||
|
* @TODO 重构祈愿部分备份&读取,处理胡桃数据&应用自身数据的导入
|
||||||
* @param {string} dir 备份目录路径
|
* @param {string} dir 备份目录路径
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
@@ -41,8 +41,8 @@ export async function backUpUserData(dir: string): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 恢复用户数据
|
* 恢复用户数据
|
||||||
* @since Beta v0.8.0
|
* @since Beta v0.9.0
|
||||||
* @param {string} dir 备份目录路径
|
* @param {string} dir 备份目录路径
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user