From 062242a63ccb2d57868033730d9edbbf68c44896 Mon Sep 17 00:00:00 2001 From: shay7sev Date: Tue, 10 Mar 2026 18:23:48 +0800 Subject: [PATCH] feat(person): add pages --- app/person/dashboard/components/Icon.tsx | 282 +++++++ .../components/PersonalProjectTable.tsx | 205 +++++ .../components/PersonalTaskTable.tsx | 225 ++++++ app/person/dashboard/page.tsx | 284 ++++++- app/person/dashboard/resource/images/data.png | Bin 0 -> 41963 bytes .../dashboard/resource/images/data_logo.png | Bin 0 -> 9272 bytes app/person/dashboard/resource/images/hour.png | Bin 0 -> 44838 bytes .../dashboard/resource/images/hour_logo.png | Bin 0 -> 9696 bytes .../dashboard/resource/images/review.png | Bin 0 -> 44997 bytes .../dashboard/resource/images/review_logo.png | Bin 0 -> 5404 bytes .../report/components/DailyReportModal.tsx | 541 +++++++++++++ app/person/report/config.ts | 68 ++ app/person/report/page.tsx | 709 +++++++++++++++++- components/label/api/const.ts | 4 + components/label/api/daily/index.ts | 49 ++ components/label/api/daily/typing.ts | 84 +++ components/label/api/label/typing.ts | 171 +++++ components/label/api/project/index.ts | 198 +++++ components/label/api/project/typing.ts | 474 ++++++++++++ components/label/api/task/index.ts | 77 ++ components/label/api/task/typing.ts | 179 +++++ components/label/store.ts | 605 +++++++++++++++ components/label/store/auth.ts | 414 ++++++++++ components/label/utils/clone.ts | 49 ++ components/label/utils/constants.ts | 248 ++++++ 25 files changed, 4862 insertions(+), 4 deletions(-) create mode 100644 app/person/dashboard/components/Icon.tsx create mode 100644 app/person/dashboard/components/PersonalProjectTable.tsx create mode 100644 app/person/dashboard/components/PersonalTaskTable.tsx create mode 100644 app/person/dashboard/resource/images/data.png create mode 100644 app/person/dashboard/resource/images/data_logo.png create mode 100644 app/person/dashboard/resource/images/hour.png create mode 100644 app/person/dashboard/resource/images/hour_logo.png create mode 100644 app/person/dashboard/resource/images/review.png create mode 100644 app/person/dashboard/resource/images/review_logo.png create mode 100644 app/person/report/components/DailyReportModal.tsx create mode 100644 app/person/report/config.ts create mode 100644 components/label/api/const.ts create mode 100644 components/label/api/daily/index.ts create mode 100644 components/label/api/daily/typing.ts create mode 100644 components/label/api/label/typing.ts create mode 100644 components/label/api/project/index.ts create mode 100644 components/label/api/project/typing.ts create mode 100644 components/label/api/task/index.ts create mode 100644 components/label/api/task/typing.ts create mode 100644 components/label/store.ts create mode 100644 components/label/store/auth.ts create mode 100644 components/label/utils/clone.ts create mode 100644 components/label/utils/constants.ts diff --git a/app/person/dashboard/components/Icon.tsx b/app/person/dashboard/components/Icon.tsx new file mode 100644 index 0000000..f3bf826 --- /dev/null +++ b/app/person/dashboard/components/Icon.tsx @@ -0,0 +1,282 @@ +"use client" + +export const DataIcon = () => ( + + + + + + + + + + + + + + +) + +export const HourIcon = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) + +export const ReviewIcon = () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/app/person/dashboard/components/PersonalProjectTable.tsx b/app/person/dashboard/components/PersonalProjectTable.tsx new file mode 100644 index 0000000..97e8c36 --- /dev/null +++ b/app/person/dashboard/components/PersonalProjectTable.tsx @@ -0,0 +1,205 @@ +"use client" + +import { getPersonProjectDashBoard } from "@/components/label/api/project" +import { Project } from "@/components/label/api/project/typing" +import { Button, Group, Text, UnstyledButton } from "@mantine/core" + +import { IconRefresh } from "@tabler/icons-react" +import dayjs from "dayjs" +import duration from "dayjs/plugin/duration" +import { DataTable, DataTableColumn } from "mantine-datatable" +import { useRouter } from "next/navigation" +import { useCallback, useEffect, useMemo, useState } from "react" + +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 "-" +} + +export default function PersonalProjectTable() { + const router = useRouter() + const [records, setRecords] = useState< + Project.PersonProjectDashboardResponseItem[] + >([]) + const [loading, setLoading] = useState(false) + + const [page, setPage] = useState(1) + const [pageSize, setPageSize] = useState(50) + const [totalItems, setTotalItems] = useState(0) + + 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 load = useCallback(async () => { + setLoading(true) + try { + const res = await getPersonProjectDashBoard() + setRecords(res ?? []) + setTotalItems(res?.length ?? 0) + setPage(1) + } finally { + setLoading(false) + } + }, []) + + useEffect(() => { + load() + }, [load]) + + useEffect(() => { + if (page > totalPages) setPage(totalPages) + }, [page, totalPages]) + + const [currentRowId, setCurrentRowId] = useState(0) + + const originColumn = useMemo(() => { + let column: DataTableColumn[] = + [ + { + accessor: "project_id", + title: "项目ID", + width: 150, + render: (record: Project.PersonProjectDashboardResponseItem) => { + return ( + { + setCurrentRowId(record.project_id) + router.push(`/project/info/detail?id=${record.project_id}`) + }} + title={record.project_id.toString()} + c={"brand"} + style={{ + fontSize: "14px", + maxWidth: "100%", + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + }}> + {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 + }, [router]) + + return ( + + + + 参与项目 + + + + + + width="100%" + style={{ width: "100%" }} + styles={{ + header: { + color: "var(--mantine-color-grey-text)", + backgroundColor: "var(--mantine-datatable-striped-color)", + }, + }} + withTableBorder + withRowBorders + pinFirstColumn + rowBackgroundColor={(record) => { + if (record.project_id === currentRowId) + return "var(--mantine-datatable-highlight-on-hover-color-light, var(--mantine-datatable-highlight-on-hover-color))" + }} + idAccessor="project_id" + scrollAreaProps={{ type: "auto" }} + records={pageRecords} + onRecordsPerPageChange={setPageSize} + recordsPerPageOptions={[10, 15, 20]} + columns={originColumn} + totalRecords={totalItems} + recordsPerPage={pageSize} + page={page} + onPageChange={setPage} + noRecordsText="暂无数据" + recordsPerPageLabel="当前页数" + /> + + + ) +} diff --git a/app/person/dashboard/components/PersonalTaskTable.tsx b/app/person/dashboard/components/PersonalTaskTable.tsx new file mode 100644 index 0000000..06779bd --- /dev/null +++ b/app/person/dashboard/components/PersonalTaskTable.tsx @@ -0,0 +1,225 @@ +"use client" + +import { getUserTaskList } from "@/components/label/api/task" +import { Task } from "@/components/label/api/task/typing" +import { + useBackUrlStore, + usePermissionStore, +} from "@/components/label/store/auth" +import { TaskStatusEnum } from "@/components/label/utils/constants" +import { Badge, Button, Group, Text, UnstyledButton } from "@mantine/core" +import { IconRefresh } from "@tabler/icons-react" +import { DataTable, DataTableColumn } from "mantine-datatable" +import { useCallback, useEffect, useMemo, useState } from "react" + +function getStatusColor(status?: number | null) { + switch (status) { + case 2: + return "blue" + case 4: + return "yellow" + case 6: + return "orange" + case 7: + return "green" + case 8: + return "red" + default: + return "gray" + } +} + +export default function PersonalTaskTable() { + const user_name = usePermissionStore((s) => s.user_name) + const setBackProps = useBackUrlStore((s) => s.setBackProps) + + const [page, setPage] = useState(1) + const [pageSize, setPageSize] = useState(50) + const [totalItems, setTotalItems] = useState(0) + const [records, setRecords] = useState([]) + const [loading, setLoading] = useState(false) + + const totalPages = useMemo(() => { + return Math.max(1, Math.ceil(totalItems / pageSize)) + }, [pageSize, totalItems]) + + const load = useCallback(async () => { + if (!user_name) return + setLoading(true) + try { + const res = await getUserTaskList({ + page_number: page, + page_size: pageSize, + }) + setRecords(res?.simple_task_list ?? []) + setTotalItems(res?.total_items ?? 0) + } finally { + setLoading(false) + } + }, [page, pageSize, user_name]) + + useEffect(() => { + load() + }, [load]) + + useEffect(() => { + if (page > totalPages) setPage(totalPages) + }, [page, totalPages]) + + const resetData = () => { + if (page === 1) load() + else setPage(1) + } + + const [currentRowId, setCurrentRowId] = useState(0) + + const originColumn = useMemo(() => { + let column: DataTableColumn[] = [ + { + accessor: "project_name", + title: "项目名称", + width: 150, + render: (record: Task.SimpleTaskItem) => { + return {record.project_name} + }, + }, + { + accessor: "id", + title: "任务ID", + width: 150, + render: (record: Task.SimpleTaskItem) => { + return ( + { + setCurrentRowId(record.id) + if ([4, 5, 6, 7].includes(record.label_type)) { + setBackProps(`/person/dashboard`) + if ([4, 5, 6].includes(record.label_type)) { + // router.replace( + // `/image/label?project_id=${record.project_id}&task_id=${record.id}` + // ) + window.location.href = `/image/label?project_id=${record.project_id}&task_id=${record.id}` + } else if ([7].includes(record.label_type)) { + // router.replace( + // `/video/label?project_id=${record.project_id}&task_id=${record.id}` + // ) + window.location.href = `/video/label?project_id=${record.project_id}&task_id=${record.id}` + } + } else { + // await runCommand( + // record.id.toString(), + // user_name, + // user_password + // ) + } + }} + title={record.id.toString()} + c={"brand"} + style={{ + fontSize: "14px", + maxWidth: "100%", + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + }}> + {record.id} + + ) + }, + }, + { + accessor: "label_status", + title: "状态", + width: 80, + render: (record: Task.SimpleTaskItem) => { + return ( + + {TaskStatusEnum.get(record.label_status)} + + ) + }, + }, + { + accessor: "label_username", + title: "标注员", + width: 80, + }, + { + accessor: "review1_username", + title: "审核员", + width: 80, + }, + { + accessor: "review2_username", + title: "复审员", + width: 80, + }, + ] + return column + }, [setBackProps]) + + return ( + + + + 我的任务 + + + + + + width="100%" + style={{ width: "100%" }} + styles={{ + header: { + color: "var(--mantine-color-grey-text)", + backgroundColor: "var(--mantine-datatable-striped-color)", + }, + }} + withTableBorder + withRowBorders + pinFirstColumn + pinLastColumn + rowBackgroundColor={({ id }) => { + if (id === currentRowId) + return "var(--mantine-datatable-highlight-on-hover-color-light, var(--mantine-datatable-highlight-on-hover-color))" + }} + scrollAreaProps={{ type: "auto" }} + records={records} + onRecordsPerPageChange={setPageSize} + recordsPerPageOptions={[10, 15, 20]} + columns={originColumn} + totalRecords={totalItems} + recordsPerPage={pageSize} + page={page} + onPageChange={setPage} + noRecordsText="暂无数据" + recordsPerPageLabel="当前页数" + /> + + + ) +} diff --git a/app/person/dashboard/page.tsx b/app/person/dashboard/page.tsx index 5010763..0da1889 100644 --- a/app/person/dashboard/page.tsx +++ b/app/person/dashboard/page.tsx @@ -1,5 +1,285 @@ "use client" -export default function DashboardPage() { - return <>Person Dashboard +import { getCurrentPersonData } from "@/components/label/api/project" +import { + BackgroundImage, + Center, + Group, + Paper, + SimpleGrid, + Stack, + Text, + Title, +} from "@mantine/core" +import dayjs from "dayjs" +import duration from "dayjs/plugin/duration" +import { JSX, useEffect, useMemo, useState } from "react" +import { DataIcon, HourIcon, ReviewIcon } from "./components/Icon" +import PersonalProjectTable from "./components/PersonalProjectTable" +import PersonalTaskTable from "./components/PersonalTaskTable" +import DataImage from "./resource/images/data.png" +import DataLogoImage from "./resource/images/data_logo.png" +import HourImage from "./resource/images/hour.png" +import HourLogoImage from "./resource/images/hour_logo.png" +import ReviewImage from "./resource/images/review.png" +import ReviewLogoImage from "./resource/images/review_logo.png" + +dayjs.extend(duration) + +function monthText(month: string) { + const list = [ + "一月", + "二月", + "三月", + "四月", + "五月", + "六月", + "七月", + "八月", + "九月", + "十月", + "十一月", + "十二月", + ] + const idx = Number(month) - 1 + return list[idx] ?? "" +} + +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 "-" +} + +function StatCard(props: { + title: string + timeText: string + sizeTitle: string + sizeValue: number + sizeColor: string + background: string + backgroundLogo: string + Icon: () => JSX.Element +}) { + const { + title, + timeText, + sizeTitle, + sizeValue, + sizeColor, + background, + backgroundLogo, + Icon, + } = props + return ( + + + + +
+ +
+ +
+ + {title} + + + {timeText} + +
+ + + {sizeTitle} + + + {sizeValue} + + +
+
+
+ ) +} + +export default function PersonDashboardPage() { + const [data, setData] = useState<{ + label_data_size: number + label_work_time: number + review1_data_size: number + review1_work_time: number + review2_data_size: number + review2_work_time: number + } | null>(null) + + useEffect(() => { + const run = async () => { + const res = await getCurrentPersonData({ + date: dayjs().format("YYYY-MM-DD"), + }) + setData(res) + } + run() + }, []) + + const dataText = useMemo(() => { + return { + label: formatDurationSeconds(data?.label_work_time ?? 0), + review1: formatDurationSeconds(data?.review1_work_time ?? 0), + review2: formatDurationSeconds(data?.review2_work_time ?? 0), + } + }, [data]) + + return ( + + + + + 今日 + +
+ + + {dayjs().format("DD")} + + {monthText(dayjs().format("MM"))} + +
+
+ + + + + + +
+ + + +
+ +
+
+ + +
+ +
+
+
+
+ ) } diff --git a/app/person/dashboard/resource/images/data.png b/app/person/dashboard/resource/images/data.png new file mode 100644 index 0000000000000000000000000000000000000000..cc8e5225aa31e21ce59c1fa5c1c7760af9d8664e GIT binary patch literal 41963 zcmV(=K-s^EP)qs&!*x+z z&PjT&861OyjJdx5g39SucJXe9vcDmumhY z6F80fBhPzK$I_QAVIGbsc`1myT!Q z&zvQgj7zyBch0qQIU+u(32R-S5r%Fxj&v`3Mzl_RpT`+pCrkyOzWK5)STfpmDwHPw z7?X1OGyTQK8~#T5Jtk7Oms(%IkBcBVhV z#{0pGXSx@e+-7I8U-af@Eh~ll7k`cMFaG{N{ZIb8fAo+3(f{l+8Ia`v=C7xJ_Se7v z<1%0r$|&G4*Z5T+0#i?NfG_l!T4DoV6!1P!p*6VB=lJOvS2ECw12cP}6g*dS+o%bb zy@DAQoYgg?nCajH=6JIvV?d%DE*!910h%5S-U8FU*isYZfsvF-m+6>Vrn!DxV;bJF z-d=e__n9oDLmQBbNOZix!SrOtqC68EJvADDnl6=SDHj7ev4Rj22&DJtbHEoXAXlJI zXQtgG`|)46)e5-c9|)LQ%~W6@eq{T81tM>tv1NKoG?o-N=LFC~&69IlK3raK&z~l< zCy3oqIvdV-BG6|VSYwuSG1loViJ+OtJLnHZ;{W`g{{4Ua@8UoE&;Gv}w7~KI`q%S+ z8E;0*?Ci^NIwHfe$^f(2G$ZA>u}~6=WjZ+6V|`A8(U6+zWW=AxCkUVnRWu6_ig~t` z>>MowHTf#b{rIh2YZW7ZiM<`!uhxJ8BL?74r;}DCt{8C5CWH&(D;(T8hn8Zp%C>XH z^0Z1;KZ(A4hI(zLg^_46e70DJ1%R`|4JZwEtw+=H{KNVjMbZRnAOi4)0Nt$tN3AAH z@8JFm$TU7ie)QlDx2x9G*XGH^F=iYx^}?E6d&wXl8@h|((QM{do=gt?_$~hXbqAAw zkX|O0eC0pOt`2N%<9Nlh3+U(vg;uey!*yAGSyHufe=*Ac)%WlI>mQK()U|*1*T4Uw zmnP1Dq$wr`s!bkeeg=KYWlfxI91Mk-u%m~HM}b{}V?-sPX#h>krUbaG@gq+%l(C|q zCS8qs`}AY`7^MdrMjH2l+c>5kR9?aVT#s<0cqC@qCwsnByL`rK>*h)#<3$vcOq{im z6a_pL1m`uu^HTvBMqU{wucoiL!ru}ASRrIPT&4$8%Y4e`T9pQnFjg0utJw#DQ8Cmw z1SyUUe>}QHV681byRX~cLab+uRmedk450G?N9u?jMIkw(U$@2c(GMzoxzC*lpi)CEzT()Gc3&mXF&&(=K=X*K3%Eaw-M=ELR80R(xPpA0Z%NIrxS{L$u=u z1IRl8u_E@QsIi=_9$&$K`S1Ue|MZ_eW9832W9I*h1H#zB0Ps>@%tBQBum69WjCoc( znuM3990_ksvp=oAy*D-iq@^jDW(fuPN9upFNiU@>xMNjR{5`te<(+N097l!;41r9n zeN2aRqK=*!p{u;w>r)(fwW5yWYQeqnf%_1R?%X}$|nR#zfCK%?Dy zIJi`|XtoE9ZHoZkI;dBbY(hAu|EDq1mOuRU&wOA149}_x9gH3h2j!>yN4X=4rbU(E z{Fj!=nYku_y4qcNoN?=4bS>5KNv4{z45q;o7%YU~&LndVxiD+gW^v&{9v#B0)y|#x zj+iO>a$b!xu5_%|#cE*=Hpg+B*?U9lxhCZg3hMf2;~cOY;sDMha{9yu;t6yOBCSEE z7XpOXU70wZy+U9tR!))90av9=!9~r@&nc(bxr`eFxNNfYaXrh^DjoYj5!kiWcr&mliW}M<*FPd3BWxQ3sEpJb|AXUoH4LA;~(VyJpIJx zE3;nZngI>8UD1wN)H53s4fvws4%3pyYH>Nrl)ZgpCn*Kw_d80j%OBnzvGA!tGn!d2 zU_3A>hqPXvsCZ(mIHQl#$4}9)(?Oc9HlL%FoY{d29DDj3L4rvtw(VlY&(HjI5H$jb zu^V0%TRhiio`f*OE5>IDNx+kDTOXyX9)`CGURw2eSJ zn9eqz4ptQZQ%>n-Hn+I!$ccL$7*KO<=XOH-##&RK=a=_mt!TH8D;mc#VG20aG6TXE z)0`D#pIq<|wT{ku<)uSW?G_g}8Y&UA!k$d8+RJWvp)KcHo?0kw4-iD)B^lO} z1~Q}1!I1$`v!$~n+-&s>9d?Tn^)4OLrlwJ_9v2u6U@6~w={MBc59;&Tbc^-b&tY} zFn~8EI^*9MrC4+WYGO0spvu=;26a+Dme!Nqn&(&2-u`W45@tWZ2>)eNP^uDA$T~-p zGAb7sf&>K^Ac?|<1>pe1eA}lO20g&X_T4>zb%Sy?O0`4g$d+6CY;d`3XU=yfj1T8{ z#`=Du7!q~edw_|ThTCSy4)+hxz&qfc|EB?8Ib$BM>HW7YBW|EYxI?uKrfe@v+vKGT zCw9?o*v;2UZ8~OwEz?@=Hj?{*z(D&NSn-h! zj3x+X$-iZjO-+c&Vqx|+&^rx_-VVbG#9*>u=~T!BOs5<+1Q|&S5#|(A7eUq7mg+^G z@{QoOF(7@&z9_Rff4z4Z-6m|8cq@Ca_&-;lwP7OJ@jrESo6Y#|bz6WiA7v-maroLw zY(Zt(!q2BGsZ3ePSS=RtQpN+f7keXT;y<5#x>f$Jn1SONBi@=`C|rn>CtDOX?2@X+ zY?mloJwa?N&Y4I|x#C5H3gd#n_@VT8T{%ohPHnFk^6^Fr$-iHaOB6XXc3c z280HoNhn7Y1AuP@_%=uEy;V-0EnkE!#gCj{F;OJ}z?m3?nW!9Gjv_XA$5=A39=!uL z_p!~H+XJV!auDXszP=UE=b2gDW6nx5F@O%ZBYmkUaEM{9Y!M`mu9XuUwHXthAiLk0 zKgPb_G1&@`0z_;(_?+}j8@Kv?(sb<@@U56^aID7XTtVu>MXEBmrfs2I;C=}kMC#n+ z;kQR9-i{4c$qlhn#lcxif`N4G^>jh@bnLq-S&M&eofyE+_|J}i{FK>D09_X|k*P7*R&ctB$ z0ZZP?Zm;ow-e>Er{nL@Su6dv@D~$Np8f3nKcCPnrhsl7wyq2G7UJdIw0f_z6<~=UX zDK;iO5Ch=IG{AFD*Qq#$(z7?FD^IthGaPpGZO5D-(i0CG74y5wwJ}8>jjM9>ii_YF zn4P;EPi-}6kEa+P9sRU{*jxqp_l^Fe_ia1WvQmd+z?ZikNbuj z<>evgSfo$v5gq8xfB;Lf(OzBcWrNpA!*66Rb+lx^KN$2|bY{oOBA35oMd(!YWvszH zmp)|v1xR#hx%cnFYp%3-iY8Wn)V;=#-4y@J_JB%pT)Gpm-`CATvdi<2*(r;G08nYA zwDa79_W9V2$K%j|8b0Na%IP?#l>Aq#N7fKkl62~I8!6u*Jy~#3$dqueOUc&lfKKX2 zLL)K07ERRptUni_B6&=pg%!{UbNR1Jc&Oe@jU$>*k*G+j5A`j3PCav~imfyM2Ky1IQp?b94sdgW2{OM^?X7(w=Kr8f$iyp52I#`spb{by+$5 z@M8j0LeO7X$Mu`-fU%wN7R)xN$zhBO+-r%aO~G93G$wRUu3k+^or~l z459iAKVB?yg9dD~-`Jv?E>fD6zXtAMtN2ZXj8#c#Hez-=xC4;r;dTGmd}ll-EeO zmfT!(d=6T^7)N8gW^l2{POv-lZ6InXN_KT?nleOi<2MV z`UZ1Dj!(`*+(kyQ0TfGPQFG0a9V8N;KJg^fH~Q0cDRVzwFdKA% zm}O!0(x}IoMnt4Ftj{jsffbkQv^b&*=9YCS%y*IB~yL zuE=Hxxqld=l1t3nYEUeO^F==!p!gGB61jUAyl}{^kN+D?HfrCvgw?P903&t8+D{Z% z84E41Z);74%8M8Py!A=5X$L;XdyRjf_Y%?Ih_rRd$;SOKWUT*-AIlB`W!Jwu0zGH` zA<;S*ztIL^GgpG7{ML9L z3It0}V~Hg|l-$@4cYeh6Q4S-y{F$orlhqQL#wz1om(#fcB*An(*GKD=w(H^o+5rJ| z%-;8jd-jr>rF_`0NX@oc$w>2Dj~Lr3ihq#Av<#NtB-`{RPh@_r0lV^Xm&WyrM@|6J z#)|5H$G;_;aA15P4E?{3SMwE?(`}2zL_al&HOk(@OQ_n&lWEE!RO+4Z6=)ngudM}1 z8l4!*i7NZbwGeKqlB2cNvW@b+GZw!Qpv1Di{~2z$K5&RWbO|?-Q#wo0K2U&rNDa_L zHtyF>wV2%{NaACTN?>D&!GvKf-1m6eNwwEhr=qDGJTo-+{pgsJG2Tvpe6aVCbRAW` zXPdO-NCV+o_xDc~h!(`uqnM%DOp~Pa&_JG4pC(=^VJ;ZZC9FqOpW^nI7rPO&^58U( zT0bcgLeOfEgk+jAJ$ z$XY1hQn_mPelh`18Cf03E~bd4^5piSl1J82Bw*NFSE(ovg^z*zUU@fx(zY+Da&7~Ovz)YN9S*9Pt-(G z01{89_e#OqS0qCUB@8+l5z1KO#0itheQp5Aey@NrfGQRIv^m_qvVx8A>bIv;ILmN* z+q{Eu$k&Vy*8Fd$t=D6&C4SfaT=dl;$N!RlC8!zy zws!5??{>K2{{RO}-&dPqEw$UN;);7O?%uo4Uyc6$n_dd(lf57`TbhvL(0x)HY=3p~s@Hm&{>$OXt5YZJ8BI;9Dvh_{J70M(vB zvZ9WOF{N?-jvRk@*jyW&1~BTf$CfCjJ55MYpWop4cyMyey|a10P3=t>u~|+ zaO4K9cyMBGoBf6PtbZTU>$Zd`~5sVumoQ~5!z!) zI|vAL2~+K|_x~n1p7F|<`agB2qo&l0;jzTsJjxzhW$ia_a7^gS`AI#2rsuWE=6WHT zOhOgO_7@ri1FSNlU zG0$O7^{c+ezQt~3uh3p05j>bg6#rAE7&^v=kzT8~bwSD1hdjoV0kM5DXkk`;Hf%_F z!}fBAb#A7vK>R$w@zEaa*@!0~%~7H{rbP{3wcl-=j1JOzMtED^Y|`h^&Hv}v)|0?{=&u(GSu&P?&Gzf+&d94`6DHJ z>Ncv9`vzm%W?-_IEq*DL_MDHU$~eez`fO73#{V%Kj3ua3G-H63t`{vz{QgM1GrgS7 z&d;B{)X(R`+7aJP5%lAUn++LvFqb?j_#93bXk z9dy*NCBd4$0rbS*ta5^YQ%zUGNzUZVP%<6kcvN)12)x1^EdF1>+sT+s)}TneS2-MR zo2B{~r!E>ZZ~c=wrF}@ZT$OKp3Z7~~(ro*(FHspdqLr}Z+9HN|P1blLlUkp1(~Dbo z)T@S>ao{e6(Dkfu_vkgR^L{~;Q_2~-L^TxT>)>1xw|uSZ>sX0EVGsbnIS_M04&k>o zImGD%hRejw%mLa=5-5OY@Pk<>i!YZT5q|GT5yu9qwr^npuSZ$H9!oYm8SeWG(Kw3X z!+B!~t=B+1nIesD?UF{2tki*>@7BaJc;DDQ(9Zt!O@ zt6TnR2j3Y1_GWyKxk|!0p-N*Hi!7e4bk8AT9DphjfcrcUYAv<2aG9GS!Q#IKkuU5j zGHZC+X++EcQzZkHzUQ+RYOa0268K`+UcPr9OQK(^c5H%{xhn=Gub&w{(QfS7YcE#1 zz?lh8UNI1l1EG?gvQI#F3;E_LQIb8=gKbm{EQ4Y=)?vFW#gQ{(4@WawANx_>uzOyz z)nX5AOO&x12a@}Vjjm6Js09&tKAZ80=vHZ4EFsS|Cu^K9u_?#MKWX>PJ$`atfBAPf z1f{&MY}h|~4>x+lAC7t{Ko}1zKTVD(!zBdL!BT)b8IwI_;vHQQaJD1)!>>yZCIAP! zT&rFy76Xvt+JgiKhzhb*CfBw|?{nqekEM*XZ~+wxc;kF!Z-UjOey=;+`5Mf?WPpxO z`d>5B)z^ST@dRMA*TKxL_+PThW<4%d2kn${r?!LlQ3p$8CnWiG-(!1Qe-ls1Sg*7D ztVWW_RY|kEkBj*J9MUu(_agg4zS?19^Lw90dMSJcsFD)!!xWxb4CLu?SdPb2K7F2rd>X`4i}0E z^u2nsRE)J$ri(pWzvr1>S<88P{bs(f0}PY>nqLmRN>)s7a{V*^hVC%C8-vHMgBM%I z+t@uXyCL7@!tJ-#r`g$N&6IeIz1EBar9xEW^sRib{m0MW_8cNoCajCGo=9*69XPs$_QzoN$ZFN|!-~^lw1e+I_i6zKJDJK6i6|9|HiS#@_Wflu(mAirp&rE})JXBIa9ESoE!l-KuI9Pz-g4;9|bBcyhrrPxE#6>b@BiYX4*nZF4A8i8`VBsa*u~sf4ur|W7ZV)$d5_OUh&x z6k(N8v@I3b$ISCqppsjDJ(9yp6rZvmJGgDKY19VIocS&R0b zmCSut!j+C`3xZF&DU$nH7XLb}7O=RF*@M>}-C^4b%a2r8)SK|oNPlYIc@+H+_^<~9 zE%-&u>}NNt$WXeaqwKY`5FiB|FfF5r3CqZ$duRhF1NErITKh)#noBC^E(g{0Bj~kv z7njGTX6J-}X@~)6L^- zJ&iGoukylvURxP1VZyvg@&Ej_fn%$fCZ@j=l+v!j$-+pCY-jxeY*_{?uE})TO%G57 z)??EG-Y!=ECr&eK9ewH1@;9|`lnxs;+gJdf18)u676-Z(LgMl+=hpAJ#Ye&d;X?z08 zmC|1zXxv5s7pAPtAyI9cp^}deQF?Z;d%ALYjv#E;+Dw0;9&v$zKkSg_h&F!jQcmkq z+F%}l&1kZ3_(t{*xE275^`-d--_x^Ah7s6d;O;s+{p#Bo=`uQN+>a6Tdr1{z)BoA8 zi))Zk)|j3q7@s62U1Sb18r+N}U-9qb6)1Q7_xRV?)`yis`-J(rRIIuFvL`Yxanr|* zxN?yvf!HK(BwGjA)$TJ#%#D)6+%RLiT>Wi0Af?N4u}c63>5i(f8!%s25yK2 zJh($gP1#^{7X7nYp3|6Fi$%a2OOWJ}C3Dq@!^#?CewYn- zXf7b9JwOK6acm=0$sg#Tp}ycJV$;X|9{E-JD=;eS5;od^1|$?Z8{7yg956&7Z|NDPw*e3pI6+*ce`t#88x!DTB^Ed+(guR@ z!1`>+7r)r@XY6%I73=e1t8edBYtC#Pb8Oe--~HW}PQqSsC9#?LdvxZaWs;ff)+y=< zyr-*f_GZwg`q!R8_7F_^Z8n>tZ<_%DkEMq(00Kt=dmjXujyVKprZyeIZX=L*VW&`8 zKU6{6wdO5qR+8pRb^y6H?v*zGb&z;03I| z>c1X8W7f^k6s>f%ts4KJC%EF4$;)ik$!jGa8%vRv3$(QCFZy56KVoOTuO!qg-t{*I zyN2#~4qG}h(Z-_ zTT^ob$eZo%yis&ty?Dq+>vRv#8HRB1$=V#%K5uO07J`T91nRKHr=|k%< zDQIW#plS>f+jO(cEGMu%B6A(%R7wD$3?CY0txPi8mcjgc?rh=n^xXDQ9;6o&TN7L{ z)Sa85qsu|S#&KDm=|W#+go9%xG1u#`3P6nV`AeO&Mg>^u&O;psD6uC4$EK^M=YApInCm@UDYSyeUdKI_2wX!f7b#!rb!|pT%*2p$4ICzC zM?WTR04}%75So+BueVLe+`~XW%y*)yF`J)m^P0$?e;*Ktl37}SHTNqcg?;er3_H$rCpdOeRfhYIFWoyZ_zawfE5}2EI=L zYOCwi#bY5)QP#JIoQBOndYwn*!91gneJ>HCk&jU)zAcm55${4}EWuy_qy==e=85-! zE)b~|)ndnNe%f$21$Ws3LdWb;7<|IT0dG7)H@~;7OW^(Jl@|J_uj>pZ8VZUAnQBOI<|<`kZ7Kay zw$|Lc4jiE4x*_jz)704Z+CaB;_c62Oj2U2XyF|9WUJLBNSfXoh+Wp11HcsDmgcv$5 z|Emv%N`Lf=w?_vVgNHU4W}5yzlYMsL8vg3~e#(TPAq!Fm*k%uS-mMIIvU+6_0@%;r zss>MyJ!V5ID&dJ~^|{&=uXP8FMvYvIsbnriPgg1s)9$tB?i!B#*GY!}m$vE6@ib3m zyyOWn`VV%+T$hv%Hn)RXl&yn%Bw5)wd8T0U`WA=2@+u(3))^7f>45bjq5HVX6lK4lZh}?=HJ?zDn6b7jGs5)5YK>iGAsT6ax%hCq@cC(1FWo z^K+v8bE5b)Mw1#hhYB;PbzU-n#7dNOS{3@CB>z=S(^bp~i`lVXuW7upMPA#ost*&wt+O3e{%ywh zE0)B2*ZhS!V~!&^RwCU%dnFRe!RukE-u?Cg@BF);zuM*7Q8Up6*P#M1bOXa2=z!jF zaAt(m7<3Y-3WptVDExl9*LQK{bEk9{gfS9(v$_B|zi}JD6+W^-rR>ux(E3K!Qv>3U!r@-f;%xd+qCdQz9qYQU4ofmqJeBB z#XrdtEW-eEnjX{puK5UnSc&2Igw5qs<0Y|t&|ezJk+~AhzF?OR>za;w7>u<#^9B3_ zRTp9X(-z~<5c@L)NrH{Oft~stAbUXZc@9-PEz{mhDrHi}>5`PP#8h~1JVO-yxkU+i zIa3LoLM!NCgRK@rtW(qL-pdNu9EKk6k2CE=(=XG?8;g(gS;=1I6v0#45K!M(Z8u5= zxE$MnZL&!_P(T4|(q4mJO!#+#JD@wx!_ZU+5r4@;p~RVVloxUipDQCFr9L zo^R~Nm&R-Yyf)&$KHQ}?3NRnXdX?uEqGJSUYh{3Q$G>$P z`Z2L}neXd0;{WG=-<*4})h7vv=n_4u?L4t(h2YyjLtB0`?A{+w+O5X zDxmgb;C5`0oWhuHL}peIWQh%jOlibi0A_$nNehUyZz{CPS=Dfyau~95zq^219fv{E zQ>+?0_CVkMKqI`w{RoEPP`y}_2~K8&(Z2;Cc+p8i2p*pB$K4ccXNgV9I%5EXMZZKv zAg?)6Ch2wDU{K`i21lyy_QTm$!8%GEWwPmDU~x!A ziA@0T7QsP)b%QYxPgM`Fvd4id8vf=>yDf_Mmjil0{|`@Bt=A68L+#^bYl6 zY~`v=SQf??-}ceu5$%v8_{Z8ifaK_FiaZU&g2e+TTRsfa zU~Ju>uQv1K1z3>FkYVa|9^{jRs`!Tu}Q`9mZmhw2MJxdVVrsIK~Z)BX$>VEIRg?+X3_p7q^)S z8;!buaQyS?AkZV5Oeba1uuG8~j?$pHe?Hq)6ydazeE-?+TvEt@?vU;e@%&-?U1HwM|| zea9-cai28AQ&_ zQ0P~{jv0Dfg1DFxeFMN?eKFT8Y@G*4x?MlKh8>fH$=U;|QaLSPjbXM!w2@EDazud; z4U)jxTN#T}FiP+mnx&U8N0;=n7+xC5@JEc`YtA17=(FXnicAM5^*`{Srp60vE7Mm) zKk>y?wo?}jTY%1Uumgf6lhPl3*Mscpp-cxh_5q$+H&8%plbY?-!TAPgr|eYjjEv=4 z%!7q;{D@`;SCFE{RG_8Zz>Z-Ad9nrfaCjQs%Ie5fR;Pw&fG)7%7$*igz;iJef3DbQ zoyBM-BMjOJvVK=Hj>h5TZi6;olW9iHG##W%GNDU!Tu-^zBN_=F4Put9EvK{M1~*{( z!|4-qf7zaO8`ThjHnW*?+1?X485VZ@V@8oBOCy8c|Ib?#hdADE7PFdtc<}?f@`W^uZa-8;$ zOLlK_#`VvPb%g^|4i(5MpoplU#%(m?x$A;}l}zC}zR9}m(Im$9*}RXvl^A$!4V>z~(MJ{rW1Uoz>*H|eO=o~r??bS{EXlPvvZr0+nz%yIB?Yf( z&;gDN6H=(3v8_s)W6n#!OzOuG`%(jAs{Vaa&gWB3TS#Au5+x!qH^9$xXXPw;M#� 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 TqOdWX00000NkvXXu0mjf`C@;& literal 0 HcmV?d00001 diff --git a/app/person/dashboard/resource/images/data_logo.png b/app/person/dashboard/resource/images/data_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0288cd989f7a6b4deb9bcb9749998ec4c89aad36 GIT binary patch literal 9272 zcmV-8B*)u{P)76whl9T|+1?GG&4Qg49wFuzbM^@4GWo-Cb9eU0IdY)3ZCXF950Al!%?_ z*Q$CdvofE`ssY%Sec6|N*_VCUmwkB%B47_ifB4}XZ0H4;n>_%-K@LI)NV9b)^#)|c zsyKUg0DmT;FJ7F1{(%%8H(yp)H^fUX6|e`gCxGeS=^WCJPboE=v)`qZcw8w3_$kXY zf~SW!#52#V!dF=I`|m%YMCYhXL}KfNb;SCrHB--B@01DbvRwV?)ecl2p0i*{3k=ji zf!4aNhy+y>!hQ#lFX<0HI0|1;(U*RI3exT|nI@^N6V}s-`M3ZZ#j>{Tv5T^+8s;?X z9Oz0SC`P2$Cavo?n$M;-wrXD6`u9E+&p&?yz9ORE)G2)J!xN?w3s?_R2U}lmJrF$e zS7vem<aNbmzQ=;TKhF8huv7 z9L?j^otwuUYncA0OA9cYo*=NikeMJ&vtldhD`NgH>PnJXfx)1Hjk}k{-~7!6e96R) zMZ+ftr}HfBg@alv0*#wR_Z{m?)}%fUT+4RjlV9J$psGAxd~iLSq&*Gz%Tt zEG{c)kD_BOZBrkv<1+gh<2HWX6d}#T8n*ua`zIi+p7imPGXr#9I@3TNQ9X7s&2!(W zz{Gqgbp2gr-TgrKnD4n6=;7>#C*Wbq32_9PW)RC;e?%=}mc?2TGKZXoYl^Kmf#qXV zdu;}%?q0a~I7}cD0j7U*=~Pc=M|{t6CcsDZyigc4It^<$A_z_ckot2Gm;ouH`|xjMtazoULPs*=p?O7G_WCfBfwc*g`f1 zOq)PafAH~1Wg3jX+;f50!&p(M$6%19Ja}|mvP#o)n%aifQ7?4CsjX4BN*DCI?=8VY z67k&m71^D;PW5VXg&q)U3t)9CT!#i48dM++00Ikwbz|dwSDe_Yj$;A4@Pi*@!`J4Q z)y93Vs-*7Zrek5&2mZj5M}Eesov5Fl>isl(z0vc85}7gsN(+;w=~f@|)dkxTmGctTu^tH7DV zPo6eU>iHOp|7E~L18|7wA-+!t0xlv-dGx}0MaRV{GC9^wwwF54WnW(tFaE{nunVFu zUY~*PgJrmV|8wz;b^=;|uyRyw++FfxGvh)dK9O4q`qz!y(RJ=x(%cd9*gj&Q{@7N> z5x{JqIP6#Fa$%zK#<_^pYZ5jf1JlfCE^Xtk z@vOeSBeGaq?(&d$S`7vnK7YeZs*VNC^!klrDIy6PX54qE#=ShS=A?m-&GKBt?JDaF zSFT1ooYPJBuI+!Cckt2a+E*Gs= z+;*P_jp_}xgXQgukHunb0;&TOYv$3-hoEf~0#Unklg@!=8DhXnHHW>QG=yHPYXE~I zVH&@8;HDvJZ$vbVFH{(zyhkV;b5DS%HXvoq61bQS`>uVrrE;iJ()DO7mMu8;uUa)? zoFE5kz>4ZaWuS4zc*XkvzJFf7`Q`}Af}oi(lw%^gpC}7>i zl_fAE#>$L1Lk%xcOMW{&jyync59*iQHSx^TpI9%-7}(Y3Sf_v&gxhNwD#Lo54V=-j zFqP)6f9)|ALNb1m!VA2v(<$J{p%s`=^n1p`EX0Y(61Wn2v!R!zY%k;XPWZ;UAZLcmF@YI>(;>0M|5!L)jpnK28*=u3K_FksEkToETGW4tjO zsM04R+6;mtgx!oBRPQJm(2N7t3Ywvkqyx=st7ybzz{W2g3Qz|`*B(NfxU%@pe)sN( zQxyT0%ib;DK-6G-d@^8(=b!nc`H-fj0JKmqyiZgs9LRzuJ_PhN&3DZS%>0d{DI zXe=XuBI3ZY{m!D0q8M{Jfa}*c2Mp4|=lJp{D0jh~8ME5J@`bnNQRJ(av%VTvtSjVA8qxa%>Il{)+JMs?XPaS@u9kgeU z+?QqlitKbsZ}y$wc-v$_s9x@T#Gp7QPo{cccw0kwzcE61C-KXl9YRvxh#J~HB=6m{ zV-{>7GwaOc+8$$j5GO;)EV^?xR*O@^T;stgDO~@Bp?us-{7nkhuMGcaHOq`4E?2NN zM=CtihYNKHf@ZP$V|7f)&KxWo~KE`P9}$hFNh%Quec$%>|4Fe=7k0wv;jhM(9A=K)gV@N~GE z<(F|KsUp*WC6mMSoyt{rA~#Mk(={^oNErxfauy1e!~D_nZJ~q(P0qjvSWe&J>M<>z zS_yT+cd$+=JKg?fU|DJ9647-n@+-2JebzH1C~Va@4y?LBrr|THJR1`z5cY(zLfVGs zbr679xhyoG@v(+mRm7LYaG?7CU49z!bb%VoPip`pq^-EQt*GJ1J8d*HSvr+gDLirf ztiE`0zWHt}pD8DrG%O4`N;1+`fIx5IGi_%|&6p+i)vfBdsyzOru%G5f~mivYh8qdaZJr>{)U)jW0=iiSsK$eq^H*BN8$6WWvjPpNemM zV}vx0>dos(Rz$-(T>Gfi8yqLw(l8H}8yCXFC25xR#)j+g@ud}eJoLEC+4j1k^|Xof z)K~os1;a`Yrv*zSB3CSxP9??zbqPTD9zLPS85|ZsM=S*vTr?~J1P2Pwn~sNp|G}dV zHr2Gc-d^LeoXOp3!NO<4lwzl`Ra%_z5qwKzkJ@3?yipkHabUbH%MaE)Q~}pED2*AJ z?@gy!1}qxjJ@+XboyI)VanF$>NkExnV1hRB`tf>4npwl}`Z{7_h)<79CXHBKv3hPEpj; z@g#V@2>BV&JaPM}Uq0Evs@z>9-jFj7eW-i%Ly56?Nu%;J;mA9sBf(AE@eUyWRR7|&;7_93C zEH$W5voHvS(6Gd;__52n-YV7eXS_dOP*u6X{SW8uEXNgnFM3UY-F(XEQXnf(* z_#(_G1cH~DMn7{bebQ(gV!8l?CzLYsHWa{mp>lmYj>TrO^W{bswE6jTE6NDtm8^$s z2$`3u9E=MW9#{FHqNW zKbGeOEGPlPcDvSVz-R>LC^6I2unc3}=)W}w1(iXhqGvd|pL>UJZ z2YV!QiCu$lqwFYaW^snOMWZ2prkZk0o<{b3p@EH0OofkDRZYI8(!R7afNR-R@zMlf znJInK08gb!qAOh{G&NFH6{I$E02db2=Exk2;wD4;2{YYafA_%QecE12&q(VG1er|Zp1g237egOb;=U+9#e+O9G7Vw^C!k~9LRSaEPOZYp`aPm*-=~Z z$~Kg#91PV4tbTl1ys`B@7WyA9+NqJ_SWwgW6_hm)uEA|X+s3qwYsL2W)B{zBRGY@k zQ#^0~bN4!CLt>fmITk2$tkN1a46n5S8$eP7#GE&s#e#&w#w!FKDteXyOH6F$wm6cwH&#p~02wMjQ^8lGivm)DqSqhZ-F?@(~?_18P#`8R(>ylo5 ziXO#XEoo};%(Qt%lI|&3R(5@#4iYKyBYsN4R9a61meni+7P{a?ycCtbN5_O~aDEKj zMM8+?ct^7Wvaxd1r=HvKDs!_62wL9Sv3dUF!vM=l274s3Og@83V0tr53zjH+T6A;K zgjtbB_ZBQG zd!}KK4R2$}ISp99{a^nq+!-%?+~rbeH33KdNRrIQz`OLTQ*bu9*me3dh3x z*)l77Hl?^#hUC8fd&8UVJy=)-*hA63{_S!2!{yb9!1~p%PMHQc90=Sv?aONqOEFL` zM}v+B4v@};MdQGZ<7XQ86oeqyY7mmrY@Ifc1}a89Iqq{X+{pj*>E+!FjJJ}95{GRj zI7|HMtH%*6CrtvD|0NZoc!)C&!NhUqK70l?ldO1-AbTIUXEx`?@E&_EbuOufjY%!X zZpz-7#0dn~p#8g-mkF%q%FBp8^0WhZX9AD&d_KCDru8{DNI@;GRf`wM*AuSp(UeQV z2t?u^ebAhC)*b~|Rvwv#Au)RR$#bfc;~Y^mrJ+Z)hlDhRsB@XcEIr-l`N7EP;OquV zu3^-MY^0D!l$O;_1D1I4`A^^x$s^G);Vkj&p=D8) zIl2K}3*2T~Xxz&V$%MIjUIo%3@FKOOTHx{?6FdjKC z&x2L)sSw37nkY|F0fAMIYrPxez_Rq4dF7Jf$@1Z2Yv->1@TYsad(T4y4D-^BX60oE zSAtM)j;15zD2+to!OGmC1zPA%i{r@=@m?g2JN5O_flLd?!;_t>uOKAl_~$5_;dDcM z^M%%JZuJEdiWsgGmjK(_3}{cCpKVR&-Yt13fY}N>Wi-o-3;F2$t^3Au%{f0;KfpDx z1(an%k>*AGA{%#no+G^jy+_sP6z-jQSa?X!QA0f*tbcs(q|!yb9R_@w{)O9E6tn+jv$V?x94av zM7%Le7Sl~b=G{>aAQvKnX<;A)Cxl04oE#=5gv4v9{fF}4*T;ZmJ;BGGSdPHL6K+8w zfH&2$GV?eG9y_n!d1tE4zqXP+(=ePR)-%UI57LN9fY9UpU+VWfhtTqepyH{JG1DA) z4qqB;60~S#xRx;>B<9Ni*00Td>surHW7skHDacRf-2**b&&)_*|IS9e{JT_gO?>Oc zUD;P;PXNvJy;Rndu4QS0}Dkq>oioKwzN3o?5v70p5`>N>ww)gV0AkVtc>m7;ny^aFy$df z@ApiH-KvjxJD2>@1Vk~CF$#{yX(0m_fN8G%r!ru@G71*%3S^uJRV6tl=kQFcjIy%A zgLt_j{u2ZG@v+>bva5jE0Mb&XL8B>kp@7+{BckjYvCJ&H6Gq0!=nX<)#DH+c)hDv|R)2 zi?`mLoA2r6x`fQ!s3wcxE&&X?9eJ;NBx7T1Bva1@VfA$acY;i;ljTkcj znQ!ahO&c?ls?h-cxXZVQSg8idTi=((CJPu9HDfd@UAoe?QSx;YLoId}mStM!Kym^Y zpe@0acPds9zS4ye+V${|+!Qar_z6rYyFP|l&`g<+a*c}OrRFav_*}xkE7G%QgE7wW z1$MsHDo?gYyQbBR)_gvd$F%k!pX+?os#zv(RNZ^arbDd4AD(Yqy_8F7wu-yI81P0)`$detGvky^GBZ3am#_ZthZBLeeGTiV1xV9maU5u` ze0@!(vn!F=z!No}=PSkSe0>C(d|%ku*j+=Dm26b^41?nZRnr`=7Y3~PRavJzb}+KUxamNVa&?3T6v}y$l4FIw&@PgQE`TYm2G)Q31D>h9X9(UlN#!-V=g-FsNtS??^o2z>8 zi(f3w7WpyWX>i;ep}~S#_f~-rV{A%Dj|&~MNvlbwx%3>7rTLk2Upu>%dEDMFLl|>t z>~9{@!LoEQ?T*p3SJu85+`nW-`a*#k3mQq-e=z1Ao7Y6^k7*aRqF{^bTqB8cIBsIm zf@SVKs@&Mi6oA%;L6Rx~QMQ%1@l-NWFB&n#aw4n`L_%X3QaNmsh{Y z?x)c;=CQl1e|+Ik^YUYcvA!|9b=5R-$r*GRRfrL?biRdw_re>7dbeVfmHkhp>u_g` zX1(=`r5W8j$~(kJ*hCJ7n=j+n)MXoGRQQTaUS>C^>L22*Mf9^D5;aZT8k`#k+O`0* z=FktO?mrhBr7)vU-~F#|k8GN6L6ZkMm+ipsfnWo%V$btGLKA@nY`TPHHYo=bbMxz( zmFuwn*;q3;)9pU#9{|v*_mXn$A&w8xYZO7te4|r&MA+3Q%ID&Ncf?x((6w&Mrc~YQ zKXdm-KN?~Br;fv{IaGG9Tvyoe6Bgh}Pg|J&+Wk)s{-^KW9J$}pJ=ecj&W-wWVwRp4 zwonb*7X?0kETV|HqPaRqnqcacOJo3ECu1uoI z(y0Km4uu$`K8eN`l8GNr+?TnT`IDQ0re!_|Bf1LfiS2*R{S5(F{SUV9AjC%YeSHaQ zZQLAY7eDv)WhK)Y-~+$){A`DyF)EVR@byRM{LZ7;)j%2MJLv!LDo$xohWK90m2!HzY!!~ZQ4oB{ra3n8-mdBowr^T#Pw3n29cF1vzS|ek-#qrJqDwNCC zTRK-#mE(UIVl%PkP!*PE3;dnuFS3xii;XU2JXrfi+E~&i{%JlNLA&$CC0&%R(ZV}I z#iZY=kDj>>YIXM2S64SHHv)l;ZZ|cdvbfSE$uJ*2xZFlpkzhD7gcZ^zVD;j=!QuCM zu&DpbA>tK%ooEpk;@;M5w`wL27d_`4RxW@yD zORugPt4C7zo0k+rRV~z#)wG}etQ9mH>}p8XF^DY9Taz}<(3rsq!Sc^Gnns|R0u8p( zEGu@_`ApS2n`^^9C{IhXdIWde9r5+`++?LSG}HO)l?mJEvvO&2d}(im4LE?}Pq(9b zzyyNkP!3N+Y`#aOa?=`ZjU4fD?wHLadj0R(bJk7Fq{?CNF3F=RHdbd}e|_6I5ti>< z>h}j*O&TIK^ryjT1;b6rSOUn_8LdlFY=2UiVmtR7V~s|v$V3{}Plu0T;hK~}Lt4SA z>HZ(KR%#CCGXVX14leh&HjQ$=y`Udkyikzs|j`+SzGekg~3j zDnk&7->G6*?`WGNVx?z5lUe6;tibTW%IuV8a66)Z{NqE5Wp`QWVH(u~ATTPX9(t(O zaZId2-oF=g?(FV3qs)df9T&l@XvlCswxIa!Cd^sC(>lIxtzp^WL&{E>SM?9sNV2!i zy~cQ`Su+w`@8tqSYz_9A)dC%nF`$WWzw}3WcP?{Wv!ZuMz;SC6XJ|`% z+yBYW&U6GEgoLt$ToA-P!8NjMXfX&3|Rqn8TzJ^R_qm z25y4IO9-wI?i^NH@w4t#o+tlGhSdn>0>yB3@!+m4ju) zd!M;6k3@!$mL;`?LEykWJE?9bqsjJJheqN*ptwR!7kCBrIvRRKjbi@2s_y2CRHau&j&+tUEje z1GfJqIuK5ClEN2+xIK!=6x0j!Jm+WrR=T(c$=ofe?%bKgPCsf9Z&=XYe1D=nvi|%3 zI;r|<0TN3ZC{Y6gVa*wW2!ey9s_e$>cV6CBOxbD@Er+HC)w7&x!FYnA`Kq$Nl;_M| z7MVS~Hp>baBPzL%;jP6iC{35m+ra-72u{Et4 zcCRSry2c;z;G}7y`b8Ls69{%WaT=AG$&q5?&V3=)9^Y7B|8oS1#DX>aH_t5_uzHc- z&v?N4ud3s?(za2i&BT@&55Kb`wx$)Zyv*k9M#bI^C%o6F5bH`gfI)ftX1Z}_@!!Ax zr5lg-LI^AYSr0q2Ov2tEXl(>`a?UH-wpthcPmN~nm|ANEtYchT46)LIwmv&QXPt(! zRQG3K{;v3sUk=aiVF}KS4fV3nISsK literal 0 HcmV?d00001 diff --git a/app/person/dashboard/resource/images/hour.png b/app/person/dashboard/resource/images/hour.png new file mode 100644 index 0000000000000000000000000000000000000000..b4c1a425f2519b988c528718aa6744579981b7ee GIT binary patch literal 44838 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 literal 0 HcmV?d00001 diff --git a/app/person/dashboard/resource/images/review.png b/app/person/dashboard/resource/images/review.png new file mode 100644 index 0000000000000000000000000000000000000000..e432d306ad18eed8bbb50bb459105534210b8e35 GIT binary patch literal 44997 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

<`8cv1l%UtZw3;c+9wC#wy=GhmyA(LqW;w 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 literal 0 HcmV?d00001 diff --git a/app/person/dashboard/resource/images/review_logo.png b/app/person/dashboard/resource/images/review_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..76b3fecf1de35a1e40189f3e2c93891a284cba46 GIT binary patch literal 5404 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 5 ? value.slice(0, 5) : value +} + +function toTimeWithSeconds(value?: string) { + if (!value) return undefined + return value.length === 5 ? `${value}:00` : value +} + +type LeaderTreeNode = { + title?: string + value?: string | number + children?: LeaderTreeNode[] +} + +function flattenLeaderTree( + nodes: LeaderTreeNode[], + prefixTitle: string[] = [] +): Array<{ label: string; value: string }> { + const result: Array<{ label: string; value: string }> = [] + + nodes.forEach((node) => { + const title = node.title ?? "" + const nextPrefix = title ? [...prefixTitle, title] : prefixTitle + const children = node.children ?? [] + const hasChildren = children.length > 0 + const valueRaw = node.value + + if (hasChildren) { + result.push(...flattenLeaderTree(children, nextPrefix)) + return + } + + if (valueRaw === undefined || valueRaw === null) return + if (typeof valueRaw === "string" && valueRaw.includes("-")) return + + result.push({ + label: nextPrefix.join(" / "), + value: String(valueRaw), + }) + }) + + return result +} + +function HourRightSection() { + return ( + + 小时(H) + + ) +} + +export default function DailyReportModal(props: { + opened: boolean + record: Daily.DailyWorkList | null + projectOptions: Array<{ label: string; value: string }> + onCloseAction: (refresh?: boolean) => void +}) { + const { opened, record, onCloseAction, projectOptions } = props + + const user_id = usePermissionStore((s) => s.user_id) + const user_name = usePermissionStore((s) => s.user_name) + const treeData = useAllUserStore((s) => s.treeData) + + const leaderOptions = useMemo(() => { + return flattenLeaderTree(treeData ?? []) + }, [treeData]) + + const form = useForm({ + initialValues: { + user_name: user_name ?? "", + date: "", + start_time: "", + end_time: "", + set_type: "", + actual_type: "", + project_id: "", + leader_uid: "", + work_type: "", + accounting_type: "", + performance_accounting: "", + obj_type: "", + work_time: undefined as number | undefined, + rate: undefined as number | undefined, + standard_size: undefined as number | undefined, + completed_size: undefined as number | undefined, + residual_size: undefined as number | undefined, + residual_work_time: undefined as number | undefined, + residual_pm: "", + remarks: "", + }, + validate: { + date: (v) => (v ? null : "请输入日期"), + // set_type: (v) => (v ? null : "请选择规定类型"), + actual_type: (v) => (v ? null : "请选择出勤类型"), + }, + validateInputOnChange: true, + validateInputOnBlur: true, + clearInputErrorOnChange: true, + }) + + useEffect(() => { + if (!opened) return + + if (!record) { + form.setValues({ + user_name: user_name ?? "", + date: new Date().toISOString().slice(0, 10), + start_time: "", + end_time: "", + set_type: "", + actual_type: "", + project_id: "", + leader_uid: "", + work_type: "", + accounting_type: "", + performance_accounting: "", + obj_type: "", + work_time: undefined, + rate: undefined, + standard_size: undefined, + completed_size: undefined, + residual_size: undefined, + residual_work_time: undefined, + residual_pm: "", + remarks: "", + }) + form.resetDirty() + return + } + + form.setValues({ + user_name: user_name ?? "", + date: record.date ?? "", + start_time: normalizeTimeValue(record.start_time), + end_time: normalizeTimeValue(record.end_time), + set_type: record.set_type ?? "", + actual_type: record.actual_type ?? "", + project_id: + record.project_id === undefined || record.project_id === null + ? "" + : String(record.project_id), + leader_uid: + record.leader_uid === undefined || record.leader_uid === null + ? "" + : String(record.leader_uid), + work_type: record.work_type ?? "", + accounting_type: record.accounting_type ?? "", + performance_accounting: + record.performance_accounting === true + ? "true" + : record.performance_accounting === false + ? "false" + : "", + obj_type: + record.obj_type === undefined || record.obj_type === null + ? "" + : String(record.obj_type), + work_time: record.work_time ?? undefined, + rate: record.rate ?? undefined, + standard_size: record.standard_size ?? undefined, + completed_size: record.completed_size ?? undefined, + residual_size: record.residual_size ?? undefined, + residual_work_time: record.residual_work_time ?? undefined, + residual_pm: + record.residual_pm === true + ? "正" + : record.residual_pm === false + ? "负" + : "", + remarks: record.remarks ?? "", + }) + form.resetDirty() + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [opened, record, user_name]) + + useEffect(() => { + const workTime = form.values.work_time + const rate = form.values.rate + if (workTime !== undefined && rate !== undefined) { + form.setFieldValue("standard_size", Number((workTime * rate).toFixed(1))) + } else { + form.setFieldValue("standard_size", undefined) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + useEffect(() => { + const standardSize = form.values.standard_size + const completedSize = form.values.completed_size + const workTime = form.values.work_time + + if ( + standardSize !== undefined && + completedSize !== undefined && + workTime !== undefined && + standardSize !== 0 + ) { + const residualSize = completedSize - standardSize + const residualWorkTime = Number( + ((residualSize / standardSize) * workTime).toFixed(1) + ) + form.setFieldValue("residual_size", Number(residualSize.toFixed(1))) + form.setFieldValue("residual_work_time", residualWorkTime) + form.setFieldValue("residual_pm", residualSize >= 0 ? "正" : "负") + } else { + form.setFieldValue("residual_size", undefined) + form.setFieldValue("residual_work_time", undefined) + form.setFieldValue("residual_pm", "") + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + const handleSubmit = form.onSubmit(async (values) => { + const uid = typeof user_id === "number" ? user_id : Number(user_id ?? 0) + if (!uid) { + notifications.show({ + color: "red", + title: "提交失败", + message: "未获取到用户信息", + }) + return + } + + const params: Daily.CreateProps = { + uid, + date: values.date, + start_time: toTimeWithSeconds(values.start_time), + end_time: toTimeWithSeconds(values.end_time), + set_type: values.set_type, + actual_type: values.actual_type, + project_id: values.project_id ? Number(values.project_id) : undefined, + leader_uid: values.leader_uid ? Number(values.leader_uid) : undefined, + work_type: values.work_type || undefined, + accounting_type: values.accounting_type || undefined, + performance_accounting: + values.performance_accounting === "true" + ? true + : values.performance_accounting === "false" + ? false + : undefined, + obj_type: values.obj_type ? Number(values.obj_type) : undefined, + work_time: values.work_time, + rate: values.rate, + standard_size: values.standard_size, + completed_size: values.completed_size, + residual_size: values.residual_size, + residual_work_time: values.residual_work_time, + residual_pm: + values.residual_pm === "正" + ? true + : values.residual_pm === "负" + ? false + : undefined, + remarks: values.remarks || undefined, + } + + try { + if (record?.id) { + await editDailyWorkData(params, record.id) + notifications.show({ + color: "green", + title: "操作成功", + message: "已更新日报", + }) + } else { + await addDailyWorkData(params) + notifications.show({ + color: "green", + title: "操作成功", + message: "已提交日报", + }) + } + onCloseAction(true) + form.reset() + } catch (e) { + notifications.show({ + color: "red", + title: "操作失败", + message: e instanceof Error ? e.message : "请求失败", + }) + } + }) + + return ( + { + form.reset() + onCloseAction() + }} + title={record ? "编辑日报" : "填写日报"} + size={840} + centered + closeOnClickOutside={false}> +

+ + + + +
+ + + +
+ + +
+ + + + + + } + rightSectionWidth={78} + {...form.getInputProps("work_time")} + /> + +
+ + + +
+ + + } + rightSectionWidth={78} + /> + + + + + + + + + + + + + ) +} diff --git a/app/person/report/config.ts b/app/person/report/config.ts new file mode 100644 index 0000000..8763169 --- /dev/null +++ b/app/person/report/config.ts @@ -0,0 +1,68 @@ +export const setTypeOpts = [ + { label: "出勤", value: "出勤" }, + { label: "周末休", value: "周末休" }, + { label: "节假休", value: "节假休" }, +] + +export const actualTypeOpts = [ + { label: "出勤", value: "出勤" }, + { label: "周末休", value: "周末休" }, + { label: "节假休", value: "节假休" }, + { label: "调休", value: "调休" }, + { label: "补勤", value: "补勤" }, + { label: "增勤", value: "增勤" }, + { label: "年假", value: "年假" }, + { label: "事假", value: "事假" }, + { label: "病假", value: "病假" }, + { label: "婚假", value: "婚假" }, + { label: "产假", value: "产假" }, + { label: "陪产假", value: "陪产假" }, + { label: "丧假", value: "丧假" }, + { label: "其他", value: "其他" }, +] + +export const workTypeOpts = [ + { label: "标注", value: "标注" }, + { label: "审核", value: "审核" }, + { label: "复审", value: "复审" }, + { label: "标注返工", value: "标注返工" }, + { label: "审核返工", value: "审核返工" }, + { label: "复审返工", value: "复审返工" }, + { label: "管理", value: "管理" }, +] + +export const accountTypeOpts = [ + { label: "对象核算", value: "对象核算" }, + { label: "素材核算", value: "素材核算" }, + { label: "会议", value: "会议" }, + { label: "培训", value: "培训" }, + { label: "项目管理", value: "项目管理" }, + { label: "出差", value: "出差" }, + { label: "断电", value: "断电" }, + { label: "网络故障", value: "网络故障" }, + { label: "平台故障", value: "平台故障" }, + { label: "支援行政", value: "支援行政" }, + { label: "公司活动", value: "公司活动" }, + { label: "请假", value: "请假" }, + { label: "其他", value: "其他" }, +] + +export const performanceOpts = [ + { label: "是", value: "true" }, + { label: "否", value: "false" }, +] + +export const objTypeOpts = [ + { label: "静态", value: "0" }, + { label: "动态", value: "1" }, +] + +export const performanceTextMap = new Map([ + [true, "是"], + [false, "否"], +]) + +export const objTypeTextMap = new Map([ + [0, "静态"], + [1, "动态"], +]) diff --git a/app/person/report/page.tsx b/app/person/report/page.tsx index c344805..1c4aefd 100644 --- a/app/person/report/page.tsx +++ b/app/person/report/page.tsx @@ -1,5 +1,710 @@ "use client" -export default function ReportPage() { - return <>Person Report +import { + deleteDailyWorkData, + getSelfDailyWorkList, +} from "@/components/label/api/daily" +import { Daily } from "@/components/label/api/daily/typing" +import { getSelfProjectList } from "@/components/label/api/project" +import { useAllUserStore } from "@/components/label/store/auth" +import { + ActionIcon, + Badge, + Button, + Collapse, + Flex, + Group, + MultiSelect, + Paper, + SimpleGrid, + Stack, + Text, + TextInput, +} from "@mantine/core" +import { modals } from "@mantine/modals" +import { notifications } from "@mantine/notifications" +import { + IconChevronDown, + IconChevronUp, + IconPencil, + IconPlus, + IconRefresh, + IconSearch, + IconTrash, +} from "@tabler/icons-react" + +import dayjs from "dayjs" +import { + DataTable, + DataTableColumn, + DataTableSortStatus, +} from "mantine-datatable" +import { useCallback, useEffect, useMemo, useState } from "react" +import DailyReportModal from "./components/DailyReportModal" +import { + accountTypeOpts, + actualTypeOpts, + objTypeOpts, + objTypeTextMap, + performanceOpts, + performanceTextMap, + setTypeOpts, + workTypeOpts, +} from "./config" + +type LeaderTreeNode = { + title?: string + value?: string | number + children?: LeaderTreeNode[] +} + +function flattenLeaderTree( + nodes: LeaderTreeNode[], + prefixTitle: string[] = [] +): Array<{ label: string; value: string }> { + const result: Array<{ label: string; value: string }> = [] + + nodes.forEach((node) => { + const title = node.title ?? "" + const nextPrefix = title ? [...prefixTitle, title] : prefixTitle + const children = node.children ?? [] + const hasChildren = children.length > 0 + const valueRaw = node.value + + if (hasChildren) { + result.push(...flattenLeaderTree(children, nextPrefix)) + return + } + + if (valueRaw === undefined || valueRaw === null) return + if (typeof valueRaw === "string" && valueRaw.includes("-")) return + + result.push({ + label: nextPrefix.join(" / "), + value: String(valueRaw), + }) + }) + + return result +} + +function weekDayText(day: number) { + const list = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"] + return list[day] ?? "-" +} + +function toBoolean(value?: string) { + if (value === "true") return true + if (value === "false") return false + return undefined +} + +function toNumber(value?: string) { + if (!value) return undefined + const n = Number(value) + return Number.isFinite(n) ? n : undefined +} + +export default function PersonReportPage() { + const treeData = useAllUserStore((s) => s.treeData) + + const leaderOptions = useMemo(() => { + return flattenLeaderTree(treeData ?? []) + }, [treeData]) + + const defaultFilters = useMemo(() => { + return { + date_start: dayjs().subtract(6, "day").format("YYYY-MM-DD"), + date_end: dayjs().format("YYYY-MM-DD"), + set_type: "", + actual_type: "", + leader_uid: [] as string[], + work_type: "", + accounting_type: "", + project_id: [] as string[], + performance_accounting: "", + obj_type: "", + } + }, []) + + const [projectOptions, setProjectOptions] = useState< + Array<{ label: string; value: string }> + >([]) + + const [filters, setFilters] = useState(defaultFilters) + const [appliedFilters, setAppliedFilters] = useState(defaultFilters) + const [queryTrigger, setQueryTrigger] = useState(0) + + const [page, setPage] = useState(1) + const [pageSize, setPageSize] = useState(20) + const [totalItems, setTotalItems] = useState(0) + const [loading, setLoading] = useState(false) + const [records, setRecords] = useState([]) + const [summary, setSummary] = useState(null) + + const [sortStatus, setSortStatus] = useState({ + columnAccessor: "id", + direction: "desc", + }) + + const [modalOpened, setModalOpened] = useState(false) + const [editingRecord, setEditingRecord] = + useState(null) + + const [searchExpanded, setSearchExpanded] = useState(false) + + const queryParams = useMemo(() => { + const params: Daily.Request = { + page_number: page, + page_size: pageSize, + flag: 0, + date_start: appliedFilters.date_start || undefined, + date_end: appliedFilters.date_end || undefined, + set_type: appliedFilters.set_type || undefined, + actual_type: appliedFilters.actual_type || undefined, + leader_uid: appliedFilters.leader_uid.length + ? appliedFilters.leader_uid + .map((v) => Number(v)) + .filter((v) => Number.isFinite(v)) + : undefined, + work_type: appliedFilters.work_type || undefined, + accounting_type: appliedFilters.accounting_type || undefined, + project_id: appliedFilters.project_id.length + ? appliedFilters.project_id + .map((v) => Number(v)) + .filter((v) => Number.isFinite(v)) + : undefined, + performance_accounting: toBoolean(appliedFilters.performance_accounting), + obj_type: toNumber(appliedFilters.obj_type), + order_by: `${sortStatus.columnAccessor} ${sortStatus.direction}`, + } + + Object.keys(params).forEach((k) => { + const key = k as keyof Daily.Request + const value = params[key] + if (value === "" || value === null) delete params[key] + if (Array.isArray(value) && value.length === 0) delete params[key] + if (value !== 0 && value !== false && value !== "" && !value) + delete params[key] + }) + + return params + }, [ + appliedFilters, + page, + pageSize, + sortStatus.columnAccessor, + sortStatus.direction, + ]) + + const load = useCallback(async () => { + if (!queryTrigger) return + setLoading(true) + try { + const res = await getSelfDailyWorkList(queryParams) + setRecords(res?.daily_work_list ?? []) + setTotalItems(res?.total_items ?? 0) + setSummary(res?.total_summary ?? null) + } catch (e) { + setRecords([]) + setTotalItems(0) + setSummary(null) + notifications.show({ + color: "red", + title: "加载失败", + message: e instanceof Error ? e.message : "请求失败", + }) + } finally { + setLoading(false) + } + }, [queryParams, queryTrigger]) + + useEffect(() => { + load() + }, [load]) + + useEffect(() => { + queueMicrotask(() => { + setQueryTrigger((v) => v + 1) + }) + }, []) + + const columns = useMemo(() => { + const cols: DataTableColumn[] = [ + { accessor: "id", title: "ID", width: 80, sortable: true }, + { + accessor: "date", + title: "日期", + width: 120, + sortable: true, + render: (record) => record.date ?? "-", + }, + { + accessor: "week", + title: "星期", + width: 90, + render: (record) => + record.date ? weekDayText(dayjs(record.date).day()) : "-", + }, + { + accessor: "set_type", + title: "规定类型", + width: 120, + render: (record) => record.set_type ?? "-", + }, + { + accessor: "actual_type", + title: "实际类型", + width: 120, + render: (record) => record.actual_type ?? "-", + }, + { accessor: "leader_name", title: "任务组长", width: 120 }, + { accessor: "work_type", title: "工作类别", width: 140 }, + { accessor: "accounting_type", title: "核算方式", width: 140 }, + { + accessor: "project_name", + title: "项目名称", + width: 220, + render: (record) => ( + + {record.project_name ?? "-"} + + ), + }, + { + accessor: "performance_accounting", + title: "绩效核算", + width: 110, + render: (record) => { + if (record.performance_accounting === true) + return {performanceTextMap.get(true)} + if (record.performance_accounting === false) + return {performanceTextMap.get(false)} + return "-" + }, + }, + { + accessor: "obj_type", + title: "对象类型", + width: 100, + render: (record) => { + if (record.obj_type === 0 || record.obj_type === 1) + return objTypeTextMap.get(record.obj_type) ?? "-" + return "-" + }, + }, + { accessor: "start_time", title: "开始时间", width: 120 }, + { accessor: "end_time", title: "结束时间", width: 120 }, + { + accessor: "work_time", + title: "工时", + width: 90, + sortable: true, + }, + { accessor: "rate", title: "额定倍率", width: 90 }, + { + accessor: "standard_size", + title: "标准量", + width: 90, + sortable: true, + }, + { + accessor: "completed_size", + title: "完成量", + width: 90, + sortable: true, + }, + { + accessor: "residual_size", + title: "余量", + width: 90, + sortable: true, + }, + { + accessor: "residual_work_time", + title: "余量工时", + width: 110, + sortable: true, + }, + { + accessor: "remarks", + title: "备注", + width: 200, + render: (record) => ( + + {record.remarks ?? "-"} + + ), + }, + { + accessor: "operation", + title: "操作", + width: 90, + textAlign: "center", + render: (record) => { + const disabled = !!record.lock_status + return ( + + { + if (disabled) return + setEditingRecord(record) + setModalOpened(true) + }}> + + + { + if (disabled || !record.id) return + modals.openConfirmModal({ + title: "删除日报", + centered: true, + children: ( + + 删除后不可恢复,你确定删除该日报吗? + + ), + labels: { confirm: "删除", cancel: "取消" }, + confirmProps: { color: "red" }, + onConfirm: async () => { + await deleteDailyWorkData(record.id as number) + notifications.show({ + color: "green", + title: "操作成功", + message: "已删除日报", + }) + load() + }, + }) + }}> + + + + ) + }, + }, + ] + return cols + }, [load]) + + const summaryText = useMemo(() => { + return { + total_work_time: summary?.total_work_time ?? 0, + total_standard_size: summary?.total_standard_size ?? 0, + total_completed_size: summary?.total_completed_size ?? 0, + total_residual_size: summary?.total_residual_size ?? 0, + total_residual_work_time: summary?.total_residual_work_time ?? 0, + } + }, [summary]) + + const asyncGetSelfProjectList = useCallback(async () => { + const res = await getSelfProjectList() + setProjectOptions( + (res ?? []).map((r) => ({ label: r.label, value: String(r.value) })) + ) + }, []) + + useEffect(() => { + queueMicrotask(() => asyncGetSelfProjectList()) + }, [asyncGetSelfProjectList]) + + return ( + + + + + + 搜索条件 + + + + + + + + + + + + setFilters((s) => ({ + ...s, + date_start: e.target.value, + })) + } + /> + { + setFilters((s) => ({ ...s, date_end: e.target.value })) + }} + /> + setFilters((s) => ({ ...s, project_id: v }))} + /> + setFilters((s) => ({ ...s, leader_uid: v }))} + /> + + setFilters((s) => ({ ...s, set_type: v[0] ?? "" })) + } + /> + + setFilters((s) => ({ ...s, actual_type: v[0] ?? "" })) + } + /> + + setFilters((s) => ({ ...s, work_type: v[0] ?? "" })) + } + /> + + setFilters((s) => ({ ...s, accounting_type: v[0] ?? "" })) + } + /> + + setFilters((s) => ({ + ...s, + performance_accounting: v[0] ?? "", + })) + } + /> + + setFilters((s) => ({ ...s, obj_type: v[0] ?? "" })) + } + /> + + + + + + + + + + + + + + + width="100%" + style={{ width: "100%" }} + withTableBorder + withRowBorders + pinFirstColumn + pinLastColumn + scrollAreaProps={{ type: "auto" }} + fetching={loading} + records={records} + columns={columns} + totalRecords={totalItems} + recordsPerPage={pageSize} + page={page} + onPageChange={setPage} + onRecordsPerPageChange={(v) => { + setPageSize(v) + setPage(1) + }} + recordsPerPageOptions={[10, 15, 20, 50]} + noRecordsText="暂无数据" + recordsPerPageLabel="当前页数" + sortStatus={sortStatus} + onSortStatusChange={(s) => { + setSortStatus(s) + setPage(1) + }} + /> + + + + 当前页总计 + + + 工时:{summaryText.total_work_time} + 标准量:{summaryText.total_standard_size} + + 完成量:{summaryText.total_completed_size} + + 余量:{summaryText.total_residual_size} + + 余量工时:{summaryText.total_residual_work_time} + + + + + + + + { + setModalOpened(false) + setEditingRecord(null) + if (refresh) load() + }} + /> + + ) } diff --git a/components/label/api/const.ts b/components/label/api/const.ts new file mode 100644 index 0000000..25355ce --- /dev/null +++ b/components/label/api/const.ts @@ -0,0 +1,4 @@ +export const BASE_LABEL_API = + process.env.NEXT_PUBLIC_ENV === "production" + ? "https://label.cowarobot.com" + : "https://label.softtest.cowarobot.com" diff --git a/components/label/api/daily/index.ts b/components/label/api/daily/index.ts new file mode 100644 index 0000000..b3011f9 --- /dev/null +++ b/components/label/api/daily/index.ts @@ -0,0 +1,49 @@ +import httpFetch from "@/api/fetch" +import { Daily } from "./typing" +import { BASE_LABEL_API } from "../const" + +export const getSelfDailyWorkList = (data: Daily.Request) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/daily_work/list/self", + method: "POST", + body: JSON.stringify(data), + }) +} +export const getTeamDailyWorkList = (data: Daily.Request) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/daily_work/list/team", + method: "POST", + body: JSON.stringify(data), + }) +} + +export const addDailyWorkData = (data: Daily.CreateProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/daily_work/add", + method: "POST", + body: JSON.stringify(data), + }) +} + +export const editDailyWorkData = (data: Daily.CreateProps, id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/daily_work/edit/${id}`, + method: "put", + body: JSON.stringify(data), + }) +} + +export const deleteDailyWorkData = (id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/daily_work/delete/${id}`, + method: "delete", + }) +} + +export const lockDailyWorkData = (lock_status: boolean, id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/daily_work/lock/${id}`, + method: "put", + body: JSON.stringify({ lock_status }), + }) +} diff --git a/components/label/api/daily/typing.ts b/components/label/api/daily/typing.ts new file mode 100644 index 0000000..df920ae --- /dev/null +++ b/components/label/api/daily/typing.ts @@ -0,0 +1,84 @@ +export namespace Daily { + export interface Request { + date_end?: string + date_start?: string + /** + * 0-个人日报 1-团队日报 + */ + flag?: number + name?: string + order_by?: string + page_number?: number + page_size?: number + [property: string]: any + } + + export interface Summary { + total_work_time: number + total_standard_size: number + total_completed_size: number + total_residual_size: number + total_residual_work_time: number + } + + export interface Response { + daily_work_list: DailyWorkList[] + total_items: number + total_pages: number + total_summary: Summary + [property: string]: any + } + + export interface DailyWorkList { + accounting_type?: string | null + actual_type?: string + completed_size?: number + date?: string + end_time?: string + id?: number + leader_name?: string | null + leader_uid?: number | null + lock_status?: boolean + obj_type?: number | null + performance_accounting?: boolean | null + project_id?: number | null + project_name?: string | null + rate?: number + remarks?: string | null + residual_pm?: boolean | null + residual_size?: number + residual_work_time?: number + set_type?: string + standard_size?: number + start_time?: string + uid?: number + username?: string + work_time?: number + work_type?: string | null + [property: string]: any + } + + export interface CreateProps { + accounting_type?: string + actual_type: string + completed_size?: number + date: string + end_time?: string + leader_uid?: number + obj_type?: number + performance_accounting?: boolean + project_id?: number + rate?: number + remarks?: string + residual_pm?: boolean + residual_size?: number + residual_work_time?: number + set_type: string + standard_size?: number + start_time?: string + uid: number + work_time?: number + work_type?: string + [property: string]: any + } +} diff --git a/components/label/api/label/typing.ts b/components/label/api/label/typing.ts new file mode 100644 index 0000000..5d41646 --- /dev/null +++ b/components/label/api/label/typing.ts @@ -0,0 +1,171 @@ +export interface LabelResult { + data_name: string + image_objects?: ImageObjects + video_objects?: { + [key: string]: ImageObjects + } + pc_box_objects?: { [key: string]: any }[] + pc_segment_objects?: { [key: string]: any }[] + pc_vegetation_objects?: { [key: string]: any }[] +} + +export interface ImageObjects { + annotations: Annotation[] + categories: Category[] + desc?: Desc + image_groups: ImageGroups + images: Images + key_frame?: boolean + label1_ts?: number + label1_uid?: number + review1_ts?: number + review1_uid?: number + review2_ts?: number + review2_uid?: number +} + +export interface Annotation { + bbox?: number[] + category_id: number + comment?: Comment[] + create_timestamp: number + first_modified_timestamp: number + first_modified_uid: number + hollow_segmentation?: Array> + id: number + image_id: number + key_points?: KeyPoint[] + last_modified_timestamp: number + last_modified_uid: number + line_segment?: Array> + prelabel: boolean + rect?: number[] + segmentation?: Array> + sub_attributes?: { [key: string]: any } + uid: number +} + +export interface Comment { + check_box_comments: string[] + comment_type: number + date: number + scene_info: SceneInfo + text_comments: string[] + times: number + turn: number + uid: number +} + +export interface SceneInfo { + phi?: number + point_idx?: number[] + theta?: number + type: number + vfov_factor?: number + x?: number + x_offset?: number + y?: number + y_offset?: number + z?: number + zoom?: number +} + +export interface KeyPoint { + attributes?: { [key: string]: any } + point: [number, number] +} + +export interface Category { + id: number + name: string + supercategory: string +} + +export interface Desc { + meta_operation: string[] + other_desc: string +} + +export interface ImageGroups { + // "01J4GZMQ2G8KKQVF52S6EXBGRA": string; +} + +export interface Images { + file_name: string + height: number + id: number + width: number +} + +export interface RequestLabelResult { + label_object_size: { [key: string]: any } + results: LabelResult[] + task_id: number + uid: number + work_load: WorkLoad + work_time: { [key: string]: any } +} + +export interface WorkLoad { + comment_size: number + dynamic_size: { [key: number]: number } + key_frame_size: { [key: number]: number } + object_size: { [key: number]: number } + prelabel_modify_size: { [key: number]: number } + question_size: { [key: number]: number } + review_dynamic_size: { [key: number]: number } + review_key_frame_size: { [key: number]: number } + review_question_size: { [key: number]: number } + review_size: number + review_static_size: { [key: number]: number } + static_size: { [key: number]: number } + work_time: number +} + +export interface ServerResponse { + data_list?: DataList[] + proxy?: string + [property: string]: any +} + +export interface DataList { + data_name: string + data_type: string + image_data?: string + video_data?: string + pointcloud_data?: PointcloudDatum[] + [property: string]: any +} + +export interface PointcloudDatum { + intensity: number + time_offset: number + x: number + y: number + z: number + [property: string]: any +} + +export interface AuxiliaryParams { + project_id: number + file_name: string + image_hw: [number, number] + points_and_box: Array<[number, number]> + tags: number[] + clear_previous_state?: boolean +} + +interface UserInfo { + uid: number + name: string + all_projects: { [x: number]: number[] } + collect_projects: number[] + group_name: string + work_status: number + base_city: string +} + +export interface LoginInfo extends UserInfo { + token: string + refresh_token: string +} diff --git a/components/label/api/project/index.ts b/components/label/api/project/index.ts new file mode 100644 index 0000000..efdb526 --- /dev/null +++ b/components/label/api/project/index.ts @@ -0,0 +1,198 @@ +import httpFetch from "@/api/fetch" +import { Project, ProjectDetail, ReviewUsers } from "./typing" +import { BASE_LABEL_API } from "../const" + +// 获取项目列表 +export const getProjectList = (data: Project.ListRequest) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/list", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取项目详情 +export const getProjectDetailById = (id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/project/detail/${id}`, + method: "GET", + }) +} + +// 校验项目源数据 +export const checkLabelDataSource = (data: Project.CheckRequest) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/check_data", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 创建项目 +export const projectAdd = (data: Project.CreateProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/add", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 审核项目 +export const projectReview = (data: Project.CreateProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/review", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 配置项目 +export const projectConfig = (data: Project.ConfigProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/config", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 编辑项目 +export const projectEditById = (data: any, id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/project/edit/${id}`, + method: "POST", + body: JSON.stringify(data), + }) +} + +// 审核试标项目 +export const projectPreLabelReview = (data: Project.PreLabelProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/prototype_review", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 提交验收 +export const projectDeliver = (data: { project_id: number }) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/deliver", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 完成项目 +export const projectAccept = (data: { project_id: number; pass: boolean }) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/accept", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 收藏项目 +export const projectCollect = (data: { + project_id: number + is_collect: boolean +}) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/collect", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取项目抽检比例 +export const getReviewScaleList = (params: { project_id: number }) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/review_scale/list", + method: "GET", + data: params, + }) +} + +// 保存抽检比例 +export const saveUserReviewScale = (data: Project.ReviewScaleProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/review_scale/save", + method: "POST", + body: JSON.stringify(data), + }) +} + +export const getProjectDetail = (id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/project/detail/${id}`, + method: "GET", + }) +} + +// 重新生成Embedding +export const regenerateProjectEmbedding = (data: { project_id: number }) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/project/regenerate_embedding`, + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取个人参与项目 +export const getPersonProjectDashBoard = () => { + return httpFetch>({ + url: + BASE_LABEL_API + `/api/v1/label_server/data_statistics/personal_project`, + method: "GET", + }) +} + +// 获取个人看板数据 +export const getCurrentPersonData = (params: { date: string }) => { + return httpFetch<{ + label_data_size: number + label_work_time: number + review1_data_size: number + review1_work_time: number + review2_data_size: number + review2_work_time: number + }>({ + url: + BASE_LABEL_API + + "/api/v1/label_server/data_statistics/personal_dashboard", + method: "GET", + data: params, + }) +} + +/* ****************************** Options ****************************** */ +// 获取项目所属业务列表 +export const getProjectTypeList = () => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/type_list", + method: "GET", + }) +} + +// 获取项目管理员列表 +export const getProjectAdminList = () => { + return httpFetch>({ + url: BASE_LABEL_API + "/api/v1/label_server/project/admin_list", + method: "GET", + }) +} + +// 获取项目审核员 +export const getProjectReviewers = () => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/project/reviewer_map", + method: "GET", + }) +} + +// 获取用户有权限的项目 +export const getSelfProjectList = () => { + return httpFetch>({ + url: BASE_LABEL_API + "/api/v1/label_server/project/self", + method: "GET", + }) +} diff --git a/components/label/api/project/typing.ts b/components/label/api/project/typing.ts new file mode 100644 index 0000000..a3b8e42 --- /dev/null +++ b/components/label/api/project/typing.ts @@ -0,0 +1,474 @@ +export namespace Project { + export interface DataProps { + key: React.Key + id: number // 项目ID + name: string // 项目名称 + is_collect: boolean // 是否收藏 + project_type?: string // 所属业务 + label_schema_name?: string // 标注方案 + label_schema_version?: string + status: number // 项目状态 + labeled_scale?: number // 标注完成比例 + reviewed_scale?: number // 审核完成比例 + data_size?: number // 总数据量 + rate_speed?: number // 额定倍速 + create_user: string // 创建人 + owner: string // 项目负责人 + label_process?: string[] // 工序 + admin_user: number[] // 标注管理员id + data_source?: string // 数据源 + remarks?: string // 备注 + // reviewer_user?: string; // 审核人 + // reviewer_comment?: string; // 审核意见 + create_at?: string // 创建时间 + update_at?: string // 更新时间 + modify?: number //0=可以发起变更,无变更 1=正在变更,无变更 2=可以发起变更,有变更 3=正在变更,有变更 + } + + export interface CheckRequest { + project_type: string + nfs_path: string + flag: number + } + + export interface CheckResponse { + data_size: number + error_code: number + } + + export interface CreateProps { + admin_user: string[] + create_user: string + data_size: number + data_source: string + label_schema_name: string + label_schema_version: string + project_name: string + project_type: string + related_task?: number[] + remarks?: string + [property: string]: any + } + + export interface ReviewProps { + pass: boolean + project_id: number + project_name: string + review_comment?: string + review_user: string + test_proportion?: number + } + + export interface ListRequest { + admin_user?: string + create_user?: string + end_date?: string + page_number: number + page_size: number + project_id?: number + project_name?: string + project_type?: string + review_user?: string + start_date?: string + status?: number[] + [property: string]: any + } + + export interface ListResponse { + project_list: DataProps[] + total_pages: number + total_items: number + } + + export interface LabelConfig { + acquire_mode: number + acquire_size: number + avg_remind_threshold: number + dynamic_label_speed: number + filter_pre_label: boolean + fix_remind_threshold: number + label_accuracy_rate: number + label_update_month: number + max_size: number + pre_label_confirm: boolean + static_label_speed: number + } + + export interface Review1Config { + acquire_mode: number + acquire_size: number + dynamic_review1_speed: number + end_date?: string + filter_label_first_sub: boolean + filter_objs: boolean + filter_rework: boolean + filter_task_batch: boolean + filter_track_user: boolean + is_rework?: boolean + label_first_sub_end_date?: string + label_first_sub_start_date?: string + max_objs?: number + max_size: number + min_objs?: number + review1_accuracy_rate: number + review1_update_month: number + start_date?: string + static_review1_speed: number + track_user_list?: number[] + } + + export interface Review2Config { + acquire_mode: number + acquire_size: number + dynamic_review2_speed: number + end_date?: string + filter_objs: boolean + filter_review1_first_sub: boolean + filter_review1_user: boolean + filter_rework: boolean + filter_task_batch: boolean + filter_track_user: boolean + is_rework?: boolean + max_objs?: number + max_size: number + min_objs?: number + review1_first_sub_end_date?: string + review1_first_sub_start_date?: string + review1_user_list?: number[] + review2_update_month: number + start_date?: string + static_review2_speed: number + track_user_list?: number[] + } + + export interface ConfigProps { + admin_user?: number[] + check_frame?: boolean + check_task?: boolean + comment_rule?: { [key: string]: any } + default_pose?: string + is_lock_object?: boolean + label_config?: LabelConfig + label_users?: number[] + modifiable_types?: string[] + project_id: number + project_name?: string + project_remark?: string + review1_config?: Review1Config + review1_users?: number[] + review2_config?: Review2Config + review2_users?: number[] + user_grade?: { [key: string]: any } + } + + // 试标审核 + export interface PreLabelProps { + id: number + review_user: string + action: number // 1-试标完成,2-试标通过,3-试标不通过 + detail?: string + } + + export interface ReviewScaleProps { + frame_scale?: number + grade?: string + project_id: number + task_scale?: number + uids: number[] + } + /** + * DetailResponse + */ + export interface DetailResponse { + admin_user: string[] + alarm_threshold: AlarmThreshold + check_frame: boolean + check_task: boolean + comment_rule: CommentRule + create_at: string + create_user: string + data_size: number + default_pose: null + id: number + is_lock_object: boolean + label_process: LabelProcess + label_schema_list: LabelSchemaList[] + label_type: number + labeled_multiplier: LabeledMultiplier + modifiable_types: string[] + name: string + project_progress: ProjectProgress + remarks: string + rpath: string + status: number + task_size: number + user_grade: UserGrade + } + + export interface AlarmThreshold { + avg_remind_threshold: number + fix_remind_threshold: number + } + + export interface CommentRule { + check_box_rules: { + create_date: string + create_user: string + text: string + }[] + text_rules: string[] + } + + export interface LabelProcess { + filter_pre_label: boolean + filter_task_info: string[] + pre_label_confirm: boolean + step_detail: StepDetail[] + } + + export interface StepDetail { + acquire_mode: number + acquire_size: number + action: number + max_size: number + user_list: number[] + } + + export interface LabelSchemaList { + bbox_range: number[] + bbox_size: number[] + bbox_type: number + category_id: number + color: [number, number, number] + label_class: string + label_type: number + radius: number + sensor_list: string[] + sub_attributes: string[] + sub_attributes_describe: SubAttributesDescribe[] + super_category: string + } + + export interface SubAttributesDescribe { + chinese_name: string + english_name: string + isrequired: number + optional_item: string[] + round_id: number + select_mode: number + } + + export interface LabeledMultiplier { + dynamic_label_speed: null + dynamic_review1_speed: null + dynamic_review2_speed: null + label_accuracy_rate: null + label_update_month: null + review1_accuracy_rate: null + review1_update_month: null + review2_update_month: null + static_label_speed: null + static_review1_speed: null + static_review2_speed: null + } + + export interface ProjectProgress { + normal_labeled_task_size: number + normal_reviewed1_task_size: number + normal_reviewed2_task_size: number + rework_labeled_task_size: number + rework_reviewed1_task_size: number + rework_reviewed2_task_size: number + unlabeled_task_size: number + } + + export interface UserGrade { + A: { + frame: number + task: number + } + B: { + frame: number + task: number + } + C: { + frame: number + task: number + } + } + /** + * DetailResponse + */ + + export interface PersonProjectDashboardResponseItem { + project_id: number + project_label_type: string + project_name: string + project_type: string + work_time: number + } +} + +export interface ReviewUsers { + reviewer1: string[] + reviewer2: string[] + reviewer3: string[] +} + +export namespace ProjectDetail { + export interface DataProps { + admin_user: number[] + alarm_threshold: AlarmThreshold + check_frame: boolean + check_task: boolean + comment_rule: CommentRule + create_at: string + create_user: string + data_size: number + default_pose: null + id: number + is_lock_object: boolean + label_process: LabelProcess + label_schema_list: LabelSchemaList[] + label_type: number + labeled_multiplier: LabeledMultiplier + modifiable_types: string[] + name: string + project_progress: ProjectProgress + remarks: string + rpath: string + status: number + task_size: number + user_grade: UserGrade + [property: string]: any + } + + export interface AlarmThreshold { + avg_remind_threshold: number + fix_remind_threshold: number + [property: string]: any + } + + export interface CommentRule { + check_box_rules: string[] + text_rules: string[] + [property: string]: any + } + + export interface LabelProcess { + filter_pre_label: boolean + filter_task_info: FilterTaskInfo[] + pre_label_confirm: boolean + step_detail: StepDetail[] + [property: string]: any + } + + export interface FilterTaskInfo { + action: number + end_date: string + filter_label_first_sub: boolean + filter_objs: boolean + filter_review1_first_sub: boolean + filter_review1_user: boolean + filter_rework: boolean + filter_task_batch: boolean + filter_track_user: boolean + is_rework: boolean + label_first_sub_end_date: string + label_first_sub_start_date: string + max_objs: number + min_objs: number + review1_first_sub_end_date: string + review1_first_sub_start_date: string + review1_user_list: number[] + start_date: string + track_user_list: number[] + [property: string]: any + } + + export interface StepDetail { + acquire_mode: number + acquire_size: number + action: number + max_size: number + user_list: number[] + [property: string]: any + } + + export interface LabelSchemaList { + bbox_range: number[] + bbox_size: number[] + bbox_type: number + category_id: number + color: number[] + label_class: string + label_type: number + radius: number + sensor_list: string[] + sub_attributes: string[] + sub_attributes_describe: SubAttributesDescribe[] + super_category: string + [property: string]: any + } + + export interface SubAttributesDescribe { + chinese_name: string + english_name: string + isrequired: number + optional_item: string[] + round_id: number + select_mode: number + [property: string]: any + } + + export interface LabeledMultiplier { + dynamic_label_speed: number + dynamic_review1_speed: number + dynamic_review2_speed: number + label_accuracy_rate: number + label_update_month: number + review1_accuracy_rate: number + review1_update_month: number + review2_update_month: number + static_label_speed: number + static_review1_speed: number + static_review2_speed: number + [property: string]: any + } + + export interface ProjectProgress { + normal_labeled_task_size: number + normal_reviewed1_task_size: number + normal_reviewed2_task_size: number + rework_labeled_task_size: number + rework_reviewed1_task_size: number + rework_reviewed2_task_size: number + unlabeled_task_size: number + [property: string]: any + } + + export interface UserGrade { + A: A + B: B + C: C + [property: string]: any + } + + export interface A { + frame: number + task: number + [property: string]: any + } + + export interface B { + frame: number + task: number + [property: string]: any + } + + export interface C { + frame: number + task: number + [property: string]: any + } +} diff --git a/components/label/api/task/index.ts b/components/label/api/task/index.ts new file mode 100644 index 0000000..a02c752 --- /dev/null +++ b/components/label/api/task/index.ts @@ -0,0 +1,77 @@ +import httpFetch from "@/api/fetch" +import { Task } from "./typing" +import { BASE_LABEL_API } from "../const" + +// 获取任务列表 +export const getTaskList = (data: Task.ListRequest) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/list", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 领取任务 +export const taskAcquire = (data: Task.AcquireReqProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/acquire", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 调度任务 +export const taskDispatch = (data: Task.DispatchReqProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/dispatch", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 释放任务 +export const taskRelease = (data: Task.ReleaseReqProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/release", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取下一个任务 +export const getNextTaskId = (data: Task.NextReqProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/next", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 提交任务 +export const taskCommit = (data: Task.CommitReqProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/task/commit", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取任务的工作流程 +export const getTaskWorkFlow = (id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/task/workflow/${id}`, + method: "GET", + }) +} + +// 获取个人任务列表 +export const getUserTaskList = (params: { + page_size: number + page_number: number +}) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/task/list_by_user`, + method: "GET", + data: params, + }) +} diff --git a/components/label/api/task/typing.ts b/components/label/api/task/typing.ts new file mode 100644 index 0000000..3ca89f2 --- /dev/null +++ b/components/label/api/task/typing.ts @@ -0,0 +1,179 @@ +export namespace Task { + export interface DataProps { + id: number + create_date: string + data_type?: number + data_name: { + name: [string] + related_images: [] + }[] + project_id: number + project_name: string + project_uuid: string + label_status: number + current_uid?: number + current_username?: string + label_user?: number + label_username?: string + review_user1?: number + review1_username?: string + review_user2?: number + review2_username?: string + rejected: boolean + work_time: { + label_work_time: number + first_review_work_time: number + second_review_work_time: number + } + label_object_size: { + object_size: number + valid_size: number + first_comment_size: number + second_comment_size: number + new_size: number + prelabel_size: number + prelabel_modify_size: number + dynamic_size: number + static_size: number + review_size: number + review_dynamic_size: number + review_static_size: number + key_frame_size: number + question_size: number + total_qa_group_size: number + single_qa_group_size: number + multiple_qa_group_size: number + new_qa_group_size: number + new_single_qa_group_size: number + new_multiple_qa_group_size: number + review_question_size: number + comment_question_size: number + } + first_commit_label_time?: string + first_commit_review1_time?: string + reject_times: number + review_rate: { + review1_rate: number + review2_rate: number + } + label_first_work_time: number + review1_first_work_time: number + review2_first_work_time: number + first_reject_label_time?: string + } + + export interface ListRequest { + data_type?: number + current_uid?: number[] + data_name?: string + first_commit_label_time_end?: string + first_commit_label_time_start?: string + first_commit_review1_time_end?: string + first_commit_review1_time_start?: string + get_data: boolean + id?: number[] + label_status?: number[] + label_user?: number[] + order_by?: string + page_number: number + page_size: number + project_id?: number[] + rejected?: number + review_user1?: number[] + review_user2?: number[] + } + + export interface SizeProps { + object_size: number + valid_size: number + first_comment_size: number + second_comment_size: number + new_size: number + prelabel_size: number + prelabel_modify_size: number + dynamic_size: number + static_size: number + review_size: number + review_dynamic_size: number + review_static_size: number + key_frame_size: number + question_size: number + total_qa_group_size: number + single_qa_group_size: number + multiple_qa_group_size: number + new_qa_group_size: number + new_single_qa_group_size: number + new_multiple_qa_group_size: number + review_question_size: number + comment_question_size: number + } + + export interface ListResponse { + task_list: DataProps[] + total_items: number + total_pages: number + total_size: SizeProps + } + + export interface AcquireReqProps { + uid: number + project_id: number + label_action: 1 | 2 | 3 // 1-领取标注任务 2-领取审核任务 3-领取复审任务 + } + + export interface DispatchReqProps { + operation_uid: number + reject: boolean + task_ids: number[] + task_status_dst: number + task_status_src: number + uid_dst: number | null + uid_src: number | null + } + + export interface ReleaseReqProps { + operation_uid: number + reject: boolean + task_ids: number[] + task_status: number + uid: number + } + + export interface NextReqProps { + project_id: number + task_status: number + rejected: boolean + last_task_id: number + } + + export interface NextResProps { + project_id: number + task_id: number | null + } + + export interface CommitReqProps { + task_id: number + uid: number + commit_action: number //1-提交标注 2-提交审核1 3-提交审核2 4-驳回 5-无法标注 + work_time: number + comment_question_size?: number + } + + export interface ResGetUserTaskList { + simple_task_list: SimpleTaskItem[] + total_items: number + total_pages: number + } + + export interface SimpleTaskItem { + id: number + label_status: number + label_type: number + label_username?: string + project_id: number + project_name: string + rejected: boolean + review1_username?: string + review2_username?: string + } +} diff --git a/components/label/store.ts b/components/label/store.ts new file mode 100644 index 0000000..a479563 --- /dev/null +++ b/components/label/store.ts @@ -0,0 +1,605 @@ +import { del, get, set } from "idb-keyval" +import superjson from "superjson" +import { create } from "zustand" +import { persist, PersistStorage, StorageValue } from "zustand/middleware" +import { Comment } from "./api/label/typing" +import { safeClone } from "./utils/clone" + +type LabelData = Map> +type LabelPathTuple = [number, any[], any, any[]] +type LabelTime = { + label: number + review1: number + review2: number +} + +const isPaperPointLike = (value: any) => { + return ( + value && + typeof value === "object" && + !Array.isArray(value) && + typeof value.x === "number" && + typeof value.y === "number" + ) +} + +const isPaperSegmentLike = (value: any) => { + return ( + value && + typeof value === "object" && + !Array.isArray(value) && + value.point && + isPaperPointLike(value.point) + ) +} + +const normalizePointCollection = (value: any): any => { + if (Array.isArray(value)) { + return value.map((item) => normalizePointCollection(item)) + } + if (isPaperSegmentLike(value)) { + return [value.point.x, value.point.y] + } + if (isPaperPointLike(value)) { + return [value.x, value.y] + } + return value +} + +const normalizeLabelPathTuple = (path: LabelPathTuple): LabelPathTuple => { + return [ + path[0], + normalizePointCollection(path[1]), + path[2], + normalizePointCollection(path[3]), + ] +} + +interface LabelState { + // pathId pathPoints detail hollowPathPoints + label: LabelData + labelTime: LabelTime + labelDefaultComments: Comment[] + setLabel: (label: LabelData) => void + stateStack: LabelData[] + setStateStack: (data: LabelData[]) => void + popStateStack: () => LabelData | null + pushStateStack: (newData: LabelData) => void + getLabelDetailDataByKeys: ( + imageId: string, + categoryId: string, + id: number + ) => any + updateLabelDetailDataByKeys: ( + imageId: string, + categoryId: string, + id: number, + newDetail: any + ) => void + addDetail: ( + imageId: string, + categoryId: string, + id: number, + obj: { + [keys: string]: any + } + ) => void + setLabelTime: ( + labelTime: LabelTime | ((prev: LabelTime) => LabelTime) + ) => void + setLabelDefaultComments: (arr: Comment[]) => void + setImage: ( + imageId: string, + operation: Map + ) => void + setOperation: ( + imageId: string, + operationId: string, + path: [number, any[], any, any[]] + ) => void + deleteOperation: ( + imageId: string, + operationId: string, + pathId: number + ) => void + resetLabel: () => void +} + +interface ObjectState { + pathStatus: { + // key = imageId + pathId + [key: string]: { + ["HIDE"]?: boolean + } + } + selectedPath: { + // key = imageId + [key: string]: number[] + } + operationStatus: { + // key = imageId + operationId + [key: string]: { + ["HIDE"]?: boolean + ["INPUT"]?: string + ["COLLAPSE"]?: boolean + } + } + groupStatus: { + // key = imageId + groupId + [key: string]: { + ["COLLAPSE"]?: boolean + } + } + imageStatus: { + // key = imageId + [key: string]: { + ["INPUT"]?: string + ["COLLAPSE"]?: boolean + ["FILTERCOLOR"]?: { + [key: string]: boolean + } + } + } + updatePathStatus: ( + id: string, + statusKey: "HIDE", + statusValue: boolean + ) => void + updateSelectedPath: ( + id: string, + type: "ADD" | "DELETE" | "ADDSOME", + pathValue?: number + ) => void + resetPathAndOperationStatus: () => void + updateOperationStatus: ( + id: string, + statusKey: "HIDE" | "COLLAPSE" | "INPUT", + statusValue: string | boolean + ) => void + updateGroupStatus: ( + id: string, + statusKey: "COLLAPSE", + statusValue: string | boolean + ) => void + updateImageStatus: ( + id: string, + statusKey: "INPUT" | "COLLAPSE" | "FILTERCOLOR", + statusValue: + | string + | boolean + | { + [key: string]: boolean + } + ) => void +} + +interface KeyEventState { + shift: boolean + focusInput: boolean + setShift: (value: boolean) => void + setFocusInput: (value: boolean) => void +} + +const initialLabelState = { + label: new Map(), + labelTime: { + label: 0, + review1: 0, + review2: 0, + }, +} + +export const initialDetail = { + comment: [], + create_timestamp: 0, + first_modified_timestamp: 0, + first_modified_uid: 0, + last_modified_timestamp: 0, + last_modified_uid: 0, + sub_attributes: {}, + prelabel: false, +} + +// 自定义 storage 对象 +export const storage: PersistStorage = { + getItem: async (name: string) => { + // console.log(name, "has been retrieved"); + let str = await get(name) + if (!str) return null + return superjson.parse(str) || null + }, + setItem: async (name: string, value: StorageValue): Promise => { + // console.log(name, "with value", value, "has been saved"); + await set(name, superjson.stringify(value)) + }, + removeItem: async (name: string): Promise => { + console.log(name, "has been deleted") + await del(name) + }, +} + +// store path data +export const useLabelStore = create( + persist( + (storeSet) => ({ + label: initialLabelState.label, + labelTime: initialLabelState.labelTime, + labelDefaultComments: [], + stateStack: [], + setLabel: (label) => + storeSet((state) => { + return { + ...state, + label, + } + }), + setStateStack: (data) => + storeSet((state) => { + return { + ...state, + stateStack: data, + } + }), + popStateStack: () => { + const arr: LabelData[] = useLabelStore.getState().stateStack + console.log("弹出栈", arr) + if (!arr.length) return null + if (arr.length === 1) { + return arr[0] + } else { + arr.pop() + storeSet((state) => { + return { + ...state, + stateStack: arr, + } + }) + return arr[arr.length - 1] + } + }, + pushStateStack: (newData) => { + const arr: LabelData[] = useLabelStore.getState().stateStack + if (arr.length === 10) { + arr.shift() + } + arr.push(safeClone(newData)) + console.log(arr) + return storeSet((state) => { + return { + ...state, + stateStack: arr, + } + }) + }, + getLabelDetailDataByKeys: ( + imageId: string, + categoryId: string, + id: number + ) => { + const data = useLabelStore.getState().label + if (!data.has(imageId)) return null + const image = data.get(imageId) + if (!image?.has(categoryId)) return null + const category = image.get(categoryId) + let detail = null + category?.map((item) => { + if (item[0] === id) detail = item[2] + }) + return detail + }, + updateLabelDetailDataByKeys: (imageId, categoryId, id, newData) => { + const labelData = useLabelStore.getState().label + if (!labelData.has(imageId)) return + const image = labelData.get(imageId) + if (!image?.has(categoryId)) return + const category = image.get(categoryId) + category?.map((item) => { + if (item[0] === id) item[2] = newData + }) + }, + addDetail: (imageId, categoryId, id, obj) => { + const labelData = useLabelStore.getState().label + if (!labelData.has(imageId)) return + const image = labelData.get(imageId) + if (!image?.has(categoryId)) return + const category = image.get(categoryId) + category?.map((item) => { + if (item[0] === id) item[2] = Object.assign(item[2], obj) + }) + }, + setLabelTime: (labelTime) => + storeSet((state) => { + return { + ...state, + labelTime: + typeof labelTime === "function" + ? labelTime(state.labelTime) + : labelTime, + } + }), + setLabelDefaultComments: (labelDefaultComments) => + storeSet((state) => { + return { + ...state, + labelDefaultComments, + } + }), + setImage: (imageId, operation) => + storeSet((state) => { + state.label.set(imageId, operation) + return state + }), + setOperation: (imageId, operationId, path) => + storeSet((state) => { + const normalizedPath = normalizeLabelPathTuple(path) + const labelData = useLabelStore.getState().label + if (!labelData.has(imageId)) { + labelData.set(imageId, new Map()) + } + if (labelData.get(imageId)?.get(operationId)?.length) { + let result = [ + ...labelData.get(imageId)?.get(operationId)!, + normalizedPath, + ] + .reduce((acc, curr) => { + const key = curr[0] + acc.set(key, curr) + return acc + }, new Map()) + .values() + labelData.get(imageId)?.set(operationId, Array.from(result)) + } else { + labelData.get(imageId)?.set(operationId, [normalizedPath]) + } + console.log("绘制时", labelData) + useLabelStore.getState().pushStateStack(safeClone(labelData)) + return { ...state, label: safeClone(labelData) } + }), + + // 删除path + deleteOperation: (imageId, operationId, pathId) => + storeSet((state) => { + if (state.label.get(imageId)?.get(operationId)?.length) { + let result = + state.label + .get(imageId) + ?.get(operationId) + ?.filter((item) => item[0] !== pathId) || [] + state.label.get(imageId)?.set(operationId, result) + } + return state + }), + resetLabel: () => + storeSet((state) => { + return { + ...state, + label: initialLabelState.label, + labelTime: initialLabelState.labelTime, + } + }), + }), + { + name: "label-data-storage", + storage: storage, + } + ) +) + +const initialObjectState = { + pathStatus: {}, + selectedPath: {}, + operationStatus: {}, + groupStatus: {}, + imageStatus: {}, +} + +// store object list status +export const useObjectStore = create( + persist( + (storeSet) => ({ + pathStatus: initialObjectState.pathStatus, + selectedPath: initialObjectState.selectedPath, + operationStatus: initialObjectState.operationStatus, + groupStatus: initialObjectState.groupStatus, + imageStatus: initialObjectState.imageStatus, + updatePathStatus: (id: string, statusKey: "HIDE", statusValue: boolean) => + storeSet((state) => { + let idStatus = state.pathStatus[id] || {} + idStatus = Object.assign(idStatus, { + [statusKey]: statusValue, + }) + return { + ...state, + pathStatus: { + ...state.pathStatus, + [id]: idStatus, + }, + } + }), + updateSelectedPath: ( + id: string, + type: "ADD" | "DELETE" | "ADDSOME", + pathValue?: number + ) => + storeSet((state) => { + let idSelectedPath = state.selectedPath[id] || [] + if (type === "ADD") { + if (useKeyEventStore.getState().shift) { + idSelectedPath = pathValue + ? [...new Set([...idSelectedPath, pathValue])] + : idSelectedPath + } else { + idSelectedPath = pathValue ? [pathValue] : [] + } + } else if (type === "ADDSOME") { + idSelectedPath = pathValue + ? [...new Set([...idSelectedPath, pathValue])] + : idSelectedPath + } else if (type === "DELETE") { + idSelectedPath = + idSelectedPath?.filter((id) => id !== pathValue) || [] + } + return { + ...state, + selectedPath: { + ...state.selectedPath, + [id]: idSelectedPath, + }, + } + }), + resetPathAndOperationStatus: () => + storeSet((state) => { + return { + ...state, + selectedPath: {}, + pathStatus: {}, + operationStatus: {}, + } + }), + updateOperationStatus: ( + id: string, + statusKey: "HIDE" | "COLLAPSE" | "INPUT", + statusValue: string | boolean + ) => + storeSet((state) => { + let idStatus = state.operationStatus[id] || {} + idStatus = Object.assign(idStatus, { + [statusKey]: statusValue, + }) + return { + ...state, + operationStatus: { + ...state.operationStatus, + [id]: idStatus, + }, + } + }), + updateGroupStatus: ( + id: string, + statusKey: "COLLAPSE", + statusValue: string | boolean + ) => + storeSet((state) => { + let idStatus = state.groupStatus[id] || {} + idStatus = Object.assign(idStatus, { + [statusKey]: statusValue, + }) + return { + ...state, + groupStatus: { + ...state.groupStatus, + [id]: idStatus, + }, + } + }), + updateImageStatus: ( + id: string, + statusKey: "INPUT" | "COLLAPSE" | "FILTERCOLOR", + statusValue: + | string + | boolean + | { + [key: string]: boolean + } + ) => + storeSet((state) => { + let idStatus = state.imageStatus[id] || {} + idStatus = Object.assign(idStatus, { + [statusKey]: statusValue, + }) + return { + ...state, + imageStatus: { + ...state.imageStatus, + [id]: idStatus, + }, + } + }), + }), + { + name: "object-data-storage", + storage: storage, + partialize: (state: ObjectState) => + Object.fromEntries( + Object.entries(state).filter( + ([key]) => !["selectedPath"].includes(key) + ) + ) as any, + } + ) +) + +const initialKeyEventState = { + shift: false, + focusInput: false, +} + +// store keyboard and mouse status +export const useKeyEventStore = create((set) => ({ + shift: initialKeyEventState.shift, + setShift: (value: boolean) => + set((state: KeyEventState) => ({ ...state, shift: value })), + focusInput: initialKeyEventState.focusInput, + setFocusInput: (value: boolean) => + set((state: KeyEventState) => ({ ...state, focusInput: value })), +})) + +interface ImageState { + images: Map + setImages: (value: any) => void +} + +interface VideoFrameState { + videoFrames: Map + setVideoFrames: (key: string, value: string[]) => void + removeVideoFrames: (key: string) => void +} + +export const useImagesStore = create( + persist( + (storeSet) => ({ + images: new Map(), + setImages: (value: any) => + storeSet((state) => { + return { + ...state, + images: value, + } + }), + }), + { + name: "image-data-storage", + storage: storage, + } + ) +) + +export const useVideoFrameStore = create( + persist( + (storeSet) => ({ + videoFrames: new Map(), + setVideoFrames: (key: string, value: string[]) => + storeSet((state) => { + const nextMap = new Map(state.videoFrames) + nextMap.set(key, value) + return { + ...state, + videoFrames: nextMap, + } + }), + removeVideoFrames: (key: string) => + storeSet((state) => { + const nextMap = new Map(state.videoFrames) + nextMap.delete(key) + return { + ...state, + videoFrames: nextMap, + } + }), + }), + { + name: "video-frame-storage", + storage: storage, + } + ) +) diff --git a/components/label/store/auth.ts b/components/label/store/auth.ts new file mode 100644 index 0000000..ac584ce --- /dev/null +++ b/components/label/store/auth.ts @@ -0,0 +1,414 @@ +import dayjs from "dayjs" +import { create } from "zustand" +import { persist } from "zustand/middleware" +import { storage } from "../store" +import { ALL_CODE } from "../utils/constants" + +const initUserInfo = { + user_id: null, + user_name: null, + user_password: null, + detailInfo: null, +} + +export const usePermissionStore = create( + persist( + (set) => ({ + user_id: null, + user_name: null, + user_password: null, + detailInfo: null, + setUserPermissionInfo: ({ user_id, user_name, detailInfo }: any) => + set({ + user_id, + user_name, + detailInfo, + user_password: usePermissionStore.getState().user_password, + }), + setUserPassword: (user_password: string) => + set((state: any) => { + return { + ...state, + user_password, + } + }), + logout: () => set(initUserInfo), + }), + { + name: "label_permission", + } + ) +) + +export interface Option { + label: string + value: any +} + +interface UserStoreProps { + userOpts: Option[] + treeData: any[] + adminOpts: Option[] + needUpdate: boolean + setUserOpts: (opts: Option[]) => any + setTreeData: (opts: any[]) => any + setAdminOpts: (opts: Option[]) => any + setFlag: (f: boolean) => void +} + +export const useAllUserStore = create((set) => ({ + userOpts: [], + treeData: [], + adminOpts: [], + needUpdate: true, + setUserOpts: (opts: Option[]) => + set((state: any) => ({ ...state, userOpts: opts })), + setTreeData: (opts: any[]) => + set((state: any) => ({ ...state, treeData: opts })), + setAdminOpts: (opts: Option[]) => + set((state: any) => ({ ...state, adminOpts: opts })), + setFlag: (flag) => set((state: any) => ({ ...state, needUpdate: flag })), +})) + +/* ******************* Project *********************** */ +type paramsType = "all" | "collect" | "dynamic" +export const initAllParams = { + page_number: 1, + page_size: 15, + status: ALL_CODE, +} +export const initCollectParams = { + page_number: 1, + page_size: 15, + status: ALL_CODE, + is_collect: 1, +} +export const initDynamicParams = { + page_number: 1, + page_size: 15, + status: ALL_CODE, + is_dynamic: 1, +} + +export const useProjectStore = create((set) => ({ + allParams: initAllParams, + allTotal: 0, + collectParams: initCollectParams, + collectTotal: 0, + dynamicParams: initDynamicParams, + dynamicTotal: 0, + setSearchParams: (params: any, type: paramsType) => + set((state: any) => { + let obj = { ...state } + if (type === "all") { + obj.allParams = params + } else if (type === "collect") { + obj.collectParams = params + } else if (type === "dynamic") { + obj.dynamicParams = params + } + return obj + }), + setTotal: (total: number, type: paramsType) => + set((state: any) => { + let obj = { ...state } + if (type === "all") { + obj.allTotal = total + } else if (type === "collect") { + obj.collectTotal = total + } else if (type === "dynamic") { + obj.dynamicTotal = total + } + return obj + }), + resetParams: (type: paramsType) => + set((state: any) => { + let obj = { ...state } + if (type === "all") { + obj.allParams = initAllParams + } else if (type === "collect") { + obj.collectParams = initCollectParams + } else if (type === "dynamic") { + obj.dynamicParams = initDynamicParams + } + return obj + }), +})) + +/* ******************* Task *********************** */ +interface TaskStore { + params: any + total: number + setParams: (params: any) => void + resetParams: () => void + setPagination: (page: number, size: number) => void + setTotal: (total: number) => void +} + +export const initTaskParams = { + page_number: 1, + page_size: 20, +} + +export const useOwnTaskStore = create((set) => ({ + params: initTaskParams, + total: 0, + setParams: (params: any) => set((state: any) => ({ ...state, params })), + resetParams: () => + set((state: any) => ({ ...state, params: initTaskParams })), + setPagination: (p, s) => + set((state: any) => ({ + ...state, + params: { ...state.params, page_number: p, page_size: s }, + })), + setTotal: (total: number) => set((state: any) => ({ ...state, total })), +})) + +export const useAllTaskStore = create((set) => ({ + params: initTaskParams, + total: 0, + setParams: (params: any) => set((state: any) => ({ ...state, params })), + resetParams: () => + set((state: any) => ({ ...state, params: initTaskParams })), + setPagination: (p, s) => + set((state: any) => ({ + ...state, + params: { ...state.params, page_number: p, page_size: s }, + })), + setTotal: (total: number) => set((state: any) => ({ ...state, total })), +})) + +/* ******************* Scheme *********************** */ +// 处理标注方案数据结构 +const handlePlanData = (data: any) => { + const id = data.length + let fieldsObj: any = {} + const list: any = [] + data.forEach((item: any, index: number) => { + const { label_class, color, label_type, radius, sub_attributes_describe } = + item + const singleClass: any = { + [`class${index}-label_class`]: label_class, + [`class${index}-color`]: color.join("_"), + [`class${index}-label_type`]: label_type, + [`class${index}-radius`]: radius, + } + const sub_count = sub_attributes_describe.length + const sub_attr: string[] = [] + sub_attributes_describe.forEach((subItem: any, subIndex: number) => { + const { chinese_name, select_mode, round_id, isrequired, optional_item } = + subItem + sub_attr.push(`sub${subIndex}`) + singleClass[`class${index}-sub${subIndex}-sub_attributes`] = chinese_name + singleClass[`class${index}-sub${subIndex}-select_mode`] = select_mode + singleClass[`class${index}-sub${subIndex}-round_id`] = round_id + singleClass[`class${index}-sub${subIndex}-isrequired`] = isrequired + singleClass[`class${index}-sub${subIndex}-optional_item`] = optional_item + }) + if (sub_count === 0) + list.push({ name: `class${index}`, sub_attr: ["sub0"], sub_count }) + else list.push({ name: `class${index}`, sub_attr, sub_count }) + fieldsObj = { ...fieldsObj, ...singleClass } + }) + return { id, fieldsObj, list } +} + +// scheme Store +export const useSchemeStore = create((set) => ({ + // 首页搜索 + searchParams: { + current_page: 1, + page_size: 20, + }, + total: 0, + setSearchParams: (params: any) => + set((state: any) => ({ ...state, searchParams: params })), + setTotal: (total: number) => + set((state: any) => ({ ...state, total: total })), + // 方案版本数据 + nowVersionPlan: [], + nowVersionFormData: {}, + nowVersionFormId: 0, + nowVersionFormLabel: [ + { name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 }, + ], + selectPlan: (obj: any, data: any) => { + const { id, fieldsObj, list } = handlePlanData(data) + set((state: any) => ({ + ...state, + nowVersionPlan: data, + nowVersionFormId: id, + nowVersionFormData: { ...fieldsObj, ...obj }, + nowVersionFormLabel: list.length + ? list + : [{ name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 }], + })) + }, + resetPlan: () => + set((state: any) => ({ + ...state, + nowVersionPlan: [], + nowVersionFormData: {}, + nowVersionFormId: 0, + nowVersionFormLabel: [ + { name: `class${0}`, sub_attr: ["sub0"], sub_count: 0 }, + ], + })), +})) + +/* ******************* 标注页面返回跳转 *********************** */ +// 返回跳转 +export const useBackUrlStore = create( + persist( + (set) => ({ + backUrl: null, + backTitle: null, + setBackProps: (url: string, title?: string) => + set({ backUrl: url, backTitle: title || null }), + }), + { + name: "back_url", + } + ) +) + +/* ******************* 数据统计 *********************** */ +interface WorkLoadDataProps { + all: any[] + order_by_group_name: any[] + order_by_project_name: any[] + order_by_project_type: any[] + order_by_user_name: any[] +} +type dimensionType = + | "all" + | "order_by_group_name" + | "order_by_project_name" + | "order_by_project_type" + | "order_by_user_name" +interface WorkloadStore { + labelData: WorkLoadDataProps + reviewData: WorkLoadDataProps + review2Data: WorkLoadDataProps + filters: { + label: [any, any] + review1: [any, any] + review2: [any, any] + } + dimensions: { + label: dimensionType + review1: dimensionType + review2: dimensionType + } + setLabelData: (data: WorkLoadDataProps) => void + setReviewData: (data: WorkLoadDataProps) => void + setReview2Data: (data: WorkLoadDataProps) => void + setFilters: (key: "label" | "review1" | "review2", data: [any, any]) => void + setDimensions: ( + key: "label" | "review1" | "review2", + data: dimensionType + ) => void +} + +export const dimensionOpts = [ + { label: "全部", value: "all" }, + { label: "用户名", value: "order_by_user_name" }, + { label: "用户组", value: "order_by_group_name" }, + { label: "项目名称", value: "order_by_project_name" }, + { label: "项目类型", value: "order_by_project_type" }, +] + +export const useWorkloadStore = create( + persist( + (set) => ({ + labelData: { + all: [], + order_by_group_name: [], + order_by_project_name: [], + order_by_project_type: [], + order_by_user_name: [], + }, + reviewData: { + all: [], + order_by_group_name: [], + order_by_project_name: [], + order_by_project_type: [], + order_by_user_name: [], + }, + review2Data: { + all: [], + order_by_group_name: [], + order_by_project_name: [], + order_by_project_type: [], + order_by_user_name: [], + }, + filters: { + label: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")], + review1: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")], + review2: [dayjs().subtract(1, "day"), dayjs().subtract(1, "day")], + }, + dimensions: { + label: "all", + review1: "all", + review2: "all", + }, + setLabelData: (data) => set((state) => ({ ...state, labelData: data })), + setReviewData: (data) => set((state) => ({ ...state, reviewData: data })), + setReview2Data: (data) => + set((state) => ({ ...state, review2Data: data })), + setFilters: (key, data) => + set((state) => ({ + ...state, + filters: { ...state.filters, [key]: data }, + })), + setDimensions: (key, data) => + set((state) => ({ + ...state, + dimensions: { ...state.dimensions, [key]: data }, + })), + }), + { + name: "workload", + storage: storage, + } + ) +) + +interface TaskDataStore { + taskData: any[] + filters: { + page_size: number + project_type?: string[] + project_id?: number[] + label_status?: number[] + current_uid?: number[] + label_user?: number[] + review_user1?: number[] + review_user2?: number[] + } + totalSize: any + total: number | null + setTaskData: (data: any[]) => void + setFilters: (data: any) => void + setTotal: (n: number) => void + setTotalSize: (data: any) => void +} + +export const useTaskDataStore = create( + persist( + (set) => ({ + taskData: [], + filters: { page_size: 1000 }, + total: null, + totalSize: {}, + setTaskData: (data) => set((state) => ({ ...state, taskData: data })), + setFilters: (data) => set((state) => ({ ...state, filters: data })), + setTotal: (num) => set((state) => ({ ...state, total: num })), + setTotalSize: (data) => set((state) => ({ ...state, totalSize: data })), + }), + { + name: "task-list", + storage: storage, + } + ) +) diff --git a/components/label/utils/clone.ts b/components/label/utils/clone.ts new file mode 100644 index 0000000..ca8d4c9 --- /dev/null +++ b/components/label/utils/clone.ts @@ -0,0 +1,49 @@ +const deepCloneFallback = (value: T, cache = new WeakMap()): T => { + if (value === null || typeof value !== "object") return value + if (cache.has(value as object)) return cache.get(value as object) + + if (value instanceof Date) return new Date(value.getTime()) as T + if (value instanceof Map) { + const clonedMap = new Map() + cache.set(value as object, clonedMap) + value.forEach((mapValue, mapKey) => { + clonedMap.set( + deepCloneFallback(mapKey, cache), + deepCloneFallback(mapValue, cache) + ) + }) + return clonedMap as T + } + if (value instanceof Set) { + const clonedSet = new Set() + cache.set(value as object, clonedSet) + value.forEach((setValue) => { + clonedSet.add(deepCloneFallback(setValue, cache)) + }) + return clonedSet as T + } + if (Array.isArray(value)) { + const clonedArr: any[] = [] + cache.set(value as object, clonedArr) + value.forEach((item, index) => { + clonedArr[index] = deepCloneFallback(item, cache) + }) + return clonedArr as T + } + + const clonedObj: Record = {} + cache.set(value as object, clonedObj) + Object.keys(value as object).forEach((key) => { + clonedObj[key] = deepCloneFallback((value as any)[key], cache) + }) + return clonedObj as T +} + +export const safeClone = (value: T): T => { + try { + return structuredClone(value) + } catch (error) { + console.warn("structuredClone failed, fallback to deep clone", error) + return deepCloneFallback(value) + } +} diff --git a/components/label/utils/constants.ts b/components/label/utils/constants.ts new file mode 100644 index 0000000..4a8e7e7 --- /dev/null +++ b/components/label/utils/constants.ts @@ -0,0 +1,248 @@ +"use client" + +export const dateFormat = "YYYY-MM-DD HH:mm:ss" +export const weekDayText = (data: number) => { + switch (data) { + case 0: + return "星期日" + case 1: + return "星期一" + case 2: + return "星期二" + case 3: + return "星期三" + case 4: + return "星期四" + case 5: + return "星期五" + case 6: + return "星期六" + default: + return "-" + } +} + +// 标注任务工序 +export const processOpts = [ + { label: "标注", value: "标注" }, + { label: "审核1", value: "审核1" }, + { label: "审核2", value: "审核2" }, +] + +// 状态码 +export const STATUS_CODE = new Map([ + [1, "已创建"], + [101, "已创建"], // 审核 + [102, "已创建"], // 复审 + [103, "已创建"], // 审核3 + [180, "数据同步中"], + [190, "Embedding生成中"], + [191, "Embedding生成失败"], + [199, "审核失败"], + [201, "试标阶段"], // 试标中 + [202, "试标阶段"], // 试标完成 + [203, "试标阶段"], // 试标确认 + [500, "标注中"], + [580, "待验收"], + [600, "已完成"], + [700, "已终止"], +]) + +// 状态码 +export const projectStatusOpts = [ + { label: "试标阶段", value: "201,202,203" }, + { label: "标注中", value: 500 }, + { label: "待验收", value: 580 }, + { label: "已完成", value: 600 }, + // { label: "审核失败", value: 199 }, + { label: "已终止", value: 700 }, +] + +export const CREATED_CODE = [1, 101, 102, 103, 190, 191, 199] // 已创建的状态码数组 +export const ALL_CODE = [201, 202, 203, 500, 580, 600, 700] // 其他的状态码数组 +export const PRELABEL_CODE = [201, 202, 203] +export const LABEL_CODE = [500, 580] + +export const projectLabelTypeOpts = [ + { label: "点云框", value: 1 }, + { label: "点云分割", value: 2 }, + { label: "点云分类", value: 3 }, + { label: "图片", value: 4 }, + { label: "大语言基础", value: 5 }, + { label: "大语言QA", value: 6 }, + { label: "视频", value: 7 }, +] + +// 项目列表中状态码对应值及style +export const statusStyles = { + 1: { + label: "已创建", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 101: { + label: "已创建", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 102: { + label: "已创建", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 103: { + label: "已创建", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 190: { + label: "Embedding生成中", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 191: { + label: "Embedding生成失败", + styleText: "text-[#D9333E] bg-[#FBEBEC]", + }, + 199: { + label: "审核失败", + styleText: "text-[#D9333E] bg-[#FBEBEC]", + }, + 201: { + label: "试标阶段", + styleText: "text-[#21D3ED] bg-[#EEFDFF]", + }, + 202: { + label: "试标阶段", + styleText: "text-[#21D3ED] bg-[#EEFDFF]", + }, + 203: { + label: "试标阶段", + styleText: "text-[#21D3ED] bg-[#EEFDFF]", + }, + 500: { + label: "标注中", + styleText: "text-[#1874FF] bg-[#E8F0FC]", + }, + 580: { + label: "待验收", + styleText: "text-[#FFB84D] bg-[#FEF5E7]", + }, + 600: { + label: "已完成", + styleText: "text-[#4FD796] bg-[#E7F9F0]", + }, + 700: { + label: "已终止", + styleText: "text-[#34425F] bg-[#F7F8F9]", + }, +} + +export const staticsColor = [ + { "8_151_156": 1 }, + { "9_109_217": 2 }, + { "15_15_118": 3 }, + { "28_27_175": 4 }, + { "35_84_116": 5 }, + { "45_69_235": 6 }, + { "53_127_127": 7 }, + { "54_124_171": 8 }, + { "54_207_201": 9 }, + { "56_158_13": 10 }, + { "63_18_119": 11 }, + { "69_151_223": 12 }, + { "81_188_187": 13 }, + { "83_29_171": 14 }, + { "84_119_48": 15 }, + { "95_33_176": 16 }, + { "100_16_23": 17 }, + { "113_249_251": 18 }, + { "116_78_41": 19 }, + { "125_179_75": 20 }, + { "127_48_236": 21 }, + { "127_127_54": 22 }, + { "132_133_239": 23 }, + { "147_210_239": 24 }, + { "151_29_36": 25 }, + { "155_125_62": 26 }, + { "156_239_102": 27 }, + { "161_98_48": 28 }, + { "178_253_253": 29 }, + { "188_136_242": 30 }, + { "189_191_84": 31 }, + { "191_49_47": 32 }, + { "196_29_127": 33 }, + { "202_247_138": 34 }, + { "203_164_81": 35 }, + { "207_19_34": 36 }, + { "212_107_8": 37 }, + { "212_177_6": 38 }, + { "223_134_144": 39 }, + { "233_157_84": 40 }, + { "244_206_159": 41 }, + { "252_202_0": 42 }, + { "252_250_147": 43 }, + { "253_247_87": 44 }, + { "255_191_120": 45 }, + { "255_236_61": 46 }, +] + +export const labelTypeOpts = [ + { label: "点云框", value: 1 }, + { label: "点云分割", value: 2 }, + // { label: '点云分类', value: '点云分类' }, + { label: "2D框", value: 101 }, + { label: "多边形", value: 102 }, + { label: "关键点", value: 103 }, + { label: "多线段", value: 104 }, + { label: "文本描述", value: 201 }, +] + +export const labelTypeMap = new Map([ + [1, "点云框"], + [2, "点云分割"], + [101, "2D框"], + [102, "多边形"], + [103, "关键点"], + [104, "多线段"], + [201, "文本描述"], +]) + +export const selectModeOpts = [ + { label: "输入", value: 0 }, + { label: "单选", value: 1 }, + { label: "多选", value: 2 }, +] + +export const selectModeMap = new Map([ + [0, "输入"], + [1, "单选"], + [2, "多选"], +]) + +// 标注任务状态码 +export const TaskStatusEnum = new Map([ + // [0, "None"], + [1, "待领取"], + [2, "标注中"], + [3, "标注完成"], + [4, "审核中"], + [5, "审核完成"], + [6, "复审中"], + [7, "复审完成"], + [8, "无法标注"], +]) + +export const OwnTaskStatusOpts = { + 0: "全部", + 2: "标注中", + 4: "审核中", + 6: "复审中", +} + +export const TaskStatusOpts = { + 0: "全部", + 1: "待领取", + 2: "标注中", + 3: "标注完成", + 4: "审核中", + 5: "审核完成", + 6: "复审中", + 7: "复审完成", + 8: "无法标注", +}