UI彻底重做: 全新设计语言, 纯手工精调
设计系统: - CSS变量体系: 暖纸底色(#F9F7F4), 6级灰阶, 5级阴影 - 字体节奏: clamp响应式字号, -0.02em字间距 - 间距韵律: 4-128px 8级递进 首页: - 96px大留白英雄区, clamp(36px,5vw,56px)巨型标题 - 200px暗色封面卡片(#2C2824) - LIVE红点脉动标签, 待开播黑底白字徽章 - hover抬升2px + 阴影, 淡棕描边高亮 管理页: - stat卡片: 1px边框+3px彩色顶线 - 表格卡片化: borderRadius 12, 统一白底+边框 - 表单/设置: 统一圆角8px, 大内边距36px 播放页: - #1A1814暗底, 毛玻璃顶栏 - 视频圆角12px + boxShadow景深 - document.title动态标题 登录页: 56px内边距, 品牌居中, 返回链接
This commit is contained in:
1 parent
f0b8c2d64f
commit
2685ebdd47
11 files changed
+486
-553
No files matched your search
@@ -1,18 +1,11 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { Row, Col, Card, Typography, Tag, Skeleton, Empty, Divider } from 'antd'
|
||||
import { FireOutlined, ClockCircleOutlined, VideoCameraOutlined } from '@ant-design/icons'
|
||||
import { Row, Col, Tag, Skeleton } from 'antd'
|
||||
import { VideoCameraOutlined } from '@ant-design/icons'
|
||||
import { fetchStreams, type StreamInfo } from '../../api/streams'
|
||||
import { useBrand } from '../../brand/BrandContext'
|
||||
|
||||
const { Title, Text } = Typography
|
||||
|
||||
const statusMeta: Record<string, { color: string; label: string; icon: React.ReactNode }> = {
|
||||
live: { color: 'red', label: 'LIVE', icon: <FireOutlined /> },
|
||||
pending: { color: 'blue', label: '待开播', icon: <ClockCircleOutlined /> },
|
||||
ended: { color: 'default', label: '已结束', icon: null },
|
||||
cancelled: { color: 'default', label: '已取消', icon: null },
|
||||
}
|
||||
const liveDot = { width: 8, height: 8, borderRadius: '50%', background: '#E53935', display: 'inline-block', marginRight: 6, boxShadow: '0 0 0 2px rgba(229,57,53,0.2)' }
|
||||
|
||||
export default function HomePage() {
|
||||
const { brand } = useBrand()
|
||||
@@ -25,138 +18,181 @@ export default function HomePage() {
|
||||
}, [])
|
||||
|
||||
const sorted = [...streams].sort((a, b) => {
|
||||
const order: Record<string, number> = { live: 0, pending: 1, ended: 2, cancelled: 3 }
|
||||
return (order[a.status] ?? 9) - (order[b.status] ?? 9)
|
||||
const o: Record<string, number> = { live: 0, pending: 1, ended: 2, cancelled: 3 }
|
||||
return (o[a.status] ?? 9) - (o[b.status] ?? 9)
|
||||
})
|
||||
|
||||
return (
|
||||
<div style={{ minHeight: '100vh', background: '#F6F3ED', display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{
|
||||
background: 'linear-gradient(180deg, #FCFAF7 0%, #F6F3ED 100%)',
|
||||
borderBottom: '1px solid #E6E0D6',
|
||||
padding: '64px 48px 56px',
|
||||
<div style={{ minHeight: '100vh', background: '#F9F7F4' }}>
|
||||
{/* Hero */}
|
||||
<section style={{
|
||||
padding: '96px 48px 80px',
|
||||
maxWidth: 1200, margin: '0 auto',
|
||||
}}>
|
||||
<div style={{ maxWidth: 1200, margin: '0 auto' }}>
|
||||
{brand.brand_logo_url && (
|
||||
<img src={brand.brand_logo_url} alt={brand.brand_name}
|
||||
style={{ height: 44, marginBottom: 20 }} />
|
||||
)}
|
||||
<Title style={{
|
||||
margin: 0, fontWeight: 600, fontSize: 40, letterSpacing: -1.5, lineHeight: 1.2,
|
||||
fontFamily: '"Source Serif 4", "Noto Serif SC", Georgia, serif',
|
||||
{brand.brand_logo_url && (
|
||||
<img src={brand.brand_logo_url} alt={brand.brand_name}
|
||||
style={{ height: 36, marginBottom: 24, display: 'block' }} />
|
||||
)}
|
||||
<h1 style={{
|
||||
fontSize: 'clamp(36px, 5vw, 56px)',
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.1,
|
||||
letterSpacing: '-0.03em',
|
||||
margin: 0,
|
||||
color: '#1C1A17',
|
||||
}}>
|
||||
{brand.brand_name}
|
||||
</h1>
|
||||
{brand.brand_tagline && (
|
||||
<p style={{
|
||||
fontSize: 'clamp(16px, 2vw, 20px)',
|
||||
color: '#5E5A52', marginTop: 16,
|
||||
fontWeight: 400, lineHeight: 1.5,
|
||||
}}>
|
||||
{brand.brand_name}
|
||||
</Title>
|
||||
{brand.brand_tagline && (
|
||||
<Text style={{ fontSize: 18, marginTop: 12, display: 'block', fontWeight: 400, color: '#5C5952' }}>
|
||||
{brand.brand_tagline}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{brand.brand_tagline}
|
||||
</p>
|
||||
)}
|
||||
</section>
|
||||
|
||||
<div style={{ flex: 1, maxWidth: 1200, margin: '0 auto', width: '100%', padding: '44px 48px' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 28 }}>
|
||||
<Title level={3} style={{ margin: 0, fontWeight: 600 }}>直播频道</Title>
|
||||
<Text type="secondary" style={{ fontSize: 15 }}>共 {sorted.length} 个</Text>
|
||||
{/* Streams */}
|
||||
<section style={{
|
||||
maxWidth: 1200, margin: '0 auto',
|
||||
padding: '0 48px 96px',
|
||||
}}>
|
||||
<div style={{
|
||||
display: 'flex', alignItems: 'baseline', justifyContent: 'space-between',
|
||||
marginBottom: 40, paddingBottom: 16,
|
||||
borderBottom: '1px solid #EBE5DB',
|
||||
}}>
|
||||
<h2 style={{ fontSize: 22, fontWeight: 600, margin: 0, letterSpacing: '-0.02em' }}>
|
||||
直播频道
|
||||
</h2>
|
||||
<span style={{ fontSize: 14, color: '#949088' }}>
|
||||
{sorted.length} 个节目
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<Row gutter={[28, 28]}>
|
||||
{[1, 2, 3, 4, 5, 6].map(i => (
|
||||
<Col key={i} xs={24} sm={12} md={8} lg={8}>
|
||||
<Card style={{ borderRadius: 12 }}><Skeleton active paragraph={{ rows: 3 }} /></Card>
|
||||
<Row gutter={[32, 40]}>
|
||||
{[1,2,3,4,5,6].map(i => (
|
||||
<Col key={i} xs={24} sm={12} lg={8}>
|
||||
<div style={{ background: '#fff', borderRadius: 10, overflow: 'hidden' }}>
|
||||
<div style={{ height: 200, background: '#F3F0EC' }} />
|
||||
<div style={{ padding: '20px 24px 24px' }}>
|
||||
<Skeleton active paragraph={{ rows: 2 }} title={{ width: '60%' }} />
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
) : sorted.length === 0 ? (
|
||||
<div style={{
|
||||
textAlign: 'center', padding: '80px 0',
|
||||
background: '#FCFAF7', borderRadius: 12, border: '1px solid #E6E0D6',
|
||||
background: '#fff', borderRadius: 14,
|
||||
}}>
|
||||
<VideoCameraOutlined style={{ fontSize: 48, color: '#B0ABA3', marginBottom: 16 }} />
|
||||
<Title level={4} type="secondary" style={{ fontWeight: 400 }}>暂无直播</Title>
|
||||
<Text type="secondary">当前没有正在播出或排期的直播节目</Text>
|
||||
<VideoCameraOutlined style={{ fontSize: 40, color: '#C4BCB0', marginBottom: 16 }} />
|
||||
<h3 style={{ fontSize: 18, fontWeight: 500, color: '#5E5A52' }}>暂无直播</h3>
|
||||
<p style={{ color: '#949088', fontSize: 14, marginTop: 4 }}>当前没有正在播出或排期的直播节目</p>
|
||||
</div>
|
||||
) : (
|
||||
<Row gutter={[28, 28]}>
|
||||
<Row gutter={[32, 40]}>
|
||||
{sorted.map(s => {
|
||||
const meta = statusMeta[s.status] ?? statusMeta.pending
|
||||
const isLive = s.status === 'live'
|
||||
const isPending = s.status === 'pending'
|
||||
return (
|
||||
<Col key={s.id} xs={24} sm={12} md={8} lg={8}>
|
||||
<Card
|
||||
hoverable
|
||||
style={{
|
||||
overflow: 'hidden',
|
||||
borderRadius: 12,
|
||||
borderColor: isLive ? '#E0C8B6' : '#E6E0D6',
|
||||
transition: 'transform 0.2s, box-shadow 0.2s, border-color 0.2s',
|
||||
}}
|
||||
bodyStyle={{ padding: '20px 24px' }}
|
||||
cover={
|
||||
<div style={{
|
||||
height: 192,
|
||||
position: 'relative',
|
||||
background: s.cover_url
|
||||
? `url(${s.cover_url}) center/cover no-repeat`
|
||||
: 'linear-gradient(135deg, #3D3226 0%, #5C4A3A 50%, #3D3226 100%)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
{!s.cover_url && (
|
||||
<VideoCameraOutlined style={{ color: 'rgba(232,227,216,0.08)', fontSize: 64 }} />
|
||||
)}
|
||||
{isLive && (
|
||||
<div style={{
|
||||
position: 'absolute', top: 14, left: 14,
|
||||
display: 'flex', alignItems: 'center', gap: 6,
|
||||
background: '#C62828', color: '#fff',
|
||||
padding: '3px 10px', borderRadius: 4,
|
||||
fontSize: 12, fontWeight: 600, letterSpacing: 0.5,
|
||||
}}>
|
||||
<span style={{
|
||||
width: 8, height: 8, borderRadius: '50%',
|
||||
background: '#fff', display: 'inline-block',
|
||||
animation: 'pulse 2s infinite',
|
||||
}} />
|
||||
LIVE
|
||||
</div>
|
||||
)}
|
||||
{!isLive && (
|
||||
<div style={{ position: 'absolute', bottom: 12, left: 12 }}>
|
||||
<Tag color={meta.color} style={{ margin: 0, fontWeight: 500, border: 0, fontSize: 12 }}>
|
||||
{meta.icon} {meta.label}
|
||||
</Tag>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
<Col key={s.id} xs={24} sm={12} lg={8}>
|
||||
<div
|
||||
onClick={() => navigate(`/watch/${s.id}`)}
|
||||
style={{
|
||||
background: '#fff',
|
||||
borderRadius: 10,
|
||||
overflow: 'hidden',
|
||||
cursor: 'pointer',
|
||||
transition: 'transform 0.2s, box-shadow 0.2s',
|
||||
border: `1px solid ${isLive ? '#E8D0BE' : '#EBE5DB'}`,
|
||||
}}
|
||||
onMouseEnter={e => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 8px 24px rgba(28,26,23,0.06)' }}
|
||||
onMouseLeave={e => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = 'none' }}
|
||||
>
|
||||
<Text strong style={{ fontSize: 16, display: 'block', marginBottom: 4 }} ellipsis>
|
||||
{s.title}
|
||||
</Text>
|
||||
<Text type="secondary" style={{ fontSize: 13, lineHeight: 1.5 }} ellipsis>
|
||||
{s.description || '暂无简介'}
|
||||
</Text>
|
||||
</Card>
|
||||
{/* Cover */}
|
||||
<div style={{
|
||||
height: 200, position: 'relative',
|
||||
background: s.cover_url
|
||||
? `url(${s.cover_url}) center/cover no-repeat`
|
||||
: '#2C2824',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
}}>
|
||||
{!s.cover_url && (
|
||||
<VideoCameraOutlined style={{ color: 'rgba(249,247,244,0.08)', fontSize: 56 }} />
|
||||
)}
|
||||
{/* Status badge */}
|
||||
{isLive && (
|
||||
<div style={{
|
||||
position: 'absolute', top: 16, left: 16,
|
||||
display: 'inline-flex', alignItems: 'center',
|
||||
background: 'rgba(229,57,53,0.92)', color: '#fff',
|
||||
padding: '4px 12px', borderRadius: 4,
|
||||
fontSize: 12, fontWeight: 600, letterSpacing: '0.04em',
|
||||
}}>
|
||||
<span style={liveDot} />LIVE
|
||||
</div>
|
||||
)}
|
||||
{isPending && (
|
||||
<div style={{
|
||||
position: 'absolute', top: 16, left: 16,
|
||||
background: '#1C1A17', color: '#F9F7F4',
|
||||
padding: '4px 12px', borderRadius: 4,
|
||||
fontSize: 12, fontWeight: 600,
|
||||
}}>
|
||||
待开播
|
||||
</div>
|
||||
)}
|
||||
{!isLive && !isPending && (
|
||||
<div style={{
|
||||
position: 'absolute', bottom: 16, left: 16,
|
||||
}}>
|
||||
<Tag color="default" style={{ margin: 0, border: 0, fontSize: 11 }}>
|
||||
{s.status === 'ended' ? '已结束' : '已取消'}
|
||||
</Tag>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Info */}
|
||||
<div style={{ padding: '20px 24px 24px' }}>
|
||||
<h3 style={{
|
||||
fontSize: 17, fontWeight: 600, margin: '0 0 6px',
|
||||
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||
letterSpacing: '-0.01em',
|
||||
}}>
|
||||
{s.title}
|
||||
</h3>
|
||||
<p style={{
|
||||
fontSize: 14, color: '#949088', margin: 0,
|
||||
overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
|
||||
lineHeight: 1.4,
|
||||
}}>
|
||||
{s.description || '暂无简介'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
)
|
||||
})}
|
||||
</Row>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div style={{
|
||||
borderTop: '1px solid #E6E0D6',
|
||||
{/* Footer */}
|
||||
<footer style={{
|
||||
borderTop: '1px solid #EBE5DB',
|
||||
padding: '24px 48px',
|
||||
textAlign: 'center',
|
||||
background: '#FCFAF7',
|
||||
background: '#fff',
|
||||
}}>
|
||||
<Text style={{ fontSize: 13, color: '#8B867D' }}>
|
||||
<span style={{ fontSize: 13, color: '#949088' }}>
|
||||
{brand.brand_name} © {new Date().getFullYear()}
|
||||
</Text>
|
||||
</div>
|
||||
</span>
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { Select, Button, Typography, Space, Tag, Spin, Skeleton, Empty, message } from 'antd'
|
||||
import { Select, Button, Typography, Space, Tag, Spin, Empty, message } from 'antd'
|
||||
import { ArrowLeftOutlined, WifiOutlined, SignalFilled } from '@ant-design/icons'
|
||||
import Hls from 'hls.js'
|
||||
import { getWatchUrls, type WatchInfo, type LineInfo } from '../../api/streams'
|
||||
import { useBrand } from '../../brand/BrandContext'
|
||||
|
||||
const { Title, Text } = Typography
|
||||
const { Text } = Typography
|
||||
|
||||
export default function WatchPage() {
|
||||
const { brand } = useBrand()
|
||||
@@ -56,28 +56,26 @@ export default function WatchPage() {
|
||||
const quality = activeQuality ? line.qualities.find(q => q.label === activeQuality) : line.qualities[0]
|
||||
if (!quality) return
|
||||
if (hls) hls.destroy()
|
||||
const url = quality.url
|
||||
if (Hls.isSupported()) {
|
||||
const hi = new Hls({ enableWorker: false, lowLatencyMode: false })
|
||||
hi.loadSource(url); hi.attachMedia(videoRef.current!)
|
||||
hi.loadSource(quality.url); hi.attachMedia(videoRef.current!)
|
||||
hi.on(Hls.Events.MANIFEST_PARSED, () => { videoRef.current?.play().catch(() => {}) })
|
||||
hi.on(Hls.Events.ERROR, (_e, d) => { if (d.fatal) message.warning('播放异常,尝试切换线路...') })
|
||||
setHls(hi)
|
||||
} else if (videoRef.current!.canPlayType('application/vnd.apple.mpegurl')) {
|
||||
videoRef.current!.src = url
|
||||
videoRef.current!.src = quality.url
|
||||
}
|
||||
}, [activeLine, activeQuality, info])
|
||||
|
||||
useEffect(() => { document.title = info ? `${info.title} - ${brand.brand_name}` : brand.brand_name }, [info, brand])
|
||||
|
||||
if (loading) return (
|
||||
<div style={{ minHeight: '100vh', background: '#1A1815', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<div style={{ minHeight: '100vh', background: '#1A1814', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<Spin size="large" />
|
||||
</div>
|
||||
)
|
||||
|
||||
if (!info) return (
|
||||
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#F6F3ED' }}>
|
||||
<div style={{ minHeight: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#F9F7F4' }}>
|
||||
<Empty description="未找到该直播" />
|
||||
</div>
|
||||
)
|
||||
@@ -85,52 +83,46 @@ export default function WatchPage() {
|
||||
const statusLabel = info.status === 'live' ? 'LIVE' : info.status === 'pending' ? '待开播' : info.status === 'ended' ? '已结束' : info.status
|
||||
|
||||
return (
|
||||
<div style={{ minHeight: '100vh', background: '#1A1815', display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ minHeight: '100vh', background: '#1A1814', display: 'flex', flexDirection: 'column' }}>
|
||||
{/* Top bar */}
|
||||
<div style={{
|
||||
height: 56, minHeight: 56,
|
||||
background: 'rgba(26,24,21,0.98)',
|
||||
borderBottom: '1px solid rgba(230,224,214,0.06)',
|
||||
height: 52, minHeight: 52,
|
||||
background: 'rgba(26,24,20,0.97)',
|
||||
backdropFilter: 'blur(12px)',
|
||||
borderBottom: '1px solid rgba(235,229,219,0.06)',
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
padding: '0 28px',
|
||||
backdropFilter: 'blur(12px)',
|
||||
}}>
|
||||
<Space size={16}>
|
||||
<Button type="text" icon={<ArrowLeftOutlined />} style={{ color: '#8B867D' }}
|
||||
onClick={() => navigate('/')}>
|
||||
{brand.brand_name}
|
||||
</Button>
|
||||
<div style={{ width: 1, height: 20, background: 'rgba(230,224,214,0.1)' }} />
|
||||
<div>
|
||||
<Text style={{ color: '#E6E0D6', fontSize: 15, fontWeight: 500 }}>{info.title}</Text>
|
||||
<Tag color={info.status === 'live' ? 'green' : 'default'}
|
||||
style={{ marginLeft: 10, fontWeight: 600, fontSize: 11 }}>
|
||||
{statusLabel}
|
||||
</Tag>
|
||||
</div>
|
||||
<Button type="text" icon={<ArrowLeftOutlined />} style={{ color: '#949088' }}
|
||||
onClick={() => navigate('/')}>{brand.brand_name}</Button>
|
||||
<div style={{ width: 1, height: 18, background: 'rgba(235,229,219,0.1)' }} />
|
||||
<Text style={{ color: '#EBE5DB', fontSize: 14, fontWeight: 500 }}>{info.title}</Text>
|
||||
<Tag color={info.status === 'live' ? 'green' : 'default'} style={{ fontWeight: 600, fontSize: 11 }}>
|
||||
{statusLabel}
|
||||
</Tag>
|
||||
</Space>
|
||||
<Space size={16}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 6, color: '#8B867D', fontSize: 13 }}>
|
||||
<SignalFilled style={{ color: info.multicast_available ? '#5B8C5A' : '#5C5952', fontSize: 12 }} />
|
||||
<Text style={{ color: '#949088', fontSize: 13, display: 'flex', alignItems: 'center', gap: 6 }}>
|
||||
<SignalFilled style={{ color: info.multicast_available ? '#5B8C5A' : '#5E5A52', fontSize: 12 }} />
|
||||
{info.multicast_available ? '组播' : '单播'}
|
||||
</div>
|
||||
</Text>
|
||||
<Select value={activeQuality} onChange={setActiveQuality} style={{ width: 100 }} size="small"
|
||||
options={info.qualities.map(q => ({ value: q.label, label: q.label }))} placeholder="清晰度" />
|
||||
<Select value={activeLine} onChange={setActiveLine} style={{ width: 160 }} size="small"
|
||||
options={info.lines.map(l => ({ value: l.node_id, label: `${l.node_name}` }))}
|
||||
<Select value={activeLine} onChange={setActiveLine} style={{ width: 150 }} size="small"
|
||||
options={info.lines.map(l => ({ value: l.node_id, label: l.node_name }))}
|
||||
prefix={<WifiOutlined />} placeholder="线路" />
|
||||
</Space>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
padding: '32px',
|
||||
}}>
|
||||
{/* Video */}
|
||||
<div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 40 }}>
|
||||
<div style={{
|
||||
width: '100%', maxWidth: 1280,
|
||||
aspectRatio: '16 / 9', maxHeight: 'calc(100vh - 120px)',
|
||||
background: '#0A0A08', position: 'relative',
|
||||
borderRadius: 10, overflow: 'hidden',
|
||||
boxShadow: '0 8px 40px rgba(0,0,0,0.4)',
|
||||
aspectRatio: '16/9', maxHeight: 'calc(100vh - 132px)',
|
||||
background: '#0A0A08', borderRadius: 12, overflow: 'hidden',
|
||||
position: 'relative',
|
||||
boxShadow: '0 12px 48px rgba(0,0,0,0.5)',
|
||||
}}>
|
||||
<video ref={videoRef} controls autoPlay playsInline
|
||||
style={{ width: '100%', height: '100%', objectFit: 'contain', display: 'block' }} />
|
||||
@@ -138,12 +130,12 @@ export default function WatchPage() {
|
||||
<div style={{
|
||||
position: 'absolute', inset: 0,
|
||||
display: 'flex', alignItems: 'center', justifyContent: 'center',
|
||||
background: 'rgba(10,10,8,0.9)',
|
||||
background: 'rgba(10,10,8,0.92)',
|
||||
}}>
|
||||
<Space direction="vertical" align="center" size={16}>
|
||||
<Spin size="large" />
|
||||
<Text style={{
|
||||
color: '#8B867D', fontSize: 17,
|
||||
color: '#949088', fontSize: 17,
|
||||
fontFamily: '"Source Serif 4", "Noto Serif SC", Georgia, serif',
|
||||
}}>
|
||||
等待主播开播...
|
||||
|
||||
Reference in new issue
Block a user