diff --git a/web/src/components/api-service/chat-overview-modal/api-content.tsx b/web/src/components/api-service/chat-overview-modal/api-content.tsx
index cd00e69fe..c2189998a 100644
--- a/web/src/components/api-service/chat-overview-modal/api-content.tsx
+++ b/web/src/components/api-service/chat-overview-modal/api-content.tsx
@@ -5,6 +5,7 @@ import { Button, Card, Flex, Space } from 'antd';
import ChatApiKeyModal from '../chat-api-key-modal';
import { usePreviewChat } from '../hooks';
import BackendServiceApi from './backend-service-api';
+import MarkdownToc from './markdown-toc';
const ApiContent = ({
id,
@@ -42,6 +43,9 @@ const ApiContent = ({
)}
+
+
+
{apiKeyVisible && (
diff --git a/web/src/components/api-service/chat-overview-modal/markdown-toc.tsx b/web/src/components/api-service/chat-overview-modal/markdown-toc.tsx
new file mode 100644
index 000000000..25e29b1a1
--- /dev/null
+++ b/web/src/components/api-service/chat-overview-modal/markdown-toc.tsx
@@ -0,0 +1,74 @@
+import { Anchor } from 'antd';
+import type { AnchorLinkItemProps } from 'antd/es/anchor/Anchor';
+import React, { useEffect, useState } from 'react';
+
+interface MarkdownTocProps {
+ content: string;
+}
+
+const MarkdownToc: React.FC = ({ content }) => {
+ const [items, setItems] = useState([]);
+
+ useEffect(() => {
+ const generateTocItems = () => {
+ const headings = document.querySelectorAll(
+ '.wmde-markdown h2, .wmde-markdown h3',
+ );
+ const tocItems: AnchorLinkItemProps[] = [];
+ let currentH2Item: AnchorLinkItemProps | null = null;
+
+ headings.forEach((heading) => {
+ const title = heading.textContent || '';
+ const id = heading.id;
+ const isH2 = heading.tagName.toLowerCase() === 'h2';
+
+ if (id && title) {
+ const item: AnchorLinkItemProps = {
+ key: id,
+ href: `#${id}`,
+ title,
+ };
+
+ if (isH2) {
+ currentH2Item = item;
+ tocItems.push(item);
+ } else {
+ if (currentH2Item) {
+ if (!currentH2Item.children) {
+ currentH2Item.children = [];
+ }
+ currentH2Item.children.push(item);
+ } else {
+ tocItems.push(item);
+ }
+ }
+ }
+ });
+
+ setItems(tocItems.slice(1));
+ };
+
+ setTimeout(generateTocItems, 100);
+ }, [content]);
+
+ return (
+
+ );
+};
+
+export default MarkdownToc;