mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-04-22 21:59:49 +08:00
♻️ 请求重构
This commit is contained in:
@@ -122,7 +122,6 @@ import showGeetest from "@comp/func/geetest.js";
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import ToGameLogin from "@comp/pageConfig/tco-gameLogin.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import TSUserAccount from "@Sqlite/modules/userAccount.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, ref, shallowRef } from "vue";
|
||||
@@ -132,6 +131,7 @@ import { useUserStore } from "@/store/modules/user.js";
|
||||
import TGLogger from "@/utils/TGLogger.js";
|
||||
import BBSApi from "@/web/request/bbsReq.js";
|
||||
import PassportApi from "@/web/request/passportReq.js";
|
||||
import passportReq from "@/web/request/passportReq.js";
|
||||
import TakumiApi from "@/web/request/takumiReq.js";
|
||||
|
||||
const { isLogin } = storeToRefs(useAppStore());
|
||||
@@ -398,13 +398,13 @@ async function confirmCopyCookie(): Promise<void> {
|
||||
}
|
||||
|
||||
async function tryGetCaptcha(phone: string, aigis?: string): Promise<string | false> {
|
||||
const captchaResp = await Mys.User.getCaptcha(phone, aigis);
|
||||
const captchaResp = await passportReq.captcha.create(phone, aigis);
|
||||
if ("retcode" in captchaResp) {
|
||||
if (!captchaResp.data || captchaResp.data === "") {
|
||||
showSnackbar.error(`[${captchaResp.retcode}] ${captchaResp.message}`);
|
||||
return false;
|
||||
}
|
||||
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
|
||||
const aigisResp: TGApp.BBS.CaptchaLogin.CaptchaAigis = JSON.parse(captchaResp.data);
|
||||
const resp = await showGeetest(JSON.parse(aigisResp.data));
|
||||
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
|
||||
return await tryGetCaptcha(phone, aigisStr);
|
||||
@@ -417,14 +417,14 @@ async function tryLoginByCaptcha(
|
||||
captcha: string,
|
||||
actionType: string,
|
||||
aigis?: string,
|
||||
): Promise<TGApp.Plugins.Mys.CaptchaLogin.LoginData | false> {
|
||||
const loginResp = await Mys.User.login(phone, captcha, actionType, aigis);
|
||||
): Promise<TGApp.BBS.CaptchaLogin.LoginRes | false> {
|
||||
const loginResp = await passportReq.captcha.login(phone, captcha, actionType, aigis);
|
||||
if ("retcode" in loginResp) {
|
||||
if (!loginResp.data || loginResp.data === "") {
|
||||
showSnackbar.error(`[${loginResp.retcode}] ${loginResp.message}`);
|
||||
return false;
|
||||
}
|
||||
const aigisResp: TGApp.Plugins.Mys.CaptchaLogin.CaptchaAigis = JSON.parse(loginResp.data);
|
||||
const aigisResp: TGApp.BBS.CaptchaLogin.CaptchaAigis = JSON.parse(loginResp.data);
|
||||
const resp = await showGeetest(JSON.parse(aigisResp.data));
|
||||
const aigisStr = `${aigisResp.session_id};${btoa(JSON.stringify(resp))}`;
|
||||
return await tryLoginByCaptcha(phone, captcha, actionType, aigisStr);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<span>{{ showNew ? "查看当前祈愿" : "查看后续祈愿" }}</span>
|
||||
</template>
|
||||
<template #default>
|
||||
<!-- todo 组件化 -->
|
||||
<div class="pool-grid">
|
||||
<div v-for="pool in poolSelect" :key="pool.postId" class="pool-card">
|
||||
<div class="pool-cover" @click="createPost(pool.postId, pool.title)">
|
||||
@@ -58,20 +59,41 @@
|
||||
import TItembox, { type TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, onMounted, onUnmounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import THomeCard from "./ph-comp-card.vue";
|
||||
|
||||
import { AppCharacterData } from "@/data/index.js";
|
||||
import { useHomeStore } from "@/store/modules/home.js";
|
||||
import { createPost, createTGWindow } from "@/utils/TGWindow.js";
|
||||
import { stamp2LastTime } from "@/utils/toolFunc.js";
|
||||
import postReq from "@/web/request/postReq.js";
|
||||
import takumiReq from "@/web/request/takumiReq.js";
|
||||
|
||||
type TPoolEmits = (e: "success") => void;
|
||||
type PoolStat = "future" | "now" | "past"; // 未开始 | 进行中 | 已结束
|
||||
type PoolItem = TGApp.Plugins.Mys.Gacha.RenderCard & { timeRest: number; stat: PoolStat };
|
||||
type AvatarRender = {
|
||||
icon: string;
|
||||
url: string;
|
||||
info?: TGApp.App.Character.WikiBriefInfo;
|
||||
};
|
||||
type PoolCard = {
|
||||
id: number;
|
||||
title: string;
|
||||
cover: string;
|
||||
postId: number;
|
||||
characters: Array<AvatarRender>;
|
||||
time: {
|
||||
str: string;
|
||||
startStamp: number;
|
||||
endStamp: number;
|
||||
totalStamp: number;
|
||||
};
|
||||
timeRest: number;
|
||||
stat: PoolStat;
|
||||
};
|
||||
|
||||
const emits = defineEmits<TPoolEmits>();
|
||||
const { poolCover } = storeToRefs(useHomeStore());
|
||||
@@ -80,43 +102,91 @@ const router = useRouter();
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
|
||||
const showNew = ref<boolean>(false);
|
||||
const poolCards = ref<Array<PoolItem>>([]);
|
||||
const poolCards = ref<Array<PoolCard>>([]);
|
||||
const hasNew = computed<boolean>(
|
||||
() => poolCards.value.find((pool) => pool.stat === "future") !== undefined,
|
||||
);
|
||||
const poolSelect = computed<Array<PoolItem>>(() => {
|
||||
const poolSelect = computed<Array<PoolCard>>(() => {
|
||||
if (!hasNew.value) return poolCards.value;
|
||||
if (showNew.value) return poolCards.value.filter((pool) => pool.stat === "future");
|
||||
return poolCards.value.filter((pool) => pool.stat !== "future");
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const gachaData = await Mys.Gacha.get();
|
||||
let cards: Array<TGApp.Plugins.Mys.Gacha.RenderCard>;
|
||||
if (!checkCover(gachaData)) {
|
||||
cards = await Mys.Gacha.card(gachaData);
|
||||
const coverData: Record<string, string> = {};
|
||||
poolCards.value.map((pool) => {
|
||||
coverData[pool.id] = pool.cover;
|
||||
return pool;
|
||||
});
|
||||
poolCover.value = coverData;
|
||||
const gachaData = await takumiReq.obc.gacha();
|
||||
if (checkCover(gachaData)) {
|
||||
poolCards.value = await getGachaCard(gachaData, poolCover.value);
|
||||
} else {
|
||||
cards = await Mys.Gacha.card(gachaData, poolCover.value);
|
||||
}
|
||||
for (const pool of cards) {
|
||||
const timeRest = pool.time.endStamp - Date.now();
|
||||
poolCards.value.push({
|
||||
...pool,
|
||||
stat: timeRest > pool.time.totalStamp ? "future" : timeRest > 0 ? "now" : "past",
|
||||
timeRest: timeRest,
|
||||
});
|
||||
poolCards.value = await getGachaCard(gachaData);
|
||||
const coverData: Record<string, string> = {};
|
||||
for (const pool of poolCards.value) coverData[pool.id] = pool.cover;
|
||||
poolCover.value = coverData;
|
||||
}
|
||||
if (timer !== null) clearInterval(timer);
|
||||
timer = setInterval(poolTimeout, 1000);
|
||||
emits("success");
|
||||
});
|
||||
|
||||
async function getGachaItemCard(
|
||||
data: TGApp.BBS.Obc.GachaItem,
|
||||
poolCover?: string,
|
||||
): Promise<PoolCard | null> {
|
||||
let cover = "/source/UI/empty.webp";
|
||||
const postId: number | undefined = Number(data.activity_url.split("/").pop()) || undefined;
|
||||
if (postId === undefined || isNaN(postId)) return null;
|
||||
if (poolCover !== undefined) {
|
||||
cover = poolCover;
|
||||
} else {
|
||||
const postResp = await postReq.post(postId);
|
||||
if ("retcode" in postResp) {
|
||||
showSnackbar.error(`[${postResp.retcode}] ${postResp.message}`);
|
||||
return null;
|
||||
}
|
||||
cover = postResp.cover?.url ?? postResp.post.images[0];
|
||||
}
|
||||
const timeStr = `${data.start_time} ~ ${data.end_time}`;
|
||||
const characters: Array<AvatarRender> = [];
|
||||
for (const character of data.pool) {
|
||||
const item: AvatarRender = { icon: character.icon, url: character.url };
|
||||
const contentId = character.url.match(/(?<=content\/)\d+/)?.[0];
|
||||
if (contentId) {
|
||||
const itemF = AppCharacterData.find((item) => item.contentId.toString() === contentId);
|
||||
if (itemF) item.info = itemF;
|
||||
}
|
||||
characters.push(item);
|
||||
}
|
||||
const endTs = new Date(data.end_time).getTime();
|
||||
const totalTs = endTs - new Date(data.start_time).getTime();
|
||||
const restTs = endTs - Date.now();
|
||||
return {
|
||||
id: data.id,
|
||||
title: data.title,
|
||||
cover,
|
||||
postId,
|
||||
characters,
|
||||
time: {
|
||||
str: timeStr,
|
||||
startStamp: new Date(data.start_time).getTime(),
|
||||
endStamp: endTs,
|
||||
totalStamp: totalTs,
|
||||
},
|
||||
timeRest: restTs,
|
||||
stat: restTs > totalTs ? "future" : restTs > 0 ? "now" : "past",
|
||||
};
|
||||
}
|
||||
|
||||
async function getGachaCard(
|
||||
gachaData: Array<TGApp.BBS.Obc.GachaItem>,
|
||||
poolCover?: Record<number, string>,
|
||||
): Promise<Array<PoolCard>> {
|
||||
const gachaCard: Array<PoolCard> = [];
|
||||
for (const data of gachaData) {
|
||||
const item = await getGachaItemCard(data, poolCover?.[Number(data.id)]);
|
||||
if (item !== null) gachaCard.push(item);
|
||||
}
|
||||
return gachaCard;
|
||||
}
|
||||
|
||||
function poolTimeout(): void {
|
||||
for (const pool of poolCards.value) {
|
||||
if (pool.stat === "past") {
|
||||
@@ -139,7 +209,7 @@ function poolTimeout(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function checkCover(data: Array<TGApp.Plugins.Mys.Gacha.Data>): boolean {
|
||||
function checkCover(data: Array<TGApp.BBS.Obc.GachaItem>): boolean {
|
||||
if (poolCover.value === undefined || Object.keys(poolCover.value).length === 0) return false;
|
||||
let checkList = data.length;
|
||||
Object.entries(poolCover.value).forEach(([key, value]: [string, unknown]) => {
|
||||
@@ -149,10 +219,7 @@ function checkCover(data: Array<TGApp.Plugins.Mys.Gacha.Data>): boolean {
|
||||
return checkList === 0;
|
||||
}
|
||||
|
||||
async function toOuter(
|
||||
character: TGApp.Plugins.Mys.Gacha.RenderItem,
|
||||
title: string,
|
||||
): Promise<void> {
|
||||
async function toOuter(character: AvatarRender, title: string): Promise<void> {
|
||||
if (character.info !== undefined) {
|
||||
await router.push({ name: "角色图鉴", params: { id: character.info.id } });
|
||||
return;
|
||||
|
||||
@@ -10,47 +10,64 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import PhPositionCard from "@comp/pageHome/ph-position-card.vue";
|
||||
import Mys from "@Mys/index.js";
|
||||
import { onMounted, onUnmounted, ref } from "vue";
|
||||
|
||||
import THomeCard from "./ph-comp-card.vue";
|
||||
|
||||
import takumiReq from "@/web/request/takumiReq.js";
|
||||
|
||||
type TPositionEmits = (e: "success") => void;
|
||||
type PositionStat = "past" | "now" | "future" | "unknown"; // 已结束 | 进行中 | 未开始 | 未知
|
||||
export type PositionItem = TGApp.Plugins.Mys.Position.RenderCard & {
|
||||
export type PositionCard = {
|
||||
title: string;
|
||||
postId: number;
|
||||
link: string;
|
||||
icon: string;
|
||||
abstract: string;
|
||||
time: { startStamp: number; endStamp: number; totalStamp: number };
|
||||
timeRest: number;
|
||||
stat: PositionStat;
|
||||
};
|
||||
const emits = defineEmits<TPositionEmits>();
|
||||
// eslint-disable-next-line no-undef
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
const positionCards = ref<Array<PositionItem>>([]);
|
||||
const positionCards = ref<Array<PositionCard>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
const positionData = await Mys.Position.get();
|
||||
console.log(positionData);
|
||||
const cards = Mys.Position.card(positionData);
|
||||
for (const position of cards) {
|
||||
if (position.time.endStamp === 0 || position.time.totalStamp < 0) {
|
||||
positionCards.value.push({
|
||||
...position,
|
||||
timeRest: 0,
|
||||
stat: "unknown",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
const timeRest = position.time.endStamp - Date.now();
|
||||
positionCards.value.push({
|
||||
...position,
|
||||
timeRest,
|
||||
stat: timeRest > position.time.totalStamp ? "future" : timeRest > 0 ? "now" : "past",
|
||||
});
|
||||
}
|
||||
const resp = await takumiReq.obc.position();
|
||||
console.log("positionCards", resp);
|
||||
positionCards.value = getPositionCard(resp);
|
||||
if (timer !== null) clearInterval(timer);
|
||||
timer = setInterval(getPositionTimer, 1000);
|
||||
emits("success");
|
||||
});
|
||||
|
||||
function getPositionCard(list: Array<TGApp.BBS.Obc.PositionItem>): Array<PositionCard> {
|
||||
const res: Array<PositionCard> = [];
|
||||
for (const position of list) {
|
||||
let link = position.url;
|
||||
if (position.url === "" && position.content_id !== 0) {
|
||||
link = `https://bbs.mihoyo.com/ys/obc/content/${position.content_id}/detail?bbs_presentation_style=no_header`;
|
||||
}
|
||||
const startTs = new Date(position.create_time).getTime();
|
||||
const endTs = Number(position.end_time);
|
||||
const totalTs = endTs - startTs;
|
||||
const restTs = endTs === 0 || totalTs < 0 ? 0 : endTs - Date.now();
|
||||
const card: PositionCard = {
|
||||
title: position.title,
|
||||
postId: position.url !== "" ? Number(position.url.split("/").pop()) : position.content_id,
|
||||
link: link,
|
||||
icon: position.icon,
|
||||
abstract: position.abstract,
|
||||
time: { startStamp: startTs, endStamp: endTs, totalStamp: totalTs },
|
||||
timeRest: restTs,
|
||||
stat: restTs === 0 ? "unknown" : restTs > totalTs ? "future" : restTs > 0 ? "now" : "past",
|
||||
};
|
||||
res.push(card);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function getPositionTimer(): void {
|
||||
for (const position of positionCards.value) {
|
||||
if (position.stat === "unknown") continue;
|
||||
|
||||
@@ -40,16 +40,16 @@
|
||||
<script lang="ts" setup>
|
||||
import TMiImg from "@comp/app/t-mi-img.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import type { PositionItem } from "@comp/pageHome/ph-comp-position.vue";
|
||||
import type { PositionCard } from "@comp/pageHome/ph-comp-position.vue";
|
||||
|
||||
import { parseLink } from "@/utils/linkParser.js";
|
||||
import { createPost } from "@/utils/TGWindow.js";
|
||||
import { stamp2LastTime, timestampToDate } from "@/utils/toolFunc.js";
|
||||
|
||||
type PhPositionCardProps = { position: PositionItem };
|
||||
type PhPositionCardProps = { position: PositionCard };
|
||||
const props = defineProps<PhPositionCardProps>();
|
||||
|
||||
async function openPosition(card: TGApp.Plugins.Mys.Position.RenderCard): Promise<void> {
|
||||
async function openPosition(card: PositionCard): Promise<void> {
|
||||
const res = await parseLink(card.link);
|
||||
if (res === "post") {
|
||||
await createPost(card.postId, card.title);
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import { getEmojis } from "@Mys/request/getEmojis.js";
|
||||
import { onMounted, ref, shallowRef, StyleValue, toRaw } from "vue";
|
||||
|
||||
import { parseLink, parsePost } from "@/utils/linkParser.js";
|
||||
import { isColorSimilar, decodeRegExp } from "@/utils/toolFunc.js";
|
||||
import bbsReq from "@/web/request/bbsReq.js";
|
||||
|
||||
export type TpText = {
|
||||
insert: string;
|
||||
@@ -114,7 +114,7 @@ async function toLink(): Promise<void> {
|
||||
function getEmojiUrl(): string {
|
||||
if (localEmojis.value === null || !JSON.parse(localEmojis.value)[getEmojiName()]) {
|
||||
console.warn("tpEmoji unknown", getEmojiName());
|
||||
getEmojis().then((res) => {
|
||||
bbsReq.emojis().then((res) => {
|
||||
if ("retcode" in res) {
|
||||
console.error(res);
|
||||
showSnackbar.error("获取表情包失败!");
|
||||
|
||||
Reference in New Issue
Block a user