feat(frontend): 首页广告位网格溢出根治(minmax(0,1fr) minmax(0,1.2fr)+min-width:0) + 精选推荐对接平台广告接口 GET /app/api/market/ads
This commit is contained in:
1 parent
e38e18fbe7
commit
9b87012248
3 files changed
+74
-7
No files matched your search
@@ -79,7 +79,9 @@ const LandingPage: React.FC = () => {
|
||||
const [isPaused, setIsPaused] = useState(false);
|
||||
const [mobileMenu, setMobileMenu] = useState(false);
|
||||
|
||||
const banners = mockAdBanners.filter(b => b.status === 'active');
|
||||
const [banners, setBanners] = useState<AdBanner[]>(
|
||||
mockAdBanners.filter(b => b.status === 'active')
|
||||
);
|
||||
const publishedApps = mockApps.filter(a => a.status === 'published');
|
||||
const topSkills = [...publishedApps].sort((a, b) => b.installCount - a.installCount).slice(0, 5);
|
||||
|
||||
@@ -94,6 +96,32 @@ const LandingPage: React.FC = () => {
|
||||
return () => clearInterval(timer);
|
||||
}, [banners.length, isPaused, nextSlide]);
|
||||
|
||||
// 精选推荐:对接平台「广告位」能力——拉取后台已上架(active)的真实广告轮播;
|
||||
// 无数据或接口异常时回退到内置示例,保证首屏不空。
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
fetch('/app/api/market/ads')
|
||||
.then(r => (r.ok ? r.json() : Promise.reject(r.status)))
|
||||
.then((rows: any[]) => {
|
||||
if (!alive || !Array.isArray(rows) || rows.length === 0) return;
|
||||
const mapped: AdBanner[] = rows.map(a => ({
|
||||
id: a.id,
|
||||
title: a.title,
|
||||
imageUrl: a.image_url || '',
|
||||
linkAppId: a.link_app_id || undefined,
|
||||
linkAppName: a.link_app_name || undefined,
|
||||
sortOrder: a.sort_order ?? 0,
|
||||
clickCount: a.click_count ?? 0,
|
||||
status: (a.status as 'active' | 'inactive') || 'active',
|
||||
createdAt: a.created_at || '',
|
||||
}));
|
||||
setBanners(mapped);
|
||||
setCurrentSlide(0);
|
||||
})
|
||||
.catch(() => { /* 静默失败,保留 mock 回退 */ });
|
||||
return () => { alive = false; };
|
||||
}, []);
|
||||
|
||||
// SEO / GEO:动态写入标题与描述
|
||||
useEffect(() => {
|
||||
document.title = '七虎AI · 个人体验 AI、办公提效与 AI 创收的一站式平台';
|
||||
@@ -214,13 +242,14 @@ const LandingPage: React.FC = () => {
|
||||
{banners.map(b => (
|
||||
<div key={b.id} className="lp-slide">
|
||||
<div className="lp-carousel-card" style={{ background: gradFor(b.linkAppId || 'a1') }}>
|
||||
{b.imageUrl && (<><img className="lp-cc-cover" src={b.imageUrl} alt={b.title} loading="lazy" /><span className="lp-cc-scrim" /></>)}
|
||||
<div className="lp-cc-content">
|
||||
<div className="lp-cc-badge">推荐</div>
|
||||
<h3 className="lp-cc-title">{b.title}</h3>
|
||||
{b.linkAppName && <p className="lp-cc-sub">立即体验 {b.linkAppName}</p>}
|
||||
<button className="lp-cc-cta" onClick={goLogin}>查看详情 <Icon d={<polyline points="9 18 15 12 9 6" />} size={14} /></button>
|
||||
</div>
|
||||
<div className="lp-cc-visual"><span className="c1" /><span className="c2" /><span className="c3" /></div>
|
||||
{!b.imageUrl && <div className="lp-cc-visual"><span className="c1" /><span className="c2" /><span className="c3" /></div>}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
Reference in new issue
Block a user