瀏覽代碼

feat: build sidebar

Carson 9 月之前
父節點
當前提交
a5e4a122ce

+ 42 - 28
.vitepress/config.mts

@@ -14,21 +14,26 @@ import {
 import fs from "node:fs";
 import path from "node:path";
 import { exec } from "child_process";
+import { buildSideBar } from "../utils/sideBar";
 
 const DOC_BASE_PATH = "pages";
 
-// 执行 git restore 命令
-await new Promise((resolve, reject) =>
-  exec(`git restore ${DOC_BASE_PATH}`, (error, stdout, stderr) => {
-    if (error) {
-      console.error(`执行 git restore 时出错: ${error.message}`);
-      reject(stderr);
-    }
-    console.log(`git restore 输出结果: ${stdout}`);
-    resolve(stdout);
-  })
-);
-process.exit();
+if (process.env.NODE_ENV === "production") {
+  // 执行清理pages命令
+  await new Promise((resolve, reject) =>
+    exec(
+      `git checkout -- ${DOC_BASE_PATH} & git clean -df ${DOC_BASE_PATH}`,
+      (error, stdout, stderr) => {
+        if (error) {
+          console.error(`清理pages时出错: ${error.message}`);
+          reject(stderr);
+        }
+        console.log(`清理pages结果: ${stdout}`);
+        resolve(stdout);
+      }
+    )
+  );
+}
 
 // 从S3构建pages里面的markdown文件
 const s3 = new S3Client({
@@ -42,9 +47,7 @@ const command = new ListObjectsCommand({
   Bucket: process.env.VITE_DOCS_LIST_BUCKET,
 });
 const { Contents: contents } = await s3.send(command);
-console.log(contents);
-process.exit();
-await fs.emptyDir(DOC_BASE_PATH, { recursive: true });
+
 await Promise.all(
   contents!.map((content) => {
     return new Promise(async (resolve, reject) => {
@@ -69,6 +72,14 @@ await Promise.all(
 );
 
 // 构建sideBar数据
+let { rootSideBar, zhHKSideBar } = buildSideBar(contents);
+// rootSideBar = rootSideBar.map(sb => { sb.items = undefined;return sb })
+import util from "util";
+console.log(
+  util.inspect(rootSideBar, { showHidden: false, depth: null, colors: true }),
+  util.inspect(zhHKSideBar, { showHidden: false, depth: null, colors: true })
+);
+// process.exit();
 
 // https://vitepress.dev/reference/site-config
 export default defineConfig({
@@ -181,19 +192,22 @@ export default defineConfig({
         //   { text: 'Home', link: '/' },
         //   { text: 'Examples', link: '/markdown-examples' }
         // ],
-        sidebar: [
-          { text: "关于CocoBlockly X", link: "/docs" },
-          { text: "常见问题解答", link: "/docs/常见问题解答" },
-          {
-            text: "开始使用CocoBlockly X",
-            link: "/docs/start-using-cocoblockly-x",
-          },
-          {
-            text: "电子模块基本教学",
-            collapsed: true,
-            items: [{ text: "todo", link: "/docs" }],
-          },
-        ],
+        // sidebar: [
+        //   { text: "关于CocoBlockly X", link: "/docs" },
+        //   { text: "常见问题解答", link: "/docs/常见问题解答" },
+        //   {
+        //     text: "开始使用CocoBlockly X",
+        //     link: "/docs/start-using-cocoblockly-x",
+        //     collapsed: true,
+        //     items: [],
+        //   },
+        //   {
+        //     text: "电子模块基本教学",
+        //     collapsed: true,
+        //     items: [{ text: "todo", link: "/docs" }],
+        //   },
+        // ],
+        sidebar: rootSideBar,
         // socialLinks: [
         //   { icon: 'github', link: 'https://github.com/vuejs/vitepress' }
         // ]

+ 2 - 1
components/Edit/index.vue

@@ -40,7 +40,8 @@ const loadS3DocsListObjects = async () => {
 const loadSideBar = async () => {
   sideLoading.value = true;
   dataSource.value = s3ContentsToTree(await loadS3DocsListObjects(), {}, (r, label, i, a, thisContent) => ({
-    isDir: a.length !== i + 1
+    isDir: a.length !== i + 1,
+    ...( a.length === i + 1 ? thisContent : {} )
   }));
   sideLoading.value = false;
 };

+ 2 - 2
package.json

@@ -1,7 +1,7 @@
 {
   "scripts": {
-    "docs:dev": "vitepress dev",
-    "docs:build": "vitepress build",
+    "docs:dev": "NODE_ENV=development vitepress dev",
+    "docs:build": "NODE_ENV=production vitepress build",
     "docs:preview": "vitepress preview"
   },
   "devDependencies": {

+ 0 - 0
pages/docs/dir1/dir1-file1.md


+ 0 - 0
pages/docs/dir1/dir1-file2.md


+ 45 - 0
pages/docs/index.md

@@ -0,0 +1,45 @@
+# CocoBlockly X 在线帮助文档
+
+
+CocoBlockly X是一个在线编程平台,集成图形化编程与Python代码编程,工具界面友好,功能强大。结合人工智能套件模块,CocoBlockly X可进行程序编写及上传,从而学习人工智能、物联网及Python基础。
+
+###### 1. AI模块编程界面
+
+<img src="../../media/关于CocoBlockly X/关于CocoBlockly X(1).png" width="650">
+
+
+###### 2. IoT模块编程界面
+
+<img src="../../media/关于CocoBlockly X/关于CocoBlockly X(2).png" width="650"/>
+
+---
+
+## 教程索引
+
+- [关于CocoBlockly X](index)
+- [常见问题解答](faq)
+- [开始使用CocoBlockly X](start-using-cocoblockly-x)
+- 电子模块基本教学
+	- [整体模块预览](docs/preview)
+	- [使用AI模块](md/使用AI模块)
+	- [使用IoT模块](md/使用IoT模块)
+	- [使用屏幕模块](md/使用屏幕模块)
+	- [使用摄像头](md/使用摄像头)
+	- [使用LED灯屏模块](md/使用LED灯屏模块)
+	- [使用电机驱动模块](md/使用电机驱动模块)
+	- [使用扩展转接模块](md/使用扩展转接模块)
+	- [使用游戏手柄模块](md/使用游戏手柄模块)
+	- [使用多线程](md/使用多线程)
+- 其他使用帮助
+	- [固件更新与烧录](md/固件更新与烧录)
+	- [SD卡文件更新(针对AI模块)](md/SD)
+	- [图形处理](md/图形处理)
+	- [视频处理](md/视频处理)
+	- [音频处理](md/音频处理)
+	- [AI模型](md/AI模型)
+	- [IoT蓝牙](md/IoT蓝牙)
+	- [机器狗](md/机器狗)
+	- [第三方主控模块通信-盛思](md/盛思)
+	- [AI模块案例说明](help-docs/md/AI)
+	- [模块使用介绍视频](md/模块使用介绍视频)
+- [版本更新日志](changelog)

+ 2 - 0
pages/docs/test.md

@@ -0,0 +1,2 @@
+### test
+![close-btn.png](https://cococlass-help-docs-medias.s3.amazonaws.com/77f06475-9352-4364-a763-7c4315eda69f::close-btn.png 'close-btn.png')

+ 135 - 0
pages/docs/常见问题解答.md

@@ -0,0 +1,135 @@
+# 常见问题解答
+
+- [关于模块使用](/md/faq?id=关于模块使用)
+- [关于平台使用](/md/faq?id=关于平台使用)
+- [关于常见报错](/md/faq?id=关于常见报错)
+
+## 关于模块使用
+
+**1.AI模块与屏幕模块的组合在连接电脑或电源后,屏幕一直黑屏。**
+
+A:如果您无TF 卡读卡器,请在CocoBlockly X上按下图步骤上传程序,尝试解决问题。
+
+<img src="@/media/常见问题解答/常见问题解答(1).png" width="650"/><br>
+
+B:如果您有TF 卡读卡器,请您用 TF 卡读卡器检查一下 AI 模块中 TF 卡,确认其中是否有包含main.py这个文件,如果没有的话,可以从<a href="/download/main.py">这里</a>下载后放入 TF 卡便可以了。
+
+**2.我的AI模块显示以下效果,应该怎么办?**
+
+<img src="@/media/常见问题解答/AI_lack_sd.jpg" width="365"/><br>
+
+A:首先检查AI模块上是否已经插入SD卡。
+
+B:可能是运输过程中SD卡松动导致的,这种情况下需要重新插拔一下SD卡即可。
+
+**3.AI模块与屏幕模块的组合在连接电脑或电源后,屏幕红屏显示“Welcome to MaixPy”。**
+
+<img src="../../media/常见问题解答/w4.png" width="365"/><br>
+
+A:插拔电源线重新连接看能否正常启动。
+
+B:格式化SD卡,重新拷贝预置文件。
+
+C:更换SD卡,重新拷贝预置文件再试试。
+
+
+## 关于平台使用
+
+### 1. **电脑Windows 7系统,使用Chrome浏览器编程,CocoBlockly X上传区一直显示“正在连接模块”。**
+
+  描述:Windows 7系统的更新补丁没有安装,可以通过下载安装补丁解决问题。
+
+  解决办法:补丁下载地址:[32位](https://cocorobo.cn/downloads/Windows6.1-KB2999226-x86.msu) [64位](https://cocorobo.cn/downloads/Windows6.1-KB2999226-x64.msu)
+
+
+
+## 关于常见报错
+
+### 1. 关键字:Timeout
+
+描述1:模块还在连接中/重启中。
+
+解决办法1:等待模块连接/重启完成后再上传。如果使用的是AI模块与屏幕模块的组合,可以观察屏幕模块,当AI模块重启时屏幕会短暂黑屏刷新一次,等待黑屏刷新后重新上传程序即可解决问题。
+
+描述2:AI模块SD卡内“user_lastest_code.py”文件编辑权限被锁定。
+
+解决办法2:取出模块内SD卡并连接至电脑,将SD卡内根目录下“user_lastest_code.py”文件删除,重新将SD卡安装至AI模块并上传程序即可解决问题。
+
+### 2. 关键字:name 'xxx' isn't defined
+
+描述:程序中有变量没有被定义。
+
+解决办法:检查程序并修改即可解决问题。
+
+### 3. 关键字:Sipeed_M1 with kendryte-k210
+
+描述:摄像头没有插好/摄像头损坏。
+
+解决办法:重新插好摄像头/更换摄像头即可解决问题。
+
+### 4. 关键字:could not open port 'xxx': PermissionError
+
+描述:USB接口被占用。
+
+解决办法:重新插拔模块或重启CocoBlockly X Uploader即可解决问题。
+
+### 5. 关键字:'/private/tmp/PKInstallSandbox.rELsyx/tmp/python'
+
+描述:Mac系统出现此报错的原因是无法访问Python,一般发生在用户安装的时候没有输入密码给软件绝对权限安装。
+
+解决办法:重启CocoBlockly X Uploader即可。
+
+### 6. 关键字:file “&lt;stadin&gt;” line xx in &lt;module&gt;
+
+描述:代码运行错误。
+
+解决办法:固件版本过期,因此部分函数不支持,需要更新固件,更新方式见[AI模块固件更新](md/固件更新与烧录?id=AI模块固件)及[IoT模块固件更新](md/固件更新与烧录?id=IoT模块固件);或程序错误,尝试检查程序结构。
+
+### 7. 上传一直卡在77%的问题
+
+描述:Windows电脑有多个版本的Python。
+
+解决办法:卸载电脑所有的Python版本,然后重新安装Uploader。卸载方式如下图(以Windows系统为例):
+
+(1)点击控制面板;
+
+​         <img src="../../media/常见问题解答/w1.png" width="400"/>
+
+(2)点击程序里面的卸载程序;
+
+​         <img src="../../media/常见问题解答/w2.png"/>
+
+(3)找到所有的Python,全部右键卸载。
+
+​         <img src="../../media/常见问题解答/w3.png"/>
+
+
+
+### 8. 关键字:[Errno 5] EIO(AI)或[Errno 19] ENODEV (IOT)
+描述:编程时使用了电机驱动、MLX90614传感器、RTC模块等设备的编程积木,但实际设备未连接模块(物理线路)或者连接故障(接线错误、接触不良)。
+
+解决办法:检查对应设备的电路接线。
+
+### 10. 关键字:[MAIXPY] no senor 
+
+描述:没有检测到外部传感器。
+
+解决办法:摄像头松动,尝试重新连接摄像头。
+
+### 11. 关键词:IoT模块-【ERRNO 19】No Such Device Error
+
+描述:需要更新IoT固件。
+
+解决办法:更新IoT固件至最新版本,更新方式见[IoT模块固件更新](md/固件更新与烧录?id=IoT模块固件)。
+
+### 12. 关键词:free XX heap memory
+
+描述:程序中调用的kmodel文件路径非法或SD卡中不存在此文件。
+
+解决办法:检查SD卡中的kmodel文件是否存在,或与程序中路径是否一致。
+
+### 13. 关键词:only support kmodel V3/V4 now
+
+描述:AI模块无法使用.emodel文件。
+
+解决办法:联系CocoRobo工作人员[support@cocorobo.cc](mailto:support@cocorobo.cc)。

+ 42 - 0
pages/zh-HK/docs/index.md

@@ -0,0 +1,42 @@
+# 什麽是 CocoBlockly X 
+
+
+CocoBlockly X是一個程式編寫平臺,集成了視覺化編程與Python代碼編程。結合人工智能套件模組,CocoBlockly X可以進行程式編寫與運行,從而學習人工智慧、物聯網、Python基礎。
+
+###### 1. AI 模組編程界面
+
+<img src="../../../media/关于CocoBlockly X/关于CocoBlockly X(1).png" width="650">
+
+
+###### 2. IoT 模組編程界面
+
+<img src="../../../media/关于CocoBlockly X/关于CocoBlockly X(2).png" width="650"/>
+
+---
+
+## 教程索引
+
+- [什麽是CocoBlockly X](index)
+- [常見問題解答](faq)
+- [開始使用CocoBlockly X](start-using-cocoblockly-x)
+- 電子模組基本教學
+	- [整體模組預覽](md/preview)
+	- [使用AI模組](md/使用AI模組)
+	- [使用IoT模組](md/使用IoT模組)
+	- [使用螢幕模組](md/使用螢幕模組)
+	- [使用相機模組](md/使用相機)
+	- [使用LED燈屏模組](md/使用LED燈屏模組)
+	- [使用馬達驅動模組](md/使用馬達驅動模組)
+	- [使用擴展轉接模組](md/使用擴展轉接模組)
+	- [使用遊戲手柄模組](md/使用遊戲手柄模組)
+	- [使用多線程](md/使用多線程)
+- 其他使用幫助
+	- [固件更新與燒錄](md/固件更新與燒錄)
+	- [SD卡文件更新(AI模組)](md/SD)
+	- [圖形處理](md/圖形處理)
+	- [視訊處理](md/視訊處理)
+	- [音訊處理](md/音訊處理)
+	- [AI模型](md/AI模型)
+	- [IoT藍牙](md/IoT藍牙)
+	- [機器狗](md/機器狗)
+- [版本更新日誌](changelog)

+ 7 - 2
utils/s3Helper.ts

@@ -17,15 +17,16 @@ export const s3ContentsToTree = (
   );
 
   s3Contents.forEach((s3Content) => {
-    s3Content.Key.split("/").reduce((r, label, i, a, s3Content) => {
+    s3Content.Key.split("/").reduce((r, label, i, a) => {
       if (!r[label]) {
         const __prefix = `${r.__prefix ? r.__prefix + "/" : ""}${label}`;
         r[label] = { __result: [], __prefix };
         r.__result.push({
-          ...reducer(r, label, i, a),
           [props.key]: __prefix,
           [props.label]: label,
           [props.children]: r[label].__result,
+          // NOTE 这里要小心覆盖掉props.key props.label props.children
+          ...reducer(r, label, i, a, s3Content),
         });
       }
 
@@ -35,6 +36,10 @@ export const s3ContentsToTree = (
   return __result;
 };
 
+export const trimTreeForSideBar = (tree) => {
+
+}
+
 type TreeNodeLike = {
   children?: TreeNodeLike[];
 };

+ 47 - 0
utils/sideBar.ts

@@ -0,0 +1,47 @@
+import { s3ContentsToTree } from "../utils/s3Helper";
+import _ from "lodash";
+
+const trimPrefix = (str, prefix) => {
+  return str.replace(new RegExp(`^${prefix}`), "docs");
+};
+const trimSuffix = (str) => {
+  return str.replace(/.md$/, "");
+};
+
+const filterLocaleContents = (contents, prefix) => {
+  return contents!
+    .filter((cont) => new RegExp(`^${prefix}/`).test(cont.Key!))
+    .map((cont) => {
+      return {
+        ...cont,
+        Key: trimSuffix(trimPrefix(cont.Key, prefix)),
+      };
+    });
+};
+
+const sideBarReducer = (r, label, i, a, Content) => {
+  const extra = {
+    collapsed: a.length !== i + 1,
+  };
+  if (a.length === i + 1) {
+    extra.items = undefined;
+  } else {
+    extra.link = undefined
+  }
+  return extra;
+};
+export const buildSideBar = (contents) => {
+  const rootContents = filterLocaleContents(contents, "docs");
+  const zhHKContents = filterLocaleContents(contents, "zh-HK/docs");
+  const rootSideBar = s3ContentsToTree(
+    rootContents,
+    { key: "link", label: "text", children: "items" },
+    sideBarReducer
+  )[0].items;
+  const zhHKSideBar = s3ContentsToTree(
+    zhHKContents,
+    { key: "link", label: "text", children: "items" },
+    sideBarReducer
+  )[0].items;
+  return { rootSideBar, zhHKSideBar };
+};