fix: 修复用户管理和任务抢单权限控制
1. 修复设置管理员报错 - 修正BusinessException构造函数调用 2. 完善抢单权限控制 - 需求部门成员不能抢单 - 所有部门负责人不能抢单(包括需求和接单部门) - 只有指定接单部门的普通成员可以抢单 - 验证部门是否允许接该需求类型 - 抢单成功后发送通知给任务发起人 3. 前端抢单按钮状态控制 - 添加canGrabTask方法判断抢单权限 - 可接单:绿色按钮 - 不可接单:灰色按钮并禁用 - 鼠标悬停显示不能抢单的原因 - 支持任务列表和详情页面 4. 优化用户体验 - 点击不可抢单按钮时提示具体原因 - 按钮文案动态显示状态
This commit is contained in:
parent
93781bb202
commit
038659bd41
@ -670,26 +670,39 @@ public class TaskService {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "该任务不支持抢单");
|
||||
}
|
||||
|
||||
// 验证用户权限:只有接单部门可以接任务(管理员除外)
|
||||
// 获取用户信息
|
||||
var user = userService.getUserById(userId);
|
||||
if (user == null) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "用户不存在");
|
||||
}
|
||||
|
||||
// 检查是否是管理员(管理员可以同时拥有需求部门和接单部门权限)
|
||||
boolean isAdmin = isAdminUser(userId);
|
||||
|
||||
Long deptId = user.getDeptId();
|
||||
Department department = deptId != null ? departmentService.getDepartmentById(deptId) : null;
|
||||
if (deptId == null) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "您未分配部门,无法接单");
|
||||
}
|
||||
|
||||
// 获取用户所属部门
|
||||
Department department = departmentService.getDepartmentById(deptId);
|
||||
if (department == null) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "未找到用户所属部门,请联系管理员");
|
||||
}
|
||||
|
||||
// 检查1:需求部门不能抢单
|
||||
if ("demand".equals(department.getDeptType())) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "需求部门成员不能接单,只能发起需求");
|
||||
}
|
||||
|
||||
// 检查2:接单部门类型验证
|
||||
if (!"receiving".equals(department.getDeptType())) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "只有接单部门可以接收任务");
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "只有接单部门成员可以接收任务");
|
||||
}
|
||||
if (!isAdmin && deptId == null) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "用户部门信息不完整");
|
||||
|
||||
// 检查3:部门负责人不能抢单
|
||||
if (department.getLeaderId() != null && department.getLeaderId().equals(userId)) {
|
||||
throw new BusinessException(ResultCode.FORBIDDEN, "部门负责人不能接单,请分配给设计师");
|
||||
}
|
||||
|
||||
// 检查4:验证部门是否允许接该需求类型
|
||||
if (task.getDemandTypeId() != null) {
|
||||
validateAllowedDemandTypes(department, task.getDemandTypeId());
|
||||
}
|
||||
@ -708,7 +721,22 @@ public class TaskService {
|
||||
throw new BusinessException(ResultCode.TASK_ALREADY_TAKEN, "任务已被其他设计师抢走");
|
||||
}
|
||||
|
||||
// TODO: 发送通知
|
||||
log.info("用户 {} 成功抢单任务 {}", userId, taskId);
|
||||
|
||||
// 发送通知给任务发起人
|
||||
if (task.getPublisherId() != null) {
|
||||
try {
|
||||
notificationService.sendNotification(
|
||||
task.getPublisherId(),
|
||||
"任务已被接单",
|
||||
String.format("您的任务【%s】已被 %s 接单", task.getTitle(), user.getRealName() != null ? user.getRealName() : user.getUsername()),
|
||||
"task_grabbed",
|
||||
taskId
|
||||
);
|
||||
} catch (Exception e) {
|
||||
log.error("发送抢单通知失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1272,7 +1272,7 @@ public class UserService {
|
||||
|
||||
User user = getUserById(userId);
|
||||
if (user == null) {
|
||||
throw new BusinessException("用户不存在");
|
||||
throw new BusinessException(ResultCode.NOT_FOUND, "用户不存在");
|
||||
}
|
||||
|
||||
// 更新管理员标识
|
||||
|
||||
@ -320,11 +320,21 @@
|
||||
查看详情
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
style="flex: 1"
|
||||
:class="[
|
||||
'btn',
|
||||
canGrabTask(task).canGrab ? 'btn-primary' : 'btn-disabled'
|
||||
]"
|
||||
:style="{
|
||||
flex: 1,
|
||||
backgroundColor: canGrabTask(task).canGrab ? '#31f08b' : '#666',
|
||||
cursor: canGrabTask(task).canGrab ? 'pointer' : 'not-allowed',
|
||||
opacity: canGrabTask(task).canGrab ? 1 : 0.6
|
||||
}"
|
||||
:disabled="!canGrabTask(task).canGrab"
|
||||
:title="canGrabTask(task).canGrab ? '点击抢单' : canGrabTask(task).reason"
|
||||
@click.stop="handleGrab(task)"
|
||||
>
|
||||
抢单
|
||||
{{ canGrabTask(task).canGrab ? '抢单' : '不可接单' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1840,11 +1850,19 @@
|
||||
<!-- 可接任务:显示抢单 -->
|
||||
<a-button
|
||||
v-if="selectedTask.status === 'pending'"
|
||||
type="primary"
|
||||
:type="canGrabTask(selectedTask).canGrab ? 'primary' : 'default'"
|
||||
:style="{
|
||||
backgroundColor: canGrabTask(selectedTask).canGrab ? '#31f08b' : '#999',
|
||||
borderColor: canGrabTask(selectedTask).canGrab ? '#31f08b' : '#999',
|
||||
color: '#fff',
|
||||
cursor: canGrabTask(selectedTask).canGrab ? 'pointer' : 'not-allowed',
|
||||
opacity: canGrabTask(selectedTask).canGrab ? 1 : 0.6
|
||||
}"
|
||||
size="large"
|
||||
block
|
||||
block
|
||||
:disabled="!canGrabTask(selectedTask).canGrab"
|
||||
@click="handleGrabFromDetail">
|
||||
确认抢单
|
||||
{{ canGrabTask(selectedTask).canGrab ? '确认抢单' : `不可接单(${canGrabTask(selectedTask).reason})` }}
|
||||
</a-button>
|
||||
|
||||
<!-- 进行中任务:显示更新进度和完结 -->
|
||||
@ -3372,12 +3390,49 @@ const handleTaskClick = (task: TaskOrSubTask) => {
|
||||
detailDrawerVisible.value = true
|
||||
}
|
||||
|
||||
// 判断用户是否可以抢单
|
||||
const canGrabTask = (task: TaskOrSubTask) => {
|
||||
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}')
|
||||
const userDeptId = userInfo.deptId
|
||||
const userDeptType = userInfo.deptType // 'demand' 或 'receiving'
|
||||
|
||||
// 检查1:没有部门不能抢单
|
||||
if (!userDeptId) {
|
||||
return { canGrab: false, reason: '您未分配部门,无法接单' }
|
||||
}
|
||||
|
||||
// 检查2:需求部门不能抢单
|
||||
if (userDeptType === 'demand') {
|
||||
return { canGrab: false, reason: '需求部门成员不能接单' }
|
||||
}
|
||||
|
||||
// 检查3:部门负责人不能抢单
|
||||
if (userInfo.isDepartmentLeader === 1 || userInfo.isDepartmentLeader === true) {
|
||||
return { canGrab: false, reason: '部门负责人不能接单' }
|
||||
}
|
||||
|
||||
// 检查4:验证部门是否允许接该需求类型(如果任务有需求类型限制)
|
||||
if (task.demandTypeId) {
|
||||
// 这里需要检查任务的需求类型是否允许当前用户的部门接单
|
||||
// 由于前端没有完整的需求类型配置,暂时信任后端验证
|
||||
}
|
||||
|
||||
return { canGrab: true, reason: '' }
|
||||
}
|
||||
|
||||
// 抢单(支持普通任务和子任务)
|
||||
const handleGrab = async (task: TaskOrSubTask) => {
|
||||
const isSubTask = task.isSubTask
|
||||
const taskType = isSubTask ? '子任务' : '任务'
|
||||
const taskNo = isSubTask ? task.subTaskNo : task.taskNo
|
||||
|
||||
// 先检查权限
|
||||
const { canGrab, reason } = canGrabTask(task)
|
||||
if (!canGrab) {
|
||||
message.warning(reason)
|
||||
return
|
||||
}
|
||||
|
||||
Modal.confirm({
|
||||
title: `确认抢单${taskType}`,
|
||||
content: `确定要抢单${taskType}"${task.title}"吗?${taskNo ? `(编号:${taskNo})` : ''}`,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user