feat: KPI细条新增两项完成率 + 侧边菜单加两个占位项

This commit is contained in:
simonkoson
2026-05-25 13:45:00 +08:00
parent 72ae73764a
commit 2881b866a6
3 changed files with 90 additions and 2 deletions
+42 -1
View File
@@ -7,6 +7,8 @@ import {
BarChartOutlined,
PictureOutlined,
UploadOutlined,
TargetOutlined,
AimOutlined,
} from '@ant-design/icons'
import useAuthStore from '../../stores/authStore'
import { listEpisodes } from '../../services/episodeService'
@@ -54,6 +56,32 @@ function getShortTitle(title) {
return title.length > 9 ? title.slice(0, 9) + '...' : title
}
/**
* 计算当年完成率(纯前端,量纲已确认为 0~1 小数直接相除)
* - "当年"= 当前自然年(new Date().getFullYear()
* - avg(audience_share) 当年已录期 ÷ base/stretch_target
* - 无数据时始终返回 { base: '—', stretch: '—' }
* - 完成率可 >100% 正常显示
*/
function calcCompletionRate(episodes, targets) {
const yearInt = new Date().getFullYear()
const yearEpisodes = episodes.filter(e => {
const airYear = new Date(e.air_date).getFullYear()
return airYear === yearInt && e.audience_share != null
})
const target = (targets || []).find(t => Number(t.year) === yearInt)
if (!yearEpisodes.length || !target) return { base: '—', stretch: '—' }
const avgShare = yearEpisodes.reduce((sum, e) => sum + Number(e.audience_share), 0) / yearEpisodes.length
const baseRate = avgShare / Number(target.base_target)
const stretchRate = avgShare / Number(target.stretch_target)
return {
base: (baseRate * 100).toFixed(1) + '%',
stretch: (stretchRate * 100).toFixed(1) + '%',
}
}
function Dashboard() {
const { user } = useAuthStore()
const [episodes, setEpisodes] = useState([])
@@ -95,7 +123,8 @@ function Dashboard() {
setCoverModalOpen(false)
}
// KPI 数据
// KPI 数据(扩为 5 项:原有 3 项 + 年度完成率 2 项)
const completion = calcCompletionRate(episodes, targets)
const kpiData = [
{
icon: <EyeOutlined style={{ color: '#6b8e6b', fontSize: 14 }} />,
@@ -115,6 +144,18 @@ function Dashboard() {
label: '年度目标',
value: targets.length || '--',
},
{
icon: <TargetOutlined style={{ color: '#7b5e9e', fontSize: 14 }} />,
bg: '#f3e5f5',
label: '基础目标完成率',
value: completion.base,
},
{
icon: <AimOutlined style={{ color: '#c0584f', fontSize: 14 }} />,
bg: '#fce4ec',
label: '摸高目标完成率',
value: completion.stretch,
},
]
return (