feat: light theme, frontend link, nav fix, rename to 七虎AI
This commit is contained in:
1 parent
effef176e2
commit
e38a32e04e
12 files changed
+429
-345
No files matched your search
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Qihu-AIFlow - 智能自动化PaaS平台</title>
|
<title>七虎AI - 智能AI能力集成平台</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0A0E1A;
|
background: #F5F7FC;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
.admin-sidebar {
|
.admin-sidebar {
|
||||||
width: var(--admin-sidebar-width);
|
width: var(--admin-sidebar-width);
|
||||||
min-width: var(--admin-sidebar-width);
|
min-width: var(--admin-sidebar-width);
|
||||||
background: linear-gradient(180deg, #0E1225 0%, #111627 100%);
|
background: linear-gradient(180deg, #FFFFFF 0%, #FAFBFE 100%);
|
||||||
border-right: 1px solid rgba(255, 255, 255, 0.06);
|
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transition: width 0.25s ease, min-width 0.25s ease;
|
transition: width 0.25s ease, min-width 0.25s ease;
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 16px 16px 16px 20px;
|
padding: 16px 16px 16px 20px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@
|
|||||||
.admin-brand {
|
.admin-brand {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: -0.02em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
background: linear-gradient(135deg, #C4B5FD, #A78BFA);
|
background: linear-gradient(135deg, #6C63FF, #A78BFA);
|
||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
background-clip: text;
|
background-clip: text;
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #5A6480;
|
color: #8892B0;
|
||||||
transition: all 0.15s ease;
|
transition: all 0.15s ease;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-nav::-webkit-scrollbar-thumb {
|
.admin-nav::-webkit-scrollbar-thumb {
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(108, 99, 255, 0.10);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-nav-item:hover {
|
.admin-nav-item:hover {
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(108, 99, 255, 0.06);
|
||||||
color: #CCD6F6;
|
color: #CCD6F6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@
|
|||||||
/* Sidebar Footer */
|
/* Sidebar Footer */
|
||||||
.admin-sidebar-footer {
|
.admin-sidebar-footer {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0 32px;
|
padding: 0 32px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
background: rgba(10, 14, 26, 0.85);
|
background: rgba(10, 14, 26, 0.85);
|
||||||
backdrop-filter: blur(12px);
|
backdrop-filter: blur(12px);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
.admin-page-title {
|
.admin-page-title {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-item {
|
.breadcrumb-item {
|
||||||
color: #5A6480;
|
color: #8892B0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breadcrumb-item.current {
|
.breadcrumb-item.current {
|
||||||
@@ -343,7 +343,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-topbar-action:hover {
|
.admin-topbar-action:hover {
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: rgba(108, 99, 255, 0.06);
|
||||||
color: #A78BFA;
|
color: #A78BFA;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@
|
|||||||
padding: 2px 12px 2px 4px;
|
padding: 2px 12px 2px 4px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #CCD6F6;
|
color: #CCD6F6;
|
||||||
}
|
}
|
||||||
@@ -379,7 +379,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: #0A0E1A;
|
background: #F5F7FC;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-content {
|
.admin-content {
|
||||||
@@ -398,7 +398,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-content::-webkit-scrollbar-thumb {
|
.admin-content::-webkit-scrollbar-thumb {
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(108, 99, 255, 0.10);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@
|
|||||||
|
|
||||||
.admin-stat-card {
|
.admin-stat-card {
|
||||||
background: linear-gradient(135deg, rgba(17, 22, 39, 0.8), rgba(17, 22, 39, 0.6));
|
background: linear-gradient(135deg, rgba(17, 22, 39, 0.8), rgba(17, 22, 39, 0.6));
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
.admin-stat-card .stat-value {
|
.admin-stat-card .stat-value {
|
||||||
font-size: 28px;
|
font-size: 28px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@
|
|||||||
/* Page section card */
|
/* Page section card */
|
||||||
.admin-section {
|
.admin-section {
|
||||||
background: rgba(17, 22, 39, 0.5);
|
background: rgba(17, 22, 39, 0.5);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
@@ -467,13 +467,13 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-section-header h3 {
|
.admin-section-header h3 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,7 +522,7 @@
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
background: rgba(255, 255, 255, 0.02);
|
background: rgba(255, 255, 255, 0.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,7 +565,7 @@
|
|||||||
.admin-btn-secondary {
|
.admin-btn-secondary {
|
||||||
background: rgba(255, 255, 255, 0.06);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
color: #8892B0;
|
color: #8892B0;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-btn-secondary:hover {
|
.admin-btn-secondary:hover {
|
||||||
@@ -614,7 +614,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 8px 14px;
|
padding: 8px 14px;
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #8892B0;
|
color: #8892B0;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -631,7 +631,7 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
@@ -708,8 +708,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-modal {
|
.admin-modal {
|
||||||
background: #111627;
|
background: #FFFFFF;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
min-width: 420px;
|
min-width: 420px;
|
||||||
@@ -722,7 +722,7 @@
|
|||||||
.admin-modal h3 {
|
.admin-modal h3 {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
margin: 0 0 20px 0;
|
margin: 0 0 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -745,9 +745,9 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
transition: border-color 0.15s ease;
|
transition: border-color 0.15s ease;
|
||||||
outline: none;
|
outline: none;
|
||||||
@@ -766,8 +766,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-form-group select option {
|
.admin-form-group select option {
|
||||||
background: #111627;
|
background: #FFFFFF;
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toggle switch */
|
/* Toggle switch */
|
||||||
@@ -840,7 +840,7 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: #8892B0;
|
color: #8892B0;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@@ -905,7 +905,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-modal-header h3 {
|
.admin-modal-header h3 {
|
||||||
@@ -926,7 +926,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.admin-modal-close:hover {
|
.admin-modal-close:hover {
|
||||||
color: #E8ECF4;
|
color: #1A1F36;
|
||||||
background: rgba(255, 255, 255, 0.06);
|
background: rgba(255, 255, 255, 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -939,7 +939,7 @@
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.06);
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spinner animation for logo upload */
|
/* Spinner animation for logo upload */
|
||||||
@@ -987,3 +987,31 @@
|
|||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Frontend access link */
|
||||||
|
.admin-frontend-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
margin: 8px 12px;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #6C63FF;
|
||||||
|
background: rgba(108, 99, 255, 0.08);
|
||||||
|
text-decoration: none;
|
||||||
|
transition: all 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-frontend-link:hover {
|
||||||
|
background: rgba(108, 99, 255, 0.15);
|
||||||
|
color: #5B5FED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nav link cursor pointer */
|
||||||
|
.landing-nav-v2 a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
@@ -139,9 +139,13 @@ const AdminLayout: React.FC = () => {
|
|||||||
<div className="admin-layout">
|
<div className="admin-layout">
|
||||||
<aside className="admin-sidebar">
|
<aside className="admin-sidebar">
|
||||||
<div className="admin-sidebar-header">
|
<div className="admin-sidebar-header">
|
||||||
<h1 className="admin-logo">AIFlow</h1>
|
<h1 className="admin-logo">七虎AI</h1>
|
||||||
<span className="admin-subtitle">管理控制台</span>
|
<span className="admin-subtitle">管理控制台</span>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="/#/portal" target="_blank" rel="noopener noreferrer" className="admin-frontend-link">
|
||||||
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
|
||||||
|
<span>访问前台</span>
|
||||||
|
</a>
|
||||||
<nav className="sidebar-nav">
|
<nav className="sidebar-nav">
|
||||||
{adminNavGroups.map((group) => {
|
{adminNavGroups.map((group) => {
|
||||||
const isCollapsed = collapsedGroups.has(group.title);
|
const isCollapsed = collapsedGroups.has(group.title);
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
/* ===== Front Layout ===== */
|
/* ===== Front Layout V3 - Light Theme ===== */
|
||||||
.front-layout {
|
.front-layout {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background: #F5F7FC;
|
||||||
|
color: #1A1F36;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar */
|
/* Sidebar */
|
||||||
.front-sidebar {
|
.front-sidebar {
|
||||||
width: var(--sidebar-width);
|
width: var(--sidebar-width);
|
||||||
min-width: var(--sidebar-width);
|
min-width: var(--sidebar-width);
|
||||||
background: var(--color-sidebar-bg);
|
background: linear-gradient(180deg, #FFFFFF 0%, #FAFBFE 100%);
|
||||||
border-right: 1px solid var(--color-border-light);
|
border-right: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transition: width var(--transition-slow), min-width var(--transition-slow);
|
transition: width var(--transition-slow), min-width var(--transition-slow);
|
||||||
@@ -29,7 +31,7 @@
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: var(--space-lg) var(--space-lg);
|
padding: var(--space-lg) var(--space-lg);
|
||||||
height: var(--header-height);
|
height: var(--header-height);
|
||||||
border-bottom: 1px solid var(--color-border-light);
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-logo {
|
.sidebar-logo {
|
||||||
@@ -41,7 +43,7 @@
|
|||||||
.sidebar-brand {
|
.sidebar-brand {
|
||||||
font-size: var(--text-lg);
|
font-size: var(--text-lg);
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--color-text-primary);
|
color: #1A1F36;
|
||||||
letter-spacing: -0.02em;
|
letter-spacing: -0.02em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -53,13 +55,14 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-text-tertiary);
|
color: #8892B0;
|
||||||
transition: all var(--transition-fast);
|
transition: all var(--transition-fast);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapse-btn:hover {
|
.collapse-btn:hover {
|
||||||
background: var(--color-bg-hover);
|
background: rgba(0, 0, 0, 0.08);
|
||||||
color: var(--color-text-primary);
|
color: #8892B0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Navigation */
|
/* Navigation */
|
||||||
@@ -68,7 +71,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: var(--space-sm) var(--space-sm);
|
padding: var(--space-sm);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,12 +82,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
padding: var(--space-md) var(--space-md);
|
padding: 10px var(--space-md);
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
color: var(--color-text-secondary);
|
color: #8892B0;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-size: var(--text-base);
|
font-size: var(--text-base);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -93,13 +97,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nav-item:hover {
|
.nav-item:hover {
|
||||||
background: var(--color-sidebar-hover);
|
background: rgba(108, 99, 255, 0.06);
|
||||||
color: var(--color-text-primary);
|
color: #1A1F36;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item.active {
|
.nav-item.active {
|
||||||
background: var(--color-sidebar-active);
|
background: rgba(108, 99, 255, 0.12);
|
||||||
color: var(--color-accent);
|
color: #8B85FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-icon {
|
.nav-icon {
|
||||||
@@ -115,10 +119,30 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Active dot indicator */
|
||||||
|
.nav-active-dot {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item.active .nav-active-dot {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #6C63FF;
|
||||||
|
box-shadow: 0 0 8px rgba(108, 99, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
/* Sidebar Footer */
|
/* Sidebar Footer */
|
||||||
.sidebar-footer {
|
.sidebar-footer {
|
||||||
padding: var(--space-md);
|
padding: var(--space-md);
|
||||||
border-top: 1px solid var(--color-border-light);
|
border-top: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-footer .nav-item {
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info-mini {
|
.user-info-mini {
|
||||||
@@ -126,13 +150,14 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
padding: var(--space-sm);
|
padding: var(--space-sm);
|
||||||
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-avatar-sm {
|
.user-avatar-sm {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: var(--radius-full);
|
border-radius: var(--radius-full);
|
||||||
background: linear-gradient(135deg, var(--color-accent), #8B8DFF);
|
background: linear-gradient(135deg, #6C63FF, #A78BFA);
|
||||||
color: white;
|
color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -151,16 +176,21 @@
|
|||||||
.user-name {
|
.user-name {
|
||||||
font-size: var(--text-sm);
|
font-size: var(--text-sm);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--color-text-primary);
|
color: #1A1F36;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-plan {
|
.user-plan {
|
||||||
font-size: var(--text-xs);
|
font-size: var(--text-xs);
|
||||||
color: var(--color-accent);
|
color: #8B85FF;
|
||||||
line-height: 1.3;
|
line-height: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.logout-btn:hover {
|
||||||
|
color: #EF4444 !important;
|
||||||
|
background: rgba(239, 68, 68, 0.1) !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Main Content */
|
/* Main Content */
|
||||||
.front-main {
|
.front-main {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -168,6 +198,12 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
background: #F5F7FC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forward-slash route for apps - hidden default route */
|
||||||
|
.front-main > * {
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive */
|
/* Responsive */
|
||||||
@@ -187,3 +223,11 @@
|
|||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Home & Admin links */
|
||||||
|
.nav-home-link {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
@@ -5,13 +5,13 @@ import './FrontLayout.css';
|
|||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ path: '/chat', icon: 'chat', label: 'AI聊天' },
|
{ path: '/chat', icon: 'chat', label: 'AI聊天' },
|
||||||
{ path: '/channels', icon: 'channel', label: '频道' },
|
{ path: '/channels', icon: 'channel', label: 'IM Bot' },
|
||||||
{ path: '/knowledge', icon: 'knowledge', label: '知识库' },
|
{ path: '/knowledge', icon: 'knowledge', label: '知识库' },
|
||||||
{ path: '/market', icon: 'market', label: '应用市场' },
|
{ path: '/market', icon: 'market', label: '技能市场' },
|
||||||
{ path: '/token', icon: 'token', label: 'Token驾驶舱' },
|
{ path: '/token', icon: 'token', label: 'Token驾驶舱' },
|
||||||
{ path: '/pricing', icon: 'pricing', label: '付费中心' },
|
{ path: '/pricing', icon: 'pricing', label: '付费中心' },
|
||||||
{ path: '/assets', icon: 'assets', label: '资产' },
|
{ path: '/assets', icon: 'assets', label: '资产文件' },
|
||||||
{ path: '/evolution', icon: 'evolution', label: 'AI进化' },
|
{ path: '/evolution', icon: 'evolution', label: 'AI自进化' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const bottomItems = [
|
const bottomItems = [
|
||||||
@@ -24,6 +24,7 @@ const iconPaths: Record<string, JSX.Element> = {
|
|||||||
channel: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>,
|
channel: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>,
|
||||||
knowledge: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>,
|
knowledge: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>,
|
||||||
market: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.2"/><rect x="14" y="3" width="7" height="7" rx="1.2"/><rect x="3" y="14" width="7" height="7" rx="1.2"/><rect x="14" y="14" width="7" height="7" rx="1.2"/></svg>,
|
market: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="7" height="7" rx="1.2"/><rect x="14" y="3" width="7" height="7" rx="1.2"/><rect x="3" y="14" width="7" height="7" rx="1.2"/><rect x="14" y="14" width="7" height="7" rx="1.2"/></svg>,
|
||||||
|
apps: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="2" width="9" height="9" rx="2"/><rect x="13" y="2" width="9" height="9" rx="2"/><rect x="2" y="13" width="9" height="9" rx="2"/><rect x="13" y="13" width="5" height="5" rx="1.5"/><path d="M18 18v3"/><path d="M19.5 16.5v6"/></svg>,
|
||||||
token: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>,
|
token: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>,
|
||||||
pricing: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 18V6"/></svg>,
|
pricing: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"/><path d="M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8"/><path d="M12 18V6"/></svg>,
|
||||||
profile: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>,
|
profile: <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>,
|
||||||
@@ -46,32 +47,48 @@ const FrontLayout: React.FC = () => {
|
|||||||
<div className="front-layout">
|
<div className="front-layout">
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<aside className={`front-sidebar ${collapsed ? 'collapsed' : ''}`}>
|
<aside className={`front-sidebar ${collapsed ? 'collapsed' : ''}`}>
|
||||||
|
{/* Header */}
|
||||||
<div className="sidebar-header">
|
<div className="sidebar-header">
|
||||||
<div className="sidebar-logo">
|
<div className="sidebar-logo">
|
||||||
<svg width="28" height="28" viewBox="0 0 32 32" fill="none">
|
<svg width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||||
<rect width="32" height="32" rx="8" fill="#5B5FED"/>
|
<defs>
|
||||||
|
<linearGradient id="flGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" stopColor="#6C63FF"/>
|
||||||
|
<stop offset="100%" stopColor="#A78BFA"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="32" height="32" rx="8" fill="url(#flGrad)"/>
|
||||||
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
||||||
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
||||||
</svg>
|
</svg>
|
||||||
{!collapsed && <span className="sidebar-brand">Qihu-AIFlow</span>}
|
{!collapsed && <span className="sidebar-brand">七虎AI</span>}
|
||||||
</div>
|
</div>
|
||||||
<button className="collapse-btn" onClick={() => setCollapsed(!collapsed)}>
|
<button className="collapse-btn" onClick={() => setCollapsed(!collapsed)}>
|
||||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
||||||
<line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="18" x2="21" y2="18"/>
|
{collapsed ? <><polyline points="13 17 18 12 13 7"/><polyline points="6 17 11 12 6 7"/></> : <><polyline points="11 17 6 12 11 7"/><polyline points="18 17 13 12 18 7"/></>}
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Navigation */}
|
||||||
<nav className="sidebar-nav">
|
<nav className="sidebar-nav">
|
||||||
|
<NavLink to="/" className={({ isActive }) => `nav-item nav-home-link`} end>
|
||||||
|
<span className="nav-item-icon">
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
|
||||||
|
</span>
|
||||||
|
{!collapsed && <span className="nav-item-label">返回首页</span>}
|
||||||
|
</NavLink>
|
||||||
<div className="nav-section">
|
<div className="nav-section">
|
||||||
{navItems.map(item => (
|
{navItems.map(item => (
|
||||||
<NavLink
|
<NavLink
|
||||||
key={item.path}
|
key={item.path}
|
||||||
to={item.path}
|
to={item.path}
|
||||||
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
||||||
|
title={collapsed ? item.label : undefined}
|
||||||
>
|
>
|
||||||
<span className="nav-icon">{iconPaths[item.icon]}</span>
|
<span className="nav-icon">{iconPaths[item.icon]}</span>
|
||||||
{!collapsed && <span className="nav-label">{item.label}</span>}
|
{!collapsed && <span className="nav-label">{item.label}</span>}
|
||||||
|
{!collapsed && <span className="nav-active-dot" />}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -81,14 +98,17 @@ const FrontLayout: React.FC = () => {
|
|||||||
key={item.path}
|
key={item.path}
|
||||||
to={item.path}
|
to={item.path}
|
||||||
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
||||||
|
title={collapsed ? item.label : undefined}
|
||||||
>
|
>
|
||||||
<span className="nav-icon">{iconPaths[item.icon]}</span>
|
<span className="nav-icon">{iconPaths[item.icon]}</span>
|
||||||
{!collapsed && <span className="nav-label">{item.label}</span>}
|
{!collapsed && <span className="nav-label">{item.label}</span>}
|
||||||
|
{!collapsed && <span className="nav-active-dot" />}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
<div className="sidebar-footer">
|
<div className="sidebar-footer">
|
||||||
<div className="user-info-mini">
|
<div className="user-info-mini">
|
||||||
<div className="user-avatar-sm">
|
<div className="user-avatar-sm">
|
||||||
@@ -105,17 +125,14 @@ const FrontLayout: React.FC = () => {
|
|||||||
<NavLink
|
<NavLink
|
||||||
to="/admin"
|
to="/admin"
|
||||||
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`}
|
||||||
title="返回后台"
|
title="管理后台"
|
||||||
>
|
>
|
||||||
<span className="nav-icon">
|
<span className="nav-icon">
|
||||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
|
||||||
<rect x="3" y="3" width="7" height="7" rx="1.2"/>
|
<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
|
||||||
<rect x="14" y="3" width="7" height="7" rx="1.2"/>
|
|
||||||
<rect x="3" y="14" width="7" height="7" rx="1.2"/>
|
|
||||||
<rect x="14" y="14" width="7" height="7" rx="1.2"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
</span>
|
</span>
|
||||||
{!collapsed && <span className="nav-label">返回后台</span>}
|
{!collapsed && <span className="nav-label">管理后台</span>}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ const SiteSettings: React.FC = () => {
|
|||||||
<FormGroup label="网站名称" required>
|
<FormGroup label="网站名称" required>
|
||||||
<input className="admin-form-input" value={brand.siteName}
|
<input className="admin-form-input" value={brand.siteName}
|
||||||
onChange={e => setBrand({ ...brand, siteName: e.target.value })}
|
onChange={e => setBrand({ ...brand, siteName: e.target.value })}
|
||||||
placeholder="例如: Qihu-AIFlow" />
|
placeholder="例如: 七虎AI" />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
<FormGroup label="LOGO URL">
|
<FormGroup label="LOGO URL">
|
||||||
<input className="admin-form-input" value={brand.logo}
|
<input className="admin-form-input" value={brand.logo}
|
||||||
@@ -638,7 +638,7 @@ const SiteSettings: React.FC = () => {
|
|||||||
value={registration.welcome_message}
|
value={registration.welcome_message}
|
||||||
onChange={e => setRegistration({ ...registration, welcome_message: e.target.value })}
|
onChange={e => setRegistration({ ...registration, welcome_message: e.target.value })}
|
||||||
style={{ minHeight: 80 }}
|
style={{ minHeight: 80 }}
|
||||||
placeholder="欢迎加入 Qihu-AIFlow!从这里开始你的 AI 创造之旅..." />
|
placeholder="欢迎加入七虎AI!从这里开始你的 AI 创造之旅..." />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
||||||
<FormActions>
|
<FormActions>
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ const TimelinePanel: React.FC<{
|
|||||||
pdf.text('我的AI进化时间线', 10, 15);
|
pdf.text('我的AI进化时间线', 10, 15);
|
||||||
pdf.setFontSize(10);
|
pdf.setFontSize(10);
|
||||||
pdf.text(`生成日期: ${dateStr}`, 10, 22);
|
pdf.text(`生成日期: ${dateStr}`, 10, 22);
|
||||||
pdf.text('Qihu-AIFlow', pageWidth - 10, 22, { align: 'right' });
|
pdf.text('七虎AI', pageWidth - 10, 22, { align: 'right' });
|
||||||
|
|
||||||
// 单页添加图片,自动缩放适应
|
// 单页添加图片,自动缩放适应
|
||||||
const maxHeight = pageHeight - 35;
|
const maxHeight = pageHeight - 35;
|
||||||
@@ -417,7 +417,7 @@ const TimelinePanel: React.FC<{
|
|||||||
// 底部水印
|
// 底部水印
|
||||||
pdf.setFontSize(8);
|
pdf.setFontSize(8);
|
||||||
pdf.setTextColor(200, 200, 200);
|
pdf.setTextColor(200, 200, 200);
|
||||||
pdf.text('Qihu-AIFlow', pageWidth / 2, pageHeight - 5, { align: 'center' });
|
pdf.text('七虎AI', pageWidth / 2, pageHeight - 5, { align: 'center' });
|
||||||
|
|
||||||
pdf.save(`${filename}.pdf`);
|
pdf.save(`${filename}.pdf`);
|
||||||
setExportMsg(`时间线已导出为 PDF: ${filename}.pdf`);
|
setExportMsg(`时间线已导出为 PDF: ${filename}.pdf`);
|
||||||
@@ -746,7 +746,7 @@ const ProfilePanel: React.FC<{ profile: EvolutionProfile; skills: EvolutionSkill
|
|||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="evo-share-card-footer">
|
<div className="evo-share-card-footer">
|
||||||
<span style={{ opacity: 0.5, fontSize: '11px' }}>{new Date().toLocaleDateString()}</span>
|
<span style={{ opacity: 0.5, fontSize: '11px' }}>{new Date().toLocaleDateString()}</span>
|
||||||
<span style={{ opacity: 0.5, fontSize: '11px' }}>Qihu-AIFlow</span>
|
<span style={{ opacity: 0.5, fontSize: '11px' }}>七虎AI</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,27 +10,27 @@
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* === Dark Theme Variables (scoped to landing page) === */
|
/* === Light Theme Variables (scoped to landing page) === */
|
||||||
.landing-page-v2 {
|
.landing-page-v2 {
|
||||||
--lp-bg: #0A0E1A;
|
--lp-bg: #FFFFFF;
|
||||||
--lp-bg-secondary: #111627;
|
--lp-bg-secondary: #F5F7FC;
|
||||||
--lp-bg-card: #161B2E;
|
--lp-bg-card: #FFFFFF;
|
||||||
--lp-bg-card-hover: #1C2240;
|
--lp-bg-card-hover: #F5F7FC;
|
||||||
--lp-bg-glass: rgba(22, 27, 46, 0.7);
|
--lp-bg-glass: rgba(255, 255, 255, 0.8);
|
||||||
--lp-border: rgba(255, 255, 255, 0.06);
|
--lp-border: rgba(0, 0, 0, 0.08);
|
||||||
--lp-border-light: rgba(255, 255, 255, 0.04);
|
--lp-border-light: rgba(0, 0, 0, 0.05);
|
||||||
--lp-text: #E8ECF4;
|
--lp-text: #1A1F36;
|
||||||
--lp-text-secondary: #8892B0;
|
--lp-text-secondary: #5A6480;
|
||||||
--lp-text-tertiary: #5A6480;
|
--lp-text-tertiary: #8892B0;
|
||||||
--lp-accent: #6C63FF;
|
--lp-accent: #6C63FF;
|
||||||
--lp-accent-light: #8B85FF;
|
--lp-accent-light: #8B85FF;
|
||||||
--lp-accent-glow: rgba(108, 99, 255, 0.3);
|
--lp-accent-glow: rgba(108, 99, 255, 0.3);
|
||||||
--lp-gradient-1: linear-gradient(135deg, #6C63FF 0%, #A78BFA 50%, #C084FC 100%);
|
--lp-gradient-1: linear-gradient(135deg, #6C63FF 0%, #A78BFA 50%, #C084FC 100%);
|
||||||
--lp-gradient-2: linear-gradient(135deg, #06B6D4 0%, #3B82F6 100%);
|
--lp-gradient-2: linear-gradient(135deg, #06B6D4 0%, #3B82F6 100%);
|
||||||
--lp-gradient-3: linear-gradient(135deg, #10B981 0%, #34D399 100%);
|
--lp-gradient-3: linear-gradient(135deg, #10B981 0%, #34D399 100%);
|
||||||
--lp-gradient-hero: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(108, 99, 255, 0.15), transparent 70%);
|
--lp-gradient-hero: radial-gradient(ellipse 80% 50% at 50% -20%, rgba(108, 99, 255, 0.08), transparent 70%);
|
||||||
--lp-shadow-card: 0 1px 3px rgba(0,0,0,0.3), 0 4px 12px rgba(0,0,0,0.2);
|
--lp-shadow-card: 0 1px 3px rgba(0,0,0,0.06), 0 4px 12px rgba(0,0,0,0.04);
|
||||||
--lp-shadow-lg: 0 8px 32px rgba(0,0,0,0.4);
|
--lp-shadow-lg: 0 8px 32px rgba(0,0,0,0.10);
|
||||||
--lp-radius: 12px;
|
--lp-radius: 12px;
|
||||||
--lp-radius-sm: 8px;
|
--lp-radius-sm: 8px;
|
||||||
--lp-radius-lg: 16px;
|
--lp-radius-lg: 16px;
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
top: 24px;
|
top: 24px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
background: rgba(22, 27, 46, 0.95);
|
background: rgba(255, 255, 255, 0.95);
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
border: 1px solid rgba(108, 99, 255, 0.3);
|
border: 1px solid rgba(108, 99, 255, 0.3);
|
||||||
color: var(--lp-text);
|
color: var(--lp-text);
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-header-v2.scrolled {
|
.landing-header-v2.scrolled {
|
||||||
background: rgba(10, 14, 26, 0.85);
|
background: rgba(255, 255, 255, 0.85);
|
||||||
backdrop-filter: blur(20px);
|
backdrop-filter: blur(20px);
|
||||||
border-bottom: 1px solid var(--lp-border);
|
border-bottom: 1px solid var(--lp-border);
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--lp-text-secondary);
|
color: var(--lp-text-secondary);
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(108, 99, 255, 0.04);
|
||||||
border: 1px solid var(--lp-border);
|
border: 1px solid var(--lp-border);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
@@ -319,8 +319,8 @@
|
|||||||
|
|
||||||
.btn-hero-secondary:hover {
|
.btn-hero-secondary:hover {
|
||||||
color: var(--lp-text);
|
color: var(--lp-text);
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(108, 99, 255, 0.10);
|
||||||
border-color: rgba(255, 255, 255, 0.12);
|
border-color: rgba(0, 0, 0, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-stats-v2 {
|
.hero-stats-v2 {
|
||||||
@@ -441,7 +441,7 @@
|
|||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: rgba(255, 255, 255, 0.2);
|
background: rgba(108, 99, 255, 0.20);
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
@@ -622,8 +622,8 @@
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--lp-text-secondary);
|
color: var(--lp-text-secondary);
|
||||||
background: rgba(255, 255, 255, 0.04);
|
background: rgba(108, 99, 255, 0.04);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@@ -763,7 +763,7 @@
|
|||||||
|
|
||||||
.filter-chip:hover {
|
.filter-chip:hover {
|
||||||
color: var(--lp-text);
|
color: var(--lp-text);
|
||||||
border-color: rgba(255, 255, 255, 0.12);
|
border-color: rgba(0, 0, 0, 0.10);
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-chip.active {
|
.filter-chip.active {
|
||||||
|
|||||||
@@ -157,14 +157,14 @@ const LandingPage: React.FC = () => {
|
|||||||
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
||||||
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span className="landing-brand-text">Qihu-AIFlow</span>
|
<span className="landing-brand-text">七虎AI</span>
|
||||||
</div>
|
</div>
|
||||||
<nav className="landing-nav-v2">
|
<nav className="landing-nav-v2" style={{ cursor: 'pointer' }}>
|
||||||
<a href="#what-is">平台介绍</a>
|
<a onClick={() => document.getElementById('what-is')?.scrollIntoView({ behavior: 'smooth' })}>平台介绍</a>
|
||||||
<a href="#architecture">平台架构</a>
|
<a onClick={() => document.getElementById('architecture')?.scrollIntoView({ behavior: 'smooth' })}>平台架构</a>
|
||||||
<a href="#capabilities">能力体系</a>
|
<a onClick={() => document.getElementById('capabilities')?.scrollIntoView({ behavior: 'smooth' })}>能力体系</a>
|
||||||
<a href="#scenarios">应用场景</a>
|
<a onClick={() => document.getElementById('scenarios')?.scrollIntoView({ behavior: 'smooth' })}>应用场景</a>
|
||||||
<a href="#market">技能生态</a>
|
<a onClick={() => document.getElementById('market')?.scrollIntoView({ behavior: 'smooth' })}>技能生态</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div className="landing-actions-v2">
|
<div className="landing-actions-v2">
|
||||||
<button className="btn-ghost-v2" onClick={() => navigate('/login')}>登录</button>
|
<button className="btn-ghost-v2" onClick={() => navigate('/login')}>登录</button>
|
||||||
@@ -173,7 +173,7 @@ const LandingPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Hero Section — What is Qihu-AIFlow */}
|
{/* Hero Section — What is 七虎AI */}
|
||||||
<section className="hero-section-v2">
|
<section className="hero-section-v2">
|
||||||
<div className="hero-bg-orb orb-1" />
|
<div className="hero-bg-orb orb-1" />
|
||||||
<div className="hero-bg-orb orb-2" />
|
<div className="hero-bg-orb orb-2" />
|
||||||
@@ -188,7 +188,7 @@ const LandingPage: React.FC = () => {
|
|||||||
<span className="hero-gradient-text"> 的超级工作台</span>
|
<span className="hero-gradient-text"> 的超级工作台</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="hero-subtitle-v2">
|
<p className="hero-subtitle-v2">
|
||||||
Qihu-AIFlow 是一站式 AI 能力集成平台,让你在一个地方完成对话、知识库、技能编排、模型切换、自动化搭建<br/>
|
七虎AI 是一站式 AI 能力集成平台,让你在一个地方完成对话、知识库、技能编排、模型切换、自动化搭建<br/>
|
||||||
无需拼接多个工具,从想法到落地,一个平台就够了
|
无需拼接多个工具,从想法到落地,一个平台就够了
|
||||||
</p>
|
</p>
|
||||||
<div className="hero-cta-v2">
|
<div className="hero-cta-v2">
|
||||||
@@ -226,11 +226,11 @@ const LandingPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* What is Qihu-AIFlow — Platform Introduction */}
|
{/* What is 七虎AI — Platform Introduction */}
|
||||||
<section id="what-is" className="whatis-section-v2">
|
<section id="what-is" className="whatis-section-v2">
|
||||||
<div className="section-header-v2">
|
<div className="section-header-v2">
|
||||||
<span className="section-badge-v2">平台介绍</span>
|
<span className="section-badge-v2">平台介绍</span>
|
||||||
<h2>Qihu-AIFlow 是什么?</h2>
|
<h2>七虎AI 是什么?</h2>
|
||||||
<p>一个面向 AI 爱好者和从业者的个人 AI 能力集成平台</p>
|
<p>一个面向 AI 爱好者和从业者的个人 AI 能力集成平台</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="whatis-cards-v2">
|
<div className="whatis-cards-v2">
|
||||||
@@ -262,7 +262,7 @@ const LandingPage: React.FC = () => {
|
|||||||
<div className="section-header-v2">
|
<div className="section-header-v2">
|
||||||
<span className="section-badge-v2">平台架构</span>
|
<span className="section-badge-v2">平台架构</span>
|
||||||
<h2>四层架构 · 层层赋能</h2>
|
<h2>四层架构 · 层层赋能</h2>
|
||||||
<p>从基础设施到上层应用,理解 Qihu-AIFlow 的技术全貌</p>
|
<p>从基础设施到上层应用,理解 七虎AI 的技术全貌</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="arch-layers-v2">
|
<div className="arch-layers-v2">
|
||||||
{archLayers.map((layer, idx) => (
|
{archLayers.map((layer, idx) => (
|
||||||
@@ -417,14 +417,14 @@ const LandingPage: React.FC = () => {
|
|||||||
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
||||||
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span>Qihu-AIFlow</span>
|
<span>七虎AI</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="footer-links-v2">
|
<div className="footer-links-v2">
|
||||||
<div className="footer-col-v2">
|
<div className="footer-col-v2">
|
||||||
<h4>平台</h4>
|
<h4>平台</h4>
|
||||||
<a href="#what-is">平台介绍</a>
|
<a onClick={() => document.getElementById('what-is')?.scrollIntoView({ behavior: 'smooth' })}>平台介绍</a>
|
||||||
<a href="#architecture">平台架构</a>
|
<a onClick={() => document.getElementById('architecture')?.scrollIntoView({ behavior: 'smooth' })}>平台架构</a>
|
||||||
<a href="#capabilities">能力体系</a>
|
<a onClick={() => document.getElementById('capabilities')?.scrollIntoView({ behavior: 'smooth' })}>能力体系</a>
|
||||||
</div>
|
</div>
|
||||||
<div className="footer-col-v2">
|
<div className="footer-col-v2">
|
||||||
<h4>资源</h4>
|
<h4>资源</h4>
|
||||||
@@ -441,7 +441,7 @@ const LandingPage: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="footer-bottom-v2">
|
<div className="footer-bottom-v2">
|
||||||
<p>© 2026 Qihu-AIFlow. All rights reserved.</p>
|
<p>© 2026 七虎AI. All rights reserved.</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
/* ===== Login Page ===== */
|
/* ===== Login Page V3 - Dark Theme ===== */
|
||||||
.login-page {
|
.login-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: var(--color-bg-primary);
|
background: #F5F7FC;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Background decorations */
|
||||||
.login-bg-decor {
|
.login-bg-decor {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
@@ -19,35 +20,37 @@
|
|||||||
.bg-circle {
|
.bg-circle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
opacity: 0.08;
|
filter: blur(80px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-circle.c1 {
|
.bg-circle.c1 {
|
||||||
width: 600px; height: 600px;
|
width: 600px; height: 600px;
|
||||||
background: var(--color-accent);
|
background: #6C63FF;
|
||||||
top: -200px; right: -100px;
|
top: -200px; right: -100px;
|
||||||
|
opacity: 0.12;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-circle.c2 {
|
.bg-circle.c2 {
|
||||||
width: 400px; height: 400px;
|
width: 400px; height: 400px;
|
||||||
background: #8B8DFF;
|
background: #06B6D4;
|
||||||
bottom: -100px; left: -50px;
|
bottom: -100px; left: -50px;
|
||||||
|
opacity: 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-circle.c3 {
|
.bg-circle.c3 {
|
||||||
width: 300px; height: 300px;
|
width: 300px; height: 300px;
|
||||||
background: var(--color-accent);
|
background: #A78BFA;
|
||||||
top: 50%; left: 50%;
|
top: 50%; left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
opacity: 0.04;
|
opacity: 0.06;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-grid {
|
.bg-grid {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
background-image:
|
background-image:
|
||||||
linear-gradient(rgba(0,0,0,0.02) 1px, transparent 1px),
|
linear-gradient(rgba(108, 99, 255, 0.03) 1px, transparent 1px),
|
||||||
linear-gradient(90deg, rgba(0,0,0,0.02) 1px, transparent 1px);
|
linear-gradient(90deg, rgba(108, 99, 255, 0.03) 1px, transparent 1px);
|
||||||
background-size: 60px 60px;
|
background-size: 60px 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,203 +59,212 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
min-height: 560px;
|
min-height: 560px;
|
||||||
background: #FFFFFF;
|
background: rgba(17, 22, 39, 0.95);
|
||||||
border-radius: var(--radius-2xl);
|
backdrop-filter: blur(24px);
|
||||||
box-shadow: var(--shadow-xl);
|
border: 1px solid rgba(0, 0, 0, 0.08);
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: var(--z-base);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
animation: loginSlideUp 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Brand Panel */
|
@keyframes loginSlideUp {
|
||||||
|
from { opacity: 0; transform: translateY(24px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left brand panel */
|
||||||
.login-brand-panel {
|
.login-brand-panel {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
background: linear-gradient(135deg, #2D2B55 0%, #1A1A2E 50%, #2D2B55 100%);
|
background: linear-gradient(135deg, rgba(108, 99, 255, 0.08) 0%, rgba(167, 139, 250, 0.05) 100%);
|
||||||
|
padding: 48px 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
border-right: 1px solid rgba(255, 255, 255, 0.04);
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-brand-panel::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
width: 300px; height: 300px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: radial-gradient(circle, rgba(91,95,237,0.3) 0%, transparent 70%);
|
|
||||||
top: -50px; right: -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-brand-panel::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
width: 200px; height: 200px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: radial-gradient(circle, rgba(139,141,255,0.2) 0%, transparent 70%);
|
|
||||||
bottom: -30px; left: -30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-content {
|
.brand-content {
|
||||||
text-align: center;
|
width: 100%;
|
||||||
color: white;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-icon {
|
.brand-icon {
|
||||||
margin-bottom: var(--space-xl);
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-title {
|
.brand-title {
|
||||||
font-size: 36px;
|
font-size: 32px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
letter-spacing: -0.03em;
|
color: #1A1F36;
|
||||||
margin-bottom: var(--space-sm);
|
margin-bottom: 8px;
|
||||||
|
letter-spacing: -0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-desc {
|
.brand-desc {
|
||||||
font-size: var(--text-base);
|
font-size: 15px;
|
||||||
color: rgba(255,255,255,0.6);
|
color: #5A6480;
|
||||||
margin-bottom: var(--space-3xl);
|
margin-bottom: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-features {
|
.brand-features {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-md);
|
gap: 14px;
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-feature {
|
.brand-feature {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-md);
|
gap: 10px;
|
||||||
font-size: var(--text-sm);
|
font-size: 14px;
|
||||||
color: rgba(255,255,255,0.75);
|
color: #5A6480;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bf-icon {
|
.bf-icon {
|
||||||
color: #6C63FF;
|
width: 20px;
|
||||||
font-weight: 700;
|
height: 20px;
|
||||||
font-size: var(--text-base);
|
border-radius: 50%;
|
||||||
}
|
background: rgba(16, 185, 129, 0.15);
|
||||||
|
color: #10B981;
|
||||||
/* Form Panel */
|
|
||||||
.login-form-panel {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: var(--space-4xl);
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right form panel */
|
||||||
|
.login-form-panel {
|
||||||
|
flex: 1;
|
||||||
|
padding: 48px 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-form-inner {
|
.login-form-inner {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 340px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
.login-tabs {
|
.login-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-2xl);
|
background: rgba(255, 255, 255, 0.04);
|
||||||
margin-bottom: var(--space-3xl);
|
border-radius: 10px;
|
||||||
|
padding: 4px;
|
||||||
|
margin-bottom: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-tab {
|
.login-tab {
|
||||||
font-size: var(--text-lg);
|
flex: 1;
|
||||||
font-weight: 700;
|
padding: 10px;
|
||||||
color: var(--color-text-tertiary);
|
border-radius: 8px;
|
||||||
padding-bottom: var(--space-sm);
|
font-size: 14px;
|
||||||
border-bottom: 2px solid transparent;
|
font-weight: 600;
|
||||||
transition: all var(--transition-fast);
|
color: #5A6480;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-tab.active {
|
.login-tab.active {
|
||||||
color: var(--color-text-primary);
|
background: rgba(108, 99, 255, 0.15);
|
||||||
border-bottom-color: var(--color-accent);
|
color: #8B85FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-tab:hover {
|
.login-tab:hover:not(.active) {
|
||||||
color: var(--color-text-primary);
|
color: #5A6480;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Error message */
|
||||||
|
.form-error {
|
||||||
|
padding: 10px 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(239, 68, 68, 0.1);
|
||||||
|
border: 1px solid rgba(239, 68, 68, 0.2);
|
||||||
|
color: #F87171;
|
||||||
|
font-size: 13px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form */
|
||||||
.login-form {
|
.login-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-xl);
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-group {
|
.form-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-sm);
|
gap: 6px;
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-label {
|
.form-label {
|
||||||
font-size: var(--text-sm);
|
font-size: 13px;
|
||||||
font-weight: 600;
|
font-weight: 500;
|
||||||
color: var(--color-text-primary);
|
color: #5A6480;
|
||||||
margin-bottom: 6px;
|
}
|
||||||
|
|
||||||
|
.required {
|
||||||
|
color: #EF4444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input {
|
.form-input {
|
||||||
width: 100%;
|
padding: 12px 14px;
|
||||||
padding: 12px 16px;
|
border-radius: 10px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
border-radius: var(--radius-lg);
|
background: rgba(255, 255, 255, 0.03);
|
||||||
font-size: var(--text-base);
|
color: #1A1F36;
|
||||||
color: var(--color-text-primary);
|
font-size: 14px;
|
||||||
background: var(--color-bg-primary);
|
|
||||||
transition: all var(--transition-fast);
|
|
||||||
outline: none;
|
outline: none;
|
||||||
|
transition: all 0.2s;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input:focus {
|
.form-input:focus {
|
||||||
border-color: var(--color-accent);
|
border-color: rgba(108, 99, 255, 0.4);
|
||||||
box-shadow: 0 0 0 3px var(--color-accent-light);
|
background: rgba(108, 99, 255, 0.05);
|
||||||
background: #FFFFFF;
|
box-shadow: 0 0 0 3px rgba(108, 99, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input::placeholder {
|
.form-input::placeholder {
|
||||||
color: var(--color-text-disabled);
|
color: #3A4460;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Submit button */
|
||||||
.login-submit-btn {
|
.login-submit-btn {
|
||||||
height: 46px;
|
width: 100%;
|
||||||
background: linear-gradient(135deg, #5B5FED, #6C63FF);
|
padding: 13px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: none;
|
||||||
|
background: linear-gradient(135deg, #6C63FF, #A78BFA);
|
||||||
color: white;
|
color: white;
|
||||||
border-radius: var(--radius-lg);
|
font-size: 15px;
|
||||||
font-size: var(--text-base);
|
font-weight: 600;
|
||||||
font-weight: 700;
|
cursor: pointer;
|
||||||
letter-spacing: 0.15em;
|
transition: all 0.3s;
|
||||||
transition: all var(--transition-fast);
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-submit-btn:hover {
|
.login-submit-btn:hover:not(:disabled) {
|
||||||
background: linear-gradient(135deg, #4A4ECC, #5B5FED);
|
box-shadow: 0 4px 20px rgba(108, 99, 255, 0.4);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
box-shadow: var(--shadow-md);
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-submit-btn:active {
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-submit-btn:disabled {
|
.login-submit-btn:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.6;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-submit-btn:disabled:hover {
|
/* Register method tabs */
|
||||||
transform: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register Method Tabs */
|
|
||||||
.register-method-tabs {
|
.register-method-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-sm);
|
gap: 12px;
|
||||||
margin-bottom: var(--space-lg);
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-method-tab {
|
.register-method-tab {
|
||||||
@@ -261,32 +273,32 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: var(--space-sm) var(--space-md);
|
padding: 8px;
|
||||||
border-radius: var(--radius-md);
|
border-radius: 8px;
|
||||||
border: 1px solid var(--color-border);
|
border: 1px solid rgba(0, 0, 0, 0.10);
|
||||||
background: var(--color-bg-primary);
|
background: transparent;
|
||||||
font-size: var(--text-sm);
|
color: #5A6480;
|
||||||
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--color-text-secondary);
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all var(--transition-fast);
|
transition: all 0.2s;
|
||||||
}
|
|
||||||
|
|
||||||
.register-method-tab:hover {
|
|
||||||
border-color: var(--color-accent-light);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-method-tab.active {
|
.register-method-tab.active {
|
||||||
border-color: var(--color-accent);
|
border-color: rgba(108, 99, 255, 0.3);
|
||||||
background: var(--color-accent-subtle);
|
background: rgba(108, 99, 255, 0.1);
|
||||||
color: var(--color-accent);
|
color: #8B85FF;
|
||||||
font-weight: 600;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SMS Row */
|
.register-method-tab:hover:not(.active) {
|
||||||
|
border-color: rgba(255, 255, 255, 0.12);
|
||||||
|
color: #5A6480;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SMS row */
|
||||||
.sms-row {
|
.sms-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--space-sm);
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sms-input {
|
.sms-input {
|
||||||
@@ -294,49 +306,42 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sms-btn {
|
.sms-btn {
|
||||||
padding: var(--space-sm) var(--space-lg);
|
padding: 10px 16px;
|
||||||
border-radius: var(--radius-md);
|
border-radius: 10px;
|
||||||
border: 1px solid var(--color-accent);
|
border: 1px solid rgba(108, 99, 255, 0.2);
|
||||||
background: transparent;
|
background: rgba(108, 99, 255, 0.08);
|
||||||
color: var(--color-accent);
|
color: #8B85FF;
|
||||||
font-size: var(--text-sm);
|
font-size: 13px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
transition: all var(--transition-fast);
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sms-btn:hover:not(:disabled) {
|
.sms-btn:hover:not(:disabled) {
|
||||||
background: var(--color-accent);
|
background: rgba(108, 99, 255, 0.15);
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sms-btn:disabled {
|
.sms-btn:disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
border-color: var(--color-border);
|
|
||||||
color: var(--color-text-tertiary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Required Marker */
|
|
||||||
.required {
|
|
||||||
color: var(--color-error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.login-container {
|
.login-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 90vw;
|
width: calc(100vw - 32px);
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
|
margin: 16px;
|
||||||
}
|
}
|
||||||
.login-brand-panel {
|
.login-brand-panel {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: var(--space-3xl) var(--space-2xl);
|
padding: 32px 24px;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
||||||
}
|
}
|
||||||
.login-form-panel {
|
.login-form-panel {
|
||||||
padding: var(--space-2xl);
|
padding: 32px 24px;
|
||||||
}
|
|
||||||
.brand-features {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,38 +65,22 @@ const LoginPage: React.FC = () => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await authAPI.login(loginAccount, loginPassword);
|
const res = await authAPI.login(loginAccount, loginPassword);
|
||||||
const { access_token, user: userData } = res.data;
|
const data: any = (res as any).data || res;
|
||||||
localStorage.setItem('aiflow_token', access_token);
|
const token = data.access_token || data.token;
|
||||||
|
const userData = data.user || data;
|
||||||
|
localStorage.setItem('aiflow_token', token);
|
||||||
const userObj: User = {
|
const userObj: User = {
|
||||||
id: userData.id,
|
id: userData.id, username: userData.username,
|
||||||
username: userData.username,
|
email: userData.email || '', phone: userData.phone || '',
|
||||||
email: userData.email || '',
|
avatar: userData.avatar || '', role: userData.role || 'user',
|
||||||
phone: userData.phone || '',
|
status: 'active', realNameStatus: 'unverified',
|
||||||
avatar: userData.avatar || '',
|
createdAt: new Date().toISOString(),
|
||||||
role: userData.role,
|
|
||||||
status: userData.status,
|
|
||||||
realNameStatus: userData.real_name_status || 'unverified',
|
|
||||||
createdAt: userData.created_at || new Date().toISOString(),
|
|
||||||
membership: userData.membership_level > 0 ? {
|
|
||||||
planId: userData.membership_level >= 3 ? 'mp3' : (userData.membership_level >= 2 ? 'mp2' : 'mp1'),
|
|
||||||
planName: userData.role === 'admin' ? '管理员' : (userData.membership_level >= 3 ? '企业版' : (userData.membership_level >= 2 ? '专业版' : '免费版')),
|
|
||||||
level: userData.membership_level,
|
|
||||||
expireAt: userData.membership_expire_at || '',
|
|
||||||
autoRenew: userData.auto_renew || false,
|
|
||||||
} : undefined,
|
|
||||||
};
|
};
|
||||||
login(userObj);
|
login(userObj);
|
||||||
navigate(userData.role === 'admin' ? '/admin' : '/chat');
|
navigate(userObj.role === 'admin' ? '/admin' : '/chat');
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
// 处理后端返回的精确错误信息,区分用户不存在和密码错误
|
const msg = (e as any).detail || (e as any).message || '';
|
||||||
const status = e.status || e.response?.status || 0;
|
if (msg.includes('Network') || msg.includes('fetch')) {
|
||||||
const msg = e.detail || e.message || '';
|
|
||||||
if (status === 403) {
|
|
||||||
setErrorMsg('账号已被禁用,请联系管理员');
|
|
||||||
} else if (status === 401) {
|
|
||||||
// 后端的detail精确指明了原因:"用户名不存在" 或 "密码错误"
|
|
||||||
setErrorMsg(msg || '用户名或密码错误');
|
|
||||||
} else if (status === 0 || msg.includes('NetworkError') || msg.includes('Failed to fetch')) {
|
|
||||||
setErrorMsg('网络连接失败,请检查网络');
|
setErrorMsg('网络连接失败,请检查网络');
|
||||||
} else {
|
} else {
|
||||||
setErrorMsg(msg || '登录失败,请稍后重试');
|
setErrorMsg(msg || '登录失败,请稍后重试');
|
||||||
@@ -121,14 +105,10 @@ const LoginPage: React.FC = () => {
|
|||||||
const { access_token, user: userData } = res.data;
|
const { access_token, user: userData } = res.data;
|
||||||
localStorage.setItem('aiflow_token', access_token);
|
localStorage.setItem('aiflow_token', access_token);
|
||||||
const userObj: User = {
|
const userObj: User = {
|
||||||
id: userData.id,
|
id: userData.id, username: userData.username,
|
||||||
username: userData.username,
|
email: userData.email || '', phone: userData.phone || '',
|
||||||
email: userData.email || '',
|
avatar: userData.avatar || '', role: 'user',
|
||||||
phone: userData.phone || '',
|
status: 'active', realNameStatus: 'unverified',
|
||||||
avatar: userData.avatar || '',
|
|
||||||
role: 'user',
|
|
||||||
status: 'active',
|
|
||||||
realNameStatus: 'unverified',
|
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
};
|
};
|
||||||
login(userObj);
|
login(userObj);
|
||||||
@@ -158,12 +138,18 @@ const LoginPage: React.FC = () => {
|
|||||||
<div className="brand-content">
|
<div className="brand-content">
|
||||||
<div className="brand-icon">
|
<div className="brand-icon">
|
||||||
<svg width="48" height="48" viewBox="0 0 32 32" fill="none">
|
<svg width="48" height="48" viewBox="0 0 32 32" fill="none">
|
||||||
<rect width="32" height="32" rx="8" fill="white"/>
|
<defs>
|
||||||
<path d="M8 20V12l4 4 4-4v8" stroke="#5B5FED" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
<linearGradient id="lpBrandGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
<path d="M6 22h20" stroke="#5B5FED" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
<stop offset="0%" stopColor="#6C63FF"/>
|
||||||
|
<stop offset="100%" stopColor="#A78BFA"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect width="32" height="32" rx="8" fill="url(#lpBrandGrad)"/>
|
||||||
|
<path d="M8 20V12l4 4 4-4v8" stroke="white" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round" fill="none"/>
|
||||||
|
<path d="M6 22h20" stroke="white" strokeWidth="1.5" strokeLinecap="round" opacity="0.5"/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<h1 className="brand-title">AIFlow</h1>
|
<h1 className="brand-title">七虎AI</h1>
|
||||||
<p className="brand-desc">智能自动化PaaS平台</p>
|
<p className="brand-desc">智能自动化PaaS平台</p>
|
||||||
<div className="brand-features">
|
<div className="brand-features">
|
||||||
<div className="brand-feature"><span className="bf-icon">✓</span><span>一站式AI自动化SOP</span></div>
|
<div className="brand-feature"><span className="bf-icon">✓</span><span>一站式AI自动化SOP</span></div>
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
/* ===== AIFlow Design System v2 - Dark Theme Default ===== */
|
/* ===== 七虎AI Design System v2 - Light Theme ===== */
|
||||||
/* 设计方向:融合暗黑科技感 + 极简主义 */
|
/* 设计方向:明亮简洁 + 透明玻璃态 */
|
||||||
|
|
||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap');
|
||||||
|
|
||||||
/* CSS Custom Properties - Dark Theme */
|
/* CSS Custom Properties - Light Theme */
|
||||||
:root {
|
:root {
|
||||||
/* Colors - Dark Theme */
|
/* Colors - Dark Theme */
|
||||||
--color-bg-primary: #0A0E1A;
|
--color-bg-primary: #FFFFFF;
|
||||||
--color-bg-secondary: #111627;
|
--color-bg-secondary: #F5F7FC;
|
||||||
--color-bg-tertiary: #161B2E;
|
--color-bg-tertiary: #FFFFFF;
|
||||||
--color-bg-hover: #1C2240;
|
--color-bg-hover: #F0F2F8;
|
||||||
--color-bg-active: #22284A;
|
--color-bg-active: #E8EBF5;
|
||||||
|
|
||||||
--color-text-primary: #E8ECF4;
|
--color-text-primary: #1A1F36;
|
||||||
--color-text-secondary: #8892B0;
|
--color-text-secondary: #5A6480;
|
||||||
--color-text-tertiary: #5A6480;
|
--color-text-tertiary: #8892B0;
|
||||||
--color-text-disabled: #3A4460;
|
--color-text-disabled: #C4C9D9;
|
||||||
--color-text-inverse: #0A0E1A;
|
--color-text-inverse: #FFFFFF;
|
||||||
|
|
||||||
--color-accent: #6C63FF;
|
--color-accent: #6C63FF;
|
||||||
--color-accent-hover: #8B85FF;
|
--color-accent-hover: #8B85FF;
|
||||||
@@ -32,25 +32,25 @@
|
|||||||
--color-info: #3B82F6;
|
--color-info: #3B82F6;
|
||||||
--color-info-light: rgba(59, 130, 246, 0.12);
|
--color-info-light: rgba(59, 130, 246, 0.12);
|
||||||
|
|
||||||
--color-border: rgba(255, 255, 255, 0.08);
|
--color-border: rgba(0, 0, 0, 0.10);
|
||||||
--color-border-light: rgba(255, 255, 255, 0.05);
|
--color-border-light: rgba(0, 0, 0, 0.06);
|
||||||
--color-border-hover: rgba(255, 255, 255, 0.14);
|
--color-border-hover: rgba(0, 0, 0, 0.16);
|
||||||
|
|
||||||
--color-sidebar-bg: #0E1225;
|
--color-sidebar-bg: #FFFFFF;
|
||||||
--color-sidebar-hover: rgba(255, 255, 255, 0.05);
|
--color-sidebar-hover: rgba(108, 99, 255, 0.06);
|
||||||
--color-sidebar-active: rgba(108, 99, 255, 0.12);
|
--color-sidebar-active: rgba(108, 99, 255, 0.12);
|
||||||
|
|
||||||
/* Surface/card colors */
|
/* Surface/card colors */
|
||||||
--color-surface: #111627;
|
--color-surface: #FFFFFF;
|
||||||
--color-surface-hover: #161B2E;
|
--color-surface-hover: #F5F7FC;
|
||||||
--color-surface-elevated: #1C2240;
|
--color-surface-elevated: #FFFFFF;
|
||||||
|
|
||||||
/* Shadows - Dark theme */
|
/* Shadows - Dark theme */
|
||||||
--shadow-xs: 0 1px 2px rgba(0,0,0,0.2);
|
--shadow-xs: 0 1px 2px rgba(0,0,0,0.06);
|
||||||
--shadow-sm: 0 1px 3px rgba(0,0,0,0.25), 0 1px 2px rgba(0,0,0,0.15);
|
--shadow-sm: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.04);
|
||||||
--shadow-md: 0 4px 12px rgba(0,0,0,0.3), 0 1px 3px rgba(0,0,0,0.2);
|
--shadow-md: 0 4px 12px rgba(0,0,0,0.10), 0 1px 3px rgba(0,0,0,0.06);
|
||||||
--shadow-lg: 0 12px 32px rgba(0,0,0,0.35), 0 2px 6px rgba(0,0,0,0.2);
|
--shadow-lg: 0 12px 32px rgba(0,0,0,0.12), 0 2px 6px rgba(0,0,0,0.06);
|
||||||
--shadow-xl: 0 20px 48px rgba(0,0,0,0.4), 0 4px 12px rgba(0,0,0,0.25);
|
--shadow-xl: 0 20px 48px rgba(0,0,0,0.15), 0 4px 12px rgba(0,0,0,0.08);
|
||||||
|
|
||||||
/* Spacing */
|
/* Spacing */
|
||||||
--space-xs: 4px;
|
--space-xs: 4px;
|
||||||
@@ -553,7 +553,7 @@ input, textarea, select {
|
|||||||
.admin-card,
|
.admin-card,
|
||||||
.stat-card,
|
.stat-card,
|
||||||
.dashboard-card {
|
.dashboard-card {
|
||||||
background: rgba(22, 27, 46, 0.6) !important;
|
background: rgba(255, 255, 255, 0.7) !important;
|
||||||
backdrop-filter: blur(12px) !important;
|
backdrop-filter: blur(12px) !important;
|
||||||
-webkit-backdrop-filter: blur(12px) !important;
|
-webkit-backdrop-filter: blur(12px) !important;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.06) !important;
|
border: 1px solid rgba(255, 255, 255, 0.06) !important;
|
||||||
@@ -605,7 +605,7 @@ select,
|
|||||||
.form-input,
|
.form-input,
|
||||||
.form-control {
|
.form-control {
|
||||||
background: rgba(10, 14, 26, 0.6) !important;
|
background: rgba(10, 14, 26, 0.6) !important;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08) !important;
|
border: 1px solid rgba(0, 0, 0, 0.08) !important;
|
||||||
color: var(--color-text-primary) !important;
|
color: var(--color-text-primary) !important;
|
||||||
border-radius: var(--radius-md) !important;
|
border-radius: var(--radius-md) !important;
|
||||||
transition: border-color 0.2s, box-shadow 0.2s !important;
|
transition: border-color 0.2s, box-shadow 0.2s !important;
|
||||||
@@ -647,14 +647,14 @@ button[type="submit"] {
|
|||||||
/* Secondary/ghost button */
|
/* Secondary/ghost button */
|
||||||
.btn-secondary,
|
.btn-secondary,
|
||||||
.admin-btn-secondary {
|
.admin-btn-secondary {
|
||||||
background: rgba(255, 255, 255, 0.05) !important;
|
background: rgba(108, 99, 255, 0.06) !important;
|
||||||
color: var(--color-text-secondary) !important;
|
color: var(--color-text-secondary) !important;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.08) !important;
|
border: 1px solid rgba(0, 0, 0, 0.08) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary:hover,
|
.btn-secondary:hover,
|
||||||
.admin-btn-secondary:hover {
|
.admin-btn-secondary:hover {
|
||||||
background: rgba(255, 255, 255, 0.08) !important;
|
background: rgba(108, 99, 255, 0.10) !important;
|
||||||
color: var(--color-text-primary) !important;
|
color: var(--color-text-primary) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,7 +735,7 @@ a:hover {
|
|||||||
/* Modal/dialog overlay */
|
/* Modal/dialog overlay */
|
||||||
.modal-overlay,
|
.modal-overlay,
|
||||||
.dialog-overlay {
|
.dialog-overlay {
|
||||||
background: rgba(10, 14, 26, 0.7) !important;
|
background: rgba(255, 255, 255, 0.7) !important;
|
||||||
backdrop-filter: blur(4px) !important;
|
backdrop-filter: blur(4px) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,5 +743,5 @@ a:hover {
|
|||||||
.admin-card:hover,
|
.admin-card:hover,
|
||||||
.stat-card:hover {
|
.stat-card:hover {
|
||||||
border-color: rgba(108, 99, 255, 0.2) !important;
|
border-color: rgba(108, 99, 255, 0.2) !important;
|
||||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2) !important;
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08) !important;
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user