fix: 修复接单部门审核弹窗的任务类型和数量显示问题

1. 添加层级任务类型数据加载,支持递归查找三级分类
2. 修复任务类型显示为'未知类型'的问题(支持从层级数据中递归查找)
3. 修复任务数量全部显示为1的问题(从typeDetails中获取实际数量)
4. 将添加任务类型改为级联选择器(树形结构)
This commit is contained in:
Your Name 2026-01-07 11:51:09 +08:00
parent 48afa392fc
commit c7fbcb2b56

View File

@ -1991,27 +1991,19 @@
</div>
</div>
<!-- 添加类型 -->
<!-- 添加类型(使用级联选择器) -->
<div class="add-type-row" style="margin-top: 12px; display: flex; gap: 8px;">
<a-select
v-model:value="newTaskTypeId"
<a-cascader
v-model:value="newTaskTypePath"
:options="taskTypeCascaderOptions"
placeholder="选择要添加的任务类型"
style="flex: 1"
allow-clear
change-on-select
:show-search="{ filter: cascaderFilter }"
:dropdown-style="{ background: '#262626' }"
>
<a-select-option v-for="type in demandTypes" :key="type.id" :value="type.id">
{{ type.name }}
</a-select-option>
</a-select>
<a-button type="primary" ghost style="border-color: #31f08b; color: #31f08b;" @click="() => {
if (newTaskTypeId && !approveTaskTypes.find(t => t.typeId === newTaskTypeId)) {
approveTaskTypes.push({ typeId: newTaskTypeId, quantity: 1 })
newTaskTypeId = undefined
} else if (newTaskTypeId) {
message.warning('该任务类型已添加')
}
}">
/>
<a-button type="primary" ghost style="border-color: #31f08b; color: #31f08b;" @click="handleAddApproveTaskType">
<Icon name="plus" size="sm" style="margin-right: 4px" /> 添加
</a-button>
</div>
@ -2364,6 +2356,7 @@ import DefaultLayout from '@/layouts/DefaultLayout.vue'
import Icon from '@/components/Icon.vue'
import * as taskApi from '@/api/task'
import * as userApi from '@/api/user'
import * as configApi from '@/api/config'
import type { Task, TaskApprovalDTO, TaskProduct } from '@/api/task'
import type { DesignerWithWorkload } from '@/api/user'
import { useConfigStore } from '@/stores/config'
@ -2485,6 +2478,38 @@ const brands = computed(() => configStore.brands)
const platforms = computed(() => configStore.platforms)
const categories = computed(() => configStore.categories)
// 层级任务类型数据(用于级联选择器)
const hierarchicalTaskTypes = ref<any[]>([])
// 递归查找任务类型(从层级数据中查找,支持三级分类)
const findTaskTypeById = (id: number, items: any[] = hierarchicalTaskTypes.value): any => {
for (const item of items) {
if (item.id === id) return item
if (item.children) {
const found = findTaskTypeById(id, item.children)
if (found) return found
}
}
return null
}
// 构建级联选择器选项
const taskTypeCascaderOptions = computed(() => {
const buildOptions = (items: any[]): any[] => {
return items.map(item => {
const option: any = {
value: item.id,
label: item.name
}
if (item.children && item.children.length > 0) {
option.children = buildOptions(item.children)
}
return option
})
}
return buildOptions(hierarchicalTaskTypes.value)
})
// 筛选条件
const filters = reactive({
taskTypeId: undefined as number | undefined,
@ -2573,7 +2598,10 @@ const getTaskTypeName = (typeId: number, taskTypeName?: string, taskSubType?: st
if (taskSubType) return taskSubType
// 如果有直接传入的类型名称,使用它
if (taskTypeName) return taskTypeName
// 从需求类型列表中查找
// 从层级数据中递归查找(支持三级分类)
const typeInfo = findTaskTypeById(typeId)
if (typeInfo) return typeInfo.name
// 兼容:从平铺列表中查找
const type = demandTypes.value.find(t => t.id === typeId)
return type?.name || '未知类型'
}
@ -2592,6 +2620,10 @@ const parseTypeDetails = (typeDetails: string | TaskTypeDetail[] | undefined): T
// 获取任务类型单位积分
const getTaskTypeUnitScore = (typeId: number) => {
// 从层级数据中递归查找(支持三级分类)
const typeInfo = findTaskTypeById(typeId)
if (typeInfo && typeInfo.unitScore) return typeInfo.unitScore
// 兼容:从平铺列表中查找
const type = demandTypes.value.find(t => t.id === typeId)
return type?.unitScore || 0
}
@ -2714,6 +2746,11 @@ const isHighScoreTask = (task: TaskOrSubTask) => {
const loadConfigs = async () => {
try {
await configStore.loadAllConfigs()
// 加载层级任务类型数据(用于级联选择器和递归查找)
const response = await configApi.getDemandTypesTree()
if (response && response.data) {
hierarchicalTaskTypes.value = response.data
}
} catch (error) {
console.error('加载配置数据失败:', error)
}
@ -3024,7 +3061,30 @@ const approveAssignType = ref<'auto' | 'manual'>('auto')
const approveTaskTypes = ref<Array<{typeId: number, quantity: number}>>([])
const approveDesignerId = ref<number | undefined>(undefined)
const designersList = ref<DesignerWithWorkload[]>([])
const newTaskTypeId = ref<number | undefined>(undefined)
const newTaskTypePath = ref<(string | number)[] | undefined>(undefined)
// 级联选择器搜索过滤
const cascaderFilter = (inputValue: string, path: any[]) => {
return path.some(option =>
option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
)
}
// 添加审核弹窗中的任务类型
const handleAddApproveTaskType = () => {
if (!newTaskTypePath.value || newTaskTypePath.value.length === 0) {
message.warning('请选择任务类型')
return
}
// 获取最后一个ID(即最深层级的类型ID)
const typeId = newTaskTypePath.value[newTaskTypePath.value.length - 1] as number
if (approveTaskTypes.value.find(t => t.typeId === typeId)) {
message.warning('该任务类型已添加')
return
}
approveTaskTypes.value.push({ typeId, quantity: 1 })
newTaskTypePath.value = undefined
}
// 格式化相对时间
const formatDeadlineRelative = (deadline: string) => {
@ -3067,17 +3127,34 @@ const showAssignDesignerModal = async (task: Task) => {
approveTaskData.value = task
approveAssignType.value = 'auto'
approveDesignerId.value = undefined
newTaskTypeId.value = undefined
newTaskTypePath.value = undefined
// 解析任务类型
const taskTypeIdsStr = task.taskTypeIds || task.taskTypeId?.toString() || ''
const taskTypeIdArray = taskTypeIdsStr.split(',').filter(id => id.trim())
// 解析任务类型 - 优先从 typeDetails 获取(包含每个类型的实际数量)
let typeDetailsArray: TaskTypeDetail[] = []
if ((task as any).typeDetails) {
try {
const details = (task as any).typeDetails
typeDetailsArray = typeof details === 'string' ? JSON.parse(details) : details
} catch (e) {
console.warn('解析 typeDetails 失败:', e)
}
}
// 初始化任务类型列表
approveTaskTypes.value = taskTypeIdArray.map(id => ({
typeId: parseInt(id.trim()),
quantity: task.quantity || 1
}))
// 如果有 typeDetails,从中获取任务类型和数量
if (typeDetailsArray.length > 0) {
approveTaskTypes.value = typeDetailsArray.map(detail => ({
typeId: detail.typeId,
quantity: detail.quantity || 1
}))
} else {
// 兼容旧数据:从 taskTypeIds 获取
const taskTypeIdsStr = task.taskTypeIds || task.taskTypeId?.toString() || ''
const taskTypeIdArray = taskTypeIdsStr.split(',').filter(id => id.trim())
approveTaskTypes.value = taskTypeIdArray.map(id => ({
typeId: parseInt(id.trim()),
quantity: task.quantity || 1
}))
}
approveModalVisible.value = true
} catch (error: any) {