fix(project): page

This commit is contained in:
zhangheng
2026-04-11 16:54:21 +08:00
parent 033f11fb9b
commit e8dc6abb97

View File

@@ -19,6 +19,7 @@ import {
useProjectStore, useProjectStore,
} from "@/components/label/store/auth" } from "@/components/label/store/auth"
import { import {
ALL_CODE,
projectLabelTypeOpts, projectLabelTypeOpts,
projectStatusOpts, projectStatusOpts,
STATUS_CODE, STATUS_CODE,
@@ -36,7 +37,6 @@ import {
Modal, Modal,
MultiSelect, MultiSelect,
Pagination, Pagination,
Paper,
Select, Select,
SimpleGrid, SimpleGrid,
Stack, Stack,
@@ -46,6 +46,15 @@ import {
Tooltip, Tooltip,
UnstyledButton, UnstyledButton,
} from "@mantine/core" } from "@mantine/core"
import {
SettingContentPanel,
SettingFilterActions,
SettingFilterPanel,
SettingHeaderActions,
SettingListHeader,
SettingPage,
SettingPanel,
} from "@/components/setting/PageSurface"
import { useForm } from "@mantine/form" import { useForm } from "@mantine/form"
import { notifications } from "@mantine/notifications" import { notifications } from "@mantine/notifications"
import { import {
@@ -134,6 +143,7 @@ export default function ProjectInfoPage({
type: "dynamic" | "collect" | "" type: "dynamic" | "collect" | ""
}) { }) {
const router = useRouter() const router = useRouter()
const storeType = type || "all"
const { userOpts } = useAllUserStore() const { userOpts } = useAllUserStore()
const userName = usePermissionStore((s) => s.user_name) const userName = usePermissionStore((s) => s.user_name)
@@ -150,20 +160,20 @@ export default function ProjectInfoPage({
}: any = useProjectStore() }: any = useProjectStore()
const storeParams = useMemo(() => { const storeParams = useMemo(() => {
return type === "collect" return storeType === "collect"
? collectParams ? collectParams
: type === "dynamic" : storeType === "dynamic"
? dynamicParams ? dynamicParams
: allParams : allParams
}, [allParams, collectParams, dynamicParams, type]) }, [allParams, collectParams, dynamicParams, storeType])
const total = useMemo(() => { const total = useMemo(() => {
return type === "collect" return storeType === "collect"
? collectTotal ? collectTotal
: type === "dynamic" : storeType === "dynamic"
? dynamicTotal ? dynamicTotal
: allTotal : allTotal
}, [allTotal, collectTotal, dynamicTotal, type]) }, [allTotal, collectTotal, dynamicTotal, storeType])
const [typeOpts, setTypeOpts] = useState< const [typeOpts, setTypeOpts] = useState<
Array<{ label: string; value: string }> Array<{ label: string; value: string }>
@@ -179,7 +189,7 @@ export default function ProjectInfoPage({
status: "", status: "",
owner: "", owner: "",
label_type: "", label_type: "",
admin_user: "", admin_user: [] as string[],
start_date: dayjs().subtract(6, "day").format("YYYY-MM-DD"), start_date: dayjs().subtract(6, "day").format("YYYY-MM-DD"),
end_date: dayjs().format("YYYY-MM-DD"), end_date: dayjs().format("YYYY-MM-DD"),
} }
@@ -200,9 +210,9 @@ export default function ProjectInfoPage({
const queryParams = useMemo(() => { const queryParams = useMemo(() => {
const base = const base =
type === "collect" storeType === "collect"
? { ...initCollectParams } ? { ...initCollectParams }
: type === "dynamic" : storeType === "dynamic"
? { ...initDynamicParams } ? { ...initDynamicParams }
: { ...initAllParams } : { ...initAllParams }
@@ -214,7 +224,9 @@ export default function ProjectInfoPage({
project_name: appliedFilters.project_name || undefined, project_name: appliedFilters.project_name || undefined,
project_type: appliedFilters.project_type || undefined, project_type: appliedFilters.project_type || undefined,
owner: appliedFilters.owner || undefined, owner: appliedFilters.owner || undefined,
admin_user: appliedFilters.admin_user || undefined, admin_user: appliedFilters.admin_user?.length
? appliedFilters.admin_user.map((n) => Number(n))
: undefined,
start_date: appliedFilters.start_date || undefined, start_date: appliedFilters.start_date || undefined,
end_date: appliedFilters.end_date || undefined, end_date: appliedFilters.end_date || undefined,
label_type: appliedFilters.label_type label_type: appliedFilters.label_type
@@ -222,11 +234,11 @@ export default function ProjectInfoPage({
: undefined, : undefined,
// 0: 图片标注 1: 点云标注 2: 视频标注 // 0: 图片标注 1: 点云标注 2: 视频标注
project_data_type: 0, project_data_type: 0,
status: parseStatusValue(appliedFilters.status), status: parseStatusValue(appliedFilters.status) ?? [...ALL_CODE],
} }
return params return params
}, [appliedFilters, storeParams, type]) }, [appliedFilters, storeParams, storeType])
const load = useCallback(async () => { const load = useCallback(async () => {
if (!queryTrigger) return if (!queryTrigger) return
@@ -234,10 +246,10 @@ export default function ProjectInfoPage({
try { try {
const res = await getProjectList(queryParams) const res = await getProjectList(queryParams)
setRecords(res?.project_list ?? []) setRecords(res?.project_list ?? [])
setTotal(res?.total_items ?? 0, type) setTotal(res?.total_items ?? 0, storeType)
} catch (e) { } catch (e) {
setRecords([]) setRecords([])
setTotal(0, type) setTotal(0, storeType)
notifications.show({ notifications.show({
color: "red", color: "red",
title: "加载失败", title: "加载失败",
@@ -246,7 +258,7 @@ export default function ProjectInfoPage({
} finally { } finally {
setLoading(false) setLoading(false)
} }
}, [queryParams, queryTrigger, setTotal, type]) }, [queryParams, queryTrigger, setTotal, storeType])
useEffect(() => { useEffect(() => {
load() load()
@@ -345,11 +357,10 @@ export default function ProjectInfoPage({
const canDoAction = !!actionKey const canDoAction = !!actionKey
return ( return (
<Paper <SettingPanel
key={record.id} key={record.id}
withBorder
radius="md" radius="md"
shadow="sm" shadow="xs"
style={{ style={{
height: 160, height: 160,
padding: 14, padding: 14,
@@ -357,6 +368,9 @@ export default function ProjectInfoPage({
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
justifyContent: "space-between", justifyContent: "space-between",
borderColor: "#E8EDF3",
background:
"linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(247,250,252,0.96) 100%)",
}}> }}>
<Group justify="space-between" wrap="nowrap" align="flex-start"> <Group justify="space-between" wrap="nowrap" align="flex-start">
<Flex flex={1}> <Flex flex={1}>
@@ -551,7 +565,7 @@ export default function ProjectInfoPage({
</div> </div>
</div> </div>
</Stack> </Stack>
</Paper> </SettingPanel>
) )
} }
@@ -604,19 +618,12 @@ export default function ProjectInfoPage({
} }
return ( return (
<Stack w="100%" h="calc(100vh - 56px)" p="md" gap="md"> <SettingPage>
<Paper withBorder p="md" radius="md"> <SettingFilterPanel>
<Group justify="space-between" wrap="wrap" gap="sm"> <Group justify="space-between" wrap="wrap" gap="sm">
<Group gap="xs"> <Group gap="xs">
<Text fw={700}> <Text fw={700}></Text>
{type === "collect"
? "我的收藏"
: type === "dynamic"
? "动态项目"
: "我的项目"}
</Text>
<Button <Button
size="xs"
variant="transparent" variant="transparent"
rightSection={ rightSection={
searchExpanded ? ( searchExpanded ? (
@@ -629,21 +636,19 @@ export default function ProjectInfoPage({
{searchExpanded ? "收起筛选" : "展开筛选"} {searchExpanded ? "收起筛选" : "展开筛选"}
</Button> </Button>
</Group> </Group>
<Group gap="xs"> <SettingFilterActions mt={0}>
<Button <Button
size="xs"
radius="xs"
variant="default" variant="default"
leftSection={<IconRefresh size={16} />} leftSection={<IconRefresh size={16} />}
onClick={() => { onClick={() => {
resetParams(type) resetParams(storeType)
const next = { const next = {
project_name: "", project_name: "",
project_type: "", project_type: "",
status: "", status: "",
owner: "", owner: "",
label_type: "", label_type: "",
admin_user: "", admin_user: [],
start_date: dayjs().subtract(6, "day").format("YYYY-MM-DD"), start_date: dayjs().subtract(6, "day").format("YYYY-MM-DD"),
end_date: dayjs().format("YYYY-MM-DD"), end_date: dayjs().format("YYYY-MM-DD"),
} }
@@ -654,17 +659,15 @@ export default function ProjectInfoPage({
</Button> </Button>
<Button <Button
size="xs"
radius="xs"
leftSection={<IconSearch size={16} />} leftSection={<IconSearch size={16} />}
onClick={() => { onClick={() => {
setSearchParams({ ...storeParams, page_number: 1 }, type) setSearchParams({ ...storeParams, page_number: 1 }, storeType)
setAppliedFilters(filters) setAppliedFilters(filters)
setQueryTrigger((v) => v + 1) setQueryTrigger((v) => v + 1)
}}> }}>
</Button> </Button>
</Group> </SettingFilterActions>
</Group> </Group>
<Collapse <Collapse
@@ -676,8 +679,6 @@ export default function ProjectInfoPage({
<SimpleGrid cols={{ base: 1, sm: 2, md: 3, lg: 4 }} spacing="sm"> <SimpleGrid cols={{ base: 1, sm: 2, md: 3, lg: 4 }} spacing="sm">
<TextInput <TextInput
label="项目名称" label="项目名称"
size="xs"
radius="xs"
value={filters.project_name} value={filters.project_name}
onChange={(e) => onChange={(e) =>
setFilters((s) => ({ setFilters((s) => ({
@@ -688,8 +689,6 @@ export default function ProjectInfoPage({
/> />
<Select <Select
label="所属业务" label="所属业务"
size="xs"
radius="xs"
searchable searchable
clearable clearable
data={typeOpts} data={typeOpts}
@@ -700,20 +699,16 @@ export default function ProjectInfoPage({
/> />
<Select <Select
label="状态" label="状态"
size="xs"
radius="xs"
searchable searchable
data={projectStatusOpts.map((o) => ({ data={projectStatusOpts.map((o) => ({
label: o.label, label: o.label,
value: o.label, value: o.value.toString(),
}))} }))}
value={filters.status} value={filters.status}
onChange={(v) => setFilters((s) => ({ ...s, status: v ?? "" }))} onChange={(v) => setFilters((s) => ({ ...s, status: v ?? "" }))}
/> />
<TextInput <TextInput
label="负责人" label="负责人"
size="xs"
radius="xs"
value={filters.owner} value={filters.owner}
onChange={(e) => onChange={(e) =>
setFilters((s) => ({ ...s, owner: e.currentTarget.value })) setFilters((s) => ({ ...s, owner: e.currentTarget.value }))
@@ -721,8 +716,6 @@ export default function ProjectInfoPage({
/> />
<Select <Select
label="标注类型" label="标注类型"
size="xs"
radius="xs"
searchable searchable
clearable clearable
data={projectLabelTypeOpts.map((o) => ({ data={projectLabelTypeOpts.map((o) => ({
@@ -734,25 +727,19 @@ export default function ProjectInfoPage({
setFilters((s) => ({ ...s, label_type: v ?? "" })) setFilters((s) => ({ ...s, label_type: v ?? "" }))
} }
/> />
<Select <MultiSelect
label="标注管理员" label="标注管理员"
size="xs"
radius="xs"
searchable
clearable
data={userOpts.map((o) => ({ data={userOpts.map((o) => ({
label: o.label, label: o.label,
value: String(o.value), value: String(o.value),
}))} }))}
value={filters.admin_user || null} value={filters.admin_user}
onChange={(v) => onChange={(v) => setFilters((s) => ({ ...s, admin_user: v }))}
setFilters((s) => ({ ...s, admin_user: v ?? "" })) searchable
} clearable
/> />
<TextInput <TextInput
label="开始日期" label="开始日期"
size="xs"
radius="xs"
type="date" type="date"
value={filters.start_date} value={filters.start_date}
onChange={(e) => onChange={(e) =>
@@ -764,8 +751,6 @@ export default function ProjectInfoPage({
/> />
<TextInput <TextInput
label="结束日期" label="结束日期"
size="xs"
radius="xs"
type="date" type="date"
value={filters.end_date} value={filters.end_date}
onChange={(e) => onChange={(e) =>
@@ -775,18 +760,36 @@ export default function ProjectInfoPage({
</SimpleGrid> </SimpleGrid>
</Stack> </Stack>
</Collapse> </Collapse>
</Paper> </SettingFilterPanel>
<Paper <SettingContentPanel
withBorder
p="md"
radius="md"
style={{ style={{
flex: 1, flex: 1,
minHeight: 0, minHeight: 0,
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
}}> }}>
<SettingListHeader
title={
type === "collect"
? "我的收藏"
: type === "dynamic"
? "动态项目"
: "全部项目"
}
count={`${total ?? 0}`}
actions={
<SettingHeaderActions>
<Button
variant="default"
leftSection={<IconRefresh size={16} />}
onClick={() => setQueryTrigger((v) => v + 1)}
loading={loading}>
</Button>
</SettingHeaderActions>
}
/>
<div <div
style={{ style={{
flex: 1, flex: 1,
@@ -839,19 +842,19 @@ export default function ProjectInfoPage({
pageSize={pageSize} pageSize={pageSize}
total={total ?? 0} total={total ?? 0}
onChangePage={(p) => { onChangePage={(p) => {
setSearchParams({ ...storeParams, page_number: p }, type) setSearchParams({ ...storeParams, page_number: p }, storeType)
setQueryTrigger((v) => v + 1) setQueryTrigger((v) => v + 1)
}} }}
onChangePageSize={(s) => { onChangePageSize={(s) => {
setSearchParams( setSearchParams(
{ ...storeParams, page_number: 1, page_size: s }, { ...storeParams, page_number: 1, page_size: s },
type storeType
) )
setQueryTrigger((v) => v + 1) setQueryTrigger((v) => v + 1)
}} }}
/> />
</div> </div>
</Paper> </SettingContentPanel>
<Modal <Modal
opened={infoModalRecord !== null} opened={infoModalRecord !== null}
@@ -1139,6 +1142,6 @@ export default function ProjectInfoPage({
</Group> </Group>
</Stack> </Stack>
</Modal> </Modal>
</Stack> </SettingPage>
) )
} }