diff --git a/frontend/public/default-avatar.svg b/frontend/public/default-avatar.svg index 8687dbe..558cc22 100644 --- a/frontend/public/default-avatar.svg +++ b/frontend/public/default-avatar.svg @@ -1,4 +1,11 @@ diff --git a/frontend/public/game-placeholder.svg b/frontend/public/game-placeholder.svg index 64043e1..55490cc 100644 --- a/frontend/public/game-placeholder.svg +++ b/frontend/public/game-placeholder.svg @@ -1,5 +1,17 @@ diff --git a/frontend/src/assets/mobile.css b/frontend/src/assets/mobile.css index f34789f..1e5e12b 100644 --- a/frontend/src/assets/mobile.css +++ b/frontend/src/assets/mobile.css @@ -51,3 +51,105 @@ .mobile-app * { -webkit-tap-highlight-color: transparent; } + +/* ============ 细节体验优化(全局) ============ */ + +/* 1. 按钮点击反馈:统一按压缩放 */ +.mobile-app .van-button:active { + opacity: 0.85; + transform: scale(0.98); +} +.mobile-app .van-button { + transition: opacity 0.15s, transform 0.15s; +} + +/* 2. 可点击卡片按压反馈(约定:凡 .clickable 或带 @click 的卡片建议加此类) */ +.mobile-app .clickable { + transition: transform 0.12s, box-shadow 0.12s; + cursor: pointer; +} +.mobile-app .clickable:active { + transform: scale(0.98); +} + +/* 3. van-empty 空状态:图标加品牌色淡背景,提升存在感 */ +.mobile-app .van-empty__image { + opacity: 0.85; +} +.mobile-app .van-empty__description { + color: var(--gg-text-muted); + font-size: 13px; +} + +/* 4. 列表项分隔线统一为更柔和的颜色 */ +.mobile-app .van-cell { + border-color: var(--gg-border); +} +.mobile-app .van-cell::after { + border-color: var(--gg-border) !important; +} + +/* 5. 全局卡片阴影统一(覆盖各页面自定义的过深/过浅阴影) */ +.mobile-app .van-popup, +.mobile-app .van-action-sheet { + box-shadow: 0 -4px 24px rgba(15, 23, 42, 0.08); +} + +/* 6. Tab 栏激活态下划线更柔和 */ +.mobile-app .van-tabs__line { + background: var(--gg-gradient); + border-radius: 3px; +} + +/* 7. 输入框聚焦态:边框过渡更顺滑 */ +.mobile-app .van-field { + transition: border-color 0.2s; +} + +/* 8. 骨架屏占位(list 加载时,配合 van-skeleton 或 .skeleton 类使用) */ +.mobile-app .skeleton-block { + background: linear-gradient(90deg, var(--gg-bg-elevated) 25%, var(--gg-bg) 37%, var(--gg-bg-elevated) 63%); + background-size: 400% 100%; + animation: skeleton-loading 1.4s ease infinite; + border-radius: var(--gg-radius-sm); +} +@keyframes skeleton-loading { + 0% { background-position: 100% 50%; } + 100% { background-position: 0 50%; } +} + +/* 9. 滚动容器:隐藏滚动条但保留滚动能力(移动端原生体验) */ +.mobile-app .scroll-hide { + scrollbar-width: none; + -ms-overflow-style: none; +} +.mobile-app .scroll-hide::-webkit-scrollbar { + display: none; +} + +/* 10. 文字溢出省略工具类(列表标题常用) */ +.mobile-app .ellipsis { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.mobile-app .ellipsis-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* 11. 页面切换淡入动画(router-view 配合) */ +.mobile-app .mobile-content { + animation: page-fade-in 0.25s ease; +} +@keyframes page-fade-in { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: translateY(0); } +} + +/* 12. Toast 在刘海屏顶部不被遮挡 */ +.mobile-app .van-toast { + top: calc(env(safe-area-inset-top, 0px) + 10%); +} diff --git a/frontend/src/components-mobile/MobileIcon.vue b/frontend/src/components-mobile/MobileIcon.vue new file mode 100644 index 0000000..983cf87 --- /dev/null +++ b/frontend/src/components-mobile/MobileIcon.vue @@ -0,0 +1,113 @@ + + + + + + + + diff --git a/frontend/src/components-mobile/bet/BetListMobile.vue b/frontend/src/components-mobile/bet/BetListMobile.vue index 347ea80..d2a9327 100644 --- a/frontend/src/components-mobile/bet/BetListMobile.vue +++ b/frontend/src/components-mobile/bet/BetListMobile.vue @@ -6,6 +6,7 @@ import { listBets, getBet, getBetOptions, getBetEntries, placeBet, createBet, cl import { useUserStore } from '@/stores/user' import type { Bet, BetOption, BetEntry } from '@/types' import { showSuccessToast, showFailToast, showConfirmDialog } from 'vant' +import MobileIcon from '@/components-mobile/MobileIcon.vue' const props = defineProps<{ groupId: string }>() @@ -224,7 +225,7 @@ function timeAgo(dateStr: string): string { >
{{ event.description }}
@@ -296,8 +297,8 @@ async function onCreated() { .expand-icon { margin-left: auto; color: var(--gg-text-muted); font-size: 14px; } .event-title { font-size: 16px; font-weight: 600; color: var(--gg-text); } -.event-time { font-size: 13px; color: var(--gg-text-secondary); margin-top: 6px; } -.event-loc { font-size: 13px; color: var(--gg-text-secondary); margin-top: 2px; } +.event-time { display: flex; align-items: center; gap: 4px; font-size: 13px; color: var(--gg-text-secondary); margin-top: 6px; } +.event-loc { display: flex; align-items: center; gap: 4px; font-size: 13px; color: var(--gg-text-secondary); margin-top: 2px; } .event-detail { background: var(--gg-bg); diff --git a/frontend/src/components-mobile/game/GameDetailSheetMobile.vue b/frontend/src/components-mobile/game/GameDetailSheetMobile.vue index 339c4e5..5597d2d 100644 --- a/frontend/src/components-mobile/game/GameDetailSheetMobile.vue +++ b/frontend/src/components-mobile/game/GameDetailSheetMobile.vue @@ -13,6 +13,7 @@ import { createTeamSession } from '@/api/sessions' import { useTeamStore } from '@/stores/team' import { pb } from '@/api/pocketbase' import { showSuccessToast, showFailToast, showConfirmDialog } from 'vant' +import MobileIcon from '@/components-mobile/MobileIcon.vue' const props = defineProps<{ show: boolean @@ -239,7 +240,7 @@ function formatDate(dateStr: string): string {