feat(player): 新增长页面一键回到顶部按钮

- 在 MainLayout 主滚动区挂载浮动回顶按钮,投注列表与赛事详情等长页通用

- 滚动超过阈值后显示,支持平滑回顶与底部导航避让

- 补充中/英/马来语文案 common.back_to_top

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-16 10:07:09 +08:00
parent 2a8b8415e7
commit 06d85953ba
6 changed files with 123 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
<script setup lang="ts">
import { toRef } from 'vue';
import { useI18n } from 'vue-i18n';
import { useBackToTop } from '../composables/useBackToTop';
const props = defineProps<{
scrollEl: HTMLElement | null;
aboveNav?: boolean;
}>();
const { t } = useI18n();
const { visible, scrollToTop } = useBackToTop(toRef(props, 'scrollEl'));
</script>
<template>
<Transition name="back-top-fade">
<button
v-if="visible"
type="button"
class="back-top-btn"
:class="{ 'above-nav': aboveNav }"
:aria-label="t('common.back_to_top')"
@click="scrollToTop"
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path
d="M12 5.5 6 11.5l1.4 1.4 3.6-3.6V18h2V9.3l3.6 3.6 1.4-1.4-6-6Z"
fill="currentColor"
/>
</svg>
</button>
</Transition>
</template>
<style scoped>
.back-top-btn {
position: fixed;
right: 16px;
bottom: calc(12px + env(safe-area-inset-bottom, 0px));
z-index: 120;
display: flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
border-radius: 50%;
border: 1px solid var(--border-gold-soft, rgba(200, 168, 78, 0.35));
background: rgba(17, 17, 17, 0.92);
color: var(--primary-light, #c8a84e);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
cursor: pointer;
transition: background 0.2s, transform 0.2s;
}
.back-top-btn.above-nav {
bottom: calc(68px + env(safe-area-inset-bottom, 0px));
}
.back-top-btn:active {
background: rgba(200, 168, 78, 0.16);
transform: scale(0.96);
}
.back-top-btn svg {
width: 22px;
height: 22px;
}
.back-top-fade-enter-active,
.back-top-fade-leave-active {
transition: opacity 0.2s ease, transform 0.2s ease;
}
.back-top-fade-enter-from,
.back-top-fade-leave-to {
opacity: 0;
transform: translateY(8px);
}
</style>