diff --git a/components/label/components/RightTaskTools.tsx b/components/label/components/RightTaskTools.tsx index 1f1d57b..1a4d02b 100644 --- a/components/label/components/RightTaskTools.tsx +++ b/components/label/components/RightTaskTools.tsx @@ -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 = (props) => { @@ -57,11 +101,12 @@ const RightTaskTools: React.FC = (props) => { const { userOpts } = useAllUserStore() - const [taskList, setTaskList] = useState([]) + const [taskList, setTaskList] = useState([]) const [activePage, setPage] = useState(1) const [pageSize, setPageSize] = useState(20) + const [filterOpened, setFilterOpened] = useState(false) - const filterForm = useForm({ + const filterForm = useForm({ initialValues: { label_status: [], current_uid: [], @@ -72,32 +117,25 @@ const RightTaskTools: React.FC = (props) => { id: "", }, }) - const [filterParams, setFilterParams] = useState({}) - const isParamsEmpty: boolean = JSON.stringify(filterParams) === "{}" + const [filterParams, setFilterParams] = useState({}) + 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 = (props) => { queueMicrotask(() => getListData()) }, [getListData]) + const normalizedUserOpts = useMemo(() => { + return userOpts.reduce((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 = (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 = (props) => { label: value, value: key, }))} + comboboxProps={{ withinPortal: false }} {...filterForm.getInputProps("label_status")} clearable /> = (props) => { = (props) => { = (props) => { = (props) => { { label: "是", value: "1" }, { label: "否", value: "0" }, ]} + comboboxProps={{ withinPortal: false }} {...filterForm.getInputProps("rejected")} clearable /> @@ -237,23 +297,36 @@ const RightTaskTools: React.FC = (props) => { filterForm.reset() setFilterParams({}) setPage(1) + setFilterOpened(false) }}> 重置 @@ -276,12 +349,18 @@ const RightTaskTools: React.FC = (props) => { - + + color={!isParamsEmpty ? "blue" : "gray"} + onClick={() => setFilterOpened((opened) => !opened)}>