feat: 一级需求任务完善

1. 需求部门处理人进行中任务显示一级需求部门的任务
2. 一级需求任务完结后由明细完善人确认接收并评分
3. 商品条码由一级需求发起人填写,明细编辑模式下只读
This commit is contained in:
Your Name 2026-01-20 00:32:53 +08:00
parent 4163799b63
commit 048c5e189e
3 changed files with 92 additions and 42 deletions

View File

@ -171,6 +171,7 @@ public interface TaskMapper extends BaseMapper<Task> {
/**
* 查询我接收的任务
* 包括:作为接收人的任务 或 作为一级需求任务明细完善人的任务
*/
@Select("<script>" +
"SELECT t.*, " +
@ -187,7 +188,7 @@ public interface TaskMapper extends BaseMapper<Task> {
"LEFT JOIN sys_user u ON t.publisher_id = u.id " +
"LEFT JOIN sys_dept d ON t.publisher_dept_id = d.id " +
"LEFT JOIN sys_user approver ON t.current_approver_id = approver.id " +
"WHERE t.receiver_id = #{userId} AND t.deleted = 0 " +
"WHERE (t.receiver_id = #{userId} OR t.detail_completer_id = #{userId}) AND t.deleted = 0 " +
"<if test='status != null'> AND t.status = #{status}</if> " +
"ORDER BY t.create_time DESC" +
"</script>")

View File

@ -3119,12 +3119,27 @@ public class TaskService {
task.setUpdateTime(LocalDateTime.now());
taskMapper.updateById(task);
// 发送通知给发起人
// 发送通知
// 对于一级需求任务,通知明细完善人;否则通知发起人
try {
Notification notification = new Notification();
notification.setReceiverId(task.getPublisherId());
notification.setTitle("任务提交审核");
notification.setContent("任务【" + task.getTitle() + "】已提交审核,请查看");
boolean isPrimaryTask = task.getIsPrimaryTask() != null && task.getIsPrimaryTask() == 1;
Long receiverId;
if (isPrimaryTask && task.getDetailCompleterId() != null) {
// 一级需求任务:通知明细完善人确认接收并评分
receiverId = task.getDetailCompleterId();
notification.setTitle("一级需求任务待确认");
notification.setContent("一级需求任务【" + task.getTitle() + "】已完成,请确认接收并评分");
} else {
// 普通任务:通知发起人
receiverId = task.getPublisherId();
notification.setTitle("任务提交审核");
notification.setContent("任务【" + task.getTitle() + "】已提交审核,请查看");
}
notification.setReceiverId(receiverId);
notification.setNotificationType("TASK_REVIEW");
notification.setRelatedType("task");
notification.setRelatedId(taskId);
@ -3149,12 +3164,16 @@ public class TaskService {
throw new BusinessException("任务不存在");
}
// 验证权限(发起人或部门负责人)
// 验证权限
// 对于一级需求任务:明细完善人可以审核
// 对于普通任务:发起人或部门负责人可以审核
User user = userService.getUserById(userId);
if (user == null) {
throw new BusinessException("用户不存在");
}
boolean isPrimaryTask = task.getIsPrimaryTask() != null && task.getIsPrimaryTask() == 1;
boolean isDetailCompleter = isPrimaryTask && userId.equals(task.getDetailCompleterId());
boolean isPublisher = userId.equals(task.getPublisherId());
boolean isDeptLeader = false;
@ -3165,8 +3184,12 @@ public class TaskService {
}
}
if (!isPublisher && !isDeptLeader) {
throw new BusinessException("只有任务发起人或部门负责人才能审核任务");
if (!isDetailCompleter && !isPublisher && !isDeptLeader) {
if (isPrimaryTask) {
throw new BusinessException("只有明细完善人才能确认接收一级需求任务");
} else {
throw new BusinessException("只有任务发起人或部门负责人才能审核任务");
}
}
// 验证任务状态

View File

@ -266,42 +266,63 @@
label="商品条码"
required
>
<!-- 已添加的条码列表 -->
<div v-if="formData.productBarcodes && formData.productBarcodes.length > 0" class="barcode-list">
<div class="barcode-list-title">
<span>已添加条码 ({{ formData.productBarcodes.length }}个)</span>
<!-- 一级需求任务编辑模式:商品条码只读 -->
<template v-if="formData.isPrimaryTaskEdit && formData.productBarcodes && formData.productBarcodes.length > 0">
<div class="barcode-list readonly">
<div class="barcode-list-title">
<span>商品条码 ({{ formData.productBarcodes.length }}个) - 由一级需求发起人填写,不可修改</span>
</div>
<div class="barcode-tags">
<a-tag
v-for="(barcode, index) in formData.productBarcodes"
:key="index"
color="blue"
>
{{ barcode }}
</a-tag>
</div>
</div>
<div class="barcode-tags">
<a-tag
v-for="(barcode, index) in formData.productBarcodes"
:key="index"
color="green"
closable
@close="removeBarcode(index)"
>
{{ barcode }}
</a-tag>
</div>
</div>
</template>
<!-- 添加新条码 -->
<div style="margin-top: 8px; display: flex; gap: 10px;">
<a-input
v-model:value="newBarcodeInput"
placeholder="请输入商品条码,验证库存后添加"
size="large"
style="flex: 1;"
@pressEnter="handleAddBarcode"
/>
<a-button
type="primary"
size="large"
@click="handleAddBarcode"
:loading="checkingInventory"
>
验证并添加
</a-button>
</div>
<!-- 普通模式:可编辑 -->
<template v-else>
<!-- 已添加的条码列表 -->
<div v-if="formData.productBarcodes && formData.productBarcodes.length > 0" class="barcode-list">
<div class="barcode-list-title">
<span>已添加条码 ({{ formData.productBarcodes.length }}个)</span>
</div>
<div class="barcode-tags">
<a-tag
v-for="(barcode, index) in formData.productBarcodes"
:key="index"
color="green"
closable
@close="removeBarcode(index)"
>
{{ barcode }}
</a-tag>
</div>
</div>
<!-- 添加新条码 -->
<div style="margin-top: 8px; display: flex; gap: 10px;">
<a-input
v-model:value="newBarcodeInput"
placeholder="请输入商品条码,验证库存后添加"
size="large"
style="flex: 1;"
@pressEnter="handleAddBarcode"
/>
<a-button
type="primary"
size="large"
@click="handleAddBarcode"
:loading="checkingInventory"
>
验证并添加
</a-button>
</div>
</template>
<!-- 库存检查结果(临时显示) -->
<div v-if="inventoryCheckResult" class="inventory-result" :class="{ 'success': inventoryCheckResult.canPublish, 'error': !inventoryCheckResult.canPublish }">
@ -2184,6 +2205,11 @@ const loadPrimaryTaskForEdit = async () => {
formData.releaseType = task.releaseType || 'recruitment'
formData.isUrgent = task.isUrgent === 1 || task.isUrgent === true
// 加载商品条码(一级需求发起人填写的)
if (task.productBarcodes) {
formData.productBarcodes = task.productBarcodes.split(',').filter((b: string) => b.trim())
}
// 处理预览图
if (task.previewImage) {
formData.previewImage = task.previewImage