feat: use login popup announcement on home
Deploy olons-server production / deploy (push) Successful in 4m57s

This commit is contained in:
richjohnrambo
2026-10-20 22:13:51 +08:00
parent 6954d375b5
commit 78165b7a15
2 changed files with 31 additions and 17 deletions
@@ -35,6 +35,7 @@
title: string; title: string;
content: string; content: string;
body_html?: string; body_html?: string;
source_type?: string;
} }
const props = defineProps<{ const props = defineProps<{
+30 -17
View File
@@ -1,8 +1,8 @@
<template> <template>
<section class="m-home"> <section class="m-home">
<AnnouncementPopup <AnnouncementPopup
:show="Boolean(popupNotice)" :show="popupVisible"
:notice="popupNotice" :notice="loginPopupNotice"
@read="markPopupRead" @read="markPopupRead"
/> />
<div class="m-home-hero" :style="bannerStyle"> <div class="m-home-hero" :style="bannerStyle">
@@ -54,18 +54,18 @@
</div> </div>
<button <button
v-if="currentNotice" v-if="displayNotice"
class="m-notice m-card" class="m-notice m-card"
type="button" type="button"
aria-label="查看全部通知" :aria-label="`查看公告:${displayNotice.title || '最新公告'}`"
@click="router.push('/app/content/notices')" @click="openNotice"
> >
<n-icon :component="MegaphoneOutline" /> <n-icon :component="MegaphoneOutline" />
<span :class="['m-notice-tag', { 'is-activity': currentNotice.source_type === 'operational_simulation' }]"> <span :class="['m-notice-tag', { 'is-activity': displayNotice.source_type === 'operational_simulation' }]">
{{ currentNotice.source_type === 'operational_simulation' ? '活动' : '公告' }} {{ displayNotice.source_type === 'operational_simulation' ? '活动' : '公告' }}
</span> </span>
<p :key="currentNotice.id" class="m-notice-copy"> <p :key="displayNotice.id" class="m-notice-copy">
{{ currentNotice.title || currentNotice.content || '查看最新通知' }} {{ displayNotice.title || displayNotice.content || '查看最新通知' }}
</p> </p>
<n-icon class="m-notice-arrow" :component="ChevronForwardOutline" /> <n-icon class="m-notice-arrow" :component="ChevronForwardOutline" />
</button> </button>
@@ -165,7 +165,9 @@
const loading = ref(true); const loading = ref(true);
const error = ref(''); const error = ref('');
const leaderboard = ref<LeaderboardEntry[]>([]); const leaderboard = ref<LeaderboardEntry[]>([]);
const popupNotice = ref<AnnouncementNotice | null>(null); const loginPopupNotice = ref<AnnouncementNotice | null>(null);
const popupVisible = ref(false);
const homeAnnouncement = ref<AnnouncementNotice | null>(null);
const activeBannerIndex = ref(0); const activeBannerIndex = ref(0);
const activeNoticeIndex = ref(0); const activeNoticeIndex = ref(0);
let bannerTimer: number | undefined; let bannerTimer: number | undefined;
@@ -176,6 +178,7 @@
); );
const currentBanner = computed(() => home.value?.banners?.[activeBannerIndex.value]); const currentBanner = computed(() => home.value?.banners?.[activeBannerIndex.value]);
const currentNotice = computed(() => home.value?.notices?.[activeNoticeIndex.value]); const currentNotice = computed(() => home.value?.notices?.[activeNoticeIndex.value]);
const displayNotice = computed(() => homeAnnouncement.value || currentNotice.value);
const bannerStyle = computed(() => { const bannerStyle = computed(() => {
const url = safeImage(currentBanner.value?.image_url); const url = safeImage(currentBanner.value?.image_url);
return { return {
@@ -271,9 +274,7 @@
loading.value = true; loading.value = true;
error.value = ''; error.value = '';
try { try {
const noticeRequest = shouldShowLoginNotice() const noticeRequest = request<AnnouncementNotice | null>({ url: '/v1/notices/popup' }).catch(() => null);
? request<AnnouncementNotice | null>({ url: '/v1/notices/popup' }).catch(() => null)
: Promise.resolve(null);
const [homeData, rankData, noticeData] = await Promise.all([ const [homeData, rankData, noticeData] = await Promise.all([
request<HomeData>({ url: '/v1/home' }), request<HomeData>({ url: '/v1/home' }),
request<LeaderboardEntry[]>({ url: '/v1/leaderboard' }).catch(() => []), request<LeaderboardEntry[]>({ url: '/v1/leaderboard' }).catch(() => []),
@@ -281,7 +282,9 @@
]); ]);
home.value = homeData; home.value = homeData;
leaderboard.value = rankData || []; leaderboard.value = rankData || [];
popupNotice.value = noticeData; homeAnnouncement.value = noticeData;
loginPopupNotice.value = shouldShowLoginNotice() ? noticeData : null;
popupVisible.value = Boolean(loginPopupNotice.value);
} catch (err) { } catch (err) {
error.value = errorText(err); error.value = errorText(err);
} finally { } finally {
@@ -290,14 +293,24 @@
} }
function markPopupRead() { function markPopupRead() {
if (!popupNotice.value) return; if (!loginPopupNotice.value) return;
const noticeId = popupNotice.value.id; const noticeId = loginPopupNotice.value.id;
popupNotice.value = null; popupVisible.value = false;
loginPopupNotice.value = null;
completeLoginNotice(); completeLoginNotice();
if (noticeId > 0) { if (noticeId > 0) {
request<void>({ url: `/v1/notices/${noticeId}/read`, method: 'POST' }).catch(() => undefined); request<void>({ url: `/v1/notices/${noticeId}/read`, method: 'POST' }).catch(() => undefined);
} }
} }
function openNotice() {
if (homeAnnouncement.value) {
loginPopupNotice.value = homeAnnouncement.value;
popupVisible.value = true;
return;
}
void router.push('/app/content/notices');
}
watch(() => home.value?.banners?.length, () => { watch(() => home.value?.banners?.length, () => {
activeBannerIndex.value = 0; activeBannerIndex.value = 0;
restartBannerTimer(); restartBannerTimer();