Skip to content

Commit 9be8c78

Browse files
committed
✨ 重构UIGF导入导出备份恢复,支持UIGF4.2
1 parent b5562a0 commit 9be8c78

10 files changed

Lines changed: 549 additions & 298 deletions

File tree

src/components/userGacha/ugo-uid.vue

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- UIGF4导入导出组件 -->
12
<template>
23
<TOverlay v-model="visible" blur-val="5px">
34
<div class="ugo-box">
@@ -32,7 +33,10 @@
3233
>
3334
<div class="ugo-item" @click="toggle">
3435
<div class="ugo-item-left">
35-
<div class="ugo-item-title">{{ item.uid }} - {{ item.length }}条记录</div>
36+
<div class="ugo-item-title">
37+
<span>{{ item.uid }} - {{ item.length }}条</span>
38+
<span>{{ item.isUgc ? "颂愿记录" : "祈愿记录" }}</span>
39+
</div>
3640
<div class="ugo-item-sub">{{ item.time }}</div>
3741
</div>
3842
<div class="ugo-item-right">
@@ -55,6 +59,7 @@ import TOverlay from "@comp/app/t-overlay.vue";
5559
import showLoading from "@comp/func/loading.js";
5660
import showSnackbar from "@comp/func/snackbar.js";
5761
import TSUserGacha from "@Sqlm/userGacha.js";
62+
import TSUserGachaB from "@Sqlm/userGachaB.js";
5863
import { path } from "@tauri-apps/api";
5964
import { open } from "@tauri-apps/plugin-dialog";
6065
import TGLogger from "@utils/TGLogger.js";
@@ -68,7 +73,19 @@ type UgoUidProps = {
6873
/** filePathImport,导出路径 */
6974
fpi?: string;
7075
};
71-
type UgoUidItem = { uid: string; length: number; time: string };
76+
/**
77+
* UID项
78+
*/
79+
type UgoUidItem = {
80+
/** UID */
81+
uid: string;
82+
/** 数据条数 */
83+
length: number;
84+
/** 数据时间段 */
85+
time: string;
86+
/** 是否是颂愿数据 */
87+
isUgc: boolean;
88+
};
7289
/** 兼容不同版本的导入 */
7390
type UgoUidImportRaw =
7491
| { isV4: true; data: TGApp.Plugins.UIGF.Schema4 }
@@ -98,7 +115,7 @@ watch(
98115
99116
async function getDefaultSavePath(): Promise<string> {
100117
const tsNow = Math.floor(Date.now() / 1000);
101-
return `${await path.downloadDir()}${path.sep()}UIGFv4.1_${tsNow}.json`;
118+
return `${await path.downloadDir()}${path.sep()}UIGFv4.2_${tsNow}.json`;
102119
}
103120
104121
async function refreshData(): Promise<void> {
@@ -147,7 +164,9 @@ async function refreshImport(): Promise<void> {
147164
if (isV4) {
148165
const read = await readUigf4Data(fp.value);
149166
importRaw.value = { isV4: true, data: read };
150-
data.value = read.hk4e.map(parseData4);
167+
const hk4eUids = read.hk4e?.map(parseData4) ?? [];
168+
const ugcUids = read.hk4e_ugc?.map(parseUgc) ?? [];
169+
data.value = [...hk4eUids, ...ugcUids];
151170
} else {
152171
const read = await readUigfData(fp.value);
153172
console.log(read.list.length);
@@ -172,6 +191,7 @@ function parseData(data: TGApp.Plugins.UIGF.Schema): UgoUidItem {
172191
uid: data.info.uid,
173192
length: data.list.length,
174193
time: `${timestampToDate(Math.min(...timeList))} ~ ${timestampToDate(Math.max(...timeList))}`,
194+
isUgc: false,
175195
};
176196
}
177197
@@ -181,25 +201,52 @@ function parseData4(data: TGApp.Plugins.UIGF.GachaHk4e): UgoUidItem {
181201
uid: data.uid.toString(),
182202
length: data.list.length,
183203
time: `${timestampToDate(Math.min(...timeList))} ~ ${timestampToDate(Math.max(...timeList))}`,
204+
isUgc: false,
205+
};
206+
}
207+
208+
function parseUgc(data: TGApp.Plugins.UIGF.GachaUgc): UgoUidItem {
209+
const timeList = data.list.map((item) => new Date(item.time).getTime());
210+
return {
211+
uid: data.uid.toString(),
212+
length: data.list.length,
213+
time: `${timestampToDate(Math.min(...timeList))} ~ ${timestampToDate(Math.max(...timeList))}`,
214+
isUgc: true,
184215
};
185216
}
186217
187218
async function refreshExport(): Promise<void> {
188-
const uidList = await TSUserGacha.getUidList();
219+
const uidHk4e = await TSUserGacha.getUidList();
220+
const uidUgc = await TSUserGachaB.getUidList();
189221
const tmpData: Array<UgoUidItem> = [];
190-
for (const uid of uidList) {
222+
for (const uid of uidHk4e) {
191223
const dataRaw = await TSUserGacha.record.all(uid);
192-
tmpData.push(parseDataRaw(dataRaw));
224+
tmpData.push(parseLocalHk4e(dataRaw));
225+
}
226+
for (const uid of uidUgc) {
227+
const dataRaw = await TSUserGachaB.getGachaRecords(uid);
228+
tmpData.push(parseLocalUgc(dataRaw));
193229
}
194230
data.value = tmpData;
195231
}
196232
197-
function parseDataRaw(data: Array<TGApp.Sqlite.Gacha.Gacha>): UgoUidItem {
233+
function parseLocalHk4e(data: Array<TGApp.Sqlite.Gacha.Gacha>): UgoUidItem {
198234
const timeList = data.map((item) => new Date(item.time).getTime());
199235
return {
200236
uid: data[0].uid,
201237
length: data.length,
202238
time: `${timestampToDate(Math.min(...timeList))} ~ ${timestampToDate(Math.max(...timeList))}`,
239+
isUgc: false,
240+
};
241+
}
242+
243+
function parseLocalUgc(data: Array<TGApp.Sqlite.Gacha.GachaB>): UgoUidItem {
244+
const timeList = data.map((item) => new Date(item.time).getTime());
245+
return {
246+
uid: data[0].uid,
247+
length: data.length,
248+
time: `${timestampToDate(Math.min(...timeList))} ~ ${timestampToDate(Math.max(...timeList))}`,
249+
isUgc: true,
203250
};
204251
}
205252
@@ -222,13 +269,23 @@ async function handleImport(): Promise<void> {
222269
if (importRaw.value.isV4) {
223270
for (const item of selectedData.value) {
224271
await showLoading.update(`正在导入UID: ${item.uid}`);
225-
const dataFind = importRaw.value.data.hk4e.find((i) => i.uid.toString() === item.uid);
226-
if (!dataFind) {
227-
showSnackbar.error(`未找到UID: ${item.uid}`);
228-
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
229-
continue;
272+
if (!item.isUgc) {
273+
const dataFind = importRaw.value.data.hk4e?.find((i) => i.uid.toString() === item.uid);
274+
if (!dataFind) {
275+
showSnackbar.error(`未找到UID: ${item.uid}`);
276+
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
277+
continue;
278+
}
279+
await TSUserGacha.mergeUIGF4(dataFind, true);
280+
} else {
281+
const dataFind = importRaw.value.data.hk4e_ugc?.find((i) => i.uid.toString() === item.uid);
282+
if (!dataFind) {
283+
showSnackbar.error(`未找到UID: ${item.uid}`);
284+
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
285+
continue;
286+
}
287+
await TSUserGachaB.mergeUIGF4(dataFind, true);
230288
}
231-
await TSUserGacha.mergeUIGF4(dataFind, true);
232289
}
233290
} else {
234291
const iUid = selectedData.value[0].uid;
@@ -251,7 +308,8 @@ async function handleExport(): Promise<void> {
251308
`${selectedData.value.length}条UID - ${totalCnt}条记录`,
252309
);
253310
await exportUigf4Data(
254-
selectedData.value.map((s) => s.uid.toString()),
311+
selectedData.value.filter((i) => !i.isUgc).map((s) => s.uid.toString()),
312+
selectedData.value.filter((i) => i.isUgc).map((s) => s.uid.toString()),
255313
fp.value,
256314
);
257315
await showLoading.end();
@@ -348,8 +406,17 @@ async function handleExport(): Promise<void> {
348406
}
349407
350408
.ugo-item-title {
409+
position: relative;
410+
display: flex;
411+
align-items: center;
412+
justify-content: flex-start;
413+
column-gap: 8px;
351414
font-family: var(--font-title);
352415
font-size: 16px;
416+
417+
:last-child {
418+
color: var(--tgc-od-red);
419+
}
353420
}
354421
355422
.ugo-item-sub {

src/pages/User/GachaB.vue

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
variantelevated<!-- 千星奇域祈愿记录页面 TODO:处理活动卡池次数共享 -->
1+
<!-- 千星奇域祈愿记录页面 TODO:处理活动卡池次数共享 -->
22
<template>
33
<v-app-bar>
44
<template #prepend>
@@ -34,6 +34,31 @@ variantelevated<!-- 千星奇域祈愿记录页面 TODO:处理活动卡池次
3434
>
3535
全量刷新
3636
</v-btn>
37+
<v-btn
38+
class="gb-top-btn"
39+
prepend-icon="mdi-import"
40+
variant="elevated"
41+
@click="importUigf()"
42+
>
43+
导入
44+
</v-btn>
45+
<v-btn
46+
class="gb-top-btn"
47+
prepend-icon="mdi-export"
48+
variant="elevated"
49+
@click="exportUigf()"
50+
>
51+
导出
52+
</v-btn>
53+
<v-btn
54+
class="gb-top-btn"
55+
prepend-icon="mdi-database"
56+
title="将数据库中非中文数据转换为中文"
57+
variant="elevated"
58+
@click="checkData()"
59+
>
60+
检测数据
61+
</v-btn>
3762
<v-btn
3863
class="gb-top-btn"
3964
prepend-icon="mdi-delete"
@@ -59,18 +84,22 @@ variantelevated<!-- 千星奇域祈愿记录页面 TODO:处理活动卡池次
5984
</v-window-item>
6085
</v-window>
6186
</div>
87+
<UgoUid v-model="ovShow" :fpi="ovFpi" :mode="ovMode" />
6288
</template>
6389
<script lang="ts" setup>
6490
import showDialog from "@comp/func/dialog.js";
6591
import showLoading from "@comp/func/loading.js";
6692
import showSnackbar from "@comp/func/snackbar.js";
6793
import GbrOverview from "@comp/userGacha/gbr-overview.vue";
6894
import GbrTable from "@comp/userGacha/gbr-table.vue";
95+
import UgoUid from "@comp/userGacha/ugo-uid.vue";
6996
import hk4eReq from "@req/hk4eReq.js";
7097
import takumiReq from "@req/takumiReq.js";
7198
import TSUserGachaB from "@Sqlm/userGachaB.js";
7299
import useAppStore from "@store/app.js";
73100
import useUserStore from "@store/user.js";
101+
import { path } from "@tauri-apps/api";
102+
import { open } from "@tauri-apps/plugin-dialog";
74103
import TGLogger from "@utils/TGLogger.js";
75104
import { storeToRefs } from "pinia";
76105
import { onMounted, ref, shallowRef, watch } from "vue";
@@ -80,6 +109,10 @@ const router = useRouter();
80109
const { isLogin } = storeToRefs(useAppStore());
81110
const { account, cookie } = storeToRefs(useUserStore());
82111
112+
const ovMode = ref<"export" | "import">("import");
113+
const ovShow = ref<boolean>(false);
114+
const ovFpi = ref<string>();
115+
83116
const authkey = ref<string>("");
84117
const uidCur = ref<string>();
85118
const tab = ref<string>("overview");
@@ -219,27 +252,26 @@ async function refreshGachaPool(
219252
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
220253
break;
221254
}
222-
if (gachaRes.length === 0) {
223-
// if (force) {
224-
// await showLoading.update(`正在清理${label}数据`);
225-
// if (gachaDataMap) {
226-
// await TSUserGacha.cleanGachaRecords(account.value.gameUid, type, gachaDataMap);
227-
// }
228-
// }
229-
break;
230-
}
255+
if (gachaRes.length === 0) break;
256+
const uigfList: Array<TGApp.Plugins.UIGF.GachaItemB> = [];
231257
if (force) await showLoading.update(`[${gachaName}] 第${page}页,${gachaRes.length}条`);
232258
for (const item of gachaRes) {
233259
if (!force) {
234260
await showLoading.update(`[${item.item_type}][${item.time}] ${item.item_name}`);
235261
}
236-
if (force) {
237-
// if (!gachaDataMap) gachaDataMap = {};
238-
// if (!gachaDataMap[item.time]) gachaDataMap[item.time] = [];
239-
// gachaDataMap[item.time].push(item.id.toString());
240-
}
262+
const tempItem: TGApp.Plugins.UIGF.GachaItemB = {
263+
id: item.id,
264+
item_id: item.item_id,
265+
item_name: item.item_name,
266+
item_type: item.item_type,
267+
op_gacha_type: item.op_gacha_type,
268+
rank_type: item.rank_type,
269+
schedule_id: item.schedule_id,
270+
time: item.time,
271+
};
272+
uigfList.push(tempItem);
241273
}
242-
await TSUserGachaB.insertGachaList(gachaRes);
274+
await TSUserGachaB.insertGachaList(account.value.gameUid, uigfList);
243275
if (!force && gachaRes.some((i) => i.id.toString() === endId.toString())) break;
244276
reqId = gachaRes[gachaRes.length - 1].id.toString();
245277
if (force) await new Promise<void>((resolve) => setTimeout(resolve, 1000));
@@ -283,6 +315,39 @@ async function deleteGacha(): Promise<void> {
283315
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
284316
window.location.reload();
285317
}
318+
319+
async function importUigf(): Promise<void> {
320+
await TGLogger.Info(`[UserGachaB][importUigf] 导入祈愿数据`);
321+
const selectedFile = await open({
322+
multiple: false,
323+
title: "导入UIGF文件",
324+
filters: [{ name: "UIGF JSON", extensions: ["json"] }],
325+
defaultPath: await path.downloadDir(),
326+
directory: false,
327+
});
328+
if (selectedFile === null) {
329+
showSnackbar.cancel("已取消文件选择");
330+
return;
331+
}
332+
ovFpi.value = selectedFile;
333+
ovMode.value = "import";
334+
ovShow.value = true;
335+
}
336+
337+
async function exportUigf(): Promise<void> {
338+
if (!uidCur.value) {
339+
showSnackbar.error("未获取到 UID");
340+
return;
341+
}
342+
await TGLogger.Info(`[UserGachaB][${uidCur.value}][exportUigf] 导出祈愿数据`);
343+
ovMode.value = "export";
344+
ovShow.value = true;
345+
}
346+
347+
async function checkData(): Promise<void> {
348+
// TODO
349+
showSnackbar.warn("暂未支持");
350+
}
286351
</script>
287352
<style lang="scss" scoped>
288353
.gb-top-title {

0 commit comments

Comments
 (0)