1+ import React , { useState } from 'react' ;
2+ import clsx from 'clsx' ;
3+ import styles from './styles.module.css' ;
4+
5+ const ArrowGuide = ( { sections = [ ] } ) => {
6+ const [ activeSection , setActiveSection ] = useState ( null ) ;
7+
8+ // 示例章节数据,如果没有传入sections
9+ const defaultSections = [
10+ {
11+ id : 'intro' ,
12+ title : '01 入门' ,
13+ description : '本章节将详细介绍 Luckfox Omni3576 产品的基本信息、技术参数,以及如何快速上手使用该产品。' ,
14+ items : [
15+ { name : '产品介绍' , url : '/docs/T113x/intro/product' } ,
16+ { name : '镜像烧录' , url : '/docs/T113x/intro/flashing' }
17+ ]
18+ } ,
19+ {
20+ id : 'linux-config' ,
21+ title : '02 Linux系统配置指南' ,
22+ description : '本章节提供 LuckFox Omni3576 开发板上 Buildroot、Debian 12 和 Ubuntu 22.04 的使用与配置说明。' ,
23+ items : [
24+ { name : 'Buildroot' , url : '/docs/T113x/linux/buildroot' } ,
25+ { name : 'Debian12(推荐)' , url : '/docs/T113x/linux/debian' }
26+ ]
27+ } ,
28+ {
29+ id : 'android-usage' ,
30+ title : '03 Android 使用' ,
31+ description : '本章节将为您提供 Luckfox Omni3576 在Android环境下使用。' ,
32+ items : [
33+ { name : 'ADB 登录' , url : '/docs/T113x/android/adb' }
34+ ]
35+ } ,
36+ {
37+ id : 'linux-dev' ,
38+ title : '04 Linux开发' ,
39+ description : '本章节将介绍在PC上搭建 Luckfox Omni3576 开发环境的步骤,包括SDK的基本介绍、开发环境搭建、编译Buildroot和Debian系统、内核定制,以及使用Docker简化开发流程。' ,
40+ items : [
41+ { name : 'SDK 开发环境搭建' , url : '/docs/T113x/development/sdk' }
42+ ]
43+ } ,
44+ {
45+ id : 'appendix' ,
46+ title : '05 附录' ,
47+ description : '本章节提供了与 Luckfox Omni3576 相关的各种资源和支持信息。您可以在这里找到必要的烧录软件、开发工具,以及开发板的原理图、数据手册等技术文档。' ,
48+ items : [
49+ { name : '资料下载' , url : '/docs/T113x/appendix/downloads' } ,
50+ { name : '技术支持' , url : '/docs/T113x/appendix/support' }
51+ ]
52+ }
53+ ] ;
54+
55+ const displaySections = sections . length > 0 ? sections : defaultSections ;
56+
57+ // 处理章节点击
58+ const handleSectionClick = ( index , e ) => {
59+ // 只有当点击的不是链接时才切换激活状态
60+ if ( ! e . target . closest ( 'a' ) ) {
61+ setActiveSection ( activeSection === index ? null : index ) ;
62+ }
63+ } ;
64+
65+ // 处理章节项点击跳转
66+ const handleItemClick = ( item , e ) => {
67+ e . stopPropagation ( ) ; // 防止触发章节容器的点击事件
68+
69+ if ( item . url ) {
70+ // 使用Docusaurus的路由进行导航
71+ window . location . href = item . url ;
72+ }
73+ } ;
74+
75+ // 规范化章节数据,确保每个item都有url属性
76+ const normalizeSections = ( sections ) => {
77+ return sections . map ( section => ( {
78+ ...section ,
79+ items : section . items . map ( item =>
80+ typeof item === 'string'
81+ ? { name : item , url : `#${ section . id } -${ item . toLowerCase ( ) . replace ( / \s + / g, '-' ) } ` }
82+ : item
83+ )
84+ } ) ) ;
85+ } ;
86+
87+ const normalizedSections = normalizeSections ( displaySections ) ;
88+
89+ return (
90+ < div className = { styles . container } >
91+ < div className = { styles . guideContainer } >
92+ { normalizedSections . map ( ( section , index ) => {
93+ // 将两个章节配对在同一行显示
94+ const isLeft = index % 2 === 0 ;
95+ const isRight = index % 2 !== 0 ;
96+
97+ // 如果是右侧章节,跳过渲染,因为它已经在左侧章节中处理了
98+ if ( isRight ) return null ;
99+
100+ // 获取配对的右侧章节,如果没有则使用null
101+ const rightSection = normalizedSections [ index + 1 ] ;
102+
103+ return (
104+ < div key = { section . id } className = { clsx ( styles . rowContainer , rightSection && styles . withConnection ) } >
105+ { /* 左侧章节 */ }
106+ < div
107+ className = { clsx ( styles . sectionContainer , styles . left , {
108+ [ styles . active ] : activeSection === index
109+ } ) }
110+ onClick = { ( e ) => handleSectionClick ( index , e ) }
111+ id = { section . id }
112+ >
113+ < div className = { styles . sectionContent } >
114+ < h3 className = { styles . sectionTitle } > { section . title } </ h3 >
115+ < p className = { styles . sectionDescription } > { section . description } </ p >
116+ < div className = { styles . sectionItems } >
117+ { section . items . map ( ( item , itemIndex ) => (
118+ < div
119+ key = { itemIndex }
120+ className = { styles . item }
121+ onClick = { ( e ) => handleItemClick ( item , e ) }
122+ style = { { cursor : item . url ? 'pointer' : 'default' } }
123+ >
124+ { item . name }
125+ </ div >
126+ ) ) }
127+ </ div >
128+ </ div >
129+ </ div >
130+
131+ { /* 右侧章节 */ }
132+ { rightSection && (
133+ < div
134+ className = { clsx ( styles . sectionContainer , styles . right , {
135+ [ styles . active ] : activeSection === index + 1
136+ } ) }
137+ onClick = { ( e ) => handleSectionClick ( index + 1 , e ) }
138+ id = { rightSection . id }
139+ >
140+ < div className = { styles . sectionContent } >
141+ < h3 className = { styles . sectionTitle } > { rightSection . title } </ h3 >
142+ < p className = { styles . sectionDescription } > { rightSection . description } </ p >
143+ < div className = { styles . sectionItems } >
144+ { rightSection . items . map ( ( item , itemIndex ) => (
145+ < div
146+ key = { itemIndex }
147+ className = { styles . item }
148+ onClick = { ( e ) => handleItemClick ( item , e ) }
149+ style = { { cursor : item . url ? 'pointer' : 'default' } }
150+ >
151+ { item . name }
152+ </ div >
153+ ) ) }
154+ </ div >
155+ </ div >
156+ </ div >
157+ ) }
158+ </ div >
159+ ) ;
160+ } ) }
161+ </ div >
162+ </ div >
163+ ) ;
164+ } ;
165+
166+ export default ArrowGuide ;
0 commit comments