结构优化:
- 新增 mobile-game/config.js:集中模块静态配置(资源路径、排行榜端点、
hero meta、子标签页定义),消除散落在各组件的硬编码
- 新增 composables/useLocale.js:共享语言辅助(t/isZh/pick),
消除 6 个组件各自重复定义的 L() helper
- 文案全部迁入 i18n locale(mobileGame 命名空间),消除模板内联 L('中','英')
- 数据文件 versions.js 去除 {zh,en} 对象,文案改由 i18n 键(tracks/versions)取
- 各组件改为读 config + t(),不再直接 useI18n,降低与 i18n 实现的耦合
headless 验证:中文(hero/meta/team/timeline/3D置顶) + 英文切换 + 切回中文 全通过
66 lines
1.4 KiB
Vue
66 lines
1.4 KiB
Vue
<script setup>
|
|
import { useLocale } from '../../../composables/useLocale.js'
|
|
|
|
const props = defineProps({
|
|
tabs: { type: Array, required: true }, // [{ id, labelKey }]
|
|
modelValue: { type: String, required: true }
|
|
})
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const { t } = useLocale()
|
|
</script>
|
|
|
|
<template>
|
|
<div class="subtabs">
|
|
<button
|
|
v-for="tab in tabs"
|
|
:key="tab.id"
|
|
type="button"
|
|
class="subtabs__btn"
|
|
:class="{ 'is-active': modelValue === tab.id }"
|
|
@click="emit('update:modelValue', tab.id)"
|
|
>
|
|
{{ t(tab.labelKey) }}
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.subtabs {
|
|
display: flex;
|
|
gap: var(--space-xs);
|
|
border-bottom: 1px solid var(--border);
|
|
margin-bottom: var(--space-lg);
|
|
overflow-x: auto;
|
|
scrollbar-width: none;
|
|
}
|
|
.subtabs::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
.subtabs__btn {
|
|
position: relative;
|
|
padding: var(--space-sm) var(--space-md);
|
|
font-size: 0.92rem;
|
|
font-weight: 500;
|
|
color: var(--text-secondary);
|
|
white-space: nowrap;
|
|
transition: color var(--transition);
|
|
}
|
|
.subtabs__btn:hover {
|
|
color: var(--text-primary);
|
|
}
|
|
.subtabs__btn.is-active {
|
|
color: var(--accent);
|
|
}
|
|
.subtabs__btn.is-active::after {
|
|
content: '';
|
|
position: absolute;
|
|
left: var(--space-md);
|
|
right: var(--space-md);
|
|
bottom: -1px;
|
|
height: 2px;
|
|
background: var(--accent);
|
|
border-radius: 2px;
|
|
}
|
|
</style>
|