Compare commits

..

3 Commits

Author SHA1 Message Date
54130d4401 docs: 更新README文档和修复模型复数名称
- 更新README文档,添加新功能描述和API端点详情
- 修复TaskResult模型的verbose_name_plural字段
2026-01-28 16:47:17 +08:00
a8e24fad63 Merge branch 'main' of http://14.103.237.41:16001/xiaji/central-task 2025-12-12 12:02:59 +08:00
97c0e0db0d 当创建一个客户端的时候,自动创建一个API Token 2025-12-12 11:55:36 +08:00
4 changed files with 93 additions and 30 deletions

View File

@@ -9,21 +9,30 @@
- 设置任务执行客户端(指定或自动分配) - 设置任务执行客户端(指定或自动分配)
- 配置任务超时时间 - 配置任务超时时间
- 支持任务脚本存储 - 支持任务脚本存储
- 完整的任务生命周期管理
### 2. 客户端管理 ### 2. 客户端管理
- 客户端注册和身份验证 - 客户端注册和身份验证
- 自动生成API Token - 自动生成安全的API Token
- 客户端活跃状态跟踪 - 客户端活跃状态跟踪
### 3. 任务执行流程 ### 3. 任务执行流程
- **原子任务认领**:避免竞态条件 - **原子任务认领**使用数据库事务确保并发安全,避免竞态条件
- 任务状态跟踪:待分配、已分配、执行中、成功、失败、重试中、超时 - 任务状态跟踪:待分配、已分配、执行中、成功、失败、重试中、超时
- 任务结果上传和下载 - 任务结果上传和下载
- 完整的任务执行API认领、开始、完成
### 4. 系统管理 ### 4. 系统管理
- 完整的后台管理界面 - 完整的后台管理界面
- 任务超时自动回收 - 任务超时自动回收
- 结果文件管理 - 结果文件管理
- API权限控制所有API端点均需要认证
### 5. 前端界面
- 响应式设计基于Bootstrap 5
- 任务管理:列表、创建、详情
- 客户端管理:列表、创建
- 结果查看和下载
## 技术栈 ## 技术栈
@@ -91,7 +100,7 @@ python manage.py runserver
#### 1.2 管理客户端 #### 1.2 管理客户端
- 在左侧菜单栏点击 "客户端" - 在左侧菜单栏点击 "客户端"
- 点击 "添加客户端" 创建新客户端 - 点击 "添加客户端" 创建新客户端
- 系统会自动生成API Token - 系统会自动生成安全的API Token
#### 1.3 管理任务 #### 1.3 管理任务
- 在左侧菜单栏点击 "任务" - 在左侧菜单栏点击 "任务"
@@ -127,19 +136,30 @@ python manage.py runserver
Authorization: Token <your-token> Authorization: Token <your-token>
``` ```
**注意**所有API端点均需要认证使用 `IsAuthenticated` 权限类控制。
#### 3.2 主要API端点 #### 3.2 主要API端点
| 端点 | 方法 | 功能 | | 端点 | 方法 | 功能 | 权限 |
|------|------|------| |------|------|------|------|
| `/api/clients/` | GET | 获取客户端列表 | | `/api/clients/` | GET | 获取客户端列表 | 需要认证 |
| `/api/clients/` | POST | 创建客户端 | | `/api/clients/` | POST | 创建客户端 | 需要认证 |
| `/api/tasks/` | GET | 获取任务列表 | | `/api/clients/<id>/` | GET | 获取客户端详情 | 需要认证 |
| `/api/tasks/` | POST | 创建任务 | | `/api/clients/<id>/` | PUT | 更新客户端 | 需要认证 |
| `/api/tasks/claim/` | POST | 客户端认领任务 | | `/api/clients/<id>/` | DELETE | 删除客户端 | 需要认证 |
| `/api/tasks/<id>/start/` | POST | 开始执行任务 | | `/api/tasks/` | GET | 获取任务列表 | 需要认证 |
| `/api/tasks/<id>/complete/` | POST | 完成任务 | | `/api/tasks/` | POST | 创建任务 | 需要认证 |
| `/api/task_results/` | POST | 上传任务结果 | | `/api/tasks/<id>/` | GET | 获取任务详情 | 需要认证 |
| `/api/task_results/<id>/download/` | GET | 下载结果文件 | | `/api/tasks/<id>/` | PUT | 更新任务 | 需要认证 |
| `/api/tasks/<id>/` | DELETE | 删除任务 | 需要认证 |
| `/api/tasks/claim/` | POST | 客户端认领任务 | 需要认证 |
| `/api/tasks/<id>/start/` | POST | 开始执行任务 | 需要认证 |
| `/api/tasks/<id>/complete/` | POST | 完成任务 | 需要认证 |
| `/api/task_results/` | GET | 获取任务结果列表 | 需要认证 |
| `/api/task_results/` | POST | 上传任务结果 | 需要认证 |
| `/api/task_results/<id>/` | GET | 获取任务结果详情 | 需要认证 |
| `/api/task_results/<id>/` | DELETE | 删除任务结果 | 需要认证 |
| `/api/task_results/<id>/download/` | GET | 下载结果文件 | 需要认证 |
#### 3.3 API使用示例 #### 3.3 API使用示例
@@ -159,6 +179,20 @@ curl -X POST http://127.0.0.1:8000/api/tasks/claim/ \
-d '{"client_name":"client1"}' -d '{"client_name":"client1"}'
``` ```
##### 开始执行任务
```bash
curl -X POST http://127.0.0.1:8000/api/tasks/1/start/ \
-H "Authorization: Token <token>"
```
##### 完成任务
```bash
curl -X POST http://127.0.0.1:8000/api/tasks/1/complete/ \
-H "Authorization: Token <token>" \
-H "Content-Type: application/json" \
-d '{"status":"success","message":"任务执行成功"}'
```
##### 上传任务结果 ##### 上传任务结果
```bash ```bash
curl -X POST http://127.0.0.1:8000/api/task_results/ \ curl -X POST http://127.0.0.1:8000/api/task_results/ \
@@ -170,22 +204,31 @@ curl -X POST http://127.0.0.1:8000/api/task_results/ \
-F "result_file=@result.txt" -F "result_file=@result.txt"
``` ```
##### 下载任务结果文件
```bash
curl -X GET http://127.0.0.1:8000/api/task_results/1/download/ \
-H "Authorization: Token <token>" \
-o result.txt
```
## 项目结构 ## 项目结构
``` ```
task_center/ 任务中心/
├── task_center/ # 项目配置 ├── task_center/ # 项目配置
│ ├── settings.py # 项目设置 │ ├── settings.py # 项目设置
│ └── urls.py # 主URL配置 │ └── urls.py # 主URL配置
├── tasks/ # 任务应用 ├── tasks/ # 任务应用
│ ├── models.py # 数据库模型 │ ├── models.py # 数据库模型
│ ├── serializers.py # API序列化器 │ ├── serializers.py # API序列化器
│ ├── views.py # API视图 │ ├── views.py # API视图使用IsAuthenticated权限
│ ├── views_frontend.py # 前端视图 │ ├── views_frontend.py # 前端视图
│ ├── urls.py # 应用URL配置 │ ├── urls.py # 应用URL配置
│ ├── templates/ # 前端模板 │ ├── templates/ # 前端模板
│ ├── tests/ # 测试用例 │ ├── tests/ # 测试用例
│ └── management/ # 管理命令 │ └── management/ # 管理命令
├── media/ # 媒体文件存储
│ └── task_results/ # 任务结果文件
└── manage.py # 项目入口 └── manage.py # 项目入口
``` ```
@@ -199,15 +242,20 @@ python manage.py check_task_timeouts
建议将此命令添加到系统定时任务中,例如每小时执行一次。 建议将此命令添加到系统定时任务中,例如每小时执行一次。
### 命令功能说明
- **check_task_timeouts**:检查所有执行中任务,将超过超时时间的任务标记为超时状态,使其可以被重新分配执行。
## 注意事项 ## 注意事项
1. **文件存储**:结果文件存储在 `media/task_results/` 目录下,请确保该目录有写入权限 1. **文件存储**:结果文件存储在 `media/task_results/` 目录下,请确保该目录有写入权限
2. **API Token安全**请妥善保管客户端API Token避免泄露 2. **API Token安全**请妥善保管客户端API Token避免泄露
3. **生产环境配置** 3. **API权限控制**所有API端点均需要认证使用 `IsAuthenticated` 权限类控制
4. **生产环境配置**
- 建议使用PostgreSQL或MySQL数据库 - 建议使用PostgreSQL或MySQL数据库
- 配置合适的文件存储后端如S3 - 配置合适的文件存储后端如S3
- 启用HTTPS - 启用HTTPS
- 配置适当的日志记录 - 配置适当的日志记录
- 实现更细粒度的权限控制(如基于角色的权限)
## 许可证 ## 许可证
@@ -233,6 +281,13 @@ python -m pytest --ds=task_center.settings
## 更新日志 ## 更新日志
### v1.1.0
- 增强API权限控制所有API端点均使用 `IsAuthenticated` 权限类
- 完善API文档更新API端点描述和使用示例
- 优化前端界面:改进任务和客户端管理功能
- 增强任务执行流程完善认领、开始、完成的API实现
- 改进项目结构文档:添加媒体文件存储目录说明
### v1.0.0 ### v1.0.0
- 初始版本发布 - 初始版本发布
- 完成任务管理核心功能 - 完成任务管理核心功能

View File

@@ -14,15 +14,15 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path 1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf import settings from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from tasks.views_frontend import index from tasks.views_frontend import index
urlpatterns = [ urlpatterns = [
path('houtai/', admin.site.urls), path('houtai/', admin.site.urls),
path('api/', include('tasks.urls')), path('api/', include('tasks.urls')),
# Root URL points to home page # Root URL points to home page
path('', index, name='index'), path('', index, name='index'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -53,4 +53,4 @@ class TaskResultAdmin(admin.ModelAdmin):
'classes': ('collapse',) 'classes': ('collapse',)
}), }),
) )

View File

@@ -1,5 +1,6 @@
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
import secrets
# Status choices for tasks # Status choices for tasks
STATUS_CHOICES = [ STATUS_CHOICES = [
@@ -20,6 +21,13 @@ class Client(models.Model):
def __str__(self): def __str__(self):
return self.name return self.name
def save(self, *args, **kwargs):
# Generate a unique token if this is a new client
if not self.pk and not self.token:
# Use secrets module to generate a secure random token
self.token = secrets.token_urlsafe(64) # 64 bytes -> ~86 characters
super().save(*args, **kwargs)
class Meta: class Meta:
verbose_name = '客户端' verbose_name = '客户端'
@@ -57,4 +65,4 @@ class TaskResult(models.Model):
class Meta: class Meta:
verbose_name = '任务结果' verbose_name = '任务结果'
verbose_name_plural = '任务结果' verbose_name_plural = '任务结果'