style(theme): Refactor global CSS with professional color scheme and design system
- Update root and dark mode color variables using HSL color system - Implement professional color palette with deep red and gradient backgrounds - Add custom shadow and gradient variables for enhanced visual design - Improve component classes with new color tokens and design tokens - Enhance readability and consistency of color and styling approach - Introduce more semantic and professional color definitions for light and dark modes
This commit is contained in:
parent
bfd00ae29d
commit
ecfc9c02cf
|
|
@ -5,93 +5,113 @@
|
|||
|
||||
/* Definition of the design system. All colors, gradients, fonts, etc should be defined here.
|
||||
All colors MUST be HSL.
|
||||
|
||||
专业深红色配色方案:
|
||||
- 主色调:深红色 (0 75% 25%) - 体现专业性和权威感
|
||||
- 强调色:暗红色 (0 60% 35%) - 用于交互元素和重点突出
|
||||
- 背景色:浅灰到黑色渐变 - 提供高对比度和现代感
|
||||
- 状态色:保持语义化的绿色(成功)、红色(错误)、黄色(警告)
|
||||
*/
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--background: 0 0% 98%;
|
||||
--foreground: 0 0% 5%;
|
||||
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--card-foreground: 0 0% 5%;
|
||||
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
--popover-foreground: 0 0% 5%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
--primary: 0 75% 25%;
|
||||
--primary-foreground: 0 0% 98%;
|
||||
|
||||
--secondary: 210 40% 96.1%;
|
||||
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||
--secondary: 0 0% 95%;
|
||||
--secondary-foreground: 0 75% 25%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
--muted: 0 0% 94%;
|
||||
--muted-foreground: 0 0% 40%;
|
||||
|
||||
--accent: 210 40% 96.1%;
|
||||
--accent-foreground: 222.2 47.4% 11.2%;
|
||||
--accent: 0 60% 35%;
|
||||
--accent-foreground: 0 0% 98%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--destructive: 0 84% 60%;
|
||||
--destructive-foreground: 0 0% 98%;
|
||||
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--border: 0 0% 90%;
|
||||
--input: 0 0% 90%;
|
||||
--ring: 0 75% 25%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
|
||||
--sidebar-background: 0 0% 98%;
|
||||
/* 专业渐变效果 */
|
||||
--gradient-primary: linear-gradient(135deg, hsl(0 75% 25%) 0%, hsl(0 60% 35%) 100%);
|
||||
--gradient-card: linear-gradient(145deg, hsl(0 0% 100%) 0%, hsl(0 0% 98%) 100%);
|
||||
--gradient-background: linear-gradient(180deg, hsl(0 0% 98%) 0%, hsl(0 0% 95%) 100%);
|
||||
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
/* 专业阴影效果 */
|
||||
--shadow-card: 0 1px 3px 0 hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
|
||||
--shadow-hover: 0 4px 6px -1px hsl(0 0% 0% / 0.1), 0 2px 4px -2px hsl(0 0% 0% / 0.1);
|
||||
--shadow-focus: 0 0 0 3px hsl(0 75% 25% / 0.1);
|
||||
|
||||
--sidebar-background: 0 0% 8%;
|
||||
--sidebar-foreground: 0 0% 85%;
|
||||
--sidebar-primary: 0 75% 35%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
|
||||
--sidebar-border: 220 13% 91%;
|
||||
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--sidebar-accent: 0 0% 12%;
|
||||
--sidebar-accent-foreground: 0 0% 85%;
|
||||
--sidebar-border: 0 0% 15%;
|
||||
--sidebar-ring: 0 75% 45%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--background: 0 0% 3%;
|
||||
--foreground: 0 0% 95%;
|
||||
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--card: 0 0% 5%;
|
||||
--card-foreground: 0 0% 95%;
|
||||
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
--popover: 0 0% 5%;
|
||||
--popover-foreground: 0 0% 95%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
--primary: 0 75% 45%;
|
||||
--primary-foreground: 0 0% 5%;
|
||||
|
||||
--secondary: 217.2 32.6% 17.5%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--secondary: 0 0% 8%;
|
||||
--secondary-foreground: 0 0% 95%;
|
||||
|
||||
--muted: 217.2 32.6% 17.5%;
|
||||
--muted-foreground: 215 20.2% 65.1%;
|
||||
--muted: 0 0% 8%;
|
||||
--muted-foreground: 0 0% 60%;
|
||||
|
||||
--accent: 217.2 32.6% 17.5%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--accent: 0 60% 50%;
|
||||
--accent-foreground: 0 0% 5%;
|
||||
|
||||
--destructive: 0 62.8% 30.6%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
--destructive: 0 75% 55%;
|
||||
--destructive-foreground: 0 0% 95%;
|
||||
|
||||
--border: 217.2 32.6% 17.5%;
|
||||
--input: 217.2 32.6% 17.5%;
|
||||
--ring: 212.7 26.8% 83.9%;
|
||||
--sidebar-background: 240 5.9% 10%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 240 3.7% 15.9%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--border: 0 0% 12%;
|
||||
--input: 0 0% 12%;
|
||||
--ring: 0 75% 45%;
|
||||
|
||||
/* 暗色模式专业渐变效果 */
|
||||
--gradient-primary: linear-gradient(135deg, hsl(0 75% 45%) 0%, hsl(0 60% 50%) 100%);
|
||||
--gradient-card: linear-gradient(145deg, hsl(0 0% 5%) 0%, hsl(0 0% 3%) 100%);
|
||||
--gradient-background: linear-gradient(180deg, hsl(0 0% 3%) 0%, hsl(0 0% 1%) 100%);
|
||||
|
||||
/* 暗色模式专业阴影效果 */
|
||||
--shadow-card: 0 1px 3px 0 hsl(0 0% 0% / 0.3), 0 1px 2px -1px hsl(0 0% 0% / 0.3);
|
||||
--shadow-hover: 0 4px 6px -1px hsl(0 0% 0% / 0.4), 0 2px 4px -2px hsl(0 0% 0% / 0.4);
|
||||
--shadow-focus: 0 0 0 3px hsl(0 75% 45% / 0.2);
|
||||
|
||||
--sidebar-background: 0 0% 2%;
|
||||
--sidebar-foreground: 0 0% 85%;
|
||||
--sidebar-primary: 0 75% 50%;
|
||||
--sidebar-primary-foreground: 0 0% 5%;
|
||||
--sidebar-accent: 0 0% 6%;
|
||||
--sidebar-accent-foreground: 0 0% 85%;
|
||||
--sidebar-border: 0 0% 8%;
|
||||
--sidebar-ring: 0 75% 55%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,42 +129,42 @@ All colors MUST be HSL.
|
|||
@layer components {
|
||||
/* 页面标题样式 */
|
||||
.page-title {
|
||||
@apply text-2xl md:text-3xl font-bold text-gray-900 tracking-tight;
|
||||
@apply text-2xl md:text-3xl font-bold text-foreground tracking-tight;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
@apply text-sm md:text-base text-gray-600 mt-1;
|
||||
@apply text-sm md:text-base text-muted-foreground mt-1;
|
||||
}
|
||||
|
||||
/* 现代化卡片样式 */
|
||||
.card-modern {
|
||||
@apply bg-white rounded-xl border border-gray-200/60 shadow-sm hover:shadow-md transition-all duration-200;
|
||||
@apply bg-card rounded-xl border border-border shadow-sm hover:shadow-md transition-all duration-200;
|
||||
}
|
||||
|
||||
/* 统计卡片样式 */
|
||||
.stat-card {
|
||||
@apply bg-white rounded-xl border border-gray-200/60 shadow-sm hover:shadow-lg transition-all duration-300 hover:border-gray-300/60;
|
||||
@apply bg-card rounded-xl border border-border shadow-sm hover:shadow-lg transition-all duration-300 hover:border-accent/30;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
@apply text-xs font-medium text-gray-500 uppercase tracking-wide;
|
||||
@apply text-xs font-medium text-muted-foreground uppercase tracking-wide;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
@apply text-2xl md:text-3xl font-bold text-gray-900 mt-1;
|
||||
@apply text-2xl md:text-3xl font-bold text-foreground mt-1;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
@apply w-12 h-12 rounded-lg bg-gradient-to-br flex items-center justify-center shadow-sm;
|
||||
@apply w-12 h-12 rounded-lg bg-gradient-to-br from-primary/10 to-accent/10 flex items-center justify-center shadow-sm;
|
||||
}
|
||||
|
||||
/* 按钮样式 */
|
||||
.btn-primary {
|
||||
@apply bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white shadow-sm hover:shadow-md transition-all duration-200;
|
||||
@apply bg-gradient-to-r from-primary to-accent hover:from-primary/90 hover:to-accent/90 text-primary-foreground shadow-sm hover:shadow-md transition-all duration-200;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply border-gray-300 hover:border-gray-400 hover:bg-gray-50 transition-all duration-200;
|
||||
@apply border-border hover:border-accent/50 hover:bg-accent/5 transition-all duration-200;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
|
|
@ -153,7 +173,7 @@ All colors MUST be HSL.
|
|||
}
|
||||
|
||||
.empty-icon {
|
||||
@apply w-16 h-16 rounded-full bg-gray-100 flex items-center justify-center mb-4;
|
||||
@apply w-16 h-16 rounded-full bg-muted flex items-center justify-center mb-4;
|
||||
}
|
||||
|
||||
/* 动画 */
|
||||
|
|
@ -174,7 +194,7 @@ All colors MUST be HSL.
|
|||
|
||||
/* 渐变背景 */
|
||||
.gradient-bg {
|
||||
@apply bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50;
|
||||
@apply bg-gradient-to-br from-background via-muted/30 to-accent/5;
|
||||
}
|
||||
|
||||
/* 响应式容器 */
|
||||
|
|
@ -211,11 +231,138 @@ All colors MUST be HSL.
|
|||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(156, 163, 175, 0.5);
|
||||
background: hsl(var(--muted-foreground) / 0.3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(156, 163, 175, 0.8);
|
||||
background: hsl(var(--accent) / 0.6);
|
||||
}
|
||||
|
||||
/* 专业高级感样式 */
|
||||
.professional-card {
|
||||
@apply bg-gradient-card border border-border/50 shadow-card hover:shadow-hover transition-all duration-300;
|
||||
}
|
||||
|
||||
.professional-button {
|
||||
@apply bg-gradient-primary text-primary-foreground font-semibold px-6 py-3 rounded-lg shadow-sm hover:shadow-md transition-all duration-200 focus:ring-2 focus:ring-primary/20 focus:outline-none;
|
||||
}
|
||||
|
||||
.professional-input {
|
||||
@apply bg-background border border-border rounded-lg px-4 py-2 focus:border-primary focus:ring-2 focus:ring-primary/10 transition-all duration-200;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
@apply bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400;
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
@apply bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400;
|
||||
}
|
||||
|
||||
.status-error {
|
||||
@apply bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
@apply bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400;
|
||||
}
|
||||
|
||||
/* 高级导航样式 */
|
||||
.nav-link {
|
||||
@apply flex items-center px-3 py-2 text-sm font-medium rounded-lg transition-all duration-200 hover:bg-accent/10 hover:text-accent-foreground;
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
@apply bg-primary/10 text-primary border-r-2 border-primary;
|
||||
}
|
||||
|
||||
/* 专业表格样式 */
|
||||
.professional-table {
|
||||
@apply w-full border-collapse bg-card rounded-lg overflow-hidden shadow-card;
|
||||
}
|
||||
|
||||
.professional-table th {
|
||||
@apply bg-muted/50 px-6 py-3 text-left text-xs font-semibold text-muted-foreground uppercase tracking-wider border-b border-border;
|
||||
}
|
||||
|
||||
.professional-table td {
|
||||
@apply px-6 py-4 whitespace-nowrap text-sm text-foreground border-b border-border/50;
|
||||
}
|
||||
|
||||
.professional-table tr:hover {
|
||||
@apply bg-accent/5;
|
||||
}
|
||||
|
||||
/* 图表和图标专用样式 */
|
||||
.chart-primary {
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.chart-accent {
|
||||
color: hsl(var(--accent));
|
||||
}
|
||||
|
||||
.chart-success {
|
||||
color: #10b981;
|
||||
}
|
||||
|
||||
.chart-warning {
|
||||
color: #f59e0b;
|
||||
}
|
||||
|
||||
.chart-error {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.icon-primary {
|
||||
@apply text-primary;
|
||||
}
|
||||
|
||||
.icon-accent {
|
||||
@apply text-accent;
|
||||
}
|
||||
|
||||
.icon-muted {
|
||||
@apply text-muted-foreground;
|
||||
}
|
||||
|
||||
/* 加载动画 */
|
||||
.loading-spinner {
|
||||
@apply animate-spin rounded-full border-2 border-primary border-t-transparent;
|
||||
}
|
||||
|
||||
/* 状态指示器颜色 */
|
||||
.status-running {
|
||||
@apply bg-red-50 text-red-800 border-red-200;
|
||||
}
|
||||
|
||||
.status-completed {
|
||||
@apply bg-green-50 text-green-800 border-green-200;
|
||||
}
|
||||
|
||||
.status-failed {
|
||||
@apply bg-red-100 text-red-900 border-red-300;
|
||||
}
|
||||
|
||||
/* 渐变图标背景 */
|
||||
.icon-bg-primary {
|
||||
@apply bg-gradient-to-br from-primary/10 to-accent/10;
|
||||
}
|
||||
|
||||
.icon-bg-success {
|
||||
@apply bg-gradient-to-br from-green-100 to-emerald-100;
|
||||
}
|
||||
|
||||
.icon-bg-warning {
|
||||
@apply bg-gradient-to-br from-yellow-100 to-orange-100;
|
||||
}
|
||||
|
||||
.icon-bg-error {
|
||||
@apply bg-gradient-to-br from-red-100 to-red-200;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ export default function DatabaseTest() {
|
|||
case 'error':
|
||||
return <AlertTriangle className="w-4 h-4 text-red-600" />;
|
||||
case 'pending':
|
||||
return <Loader2 className="w-4 h-4 text-blue-600 animate-spin" />;
|
||||
return <Loader2 className="w-4 h-4 text-primary animate-spin" />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ export default function DatabaseTest() {
|
|||
case 'error':
|
||||
return <Badge className="bg-red-100 text-red-800">失败</Badge>;
|
||||
case 'pending':
|
||||
return <Badge className="bg-blue-100 text-blue-800">测试中</Badge>;
|
||||
return <Badge className="bg-red-50 text-red-800">测试中</Badge>;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export default function Header() {
|
|||
alt="XCodeReviewer Logo"
|
||||
className="w-9 h-9 rounded-xl shadow-sm group-hover:shadow-md transition-all"
|
||||
/>
|
||||
<span className="text-xl font-bold text-gray-900 group-hover:text-blue-600 transition-colors">XCodeReviewer</span>
|
||||
<span className="text-xl font-bold text-gray-900 group-hover:text-primary transition-colors">XCodeReviewer</span>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
|
|
@ -35,8 +35,8 @@ export default function Header() {
|
|||
to={route.path}
|
||||
className={`px-4 py-2 text-sm font-medium rounded-lg transition-all ${
|
||||
location.pathname === route.path
|
||||
? "text-blue-600 bg-blue-50"
|
||||
: "text-gray-700 hover:text-blue-600 hover:bg-gray-50"
|
||||
? "text-primary bg-red-50"
|
||||
: "text-gray-700 hover:text-primary hover:bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
{route.name}
|
||||
|
|
@ -74,8 +74,8 @@ export default function Header() {
|
|||
to={route.path}
|
||||
className={`block px-3 py-2 text-base font-medium rounded-md transition-colors ${
|
||||
location.pathname === route.path
|
||||
? "text-blue-600 bg-blue-50"
|
||||
: "text-gray-700 hover:text-blue-600 hover:bg-gray-50"
|
||||
? "text-primary bg-red-50"
|
||||
: "text-gray-700 hover:text-primary hover:bg-gray-50"
|
||||
}`}
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default function AdminDashboard() {
|
|||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ export default function AdminDashboard() {
|
|||
管理系统用户、配置和监控系统状态
|
||||
</p>
|
||||
</div>
|
||||
<Badge variant="outline" className="bg-blue-50 text-blue-700">
|
||||
<Badge variant="outline" className="bg-red-50 text-red-700">
|
||||
<Shield className="w-4 h-4 mr-2" />
|
||||
管理员权限
|
||||
</Badge>
|
||||
|
|
@ -120,7 +120,7 @@ export default function AdminDashboard() {
|
|||
<Card>
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-center">
|
||||
<Users className="h-8 w-8 text-blue-600" />
|
||||
<Users className="h-8 w-8 text-primary" />
|
||||
<div className="ml-4">
|
||||
<p className="text-sm font-medium text-muted-foreground">总用户数</p>
|
||||
<p className="text-2xl font-bold">{profiles.length}</p>
|
||||
|
|
@ -211,7 +211,7 @@ export default function AdminDashboard() {
|
|||
{filteredProfiles.map((profile) => (
|
||||
<div key={profile.id} className="flex items-center justify-between p-4 border rounded-lg">
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="w-10 h-10 bg-gradient-to-r from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-medium">
|
||||
<div className="w-10 h-10 bg-gradient-to-r from-primary to-accent rounded-full flex items-center justify-center text-white font-medium">
|
||||
{profile.full_name?.charAt(0) || profile.phone?.charAt(0) || 'U'}
|
||||
</div>
|
||||
<div>
|
||||
|
|
@ -282,7 +282,7 @@ export default function AdminDashboard() {
|
|||
<span className="text-sm text-muted-foreground">15%</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
||||
<div className="bg-blue-600 h-2 rounded-full" style={{ width: '15%' }}></div>
|
||||
<div className="bg-primary h-2 rounded-full" style={{ width: '15%' }}></div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
|
|
@ -347,8 +347,8 @@ export default function AdminDashboard() {
|
|||
<p className="text-xs text-muted-foreground">2024-01-15 09:00:00</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-3 p-3 bg-blue-50 rounded-lg">
|
||||
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||
<div className="flex items-center space-x-3 p-3 bg-red-50 rounded-lg">
|
||||
<div className="w-2 h-2 bg-primary rounded-full"></div>
|
||||
<div className="flex-1">
|
||||
<p className="text-sm font-medium">新用户注册</p>
|
||||
<p className="text-xs text-muted-foreground">2024-01-15 08:45:00</p>
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ export default function AuditTasks() {
|
|||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed': return 'bg-green-100 text-green-800';
|
||||
case 'running': return 'bg-blue-100 text-blue-800';
|
||||
case 'failed': return 'bg-red-100 text-red-800';
|
||||
case 'running': return 'bg-red-50 text-red-800';
|
||||
case 'failed': return 'bg-red-100 text-red-900';
|
||||
default: return 'bg-gray-100 text-gray-800';
|
||||
}
|
||||
};
|
||||
|
|
@ -79,7 +79,7 @@ export default function AuditTasks() {
|
|||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ export default function AuditTasks() {
|
|||
<p className="stat-label">总任务数</p>
|
||||
<p className="stat-value text-xl">{tasks.length}</p>
|
||||
</div>
|
||||
<div className="stat-icon from-blue-500 to-blue-600">
|
||||
<div className="stat-icon from-primary to-accent">
|
||||
<Activity className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -214,13 +214,13 @@ export default function AuditTasks() {
|
|||
<div className="flex items-center space-x-4">
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
|
||||
task.status === 'completed' ? 'bg-emerald-100 text-emerald-600' :
|
||||
task.status === 'running' ? 'bg-blue-100 text-blue-600' :
|
||||
task.status === 'running' ? 'bg-red-50 text-red-600' :
|
||||
task.status === 'failed' ? 'bg-red-100 text-red-600' : 'bg-gray-100 text-gray-600'
|
||||
}`}>
|
||||
{getStatusIcon(task.status)}
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold text-lg text-gray-900 group-hover:text-blue-600 transition-colors">
|
||||
<h3 className="font-semibold text-lg text-gray-900 group-hover:text-primary transition-colors">
|
||||
{task.project?.name || '未知项目'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500">
|
||||
|
|
@ -249,7 +249,7 @@ export default function AuditTasks() {
|
|||
<p className="text-xs text-gray-500 mt-1">发现问题</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p className="text-2xl font-bold text-blue-600">{task.quality_score.toFixed(1)}</p>
|
||||
<p className="text-2xl font-bold text-primary">{task.quality_score.toFixed(1)}</p>
|
||||
<p className="text-xs text-gray-500 mt-1">质量评分</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
|
|
@ -298,7 +298,7 @@ export default function AuditTasks() {
|
|||
<Card className="card-modern">
|
||||
<CardContent className="empty-state py-16">
|
||||
<div className="empty-icon">
|
||||
<Activity className="w-8 h-8 text-blue-600" />
|
||||
<Activity className="w-8 h-8 text-primary" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
||||
{searchTerm || statusFilter !== "all" ? '未找到匹配的任务' : '暂无审计任务'}
|
||||
|
|
|
|||
|
|
@ -74,18 +74,18 @@ export default function Dashboard() {
|
|||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed': return 'bg-emerald-100 text-emerald-700 border-emerald-200';
|
||||
case 'running': return 'bg-blue-100 text-blue-700 border-blue-200';
|
||||
case 'failed': return 'bg-red-100 text-red-700 border-red-200';
|
||||
case 'running': return 'bg-red-50 text-red-700 border-red-200';
|
||||
case 'failed': return 'bg-red-100 text-red-800 border-red-300';
|
||||
default: return 'bg-gray-100 text-gray-700 border-gray-200';
|
||||
}
|
||||
};
|
||||
|
||||
const issueTypeData = [
|
||||
{ name: '安全问题', value: 15, color: '#ef4444' },
|
||||
{ name: '性能问题', value: 25, color: '#f97316' },
|
||||
{ name: '代码风格', value: 35, color: '#eab308' },
|
||||
{ name: '潜在Bug', value: 20, color: '#3b82f6' },
|
||||
{ name: '可维护性', value: 5, color: '#8b5cf6' }
|
||||
{ name: '安全问题', value: 15, color: '#dc2626' },
|
||||
{ name: '性能问题', value: 25, color: '#b91c1c' },
|
||||
{ name: '代码风格', value: 35, color: '#991b1b' },
|
||||
{ name: '潜在Bug', value: 20, color: '#7f1d1d' },
|
||||
{ name: '可维护性', value: 5, color: '#450a0a' }
|
||||
];
|
||||
|
||||
const qualityTrendData = [
|
||||
|
|
@ -145,7 +145,7 @@ export default function Dashboard() {
|
|||
<p className="stat-value">{stats?.total_projects || 5}</p>
|
||||
<p className="text-xs text-gray-500 mt-1">活跃 {stats?.active_projects || 4} 个</p>
|
||||
</div>
|
||||
<div className="stat-icon from-blue-500 to-blue-600 group-hover:scale-110 transition-transform">
|
||||
<div className="stat-icon from-primary to-accent group-hover:scale-110 transition-transform">
|
||||
<Code className="w-6 h-6 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -211,7 +211,7 @@ export default function Dashboard() {
|
|||
<Card className="card-modern">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="flex items-center text-lg">
|
||||
<TrendingUp className="w-5 h-5 mr-2 text-blue-600" />
|
||||
<TrendingUp className="w-5 h-5 mr-2 text-primary" />
|
||||
代码质量趋势
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
|
@ -232,9 +232,9 @@ export default function Dashboard() {
|
|||
<Line
|
||||
type="monotone"
|
||||
dataKey="score"
|
||||
stroke="#3b82f6"
|
||||
stroke="hsl(var(--primary))"
|
||||
strokeWidth={3}
|
||||
dot={{ fill: '#3b82f6', strokeWidth: 2, r: 4 }}
|
||||
dot={{ fill: 'hsl(var(--primary))', strokeWidth: 2, r: 4 }}
|
||||
activeDot={{ r: 6 }}
|
||||
/>
|
||||
</LineChart>
|
||||
|
|
@ -246,7 +246,7 @@ export default function Dashboard() {
|
|||
<Card className="card-modern">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="flex items-center text-lg">
|
||||
<BarChart3 className="w-5 h-5 mr-2 text-orange-600" />
|
||||
<BarChart3 className="w-5 h-5 mr-2 text-accent" />
|
||||
问题类型分布
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
|
@ -278,7 +278,7 @@ export default function Dashboard() {
|
|||
<Card className="card-modern">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="flex items-center text-lg">
|
||||
<FileText className="w-5 h-5 mr-2 text-blue-600" />
|
||||
<FileText className="w-5 h-5 mr-2 text-primary" />
|
||||
项目概览
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
|
@ -289,10 +289,10 @@ export default function Dashboard() {
|
|||
<Link
|
||||
key={project.id}
|
||||
to={`/projects/${project.id}`}
|
||||
className="block p-4 rounded-lg border border-gray-200 hover:border-blue-300 hover:bg-blue-50/50 transition-all group"
|
||||
className="block p-4 rounded-lg border border-gray-200 hover:border-primary/30 hover:bg-primary/5 transition-all group"
|
||||
>
|
||||
<div className="flex items-start justify-between mb-2">
|
||||
<h4 className="font-medium text-gray-900 group-hover:text-blue-600 transition-colors truncate">
|
||||
<h4 className="font-medium text-gray-900 group-hover:text-primary transition-colors truncate">
|
||||
{project.name}
|
||||
</h4>
|
||||
<Badge
|
||||
|
|
@ -348,7 +348,7 @@ export default function Dashboard() {
|
|||
>
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${task.status === 'completed' ? 'bg-emerald-100 text-emerald-600' :
|
||||
task.status === 'running' ? 'bg-blue-100 text-blue-600' :
|
||||
task.status === 'running' ? 'bg-red-50 text-red-600' :
|
||||
'bg-red-100 text-red-600'
|
||||
}`}>
|
||||
{task.status === 'completed' ? <Activity className="w-4 h-4" /> :
|
||||
|
|
@ -356,7 +356,7 @@ export default function Dashboard() {
|
|||
<AlertTriangle className="w-4 h-4" />}
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium text-sm text-gray-900 group-hover:text-blue-600 transition-colors">
|
||||
<p className="font-medium text-sm text-gray-900 group-hover:text-primary transition-colors">
|
||||
{task.project?.name || '未知项目'}
|
||||
</p>
|
||||
<p className="text-xs text-gray-500">
|
||||
|
|
@ -384,7 +384,7 @@ export default function Dashboard() {
|
|||
{/* 右侧边栏 - 紧凑设计 */}
|
||||
<div className="xl:col-span-1 space-y-4">
|
||||
{/* 快速操作 */}
|
||||
<Card className="card-modern bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50 border border-blue-100/50">
|
||||
<Card className="card-modern bg-gradient-to-br from-red-50/30 via-background to-red-50/20 border border-red-100/50">
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-lg flex items-center">
|
||||
<Zap className="w-5 h-5 mr-2 text-indigo-600" />
|
||||
|
|
@ -450,10 +450,10 @@ export default function Dashboard() {
|
|||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="p-3 bg-blue-50 rounded-lg border border-blue-200">
|
||||
<p className="text-sm font-medium text-blue-900">系统更新</p>
|
||||
<p className="text-xs text-blue-700 mt-1">新增代码安全检测功能</p>
|
||||
<p className="text-xs text-blue-600 mt-1">2小时前</p>
|
||||
<div className="p-3 bg-red-50 rounded-lg border border-red-200">
|
||||
<p className="text-sm font-medium text-red-900">系统更新</p>
|
||||
<p className="text-xs text-red-700 mt-1">新增代码安全检测功能</p>
|
||||
<p className="text-xs text-red-600 mt-1">2小时前</p>
|
||||
</div>
|
||||
<div className="p-3 bg-emerald-50 rounded-lg border border-emerald-200">
|
||||
<p className="text-sm font-medium text-emerald-900">任务完成</p>
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ public class Example {
|
|||
case 'critical': return 'bg-red-100 text-red-800 border-red-200';
|
||||
case 'high': return 'bg-orange-100 text-orange-800 border-orange-200';
|
||||
case 'medium': return 'bg-yellow-100 text-yellow-800 border-yellow-200';
|
||||
case 'low': return 'bg-blue-100 text-blue-800 border-blue-200';
|
||||
case 'low': return 'bg-red-50 text-red-800 border-red-200';
|
||||
default: return 'bg-gray-100 text-gray-800 border-gray-200';
|
||||
}
|
||||
};
|
||||
|
|
@ -370,14 +370,14 @@ public class Example {
|
|||
<CardContent>
|
||||
{/* 核心指标 */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||
<div className="text-center p-6 bg-gradient-to-br from-blue-50 to-indigo-50 rounded-xl border border-blue-200">
|
||||
<div className="w-16 h-16 bg-blue-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<div className="text-center p-6 bg-gradient-to-br from-red-50/50 to-red-100/30 rounded-xl border border-red-200">
|
||||
<div className="w-16 h-16 bg-primary rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<Target className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div className="text-3xl font-bold text-blue-600 mb-2">
|
||||
<div className="text-3xl font-bold text-primary mb-2">
|
||||
{result.quality_score.toFixed(1)}
|
||||
</div>
|
||||
<p className="text-sm font-medium text-blue-700 mb-3">质量评分</p>
|
||||
<p className="text-sm font-medium text-primary/80 mb-3">质量评分</p>
|
||||
<Progress value={result.quality_score} className="h-2" />
|
||||
</div>
|
||||
|
||||
|
|
@ -478,11 +478,10 @@ public class Example {
|
|||
<div key={index} className="border border-gray-200 rounded-xl p-6 hover:shadow-md transition-all duration-200 bg-white">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex items-start space-x-3">
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${
|
||||
issue.severity === 'critical' ? 'bg-red-100 text-red-600' :
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${issue.severity === 'critical' ? 'bg-red-100 text-red-600' :
|
||||
issue.severity === 'high' ? 'bg-orange-100 text-orange-600' :
|
||||
issue.severity === 'medium' ? 'bg-yellow-100 text-yellow-600' :
|
||||
'bg-blue-100 text-blue-600'
|
||||
'bg-red-50 text-red-600'
|
||||
}`}>
|
||||
{getTypeIcon(issue.type)}
|
||||
</div>
|
||||
|
|
@ -513,12 +512,12 @@ public class Example {
|
|||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="bg-blue-50 rounded-lg p-4 border border-blue-200">
|
||||
<div className="bg-red-50 rounded-lg p-4 border border-red-200">
|
||||
<div className="flex items-center mb-2">
|
||||
<Lightbulb className="w-5 h-5 text-blue-600 mr-2" />
|
||||
<span className="font-medium text-blue-800">修复建议</span>
|
||||
<Lightbulb className="w-5 h-5 text-primary mr-2" />
|
||||
<span className="font-medium text-red-800">修复建议</span>
|
||||
</div>
|
||||
<p className="text-blue-700 text-sm leading-relaxed">{issue.suggestion}</p>
|
||||
<p className="text-red-700 text-sm leading-relaxed">{issue.suggestion}</p>
|
||||
</div>
|
||||
|
||||
{issue.ai_explanation && (
|
||||
|
|
@ -539,44 +538,60 @@ public class Example {
|
|||
<TabsContent key={severity} value={severity} className="space-y-4 mt-6">
|
||||
{result.issues.filter(issue => issue.severity === severity).length > 0 ? (
|
||||
result.issues.filter(issue => issue.severity === severity).map((issue, index) => (
|
||||
<div key={index} className={`border rounded-xl p-6 ${
|
||||
severity === 'critical' ? 'border-red-200 bg-red-50' :
|
||||
severity === 'high' ? 'border-orange-200 bg-orange-50' :
|
||||
'border-yellow-200 bg-yellow-50'
|
||||
}`}>
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className={`w-8 h-8 rounded-lg flex items-center justify-center ${
|
||||
severity === 'critical' ? 'bg-red-600 text-white' :
|
||||
severity === 'high' ? 'bg-orange-600 text-white' :
|
||||
'bg-yellow-600 text-white'
|
||||
<div key={index} className="border border-gray-200 rounded-xl p-6 hover:shadow-md transition-all duration-200 bg-white">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex items-start space-x-3">
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center ${issue.severity === 'critical' ? 'bg-red-100 text-red-600' :
|
||||
issue.severity === 'high' ? 'bg-orange-100 text-orange-600' :
|
||||
issue.severity === 'medium' ? 'bg-yellow-100 text-yellow-600' :
|
||||
'bg-red-50 text-red-600'
|
||||
}`}>
|
||||
{getTypeIcon(issue.type)}
|
||||
</div>
|
||||
<h4 className={`font-semibold ${
|
||||
severity === 'critical' ? 'text-red-800' :
|
||||
severity === 'high' ? 'text-orange-800' :
|
||||
'text-yellow-800'
|
||||
}`}>{issue.title}</h4>
|
||||
<div>
|
||||
<h4 className="font-semibold text-lg text-gray-900 mb-1">{issue.title}</h4>
|
||||
<p className="text-gray-600 text-sm">第 {issue.line} 行</p>
|
||||
</div>
|
||||
<span className={`text-xs px-2 py-1 rounded ${
|
||||
severity === 'critical' ? 'bg-red-200 text-red-800' :
|
||||
severity === 'high' ? 'bg-orange-200 text-orange-800' :
|
||||
'bg-yellow-200 text-yellow-800'
|
||||
}`}>
|
||||
第 {issue.line} 行
|
||||
</span>
|
||||
</div>
|
||||
<p className={`text-sm mb-3 ${
|
||||
severity === 'critical' ? 'text-red-700' :
|
||||
severity === 'high' ? 'text-orange-700' :
|
||||
'text-yellow-700'
|
||||
}`}>
|
||||
<Badge className={`${getSeverityColor(issue.severity)} px-3 py-1`}>
|
||||
{issue.severity === 'critical' ? '严重' :
|
||||
issue.severity === 'high' ? '高' :
|
||||
issue.severity === 'medium' ? '中等' : '低'}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<p className="text-gray-700 mb-4 leading-relaxed">
|
||||
{issue.description}
|
||||
</p>
|
||||
<div className="bg-white rounded-lg p-3 border">
|
||||
<p className="text-sm font-medium text-gray-800 mb-1">修复建议:</p>
|
||||
<p className="text-sm text-gray-600">{issue.suggestion}</p>
|
||||
|
||||
<div className="bg-gray-900 rounded-lg p-4 mb-4">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="text-gray-300 text-sm font-medium">问题代码</span>
|
||||
<span className="text-gray-400 text-xs">第 {issue.line} 行</span>
|
||||
</div>
|
||||
<pre className="text-sm text-gray-100 overflow-x-auto">
|
||||
<code>{issue.code_snippet}</code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="bg-red-50 rounded-lg p-4 border border-red-200">
|
||||
<div className="flex items-center mb-2">
|
||||
<Lightbulb className="w-5 h-5 text-primary mr-2" />
|
||||
<span className="font-medium text-red-800">修复建议</span>
|
||||
</div>
|
||||
<p className="text-red-700 text-sm leading-relaxed">{issue.suggestion}</p>
|
||||
</div>
|
||||
|
||||
{issue.ai_explanation && (
|
||||
<div className="bg-green-50 rounded-lg p-4 border border-green-200">
|
||||
<div className="flex items-center mb-2">
|
||||
<Zap className="w-5 h-5 text-green-600 mr-2" />
|
||||
<span className="font-medium text-green-800">AI 解释</span>
|
||||
</div>
|
||||
<p className="text-green-700 text-sm leading-relaxed">{issue.ai_explanation}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
|
@ -620,13 +635,13 @@ public class Example {
|
|||
<Card className="card-modern">
|
||||
<CardContent className="py-16">
|
||||
<div className="text-center">
|
||||
<div className="w-20 h-20 bg-blue-100 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-4 border-blue-600 border-t-transparent"></div>
|
||||
<div className="w-20 h-20 bg-red-50 rounded-full flex items-center justify-center mx-auto mb-6">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-4 border-primary border-t-transparent"></div>
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">AI正在分析您的代码</h3>
|
||||
<p className="text-gray-600 text-lg mb-6">请稍候,这通常只需要几秒钟...</p>
|
||||
<div className="bg-blue-50 rounded-lg p-6 max-w-md mx-auto">
|
||||
<p className="text-blue-700 text-sm">
|
||||
<p className="text-gray-600 text-lg mb-6">请稍候,这通常需要至少30秒钟...</p>
|
||||
<div className="bg-red-50 rounded-lg p-6 max-w-md mx-auto">
|
||||
<p className="text-red-700 text-sm">
|
||||
正在进行安全检测、性能分析、代码风格检查等多维度评估
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ const login_config = {
|
|||
export default function Login() {
|
||||
return (
|
||||
<div
|
||||
className="min-h-screen bg-gradient-to-br from-blue-50 via-white to-indigo-50 flex items-center justify-center p-4"
|
||||
className="min-h-screen bg-gradient-to-br from-red-50/30 via-white to-red-50/20 flex items-center justify-center p-4"
|
||||
style={{
|
||||
backgroundImage: `linear-gradient(rgba(59, 130, 246, 0.1), rgba(99, 102, 241, 0.1)), url('https://miaoda-site-img.cdn.bcebos.com/30639cc7-9e0c-45fa-8987-a5389e64f8e9/images/94d4a1a8-923b-11f0-b78c-5a8ff2041e7f_0.jpg')`,
|
||||
backgroundSize: 'cover',
|
||||
|
|
@ -39,7 +39,7 @@ export default function Login() {
|
|||
>
|
||||
<div className="w-full max-w-md">
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-blue-600 to-indigo-600 rounded-full mb-4 shadow-lg">
|
||||
<div className="inline-flex items-center justify-center w-16 h-16 bg-gradient-to-r from-primary to-accent rounded-full mb-4 shadow-lg">
|
||||
<svg className="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ export default function Projects() {
|
|||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-blue-600"></div>
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-primary"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -413,10 +413,10 @@ export default function Projects() {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<div className="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div className="flex items-start space-x-3">
|
||||
<AlertCircle className="w-5 h-5 text-blue-600 mt-0.5" />
|
||||
<div className="text-sm text-blue-800">
|
||||
<AlertCircle className="w-5 h-5 text-primary mt-0.5" />
|
||||
<div className="text-sm text-red-800">
|
||||
<p className="font-medium mb-1">上传说明:</p>
|
||||
<ul className="space-y-1 text-xs">
|
||||
<li>• 请确保 ZIP 文件包含完整的项目代码</li>
|
||||
|
|
@ -469,11 +469,11 @@ export default function Projects() {
|
|||
<CardHeader className="pb-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-blue-500 to-indigo-600 flex items-center justify-center text-white text-lg">
|
||||
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-primary to-accent flex items-center justify-center text-white text-lg">
|
||||
{getRepositoryIcon(project.repository_type)}
|
||||
</div>
|
||||
<div>
|
||||
<CardTitle className="text-lg group-hover:text-blue-600 transition-colors">
|
||||
<CardTitle className="text-lg group-hover:text-primary transition-colors">
|
||||
<Link to={`/projects/${project.id}`}>
|
||||
{project.name}
|
||||
</Link>
|
||||
|
|
@ -501,7 +501,7 @@ export default function Projects() {
|
|||
href={project.repository_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-blue-600 transition-colors flex items-center truncate"
|
||||
className="hover:text-primary transition-colors flex items-center truncate"
|
||||
>
|
||||
<span className="truncate">{project.repository_url.replace('https://', '')}</span>
|
||||
<ExternalLink className="w-3 h-3 ml-1 flex-shrink-0" />
|
||||
|
|
@ -558,7 +558,7 @@ export default function Projects() {
|
|||
<Card className="card-modern">
|
||||
<CardContent className="empty-state py-16">
|
||||
<div className="empty-icon">
|
||||
<Code className="w-8 h-8 text-blue-600" />
|
||||
<Code className="w-8 h-8 text-primary" />
|
||||
</div>
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
||||
{searchTerm ? '未找到匹配的项目' : '暂无项目'}
|
||||
|
|
@ -588,7 +588,7 @@ export default function Projects() {
|
|||
<p className="stat-label">总项目数</p>
|
||||
<p className="stat-value text-xl">{projects.length}</p>
|
||||
</div>
|
||||
<div className="stat-icon from-blue-500 to-blue-600">
|
||||
<div className="stat-icon from-primary to-accent">
|
||||
<Code className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default function TaskDetail() {
|
|||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed': return 'bg-green-100 text-green-800';
|
||||
case 'running': return 'bg-blue-100 text-blue-800';
|
||||
case 'running': return 'bg-red-50 text-red-800';
|
||||
case 'failed': return 'bg-red-100 text-red-800';
|
||||
default: return 'bg-gray-100 text-gray-800';
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ export default function TaskDetail() {
|
|||
case 'critical': return 'bg-red-100 text-red-800 border-red-200';
|
||||
case 'high': return 'bg-orange-100 text-orange-800 border-orange-200';
|
||||
case 'medium': return 'bg-yellow-100 text-yellow-800 border-yellow-200';
|
||||
case 'low': return 'bg-blue-100 text-blue-800 border-blue-200';
|
||||
case 'low': return 'bg-red-50 text-red-800 border-red-200';
|
||||
default: return 'bg-gray-100 text-gray-800 border-gray-200';
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,9 +55,32 @@ export default {
|
|||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
education: {
|
||||
blue: 'hsl(var(--education-blue))',
|
||||
green: 'hsl(var(--education-green))',
|
||||
// 专业深红色调色板
|
||||
crimson: {
|
||||
50: '#fef2f2',
|
||||
100: '#fee2e2',
|
||||
200: '#fecaca',
|
||||
300: '#fca5a5',
|
||||
400: '#f87171',
|
||||
500: '#ef4444',
|
||||
600: '#dc2626',
|
||||
700: '#b91c1c',
|
||||
800: '#991b1b',
|
||||
900: '#7f1d1d',
|
||||
950: '#450a0a',
|
||||
},
|
||||
burgundy: {
|
||||
50: '#fdf2f8',
|
||||
100: '#fce7f3',
|
||||
200: '#fbcfe8',
|
||||
300: '#f9a8d4',
|
||||
400: '#f472b6',
|
||||
500: '#ec4899',
|
||||
600: '#db2777',
|
||||
700: '#be185d',
|
||||
800: '#9d174d',
|
||||
900: '#831843',
|
||||
950: '#500724',
|
||||
},
|
||||
success: 'hsl(var(--success))',
|
||||
warning: 'hsl(var(--warning))',
|
||||
|
|
|
|||
Loading…
Reference in New Issue