- 服务端补下发:dto.EventResultRow 与 athleteStandingDTO 各加 logoPath, 分别取「该行单位」与「该运动员所属单位」的 teams.logo_path;空串统一收敛为 null - 大屏抽出 TeamLogo.vue(1em / object-fit:contain / 加载失败保留占位、@load 复原), 原先在积分榜与团体奖牌榜各写一遍的逻辑收敛成一份,四处复用 - 分项成绩页:单位列名字前显示 logo;个人积分榜:运动员姓名前显示其单位 logo - guards/mock 同步解析与补字段;补 11 条测试(类型解析 + SFC 模板断言) 顺带修:管理端示例数据 athleteStandings 缺新必填字段导致的 vue-tsc 报错。 自检:服务端 11 包全绿;前端 vue-tsc + build、node --test 80/80。
33 lines
840 B
Vue
33 lines
840 B
Vue
<script setup lang="ts">
|
|
import { resolveAssetUrl } from '@/shared'
|
|
|
|
defineProps<{ path: string | null | undefined }>()
|
|
|
|
// 加载失败时不显示破图:藏起来但保留占位,重新加载出图后再放出来,
|
|
// 两种情况行内的名字与行高都不会跳动。
|
|
function setVisible(event: Event, visible: boolean): void {
|
|
;(event.target as HTMLImageElement).style.visibility = visible ? '' : 'hidden'
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<img
|
|
v-if="path"
|
|
class="team-logo"
|
|
:src="resolveAssetUrl(path)"
|
|
alt=""
|
|
@error="setVisible($event, false)"
|
|
@load="setVisible($event, true)"
|
|
/>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* 尺寸用 em 跟着所在行字号浮动:既不会撑开行高,也不会挤动名次/分数列。 */
|
|
.team-logo {
|
|
flex: none;
|
|
width: 1em;
|
|
height: 1em;
|
|
object-fit: contain;
|
|
}
|
|
</style>
|