feat: 系统设置增加管理员根据任务编号删除任务功能

This commit is contained in:
Your Name 2026-01-15 18:12:35 +08:00
parent 286162aeb2
commit e7822faaca
3 changed files with 170 additions and 0 deletions

View File

@ -464,5 +464,29 @@ public class TaskController {
taskService.rejectTask(id, userId, reason);
return Result.success("任务已驳回");
}
@Operation(summary = "根据任务编号删除任务", description = "管理员根据任务编号删除任务及其所有子任务(仅管理员可用)")
@DeleteMapping("/by-task-no/{taskNo}")
public Result<String> deleteTaskByTaskNo(
@PathVariable String taskNo,
@RequestHeader("Authorization") String authHeader) {
log.info("根据任务编号删除任务: taskNo={}", taskNo);
String token = jwtUtil.extractTokenFromHeader(authHeader);
Long userId = jwtUtil.getUserIdFromToken(token);
// 验证是否为管理员
com.designhub.entity.User user = taskService.getUserById(userId);
if (user == null || user.getIsAdmin() != 1) {
return Result.error("权限不足,仅管理员可以删除任务");
}
try {
taskService.deleteTaskByTaskNo(taskNo);
return Result.success("任务删除成功");
} catch (RuntimeException e) {
return Result.error(e.getMessage());
}
}
}

View File

@ -3335,5 +3335,44 @@ public class TaskService {
collectChildDeptIds(child.getId(), result);
}
}
/**
* 根据任务编号删除任务及其所有子任务
* @param taskNo 任务编号
*/
@Transactional
public void deleteTaskByTaskNo(String taskNo) {
log.info("根据任务编号删除任务: taskNo={}", taskNo);
// 查找任务
Task task = taskMapper.selectOne(
new LambdaQueryWrapper<Task>()
.eq(Task::getTaskNo, taskNo)
);
if (task == null) {
throw new RuntimeException("任务不存在,请检查任务编号是否正确");
}
Long taskId = task.getId();
// 1. 删除所有子任务
int deletedItems = taskItemMapper.delete(
new LambdaQueryWrapper<TaskItem>()
.eq(TaskItem::getTaskId, taskId)
);
log.info("已删除 {} 个子任务", deletedItems);
// 2. 删除主任务
taskMapper.deleteById(taskId);
log.info("已删除主任务: taskNo={}, taskId={}", taskNo, taskId);
}
/**
* 获取用户信息(供Controller调用)
*/
public User getUserById(Long userId) {
return userService.getUserById(userId);
}
}

View File

@ -1532,6 +1532,61 @@
</div>
</a-tab-pane>
<!-- 任务数据管理 -->
<a-tab-pane key="task-management" tab="任务数据管理">
<div class="settings-section">
<div class="section-header">
<h2 class="section-title">任务数据管理</h2>
</div>
<a-alert
message="危险操作"
description="删除任务将永久删除该任务及其所有子任务数据,此操作不可恢复,请谨慎操作!"
type="warning"
show-icon
style="margin-bottom: 24px;"
/>
<a-card title="删除任务" class="task-delete-card">
<a-form layout="vertical">
<a-form-item label="任务编号">
<a-input
v-model:value="taskDeleteForm.taskNo"
placeholder="请输入要删除的任务编号,例如:TASK202601150001"
size="large"
style="max-width: 400px;"
/>
<div style="margin-top: 8px; font-size: 12px; color: #888;">
<Icon name="info" size="sm" color="#888" style="margin-right: 4px;" />
任务编号可以在任务卡片或任务详情中找到
</div>
</a-form-item>
<a-form-item>
<a-popconfirm
title="确定要删除这个任务吗?"
description="删除后将无法恢复,包括所有子任务数据!"
ok-text="确认删除"
cancel-text="取消"
ok-type="danger"
@confirm="handleDeleteTask"
>
<a-button
type="primary"
danger
size="large"
:loading="deletingTask"
:disabled="!taskDeleteForm.taskNo"
>
<template #icon><Icon name="trash" size="sm" /></template>
删除任务
</a-button>
</a-popconfirm>
</a-form-item>
</a-form>
</a-card>
</div>
</a-tab-pane>
<!-- 第三方数据库配置 -->
<a-tab-pane key="third-party-db" tab="第三方数据库">
<div class="settings-section">
@ -2433,6 +2488,7 @@ import {
testConnection as testThirdPartyDbConnection,
type ThirdPartyDbConfig
} from '@/api/thirdPartyDb'
import { deleteTaskByTaskNo } from '@/api/task'
import request from '@/utils/request'
type LimitPeriod = 'DAILY' | 'WEEKLY' | 'MONTHLY'
@ -2565,6 +2621,35 @@ const s3ConfigColumns = [
{ title: '操作', key: 'actions', width: 200 }
]
// 任务数据管理相关
const taskDeleteForm = reactive({
taskNo: ''
})
const deletingTask = ref(false)
// 删除任务
const handleDeleteTask = async () => {
if (!taskDeleteForm.taskNo) {
message.warning('请输入任务编号')
return
}
deletingTask.value = true
try {
const response = await deleteTaskByTaskNo(taskDeleteForm.taskNo.trim())
if (response.code === 200) {
message.success('任务删除成功')
taskDeleteForm.taskNo = ''
} else {
message.error(response.message || '删除失败')
}
} catch (error: any) {
message.error(error.response?.data?.message || error.message || '删除失败')
} finally {
deletingTask.value = false
}
}
// 第三方数据库配置相关
const thirdPartyDbConfigs = ref<ThirdPartyDbConfig[]>([])
const loadingThirdPartyDb = ref(false)
@ -6525,6 +6610,28 @@ watch(activeTab, (value) => {
}
}
}
// 任务删除卡片样式
.task-delete-card {
max-width: 600px;
background: rgba(0, 0, 0, 0.2) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 8px;
:deep(.ant-card-head) {
background: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
.ant-card-head-title {
color: rgba(255, 255, 255, 0.85);
font-weight: 500;
}
}
:deep(.ant-card-body) {
background: transparent !important;
}
}
</style>