"use client" import { getProjectList, getProjectTypeList, projectCollect, } from "@/components/label/api/project" import { Project } from "@/components/label/api/project/typing" import { initAllParams, initCollectParams, initDynamicParams, useAllUserStore, useProjectStore, } from "@/components/label/store/auth" import { projectLabelTypeOpts, projectStatusOpts, STATUS_CODE, } from "@/components/label/utils/constants" import { ActionIcon, Badge, Button, Collapse, Group, Paper, Select, SimpleGrid, Stack, Text, TextInput, } from "@mantine/core" import { notifications } from "@mantine/notifications" import { IconChevronDown, IconChevronUp, IconRefresh, IconSearch, IconStar, IconStarFilled, } from "@tabler/icons-react" import dayjs from "dayjs" import { DataTable, DataTableColumn } from "mantine-datatable" import { useRouter, useSearchParams } from "next/navigation" import { useCallback, useEffect, useMemo, useState } from "react" type PageType = "all" | "collect" | "dynamic" function statusBadgeColor(status?: number | null) { if (!status) return "gray" if ([191, 199, 700].includes(status)) return "red" if ([580].includes(status)) return "yellow" if ([600].includes(status)) return "green" if ([201, 202, 203].includes(status)) return "cyan" return "blue" } function parseStatusValue(value?: string) { if (!value) return undefined if (value.includes(",")) { return value .split(",") .map((v) => Number(v)) .filter((n) => Number.isFinite(n)) } const n = Number(value) return Number.isFinite(n) ? [n] : undefined } export default function CollectionPage() { const router = useRouter() const urlParams = useSearchParams() const type = (urlParams.get("type") as PageType | null) ?? "collect" const { userOpts } = useAllUserStore() const { allParams, allTotal, collectParams, collectTotal, dynamicParams, dynamicTotal, resetParams, setSearchParams, setTotal, }: any = useProjectStore() const storeParams = useMemo(() => { return type === "collect" ? collectParams : type === "dynamic" ? dynamicParams : allParams }, [allParams, collectParams, dynamicParams, type]) const total = useMemo(() => { return type === "collect" ? collectTotal : type === "dynamic" ? dynamicTotal : allTotal }, [allTotal, collectTotal, dynamicTotal, type]) const [typeOpts, setTypeOpts] = useState< Array<{ label: string; value: string }> >([]) const [loading, setLoading] = useState(false) const [records, setRecords] = useState([]) const [searchExpanded, setSearchExpanded] = useState(false) const [filters, setFilters] = useState(() => { return { project_name: "", project_type: "", status: "", owner: "", label_type: "", admin_user: "", start_date: dayjs().subtract(6, "day").format("YYYY-MM-DD"), end_date: dayjs().format("YYYY-MM-DD"), } }) const [appliedFilters, setAppliedFilters] = useState(filters) const [queryTrigger, setQueryTrigger] = useState(0) useEffect(() => { const initFormOpts = async () => { const res = await getProjectTypeList() setTypeOpts((res ?? []).map((name) => ({ label: name, value: name }))) } initFormOpts() }, []) const queryParams = useMemo(() => { const base = type === "collect" ? { ...initCollectParams } : type === "dynamic" ? { ...initDynamicParams } : { ...initAllParams } const params: Project.ListRequest & any = { ...base, ...storeParams, page_number: storeParams.page_number ?? 1, page_size: storeParams.page_size ?? 15, project_name: appliedFilters.project_name || undefined, project_type: appliedFilters.project_type || undefined, owner: appliedFilters.owner || undefined, admin_user: appliedFilters.admin_user || undefined, start_date: appliedFilters.start_date || undefined, end_date: appliedFilters.end_date || undefined, label_type: appliedFilters.label_type ? Number(appliedFilters.label_type) : undefined, status: parseStatusValue(appliedFilters.status), } return params }, [appliedFilters, storeParams, type]) const load = useCallback(async () => { if (!queryTrigger) return setLoading(true) try { const res = await getProjectList(queryParams) setRecords(res?.project_list ?? []) setTotal(res?.total_items ?? 0, type) } catch (e) { setRecords([]) setTotal(0, type) notifications.show({ color: "red", title: "加载失败", message: e instanceof Error ? e.message : "请求失败", }) } finally { setLoading(false) } }, [queryParams, queryTrigger, setTotal, type]) useEffect(() => { load() }, [load]) useEffect(() => { queueMicrotask(() => { setQueryTrigger((v) => v + 1) }) }, []) const columns = useMemo(() => { const cols: DataTableColumn[] = [ { accessor: "id", title: "项目ID", width: 90, }, { accessor: "name", title: "项目名称", width: 220, render: (record) => ( ), }, { accessor: "project_type", title: "所属业务", width: 140, render: (record) => record.project_type ?? "-", }, { accessor: "status", title: "状态", width: 110, render: (record) => ( {STATUS_CODE.get(record.status) ?? record.status} ), }, { accessor: "owner", title: "负责人", width: 120, render: (record) => record.owner ?? "-", }, { accessor: "label_schema_name", title: "标注方案", width: 160, render: (record) => record.label_schema_name ?? "-", }, { accessor: "update_at", title: "更新时间", width: 160, render: (record) => record.update_at ?? record.create_at ?? "-", }, { accessor: "operation", title: "操作", width: 80, textAlign: "center", render: (record) => ( { try { await projectCollect({ project_id: record.id, is_collect: !record.is_collect, }) notifications.show({ color: "green", title: "操作成功", message: record.is_collect ? "已取消收藏" : "已收藏", }) load() } catch (e) { notifications.show({ color: "red", title: "操作失败", message: e instanceof Error ? e.message : "请求失败", }) } }}> {record.is_collect ? ( ) : ( )} ), }, ] return cols }, [load, router, type]) return ( {/* { const next = v as PageType router.replace(`/management/person/collection?type=${next}`) }} /> */} 我的收藏 setFilters((s) => ({ ...s, project_name: e.currentTarget.value, })) } /> ({ label: o.label, value: o.label, }))} value={filters.status} onChange={(v) => setFilters((s) => ({ ...s, status: v ?? "" }))} /> setFilters((s) => ({ ...s, owner: e.currentTarget.value })) } /> ({ label: o.label, value: String(o.value), }))} value={filters.admin_user || null} onChange={(v) => setFilters((s) => ({ ...s, admin_user: v ?? "" })) } /> setFilters((s) => ({ ...s, start_date: e.currentTarget.value, })) } /> setFilters((s) => ({ ...s, end_date: e.currentTarget.value })) } /> width="100%" style={{ width: "100%" }} withTableBorder withRowBorders pinFirstColumn pinLastColumn scrollAreaProps={{ type: "auto" }} fetching={loading} records={records} columns={columns} totalRecords={total} recordsPerPage={storeParams.page_size ?? 15} page={storeParams.page_number ?? 1} onPageChange={(p) => { setSearchParams({ ...storeParams, page_number: p }, type) setQueryTrigger((v) => v + 1) }} onRecordsPerPageChange={(s) => { setSearchParams( { ...storeParams, page_number: 1, page_size: s }, type ) setQueryTrigger((v) => v + 1) }} recordsPerPageOptions={[10, 15, 20, 50]} noRecordsText="暂无数据" /> ) }