refactor(前端): 集中管理设计令牌和工具函数

This commit is contained in:
zhang1106
2026-03-10 15:49:02 +08:00
parent 196dc4ae41
commit 7f007f5010
17 changed files with 158 additions and 663 deletions
+2 -74
View File
@@ -51,86 +51,14 @@ import axios from 'axios';
import * as XLSX from 'xlsx';
import Papa from 'papaparse';
import { motion, AnimatePresence } from 'framer-motion';
import { designTokens } from '../config/theme';
import { debounce } from '../utils/common';
const { Option } = Select;
const { Panel } = Collapse;
const { Text, Title } = Typography;
const { TextArea } = Input;
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// 设计令牌 - 现代化配色方案
const designTokens = {
colors: {
primary: {
main: '#6366f1',
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
light: '#818cf8',
dark: '#4f46e5',
bg: '#eef2ff',
},
success: {
main: '#10b981',
gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
light: '#34d399',
dark: '#047857',
bg: '#ecfdf5',
},
warning: {
main: '#f59e0b',
gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
light: '#fbbf24',
dark: '#b45309',
bg: '#fffbeb',
},
error: {
main: '#ef4444',
gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
light: '#f87171',
dark: '#b91c1c',
bg: '#fef2f2',
},
info: {
main: '#3b82f6',
bg: '#eff6ff',
},
neutral: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
},
},
borderRadius: {
sm: '6px',
md: '10px',
lg: '16px',
xl: '20px',
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
},
};
// 动画配置
const animations = {
container: {
+1 -62
View File
@@ -48,6 +48,7 @@ import {
} from '@ant-design/icons';
import axios from 'axios';
import { motion, AnimatePresence } from 'framer-motion';
import { designTokens } from '../config/theme';
import {
inputStyles,
selectStyles,
@@ -62,68 +63,6 @@ const { Option } = Select;
const { Text, Title } = Typography;
const { TextArea } = Input;
// 设计令牌 - 与接线/端口管理页面保持一致
const designTokens = {
colors: {
primary: {
main: '#6366f1',
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
light: '#818cf8',
dark: '#4f46e5',
bg: '#eef2ff',
},
success: {
main: '#10b981',
gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
light: '#34d399',
dark: '#047857',
bg: '#ecfdf5',
},
warning: {
main: '#f59e0b',
gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
light: '#fbbf24',
dark: '#b45309',
bg: '#fffbeb',
},
error: {
main: '#ef4444',
gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
light: '#f87171',
dark: '#b91c1c',
bg: '#fef2f2',
},
info: {
main: '#3b82f6',
bg: '#eff6ff',
},
neutral: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
},
},
borderRadius: {
sm: '6px',
md: '10px',
lg: '16px',
xl: '20px',
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
},
};
// 动画配置
const animations = {
container: {
+1 -60
View File
@@ -43,71 +43,12 @@ import {
datePickerStyles,
inputPlaceholders,
} from '../styles/deviceManagementStyles';
import { designTokens } from '../config/theme';
const { Title, Text } = Typography;
const { RangePicker } = DatePicker;
const { Option } = Select;
// 设计令牌 - 与其他页面统一
const designTokens = {
colors: {
primary: {
main: '#6366f1',
light: '#818cf8',
dark: '#4f46e5',
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
},
secondary: {
main: '#ec4899',
light: '#f472b6',
gradient: 'linear-gradient(135deg, #ec4899 0%, #f97316 100%)',
},
success: {
main: '#10b981',
light: '#34d399',
gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
},
warning: {
main: '#f59e0b',
light: '#fbbf24',
gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
},
error: {
main: '#ef4444',
light: '#f87171',
gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
},
info: {
main: '#3b82f6',
light: '#60a5fa',
},
background: {
main: '#f8fafc',
card: '#ffffff',
elevated: '#ffffff',
},
text: {
primary: '#1e293b',
secondary: '#64748b',
muted: '#94a3b8',
},
border: '#e2e8f0',
},
shadows: {
small: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
medium: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
large: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
glow: '0 0 20px rgba(99, 102, 241, 0.15)',
},
borderRadius: {
small: '8px',
medium: '12px',
large: '16px',
xl: '20px',
full: '9999px',
},
};
// 动画配置
const containerVariants = {
hidden: { opacity: 0 },
+1 -69
View File
@@ -28,78 +28,10 @@ import {
LockOutlined,
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
const { Option = Select.Option } = Select;
const designTokens = {
colors: {
primary: {
main: '#667eea',
gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
light: '#8b9ff0',
dark: '#4f5db8',
},
success: {
main: '#10b981',
gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
},
warning: {
main: '#f59e0b',
gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
},
error: {
main: '#ef4444',
gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
},
text: {
primary: '#1e293b',
secondary: '#64748b',
tertiary: '#94a3b8',
inverse: '#ffffff',
},
background: {
primary: '#ffffff',
secondary: '#f8fafc',
tertiary: '#f1f5f9',
},
border: {
light: '#e2e8f0',
medium: '#cbd5e1',
dark: '#94a3b8',
},
fieldType: {
string: '#3b82f6',
number: '#10b981',
boolean: '#f59e0b',
select: '#8b5cf6',
date: '#06b6d4',
textarea: '#64748b',
},
},
shadows: {
small: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
medium: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
large: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
glow: '0 0 20px rgba(102, 126, 234, 0.15)',
},
borderRadius: {
small: '6px',
medium: '10px',
large: '16px',
},
transitions: {
fast: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
normal: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
},
spacing: {
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px',
xl: '32px',
},
};
const pageContainerStyle = {
minHeight: '100vh',
background: designTokens.colors.background.secondary,
+2 -74
View File
@@ -53,86 +53,14 @@ import { motion, AnimatePresence } from 'framer-motion';
import VirtualDeviceList from '../components/VirtualDeviceList';
import NetworkCardPanel from '../components/NetworkCardPanel';
import NetworkCardCreateModal from '../components/NetworkCardCreateModal';
import { designTokens } from '../config/theme';
import { debounce } from '../utils/common';
const { Option } = Select;
const { Panel } = Collapse;
const { Text, Title } = Typography;
const { TextArea } = Input;
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// 设计令牌 - 与接线管理页面保持一致
const designTokens = {
colors: {
primary: {
main: '#6366f1',
gradient: 'linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%)',
light: '#818cf8',
dark: '#4f46e5',
bg: '#eef2ff',
},
success: {
main: '#10b981',
gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
light: '#34d399',
dark: '#047857',
bg: '#ecfdf5',
},
warning: {
main: '#f59e0b',
gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
light: '#fbbf24',
dark: '#b45309',
bg: '#fffbeb',
},
error: {
main: '#ef4444',
gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
light: '#f87171',
dark: '#b91c1c',
bg: '#fef2f2',
},
info: {
main: '#3b82f6',
bg: '#eff6ff',
},
neutral: {
50: '#f8fafc',
100: '#f1f5f9',
200: '#e2e8f0',
300: '#cbd5e1',
400: '#94a3b8',
500: '#64748b',
600: '#475569',
700: '#334155',
800: '#1e293b',
900: '#0f172a',
},
},
borderRadius: {
sm: '6px',
md: '10px',
lg: '16px',
xl: '20px',
},
shadows: {
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)',
},
};
// 动画配置
const animations = {
container: {
+1 -44
View File
@@ -50,54 +50,11 @@ import {
DeleteFilled,
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
const { Option } = Select;
const { Title, Text } = Typography;
const designTokens = {
colors: {
primary: {
main: '#1890ff',
gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
bgGradient: 'linear-gradient(135deg, #667eea15 0%, #764ba208 100%)',
},
success: {
main: '#52c41a',
gradient: 'linear-gradient(135deg, #52c41a 0%, #389e0d 100%)',
},
warning: {
main: '#faad14',
gradient: 'linear-gradient(135deg, #faad14 0%, #d48806 100%)',
},
error: {
main: '#ff4d4f',
gradient: 'linear-gradient(135deg, #ff4d4f 0%, #cf1322 100%)',
},
purple: {
main: '#722ed1',
gradient: 'linear-gradient(135deg, #722ed1 0%, #531dab 100%)',
},
text: {
primary: '#262626',
secondary: '#8c8c8c',
tertiary: '#bfbfbf',
},
},
shadows: {
small: '0 2px 8px rgba(0, 0, 0, 0.06)',
medium: '0 4px 16px rgba(0, 0, 0, 0.08)',
large: '0 8px 24px rgba(0, 0, 0, 0.12)',
},
borderRadius: {
small: '8px',
medium: '12px',
large: '16px',
},
transitions: {
normal: '0.3s cubic-bezier(0.4, 0, 0.2, 1)',
},
};
const containerStyle = {
minHeight: '100vh',
background: 'linear-gradient(180deg, #f5f7fa 0%, #e8ecf1 100%)',
+1 -40
View File
@@ -45,50 +45,11 @@ import {
DeleteFilled,
} from '@ant-design/icons';
import axios from 'axios';
import { designTokens } from '../config/theme';
const { Option } = Select;
const { Title, Text } = Typography;
const designTokens = {
colors: {
primary: {
main: '#1890ff',
gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
bgGradient: 'linear-gradient(135deg, #667eea15 0%, #764ba208 100%)',
},
success: {
main: '#52c41a',
gradient: 'linear-gradient(135deg, #52c41a 0%, #389e0d 100%)',
},
warning: {
main: '#faad14',
gradient: 'linear-gradient(135deg, #faad14 0%, #d48806 100%)',
},
error: {
main: '#ff4d4f',
gradient: 'linear-gradient(135deg, #ff4d4f 0%, #cf1322 100%)',
},
text: {
primary: '#262626',
secondary: '#8c8c8c',
tertiary: '#bfbfbf',
},
},
shadows: {
small: '0 2px 8px rgba(0, 0, 0, 0.06)',
medium: '0 4px 16px rgba(0, 0, 0, 0.08)',
large: '0 8px 24px rgba(0, 0, 0, 0.12)',
},
borderRadius: {
small: '8px',
medium: '12px',
large: '16px',
},
transitions: {
normal: '0.3s cubic-bezier(0.4, 0, 0.2, 1)',
},
};
const containerStyle = {
minHeight: '100vh',
background: 'linear-gradient(180deg, #f5f7fa 0%, #e8ecf1 100%)',
+1 -23
View File
@@ -45,29 +45,7 @@ import {
import axios from 'axios';
import dayjs from 'dayjs';
import { useSearchParams } from 'react-router-dom';
const debounce = (func, wait) => {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
// 安全地从 localStorage 获取用户信息
const getUserFromStorage = () => {
try {
const userStr = localStorage.getItem('user');
return userStr ? JSON.parse(userStr) : {};
} catch (e) {
console.error('解析用户信息失败:', e);
return {};
}
};
import { debounce, getUserFromStorage } from '../utils/common';
const { Option } = Select;
const { RangePicker } = DatePicker;