feat(admin,player,api): 公共管理与优胜冠军国旗、玩家端内容对接
新增公共内容 CRUD 与批量操作;公告滚动合并管理;优胜冠军内置国家选择与单行保存;玩家端统一 usePlayerHome 对接轮播与跑马灯。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,50 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
|
||||
const { t } = useI18n();
|
||||
import api from '../api';
|
||||
import emptyMatchesImg from '../assets/images/empty-matches.svg';
|
||||
import BannerCarousel from '../components/BannerCarousel.vue';
|
||||
import { resolveBanners } from '../constants/defaultBanner';
|
||||
import { useOnLocaleChange } from '../composables/useOnLocaleChange';
|
||||
import { usePlayerHome } from '../composables/usePlayerHome';
|
||||
|
||||
const { t } = useI18n();
|
||||
const router = useRouter();
|
||||
const home = ref<{
|
||||
banners: Banner[];
|
||||
hotMatches: Match[];
|
||||
ticker: ContentItem[];
|
||||
notices: ContentItem[];
|
||||
} | null>(null);
|
||||
|
||||
interface ContentItem {
|
||||
translation?: { title?: string; body?: string; imageUrl?: string };
|
||||
}
|
||||
|
||||
interface Banner {
|
||||
id?: string;
|
||||
linkType?: string | null;
|
||||
linkTarget?: string | null;
|
||||
translation?: { title?: string; body?: string; imageUrl?: string };
|
||||
}
|
||||
|
||||
interface Match {
|
||||
id: string;
|
||||
homeTeamName: string;
|
||||
awayTeamName: string;
|
||||
startTime: string;
|
||||
isHot: boolean;
|
||||
}
|
||||
|
||||
const displayBanners = computed(() => resolveBanners(home.value?.banners));
|
||||
|
||||
async function loadHome() {
|
||||
const { data } = await api.get('/player/home');
|
||||
home.value = data.data;
|
||||
}
|
||||
|
||||
useOnLocaleChange(loadHome);
|
||||
const { banners, hotMatches, loading } = usePlayerHome();
|
||||
|
||||
function goMatch(id: string) {
|
||||
router.push(`/match/${id}`);
|
||||
@@ -53,15 +16,15 @@ function goMatch(id: string) {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<BannerCarousel :banners="displayBanners" />
|
||||
<BannerCarousel :banners="banners" />
|
||||
|
||||
<h2 class="section-title">{{ t('home.hot_matches') }}</h2>
|
||||
<div v-for="match in home?.hotMatches || []" :key="match.id" class="card match-card" @click="goMatch(match.id)">
|
||||
<div v-for="match in hotMatches" :key="match.id" class="card match-card" @click="goMatch(match.id)">
|
||||
<div class="match-teams">{{ match.homeTeamName }} vs {{ match.awayTeamName }}</div>
|
||||
<div class="match-time">{{ new Date(match.startTime).toLocaleString() }}</div>
|
||||
</div>
|
||||
|
||||
<div v-if="home && !home.hotMatches?.length" class="empty">
|
||||
<div v-if="!loading && !hotMatches.length" class="empty">
|
||||
<img :src="emptyMatchesImg" alt="" class="empty-icon" />
|
||||
<p>{{ t('home.no_matches') }}</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user