生产管理系统 前端不需要的文件删除
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 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'
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -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