Merge branch 'zh' into 'main'

Zh

See merge request prism/lable/labelmain!2
This commit is contained in:
刘耀勇
2026-03-28 18:39:40 +08:00
13 changed files with 240 additions and 50 deletions

View File

@@ -5,10 +5,10 @@ NEXT_PUBLIC_ENV=development
# redis # redis
# NEXT_PUBLIC_REDIS_URL="172.16.112.128" # NEXT_PUBLIC_REDIS_URL="172.16.115.128"
NEXT_PUBLIC_REDIS_URL="localhost" NEXT_PUBLIC_REDIS_URL="172.30.21.213"
NEXT_PUBLIC_REDIS_PORT=9765 NEXT_PUBLIC_REDIS_PORT=9765
NEXT_PUBLIC_REDIS_PASSWORD=password NEXT_PUBLIC_REDIS_PASSWORD=password
NEXT_PUBLIC_REDIS_USERNAME=default NEXT_PUBLIC_REDIS_USERNAME=default
NEXT_PUBLIC_REDIS_DB=0 NEXT_PUBLIC_REDIS_DB=1

View File

@@ -3,7 +3,7 @@ NEXT_PUBLIC_BASE_PATH=""
NEXT_PUBLIC_ENV=staging NEXT_PUBLIC_ENV=staging
# redis # redis
NEXT_PUBLIC_REDIS_URL="172.30.21.213" NEXT_PUBLIC_REDIS_URL="172.16.115.128"
NEXT_PUBLIC_REDIS_PORT=9765 NEXT_PUBLIC_REDIS_PORT=9765
NEXT_PUBLIC_REDIS_PASSWORD=password NEXT_PUBLIC_REDIS_PASSWORD=password
NEXT_PUBLIC_REDIS_USERNAME=default NEXT_PUBLIC_REDIS_USERNAME=default

28
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,28 @@
stages:
- sync_github
sync_github:
stage: sync_github
tags:
- webbuild
image: harbor.cowarobot.cn/softrepo/rust_build:1.94
script:
- echo "代码已合并到 main, 开始执行发布逻辑..."
- |
for i in {1..10}; do
if command -v docker >/dev/null 2>&1 && [ -S /var/run/docker.sock ]; then
echo "Docker is ready!"
break
fi
echo "Waiting for Docker..."
sleep 2
done
- docker info
- echo ${CI_PROJECT_NAME} ${CI_PROJECT_PATH} ${CI_PROJECT_DIR} ${CI_PROJECT_URL} ${CI_COMMIT_SHA}
- echo ${HARBORKEY} | docker login harbor.cowarobot.cn -u 'robot$softpro+cibuild' --password-stdin
- rm -rf ${CI_PROJECT_NAME}
- git clone https://oauth2:${TOKEN}@git.cowarobot.com/${CI_PROJECT_PATH}
- cd ${CI_PROJECT_NAME}
- bash build.sh prod
rules:
- if: $CI_COMMIT_BRANCH == "main"

View File

@@ -2,7 +2,7 @@
import { getPersonProjectDashBoard } from "@/components/label/api/project" import { getPersonProjectDashBoard } from "@/components/label/api/project"
import { Project } from "@/components/label/api/project/typing" import { Project } from "@/components/label/api/project/typing"
import { Button, Group, Text, UnstyledButton } from "@mantine/core" import { Button, Group, Text } from "@mantine/core"
import { IconRefresh } from "@tabler/icons-react" import { IconRefresh } from "@tabler/icons-react"
import dayjs from "dayjs" import dayjs from "dayjs"
@@ -76,15 +76,16 @@ export default function PersonalProjectTable() {
width: 150, width: 150,
render: (record: Project.PersonProjectDashboardResponseItem) => { render: (record: Project.PersonProjectDashboardResponseItem) => {
return ( return (
<UnstyledButton <Text
px={6} px={6}
variant="transparent" variant="transparent"
onClick={async () => { onClick={async () => {
setCurrentRowId(record.project_id) false && setCurrentRowId(record.project_id)
router.push(`/project/info/detail?id=${record.project_id}`) false &&
router.push(`/project/info/detail?id=${record.project_id}`)
}} }}
title={record.project_id.toString()} title={record.project_id.toString()}
c={"brand"} // c={"brand"}
style={{ style={{
fontSize: "14px", fontSize: "14px",
maxWidth: "100%", maxWidth: "100%",
@@ -93,7 +94,7 @@ export default function PersonalProjectTable() {
textOverflow: "ellipsis", textOverflow: "ellipsis",
}}> }}>
{record.project_id} {record.project_id}
</UnstyledButton> </Text>
) )
}, },
}, },

View File

@@ -247,7 +247,10 @@ export default function PersonDashboardPage() {
</SimpleGrid> </SimpleGrid>
</Group> </Group>
<SimpleGrid cols={{ base: 1, lg: 2 }} spacing="md" style={{ flex: 1 }}> <SimpleGrid
cols={{ base: 1, lg: 2 }}
spacing="md"
style={{ flex: 1, maxHeight: "calc(100% - 194px)" }}>
<Paper <Paper
shadow="xs" shadow="xs"
withBorder withBorder

View File

@@ -1,17 +1,28 @@
"use client"
import { usePermissionStore } from "@/components/label/store/auth"
import AppLayout from "@/components/layout/AppLayout" import AppLayout from "@/components/layout/AppLayout"
import { PathnameRecorder } from "@/components/layout/PathnameRecorder" import { PathnameRecorder } from "@/components/layout/PathnameRecorder"
import { componentList, showList } from "@/components/layout/common" import { componentList, showList } from "@/components/layout/common"
import { useMemo } from "react"
async function getMenu() { // async function getMenu() {
return [...componentList, ...showList] // return [...componentList, ...showList]
} // }
export default function Layout({ children }: { children: React.ReactNode }) {
const detailInfo = usePermissionStore((s) => s.detailInfo)
const menu = useMemo(() => {
if (detailInfo?.roles?.length) {
return [...componentList, ...showList]
} else {
return [...componentList, ...showList].filter(
(item) => item.title !== "管理中心"
)
}
}, [detailInfo?.roles?.length])
export default async function Layout({
children,
}: {
children: React.ReactNode
}) {
const menu = await getMenu()
return ( return (
<AppLayout menu={menu}> <AppLayout menu={menu}>
{children} {children}

View File

@@ -51,11 +51,11 @@ FLAG_PROD="${ENV}_latest"
cd $SHELL_FOLDER cd $SHELL_FOLDER
# 检查git状态 # # 检查git状态
echo -e "${GREEN}Checking git status...${NC}" # echo -e "${GREEN}Checking git status...${NC}"
git fetch # git fetch
git merge # git merge
if [[ $? != 0 ]]; then echo -e "${RED}git pull error${NC}"; exit 100; fi # if [[ $? != 0 ]]; then echo -e "${RED}git pull error${NC}"; exit 100; fi
BRANCH_NAME=`git branch | grep "*"` BRANCH_NAME=`git branch | grep "*"`
echo -e "${GREEN}Current branch: ${BRANCH_NAME/* /}${NC}" echo -e "${GREEN}Current branch: ${BRANCH_NAME/* /}${NC}"
@@ -71,23 +71,27 @@ pnpm run $BUILD_FLAG
if [[ $? != 0 ]]; then echo -e "${RED}build error${NC}"; exit 100; fi if [[ $? != 0 ]]; then echo -e "${RED}build error${NC}"; exit 100; fi
# Docker构建和推送 # Docker构建和推送
MAIN_NAME=digitalspace_labelmain MAIN_NAME=web_digitalspace_labelmain
DOCKER_FILE=$SHELL_FOLDER/Dockerfile DOCKER_FILE=$SHELL_FOLDER/Dockerfile
HARBOR_REPO=softrepo
if [[ $ENV == prod ]]; then
HARBOR_REPO=softpro
fi
if [[ $OUTPUT_TYPE == export ]]; then if [[ $OUTPUT_TYPE == export ]]; then
DOCKER_FILE=$SHELL_FOLDER/docker/nginx.dockerfile DOCKER_FILE=$SHELL_FOLDER/docker/nginx.dockerfile
MAIN_NAME=digitalspace_labelmain_static MAIN_NAME=web_digitalspace_labelmain_static
elif [[ $OUTPUT_TYPE == standalone ]]; then elif [[ $OUTPUT_TYPE == standalone ]]; then
DOCKER_FILE=$SHELL_FOLDER/docker/node.dockerfile DOCKER_FILE=$SHELL_FOLDER/docker/node.dockerfile
MAIN_NAME=digitalspace_labelmain_ssr MAIN_NAME=web_digitalspace_labelmain_ssr
fi fi
echo -e "${GREEN}Building docker image...${NC}" echo -e "${GREEN}Building docker image...${NC}"
sudo docker build -f $DOCKER_FILE -t $MAIN_NAME $SHELL_FOLDER docker build -f $DOCKER_FILE -t $MAIN_NAME $SHELL_FOLDER
if [[ $? != 0 ]]; then echo -e "${RED}build docker with error${NC}"; exit 100; fi if [[ $? != 0 ]]; then echo -e "${RED}build docker with error${NC}"; exit 100; fi
echo -e "${GREEN}Tagging and pushing docker image...${NC}" echo -e "${GREEN}Tagging and pushing docker image...${NC}"
sudo docker tag $MAIN_NAME harbor.cowarobot.cn/gopro/$MAIN_NAME:$FLAG_PROD docker tag $MAIN_NAME harbor.cowarobot.cn/$HARBOR_REPO/$MAIN_NAME:$FLAG_PROD
# docker push harbor.cowarobot.cn/gopro/$MAIN_NAME:$FLAG_PROD docker push harbor.cowarobot.cn/$HARBOR_REPO/$MAIN_NAME:$FLAG_PROD
echo -e "${GREEN}Build completed successfully${NC}" echo -e "${GREEN}Build completed successfully${NC}"

View File

@@ -1,6 +1,6 @@
export const BASE_LABEL_API = export const BASE_LABEL_API =
process.env.NEXT_PUBLIC_ENV === "production" process.env.NEXT_PUBLIC_ENV === "production"
? "https://label.cowarobot.com" ? "https://label.soft.cowarobot.com"
: process.env.NEXT_PUBLIC_ENV === "staging" : process.env.NEXT_PUBLIC_ENV === "staging"
? "https://label.softtest.cowarobot.com" ? "http://172.16.115.128:9110"
: "https://label.softtest.cowarobot.com" : "https://label.softtest.cowarobot.com"

View File

@@ -0,0 +1,121 @@
"use client"
import { usePermissionStore } from "@/components/label/store/auth"
import { usePathname } from "next/navigation"
interface PermissionItem {
[x: string]: [boolean, null, string]
}
type PermissionMap = {
[x: string]: PermissionItem
}
const mappingList: { [x: string]: [string, string] } = {
"/project/own": ["project", "config"],
"/management/team/employee": ["user", "view"],
"/management/team/organization": ["user", "group_view"],
"/management/team/dailypaper": ["daily_work", "team_view"],
"/management/team/cost": ["settlement_form", "view"],
"/management/team/workload": ["workload", "view"],
"/management/team/sync_server": ["data_sync", "server_view"],
"/management/team/sync_task": ["data_sync", "task_view"],
"/management/team/board": ["user", "view"],
}
export const headerBarCheckItems = (data: PermissionMap) => {
const projectTitle = [
["daily_work", "self_view"],
["label_schema", "view"],
["project", "view"],
["task", "view"],
] as const
let projectVisible = false
projectTitle.forEach(([prop, subProp]) => {
if (data[prop] && data[prop][subProp] && data[prop][subProp][0]) {
projectVisible = true
}
})
const staffTitle = [
["daily_work", "team_view"],
["user", "view"],
["user", "group_view"],
] as const
let staffVisible = false
staffTitle.forEach(([prop, subProp]) => {
if (data[prop] && data[prop][subProp] && data[prop][subProp][0]) {
staffVisible = true
}
})
return [projectVisible, staffVisible]
}
const useAuth = () => {
const pathname = usePathname()
const detailInfo = usePermissionStore((s) => s.detailInfo)
const permission = detailInfo?.permissions as PermissionMap | undefined
const roleName: string[] = detailInfo?.role_name ?? []
return {
hasPermission: () => {
if (
[
"/",
"/login",
"/management",
"/management/person/dashboard",
"/management/team",
].includes(pathname)
) {
return true
}
if (!permission) return false
if (mappingList[pathname]) {
const [prop, subProp] = mappingList[pathname]
return (
!!permission[prop] &&
!!permission[prop][subProp] &&
!!permission[prop][subProp][0]
)
}
return false
},
// path 跳转是否可见
canNv: (path: string, type = "view") => {
if (!permission) return false
if (mappingList[path]) {
const [prop] = mappingList[path]
return (
!!permission[prop] &&
!!permission[prop][type] &&
!!permission[prop][type][0]
)
}
return false
},
// 当前页面是否可见某个操作
isShow: (type = "view") => {
if (!permission) return false
if (mappingList[pathname]) {
const [prop] = mappingList[pathname]
return (
!!permission[prop] &&
!!permission[prop][type] &&
!!permission[prop][type][0]
)
}
return false
},
checkRole: (name: string) => {
if (!name) return false
return roleName.includes(name)
},
}
}
export default useAuth

View File

@@ -263,8 +263,13 @@ export const useBackUrlStore = create(
(set) => ({ (set) => ({
backUrl: null, backUrl: null,
backTitle: null, backTitle: null,
setBackProps: (url: string, title?: string) => basePath: "",
set({ backUrl: url, backTitle: title || null }), setBackProps: (url: string, title?: string, basePath?: string) =>
set({
backUrl: url,
backTitle: title || null,
basePath: basePath || "",
}),
}), }),
{ {
name: "back_url", name: "back_url",

View File

@@ -32,22 +32,39 @@ export const subConfigList: { source: string; url: string }[] =
? [ ? [
{ {
source: "/image", source: "/image",
url: "http://172.30.21.213:5532", url: "http://172.16.115.128:5532",
}, },
{ {
source: "/video", source: "/video",
url: "http://172.30.21.213:5533", url: "http://172.16.115.128:5533",
}, },
{ {
source: "/lidar", source: "/lidar",
url: "http://172.30.21.213:5534", url: "http://172.16.115.128:5534",
}, },
{ {
source: "/mgt", source: "/mgt",
url: "http://172.30.21.213:5535", url: "http://172.16.115.128:5535",
},
]
: [
{
source: "/image",
url: "https://label.soft.cowarobot.com",
},
{
source: "/video",
url: "https://label.soft.cowarobot.com",
},
{
source: "/lidar",
url: "https://label.soft.cowarobot.com",
},
{
source: "/mgt",
url: "https://label.soft.cowarobot.com",
}, },
] ]
: []
const currentComponentList: MenuItem[] = [ const currentComponentList: MenuItem[] = [
{ {
@@ -81,11 +98,11 @@ export const componentList: MenuItem[] = [
url: "video", url: "video",
icon: "SystemIcon", icon: "SystemIcon",
}, },
{ // {
title: "点云标注", // title: "点云标注",
url: "pointcloud", // url: "pointcloud",
icon: "SystemIcon", // icon: "SystemIcon",
}, // },
{ {
title: "管理中心", title: "管理中心",
url: "mgt", url: "mgt",

View File

@@ -4,9 +4,9 @@ import { Login } from "./types"
const BASE_PATH = const BASE_PATH =
process.env.NEXT_PUBLIC_ENV === "production" process.env.NEXT_PUBLIC_ENV === "production"
? "https://label.cowarobot.com" ? "https://label.soft.cowarobot.com"
: process.env.NEXT_PUBLIC_ENV === "staging" : process.env.NEXT_PUBLIC_ENV === "staging"
? "https://label.softtest.cowarobot.com" ? "http://172.16.115.128:9110"
: "https://label.softtest.cowarobot.com" : "https://label.softtest.cowarobot.com"
// 获取验证码 // 获取验证码

View File

@@ -1,9 +1,9 @@
version: "3" version: "3"
services: services:
digitalspace_labelmain_ssr: web_digitalspace_labelmain_ssr:
container_name: digitalspace_labelmain_ssr container_name: web_digitalspace_labelmain_ssr
image: harbor.cowarobot.cn/gopro/digitalspace_labelmain_ssr:stage_latest image: harbor.cowarobot.cn/softrepo/web_digitalspace_labelmain_ssr:stage_latest
restart: unless-stopped restart: unless-stopped
ports: ports:
- 5531:5531 - 5531:5531