Bläddra i källkod

fix(course): 教材目录点击无响应

页面层未传 onArticleClick,目录树点击回调为空;同时补上 mode/channel
查询参数下传,并统一 onArticleChange 的 target 类型。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F7AFuL8wggc2P543gPA88y
visuddhinanda 2 veckor sedan
förälder
incheckning
493a0857ff

+ 1 - 1
dashboard-v6/src/components/article/TypeCourse.tsx

@@ -54,7 +54,7 @@ interface IWidget {
   onArticleChange?: (
     type: ArticleType,
     id: string,
-    target: string,
+    target?: TTarget,
     param?: ISearchParams[]
   ) => void;
 }

+ 10 - 5
dashboard-v6/src/features/editor/TextBook.tsx

@@ -2,7 +2,9 @@
 // Props
 // ─────────────────────────────────────────────
 
-import type { ArticleMode } from "../../api/article";
+import type { ArticleMode, ArticleType } from "../../api/article";
+import type { ISearchParams } from "../../components/article/TypePali";
+import type { TTarget } from "../../types";
 import AnthologyTocTree from "../../components/anthology/AnthologyTocTree";
 import TypeCourse from "../../components/article/TypeCourse";
 import { useCourse } from "../../components/course/hooks/useCourse";
@@ -24,7 +26,12 @@ export interface ArticleEditorProps {
   /** 选择了新的 anthology 时触发 */
   onAnthologySelect?: (anthologyId: string) => void;
   /** 文章内部触发跳转(type: 'article' | 'anthology' 等) */
-  onArticleChange?: (type: string, id: string) => void;
+  onArticleChange?: (
+    type: ArticleType,
+    id: string,
+    target?: TTarget,
+    param?: ISearchParams[]
+  ) => void;
 }
 
 // ─────────────────────────────────────────────
@@ -40,9 +47,7 @@ export default function TextBookEditor({
   onArticleChange,
 }: ArticleEditorProps) {
   const channels = channelId ? channelId.split("_") : undefined;
-  const { data, loading, errorCode } = useCourse(courseId);
-
-  console.error(errorCode);
+  const { data, loading } = useCourse(courseId);
 
   return (
     <Editor

+ 49 - 2
dashboard-v6/src/pages/workspace/course/textbook.tsx

@@ -1,11 +1,21 @@
 //课程详情页面
-import { useMatches, useParams } from "react-router";
+import {
+  useLocation,
+  useMatches,
+  useNavigate,
+  useParams,
+  useSearchParams,
+} from "react-router";
 import { useIntl } from "react-intl";
 
+import type { ArticleMode } from "../../../api/article";
 import TextBookEditor from "../../../features/editor/TextBook";
 
 const Widget = () => {
   const { courseId, articleId } = useParams(); //url 参数
+  const [searchParams] = useSearchParams();
+  const navigate = useNavigate();
+  const { search } = useLocation();
   const intl = useIntl();
   const matches = useMatches() as {
     data?: { title?: string; name?: string; word?: string };
@@ -14,10 +24,47 @@ const Widget = () => {
   const name = data?.title ?? data?.name ?? data?.word;
   const prefix = intl.formatMessage({ id: "columns.studio.course.title" });
 
+  const mode = (searchParams.get("mode") ?? "read") as ArticleMode;
+  const channelId = searchParams.get("channel");
+
   return (
     <>
       <title>{name ? `${prefix}-${name}` : prefix}</title>
-      <TextBookEditor courseId={courseId} articleId={articleId} />
+      <TextBookEditor
+        courseId={courseId}
+        articleId={articleId}
+        mode={mode}
+        channelId={channelId}
+        onArticleClick={(_anthologyId, id, target) => {
+          const url = `workspace/course/${courseId}/textbook/${id}`;
+          if (target === "_blank") {
+            window.open(
+              `${window.location.origin}${import.meta.env.BASE_URL}${url}${search}`,
+              "_blank"
+            );
+          } else {
+            navigate(`/${url}${search}`);
+          }
+        }}
+        onArticleChange={(type, id, target, param) => {
+          const url =
+            type === "textbook"
+              ? `workspace/course/${courseId}/textbook/${id}`
+              : `workspace/tipitaka/${type}/${id}`;
+          const urlSearch =
+            param && param.length > 0
+              ? "?" + param.map((item) => `${item.key}=${item.value}`).join("&")
+              : search;
+          if (target === "_blank") {
+            window.open(
+              `${window.location.origin}${import.meta.env.BASE_URL}${url}${urlSearch}`,
+              "_blank"
+            );
+          } else {
+            navigate(`/${url}${urlSearch}`);
+          }
+        }}
+      />
     </>
   );
 };