qiangdanxitong/docs/任务节点查询功能开发文档.md

500 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 任务节点查询功能开发文档
## 1. 需求背景
用户反馈经常找不到任务当前处于什么节点,不清楚:
- 任务当前状态是什么
- 下一步需要谁操作
- 任务经历了哪些审批流程
因此需要开发一个**任务节点查询功能**,让用户可以通过任务编号快速查询任务的流程状态。
---
## 2. 功能设计
### 2.1 功能入口
在页面顶部导航栏或任务大厅页面增加「任务查询」按钮,点击后弹出查询对话框。
### 2.2 查询方式
- **任务编号查询**:输入完整的任务编号(如 `TASK202601221029343146`)
- **模糊搜索**:支持输入任务标题关键字搜索
### 2.3 展示内容
#### 基本信息卡片
| 字段 | 说明 |
|------|------|
| 任务编号 | TASK202601221029343146 |
| 任务标题 | AD0259-欧意朗-天猫 |
| 任务类型 | 一级需求任务 / 普通任务 |
| 任务积分 | 5.20 分 |
| 创建时间 | 2026-01-22 10:29:34 |
#### 当前节点信息(重点展示)
```
┌─────────────────────────────────────────────┐
│ 📍 当前节点:待接单部门审核 │
│ │
│ 等待操作人:清云(营销策划中心) │
│ 操作说明:接单部门负责人需审核此任务 │
└─────────────────────────────────────────────┘
```
#### 流程时间线(可视化展示)
```
● 一级需求发起 2026-01-22 10:29:34 瑶池(亿家达组)
↓
● 一级需求审批通过 2026-01-22 13:46:56 步惊云(策划三部)
↓
● 明细完善完成 2026-01-23 10:44:24 殷云(策划四部)
↓
○ 接单部门审核 等待中... 清云(营销策划中心) ← 当前
↓
○ 任务发布 - -
```
#### 相关人员信息
| 角色 | 姓名 | 部门 |
|------|------|------|
| 发起人 | 瑶池 | 亿家达组 |
| 明细完善人 | 殷云 | 策划四部 |
| 接单人 | 乐游 | 平面视觉五组 |
| 当前审批人 | 清云 | 营销策划中心 |
---
## 3. 任务状态映射表
### 3.1 普通任务状态
| approval_status | 中文名称 | 说明 |
|-----------------|----------|------|
| draft | 草稿 | 任务已创建但未提交 |
| pending_approval | 待审核 | 等待需求部门负责人审核 |
| approved | 已审核 | 审核通过,任务已发布 |
| rejected | 已驳回 | 审核被驳回 |
### 3.2 一级需求任务状态
| approval_status | 中文名称 | 当前操作人角色 | 说明 |
|-----------------|----------|----------------|------|
| draft | 草稿 | 发起人 | 任务已创建但未提交 |
| pending_primary_approval | 待一级需求审批 | 需求部门负责人 | 等待需求部门负责人审核并指定明细完善人 |
| pending_detail_completion | 待完善明细 | 明细完善人 | 等待指定的明细完善人填写任务明细 |
| pending_demand_approval | 待需求部门审批 | 需求部门负责人 | 明细完善后等待需求部门负责人审核 |
| pending_receiving_approval | 待接单部门审批 | 接单部门负责人 | 等待接单部门负责人审核 |
| approved | 已审核 | - | 所有审批通过,任务已发布 |
| rejected_by_demand | 需求部门驳回 | 明细完善人 | 被需求部门负责人驳回 |
| rejected_by_receiving | 接单部门驳回 | 需求部门负责人 | 被接单部门负责人驳回 |
### 3.3 任务执行状态
| status | 中文名称 | 说明 |
|--------|----------|------|
| draft | 草稿 | 未提交 |
| pending_audit | 待审核 | 审批流程中 |
| pending | 待接单/进行中 | 已发布等待接单或执行中 |
| in_progress | 进行中 | 设计师正在执行 |
| completed | 已完成 | 任务完成 |
| cancelled | 已取消 | 任务被取消 |
---
## 4. 技术实现
### 4.1 后端接口
#### 4.1.1 任务节点查询接口
**接口地址**:`GET /api/task/flow-status`
**请求参数**:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| taskNo | String | 否 | 任务编号 |
| keyword | String | 否 | 任务标题关键字 |
**响应示例**:
```json
{
"code": 200,
"message": "success",
"data": {
"task": {
"id": 432,
"taskNo": "TASK202601221029343146",
"title": "AD0259-欧意朗-天猫",
"score": 5.20,
"isPrimaryTask": true,
"createTime": "2026-01-22 10:29:34"
},
"currentNode": {
"status": "pending_receiving_approval",
"statusName": "待接单部门审批",
"description": "等待接单部门负责人审核此任务",
"waitingFor": {
"userId": 17,
"userName": "清云",
"deptName": "营销策划中心",
"role": "接单部门负责人"
}
},
"flowTimeline": [
{
"nodeName": "一级需求发起",
"status": "completed",
"operatorName": "瑶池",
"operatorDept": "亿家达组",
"time": "2026-01-22 10:29:34"
},
{
"nodeName": "一级需求审批",
"status": "completed",
"operatorName": "步惊云",
"operatorDept": "策划三部",
"time": "2026-01-22 13:46:56",
"comment": "审核通过,请完善任务明细"
},
{
"nodeName": "明细完善",
"status": "completed",
"operatorName": "殷云",
"operatorDept": "策划四部",
"time": "2026-01-23 10:44:24"
},
{
"nodeName": "接单部门审批",
"status": "pending",
"operatorName": "清云",
"operatorDept": "营销策划中心",
"time": null
},
{
"nodeName": "任务发布",
"status": "waiting",
"operatorName": null,
"operatorDept": null,
"time": null
}
],
"relatedUsers": {
"publisher": { "name": "瑶池", "dept": "亿家达组" },
"detailCompleter": { "name": "殷云", "dept": "策划四部" },
"receiver": { "name": "乐游", "dept": "平面视觉五组" },
"currentApprover": { "name": "清云", "dept": "营销策划中心" }
}
}
}
```
### 4.2 后端实现
#### 4.2.1 Controller 层
```java
// TaskController.java
/**
* 查询任务流程状态
*/
@GetMapping("/flow-status")
public Result<TaskFlowStatusVO> getTaskFlowStatus(
@RequestParam(required = false) String taskNo,
@RequestParam(required = false) String keyword) {
return Result.success(taskService.getTaskFlowStatus(taskNo, keyword));
}
```
#### 4.2.2 Service 层
```java
// TaskService.java
/**
* 获取任务流程状态
*/
public TaskFlowStatusVO getTaskFlowStatus(String taskNo, String keyword) {
// 1. 查询任务
Task task = findTaskByNoOrKeyword(taskNo, keyword);
if (task == null) {
throw new BusinessException("任务不存在");
}
// 2. 构建基本信息
TaskFlowStatusVO vo = new TaskFlowStatusVO();
vo.setTask(buildTaskInfo(task));
// 3. 构建当前节点信息
vo.setCurrentNode(buildCurrentNode(task));
// 4. 构建流程时间线
vo.setFlowTimeline(buildFlowTimeline(task));
// 5. 构建相关人员信息
vo.setRelatedUsers(buildRelatedUsers(task));
return vo;
}
```
#### 4.2.3 VO 类
```java
// TaskFlowStatusVO.java
@Data
public class TaskFlowStatusVO {
private TaskBasicInfo task;
private CurrentNodeInfo currentNode;
private List<FlowTimelineNode> flowTimeline;
private RelatedUsers relatedUsers;
@Data
public static class TaskBasicInfo {
private Long id;
private String taskNo;
private String title;
private BigDecimal score;
private Boolean isPrimaryTask;
private LocalDateTime createTime;
}
@Data
public static class CurrentNodeInfo {
private String status;
private String statusName;
private String description;
private WaitingUser waitingFor;
}
@Data
public static class WaitingUser {
private Long userId;
private String userName;
private String deptName;
private String role;
}
@Data
public static class FlowTimelineNode {
private String nodeName;
private String status; // completed, pending, waiting
private String operatorName;
private String operatorDept;
private LocalDateTime time;
private String comment;
}
@Data
public static class RelatedUsers {
private UserInfo publisher;
private UserInfo detailCompleter;
private UserInfo receiver;
private UserInfo currentApprover;
}
@Data
public static class UserInfo {
private String name;
private String dept;
}
}
```
### 4.3 前端实现
#### 4.3.1 查询对话框组件
```vue
<!-- TaskFlowQueryDialog.vue -->
<template>
<el-dialog title="任务节点查询" v-model="visible" width="700px">
<!-- 搜索框 -->
<div class="search-box">
<el-input
v-model="searchInput"
placeholder="请输入任务编号或任务标题"
@keyup.enter="handleSearch"
clearable>
<template #append>
<el-button @click="handleSearch" :loading="loading">
<el-icon><Search /></el-icon> 查询
</el-button>
</template>
</el-input>
</div>
<!-- 查询结果 -->
<div v-if="result" class="result-container">
<!-- 基本信息 -->
<el-card class="info-card">
<template #header>任务信息</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="任务编号">{{ result.task.taskNo }}</el-descriptions-item>
<el-descriptions-item label="任务标题">{{ result.task.title }}</el-descriptions-item>
<el-descriptions-item label="任务类型">
<el-tag :type="result.task.isPrimaryTask ? 'warning' : ''">
{{ result.task.isPrimaryTask ? '一级需求任务' : '普通任务' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="任务积分">{{ result.task.score }} 分</el-descriptions-item>
</el-descriptions>
</el-card>
<!-- 当前节点(重点展示) -->
<el-card class="current-node-card">
<div class="current-node">
<div class="node-icon">📍</div>
<div class="node-info">
<div class="node-status">当前节点:{{ result.currentNode.statusName }}</div>
<div class="node-waiting">
等待操作人:{{ result.currentNode.waitingFor?.userName }}
({{ result.currentNode.waitingFor?.deptName }})
</div>
<div class="node-desc">{{ result.currentNode.description }}</div>
</div>
</div>
</el-card>
<!-- 流程时间线 -->
<el-card class="timeline-card">
<template #header>流程进度</template>
<el-timeline>
<el-timeline-item
v-for="node in result.flowTimeline"
:key="node.nodeName"
:type="getTimelineType(node.status)"
:hollow="node.status !== 'completed'">
<div class="timeline-node">
<div class="node-name">{{ node.nodeName }}</div>
<div class="node-operator" v-if="node.operatorName">
{{ node.operatorName }}({{ node.operatorDept }})
</div>
<div class="node-time" v-if="node.time">{{ formatTime(node.time) }}</div>
<div class="node-comment" v-if="node.comment">备注:{{ node.comment }}</div>
</div>
</el-timeline-item>
</el-timeline>
</el-card>
</div>
<!-- 空状态 -->
<el-empty v-else-if="searched && !result" description="未找到相关任务" />
</el-dialog>
</template>
```
#### 4.3.2 样式设计
```scss
.current-node-card {
margin: 16px 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
.current-node {
display: flex;
align-items: center;
color: #fff;
.node-icon {
font-size: 48px;
margin-right: 20px;
}
.node-status {
font-size: 20px;
font-weight: bold;
margin-bottom: 8px;
}
.node-waiting {
font-size: 16px;
margin-bottom: 4px;
}
.node-desc {
font-size: 14px;
opacity: 0.9;
}
}
}
.timeline-card {
.timeline-node {
.node-name {
font-weight: bold;
font-size: 15px;
}
.node-operator {
color: #409eff;
margin-top: 4px;
}
.node-time {
color: #909399;
font-size: 12px;
margin-top: 4px;
}
.node-comment {
color: #67c23a;
font-size: 12px;
margin-top: 4px;
}
}
}
```
---
## 5. 功能入口位置
### 5.1 方案A:顶部导航栏
在导航栏右侧增加「🔍 任务查询」按钮,全局可用。
### 5.2 方案B:任务大厅页面
在任务大厅页面顶部筛选区域增加「任务节点查询」按钮。
### 5.3 方案C:快捷搜索框
在页面顶部增加全局搜索框,支持直接输入任务编号快速查询。
**推荐方案**:方案A + 方案C 组合,既有明显入口,又支持快捷查询。
---
## 6. 权限控制
| 用户角色 | 可查询范围 |
|----------|-----------|
| 管理员 | 所有任务 |
| 需求部门成员 | 本部门发起的任务 + 自己参与的任务 |
| 接单部门成员 | 自己接单的任务 + 本部门的任务 |
| 普通用户 | 自己发起或参与的任务 |
---
## 7. 开发工作量估算
| 模块 | 工作内容 | 预估时间 |
|------|----------|----------|
| 后端 | 接口开发、VO类、Service逻辑 | 4小时 |
| 前端 | 对话框组件、时间线、样式 | 4小时 |
| 测试 | 功能测试、边界情况 | 2小时 |
| **合计** | | **10小时** |
---
## 8. 后续扩展
1. **消息通知集成**:在通知消息中增加「查看任务进度」链接
2. **批量查询**:支持一次查询多个任务的状态
3. **导出功能**:支持导出任务流程记录
4. **订阅提醒**:用户可订阅任务状态变更通知