fix: 修复8个bug + 确保任务必须审核通过后才能发布到大厅
Bug修复: 1. 驳回任务卡片显示'草稿'改为'驳回',显示驳回时间 2. 重新编辑被驳回任务时加载原有信息 3. 任务详情页关联信息显示不全 4. 任务卡片发布时间显示到时分 5. 被指定任务卡片增加'指定'标识 6. 设计师在已完成任务中看不到完成的任务 7. 设计师更新进度后需求方看到的进度还是0% 8. 完结任务卡片无法查看交付路径和填写商品ID 审核流程修复: - TaskMapper: 任务大厅查询添加 approval_status='approved' 条件 - TaskItemMapper: 子任务查询添加 t.approval_status='approved' 条件 - 确保只有审核通过的任务才能发布到任务大厅
This commit is contained in:
parent
80241a394d
commit
3ba4a5f7f7
@ -44,7 +44,7 @@ public interface TaskItemMapper extends BaseMapper<TaskItem> {
|
||||
"LEFT JOIN category c ON t.category_id = c.id " +
|
||||
"LEFT JOIN platform p ON t.platform_id = p.id " +
|
||||
"LEFT JOIN demand_type dt ON ti.task_type_id = dt.id " +
|
||||
"WHERE ti.status = 'pending' AND ti.is_locked = 0 AND t.deleted = 0 " +
|
||||
"WHERE ti.status = 'pending' AND ti.is_locked = 0 AND t.deleted = 0 AND t.approval_status = 'approved' " +
|
||||
"<if test='taskTypeId != null'> AND ti.task_type_id = #{taskTypeId}</if> " +
|
||||
"<if test='keyword != null and keyword != \"\"'> " +
|
||||
" AND (t.title LIKE CONCAT('%', #{keyword}, '%') " +
|
||||
|
||||
@ -36,7 +36,7 @@ public interface TaskMapper extends BaseMapper<Task> {
|
||||
"LEFT JOIN category c ON t.category_id = c.id " +
|
||||
"LEFT JOIN platform p ON t.platform_id = p.id " +
|
||||
"LEFT JOIN sys_user approver ON t.current_approver_id = approver.id " +
|
||||
"WHERE t.status = 'pending' AND t.release_type = 'recruitment' AND t.deleted = 0" +
|
||||
"WHERE t.status = 'pending' AND t.release_type = 'recruitment' AND t.approval_status = 'approved' AND t.deleted = 0" +
|
||||
"<if test='taskTypeId != null'> AND t.task_type_id = #{taskTypeId}</if>" +
|
||||
"<if test='demandTypeId != null'> AND t.demand_type_id = #{demandTypeId}</if>" +
|
||||
"<if test='brandId != null'> AND t.brand_id = #{brandId}</if>" +
|
||||
|
||||
@ -376,7 +376,7 @@
|
||||
:loading="submitting"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
发起任务
|
||||
{{ editMode ? '重新提交' : '发起任务' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</a-form>
|
||||
@ -387,8 +387,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { message } from 'ant-design-vue'
|
||||
import type { UploadFile, UploadProps } from 'ant-design-vue'
|
||||
import DefaultLayout from '@/layouts/DefaultLayout.vue'
|
||||
@ -404,8 +404,13 @@ import { useAuthStore } from '@/stores/auth'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// 编辑模式
|
||||
const editMode = ref(false)
|
||||
const editTaskId = ref<number | null>(null)
|
||||
|
||||
// 全局配置store
|
||||
const configStore = useConfigStore()
|
||||
|
||||
@ -797,13 +802,32 @@ const handleSubmit = async () => {
|
||||
receiverId: undefined // 主任务不设接收人,由子任务指定
|
||||
}
|
||||
|
||||
const response = await taskApi.createPipelineTask(pipelineData)
|
||||
let response: any
|
||||
|
||||
if (editMode.value && editTaskId.value) {
|
||||
// 编辑模式:更新任务并重新提交审核
|
||||
const updateData = {
|
||||
...pipelineData,
|
||||
id: editTaskId.value
|
||||
}
|
||||
response = await taskApi.updateTask(editTaskId.value, updateData)
|
||||
|
||||
if (response.code === 200) {
|
||||
message.success('任务已重新提交审核')
|
||||
setTimeout(() => {
|
||||
router.push('/tasks')
|
||||
}, 1000)
|
||||
}
|
||||
} else {
|
||||
// 新建模式
|
||||
response = await taskApi.createPipelineTask(pipelineData)
|
||||
|
||||
if (response.code === 200) {
|
||||
message.success('流水线任务创建成功')
|
||||
setTimeout(() => {
|
||||
router.push('/tasks')
|
||||
}, 1000)
|
||||
if (response.code === 200) {
|
||||
message.success('流水线任务创建成功')
|
||||
setTimeout(() => {
|
||||
router.push('/tasks')
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('发起任务失败:', error)
|
||||
@ -1010,6 +1034,59 @@ const handleRemove = (file: UploadFile) => {
|
||||
return true
|
||||
}
|
||||
|
||||
// 加载任务数据用于编辑
|
||||
const loadTaskForEdit = async (taskId: number) => {
|
||||
try {
|
||||
loading.value = true
|
||||
const response = await taskApi.getTaskById(taskId)
|
||||
const task = response.data
|
||||
|
||||
if (task) {
|
||||
// 填充表单数据
|
||||
formData.title = task.title || ''
|
||||
formData.taskSubType = task.taskSubType || ''
|
||||
formData.brandId = task.brandId
|
||||
formData.platformId = task.platformId
|
||||
formData.categoryId = task.categoryId
|
||||
formData.spuInfo = task.spuInfo || ''
|
||||
formData.remark = task.remark || ''
|
||||
formData.releaseType = task.releaseType || 'recruitment'
|
||||
|
||||
// 处理任务类型
|
||||
if (task.taskTypeIds) {
|
||||
const typeIds = task.taskTypeIds.split(',').map((id: string) => parseInt(id.trim()))
|
||||
formData.taskTypes = typeIds.map((typeId: number, index: number) => ({
|
||||
taskTypeId: typeId,
|
||||
quantity: index === 0 ? (task.quantity || 1) : 1,
|
||||
receiverId: task.receiverId
|
||||
}))
|
||||
}
|
||||
|
||||
// 处理附件
|
||||
if (task.attachmentUrl) {
|
||||
formData.attachmentUrl = task.attachmentUrl
|
||||
// 将附件URL转换为fileList格式
|
||||
const urls = task.attachmentUrl.split(',').filter((u: string) => u.trim())
|
||||
fileList.value = urls.map((url: string, index: number) => ({
|
||||
uid: `existing-${index}`,
|
||||
name: `附件${index + 1}`,
|
||||
status: 'done',
|
||||
url: url.trim()
|
||||
}))
|
||||
}
|
||||
|
||||
editMode.value = true
|
||||
editTaskId.value = taskId
|
||||
console.log('任务数据加载成功:', task)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载任务数据失败:', error)
|
||||
message.error('加载任务数据失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载
|
||||
onMounted(async () => {
|
||||
// 先刷新用户信息,确保部门信息最新
|
||||
@ -1027,6 +1104,12 @@ onMounted(async () => {
|
||||
loadTaskSubTypes()
|
||||
])
|
||||
|
||||
// 检查是否是编辑模式
|
||||
const editId = route.query.editId
|
||||
if (editId) {
|
||||
await loadTaskForEdit(Number(editId))
|
||||
}
|
||||
|
||||
// 监听配置更新事件
|
||||
window.addEventListener('configUpdated', handleConfigUpdate as EventListener)
|
||||
})
|
||||
|
||||
@ -1430,13 +1430,19 @@
|
||||
:key="task.id"
|
||||
class="task-card chart-card"
|
||||
:class="[`status-${task.status}`]"
|
||||
@click="handleTaskClick(task)"
|
||||
style="cursor: pointer;"
|
||||
>
|
||||
<!-- 任务标题 -->
|
||||
<div class="task-header">
|
||||
<h3 class="task-title">{{ task.title }}</h3>
|
||||
<div class="task-badges">
|
||||
<span :class="['badge', `status-${task.status}`]">
|
||||
{{ getTaskStatusText(task.status) }}
|
||||
<span :class="['badge', `status-${task.approvalStatus?.includes('rejected') ? 'rejected' : task.status}`]">
|
||||
{{ getTaskStatusText(task.status, task) }}
|
||||
</span>
|
||||
<span v-if="task.releaseType === 'assigned'" class="badge badge-assigned">
|
||||
<Icon name="target" size="sm" color="#1890ff" style="margin-right: 4px; vertical-align: middle;" />
|
||||
指定
|
||||
</span>
|
||||
<span v-if="task.isUrgent" class="badge badge-urgent">
|
||||
<Icon name="fire" size="sm" color="#31f08b" style="margin-right: 4px; vertical-align: middle;" />
|
||||
@ -1445,6 +1451,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 驳回原因显示 -->
|
||||
<div v-if="task.approvalStatus?.includes('rejected') && task.rejectReason" class="reject-info">
|
||||
<span class="reject-label">驳回原因:</span>
|
||||
<span class="reject-reason">{{ task.rejectReason }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 流程阶段 -->
|
||||
<div v-if="getProcessStage(task)" class="process-stage">
|
||||
<span class="stage-icon">
|
||||
@ -1560,16 +1572,21 @@
|
||||
<div class="task-footer">
|
||||
<div class="footer-item">
|
||||
<Icon name="calendar" size="sm" color="#31f08b" />
|
||||
<span style="color: #ffffff;">发布: {{ formatDate(task.createTime) }}</span>
|
||||
<span style="color: #ffffff;">发布: {{ formatTime(task.createTime) }}</span>
|
||||
</div>
|
||||
<div class="footer-item" v-if="task.deadline">
|
||||
<Icon name="clock" size="sm" color="#31f08b" />
|
||||
<span style="color: #ffffff;">截止: {{ formatDate(task.deadline) }}</span>
|
||||
<span style="color: #ffffff;">截止: {{ formatTime(task.deadline) }}</span>
|
||||
</div>
|
||||
<!-- 驳回时间 -->
|
||||
<div class="footer-item" v-if="task.approvalStatus?.includes('rejected') && task.updateTime">
|
||||
<Icon name="x-circle" size="sm" color="#f5222d" />
|
||||
<span style="color: #f5222d;">驳回: {{ formatTime(task.updateTime) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 被驳回或草稿任务的操作按钮 -->
|
||||
<div v-if="['rejected', 'draft'].includes(task.status)" class="task-actions" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(49, 240, 139, 0.2);">
|
||||
<div v-if="['rejected', 'draft'].includes(task.status) || task.approvalStatus?.includes('rejected')" class="task-actions" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(49, 240, 139, 0.2);">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@ -1579,6 +1596,18 @@
|
||||
重新编辑提交
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<!-- 已完成任务:查看详情和交付信息 -->
|
||||
<div v-if="task.status === 'completed'" class="task-actions" style="margin-top: 16px; padding-top: 16px; border-top: 1px solid rgba(49, 240, 139, 0.2);">
|
||||
<a-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click.stop="handleTaskClick(task)"
|
||||
style="width: 100%;">
|
||||
<Icon name="eye" size="sm" style="margin-right: 4px;" />
|
||||
查看详情
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1992,6 +2021,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 交付路径(已完成或待审核任务显示) -->
|
||||
<div v-if="selectedTask.deliveryPath && (selectedTask.status === 'completed' || selectedTask.status === 'review')" class="detail-section">
|
||||
<h4>
|
||||
<Icon name="link" size="sm" style="margin-right: 6px;" />
|
||||
交付路径
|
||||
</h4>
|
||||
<div class="delivery-path">
|
||||
<a v-if="selectedTask.deliveryPath.startsWith('http')"
|
||||
:href="selectedTask.deliveryPath"
|
||||
target="_blank"
|
||||
class="delivery-link">
|
||||
<Icon name="external-link" size="sm" style="margin-right: 4px;" />
|
||||
{{ selectedTask.deliveryPath }}
|
||||
</a>
|
||||
<p v-else class="delivery-text">{{ selectedTask.deliveryPath }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 商品ID管理(已完成任务显示) -->
|
||||
<div v-if="selectedTask.status === 'completed'" class="detail-section product-section">
|
||||
<h4>
|
||||
@ -3838,8 +3885,15 @@ const handleConfigUpdate = async (event: CustomEvent) => {
|
||||
}
|
||||
|
||||
// 组件挂载
|
||||
// 获取任务状态文本
|
||||
const getTaskStatusText = (status: string) => {
|
||||
// 获取任务状态文本(增强版,支持区分驳回和草稿)
|
||||
const getTaskStatusText = (status: string, task?: any) => {
|
||||
// 如果有task对象,检查approvalStatus来区分驳回和草稿
|
||||
if (task && status === 'draft') {
|
||||
if (task.approvalStatus === 'rejected_by_demand' || task.approvalStatus === 'rejected_by_receiving') {
|
||||
return '已驳回'
|
||||
}
|
||||
}
|
||||
|
||||
const statusMap: Record<string, string> = {
|
||||
'pending': '待接单',
|
||||
'in_progress': '进行中',
|
||||
@ -4359,6 +4413,55 @@ onUnmounted(() => {
|
||||
color: #31f08b;
|
||||
}
|
||||
|
||||
.badge-assigned {
|
||||
background: rgba(24, 144, 255, 0.1);
|
||||
border: 1px solid rgba(24, 144, 255, 0.2);
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
// 驳回信息显示
|
||||
.reject-info {
|
||||
margin: 12px 0;
|
||||
padding: 10px 12px;
|
||||
background: rgba(245, 34, 45, 0.08);
|
||||
border: 1px solid rgba(245, 34, 45, 0.2);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
|
||||
.reject-label {
|
||||
color: #f5222d;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.reject-reason {
|
||||
color: #ff7875;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
// 交付路径
|
||||
.delivery-path {
|
||||
padding: 12px;
|
||||
background: rgba(49, 240, 139, 0.05);
|
||||
border-radius: 6px;
|
||||
|
||||
.delivery-link {
|
||||
color: #31f08b;
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.delivery-text {
|
||||
color: #e0e0e0;
|
||||
margin: 0;
|
||||
word-break: break-all;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-completed {
|
||||
background: rgba(49, 240, 139, 0.1);
|
||||
color: #31f08b;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user