commit bbc8692e7ff7581c46af4fd0dcd44366c51fb3b1 Author: wintsa <770775984@qq.com> Date: Wed May 6 14:51:57 2026 +0800 '1' diff --git a/index.html b/index.html new file mode 100644 index 0000000..ccbc682 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + AG Chart Service + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..f7e9c33 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "agchart-service", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "tsc -b && vite build", + "preview": "vite preview --host 0.0.0.0" + }, + "dependencies": { + "@vitejs/plugin-react": "^5.0.0", + "ag-charts-community": "^13.2.1", + "ag-charts-react": "^13.2.1", + "vite": "^7.0.0", + "typescript": "^5.8.3", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6" + } +} diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..e1be1da --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,104 @@ +import { useMemo, useState } from 'react'; +import { AgCharts } from 'ag-charts-react'; +import type { AgChartOptions } from 'ag-charts-community'; + +const revenueData = [ + { month: '1月', revenue: 146, orders: 92, margin: 36 }, + { month: '2月', revenue: 158, orders: 101, margin: 39 }, + { month: '3月', revenue: 171, orders: 117, margin: 43 }, + { month: '4月', revenue: 185, orders: 126, margin: 45 }, + { month: '5月', revenue: 193, orders: 133, margin: 47 }, + { month: '6月', revenue: 221, orders: 148, margin: 52 }, +]; + +function App() { + const [chartType, setChartType] = useState<'bar' | 'line'>('bar'); + + const chartOptions = useMemo( + () => ({ + title: { + text: '业务趋势', + }, + subtitle: { + text: '收入、订单与毛利表现', + }, + data: revenueData, + series: [ + { + type: chartType, + xKey: 'month', + yKey: 'revenue', + yName: '收入', + fill: '#2563eb', + stroke: '#2563eb', + }, + { + type: chartType, + xKey: 'month', + yKey: 'orders', + yName: '订单', + fill: '#059669', + stroke: '#059669', + }, + { + type: chartType, + xKey: 'month', + yKey: 'margin', + yName: '毛利', + fill: '#d97706', + stroke: '#d97706', + }, + ], + axes: [ + { + type: 'category', + position: 'bottom', + }, + { + type: 'number', + position: 'left', + title: { + text: '数值', + }, + }, + ], + legend: { + position: 'bottom', + }, + }), + [chartType], + ); + + return ( +
+
+
+

AG Chart Service

+

React 单页图表服务,无路由。

+
+
+ + +
+
+ +
+ +
+
+ ); +} + +export default App; diff --git a/src/main.tsx b/src/main.tsx new file mode 100644 index 0000000..84bd146 --- /dev/null +++ b/src/main.tsx @@ -0,0 +1,13 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { AllCommunityModule, ModuleRegistry } from 'ag-charts-community'; +import App from './App'; +import './styles.css'; + +ModuleRegistry.registerModules([AllCommunityModule]); + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..a6367b6 --- /dev/null +++ b/src/styles.css @@ -0,0 +1,116 @@ +:root { + color: #172033; + background: #f4f7fb; + font-family: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", + sans-serif; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-width: 320px; + min-height: 100vh; +} + +button { + font: inherit; +} + +.app-shell { + display: grid; + grid-template-rows: auto minmax(360px, 1fr); + gap: 18px; + width: min(1180px, calc(100vw - 32px)); + min-height: 100vh; + margin: 0 auto; + padding: 24px 0; +} + +.toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; +} + +.toolbar h1 { + margin: 0; + font-size: 28px; + line-height: 1.15; +} + +.toolbar p { + margin: 6px 0 0; + color: #5b6578; + font-size: 14px; +} + +.segmented-control { + display: inline-grid; + grid-template-columns: repeat(2, minmax(72px, 1fr)); + min-width: 160px; + padding: 4px; + border: 1px solid #cfd7e6; + border-radius: 8px; + background: #ffffff; +} + +.segmented-control button { + min-height: 34px; + border: 0; + border-radius: 6px; + color: #4a5568; + background: transparent; + cursor: pointer; +} + +.segmented-control button.active { + color: #ffffff; + background: #1f4ed8; +} + +.chart-panel { + min-height: 520px; + padding: 16px; + border: 1px solid #d9e1ee; + border-radius: 8px; + background: #ffffff; +} + +.chart-panel > div { + height: 100%; +} + +@media (max-width: 640px) { + .app-shell { + width: min(100vw - 20px, 1180px); + grid-template-rows: auto minmax(420px, 1fr); + padding: 16px 0; + } + + .toolbar { + align-items: stretch; + flex-direction: column; + } + + .toolbar h1 { + font-size: 24px; + } + + .segmented-control { + width: 100%; + } + + .chart-panel { + min-height: 460px; + padding: 10px; + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..782609a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..3adda81 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..5c59447 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + plugins: [react()], + server: { + port: 5173, + }, +});