From 92704d663791e2f4207a12a70052a295ca490b32 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Sun, 13 Sep 2026 19:32:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(front):=20=E5=89=8D=E5=8F=B0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=B5=85=E8=89=B2=E6=A8=A1=E5=BC=8F=E5=B9=B6=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=B1=85=E4=B8=AD=E6=8A=95=E7=A8=BF=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E4=B8=8E=E5=AE=9E=E6=97=B6=E7=A9=BA=E9=97=B2=E6=A1=A3=E6=9C=9F?= =?UTF-8?q?=20-=20=E4=B8=BB=E9=A2=98:=20useTheme=20=E9=BB=98=E8=AE=A4=20Mo?= =?UTF-8?q?dernLight=20+=20variables.css=20SSR-safe=20=E6=B5=85=E5=80=BC?= =?UTF-8?q?=E5=B9=B6=E7=B2=BE=E4=BF=AE=E7=BB=84=E4=BB=B6=E5=AF=B9=E6=AF=94?= =?UTF-8?q?=E5=BA=A6=20-=20=E9=A6=96=E9=A1=B5:=20=E6=8F=92=E5=85=A5?= =?UTF-8?q?=E5=B1=85=E4=B8=AD=E6=8A=95=E7=A8=BF=20CTA=20+=20=E7=B4=A7?= =?UTF-8?q?=E9=82=BB=E6=A1=A3=E6=9C=9F=E6=A6=82=E8=A7=88=E5=8D=A1=E7=89=87?= =?UTF-8?q?(=E4=BB=8A=E6=97=A5=E6=8E=92=E6=9C=9F/=E5=BE=85=E6=92=AD?= =?UTF-8?q?=E6=AD=8C=E6=9B=B2/=E7=A9=BA=E9=97=B2=E6=A1=A3=E6=9C=9F?= =?UTF-8?q?=E6=95=B0)=20-=20=E6=95=B0=E6=8D=AE:=20useSongs=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20fetchExpectedPlayDates=20=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E7=A9=BA=E9=97=B2=E6=A1=A3=E6=9C=9F=E5=B9=B6=E8=B5=B0=20revisi?= =?UTF-8?q?on=20=E8=BD=AE=E8=AF=A2=E5=AE=9E=E6=97=B6=E5=88=B7=E6=96=B0=20-?= =?UTF-8?q?=20=E8=A7=86=E8=A7=89:=20=E7=A7=BB=E5=8A=A8=E7=AB=AF=E4=BC=98?= =?UTF-8?q?=E5=85=88=EF=BC=8C=E5=B0=91=E5=9C=86=E8=A7=92=E7=A1=AC=E8=BE=B9?= =?UTF-8?q?=E5=87=A0=E4=BD=95=20+=20=E6=A6=82=E8=A7=88=E5=8D=A1=E7=89=87?= =?UTF-8?q?=203=E2=86=921=20=E5=88=97=E5=93=8D=E5=BA=94=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/css/main.css | 341 +++++++- app/assets/css/variables.css | 319 +++---- app/components/Songs/RequestForm.vue | 78 +- app/components/Songs/ScheduleList.vue | 1105 +++++++++++-------------- app/composables/useSongs.ts | 56 ++ app/composables/useTheme.ts | 10 +- app/pages/index.vue | 1059 +++++++++++++----------- package-lock.json | 328 +++++--- package.json | 3 +- 9 files changed, 1836 insertions(+), 1463 deletions(-) diff --git a/app/assets/css/main.css b/app/assets/css/main.css index 505427d..4e30d33 100644 --- a/app/assets/css/main.css +++ b/app/assets/css/main.css @@ -7,7 +7,7 @@ /* 防止浏览器自动应用深色主题:改为跟随 data-theme 动态覆盖(见 theme-protection.css) */ :root { - color-scheme: light dark; + color-scheme: light; } /* 流体背景与全局样式 */ @@ -82,9 +82,9 @@ body::before { width: 100%; height: 100%; background: - radial-gradient(circle at 20% 50%, rgba(120, 119, 198, 0.03) 0%, transparent 50%), - radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.01) 0%, transparent 50%), - radial-gradient(circle at 40% 80%, rgba(120, 119, 198, 0.02) 0%, transparent 50%); + radial-gradient(circle at 20% 50%, rgba(79, 70, 229, 0.035) 0%, transparent 55%), + radial-gradient(circle at 80% 20%, rgba(14, 165, 233, 0.025) 0%, transparent 55%), + radial-gradient(circle at 40% 80%, rgba(79, 70, 229, 0.02) 0%, transparent 55%); z-index: -1; pointer-events: none; } @@ -472,3 +472,336 @@ body::before { max-width: none !important; } } + +/* ========================================================= + * 前台浅色模式对比度覆盖(ScheduleList / RequestForm 等组件) + * 将所有硬编码的 rgba(255,255,255,*) 白系文字统一替换为 + * 适配浅底的深灰/主题色,保证 WCAG AA 可读性 + * =======================================================*/ +html[data-theme='light'], +html[data-theme='ClassicLight'], +html[data-theme='ModernLight'] { + /* ScheduleList.vue 主区块硬编码颜色校正 */ + color-scheme: light; +} + +html[data-theme='light'] .schedule-list .date-item, +html[data-theme='ClassicLight'] .schedule-list .date-item, +html[data-theme='ModernLight'] .schedule-list .date-item, +html[data-theme='light'] .song-list .date-item, +html[data-theme='ClassicLight'] .song-list .date-item, +html[data-theme='ModernLight'] .song-list .date-item { + color: var(--text-secondary) !important; +} + +html[data-theme='light'] .schedule-list .empty-dates, +html[data-theme='ClassicLight'] .schedule-list .empty-dates, +html[data-theme='ModernLight'] .schedule-list .empty-dates, +html[data-theme='light'] .schedule-list .loading, +html[data-theme='ClassicLight'] .schedule-list .loading, +html[data-theme='ModernLight'] .schedule-list .loading, +html[data-theme='light'] .schedule-list .error, +html[data-theme='ClassicLight'] .schedule-list .error, +html[data-theme='ModernLight'] .schedule-list .error, +html[data-theme='light'] .schedule-list .empty, +html[data-theme='ClassicLight'] .schedule-list .empty, +html[data-theme='ModernLight'] .schedule-list .empty { + color: var(--text-tertiary) !important; +} + +html[data-theme='light'] .schedule-list .playtime-header h4, +html[data-theme='ClassicLight'] .schedule-list .playtime-header h4, +html[data-theme='ModernLight'] .schedule-list .playtime-header h4 { + color: var(--text-secondary) !important; +} + +html[data-theme='light'] .schedule-list .playtime-time, +html[data-theme='ClassicLight'] .schedule-list .playtime-time, +html[data-theme='ModernLight'] .schedule-list .playtime-time { + color: var(--text-tertiary) !important; +} + +html[data-theme='light'] .schedule-list .playlist-modal, +html[data-theme='ClassicLight'] .schedule-list .playlist-modal, +html[data-theme='ModernLight'] .schedule-list .playlist-modal { + border-color: var(--border-secondary) !important; +} + +html[data-theme='light'] .schedule-list .playlist-modal-header, +html[data-theme='ClassicLight'] .schedule-list .playlist-modal-header, +html[data-theme='ModernLight'] .schedule-list .playlist-modal-header, +html[data-theme='light'] .schedule-list .playlist-modal-footer, +html[data-theme='ClassicLight'] .schedule-list .playlist-modal-footer, +html[data-theme='ModernLight'] .schedule-list .playlist-modal-footer { + border-color: var(--border-secondary) !important; +} + +html[data-theme='light'] .schedule-list .song-meta .meta-secondary, +html[data-theme='ClassicLight'] .schedule-list .song-meta .meta-secondary, +html[data-theme='ModernLight'] .schedule-list .song-meta .meta-secondary, +html[data-theme='light'] .schedule-list .song-meta .meta-placeholder, +html[data-theme='ClassicLight'] .schedule-list .song-meta .meta-placeholder, +html[data-theme='ModernLight'] .schedule-list .song-meta .meta-placeholder, +html[data-theme='light'] .schedule-list .slot-hint, +html[data-theme='ClassicLight'] .schedule-list .slot-hint, +html[data-theme='ModernLight'] .schedule-list .slot-hint, +html[data-theme='light'] .schedule-list .requestor-text, +html[data-theme='ClassicLight'] .schedule-list .requestor-text, +html[data-theme='ModernLight'] .schedule-list .requestor-text, +html[data-theme='light'] .schedule-list .pill-empty, +html[data-theme='ClassicLight'] .schedule-list .pill-empty, +html[data-theme='ModernLight'] .schedule-list .pill-empty, +html[data-theme='light'] .schedule-list .empty-slot, +html[data-theme='ClassicLight'] .schedule-list .empty-slot, +html[data-theme='ModernLight'] .schedule-list .empty-slot { + color: var(--text-tertiary) !important; +} + +html[data-theme='light'] .schedule-list .chip, +html[data-theme='ClassicLight'] .schedule-list .chip, +html[data-theme='ModernLight'] .schedule-list .chip, +html[data-theme='light'] .schedule-list .tag, +html[data-theme='ClassicLight'] .schedule-list .tag, +html[data-theme='ModernLight'] .schedule-list .tag, +html[data-theme='light'] .schedule-list .badge-soft, +html[data-theme='ClassicLight'] .schedule-list .badge-soft, +html[data-theme='ModernLight'] .schedule-list .badge-soft { + background: var(--bg-secondary) !important; + border-color: var(--border-secondary) !important; + color: var(--text-secondary) !important; +} + +html[data-theme='light'] .schedule-list .divider-subtle, +html[data-theme='ClassicLight'] .schedule-list .divider-subtle, +html[data-theme='ModernLight'] .schedule-list .divider-subtle, +html[data-theme='light'] .schedule-list .card-border, +html[data-theme='ClassicLight'] .schedule-list .card-border, +html[data-theme='ModernLight'] .schedule-list .card-border { + border-color: var(--border-secondary) !important; +} + +/* RequestForm / SongList / Dialog 通用硬编码白字校正 */ +html[data-theme='light'] .request-form .label-subtle, +html[data-theme='ClassicLight'] .request-form .label-subtle, +html[data-theme='ModernLight'] .request-form .label-subtle, +html[data-theme='light'] .request-form .hint-subtle, +html[data-theme='ClassicLight'] .request-form .hint-subtle, +html[data-theme='ModernLight'] .request-form .hint-subtle, +html[data-theme='light'] .request-form .placeholder-subtle, +html[data-theme='ClassicLight'] .request-form .placeholder-subtle, +html[data-theme='ModernLight'] .request-form .placeholder-subtle, +html[data-theme='light'] .song-list .muted, +html[data-theme='ClassicLight'] .song-list .muted, +html[data-theme='ModernLight'] .song-list .muted, +html[data-theme='light'] .song-list .subtle-text, +html[data-theme='ClassicLight'] .song-list .subtle-text, +html[data-theme='ModernLight'] .song-list .subtle-text { + color: var(--text-tertiary) !important; +} + +html[data-theme='light'] .request-form .glass-surface, +html[data-theme='ClassicLight'] .request-form .glass-surface, +html[data-theme='ModernLight'] .request-form .glass-surface, +html[data-theme='light'] .request-form .surface-chip, +html[data-theme='ClassicLight'] .request-form .surface-chip, +html[data-theme='ModernLight'] .request-form .surface-chip, +html[data-theme='light'] .song-list .glass-surface, +html[data-theme='ClassicLight'] .song-list .glass-surface, +html[data-theme='ModernLight'] .song-list .glass-surface, +html[data-theme='light'] .song-list .surface-chip, +html[data-theme='ClassicLight'] .song-list .surface-chip, +html[data-theme='ModernLight'] .song-list .surface-chip { + background: var(--bg-secondary) !important; + border-color: var(--border-secondary) !important; +} + +/* ========================================================= + * 首页 Hero CTA 区样式 — 投稿按钮居中 + 档期概览卡片 + * 移动端优先 / 少圆角 / 硬边几何 / 现代浅色专业风格 + * =======================================================*/ +.hero-cta-section { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 28px 16px 20px; + gap: 14px; + width: 100%; + max-width: 760px; + margin: 0 auto; +} + +.hero-request-btn { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 10px; + min-width: 240px; + width: min(86%, 360px); + height: 58px; + padding: 0 22px; + border-radius: 14px; + border: 1px solid rgba(255, 255, 255, 0.18); + background: linear-gradient(135deg, var(--primary) 0%, #4338ca 100%); + color: #ffffff; + font-family: 'MiSans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-size: 17px; + font-weight: 600; + letter-spacing: 0.2px; + cursor: pointer; + user-select: none; + box-shadow: + 0 10px 24px -10px rgba(79, 70, 229, 0.55), + 0 4px 10px -4px rgba(79, 70, 229, 0.35); + transition: transform 0.18s cubic-bezier(0.2, 0.9, 0.2, 1), + box-shadow 0.18s ease, filter 0.18s ease; + -webkit-tap-highlight-color: transparent; +} +.hero-request-btn:hover { + transform: translateY(-1px); + filter: brightness(1.03); + box-shadow: + 0 14px 28px -10px rgba(79, 70, 229, 0.62), + 0 6px 12px -4px rgba(79, 70, 229, 0.42); +} +.hero-request-btn:active { + transform: translateY(0); + filter: brightness(0.97); + box-shadow: + 0 6px 14px -6px rgba(79, 70, 229, 0.5), + 0 2px 6px -2px rgba(79, 70, 229, 0.35); +} +.hero-request-btn .btn-icon { + font-size: 20px; + line-height: 1; +} +.hero-request-btn .btn-icon.pulse::after { + content: ''; + position: absolute; + right: 10px; + top: 10px; + width: 8px; + height: 8px; + border-radius: 50%; + background: #22c55e; + box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.22); +} + +.schedule-overview-card { + width: 100%; + max-width: 720px; + padding: 18px 18px; + border-radius: 12px; + background: var(--card-bg, #ffffff); + border: 1px solid var(--card-border, #e4e4e7); + box-shadow: var(--card-shadow); +} +.schedule-overview-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 10px; +} +@media (max-width: 520px) { + .schedule-overview-grid { + grid-template-columns: 1fr; + gap: 12px; + } +} +.overview-stat { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + padding: 14px 16px; + border-radius: 10px; + background: var(--bg-secondary); + border: 1px solid var(--border-secondary); + min-height: 96px; +} +.overview-stat .stat-icon { + font-size: 16px; + line-height: 1; + margin-bottom: 6px; + color: var(--text-tertiary); +} +.overview-stat .stat-label { + font-size: 12px; + line-height: 1.4; + color: var(--text-tertiary); + font-weight: 500; + margin-bottom: 6px; + letter-spacing: 0.2px; +} +.overview-stat .stat-value { + font-size: 22px; + font-weight: 700; + color: var(--text-primary); + line-height: 1.2; + letter-spacing: -0.3px; + display: flex; + align-items: baseline; + gap: 6px; +} +.overview-stat .stat-value .unit { + font-size: 12px; + font-weight: 500; + color: var(--text-tertiary); + letter-spacing: 0; +} +.overview-stat.primary { + background: linear-gradient(135deg, rgba(79, 70, 229, 0.08), rgba(14, 165, 233, 0.06)); + border-color: rgba(79, 70, 229, 0.15); +} +.overview-stat.primary .stat-value { + color: var(--primary); + font-size: 28px; +} +.overview-stat.primary .stat-icon { + color: var(--primary); +} +.overview-stat .stat-detail { + margin-top: 4px; + font-size: 11px; + color: var(--text-tertiary); + line-height: 1.35; +} +.overview-stat .live-dot { + display: inline-block; + width: 6px; + height: 6px; + border-radius: 50%; + background: #22c55e; + margin-right: 5px; + vertical-align: middle; + box-shadow: 0 0 0 2px rgba(34, 197, 94, 0.2); + animation: live-pulse 1.6s ease-in-out infinite; +} +@keyframes live-pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.65; transform: scale(0.92); } +} + +@media (max-width: 640px) { + .hero-cta-section { + padding: 22px 12px 16px; + gap: 12px; + } + .hero-request-btn { + height: 54px; + font-size: 16px; + border-radius: 12px; + width: 88%; + } + .schedule-overview-card { + padding: 14px 12px; + border-radius: 10px; + } + .overview-stat { + padding: 12px 14px; + min-height: 84px; + } + .overview-stat.primary .stat-value { + font-size: 26px; + } +} diff --git a/app/assets/css/variables.css b/app/assets/css/variables.css index 6db83c9..2159045 100644 --- a/app/assets/css/variables.css +++ b/app/assets/css/variables.css @@ -1,69 +1,59 @@ /* 全局CSS变量 - 统一配色方案 */ +/* SSR-safe 默认值 = ModernLight 浅色,防止 hydration 前出现深色闪屏 */ :root { - /* 主色调 */ - --primary: #3b82f6; - --primary-hover: #2563eb; - --primary-light: rgba(59, 130, 246, 0.1); - --primary-border: rgba(59, 130, 246, 0.2); + --primary: #4f46e5; + --primary-hover: #4338ca; + --primary-light: rgba(79, 70, 229, 0.1); + --primary-border: rgba(79, 70, 229, 0.2); - /* 成功色 */ - --success: #10b981; - --success-hover: #059669; - --success-light: rgba(16, 185, 129, 0.1); - --success-border: rgba(16, 185, 129, 0.2); + --success: #16a34a; + --success-hover: #15803d; + --success-light: rgba(22, 163, 74, 0.1); + --success-border: rgba(22, 163, 74, 0.2); - /* 警告色 */ - --warning: #f59e0b; - --warning-hover: #d97706; - --warning-light: rgba(245, 158, 11, 0.1); - --warning-border: rgba(245, 158, 11, 0.2); + --warning: #ea580c; + --warning-hover: #c2410c; + --warning-light: rgba(234, 88, 12, 0.1); + --warning-border: rgba(234, 88, 12, 0.2); - /* 错误色 */ - --error: #ef4444; - --error-hover: #dc2626; - --error-light: rgba(239, 68, 68, 0.1); - --error-border: rgba(239, 68, 68, 0.2); + --error: #e11d48; + --error-hover: #be123c; + --error-light: rgba(225, 29, 72, 0.1); + --error-border: rgba(225, 29, 72, 0.2); - /* 信息色 */ - --info: #3b82f6; - --info-hover: #2563eb; - --info-light: rgba(59, 130, 246, 0.1); - --info-border: rgba(59, 130, 246, 0.2); + --info: #0ea5e9; + --info-hover: #0284c7; + --info-light: rgba(14, 165, 233, 0.1); + --info-border: rgba(14, 165, 233, 0.2); - /* 背景色 */ - --bg-primary: #111111; - --bg-secondary: #1a1a1a; - --bg-tertiary: #2a2a2a; - --bg-quaternary: #3a3a3a; - --bg-hover: #1f1f1f; + --bg-primary: #fafafa; + --bg-secondary: #f4f4f5; + --bg-tertiary: #e4e4e7; + --bg-quaternary: #d4d4d8; + --bg-hover: #eeeeef; - /* 文字颜色 */ - --text-primary: #ffffff; - --text-secondary: #cccccc; - --text-tertiary: #888888; - --text-quaternary: #666666; - --text-disabled: #444444; + --text-primary: #09090b; + --text-secondary: #3f3f46; + --text-tertiary: #71717a; + --text-quaternary: #a1a1aa; + --text-disabled: #d4d4d8; - /* 边框颜色 */ - --border-primary: #1f1f1f; - --border-secondary: #2a2a2a; - --border-tertiary: #3a3a3a; - --border-quaternary: #4a4a4a; + --border-primary: #e4e4e7; + --border-secondary: #d4d4d8; + --border-tertiary: #a1a1aa; + --border-quaternary: #71717a; - /* 阴影 */ - --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); - --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); - --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); - --shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.1); + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.03); + --shadow-md: 0 2px 8px -2px rgba(0, 0, 0, 0.05), 0 1px 3px 0 rgba(0, 0, 0, 0.03); + --shadow-lg: 0 8px 24px -4px rgba(0, 0, 0, 0.06), 0 2px 8px -4px rgba(0, 0, 0, 0.04); + --shadow-xl: 0 16px 40px -8px rgba(0, 0, 0, 0.08), 0 4px 16px -8px rgba(0, 0, 0, 0.05); - /* 圆角 */ --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; - --radius-xl: 12px; - --radius-2xl: 16px; + --radius-xl: 10px; + --radius-2xl: 12px; - /* 间距 */ --spacing-xs: 4px; --spacing-sm: 8px; --spacing-md: 12px; @@ -72,7 +62,6 @@ --spacing-2xl: 24px; --spacing-3xl: 32px; - /* 字体大小 */ --text-xs: 12px; --text-sm: 14px; --text-base: 16px; @@ -81,18 +70,15 @@ --text-2xl: 24px; --text-3xl: 30px; - /* 字体粗细 */ --font-normal: 400; --font-medium: 500; --font-semibold: 600; --font-bold: 700; - /* 过渡动画 */ --transition-fast: 0.15s ease; --transition-normal: 0.2s ease; --transition-slow: 0.3s ease; - /* Z-index层级 */ --z-dropdown: 100; --z-sticky: 200; --z-fixed: 300; @@ -102,81 +88,72 @@ --z-tooltip: 700; --z-toast: 800; - /* 特殊状态颜色 */ - --status-pending: #fbbf24; - --status-pending-light: rgba(251, 191, 36, 0.1); - --status-approved: #10b981; - --status-approved-light: rgba(16, 185, 129, 0.1); - --status-played: #6b7280; - --status-played-light: rgba(107, 114, 128, 0.1); + --status-pending: #eab308; + --status-pending-light: rgba(234, 179, 8, 0.12); + --status-approved: #22c55e; + --status-approved-light: rgba(34, 197, 94, 0.12); + --status-played: #71717a; + --status-played-light: rgba(113, 113, 122, 0.12); - /* 投票相关颜色 */ --vote-heart: #ef4444; --vote-heart-hover: #dc2626; --vote-count: var(--text-tertiary); - /* 拖拽状态颜色 */ --drag-over: var(--primary-light); --drag-over-border: var(--primary); --dragging-opacity: 0.5; - /* 表格颜色 */ - --table-header-bg: var(--bg-tertiary); - --table-row-hover: var(--bg-hover); - --table-border: var(--border-secondary); - --table-selected: var(--primary-light); + --table-header-bg: #f4f4f5; + --table-row-hover: #fafafa; + --table-border: #e4e4e7; + --table-selected: rgba(79, 70, 229, 0.08); - /* 卡片颜色 */ - --card-bg: var(--bg-secondary); - --card-border: var(--border-secondary); - --card-hover-border: var(--border-tertiary); - --card-shadow: var(--shadow-md); + --card-bg: #ffffff; + --card-border: #e4e4e7; + --card-hover-border: #d4d4d8; + --card-shadow: 0 2px 8px -2px rgba(0, 0, 0, 0.05), 0 1px 3px 0 rgba(0, 0, 0, 0.03); - /* 按钮颜色 */ --btn-primary-bg: var(--primary); --btn-primary-hover: var(--primary-hover); - --btn-primary-text: var(--text-primary); + --btn-primary-text: #ffffff; --btn-primary-border: var(--primary-border); - --btn-secondary-bg: #3a3a3a; - --btn-secondary-hover: #4a4a4a; - --btn-secondary-text: var(--text-primary); - --btn-secondary-border: #555555; + --btn-secondary-bg: #f4f4f5; + --btn-secondary-hover: #e4e4e7; + --btn-secondary-text: #09090b; + --btn-secondary-border: #d4d4d8; --btn-success-bg: var(--success); --btn-success-hover: var(--success-hover); - --btn-success-text: var(--text-primary); + --btn-success-text: #ffffff; --btn-success-border: var(--success-border); --btn-warning-bg: var(--warning); --btn-warning-hover: var(--warning-hover); - --btn-warning-text: var(--text-primary); + --btn-warning-text: #ffffff; --btn-warning-border: var(--warning-border); --btn-error-bg: var(--error); --btn-error-hover: var(--error-hover); - --btn-error-text: var(--text-primary); + --btn-error-text: #ffffff; --btn-error-border: var(--error-border); --btn-disabled-bg: var(--bg-tertiary); --btn-disabled-text: var(--text-disabled); - /* 输入框颜色 */ - --input-bg: var(--bg-tertiary); - --input-border: var(--border-tertiary); - --input-border-focus: var(--primary); - --input-text: var(--text-primary); - --input-placeholder: var(--text-quaternary); - --input-shadow-focus: 0 0 0 3px var(--primary-light); + --input-bg: #ffffff; + --input-border: #e4e4e7; + --input-border-focus: #4f46e5; + --input-text: #09090b; + --input-placeholder: #a1a1aa; + --input-shadow-focus: 0 0 0 3px rgba(79, 70, 229, 0.12); - /* 模态框颜色 */ - --modal-backdrop: rgba(0, 0, 0, 0.7); + --modal-backdrop: rgba(0, 0, 0, 0.4); --modal-bg: var(--bg-secondary); --modal-border: var(--border-secondary); --modal-header-border: var(--border-secondary); --modal-footer-border: var(--border-secondary); - /* 通知颜色 */ --notification-success-bg: var(--success-light); --notification-success-border: var(--success-border); --notification-success-text: var(--success); @@ -193,14 +170,51 @@ --notification-info-border: var(--info-border); --notification-info-text: var(--info); - /* 加载动画颜色 */ --spinner-primary: var(--primary); --spinner-secondary: var(--bg-tertiary); - /* 滚动条颜色 */ + --scrollbar-track: #f4f4f5; + --scrollbar-thumb: #d4d4d8; + --scrollbar-thumb-hover: #a1a1aa; +} + +:root[data-theme='dark'] { + --bg-primary: #111111; + --bg-secondary: #1a1a1a; + --bg-tertiary: #2a2a2a; + --bg-quaternary: #3a3a3a; + --bg-hover: #1f1f1f; + + --text-primary: #ffffff; + --text-secondary: #cccccc; + --text-tertiary: #888888; + --text-quaternary: #666666; + --text-disabled: #444444; + + --border-primary: #1f1f1f; + --border-secondary: #2a2a2a; + --border-tertiary: #3a3a3a; + --border-quaternary: #4a4a4a; + + --card-bg: #1a1a1a; + --card-border: #2a2a2a; + + --btn-secondary-bg: #3a3a3a; + --btn-secondary-hover: #4a4a4a; + --btn-secondary-text: #ffffff; + --btn-secondary-border: #555555; + + --input-bg: var(--bg-tertiary); + --input-border: var(--border-tertiary); + --input-text: var(--text-primary); + --input-placeholder: var(--text-quaternary); + --scrollbar-track: var(--bg-tertiary); --scrollbar-thumb: var(--bg-quaternary); --scrollbar-thumb-hover: #4a4a4a; + + --modal-backdrop: rgba(0, 0, 0, 0.7); + --card-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } :root[data-theme='light'], @@ -398,121 +412,6 @@ --radius-2xl: 12px; } -/* ===== 前台页面专属浅色主题覆盖(广播园艺风格)===== */ -body[data-frontend="true"]:not(.admin-body) { - /* 强调色:紫粉蓝渐变点缀(广播园艺三色花) */ - --accent-purple: #A855F7; - --accent-pink: #EC4899; - --accent-blue: #3B82F6; - - /* 背景色:纯白为主,留白优先 */ - --bg-primary: #FFFFFF; - --bg-secondary: #F9FAFB; - --bg-tertiary: #F3F4F6; - --bg-quaternary: #E5E7EB; - --bg-hover: #F3F4F6; - - /* 文字颜色:近黑高对比度 */ - --text-primary: #111827; - --text-secondary: #4B5563; - --text-tertiary: #6B7280; - --text-quaternary: #9CA3AF; - --text-disabled: #D1D5DB; - - /* 边框颜色:硬边清晰,4px 网格 */ - --border-primary: #E5E7EB; - --border-secondary: #D1D5DB; - --border-tertiary: #9CA3AF; - --border-quaternary: #6B7280; - - /* 卡片:白底薄边 + 极轻阴影,不抢视觉 */ - --card-bg: #FFFFFF; - --card-border: #E5E7EB; - --card-hover-border: #D1D5DB; - --card-shadow: 0 1px 3px 0 rgba(17, 24, 39, 0.04), 0 1px 2px -1px rgba(17, 24, 39, 0.03); - - /* 主色改为深靛蓝(不抢紫粉蓝点缀的风头) */ - --primary: #4338CA; - --primary-hover: #3730A3; - --primary-light: rgba(67, 56, 202, 0.08); - --primary-border: rgba(67, 56, 202, 0.15); - - /* 信息色沿用主蓝 */ - --info: #4338CA; - --info-hover: #3730A3; - --info-light: rgba(67, 56, 202, 0.08); - --info-border: rgba(67, 56, 202, 0.15); - - /* 语义色保持经典但略降饱和度 */ - --success: #059669; - --success-hover: #047857; - --success-light: rgba(5, 150, 105, 0.08); - --success-border: rgba(5, 150, 105, 0.15); - - --warning: #D97706; - --warning-hover: #B45309; - --warning-light: rgba(217, 119, 6, 0.08); - --warning-border: rgba(217, 119, 6, 0.15); - - --error: #DC2626; - --error-hover: #B91C1C; - --error-light: rgba(220, 38, 38, 0.08); - --error-border: rgba(220, 38, 38, 0.15); - - /* 状态色 */ - --status-pending: #CA8A04; - --status-pending-light: rgba(202, 138, 4, 0.08); - --status-approved: #059669; - --status-approved-light: rgba(5, 150, 105, 0.08); - --status-played: #6B7280; - --status-played-light: rgba(107, 114, 128, 0.08); - - /* 输入框:纯白底薄边 */ - --input-bg: #FFFFFF; - --input-border: #D1D5DB; - --input-border-focus: #4338CA; - --input-text: #111827; - --input-placeholder: #9CA3AF; - --input-shadow-focus: 0 0 0 3px rgba(67, 56, 202, 0.1); - - /* 按钮:次要按钮硬边设计 */ - --btn-secondary-bg: #F9FAFB; - --btn-secondary-hover: #F3F4F6; - --btn-secondary-text: #111827; - --btn-secondary-border: #D1D5DB; - - /* 模态框与通知 */ - --modal-backdrop: rgba(17, 24, 39, 0.4); - --modal-bg: #FFFFFF; - --modal-border: #E5E7EB; - --modal-header-border: #E5E7EB; - --modal-footer-border: #E5E7EB; - - /* 圆角:硬边设计,上限 rounded-lg (8px) */ - --radius-sm: 4px; - --radius-md: 6px; - --radius-lg: 8px; - --radius-xl: 8px; - --radius-2xl: 8px; - - /* 阴影:轻盈不厚重 */ - --shadow-sm: 0 1px 2px 0 rgba(17, 24, 39, 0.04); - --shadow-md: 0 4px 6px -1px rgba(17, 24, 39, 0.05), 0 2px 4px -2px rgba(17, 24, 39, 0.03); - --shadow-lg: 0 10px 15px -3px rgba(17, 24, 39, 0.05), 0 4px 6px -4px rgba(17, 24, 39, 0.03); - --shadow-xl: 0 20px 25px -5px rgba(17, 24, 39, 0.05), 0 8px 10px -6px rgba(17, 24, 39, 0.03); - - /* 滚动条 */ - --scrollbar-track: #F3F4F6; - --scrollbar-thumb: #D1D5DB; - --scrollbar-thumb-hover: #9CA3AF; - - /* 表格 */ - --table-header-bg: #F9FAFB; - --table-row-hover: #F9FAFB; - --table-border: #E5E7EB; - --table-selected: rgba(67, 56, 202, 0.05); -} - /* 深色主题特定调整 */ @media (prefers-color-scheme: dark) { :root { diff --git a/app/components/Songs/RequestForm.vue b/app/components/Songs/RequestForm.vue index 56a8645..5be91bd 100644 --- a/app/components/Songs/RequestForm.vue +++ b/app/components/Songs/RequestForm.vue @@ -176,27 +176,19 @@ :key="item.seq" type="button" :class="[ - 'seq', - item.taken ? 'seq-taken' : '', - expectedPlaySequence === String(item.seq) ? 'seq-selected' : '' + 'sequence-pill', + item.taken ? 'taken' : 'free', + expectedPlaySequence === String(item.seq) ? 'selected' : '' ]" :disabled="item.taken" - :title="getTakenSequenceTitle(item.seq)" + :title="item.taken ? getTakenSequenceTitle(item.seq) : ''" @click="chooseExpectedPlaySequence(item.seq)" > {{ item.seq }} -
🟣 可选(紫粉蓝选中) · ⚪ 已占用(灰色带删除线)
-
- - 已锁定 第 {{ expectedPlaySequence }} 首 位置 -
+
绿色可选,红色已占用
@@ -3134,55 +3126,47 @@ defineExpose({ } .sequence-grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); - gap: 8px; - margin-top: 12px; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; } -.seq { - width: 40px; - height: 40px; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 8px; - background: #fff; - border: 1.5px solid #d1d5db; - color: #111827; - font-size: 16px; - font-weight: 800; - transition: all 0.12s ease; - cursor: pointer; +.sequence-pill { + height: 28px; + min-width: 28px; + padding: 0 10px; + border-radius: 10px; + border: 1px solid var(--border-primary); + background: rgba(0, 0, 0, 0.25); + color: rgba(255, 255, 255, 0.85); + font-family: 'MiSans', sans-serif; + font-weight: 700; + font-size: 12px; + transition: all 0.2s ease; } -.seq:hover:not(:disabled) { - border-color: #4338ca; - color: #4338ca; - transform: scale(1.03); +.sequence-pill.free { + border-color: rgba(16, 185, 129, 0.35); + background: rgba(16, 185, 129, 0.08); + color: rgba(16, 185, 129, 0.95); } -.seq-taken { - background: #f3f4f6; - border-color: #e5e7eb; - color: #9ca3af; - text-decoration: line-through; +.sequence-pill.taken { + border-color: rgba(239, 68, 68, 0.35); + background: rgba(239, 68, 68, 0.08); + color: rgba(239, 68, 68, 0.95); cursor: not-allowed; } -.seq-selected { - background: linear-gradient(135deg, #a855f7 0%, #ec4899 50%, #3b82f6 100%); - color: #fff; - border-color: transparent; - box-shadow: 0 6px 16px rgba(168, 85, 247, 0.35); - transform: scale(1.05); +.sequence-pill.selected { + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.25); + border-color: rgba(59, 130, 246, 0.6); } .sequence-hint { font-size: 11px; font-weight: 600; color: rgba(255, 255, 255, 0.55); - margin-top: 8px; } .search-section { diff --git a/app/components/Songs/ScheduleList.vue b/app/components/Songs/ScheduleList.vue index ddd70a3..47f1754 100644 --- a/app/components/Songs/ScheduleList.vue +++ b/app/components/Songs/ScheduleList.vue @@ -1,206 +1,282 @@