fix(label): fix task tool

This commit is contained in:
zhangheng
2026-04-20 15:42:20 +08:00
parent 67dcf85763
commit 9dab78ffac

View File

@@ -25,6 +25,7 @@ import {
import { useRouter } from "next/navigation"
import { useCallback, useEffect, useMemo, useState } from "react"
import { Project } from "../api/project/typing"
import { Task } from "../api/task/typing"
import { getTaskList } from "../api/task"
import { useObjectStore } from "../store"
import type { Option } from "../store/auth"
@@ -38,11 +39,54 @@ interface RightTaskToolsComponentProps {
task_id: number
}
interface FilterOption {
label: string
value: string
}
interface FilterOptions {
all_user: Option[]
label_user: Option[]
review_user1: Option[]
review_user2: Option[]
all_user: FilterOption[]
label_user: FilterOption[]
review_user1: FilterOption[]
review_user2: FilterOption[]
}
interface FilterFormValues {
label_status: string[]
current_uid: string[]
label_user: string[]
review_user1: string[]
review_user2: string[]
rejected: string | null
id: string
}
type TaskListFilterParams = Partial<
Pick<
Task.ListRequest,
| "label_status"
| "current_uid"
| "label_user"
| "review_user1"
| "review_user2"
| "rejected"
| "id"
>
>
const normalizeFilterOption = (option: Option): FilterOption | null => {
if (option.value === null || option.value === undefined) return null
return {
label: option.label,
value: String(option.value),
}
}
const pushUniqueOption = (options: FilterOption[], option: FilterOption) => {
if (!options.some((item) => item.value === option.value)) {
options.push(option)
}
}
const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
@@ -57,11 +101,12 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
const { userOpts } = useAllUserStore()
const [taskList, setTaskList] = useState<any[]>([])
const [taskList, setTaskList] = useState<Task.DataProps[]>([])
const [activePage, setPage] = useState(1)
const [pageSize, setPageSize] = useState(20)
const [filterOpened, setFilterOpened] = useState(false)
const filterForm = useForm({
const filterForm = useForm<FilterFormValues>({
initialValues: {
label_status: [],
current_uid: [],
@@ -72,32 +117,25 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
id: "",
},
})
const [filterParams, setFilterParams] = useState<any>({})
const isParamsEmpty: boolean = JSON.stringify(filterParams) === "{}"
const [filterParams, setFilterParams] = useState<TaskListFilterParams>({})
const isParamsEmpty = Object.keys(filterParams).length === 0
const getListData = useCallback(async () => {
let pg_num = 0,
pg_size = 1000
let total = 0
let tasksCount = 1000000
let finalData: any[] = []
let tasksCount = Number.POSITIVE_INFINITY
let finalData: Task.DataProps[] = []
while (total < tasksCount) {
pg_num += 1
const params = filterParams
? {
project_id: [projectId],
get_data: true,
page_number: pg_num,
page_size: pg_size,
...filterParams,
}
: {
project_id: [projectId],
get_data: true,
page_number: pg_num,
page_size: pg_size,
}
const params: Task.ListRequest = {
project_id: [projectId],
get_data: true,
page_number: pg_num,
page_size: pg_size,
...filterParams,
}
const res = await getTaskList(params)
const { total_items, task_list } = res
finalData = [...finalData, ...task_list]
@@ -112,6 +150,18 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
queueMicrotask(() => getListData())
}, [getListData])
const normalizedUserOpts = useMemo(() => {
return userOpts.reduce<FilterOption[]>((result, item) => {
const normalizedOption = normalizeFilterOption(item)
if (normalizedOption) {
result.push(normalizedOption)
}
return result
}, [])
}, [userOpts])
const filterUserOpts = useMemo(() => {
const opts: FilterOptions = {
all_user: [],
@@ -121,29 +171,33 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
}
if (!projectDetail) return opts
const steps = projectDetail.label_process.step_detail
const normalizedUserMap = new Map(
normalizedUserOpts.map((item) => [item.value, item])
)
const steps = projectDetail.label_process.step_detail ?? []
steps.forEach(({ action, user_list }) => {
let users: any[] = []
user_list.forEach((v) => {
userOpts.forEach((item) => {
if (item.value === v) {
users.push(item)
const flag = opts.all_user.find((u) => u.value === v)
if (!flag) opts.all_user.push(item)
}
})
const users: FilterOption[] = []
user_list.forEach((userId) => {
const matchedUser = normalizedUserMap.get(String(userId))
if (!matchedUser) return
pushUniqueOption(users, matchedUser)
pushUniqueOption(opts.all_user, matchedUser)
})
if (action === 1) {
opts.label_user.push(...users)
users.forEach((user) => pushUniqueOption(opts.label_user, user))
} else if (action === 2) {
opts.review_user1.push(...users)
users.forEach((user) => pushUniqueOption(opts.review_user1, user))
} else if (action === 3) {
opts.review_user2.push(...users)
users.forEach((user) => pushUniqueOption(opts.review_user2, user))
}
})
return opts
}, [projectDetail, userOpts])
}, [normalizedUserOpts, projectDetail])
const handleTurnPrevious = () => {
const index = taskList.findIndex((task) => task.id === taskId)
@@ -185,12 +239,14 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
label: value,
value: key,
}))}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("label_status")}
clearable
/>
<MultiSelect
label="当前负责人"
data={filterUserOpts.all_user}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("current_uid")}
searchable
clearable
@@ -198,6 +254,7 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
<MultiSelect
label="标注员"
data={filterUserOpts.label_user}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("label_user")}
searchable
clearable
@@ -205,6 +262,7 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
<MultiSelect
label="审核员"
data={filterUserOpts.review_user1}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("review_user1")}
searchable
clearable
@@ -212,6 +270,7 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
<MultiSelect
label="复审员"
data={filterUserOpts.review_user2}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("review_user2")}
searchable
clearable
@@ -222,6 +281,7 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
{ label: "是", value: "1" },
{ label: "否", value: "0" },
]}
comboboxProps={{ withinPortal: false }}
{...filterForm.getInputProps("rejected")}
clearable
/>
@@ -237,23 +297,36 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
filterForm.reset()
setFilterParams({})
setPage(1)
setFilterOpened(false)
}}>
</Button>
<Button
onClick={() => {
const obj = filterForm.values
const params: any = {}
const params: TaskListFilterParams = {}
if (obj.label_status?.length)
params.label_status = obj.label_status.map(Number)
if (obj.current_uid?.length) params.current_uid = obj.current_uid
if (obj.label_user?.length) params.label_user = obj.label_user
if (obj.review_user1?.length) params.review_user1 = obj.review_user1
if (obj.review_user2?.length) params.review_user2 = obj.review_user2
if (obj.rejected) params.rejected = Number(obj.rejected)
if (obj.id) params.id = obj.id.trim()
if (obj.current_uid?.length)
params.current_uid = obj.current_uid.map(Number)
if (obj.label_user?.length)
params.label_user = obj.label_user.map(Number)
if (obj.review_user1?.length)
params.review_user1 = obj.review_user1.map(Number)
if (obj.review_user2?.length)
params.review_user2 = obj.review_user2.map(Number)
if (obj.rejected !== null)
params.rejected = Number(obj.rejected) === 1
if (obj.id.trim()) {
const taskId = Number(obj.id.trim())
if (Number.isFinite(taskId)) {
params.id = [taskId]
}
}
setFilterParams(params)
setPage(1)
setFilterOpened(false)
}}>
</Button>
@@ -276,12 +349,18 @@ const RightTaskTools: React.FC<RightTaskToolsComponentProps> = (props) => {
<IconChevronRight size={16} />
</ActionIcon>
</Group>
<Popover position="bottom-end" withArrow shadow="md">
<Popover
position="bottom-end"
withArrow
shadow="md"
opened={filterOpened}
onChange={setFilterOpened}>
<Popover.Target>
<ActionIcon
variant="subtle"
size="sm"
color={!isParamsEmpty ? "blue" : "gray"}>
color={!isParamsEmpty ? "blue" : "gray"}
onClick={() => setFilterOpened((opened) => !opened)}>
<IconFilter size={16} />
</ActionIcon>
</Popover.Target>