From 8b7e86b8bf32b4dc4558928411c481235b68021b Mon Sep 17 00:00:00 2001 From: peng Date: Thu, 30 Oct 2025 20:20:24 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E7=AE=A1=E7=90=86=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=20-=20=E5=85=A8=E9=A2=86=E5=9F=9F=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=84=9F=E7=9F=A5=E4=B8=AD=E5=BF=83=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crop-x/docs/开发项目规范.md | 36 + crop-x/env/.env.dev | 5 +- .../data-center/external/page.tsx | 18 - .../ai-crop-model/data-center/iot/page.tsx | 18 - .../components/AddDataSourceDialog.tsx | 238 + .../external/components/DataSourceCard.tsx | 197 + .../external/components/FilterPanel.tsx | 164 + .../components/StatisticsOverview.tsx | 78 + .../components/externalDataReducer.tsx | 223 + .../data-sense-center/external/page.tsx | 831 +++ .../data-sense-center/external/types.ts | 115 + .../data-sense-center/iot/page.tsx | 1252 ++++ .../page.tsx | 0 crop-x/src/app/api-example/page.tsx | 988 +++- crop-x/src/app/layout.tsx | 20 +- crop-x/src/lib/api/client.gen.ts | 2 +- crop-x/src/lib/api/sdk.gen.ts | 1481 ++++- crop-x/src/lib/api/types.gen.ts | 5185 ++++++++++++++++- package-lock.json | 1233 +--- package.json | 3 + src/components/ai/AIDataCenter.tsx | 335 +- 21 files changed, 11093 insertions(+), 1329 deletions(-) delete mode 100644 crop-x/src/app/(app)/ai-crop-model/data-center/external/page.tsx delete mode 100644 crop-x/src/app/(app)/ai-crop-model/data-center/iot/page.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/AddDataSourceDialog.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/DataSourceCard.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/FilterPanel.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/StatisticsOverview.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/externalDataReducer.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/page.tsx create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/types.ts create mode 100644 crop-x/src/app/(app)/ai-crop-model/data-sense-center/iot/page.tsx rename crop-x/src/app/(app)/ai-crop-model/{data-center => data-sense-center}/page.tsx (100%) diff --git a/crop-x/docs/开发项目规范.md b/crop-x/docs/开发项目规范.md index 569f7ab..bbf6405 100644 --- a/crop-x/docs/开发项目规范.md +++ b/crop-x/docs/开发项目规范.md @@ -1,5 +1,41 @@ # 开发项目规范 +## 通用开发规约 + +### 1. 文件头部注释规范(filekorolheader) + +**规范要求:** +所有页面文件(page.tsx)必须在最上方添加filekorolheader注释,说明文件对应的页面功能、路径和用途。 + +**格式标准:** +```tsx +/** + * filekorolheader: [页面名称] - [功能描述] + * 功能:[主要功能列表] + * 路径:[页面路由路径] + * 规范:[遵循的特殊规范说明] + */ +``` + +**示例:** +```tsx +/** + * filekorolheader: 物联设备数据接入页面 - IoT设备数据管理中心 + * 功能:设备列表管理、实时数据监控、数据对比分析、报告生成 + * 路径:/ai-crop-model/data-sense-center/iot + * 规范:遵循crop-x/docs/开发项目规范.md,使用useReducer状态管理,shadcn语义化样式 + */ +``` + +**实施要点:** +- 必须放在文件最顶部,在'use client'之前 +- 页面名称要准确反映业务功能 +- 功能描述要简明扼要,列出核心功能 +- 路径必须是完整的路由路径 +- 如有特殊规范遵循,需要在规范字段说明 + +--- + ## path:land-information/archive/statistics,name:统计分析页面开发经验 ### 总体开发经验总结 diff --git a/crop-x/env/.env.dev b/crop-x/env/.env.dev index a300eea..8be0fea 100644 --- a/crop-x/env/.env.dev +++ b/crop-x/env/.env.dev @@ -5,7 +5,10 @@ NODE_ENV=development FRONTEND_BASE_URL=https://cavin-smart-crop-ui-app.dev.maimaiag.com # 后端 API 地址 -BACKEND_BASE_URL=http://pengcode.tech:8080 +BACKEND_BASE_URL=https://gitea-admin-hm-smart-agri-app.dev.maimaiag.com/ + +# OpenAPI 生成配置 +API_BASE_URL=https://gitea-admin-hm-smart-agri-app.dev.maimaiag.com # API 版本 API_VERSION=v1 diff --git a/crop-x/src/app/(app)/ai-crop-model/data-center/external/page.tsx b/crop-x/src/app/(app)/ai-crop-model/data-center/external/page.tsx deleted file mode 100644 index 4528c79..0000000 --- a/crop-x/src/app/(app)/ai-crop-model/data-center/external/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -'use client'; - -import { Card } from '@/components/ui/card'; - -export default function ExternalPage() { - return ( -
- -

外部数据

-
-

- 页面路径: /ai-crop-model/data-center/external -

-
-
-
- ); -} \ No newline at end of file diff --git a/crop-x/src/app/(app)/ai-crop-model/data-center/iot/page.tsx b/crop-x/src/app/(app)/ai-crop-model/data-center/iot/page.tsx deleted file mode 100644 index 3d46c81..0000000 --- a/crop-x/src/app/(app)/ai-crop-model/data-center/iot/page.tsx +++ /dev/null @@ -1,18 +0,0 @@ -'use client'; - -import { Card } from '@/components/ui/card'; - -export default function IotPage() { - return ( -
- -

IoT数据

-
-

- 页面路径: /ai-crop-model/data-center/iot -

-
-
-
- ); -} \ No newline at end of file diff --git a/crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/AddDataSourceDialog.tsx b/crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/AddDataSourceDialog.tsx new file mode 100644 index 0000000..6065802 --- /dev/null +++ b/crop-x/src/app/(app)/ai-crop-model/data-sense-center/external/components/AddDataSourceDialog.tsx @@ -0,0 +1,238 @@ +'use client'; + +import { useState } from 'react'; +import { Card } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Textarea } from '@/components/ui/textarea'; +import { Label } from '@/components/ui/label'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from '@/components/ui/dialog'; +import { ExternalDataState, ExternalDataAction } from './externalDataReducer'; +import { DataSourceForm, DataSourceType, AccessMethod, accessMethods } from '../types'; +import { Database, Plus, Upload, Code, Wifi } from 'lucide-react'; +import { toast } from 'sonner'; + +interface AddDataSourceDialogProps { + state: ExternalDataState; + dispatch: React.Dispatch; +} + +export function AddDataSourceDialog({ state, dispatch }: AddDataSourceDialogProps) { + const [formData, setFormData] = useState({ + name: '', + type: '气象数据', + provider: '', + accessMethod: 'API对接', + apiEndpoint: '', + updateFrequency: '', + description: '', + }); + + const resetForm = () => { + setFormData({ + name: '', + type: '气象数据', + provider: '', + accessMethod: 'API对接', + apiEndpoint: '', + updateFrequency: '', + description: '', + }); + }; + + const handleSubmit = () => { + if (!formData.name || !formData.provider || !formData.updateFrequency) { + toast.error('请填写必要字段'); + return; + } + + const newDataSource = { + id: `ext-${Date.now()}`, + ...formData, + lastUpdateTime: new Date().toLocaleString('zh-CN'), + dataPoints: 0, + status: '待配置' as const, + dataFields: [], + }; + + dispatch({ type: 'ADD_DATA_SOURCE', payload: newDataSource }); + dispatch({ type: 'SHOW_ADD_DIALOG', payload: false }); + resetForm(); + toast.success('数据源添加成功'); + }; + + const handleClose = () => { + dispatch({ type: 'SHOW_ADD_DIALOG', payload: false }); + resetForm(); + }; + + const getAccessMethodIcon = (method: AccessMethod) => { + switch (method) { + case 'API对接': + return ; + case 'FTP传输': + return ; + case 'WebSocket': + return ; + case '手动上传': + return ; + default: + return ; + } + }; + + return ( + + + + + + 添加数据源 + + + 配置新的外部数据源,支持多种接入方式 + + + +
+ {/* 基本信息 */} + +

基本信息

+
+
+ + setFormData({ ...formData, name: e.target.value })} + placeholder="例如:国家气象局API" + /> +
+
+ + setFormData({ ...formData, provider: e.target.value })} + placeholder="例如:中国气象局" + /> +
+
+
+ + {/* 数据配置 */} + +

数据配置

+
+
+ + +
+
+ + setFormData({ ...formData, updateFrequency: e.target.value })} + placeholder="例如:每小时、每5天" + /> +
+
+
+ + {/* 接入方式 */} + +

接入方式

+
+
+ +
+ {accessMethods.map((method) => ( + + ))} +
+
+ + {formData.accessMethod === 'API对接' && ( +
+ + setFormData({ ...formData, apiEndpoint: e.target.value })} + placeholder="https://api.example.com/v1/data" + /> +
+ )} +
+
+ + {/* 描述 */} + + +