diff --git a/app/layout.tsx b/app/layout.tsx index 230ae6c..fb37f14 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,6 +2,7 @@ import "@mantine/core/styles.css" import "@mantine/core/styles.layer.css" +import "@mantine/dates/styles.css" import "@mantine/notifications/styles.css" import "mantine-datatable/styles.css" import Script from "next/script" diff --git a/app/project/detail/TaskTableContainer.tsx b/app/project/detail/TaskTableContainer.tsx index 096744d..7999573 100644 --- a/app/project/detail/TaskTableContainer.tsx +++ b/app/project/detail/TaskTableContainer.tsx @@ -32,6 +32,7 @@ import { Text, TextInput, } from "@mantine/core" +import { DatePickerInput, type DatesRangeValue } from "@mantine/dates" import { modals } from "@mantine/modals" import { notifications } from "@mantine/notifications" import { @@ -41,8 +42,9 @@ import { IconSearch, } from "@tabler/icons-react" import dayjs from "dayjs" +import "dayjs/locale/zh-cn" import duration from "dayjs/plugin/duration" -import { DataTableColumn } from "mantine-datatable" +import { DataTableColumn, type DataTableSortStatus } from "mantine-datatable" import { useRouter, useSearchParams } from "next/navigation" import { useCallback, useEffect, useMemo, useState } from "react" import * as XLSX from "xlsx-js-style" @@ -60,6 +62,8 @@ interface FilterFormRecord { label_user: string[] review_user1: string[] review_user2: string[] + first_commit_label_time: DatesRangeValue + first_commit_review1_time: DatesRangeValue } function createInitialFilters(): FilterFormRecord { @@ -71,10 +75,52 @@ function createInitialFilters(): FilterFormRecord { label_user: [], review_user1: [], review_user2: [], + first_commit_label_time: [null, null], + first_commit_review1_time: [null, null], } } const DEFAULT_RECORDS_PER_PAGE_OPTIONS = [10, 15, 20] +const INITIAL_SORT_ACCESSOR = "__initial__" + +type SortableTaskSizeAccessor = keyof Task.SizeProps + +const SORTABLE_TASK_SIZE_COLUMNS: Array<{ + accessor: SortableTaskSizeAccessor + title: string + width: number +}> = [ + { accessor: "object_size", title: "对象总数", width: 110 }, + { accessor: "valid_size", title: "有效对象数", width: 120 }, + { accessor: "new_size", title: "新增对象数", width: 120 }, + { accessor: "key_frame_size", title: "关键帧数", width: 120 }, + { accessor: "dynamic_size", title: "动态对象数", width: 120 }, + { accessor: "static_size", title: "静态对象数", width: 120 }, + { accessor: "prelabel_size", title: "预标注对象数", width: 120 }, + { accessor: "prelabel_modify_size", title: "预标注对象修改数", width: 160 }, + { accessor: "question_size", title: "问题数", width: 120 }, + { accessor: "total_qa_group_size", title: "总问答组数", width: 120 }, + { accessor: "single_qa_group_size", title: "单轮问答组数", width: 120 }, + { accessor: "multiple_qa_group_size", title: "多轮问答组数", width: 120 }, + { accessor: "new_qa_group_size", title: "新增问答组数", width: 120 }, + { + accessor: "new_single_qa_group_size", + title: "新增单轮问答组数", + width: 160, + }, + { + accessor: "new_multiple_qa_group_size", + title: "新增多轮问答组数", + width: 160, + }, + { accessor: "review_question_size", title: "审核问题数", width: 120 }, + { accessor: "comment_question_size", title: "首次批注问题数", width: 140 }, + { accessor: "review_size", title: "审核对象数", width: 120 }, + { accessor: "review_dynamic_size", title: "审核动态对象数", width: 140 }, + { accessor: "review_static_size", title: "审核静态对象数", width: 140 }, + { accessor: "first_comment_size", title: "批注数(1)", width: 120 }, + { accessor: "second_comment_size", title: "批注数(2)", width: 120 }, +] export interface selectedDataProps { status: number @@ -167,6 +213,12 @@ export default function TaskTableContainer(props: { const [selectedRecords, setSelectedRecords] = useState([]) const [loading, setLoading] = useState(false) const [queryTrigger, setQueryTrigger] = useState(0) + const [sortStatus, setSortStatus] = useState< + DataTableSortStatus + >({ + columnAccessor: INITIAL_SORT_ACCESSOR, + direction: "asc", + }) const [workflowTaskId, setWorkflowTaskId] = useState(null) const [dispatchRecordModal, setDispatchModalConfig] = useState<{ @@ -223,9 +275,33 @@ export default function TaskTableContainer(props: { if (form.review_user2?.length) { obj.review_user2 = form.review_user2?.map((item) => Number(item)) } + if (form.first_commit_label_time[0] && form.first_commit_label_time[1]) { + obj.first_commit_label_time_start = dayjs( + form.first_commit_label_time[0] + ).format("YYYY-MM-DD") + obj.first_commit_label_time_end = dayjs( + form.first_commit_label_time[1] + ).format("YYYY-MM-DD") + } + if ( + form.first_commit_review1_time[0] && + form.first_commit_review1_time[1] + ) { + obj.first_commit_review1_time_start = dayjs( + form.first_commit_review1_time[0] + ).format("YYYY-MM-DD") + obj.first_commit_review1_time_end = dayjs( + form.first_commit_review1_time[1] + ).format("YYYY-MM-DD") + } + if (sortStatus.columnAccessor !== INITIAL_SORT_ACCESSOR) { + obj.order_by = `${sortStatus.columnAccessor} ${sortStatus.direction}` + } return obj }, [ form.current_uid, + form.first_commit_label_time, + form.first_commit_review1_time, form.label_user, form.rejected, form.review_user1, @@ -235,6 +311,8 @@ export default function TaskTableContainer(props: { pageNumber, pageSize, projectId, + sortStatus.columnAccessor, + sortStatus.direction, ]) const load = useCallback(async () => { @@ -528,6 +606,22 @@ export default function TaskTableContainer(props: { } const columns = useMemo(() => { + const createSortableSizeColumn = ({ + accessor, + title, + width, + }: { + accessor: SortableTaskSizeAccessor + title: string + width: number + }): DataTableColumn => ({ + accessor, + title, + width, + sortable: true, + render: (record) => record.label_object_size?.[accessor] ?? "-", + }) + const cols: DataTableColumn[] = [ { accessor: "id", @@ -595,148 +689,7 @@ export default function TaskTableContainer(props: { width: 120, render: (record) => record.review2_username ?? "-", }, - { - accessor: "label_object_size.object_size", - title: "对象总数", - width: 110, - render: (record) => record.label_object_size?.object_size ?? "-", - }, - { - accessor: "label_object_size.valid_size", - title: "有效对象数", - width: 120, - render: (record) => record.label_object_size?.valid_size ?? "-", - }, - { - accessor: "label_object_size.new_size", - title: "新增对象数", - width: 120, - render: (record) => record.label_object_size?.new_size ?? "-", - }, - { - accessor: "label_object_size.key_frame_size", - title: "关键帧数", - width: 120, - render: (record) => record.label_object_size?.key_frame_size ?? "-", - }, - { - accessor: "label_object_size.dynamic_size", - title: "动态对象数", - width: 120, - render: (record) => record.label_object_size?.dynamic_size ?? "-", - }, - { - accessor: "label_object_size.static_size", - title: "静态对象数", - width: 120, - render: (record) => record.label_object_size?.static_size ?? "-", - }, - { - accessor: "label_object_size.prelabel_size", - title: "预标注对象数", - width: 120, - render: (record) => record.label_object_size?.prelabel_size ?? "-", - }, - { - accessor: "label_object_size.prelabel_modify_size", - title: "预标注对象修改数", - width: 160, - render: (record) => - record.label_object_size?.prelabel_modify_size ?? "-", - }, - { - accessor: "label_object_size.question_size", - title: "问题数", - width: 120, - render: (record) => record.label_object_size?.question_size ?? "-", - }, - { - accessor: "label_object_size.total_qa_group_size", - title: "总问答组数", - width: 120, - render: (record) => - record.label_object_size?.total_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.single_qa_group_size", - title: "单轮问答组数", - width: 120, - render: (record) => - record.label_object_size?.single_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.multiple_qa_group_size", - title: "多轮问答组数", - width: 120, - render: (record) => - record.label_object_size?.multiple_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.new_qa_group_size", - title: "新增问答组数", - width: 120, - render: (record) => record.label_object_size?.new_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.new_single_qa_group_size", - title: "新增单轮问答组数", - width: 160, - render: (record) => - record.label_object_size?.new_single_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.new_multiple_qa_group_size", - title: "新增多轮问答组数", - width: 160, - render: (record) => - record.label_object_size?.new_multiple_qa_group_size ?? "-", - }, - { - accessor: "label_object_size.review_question_size", - title: "审核问题数", - width: 120, - render: (record) => - record.label_object_size?.review_question_size ?? "-", - }, - { - accessor: "label_object_size.comment_question_size", - title: "首次批注问题数", - width: 140, - render: (record) => - record.label_object_size?.comment_question_size ?? "-", - }, - { - accessor: "label_object_size.review_size", - title: "审核对象数", - width: 120, - render: (record) => record.label_object_size?.review_size ?? "-", - }, - { - accessor: "label_object_size.review_dynamic_size", - title: "审核动态对象数", - width: 140, - render: (record) => - record.label_object_size?.review_dynamic_size ?? "-", - }, - { - accessor: "label_object_size.review_static_size", - title: "审核静态对象数", - width: 140, - render: (record) => record.label_object_size?.review_static_size ?? "-", - }, - { - accessor: "label_object_size.first_comment_size", - title: "批注数(1)", - width: 120, - render: (record) => record.label_object_size?.first_comment_size ?? "-", - }, - { - accessor: "label_object_size.second_comment_size", - title: "批注数(2)", - width: 120, - render: (record) => - record.label_object_size?.second_comment_size ?? "-", - }, + ...SORTABLE_TASK_SIZE_COLUMNS.map(createSortableSizeColumn), { accessor: "first_commit_label_time", title: "标注首次提交时间", @@ -966,6 +919,36 @@ export default function TaskTableContainer(props: { setFilters((s) => ({ ...s, review_user2: v })) } /> + + setFilters((s) => ({ + ...s, + first_commit_label_time: value, + })) + } + /> + + setFilters((s) => ({ + ...s, + first_commit_review1_time: value, + })) + } + /> @@ -1038,6 +1021,13 @@ export default function TaskTableContainer(props: { fetching={loading} records={records} columns={columns} + sortStatus={sortStatus} + onSortStatusChange={( + nextSortStatus: DataTableSortStatus + ) => { + setPageNumber(1) + setSortStatus(nextSortStatus) + }} totalRecords={total} recordsPerPage={pageSize} page={pageNumber} diff --git a/components/label/api/task/typing.ts b/components/label/api/task/typing.ts index c1a1ec3..b1f77ce 100644 --- a/components/label/api/task/typing.ts +++ b/components/label/api/task/typing.ts @@ -1,5 +1,6 @@ export namespace Task { export interface DataProps { + [key: string]: unknown id: number create_date: string data_type?: number @@ -74,6 +75,7 @@ export namespace Task { id?: number[] label_status?: number[] label_user?: number[] + // sample: object_size asc/object_size desc order_by?: string page_number: number page_size: number diff --git a/package.json b/package.json index 35c1ea4..cc440cf 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@ffmpeg/util": "^0.12.2", "@fingerprintjs/fingerprintjs": "^5.0.1", "@mantine/core": "^8.3.1", + "@mantine/dates": "^8.3.18", "@mantine/form": "^8.3.1", "@mantine/hooks": "^8.3.1", "@mantine/modals": "^8.3.10",