Commit 8d3f79cf authored by 陈曦's avatar 陈曦
Browse files

继续修改首页、登录页、后台的所有设计风格

parent b4412353
<template>
<header class="glass sticky top-0 z-30 border-b border-gray-200/50 dark:border-dark-700/50">
<header class="app-header sticky top-0 z-30 border-b border-gray-200/40 dark:border-white/[0.05]">
<div class="flex h-16 items-center justify-between px-4 md:px-6">
<!-- Left: Mobile Menu Toggle + Page Title -->
<div class="flex items-center gap-4">
......@@ -335,4 +335,13 @@ onBeforeUnmount(() => {
opacity: 0;
transform: scale(0.95) translateY(-4px);
}
.app-header {
background: rgba(241, 245, 251, 0.85);
backdrop-filter: blur(20px);
}
:global(.dark) .app-header {
background: rgba(8, 14, 28, 0.85);
backdrop-filter: blur(20px);
}
</style>
<template>
<div class="min-h-screen bg-gray-50 dark:bg-dark-950">
<div class="app-root min-h-screen">
<!-- Background Decoration -->
<div class="pointer-events-none fixed inset-0 bg-mesh-gradient"></div>
<div class="pointer-events-none fixed inset-0 app-bg-layer"></div>
<!-- Sidebar -->
<AppSidebar />
......@@ -50,3 +50,25 @@ onMounted(() => {
defineExpose({ replayTour })
</script>
<style scoped>
.app-root {
background: #f1f5fb;
}
:global(.dark) .app-root {
background: #080e1c;
}
.app-bg-layer {
background:
radial-gradient(at 15% 30%, rgba(99, 102, 241, 0.06) 0px, transparent 50%),
radial-gradient(at 85% 10%, rgba(20, 184, 166, 0.05) 0px, transparent 50%),
radial-gradient(at 60% 80%, rgba(139, 92, 246, 0.04) 0px, transparent 50%);
}
:global(.dark) .app-bg-layer {
background:
radial-gradient(at 15% 30%, rgba(99, 102, 241, 0.08) 0px, transparent 50%),
radial-gradient(at 85% 10%, rgba(20, 184, 166, 0.06) 0px, transparent 50%),
radial-gradient(at 60% 80%, rgba(139, 92, 246, 0.05) 0px, transparent 50%);
}
</style>
......@@ -60,7 +60,7 @@
<div v-if="!sidebarCollapsed" class="sidebar-section-title">
{{ t('nav.myAccount') }}
</div>
<div v-else class="mx-3 my-3 h-px bg-gray-200 dark:bg-dark-700"></div>
<div v-else class="mx-3 my-3 h-px" style="background: rgba(255,255,255,0.06)"></div>
<router-link
v-for="item in personalNavItems"
......@@ -105,7 +105,7 @@
</nav>
<!-- Bottom Section -->
<div class="mt-auto border-t border-gray-100 p-3 dark:border-dark-800">
<div class="mt-auto p-3" style="border-top: 1px solid rgba(255,255,255,0.05)">
<!-- Theme Toggle -->
<button
@click="toggleTheme"
......
<template>
<div class="auth-root relative flex min-h-screen items-center justify-center overflow-hidden p-4">
<div class="auth-split min-h-screen">
<!-- Background -->
<!-- ══════════════════════════════════════════
LEFT PANEL — AI Visual (hidden on mobile)
══════════════════════════════════════════ -->
<div class="auth-left hidden lg:flex">
<!-- Background layers -->
<div class="pointer-events-none absolute inset-0 overflow-hidden">
<div class="auth-orb auth-orb-tr"></div>
<div class="auth-orb auth-orb-bl"></div>
<div class="auth-grid"></div>
<div class="auth-scan"></div>
<div class="left-aurora left-aurora-1"></div>
<div class="left-aurora left-aurora-2"></div>
</div>
<!-- Content -->
<div class="relative z-10 w-full max-w-md">
<div class="relative z-10 flex h-full flex-col px-12 py-10">
<!-- Brand -->
<div class="mb-8 text-center">
<!-- Logo + Brand -->
<div class="flex items-center gap-3">
<template v-if="settingsLoaded">
<!-- Logo -->
<div class="auth-logo-wrap mb-5 inline-flex h-16 w-16 items-center justify-center overflow-hidden rounded-2xl">
<div class="left-logo-wrap">
<img :src="siteLogo || '/logo.png'" alt="Logo" class="h-full w-full object-contain" />
</div>
<div>
<div class="text-base font-bold text-white">{{ siteName }}</div>
<div class="font-mono text-[10px] uppercase tracking-widest text-violet-400/60">// AI Gateway</div>
</div>
</template>
</div>
<!-- Center: Orbital AI Visualization -->
<div class="flex flex-1 flex-col items-center justify-center">
<div class="orbital-viz">
<!-- Hub -->
<div class="hub-outer">
<div class="hub-ring hub-ring-1"></div>
<div class="hub-ring hub-ring-2"></div>
<div class="hub-core">
<svg class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z" />
</svg>
</div>
</div>
<!-- Site name -->
<h1 class="auth-site-name mb-2 text-3xl font-black tracking-tight">
{{ siteName }}
</h1>
<!-- Orbiting model chips -->
<div class="orbit-chip chip-0">
<span class="chip-dot" style="background: #f97316"></span>
<span>Claude</span>
</div>
<div class="orbit-chip chip-1">
<span class="chip-dot" style="background: #22c55e"></span>
<span>GPT-4o</span>
</div>
<div class="orbit-chip chip-2">
<span class="chip-dot" style="background: #3b82f6"></span>
<span>Gemini</span>
</div>
<div class="orbit-chip chip-3">
<span class="chip-dot" style="background: #f43f5e"></span>
<span>DeepSeek</span>
</div>
<div class="orbit-chip chip-4">
<span class="chip-dot" style="background: #a855f7"></span>
<span>Llama</span>
</div>
<!-- Subtitle -->
<p class="auth-subtitle font-mono text-xs uppercase tracking-widest">
// {{ siteSubtitle }}
<!-- Connecting lines (SVG) -->
<svg class="orbit-lines" viewBox="0 0 340 340" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Lines from center (170,170) to chip positions -->
<line x1="170" y1="170" x2="275" y2="90" stroke="rgba(139,92,246,0.18)" stroke-width="1" stroke-dasharray="4 4">
<animate attributeName="stroke-dashoffset" values="0;-16" dur="1.2s" repeatCount="indefinite"/>
</line>
<line x1="170" y1="170" x2="300" y2="200" stroke="rgba(20,184,166,0.18)" stroke-width="1" stroke-dasharray="4 4">
<animate attributeName="stroke-dashoffset" values="0;-16" dur="1.6s" repeatCount="indefinite"/>
</line>
<line x1="170" y1="170" x2="200" y2="295" stroke="rgba(59,130,246,0.18)" stroke-width="1" stroke-dasharray="4 4">
<animate attributeName="stroke-dashoffset" values="0;-16" dur="2.0s" repeatCount="indefinite"/>
</line>
<line x1="170" y1="170" x2="65" y2="270" stroke="rgba(244,63,94,0.18)" stroke-width="1" stroke-dasharray="4 4">
<animate attributeName="stroke-dashoffset" values="0;-16" dur="1.4s" repeatCount="indefinite"/>
</line>
<line x1="170" y1="170" x2="55" y2="130" stroke="rgba(168,85,247,0.18)" stroke-width="1" stroke-dasharray="4 4">
<animate attributeName="stroke-dashoffset" values="0;-16" dur="1.8s" repeatCount="indefinite"/>
</line>
</svg>
</div>
<!-- Tagline -->
<div class="mt-10 text-center">
<h2 class="mb-3 text-2xl font-bold text-white">One Key.<br>Every Model.</h2>
<p class="max-w-xs text-sm leading-relaxed text-slate-400">
{{ siteSubtitle }}
</p>
</div>
</div>
<!-- Feature bullets -->
<div class="space-y-4 pb-4">
<div v-for="f in leftFeatures" :key="f.text" class="left-feature-row">
<div class="left-feature-icon" :style="{ background: f.iconBg }">
<component :is="f.icon" />
</div>
<div>
<div class="text-sm font-medium text-slate-200">{{ f.text }}</div>
<div class="text-xs text-slate-500">{{ f.desc }}</div>
</div>
</div>
</div>
<!-- Copyright -->
<div class="pt-6 font-mono text-[10px] text-slate-700">
&copy; {{ currentYear }} {{ siteName }}
</div>
</div>
</div>
<!-- ══════════════════════════════════════════
RIGHT PANEL — Form
══════════════════════════════════════════ -->
<div class="auth-right">
<!-- Mobile: tiny logo strip -->
<div class="mb-8 flex items-center gap-2.5 lg:hidden">
<template v-if="settingsLoaded">
<div class="h-8 w-8 overflow-hidden rounded-lg shadow-glow">
<img :src="siteLogo || '/logo.png'" alt="Logo" class="h-full w-full object-contain" />
</div>
<span class="text-base font-bold text-gray-900 dark:text-white">{{ siteName }}</span>
</template>
</div>
<!-- Card -->
<div class="auth-card rounded-2xl p-8">
<!-- Form card -->
<div class="auth-form-card">
<slot />
</div>
<!-- Footer links -->
<div class="mt-6 text-center text-sm">
<div class="mt-5 text-center text-sm">
<slot name="footer" />
</div>
<!-- Copyright -->
<div class="mt-8 text-center font-mono text-xs text-slate-600">
<!-- Copyright (mobile only) -->
<div class="mt-8 text-center font-mono text-xs text-gray-400 dark:text-slate-700 lg:hidden">
&copy; {{ currentYear }} {{ siteName }}. All rights reserved.
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted } from 'vue'
import { computed, defineComponent, h, onMounted } from 'vue'
import { useAppStore } from '@/stores'
import { sanitizeUrl } from '@/utils/url'
......@@ -61,117 +157,295 @@ const siteName = computed(() => appStore.siteName || 'TrafficAPI')
const siteLogo = computed(() => sanitizeUrl(appStore.siteLogo || '', { allowRelative: true, allowDataUrl: true }))
const siteSubtitle = computed(() => appStore.cachedPublicSettings?.site_subtitle || 'Intelligent AI Traffic Routing & Management')
const settingsLoaded = computed(() => appStore.publicSettingsLoaded)
const currentYear = computed(() => new Date().getFullYear())
// Inline icon components for feature bullets
const ShieldIcon = defineComponent({
render: () => h('svg', { class: 'h-4 w-4 text-white', fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', 'stroke-width': '1.5' }, [
h('path', { 'stroke-linecap': 'round', 'stroke-linejoin': 'round', d: 'M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z' })
])
})
const BoltIcon = defineComponent({
render: () => h('svg', { class: 'h-4 w-4 text-white', fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', 'stroke-width': '1.5' }, [
h('path', { 'stroke-linecap': 'round', 'stroke-linejoin': 'round', d: 'M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z' })
])
})
const ChartIcon = defineComponent({
render: () => h('svg', { class: 'h-4 w-4 text-white', fill: 'none', viewBox: '0 0 24 24', stroke: 'currentColor', 'stroke-width': '1.5' }, [
h('path', { 'stroke-linecap': 'round', 'stroke-linejoin': 'round', d: 'M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z' })
])
})
const leftFeatures = [
{
text: '统一 API 接入点',
desc: '一个 Key 打通所有 AI 服务商,无需多套凭证',
icon: ShieldIcon,
iconBg: 'linear-gradient(135deg,#6366f1,#8b5cf6)',
},
{
text: '智能负载均衡',
desc: '自动分发流量,账户异常时即时切换,零中断',
icon: BoltIcon,
iconBg: 'linear-gradient(135deg,#14b8a6,#06b6d4)',
},
{
text: '实时流量分析',
desc: '请求量、延迟、费用全透明,按用户精细管控',
icon: ChartIcon,
iconBg: 'linear-gradient(135deg,#a855f7,#ec4899)',
},
]
onMounted(() => {
appStore.fetchPublicSettings()
})
</script>
<style scoped>
/* ── Root ────────────────────────────────── */
.auth-root {
background: #182a40;
color: white;
/* ══════════════════════════════════════════════
SPLIT LAYOUT
══════════════════════════════════════════════ */
.auth-split {
display: flex;
min-height: 100vh;
}
/* ── Background layers ───────────────────── */
.auth-orb {
/* ── LEFT PANEL ────────────────────────────── */
.auth-left {
position: relative;
width: 55%;
max-width: 600px;
flex-shrink: 0;
background: #060c1a;
overflow: hidden;
flex-direction: column;
}
/* Aurora blobs on left panel */
.left-aurora {
position: absolute;
border-radius: 50%;
filter: blur(90px);
filter: blur(100px);
pointer-events: none;
}
.auth-orb-tr {
top: -10%;
right: -10%;
width: 420px;
height: 420px;
background: radial-gradient(ellipse, rgba(20,184,166,0.18) 0%, transparent 70%);
.left-aurora-1 {
top: -15%;
right: -15%;
width: 450px;
height: 450px;
background: radial-gradient(ellipse, rgba(139,92,246,0.22) 0%, transparent 65%);
animation: la-drift-1 20s ease-in-out infinite alternate;
}
.auth-orb-bl {
.left-aurora-2 {
bottom: -10%;
left: -10%;
width: 380px;
height: 380px;
background: radial-gradient(ellipse, rgba(6,182,212,0.13) 0%, transparent 70%);
width: 350px;
height: 350px;
background: radial-gradient(ellipse, rgba(20,184,166,0.18) 0%, transparent 65%);
animation: la-drift-2 24s ease-in-out infinite alternate;
}
@keyframes la-drift-1 {
from { transform: translate(0,0) scale(1); }
to { transform: translate(-20px,20px) scale(1.06); }
}
@keyframes la-drift-2 {
from { transform: translate(0,0) scale(1); }
to { transform: translate(20px,-20px) scale(1.04); }
}
.left-logo-wrap {
width: 36px;
height: 36px;
border-radius: 9px;
overflow: hidden;
box-shadow: 0 0 0 1px rgba(139,92,246,0.3), 0 0 16px rgba(139,92,246,0.15);
flex-shrink: 0;
}
.auth-grid {
/* ── ORBITAL VISUALIZATION ──────────────────── */
.orbital-viz {
position: relative;
width: 340px;
height: 340px;
}
/* Hub */
.hub-outer {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(20,184,166,0.07) 1px, transparent 1px),
linear-gradient(90deg, rgba(20,184,166,0.07) 1px, transparent 1px);
background-size: 48px 48px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
display: flex;
align-items: center;
justify-content: center;
}
.hub-ring {
position: absolute;
border-radius: 50%;
border: 1px solid rgba(139,92,246,0.15);
animation: hub-pulse 3s ease-in-out infinite;
}
.hub-ring-1 {
width: 80px;
height: 80px;
animation-delay: 0s;
}
.hub-ring-2 {
width: 110px;
height: 110px;
border-color: rgba(20,184,166,0.1);
animation-delay: 0.8s;
}
.auth-scan {
@keyframes hub-pulse {
0%,100% { transform: scale(1); opacity: 0.6; }
50% { transform: scale(1.06); opacity: 1; }
}
.hub-core {
width: 64px;
height: 64px;
border-radius: 16px;
background: linear-gradient(135deg, #3730a3, #4f46e5, #7c3aed);
box-shadow: 0 0 32px rgba(99,102,241,0.5), 0 0 64px rgba(99,102,241,0.2);
display: flex;
align-items: center;
justify-content: center;
position: relative;
z-index: 2;
}
/* Orbit chips — positioned around center */
.orbit-chip {
position: absolute;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent 0%, rgba(20,184,166,0.45) 30%, rgba(20,184,166,0.7) 50%, rgba(20,184,166,0.45) 70%, transparent 100%);
animation: auth-scan 12s linear infinite;
box-shadow: 0 0 8px rgba(20,184,166,0.35);
}
@keyframes auth-scan {
0% { top: 0%; opacity: 0; }
4% { opacity: 1; }
96% { opacity: 0.4; }
100% { top: 100%; opacity: 0; }
}
/* ── Logo ────────────────────────────────── */
.auth-logo-wrap {
box-shadow:
0 0 0 1px rgba(20,184,166,0.3),
0 0 20px rgba(20,184,166,0.18),
0 8px 24px rgba(0,0,0,0.4);
}
/* ── Brand text ──────────────────────────── */
.auth-site-name {
background: linear-gradient(135deg, #ffffff 0%, #7dd3c8 45%, #14b8a6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.auth-subtitle {
color: rgba(20,184,166,0.5);
}
/* ── Card ────────────────────────────────── */
.auth-card {
background: rgba(26,46,72,0.72);
border: 1px solid rgba(255,255,255,0.09);
backdrop-filter: blur(18px);
box-shadow:
0 0 0 1px rgba(20,184,166,0.08),
0 24px 60px rgba(0,0,0,0.45),
0 0 50px rgba(20,184,166,0.05);
}
/* ── Slot overrides: make child inputs/links readable ── */
display: flex;
align-items: center;
gap: 6px;
padding: 5px 11px 5px 8px;
border-radius: 20px;
border: 1px solid rgba(255,255,255,0.08);
background: rgba(15,22,40,0.85);
backdrop-filter: blur(8px);
font-size: 11px;
font-weight: 500;
color: #cbd5e1;
white-space: nowrap;
animation: chip-float 4s ease-in-out infinite;
}
.chip-dot {
width: 7px;
height: 7px;
border-radius: 50%;
flex-shrink: 0;
}
/* Position each chip around the orbital */
.chip-0 { top: 6%; left: 62%; animation-delay: 0.0s; }
.chip-1 { top: 44%; left: 80%; animation-delay: 0.6s; }
.chip-2 { top: 78%; left: 52%; animation-delay: 1.2s; }
.chip-3 { top: 72%; left: 6%; animation-delay: 1.8s; }
.chip-4 { top: 12%; left: 2%; animation-delay: 2.4s; }
@keyframes chip-float {
0%,100% { transform: translateY(0); }
50% { transform: translateY(-6px); }
}
/* SVG connecting lines */
.orbit-lines {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
/* Feature rows */
.left-feature-row {
display: flex;
align-items: flex-start;
gap: 12px;
}
.left-feature-icon {
width: 34px;
height: 34px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
/* ── RIGHT PANEL ─────────────────────────── */
.auth-right {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 32px;
background: #f8fafc;
min-height: 100vh;
}
/* Dark mode right panel */
:global(.dark) .auth-right {
background: #0f172a;
}
.auth-form-card {
width: 100%;
max-width: 400px;
background: white;
border-radius: 20px;
border: 1px solid rgba(0,0,0,0.06);
box-shadow: 0 4px 32px rgba(0,0,0,0.08), 0 1px 4px rgba(0,0,0,0.04);
padding: 36px 32px;
}
:global(.dark) .auth-form-card {
background: #1e293b;
border-color: rgba(255,255,255,0.08);
box-shadow: 0 4px 32px rgba(0,0,0,0.4);
}
/* Override slot content for right panel (light mode) */
:deep(h2) {
color: #0f172a !important;
}
:global(.dark) :deep(h2) {
color: white !important;
}
:deep(.input-label) {
color: #374151;
}
:global(.dark) :deep(.input-label) {
color: #94a3b8;
}
:deep(.input) {
background: #f9fafb;
border-color: #e5e7eb;
color: #0f172a;
}
:global(.dark) :deep(.input) {
background: rgba(15,28,48,0.7);
border-color: rgba(255,255,255,0.1);
color: white;
}
:deep(.input:focus) {
border-color: rgba(20,184,166,0.5);
box-shadow: 0 0 0 3px rgba(20,184,166,0.12);
border-color: #8b5cf6;
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
}
:deep(.input::placeholder) {
color: #475569;
color: #9ca3af;
}
:deep(h2) {
color: white !important;
:global(.dark) :deep(.input::placeholder) {
color: #475569;
}
:deep(.text-gray-500),
:deep(.dark\:text-dark-400) {
color: #6b7280 !important;
}
:global(.dark) :deep(.text-gray-500),
:global(.dark) :deep(.dark\:text-dark-400) {
color: #64748b !important;
}
</style>
......@@ -40,6 +40,13 @@ export default {
}
}
},
// Pipeline visualization labels
pipeline: {
gateway: 'Gateway',
balancer: 'Balancer',
aiPool: 'AI Pool',
response: 'Response',
},
// Solutions section
solutions: {
title: 'TrafficAPI Solves This',
......
......@@ -40,6 +40,13 @@ export default {
}
}
},
// 管道可视化标签
pipeline: {
gateway: '网关',
balancer: '均衡器',
aiPool: 'AI 池',
response: '响应',
},
// 解决方案区块
solutions: {
title: 'TrafficAPI 为你解决',
......
......@@ -96,16 +96,26 @@
@apply inline-flex items-center justify-center gap-2;
@apply rounded-xl px-4 py-2.5 text-sm font-medium;
@apply transition-all duration-200 ease-out;
@apply focus:outline-none focus:ring-2 focus:ring-primary-500/50 focus:ring-offset-2;
@apply focus:outline-none;
@apply disabled:transform-none disabled:cursor-not-allowed disabled:opacity-50;
@apply active:scale-[0.98];
}
.btn-primary {
@apply bg-gradient-to-r from-primary-500 to-primary-600;
@apply text-white shadow-md shadow-primary-500/25;
@apply hover:from-primary-600 hover:to-primary-700 hover:shadow-lg hover:shadow-primary-500/30;
@apply dark:shadow-primary-500/20;
background: linear-gradient(135deg, #7c3aed, #8b5cf6);
color: white;
box-shadow: 0 4px 14px rgba(139, 92, 246, 0.35);
}
.btn-primary:hover {
background: linear-gradient(135deg, #6d28d9, #7c3aed);
box-shadow: 0 6px 20px rgba(139, 92, 246, 0.45);
transform: translateY(-1px);
}
.btn-primary:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.35), 0 4px 14px rgba(139, 92, 246, 0.3);
}
.btn-secondary {
......@@ -165,7 +175,7 @@
@apply text-gray-900 dark:text-gray-100;
@apply placeholder:text-gray-400 dark:placeholder:text-dark-400;
@apply transition-all duration-200;
@apply focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/30;
@apply focus:outline-none focus:border-[#8b5cf6] focus:ring-2 focus:ring-[#8b5cf6]/20;
@apply disabled:cursor-not-allowed disabled:bg-gray-100 dark:disabled:bg-dark-900;
}
......@@ -522,11 +532,12 @@
@apply border-l-primary-500;
}
/* ============ 侧边栏 ============ */
/* ============ 侧边栏 — 恒暗风格 ============ */
.sidebar {
@apply fixed inset-y-0 left-0 z-40;
@apply w-64 bg-white dark:bg-dark-900;
@apply border-r border-gray-200 dark:border-dark-800;
@apply w-64;
background: #0c1220;
border-right: 1px solid rgba(139, 92, 246, 0.08);
@apply flex flex-col;
@apply transition-transform duration-300;
}
......@@ -534,7 +545,7 @@
.sidebar-header {
@apply h-16 px-6;
@apply flex items-center gap-3;
@apply border-b border-gray-100 dark:border-dark-800;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.sidebar-nav {
......@@ -544,16 +555,26 @@
.sidebar-link {
@apply flex items-center gap-3 rounded-xl px-3 py-2.5;
@apply text-sm font-medium;
@apply text-gray-600 dark:text-dark-300;
color: rgba(148, 163, 184, 0.85);
@apply transition-all duration-200;
@apply hover:bg-gray-100 dark:hover:bg-dark-800;
@apply hover:text-gray-900 dark:hover:text-white;
}
.sidebar-link:hover {
background: rgba(255, 255, 255, 0.055);
color: rgba(226, 232, 240, 1);
}
.sidebar-link-active {
@apply bg-primary-50 dark:bg-primary-900/20;
@apply text-primary-600 dark:text-primary-400;
@apply hover:bg-primary-100 dark:hover:bg-primary-900/30;
background: linear-gradient(135deg, rgba(99, 102, 241, 0.18), rgba(20, 184, 166, 0.12));
border-left: 2px solid #14b8a6;
padding-left: calc(0.75rem - 2px);
color: #5eead4 !important;
box-shadow: inset 0 0 16px rgba(20, 184, 166, 0.04);
}
.sidebar-link-active:hover {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.24), rgba(20, 184, 166, 0.18));
color: #5eead4 !important;
}
.sidebar-section {
......@@ -563,7 +584,7 @@
.sidebar-section-title {
@apply mb-2 px-3;
@apply text-xs font-semibold uppercase tracking-wider;
@apply text-gray-400 dark:text-dark-500;
color: rgba(100, 116, 139, 0.7);
}
/* ============ 页面头部 ============ */
......
This diff is collapsed.
......@@ -80,7 +80,7 @@
<router-link
v-if="passwordResetEnabled && !backendModeEnabled"
to="/forgot-password"
class="text-sm font-medium text-primary-600 transition-colors hover:text-primary-500 dark:text-primary-400 dark:hover:text-primary-300"
class="text-sm font-medium transition-colors" style="color: #8b5cf6;"
>
{{ t('auth.forgotPassword') }}
</router-link>
......
......@@ -67,8 +67,8 @@ export default {
boxShadow: {
glass: '0 8px 32px rgba(0, 0, 0, 0.08)',
'glass-sm': '0 4px 16px rgba(0, 0, 0, 0.06)',
glow: '0 0 20px rgba(20, 184, 166, 0.25)',
'glow-lg': '0 0 40px rgba(20, 184, 166, 0.35)',
glow: '0 0 0 1px rgba(99, 102, 241, 0.25), 0 0 20px rgba(99, 102, 241, 0.15)',
'glow-lg': '0 0 40px rgba(99, 102, 241, 0.35)',
card: '0 1px 3px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06)',
'card-hover': '0 10px 40px rgba(0, 0, 0, 0.08)',
'inner-glow': 'inset 0 1px 0 rgba(255, 255, 255, 0.1)'
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment