From 35b6849a644c5d1c21595cd607e607597420cae5 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Sat, 11 Apr 2026 16:09:48 +0800 Subject: [PATCH 1/4] fix(daily): fix api --- components/label/api/daily/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/label/api/daily/index.ts b/components/label/api/daily/index.ts index b3011f9..f735c80 100644 --- a/components/label/api/daily/index.ts +++ b/components/label/api/daily/index.ts @@ -28,7 +28,7 @@ export const addDailyWorkData = (data: Daily.CreateProps) => { export const editDailyWorkData = (data: Daily.CreateProps, id: number) => { return httpFetch({ url: BASE_LABEL_API + `/api/v1/label_server/daily_work/edit/${id}`, - method: "put", + method: "PUT", body: JSON.stringify(data), }) } @@ -36,14 +36,14 @@ export const editDailyWorkData = (data: Daily.CreateProps, id: number) => { export const deleteDailyWorkData = (id: number) => { return httpFetch({ url: BASE_LABEL_API + `/api/v1/label_server/daily_work/delete/${id}`, - method: "delete", + 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", + method: "PUT", body: JSON.stringify({ lock_status }), }) } From 6baeae111e739a1e043329261e6068cd52869c56 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Sat, 11 Apr 2026 17:37:09 +0800 Subject: [PATCH 2/4] fix(daily): opt --- app/layout.tsx | 2 + components/label/OptStore.tsx | 112 ++++++++++++++++++++ components/label/api/user/index.ts | 98 +++++++++++++++++ components/label/api/user/typing.ts | 76 +++++++++++++ components/layout/common.ts | 22 ++-- components/layout/components/ClientIcon.tsx | 46 +++++--- 6 files changed, 332 insertions(+), 24 deletions(-) create mode 100644 components/label/OptStore.tsx create mode 100644 components/label/api/user/index.ts create mode 100644 components/label/api/user/typing.ts diff --git a/app/layout.tsx b/app/layout.tsx index 290ac0d..230ae6c 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -7,6 +7,7 @@ import "mantine-datatable/styles.css" import Script from "next/script" import { InfoCheck } from "@/app/store/InfoCheck" +import { OptStore } from "@/components/label/OptStore" import { ColorSchemeScript, MantineProvider, @@ -58,6 +59,7 @@ export default function RootLayout({ + }>{children} diff --git a/components/label/OptStore.tsx b/components/label/OptStore.tsx new file mode 100644 index 0000000..6e8743c --- /dev/null +++ b/components/label/OptStore.tsx @@ -0,0 +1,112 @@ +"use client" +import { usePathname } from "next/navigation" +import { useEffect } from "react" +import { getProjectAdminList } from "./api/project" +import { getUserAll, getUserGroupTree } from "./api/user" +import { + useAllTaskStore, + useAllUserStore, + usePermissionStore, +} from "./store/auth" + +export function OptStore() { + // const detectEnvironment = async () => { + // try { + // const result = await getName() + // console.log("Running in Tauri environment", result) + // return true + // } catch { + // console.log("Not running in Tauri environment") + // return false + // } + // } + const user_id = usePermissionStore.getState().user_id + const { needUpdate, setUserOpts, setTreeData, setAdminOpts, setFlag } = + useAllUserStore() + const pathname = usePathname() + + useEffect(() => { + if (user_id) { + const getData = async () => { + const res = await getUserAll() + setUserOpts(res) + const gRes = await getUserGroupTree() + const getTreeData = (data: any, parentHasDisabledChild = false) => { + let hasDisabledChild = parentHasDisabledChild + + const newData: any = { + title: data.name, + value: data.id, + key: data.id, + children: [], + disabled: false, + } + + if (data.members && data.members.length) { + data.members.forEach((member: any) => { + newData.children.push({ + title: member.name, + value: member.id, + key: member.id, + }) + }) + } + + if (data.children && data.children.length) { + data.children.forEach((child: any) => { + const childData = getTreeData(child, hasDisabledChild) + newData.children.push(childData) + if (childData.disabled) { + hasDisabledChild = true + } + }) + } + if ( + data.id.includes("-") && + (!data.members || !data.members.length) && + (!data.children || !data.children.length || hasDisabledChild) + ) { + newData.disabled = true + } + + return newData + } + let arr: any[] = [] + gRes.forEach((g: any) => { + arr.push(getTreeData(g)) + }) + const aRes = await getProjectAdminList() + setAdminOpts(aRes) + setTreeData(arr) + setFlag(false) + } + if (needUpdate) getData() + } + }, [user_id, setTreeData, setUserOpts, needUpdate, setFlag, setAdminOpts]) + + // 全局监听 重置项目详情中任务列表搜索缓存 + useEffect(() => { + if (pathname !== "/project/info/detail" && pathname !== "/label") { + useAllTaskStore.getState().resetParams() + } + }, [pathname]) + + // // tauri://close-requested + // useEffect(() => { + // ;(async () => { + // if (await detectEnvironment()) { + // const window = getCurrentWindow() + // const unlisten = await window.onCloseRequested(async (_event) => { + // usePermissionStore.getState().logout() + // // event.preventDefault(); + // }) + + // return () => { + // unlisten() + // } + // } + // })() + // }, []) + + return <> +} diff --git a/components/label/api/user/index.ts b/components/label/api/user/index.ts new file mode 100644 index 0000000..50de510 --- /dev/null +++ b/components/label/api/user/index.ts @@ -0,0 +1,98 @@ +import httpFetch from "@/api/fetch" +import { BASE_LABEL_API } from "../const" +import { Organization, User } from "./typing" + +// 获取用户列表 +export const getUserList = (data: User.ListRequest) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/list", + method: "POST", + body: JSON.stringify({ ...data, tenant: "cowarobot" }), + }) +} + +// 新增用户 +export const userAdd = (data: User.CreateProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/add", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 批量导入用户 +export const userImport = (data: { user_infos: any[] }) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/batch_add", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 编辑用户 +export const userEditById = (data: User.EditProps, id: number) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/user/edit/${id}`, + method: "PUT", + body: JSON.stringify(data), + }) +} + +// 编辑用户组织 +export const userUpdateGroup = (data: User.UpdateGroupProps) => { + return httpFetch({ + url: BASE_LABEL_API + `/api/v1/label_server/user/update/group`, + method: "POST", + body: JSON.stringify(data), + }) +} + +// 获取用户组织树 +export const getUserGroupTree = () => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/group/tree", + method: "GET", + }) +} + +// 新增用户组 +export const userGroupAdd = (data: Organization.CreateProps) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/group/add", + method: "POST", + body: JSON.stringify(data), + }) +} + +// 修改用户密码 +export const modifyUserPassword = (data: { + old_password: string + new_password: string +}) => { + return httpFetch({ + url: BASE_LABEL_API + "/api/v1/label_server/user/modify_password", + method: "PUT", + body: JSON.stringify(data), + }) +} + +/* ****************************** Options ****************************** */ +interface Option { + label: string + value: string +} +// 获取所有用户组 +export const getUserGroupAll = () => { + return httpFetch>({ + url: BASE_LABEL_API + `/api/v1/label_server/user/group/all`, + method: "GET", + }) +} + +// 获取所有用户 +export const getUserAll = () => { + return httpFetch>({ + url: BASE_LABEL_API + "/api/v1/label_server/user/all", + method: "GET", + }) +} diff --git a/components/label/api/user/typing.ts b/components/label/api/user/typing.ts new file mode 100644 index 0000000..6e4c62b --- /dev/null +++ b/components/label/api/user/typing.ts @@ -0,0 +1,76 @@ +export namespace User { + export interface UserInfo { + uid: number + name: string + all_projects: { [x: number]: number[] } + collect_projects: number[] + group_name: string + group_uuid: string + work_status: number + base_city: string + } + + export interface LoginInfo extends UserInfo { + token: string + refresh_token: string + } + + export interface ListRequest { + name?: string + page_number?: number + page_size?: number + } + + export interface ListResponse { + user_list: UserInfo[] + total_pages: number + total_items: number + } + + export interface CreateProps { + user_name: string + group_uuid: string + base_city: string + } + + export interface EditProps { + user_name?: string + password?: string + group_uuid?: string + base_city?: string + work_status?: number + } + + export interface UpdateGroupProps { + user_id: number + group_uuid: string + } +} + +export namespace Organization { + export interface CreateProps { + group_name: string + leader_uid: number + parent_group_uuid: string + } + + interface Member { + base_city: string + id: number + name: string + work_status: number + } + + export interface Response { + children?: Response[] + create_at?: string + create_user?: string + group_uuid: string + leader_uid?: number + leader_name?: string + members?: Member[] + name: string + parent_group_uuid: string + [key: string]: boolean | string | number | Response[] | Member[] | undefined + } +} diff --git a/components/layout/common.ts b/components/layout/common.ts index 3ede516..ff44c0d 100644 --- a/components/layout/common.ts +++ b/components/layout/common.ts @@ -70,17 +70,17 @@ const currentComponentList: MenuItem[] = [ { title: "个人中心", url: "person", - icon: "PersonalMenuIcon", + icon: "PersonalCenterIcon", items: [ { title: "个人看板", url: "dashboard", - icon: "TaskMenuIcon", + icon: "DashboardIcon", }, { title: "个人日报", url: "report", - icon: "AuthMenuIcon", + icon: "ReportIcon", }, ], }, @@ -91,22 +91,22 @@ export const componentList: MenuItem[] = [ { title: "图片标注", url: "image", - icon: "SystemIcon", + icon: "ImageAnnotationIcon", }, { title: "视频标注", url: "video", - icon: "SystemIcon", + icon: "VideoAnnotationIcon", + }, + { + title: "点云标注", + url: "lidar", + icon: "LidarAnnotationIcon", }, - // { - // title: "点云标注", - // url: "pointcloud", - // icon: "SystemIcon", - // }, { title: "管理中心", url: "mgt", - icon: "SystemIcon", + icon: "ManagementCenterIcon", }, ] diff --git a/components/layout/components/ClientIcon.tsx b/components/layout/components/ClientIcon.tsx index 273efcc..480455a 100644 --- a/components/layout/components/ClientIcon.tsx +++ b/components/layout/components/ClientIcon.tsx @@ -1,14 +1,39 @@ -// import { type LucideIcon } from "lucide-react"; - import { - AuthMenuIcon, - PersonalMenuIcon, - SystemIcon, - TaskMenuIcon, -} from "./icons/custom" + IconCategory2, + IconCube3dSphere, + IconFileText, + IconFolder, + IconFolders, + IconHierarchy3, + IconLayoutDashboard, + IconPhoto, + IconSettings, + IconUserCircle, + IconUsersGroup, + IconVideo, +} from "@tabler/icons-react" import React from "react" +const iconMap = { + DashboardIcon: IconLayoutDashboard, + EmployeeManagementIcon: IconUsersGroup, + ImageAnnotationIcon: IconPhoto, + LidarAnnotationIcon: IconCube3dSphere, + ManagementCenterIcon: IconSettings, + MyProjectsIcon: IconFolder, + PersonalCenterIcon: IconUserCircle, + ProjectCategoryIcon: IconCategory2, + ProjectManagementIcon: IconFolders, + ReportIcon: IconFileText, + TeamManagementIcon: IconHierarchy3, + VideoAnnotationIcon: IconVideo, + SystemIcon: IconSettings, + PersonalMenuIcon: IconUserCircle, + TaskMenuIcon: IconLayoutDashboard, + AuthMenuIcon: IconFileText, +} as const + export const ClientIcon = React.forwardRef< HTMLDivElement, React.ComponentProps<"button"> & { @@ -16,12 +41,7 @@ export const ClientIcon = React.forwardRef< } >(({ icon, ...props }, _ref) => { if (icon) { - const IconComponent = { - SystemIcon, - PersonalMenuIcon, - TaskMenuIcon, - AuthMenuIcon, - }[icon] + const IconComponent = iconMap[icon as keyof typeof iconMap] return IconComponent ? : null } else { return null From a4b1d07e525032ff31713fc130e408173d50cd85 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Mon, 13 Apr 2026 14:35:18 +0800 Subject: [PATCH 3/4] fix(login): logout --- api/fetch.ts | 4 ++++ components/layout/AppLayout.tsx | 1 + 2 files changed, 5 insertions(+) diff --git a/api/fetch.ts b/api/fetch.ts index 67c5467..2a4f405 100644 --- a/api/fetch.ts +++ b/api/fetch.ts @@ -17,6 +17,7 @@ fetch 参数: "use client" import { useUserStore } from "@/app/store/user" +import { usePermissionStore } from "@/components/label/store/auth" import { deleteCookie, refreshKey } from "@/components/login/api" import { isNumber } from "@/libs/util" @@ -40,6 +41,7 @@ interface OptionsProps { async function httpfetch(options: OptionsProps): Promise { const { removeUserInfo, refreshToken } = useUserStore.getState() + const { logout } = usePermissionStore.getState() const access_token = useUserStore.getState().access_token const refresh_token = useUserStore.getState().refresh_token @@ -197,6 +199,7 @@ async function httpfetch(options: OptionsProps): Promise { } finally { // 清空身份信息并跳转至登录页面 removeUserInfo() + logout() window.location.href = "/login" } } @@ -241,6 +244,7 @@ async function httpfetch(options: OptionsProps): Promise { } finally { // 清空身份信息并跳转至登录页面 removeUserInfo() + logout() window.location.href = "/login" } } else if (status >= 510) { diff --git a/components/layout/AppLayout.tsx b/components/layout/AppLayout.tsx index 0a21bfe..a2b80f4 100644 --- a/components/layout/AppLayout.tsx +++ b/components/layout/AppLayout.tsx @@ -136,6 +136,7 @@ export default function AppLayout({ const handleLogout = async () => { useUserStore.getState().removeUserInfo() + usePermissionStore.getState().logout() process.env.NEXT_PUBLIC_OUTPUT_TYPE === "standalone" && (await deleteCookie()) router.push("/login") From c5c8a74e9ea1dd0af155919250fb742feae1a660 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Mon, 13 Apr 2026 17:00:47 +0800 Subject: [PATCH 4/4] fix(const): fix --- components/label/utils/constants.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/label/utils/constants.ts b/components/label/utils/constants.ts index 4a8e7e7..45f3b6d 100644 --- a/components/label/utils/constants.ts +++ b/components/label/utils/constants.ts @@ -32,9 +32,9 @@ export const processOpts = [ // 状态码 export const STATUS_CODE = new Map([ [1, "已创建"], - [101, "已创建"], // 审核 - [102, "已创建"], // 复审 - [103, "已创建"], // 审核3 + [101, "已创建待审核"], // 审核 + [102, "已创建待复审"], // 复审 + [103, "已创建待终审"], // 审核3 [180, "数据同步中"], [190, "Embedding生成中"], [191, "Embedding生成失败"],