fix(F006): fix rating/score page runtime crash from undefined supplierLevel/score
This commit is contained in:
parent
512111af3e
commit
6571eadc20
@ -62,17 +62,17 @@ const filtered = computed(() => {
|
||||
return rs
|
||||
})
|
||||
|
||||
// 等级统计 + 分数均值
|
||||
// 统计 + 平均分 (用可选链防御 API 字段缺失)
|
||||
const stats = computed(() => {
|
||||
const rs = filtered.value
|
||||
const aCount = rs.filter(r => r.supplierLevel.startsWith('A')).length
|
||||
const avgFinal = rs.length ? Math.round(rs.reduce((s, r) => s + r.finalScore, 0) / rs.length) : 0
|
||||
const avgClient = rs.length ? Math.round(rs.reduce((s, r) => s + r.clientScore, 0) / rs.length) : 0
|
||||
const aCount = rs.filter(r => r.supplierLevel?.startsWith('A') ?? false).length
|
||||
const avgFinal = rs.length ? Math.round(rs.reduce((s, r) => s + (r.finalScore || 0), 0) / rs.length) : 0
|
||||
const avgClient = rs.length ? Math.round(rs.reduce((s, r) => s + (r.clientScore || 0), 0) / rs.length) : 0
|
||||
return [
|
||||
{ label: '评级总数', value: rs.length, icon: 'Medal', color: 'var(--brand)' },
|
||||
{ label: 'A 战略级', value: aCount, icon: 'Top', color: 'var(--green)' },
|
||||
{ label: '平均最终得分', value: avgFinal, icon: 'DataAnalysis', color: 'var(--amber)' },
|
||||
{ label: '平均客户评价', value: avgClient, icon: 'ChatLineSquare', color: 'var(--purple)' }
|
||||
{ label: '平均最终得分', value: avgFinal, icon: 'Trophy', color: 'var(--amber)' },
|
||||
{ label: '平均客户评价', value: avgClient, icon: 'Star', color: 'var(--purple)' }
|
||||
]
|
||||
})
|
||||
|
||||
@ -98,12 +98,11 @@ async function onBatchExport() {
|
||||
}
|
||||
function onExport() { ElMessage.success(`已发起导出 (前端示例, 共 ${filtered.value.length} 条)`) }
|
||||
|
||||
// 等级 st-pill 颜色映射
|
||||
function levelPill(r: RatingRow) {
|
||||
if (r.supplierLevel.startsWith('A')) return { label: r.supplierLevel, color: 'var(--st-ok-fg)', bg: 'var(--st-ok-bg)' }
|
||||
if (r.supplierLevel.startsWith('B')) return { label: r.supplierLevel, color: 'var(--brand)', bg: 'var(--brand-soft)' }
|
||||
if (r.supplierLevel.startsWith('C')) return { label: r.supplierLevel, color: 'var(--st-warn-fg)', bg: 'var(--st-warn-bg)' }
|
||||
return { label: r.supplierLevel, color: 'var(--st-err-fg)', bg: 'var(--st-err-bg)' }
|
||||
if (r.supplierLevel?.startsWith('A')) return { label: r.supplierLevel, color: 'var(--st-ok-fg)', bg: 'var(--st-ok-bg)' }
|
||||
if (r.supplierLevel?.startsWith('B')) return { label: r.supplierLevel, color: 'var(--brand)', bg: 'var(--brand-soft)' }
|
||||
if (r.supplierLevel?.startsWith('C')) return { label: r.supplierLevel, color: 'var(--st-warn-fg)', bg: 'var(--st-warn-bg)' }
|
||||
return { label: r.supplierLevel ?? '-', color: 'var(--st-err-fg)', bg: 'var(--st-err-bg)' }
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
@ -115,7 +114,6 @@ onMounted(load)
|
||||
<el-button @click="onExport">导出明细</el-button>
|
||||
</PageHeader>
|
||||
|
||||
<!-- 顶部统计卡 -->
|
||||
<div class="stats-grid">
|
||||
<div v-for="(s, i) in stats" :key="i" class="stat-card">
|
||||
<div class="stat-icon" :style="{ color: s.color, background: 'var(--brand-soft)' }">
|
||||
@ -131,7 +129,6 @@ onMounted(load)
|
||||
<SearchBar v-model:filters="filters" :fields="searchFields" @search="onSearch" @reset="onReset" />
|
||||
|
||||
<div class="rr-list-card">
|
||||
<!-- 批量操作栏 -->
|
||||
<div class="batch-bar" :class="{ 'has-selection': selection.length > 0 }">
|
||||
<span v-if="selection.length > 0" class="batch-count">已选 <strong>{{ selection.length }}</strong> 条评级</span>
|
||||
<span v-else class="batch-hint">勾选后可批量导出</span>
|
||||
@ -147,7 +144,7 @@ onMounted(load)
|
||||
@limit-change="(l: number) => { limit = l; page = 1; load() }">
|
||||
<template #level="{ row }">
|
||||
<span class="st-pill" :style="{ color: levelPill(row).color, background: levelPill(row).bg }">
|
||||
<span class="st-dot" /><span class="truncate-text">{{ levelPill(row).label }}</span>
|
||||
<span class="st-dot"></span><span class="truncate-text">{{ levelPill(row).label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
<template #award="{ row }">
|
||||
@ -174,8 +171,6 @@ onMounted(load)
|
||||
|
||||
<style scoped lang="scss">
|
||||
.rr-page { padding: 16px; }
|
||||
|
||||
/* 顶部统计卡 */
|
||||
.stats-grid {
|
||||
display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
@ -67,7 +67,7 @@ const stats = computed(() => {
|
||||
const done = rs.filter(r => r.status === 1).length
|
||||
const pending = rs.length - done
|
||||
const avg = rs.filter(r => r.status === 1).length
|
||||
? Math.round(rs.filter(r => r.status === 1).reduce((s, r) => s + r.score, 0) / rs.filter(r => r.status === 1).length)
|
||||
? Math.round(rs.filter(r => r.status === 1).reduce((s, r) => s + (r.score || 0), 0) / rs.filter(r => r.status === 1).length)
|
||||
: 0
|
||||
return [
|
||||
{ label: '评分记录', value: rs.length, icon: 'Document', color: 'var(--brand)' },
|
||||
|
||||
Loading…
Reference in New Issue
Block a user