♻️ loading组件重构

This commit is contained in:
目棃
2024-12-16 11:13:30 +08:00
parent 1f167845a4
commit 24e3f11c4a
33 changed files with 482 additions and 428 deletions

View File

@@ -157,7 +157,7 @@ async function checkUserLoad(): Promise<void> {
if (curAccount === false) {
showSnackbar.error(`未获取到${uid.value}的账号数据!`);
await TGLogger.Error(`[App][listenOnInit] 获取${uid.value}账号数据失败`);
await new Promise((resolve) => setTimeout(resolve, 1000));
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
} else {
briefInfo.value = curAccount.brief;
cookie.value = curAccount.cookie;

View File

@@ -19,14 +19,16 @@ const showToli = ref<boolean>(false);
watch(
() => props.modelValue,
() => {
async () => {
if (props.modelValue) {
showTolo.value = true;
showToli.value = true;
return;
}
setTimeout(() => (showToli.value = false), 100);
setTimeout(() => (showTolo.value = false), 300);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showToli.value = false;
await new Promise<void>((resolve) => setTimeout(resolve, 300));
showTolo.value = false;
},
);

View File

@@ -16,12 +16,12 @@ type TShareBtnProps = { selector: string; title: string };
const props = defineProps<TShareBtnProps>();
async function shareContent(): Promise<void> {
showLoading.start("正在生成分享图片", props.title);
await showLoading.start("正在生成分享图片", props.title);
await TGLogger.Info("[TShareBtn][shareContent] 开始生成分享图片");
const shareDom = document.querySelector<HTMLElement>(props.selector);
if (shareDom === null) {
showSnackbar.error("分享内容不存在", 3000);
showLoading.end();
await showLoading.end();
return;
}
shareDom.querySelectorAll("details").forEach((item) => {
@@ -33,7 +33,7 @@ async function shareContent(): Promise<void> {
if (item.hasAttribute("details-open")) item.removeAttribute("details-open");
else item.open = false;
});
showLoading.end();
await showLoading.end();
await TGLogger.Info("[TShareBtn][shareContent] 生成分享图片完成");
}
</script>

View File

@@ -31,7 +31,7 @@
</template>
<script lang="ts" setup>
import { computed, onMounted, reactive, ref, useTemplateRef, watch } from "vue";
import { computed, onMounted, ref, shallowRef, useTemplateRef, watch } from "vue";
import type { DialogCheckParams, DialogInputParams, DialogParams } from "./dialog.js";
@@ -39,7 +39,7 @@ const defaultProp: DialogParams = { title: "", text: "", mode: "check", otcancel
const props = defineProps<DialogParams>();
// 组件参数
const data = reactive<DialogParams>(defaultProp);
const data = shallowRef<DialogParams>(defaultProp);
const show = ref<boolean>(false);
const showOuter = ref<boolean>(false);
const showInner = ref<boolean>(false);
@@ -60,14 +60,17 @@ const inputVal = computed<string | false | undefined>(() => {
watch(
() => show.value,
() => {
async () => {
if (show.value) {
showOuter.value = true;
setTimeout(() => (showInner.value = true), 100);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = true;
return;
}
setTimeout(() => (showInner.value = false), 100);
setTimeout(() => (showOuter.value = false), 300);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = false;
await new Promise<void>((resolve) => setTimeout(resolve, 300));
showOuter.value = false;
},
);
@@ -93,43 +96,51 @@ onMounted(async () => {
});
async function displayCheckBox(params: DialogCheckParams): Promise<boolean | undefined> {
data.title = params.title;
data.text = params.text ?? "";
data.mode = "check";
data.otcancel = params.otcancel ?? true;
data.value = {
title: params.title,
text: params.text ?? "",
mode: "check",
otcancel: params.otcancel ?? true,
};
show.value = true;
return await new Promise<boolean | undefined>((resolve) => {
watch(
() => show.value,
() => setTimeout(() => resolve(checkVal.value), 500),
async () => {
await new Promise<void>((res) => setTimeout(res, 500));
resolve(checkVal.value);
},
);
});
}
async function displayInputBox(params: DialogInputParams): Promise<string | false | undefined> {
data.title = params.title;
data.text = params.text ?? "";
data.mode = "input";
data.value = {
title: params.title,
text: params.text ?? "",
mode: "input",
otcancel: params.otcancel ?? true,
};
inputDefault.value = params.input ?? "";
data.otcancel = params.otcancel ?? true;
show.value = true;
return await new Promise<string | false | undefined>((resolve) => {
setTimeout(() => inputEl.value?.focus(), 100);
watch(
() => show.value,
() => setTimeout(() => resolve(inputVal.value), 500),
async () => {
await new Promise<void>((res) => setTimeout(res, 500));
resolve(inputVal.value);
},
);
});
}
// 确认
function handleConfirm(): void {
if (data.mode === "input") {
if (data.value.mode === "input") {
dialogVal.value = inputDefault.value;
inputDefault.value = "";
} else {
dialogVal.value = true;
}
} else dialogVal.value = true;
show.value = false;
}
@@ -141,7 +152,7 @@ function handleCancel(): void {
// 点击外部事件
function handleOuter(): void {
if (data.otcancel) {
if (data.value.otcancel) {
dialogVal.value = undefined;
show.value = false;
}

View File

@@ -25,14 +25,17 @@ const geetestEl = useTemplateRef<HTMLDivElement>("geetestRef");
watch(
() => show.value,
() => {
async () => {
if (show.value) {
showOuter.value = true;
setTimeout(() => (showInner.value = true), 100);
} else {
setTimeout(() => (showInner.value = false), 100);
setTimeout(() => (showOuter.value = false), 300);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = true;
return;
}
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = false;
await new Promise<void>((resolve) => setTimeout(resolve, 300));
showOuter.value = false;
},
);

View File

@@ -1,7 +1,7 @@
/**
* @file component/func/loading.ts
* @description loading 组件封装,函数式调用
* @since Beta v0.6.3
* @since Beta v0.6.7
*/
import type { ComponentInternalInstance, VNode } from "vue";
@@ -11,18 +11,19 @@ import loading from "./loading.vue";
const loadingId = "tg-func-loading";
export type LoadingParams = { show: boolean; title: string; subtitle: string; empty?: boolean };
export type LoadingParams = { show: boolean; title?: string; subtitle?: string; empty?: boolean };
type LoadingUpdateParams = Omit<LoadingParams, "show" | "subtitle"> & { timeout?: number };
// 低于100则不可感高于200则过于缓慢
const TIMEOUT: Readonly<number> = 150;
/**
* @description 自定义 loading 组件
* @since Beta v0.6.3
* @since Beta v0.6.7
* @return LoadingInstance
*/
interface LoadingInstance extends ComponentInternalInstance {
exposeProxy: {
displayBox: (props: LoadingParams) => void;
};
}
type LoadingInstance = ComponentInternalInstance & {
exposeProxy: { displayBox: (props: LoadingParams) => Promise<void> };
};
function renderBox(props: LoadingParams): VNode {
const container = document.createElement("div");
@@ -35,31 +36,36 @@ function renderBox(props: LoadingParams): VNode {
let loadingInstance: VNode;
function showLoadingFull(show: boolean, title: string, sub: string, empty: boolean): void {
const params: LoadingParams = { show: show, title: title, subtitle: sub, empty: empty };
async function showLoadingFull(option: LoadingParams): Promise<void> {
if (loadingInstance !== undefined) {
const boxVue = <LoadingInstance>loadingInstance.component;
return boxVue.exposeProxy.displayBox(params);
return await boxVue.exposeProxy.displayBox(option);
} else {
loadingInstance = renderBox(params);
return showLoadingFull(show, title, sub, empty);
loadingInstance = renderBox(option);
return await showLoadingFull(option);
}
}
function showLoadingStart(title: string, sub?: string): void {
showLoadingFull(true, title, sub ?? "", false);
async function showLoadingStart(
title: string,
subtitle?: string,
timeout: number = TIMEOUT,
): Promise<void> {
await showLoadingFull({ show: true, title, subtitle, empty: false });
await new Promise<void>((resolve) => setTimeout(resolve, timeout));
}
function showLoadingUpdate(title: string, sub?: string, empty?: boolean): void {
showLoadingFull(true, title, sub ?? "", empty ?? false);
async function showLoadingUpdate(subtitle: string, opt?: LoadingUpdateParams): Promise<void> {
await showLoadingFull({ show: true, title: opt?.title, subtitle, empty: opt?.empty });
await new Promise<void>((resolve) => setTimeout(resolve, opt?.timeout ?? TIMEOUT));
}
function showLoadingEmpty(title: string, sub?: string): void {
showLoadingFull(true, title, sub ?? "", true);
async function showLoadingEmpty(title: string, subtitle?: string): Promise<void> {
await showLoadingFull({ show: true, title, subtitle, empty: true });
}
function showLoadingEnd(): void {
showLoadingFull(false, "", "", false);
async function showLoadingEnd(): Promise<void> {
await showLoadingFull({ show: false });
}
const showLoading = {

View File

@@ -11,7 +11,9 @@
<div />
</div>
</div>
<div class="loading-subtitle" v-show="data.subtitle !== ''">{{ data.subtitle }}</div>
<div class="loading-subtitle" v-show="data.subtitle && data.subtitle !== ''">
{{ data.subtitle }}
</div>
<div class="loading-img">
<img v-if="!empty" src="/source/UI/loading.webp" alt="loading" />
<img v-else src="/source/UI/empty.webp" alt="empty" />
@@ -23,7 +25,7 @@
</transition>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, toRaw } from "vue";
import { onMounted, ref, shallowRef, watch } from "vue";
import { LoadingParams } from "./loading.js";
@@ -32,36 +34,39 @@ const showOuter = ref<boolean>(false);
const showInner = ref<boolean>(false);
const props = defineProps<LoadingParams>();
const data = ref<LoadingParams>(toRaw(props));
const data = shallowRef<LoadingParams>(props);
watch(
() => showBox.value,
() => {
async () => {
if (showBox.value) {
showOuter.value = true;
setTimeout(() => (showInner.value = true), 100);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = true;
return;
}
setTimeout(() => (showInner.value = false), 100);
setTimeout(() => (showOuter.value = false), 300);
await new Promise<void>((resolve) => setTimeout(resolve, 100));
showInner.value = false;
await new Promise<void>((resolve) => setTimeout(resolve, 300));
showOuter.value = false;
},
);
onMounted(() => displayBox(props));
onMounted(async () => await displayBox(props));
function displayBox(params: LoadingParams): void {
async function displayBox(params: LoadingParams): Promise<void> {
if (!params.show) {
showBox.value = false;
setTimeout(() => {
data.value.title = "";
data.value.subtitle = "";
data.value.empty = false;
}, 500);
await new Promise<void>((resolve) => setTimeout(resolve, 500));
data.value = { show: false, title: undefined, subtitle: undefined, empty: undefined };
return;
}
data.value.title = params.title;
data.value.subtitle = params.subtitle;
data.value.empty = params.empty;
data.value = {
title: params.title || data.value.title,
subtitle: params.subtitle || data.value.subtitle,
empty: params.empty || data.value.empty,
show: true,
};
showBox.value = true;
}

View File

@@ -10,12 +10,12 @@
</transition>
</template>
<script lang="ts" setup>
import { computed, onMounted, ref, toRaw } from "vue";
import { computed, onMounted, onUnmounted, ref, shallowRef } from "vue";
import { SnackbarParams } from "./snackbar.js";
const props = defineProps<SnackbarParams>();
const data = ref<SnackbarParams>(toRaw(props));
const data = shallowRef<SnackbarParams>(props);
const show = ref<boolean>(false);
const bgColor = computed(() => data.value.color);
@@ -43,18 +43,31 @@ function transColor(color: string): string {
}
}
function displayBox(params: TGApp.Component.Snackbar.Params): void {
data.value.text = params.text;
data.value.color = transColor(params.color);
data.value.timeout = params.timeout;
function getTimer(): void {
show.value = false;
}
function displayBox(params: SnackbarParams): void {
data.value = {
text: params.text,
color: transColor(params.color),
timeout: params.timeout,
};
show.value = true;
if (timer != undefined) {
clearTimeout(timer);
timer = undefined;
}
timer = setTimeout(() => (show.value = false), data.value.timeout);
timer = setTimeout(getTimer, data.value.timeout);
}
onUnmounted(() => {
if (timer != undefined) {
clearTimeout(timer);
timer = undefined;
}
});
defineExpose({ displayBox });
</script>
<style lang="css" scoped>

View File

@@ -119,7 +119,9 @@ async function confirmCUD(): Promise<void> {
await remove(oriDir, { recursive: true });
showSnackbar.success("已删除原用户数据目录!");
}
setTimeout(() => window.location.reload(), 4000);
showSnackbar.info("即将刷新页面...");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
async function confirmCGD(): Promise<void> {
@@ -185,15 +187,14 @@ async function confirmCLD(): Promise<void> {
showSnackbar.warn("无需清理!");
return;
}
showLoading.start("正在清理日志文件...");
await showLoading.start("正在清理日志文件...");
for (const file of delFiles) {
showLoading.update("正在清理日志文件...", `正在清理 ${file.name}`);
await showLoading.update(`正在清理 ${file.name}`);
const filePath = `${logDir.value}${sep()}${file.name}`;
await remove(filePath);
await new Promise<void>((resolve) => setTimeout(resolve, 200));
}
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
showLoading.end();
await showLoading.end();
showSnackbar.success(`已清理 ${delFiles.length} 个日志文件!`);
}

View File

@@ -24,7 +24,7 @@
@click="useUserStore().switchGameAccount(ac.gameUid)"
>
<v-list-item-title>{{ ac.nickname }}</v-list-item-title>
<v-list-item-subtitle> {{ ac.gameUid }}({{ ac.regionName }}) </v-list-item-subtitle>
<v-list-item-subtitle> {{ ac.gameUid }}({{ ac.regionName }})</v-list-item-subtitle>
<template #append>
<div v-if="ac.gameUid === account.gameUid" title="当前登录账号">
<v-icon color="green">mdi-check</v-icon>
@@ -152,7 +152,7 @@ async function tryCaptchaLogin(): Promise<void> {
}
const loginResp = await tryLoginByCaptcha(phone, captcha, actionType);
if (!loginResp) return;
showLoading.start("正在登录...");
await showLoading.start("正在尝试登录...");
const ck: TGApp.App.Account.Cookie = {
account_id: loginResp.user_info.aid,
ltuid: loginResp.user_info.aid,
@@ -162,20 +162,20 @@ async function tryCaptchaLogin(): Promise<void> {
stoken: loginResp.token.token,
ltoken: "",
};
showLoading.update("正在登录...", "正在获取 LToken");
await showLoading.update("正在获取 LToken");
const ltokenRes = await PassportApi.lToken.get(ck);
if (typeof ltokenRes !== "string") {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${ltokenRes.retcode}]${ltokenRes.message}`);
await TGLogger.Error(`获取LToken失败${ltokenRes.retcode}-${ltokenRes.message}`);
return;
}
showSnackbar.success("获取LToken成功");
ck.ltoken = ltokenRes;
showLoading.update("正在登录...", "正在获取 CookieToken");
await showLoading.update("正在获取 CookieToken");
const cookieTokenRes = await PassportApi.cookieToken(ck);
if (typeof cookieTokenRes !== "string") {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${cookieTokenRes.retcode}]${cookieTokenRes.message}`);
await TGLogger.Error(
`获取CookieToken失败${cookieTokenRes.retcode}-${cookieTokenRes.message}`,
@@ -184,10 +184,10 @@ async function tryCaptchaLogin(): Promise<void> {
}
showSnackbar.success("获取CookieToken成功");
ck.cookie_token = cookieTokenRes;
showLoading.update("正在登录...", "正在获取用户信息");
await showLoading.update("正在获取用户信息");
const briefRes = await BBSApi.userInfo(ck);
if ("retcode" in briefRes) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${briefRes.retcode}]${briefRes.message}`);
await TGLogger.Error(`获取用户数据失败:${briefRes.retcode}-${briefRes.message}`);
return;
@@ -199,7 +199,7 @@ async function tryCaptchaLogin(): Promise<void> {
avatar: briefRes.avatar_url,
desc: briefRes.introduce,
};
showLoading.update("正在登录...", "正在保存用户数据");
await showLoading.update("正在保存用户数据");
await TSUserAccount.account.saveAccount({
uid: briefInfoGet.uid,
cookie: ck,
@@ -210,10 +210,10 @@ async function tryCaptchaLogin(): Promise<void> {
briefInfo.value = briefInfoGet;
cookie.value = ck;
isLogin.value = true;
showLoading.update("正在登录...", "正在获取游戏账号");
await showLoading.update("正在获取游戏账号");
const gameRes = await TakumiApi.bind.gameRoles(cookie.value);
if (!Array.isArray(gameRes)) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${gameRes.retcode}]${gameRes.message}`);
await TGLogger.Error(`获取游戏账号失败:${gameRes.retcode}-${gameRes.message}`);
return;
@@ -223,11 +223,11 @@ async function tryCaptchaLogin(): Promise<void> {
const curAccount = await TSUserAccount.game.getCurAccount(briefInfoGet.uid);
if (!curAccount) {
showSnackbar.warn("未检测到游戏账号,请重新刷新");
showLoading.end();
await showLoading.end();
return;
}
account.value = curAccount;
showLoading.end();
await showLoading.end();
showSnackbar.success("成功登录!");
}
@@ -238,14 +238,14 @@ async function refreshUser(uid: string) {
return;
}
let ck = account.cookie;
showLoading.start("正在刷新用户信息", "正在验证 LToken");
await showLoading.start("正在刷新用户信息", "正在验证 LToken");
const verifyLTokenRes = await PassportApi.lToken.verify(ck);
if (typeof verifyLTokenRes === "string") {
showLoading.update("正在刷新用户信息", "验证 LToken 成功");
await showLoading.update("验证 LToken 成功");
showSnackbar.success("验证 LToken 成功");
await TGLogger.Info("[tc-userBadge][refreshUser] 验证 LToken 成功");
} else {
showLoading.update("正在刷新用户信息", "验证 LToken 失败");
await showLoading.update("验证 LToken 失败,将尝试重新获取 LToken");
showSnackbar.error(`[${verifyLTokenRes.retcode}]${verifyLTokenRes.message}`);
await TGLogger.Warn("[tc-userBadge][refreshUser] 验证 LToken 失败");
await TGLogger.Warn(
@@ -253,11 +253,11 @@ async function refreshUser(uid: string) {
);
const ltokenRes = await PassportApi.lToken.get(ck);
if (typeof ltokenRes === "string") {
showLoading.update("正在刷新用户信息", "获取 LToken 成功");
await showLoading.update("获取 LToken 成功");
ck.ltoken = ltokenRes;
await TGLogger.Info("[tc-userBadge][refreshUser] 获取 LToken 成功");
} else {
showLoading.update("正在刷新用户信息", "获取 LToken 失败");
await showLoading.update("获取 LToken 失败");
showSnackbar.error(`[${ltokenRes.retcode}]${ltokenRes.message}`);
await TGLogger.Error("[tc-userBadge][refreshUser] 获取 LToken 失败");
await TGLogger.Error(
@@ -265,14 +265,14 @@ async function refreshUser(uid: string) {
);
}
}
showLoading.update("正在刷新用户信息", "正在获取 CookieToken");
await showLoading.update("正在获取 CookieToken");
const cookieTokenRes = await PassportApi.cookieToken(ck);
if (typeof cookieTokenRes === "string") {
showLoading.update("正在刷新用户信息", "获取 CookieToken 成功");
await showLoading.update("获取 CookieToken 成功");
ck.cookie_token = cookieTokenRes;
await TGLogger.Info("[tc-userBadge][refreshUser] 获取 CookieToken 成功");
} else {
showLoading.update("正在刷新用户信息", "获取 CookieToken 失败");
await showLoading.update("获取 CookieToken 失败");
showSnackbar.error(`[${cookieTokenRes.retcode}]${cookieTokenRes.message}`);
await TGLogger.Error("[tc-userBadge][refreshUser] 获取 CookieToken 失败");
await TGLogger.Error(
@@ -280,15 +280,15 @@ async function refreshUser(uid: string) {
);
}
account.cookie = ck;
showLoading.update("正在刷新用户信息", "正在获取用户信息");
await showLoading.update("正在获取用户信息");
const infoRes = await BBSApi.userInfo(ck);
if ("retcode" in infoRes) {
showLoading.update("正在刷新用户信息", "获取用户信息失败");
await showLoading.update("获取用户信息失败");
showSnackbar.error(`[${infoRes.retcode}]${infoRes.message}`);
await TGLogger.Error("[tc-userBadge][refreshUserInfo] 获取用户信息失败");
await TGLogger.Error(`[tc-userBadge][refreshUserInfo] ${infoRes.retcode}: ${infoRes.message}`);
} else {
showLoading.update("正在刷新用户信息", "获取用户信息成功");
await showLoading.update("获取用户信息成功");
account.brief = {
nickname: infoRes.nickname,
uid: infoRes.uid,
@@ -298,21 +298,21 @@ async function refreshUser(uid: string) {
await TGLogger.Info("[tc-userBadge][refreshUserInfo] 获取用户信息成功");
}
await TSUserAccount.account.saveAccount(account);
showLoading.update("正在刷新用户信息", "正在获取账号信息");
await showLoading.update("正在获取账号信息");
const accountRes = await TakumiApi.bind.gameRoles(ck);
if (Array.isArray(accountRes)) {
showLoading.update("正在刷新用户信息", "获取账号信息成功");
await showLoading.update("获取账号信息成功");
await TGLogger.Info("[tc-userBadge][refreshUserInfo] 获取账号信息成功");
await TSUserAccount.game.saveAccounts(account.uid, accountRes);
} else {
showLoading.update("正在刷新用户信息", "获取账号信息失败");
await showLoading.update("获取账号信息失败");
showSnackbar.error(`[${accountRes.retcode}]${accountRes.message}`);
await TGLogger.Error("[tc-userBadge][refreshUserInfo] 获取账号信息失败");
await TGLogger.Error(
`[tc-userBadge][refreshUserInfo] ${accountRes.retcode}: ${accountRes.message}`,
);
}
showLoading.end();
await showLoading.end();
}
async function loadAccount(ac: string): Promise<void> {
@@ -441,7 +441,7 @@ async function addByCookie(): Promise<void> {
await TGLogger.Error(`解析Cookie失败${ckInput}`);
return;
}
showLoading.start("正在添加用户", "正在尝试刷新Cookie");
await showLoading.start("正在添加用户", "正在尝试刷新Cookie");
const ck: TGApp.App.Account.Cookie = {
account_id: ckRes.stuid,
ltuid: ckRes.stuid,
@@ -451,19 +451,19 @@ async function addByCookie(): Promise<void> {
stoken: ckRes.stoken,
ltoken: "",
};
showLoading.update("正在添加用户", "正在获取 LToken");
await showLoading.update("正在获取 LToken");
const ltokenRes = await PassportApi.lToken.get(ck);
if (typeof ltokenRes !== "string") {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${ltokenRes.retcode}]${ltokenRes.message}`);
await TGLogger.Error(`获取LToken失败${ltokenRes.retcode}-${ltokenRes.message}`);
return;
}
ck.ltoken = ltokenRes;
showLoading.update("正在添加用户", "正在获取 CookieToken");
await showLoading.update("正在获取 CookieToken");
const cookieTokenRes = await PassportApi.cookieToken(ck);
if (typeof cookieTokenRes !== "string") {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${cookieTokenRes.retcode}]${cookieTokenRes.message}`);
await TGLogger.Error(
`获取CookieToken失败${cookieTokenRes.retcode}-${cookieTokenRes.message}`,
@@ -471,10 +471,10 @@ async function addByCookie(): Promise<void> {
return;
}
ck.cookie_token = cookieTokenRes;
showLoading.update("正在添加用户", "正在获取用户信息");
await showLoading.update("正在获取用户信息");
const briefRes = await BBSApi.userInfo(ck);
if ("retcode" in briefRes) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${briefRes.retcode}]${briefRes.message}`);
await TGLogger.Error(`获取用户数据失败:${briefRes.retcode}-${briefRes.message}`);
return;
@@ -485,29 +485,29 @@ async function addByCookie(): Promise<void> {
avatar: briefRes.avatar_url,
desc: briefRes.introduce,
};
showLoading.update("正在添加用户", "正在保存用户数据");
await showLoading.update("正在保存用户数据");
await TSUserAccount.account.saveAccount({
uid: briefInfo.uid,
cookie: ck,
brief: briefInfo,
updated: "",
});
showLoading.update("正在添加用户", "正在获取游戏账号");
await showLoading.update("正在获取游戏账号");
const gameRes = await TakumiApi.bind.gameRoles(ck);
if (!Array.isArray(gameRes)) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${gameRes.retcode}]${gameRes.message}`);
return;
}
showLoading.update("正在添加用户", "正在保存游戏账号");
await showLoading.update("正在保存游戏账号");
await TSUserAccount.game.saveAccounts(briefInfo.uid, gameRes);
const curAccount = await TSUserAccount.game.getCurAccount(briefInfo.uid);
if (!curAccount) {
showLoading.end();
await showLoading.end();
showSnackbar.warn("未检测到游戏账号,请重新刷新");
return;
}
showLoading.end();
await showLoading.end();
showSnackbar.success("成功添加用户!");
}
@@ -521,7 +521,9 @@ async function clearUser(user: TGApp.App.Account.User): Promise<void> {
showSnackbar.cancel("已取消删除用户数据");
return;
}
await showLoading.start("正在删除用户数据", `正在删除用户${user.uid}`);
await TSUserAccount.account.deleteAccount(user.uid);
await showLoading.end();
showSnackbar.success("成功删除用户!");
}
</script>

View File

@@ -69,15 +69,15 @@ function getBoxData(item: TGApp.Plugins.Hutao.Base.Rate): TItemBoxData {
}
async function share(): Promise<void> {
showLoading.start("正在生成分享图");
const element = document.querySelector<HTMLElement>(".tuc-overlay-box");
if (element === null) {
showSnackbar.error("未获取到分享内容");
return;
}
const fileName = `真境剧诗_${new Date().getTime()}.png`;
await showLoading.start("正在生成分享图", fileName);
await generateShareImg(fileName, element, 1.2, true);
showLoading.end();
await showLoading.end();
}
</script>
<style lang="css" scoped>

View File

@@ -128,17 +128,17 @@ async function selectFile(): Promise<void> {
async function handleImportData(): Promise<void> {
if (fp.value === "未选择") return;
try {
showLoading.start("正在导入数据...", "正在验证数据...");
await showLoading.start("正在导入数据...", "正在验证数据...");
const check = await verifyUigfData(fp.value, true);
if (!check) {
showLoading.end();
await showLoading.end();
return;
}
showLoading.update("正在导入数据...", "正在读取数据...");
await showLoading.update("数据验证成功,正在读取数据...");
const uigfData = await readUigf4Data(fp.value);
dataRaw.value = uigfData;
data.value = uigfData.hk4e.map(parseData);
showLoading.end();
await showLoading.end();
} catch (e) {
if (e instanceof Error) {
showSnackbar.error(`[${e.name}] ${e.message}`);
@@ -179,45 +179,51 @@ function parseDataRaw(data: TGApp.Sqlite.GachaRecords.SingleTable[]): UgoUidItem
}
async function handleSelected(): Promise<void> {
if (props.mode === "import") {
if (!dataRaw.value) {
showSnackbar.error("未获取到数据!");
fp.value = "未选择";
return;
}
if (selectedData.value.length === 0) {
showSnackbar.warn("请至少选择一个!");
return;
}
for (const item of selectedData.value) {
showLoading.start("正在导入数据...", `正在导入UID: ${item.uid}`);
const dataFind = dataRaw.value.hk4e.find((i) => i.uid.toString() === item.uid);
if (!dataFind) {
showSnackbar.error(`未找到UID: ${item.uid}`);
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
continue;
}
await TSUserGacha.mergeUIGF4(dataFind);
}
showLoading.end();
showSnackbar.success("导入成功!");
if (props.mode === "import") return await handleImport();
return await handleExport();
}
async function handleImport(): Promise<void> {
if (!dataRaw.value) {
showSnackbar.error("未获取到数据!");
fp.value = "未选择";
return;
}
if (selectedData.value.length === 0) {
showSnackbar.warn("请至少选择一个!");
return;
}
showLoading.start("正在导数据...", "正在生成文件头");
await showLoading.start("正在导数据...");
for (const item of selectedData.value) {
await showLoading.update(`正在导入UID: ${item.uid}`);
const dataFind = dataRaw.value.hk4e.find((i) => i.uid.toString() === item.uid);
if (!dataFind) {
showSnackbar.error(`未找到UID: ${item.uid}`);
await new Promise<void>((resolve) => setTimeout(resolve, 1000));
continue;
}
await TSUserGacha.mergeUIGF4(dataFind);
}
await showLoading.end();
showSnackbar.success("导入成功!");
}
async function handleExport(): Promise<void> {
if (selectedData.value.length === 0) {
showSnackbar.warn("请至少选择一个!");
return;
}
await showLoading.start("正在导出数据...", "正在生成文件头");
const header = await getUigf4Header();
const data: TGApp.Plugins.UIGF.GachaHk4e[] = [];
for (const item of selectedData.value) {
showLoading.update("正在导出数据...", `正在导出UID: ${item.uid}`);
await showLoading.update(`正在导出UID: ${item.uid}`);
const dataItem = await getUigf4Item(item.uid);
data.push(dataItem);
}
showLoading.update("正在导出数据...", "正在生成文件...");
await showLoading.update("正在写入文件...");
await writeTextFile(fp.value, JSON.stringify({ info: header, hk4e: data }));
showLoading.end();
await showLoading.end();
showSnackbar.success(`导出成功! 文件路径: ${fp.value}`);
fp.value = await getDefaultSavePath();
}

View File

@@ -73,7 +73,7 @@ watch(
() => visible.value,
async (value) => {
if (value) {
await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise<void>((resolve) => setTimeout(resolve, 500));
if (postListEl.value === null || props.collection.total < 5) return;
let topNum: number;
if (props.collection.total - props.collection.cur < 3) topNum = props.collection.total;

View File

@@ -124,15 +124,18 @@ const localAbyss = shallowRef<TGApp.Sqlite.Abyss.TableData[]>([]);
const abyssIdList = computed<Array<number>>(() => localAbyss.value.map((abyss) => abyss.id));
onMounted(async () => {
showLoading.start("正在加载深渊数据...");
await showLoading.start("正在加载深渊数据");
version.value = await getVersion();
await TGLogger.Info("[UserAbyss][onMounted] 打开角色深渊页面");
await showLoading.update("正在获取UID列表");
uidList.value = await TSUserAbyss.getAllUid();
if (uidList.value.includes(account.value.gameUid)) uidCur.value = account.value.gameUid;
else if (uidList.value.length > 0) uidCur.value = uidList.value[0];
else uidCur.value = "";
await showLoading.update(`正在加载${uidCur.value}的深渊数据`);
await loadAbyss();
showLoading.end();
await showLoading.end();
showSnackbar.success(`已加载${uidCur.value}${localAbyss.value.length}条深渊数据`);
});
watch(() => uidCur.value, loadAbyss);
@@ -178,10 +181,10 @@ async function refreshAbyss(): Promise<void> {
}
}
await TGLogger.Info("[UserAbyss][getAbyssData] 更新深渊数据");
showLoading.start("正在获取上期深渊数据...", `UID: ${account.value.gameUid}`);
await showLoading.start(`正在获取${account.value.gameUid}的深渊数据`, "正在获取上期数据");
const resP = await TakumiRecordGenshinApi.spiralAbyss(cookie.value, account.value, "2");
if ("retcode" in resP) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${resP.retcode}]${resP.message}`);
await TGLogger.Error(
`[UserAbyss][getAbyssData] 获取${account.value.gameUid}的上期深渊数据失败`,
@@ -190,12 +193,12 @@ async function refreshAbyss(): Promise<void> {
return;
}
await TGLogger.Info("[UserAbyss][getAbyssData] 成功获取上期深渊数据");
showLoading.update("正在保存上期深渊数据...", `UID: ${account.value.gameUid}`);
await showLoading.update("正在保存上期深渊数据");
await TSUserAbyss.saveAbyss(account.value.gameUid, resP);
showLoading.update("正在获取本期深渊数据...", `UID: ${account.value.gameUid}`);
await showLoading.update("正在获取本期深渊数据");
const res = await TakumiRecordGenshinApi.spiralAbyss(cookie.value, account.value, "1");
if ("retcode" in res) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${res.retcode}]${res.message}`);
await TGLogger.Error(
`[UserAbyss][getAbyssData] 获取${account.value.gameUid}的本期深渊数据失败`,
@@ -203,29 +206,28 @@ async function refreshAbyss(): Promise<void> {
await TGLogger.Error(`[UserAbyss][getAbyssData] ${res.retcode} ${res.message}`);
return;
}
showLoading.update("正在保存本期深渊数据...", `UID: ${account.value.gameUid}`);
await showLoading.update("正在保存本期深渊数据");
await TSUserAbyss.saveAbyss(account.value.gameUid, res);
await TGLogger.Info(`[UserAbyss][getAbyssData] 成功获取${account.value.gameUid}的本期深渊数据`);
showLoading.update("正在加载深渊数据...", `UID: ${account.value.gameUid}`);
await showLoading.update("正在加载深渊数据");
uidList.value = await TSUserAbyss.getAllUid();
uidCur.value = account.value.gameUid;
await loadAbyss();
showLoading.end();
await showLoading.end();
}
async function shareAbyss(): Promise<void> {
await TGLogger.Info(`[UserAbyss][shareAbyss][${userTab.value}] 生成深渊数据分享图片`);
const fileName = `【深渊数据】${userTab.value}-${account.value.gameUid}`;
showLoading.start("正在生成图片", `${fileName}.png`);
const fileName = `【深渊数据】${userTab.value}-${account.value.gameUid}.png`;
const shareDom = document.querySelector<HTMLElement>(`#user-abyss-${userTab.value}`);
if (shareDom === null) {
showLoading.end();
showSnackbar.error("未找到深渊数据");
await TGLogger.Error("[UserAbyss][shareAbyss] 未找到深渊数据");
return;
}
await showLoading.start("正在生成图片", fileName);
await generateShareImg(fileName, shareDom);
showLoading.end();
await showLoading.end();
await TGLogger.Info(`[UserAbyss][shareAbyss][${userTab.value}] 生成深渊数据分享图片成功`);
}
@@ -252,20 +254,19 @@ async function uploadAbyss(): Promise<void> {
return;
}
try {
showLoading.start("正在上传深渊数据", `UID: ${account.value.gameUid}`);
await showLoading.start(`正在上传${account.value.gameUid}的深渊数据`, `期数:${abyssData.id}`);
const transAbyss = Hutao.Abyss.utils.transData(abyssData);
showLoading.update("正在获取角色数据", `UID: ${account.value.gameUid}`);
await showLoading.update("正在获取角色数据");
const roles = await TSUserAvatar.getAvatars(Number(account.value.gameUid));
if (!roles) {
showLoading.end();
await showLoading.end();
showSnackbar.warn("未找到角色数据");
return;
}
showLoading.update("正在转换角色数据", `UID: ${account.value.gameUid}`);
await showLoading.update("正在转换角色数据");
transAbyss.Avatars = Hutao.Abyss.utils.transAvatars(roles);
showLoading.update("正在上传深渊数据", `UID: ${account.value.gameUid}`);
await showLoading.update("正在上传深渊数据");
const res = await Hutao.Abyss.upload(transAbyss);
showLoading.end();
if (res.retcode !== 0) {
showSnackbar.error(`[${res.retcode}]${res.message}`);
await TGLogger.Error("[UserAbyss][uploadAbyss] 上传深渊数据失败");
@@ -281,7 +282,7 @@ async function uploadAbyss(): Promise<void> {
await TGLogger.Error(`[UserAbyss][uploadAbyss] ${e.message}`);
}
}
showLoading.end();
await showLoading.end();
}
async function deleteAbyss(): Promise<void> {
@@ -294,9 +295,9 @@ async function deleteAbyss(): Promise<void> {
showSnackbar.cancel("已取消删除");
return;
}
showLoading.start(`正在删除 ${uidCur.value} 的深渊数据`);
await showLoading.start("正在删除深渊数据", `UID: ${uidCur.value}`);
await TSUserAbyss.delAbyss(uidCur.value);
showLoading.end();
await showLoading.end();
showSnackbar.success(`已清除 ${uidCur.value} 的深渊数据`);
uidList.value = await TSUserAbyss.getAllUid();
if (uidList.value.length > 0) uidCur.value = uidList.value[0];

View File

@@ -143,12 +143,13 @@ const dataVal = shallowRef<TGApp.Sqlite.Character.UserRole>();
const enableShare = computed<boolean>(() => (showOverlay.value ? true : showSelect.value));
onMounted(async () => {
showLoading.start("正在获取角色数据...");
await showLoading.start("正在获取角色数据");
await TGLogger.Info("[Character][onMounted] 进入角色页面");
version.value = await getVersion();
await showLoading.update("正在加载UID列表");
await loadUid();
loadData.value = false;
showLoading.end();
await showLoading.end();
});
watch(
@@ -224,11 +225,11 @@ async function refresh(): Promise<void> {
}
if (showSelect.value) {
showSelect.value = false;
await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise<void>((resolve) => setTimeout(resolve, 500));
}
if (showOverlay.value) {
showOverlay.value = false;
await new Promise((resolve) => setTimeout(resolve, 500));
await new Promise<void>((resolve) => setTimeout(resolve, 500));
}
if (uidCur.value && uidCur.value !== account.value.gameUid) {
const switchCheck = await showDialog.check(
@@ -250,24 +251,23 @@ async function refresh(): Promise<void> {
}
}
await TGLogger.Info(`[Character][refreshRoles][${account.value.gameUid}] 正在更新角色数据`);
showLoading.start("正在更新角色数据...", `UID: ${account.value.gameUid}`);
loadData.value = true;
if (!cookie.value) {
showLoading.end();
showSnackbar.warn("请先登录");
loadData.value = false;
return;
}
showLoading.update("正在更新角色数据...", "正在刷新首页数据");
await showLoading.start(`正在更新${account.value.gameUid}的角色数据`);
loadData.value = true;
await showLoading.update("正在刷新首页数据");
const indexRes = await TakumiRecordGenshinApi.index(cookie.value, account.value, 1);
if ("retcode" in indexRes) {
showSnackbar.error(`[${indexRes.retcode}] ${indexRes.message}`);
await TGLogger.Error(JSON.stringify(indexRes.message));
showLoading.end();
await showLoading.end();
loadData.value = false;
return;
}
showLoading.update("正在更新角色数据...", "正在获取角色列表");
await showLoading.update("正在获取角色列表");
const listRes = await TakumiRecordGenshinApi.character.list(cookie.value, account.value);
if (!Array.isArray(listRes)) {
showSnackbar.error(`[${listRes.retcode}] ${listRes.message}`);
@@ -275,12 +275,12 @@ async function refresh(): Promise<void> {
await TGLogger.Error(
`[Character][refreshRoles][${account.value.gameUid}] ${listRes.retcode} ${listRes.message}`,
);
showLoading.end();
await showLoading.end();
loadData.value = false;
return;
}
const idList = listRes.map((i) => i.id.toString());
showLoading.update("正在更新角色数据...", `${idList.length}个角色`);
await showLoading.update(`${idList.length}个角色`);
const res = await TakumiRecordGenshinApi.character.detail(cookie.value, account.value, idList);
if ("retcode" in res) {
showSnackbar.error(`[${res.retcode}] ${res.message}`);
@@ -288,20 +288,21 @@ async function refresh(): Promise<void> {
await TGLogger.Error(
`[Character][refreshRoles][${account.value.gameUid}] ${res.retcode} ${res.message}`,
);
showLoading.end();
await showLoading.end();
loadData.value = false;
return;
}
propMap.value = res.property_map;
showLoading.update("正在更新角色数据...", "正在保存角色数据");
await showLoading.update("正在保存角色数据");
await TSUserAvatar.saveAvatars(account.value.gameUid, res.list);
await TGLogger.Info(`[Character][refreshRoles][${account.value.gameUid}] 成功更新角色数据`);
await TGLogger.Info(
`[Character][refreshRoles][${account.value.gameUid}] 共更新${res.list.length}个角色`,
);
await showLoading.update("正在加载角色数据");
await loadUid();
await loadRole();
showLoading.end();
await showLoading.end();
loadData.value = false;
}
@@ -316,12 +317,12 @@ async function share(): Promise<void> {
showSnackbar.error("未找到角色列表");
return;
}
const fileName = `【角色列表】-${account.value.gameUid}`;
showLoading.start("正在生成图片", `${fileName}.png`);
const fileName = `【角色列表】-${account.value.gameUid}.png`;
await showLoading.start("正在生成图片", fileName);
loadShare.value = true;
await generateShareImg(fileName, rolesBox);
showLoading.end();
loadShare.value = false;
await showLoading.end();
await TGLogger.Info(`[Character][shareRoles][${account.value.gameUid}] 生成分享图片成功`);
}

View File

@@ -127,16 +127,18 @@ const cloudCombat = shallowRef<TGApp.Plugins.Hutao.Combat.Data>();
const combatIdList = computed<Array<number>>(() => localCombat.value.map((combat) => combat.id));
onMounted(async () => {
showLoading.start("正在加载剧诗数据...");
await showLoading.start("正在加载剧诗数据");
version.value = await getVersion();
await TGLogger.Info("[UserCombat][onMounted] 打开真境剧诗页面");
showLoading.update("正在加载用户数据...");
await showLoading.update("正在加载UID列表");
uidList.value = await TSUserCombat.getAllUid();
if (uidList.value.includes(account.value.gameUid)) uidCur.value = account.value.gameUid;
else if (uidList.value.length > 0) uidCur.value = uidList.value[0];
else uidCur.value = "";
else if (uidList.value.length > 0) {
uidCur.value = uidList.value[0];
await showLoading.update(`正在加载UID${uidCur.value}的剧诗数据`);
} else uidCur.value = "";
await loadCombat();
showLoading.end();
await showLoading.end();
});
watch(() => uidCur.value, loadCombat);
@@ -153,11 +155,11 @@ async function loadCombat(): Promise<void> {
}
async function loadWiki(): Promise<void> {
showLoading.start("正在加载统计数据...");
await showLoading.start("正在加载统计数据");
const res = await Hutao.Combat.data();
if (res === undefined) showSnackbar.error("未获取到剧诗数据");
else cloudCombat.value = <TGApp.Plugins.Hutao.Combat.Data>res;
showLoading.end();
await showLoading.end();
showSnackbar.success("成功获取统计数据");
showData.value = true;
}
@@ -188,44 +190,44 @@ async function refreshCombat(): Promise<void> {
}
}
await TGLogger.Info("[UserCombat][getCombatData] 更新剧诗数据");
showLoading.start("正在获取剧诗数据...", `UID: ${account.value.gameUid}`);
await showLoading.start(`正在获取${account.value.gameUid}的剧诗数据`);
const res = await TakumiRecordGenshinApi.roleCombat(cookie.value, account.value);
if (res === false) {
showLoading.end();
await showLoading.end();
showSnackbar.warn("用户未解锁幻想真境剧诗");
return;
}
if ("retcode" in res) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${res.retcode}]${res.message}`);
await TGLogger.Error(`[UserCombat][getCombatData] 获取${account.value.gameUid}的剧诗数据失败`);
await TGLogger.Error(`[UserCombat][getCombatData] ${res.retcode} ${res.message}`);
return;
}
showLoading.update("正在保存剧诗数据...");
await showLoading.update("正在保存剧诗数据");
for (const combat of res) {
showLoading.update("正在保存剧诗数据...", `${combat.schedule.schedule_id}`);
await showLoading.update("正在保存剧诗数据");
await TSUserCombat.saveCombat(account.value.gameUid, combat);
}
showLoading.update("正在加载剧诗数据...");
await showLoading.update("正在加载剧诗数据");
uidList.value = await TSUserCombat.getAllUid();
uidCur.value = account.value.gameUid;
await loadCombat();
showLoading.end();
await showLoading.end();
}
async function shareCombat(): Promise<void> {
await TGLogger.Info(`[UserCombat][shareCombat][${userTab.value}] 生成剧诗数据分享图片`);
const fileName = `【剧诗数据】${userTab.value}-${account.value.gameUid}`;
const fileName = `【剧诗数据】${userTab.value}-${account.value.gameUid}.png`;
const shareDom = document.querySelector<HTMLElement>(`#user-combat-${userTab.value}`);
if (shareDom === null) {
showSnackbar.error("未找到分享数据");
await TGLogger.Warn(`[UserCombat][shareCombat][${userTab.value}] 未找到分享数据`);
return;
}
showLoading.start("正在生成图片", `${fileName}.png`);
await showLoading.start("正在生成图片", fileName);
await generateShareImg(fileName, shareDom);
showLoading.end();
await showLoading.end();
await TGLogger.Info(`[UserCombat][shareCombat][${userTab.value}] 生成剧诗数据分享图片成功`);
}
@@ -251,10 +253,9 @@ async function uploadCombat(): Promise<void> {
return;
}
try {
showLoading.start("正在上传剧诗数据");
await showLoading.start("正在上传剧诗数据");
const transCombat = Hutao.Combat.trans(combatData);
const res = await Hutao.Combat.upload(transCombat);
showLoading.end();
if (res.retcode === 0) {
showSnackbar.success(res.message ?? "上传剧诗数据成功");
await TGLogger.Info("[UserCombat][uploadCombat] 上传剧诗数据成功");
@@ -270,7 +271,7 @@ async function uploadCombat(): Promise<void> {
await TGLogger.Error(`[UserCombat][uploadCombat] ${e.message}`);
}
}
showLoading.end();
await showLoading.end();
}
async function deleteCombat(): Promise<void> {
@@ -283,15 +284,15 @@ async function deleteCombat(): Promise<void> {
showSnackbar.cancel("已取消删除");
return;
}
showLoading.start(`正在删除 ${uidCur.value} 的剧诗数据`);
await showLoading.start("正在删除剧诗数据", `UID: ${uidCur.value}`);
await TSUserCombat.delCombat(uidCur.value);
showLoading.update("正在加载剧诗数据...");
showSnackbar.success(`已清除 ${uidCur.value} 的剧诗数据`);
await showLoading.update("正在加载剧诗数据");
uidList.value = await TSUserCombat.getAllUid();
if (uidList.value.length > 0) uidCur.value = uidList.value[0];
else uidCur.value = undefined;
await loadCombat();
showLoading.end();
await showLoading.end();
}
</script>
<style lang="css" scoped>

View File

@@ -79,22 +79,22 @@ const selectItem = shallowRef<Array<string>>([]);
const gachaListCur = shallowRef<Array<TGApp.Sqlite.GachaRecords.SingleTable>>([]);
onMounted(async () => {
showLoading.start("正在加载祈愿数据...", "正在获取祈愿 UID 列表");
await showLoading.start("正在加载祈愿数据", "正在获取祈愿 UID 列表");
await TGLogger.Info("[UserGacha][onMounted] 进入角色祈愿页面");
selectItem.value = await TSUserGacha.getUidList();
if (selectItem.value.length === 0) {
showLoading.end();
await showLoading.end();
showSnackbar.error("暂无祈愿数据,请先导入祈愿数据");
await TGLogger.Warn("[UserGacha][onMounted] 暂无祈愿数据,请先导入祈愿数据");
return;
}
uidCur.value = selectItem.value[0];
showLoading.update("正在获取祈愿数据...", `UID${uidCur.value}`);
await showLoading.update(`UID${uidCur.value}`);
gachaListCur.value = await TSUserGacha.getGachaRecords(uidCur.value);
await TGLogger.Info(
`[UserGacha][onMounted] 获取到 ${uidCur.value}${gachaListCur.value.length} 条祈愿数据`,
);
showLoading.end();
await showLoading.end();
showSnackbar.success(`成功获取 ${gachaListCur.value.length} 条祈愿数据`);
});
@@ -114,6 +114,11 @@ watch(
// 刷新按钮点击事件
async function confirmRefresh(force: boolean): Promise<void> {
await TGLogger.Info(`[UserGacha][${account.value.gameUid}][confirmRefresh] 刷新祈愿数据`);
if (!cookie.value) {
showSnackbar.error("请先登录");
await TGLogger.Warn("[UserGacha][${account.gameUid}][confirmRefresh] 未检测到 cookie");
return;
}
if (uidCur.value && uidCur.value !== account.value.gameUid) {
const switchCheck = await showDialog.check(
"是否切换游戏账户",
@@ -133,13 +138,7 @@ async function confirmRefresh(force: boolean): Promise<void> {
return;
}
}
showLoading.start("正在刷新祈愿数据", "正在获取 authkey");
if (!cookie.value) {
showLoading.end();
showSnackbar.error("请先登录");
await TGLogger.Warn("[UserGacha][${account.gameUid}][confirmRefresh] 未检测到 cookie");
return;
}
await showLoading.start(`正在刷新祈愿数据`, `UID:${account.value.gameUid},正在获取 authkey`);
const authkeyRes = await TakumiApi.bind.authKey(cookie.value, account.value);
if (typeof authkeyRes === "string") {
authkey.value = authkeyRes;
@@ -150,7 +149,7 @@ async function confirmRefresh(force: boolean): Promise<void> {
await TGLogger.Error(
`[UserGacha][${account.value.gameUid}][confirmRefresh] ${authkeyRes.retcode} ${authkeyRes.message}`,
);
showLoading.end();
await showLoading.end();
return;
}
await refreshGachaPool("100", "新手祈愿", force);
@@ -159,9 +158,10 @@ async function confirmRefresh(force: boolean): Promise<void> {
await refreshGachaPool("400", "角色祈愿2", force);
await refreshGachaPool("302", "武器祈愿", force);
await refreshGachaPool("500", "集录祈愿", force);
showLoading.update("正在刷新祈愿数据", "数据获取完成,即将刷新页面");
showLoading.end();
await showLoading.end();
await TGLogger.Info(`[UserGacha][${account.value.gameUid}][confirmRefresh] 刷新祈愿数据完成`);
showSnackbar.success("祈愿数据刷新完成,即将刷新页面");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
@@ -174,13 +174,8 @@ async function refreshGachaPool(
let endId = "0";
let reqId = "0";
let gachaDataMap: Record<string, string[]> | undefined = undefined;
if (!force) {
showLoading.update(`正在刷新${label}数据`, "正在获取数据库祈愿最新 ID");
endId = (await TSUserGacha.getGachaCheck(account.value.gameUid, type)) ?? "0";
showLoading.update(`正在刷新${label}数据`, `最新 ID${endId}`);
} else {
showLoading.update(`正在刷新${label}数据`);
}
await showLoading.start(`正在刷新${label}数据`);
if (!force) endId = (await TSUserGacha.getGachaCheck(account.value.gameUid, type)) ?? "0";
while (true) {
const gachaRes = await Hk4eApi.gacha(authkey.value, type, reqId);
if (!Array.isArray(gachaRes)) {
@@ -195,15 +190,16 @@ async function refreshGachaPool(
}
if (gachaRes.length === 0) {
if (force) {
showLoading.update(`正在清理${label}数据`);
if (gachaDataMap)
await showLoading.update(`正在清理${label}数据`);
if (gachaDataMap) {
await TSUserGacha.cleanGachaRecords(account.value.gameUid, type, gachaDataMap);
}
}
break;
}
const uigfList: TGApp.Plugins.UIGF.GachaItem[] = [];
for (const item of gachaRes) {
showLoading.update(`正在刷新${label}数据`, `[${item.item_type}][${item.time}] ${item.name}`);
await showLoading.update(`[${item.item_type}][${item.time}] ${item.name}`);
const tempItem: TGApp.Plugins.UIGF.GachaItem = {
gacha_type: item.gacha_type,
item_id: item.item_id,
@@ -230,7 +226,6 @@ async function refreshGachaPool(
}
}
await TSUserGacha.mergeUIGF(account.value.gameUid, uigfList);
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1000));
if (!force && gachaRes.some((i) => i.id.toString() === endId.toString())) break;
reqId = gachaRes[gachaRes.length - 1].id.toString();
}
@@ -254,31 +249,28 @@ async function importUigf(): Promise<void> {
showSnackbar.cancel("已取消文件选择");
return;
}
await showLoading.start("正在导入祈愿数据", "正在验证祈愿数据");
const check = await verifyUigfData(selectedFile, false);
if (!check) return;
const remoteData = await readUigfData(selectedFile);
const importCheck = await showDialog.check(
"是否导入祈愿数据?",
`UID${remoteData.info.uid},共 ${remoteData.list.length} 条数据`,
);
if (!importCheck) {
showSnackbar.cancel("已取消祈愿数据导入");
if (!check) {
await showLoading.end();
return;
}
showLoading.start("正在导入祈愿数据");
await showLoading.update("正在读取祈愿数据");
const remoteData = await readUigfData(selectedFile);
await showLoading.update(`UID${remoteData.info.uid},共 ${remoteData.list.length} 条数据`);
if (remoteData.list.length === 0) {
showLoading.end();
await showLoading.end();
showSnackbar.error("导入的祈愿数据为空");
return;
}
showLoading.update("正在导入祈愿数据", `UID${remoteData.info.uid}`);
await TSUserGacha.mergeUIGF(remoteData.info.uid, remoteData.list);
showLoading.end();
showSnackbar.success(`成功导入 ${remoteData.list.length} 条祈愿数据`);
await showLoading.end();
showSnackbar.success(`成功导入 ${remoteData.list.length} 条祈愿数据,即将刷新页面`);
await TGLogger.Info(
`[UserGacha][importUigf] 成功导入 ${remoteData.info.uid}${remoteData.list.length} 条祈愿数据`,
);
setTimeout(() => window.location.reload(), 1000);
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
// 导出当前UID的祈愿数据
@@ -290,14 +282,6 @@ async function exportUigf(): Promise<void> {
showSnackbar.error(`UID ${uidCur.value} 暂无祈愿数据`);
return;
}
const exportCheck = await showDialog.check(
"是否导出祈愿数据?",
`UID${uidCur.value},共 ${gachaList.length} 条数据`,
);
if (!exportCheck) {
showSnackbar.cancel(`已取消 UID ${uidCur.value} 的祈愿数据导出`);
return;
}
const file = await save({
title: "导出祈愿数据",
filters: [{ name: "UIGF JSON", extensions: ["json"] }],
@@ -310,9 +294,9 @@ async function exportUigf(): Promise<void> {
await TGLogger.Info(
`[UserGacha][${uidCur.value}][exportUigf] 导出${gachaList.length} 条祈愿数据到 ${file}`,
);
showLoading.start("正在导出祈愿数据", `正在导出 ${uidCur.value} 的祈愿数据`);
await showLoading.start("正在导出祈愿数据", `UID:${uidCur.value}`);
await exportUigfData(uidCur.value, gachaList, file);
showLoading.end();
await showLoading.end();
showSnackbar.success(`成功导出 ${uidCur.value} 的祈愿数据`);
await TGLogger.Info(`[UserGacha][${uidCur.value}][exportUigf] 导出祈愿数据完成`);
}
@@ -352,14 +336,15 @@ async function deleteGacha(): Promise<void> {
return;
}
}
showLoading.start("正在删除祈愿数据", `正在删除${uidCur.value}的祈愿数据`);
await showLoading.start("正在删除祈愿数据", `UID:${uidCur.value}`);
await TSUserGacha.deleteGachaRecords(uidCur.value);
showLoading.end();
showSnackbar.success(`已成功删除 ${uidCur.value} 的祈愿数据`);
await showLoading.end();
showSnackbar.success(`已成功删除 ${uidCur.value} 的祈愿数据,即将刷新页面`);
await TGLogger.Info(
`[UserGacha][${uidCur.value}][deleteGacha] 成功删除 ${gachaListCur.value.length} 条祈愿数据`,
);
setTimeout(() => window.location.reload(), 1000);
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
</script>
<style lang="css" scoped>

View File

@@ -81,11 +81,11 @@ const uidList = shallowRef<Array<number>>([]);
const recordData = shallowRef<TGApp.Sqlite.Record.RenderData>();
onMounted(async () => {
showLoading.start("正在获取战绩数据...");
await showLoading.start("正在获取战绩数据");
await TGLogger.Info("[UserRecord][onMounted] 打开角色战绩页面");
version.value = await getVersion();
await loadUid();
showLoading.end();
await showLoading.end();
});
watch(() => uidCur.value, loadRecord);
@@ -131,11 +131,11 @@ async function refreshRecord(): Promise<void> {
return;
}
}
showLoading.start("正在刷新战绩数据...");
await showLoading.start(`正在刷新${account.value.gameUid}的战绩数据`);
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}] 刷新战绩数据`);
const res = await TakumiRecordGenshinApi.index(cookie.value, account.value);
if ("retcode" in res) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${res.retcode}] ${res.message}`);
await TGLogger.Error(`[UserRecord][refresh][${account.value.gameUid}] 获取战绩数据失败`);
await TGLogger.Error(
@@ -143,16 +143,15 @@ async function refreshRecord(): Promise<void> {
);
return;
}
await TGLogger.Info(`[UserRecord][refresh][${account.gameUid}] 获取战绩数据成功`);
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}] 获取战绩数据成功`);
await TGLogger.Info(`[UserRecord][refresh][${account.value.gameUid}]`, false);
console.log(res);
showLoading.update("正在保存战绩数据");
await showLoading.update("正在保存战绩数据");
await TSUserRecord.saveRecord(Number(account.value.gameUid), res);
showLoading.update("正在加载战绩数据");
await showLoading.update("正在加载战绩数据");
await loadUid();
await loadRecord();
if (recordData.value === undefined) await loadRecord();
showLoading.end();
await showLoading.end();
}
async function shareRecord(): Promise<void> {
@@ -166,10 +165,10 @@ async function shareRecord(): Promise<void> {
showSnackbar.error("未找到战绩数据,请尝试刷新");
return;
}
const fileName = `【原神战绩】-${account.value.gameUid}`;
showLoading.start("正在生成图片", fileName);
const fileName = `【原神战绩】-${account.value.gameUid}.png`;
await showLoading.start("正在生成图片", fileName);
await generateShareImg(fileName, recordBox);
showLoading.end();
await showLoading.end();
await TGLogger.Info(`[UserRecord][shareRecord][${account.value.gameUid}] 生成分享图片成功`);
}

View File

@@ -90,20 +90,20 @@ watch(
);
onMounted(async () => {
showLoading.start("正在获取深渊数据...", "正在获取深渊概览");
await showLoading.start("正在获取深渊数据", "正在获取深渊概览");
overview.value = {
cur: await Hutao.Abyss.overview(),
last: await Hutao.Abyss.overview(true),
};
showLoading.update("正在获取深渊数据...", "正在获取角色使用率数据");
await showLoading.update("正在获取角色使用率数据");
const useData = <AbyssDataItem<TGApp.Plugins.Hutao.Abyss.AvatarUse[]>>await getData("use");
abyssData.value = { use: useData, up: null, team: null, hold: null };
showLoading.end();
await showLoading.end();
});
async function refreshData(type: AbyssTab): Promise<void> {
if (abyssData.value && abyssData.value[type] !== null) return;
showLoading.update("正在获取深渊数据...", `正在获取 ${AbyssTabEnum[type]} 数据`);
await showLoading.start("正在获取深渊数据", `正在获取 ${AbyssTabEnum[type]} 数据`);
const data = await getData(type);
switch (type) {
case "use":
@@ -123,7 +123,7 @@ async function refreshData(type: AbyssTab): Promise<void> {
triggerRef(abyssData);
break;
}
showLoading.end();
await showLoading.end();
}
async function getData(type: AbyssTab): Promise<AbyssDataItemType<AbyssTab>> {

View File

@@ -58,7 +58,7 @@ import showSnackbar from "@comp/func/snackbar.js";
import TuaAchiList from "@comp/userAchi/tua-achi-list.vue";
import TuaSeries from "@comp/userAchi/tua-series.vue";
import TSUserAchi from "@Sqlite/modules/userAchi.js";
import { path } from "@tauri-apps/api";
import { path, window } from "@tauri-apps/api";
import { listen, type UnlistenFn } from "@tauri-apps/api/event";
import { open, save } from "@tauri-apps/plugin-dialog";
import { writeTextFile } from "@tauri-apps/plugin-fs";
@@ -92,13 +92,15 @@ const title = computed<string>(() => {
});
onMounted(async () => {
showLoading.start("正在加载成就数据...");
await showLoading.start("正在加载成就数据");
await TGLogger.Info("[Achievements][onMounted] 打开成就页面");
await showLoading.update("正在读取UID列表");
uidList.value = await TSUserAchi.getAllUid();
if (uidList.value.length === 0) uidList.value = [0];
uidCur.value = uidList.value[0];
await showLoading.update("正在获取成就概况");
await refreshOverview();
showLoading.end();
await showLoading.end();
if (route.query.app && typeof route.query.app === "string") {
await handleImportOuter(route.query.app);
}
@@ -131,8 +133,13 @@ async function importJson(): Promise<void> {
await TGLogger.Info("[Achievements][importJson] 已取消文件选择");
return;
}
await showLoading.start("正在导入数据", "正在验证数据");
const check = await verifyUiafData(selectedFile);
if (!check) return;
if (!check) {
await showLoading.end();
return;
}
await showLoading.end();
let uidInput = await showDialog.input("请输入存档UID", "UID:", uidCur.value.toString());
if (uidInput === false) {
showSnackbar.cancel("已取消存档导入");
@@ -143,18 +150,13 @@ async function importJson(): Promise<void> {
showSnackbar.warn("请输入合法数字");
return;
}
showLoading.start("正在导入数据", "正在解析数据");
await showLoading.start("正在导入数据", `存档UID${uidInput}`);
const remoteRaw = await readUiafData(selectedFile);
await TGLogger.Info("[Achievements][importJson] 读取 UIAF 数据成功");
await TGLogger.Info(`[Achievements][importJson] 导入来源:${remoteRaw.info.export_app}`);
await TGLogger.Info(`[Achievements][importJson] 导入版本:${remoteRaw.info.export_app_version}`);
await TGLogger.Info(`[Achievements][importJson] 导入时间:${remoteRaw.info.export_timestamp}`);
await TGLogger.Info(`[Achievements][importJson] 导入数据:${remoteRaw.list.length}`);
await TGLogger.Info(`[Achievements][importJson] 导入存档:${uidInput}`);
showLoading.update("正在导入数据", "正在合并数据");
await TSUserAchi.mergeUiaf(remoteRaw.list, Number(uidInput));
showLoading.end();
setTimeout(() => window.location.reload(), 1000);
await showLoading.end();
showSnackbar.success("导入成功,即将刷新页面");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
async function exportJson(): Promise<void> {
@@ -192,10 +194,15 @@ async function handleImportOuter(app: string): Promise<void> {
showSnackbar.cancel("已取消导入");
return;
}
// 读取 剪贴板
await showLoading.start("正在导入数据", "正在读取剪贴板");
const clipboard = await window.navigator.clipboard.readText();
await showLoading.update("正在验证数据");
const check = await verifyUiafDataClipboard();
if (!check) return;
if (!check) {
await showLoading.end();
return;
}
await showLoading.end();
let uidInput = await showDialog.input("请输入存档UID", "UID:", uidCur.value.toString());
if (uidInput === false) {
showSnackbar.cancel("已取消存档导入");
@@ -207,12 +214,13 @@ async function handleImportOuter(app: string): Promise<void> {
return;
}
const data: TGApp.Plugins.UIAF.Data = JSON.parse(clipboard);
showLoading.start("正在导入数据", "正在解析数据");
await showLoading.start("正在导入数据", `存档UID${uidInput}`);
await TSUserAchi.mergeUiaf(data.list, Number(uidInput));
showLoading.end();
await showLoading.end();
showSnackbar.success("导入成功,即将刷新页面");
await TGLogger.Info("[Achievements][handleImportOuter] 导入成功");
setTimeout(async () => await router.push("/achievements"), 1500);
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
await router.push("/achievements");
}
async function createUid(): Promise<void> {

View File

@@ -120,25 +120,25 @@ onMounted(async () => {
});
async function loadData(): Promise<void> {
showLoading.start(
await showLoading.start(
"正在获取公告数据",
`服务器:${getRegionName(server.value)},语言:${getLangName(lang.value)}`,
);
const annoData = await Hk4eApi.anno.list(server.value, lang.value);
const listCards = getAnnoCard(annoData);
await Promise.all(
listCards.map(async (item) => {
if (item.typeLabel === AnnoType.game) return;
const detail = await Hk4eApi.anno.content(item.id, server.value, "zh-cn");
const timeStr = getAnnoTime(detail.content);
if (timeStr !== false) item.timeStr = timeStr;
}),
);
await showLoading.update("", { title: "正在解析游戏内公告时间" });
for (const item of listCards) {
if (item.typeLabel === AnnoType.game) continue;
const detail = await Hk4eApi.anno.content(item.id, server.value, "zh-cn");
const timeStr = getAnnoTime(detail.content);
if (timeStr !== false) item.timeStr = timeStr;
await showLoading.update(`[${item.id}]${item.subtitle}:${item.timeStr}`);
}
annoCards.value = {
activity: listCards.filter((item) => item.typeLabel === AnnoType.activity),
game: listCards.filter((item) => item.typeLabel === AnnoType.game),
};
showLoading.end();
await showLoading.end();
}
function getRegionName(value: AnnoServer): string {

View File

@@ -155,7 +155,7 @@ const isNeedResize = ref<boolean>(needResize.value !== "false");
const cacheSize = ref<number>(0);
onMounted(async () => {
showLoading.start("正在获取应用信息...");
await showLoading.start("正在加载设置页面", "正在获取缓存大小");
await TGLogger.Info("[Config] 打开设置页面");
const cacheDir = await getCacheDir();
if (cacheDir === false) return;
@@ -164,8 +164,9 @@ onMounted(async () => {
const size: number = await core.invoke("get_dir_size", { path: dir });
cacheBSize += size;
}
await showLoading.update(`缓存大小:${bytesToSize(cacheBSize)}`);
cacheSize.value = cacheBSize;
showLoading.end();
await showLoading.end();
});
// 备份数据
@@ -189,9 +190,9 @@ async function confirmBackup(): Promise<void> {
await TGLogger.Info(`[Config][confirmBackup] 选择备份路径 ${dir.toString()}`);
saveDir = dir;
} else await TGLogger.Info(`[Config][confirmBackup] 备份到默认路径 ${saveDir}`);
showLoading.start("正在备份数据...");
await showLoading.start("正在备份数据");
await backUpUserData(saveDir);
showLoading.end();
await showLoading.end();
showSnackbar.success("数据已备份!");
await TGLogger.Info("[Config][confirmBackup] 备份完成");
}
@@ -217,9 +218,9 @@ async function confirmRestore(): Promise<void> {
await TGLogger.Info(`[Config][confirmRestore] 选择恢复路径 ${dir.toString()}`);
saveDir = dir;
} else await TGLogger.Info(`[Config][confirmRestore] 恢复到默认路径 ${saveDir}`);
showLoading.start("正在恢复数据...");
await showLoading.start("正在恢复数据");
await restoreUserData(saveDir);
showLoading.end();
await showLoading.end();
showSnackbar.success("数据已恢复!");
await TGLogger.Info("[Config][confirmRestore] 恢复完成");
}
@@ -231,12 +232,13 @@ async function confirmUpdate(title?: string): Promise<void> {
showSnackbar.cancel("已取消更新数据库");
return;
}
showLoading.start("正在更新数据库...");
await showLoading.start("正在更新数据库", "");
await TGSqlite.update();
buildTime.value = getBuildTime();
showLoading.end();
showSnackbar.success("数据库已更新!");
await showLoading.end();
showSnackbar.success("数据库已更新!即将刷新页面");
await TGLogger.Info("[Config][confirmUpdate] 数据库更新完成");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
@@ -333,13 +335,14 @@ async function confirmDelCache(): Promise<void> {
return;
}
let cacheBSize: number = 0;
showLoading.start("正在检测缓存...");
await showLoading.start("正在检测缓存");
for (const dir of CacheDir) {
const size: number = await core.invoke("get_dir_size", { path: dir });
cacheBSize += size;
}
await showLoading.update(`缓存大小:${bytesToSize(cacheBSize)}`);
cacheSize.value = cacheBSize;
showLoading.end();
await showLoading.end();
const delCheck = await showDialog.check(
"确认清除缓存吗?",
`当前缓存大小为 ${bytesToSize(cacheBSize)}`,
@@ -349,15 +352,16 @@ async function confirmDelCache(): Promise<void> {
await TGLogger.Info("[Config][confirmDelCache] 取消清除缓存");
return;
}
showLoading.start("正在清除缓存...");
await showLoading.start("正在清除缓存");
for (const dir of CacheDir) {
showLoading.update("正在清除缓存...", dir);
await showLoading.update(dir);
await remove(dir, { recursive: true });
}
showLoading.end();
await showLoading.end();
await TGLogger.Info("[Config][confirmDelCache] 缓存清除完成");
showSnackbar.success("缓存已清除!即将退出应用!");
setTimeout(async () => await exit(), 1000);
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
await exit();
}
// 恢复默认设置
@@ -372,8 +376,9 @@ async function confirmResetApp(): Promise<void> {
appStore.init();
homeStore.init();
await TGLogger.Info("[Config][confirmResetApp] 恢复默认设置完成");
showSnackbar.success("已恢复默认配置!即将刷新页面...");
setTimeout(() => window.location.reload(), 1500);
showSnackbar.success("已恢复默认配置!即将刷新页面");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
// 前置
@@ -405,12 +410,13 @@ async function confirmResetDB(title?: string): Promise<void> {
await TGLogger.Info("[Config][confirmResetDB] 取消重置数据库");
return;
}
showLoading.start("正在重置数据库...");
await showLoading.start("正在重置数据库");
await TGSqlite.reset();
showLoading.end();
await showLoading.end();
await TGLogger.Info("[Config][confirmResetDB] 数据库重置完成");
showSnackbar.success("数据库已重置!请进行再次检查。");
setTimeout(() => window.location.reload(), 1500);
showSnackbar.success("数据库已重置!即将刷新页面");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
// 开启 dev 模式

View File

@@ -72,7 +72,6 @@ const gameSelectList = TGConstant.BBS.CHANNELS;
const curGid = ref<string>(gameSelectList[0].gid);
onMounted(async () => {
showLoading.start("正在加载首页...");
// @ts-expect-error-next-line The import.meta meta-property is not allowed in files which will build into CommonJS output.
const isProdEnv = import.meta.env.MODE === "production";
if (isProdEnv && devMode.value) devMode.value = false;
@@ -81,14 +80,13 @@ onMounted(async () => {
watch(
() => components.value,
(cur, old) => {
async (cur, old) => {
const newComp = cur.filter((i) => !old.includes(i));
if (newComp.length === 0) showLoading.end();
if (newComp.length === 0) await showLoading.end();
},
);
async function loadComp(): Promise<void> {
showLoading.start("正在加载首页...");
const temp: Array<SFComp> = [];
for (const item of showItems.value) {
switch (item) {
@@ -103,7 +101,7 @@ async function loadComp(): Promise<void> {
break;
}
}
showLoading.update("正在加载首页...", `正在加载:${showItems.value.join("、")}`);
await showLoading.start(`正在加载:${showItems.value.join("、")}`);
components.value = temp;
await TGLogger.Info(`[Home][loadComp] 打开首页,当前显示:${showItems.value.join("、")}`);
}
@@ -136,10 +134,10 @@ async function loadEnd(item: SFComp): Promise<void> {
const compName = getName(item.__name ?? "");
if (!compName) return;
await TGLogger.Info(`[Home][loadEnd] ${compName} 加载完成`);
showLoading.update("正在加载首页...", `${compName} 加载完成`);
await showLoading.update(`${compName} 加载完成`);
if (!loadItems.value.includes(compName)) loadItems.value.push(compName);
else showSnackbar.warn(`${compName} 已加载`);
if (loadItems.value.length === components.value.length) showLoading.end();
if (loadItems.value.length === components.value.length) await showLoading.end();
}
</script>
<style lang="css" scoped>

View File

@@ -156,13 +156,13 @@ function sortPost(value: boolean): void {
}
async function load(): Promise<void> {
showLoading.start("正在加载收藏帖子...", "获取收藏合集");
await showLoading.start("正在加载收藏帖子", "获取收藏合集");
collections.value = await TSUserCollection.getCollectList();
showLoading.update("正在加载收藏帖子...", "获取未分类帖子");
await showLoading.update("获取未分类帖子");
const postUnCollect = await TSUserCollection.getUnCollectPostList();
if (curSelect.value === "未分类" || collections.value.length === 0) {
if (curSelect.value === "未分类" || collections.value.length === 0)
selected.value = postUnCollect;
} else if (collections.value.find((c) => c.title === curSelect.value)) {
else if (collections.value.find((c) => c.title === curSelect.value)) {
selected.value = await TSUserCollection.getCollectPostList(curSelect.value);
} else {
selected.value = postUnCollect;
@@ -172,7 +172,7 @@ async function load(): Promise<void> {
selectedMode.value = false;
selectedPost.value = [];
if (page.value > length.value) page.value = 1;
showLoading.end();
await showLoading.end();
}
function toSelect(): void {
@@ -239,9 +239,9 @@ async function toEdit(): Promise<void> {
showSnackbar.cancel("取消修改分类信息");
return;
}
showLoading.start("正在修改分类信息...");
await showLoading.start("正在修改分类信息");
const check = await TSUserCollection.updateCollect(collect.title, cTc, cTd);
showLoading.end();
await showLoading.end();
if (!check) {
showSnackbar.warn("修改分类信息失败");
return;
@@ -266,18 +266,19 @@ async function deletePost(force: boolean = false): Promise<void> {
showSnackbar.cancel("取消操作");
return;
}
showLoading.start(`正在${title}...`);
await showLoading.start(`正在${title}`);
let success = 0;
for (const post of selectedPost.value) {
await showLoading.update(`正在处理帖子: ${post}`);
const check = await TSUserCollection.deletePostCollect(post, force);
if (check) {
success++;
continue;
}
showSnackbar.warn(`帖子 ${post} 操作失败`);
await new Promise((resolve) => setTimeout(resolve, 1500));
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
}
showLoading.end();
await showLoading.end();
showSnackbar.success(`成功${title} ${success}`);
await load();
}
@@ -316,13 +317,13 @@ async function freshPost(select: string | null): Promise<void> {
curSelect.value = "未分类";
return;
}
showLoading.start("正在获取合集帖子...", `获取合集 ${select}`);
await showLoading.start("正在获取合集帖子", `获取合集 ${select}`);
if (select === "未分类") {
curSelect.value = "未分类";
selected.value = await TSUserCollection.getUnCollectPostList();
} else selected.value = await TSUserCollection.getCollectPostList(select);
page.value = 1;
showLoading.end();
await showLoading.end();
showSnackbar.success(`切换合集 ${select},共 ${selected.value.length} 条帖子`);
}
@@ -350,24 +351,24 @@ async function freshUser(uid?: string): Promise<void> {
return;
}
const uidReal = uid || briefInfo.value.uid;
showLoading.start("获取用户收藏...", `UID: ${uidReal}`);
await showLoading.start(`[${uidReal}]获取用户收藏`);
let res = await BBSApi.lovePost(cookie.value, uidReal);
while (true) {
if ("retcode" in res) {
showLoading.end();
await showLoading.end();
if (res.retcode === 1001) showSnackbar.warn("用户收藏已设为私密,无法获取");
else showSnackbar.error(`[${res.retcode}] ${res.message}`);
break;
}
let posts = res.list;
showLoading.update("获取用户收藏...", `合并收藏帖子 [offset]${res.next_offset}...`);
await mergePosts(posts, uid || briefInfo.value.uid);
if (res.is_last) break;
showLoading.update("获取用户收藏...", `[offset]${res.next_offset} [is_last]${res.is_last}`);
await showLoading.update(`[offset]${res.next_offset} [is_last]${res.is_last}`);
res = await BBSApi.lovePost(cookie.value, uid || briefInfo.value.uid, res.next_offset);
}
showLoading.end();
showSnackbar.success("获取用户收藏成功");
await showLoading.end();
showSnackbar.success("获取用户收藏成功,即将刷新页面");
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
window.location.reload();
}
@@ -378,7 +379,7 @@ async function mergePosts(
): Promise<void> {
const title = `用户收藏-${collect}`;
for (const post of posts) {
showLoading.start("获取用户收藏...", `[POST]${post.post.subject} [collection]${title}`);
await showLoading.update(`[POST]${post.post.subject} [collection]${title}`);
const res = await TSUserCollection.addCollect(post.post.post_id, post, title, true);
if (!res) await TGLogger.Error(`[PostCollect] mergePosts [${post.post.post_id}]`);
}

View File

@@ -78,7 +78,6 @@ import { useRoute } from "vue-router";
import TGLogger from "@/utils/TGLogger.js";
import { createPost } from "@/utils/TGWindow.js";
import { getGameName } from "@/web/utils/tools.js";
type SortSelect = { text: string; value: number };
type SortSelectGame = { gid: number; forum: Array<SortSelect>; text: string };
@@ -158,11 +157,9 @@ const posts = shallowRef<Array<TGApp.Plugins.Mys.Post.FullData>>([]);
onMounted(async () => {
if (gid && typeof gid === "string") curGid.value = Number(gid);
if (forum && typeof forum === "string") curForum.value = Number(forum);
showLoading.start(`正在获取${getGameName(curGid.value)}帖子数据...`);
const gameLabel = getGameLabel(curGid.value);
const forumLabel = getForumLabel(curGid.value, curForum.value);
await TGLogger.Info(`[Posts][${gameLabel}][onMounted][${forumLabel}] 打开帖子列表`);
showLoading.update(`正在获取 ${gameLabel}-${forumLabel} 数据`);
await freshPostData();
curForumLabel.value = forumLabel;
firstLoad.value = true;
@@ -222,19 +219,20 @@ function getSortLabel(value: number): string {
}
async function freshPostData(): Promise<void> {
await showLoading.start(`正在刷新${getGameLabel(curGid.value)}帖子`);
const gameLabel = getGameLabel(curGid.value);
const forumLabel = getForumLabel(curGid.value, curForum.value);
const sortLabel = getSortLabel(curSortType.value);
await TGLogger.Info(
`[Posts][${gameLabel}][freshPostData][${forumLabel}][${sortLabel}] 刷新帖子列表`,
);
showLoading.update(`正在刷新 ${gameLabel}-${forumLabel}-${sortLabel} 数据`);
await showLoading.update(`版块:${forumLabel},排序:${sortLabel}`);
document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
const postsGet = await Mys.Post.getForumPostList(curForum.value, curSortType.value);
posts.value = postsGet.list;
lastId.value = postsGet.last_id;
isLast.value = postsGet.is_last;
showLoading.end();
await showLoading.end();
}
async function loadMore(): Promise<void> {
@@ -242,13 +240,16 @@ async function loadMore(): Promise<void> {
showSnackbar.warn("没有更多帖子了");
return;
}
showLoading.start("正在加载更多帖子数据...");
await showLoading.start("正在加载更多帖子数据", `游戏:${getGameLabel(curGid.value)}`);
const postsGet = await Mys.Post.getForumPostList(curForum.value, curSortType.value, lastId.value);
await showLoading.update(
`版块:${curForumLabel.value},排序:${getSortLabel(curSortType.value)},数量:${postsGet.list.length}`,
);
posts.value = posts.value.concat(postsGet.list);
lastId.value = postsGet.last_id;
isLast.value = postsGet.is_last;
showSnackbar.success(`加载成功,共加载 ${postsGet.list.length} 条帖子`);
showLoading.end();
await showLoading.end();
}
function searchPost(): void {

View File

@@ -101,15 +101,16 @@ async function firstLoad(key: NewsType, refresh: boolean = false): Promise<void>
postData.value[key] = [];
rawData.value[key].lastId = 0;
}
showLoading.start(`正在获取${gameName}${rawData.value[key].name}数据...`);
await showLoading.start(`正在获取${gameName}${rawData.value[key].name}数据`);
document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
const getData = await Mys.Painter.getNewsList(gid, NewsTypeEnum[key]);
await showLoading.update(`数量:${getData.list.length},是否最后一页:${getData.is_last}`);
rawData.value[key].isLast = getData.is_last;
rawData.value[key].lastId = getData.list.length;
postData.value[key] = getData.list;
triggerRef(postData);
triggerRef(rawData);
showLoading.end();
await showLoading.end();
await TGLogger.Info(`[News][${gid}][firstLoad] 获取${rawData.value[key].name}数据成功`);
}
@@ -126,25 +127,26 @@ async function loadMore(key: NewsType): Promise<void> {
loading.value = false;
return;
}
showLoading.start(`正在获取${gameName}${rawData.value[key].name}数据...`);
await showLoading.start(`正在获取${gameName}${rawData.value[key].name}数据`);
const getData = await Mys.Painter.getNewsList(
gid,
NewsTypeEnum[key],
20,
rawData.value[key].lastId,
);
await showLoading.update(`数量:${getData.list.length},是否最后一页:${getData.is_last}`);
rawData.value[key].lastId = rawData.value[key].lastId + getData.list.length;
rawData.value[key].isLast = getData.is_last;
postData.value[key] = postData.value[key].concat(getData.list);
triggerRef(postData);
triggerRef(rawData);
if (rawData.value[key].isLast) {
showLoading.end();
await showLoading.end();
showSnackbar.warn("已经是最后一页了");
loading.value = false;
return;
}
showLoading.end();
await showLoading.end();
loading.value = false;
}

View File

@@ -97,10 +97,10 @@ const sortList = computed<Array<SortSelect>>(() => {
});
onMounted(async () => {
showLoading.start(`正在加载话题${topic}信息`);
await showLoading.start(`正在加载话题${topic}信息`);
const info = await Mys.Post.getTopicFullInfo(gid, topic);
if ("retcode" in info) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${info.retcode}] ${info.message}`);
return;
}
@@ -125,18 +125,19 @@ watch(
);
async function firstLoad(): Promise<void> {
if (curGame.value) showLoading.update(`正在加载${curGame.value.name}帖子列表`);
await showLoading.start(`正在加载话题${topicInfo.value?.topic.name}信息`);
document.documentElement.scrollTo({ top: 0, behavior: "smooth" });
const postList = await Mys.Post.getTopicPostList(curGid.value, topic, curSortType.value);
if ("retcode" in postList) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${postList.retcode}] ${postList.message}`);
return;
}
await showLoading.update(`数量:${postList.posts.length},是否最后一页:${postList.is_last}`);
isLastPage.value = postList.is_last;
lastPostId.value = postList.last_id;
posts.value = postList.posts;
showLoading.end();
await showLoading.end();
showSnackbar.success(`加载了 ${postList.posts.length} 条帖子`);
}
@@ -145,7 +146,7 @@ async function freshPostData(): Promise<void> {
showSnackbar.warn("已经到底了");
return;
}
showLoading.start("正在加载帖子列表");
await showLoading.start(`正在刷新${topicInfo.value?.topic.name}帖子列表`);
const postList = await Mys.Post.getTopicPostList(
curGid.value,
topic,
@@ -153,14 +154,15 @@ async function freshPostData(): Promise<void> {
lastPostId.value,
);
if ("retcode" in postList) {
showLoading.end();
await showLoading.end();
showSnackbar.error(`[${postList.retcode}] ${postList.message}`);
return;
}
await showLoading.update(`数量:${postList.posts.length},是否最后一页:${postList.is_last}`);
isLastPage.value = postList.is_last;
lastPostId.value = postList.last_id;
posts.value = posts.value.concat(postList.posts);
showLoading.end();
await showLoading.end();
showSnackbar.success(`加载了 ${postList.posts.length} 条帖子`);
}

View File

@@ -29,10 +29,12 @@ type InvokeArg = { func: string };
class Client {
private listener: UnlistenFn | undefined;
private route: string[] = [];
private constructor() {
this.route = [];
this.listener = undefined;
}
private static instance: Client | null = null;
static getInstance(): Client {
@@ -690,7 +692,7 @@ class Client {
const appWindow = await webviewWindow.WebviewWindow.getByLabel("TeyvatGuide");
await appWindow?.setFocus();
showSnackbar.error(`不支持的操作OpenApplication(${JSON.stringify(arg.payload)})`);
await new Promise<void>((resolve) => setTimeout(() => resolve(), 1500));
await new Promise<void>((resolve) => setTimeout(resolve, 1500));
const windowFind = await webviewWindow.WebviewWindow.getByLabel("mhy_client");
if (windowFind !== null) await windowFind.setFocus();
}
@@ -727,11 +729,7 @@ class Client {
await appWindow.setFocus();
}
showSnackbar.error(`未知链接:${arg.payload.page}`, 3000);
await new Promise<void>((resolve) => {
setTimeout(() => {
resolve();
}, 3000);
});
await new Promise<void>((resolve) => setTimeout(resolve, 3000));
const windowFind = await webviewWindow.WebviewWindow.getByLabel("mhy_client");
if (windowFind !== null) {
await windowFind.setFocus();
@@ -894,10 +892,8 @@ class Client {
}
}
console.warn("[share]", arg.payload);
// 延时 3s
setTimeout(async () => {
await this.callback(arg.callback, {});
}, 10000);
await new Promise<void>((resolve) => setTimeout(resolve, 3000));
await this.callback(arg.callback, {});
}
}

View File

@@ -1,7 +1,7 @@
/**
* @file utils/dataBS.ts
* @description 用户数据的备份、恢复、迁移
* @since Beta v0.6.3
* @since Beta v0.6.7
*/
import showLoading from "@comp/func/loading.js";
import showSnackbar from "@comp/func/snackbar.js";
@@ -16,7 +16,7 @@ import TGLogger from "./TGLogger.js";
/**
* @description 备份用户数据
* @since Beta v0.6.3
* @since Beta v0.6.7
* @param {string} dir 备份目录路径
* @returns {Promise<void>}
*/
@@ -25,16 +25,21 @@ export async function backUpUserData(dir: string): Promise<void> {
await TGLogger.Warn("备份数据不存在,即将创建");
await mkdir(dir, { recursive: true });
}
await showLoading.update("正在备份UIAF成就数据");
await TSUserAchi.backupUiaf(dir);
await showLoading.update("正在备份用户账户数据");
await TSUserAccount.account.backup(dir);
await showLoading.update("正在备份深渊数据");
await TSUserAbyss.backupAbyss(dir);
await showLoading.update("正在备份真境剧诗数据");
await TSUserCombat.backupCombat(dir);
await showLoading.update("正在备份UIGF祈愿数据");
await TSUserGacha.backUpUigf(dir);
}
/**
* @description 恢复用户数据
* @since Beta v0.6.3
* @since Beta v0.6.7
* @param {string} dir 备份目录路径
* @returns {Promise<void>}
*/
@@ -44,31 +49,31 @@ export async function restoreUserData(dir: string): Promise<void> {
showSnackbar.error("备份目录不存在");
return;
}
showLoading.update("正在恢复数据...", "正在恢复成就数据");
await showLoading.update("正在恢复成就数据");
const restoreAchi = await TSUserAchi.restoreUiaf(dir);
if (!restoreAchi) {
showSnackbar.error("成就数据恢复失败");
errNum++;
}
showLoading.update("正在恢复数据...", "正在恢复账号数据");
await showLoading.update("正在恢复账号数据");
const restoreAccount = await TSUserAccount.account.restore(dir);
if (!restoreAccount) {
showSnackbar.error("Cookie 数据恢复失败");
errNum++;
}
showLoading.update("正在恢复数据...", "正在恢复深渊数据");
await showLoading.update("正在恢复深渊数据");
const restoreAbyss = await TSUserAbyss.restoreAbyss(dir);
if (!restoreAbyss) {
showSnackbar.error("深渊数据恢复失败");
errNum++;
}
showLoading.update("正在恢复数据...", "正在恢复真境剧诗数据");
await showLoading.update("正在恢复真境剧诗数据");
const restoreCombat = await TSUserCombat.restoreCombat(dir);
if (!restoreCombat) {
showSnackbar.error("真境剧诗数据恢复失败");
errNum++;
}
showLoading.update("正在恢复数据...", "正在恢复祈愿数据");
await showLoading.update("正在恢复祈愿数据");
const restoreGacha = await TSUserGacha.restoreUigf(dir);
if (!restoreGacha) {
showSnackbar.error("祈愿数据恢复失败");

View File

@@ -25,12 +25,12 @@ const jsonList = shallowRef<TGApp.BBS.Announcement.AnnoSingle>();
const jsonContent = shallowRef<TGApp.BBS.Announcement.ContentItem>();
onMounted(async () => {
showLoading.start("正在获取公告数据...");
await showLoading.start("正在获取公告数据");
if (!annoId) {
showLoading.empty("未找到数据");
await showLoading.empty("未找到数据");
return;
}
showLoading.update("正在获取数据...", `公告ID: ${annoId}`);
await showLoading.update(`公告ID: ${annoId}`);
const listData = await Hk4eApi.anno.list(region, lang);
for (const listItem of listData.list) {
for (const single of listItem.list) {
@@ -41,7 +41,7 @@ onMounted(async () => {
}
}
jsonContent.value = await Hk4eApi.anno.content(annoId, region, lang);
showLoading.end();
await showLoading.end();
});
</script>
<style lang="css" scoped>

View File

@@ -34,17 +34,17 @@ const appVersion = ref<string>();
const annoData = shallowRef<TGApp.BBS.Announcement.ContentItem>();
onMounted(async () => {
showLoading.start("正在加载公告数据...");
await showLoading.start("正在加载公告数据");
appVersion.value = await app.getVersion();
if (!annoId || !region) {
showLoading.empty("未找到数据", "公告不存在或解析失败");
await showLoading.empty("未找到数据", "未解析到公告ID或服务器");
await TGLogger.Error("[t-anno.vue] 未找到数据");
return;
}
showLoading.update("正在获取数据...", `公告ID:${annoId}`);
await showLoading.update("正在获取数据");
try {
annoData.value = await Hk4eApi.anno.content(annoId, region, lang);
showLoading.update("正在渲染数据...", `公告ID${annoId}`);
await showLoading.update("正在渲染数据");
await webviewWindow
.getCurrentWebviewWindow()
.setTitle(`Anno_${annoId} ${annoData.value.title}`);
@@ -52,14 +52,13 @@ onMounted(async () => {
if (error instanceof Error)
await TGLogger.Error(`[t-anno.vue][${annoId}] ${error.name}${error.message}`);
else console.error(error);
showLoading.empty("未找到数据", "公告不存在或解析失败");
await showLoading.empty("未找到数据", "公告不存在或解析失败");
await webviewWindow.getCurrentWebviewWindow().setTitle(`Anno_${annoId} Parsing Error`);
return;
}
// 打开 json
const isDev = useAppStore().devMode ?? false;
if (isDev) await createAnnoJson(annoId, region, lang);
showLoading.end();
await showLoading.end();
});
function parseText(title: string): string {

View File

@@ -24,18 +24,19 @@ const jsonData = shallowRef<TGApp.Plugins.Mys.Post.FullData>();
const parseData = shallowRef<Array<TGApp.Plugins.Mys.SctPost.Base>>();
onMounted(async () => {
showLoading.start(`正在获取帖子数据...`);
await showLoading.start(`正在获取帖子数据`);
if (!postId) {
showLoading.empty("错误的帖子ID");
await showLoading.empty("未获取到PostID");
return;
}
const resp = await Mys.Post.getPostFull(postId);
if ("retcode" in resp) {
showLoading.empty("获取数据失败", `[${resp.retcode}]${resp.message}`);
await showLoading.empty("获取数据失败", `[${resp.retcode}]${resp.message}`);
showSnackbar.error(`[${resp.retcode}]${resp.message}`);
await TGLogger.Error(`[${postId}]获取帖子数据失败:${resp.retcode} ${resp.message}`);
return;
}
await showLoading.update("正在渲染帖子数据");
jsonData.value = resp;
try {
parseData.value = JSON.parse(jsonData.value.post.content);
@@ -48,7 +49,7 @@ onMounted(async () => {
}
console.warn(`[${postId}]解析帖子数据失败:${err}`);
}
showLoading.end();
await showLoading.end();
});
</script>
<style lang="css" scoped>

View File

@@ -122,34 +122,33 @@ function getGameIcon(gameId: number): string {
}
onMounted(async () => {
await showLoading.start(`正在加载帖子数据`);
appVersion.value = await app.getVersion();
showLoading.start(`正在加载帖子数据...`);
// 检查数据
if (!postId) {
showLoading.empty("未找到数据", "PostID 不存在");
await showLoading.empty("PostID 不存在");
await webviewWindow.getCurrentWebviewWindow().setTitle("未找到数据");
await TGLogger.Error("[t-post][onMounted] PostID 不存在");
return;
}
showLoading.update("正在获取数据...", `帖子ID: ${postId}`);
await showLoading.update(`帖子ID: ${postId}`);
const resp = await Mys.Post.getPostFull(postId);
if ("retcode" in resp) {
showLoading.empty(`[code]${resp.retcode}`, resp.message);
await showLoading.empty("数据加载失败", `[${resp.retcode}]${resp.message}`);
showSnackbar.error(`[${resp.retcode}] ${resp.message}`);
await webviewWindow.getCurrentWebviewWindow().setTitle(`Post_${postId} ${resp.message}`);
await TGLogger.Error(`[t-post][${postId}][onMounted] ${resp.retcode}: ${resp.message}`);
return;
}
postData.value = resp;
showLoading.update("正在渲染数据...", `帖子ID: ${postId}`);
await showLoading.update("正在渲染数据");
renderPost.value = getRenderPost(postData.value);
await webviewWindow
.getCurrentWebviewWindow()
.setTitle(`Post_${postId} ${postData.value.post.subject}`);
await TGLogger.Info(`[t-post][${postId}][onMounted] ${postData.value.post.subject}`);
// 打开 json
const isDev = useAppStore().devMode ?? false;
if (isDev) {
await showLoading.update("正在打开调试窗口");
await TGLogger.Info(`[t-post][${postId}][onMounted] 打开 JSON 窗口`);
await createPostJson(postId);
}
@@ -158,7 +157,7 @@ onMounted(async () => {
shareTimer = null;
}
shareTimer = setInterval(getShareTimer, 1000);
showLoading.end();
await showLoading.end();
});
function getShareTimer(): void {