"use client" import { getPersonProjectDashBoard } from "@/components/label/api/project" import { Project } from "@/components/label/api/project/typing" import { SettingDataTable, SettingListHeader, SettingCustomPageSizeControl, usePersistentPageSizeOptions, } from "@/components/setting/PageSurface" import { Button, Group, Stack, Text } from "@mantine/core" import { DatePickerInput, type DatesRangeValue } from "@mantine/dates" import { IconRefresh, 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 { useCallback, useEffect, useMemo, useState } from "react" import classes from "../page.module.css" dayjs.extend(duration) function formatDurationSeconds(seconds?: number | null) { const value = seconds ?? 0 if (!value) return "-" const durationObj = dayjs.duration(value, "seconds") const hours = durationObj.hours() const minutes = durationObj.minutes() if (hours) return `${hours}小时${minutes}分钟` if (minutes) return `${minutes}分钟` return "-" } interface FilterFormRecord { query_date: DatesRangeValue } function normalizeQueryDateRange(value: DatesRangeValue): [string, string] { const today = dayjs().format("YYYY-MM-DD") const [start, end] = value const normalizedStart = start ?? end ?? today const normalizedEnd = end ?? normalizedStart return [ dayjs(normalizedStart).format("YYYY-MM-DD"), dayjs(normalizedEnd).format("YYYY-MM-DD"), ] } function createInitialFilters(): FilterFormRecord { return { query_date: [ dayjs().subtract(1, "week").format("YYYY-MM-DD"), dayjs().format("YYYY-MM-DD"), ], } } const DEFAULT_RECORDS_PER_PAGE_OPTIONS = [10, 15, 20, 50] export default function PersonalProjectTable() { const [records, setRecords] = useState< Project.PersonProjectDashboardResponseItem[] >([]) const [loading, setLoading] = useState(false) const [page, setPage] = useState(1) const [pageSize, setPageSize] = useState(10) const { recordsPerPageOptions, addCustomPageSize, clearCustomPageSizeCache, hasCustomPageSizeCache, } = usePersistentPageSizeOptions(DEFAULT_RECORDS_PER_PAGE_OPTIONS, pageSize) const [totalItems, setTotalItems] = useState(0) const [filters, setFilters] = useState(() => createInitialFilters()) const [queryTrigger, setQueryTrigger] = useState(0) const [form, setForm] = useState(createInitialFilters()) const totalPages = useMemo(() => { const totalItems = records.length return Math.max(1, Math.ceil(totalItems / pageSize)) }, [pageSize, records.length]) const pageRecords = useMemo(() => { const start = (page - 1) * pageSize return records.slice(start, start + pageSize) }, [page, pageSize, records]) const appliedParams = useMemo(() => { const [start_date, end_date] = normalizeQueryDateRange(form.query_date) const params: Project.ReqPersonProjectDashBoard = { start_date, end_date, } return params }, [form.query_date]) const load = useCallback(async () => { if (!queryTrigger) return setLoading(true) try { const res = await getPersonProjectDashBoard(appliedParams) setRecords(res ?? []) setTotalItems(res?.length ?? 0) setPage(1) } finally { setLoading(false) } }, [appliedParams, queryTrigger]) useEffect(() => { load() }, [load]) useEffect(() => { queueMicrotask(() => { setQueryTrigger((v) => v + 1) }) }, []) const handleSearch = () => { setPage(1) setForm({ ...filters }) setQueryTrigger((v) => v + 1) } const handleReset = useCallback(() => { const next = createInitialFilters() setFilters(next) setForm(next) setPage(1) setQueryTrigger((v) => v + 1) }, []) useEffect(() => { if (page > totalPages) setPage(totalPages) }, [page, totalPages]) const originColumn = useMemo(() => { let column: DataTableColumn[] = [ { accessor: "project_id", title: "项目ID", width: 150, render: (record: Project.PersonProjectDashboardResponseItem) => { return ( {record.project_id} ) }, }, { accessor: "project_name", title: "项目名称", width: 160, render: (record: Project.PersonProjectDashboardResponseItem) => { return ( {record.project_name ?? "-"} ) }, }, { accessor: "project_type", title: "所属业务", width: 160, render: (record: Project.PersonProjectDashboardResponseItem) => { return ( {record.project_type ?? "-"} ) }, }, { accessor: "work_time", title: "任务耗时", width: 140, render: (record: Project.PersonProjectDashboardResponseItem) => { return ( {formatDurationSeconds(record.work_time)} ) }, }, { accessor: "project_label_type", title: "标注类别", width: 160, render: (record: Project.PersonProjectDashboardResponseItem) => { return ( {record.project_label_type ?? "-"} ) }, }, ] return column }, []) return (
统计周期
setFilters((s) => ({ ...s, query_date: value, })) } />
width="100%" minHeight={0} style={{ width: "100%", flex: 1 }} pinFirstColumn fetching={loading} scrollAreaProps={{ type: "auto" }} records={pageRecords} onRecordsPerPageChange={setPageSize} recordsPerPageOptions={recordsPerPageOptions} columns={originColumn} totalRecords={totalItems} recordsPerPage={pageSize} page={page} onPageChange={setPage} noRecordsText="暂无数据" recordsPerPageLabel="每页条数" paginationText={({ from, to, totalRecords }) => `显示 ${from}-${to} 条,共 ${totalRecords} 条记录` } renderPagination={({ Controls }) => ( )} />
) }