feat: 实现子任务组审核功能
- 修改子任务完成逻辑,解锁后的子任务组设置为pending_group_approval状态 - 添加子任务组审核API(approveTaskGroup, rejectTaskGroup) - 在待审核Tab中集成子任务组显示,统一管理主任务和子任务组审核 - 子任务组卡片显示子任务组标识 - 审核时支持选择发布到大厅或指定设计师 - 修复通知图标样式,与系统设置图标对齐统一
This commit is contained in:
parent
2a7f9f7cd7
commit
6314d2e034
@ -535,3 +535,38 @@ export const rejectByReceivingLeader = (taskId: number, reason: string) => {
|
||||
return request.post<any>(`/tasks/${taskId}/reject-receiving`, { reason })
|
||||
}
|
||||
|
||||
// ==================== 子任务组审核相关 ====================
|
||||
|
||||
/**
|
||||
* 子任务组信息
|
||||
*/
|
||||
export interface TaskGroup {
|
||||
groupId: number
|
||||
mainTaskId: number
|
||||
mainTaskTitle: string
|
||||
mainTaskNo: string
|
||||
items: TaskItem[]
|
||||
totalScore: number
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取待审核的子任务组列表
|
||||
*/
|
||||
export const getPendingApprovalTaskGroups = () => {
|
||||
return request.get<TaskGroup[]>('/tasks/items/pending-approval-groups')
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核通过子任务组
|
||||
*/
|
||||
export const approveTaskGroup = (groupId: number, data: { assignedReceiverId?: number; comment?: string }) => {
|
||||
return request.post<any>(`/tasks/items/groups/${groupId}/approve`, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* 驳回子任务组
|
||||
*/
|
||||
export const rejectTaskGroup = (groupId: number, reason: string) => {
|
||||
return request.post<any>(`/tasks/items/groups/${groupId}/reject`, { reason })
|
||||
}
|
||||
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
>
|
||||
<path
|
||||
d="M12 2.25a4.5 4.5 0 0 0-4.5 4.5V9c0 .414-.168.81-.467 1.098L5.21 11.82a1.125 1.125 0 0 0 .79 1.93h12a1.125 1.125 0 0 0 .79-1.93l-1.823-1.722A1.5 1.5 0 0 1 16.5 9V6.75a4.5 4.5 0 0 0-4.5-4.5Zm0 18.375a3.375 3.375 0 0 0 3.182-2.25H8.818A3.375 3.375 0 0 0 12 20.625Z"
|
||||
fill="#ffffff"
|
||||
stroke="#ffffff"
|
||||
fill="currentColor"
|
||||
stroke="currentColor"
|
||||
stroke-width="0"
|
||||
/>
|
||||
</svg>
|
||||
@ -263,20 +263,26 @@ onUnmounted(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.notification-bell {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: $radius-full;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: $text-secondary;
|
||||
cursor: pointer;
|
||||
padding: 8px 12px;
|
||||
border-radius: $radius-md;
|
||||
transition: all 0.2s ease-out;
|
||||
position: relative;
|
||||
transition: all $transition-base $ease-out;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
background: $bg-card;
|
||||
color: $text-primary;
|
||||
}
|
||||
|
||||
.bell-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
fill: currentColor;
|
||||
stroke: currentColor;
|
||||
stroke-width: 0;
|
||||
|
||||
@ -1560,47 +1560,55 @@
|
||||
<!-- 任务列表 - 使用统一的任务卡片样式 -->
|
||||
<div class="task-grid">
|
||||
<div
|
||||
v-for="task in pendingApprovalTasks"
|
||||
:key="task.id"
|
||||
v-for="item in pendingApprovalTasks"
|
||||
:key="`${item.type}-${item.id}`"
|
||||
class="task-card chart-card approval-card"
|
||||
@click="handleTaskClick(task)"
|
||||
@click="item.type === 'task' ? handleTaskClick(item.data) : null"
|
||||
>
|
||||
<!-- 任务标题 -->
|
||||
<div class="task-header">
|
||||
<h3 class="task-title">{{ task.title }}</h3>
|
||||
<h3 class="task-title">{{ item.title }}</h3>
|
||||
<div class="task-badges">
|
||||
<span class="badge badge-approval">
|
||||
<Icon name="file-text" size="sm" color="#31f08b" style="margin-right: 4px; vertical-align: middle;" />
|
||||
{{ getApprovalStatusText(task.approvalStatus) }}
|
||||
<span v-if="item.type === 'taskGroup'" class="badge badge-subtask">
|
||||
<Icon name="layers" size="sm" color="#31f08b" style="margin-right: 4px; vertical-align: middle;" />
|
||||
子任务组
|
||||
</span>
|
||||
<span v-if="task.isUrgent" class="badge badge-urgent">
|
||||
<span v-else class="badge badge-approval">
|
||||
<Icon name="file-text" size="sm" color="#31f08b" style="margin-right: 4px; vertical-align: middle;" />
|
||||
{{ getApprovalStatusText(item.data.approvalStatus) }}
|
||||
</span>
|
||||
<span v-if="item.isUrgent" class="badge badge-urgent">
|
||||
<Icon name="fire" size="sm" color="#31f08b" style="margin-right: 4px; vertical-align: middle;" />
|
||||
紧急
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 流程阶段 -->
|
||||
<div v-if="getProcessStage(task)" class="process-stage">
|
||||
<!-- 流程阶段(仅主任务) -->
|
||||
<div v-if="item.type === 'task' && getProcessStage(item.data)" class="process-stage">
|
||||
<span class="stage-icon">
|
||||
<Icon name="clock" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span class="stage-text">{{ getProcessStage(task) }}</span>
|
||||
<span class="stage-text">{{ getProcessStage(item.data) }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 任务信息 -->
|
||||
<div class="task-info">
|
||||
<div class="info-item">
|
||||
<div v-if="item.type === 'task'" class="info-item">
|
||||
<span class="label">任务类型</span>
|
||||
<span class="value">{{ getTaskTypeName(task.taskTypeId) }}</span>
|
||||
<span class="value">{{ getTaskTypeName(item.data.taskTypeId) }}</span>
|
||||
</div>
|
||||
<div v-if="item.type === 'taskGroup'" class="info-item">
|
||||
<span class="label">子任务数量</span>
|
||||
<span class="value">{{ item.data.items?.length || 0 }} 个</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">预估积分</span>
|
||||
<span class="value text-brand">{{ task.score }} 分</span>
|
||||
<span class="value text-brand">{{ item.score }} 分</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<div v-if="item.type === 'task'" class="info-item">
|
||||
<span class="label">数量</span>
|
||||
<span class="value">{{ task.quantity || '--' }} 个</span>
|
||||
<span class="value">{{ item.data.quantity || '--' }} 个</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1610,94 +1618,97 @@
|
||||
<span class="icon">
|
||||
<Icon name="hash" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>任务编号: {{ task.taskNo }}</span>
|
||||
<span>任务编号: {{ item.taskNo }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<div v-if="item.publisherName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="user" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>发起人: {{ task.publisherName || '未知' }}</span>
|
||||
<span>发起人: {{ item.publisherName || '未知' }}</span>
|
||||
</div>
|
||||
<div v-if="task.publisherDeptName" class="detail-item">
|
||||
<div v-if="item.publisherDeptName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="users" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>发起部门: {{ task.publisherDeptName }}</span>
|
||||
</div>
|
||||
<div v-if="task.brandName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="tag" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>品牌: {{ task.brandName }}</span>
|
||||
</div>
|
||||
<div v-if="task.categoryName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="folder" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>类目: {{ task.categoryName }}</span>
|
||||
</div>
|
||||
<div v-if="task.platformName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="monitor" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>平台: {{ task.platformName }}</span>
|
||||
</div>
|
||||
<div v-if="task.spuInfo" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="package" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>SPU: {{ task.spuInfo }}</span>
|
||||
</div>
|
||||
<div v-if="task.remark" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="message-square" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>备注: {{ task.remark }}</span>
|
||||
</div>
|
||||
<div v-if="task.attachmentUrl" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="paperclip" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>附件:
|
||||
<a
|
||||
v-for="(url, index) in (task.attachmentUrl || '').split(',').filter(u => u.trim())"
|
||||
:key="index"
|
||||
:href="url.trim()"
|
||||
target="_blank"
|
||||
class="attachment-link"
|
||||
@click.stop
|
||||
>
|
||||
附件{{ index + 1 }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="clock" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>截止: {{ formatDeadline(task.deadline) }}</span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="calendar" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>发起时间: {{ formatTime(task.createTime) }}</span>
|
||||
<span>发起部门: {{ item.publisherDeptName }}</span>
|
||||
</div>
|
||||
<template v-if="item.type === 'task'">
|
||||
<div v-if="item.data.brandName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="tag" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>品牌: {{ item.data.brandName }}</span>
|
||||
</div>
|
||||
<div v-if="item.data.categoryName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="folder" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>类目: {{ item.data.categoryName }}</span>
|
||||
</div>
|
||||
<div v-if="item.data.platformName" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="monitor" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>平台: {{ item.data.platformName }}</span>
|
||||
</div>
|
||||
<div v-if="item.data.spuInfo" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="package" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>SPU: {{ item.data.spuInfo }}</span>
|
||||
</div>
|
||||
<div v-if="item.data.remark" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="message-square" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>备注: {{ item.data.remark }}</span>
|
||||
</div>
|
||||
<div v-if="item.data.attachmentUrl" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="paperclip" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>附件:
|
||||
<a
|
||||
v-for="(url, index) in (item.data.attachmentUrl || '').split(',').filter(u => u.trim())"
|
||||
:key="index"
|
||||
:href="url.trim()"
|
||||
target="_blank"
|
||||
class="attachment-link"
|
||||
@click.stop
|
||||
>
|
||||
附件{{ index + 1 }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="item.deadline" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="clock" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>截止: {{ formatDeadline(item.deadline) }}</span>
|
||||
</div>
|
||||
<div v-if="item.createTime" class="detail-item">
|
||||
<span class="icon">
|
||||
<Icon name="calendar" size="sm" color="#31f08b" />
|
||||
</span>
|
||||
<span>发起时间: {{ formatTime(item.createTime) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- 审核操作按钮 -->
|
||||
<div class="task-actions" @click.stop>
|
||||
<button
|
||||
v-if="item.type === 'task'"
|
||||
class="btn btn-secondary"
|
||||
style="flex: 1"
|
||||
@click.stop="handleTaskClick(task)"
|
||||
@click.stop="handleTaskClick(item.data)"
|
||||
>
|
||||
查看详情
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
style="flex: 1"
|
||||
@click="handleApproveTwoLevelTask(task)"
|
||||
@click="item.type === 'task' ? handleApproveTwoLevelTask(item.data) : handleApproveTaskGroup(item)"
|
||||
:disabled="approvalLoading"
|
||||
>
|
||||
<Icon name="check" size="sm" style="margin-right: 4px;" />
|
||||
@ -1706,7 +1717,7 @@
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
style="flex: 1"
|
||||
@click="handleRejectTwoLevelTask(task)"
|
||||
@click="item.type === 'task' ? handleRejectTwoLevelTask(item.data) : handleRejectTaskGroup(item)"
|
||||
:disabled="approvalLoading"
|
||||
>
|
||||
<Icon name="x" size="sm" style="margin-right: 4px;" />
|
||||
@ -1946,8 +1957,22 @@ const reviewLoading = ref(false)
|
||||
const reviewTaskList = ref<Task[]>([])
|
||||
const reviewTotal = ref(0)
|
||||
|
||||
// 待我审核任务状态
|
||||
const pendingApprovalTasks = ref<Task[]>([])
|
||||
// 待我审核任务状态(包含主任务和子任务组)
|
||||
interface ApprovalItem {
|
||||
id: number
|
||||
type: 'task' | 'taskGroup' // 区分类型
|
||||
data: any // 主任务或子任务组数据
|
||||
title: string
|
||||
taskNo: string
|
||||
score: number
|
||||
deadline?: string | null
|
||||
createTime?: string | null
|
||||
isUrgent?: boolean | number
|
||||
publisherName?: string | null
|
||||
publisherDeptName?: string | null
|
||||
}
|
||||
|
||||
const pendingApprovalTasks = ref<ApprovalItem[]>([])
|
||||
const pendingApprovalTotal = ref(0)
|
||||
const approvalFilters = reactive({
|
||||
keyword: undefined as string | undefined
|
||||
@ -2309,27 +2334,73 @@ const handleTabChange = (key: string) => {
|
||||
|
||||
// ==================== 审核相关方法 ====================
|
||||
|
||||
// 加载待审核任务
|
||||
// 加载待审核任务(包含主任务和子任务组)
|
||||
const loadPendingApprovalTasks = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await taskApi.getPendingApprovalTasks()
|
||||
if (response.code === 200) {
|
||||
pendingApprovalTasks.value = response.data || []
|
||||
|
||||
// 如果有搜索关键词,进行本地过滤
|
||||
if (approvalFilters.keyword && approvalFilters.keyword.trim()) {
|
||||
const keyword = approvalFilters.keyword.trim().toLowerCase()
|
||||
pendingApprovalTasks.value = pendingApprovalTasks.value.filter(task =>
|
||||
task.title?.toLowerCase().includes(keyword) ||
|
||||
task.taskNo?.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
|
||||
pendingApprovalTotal.value = pendingApprovalTasks.value.length
|
||||
} else {
|
||||
message.error(response.msg || '加载待审核任务失败')
|
||||
|
||||
// 并行加载主任务和子任务组
|
||||
const [tasksResponse, groupsResponse] = await Promise.all([
|
||||
taskApi.getPendingApprovalTasks(),
|
||||
taskApi.getPendingApprovalTaskGroups()
|
||||
])
|
||||
|
||||
const approvalItems: ApprovalItem[] = []
|
||||
|
||||
// 转换主任务为ApprovalItem
|
||||
if (tasksResponse && tasksResponse.data) {
|
||||
const tasks = tasksResponse.data as Task[]
|
||||
tasks.forEach(task => {
|
||||
if (!task.id || !task.taskNo) return // 跳过无效任务
|
||||
|
||||
approvalItems.push({
|
||||
id: task.id,
|
||||
type: 'task',
|
||||
data: task,
|
||||
title: task.title,
|
||||
taskNo: task.taskNo,
|
||||
score: task.score || 0,
|
||||
deadline: task.deadline || null,
|
||||
createTime: task.createTime || null,
|
||||
isUrgent: !!task.isUrgent,
|
||||
publisherName: task.publisherName || null,
|
||||
publisherDeptName: task.publisherDeptName || null
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 转换子任务组为ApprovalItem
|
||||
if (groupsResponse && groupsResponse.data) {
|
||||
const groups = groupsResponse.data as taskApi.TaskGroup[]
|
||||
groups.forEach(group => {
|
||||
approvalItems.push({
|
||||
id: group.groupId,
|
||||
type: 'taskGroup',
|
||||
data: group,
|
||||
title: `${group.mainTaskTitle} - 第${group.groupId}组`,
|
||||
taskNo: group.mainTaskNo,
|
||||
score: group.totalScore || 0,
|
||||
deadline: null, // 子任务组没有独立的截止时间
|
||||
createTime: null,
|
||||
isUrgent: false,
|
||||
publisherName: null,
|
||||
publisherDeptName: null
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 如果有搜索关键词,进行本地过滤
|
||||
if (approvalFilters.keyword && approvalFilters.keyword.trim()) {
|
||||
const keyword = approvalFilters.keyword.trim().toLowerCase()
|
||||
pendingApprovalTasks.value = approvalItems.filter(item =>
|
||||
item.title?.toLowerCase().includes(keyword) ||
|
||||
item.taskNo?.toLowerCase().includes(keyword)
|
||||
)
|
||||
} else {
|
||||
pendingApprovalTasks.value = approvalItems
|
||||
}
|
||||
|
||||
pendingApprovalTotal.value = pendingApprovalTasks.value.length
|
||||
} catch (error: any) {
|
||||
console.error('加载待审核任务失败:', error)
|
||||
message.error(error.msg || error.message || '加载待审核任务失败')
|
||||
@ -2501,7 +2572,7 @@ const showAssignDesignerModal = async (task: Task) => {
|
||||
const approvalData: TaskApprovalDTO = {
|
||||
comment: assignType === 'manual' ?
|
||||
`指定设计师接单` : '审核通过,发布到任务大厅',
|
||||
assignedReceiverId: assignType === 'manual' ? selectedDesignerId : undefined
|
||||
assignedReceiverId: assignType === 'manual' && selectedDesignerId ? selectedDesignerId : undefined
|
||||
}
|
||||
|
||||
await taskApi.approveReceivingLevel(task.id!, approvalData)
|
||||
@ -2585,6 +2656,169 @@ const handleRejectTwoLevelTask = async (task: Task) => {
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== 子任务组审核相关方法 ====================
|
||||
|
||||
// 审核通过子任务组
|
||||
const handleApproveTaskGroup = async (item: ApprovalItem) => {
|
||||
try {
|
||||
// 获取设计师列表及工作量
|
||||
const designersWithWorkload = await userApi.getDesignersWithWorkload()
|
||||
|
||||
let assignType = ref<'auto' | 'manual'>('auto')
|
||||
let selectedDesignerId = ref<number | undefined>(undefined)
|
||||
|
||||
Modal.confirm({
|
||||
title: '审核子任务组',
|
||||
width: 600,
|
||||
content: h('div', { style: 'padding: 10px 0;' }, [
|
||||
h('p', { style: 'margin-bottom: 16px; color: #666; font-size: 13px;' },
|
||||
`即将审核通过子任务组"${item.title}",共${item.data.items?.length || 0}个子任务,总积分${item.score}分。`
|
||||
),
|
||||
h('p', { style: 'margin-bottom: 12px; font-weight: 500;' }, '请选择接单方式:'),
|
||||
h(RadioGroup, {
|
||||
value: assignType.value,
|
||||
onChange: (e: any) => {
|
||||
assignType.value = e.target.value
|
||||
if (e.target.value === 'auto') {
|
||||
selectedDesignerId.value = undefined
|
||||
}
|
||||
}
|
||||
}, () => [
|
||||
h(Radio, { value: 'auto', style: { display: 'block', marginBottom: '12px' } }, () => '发布到任务大厅(设计师抢单)'),
|
||||
h(Radio, { value: 'manual', style: { display: 'block', marginBottom: '12px' } }, () => '指定设计师接单')
|
||||
]),
|
||||
h('div', {
|
||||
style: {
|
||||
display: assignType.value === 'manual' ? 'block' : 'none',
|
||||
marginTop: '16px',
|
||||
marginLeft: '24px'
|
||||
}
|
||||
}, [
|
||||
h('p', { style: 'margin-bottom: 8px; font-size: 13px; color: #666;' }, '选择设计师:'),
|
||||
h(RadioGroup, {
|
||||
value: selectedDesignerId.value,
|
||||
onChange: (e: any) => {
|
||||
selectedDesignerId.value = e.target.value
|
||||
},
|
||||
style: { width: '100%' }
|
||||
}, () => designersWithWorkload.map(designer => {
|
||||
const workloadColor = designer.inProgressCount === 0 ? '#52c41a'
|
||||
: designer.inProgressCount <= 3 ? '#faad14'
|
||||
: '#f5222d'
|
||||
|
||||
return h(Radio, {
|
||||
value: designer.id,
|
||||
style: {
|
||||
display: 'block',
|
||||
marginBottom: '8px',
|
||||
padding: '8px',
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: '4px'
|
||||
}
|
||||
}, () => h('div', { style: 'display: flex; justify-content: space-between; align-items: center;' }, [
|
||||
h('span', {}, `${designer.realName} (${designer.deptName || '未知部门'})`),
|
||||
h('span', {
|
||||
style: {
|
||||
fontSize: '12px',
|
||||
color: workloadColor,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
}, `进行中: ${designer.inProgressCount}个任务`)
|
||||
]))
|
||||
}))
|
||||
])
|
||||
]),
|
||||
okText: '确认审核通过',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
if (assignType.value === 'manual' && !selectedDesignerId.value) {
|
||||
message.warning('请选择设计师')
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
try {
|
||||
approvalLoading.value = true
|
||||
|
||||
await taskApi.approveTaskGroup(item.id, {
|
||||
assignedReceiverId: assignType.value === 'manual' ? selectedDesignerId.value : undefined
|
||||
})
|
||||
|
||||
if (assignType.value === 'manual') {
|
||||
const designer = designersWithWorkload.find(d => d.id === selectedDesignerId.value)
|
||||
message.success(`已审核通过并指定给设计师 ${designer?.realName}`)
|
||||
} else {
|
||||
message.success('已审核通过,子任务组已发布到任务大厅')
|
||||
}
|
||||
|
||||
// 刷新列表和数量
|
||||
loadPendingApprovalTasks()
|
||||
loadAllTabCounts()
|
||||
loadDashboardStats()
|
||||
} catch (error: any) {
|
||||
console.error('审核失败:', error)
|
||||
message.error(error.msg || error.message || '审核失败')
|
||||
return Promise.reject(error)
|
||||
} finally {
|
||||
approvalLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (error: any) {
|
||||
console.error('获取设计师列表失败:', error)
|
||||
message.error('获取设计师列表失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 驳回子任务组
|
||||
const handleRejectTaskGroup = async (item: ApprovalItem) => {
|
||||
let rejectReason = ''
|
||||
|
||||
Modal.confirm({
|
||||
title: '驳回子任务组',
|
||||
content: h('div', { style: 'padding: 10px 0;' }, [
|
||||
h('p', { style: 'margin-bottom: 12px; color: #666;' },
|
||||
`即将驳回子任务组"${item.title}",共${item.data.items?.length || 0}个子任务。`
|
||||
),
|
||||
h('p', { style: 'margin-bottom: 10px; color: #666;' }, '请输入驳回原因:'),
|
||||
h(Textarea, {
|
||||
rows: 4,
|
||||
placeholder: '请详细说明驳回原因',
|
||||
maxlength: 500,
|
||||
showCount: true,
|
||||
onChange: (e: any) => {
|
||||
rejectReason = e.target.value
|
||||
}
|
||||
})
|
||||
]),
|
||||
okText: '确认驳回',
|
||||
cancelText: '取消',
|
||||
okType: 'danger',
|
||||
onOk: async () => {
|
||||
if (!rejectReason || !rejectReason.trim()) {
|
||||
message.warning('请输入驳回原因')
|
||||
return Promise.reject()
|
||||
}
|
||||
|
||||
try {
|
||||
approvalLoading.value = true
|
||||
|
||||
await taskApi.rejectTaskGroup(item.id, rejectReason.trim())
|
||||
message.success('已驳回子任务组')
|
||||
|
||||
// 刷新列表和数量
|
||||
loadPendingApprovalTasks()
|
||||
loadAllTabCounts()
|
||||
loadDashboardStats()
|
||||
} catch (error: any) {
|
||||
console.error('驳回失败:', error)
|
||||
message.error(error.msg || error.message || '驳回失败')
|
||||
} finally {
|
||||
approvalLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 已完成任务分页变化
|
||||
const handleCompletedPageChange = (page: number) => {
|
||||
completedPagination.page = page
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user