mirror of
https://github.com/BTMuli/TeyvatGuide.git
synced 2026-05-24 05:55:46 +08:00
✨ 限时祈愿增加用户源,与限时活动共享数据
This commit is contained in:
@@ -1,25 +1,57 @@
|
||||
<!-- 首页限时祈愿组件 -->
|
||||
<template>
|
||||
<THomeCard :append="false" title="限时祈愿">
|
||||
<THomeCard :append="isLogin" title="限时祈愿">
|
||||
<template #title>
|
||||
<span>限时祈愿</span>
|
||||
<v-icon class="tp-refresh" size="small" title="刷新" @click.stop="handleRefresh()">
|
||||
mdi-refresh
|
||||
</v-icon>
|
||||
</template>
|
||||
<template v-if="isLogin" #title-append>
|
||||
<v-switch v-model="isUserPool" class="tp-switch"></v-switch>
|
||||
<span>{{ isUserPool ? "用户" : "百科" }}</span>
|
||||
</template>
|
||||
<template #default>
|
||||
<div v-if="pools.length < 3" class="pool-grid">
|
||||
<PhPoolCard v-for="(pool, idx) in pools" :key="idx" :pool="pool" />
|
||||
<div v-show="!isUserPool">
|
||||
<div v-if="obcPools.length < 3" class="pool-grid">
|
||||
<PhPoolCard v-for="(pool, idx) in obcPools" :key="idx" :pool="pool" />
|
||||
</div>
|
||||
<Swiper
|
||||
v-else
|
||||
:autoplay="{ delay: 3000, disableOnInteraction: false }"
|
||||
:centered-slides="true"
|
||||
:loop="true"
|
||||
:modules="swiperModules"
|
||||
:navigation="true"
|
||||
:slides-per-view="2"
|
||||
:space-between="12"
|
||||
class="pool-swiper"
|
||||
>
|
||||
<SwiperSlide v-for="(pool, idx) in obcPools" :key="idx">
|
||||
<PhPoolCard :pool="pool" />
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</div>
|
||||
<div v-show="isUserPool">
|
||||
<div v-if="userPools.length < 3" class="pool-grid">
|
||||
<PhPoolUser v-for="(pool, idx) in userPools" :key="idx" :pool="pool" />
|
||||
</div>
|
||||
<Swiper
|
||||
v-else
|
||||
:autoplay="{ delay: 3000, disableOnInteraction: false }"
|
||||
:centered-slides="true"
|
||||
:loop="true"
|
||||
:modules="swiperModules"
|
||||
:navigation="true"
|
||||
:slides-per-view="2"
|
||||
:space-between="12"
|
||||
class="pool-swiper"
|
||||
>
|
||||
<SwiperSlide v-for="(pool, idx) in userPools" :key="idx">
|
||||
<PhPoolUser :pool="pool" />
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</div>
|
||||
<Swiper
|
||||
v-else
|
||||
:autoplay="{ delay: 3000, disableOnInteraction: false }"
|
||||
:centered-slides="true"
|
||||
:loop="true"
|
||||
:modules="swiperModules"
|
||||
:navigation="true"
|
||||
:slides-per-view="2"
|
||||
:space-between="12"
|
||||
class="pool-swiper"
|
||||
>
|
||||
<SwiperSlide v-for="(pool, idx) in pools" :key="idx">
|
||||
<PhPoolCard :pool="pool" />
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</template>
|
||||
</THomeCard>
|
||||
</template>
|
||||
@@ -28,48 +60,245 @@ import "swiper/css";
|
||||
import "swiper/css/pagination";
|
||||
import "swiper/css/navigation";
|
||||
|
||||
import showLoading from "@comp/func/loading.js";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import PhPoolCard from "@comp/pageHome/ph-pool-card.vue";
|
||||
import PhPoolUser from "@comp/pageHome/ph-pool-user.vue";
|
||||
import miscReq from "@req/miscReq.js";
|
||||
import recordReq from "@req/recordReq.js";
|
||||
import useAppStore from "@store/app.js";
|
||||
import useHomeStore from "@store/home.js";
|
||||
import useUserStore from "@store/user.js";
|
||||
import takumiReq from "@req/takumiReq.js";
|
||||
import TGHttps from "@utils/TGHttps.js";
|
||||
import TGLogger from "@utils/TGLogger.js";
|
||||
import { A11y, Autoplay } from "swiper/modules";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import { onMounted, shallowRef } from "vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { onMounted, ref, shallowRef, watch } from "vue";
|
||||
|
||||
import THomeCard from "./ph-comp-card.vue";
|
||||
|
||||
import gameEnum from "@enum/game.js";
|
||||
|
||||
type TPoolEmits = (e: "success") => void;
|
||||
|
||||
const { isLogin } = storeToRefs(useAppStore());
|
||||
const { cookie, account } = storeToRefs(useUserStore());
|
||||
const homeStore = useHomeStore();
|
||||
|
||||
const emits = defineEmits<TPoolEmits>();
|
||||
const pools = shallowRef<Array<TGApp.BBS.Obc.GachaItem>>([]);
|
||||
|
||||
const isInit = ref<boolean>(false);
|
||||
const isRefreshing = ref<boolean>(false);
|
||||
const isUserPool = ref<boolean>(isLogin.value);
|
||||
const obcPools = shallowRef<Array<TGApp.BBS.Obc.GachaItem>>([]);
|
||||
const userPools = shallowRef<Array<TGApp.Game.ActCalendar.ActPool>>([]);
|
||||
const swiperModules = [Autoplay, A11y];
|
||||
|
||||
watch(
|
||||
() => isUserPool.value,
|
||||
async () => {
|
||||
if (isUserPool.value) await loadUserPool();
|
||||
else await loadObcPool();
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => account.value.gameUid,
|
||||
async () => {
|
||||
if (isUserPool.value) {
|
||||
userPools.value = [];
|
||||
homeStore.actCalendarData = undefined;
|
||||
await loadUserPool(true);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
if (isLogin.value) await loadUserPool();
|
||||
else await loadObcPool();
|
||||
emits("success");
|
||||
isInit.value = true;
|
||||
});
|
||||
|
||||
async function handleRefresh(): Promise<void> {
|
||||
isRefreshing.value = true;
|
||||
if (isUserPool.value) {
|
||||
userPools.value = [];
|
||||
homeStore.actCalendarData = undefined;
|
||||
await loadUserPool(true);
|
||||
} else {
|
||||
obcPools.value = [];
|
||||
await loadObcPool();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUserPool(forceReload: boolean = false): Promise<void> {
|
||||
if (userPools.value.length > 0 && !forceReload) return;
|
||||
if (!cookie.value) {
|
||||
showSnackbar.warn("获取限时祈愿失败:未登录");
|
||||
isLogin.value = false;
|
||||
if (isInit.value) await showLoading.end();
|
||||
return;
|
||||
}
|
||||
if (isInit.value) await showLoading.start("正在获取限时祈愿");
|
||||
let data: TGApp.Game.ActCalendar.ActRes | undefined;
|
||||
try {
|
||||
if (homeStore.actCalendarData && !forceReload) {
|
||||
data = homeStore.actCalendarData;
|
||||
} else {
|
||||
const resp = await recordReq.actCalendar(cookie.value, account.value);
|
||||
if (<number>resp.retcode === 1034) {
|
||||
await TGLogger.Warn("[PhCompPool][loadUserPool] 触发1034验证");
|
||||
if (!isInit.value || !isRefreshing.value) {
|
||||
if (isInit.value) await showLoading.end();
|
||||
isUserPool.value = false;
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await loadObcPool();
|
||||
return;
|
||||
}
|
||||
const challenge = await miscReq.challenge({
|
||||
account_id: cookie.value.account_id,
|
||||
cookie_token: cookie.value.cookie_token,
|
||||
});
|
||||
if (challenge === false) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.error("极验验证失败,已切换至百科模式");
|
||||
await showLoading.end();
|
||||
}
|
||||
isUserPool.value = false;
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await loadObcPool();
|
||||
return;
|
||||
}
|
||||
const resp2 = await recordReq.actCalendar(cookie.value, account.value, challenge);
|
||||
if (resp2.retcode !== 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn(`[${resp2.retcode}] ${resp2.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Warn(`[PhCompPool][loadUserPool] ${resp2.retcode}-${resp2.message}`);
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
data = resp2.data;
|
||||
} else if (resp.retcode !== 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Warn(`[PhCompPool][loadUserPool] ${resp.retcode}-${resp.message}`);
|
||||
emits("success");
|
||||
return;
|
||||
} else {
|
||||
data = resp.data;
|
||||
}
|
||||
homeStore.actCalendarData = data;
|
||||
}
|
||||
} catch (e) {
|
||||
const errMsg = TGHttps.getErrMsg(e);
|
||||
if (isInit.value) {
|
||||
showSnackbar.error(`获取限时祈愿失败:${errMsg}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Error("[PhCompPool][loadUserPool] 获取限时祈愿异常");
|
||||
await TGLogger.Error(`[PhCompPool][loadUserPool] ${e}`);
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
const pools = filterPools([
|
||||
...data.avatar_card_pool_list,
|
||||
...data.weapon_card_pool_list,
|
||||
...data.mixed_card_pool_list,
|
||||
]);
|
||||
if (pools.length === 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn("用户模式暂无卡池数据,已切换至百科模式");
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
isUserPool.value = false;
|
||||
await loadObcPool();
|
||||
return;
|
||||
}
|
||||
userPools.value = pools;
|
||||
if (isInit.value) await showLoading.end();
|
||||
if (isRefreshing.value) {
|
||||
showSnackbar.success("限时祈愿数据已刷新");
|
||||
isRefreshing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadObcPool(): Promise<void> {
|
||||
if (obcPools.value.length > 0) return;
|
||||
if (isInit.value) await showLoading.start("正在加载限时祈愿");
|
||||
let resp: TGApp.BBS.Obc.GachaResp | undefined;
|
||||
try {
|
||||
resp = await takumiReq.obc.gacha();
|
||||
if (resp.retcode !== 0) {
|
||||
showSnackbar.error(`获取限时祈愿失败:[${resp.retcode}] ${resp.message}`);
|
||||
await TGLogger.Warn(`[PhCompPool] 获取限时祈愿失败:[${resp.retcode}] ${resp.message}`);
|
||||
if (isInit.value) {
|
||||
showSnackbar.error(`获取限时祈愿失败:[${resp.retcode}] ${resp.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
await TGLogger.Warn(`[PhCompPool][loadObcPool] ${resp.retcode}-${resp.message}`);
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
const errMsg = TGHttps.getErrMsg(e);
|
||||
showSnackbar.error(`获取限时祈愿失败:${errMsg}`);
|
||||
await TGLogger.Error(`[PhCompPool] 获取限时祈愿异常`);
|
||||
await TGLogger.Error(`[PhCompPool] ${e}`);
|
||||
if (isInit.value) {
|
||||
showSnackbar.error(`获取限时祈愿失败:${errMsg}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
await TGLogger.Error("[PhCompPool][loadObcPool] 获取限时祈愿异常");
|
||||
await TGLogger.Error(`[PhCompPool][loadObcPool] ${e}`);
|
||||
emits("success");
|
||||
return;
|
||||
}
|
||||
const list = resp.data.list;
|
||||
if (list.length < 3) pools.value = list;
|
||||
else pools.value = [...list, ...list];
|
||||
emits("success");
|
||||
});
|
||||
if (list.length < 3) obcPools.value = list;
|
||||
else obcPools.value = [...list, ...list];
|
||||
if (list.length === 0 && isInit.value) showSnackbar.warn("暂无卡池信息");
|
||||
if (isInit.value) await showLoading.end();
|
||||
if (isRefreshing.value) {
|
||||
showSnackbar.success("限时祈愿数据已刷新");
|
||||
isRefreshing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function filterPools(
|
||||
pools: Array<TGApp.Game.ActCalendar.ActPool>,
|
||||
): Array<TGApp.Game.ActCalendar.ActPool> {
|
||||
if (pools.length === 0) return [];
|
||||
const ongoing = pools.filter((p) => p.pool_status === gameEnum.actCalendar.poolStatus.Ongoing);
|
||||
if (ongoing.length > 0) return ongoing;
|
||||
const notStart = pools.filter((p) => p.pool_status === gameEnum.actCalendar.poolStatus.NotStart);
|
||||
if (notStart.length > 0) return notStart;
|
||||
return pools.filter((p) => p.pool_status === gameEnum.actCalendar.poolStatus.Ended);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tp-refresh {
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.tp-switch {
|
||||
display: flex;
|
||||
height: 36px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.pool-grid {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
@@ -77,4 +306,8 @@ onMounted(async () => {
|
||||
gap: 8px;
|
||||
grid-template-columns: repeat(2, 0.5fr);
|
||||
}
|
||||
|
||||
.pool-swiper {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<!-- 首页近期活动组件 -->
|
||||
<template>
|
||||
<THomeCard :append="isLogin" title="近期活动">
|
||||
<template #title>
|
||||
<span>近期活动</span>
|
||||
<v-icon class="tp-refresh" size="small" title="刷新" @click.stop="handleRefresh()">
|
||||
mdi-refresh
|
||||
</v-icon>
|
||||
</template>
|
||||
<template v-if="isLogin" #title-append>
|
||||
<v-switch v-model="isUserPos" class="tp-switch"></v-switch>
|
||||
<span>{{ isUserPos ? "用户" : "百科" }}</span>
|
||||
@@ -29,10 +35,12 @@ import PboMaterial from "@comp/pageBag/pbo-material.vue";
|
||||
import ToCalendar from "@comp/pageHome/ph-calendar-overlay.vue";
|
||||
import PhPosObc from "@comp/pageHome/ph-pos-obc.vue";
|
||||
import PhPosUser from "@comp/pageHome/ph-pos-user.vue";
|
||||
import miscReq from "@req/miscReq.js";
|
||||
import recordReq from "@req/recordReq.js";
|
||||
import takumiReq from "@req/takumiReq.js";
|
||||
import TSUserBagMaterial from "@Sqlm/userBagMaterial.js";
|
||||
import useAppStore from "@store/app.js";
|
||||
import useHomeStore from "@store/home.js";
|
||||
import TSUserBagMaterial from "@Sqlm/userBagMaterial.js";
|
||||
import useUserStore from "@store/user.js";
|
||||
import { openUrl } from "@tauri-apps/plugin-opener";
|
||||
import TGHttps from "@utils/TGHttps.js";
|
||||
@@ -50,10 +58,12 @@ type TPositionEmits = (e: "success") => void;
|
||||
|
||||
const { isLogin } = storeToRefs(useAppStore());
|
||||
const { cookie, account } = storeToRefs(useUserStore());
|
||||
const homeStore = useHomeStore();
|
||||
|
||||
const emits = defineEmits<TPositionEmits>();
|
||||
|
||||
const isInit = ref<boolean>(false);
|
||||
const isRefreshing = ref<boolean>(false);
|
||||
const isUserPos = ref<boolean>(isLogin.value);
|
||||
const showMaterial = ref<boolean>(false);
|
||||
const showCalendar = ref<boolean>(false);
|
||||
@@ -74,8 +84,9 @@ watch(
|
||||
watch(
|
||||
() => account.value.gameUid,
|
||||
async () => {
|
||||
if (isUserPos.value && isInit.value) {
|
||||
if (isUserPos.value) {
|
||||
userPos.value = [];
|
||||
homeStore.actCalendarData = undefined;
|
||||
await loadUserPosition(true);
|
||||
}
|
||||
},
|
||||
@@ -88,6 +99,18 @@ onMounted(async () => {
|
||||
isInit.value = true;
|
||||
});
|
||||
|
||||
async function handleRefresh(): Promise<void> {
|
||||
isRefreshing.value = true;
|
||||
if (isUserPos.value) {
|
||||
userPos.value = [];
|
||||
homeStore.actCalendarData = undefined;
|
||||
await loadUserPosition(true);
|
||||
} else {
|
||||
obsPos.value = [];
|
||||
await loadWikiPosition();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUserPosition(forceReload: boolean = false): Promise<void> {
|
||||
if (userPos.value.length > 0 && !forceReload) return;
|
||||
if (!cookie.value) {
|
||||
@@ -96,18 +119,61 @@ async function loadUserPosition(forceReload: boolean = false): Promise<void> {
|
||||
return;
|
||||
}
|
||||
if (isInit.value) await showLoading.start("正在获取近期活动");
|
||||
// 获取近期活动
|
||||
let resp: TGApp.Game.ActCalendar.ActResp | undefined;
|
||||
let data: TGApp.Game.ActCalendar.ActRes | undefined;
|
||||
try {
|
||||
resp = await recordReq.actCalendar(cookie.value, account.value);
|
||||
if (resp.retcode !== 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
|
||||
await showLoading.end();
|
||||
if (homeStore.actCalendarData && !forceReload) {
|
||||
data = homeStore.actCalendarData;
|
||||
} else {
|
||||
const resp = await recordReq.actCalendar(cookie.value, account.value);
|
||||
if (<number>resp.retcode === 1034) {
|
||||
await TGLogger.Warn("[PhCompPosition][loadUserPosition] 触发1034验证");
|
||||
if (!isInit.value || !isRefreshing.value) {
|
||||
if (isInit.value) await showLoading.end();
|
||||
isUserPos.value = false;
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await loadWikiPosition();
|
||||
return;
|
||||
}
|
||||
const challenge = await miscReq.challenge({
|
||||
account_id: cookie.value.account_id,
|
||||
cookie_token: cookie.value.cookie_token,
|
||||
});
|
||||
if (challenge === false) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.error("极验验证失败,已切换至百科模式");
|
||||
await showLoading.end();
|
||||
}
|
||||
isUserPos.value = false;
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await loadWikiPosition();
|
||||
return;
|
||||
}
|
||||
const resp2 = await recordReq.actCalendar(cookie.value, account.value, challenge);
|
||||
if (resp2.retcode !== 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn(`[${resp2.retcode}] ${resp2.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Warn(
|
||||
`[PhCompPosition][loadUserPosition] ${resp2.retcode}-${resp2.message}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
data = resp2.data;
|
||||
} else if (resp.retcode !== 0) {
|
||||
if (isInit.value) {
|
||||
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Warn("[PhCompPosition][loadUserPosition] 获取近期活动异常");
|
||||
await TGLogger.Warn(`[PhCompPosition][loadUserPosition] ${resp.retcode}-${resp.message}`);
|
||||
return;
|
||||
} else {
|
||||
data = resp.data;
|
||||
}
|
||||
await TGLogger.Warn(`[PhCompPosition][loadUserPosition] 获取近期活动异常`);
|
||||
await TGLogger.Warn(`[PhCompPosition][loadUserPosition] ${resp.retcode}-${resp.message}`);
|
||||
return;
|
||||
homeStore.actCalendarData = data;
|
||||
}
|
||||
} catch (e) {
|
||||
const errMsg = TGHttps.getErrMsg(e);
|
||||
@@ -115,19 +181,20 @@ async function loadUserPosition(forceReload: boolean = false): Promise<void> {
|
||||
showSnackbar.error(`获取近期活动失败:${errMsg}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
await TGLogger.Error(`[PhCompPosition][loadUserPosition] 获取近期活动异常`);
|
||||
if (isRefreshing.value) isRefreshing.value = false;
|
||||
await TGLogger.Error("[PhCompPosition][loadUserPosition] 获取近期活动异常");
|
||||
await TGLogger.Error(`[PhCompPosition][loadUserPosition] ${e}`);
|
||||
return;
|
||||
}
|
||||
if (!resp) {
|
||||
if (isInit.value) await showLoading.end();
|
||||
return;
|
||||
}
|
||||
// 处理近期活动数据
|
||||
userPos.value = [...resp.data.act_list, ...resp.data.fixed_act_list]
|
||||
userPos.value = [...data.act_list, ...data.fixed_act_list]
|
||||
.filter((i) => i.start_timestamp !== "0")
|
||||
.sort((a, b) => Number(a.is_finished) - Number(b.is_finished) || b.id - a.id);
|
||||
if (isInit.value) await showLoading.end();
|
||||
if (isRefreshing.value) {
|
||||
showSnackbar.success("近期活动数据已刷新");
|
||||
isRefreshing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadWikiPosition(): Promise<void> {
|
||||
@@ -141,7 +208,7 @@ async function loadWikiPosition(): Promise<void> {
|
||||
showSnackbar.warn(`[${resp.retcode}] ${resp.message}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
await TGLogger.Warn(`[PhCompPosition][loadWikiPosition] 获取近期活动异常`);
|
||||
await TGLogger.Warn("[PhCompPosition][loadWikiPosition] 获取近期活动异常");
|
||||
await TGLogger.Warn(`[PhCompPosition][loadWikiPosition] ${resp.retcode}-${resp.message}`);
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +218,7 @@ async function loadWikiPosition(): Promise<void> {
|
||||
showSnackbar.error(`获取近期活动失败:${errMsg}`);
|
||||
await showLoading.end();
|
||||
}
|
||||
await TGLogger.Error(`[PhCompPosition][loadWikiPosition] 获取近期活动异常`);
|
||||
await TGLogger.Error("[PhCompPosition][loadWikiPosition] 获取近期活动异常");
|
||||
await TGLogger.Error(`[PhCompPosition][loadWikiPosition] ${e}`);
|
||||
return;
|
||||
}
|
||||
@@ -159,10 +226,14 @@ async function loadWikiPosition(): Promise<void> {
|
||||
if (isInit.value) await showLoading.end();
|
||||
return;
|
||||
}
|
||||
const data = dfsObc(resp.data.list);
|
||||
obsPos.value = data;
|
||||
if (data.length === 0) showSnackbar.warn("暂无近期活动");
|
||||
const dfsRes = dfsObc(resp.data.list);
|
||||
obsPos.value = dfsRes;
|
||||
if (dfsRes.length === 0) showSnackbar.warn("暂无近期活动");
|
||||
if (isInit.value) await showLoading.end();
|
||||
if (isRefreshing.value) {
|
||||
showSnackbar.success("近期活动数据已刷新");
|
||||
isRefreshing.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function dfsObc(
|
||||
@@ -219,6 +290,15 @@ async function handleMaterial(cur: TGApp.Game.ActCalendar.ActReward): Promise<vo
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tp-refresh {
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.tp-switch {
|
||||
display: flex;
|
||||
height: 36px;
|
||||
|
||||
@@ -265,6 +265,7 @@ async function toPool(): Promise<void> {
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
box-shadow: 0 -2px 10px var(--common-shadow-2);
|
||||
}
|
||||
|
||||
.ph-pool-avatars {
|
||||
@@ -311,6 +312,7 @@ async function toPool(): Promise<void> {
|
||||
font-size: 12px;
|
||||
gap: 8px;
|
||||
text-align: left;
|
||||
text-shadow: 0 0 4px var(--tgc-dark-1);
|
||||
}
|
||||
|
||||
.ph-pool-time {
|
||||
|
||||
458
src/components/pageHome/ph-pool-user.vue
Normal file
458
src/components/pageHome/ph-pool-user.vue
Normal file
@@ -0,0 +1,458 @@
|
||||
<!-- 限时祈愿卡片组件(用户模式) -->
|
||||
<template>
|
||||
<div class="ph-pool-user-card">
|
||||
<div class="ph-pool-type">
|
||||
<span>【{{ poolTypeLabel }}】</span>
|
||||
<span>{{ props.pool.pool_name }}</span>
|
||||
</div>
|
||||
<div class="ph-pool-cover" @click="toPool()">
|
||||
<img v-if="cover" :src="cover" alt="cover" />
|
||||
<img v-else alt="empty" class="empty" src="/UI/app/empty.webp" />
|
||||
</div>
|
||||
<div class="ph-pool-bottom">
|
||||
<div v-if="totalItems < 5" class="ph-pool-avatars">
|
||||
<template v-for="item in avatarItems" :key="`av-${item.avatar.id}`">
|
||||
<div class="ph-pool-icon" @click="toAvatar(item.avatar)">
|
||||
<TItemBox
|
||||
v-if="item.info"
|
||||
:model-value="getAvatarBox(item.info)"
|
||||
:title="item.info.name"
|
||||
/>
|
||||
<img v-else :src="item.avatar.icon" alt="icon" />
|
||||
</div>
|
||||
</template>
|
||||
<template v-for="item in weaponItems" :key="`wp-${item.weapon.id}`">
|
||||
<div class="ph-pool-icon" @click="toWeapon(item.weapon)">
|
||||
<TItemBox
|
||||
v-if="item.info"
|
||||
:model-value="getWeaponBox(item.info)"
|
||||
:title="item.info.name"
|
||||
/>
|
||||
<img v-else :src="item.weapon.icon" alt="icon" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<Swiper
|
||||
v-else
|
||||
:autoplay="{ delay: 1000, disableOnInteraction: false, stopOnLastSlide: false }"
|
||||
:centered-slides="false"
|
||||
:loop="true"
|
||||
:modules="swiperModules"
|
||||
:navigation="true"
|
||||
:slides-per-view="4"
|
||||
:space-between="8"
|
||||
class="ph-pool-avatars swiper"
|
||||
>
|
||||
<SwiperSlide
|
||||
v-for="item in avatarItems"
|
||||
:key="`av-${item.avatar.id}`"
|
||||
class="ph-pool-icon"
|
||||
@click="toAvatar(item.avatar)"
|
||||
>
|
||||
<TItemBox
|
||||
v-if="item.info"
|
||||
:model-value="getAvatarBox(item.info)"
|
||||
:title="item.info.name"
|
||||
/>
|
||||
<img v-else :src="item.avatar.icon" alt="icon" />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide
|
||||
v-for="item in weaponItems"
|
||||
:key="`wp-${item.weapon.id}`"
|
||||
class="ph-pool-icon"
|
||||
@click="toWeapon(item.weapon)"
|
||||
>
|
||||
<TItemBox
|
||||
v-if="item.info"
|
||||
:model-value="getWeaponBox(item.info)"
|
||||
:title="item.info.name"
|
||||
/>
|
||||
<img v-else :src="item.weapon.icon" alt="icon" />
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
<div class="ph-pool-info">
|
||||
<div class="ph-pool-time">
|
||||
<v-icon>mdi-calendar-clock</v-icon>
|
||||
<span>{{ startTime }} ~ {{ endTime }}</span>
|
||||
</div>
|
||||
<v-progress-linear :model-value="percent" :rounded="true" color="var(--tgc-od-green)" />
|
||||
<div v-if="restTs > durationTs" class="ph-pool-stat">未开始</div>
|
||||
<div v-else-if="restTs > 0" class="ph-pool-stat">
|
||||
剩余时间:{{ stamp2LastTime(restTs) }}
|
||||
</div>
|
||||
<div v-else class="ph-pool-stat">已结束</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import "swiper/css";
|
||||
import "swiper/css/pagination";
|
||||
import "swiper/css/navigation";
|
||||
|
||||
import TItemBox, { TItemBoxData } from "@comp/app/t-itemBox.vue";
|
||||
import showSnackbar from "@comp/func/snackbar.js";
|
||||
import postReq from "@req/postReq.js";
|
||||
import useHomeStore from "@store/home.js";
|
||||
import { parsePost } from "@utils/linkParser.js";
|
||||
import TGHttps from "@utils/TGHttps.js";
|
||||
import TGLogger from "@utils/TGLogger.js";
|
||||
import { createPost } from "@utils/TGWindow.js";
|
||||
import { getWikiBrief, stamp2LastTime, timestampToDate } from "@utils/toolFunc.js";
|
||||
import { str2Color } from "@utils/colorFunc.js";
|
||||
import { openUrl } from "@tauri-apps/plugin-opener";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { A11y, Autoplay } from "swiper/modules";
|
||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
import gameEnum from "@enum/game.js";
|
||||
|
||||
type PhPoolUserProps = { pool: TGApp.Game.ActCalendar.ActPool };
|
||||
type AvatarItem = {
|
||||
avatar: TGApp.Game.ActCalendar.ActPoolAvatar;
|
||||
info?: TGApp.App.Character.WikiBriefInfo;
|
||||
};
|
||||
type WeaponItem = {
|
||||
weapon: TGApp.Game.ActCalendar.ActPoolWeapon;
|
||||
info?: TGApp.App.Weapon.WikiBriefInfo;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
let timer: NodeJS.Timeout | null = null;
|
||||
|
||||
const swiperModules = [Autoplay, A11y];
|
||||
const { poolCover } = storeToRefs(useHomeStore());
|
||||
const router = useRouter();
|
||||
|
||||
const props = defineProps<PhPoolUserProps>();
|
||||
|
||||
const cover = ref<string>();
|
||||
const endTs = ref<number>(0);
|
||||
const restTs = ref<number>(0);
|
||||
const durationTs = ref<number>(0);
|
||||
const totalItems = computed<number>(() => props.pool.avatars.length + props.pool.weapons.length);
|
||||
const avatarItems = computed<Array<AvatarItem>>(() =>
|
||||
props.pool.avatars.map((av) => {
|
||||
const info = getAvatarInfo(av.id);
|
||||
return { avatar: av, info };
|
||||
}),
|
||||
);
|
||||
const weaponItems = computed<Array<WeaponItem>>(() =>
|
||||
props.pool.weapons.map((wp) => {
|
||||
const info = getWeaponInfo(wp.id);
|
||||
return { weapon: wp, info };
|
||||
}),
|
||||
);
|
||||
const percent = computed<number>(() => {
|
||||
if (restTs.value > durationTs.value) return 100;
|
||||
if (durationTs.value === 0) return 0;
|
||||
return (restTs.value * 100) / durationTs.value;
|
||||
});
|
||||
const startTime = computed<string>(() =>
|
||||
timestampToDate(Number(props.pool.start_timestamp) * 1000),
|
||||
);
|
||||
const endTime = computed<string>(() => timestampToDate(Number(props.pool.end_timestamp) * 1000));
|
||||
const poolTypeLabel = computed<string>(() => {
|
||||
const poolTypeMap: Record<TGApp.Game.ActCalendar.PoolTypeEnum, string> = {
|
||||
[gameEnum.actCalendar.poolType.Avatar]: "角色活动祈愿",
|
||||
[gameEnum.actCalendar.poolType.Weapon]: "武器活动祈愿",
|
||||
[gameEnum.actCalendar.poolType.Mixed]: "集录祈愿",
|
||||
};
|
||||
return poolTypeMap[props.pool.pool_type] ?? "未知类型祈愿";
|
||||
});
|
||||
const typeBg = computed<string>(() =>
|
||||
str2Color(`${props.pool.pool_name}${poolTypeLabel.value}`, -60),
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
await loadCover();
|
||||
endTs.value = Number(props.pool.end_timestamp) * 1000;
|
||||
restTs.value = endTs.value - Date.now();
|
||||
durationTs.value = endTs.value - Number(props.pool.start_timestamp) * 1000;
|
||||
if (restTs.value > 0) {
|
||||
if (timer !== null) clearInterval(timer);
|
||||
timer = setInterval(handlePosition, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
async function loadCover(): Promise<void> {
|
||||
const jumpUrl = props.pool.jump_url;
|
||||
if (!jumpUrl || jumpUrl === "") return;
|
||||
const postIdStr = await parsePost(jumpUrl);
|
||||
if (postIdStr === false) return;
|
||||
const postId = Number(postIdStr);
|
||||
if (isNaN(postId)) return;
|
||||
if (poolCover.value && postId in poolCover.value && poolCover.value[postId] !== "") {
|
||||
cover.value = poolCover.value[postId];
|
||||
return;
|
||||
}
|
||||
let resp: TGApp.BBS.Post.FullResp | undefined;
|
||||
try {
|
||||
resp = await postReq.post(postId, {});
|
||||
if (resp.retcode !== 0) {
|
||||
showSnackbar.error(`[PhPoolUser][${resp.retcode}] ${resp.message}`);
|
||||
await TGLogger.Warn(`[PhPoolUser][${resp.retcode}] ${resp.message}`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
const errMsg = TGHttps.getErrMsg(e);
|
||||
showSnackbar.error(`获取帖子封面失败:${errMsg}`);
|
||||
await TGLogger.Error("[PhPoolUser] 获取帖子封面异常");
|
||||
await TGLogger.Error(`[PhPoolUser] ${typeof e === "object" ? JSON.stringify(e) : e}`);
|
||||
return;
|
||||
}
|
||||
let coverGet: string | undefined;
|
||||
if (resp.data.post.cover) coverGet = resp.data.post.cover.url;
|
||||
else if (resp.data.post.post.cover && resp.data.post.post.cover !== "") {
|
||||
coverGet = resp.data.post.post.cover;
|
||||
} else if (resp.data.post.post.images.length > 0) {
|
||||
coverGet = resp.data.post.post.images[0];
|
||||
} else {
|
||||
coverGet = "";
|
||||
}
|
||||
cover.value = coverGet;
|
||||
if (!poolCover.value) poolCover.value = { [postId]: coverGet };
|
||||
else poolCover.value[postId] = coverGet;
|
||||
}
|
||||
|
||||
function handlePosition(): void {
|
||||
if (restTs.value < 1) {
|
||||
if (timer !== null) clearInterval(timer);
|
||||
timer = null;
|
||||
restTs.value = 0;
|
||||
return;
|
||||
}
|
||||
restTs.value = endTs.value - Date.now();
|
||||
}
|
||||
|
||||
async function toAvatar(avatar: TGApp.Game.ActCalendar.ActPoolAvatar): Promise<void> {
|
||||
const info = getAvatarInfo(avatar.id);
|
||||
if (!info) {
|
||||
showSnackbar.warn(`${avatar.name} 角色图鉴暂未收录`);
|
||||
return;
|
||||
}
|
||||
await router.push({ name: "角色图鉴", params: { id: avatar.id } });
|
||||
}
|
||||
|
||||
async function toWeapon(weapon: TGApp.Game.ActCalendar.ActPoolWeapon): Promise<void> {
|
||||
const info = getWeaponInfo(weapon.id);
|
||||
if (!info) {
|
||||
showSnackbar.warn(`${weapon.name} 武器图鉴暂未收录`);
|
||||
return;
|
||||
}
|
||||
await router.push({ name: "武器图鉴", params: { id: weapon.id } });
|
||||
}
|
||||
|
||||
function getAvatarInfo(id: number): TGApp.App.Character.WikiBriefInfo | undefined {
|
||||
const info = getWikiBrief(id);
|
||||
if (info === false) return undefined;
|
||||
if ("element" in info) return <TGApp.App.Character.WikiBriefInfo>info;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getWeaponInfo(id: number): TGApp.App.Weapon.WikiBriefInfo | undefined {
|
||||
const info = getWikiBrief(id);
|
||||
if (info === false) return undefined;
|
||||
if ("weapon" in info) return <TGApp.App.Weapon.WikiBriefInfo>info;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getAvatarBox(info: TGApp.App.Character.WikiBriefInfo): TItemBoxData {
|
||||
return {
|
||||
bg: `/icon/bg/${info.star}-Star.webp`,
|
||||
icon: `/WIKI/character/${info.id}.webp`,
|
||||
size: "60px",
|
||||
height: "60px",
|
||||
display: "inner",
|
||||
clickable: true,
|
||||
lt: `/icon/element/${info.element}元素.webp`,
|
||||
ltSize: "15px",
|
||||
innerHeight: 20,
|
||||
innerIcon: `/icon/weapon/${info.weapon}.webp`,
|
||||
innerText: info.name,
|
||||
};
|
||||
}
|
||||
|
||||
function getWeaponBox(info: TGApp.App.Weapon.WikiBriefInfo): TItemBoxData {
|
||||
return {
|
||||
bg: `/icon/bg/${info.star}-Star.webp`,
|
||||
icon: `/WIKI/weapon/${info.id}.webp`,
|
||||
size: "60px",
|
||||
height: "60px",
|
||||
display: "inner",
|
||||
clickable: true,
|
||||
lt: `/icon/weapon/${info.weapon}.webp`,
|
||||
ltSize: "15px",
|
||||
innerHeight: 20,
|
||||
innerText: info.name,
|
||||
};
|
||||
}
|
||||
|
||||
async function toPool(): Promise<void> {
|
||||
const jumpUrl = props.pool.jump_url;
|
||||
if (!jumpUrl || jumpUrl === "") {
|
||||
showSnackbar.warn("暂无跳转链接");
|
||||
return;
|
||||
}
|
||||
const postIdStr = await parsePost(jumpUrl);
|
||||
if (postIdStr !== false) {
|
||||
const postId = Number(postIdStr);
|
||||
if (!isNaN(postId)) {
|
||||
await createPost(postId, props.pool.pool_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await openUrl(jumpUrl);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ph-pool-user-card {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
aspect-ratio: 69 / 32;
|
||||
box-shadow: 0 2px 4px var(--common-shadow-2);
|
||||
}
|
||||
|
||||
.ph-pool-type {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
top: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2px 4px;
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
backdrop-filter: blur(10px);
|
||||
background: v-bind(typeBg); /* stylelint-disable-line value-keyword-case */
|
||||
border-bottom-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
box-shadow: 1px 1px 6px var(--tgc-dark-1);
|
||||
color: var(--tgc-white-1);
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
text-shadow: 0 0 4px var(--tgc-dark-1);
|
||||
|
||||
span:last-child:not(:first-child) {
|
||||
font-family: var(--font-title);
|
||||
}
|
||||
}
|
||||
|
||||
.ph-pool-cover {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
background: var(--box-bg-1); /* stylelint-disable-line value-keyword-case */
|
||||
cursor: pointer;
|
||||
|
||||
.empty {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
border-radius: 4px;
|
||||
transition: all 0.5s;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.1);
|
||||
transition: all 0.5s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ph-pool-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
backdrop-filter: blur(20px);
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
box-shadow: 0 -2px 10px var(--common-shadow-2);
|
||||
}
|
||||
|
||||
.ph-pool-avatars {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: auto;
|
||||
max-width: 280px;
|
||||
height: 60px;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: 8px;
|
||||
gap: 8px;
|
||||
|
||||
&.swiper {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--common-shadow-t-4);
|
||||
}
|
||||
}
|
||||
|
||||
.ph-pool-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.ph-pool-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
margin-right: 10px;
|
||||
color: var(--tgc-white-1);
|
||||
font-size: 12px;
|
||||
gap: 8px;
|
||||
text-align: left;
|
||||
text-shadow: 0 0 4px var(--tgc-dark-1);
|
||||
}
|
||||
|
||||
.ph-pool-time {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
column-gap: 4px;
|
||||
|
||||
:first-child {
|
||||
color: var(--tgc-od-orange);
|
||||
}
|
||||
}
|
||||
|
||||
.ph-pool-stat {
|
||||
margin-left: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -122,6 +122,7 @@ const showItemsAll = shallowRef<Array<string>>(["素材日历", "限时祈愿",
|
||||
const oldItems = shallowRef<Array<string>>([]);
|
||||
|
||||
onMounted(async () => {
|
||||
homeStore.actCalendarData = undefined;
|
||||
await bbsStore.refreshGameList();
|
||||
await bbsStore.refreshGameUidCards();
|
||||
// @ts-expect-error-next-line The import.meta meta-property is not allowed in files which will build into CommonJS output.
|
||||
|
||||
@@ -201,19 +201,23 @@ async function hardChallengeDetail(
|
||||
|
||||
/**
|
||||
* 获取活动日历数据
|
||||
* @since Beta v0.10.1
|
||||
* @since Beta v0.10.2
|
||||
* @param cookie - Cookie
|
||||
* @param user - 用户
|
||||
* @param challenge - 极验验证信息(可选)
|
||||
* @returns 活动日历响应数据
|
||||
*/
|
||||
async function actCalendar(
|
||||
cookie: TGApp.App.Account.Cookie,
|
||||
user: TGApp.Sqlite.Account.Game,
|
||||
challenge?: string,
|
||||
): Promise<TGApp.Game.ActCalendar.ActResp> {
|
||||
const ck = { account_id: cookie.account_id, cookie_token: cookie.cookie_token };
|
||||
const body = { role_id: user.gameUid, server: user.region };
|
||||
const headers = getRequestHeader(ck, "POST", body);
|
||||
if (challenge) headers["x-rpc-challenge"] = challenge;
|
||||
const resp = await TGHttps.post<TGApp.Game.ActCalendar.ActResp>(`${trgAbu}act_calendar`, {
|
||||
headers: getRequestHeader(ck, "POST", body),
|
||||
headers,
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
return resp.data;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 首页组件状态
|
||||
* @since Beta v0.10.1
|
||||
* @since Beta v0.10.2
|
||||
*/
|
||||
|
||||
import { defineStore } from "pinia";
|
||||
@@ -19,6 +19,7 @@ const defaultHomeShow: Array<TGApp.Store.Home.ShowItem> = [
|
||||
const useHomeStore = defineStore("home", () => {
|
||||
const homeShow = ref<Array<TGApp.Store.Home.ShowItem>>(defaultHomeShow);
|
||||
const poolCover = ref<Record<number, string>>();
|
||||
const actCalendarData = ref<TGApp.Game.ActCalendar.ActRes>();
|
||||
|
||||
function getShowItems(): Array<string> {
|
||||
const homeShowLocal = localStorage.getItem("homeShow");
|
||||
@@ -72,7 +73,7 @@ const useHomeStore = defineStore("home", () => {
|
||||
localStorage.setItem("homeShow", JSON.stringify(homeShow.value));
|
||||
}
|
||||
|
||||
return { poolCover, getShowItems, setShowItems, init };
|
||||
return { poolCover, actCalendarData, getShowItems, setShowItems, init };
|
||||
});
|
||||
|
||||
export default useHomeStore;
|
||||
|
||||
Reference in New Issue
Block a user