chore: delete dead code, fix tailwind dark mode, fix title and start.sh port
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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>regulation-rag</title>
|
<title>T-Systems Regulation Hub</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
export const shellFrameClassName = 'mx-auto w-full max-w-[1680px] px-8';
|
|
||||||
|
|
||||||
export const shellMeta = {
|
|
||||||
productLabel: 'T-Systems Regulation',
|
|
||||||
version: 'v1.0.0',
|
|
||||||
status: 'ONLINE',
|
|
||||||
surface: 'Desktop Web',
|
|
||||||
} as const;
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface BadgeProps {
|
|
||||||
children: React.ReactNode;
|
|
||||||
color?: 'accent' | 'green' | 'orange' | 'red';
|
|
||||||
size?: 'sm' | 'md';
|
|
||||||
}
|
|
||||||
|
|
||||||
const colorMap: Record<string, { bg: string; text: string }> = {
|
|
||||||
accent: { bg: 'var(--accent)', text: '#fff' },
|
|
||||||
green: { bg: 'var(--success)', text: '#fff' },
|
|
||||||
orange: { bg: 'var(--warn)', text: '#fff' },
|
|
||||||
red: { bg: 'var(--danger)', text: '#fff' },
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Badge: React.FC<BadgeProps> = ({
|
|
||||||
children,
|
|
||||||
color = 'accent',
|
|
||||||
size = 'sm',
|
|
||||||
}) => {
|
|
||||||
const sizeStyles: Record<string, string> = {
|
|
||||||
sm: 'px-2 py-0.5 text-xs',
|
|
||||||
md: 'px-3 py-1 text-sm',
|
|
||||||
};
|
|
||||||
|
|
||||||
const c = colorMap[color] ?? colorMap.accent;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className={`${sizeStyles[size]} rounded font-mono font-medium`}
|
|
||||||
style={{ background: c.bg, color: c.text }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface ButtonProps {
|
|
||||||
variant?: 'primary' | 'secondary';
|
|
||||||
size?: 'sm' | 'md' | 'lg';
|
|
||||||
children: React.ReactNode;
|
|
||||||
onClick?: () => void;
|
|
||||||
disabled?: boolean;
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Button: React.FC<ButtonProps> = ({
|
|
||||||
variant = 'primary',
|
|
||||||
size = 'md',
|
|
||||||
children,
|
|
||||||
onClick,
|
|
||||||
disabled = false,
|
|
||||||
className = '',
|
|
||||||
}) => {
|
|
||||||
const baseStyles = `
|
|
||||||
inline-flex items-center justify-center
|
|
||||||
font-semibold rounded-xl cursor-pointer
|
|
||||||
transition-all duration-300 ease
|
|
||||||
disabled:cursor-not-allowed disabled:opacity-50
|
|
||||||
`;
|
|
||||||
|
|
||||||
const sizeStyles: Record<string, string> = {
|
|
||||||
sm: 'px-3 py-1.5 text-xs',
|
|
||||||
md: 'px-5 py-3 text-sm',
|
|
||||||
lg: 'px-8 py-5 text-base',
|
|
||||||
};
|
|
||||||
|
|
||||||
const variantStyles: Record<string, string> = {
|
|
||||||
primary: `
|
|
||||||
bg-gradient-to-r from-t-accent to-t-accent-dark
|
|
||||||
text-white hover:shadow-t-accent hover:-translate-y-0.5
|
|
||||||
hover:from-[#f0208a] hover:to-[#d01070]
|
|
||||||
`,
|
|
||||||
secondary: `
|
|
||||||
bg-t-bg-hover border border-t-border
|
|
||||||
text-t-text2 hover:bg-t-bg-elevated
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
onClick={onClick}
|
|
||||||
disabled={disabled}
|
|
||||||
className={`${baseStyles} ${sizeStyles[size]} ${variantStyles[variant]} ${className}`}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface CardProps {
|
|
||||||
accent?: boolean;
|
|
||||||
highlight?: boolean;
|
|
||||||
padding?: 'sm' | 'md' | 'lg';
|
|
||||||
children: React.ReactNode;
|
|
||||||
className?: string;
|
|
||||||
onClick?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Card: React.FC<CardProps> = ({
|
|
||||||
accent = false,
|
|
||||||
highlight = false,
|
|
||||||
padding = 'md',
|
|
||||||
children,
|
|
||||||
className = '',
|
|
||||||
onClick,
|
|
||||||
}) => {
|
|
||||||
const paddingStyles: Record<string, string> = {
|
|
||||||
sm: 'p-4',
|
|
||||||
md: 'p-5',
|
|
||||||
lg: 'p-8',
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onClick={onClick}
|
|
||||||
className={`
|
|
||||||
relative rounded-xl border transition-all duration-200 cursor-default
|
|
||||||
${paddingStyles[padding]}
|
|
||||||
${accent ? 'border-[color:var(--accent)]' : 'border-[color:var(--border)]'}
|
|
||||||
${highlight ? 'border-2 border-[color:var(--accent)]' : ''}
|
|
||||||
${onClick ? 'cursor-pointer hover:border-[color:var(--accent)]' : ''}
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'var(--surface)',
|
|
||||||
boxShadow: 'var(--shadow-card)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{accent && (
|
|
||||||
<div
|
|
||||||
className="absolute top-0 left-0 right-0 h-[3px] rounded-t-xl"
|
|
||||||
style={{ background: 'linear-gradient(90deg, var(--accent), var(--accent-hover))' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface InputProps {
|
|
||||||
value: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
placeholder?: string;
|
|
||||||
onKeyDown?: (e: React.KeyboardEvent) => void;
|
|
||||||
className?: string;
|
|
||||||
type?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Input: React.FC<InputProps> = ({
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
placeholder = '',
|
|
||||||
onKeyDown,
|
|
||||||
className = '',
|
|
||||||
type = 'text',
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<input
|
|
||||||
type={type}
|
|
||||||
value={value}
|
|
||||||
onChange={(e) => onChange(e.target.value)}
|
|
||||||
onKeyDown={onKeyDown}
|
|
||||||
placeholder={placeholder}
|
|
||||||
className={`
|
|
||||||
w-full px-4 py-3 text-sm rounded-lg outline-none
|
|
||||||
focus:ring-1
|
|
||||||
placeholder:text-[color:var(--muted)]
|
|
||||||
${className}
|
|
||||||
`}
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'var(--surface)',
|
|
||||||
borderColor: 'var(--border)',
|
|
||||||
border: '1px solid var(--border)',
|
|
||||||
color: 'var(--fg)',
|
|
||||||
}}
|
|
||||||
onFocus={(e) => {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--accent)';
|
|
||||||
e.currentTarget.style.boxShadow = '0 0 0 1px var(--accent)';
|
|
||||||
}}
|
|
||||||
onBlur={(e) => {
|
|
||||||
e.currentTarget.style.borderColor = 'var(--border)';
|
|
||||||
e.currentTarget.style.boxShadow = 'none';
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface ProgressBarProps {
|
|
||||||
percent: number;
|
|
||||||
color?: 'accent' | 'green' | 'orange' | 'red';
|
|
||||||
showLabel?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
const colorBg: Record<string, string> = {
|
|
||||||
accent: 'linear-gradient(90deg, var(--accent), var(--accent-hover))',
|
|
||||||
green: 'linear-gradient(90deg, var(--success), #00ff88)',
|
|
||||||
orange: 'linear-gradient(90deg, var(--warn), #ffaa00)',
|
|
||||||
red: 'var(--danger)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ProgressBar: React.FC<ProgressBarProps> = ({
|
|
||||||
percent,
|
|
||||||
color = 'accent',
|
|
||||||
showLabel = false,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div
|
|
||||||
className="h-2 rounded-full flex-1"
|
|
||||||
style={{ backgroundColor: 'var(--border)' }}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="h-full rounded-full transition-all duration-300"
|
|
||||||
style={{
|
|
||||||
width: `${percent}%`,
|
|
||||||
background: colorBg[color] ?? colorBg.accent,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{showLabel && (
|
|
||||||
<span
|
|
||||||
className="font-mono text-xs"
|
|
||||||
style={{ color: 'var(--accent)' }}
|
|
||||||
>
|
|
||||||
{percent}%
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
interface ScoreBarProps {
|
|
||||||
score: number; // 0-100
|
|
||||||
label?: string;
|
|
||||||
accent?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ScoreBar: React.FC<ScoreBarProps> = ({
|
|
||||||
score,
|
|
||||||
label,
|
|
||||||
accent = false,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="p-5 rounded-xl border"
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'var(--surface)',
|
|
||||||
borderColor: accent ? 'var(--accent)' : 'var(--border)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{label && (
|
|
||||||
<div
|
|
||||||
className="font-mono text-xs mb-2"
|
|
||||||
style={{ color: 'var(--muted)', letterSpacing: '1px' }}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className="font-mono text-3xl font-bold"
|
|
||||||
style={{ color: accent ? 'var(--accent)' : 'var(--fg)' }}
|
|
||||||
>
|
|
||||||
{score}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-1 mt-2">
|
|
||||||
{[...Array(10)].map((_, i) => (
|
|
||||||
<div
|
|
||||||
key={i}
|
|
||||||
className="w-2 h-4 rounded-sm"
|
|
||||||
style={{
|
|
||||||
backgroundColor: i < score / 10 ? 'var(--accent)' : 'var(--border)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,6 +1 @@
|
|||||||
export { Button } from './Button';
|
// UI components — add exports here as new components are created
|
||||||
export { Card } from './Card';
|
|
||||||
export { Input } from './Input';
|
|
||||||
export { Badge } from './Badge';
|
|
||||||
export { ProgressBar } from './ProgressBar';
|
|
||||||
export { ScoreBar } from './ScoreBar';
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// Re-export all types
|
// Re-export all types
|
||||||
export * from './theme';
|
|
||||||
export * from './doc';
|
export * from './doc';
|
||||||
export * from './compliance';
|
export * from './compliance';
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
// Theme types
|
|
||||||
export type ThemeMode = 'dark' | 'dim' | 'light';
|
|
||||||
|
|
||||||
export interface ThemeColors {
|
|
||||||
bg: string;
|
|
||||||
bgCard: string;
|
|
||||||
bgHover: string;
|
|
||||||
bgElevated: string;
|
|
||||||
border: string;
|
|
||||||
borderLight: string;
|
|
||||||
text: string;
|
|
||||||
text2: string;
|
|
||||||
text3: string;
|
|
||||||
accent: string;
|
|
||||||
accentDark: string;
|
|
||||||
accentLight: string;
|
|
||||||
green: string;
|
|
||||||
orange: string;
|
|
||||||
gradientAccent: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const darkTheme: ThemeColors = {
|
|
||||||
bg: '#0a0a12',
|
|
||||||
bgCard: '#12121f',
|
|
||||||
bgHover: '#1a1a2e',
|
|
||||||
bgElevated: '#1e1e30',
|
|
||||||
border: '#2a2a40',
|
|
||||||
borderLight: '#4a4a60',
|
|
||||||
text: '#fff',
|
|
||||||
text2: '#c0c0d0',
|
|
||||||
text3: '#9a9aaa',
|
|
||||||
accent: '#e20074',
|
|
||||||
accentDark: '#be0060',
|
|
||||||
accentLight: '#f04090',
|
|
||||||
green: '#00d4aa',
|
|
||||||
orange: '#ff8800',
|
|
||||||
gradientAccent: 'linear-gradient(135deg, #e20074, #be0060)',
|
|
||||||
};
|
|
||||||
|
|
||||||
// Dim theme — Indigo Dusk: deep navy-purple mid-tone, clearly between dark and light
|
|
||||||
export const dimTheme: ThemeColors = {
|
|
||||||
bg: '#1e1b2e',
|
|
||||||
bgCard: '#252237',
|
|
||||||
bgHover: '#2d2945',
|
|
||||||
bgElevated: '#292541',
|
|
||||||
border: '#3a3650',
|
|
||||||
borderLight: '#504c6e',
|
|
||||||
text: '#f0eeff',
|
|
||||||
text2: '#b8b4d8',
|
|
||||||
text3: '#7a7698',
|
|
||||||
accent: '#e20074',
|
|
||||||
accentDark: '#be0060',
|
|
||||||
accentLight: '#f04090',
|
|
||||||
green: '#00c4a0',
|
|
||||||
orange: '#ff8820',
|
|
||||||
gradientAccent: 'linear-gradient(135deg, #e20074, #be0060)',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const lightTheme: ThemeColors = {
|
|
||||||
bg: '#ffffff',
|
|
||||||
bgCard: '#ffffff',
|
|
||||||
bgHover: '#f8f8fc',
|
|
||||||
bgElevated: '#fafafa',
|
|
||||||
border: '#e8e8f0',
|
|
||||||
borderLight: '#d0d0d8',
|
|
||||||
text: '#1a1a2e',
|
|
||||||
text2: '#4a4a5a',
|
|
||||||
text3: '#7a7a8a',
|
|
||||||
accent: '#e20074',
|
|
||||||
accentDark: '#be0060',
|
|
||||||
accentLight: '#f04090',
|
|
||||||
green: '#00b89c',
|
|
||||||
orange: '#ff7700',
|
|
||||||
gradientAccent: 'linear-gradient(135deg, #e20074, #be0060)',
|
|
||||||
};
|
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
# Start the Vite dev server.
|
||||||
# 启动开发服务器
|
# Port defaults to FRONTEND_PORT env var, or 5173 if unset (matches vite.config.ts default).
|
||||||
# 端口: 8000
|
|
||||||
# 监听: 0.0.0.0
|
|
||||||
|
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
|
PORT="${FRONTEND_PORT:-5173}"
|
||||||
echo "Starting dev server on http://0.0.0.0:8001"
|
echo "Starting dev server on http://0.0.0.0:${PORT}"
|
||||||
npx vite --host 0.0.0.0 --port 8001
|
npx vite --host 0.0.0.0 --port "$PORT"
|
||||||
|
|||||||
@@ -4,68 +4,30 @@ export default {
|
|||||||
"./index.html",
|
"./index.html",
|
||||||
"./src/**/*.{js,ts,jsx,tsx}",
|
"./src/**/*.{js,ts,jsx,tsx}",
|
||||||
],
|
],
|
||||||
darkMode: 'class',
|
darkMode: ['selector', '[data-theme="dark"]'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
// 动态主题色(通过CSS变量)
|
't-bg': 'var(--bg)',
|
||||||
't-bg': 'var(--t-bg)',
|
't-surface': 'var(--surface)',
|
||||||
't-bg-card': 'var(--t-bg-card)',
|
't-fg': 'var(--fg)',
|
||||||
't-bg-hover': 'var(--t-bg-hover)',
|
't-muted': 'var(--muted)',
|
||||||
't-bg-elevated': 'var(--t-bg-elevated)',
|
't-border': 'var(--border)',
|
||||||
't-border': 'var(--t-border)',
|
|
||||||
't-border-light': 'var(--t-border-light)',
|
|
||||||
't-text': 'var(--t-text)',
|
|
||||||
't-text2': 'var(--t-text2)',
|
|
||||||
't-text3': 'var(--t-text3)',
|
|
||||||
// 固定品牌色
|
|
||||||
't-accent': '#e20074',
|
't-accent': '#e20074',
|
||||||
't-accent-dark': '#be0060',
|
't-accent-hover': '#c8006a',
|
||||||
't-accent-light': '#f04090',
|
't-success': 'var(--success)',
|
||||||
// 动态状态色
|
't-warn': 'var(--warn)',
|
||||||
't-green': 'var(--t-green)',
|
't-danger': 'var(--danger)',
|
||||||
't-orange': 'var(--t-orange)',
|
|
||||||
't-red': '#ff4444',
|
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
'tele': ['TeleNeo', 'Segoe UI', 'system-ui', 'sans-serif'],
|
'display': ['TeleNeoWeb-Bold', 'Inter', 'sans-serif'],
|
||||||
'mono': ['JetBrains Mono', 'monospace'],
|
'body': ['TeleNeoWeb-Regular', 'Inter', 'sans-serif'],
|
||||||
|
'mono': ['ui-monospace', 'JetBrains Mono', 'Menlo', 'monospace'],
|
||||||
},
|
},
|
||||||
boxShadow: {
|
boxShadow: {
|
||||||
't-glow': '0 0 20px rgba(226,0,116,0.15), 0 0 40px rgba(226,0,116,0.05)',
|
'card': 'var(--shadow-card)',
|
||||||
't-card': '0 2px 8px rgba(226,0,116,0.04)',
|
|
||||||
't-card-hover': '0 4px 16px rgba(226,0,116,0.08)',
|
|
||||||
't-accent': '0 4px 20px rgba(226,0,116,0.4)',
|
|
||||||
},
|
|
||||||
keyframes: {
|
|
||||||
'pulse-glow': {
|
|
||||||
'0%, 100%': {
|
|
||||||
boxShadow: '0 0 12px rgba(226,0,116,0.5), 0 0 24px rgba(226,0,116,0.2)'
|
|
||||||
},
|
|
||||||
'50%': {
|
|
||||||
boxShadow: '0 0 16px rgba(226,0,116,0.7), 0 0 32px rgba(226,0,116,0.3)'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'slideUp': {
|
|
||||||
'0%': { opacity: '0', transform: 'translateY(10px)' },
|
|
||||||
'100%': { opacity: '1', transform: 'translateY(0)' },
|
|
||||||
},
|
|
||||||
'slideIn': {
|
|
||||||
'0%': { transform: 'translateX(100%)' },
|
|
||||||
'100%': { transform: 'translateX(0)' },
|
|
||||||
},
|
|
||||||
'slideOut': {
|
|
||||||
'0%': { transform: 'translateX(0)' },
|
|
||||||
'100%': { transform: 'translateX(100%)' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
'pulse-glow': 'pulse-glow 2s infinite',
|
|
||||||
'slide-up': 'slideUp 0.3s ease',
|
|
||||||
'slide-in': 'slideIn 0.3s ease-out',
|
|
||||||
'slide-out': 'slideOut 0.3s ease-in',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user