import { useState, useEffect } from 'react' import { Row, Col, Card, Avatar, Tooltip, Button } from 'antd' import { BarChartOutlined, EyeOutlined, CalendarOutlined, FireOutlined, PictureOutlined, } from '@ant-design/icons' import useAuthStore from '../../stores/authStore' import { listEpisodes } from '../../services/episodeService' import { listTargets } from '../../services/yearlyTargetService' import './Dashboard.css' /** * 收视份额颜色判定(极易写反,禁止凭直觉): * audience_share > stretch_target → 🔴 红(优秀) * base_target ≤ audience_share ≤ stretch_target → 🔵 蓝(达标) * audience_share < base_target → 🟢 绿(待提升) * 判色取该期 air_date 所属年份的 yearly_targets 行(不是当前年)。 */ function getShareColor(share, targets, airYear) { // 强制转数值,避免后端返回字符串导致数值比较失败 const n = Number(share) const target = targets.find(t => Number(t.year) === Number(airYear)) if (!target) return '#999' if (isNaN(n)) return '#999' const stretch = Number(target.stretch_target) const base = Number(target.base_target) if (n > stretch) return '#c0584f' // 红=超过摸高目标(优秀) if (n >= base) return '#5b8db8' // 蓝=未达摸高目标(达标) return '#7aa874' // 绿=未达基础目标(待提升) } function getBarHeight(share) { return Math.round((share / 1.0) * 180) } function getShortTitle(title) { return title.length > 12 ? title.slice(0, 12) + '...' : title } function Dashboard() { const { user } = useAuthStore() const [episodes, setEpisodes] = useState([]) const [targets, setTargets] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { Promise.all([ listEpisodes(9), listTargets(), ]).then(([epData, tgtData]) => { // 按 air_date 倒序取前 9 const sorted = (epData || []).sort((a, b) => new Date(b.air_date) - new Date(a.air_date)).slice(0, 9) setEpisodes(sorted) setTargets(tgtData || []) setLoading(false) }).catch(() => { setLoading(false) }) }, []) // 显示最近有份额数据的期次(最多9个,不够用真实数据补位) const hasShare = episodes.filter(e => e.audience_share != null) const displayEpisodes = hasShare.length >= 5 ? hasShare.slice(0, 9) : episodes.slice(0, Math.max(9, hasShare.length || 5)) const bestEpisode = [...displayEpisodes].filter(e => e.audience_share != null).sort((a, b) => b.audience_share - a.audience_share)[0] const showChangeCoverBtn = user?.role === 'zhipianren' || user?.role === 'zebian' return (
第 {bestEpisode.episode_number} 期 {bestEpisode.program_name} · 收视份额 {bestEpisode.audience_share}
) : (暂无收视数据
)}热点雷达 · Phase 4c
编导个人首页核心功能,Phase 4c 实施排播计划 · Phase 4b
甘特图排期使用 frappe-gantt 实现,Phase 4b 开发