diff --git a/src/presentation/static/css/admin-base.css b/src/presentation/static/css/admin-base.css index 9e7f07b..ae2c989 100644 --- a/src/presentation/static/css/admin-base.css +++ b/src/presentation/static/css/admin-base.css @@ -24,6 +24,27 @@ --transition: 180ms ease; } +:root[data-theme="dark"] { + --bg-page: #0b1220; + --surface: #111b2e; + --surface-soft: #0f1728; + --surface-hover: #17233a; + --text-primary: #e6edf7; + --text-secondary: #a5b4cc; + --text-muted: #93a4c2; + --line: #24324c; + --line-strong: #314665; + --primary: #78a7d8; + --primary-hover: #8ab4de; + --primary-active: #6798cb; + --danger: #e0828f; + --danger-hover: #d46e7c; + --success: #6ab79f; + --focus: rgba(120, 167, 216, 0.3); + --shadow-soft: 0 10px 28px rgba(0, 0, 0, 0.38); + --shadow-card: 0 4px 14px rgba(0, 0, 0, 0.32); +} + * { margin: 0; padding: 0; @@ -66,6 +87,10 @@ body.app-page { background: linear-gradient(180deg, #fbfdff 0%, #f5f9ff 100%); } +:root[data-theme="dark"] .app-page .header { + background: linear-gradient(180deg, #121d31 0%, #0f1728 100%); +} + .app-page .header-title h1 { margin: 0; font-size: 28px; @@ -102,6 +127,10 @@ body.app-page { white-space: nowrap; } +:root[data-theme="dark"] .app-page .header-user { + background: #0d1627; +} + .app-page .header-nav { display: inline-flex; align-items: center; @@ -112,6 +141,10 @@ body.app-page { background: #fff; } +:root[data-theme="dark"] .app-page .header-nav { + background: #0d1627; +} + .app-page .header-nav-link { display: inline-flex; align-items: center; @@ -145,6 +178,11 @@ body.app-page { background: #fef5f6; } +:root[data-theme="dark"] .app-page .header-nav-link.header-nav-link-logout { + background: #321b24; + border-color: #5c2d3b; +} + .app-page .header-nav-link.header-nav-link-logout:hover { color: #fff; border-color: var(--danger-hover); @@ -219,6 +257,14 @@ body.app-page { transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition); } +:root[data-theme="dark"] .app-page .form-group input, +:root[data-theme="dark"] .app-page .form-group textarea, +:root[data-theme="dark"] .app-page .form-control, +:root[data-theme="dark"] .app-page .quick-jump input, +:root[data-theme="dark"] .app-page .page-size-controls select { + background: #0d1627; +} + .app-page .form-group textarea { min-height: 82px; padding-top: 10px; @@ -281,6 +327,10 @@ body.app-page { transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition); } +:root[data-theme="dark"] .app-page .custom-select-trigger { + background: #0d1627; +} + .app-page .custom-select-trigger::after { content: ""; position: absolute; @@ -327,6 +377,10 @@ body.app-page { overflow-y: auto; } +:root[data-theme="dark"] .app-page .custom-select-menu { + background: #0d1627; +} + .app-page .custom-select.open .custom-select-menu { display: block; } @@ -368,6 +422,10 @@ body.app-page { align-items: flex-end; } +:root[data-theme="dark"] .app-page .table-footer { + background: #111a2c; +} + /* Shared column semantics: numeric columns stay on one line */ .app-page th.num-col, .app-page td.num-col { @@ -412,6 +470,10 @@ body.app-page { transition: background-color var(--transition), border-color var(--transition), color var(--transition); } +:root[data-theme="dark"] .app-page .page-nav-text { + background: #0d1627; +} + .app-page .page-nav-text:hover:not(.disabled) { background: var(--surface-hover); border-color: #b5c9de; @@ -438,6 +500,60 @@ body.app-page { white-space: nowrap; } +:root[data-theme="dark"] .app-page .page-info, +:root[data-theme="dark"] .app-page .total-count { + background: #0d1627; +} + +.app-page .theme-toggle { + width: 34px; + height: 34px; + border: 1px solid var(--line-strong); + border-radius: 9px; + background: #fff; + color: var(--text-secondary); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition); +} + +.app-page .theme-toggle:hover { + background: var(--surface-hover); + border-color: #b5c9de; + color: var(--text-primary); +} + +.app-page .theme-toggle:focus-visible { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 3px var(--focus); +} + +.app-page .theme-toggle svg { + width: 16px; + height: 16px; + stroke: currentColor; + fill: none; +} + +.app-page .theme-icon-moon { + display: none; +} + +:root[data-theme="dark"] .app-page .theme-toggle { + background: #0d1627; +} + +:root[data-theme="dark"] .app-page .theme-icon-sun { + display: none; +} + +:root[data-theme="dark"] .app-page .theme-icon-moon { + display: inline; +} + .app-page .quick-jump, .app-page .page-size-controls { display: flex; diff --git a/src/presentation/static/css/index.css b/src/presentation/static/css/index.css index ea28690..e61cb98 100644 --- a/src/presentation/static/css/index.css +++ b/src/presentation/static/css/index.css @@ -20,6 +20,10 @@ background: var(--surface); } +:root[data-theme="dark"] .dashboard-page .filters-section { + background: #0f1728; +} + .dashboard-page .filters { display: flex; gap: 14px; @@ -65,6 +69,26 @@ transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition); } +:root[data-theme="dark"] .dashboard-page .filter-group input, +:root[data-theme="dark"] .dashboard-page .filter-group select { + background: #0d1627; + border-color: var(--line-strong); + color: var(--text-primary); +} + +:root[data-theme="dark"] .dashboard-page .filter-group input::placeholder { + color: #8ea0be; +} + +:root[data-theme="dark"] .dashboard-page .filter-group input[type="date"] { + color-scheme: dark; +} + +:root[data-theme="dark"] .dashboard-page .filter-group input[type="date"]::-webkit-calendar-picker-indicator { + filter: invert(85%) sepia(7%) saturate(445%) hue-rotate(185deg) brightness(96%) contrast(92%); + opacity: 0.95; +} + .dashboard-page .filter-group input:hover, .dashboard-page .filter-group select:hover { border-color: #b9cbde; @@ -86,6 +110,11 @@ box-shadow: var(--shadow-card); } +:root[data-theme="dark"] .dashboard-page .stats-container, +:root[data-theme="dark"] .dashboard-page .table-container { + background: #111b2e; +} + .dashboard-page .stats-table, .dashboard-page table { width: 100%; @@ -109,6 +138,11 @@ overflow-wrap: anywhere; } +:root[data-theme="dark"] .dashboard-page .stats-table th, +:root[data-theme="dark"] .dashboard-page th { + background: #15233b; +} + .dashboard-page .stats-table td, .dashboard-page td { padding: 13px 14px; @@ -120,22 +154,63 @@ background: #fff; } +:root[data-theme="dark"] .dashboard-page .stats-table td, +:root[data-theme="dark"] .dashboard-page td { + background: #111b2e; +} + .dashboard-page .stats-table tbody tr:nth-child(even) td, .dashboard-page tbody tr:nth-child(even) td { background: #fbfdff; } +:root[data-theme="dark"] .dashboard-page .stats-table tbody tr:nth-child(even) td, +:root[data-theme="dark"] .dashboard-page tbody tr:nth-child(even) td { + background: #122038; +} + .dashboard-page .stats-table tbody tr:hover td, .dashboard-page tbody tr:hover td { background: #f2f7fd; } +:root[data-theme="dark"] .dashboard-page .stats-table tbody tr:hover td, +:root[data-theme="dark"] .dashboard-page tbody tr:hover td { + background: #1a2b45; +} + .dashboard-page .stats-total-row td { font-weight: 700; color: var(--text-primary); background: #eff5fc; } +:root[data-theme="dark"] .dashboard-page .stats-total-row td { + background: #1a2a44; +} + +.dashboard-page .ip-address { + display: inline-flex; + align-items: center; + border-radius: 9px; + border: 1px solid #c8d8ea; + background: linear-gradient(180deg, #f9fcff 0%, #f1f6fc 100%); + color: #22456f; + padding: 4px 10px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.02em; + font-family: "Cascadia Mono", "Consolas", monospace; + white-space: nowrap; + line-height: 1.1; +} + +:root[data-theme="dark"] .dashboard-page .ip-address { + border-color: #2b4469; + background: linear-gradient(180deg, #112038 0%, #0d1a30 100%); + color: #a7c8f0; +} + .dashboard-page .loading, .dashboard-page .empty-state, .dashboard-page .error { @@ -150,6 +225,11 @@ background: #fef2f2; } +:root[data-theme="dark"] .dashboard-page .error { + color: #ffb4bf; + background: #3a1f2b; +} + .dashboard-page .table-footer { padding: 14px 20px; } diff --git a/src/presentation/static/css/login.css b/src/presentation/static/css/login.css index c6e568e..02d8ac8 100644 --- a/src/presentation/static/css/login.css +++ b/src/presentation/static/css/login.css @@ -13,6 +13,13 @@ body.login-page { color: var(--text-primary); } +:root[data-theme="dark"] body.login-page { + background: + radial-gradient(1100px 620px at -10% -15%, #111d34 0%, transparent 60%), + radial-gradient(980px 640px at 100% 0%, #15223b 0%, transparent 62%), + var(--bg-page); +} + .login-page .login-shell { width: 100%; max-width: 420px; @@ -23,12 +30,20 @@ body.login-page { overflow: hidden; } +:root[data-theme="dark"] .login-page .login-shell { + box-shadow: 0 12px 34px rgba(0, 0, 0, 0.4); +} + .login-page .login-head { padding: 22px 24px; border-bottom: 1px solid var(--line); background: linear-gradient(180deg, #fbfdff 0%, #f5f9ff 100%); } +:root[data-theme="dark"] .login-page .login-head { + background: linear-gradient(180deg, #121d31 0%, #0f1728 100%); +} + .login-page .login-head h1 { margin: 0; font-size: 1.38rem; @@ -65,6 +80,10 @@ body.login-page { transition: border-color var(--transition), box-shadow var(--transition), background-color var(--transition); } +:root[data-theme="dark"] .login-page .form-control { + background: #0d1627; +} + .login-page .form-control:hover { border-color: #b9cbde; background: #fcfeff; diff --git a/src/presentation/static/css/users.css b/src/presentation/static/css/users.css index 4776334..7d03626 100644 --- a/src/presentation/static/css/users.css +++ b/src/presentation/static/css/users.css @@ -28,6 +28,10 @@ background: #fff; } +:root[data-theme="dark"] .users-page .users-section { + background: #111b2e; +} + .users-page .users-section h2 { margin: 0 0 14px; font-size: 18px; @@ -95,6 +99,10 @@ overflow-wrap: anywhere; } +:root[data-theme="dark"] .users-page .users-table th { + background: #15233b; +} + .users-page .users-table th.sortable-th { padding: 0; } @@ -134,26 +142,46 @@ background: #fff; } +:root[data-theme="dark"] .users-page .users-table td { + background: #111b2e; +} + .users-page .users-table tbody tr:nth-child(even) td { background: #fbfdff; } +:root[data-theme="dark"] .users-page .users-table tbody tr:nth-child(even) td { + background: #122038; +} + .users-page .users-table tbody tr:hover td { background: #f2f7fd; } +:root[data-theme="dark"] .users-page .users-table tbody tr:hover td { + background: #1a2b45; +} + .users-page .ip-address { display: inline-flex; align-items: center; - border-radius: 8px; - border: 1px solid var(--line); - background: #f8fbff; - color: var(--text-secondary); - padding: 3px 8px; - font-size: 12px; + border-radius: 9px; + border: 1px solid #c8d8ea; + background: linear-gradient(180deg, #f9fcff 0%, #f1f6fc 100%); + color: #22456f; + padding: 4px 10px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.02em; font-family: "Cascadia Mono", "Consolas", monospace; - white-space: normal; - overflow-wrap: anywhere; + white-space: nowrap; + line-height: 1.1; +} + +:root[data-theme="dark"] .users-page .ip-address { + border-color: #2b4469; + background: linear-gradient(180deg, #112038 0%, #0d1a30 100%); + color: #a7c8f0; } .users-page .action-buttons { @@ -179,6 +207,11 @@ border-color: #d6e4f1; } +:root[data-theme="dark"] .users-page .btn-edit { + background: #1a2d49; + border-color: #28466d; +} + .users-page .btn-edit:hover { color: #fff; background: var(--primary); @@ -191,6 +224,11 @@ border-color: #f3d7dc; } +:root[data-theme="dark"] .users-page .btn-delete { + background: #3a1f2b; + border-color: #5c2d3b; +} + .users-page .btn-delete:hover { color: #fff; background: var(--danger-hover); @@ -221,6 +259,11 @@ transition: background-color var(--transition), border-color var(--transition); } +:root[data-theme="dark"] .users-page .slider { + background: #1a2b45; + border-color: #2d4163; +} + .users-page .slider::before { content: ""; position: absolute; @@ -234,6 +277,10 @@ transition: transform var(--transition); } +:root[data-theme="dark"] .users-page .slider::before { + background: #e8eef8; +} + .users-page .switch input:checked + .slider { background: #e7f5ef; border-color: #b7dccf; @@ -261,18 +308,35 @@ background: #fbfdff; } +:root[data-theme="dark"] .users-page .loading, +:root[data-theme="dark"] .users-page .empty-state { + background: #0f1728; +} + .users-page .error { color: #9b2c2c; border: 1px solid #f1d4d8; background: #fef2f2; } +:root[data-theme="dark"] .users-page .error { + color: #ffb4bf; + border-color: #5c2d3b; + background: #3a1f2b; +} + .users-page .success { color: #24604d; border: 1px solid #cce4dc; background: #edf9f4; } +:root[data-theme="dark"] .users-page .success { + background: #193229; + border-color: #2f5e4e; + color: #a9e2cb; +} + .users-page .table-footer { padding: 14px 4px 0; margin-top: 14px; diff --git a/src/presentation/templates/index.html b/src/presentation/templates/index.html index b7c20b8..07ae866 100644 --- a/src/presentation/templates/index.html +++ b/src/presentation/templates/index.html @@ -2,7 +2,14 @@
- + +实时监控 API 请求和 Token 消耗