From c9199a77094131317576536bf6f4ef11dde59d54 Mon Sep 17 00:00:00 2001 From: ditiqi Date: Wed, 26 Feb 2025 11:39:53 +0800 Subject: [PATCH] add --- apps/web/src/components/layout/breadcrumb.tsx | 70 ++++++++++--------- .../course/detail/CourseDetailContext.tsx | 27 +++++-- .../CourseDetailHeader/CourseDetailHeader.tsx | 9 ++- .../course/detail/CourseDetailLayout.tsx | 9 +-- apps/web/src/routes/index.tsx | 16 ----- 5 files changed, 66 insertions(+), 65 deletions(-) diff --git a/apps/web/src/components/layout/breadcrumb.tsx b/apps/web/src/components/layout/breadcrumb.tsx index 1804dab..bffbb65 100755 --- a/apps/web/src/components/layout/breadcrumb.tsx +++ b/apps/web/src/components/layout/breadcrumb.tsx @@ -1,38 +1,42 @@ -import React from 'react'; -import { useLocation, Link, useMatches } from 'react-router-dom'; -import { theme } from 'antd'; -import { RightOutlined } from '@ant-design/icons'; +import React from "react"; +import { useLocation, Link, useMatches } from "react-router-dom"; +import { theme } from "antd"; +import { RightOutlined } from "@ant-design/icons"; export default function Breadcrumb() { - let matches = useMatches(); - const { token } = theme.useToken() + const matches = useMatches(); + const { token } = theme.useToken(); - let crumbs = matches - // first get rid of any matches that don't have handle and crumb - .filter((match) => Boolean((match.handle as any)?.crumb)) - // now map them into an array of elements, passing the loader - // data to each one - .map((match) => (match.handle as any).crumb(match.data)); + const crumbs = matches + // first get rid of any matches that don't have handle and crumb + .filter((match) => Boolean((match.handle as any)?.crumb)) + // now map them into an array of elements, passing the loader + // data to each one + .map((match) => (match.handle as any).crumb(match.data)); - return ( -
    - {crumbs.map((crumb, index) => ( - -
  1. - {crumb} -
  2. - {index < crumbs.length - 1 && ( -
  3. - -
  4. - )} -
    - ))} -
- ); + return ( +
    + {crumbs.map((crumb, index) => ( + +
  1. + {crumb} +
  2. + {index < crumbs.length - 1 && ( +
  3. + +
  4. + )} +
    + ))} +
+ ); } diff --git a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx index 6787e13..2f702e7 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailContext.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailContext.tsx @@ -3,10 +3,17 @@ import { courseDetailSelect, CourseDto, Lecture, + RolePerms, VisitType, } from "@nice/common"; import { useAuth } from "@web/src/providers/auth-provider"; -import React, { createContext, ReactNode, useEffect, useState } from "react"; +import React, { + createContext, + ReactNode, + useEffect, + useMemo, + useState, +} from "react"; import { useNavigate, useParams } from "react-router-dom"; interface CourseDetailContextType { @@ -19,11 +26,14 @@ interface CourseDetailContextType { lectureIsLoading?: boolean; isHeaderVisible: boolean; // 新增 setIsHeaderVisible: (visible: boolean) => void; // 新增 + canEdit?: boolean; } + interface CourseFormProviderProps { children: ReactNode; editId?: string; // 添加 editId 参数 } + export const CourseDetailContext = createContext(null); export function CourseDetailProvider({ @@ -32,8 +42,9 @@ export function CourseDetailProvider({ }: CourseFormProviderProps) { const navigate = useNavigate(); const { read } = useVisitor(); - const { user } = useAuth(); + const { user, hasSomePermissions } = useAuth(); const { lectureId } = useParams(); + const { data: course, isLoading }: { data: CourseDto; isLoading: boolean } = (api.post as any).findFirst.useQuery( { @@ -45,7 +56,14 @@ export function CourseDetailProvider({ }, { enabled: Boolean(editId) } ); - + const canEdit = useMemo(() => { + const isAuthor = user?.id === course?.authorId; + const isDept = course?.depts + ?.map((dept) => dept.id) + .includes(user?.deptId); + const isRoot = hasSomePermissions(RolePerms?.MANAGE_ANY_POST); + return isAuthor || isDept || isRoot; + }, [user, course]); const [selectedLectureId, setSelectedLectureId] = useState< string | undefined >(lectureId || undefined); @@ -57,9 +75,9 @@ export function CourseDetailProvider({ }, { enabled: Boolean(editId) } ); + useEffect(() => { if (course) { - console.log("read"); read.mutateAsync({ data: { visitorId: user?.id || null, @@ -85,6 +103,7 @@ export function CourseDetailProvider({ lectureIsLoading, isHeaderVisible, setIsHeaderVisible, + canEdit, }}> {children} diff --git a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx index 36f7c71..433ef3b 100755 --- a/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx +++ b/apps/web/src/components/models/course/detail/CourseDetailHeader/CourseDetailHeader.tsx @@ -10,7 +10,7 @@ import { useAuth } from "@web/src/providers/auth-provider"; import { useNavigate, useParams } from "react-router-dom"; import { UserMenu } from "@web/src/app/main/layout/UserMenu/UserMenu"; import { CourseDetailContext } from "../CourseDetailContext"; -import { Department, RolePerms } from "@nice/common"; + const { Header } = Layout; @@ -20,9 +20,8 @@ export function CourseDetailHeader() { const { isAuthenticated, user, hasSomePermissions, hasEveryPermissions } = useAuth(); const navigate = useNavigate(); - const { course } = useContext(CourseDetailContext); - hasSomePermissions(RolePerms.MANAGE_ANY_POST, RolePerms.MANAGE_DOM_POST); - hasEveryPermissions(RolePerms.MANAGE_ANY_POST, RolePerms.MANAGE_DOM_POST); + const { course, canEdit } = useContext(CourseDetailContext); + return (
@@ -52,7 +51,7 @@ export function CourseDetailHeader() { onChange={(e) => setSearchValue(e.target.value)} />
- {isAuthenticated && ( + {canEdit && ( <>