在创建急救转运任务时,将第一个执行人员的ID写入主任务表的 assignee_id 字段,作为主要执行人(负责人)。
急救转运任务通常由多个人员协同执行(司机、护士、医生等),但系统需要明确一个主要负责人:
- assignee_id:主要执行人(通常是第一个选择的人员)
- assigneeIds:所有执行人员ID列表(关联表 sys_task_assignee)
在 buildSubmitData() 方法中添加 assigneeId 字段:
const submitData = {
taskType: 'EMERGENCY_TRANSFER',
vehicleIds: this.selectedVehicleId ? [this.selectedVehicleId] : [],
assigneeIds: this.selectedStaff.map(staff => staff.userId), // 所有执行人员ID列表
assigneeId: this.selectedStaff.length > 0 ? this.selectedStaff[0].userId : null, // 主要执行人(第一个人员)
// ... 其他字段
}
主任务表(sys_task):
-- 主要执行人ID(单个)
assignee_id BIGINT
-- 主要执行人姓名(冗余字段,便于查询显示)
assignee_name VARCHAR(100)
关联表(sys_task_assignee):
-- 任务与执行人员的多对多关联表
CREATE TABLE sys_task_assignee (
id BIGINT PRIMARY KEY,
task_id BIGINT NOT NULL, -- 任务ID
user_id BIGINT NOT NULL, -- 执行人员ID
user_name VARCHAR(100), -- 执行人员姓名
is_primary CHAR(1) DEFAULT '0' -- 是否主要执行人:0-否,1-是
)
selectedStaff: [
{
userId: 1,
nickName: "张三",
phonenumber: "13800138000",
deptName: "广州分公司",
postName: "司机",
roleName: "普通员工"
},
{
userId: 2,
nickName: "李四",
phonenumber: "13800138001",
deptName: "广州分公司",
postName: "护士",
roleName: "普通员工"
},
{
userId: 3,
nickName: "王五",
phonenumber: "13800138002",
deptName: "广州分公司",
postName: "医生",
roleName: "普通员工"
}
]
{
taskType: "EMERGENCY_TRANSFER",
assigneeId: 1, // 主要执行人(张三)
assigneeIds: [1, 2, 3], // 所有执行人员
// ... 其他字段
}
主任务表(sys_task):
| 字段 | 值 | 说明 |
|---|---|---|
| task_id | 10001 | 任务ID |
| assignee_id | 1 | 主要执行人ID(张三) |
| assignee_name | 张三 | 主要执行人姓名 |
关联表(sys_task_assignee):
| id | task_id | user_id | user_name | is_primary |
|---|---|---|---|---|
| 1 | 10001 | 1 | 张三 | 1 |
| 2 | 10001 | 2 | 李四 | 0 |
| 3 | 10001 | 3 | 王五 | 0 |
selectedStaff[0] 自动成为主要执行人assigneeId = null<view class="staff-list">
<view class="staff-item" v-for="(staff, index) in selectedStaff" :key="staff.userId">
<view class="staff-info">
<text class="staff-name">{{ staff.nickName }}</text>
<text class="staff-role">({{ staff.postName || staff.roleName }})</text>
<!-- 第一个人员显示"负责人"标识 -->
<text v-if="index === 0" class="primary-badge">负责人</text>
</view>
<!-- 第一个人员不能删除 -->
<uni-icons
v-if="index > 0"
type="closeempty"
@click="removeStaff(index)"
></uni-icons>
<uni-icons
v-else
type="checkmarkempty"
color="#007AFF"
></uni-icons>
</view>
</view>
系统发送任务通知时,主要执行人收到详细信息,其他人员收到协助通知:
// 通知主要执行人
sendNotification({
userId: task.assigneeId,
title: '您有新的转运任务',
content: `任务编号:${task.taskCode},您是本次任务的负责人`,
type: 'PRIMARY_ASSIGNEE'
})
// 通知其他执行人员
task.assigneeIds.filter(id => id !== task.assigneeId).forEach(userId => {
sendNotification({
userId,
title: '您有新的协助任务',
content: `任务编号:${task.taskCode},请协助完成`,
type: 'ASSIST_ASSIGNEE'
})
})
任务列表主要显示负责人信息:
<view class="task-item">
<text class="task-code">{{ task.taskCode }}</text>
<text class="assignee">负责人:{{ task.assigneeName }}</text>
<text class="staff-count" v-if="task.assigneeIds.length > 1">
+{{ task.assigneeIds.length - 1 }}人协助
</text>
</view>
主要执行人拥有更多操作权限:
// 判断当前用户是否是主要执行人
const isPrimaryAssignee = currentUser.userId === task.assigneeId
// 主要执行人可以操作的功能
if (isPrimaryAssignee) {
// 可以修改任务状态
// 可以添加/移除其他执行人员
// 可以填写任务报告
}
按主要执行人统计任务完成情况:
SELECT
u.user_name,
COUNT(*) AS total_tasks,
SUM(CASE WHEN t.task_status = 'COMPLETED' THEN 1 ELSE 0 END) AS completed_tasks,
AVG(TIMESTAMPDIFF(MINUTE, t.actual_start_time, t.actual_end_time)) AS avg_duration
FROM sys_task t
JOIN sys_user u ON t.assignee_id = u.user_id
WHERE t.task_type = 'EMERGENCY_TRANSFER'
AND t.create_time >= '2025-01-01'
GROUP BY u.user_name
ORDER BY completed_tasks DESC
场景:用户未选择任何执行人员
处理:javascript assigneeId: this.selectedStaff.length > 0 ? this.selectedStaff[0].userId : null
结果:assignee_id 为 NULL,允许后续补充
场景:用户先选择了A,后来删除A并选择了B
处理:
- 始终以 selectedStaff[0] 为准
- 删除第一个人员后,原来的第二个人员自动成为负责人
建议后端进行验证:
// Service层验证
if (taskCreateVO.getAssigneeIds() != null && !taskCreateVO.getAssigneeIds().isEmpty()) {
// assigneeId 必须在 assigneeIds 列表中
if (taskCreateVO.getAssigneeId() != null) {
if (!taskCreateVO.getAssigneeIds().contains(taskCreateVO.getAssigneeId())) {
throw new ServiceException("主要执行人必须在执行人员列表中");
}
} else {
// 如果没有指定 assigneeId,默认使用第一个
taskCreateVO.setAssigneeId(taskCreateVO.getAssigneeIds().get(0));
}
}
assigneeId = selectedStaff[0].userId操作:
1. 选择执行人员:张三、李四、王五
2. 保存任务
验证:
```sql
-- 检查主任务表
SELECT assignee_id, assignee_name FROM sys_task WHERE task_id = ?
-- 预期:assignee_id = 1(张三的ID),assignee_name = '张三'
-- 检查关联表
SELECT * FROM sys_task_assignee WHERE task_id = ? ORDER BY user_id
-- 预期:3条记录,张三的 is_primary = '1',其他为 '0'
```
操作:
1. 只选择张三
2. 保存任务
验证:
- assignee_id = 1
- assigneeIds = [1]
- 关联表只有1条记录
操作:
1. 不选择任何执行人员
2. 保存任务
验证:
- assignee_id = NULL
- assigneeIds = []
- 关联表无记录
操作:
1. 选择张三、李四
2. 删除张三
3. 现在李四是第一个
4. 保存任务
验证:
- assignee_id = 2(李四的ID)
- assignee_name = '李四'