feat(web): initialize react 19 vite typescript scaffold and token design system

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WeiCHEN
2026-09-13 02:50:19 +00:00
committed by weichen
co-authored by Cursor
parent ff0262c182
commit 36afce14e6
11 changed files with 2212 additions and 0 deletions
+1
View File
@@ -48,6 +48,7 @@ temp/
dist/
build/
bin/
node_modules/
*.exe
*.o
*.a
+4
View File
@@ -0,0 +1,4 @@
node_modules
dist
dist-ssr
*.local
+18
View File
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="zh-CN" data-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>水木东方 · 医疗器械现代 AI 协同工作台</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
+1911
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
{
"name": "shuimu-workbench",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"test": "node --test"
},
"dependencies": {
"lucide-react": "^1.16.0",
"react": "^19.2.0",
"react-dom": "^19.2.0"
},
"devDependencies": {
"@types/node": "^24.10.1",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.0",
"typescript": "~5.9.3",
"vite": "^7.1.14"
}
}
+30
View File
@@ -0,0 +1,30 @@
import { useState } from 'react';
export default function App() {
const [theme, setTheme] = useState<'dark' | 'light'>('dark');
const toggleTheme = () => {
const next = theme === 'dark' ? 'light' : 'dark';
setTheme(next);
document.documentElement.setAttribute('data-theme', next);
};
return (
<div style={{ padding: '24px', display: 'flex', flexDirection: 'column', gap: '16px' }}>
<h1>水木东方 · 医疗器械现代 AI 协同工作台</h1>
<p>当前主题: {theme}</p>
<button
onClick={toggleTheme}
style={{
width: '120px',
padding: '8px 16px',
background: 'var(--brand-500)',
color: '#fff',
borderRadius: 'var(--r-md)',
}}
>
切换主题
</button>
</div>
);
}
+7
View File
@@ -0,0 +1,7 @@
import ReactDOM from 'react-dom/client';
import App from './App';
import './styles/index.css';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<App />
);
+81
View File
@@ -0,0 +1,81 @@
@import './tokens.css';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body, #root {
width: 100%;
height: 100vh;
overflow: hidden;
font-family: var(--font-sans);
background-color: var(--bg-app);
color: var(--text);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* ============================================================
统一 6px 自定义极简圆角滚动条
============================================================ */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--border-strong);
border-radius: 6px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-faint);
}
/* ============================================================
智能体准备回复中:微光脉冲呼吸动效 (Breathing Pulse)
============================================================ */
@keyframes agent-pulse {
0% {
box-shadow: 0 0 0 0 rgba(79, 107, 255, 0.45);
transform: scale(1);
}
50% {
box-shadow: 0 0 16px 4px rgba(107, 132, 255, 0.7);
transform: scale(1.02);
}
100% {
box-shadow: 0 0 0 0 rgba(79, 107, 255, 0.45);
transform: scale(1);
}
}
.agent-pulse-active {
animation: agent-pulse 2s infinite ease-in-out;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.animate-spin-fast {
animation: spin 0.8s linear infinite;
}
/* 按钮通用重置 */
button {
font-family: inherit;
cursor: pointer;
border: none;
background: none;
outline: none;
}
input, textarea {
font-family: inherit;
outline: none;
}
+96
View File
@@ -0,0 +1,96 @@
/* ============================================================
水木东方医疗器械 AI 协同工作台 — 核心设计变量系统 (Tokens)
============================================================ */
:root {
/* 浅色主题 Tokens (Default fallback) */
--bg-app: #F4F6FA;
--bg-panel: #FFFFFF;
--bg-subtle: #F7F8FB;
--bg-hover: #EFF1F7;
--bg-active: #E9EDF7;
--bg-card: #FFFFFF;
--border: #E4E7F0;
--border-strong: #D4D9E5;
--border-light: #EEF0F7;
--text-strong: #1A2233;
--text: #3A4356;
--text-muted: #7A8299;
--text-faint: #A8AFC2;
--text-inverse: #FFFFFF;
--brand-50: #EEF2FF;
--brand-100: #DDE5FF;
--brand-500: #4F6BFF;
--brand-600: #3D55E8;
--brand-grad: linear-gradient(135deg, #5A75FF 0%, #3D55E8 100%);
--amber-50: #FFF7E8;
--amber-500: #F2A93B;
--amber-600: #DE9420;
--success: #21A66A;
--success-bg: #E8F7F0;
--danger: #E4574B;
--danger-bg: #FDEBEA;
--info: #2B6CC9;
--info-bg: #E8F0FE;
--shadow-xs: 0 1px 2px rgba(26, 34, 51, 0.04);
--shadow-sm: 0 1px 3px rgba(26, 34, 51, 0.06), 0 1px 2px rgba(26, 34, 51, 0.04);
--shadow-md: 0 6px 20px rgba(26, 34, 51, 0.08), 0 2px 6px rgba(26, 34, 51, 0.05);
--shadow-lg: 0 16px 40px rgba(26, 34, 51, 0.12), 0 4px 12px rgba(26, 34, 51, 0.06);
--ease: cubic-bezier(0.16, 1, 0.3, 1);
--font-sans: "Inter", "HarmonyOS Sans", "PingFang SC", "Microsoft YaHei", sans-serif;
--font-mono: "JetBrains Mono", "SF Mono", monospace;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 14px;
--r-pill: 999px;
}
/* 深色主题 Tokens */
[data-theme="dark"] {
--bg-app: #0B0E14;
--bg-panel: #131820;
--bg-subtle: #1A212C;
--bg-hover: #212A37;
--bg-active: #27303F;
--bg-card: #151B25;
--border: #242E3F;
--border-strong: #334052;
--border-light: #1E2735;
--text-strong: #E7EBF3;
--text: #B9C1D0;
--text-muted: #8993A7;
--text-faint: #5D687C;
--text-inverse: #0B0E14;
--brand-50: #202A4D;
--brand-100: #27345E;
--brand-500: #6B84FF;
--brand-600: #8498FF;
--brand-grad: linear-gradient(135deg, #7B92FF 0%, #5A75FF 100%);
--amber-50: #33290F;
--amber-500: #F5B94C;
--amber-600: #E5A73A;
--success: #35C77E;
--success-bg: #10301F;
--danger: #F06B5F;
--danger-bg: #3A1B18;
--info: #6FA3F5;
--info-bg: #11263F;
--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 8px 24px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.6), 0 4px 12px rgba(0, 0, 0, 0.4);
}
+20
View File
@@ -0,0 +1,20 @@
{
"compilerOptions": {
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": false,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
}
+19
View File
@@ -0,0 +1,19 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
proxy: {
'/api': {
target: 'http://127.0.0.1:8080',
changeOrigin: true,
},
},
},
build: {
outDir: 'dist',
emptyOutDir: true,
},
});