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