mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-18 10:18:14 +08:00
@@ -4,7 +4,7 @@
|
||||
<template #prepend>
|
||||
<div class="uc-top-title">
|
||||
<img alt="icon" src="/source/UI/userAvatar.webp" />
|
||||
<span>原神战绩</span>
|
||||
<span>我的角色</span>
|
||||
<v-btn variant="outlined" @click="showSelect = true">筛选角色</v-btn>
|
||||
<v-btn variant="outlined" @click="resetSelect = true">重置筛选</v-btn>
|
||||
</div>
|
||||
@@ -224,6 +224,7 @@ async function loadUid(): Promise<void> {
|
||||
} else {
|
||||
uidCur.value = uidList.value[0];
|
||||
}
|
||||
console.log(uidCur.value, user.value.gameUid);
|
||||
}
|
||||
|
||||
async function loadRole(): Promise<void> {
|
||||
|
||||
@@ -1,48 +1,75 @@
|
||||
<template>
|
||||
<ToLoading v-model="loading" :title="loadingTitle" :subtitle="loadingSub" />
|
||||
<div class="ur-box">
|
||||
<div class="ur-top">
|
||||
<v-app-bar>
|
||||
<template #prepend>
|
||||
<div class="ur-top-title">
|
||||
<span v-if="!isEmpty">{{ getTitle() }} 更新于 {{ recordData.updated }}</span>
|
||||
<span v-else>原神战绩【暂无数据】</span>
|
||||
<img alt="icon" src="/source/UI/userRecord.webp" />
|
||||
<span>原神战绩</span>
|
||||
<v-select
|
||||
variant="outlined"
|
||||
v-model="uidCur"
|
||||
:items="uidList"
|
||||
:hide-details="true"
|
||||
title="游戏UID"
|
||||
/>
|
||||
</div>
|
||||
<div class="ur-top-btns" data-html2canvas-ignore>
|
||||
<v-btn class="ur-top-btn" @click="refresh()">
|
||||
<template #prepend>
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</template>
|
||||
更新数据
|
||||
</v-btn>
|
||||
<v-btn class="ur-top-btn" @click="shareRecord()">
|
||||
<template #prepend>
|
||||
<v-icon>mdi-share</v-icon>
|
||||
</template>
|
||||
</template>
|
||||
<template #append>
|
||||
<div class="ur-top-btns">
|
||||
<v-btn prepend-icon="mdi-refresh" class="ur-top-btn" @click="refreshRecord()">更新</v-btn>
|
||||
<v-btn
|
||||
prepend-icon="mdi-share"
|
||||
class="ur-top-btn"
|
||||
@click="shareRecord()"
|
||||
:disabled="recordData === undefined"
|
||||
>
|
||||
分享
|
||||
</v-btn>
|
||||
<v-btn
|
||||
prepend-icon="mdi-delete"
|
||||
class="ur-top-btn"
|
||||
@click="deleteRecord()"
|
||||
:disabled="recordData === undefined"
|
||||
>
|
||||
删除
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
</v-app-bar>
|
||||
<div class="ur-box" v-if="recordData">
|
||||
<div class="ur-box-title">
|
||||
<TurRoleInfo :model-value="recordData.role" :uid="uidCur ?? 0" />
|
||||
<span>Render by TeyvatGuide v{{ version }}</span>
|
||||
</div>
|
||||
<TSubLine>数据总览</TSubLine>
|
||||
<TurOverviewGrid v-model="recordData.stats" />
|
||||
<TurOverviewGrid :model-value="recordData.stats" />
|
||||
<TSubLine>角色信息</TSubLine>
|
||||
<TurAvatarGrid v-model="recordData.avatars" />
|
||||
<TurAvatarGrid :model-value="recordData.avatars" />
|
||||
<TSubLine>世界探索</TSubLine>
|
||||
<TurWorldGrid v-model="recordData.worldExplore" />
|
||||
<TurWorldGrid :model-value="recordData.worldExplore" />
|
||||
<TSubLine>尘歌壶</TSubLine>
|
||||
<TurHomeGrid v-model="recordData.homes" />
|
||||
<TurHomeGrid :model-value="recordData.homes" />
|
||||
</div>
|
||||
<div class="ur-empty" v-else>
|
||||
<img alt="empty" src="/source/UI/empty.webp" />
|
||||
<span>DATA NOT FOUND</span>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { getVersion } from "@tauri-apps/api/app";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
|
||||
import showConfirm from "../../components/func/confirm.js";
|
||||
import showSnackbar from "../../components/func/snackbar.js";
|
||||
import TSubLine from "../../components/main/t-subline.vue";
|
||||
import ToLoading from "../../components/overlay/to-loading.vue";
|
||||
import TurAvatarGrid from "../../components/userRecord/tur-avatar-grid.vue";
|
||||
import TurHomeGrid from "../../components/userRecord/tur-home-grid.vue";
|
||||
import TurOverviewGrid from "../../components/userRecord/tur-overview-grid.vue";
|
||||
import TurRoleInfo from "../../components/userRecord/tur-role-info.vue";
|
||||
import TurWorldGrid from "../../components/userRecord/tur-world-grid.vue";
|
||||
import TGSqlite from "../../plugins/Sqlite/index.js";
|
||||
import TSUserRecord from "../../plugins/Sqlite/modules/userRecord.js";
|
||||
import { useUserStore } from "../../store/modules/user.js";
|
||||
import TGLogger from "../../utils/TGLogger.js";
|
||||
import { generateShareImg } from "../../utils/TGShare.js";
|
||||
@@ -50,7 +77,7 @@ import TGRequest from "../../web/request/TGRequest.js";
|
||||
|
||||
// store
|
||||
const userStore = storeToRefs(useUserStore());
|
||||
const user = userStore.account.value;
|
||||
const user = computed<TGApp.Sqlite.Account.Game>(() => userStore.account.value);
|
||||
|
||||
// loading
|
||||
const loading = ref<boolean>(false);
|
||||
@@ -58,107 +85,150 @@ const loadingTitle = ref<string>();
|
||||
const loadingSub = ref<string>();
|
||||
|
||||
// data
|
||||
const isEmpty = ref<boolean>(true);
|
||||
const recordData = ref<TGApp.Sqlite.Record.SingleTable>(<TGApp.Sqlite.Record.SingleTable>{});
|
||||
const uidCur = ref<number>();
|
||||
const uidList = ref<number[]>([]);
|
||||
const recordData = ref<TGApp.Sqlite.Record.RenderData>();
|
||||
const version = ref<string>();
|
||||
|
||||
onMounted(async () => {
|
||||
await TGLogger.Info("[UserRecord][onMounted] 打开角色战绩页面");
|
||||
loadingTitle.value = "正在加载战绩数据";
|
||||
loading.value = true;
|
||||
await initUserRecordData();
|
||||
version.value = await getVersion();
|
||||
await loadUid();
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
async function initUserRecordData(): Promise<void> {
|
||||
const recordGet = await TGSqlite.getUserRecord(user.gameUid);
|
||||
if (recordGet !== false) {
|
||||
await TGLogger.Info(`[UserRecord][initUserRecordData][${user.gameUid}] 成功加载战绩数据`);
|
||||
recordData.value = recordGet;
|
||||
isEmpty.value = false;
|
||||
watch(
|
||||
() => uidCur.value,
|
||||
async () => await loadRecord(),
|
||||
);
|
||||
|
||||
async function loadUid(): Promise<void> {
|
||||
uidList.value = await TSUserRecord.getAllUid();
|
||||
if (uidList.value.length === 0) uidList.value = [Number(user.value.gameUid)];
|
||||
if (uidList.value.includes(Number(user.value.gameUid))) {
|
||||
uidCur.value = Number(user.value.gameUid);
|
||||
} else {
|
||||
await TGLogger.Info(`[UserRecord][initUserRecordData][${user.gameUid}] 未找到战绩数据`);
|
||||
isEmpty.value = true;
|
||||
uidCur.value = uidList.value[0];
|
||||
}
|
||||
}
|
||||
|
||||
async function refresh(): Promise<void> {
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.gameUid}] 刷新战绩数据`);
|
||||
async function loadRecord(): Promise<void> {
|
||||
recordData.value = undefined;
|
||||
if (!uidCur.value) return;
|
||||
const record = await TSUserRecord.getRecord(uidCur.value);
|
||||
if (!record) return;
|
||||
recordData.value = record;
|
||||
}
|
||||
|
||||
async function refreshRecord(): Promise<void> {
|
||||
if (!user.value) return;
|
||||
if (uidCur.value && uidCur.value.toString() !== user.value.gameUid) {
|
||||
const switchConfirm = await showConfirm({
|
||||
title: "是否切换游戏账户",
|
||||
text: `确认则尝试切换至${uidCur.value}`,
|
||||
});
|
||||
if (switchConfirm) {
|
||||
await useUserStore().switchGameAccount(uidCur.value.toString());
|
||||
await refreshRecord();
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定刷新?",
|
||||
text: `用户${user.value.gameUid}与当前UID${uidCur.value}不一致`,
|
||||
});
|
||||
if (!confirm) {
|
||||
showSnackbar({ text: "已取消战绩数据刷新", color: "cancel" });
|
||||
return;
|
||||
}
|
||||
}
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.value.gameUid}] 刷新战绩数据`);
|
||||
loadingTitle.value = "正在获取战绩数据";
|
||||
loading.value = true;
|
||||
if (!userStore.cookie.value) {
|
||||
showSnackbar({
|
||||
text: "请先登录",
|
||||
color: "error",
|
||||
});
|
||||
showSnackbar({ text: "请先登录", color: "error" });
|
||||
loading.value = false;
|
||||
await TGLogger.Warn(`[UserRecord][refresh][${user.gameUid}] 未登录`);
|
||||
await TGLogger.Warn(`[UserRecord][refresh][${user.value.gameUid}] 未登录`);
|
||||
return;
|
||||
}
|
||||
const cookie = {
|
||||
account_id: userStore.cookie.value.account_id,
|
||||
cookie_token: userStore.cookie.value.cookie_token,
|
||||
};
|
||||
const res = await TGRequest.User.getRecord(cookie, user);
|
||||
const res = await TGRequest.User.getRecord(cookie, user.value);
|
||||
if (!("retcode" in res)) {
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.gameUid}] 获取战绩数据成功`);
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.gameUid}]`, false);
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.value.gameUid}] 获取战绩数据成功`);
|
||||
await TGLogger.Info(`[UserRecord][refresh][${user.value.gameUid}]`, false);
|
||||
await TGLogger.Info(JSON.stringify(res), false);
|
||||
loadingTitle.value = "正在保存战绩数据";
|
||||
await TGSqlite.saveUserRecord(res, user.gameUid);
|
||||
await initUserRecordData();
|
||||
await TSUserRecord.saveRecord(Number(user.value.gameUid), res);
|
||||
await loadUid();
|
||||
if (recordData.value === undefined) await loadRecord();
|
||||
} else {
|
||||
showSnackbar({
|
||||
text: `[${res.retcode}] ${res.message}`,
|
||||
color: "error",
|
||||
});
|
||||
await TGLogger.Error(`[UserRecord][refresh][${user.gameUid}] 获取战绩数据失败`);
|
||||
await TGLogger.Error(`[UserRecord][refresh][${user.gameUid}] ${res.retcode} ${res.message}`);
|
||||
showSnackbar({ text: `[${res.retcode}] ${res.message}`, color: "error" });
|
||||
await TGLogger.Error(`[UserRecord][refresh][${user.value.gameUid}] 获取战绩数据失败`);
|
||||
await TGLogger.Error(
|
||||
`[UserRecord][refresh][${user.value.gameUid}] ${res.retcode} ${res.message}`,
|
||||
);
|
||||
}
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
function getTitle(): string {
|
||||
const role = <TGApp.Sqlite.Record.Role>JSON.parse(recordData.value.role);
|
||||
return `${role.nickname} Lv.${role.level}【${recordData.value.uid}】`;
|
||||
}
|
||||
|
||||
async function shareRecord(): Promise<void> {
|
||||
await TGLogger.Info(`[UserRecord][shareRecord][${user.gameUid}] 生成分享图片`);
|
||||
if (!recordData.value) {
|
||||
showSnackbar({ text: "未找到战绩数据,请尝试刷新", color: "warn" });
|
||||
return;
|
||||
}
|
||||
await TGLogger.Info(`[UserRecord][shareRecord][${user.value.gameUid}] 生成分享图片`);
|
||||
const recordBox = <HTMLElement>document.querySelector(".ur-box");
|
||||
const fileName = `【原神战绩】-${user.gameUid}`;
|
||||
const fileName = `【原神战绩】-${user.value.gameUid}`;
|
||||
loadingTitle.value = "正在生成图片";
|
||||
loadingSub.value = `${fileName}.png`;
|
||||
loading.value = true;
|
||||
await generateShareImg(fileName, recordBox);
|
||||
loadingSub.value = "";
|
||||
loading.value = false;
|
||||
await TGLogger.Info(`[UserRecord][shareRecord][${user.gameUid}] 生成分享图片成功`);
|
||||
await TGLogger.Info(`[UserRecord][shareRecord][${user.value.gameUid}] 生成分享图片成功`);
|
||||
}
|
||||
|
||||
async function deleteRecord(): Promise<void> {
|
||||
if (!uidCur.value) {
|
||||
showSnackbar({ text: "未找到当前UID", color: "error" });
|
||||
return;
|
||||
}
|
||||
const confirm = await showConfirm({
|
||||
title: "确定删除?",
|
||||
text: `将删除${uidCur.value}对应的战绩数据`,
|
||||
});
|
||||
if (!confirm) {
|
||||
showSnackbar({ text: "已取消删除战绩数据", color: "cancel" });
|
||||
return;
|
||||
}
|
||||
await TSUserRecord.deleteUid(uidCur.value);
|
||||
showSnackbar({ text: `成功删除${uidCur.value}的战绩数据` });
|
||||
await loadUid();
|
||||
await loadRecord();
|
||||
}
|
||||
</script>
|
||||
<style lang="css" scoped>
|
||||
.ur-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
row-gap: 5px;
|
||||
}
|
||||
|
||||
.ur-top {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid var(--common-shadow-2);
|
||||
}
|
||||
|
||||
.ur-top-title {
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
gap: 10px;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--common-text-title);
|
||||
font-family: var(--font-title);
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.ur-top-btns {
|
||||
@@ -172,4 +242,29 @@ async function shareRecord(): Promise<void> {
|
||||
color: var(--btn-text);
|
||||
font-family: var(--font-text);
|
||||
}
|
||||
|
||||
.ur-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 10px;
|
||||
border: 1px solid var(--common-shadow-1);
|
||||
border-radius: 5px;
|
||||
background: var(--box-bg-1);
|
||||
row-gap: 5px;
|
||||
}
|
||||
|
||||
.ur-box-title {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.ur-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user