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 @@
-
-
-
-
暂无排期日期
-
-
-
-
-
-
-
-
- 加载中...
-
-
- {{ error }}
-
-
-
-
🎵
-
暂无排期信息
-
点歌后等待管理员安排播出时间
-
-
-
-
📅
-
当前日期暂无排期
-
请选择其他日期查看
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 加载中...
+
+
+ {{ error }}
+
+
+
+
🎵
+
暂无排期信息
+
点歌后等待管理员安排播出时间
+
+
+
+
📅
+
当前日期暂无排期
+
请选择其他日期查看
+
+
+
+
+
+
+
+
+
-
-
该时段暂无排期 📻
-
-
{{ schedule.sequence || '–' }}
-
-
-
- {{ schedule.song.title }}
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -224,6 +300,7 @@
class="relative w-full max-w-2xl bg-zinc-900 border border-zinc-800 rounded-3xl shadow-2xl flex flex-col max-h-[90vh] overflow-hidden"
@click.stop
>
+