Files
labelmain-demo/app/management/project/detail/page.tsx
2026-02-26 19:26:46 +08:00

229 lines
6.7 KiB
TypeScript

"use client"
import { getProjectDetailById } from "@/components/label/api/project"
import { ProjectDetail } from "@/components/label/api/project/typing"
import {
useAllUserStore,
useBackUrlStore,
usePermissionStore,
} from "@/components/label/store/auth"
import {
Breadcrumbs,
Flex,
Group,
Paper,
Stack,
Text,
UnstyledButton,
} from "@mantine/core"
import { useRouter, useSearchParams } from "next/navigation"
import { useEffect, useMemo, useState } from "react"
import InfoSettingContainer from "./InfoSettingContainer"
import OwnTaskTableContainer from "./OwnTaskTableContainer"
import TaskBoardContainer from "./TaskBoardContainer"
import TaskTableContainer from "./TaskTableContainer"
type TabKey = "own" | "all" | "setting" | "board"
export default function CollectionDetailPage() {
const router = useRouter()
const urlParams = useSearchParams()
const type = urlParams.get("type")
const id = urlParams.get("id")
const projectId =
typeof id === "string" && !isNaN(Number(id)) ? Number(id) : -1
const { backTitle, setBackProps } = useBackUrlStore()
const { userOpts } = useAllUserStore()
const permissions = usePermissionStore((s) => s.detailInfo?.permissions)
const canConfig = useMemo(() => {
const v = permissions?.project?.config?.[0]
return typeof v === "boolean" ? v : true
}, [permissions])
const [selectKey, setSelectedKey] = useState<TabKey>(
(backTitle as TabKey) || "all"
)
const [info, setInfo] = useState<ProjectDetail.DataProps>()
const [userEnums, setUserEnums] = useState<{
allEnum: Map<any, any>
labelEnum: Map<any, any>
review1Enum: Map<any, any>
review2Enum: Map<any, any>
}>({
allEnum: new Map(),
labelEnum: new Map(),
review1Enum: new Map(),
review2Enum: new Map(),
})
useEffect(() => {
if (projectId === -1) return
const getProjectInfo = async () => {
const res = await getProjectDetailById(projectId)
setInfo(res)
}
getProjectInfo()
}, [projectId])
const updateProjectInfo = async () => {
if (projectId === -1) return
const res = await getProjectDetailById(projectId)
setInfo(res)
}
useEffect(() => {
if (!info?.label_process) return
const { step_detail } = info.label_process
let label: number[] = []
let review1: number[] = []
let review2: number[] = []
step_detail.forEach(({ action, user_list }: any) => {
if (action === 1) label = user_list
else if (action === 2) review1 = user_list
else if (action === 3) review2 = user_list
})
const all = Array.from(new Set([...label, ...review1, ...review2]))
const toLabelMap = (uids: number[]) =>
new Map(
uids.map((uid) => {
const opt = userOpts.find((o) => o.value === uid)
return [uid, opt?.label ?? String(uid)]
})
)
queueMicrotask(() => {
setUserEnums({
allEnum: toLabelMap(all),
labelEnum: toLabelMap(label),
review1Enum: toLabelMap(review1),
review2Enum: toLabelMap(review2),
})
})
}, [info, userOpts])
const breadcrumbsItems = useMemo(() => {
return [
{
title: type
? type === "collect"
? "我的收藏"
: type === "dynamic"
? "动态项目"
: "全部项目"
: "全部项目",
href: type
? type === "collect"
? `/management/person/collection`
: "/management/project/dynamic"
: "/management/project/all",
},
{
title: info?.name || "项目名称",
href: "",
},
].map((item) => (
<UnstyledButton
key={item.title}
onClick={() => {
if (!item.href) return
router.push(item.href)
}}>
<Text
size="sm"
c={item.href ? "dimmed" : "dark"}
fw={item.href ? 400 : 700}>
{item.title}
</Text>
</UnstyledButton>
))
}, [info?.name, router, type])
const menuItems = useMemo(() => {
const arr: Array<{ label: string; key: TabKey }> = [
{ label: "我的任务", key: "own" },
{ label: "任务列表", key: "all" },
]
if (canConfig) arr.push({ label: "任务配置", key: "setting" })
return arr
}, [canConfig])
useEffect(() => {
if (menuItems.some((i) => i.key === selectKey)) return
queueMicrotask(() => {
setSelectedKey(menuItems[0]?.key ?? "own")
})
}, [menuItems, selectKey])
const DetailMenuItems = () => {
return (
<Group gap={0} wrap="nowrap">
{menuItems.map((item, index) => {
const active = item.key === selectKey
return (
<UnstyledButton
key={item.key}
onClick={() => {
const next = item.key
setSelectedKey(next)
const backUrl = type
? `/management/project/detail?id=${projectId}&type=${type}`
: `/management/project/detail?id=${projectId}`
setBackProps(backUrl, next)
}}
style={{
paddingLeft: 14,
paddingRight: 14,
paddingTop: 6,
paddingBottom: 6,
borderTopLeftRadius: index === 0 ? 4 : 0,
borderBottomLeftRadius: index === 0 ? 4 : 0,
borderTopRightRadius: index === menuItems.length - 1 ? 4 : 0,
borderBottomRightRadius: index === menuItems.length - 1 ? 4 : 0,
background: active
? "var(--mantine-color-brand-filled)"
: "rgba(0,0,0,0.04)",
}}>
<Text size="sm" fw={600} c={active ? "white" : "dimmed"}>
{item.label}
</Text>
</UnstyledButton>
)
})}
</Group>
)
}
return (
<Stack w="100%" h="calc(100vh - 56px)" p="md" gap="md">
<Paper withBorder p="md" radius="sm">
<Group justify="space-between" wrap="wrap" gap="sm">
<Flex gap="sm" w="100%" justify="space-between">
<Breadcrumbs separator=">">{breadcrumbsItems}</Breadcrumbs>
{DetailMenuItems()}
</Flex>
</Group>
</Paper>
<Stack style={{ flex: 1, minHeight: 0 }} gap="md">
{selectKey === "own" ? (
<OwnTaskTableContainer info={info} userEnums={userEnums} />
) : null}
{selectKey === "all" ? (
<TaskTableContainer info={info} userEnums={userEnums} />
) : null}
{selectKey === "board" ? <TaskBoardContainer /> : null}
{selectKey === "setting" ? (
<InfoSettingContainer
info={info}
userEnums={userEnums}
updateAction={updateProjectInfo}
/>
) : null}
</Stack>
</Stack>
)
}