fix: 修复审核弹窗任务类型显示和部门负责人看任务卡片问题
1. 审核弹窗任务类型显示增加完整路径(父级名称)和单位积分 2. 修复级联选择器弹窗为深色主题 3. 添加task_item.receiver_dept_id字段支持部门负责人查看部门成员任务 4. 更新grabItem和分配任务逻辑设置receiver_dept_id
This commit is contained in:
parent
c87c646d4d
commit
0ef762baa4
@ -76,6 +76,11 @@ public class TaskItem implements Serializable {
|
||||
*/
|
||||
private String receiverName;
|
||||
|
||||
/**
|
||||
* 接单部门ID
|
||||
*/
|
||||
private Long receiverDeptId;
|
||||
|
||||
/**
|
||||
* 状态:locked/pending/in_progress/completed/rejected
|
||||
*/
|
||||
|
||||
@ -163,6 +163,7 @@ public interface TaskItemMapper extends BaseMapper<TaskItem> {
|
||||
@Update("UPDATE task_item SET " +
|
||||
"receiver_id = #{receiverId}, " +
|
||||
"receiver_name = #{receiverName}, " +
|
||||
"receiver_dept_id = #{receiverDeptId}, " +
|
||||
"status = 'in_progress', " +
|
||||
"update_time = NOW() " +
|
||||
"WHERE id = #{itemId} " +
|
||||
@ -171,7 +172,8 @@ public interface TaskItemMapper extends BaseMapper<TaskItem> {
|
||||
"AND receiver_id IS NULL")
|
||||
int grabItem(@Param("itemId") Long itemId,
|
||||
@Param("receiverId") Long receiverId,
|
||||
@Param("receiverName") String receiverName);
|
||||
@Param("receiverName") String receiverName,
|
||||
@Param("receiverDeptId") Long receiverDeptId);
|
||||
|
||||
/**
|
||||
* 解锁子任务
|
||||
|
||||
@ -209,8 +209,8 @@ public class TaskItemService {
|
||||
throw new BusinessException(ResultCode.TASK_ALREADY_TAKEN, "该子任务已被接单");
|
||||
}
|
||||
|
||||
// 乐观锁抢单
|
||||
int result = taskItemMapper.grabItem(itemId, userId, user.getRealName());
|
||||
// 乐观锁抢单(同时设置接单部门ID)
|
||||
int result = taskItemMapper.grabItem(itemId, userId, user.getRealName(), user.getDeptId());
|
||||
if (result == 0) {
|
||||
throw new BusinessException(ResultCode.TASK_ALREADY_TAKEN, "抢单失败,该子任务可能已被他人接单");
|
||||
}
|
||||
@ -619,6 +619,7 @@ public class TaskItemService {
|
||||
for (TaskItem item : groupItems) {
|
||||
item.setStatus("in_progress");
|
||||
item.setReceiverId(assignedReceiverId);
|
||||
item.setReceiverDeptId(receiver.getDeptId()); // 设置接单部门ID
|
||||
item.setUpdateTime(LocalDateTime.now());
|
||||
taskItemMapper.updateById(item);
|
||||
}
|
||||
|
||||
@ -1968,18 +1968,26 @@
|
||||
<span class="section-title" style="font-weight: 600; color: #fff;">编辑任务类型</span>
|
||||
</div>
|
||||
<div class="task-type-list" style="background: #141414; padding: 12px; border-radius: 8px;">
|
||||
<div v-for="(item, index) in approveTaskTypes" :key="index" class="task-type-item" style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; padding: 8px; background: #262626; border-radius: 4px;">
|
||||
<div class="type-info">
|
||||
<a-tag color="#303030" style="color: #fff; border: 1px solid #444;">{{ getTaskTypeName(item.typeId) }}</a-tag>
|
||||
<div v-for="(item, index) in approveTaskTypes" :key="index" class="task-type-item" style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; padding: 12px; background: #262626; border-radius: 6px;">
|
||||
<div class="type-info" style="flex: 1; min-width: 0;">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px;">
|
||||
<span style="color: #fff; font-weight: 500; font-size: 14px;">{{ getTaskTypeFullPath(item.typeId)?.name || getTaskTypeName(item.typeId) }}</span>
|
||||
<span style="color: #888; font-size: 12px;">{{ getTaskTypeFullPath(item.typeId)?.fullPath || '' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="type-controls" style="display: flex; align-items: center;">
|
||||
<span class="label" style="color: #888; margin-right: 8px; font-size: 12px;">数量</span>
|
||||
<a-input-number
|
||||
v-model:value="item.quantity"
|
||||
:min="1"
|
||||
size="small"
|
||||
style="width: 60px; margin-right: 8px;"
|
||||
/>
|
||||
<div class="type-controls" style="display: flex; align-items: center; gap: 12px;">
|
||||
<div style="display: flex; align-items: center; background: #31f08b22; padding: 4px 10px; border-radius: 4px;">
|
||||
<span style="color: #31f08b; font-weight: 600; font-size: 14px;">{{ getTaskTypeUnitScore(item.typeId) }} 分/个</span>
|
||||
</div>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<span class="label" style="color: #888; margin-right: 8px; font-size: 12px;">数量</span>
|
||||
<a-input-number
|
||||
v-model:value="item.quantity"
|
||||
:min="1"
|
||||
size="small"
|
||||
style="width: 70px;"
|
||||
/>
|
||||
</div>
|
||||
<a-button
|
||||
type="text"
|
||||
danger
|
||||
@ -2001,7 +2009,7 @@
|
||||
allow-clear
|
||||
change-on-select
|
||||
:show-search="{ filter: cascaderFilter }"
|
||||
:dropdown-style="{ background: '#262626' }"
|
||||
popup-class-name="dark-cascader-popup"
|
||||
/>
|
||||
<a-button type="primary" ghost style="border-color: #31f08b; color: #31f08b;" @click="handleAddApproveTaskType">
|
||||
<Icon name="plus" size="sm" style="margin-right: 4px" /> 添加
|
||||
@ -2492,6 +2500,25 @@ const findTaskTypeById = (id: number, items: any[] = hierarchicalTaskTypes.value
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取任务类型的完整路径信息(包含父级名称和积分)
|
||||
const getTaskTypeFullPath = (id: number, items: any[] = hierarchicalTaskTypes.value, path: string[] = []): { name: string, fullPath: string, unitScore: number } | null => {
|
||||
for (const item of items) {
|
||||
const currentPath = [...path, item.name]
|
||||
if (item.id === id) {
|
||||
return {
|
||||
name: item.name,
|
||||
fullPath: currentPath.join(' > '),
|
||||
unitScore: item.unitScore || 0
|
||||
}
|
||||
}
|
||||
if (item.children) {
|
||||
const found = getTaskTypeFullPath(id, item.children, currentPath)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// 构建级联选择器选项
|
||||
const taskTypeCascaderOptions = computed(() => {
|
||||
const buildOptions = (items: any[]): any[] => {
|
||||
@ -5838,5 +5865,79 @@ onUnmounted(() => {
|
||||
:deep(.approve-modal) .ant-btn-text.ant-btn-danger:hover {
|
||||
background-color: rgba(255, 77, 79, 0.1);
|
||||
}
|
||||
|
||||
/* 级联选择器深色主题 - 组件内部 */
|
||||
:deep(.approve-modal) .ant-cascader {
|
||||
.ant-select-selector {
|
||||
background-color: #141414 !important;
|
||||
border-color: #303030 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
&:hover .ant-select-selector {
|
||||
border-color: #31f08b !important;
|
||||
}
|
||||
|
||||
.ant-select-selection-placeholder {
|
||||
color: #666 !important;
|
||||
}
|
||||
|
||||
.ant-select-selection-item {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- 全局样式:级联选择器弹窗深色主题(弹窗渲染在body上) -->
|
||||
<style>
|
||||
.dark-cascader-popup {
|
||||
background-color: #1f1f1f !important;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.5) !important;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu {
|
||||
background-color: #1f1f1f !important;
|
||||
border-color: #303030 !important;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu-item {
|
||||
color: #fff !important;
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu-item:hover {
|
||||
background-color: rgba(49, 240, 139, 0.1) !important;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled),
|
||||
.dark-cascader-popup .ant-cascader-menu-item-active:not(.ant-cascader-menu-item-disabled):hover {
|
||||
background-color: rgba(49, 240, 139, 0.2) !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu-item-expand-icon {
|
||||
color: #888 !important;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-menu-item-content {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* 搜索框深色主题 */
|
||||
.dark-cascader-popup .ant-cascader-input {
|
||||
background-color: #262626 !important;
|
||||
border-color: #303030 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.dark-cascader-popup .ant-cascader-input::placeholder {
|
||||
color: #666 !important;
|
||||
}
|
||||
|
||||
/* 空状态 */
|
||||
.dark-cascader-popup .ant-cascader-empty {
|
||||
color: #888 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user