mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2025-12-18 10:18:14 +08:00
♻️ loading组件重构
This commit is contained in:
@@ -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;
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} 个日志文件!`);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user