生产管理系统 前端不需要的文件删除

This commit is contained in:
2025-10-28 09:40:08 +08:00
parent 42a4a9f566
commit 59a9743992
23 changed files with 343 additions and 2107 deletions

View File

@@ -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 APIWebSocket 需要单独实现。
**Q: 如何添加 Mock 数据?**
A: 可以创建另一个客户端实例,返回模拟数据而不是真实请求。

342
crop-x/scripts/openapi.json Normal file
View 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": "测试环境服务器"
}
]
}

View File

@@ -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'

View File

@@ -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 })
}
}

View File

@@ -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 })
}
}

View File

@@ -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)
}
}

View File

@@ -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')
}
}

View File

@@ -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`)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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}`)
}
}

View File

@@ -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()

View File

@@ -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'
}

View File

@@ -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 type CreateClientConfig<T extends ClientOptions = ClientOptions2> = (override?: Config<ClientOptions & T>) => Config<Required<ClientOptions> & T>;
export const client = createClient(createConfig<ClientOptions2>({ export const client = createClient(createConfig<ClientOptions2>({
baseUrl: 'http://localhost:8080' baseUrl: 'http://26.26.26.1:8080'
})); }));

View File

@@ -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} />
}

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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 />
}
]
}
]

View File

@@ -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();