生产管理系统 前端不需要的文件删除
This commit is contained in:
@@ -1,178 +0,0 @@
|
||||
# OpenAPI TypeScript 设置指南
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 1. 已完成的步骤
|
||||
|
||||
✅ 创建了示例 OpenAPI 规范文件 (`./api/v1.yaml`)
|
||||
✅ 生成了 TypeScript 类型定义 (`./src/lib/api/v1.d.ts`)
|
||||
✅ 创建了 API 客户端 (`./src/lib/api/client.ts`)
|
||||
✅ 创建了使用示例组件 (`./src/components/examples/ApiExample.tsx`)
|
||||
|
||||
### 2. 如何使用
|
||||
|
||||
#### 基本用法
|
||||
|
||||
```typescript
|
||||
import { api } from '@/lib/api/client';
|
||||
|
||||
// 获取用户列表
|
||||
const users = await api.users.getList({ page: 1, limit: 20 });
|
||||
|
||||
// 获取用户详情
|
||||
const user = await api.users.getDetail(1);
|
||||
|
||||
// 创建农机
|
||||
const newMachine = await api.machinery.create({
|
||||
name: '新拖拉机',
|
||||
type: 'tractor',
|
||||
model: 'John Deere 6M',
|
||||
});
|
||||
```
|
||||
|
||||
#### 类型安全
|
||||
|
||||
```typescript
|
||||
// ✅ 类型安全的 API 调用
|
||||
const params = {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
status: 'running' as const, // TypeScript 会检查枚举值
|
||||
};
|
||||
|
||||
// ❌ 错误会被 TypeScript 捕获
|
||||
const wrongParams = {
|
||||
status: 'invalid-status', // TypeScript 错误: 类型不匹配
|
||||
};
|
||||
```
|
||||
|
||||
## 🔄 更新 API 规范
|
||||
|
||||
### 当后端 API 发生变化时:
|
||||
|
||||
1. **更新 OpenAPI 规范文件**
|
||||
```bash
|
||||
# 方式一:手动编辑 ./api/v1.yaml
|
||||
# 方式二:从后端自动生成(如果后端支持)
|
||||
curl https://gitea-admin-test-app-app.dev.maimaiag.com/v3/api-docs > ./api/v1.yaml
|
||||
```
|
||||
|
||||
2. **重新生成 TypeScript 类型**
|
||||
```bash
|
||||
npx openapi-typescript ./api/v1.yaml -o ./src/lib/api/v1.d.ts
|
||||
```
|
||||
|
||||
3. **更新客户端代码**(如果接口有重大变化)
|
||||
|
||||
## 🛠️ 进阶配置
|
||||
|
||||
### 添加认证
|
||||
|
||||
```typescript
|
||||
import { authClient } from '@/lib/api/client';
|
||||
|
||||
// 使用认证客户端
|
||||
const token = localStorage.getItem('jwt-token');
|
||||
const authenticatedApi = authClient.withAuth(token);
|
||||
|
||||
const user = await authenticatedApi.users.getDetail(1);
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
```typescript
|
||||
try {
|
||||
const result = await api.users.getList();
|
||||
// 处理成功响应
|
||||
} catch (error) {
|
||||
if (error.message.includes('404')) {
|
||||
// 处理 404 错误
|
||||
} else if (error.message.includes('401')) {
|
||||
// 处理认证错误
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 自定义配置
|
||||
|
||||
```typescript
|
||||
const customClient = createClient<paths>({
|
||||
baseUrl: 'https://gitea-admin-test-app-app.dev.maimaiag.com/api/v1',
|
||||
headers: {
|
||||
'User-Agent': 'Smart-Crop-UI/1.0',
|
||||
'X-API-Key': process.env.API_KEY,
|
||||
},
|
||||
// 添加请求拦截器
|
||||
onRequest: async ({ request }) => {
|
||||
// 可以在这里添加日志、重试逻辑等
|
||||
console.log('发送请求:', request.url);
|
||||
return request;
|
||||
},
|
||||
// 添加响应拦截器
|
||||
onResponse: async ({ response }) => {
|
||||
if (response.status === 401) {
|
||||
// 处理 token 过期
|
||||
window.location.href = '/login';
|
||||
}
|
||||
return response;
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
## 📁 文件结构
|
||||
|
||||
```
|
||||
crop-x/
|
||||
├── api/
|
||||
│ └── v1.yaml # OpenAPI 规范文件
|
||||
├── src/
|
||||
│ ├── lib/
|
||||
│ │ └── api/
|
||||
│ │ ├── v1.d.ts # 生成的类型定义
|
||||
│ │ └── client.ts # API 客户端封装
|
||||
│ └── components/
|
||||
│ └── examples/
|
||||
│ └── ApiExample.tsx # 使用示例
|
||||
```
|
||||
|
||||
## 🎯 最佳实践
|
||||
|
||||
### 1. 版本控制
|
||||
- 将 `v1.yaml` 纳入版本控制
|
||||
- 将生成的 `v1.d.ts` 也纳入版本控制,方便代码审查
|
||||
- 在 CI/CD 中自动重新生成类型文件
|
||||
|
||||
### 2. 类型安全
|
||||
- 优先使用 `api.machinery.create()` 这样的封装方法
|
||||
- 避免直接使用 `client.POST()`
|
||||
- 充分利用 TypeScript 的类型检查
|
||||
|
||||
### 3. 错误处理
|
||||
- 在客户端封装中统一处理 API 错误
|
||||
- 提供有意义的错误信息给用户
|
||||
- 实现重试机制和降级策略
|
||||
|
||||
### 4. 性能优化
|
||||
- 实现请求缓存
|
||||
- 使用 React Query 或 SWR 进行数据获取
|
||||
- 考虑添加请求去重
|
||||
|
||||
## 🔗 相关资源
|
||||
|
||||
- [openapi-typescript 官方文档](https://github.com/drwp/openapi-typescript)
|
||||
- [OpenAPI 规范](https://swagger.io/specification/)
|
||||
- [shadcn/ui](https://ui.shadcn.com/)
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
**Q: 如何处理分页?**
|
||||
A: API 已经支持分页参数 `page` 和 `limit`,响应中包含 `total` 字段。
|
||||
|
||||
**Q: 如何处理文件上传?**
|
||||
A: 需要在 OpenAPI 规范中定义 `multipart/form-data` 格式的接口。
|
||||
|
||||
**Q: 如何实现 WebSocket 连接?**
|
||||
A: 当前只支持 HTTP REST API,WebSocket 需要单独实现。
|
||||
|
||||
**Q: 如何添加 Mock 数据?**
|
||||
A: 可以创建另一个客户端实例,返回模拟数据而不是真实请求。
|
||||
342
crop-x/scripts/openapi.json
Normal file
342
crop-x/scripts/openapi.json
Normal file
@@ -0,0 +1,342 @@
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
"title": "Crop Admin API",
|
||||
"description": "一个支持OpenAPI和前端代码自动生成的后台管理系统",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"/api/v1/auth/login": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"认证"
|
||||
],
|
||||
"summary": "用户登录",
|
||||
"description": "用户登录接口\n\n- **username**: 用户名\n- **password**: 密码\n\n返回JWT访问令牌",
|
||||
"operationId": "login_api_v1_auth_login_post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UserLogin"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/auth/register": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"认证"
|
||||
],
|
||||
"summary": "用户注册",
|
||||
"description": "用户注册接口\n\n- **username**: 用户名 (必须唯一)\n- **password**: 密码\n\n注意:这是一个演示版本,实际生产环境需要更严格的验证",
|
||||
"operationId": "register_api_v1_auth_register_post",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UserRegister"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/auth/me": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"认证"
|
||||
],
|
||||
"summary": "获取当前用户信息",
|
||||
"description": "获取当前登录用户的信息",
|
||||
"operationId": "get_current_user_api_v1_auth_me_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"HTTPBearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/auth/logout": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"认证"
|
||||
],
|
||||
"summary": "用户登出",
|
||||
"description": "用户登出接口\n\n注意:由于JWT是无状态的,实际登出需要客户端删除token\n这里只是验证token并返回成功消息",
|
||||
"operationId": "logout_api_v1_auth_logout_post",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"HTTPBearer": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/auth/users": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"认证"
|
||||
],
|
||||
"summary": "获取所有用户列表",
|
||||
"description": "获取系统中所有用户的列表 (仅用于演示)",
|
||||
"operationId": "get_all_users_api_v1_auth_users_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/APIResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/": {
|
||||
"get": {
|
||||
"summary": "Root",
|
||||
"operationId": "root__get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/health": {
|
||||
"get": {
|
||||
"summary": "Health Check",
|
||||
"operationId": "health_check_health_get",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"APIResponse": {
|
||||
"properties": {
|
||||
"success": {
|
||||
"type": "boolean",
|
||||
"title": "Success"
|
||||
},
|
||||
"message": {
|
||||
"type": "string",
|
||||
"title": "Message"
|
||||
},
|
||||
"data": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Data"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"success",
|
||||
"message"
|
||||
],
|
||||
"title": "APIResponse",
|
||||
"example": {
|
||||
"data": {},
|
||||
"message": "操作成功",
|
||||
"success": true
|
||||
}
|
||||
},
|
||||
"HTTPValidationError": {
|
||||
"properties": {
|
||||
"detail": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/ValidationError"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Detail"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"title": "HTTPValidationError"
|
||||
},
|
||||
"UserLogin": {
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string",
|
||||
"title": "Username"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"title": "Password"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"title": "UserLogin",
|
||||
"example": {
|
||||
"password": "admin123",
|
||||
"username": "admin"
|
||||
}
|
||||
},
|
||||
"UserRegister": {
|
||||
"properties": {
|
||||
"username": {
|
||||
"type": "string",
|
||||
"title": "Username"
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
"title": "Password"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"username",
|
||||
"password"
|
||||
],
|
||||
"title": "UserRegister",
|
||||
"example": {
|
||||
"password": "newpassword",
|
||||
"username": "newuser"
|
||||
}
|
||||
},
|
||||
"ValidationError": {
|
||||
"properties": {
|
||||
"loc": {
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Location"
|
||||
},
|
||||
"msg": {
|
||||
"type": "string",
|
||||
"title": "Message"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"title": "Error Type"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"loc",
|
||||
"msg",
|
||||
"type"
|
||||
],
|
||||
"title": "ValidationError"
|
||||
}
|
||||
},
|
||||
"securitySchemes": {
|
||||
"HTTPBearer": {
|
||||
"type": "http",
|
||||
"scheme": "bearer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://gitea-admin-smart-crop-x-app.dev.maimaiag.com/",
|
||||
"description": "测试环境服务器"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import { authApi } from './modules/auth'
|
||||
import { machineryApi } from './modules/machinery'
|
||||
import { landApi } from './modules/land'
|
||||
import { operationApi } from './modules/operation'
|
||||
import { assetApi } from './modules/asset'
|
||||
import { aiModelApi } from './modules/ai-model'
|
||||
import { irrigationApi } from './modules/irrigation'
|
||||
import { configApi } from './modules/config'
|
||||
|
||||
export const api = {
|
||||
auth: authApi,
|
||||
machinery: machineryApi,
|
||||
land: landApi,
|
||||
operation: operationApi,
|
||||
asset: assetApi,
|
||||
aiModel: aiModelApi,
|
||||
irrigation: irrigationApi,
|
||||
config: configApi
|
||||
}
|
||||
|
||||
export * from './types'
|
||||
@@ -1,163 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// AI模型相关类型
|
||||
export interface AIModel {
|
||||
id: string
|
||||
name: string
|
||||
version: string
|
||||
type: 'prediction' | 'classification' | 'recommendation' | 'anomaly_detection'
|
||||
domain: 'crop_yield' | 'disease_detection' | 'pest_prediction' | 'irrigation_optimization' | 'fertilizer_recommendation'
|
||||
description: string
|
||||
algorithm: string
|
||||
accuracy: number
|
||||
trainingDataset: string
|
||||
trainingDate: string
|
||||
status: 'training' | 'trained' | 'deployed' | 'deprecated'
|
||||
parameters: Record<string, any>
|
||||
features: string[]
|
||||
targetVariable: string
|
||||
modelFile?: string
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface ModelTraining {
|
||||
id: string
|
||||
modelId: string
|
||||
name: string
|
||||
datasetId: string
|
||||
parameters: Record<string, any>
|
||||
status: 'pending' | 'running' | 'completed' | 'failed'
|
||||
progress: number
|
||||
startTime?: string
|
||||
endTime?: string
|
||||
metrics?: {
|
||||
accuracy: number
|
||||
precision: number
|
||||
recall: number
|
||||
f1Score: number
|
||||
loss?: number
|
||||
}
|
||||
logs?: string[]
|
||||
errorMessage?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface PredictionRequest {
|
||||
modelId: string
|
||||
inputData: Record<string, any>
|
||||
options?: {
|
||||
probability?: boolean
|
||||
explanations?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export interface PredictionResult {
|
||||
id: string
|
||||
modelId: string
|
||||
prediction: any
|
||||
confidence?: number
|
||||
probability?: Record<string, number>
|
||||
explanations?: Array<{
|
||||
feature: string
|
||||
importance: number
|
||||
contribution: string
|
||||
}>
|
||||
inputData: Record<string, any>
|
||||
timestamp: string
|
||||
processingTime: number
|
||||
}
|
||||
|
||||
export interface Recommendation {
|
||||
id: string
|
||||
type: 'fertilizer' | 'irrigation' | 'planting' | 'harvesting' | 'pest_control'
|
||||
priority: 'low' | 'medium' | 'high'
|
||||
title: string
|
||||
description: string
|
||||
recommendation: string
|
||||
confidence: number
|
||||
validFrom: string
|
||||
validTo: string
|
||||
applicableArea?: string
|
||||
estimatedCost?: number
|
||||
estimatedBenefit?: number
|
||||
landParcelId?: string
|
||||
cropType?: string
|
||||
metadata: Record<string, any>
|
||||
status: 'active' | 'applied' | 'expired' | 'dismissed'
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export const aiModelApi = {
|
||||
// 模型管理
|
||||
getModelList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<AIModel>>> => {
|
||||
return request.get('/ai-model/models', params)
|
||||
},
|
||||
|
||||
getModelDetail: (id: string): Promise<ApiResponse<AIModel>> => {
|
||||
return request.get(`/ai-model/models/${id}`)
|
||||
},
|
||||
|
||||
createModel: (data: Omit<AIModel, 'id' | 'createdAt' | 'updatedAt' | 'accuracy' | 'status' | 'trainingDate'>): Promise<ApiResponse<AIModel>> => {
|
||||
return request.post('/ai-model/models', data)
|
||||
},
|
||||
|
||||
updateModel: (id: string, data: Partial<AIModel>): Promise<ApiResponse<AIModel>> => {
|
||||
return request.put(`/ai-model/models/${id}`, data)
|
||||
},
|
||||
|
||||
deleteModel: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/ai-model/models/${id}`)
|
||||
},
|
||||
|
||||
deployModel: (id: string): Promise<ApiResponse<AIModel>> => {
|
||||
return request.post(`/ai-model/models/${id}/deploy`)
|
||||
},
|
||||
|
||||
// 模型训练
|
||||
startTraining: (data: Omit<ModelTraining, 'id' | 'status' | 'progress' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<ModelTraining>> => {
|
||||
return request.post('/ai-model/training', data)
|
||||
},
|
||||
|
||||
getTrainingDetail: (id: string): Promise<ApiResponse<ModelTraining>> => {
|
||||
return request.get(`/ai-model/training/${id}`)
|
||||
},
|
||||
|
||||
getTrainingList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<ModelTraining>>> => {
|
||||
return request.get('/ai-model/training', params)
|
||||
},
|
||||
|
||||
stopTraining: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.post(`/ai-model/training/${id}/stop`)
|
||||
},
|
||||
|
||||
// 预测分析
|
||||
makePrediction: (data: PredictionRequest): Promise<ApiResponse<PredictionResult>> => {
|
||||
return request.post('/ai-model/predict', data)
|
||||
},
|
||||
|
||||
getPredictionHistory: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<PredictionResult>>> => {
|
||||
return request.get('/ai-model/predictions', params)
|
||||
},
|
||||
|
||||
getPredictionDetail: (id: string): Promise<ApiResponse<PredictionResult>> => {
|
||||
return request.get(`/ai-model/predictions/${id}`)
|
||||
},
|
||||
|
||||
// 推荐系统
|
||||
getRecommendations: (params: QueryRequest & { type?: string; landParcelId?: string }): Promise<ApiResponse<PaginatedResponse<Recommendation>>> => {
|
||||
return request.get('/ai-model/recommendations', params)
|
||||
},
|
||||
|
||||
applyRecommendation: (id: string): Promise<ApiResponse<Recommendation>> => {
|
||||
return request.put(`/ai-model/recommendations/${id}/apply`)
|
||||
},
|
||||
|
||||
dismissRecommendation: (id: string, reason: string): Promise<ApiResponse<Recommendation>> => {
|
||||
return request.put(`/ai-model/recommendations/${id}/dismiss`, { reason })
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 资产管理相关类型
|
||||
export interface AgriculturalAsset {
|
||||
id: string
|
||||
name: string
|
||||
category: 'machinery' | 'equipment' | 'building' | 'land_improvement' | 'livestock' | 'other'
|
||||
subcategory: string
|
||||
serialNumber?: string
|
||||
model?: string
|
||||
brand?: string
|
||||
purchaseDate: string
|
||||
purchasePrice: number
|
||||
currentValue: number
|
||||
depreciationMethod: 'straight_line' | 'declining_balance' | 'units_of_production'
|
||||
usefulLifeYears: number
|
||||
salvageValue: number
|
||||
location: string
|
||||
status: 'active' | 'inactive' | 'disposed' | 'maintenance'
|
||||
assignedTo?: string
|
||||
description?: string
|
||||
images?: string[]
|
||||
documents?: string[]
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface MaintenanceRecord {
|
||||
id: string
|
||||
assetId: string
|
||||
type: 'preventive' | 'corrective' | 'emergency'
|
||||
description: string
|
||||
performedDate: string
|
||||
performedBy: string
|
||||
cost: number
|
||||
partsUsed?: Array<{
|
||||
name: string
|
||||
quantity: number
|
||||
unitCost: number
|
||||
}>
|
||||
nextMaintenanceDate?: string
|
||||
notes?: string
|
||||
documents?: string[]
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface AssetInventory {
|
||||
id: string
|
||||
assetId: string
|
||||
quantity: number
|
||||
unit: string
|
||||
location: string
|
||||
lastCountDate: string
|
||||
expectedQuantity: number
|
||||
variance: number
|
||||
varianceReason?: string
|
||||
countedBy: string
|
||||
verifiedBy?: string
|
||||
status: 'verified' | 'pending_verification' | 'discrepancy'
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export const assetApi = {
|
||||
// 资产管理
|
||||
getAssetList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<AgriculturalAsset>>> => {
|
||||
return request.get('/asset/assets', params)
|
||||
},
|
||||
|
||||
getAssetDetail: (id: string): Promise<ApiResponse<AgriculturalAsset>> => {
|
||||
return request.get(`/asset/assets/${id}`)
|
||||
},
|
||||
|
||||
createAsset: (data: Omit<AgriculturalAsset, 'id' | 'createdAt' | 'updatedAt' | 'currentValue'>): Promise<ApiResponse<AgriculturalAsset>> => {
|
||||
return request.post('/asset/assets', data)
|
||||
},
|
||||
|
||||
updateAsset: (id: string, data: Partial<AgriculturalAsset>): Promise<ApiResponse<AgriculturalAsset>> => {
|
||||
return request.put(`/asset/assets/${id}`, data)
|
||||
},
|
||||
|
||||
deleteAsset: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/asset/assets/${id}`)
|
||||
},
|
||||
|
||||
calculateDepreciation: (id: string, date: string): Promise<ApiResponse<{ currentValue: number; accumulatedDepreciation: number }>> => {
|
||||
return request.post(`/asset/assets/${id}/depreciation`, { date })
|
||||
},
|
||||
|
||||
// 维护记录
|
||||
getMaintenanceRecords: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<MaintenanceRecord>>> => {
|
||||
return request.get('/asset/maintenance', params)
|
||||
},
|
||||
|
||||
getMaintenanceDetail: (id: string): Promise<ApiResponse<MaintenanceRecord>> => {
|
||||
return request.get(`/asset/maintenance/${id}`)
|
||||
},
|
||||
|
||||
createMaintenanceRecord: (data: Omit<MaintenanceRecord, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<MaintenanceRecord>> => {
|
||||
return request.post('/asset/maintenance', data)
|
||||
},
|
||||
|
||||
updateMaintenanceRecord: (id: string, data: Partial<MaintenanceRecord>): Promise<ApiResponse<MaintenanceRecord>> => {
|
||||
return request.put(`/asset/maintenance/${id}`, data)
|
||||
},
|
||||
|
||||
deleteMaintenanceRecord: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/asset/maintenance/${id}`)
|
||||
},
|
||||
|
||||
// 库存管理
|
||||
getInventoryList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<AssetInventory>>> => {
|
||||
return request.get('/asset/inventory', params)
|
||||
},
|
||||
|
||||
getInventoryDetail: (id: string): Promise<ApiResponse<AssetInventory>> => {
|
||||
return request.get(`/asset/inventory/${id}`)
|
||||
},
|
||||
|
||||
createInventoryRecord: (data: Omit<AssetInventory, 'id' | 'createdAt' | 'updatedAt' | 'variance'>): Promise<ApiResponse<AssetInventory>> => {
|
||||
return request.post('/asset/inventory', data)
|
||||
},
|
||||
|
||||
updateInventoryRecord: (id: string, data: Partial<AssetInventory>): Promise<ApiResponse<AssetInventory>> => {
|
||||
return request.put(`/asset/inventory/${id}`, data)
|
||||
},
|
||||
|
||||
verifyInventory: (id: string, verifiedBy: string): Promise<ApiResponse<AssetInventory>> => {
|
||||
return request.put(`/asset/inventory/${id}/verify`, { verifiedBy })
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse } from '../types'
|
||||
|
||||
// 认证相关类型
|
||||
export interface LoginRequest {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export interface PhoneLoginRequest {
|
||||
phone: string
|
||||
code: string
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
token: string
|
||||
refreshToken: string
|
||||
user: {
|
||||
id: string
|
||||
username: string
|
||||
phone: string
|
||||
role: string
|
||||
tenantId: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string
|
||||
username: string
|
||||
phone: string
|
||||
role: string
|
||||
tenantId: string
|
||||
avatar?: string
|
||||
email?: string
|
||||
}
|
||||
|
||||
export const authApi = {
|
||||
// 用户名密码登录
|
||||
login: (data: LoginRequest): Promise<ApiResponse<LoginResponse>> => {
|
||||
return request.post('/auth/login', data)
|
||||
},
|
||||
|
||||
// 手机验证码登录
|
||||
loginByPhone: (data: PhoneLoginRequest): Promise<ApiResponse<LoginResponse>> => {
|
||||
return request.post('/auth/login/phone', data)
|
||||
},
|
||||
|
||||
// 获取验证码
|
||||
sendSmsCode: (phone: string): Promise<ApiResponse<void>> => {
|
||||
return request.post('/auth/sms/send', { phone })
|
||||
},
|
||||
|
||||
// 刷新token
|
||||
refreshToken: (refreshToken: string): Promise<ApiResponse<{ token: string }>> => {
|
||||
return request.post('/auth/refresh', { refreshToken })
|
||||
},
|
||||
|
||||
// 登出
|
||||
logout: (): Promise<ApiResponse<void>> => {
|
||||
return request.post('/auth/logout')
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
getUserInfo: (): Promise<ApiResponse<User>> => {
|
||||
return request.get('/auth/user')
|
||||
},
|
||||
|
||||
// 更新用户信息
|
||||
updateUserInfo: (data: Partial<User>): Promise<ApiResponse<User>> => {
|
||||
return request.put('/auth/user', data)
|
||||
}
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 中心配置相关类型
|
||||
export interface Tenant {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
type: 'individual' | 'enterprise' | 'cooperative'
|
||||
status: 'active' | 'inactive' | 'suspended'
|
||||
contactPerson: string
|
||||
contactPhone: string
|
||||
contactEmail: string
|
||||
address: string
|
||||
maxUsers: number
|
||||
currentUsers: number
|
||||
subscriptionPlan: 'basic' | 'standard' | 'premium'
|
||||
subscriptionExpiry?: string
|
||||
settings: {
|
||||
timezone: string
|
||||
language: string
|
||||
currency: string
|
||||
dateFormat: string
|
||||
numberFormat: string
|
||||
}
|
||||
features: string[]
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string
|
||||
username: string
|
||||
email: string
|
||||
phone: string
|
||||
realName: string
|
||||
avatar?: string
|
||||
role: 'admin' | 'manager' | 'operator' | 'viewer'
|
||||
tenantId: string
|
||||
status: 'active' | 'inactive' | 'locked'
|
||||
lastLoginAt?: string
|
||||
permissions: string[]
|
||||
preferences: {
|
||||
language: string
|
||||
theme: 'light' | 'dark' | 'auto'
|
||||
notifications: {
|
||||
email: boolean
|
||||
sms: boolean
|
||||
push: boolean
|
||||
}
|
||||
}
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface SystemParameter {
|
||||
id: string
|
||||
category: 'system' | 'business' | 'notification' | 'security' | 'integration'
|
||||
key: string
|
||||
value: string
|
||||
type: 'string' | 'number' | 'boolean' | 'json'
|
||||
description: string
|
||||
isEditable: boolean
|
||||
requiresRestart: boolean
|
||||
validationRules?: {
|
||||
required?: boolean
|
||||
min?: number
|
||||
max?: number
|
||||
pattern?: string
|
||||
options?: string[]
|
||||
}
|
||||
tenantId?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface SystemLog {
|
||||
id: string
|
||||
level: 'debug' | 'info' | 'warn' | 'error' | 'fatal'
|
||||
category: 'system' | 'business' | 'security' | 'performance'
|
||||
message: string
|
||||
details?: any
|
||||
userId?: string
|
||||
tenantId?: string
|
||||
ip?: string
|
||||
userAgent?: string
|
||||
timestamp: string
|
||||
duration?: number
|
||||
stackTrace?: string
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: string
|
||||
type: 'system' | 'business' | 'notification' | 'alert'
|
||||
category: 'info' | 'warning' | 'error' | 'success'
|
||||
title: string
|
||||
content: string
|
||||
senderId?: string
|
||||
recipientId?: string
|
||||
recipientRole?: string
|
||||
tenantId?: string
|
||||
status: 'unread' | 'read' | 'archived'
|
||||
priority: 'low' | 'medium' | 'high' | 'urgent'
|
||||
expiresAt?: string
|
||||
metadata?: Record<string, any>
|
||||
createdAt: string
|
||||
readAt?: string
|
||||
}
|
||||
|
||||
export const configApi = {
|
||||
// 租户管理
|
||||
getTenantList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<Tenant>>> => {
|
||||
return request.get('/config/tenants', params)
|
||||
},
|
||||
|
||||
getTenantDetail: (id: string): Promise<ApiResponse<Tenant>> => {
|
||||
return request.get(`/config/tenants/${id}`)
|
||||
},
|
||||
|
||||
createTenant: (data: Omit<Tenant, 'id' | 'createdAt' | 'updatedAt' | 'currentUsers'>): Promise<ApiResponse<Tenant>> => {
|
||||
return request.post('/config/tenants', data)
|
||||
},
|
||||
|
||||
updateTenant: (id: string, data: Partial<Tenant>): Promise<ApiResponse<Tenant>> => {
|
||||
return request.put(`/config/tenants/${id}`, data)
|
||||
},
|
||||
|
||||
deleteTenant: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/config/tenants/${id}`)
|
||||
},
|
||||
|
||||
suspendTenant: (id: string): Promise<ApiResponse<Tenant>> => {
|
||||
return request.post(`/config/tenants/${id}/suspend`)
|
||||
},
|
||||
|
||||
activateTenant: (id: string): Promise<ApiResponse<Tenant>> => {
|
||||
return request.post(`/config/tenants/${id}/activate`)
|
||||
},
|
||||
|
||||
// 用户管理
|
||||
getUserList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<User>>> => {
|
||||
return request.get('/config/users', params)
|
||||
},
|
||||
|
||||
getUserDetail: (id: string): Promise<ApiResponse<User>> => {
|
||||
return request.get(`/config/users/${id}`)
|
||||
},
|
||||
|
||||
createUser: (data: Omit<User, 'id' | 'createdAt' | 'updatedAt' | 'lastLoginAt'>): Promise<ApiResponse<User>> => {
|
||||
return request.post('/config/users', data)
|
||||
},
|
||||
|
||||
updateUser: (id: string, data: Partial<User>): Promise<ApiResponse<User>> => {
|
||||
return request.put(`/config/users/${id}`, data)
|
||||
},
|
||||
|
||||
deleteUser: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/config/users/${id}`)
|
||||
},
|
||||
|
||||
resetPassword: (id: string, newPassword: string): Promise<ApiResponse<void>> => {
|
||||
return request.post(`/config/users/${id}/reset-password`, { newPassword })
|
||||
},
|
||||
|
||||
lockUser: (id: string): Promise<ApiResponse<User>> => {
|
||||
return request.post(`/config/users/${id}/lock`)
|
||||
},
|
||||
|
||||
unlockUser: (id: string): Promise<ApiResponse<User>> => {
|
||||
return request.post(`/config/users/${id}/unlock`)
|
||||
},
|
||||
|
||||
// 系统参数
|
||||
getParameterList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<SystemParameter>>> => {
|
||||
return request.get('/config/parameters', params)
|
||||
},
|
||||
|
||||
getParameterDetail: (id: string): Promise<ApiResponse<SystemParameter>> => {
|
||||
return request.get(`/config/parameters/${id}`)
|
||||
},
|
||||
|
||||
createParameter: (data: Omit<SystemParameter, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<SystemParameter>> => {
|
||||
return request.post('/config/parameters', data)
|
||||
},
|
||||
|
||||
updateParameter: (id: string, data: Partial<SystemParameter>): Promise<ApiResponse<SystemParameter>> => {
|
||||
return request.put(`/config/parameters/${id}`, data)
|
||||
},
|
||||
|
||||
deleteParameter: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/config/parameters/${id}`)
|
||||
},
|
||||
|
||||
getParametersByCategory: (category: string): Promise<ApiResponse<SystemParameter[]>> => {
|
||||
return request.get(`/config/parameters/category/${category}`)
|
||||
},
|
||||
|
||||
// 系统监控
|
||||
getSystemLogs: (params: QueryRequest & { level?: string; category?: string }): Promise<ApiResponse<PaginatedResponse<SystemLog>>> => {
|
||||
return request.get('/config/logs', params)
|
||||
},
|
||||
|
||||
getSystemMetrics: (): Promise<ApiResponse<{
|
||||
totalUsers: number
|
||||
activeUsers: number
|
||||
totalTenants: number
|
||||
activeTenants: number
|
||||
systemUptime: number
|
||||
cpuUsage: number
|
||||
memoryUsage: number
|
||||
diskUsage: number
|
||||
databaseConnections: number
|
||||
}>> => {
|
||||
return request.get('/config/metrics')
|
||||
},
|
||||
|
||||
getSystemHealth: (): Promise<ApiResponse<{
|
||||
status: 'healthy' | 'warning' | 'critical'
|
||||
services: Array<{
|
||||
name: string
|
||||
status: 'up' | 'down'
|
||||
responseTime: number
|
||||
lastCheck: string
|
||||
}>
|
||||
issues: Array<{
|
||||
type: 'error' | 'warning'
|
||||
message: string
|
||||
timestamp: string
|
||||
}>
|
||||
}>> => {
|
||||
return request.get('/config/health')
|
||||
},
|
||||
|
||||
// 消息中心
|
||||
getMessageList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<Message>>> => {
|
||||
return request.get('/config/messages', params)
|
||||
},
|
||||
|
||||
getMessageDetail: (id: string): Promise<ApiResponse<Message>> => {
|
||||
return request.get(`/config/messages/${id}`)
|
||||
},
|
||||
|
||||
createMessage: (data: Omit<Message, 'id' | 'createdAt' | 'readAt' | 'status'>): Promise<ApiResponse<Message>> => {
|
||||
return request.post('/config/messages', data)
|
||||
},
|
||||
|
||||
markMessageAsRead: (id: string): Promise<ApiResponse<Message>> => {
|
||||
return request.put(`/config/messages/${id}/read`)
|
||||
},
|
||||
|
||||
archiveMessage: (id: string): Promise<ApiResponse<Message>> => {
|
||||
return request.put(`/config/messages/${id}/archive`)
|
||||
},
|
||||
|
||||
deleteMessage: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/config/messages/${id}`)
|
||||
},
|
||||
|
||||
getUnreadCount: (): Promise<ApiResponse<{ count: number }>> => {
|
||||
return request.get('/config/messages/unread/count')
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 灌溉控制相关类型
|
||||
export interface IrrigationSystem {
|
||||
id: string
|
||||
name: string
|
||||
type: 'drip' | 'sprinkler' | 'flood' | 'micro_sprinkler'
|
||||
location: string
|
||||
landParcelId: string
|
||||
area: number
|
||||
waterSource: string
|
||||
pumpCapacity: number
|
||||
flowRate: number
|
||||
pressure: number
|
||||
status: 'active' | 'inactive' | 'maintenance'
|
||||
installationDate: string
|
||||
lastMaintenanceDate?: string
|
||||
nextMaintenanceDate?: string
|
||||
description?: string
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface IrrigationZone {
|
||||
id: string
|
||||
systemId: string
|
||||
name: string
|
||||
area: number
|
||||
cropType: string
|
||||
soilType: string
|
||||
waterRequirement: number
|
||||
currentMoisture: number
|
||||
targetMoisture: number
|
||||
status: 'active' | 'inactive' | 'irrigating'
|
||||
sensors: Array<{
|
||||
id: string
|
||||
type: 'moisture' | 'temperature' | 'humidity' | 'ph'
|
||||
location: string
|
||||
currentValue: number
|
||||
unit: string
|
||||
lastReading: string
|
||||
}>
|
||||
valves: Array<{
|
||||
id: string
|
||||
name: string
|
||||
status: 'open' | 'closed'
|
||||
flowRate: number
|
||||
}>
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface IrrigationSchedule {
|
||||
id: string
|
||||
zoneId: string
|
||||
name: string
|
||||
type: 'fixed_time' | 'sensor_based' | 'weather_based'
|
||||
startTime: string
|
||||
duration: number
|
||||
waterAmount: number
|
||||
frequency: 'daily' | 'weekly' | 'custom'
|
||||
daysOfWeek?: number[]
|
||||
startDate: string
|
||||
endDate?: string
|
||||
priority: 'low' | 'medium' | 'high'
|
||||
status: 'active' | 'paused' | 'completed' | 'cancelled'
|
||||
conditions?: {
|
||||
moistureThreshold?: number
|
||||
weatherCondition?: string
|
||||
temperatureRange?: {
|
||||
min: number
|
||||
max: number
|
||||
}
|
||||
}
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface MonitoringData {
|
||||
id: string
|
||||
zoneId: string
|
||||
sensorType: 'moisture' | 'temperature' | 'humidity' | 'ph' | 'flow_rate' | 'pressure'
|
||||
value: number
|
||||
unit: string
|
||||
timestamp: string
|
||||
location?: string
|
||||
}
|
||||
|
||||
export interface ControlCommand {
|
||||
id: string
|
||||
systemId: string
|
||||
zoneId?: string
|
||||
command: 'start_irrigation' | 'stop_irrigation' | 'open_valve' | 'close_valve' | 'adjust_flow_rate'
|
||||
parameters: Record<string, any>
|
||||
status: 'pending' | 'executing' | 'completed' | 'failed'
|
||||
executedAt?: string
|
||||
errorMessage?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export const irrigationApi = {
|
||||
// 系统控制
|
||||
getSystemList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<IrrigationSystem>>> => {
|
||||
return request.get('/irrigation/systems', params)
|
||||
},
|
||||
|
||||
getSystemDetail: (id: string): Promise<ApiResponse<IrrigationSystem>> => {
|
||||
return request.get(`/irrigation/systems/${id}`)
|
||||
},
|
||||
|
||||
createSystem: (data: Omit<IrrigationSystem, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<IrrigationSystem>> => {
|
||||
return request.post('/irrigation/systems', data)
|
||||
},
|
||||
|
||||
updateSystem: (id: string, data: Partial<IrrigationSystem>): Promise<ApiResponse<IrrigationSystem>> => {
|
||||
return request.put(`/irrigation/systems/${id}`, data)
|
||||
},
|
||||
|
||||
deleteSystem: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/irrigation/systems/${id}`)
|
||||
},
|
||||
|
||||
startIrrigation: (systemId: string, zoneId?: string, duration?: number): Promise<ApiResponse<ControlCommand>> => {
|
||||
return request.post(`/irrigation/systems/${systemId}/start`, { zoneId, duration })
|
||||
},
|
||||
|
||||
stopIrrigation: (systemId: string, zoneId?: string): Promise<ApiResponse<ControlCommand>> => {
|
||||
return request.post(`/irrigation/systems/${systemId}/stop`, { zoneId })
|
||||
},
|
||||
|
||||
// 分区管理
|
||||
getZoneList: (systemId: string, params: QueryRequest): Promise<ApiResponse<PaginatedResponse<IrrigationZone>>> => {
|
||||
return request.get(`/irrigation/systems/${systemId}/zones`, params)
|
||||
},
|
||||
|
||||
getZoneDetail: (id: string): Promise<ApiResponse<IrrigationZone>> => {
|
||||
return request.get(`/irrigation/zones/${id}`)
|
||||
},
|
||||
|
||||
createZone: (data: Omit<IrrigationZone, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<IrrigationZone>> => {
|
||||
return request.post('/irrigation/zones', data)
|
||||
},
|
||||
|
||||
updateZone: (id: string, data: Partial<IrrigationZone>): Promise<ApiResponse<IrrigationZone>> => {
|
||||
return request.put(`/irrigation/zones/${id}`, data)
|
||||
},
|
||||
|
||||
deleteZone: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/irrigation/zones/${id}`)
|
||||
},
|
||||
|
||||
// 监控系统
|
||||
getMonitoringData: (zoneId: string, params: QueryRequest & { sensorType?: string }): Promise<ApiResponse<PaginatedResponse<MonitoringData>>> => {
|
||||
return request.get(`/irrigation/zones/${zoneId}/monitoring`, params)
|
||||
},
|
||||
|
||||
getRealTimeData: (zoneId: string): Promise<ApiResponse<MonitoringData[]>> => {
|
||||
return request.get(`/irrigation/zones/${zoneId}/realtime`)
|
||||
},
|
||||
|
||||
// 调度系统
|
||||
getScheduleList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<IrrigationSchedule>>> => {
|
||||
return request.get('/irrigation/schedules', params)
|
||||
},
|
||||
|
||||
getScheduleDetail: (id: string): Promise<ApiResponse<IrrigationSchedule>> => {
|
||||
return request.get(`/irrigation/schedules/${id}`)
|
||||
},
|
||||
|
||||
createSchedule: (data: Omit<IrrigationSchedule, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<IrrigationSchedule>> => {
|
||||
return request.post('/irrigation/schedules', data)
|
||||
},
|
||||
|
||||
updateSchedule: (id: string, data: Partial<IrrigationSchedule>): Promise<ApiResponse<IrrigationSchedule>> => {
|
||||
return request.put(`/irrigation/schedules/${id}`, data)
|
||||
},
|
||||
|
||||
deleteSchedule: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/irrigation/schedules/${id}`)
|
||||
},
|
||||
|
||||
pauseSchedule: (id: string): Promise<ApiResponse<IrrigationSchedule>> => {
|
||||
return request.post(`/irrigation/schedules/${id}/pause`)
|
||||
},
|
||||
|
||||
resumeSchedule: (id: string): Promise<ApiResponse<IrrigationSchedule>> => {
|
||||
return request.post(`/irrigation/schedules/${id}/resume`)
|
||||
}
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 地块相关类型
|
||||
export interface LandParcel {
|
||||
id: string
|
||||
name: string
|
||||
code: string
|
||||
area: number
|
||||
areaUnit: 'mu' | 'hectare' | 'acre'
|
||||
location: {
|
||||
latitude: number
|
||||
longitude: number
|
||||
address: string
|
||||
}
|
||||
boundaries: Array<{
|
||||
latitude: number
|
||||
longitude: number
|
||||
}>
|
||||
soilType: string
|
||||
landUse: string
|
||||
ownershipType: 'owned' | 'rented' | 'shared'
|
||||
tenantId: string
|
||||
description?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface LandClassification {
|
||||
id: string
|
||||
landParcelId: string
|
||||
category: string
|
||||
subcategory: string
|
||||
tags: string[]
|
||||
attributes: Record<string, any>
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface MapLayer {
|
||||
id: string
|
||||
name: string
|
||||
type: 'base' | 'overlay' | 'analysis'
|
||||
url: string
|
||||
opacity: number
|
||||
visible: boolean
|
||||
attribution?: string
|
||||
}
|
||||
|
||||
export interface SpatialAnalysis {
|
||||
id: string
|
||||
name: string
|
||||
type: 'buffer' | 'overlay' | 'proximity' | 'suitability'
|
||||
parameters: Record<string, any>
|
||||
result: {
|
||||
area: number
|
||||
geometry: any
|
||||
statistics: Record<string, number>
|
||||
}
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export const landApi = {
|
||||
// 地块档案管理
|
||||
getLandParcelList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<LandParcel>>> => {
|
||||
return request.get('/land/parcels', params)
|
||||
},
|
||||
|
||||
getLandParcelDetail: (id: string): Promise<ApiResponse<LandParcel>> => {
|
||||
return request.get(`/land/parcels/${id}`)
|
||||
},
|
||||
|
||||
createLandParcel: (data: Omit<LandParcel, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<LandParcel>> => {
|
||||
return request.post('/land/parcels', data)
|
||||
},
|
||||
|
||||
updateLandParcel: (id: string, data: Partial<LandParcel>): Promise<ApiResponse<LandParcel>> => {
|
||||
return request.put(`/land/parcels/${id}`, data)
|
||||
},
|
||||
|
||||
deleteLandParcel: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/land/parcels/${id}`)
|
||||
},
|
||||
|
||||
// 地块分类管理
|
||||
getClassificationList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<LandClassification>>> => {
|
||||
return request.get('/land/classifications', params)
|
||||
},
|
||||
|
||||
createClassification: (data: Omit<LandClassification, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<LandClassification>> => {
|
||||
return request.post('/land/classifications', data)
|
||||
},
|
||||
|
||||
updateClassification: (id: string, data: Partial<LandClassification>): Promise<ApiResponse<LandClassification>> => {
|
||||
return request.put(`/land/classifications/${id}`, data)
|
||||
},
|
||||
|
||||
deleteClassification: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/land/classifications/${id}`)
|
||||
},
|
||||
|
||||
// 地图管理
|
||||
getMapLayers: (): Promise<ApiResponse<MapLayer[]>> => {
|
||||
return request.get('/land/maps/layers')
|
||||
},
|
||||
|
||||
createMapLayer: (data: Omit<MapLayer, 'id'>): Promise<ApiResponse<MapLayer>> => {
|
||||
return request.post('/land/maps/layers', data)
|
||||
},
|
||||
|
||||
updateMapLayer: (id: string, data: Partial<MapLayer>): Promise<ApiResponse<MapLayer>> => {
|
||||
return request.put(`/land/maps/layers/${id}`, data)
|
||||
},
|
||||
|
||||
deleteMapLayer: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/land/maps/layers/${id}`)
|
||||
},
|
||||
|
||||
// 空间分析
|
||||
performSpatialAnalysis: (data: Omit<SpatialAnalysis, 'id' | 'createdAt' | 'result'>): Promise<ApiResponse<SpatialAnalysis>> => {
|
||||
return request.post('/land/analysis/spatial', data)
|
||||
},
|
||||
|
||||
getAnalysisHistory: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<SpatialAnalysis>>> => {
|
||||
return request.get('/land/analysis/history', params)
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 农机相关类型
|
||||
export interface Machinery {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
model: string
|
||||
status: 'active' | 'inactive' | 'maintenance' | 'repair'
|
||||
location: {
|
||||
latitude: number
|
||||
longitude: number
|
||||
address: string
|
||||
}
|
||||
driverId?: string
|
||||
lastMaintenanceDate?: string
|
||||
nextMaintenanceDate?: string
|
||||
purchaseDate: string
|
||||
price: number
|
||||
description?: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface Driver {
|
||||
id: string
|
||||
name: string
|
||||
phone: string
|
||||
licenseNumber: string
|
||||
licenseType: string
|
||||
experience: number
|
||||
status: 'active' | 'inactive'
|
||||
machineryId?: string
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface MonitoringData {
|
||||
id: string
|
||||
machineryId: string
|
||||
location: {
|
||||
latitude: number
|
||||
longitude: number
|
||||
}
|
||||
speed: number
|
||||
fuelLevel: number
|
||||
engineHours: number
|
||||
workingStatus: 'working' | 'idle' | 'stopped'
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export const machineryApi = {
|
||||
// 农机管理
|
||||
getMachineryList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<Machinery>>> => {
|
||||
return request.get('/machinery', params)
|
||||
},
|
||||
|
||||
getMachineryDetail: (id: string): Promise<ApiResponse<Machinery>> => {
|
||||
return request.get(`/machinery/${id}`)
|
||||
},
|
||||
|
||||
createMachinery: (data: Omit<Machinery, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<Machinery>> => {
|
||||
return request.post('/machinery', data)
|
||||
},
|
||||
|
||||
updateMachinery: (id: string, data: Partial<Machinery>): Promise<ApiResponse<Machinery>> => {
|
||||
return request.put(`/machinery/${id}`, data)
|
||||
},
|
||||
|
||||
deleteMachinery: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/machinery/${id}`)
|
||||
},
|
||||
|
||||
// 驾驶员管理
|
||||
getDriverList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<Driver>>> => {
|
||||
return request.get('/machinery/drivers', params)
|
||||
},
|
||||
|
||||
getDriverDetail: (id: string): Promise<ApiResponse<Driver>> => {
|
||||
return request.get(`/machinery/drivers/${id}`)
|
||||
},
|
||||
|
||||
createDriver: (data: Omit<Driver, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<Driver>> => {
|
||||
return request.post('/machinery/drivers', data)
|
||||
},
|
||||
|
||||
updateDriver: (id: string, data: Partial<Driver>): Promise<ApiResponse<Driver>> => {
|
||||
return request.put(`/machinery/drivers/${id}`, data)
|
||||
},
|
||||
|
||||
deleteDriver: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/machinery/drivers/${id}`)
|
||||
},
|
||||
|
||||
// 实时监控
|
||||
getRealTimeData: (machineryId: string): Promise<ApiResponse<MonitoringData>> => {
|
||||
return request.get(`/machinery/monitoring/${machineryId}`)
|
||||
},
|
||||
|
||||
getMonitoringHistory: (machineryId: string, params: QueryRequest): Promise<ApiResponse<PaginatedResponse<MonitoringData>>> => {
|
||||
return request.get(`/machinery/monitoring/${machineryId}/history`, params)
|
||||
}
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
import { request } from '../request'
|
||||
import { ApiResponse, PaginatedResponse, QueryRequest } from '../types'
|
||||
|
||||
// 农事操作相关类型
|
||||
export interface FarmingTask {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
type: 'planting' | 'harvesting' | 'fertilizing' | 'irrigating' | 'pest_control' | 'other'
|
||||
status: 'pending' | 'in_progress' | 'completed' | 'cancelled'
|
||||
priority: 'low' | 'medium' | 'high' | 'urgent'
|
||||
assignedTo?: string
|
||||
landParcelId: string
|
||||
machineryId?: string
|
||||
scheduledStartDate: string
|
||||
scheduledEndDate: string
|
||||
actualStartDate?: string
|
||||
actualEndDate?: string
|
||||
estimatedCost?: number
|
||||
actualCost?: number
|
||||
notes?: string
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export interface TaskTemplate {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
taskType: string
|
||||
defaultDuration: number
|
||||
requiredResources: string[]
|
||||
checklistItems: string[]
|
||||
costEstimate: number
|
||||
tenantId: string
|
||||
}
|
||||
|
||||
export interface ResourceAllocation {
|
||||
id: string
|
||||
taskId: string
|
||||
resourceType: 'machinery' | 'labor' | 'material' | 'tool'
|
||||
resourceId: string
|
||||
quantity: number
|
||||
allocatedDate: string
|
||||
returnDate?: string
|
||||
status: 'allocated' | 'in_use' | 'returned'
|
||||
}
|
||||
|
||||
export interface Workflow {
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
stages: Array<{
|
||||
id: string
|
||||
name: string
|
||||
description: string
|
||||
duration: number
|
||||
dependencies: string[]
|
||||
resources: string[]
|
||||
}>
|
||||
landParcelId: string
|
||||
status: 'draft' | 'active' | 'completed' | 'paused'
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
tenantId: string
|
||||
createdAt: string
|
||||
updatedAt: string
|
||||
}
|
||||
|
||||
export const operationApi = {
|
||||
// 任务管理
|
||||
getTaskList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<FarmingTask>>> => {
|
||||
return request.get('/operation/tasks', params)
|
||||
},
|
||||
|
||||
getTaskDetail: (id: string): Promise<ApiResponse<FarmingTask>> => {
|
||||
return request.get(`/operation/tasks/${id}`)
|
||||
},
|
||||
|
||||
createTask: (data: Omit<FarmingTask, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<FarmingTask>> => {
|
||||
return request.post('/operation/tasks', data)
|
||||
},
|
||||
|
||||
updateTask: (id: string, data: Partial<FarmingTask>): Promise<ApiResponse<FarmingTask>> => {
|
||||
return request.put(`/operation/tasks/${id}`, data)
|
||||
},
|
||||
|
||||
deleteTask: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/operation/tasks/${id}`)
|
||||
},
|
||||
|
||||
updateTaskStatus: (id: string, status: FarmingTask['status']): Promise<ApiResponse<FarmingTask>> => {
|
||||
return request.put(`/operation/tasks/${id}/status`, { status })
|
||||
},
|
||||
|
||||
// 任务模板
|
||||
getTaskTemplateList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<TaskTemplate>>> => {
|
||||
return request.get('/operation/templates', params)
|
||||
},
|
||||
|
||||
createTaskTemplate: (data: Omit<TaskTemplate, 'id'>): Promise<ApiResponse<TaskTemplate>> => {
|
||||
return request.post('/operation/templates', data)
|
||||
},
|
||||
|
||||
updateTaskTemplate: (id: string, data: Partial<TaskTemplate>): Promise<ApiResponse<TaskTemplate>> => {
|
||||
return request.put(`/operation/templates/${id}`, data)
|
||||
},
|
||||
|
||||
deleteTaskTemplate: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/operation/templates/${id}`)
|
||||
},
|
||||
|
||||
// 资源分配
|
||||
getResourceAllocations: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<ResourceAllocation>>> => {
|
||||
return request.get('/operation/resources', params)
|
||||
},
|
||||
|
||||
allocateResource: (data: Omit<ResourceAllocation, 'id' | 'allocatedDate'>): Promise<ApiResponse<ResourceAllocation>> => {
|
||||
return request.post('/operation/resources/allocate', data)
|
||||
},
|
||||
|
||||
returnResource: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.put(`/operation/resources/${id}/return`)
|
||||
},
|
||||
|
||||
// 工作流管理
|
||||
getWorkflowList: (params: QueryRequest): Promise<ApiResponse<PaginatedResponse<Workflow>>> => {
|
||||
return request.get('/operation/workflows', params)
|
||||
},
|
||||
|
||||
getWorkflowDetail: (id: string): Promise<ApiResponse<Workflow>> => {
|
||||
return request.get(`/operation/workflows/${id}`)
|
||||
},
|
||||
|
||||
createWorkflow: (data: Omit<Workflow, 'id' | 'createdAt' | 'updatedAt'>): Promise<ApiResponse<Workflow>> => {
|
||||
return request.post('/operation/workflows', data)
|
||||
},
|
||||
|
||||
updateWorkflow: (id: string, data: Partial<Workflow>): Promise<ApiResponse<Workflow>> => {
|
||||
return request.put(`/operation/workflows/${id}`, data)
|
||||
},
|
||||
|
||||
deleteWorkflow: (id: string): Promise<ApiResponse<void>> => {
|
||||
return request.delete(`/operation/workflows/${id}`)
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
||||
import { config } from '@/config/features'
|
||||
import { ApiResponse, ApiError } from './types'
|
||||
|
||||
/**
|
||||
* 请求管理器类
|
||||
* 封装了基于Axios的HTTP请求操作,包括请求和响应拦截器
|
||||
*/
|
||||
/**
|
||||
private instance: AxiosInstance // Axios实例,用于发送HTTP请求
|
||||
* 使用Axios库进行HTTP请求,并添加了请求和响应拦截器
|
||||
*/
|
||||
class RequestManager {
|
||||
private instance: AxiosInstance
|
||||
|
||||
constructor() {
|
||||
this.instance = axios.create({
|
||||
baseURL: config.apiUrl,
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
|
||||
this.setupInterceptors()
|
||||
}
|
||||
|
||||
private setupInterceptors() {
|
||||
// 请求拦截器
|
||||
this.instance.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('token')
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
this.instance.interceptors.response.use(
|
||||
(response: AxiosResponse<ApiResponse>) => {
|
||||
const { data } = response
|
||||
if (data.success) {
|
||||
return response
|
||||
} else {
|
||||
return Promise.reject(new Error(data.message))
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
localStorage.removeItem('token')
|
||||
window.location.href = '/login'
|
||||
}
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
public get<T = any>(url: string, params?: any): Promise<ApiResponse<T>> {
|
||||
return this.instance.get(url, { params }).then(res => res.data)
|
||||
}
|
||||
|
||||
public post<T = any>(url: string, data?: any): Promise<ApiResponse<T>> {
|
||||
return this.instance.post(url, data).then(res => res.data)
|
||||
}
|
||||
|
||||
public put<T = any>(url: string, data?: any): Promise<ApiResponse<T>> {
|
||||
return this.instance.put(url, data).then(res => res.data)
|
||||
}
|
||||
|
||||
public delete<T = any>(url: string): Promise<ApiResponse<T>> {
|
||||
return this.instance.delete(url).then(res => res.data)
|
||||
}
|
||||
}
|
||||
|
||||
export const request = new RequestManager()
|
||||
@@ -1,51 +0,0 @@
|
||||
// API 响应类型定义
|
||||
export interface ApiResponse<T = any> {
|
||||
code: number
|
||||
message: string
|
||||
data: T
|
||||
success: boolean
|
||||
}
|
||||
|
||||
// 分页请求参数
|
||||
export interface PaginationParams {
|
||||
page: number
|
||||
pageSize: number
|
||||
total?: number
|
||||
}
|
||||
|
||||
// 分页响应数据
|
||||
export interface PaginatedResponse<T> {
|
||||
items: T[]
|
||||
total: number
|
||||
page: number
|
||||
pageSize: number
|
||||
totalPages: number
|
||||
}
|
||||
|
||||
// 错误响应
|
||||
export interface ApiError {
|
||||
code: number
|
||||
message: string
|
||||
details?: any
|
||||
}
|
||||
|
||||
// 通用CRUD操作类型
|
||||
export interface CreateRequest<T> {
|
||||
data: Omit<T, 'id' | 'createdAt' | 'updatedAt'>
|
||||
}
|
||||
|
||||
export interface UpdateRequest<T> {
|
||||
id: string | number
|
||||
data: Partial<T>
|
||||
}
|
||||
|
||||
export interface DeleteRequest {
|
||||
id: string | number
|
||||
}
|
||||
|
||||
export interface QueryRequest extends PaginationParams {
|
||||
keyword?: string
|
||||
filters?: Record<string, any>
|
||||
sortBy?: string
|
||||
sortOrder?: 'asc' | 'desc'
|
||||
}
|
||||
@@ -14,5 +14,5 @@ import type { ClientOptions as ClientOptions2 } from './types.gen';
|
||||
export type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
|
||||
|
||||
export const client = createClient(createConfig<ClientOptions2>({
|
||||
baseUrl: 'http://localhost:8080'
|
||||
baseUrl: 'http://26.26.26.1:8080'
|
||||
}));
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { createBrowserRouter, RouterProvider, Navigate } from 'react-router-dom'
|
||||
import { Layout } from '@/components/layout/Layout'
|
||||
import { Login } from '@/pages/auth/Login'
|
||||
import { Dashboard } from '@/pages/dashboard/Dashboard'
|
||||
|
||||
// 模块路由
|
||||
import { machineryRoutes } from './modules/machinery'
|
||||
import { landRoutes } from './modules/land'
|
||||
import { operationRoutes } from './modules/operation'
|
||||
import { assetRoutes } from './modules/asset'
|
||||
import { aiModelRoutes } from './modules/ai-model'
|
||||
import { irrigationRoutes } from './modules/irrigation'
|
||||
import { configRoutes } from './modules/config'
|
||||
|
||||
// 错误页面
|
||||
import { NotFound } from '@/pages/error/NotFound'
|
||||
import { ServerError } from '@/pages/error/ServerError'
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: '/login',
|
||||
element: <Login />,
|
||||
errorElement: <ServerError />
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
element: <Layout />,
|
||||
errorElement: <ServerError />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Navigate to="/dashboard" replace />
|
||||
},
|
||||
{
|
||||
path: 'dashboard',
|
||||
element: <Dashboard />
|
||||
},
|
||||
...machineryRoutes,
|
||||
...landRoutes,
|
||||
...operationRoutes,
|
||||
...assetRoutes,
|
||||
...aiModelRoutes,
|
||||
...irrigationRoutes,
|
||||
...configRoutes,
|
||||
{
|
||||
path: '*',
|
||||
element: <NotFound />
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
|
||||
export const AppRouter = () => {
|
||||
return <RouterProvider router={router} />
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { AIModelEntry } from '@/pages/ai-model/AIModelEntry'
|
||||
import { ModelTraining } from '@/pages/ai-model/ModelTraining'
|
||||
import { PredictionAnalysis } from '@/pages/ai-model/PredictionAnalysis'
|
||||
import { RecommendationSystem } from '@/pages/ai-model/RecommendationSystem'
|
||||
|
||||
export const aiModelRoutes = [
|
||||
{
|
||||
path: 'ai-model',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <AIModelEntry />
|
||||
},
|
||||
{
|
||||
path: 'model-training',
|
||||
element: <ModelTraining />
|
||||
},
|
||||
{
|
||||
path: 'prediction-analysis',
|
||||
element: <PredictionAnalysis />
|
||||
},
|
||||
{
|
||||
path: 'recommendation-system',
|
||||
element: <RecommendationSystem />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,28 +0,0 @@
|
||||
import { AssetEntry } from '@/pages/asset/AssetEntry'
|
||||
import { InventoryManagement } from '@/pages/asset/InventoryManagement'
|
||||
import { AssetDepreciation } from '@/pages/asset/AssetDepreciation'
|
||||
import { MaintenanceRecords } from '@/pages/asset/MaintenanceRecords'
|
||||
|
||||
export const assetRoutes = [
|
||||
{
|
||||
path: 'asset',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <AssetEntry />
|
||||
},
|
||||
{
|
||||
path: 'inventory-management',
|
||||
element: <InventoryManagement />
|
||||
},
|
||||
{
|
||||
path: 'asset-depreciation',
|
||||
element: <AssetDepreciation />
|
||||
},
|
||||
{
|
||||
path: 'maintenance-records',
|
||||
element: <MaintenanceRecords />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,38 +0,0 @@
|
||||
import { CentralConfigEntry } from '@/pages/config/CentralConfigEntry'
|
||||
import { TenantManagement } from '@/pages/config/TenantManagement'
|
||||
import { UserManagement } from '@/pages/config/UserManagement'
|
||||
import { SystemParameters } from '@/pages/config/SystemParameters'
|
||||
import { SystemMonitoring } from '@/pages/config/SystemMonitoring'
|
||||
import { MessageCenter } from '@/pages/config/MessageCenter'
|
||||
|
||||
export const configRoutes = [
|
||||
{
|
||||
path: 'config',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <CentralConfigEntry />
|
||||
},
|
||||
{
|
||||
path: 'tenant-management',
|
||||
element: <TenantManagement />
|
||||
},
|
||||
{
|
||||
path: 'user-management',
|
||||
element: <UserManagement />
|
||||
},
|
||||
{
|
||||
path: 'system-parameters',
|
||||
element: <SystemParameters />
|
||||
},
|
||||
{
|
||||
path: 'system-monitoring',
|
||||
element: <SystemMonitoring />
|
||||
},
|
||||
{
|
||||
path: 'message-center',
|
||||
element: <MessageCenter />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,28 +0,0 @@
|
||||
import { IrrigationEntry } from '@/pages/irrigation/IrrigationEntry'
|
||||
import { SystemControl } from '@/pages/irrigation/SystemControl'
|
||||
import { MonitoringSystem } from '@/pages/irrigation/MonitoringSystem'
|
||||
import { SchedulingSystem } from '@/pages/irrigation/SchedulingSystem'
|
||||
|
||||
export const irrigationRoutes = [
|
||||
{
|
||||
path: 'irrigation',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <IrrigationEntry />
|
||||
},
|
||||
{
|
||||
path: 'system-control',
|
||||
element: <SystemControl />
|
||||
},
|
||||
{
|
||||
path: 'monitoring-system',
|
||||
element: <MonitoringSystem />
|
||||
},
|
||||
{
|
||||
path: 'scheduling-system',
|
||||
element: <SchedulingSystem />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,48 +0,0 @@
|
||||
import { LandEntry } from '@/pages/land/LandEntry'
|
||||
import { LandArchiveManagement } from '@/pages/land/LandArchiveManagement'
|
||||
import { LandClassification } from '@/pages/land/LandClassification'
|
||||
import { MapManagement } from '@/pages/land/MapManagement'
|
||||
import { SpatialAnalysis } from '@/pages/land/SpatialAnalysis'
|
||||
import { SuitabilityEvaluation } from '@/pages/land/SuitabilityEvaluation'
|
||||
import { ComparativeAnalysis } from '@/pages/land/ComparativeAnalysis'
|
||||
import { RiskWarning } from '@/pages/land/RiskWarning'
|
||||
|
||||
export const landRoutes = [
|
||||
{
|
||||
path: 'land',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <LandEntry />
|
||||
},
|
||||
{
|
||||
path: 'archive-management',
|
||||
element: <LandArchiveManagement />
|
||||
},
|
||||
{
|
||||
path: 'classification',
|
||||
element: <LandClassification />
|
||||
},
|
||||
{
|
||||
path: 'map-management',
|
||||
element: <MapManagement />
|
||||
},
|
||||
{
|
||||
path: 'spatial-analysis',
|
||||
element: <SpatialAnalysis />
|
||||
},
|
||||
{
|
||||
path: 'suitability-evaluation',
|
||||
element: <SuitabilityEvaluation />
|
||||
},
|
||||
{
|
||||
path: 'comparative-analysis',
|
||||
element: <ComparativeAnalysis />
|
||||
},
|
||||
{
|
||||
path: 'risk-warning',
|
||||
element: <RiskWarning />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,43 +0,0 @@
|
||||
import { MachineryEntry } from '@/pages/machinery/MachineryEntry'
|
||||
import { MachineryArchive } from '@/pages/machinery/MachineryArchive'
|
||||
import { DriverArchive } from '@/pages/machinery/DriverArchive'
|
||||
import { RealTimeMonitoring } from '@/pages/machinery/RealTimeMonitoring'
|
||||
import { FaultDiagnosis } from '@/pages/machinery/FaultDiagnosis'
|
||||
import { PrecisionFarming } from '@/pages/machinery/PrecisionFarming'
|
||||
import { SchedulingManagement } from '@/pages/machinery/SchedulingManagement'
|
||||
|
||||
export const machineryRoutes = [
|
||||
{
|
||||
path: 'machinery',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <MachineryEntry />
|
||||
},
|
||||
{
|
||||
path: 'archive',
|
||||
element: <MachineryArchive />
|
||||
},
|
||||
{
|
||||
path: 'driver-archive',
|
||||
element: <DriverArchive />
|
||||
},
|
||||
{
|
||||
path: 'real-time-monitoring',
|
||||
element: <RealTimeMonitoring />
|
||||
},
|
||||
{
|
||||
path: 'fault-diagnosis',
|
||||
element: <FaultDiagnosis />
|
||||
},
|
||||
{
|
||||
path: 'precision-farming',
|
||||
element: <PrecisionFarming />
|
||||
},
|
||||
{
|
||||
path: 'scheduling-management',
|
||||
element: <SchedulingManagement />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,38 +0,0 @@
|
||||
import { FarmingEntry } from '@/pages/operation/FarmingEntry'
|
||||
import { TaskPlanning } from '@/pages/operation/TaskPlanning'
|
||||
import { TaskTracking } from '@/pages/operation/TaskTracking'
|
||||
import { TaskAnalysis } from '@/pages/operation/TaskAnalysis'
|
||||
import { ResourceManagement } from '@/pages/operation/ResourceManagement'
|
||||
import { WorkflowManagement } from '@/pages/operation/WorkflowManagement'
|
||||
|
||||
export const operationRoutes = [
|
||||
{
|
||||
path: 'operation',
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <FarmingEntry />
|
||||
},
|
||||
{
|
||||
path: 'task-planning',
|
||||
element: <TaskPlanning />
|
||||
},
|
||||
{
|
||||
path: 'task-tracking',
|
||||
element: <TaskTracking />
|
||||
},
|
||||
{
|
||||
path: 'task-analysis',
|
||||
element: <TaskAnalysis />
|
||||
},
|
||||
{
|
||||
path: 'resource-management',
|
||||
element: <ResourceManagement />
|
||||
},
|
||||
{
|
||||
path: 'workflow-management',
|
||||
element: <WorkflowManagement />
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,267 +0,0 @@
|
||||
import { MessageLog } from '@/types/message';
|
||||
|
||||
export interface MessageLogFilters {
|
||||
searchKeyword?: string;
|
||||
type?: string;
|
||||
status?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export interface MessageLogResponse {
|
||||
data: MessageLog[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息日志API服务
|
||||
* 提供消息日志相关的接口调用方法
|
||||
*/
|
||||
class MessageLogApiService {
|
||||
/**
|
||||
* 获取消息日志列表
|
||||
* @param filters 过滤条件
|
||||
* @returns 消息日志列表数据
|
||||
*/
|
||||
async getMessageLogs(filters: MessageLogFilters = {}): Promise<MessageLogResponse> {
|
||||
// TODO: 替换为实际的API调用
|
||||
// const response = await fetch('/api/message-logs', {
|
||||
// method: 'GET',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify(filters),
|
||||
// });
|
||||
// return response.json();
|
||||
|
||||
// 模拟API调用延迟
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
|
||||
// 从localStorage获取数据作为模拟数据
|
||||
const data = localStorage.getItem('smart_agriculture_message_logs');
|
||||
let logs: MessageLog[] = [];
|
||||
|
||||
if (data) {
|
||||
logs = JSON.parse(data);
|
||||
} else {
|
||||
// 初始化模拟数据
|
||||
logs = this.generateMockData();
|
||||
localStorage.setItem('smart_agriculture_message_logs', JSON.stringify(logs));
|
||||
}
|
||||
|
||||
// 应用过滤条件
|
||||
let filteredLogs = logs.filter(log => {
|
||||
const matchKeyword = !filters.searchKeyword ||
|
||||
(log.recipientName && log.recipientName.includes(filters.searchKeyword)) ||
|
||||
log.recipient.includes(filters.searchKeyword) ||
|
||||
log.content.includes(filters.searchKeyword);
|
||||
const matchType = !filters.type || filters.type === 'all' || log.type === filters.type;
|
||||
const matchStatus = !filters.status || filters.status === 'all' || log.status === filters.status;
|
||||
return matchKeyword && matchType && matchStatus;
|
||||
});
|
||||
|
||||
// 排序(按发送时间倒序)
|
||||
filteredLogs.sort((a, b) => new Date(b.sentTime).getTime() - new Date(a.sentTime).getTime());
|
||||
|
||||
// 分页
|
||||
const page = filters.page || 1;
|
||||
const pageSize = filters.pageSize || 20;
|
||||
const startIndex = (page - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedLogs = filteredLogs.slice(startIndex, endIndex);
|
||||
|
||||
return {
|
||||
data: paginatedLogs,
|
||||
total: filteredLogs.length,
|
||||
page,
|
||||
pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出消息日志
|
||||
* @param filters 过滤条件
|
||||
* @returns 导出文件
|
||||
*/
|
||||
async exportMessageLogs(filters: MessageLogFilters = {}): Promise<void> {
|
||||
const response = await this.getMessageLogs(filters);
|
||||
const dataStr = JSON.stringify(response.data, null, 2);
|
||||
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
||||
const url = URL.createObjectURL(dataBlob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = `message_logs_${new Date().getTime()}.json`;
|
||||
link.click();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量标记消息为已读
|
||||
* @param ids 消息ID列表
|
||||
*/
|
||||
async markMessagesAsRead(ids: string[]): Promise<void> {
|
||||
// TODO: 替换为实际的API调用
|
||||
// await fetch('/api/message-logs/mark-read', {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify({ ids }),
|
||||
// });
|
||||
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
|
||||
// 更新本地数据
|
||||
const data = localStorage.getItem('smart_agriculture_message_logs');
|
||||
if (data) {
|
||||
const logs: MessageLog[] = JSON.parse(data);
|
||||
const updatedLogs = logs.map(log =>
|
||||
ids.includes(log.id)
|
||||
? { ...log, status: 'read' as const, readTime: new Date().toISOString() }
|
||||
: log
|
||||
);
|
||||
localStorage.setItem('smart_agriculture_message_logs', JSON.stringify(updatedLogs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除消息日志
|
||||
* @param ids 消息ID列表
|
||||
*/
|
||||
async deleteMessageLogs(ids: string[]): Promise<void> {
|
||||
// TODO: 替换为实际的API调用
|
||||
// await fetch('/api/message-logs', {
|
||||
// method: 'DELETE',
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// },
|
||||
// body: JSON.stringify({ ids }),
|
||||
// });
|
||||
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
|
||||
// 更新本地数据
|
||||
const data = localStorage.getItem('smart_agriculture_message_logs');
|
||||
if (data) {
|
||||
const logs: MessageLog[] = JSON.parse(data);
|
||||
const updatedLogs = logs.filter(log => !ids.includes(log.id));
|
||||
localStorage.setItem('smart_agriculture_message_logs', JSON.stringify(updatedLogs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成模拟数据
|
||||
* @returns 模拟消息日志数据
|
||||
*/
|
||||
private generateMockData(): MessageLog[] {
|
||||
const mockLogs: MessageLog[] = [
|
||||
{
|
||||
id: 'msg-1',
|
||||
templateId: 'tpl-1',
|
||||
templateName: '任务分配通知',
|
||||
type: 'internal',
|
||||
recipient: 'user-2',
|
||||
recipientName: '张三',
|
||||
subject: '新任务分配',
|
||||
content: '您好,张三!您有新的作业任务:小麦播种作业,计划执行时间:2024-10-15 08:00。请及时查看并准备。',
|
||||
status: 'sent',
|
||||
sentTime: '2024-10-14T09:30:00',
|
||||
readTime: '2024-10-14T10:15:00',
|
||||
retryCount: 0,
|
||||
variables: {
|
||||
username: '张三',
|
||||
taskName: '小麦播种作业',
|
||||
executeTime: '2024-10-15 08:00',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'msg-2',
|
||||
templateId: 'tpl-2',
|
||||
templateName: '设备预警通知',
|
||||
type: 'sms',
|
||||
recipient: '13800138000',
|
||||
recipientName: '李四',
|
||||
content: '【智慧农业】设备预警:约翰迪尔拖拉机检测到异常,发动机温度过高,请及时处理。',
|
||||
status: 'sent',
|
||||
sentTime: '2024-10-14T11:20:00',
|
||||
retryCount: 0,
|
||||
},
|
||||
{
|
||||
id: 'msg-3',
|
||||
templateId: 'tpl-3',
|
||||
templateName: '保养提醒',
|
||||
type: 'email',
|
||||
recipient: 'wangwu@example.com',
|
||||
recipientName: '王五',
|
||||
subject: '设备保养提醒',
|
||||
content: '尊敬的用户:\n\n您的设备约翰迪尔拖拉机(编号:JD-001)已使用500小时,建议进行保养维护...',
|
||||
status: 'sent',
|
||||
sentTime: '2024-10-14T14:00:00',
|
||||
retryCount: 0,
|
||||
},
|
||||
{
|
||||
id: 'msg-4',
|
||||
templateId: 'tpl-4',
|
||||
templateName: '任务完成通知',
|
||||
type: 'push',
|
||||
recipient: 'user-2',
|
||||
recipientName: '张三',
|
||||
subject: '任务完成',
|
||||
content: '作业任务小麦播种作业已完成,作业面积:50亩,耗时:3小时。',
|
||||
status: 'read',
|
||||
sentTime: '2024-10-14T15:30:00',
|
||||
readTime: '2024-10-14T15:32:00',
|
||||
retryCount: 0,
|
||||
},
|
||||
{
|
||||
id: 'msg-5',
|
||||
templateId: 'tpl-5',
|
||||
templateName: '验证码通知',
|
||||
type: 'sms',
|
||||
recipient: '13900139000',
|
||||
recipientName: '赵六',
|
||||
subject: '验证码',
|
||||
content: '【智慧农业】验证码:123456,有效期5分钟。',
|
||||
status: 'failed',
|
||||
sentTime: '2024-10-14T16:00:00',
|
||||
failReason: '手机号码格式错误',
|
||||
retryCount: 2,
|
||||
},
|
||||
];
|
||||
|
||||
// 添加更多模拟数据
|
||||
for (let i = 6; i <= 50; i++) {
|
||||
const types: MessageLog['type'][] = ['sms', 'email', 'internal', 'push'];
|
||||
const statuses: MessageLog['status'][] = ['sent', 'read', 'failed', 'pending'];
|
||||
const type = types[Math.floor(Math.random() * types.length)];
|
||||
const status = statuses[Math.floor(Math.random() * statuses.length)];
|
||||
|
||||
mockLogs.push({
|
||||
id: `msg-${i}`,
|
||||
templateId: `tpl-${Math.floor(Math.random() * 4) + 1}`,
|
||||
templateName: `通知模板${Math.floor(Math.random() * 4) + 1}`,
|
||||
type,
|
||||
recipient: type === 'sms' ? `138${String(Math.floor(Math.random() * 100000000)).padStart(8, '0')}` :
|
||||
type === 'email' ? `user${i}@example.com` : `user-${i}`,
|
||||
recipientName: `用户${i}`,
|
||||
subject: status === 'read' || status === 'sent' ? `通知主题${i}` : undefined,
|
||||
content: `这是第${i}条测试消息内容,用于展示消息日志功能。`,
|
||||
status,
|
||||
sentTime: new Date(Date.now() - Math.random() * 7 * 24 * 60 * 60 * 1000).toISOString(),
|
||||
readTime: status === 'read' ? new Date(Date.now() - Math.random() * 24 * 60 * 60 * 1000).toISOString() : undefined,
|
||||
failReason: status === 'failed' ? '网络连接失败' : undefined,
|
||||
retryCount: status === 'failed' ? Math.floor(Math.random() * 3) : 0,
|
||||
variables: type === 'internal' ? { userId: `user-${i}` } : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
return mockLogs;
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例
|
||||
export const messageLogApi = new MessageLogApiService();
|
||||
Reference in New Issue
Block a user