From bbc8692e7ff7581c46af4fd0dcd44366c51fb3b1 Mon Sep 17 00:00:00 2001
From: wintsa <770775984@qq.com>
Date: Wed, 6 May 2026 14:51:57 +0800
Subject: [PATCH] '1'
---
index.html | 12 +++++
package.json | 24 ++++++++++
src/App.tsx | 104 ++++++++++++++++++++++++++++++++++++++++
src/main.tsx | 13 +++++
src/styles.css | 116 +++++++++++++++++++++++++++++++++++++++++++++
tsconfig.json | 21 ++++++++
tsconfig.node.json | 10 ++++
vite.config.ts | 9 ++++
8 files changed, 309 insertions(+)
create mode 100644 index.html
create mode 100644 package.json
create mode 100644 src/App.tsx
create mode 100644 src/main.tsx
create mode 100644 src/styles.css
create mode 100644 tsconfig.json
create mode 100644 tsconfig.node.json
create mode 100644 vite.config.ts
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,
+ },
+});