docs: 临时注释缺失的图片引用以修复构建错误

- 注释 stage-3 目录 6 个教程的所有图片引用(共 67 张)
  - 3.9-browser-ai-extension (11 张)
  - 3.12-vscode-extension (12 张)
  - 3.10-electron-voice-to-text (10 张)
  - 3.8-pwa-local-app (11 张)
  - 3.13-qt-industrial-hmi (11 张)
  - 3.11-nft-minting (12 张)
- 注释 stage-2 的 2.6-modern-component-library (11 张)
- 这些图片文件暂时缺失,后续需要补充或重新生成
- 构建现在可以成功完成
This commit is contained in:
sanbuphy
2026-02-28 15:00:32 +08:00
parent 3d932c1e0a
commit 09cbd870e5
7 changed files with 78 additions and 78 deletions
@@ -47,7 +47,7 @@
在 Trae 中直接运行后的效果: 在 Trae 中直接运行后的效果:
<!-- TODO: 替换为 Trae 中不使用组件库生成的仪表盘截图 --> <!-- TODO: 替换为 Trae 中不使用组件库生成的仪表盘截图 -->
![Trae 生成的仪表盘(不使用组件库)](images/compare-without-lib.png) <!-- ![Trae 生成的仪表盘(不使用组件库)](images/compare-without-lib.png) -->
**提示词二:使用 shadcn/ui 组件库** **提示词二:使用 shadcn/ui 组件库**
@@ -63,7 +63,7 @@
同样在 Trae 中直接运行后的效果: 同样在 Trae 中直接运行后的效果:
<!-- TODO: 替换为 Trae 中使用 shadcn/ui 生成的仪表盘截图 --> <!-- TODO: 替换为 Trae 中使用 shadcn/ui 生成的仪表盘截图 -->
![Trae 生成的仪表盘(使用 shadcn/ui)](images/compare-with-lib.png) <!-- ![Trae 生成的仪表盘(使用 shadcn/ui)](images/compare-with-lib.png) -->
同样的需求,唯一的区别只是在提示词开头加上了 `shadcn/ui + Tailwind CSS`,Trae 生成的结果在视觉一致性、交互细节、整体打磨程度上就完全不在一个层级。这就是组件库带来的"免费升级"——你只需要在提示词里多写一个组件库的名字。 同样的需求,唯一的区别只是在提示词开头加上了 `shadcn/ui + Tailwind CSS`,Trae 生成的结果在视觉一致性、交互细节、整体打磨程度上就完全不在一个层级。这就是组件库带来的"免费升级"——你只需要在提示词里多写一个组件库的名字。
@@ -100,7 +100,7 @@ npm install
``` ```
<!-- TODO: 替换为 HeroUI 官网首页或组件展示截图 --> <!-- TODO: 替换为 HeroUI 官网首页或组件展示截图 -->
![HeroUI 组件库官网](images/heroui-homepage.png) <!-- ![HeroUI 组件库官网](images/heroui-homepage.png) -->
### 3.2 用 AI IDE 生成落地页 ### 3.2 用 AI IDE 生成落地页
@@ -121,7 +121,7 @@ npm install
``` ```
<!-- TODO: 替换为 AI IDE 生成落地页的过程截图或生成结果截图 --> <!-- TODO: 替换为 AI IDE 生成落地页的过程截图或生成结果截图 -->
![AI 生成的 HeroUI 落地页效果](images/heroui-landing-result.png) <!-- ![AI 生成的 HeroUI 落地页效果](images/heroui-landing-result.png) -->
### 3.3 AI 会用到的关键组件 ### 3.3 AI 会用到的关键组件
@@ -161,7 +161,7 @@ import {
``` ```
<!-- TODO: 替换为迭代优化后的落地页效果截图 --> <!-- TODO: 替换为迭代优化后的落地页效果截图 -->
![迭代优化后的落地页](images/heroui-landing-iterated.png) <!-- ![迭代优化后的落地页](images/heroui-landing-iterated.png) -->
> **Vibe Coding 的核心**:你不需要记住每个组件的 API,只需要用自然语言描述你想要的效果,AI 会帮你找到合适的组件和写法。遇到不满意的地方,继续对话迭代就好。 > **Vibe Coding 的核心**:你不需要记住每个组件的 API,只需要用自然语言描述你想要的效果,AI 会帮你找到合适的组件和写法。遇到不满意的地方,继续对话迭代就好。
@@ -172,7 +172,7 @@ import {
**为什么选 shadcn/ui**:shadcn/ui 把组件代码直接放进你的项目,你可以随意修改任何细节。对于需要深度定制的产品界面,这种"拥有代码"的模式最灵活。 **为什么选 shadcn/ui**:shadcn/ui 把组件代码直接放进你的项目,你可以随意修改任何细节。对于需要深度定制的产品界面,这种"拥有代码"的模式最灵活。
<!-- TODO: 替换为 shadcn/ui 官网或组件展示截图 --> <!-- TODO: 替换为 shadcn/ui 官网或组件展示截图 -->
![shadcn/ui 组件库官网](images/shadcn-homepage.png) <!-- ![shadcn/ui 组件库官网](images/shadcn-homepage.png) -->
### 4.1 创建项目 ### 4.1 创建项目
@@ -210,7 +210,7 @@ shadcn/ui 的独特之处:每次 `add` 一个组件,它会把源代码复制
``` ```
<!-- TODO: 替换为 AI 生成的 shadcn/ui 产品界面截图 --> <!-- TODO: 替换为 AI 生成的 shadcn/ui 产品界面截图 -->
![AI 生成的 shadcn/ui 产品页面效果](images/shadcn-product-result.png) <!-- ![AI 生成的 shadcn/ui 产品页面效果](images/shadcn-product-result.png) -->
### 4.3 AI 会用到的关键组件 ### 4.3 AI 会用到的关键组件
@@ -258,7 +258,7 @@ shadcn/ui 的优势在于你可以直接修改组件源码。比如你想让按
AI 会直接修改你项目中的组件文件,而不是覆盖 npm 包的样式——这就是 shadcn/ui "拥有代码"的好处。 AI 会直接修改你项目中的组件文件,而不是覆盖 npm 包的样式——这就是 shadcn/ui "拥有代码"的好处。
<!-- TODO: 替换为 shadcn/ui 组件源码在项目中的截图,展示可直接编辑 --> <!-- TODO: 替换为 shadcn/ui 组件源码在项目中的截图,展示可直接编辑 -->
![shadcn/ui 组件代码在项目中可直接编辑](images/shadcn-code-ownership.png) <!-- ![shadcn/ui 组件代码在项目中可直接编辑](images/shadcn-code-ownership.png) -->
## 5. 实战三:用 Ant Design 构建后台管理界面 ## 5. 实战三:用 Ant Design 构建后台管理界面
@@ -267,7 +267,7 @@ AI 会直接修改你项目中的组件文件,而不是覆盖 npm 包的样式
**为什么选 Ant Design**:Ant Design 在中后台领域积累最深,表格、表单、图表等业务组件开箱即用,内置了大量企业级交互模式(批量操作、高级筛选、数据导出等)。 **为什么选 Ant Design**:Ant Design 在中后台领域积累最深,表格、表单、图表等业务组件开箱即用,内置了大量企业级交互模式(批量操作、高级筛选、数据导出等)。
<!-- TODO: 替换为 Ant Design 官网或 Pro Components 展示截图 --> <!-- TODO: 替换为 Ant Design 官网或 Pro Components 展示截图 -->
![Ant Design 组件库官网](images/antd-homepage.png) <!-- ![Ant Design 组件库官网](images/antd-homepage.png) -->
### 5.1 创建项目 ### 5.1 创建项目
@@ -310,7 +310,7 @@ npm install antd @ant-design/icons @ant-design/pro-components
``` ```
<!-- TODO: 替换为 AI 生成的 Ant Design 后台管理界面截图 --> <!-- TODO: 替换为 AI 生成的 Ant Design 后台管理界面截图 -->
![AI 生成的 Ant Design 后台管理界面](images/antd-admin-result.png) <!-- ![AI 生成的 Ant Design 后台管理界面](images/antd-admin-result.png) -->
### 5.3 AI 会用到的关键组件 ### 5.3 AI 会用到的关键组件
@@ -351,7 +351,7 @@ import {
``` ```
<!-- TODO: 替换为仪表盘页面效果截图 --> <!-- TODO: 替换为仪表盘页面效果截图 -->
![Ant Design 仪表盘页面效果](images/antd-dashboard-result.png) <!-- ![Ant Design 仪表盘页面效果](images/antd-dashboard-result.png) -->
> **后台管理的 Vibe Coding 技巧**:后台页面结构相对固定(表格 + 搜索 + 弹窗),非常适合用 AI 批量生成。你可以先让 AI 生成一个"用户管理"页面作为模板,然后说"参考用户管理页面的结构,帮我生成文档管理页面",AI 会复用相同的布局模式。 > **后台管理的 Vibe Coding 技巧**:后台页面结构相对固定(表格 + 搜索 + 弹窗),非常适合用 AI 批量生成。你可以先让 AI 生成一个"用户管理"页面作为模板,然后说"参考用户管理页面的结构,帮我生成文档管理页面",AI 会复用相同的布局模式。
@@ -20,7 +20,7 @@ Electron 是一个开源框架,它让你可以用 **HTML + CSS + JavaScript**
**一句话理解**Electron = 一个"隐形的 Chrome 浏览器" + Node.js 的系统能力。 **一句话理解**Electron = 一个"隐形的 Chrome 浏览器" + Node.js 的系统能力。
![placeholder: 一张示意图,展示 Electron 的架构:Chromium(负责 UI 渲染)+ Node.js(负责系统访问)= 桌面应用](images/image1.png) <!-- ![placeholder: 一张示意图,展示 Electron 的架构:Chromium(负责 UI 渲染)+ Node.js(负责系统访问)= 桌面应用](images/image1.png) -->
## 1.2 Electron 的核心架构 ## 1.2 Electron 的核心架构
@@ -47,7 +47,7 @@ Electron 应用由两种进程组成,理解它们是开发的关键:
它们之间通过 **IPC(进程间通信)** 来传递消息,就像打电话一样:渲染进程说"我要录音",主进程收到后去调用系统麦克风。 它们之间通过 **IPC(进程间通信)** 来传递消息,就像打电话一样:渲染进程说"我要录音",主进程收到后去调用系统麦克风。
![placeholder: 一张 Electron 进程架构图,展示 Main Process、Renderer Process、Preload Script 之间的关系和 IPC 通信](images/image2.png) <!-- ![placeholder: 一张 Electron 进程架构图,展示 Main Process、Renderer Process、Preload Script 之间的关系和 IPC 通信](images/image2.png) -->
## 1.3 我们要做什么? ## 1.3 我们要做什么?
@@ -69,7 +69,7 @@ Electron 应用由两种进程组成,理解它们是开发的关键:
| 模型体积 | 无需下载 | tiny 模型 75MBlarge 模型 3GB | | 模型体积 | 无需下载 | tiny 模型 75MBlarge 模型 3GB |
| 适合场景 | 快速上手、轻量使用 | 注重隐私、离线使用、长期高频使用 | | 适合场景 | 快速上手、轻量使用 | 注重隐私、离线使用、长期高频使用 |
![placeholder: 一张应用效果预览图,展示语音转文字应用的 UI:顶部有录音按钮和波形动画,下方是识别出的文字,右上角有模式切换开关](images/image3.png) <!-- ![placeholder: 一张应用效果预览图,展示语音转文字应用的 UI:顶部有录音按钮和波形动画,下方是识别出的文字,右上角有模式切换开关](images/image3.png) -->
## 1.4 重要提醒:Web Speech API 在 Electron 中不可用 ## 1.4 重要提醒:Web Speech API 在 Electron 中不可用
@@ -130,7 +130,7 @@ voice-to-text/
几秒钟后,一个桌面窗口会弹出来——这就是你的 Electron 应用!虽然现在只有一个默认的欢迎页面,但它已经是一个真正的桌面程序了。 几秒钟后,一个桌面窗口会弹出来——这就是你的 Electron 应用!虽然现在只有一个默认的欢迎页面,但它已经是一个真正的桌面程序了。
![placeholder: Electron 应用首次启动的截图,展示默认的欢迎页面窗口](images/image4.png) <!-- ![placeholder: Electron 应用首次启动的截图,展示默认的欢迎页面窗口](images/image4.png) -->
## 2.3 理解进程间通信(IPC) ## 2.3 理解进程间通信(IPC)
@@ -174,7 +174,7 @@ ipcMain.handle('transcribe-audio', async (event, audioData) => {
}) })
``` ```
![placeholder: 一张 IPC 通信流程图,展示 Renderer → Preload → Main 的消息传递过程](images/image5.png) <!-- ![placeholder: 一张 IPC 通信流程图,展示 Renderer → Preload → Main 的消息传递过程](images/image5.png) -->
# 第 3 章:实现录音功能 # 第 3 章:实现录音功能
@@ -237,7 +237,7 @@ async function startRecording() {
} }
``` ```
![placeholder: 应用录音界面的截图,展示录音按钮(录音中状态,红色脉冲动画)和下方的文字显示区域](images/image6.png) <!-- ![placeholder: 应用录音界面的截图,展示录音按钮(录音中状态,红色脉冲动画)和下方的文字显示区域](images/image6.png) -->
## 3.2 处理麦克风权限 ## 3.2 处理麦克风权限
@@ -319,7 +319,7 @@ async function transcribeWithWhisper(audioBuffer, apiKey) {
} }
``` ```
![placeholder: 应用运行截图,展示用户说了一段中文后,Whisper API 返回的识别结果](images/image7.png) <!-- ![placeholder: 应用运行截图,展示用户说了一段中文后,Whisper API 返回的识别结果](images/image7.png) -->
## 4.3 添加设置界面 ## 4.3 添加设置界面
@@ -336,7 +336,7 @@ async function transcribeWithWhisper(audioBuffer, apiKey) {
4. 面板可以点击外部区域关闭 4. 面板可以点击外部区域关闭
``` ```
![placeholder: 设置面板展开的截图,展示模式切换开关和 API Key 输入框](images/image8.png) <!-- ![placeholder: 设置面板展开的截图,展示模式切换开关和 API Key 输入框](images/image8.png) -->
# 第 5 章:方案 B——本地识别(whisper.cpp # 第 5 章:方案 B——本地识别(whisper.cpp
@@ -406,7 +406,7 @@ async function transcribeWithLocal(audioBuffer) {
} }
``` ```
![placeholder: 本地模型识别的运行截图,展示离线状态下依然能正常识别中文语音](images/image9.png) <!-- ![placeholder: 本地模型识别的运行截图,展示离线状态下依然能正常识别中文语音](images/image9.png) -->
## 5.3 Apple Silicon 用户的福音 ## 5.3 Apple Silicon 用户的福音
@@ -435,7 +435,7 @@ npx electron-forge make
打包产物在 `out/make/` 目录下。 打包产物在 `out/make/` 目录下。
![placeholder: out/make 目录的文件列表截图,展示生成的 .dmg 或 .exe 安装包](images/image10.png) <!-- ![placeholder: out/make 目录的文件列表截图,展示生成的 .dmg 或 .exe 安装包](images/image10.png) -->
## 6.2 应用体积优化 ## 6.2 应用体积优化
@@ -26,7 +26,7 @@ NFTNon-Fungible Token,非同质化代币)是区块链上的一种数字
NFT 的核心价值在于:**它用区块链技术证明了"这个数字物品属于你",而且这个证明是公开透明、不可篡改的。** NFT 的核心价值在于:**它用区块链技术证明了"这个数字物品属于你",而且这个证明是公开透明、不可篡改的。**
![placeholder: 一张示意图,展示 NFT 的概念:左边是一幅数字画作,右边是区块链上的所有权记录,中间用箭头连接](images/image1.png) <!-- ![placeholder: 一张示意图,展示 NFT 的概念:左边是一幅数字画作,右边是区块链上的所有权记录,中间用箭头连接](images/image1.png) -->
## 1.2 什么是智能合约? ## 1.2 什么是智能合约?
@@ -81,7 +81,7 @@ MetaMask 是最流行的以太坊钱包,它是一个浏览器插件,让你
4. 选择 **"创建新钱包"**,设置密码 4. 选择 **"创建新钱包"**,设置密码
5. **重要**:妥善保存你的助记词(12 个英文单词)。测试网钱包丢了无所谓,但养成好习惯很重要 5. **重要**:妥善保存你的助记词(12 个英文单词)。测试网钱包丢了无所谓,但养成好习惯很重要
![placeholder: MetaMask 安装和创建钱包的截图流程:安装插件 → 创建钱包 → 设置密码 → 备份助记词](images/image2.png) <!-- ![placeholder: MetaMask 安装和创建钱包的截图流程:安装插件 → 创建钱包 → 设置密码 → 备份助记词](images/image2.png) -->
## 2.2 切换到 Sepolia 测试网 ## 2.2 切换到 Sepolia 测试网
@@ -101,7 +101,7 @@ MetaMask 默认连接的是以太坊主网。我们需要切换到 Sepolia 测
| Currency Symbol | SepoliaETH | | Currency Symbol | SepoliaETH |
| Block Explorer | `https://sepolia.etherscan.io` | | Block Explorer | `https://sepolia.etherscan.io` |
![placeholder: MetaMask 切换到 Sepolia 测试网的截图,展示网络下拉菜单和 Sepolia 选项](images/image3.png) <!-- ![placeholder: MetaMask 切换到 Sepolia 测试网的截图,展示网络下拉菜单和 Sepolia 选项](images/image3.png) -->
## 2.3 领取免费测试 ETH ## 2.3 领取免费测试 ETH
@@ -119,7 +119,7 @@ MetaMask 默认连接的是以太坊主网。我们需要切换到 Sepolia 测
领取成功后,回到 MetaMask,你会看到余额从 0 变成了 0.1 ETH(可能需要等待几秒钟)。 领取成功后,回到 MetaMask,你会看到余额从 0 变成了 0.1 ETH(可能需要等待几秒钟)。
![placeholder: 水龙头网站截图,展示输入钱包地址并领取测试 ETH 的过程](images/image4.png) <!-- ![placeholder: 水龙头网站截图,展示输入钱包地址并领取测试 ETH 的过程](images/image4.png) -->
# 第 3 章:编写并部署 NFT 智能合约(4 分钟) # 第 3 章:编写并部署 NFT 智能合约(4 分钟)
@@ -131,7 +131,7 @@ Remix 是以太坊官方推荐的在线智能合约开发环境,完全在浏
你会看到一个类似 VS Code 的界面,左侧是文件管理器,中间是代码编辑器,右侧是编译和部署面板。 你会看到一个类似 VS Code 的界面,左侧是文件管理器,中间是代码编辑器,右侧是编译和部署面板。
![placeholder: Remix IDE 首页截图,展示文件管理器、代码编辑器和右侧面板](images/image5.png) <!-- ![placeholder: Remix IDE 首页截图,展示文件管理器、代码编辑器和右侧面板](images/image5.png) -->
## 3.2 创建合约文件 ## 3.2 创建合约文件
@@ -175,7 +175,7 @@ contract MySimpleNFT is ERC721 {
> **ERC721 是什么?** 它是以太坊上 NFT 的标准协议,定义了 NFT 应该具备的基本功能(转账、查询所有者等)。OpenZeppelin 提供了经过安全审计的实现,我们直接继承就行,不用自己从零写。 > **ERC721 是什么?** 它是以太坊上 NFT 的标准协议,定义了 NFT 应该具备的基本功能(转账、查询所有者等)。OpenZeppelin 提供了经过安全审计的实现,我们直接继承就行,不用自己从零写。
![placeholder: Remix IDE 中粘贴合约代码的截图](images/image6.png) <!-- ![placeholder: Remix IDE 中粘贴合约代码的截图](images/image6.png) -->
## 3.3 编译合约 ## 3.3 编译合约
@@ -186,7 +186,7 @@ contract MySimpleNFT is ERC721 {
> 如果报错,检查 Solidity 版本是否匹配,以及 OpenZeppelin 的 import 路径是否正确。Remix 会自动从 npm 下载 OpenZeppelin 依赖。 > 如果报错,检查 Solidity 版本是否匹配,以及 OpenZeppelin 的 import 路径是否正确。Remix 会自动从 npm 下载 OpenZeppelin 依赖。
![placeholder: Remix 编译成功的截图,展示绿色对勾和编译器版本选择](images/image7.png) <!-- ![placeholder: Remix 编译成功的截图,展示绿色对勾和编译器版本选择](images/image7.png) -->
## 3.4 部署合约到 Sepolia 测试网 ## 3.4 部署合约到 Sepolia 测试网
@@ -201,7 +201,7 @@ contract MySimpleNFT is ERC721 {
等待几秒钟,部署成功后,下方 **"Deployed Contracts"** 区域会显示你的合约地址。**复制并保存这个地址**,后面查看 NFT 时需要用到。 等待几秒钟,部署成功后,下方 **"Deployed Contracts"** 区域会显示你的合约地址。**复制并保存这个地址**,后面查看 NFT 时需要用到。
![placeholder: Remix 部署合约的截图,展示 Environment 选择、MetaMask 连接确认、Deploy 按钮和部署成功后的合约地址](images/image8.png) <!-- ![placeholder: Remix 部署合约的截图,展示 Environment 选择、MetaMask 连接确认、Deploy 按钮和部署成功后的合约地址](images/image8.png) -->
# 第 4 章:铸造 NFT 并查看成果(4 分钟) # 第 4 章:铸造 NFT 并查看成果(4 分钟)
@@ -218,7 +218,7 @@ contract MySimpleNFT is ERC721 {
你可以继续点击 "mint" 铸造更多——每次铸造的 NFT 编号会自动递增(#1#2#3……)。 你可以继续点击 "mint" 铸造更多——每次铸造的 NFT 编号会自动递增(#1#2#3……)。
![placeholder: Remix 中点击 mint 按钮并在 MetaMask 中确认交易的截图](images/image9.png) <!-- ![placeholder: Remix 中点击 mint 按钮并在 MetaMask 中确认交易的截图](images/image9.png) -->
## 4.2 验证铸造结果 ## 4.2 验证铸造结果
@@ -237,7 +237,7 @@ contract MySimpleNFT is ERC721 {
在 Etherscan 上,每一笔铸造交易都有完整的记录:谁铸造的、什么时候铸造的、Token ID 是多少——这就是区块链"公开透明、不可篡改"的魅力。 在 Etherscan 上,每一笔铸造交易都有完整的记录:谁铸造的、什么时候铸造的、Token ID 是多少——这就是区块链"公开透明、不可篡改"的魅力。
![placeholder: Sepolia Etherscan 上查看合约和 NFT 铸造记录的截图,展示交易列表和 Token Tracker](images/image10.png) <!-- ![placeholder: Sepolia Etherscan 上查看合约和 NFT 铸造记录的截图,展示交易列表和 Token Tracker](images/image10.png) -->
# 第 5 章:进阶——给 NFT 添加图片(可选) # 第 5 章:进阶——给 NFT 添加图片(可选)
@@ -262,7 +262,7 @@ IPFS 是一个去中心化的文件存储网络。和普通的云存储不同,
你的图片地址就是:`ipfs://你的CID` 你的图片地址就是:`ipfs://你的CID`
![placeholder: Pinata 上传图片的截图,展示上传按钮和上传成功后的 CID](images/image11.png) <!-- ![placeholder: Pinata 上传图片的截图,展示上传按钮和上传成功后的 CID](images/image11.png) -->
## 5.3 创建元数据 JSON ## 5.3 创建元数据 JSON
@@ -325,7 +325,7 @@ contract MyNFTWithImage is ERC721, ERC721URIStorage {
部署后,调用 `mint` 时传入你的元数据地址(如 `ipfs://QmAbc.../metadata.json`),铸造出的 NFT 就会带上图片和描述了。 部署后,调用 `mint` 时传入你的元数据地址(如 `ipfs://QmAbc.../metadata.json`),铸造出的 NFT 就会带上图片和描述了。
![placeholder: 在 Etherscan 上查看带图片的 NFT 详情截图](images/image12.png) <!-- ![placeholder: 在 Etherscan 上查看带图片的 NFT 详情截图](images/image12.png) -->
# 第 6 章:写在最后 # 第 6 章:写在最后
@@ -25,7 +25,7 @@ VS Code 插件可以做的事情远比你想象的多:
* **扩展编辑器能力**:自定义语言支持、代码补全、诊断提示 * **扩展编辑器能力**:自定义语言支持、代码补全、诊断提示
* **接入 AI 能力**:通过 Chat Participant API 创建 AI 对话助手,通过 Language Model API 调用大模型 * **接入 AI 能力**:通过 Chat Participant API 创建 AI 对话助手,通过 Language Model API 调用大模型
![placeholder: VS Code 插件生态示意图,展示插件可以扩展的各个区域:侧边栏、编辑器、状态栏、命令面板、Chat 面板](images/image1.png) <!-- ![placeholder: VS Code 插件生态示意图,展示插件可以扩展的各个区域:侧边栏、编辑器、状态栏、命令面板、Chat 面板](images/image1.png) -->
## 1.2 VS Code 插件的核心架构 ## 1.2 VS Code 插件的核心架构
@@ -52,7 +52,7 @@ VS Code 编辑器
└── 编辑器主进程(UI 渲染) └── 编辑器主进程(UI 渲染)
``` ```
![placeholder: VS Code 插件架构图,展示 Extension Host 进程与编辑器主进程的关系](images/image2.png) <!-- ![placeholder: VS Code 插件架构图,展示 Extension Host 进程与编辑器主进程的关系](images/image2.png) -->
## 1.3 我们要做什么插件? ## 1.3 我们要做什么插件?
@@ -66,7 +66,7 @@ VS Code 编辑器
| 多文件问答 | 在资源管理器中多选文件,一键让 AI 梳理文件关系和逻辑 | | 多文件问答 | 在资源管理器中多选文件,一键让 AI 梳理文件关系和逻辑 |
| 快捷键 | 自定义快捷键快速触发常用操作 | | 快捷键 | 自定义快捷键快速触发常用操作 |
![placeholder: AI Project Bot 插件效果预览图,展示侧边栏模板列表、Chat 面板中的 @project-bot 对话、右键菜单](images/image3.png) <!-- ![placeholder: AI Project Bot 插件效果预览图,展示侧边栏模板列表、Chat 面板中的 @project-bot 对话、右键菜单](images/image3.png) -->
## 1.4 本教程的路线图 ## 1.4 本教程的路线图
@@ -144,7 +144,7 @@ ai-project-bot/
| `main` | 编译后的入口文件路径 | | `main` | 编译后的入口文件路径 |
| `contributes` | 插件贡献的所有功能(命令、菜单、快捷键、视图等) | | `contributes` | 插件贡献的所有功能(命令、菜单、快捷键、视图等) |
![placeholder: package.json 文件在编辑器中的截图,高亮 contributes 字段](images/image4.png) <!-- ![placeholder: package.json 文件在编辑器中的截图,高亮 contributes 字段](images/image4.png) -->
## 2.3 理解 extension.ts——插件的"大脑" ## 2.3 理解 extension.ts——插件的"大脑"
@@ -184,7 +184,7 @@ export function deactivate() {}
在新窗口中按 **Ctrl+Shift+P**,输入 "Hello World",你会看到右下角弹出一条消息。这说明你的插件已经在运行了。 在新窗口中按 **Ctrl+Shift+P**,输入 "Hello World",你会看到右下角弹出一条消息。这说明你的插件已经在运行了。
![placeholder: VS Code 调试插件的截图,展示 Extension Development Host 窗口和 Hello World 消息](images/image5.png) <!-- ![placeholder: VS Code 调试插件的截图,展示 Extension Development Host 窗口和 Hello World 消息](images/image5.png) -->
> **调试技巧**:修改代码后,在 Extension Development Host 窗口中按 **Ctrl+Shift+P** → **"Developer: Reload Window"** 即可重新加载插件,不需要重启调试。 > **调试技巧**:修改代码后,在 Extension Development Host 窗口中按 **Ctrl+Shift+P** → **"Developer: Reload Window"** 即可重新加载插件,不需要重启调试。
@@ -267,7 +267,7 @@ export function deactivate() {}
2. 在该入口下创建了一个 "项目模板" 视图 2. 在该入口下创建了一个 "项目模板" 视图
3. 在视图标题栏添加了一个 "+" 按钮用于创建项目 3. 在视图标题栏添加了一个 "+" 按钮用于创建项目
![placeholder: VS Code 侧边栏中显示 AI Project Bot 图标和项目模板列表的截图](images/image6.png) <!-- ![placeholder: VS Code 侧边栏中显示 AI Project Bot 图标和项目模板列表的截图](images/image6.png) -->
## 3.3 实现 TreeDataProvider ## 3.3 实现 TreeDataProvider
@@ -393,7 +393,7 @@ export function activate(context: vscode.ExtensionContext) {
现在按 F5 调试,你会在左侧活动栏看到 AI Project Bot 图标,点击后展开模板列表,点击任意模板即可创建项目。 现在按 F5 调试,你会在左侧活动栏看到 AI Project Bot 图标,点击后展开模板列表,点击任意模板即可创建项目。
![placeholder: 点击模板后弹出项目名称输入框和文件夹选择对话框的截图](images/image7.png) <!-- ![placeholder: 点击模板后弹出项目名称输入框和文件夹选择对话框的截图](images/image7.png) -->
# 第 4 章:实现 AI Chat 参与者(5 分钟) # 第 4 章:实现 AI Chat 参与者(5 分钟)
@@ -530,7 +530,7 @@ export function activate(context: vscode.ExtensionContext) {
现在在 Chat 面板中输入 `@project-bot /explain 这段代码是做什么的?`,你的插件就会调用大模型生成解释。 现在在 Chat 面板中输入 `@project-bot /explain 这段代码是做什么的?`,你的插件就会调用大模型生成解释。
![placeholder: VS Code Chat 面板中 @project-bot 对话的截图,展示 /explain 命令的使用和流式回复](images/image8.png) <!-- ![placeholder: VS Code Chat 面板中 @project-bot 对话的截图,展示 /explain 命令的使用和流式回复](images/image8.png) -->
# 第 5 章:文件/段落 Chat 与多文件问答(5 分钟) # 第 5 章:文件/段落 Chat 与多文件问答(5 分钟)
@@ -631,7 +631,7 @@ export function registerSelectionCommands(context: vscode.ExtensionContext) {
} }
``` ```
![placeholder: 编辑器中右键选中代码后显示 AI 菜单项的截图](images/image9.png) <!-- ![placeholder: 编辑器中右键选中代码后显示 AI 菜单项的截图](images/image9.png) -->
## 5.3 多文件问答:批量分析文件关系 ## 5.3 多文件问答:批量分析文件关系
@@ -730,7 +730,7 @@ export function registerMultiFileCommands(context: vscode.ExtensionContext) {
使用方式:在资源管理器中按住 Ctrl(Mac 上是 Cmd)多选文件,右键选择 "AI: 分析选中文件的关系",AI 就会读取所有文件内容并给出分析报告。 使用方式:在资源管理器中按住 Ctrl(Mac 上是 Cmd)多选文件,右键选择 "AI: 分析选中文件的关系",AI 就会读取所有文件内容并给出分析报告。
![placeholder: 资源管理器中多选文件后右键菜单显示 AI 分析选项的截图](images/image10.png) <!-- ![placeholder: 资源管理器中多选文件后右键菜单显示 AI 分析选项的截图](images/image10.png) -->
# 第 6 章:快捷键与 UX 优化(3 分钟) # 第 6 章:快捷键与 UX 优化(3 分钟)
@@ -800,7 +800,7 @@ export function createStatusBarItem(context: vscode.ExtensionContext) {
`$(hubot)` 是 VS Code 内置的图标语法,你可以在 [Codicon 图标库](https://microsoft.github.io/vscode-codicons/dist/codicon.html) 中找到所有可用图标。 `$(hubot)` 是 VS Code 内置的图标语法,你可以在 [Codicon 图标库](https://microsoft.github.io/vscode-codicons/dist/codicon.html) 中找到所有可用图标。
![placeholder: VS Code 状态栏中显示 AI Bot 图标的截图](images/image11.png) <!-- ![placeholder: VS Code 状态栏中显示 AI Bot 图标的截图](images/image11.png) -->
# 第 7 章:发布到插件市场(可选) # 第 7 章:发布到插件市场(可选)
@@ -855,7 +855,7 @@ vsce publish
如果要正式发布到市场,执行 `vsce publish` 后,插件会在几分钟内出现在 VS Code 插件市场中。 如果要正式发布到市场,执行 `vsce publish` 后,插件会在几分钟内出现在 VS Code 插件市场中。
![placeholder: VS Code 插件市场中 AI Project Bot 插件页面的截图](images/image12.png) <!-- ![placeholder: VS Code 插件市场中 AI Project Bot 插件页面的截图](images/image12.png) -->
> **提示**:首次发布可能需要等待审核。确保你的 README 描述清晰、截图完整,审核通过会更快。 > **提示**:首次发布可能需要等待审核。确保你的 README 描述清晰、截图完整,审核通过会更快。
@@ -54,7 +54,7 @@
└──────────┘ └──────────┘ └──────────┘ └──────────┘
``` ```
![placeholder: 上位机和下位机的关系示意图,左边是控制室的 PC 屏幕(上位机),右边是工厂现场的 PLC 和水泵(下位机),中间用 Modbus 协议连接](images/image1.png) <!-- ![placeholder: 上位机和下位机的关系示意图,左边是控制室的 PC 屏幕(上位机),右边是工厂现场的 PLC 和水泵(下位机),中间用 Modbus 协议连接](images/image1.png) -->
## 1.2 什么是 Modbus 协议? ## 1.2 什么是 Modbus 协议?
@@ -98,7 +98,7 @@ Qt 是工业软件开发的首选框架之一,很多你在工厂、医院、
| 故障日志 | 所有报警事件记录到数据库,可查询历史 | | 故障日志 | 所有报警事件记录到数据库,可查询历史 |
| 手动控制 | 一键启停水泵(写入下位机寄存器) | | 手动控制 | 一键启停水泵(写入下位机寄存器) |
![placeholder: 水泵监控 HMI 系统效果预览图,展示实时压力数值、趋势图、报警指示灯、启停按钮和日志列表](images/image2.png) <!-- ![placeholder: 水泵监控 HMI 系统效果预览图,展示实时压力数值、趋势图、报警指示灯、启停按钮和日志列表](images/image2.png) -->
## 1.5 本教程的路线图 ## 1.5 本教程的路线图
@@ -128,7 +128,7 @@ Qt 提供了免费的开源版本,足够我们使用。
> **提示**:如果你已经安装了 Qt 但没有 Serial Bus 或 Charts 模块,可以重新运行 Qt Maintenance Tool,在"添加或移除组件"中补装。 > **提示**:如果你已经安装了 Qt 但没有 Serial Bus 或 Charts 模块,可以重新运行 Qt Maintenance Tool,在"添加或移除组件"中补装。
![placeholder: Qt 安装器的组件选择页面截图,高亮 Qt Serial Bus 和 Qt Charts 的勾选项](images/image3.png) <!-- ![placeholder: Qt 安装器的组件选择页面截图,高亮 Qt Serial Bus 和 Qt Charts 的勾选项](images/image3.png) -->
## 2.2 安装 Modbus Slave——你的"虚拟水泵" ## 2.2 安装 Modbus Slave——你的"虚拟水泵"
@@ -151,7 +151,7 @@ Modbus Slave 是一款免费的 Modbus 从站模拟软件,它可以在你的
现在 Modbus Slave 就是你的"24 小时运行的虚拟水泵"——窗口保持开着,它会一直响应上位机的读写请求。 现在 Modbus Slave 就是你的"24 小时运行的虚拟水泵"——窗口保持开着,它会一直响应上位机的读写请求。
![placeholder: Modbus Slave 软件截图,展示 TCP 连接配置和寄存器表格中的模拟数据](images/image4.png) <!-- ![placeholder: Modbus Slave 软件截图,展示 TCP 连接配置和寄存器表格中的模拟数据](images/image4.png) -->
> **动态模拟技巧**Modbus Slave 支持自动递增/随机变化。右键点击寄存器值,选择 "Auto increment" 或 "Random",就能模拟真实传感器的数据波动,让你的趋势图更生动。 > **动态模拟技巧**Modbus Slave 支持自动递增/随机变化。右键点击寄存器值,选择 "Auto increment" 或 "Random",就能模拟真实传感器的数据波动,让你的趋势图更生动。
@@ -263,7 +263,7 @@ private:
#endif // MAINWINDOW_H #endif // MAINWINDOW_H
``` ```
![placeholder: Qt Creator 中 mainwindow.h 文件的截图](images/image5.png) <!-- ![placeholder: Qt Creator 中 mainwindow.h 文件的截图](images/image5.png) -->
## 3.3 建立 Modbus TCP 连接 ## 3.3 建立 Modbus TCP 连接
@@ -378,7 +378,7 @@ readPressure() 被定时器触发
→ 解析寄存器值,更新界面 → 解析寄存器值,更新界面
``` ```
![placeholder: 程序运行截图,展示压力数值实时更新,状态栏显示"已连接到下位机"](images/image6.png) <!-- ![placeholder: 程序运行截图,展示压力数值实时更新,状态栏显示"已连接到下位机"](images/image6.png) -->
# 第 4 章:绘制实时压力趋势图(3 分钟) # 第 4 章:绘制实时压力趋势图(3 分钟)
@@ -468,7 +468,7 @@ updateChart(pressure);
现在运行程序,你会看到一条蓝色折线在实时滚动——每秒新增一个数据点,始终显示最近 60 秒的压力变化。如果你在 Modbus Slave 中手动修改寄存器值,折线会立刻反映出变化。 现在运行程序,你会看到一条蓝色折线在实时滚动——每秒新增一个数据点,始终显示最近 60 秒的压力变化。如果你在 Modbus Slave 中手动修改寄存器值,折线会立刻反映出变化。
![placeholder: 实时压力趋势图运行截图,展示蓝色折线在滚动更新,X 轴为时间,Y 轴为压力值](images/image7.png) <!-- ![placeholder: 实时压力趋势图运行截图,展示蓝色折线在滚动更新,X 轴为时间,Y 轴为压力值](images/image7.png) -->
> **性能提示**`QChart::NoAnimation` 很重要——实时数据每秒刷新,如果开启动画会导致界面卡顿。这是工业 HMI 开发中的常见经验。 > **性能提示**`QChart::NoAnimation` 很重要——实时数据每秒刷新,如果开启动画会导致界面卡顿。这是工业 HMI 开发中的常见经验。
@@ -520,7 +520,7 @@ void MainWindow::triggerAlarm(float pressure)
} }
``` ```
![placeholder: 压力超阈值时的报警截图,展示红色背景的压力数值、红色指示灯和报警弹窗](images/image8.png) <!-- ![placeholder: 压力超阈值时的报警截图,展示红色背景的压力数值、红色指示灯和报警弹窗](images/image8.png) -->
## 5.2 SQLite 故障日志 ## 5.2 SQLite 故障日志
@@ -583,7 +583,7 @@ void MainWindow::logAlarm(float pressure, const QString &message)
日志表格显示三列:时间、压力值、报警信息。每次报警都会自动追加一行,同时写入 SQLite 数据库持久化存储。 日志表格显示三列:时间、压力值、报警信息。每次报警都会自动追加一行,同时写入 SQLite 数据库持久化存储。
![placeholder: 故障日志表格截图,展示多条报警记录,包含时间戳、压力值和报警信息](images/image9.png) <!-- ![placeholder: 故障日志表格截图,展示多条报警记录,包含时间戳、压力值和报警信息](images/image9.png) -->
## 5.4 手动启停水泵 ## 5.4 手动启停水泵
@@ -621,7 +621,7 @@ void MainWindow::togglePump()
在 Modbus Slave 中,你会看到地址 2 的值随着你点击按钮在 0 和 1 之间切换——这就是上位机"控制"下位机的过程。 在 Modbus Slave 中,你会看到地址 2 的值随着你点击按钮在 0 和 1 之间切换——这就是上位机"控制"下位机的过程。
![placeholder: 水泵启停按钮的截图,展示绿色"启动水泵"和红色"停止水泵"两种状态](images/image10.png) <!-- ![placeholder: 水泵启停按钮的截图,展示绿色"启动水泵"和红色"停止水泵"两种状态](images/image10.png) -->
# 第 6 章:打包与部署(可选) # 第 6 章:打包与部署(可选)
@@ -658,7 +658,7 @@ macdeployqt PumpHMI.app -dmg
4. 运行 binarycreator 生成安装包 4. 运行 binarycreator 生成安装包
``` ```
![placeholder: PumpHMI 安装向导截图,展示安装路径选择和安装进度](images/image11.png) <!-- ![placeholder: PumpHMI 安装向导截图,展示安装路径选择和安装进度](images/image11.png) -->
# 第 7 章:写在最后 # 第 7 章:写在最后
@@ -25,7 +25,7 @@ PWA 本质上还是一个网页,但它通过几项关键技术,让自己"进
简单来说,PWA 就是 **"穿上了 App 外衣的网页"**。 简单来说,PWA 就是 **"穿上了 App 外衣的网页"**。
![placeholder: 一张对比图,左边是普通网页在浏览器中打开的样子(有地址栏),右边是同一个网页以 PWA 模式安装后的样子(独立窗口,无地址栏,像原生 App)](images/image1.png) <!-- ![placeholder: 一张对比图,左边是普通网页在浏览器中打开的样子(有地址栏),右边是同一个网页以 PWA 模式安装后的样子(独立窗口,无地址栏,像原生 App)](images/image1.png) -->
## 1.2 PWA 的三大核心技术 ## 1.2 PWA 的三大核心技术
@@ -43,7 +43,7 @@ PWA 必须运行在 HTTPS 协议下。这是浏览器的硬性要求——只有
这是 PWA 的"灵魂"。它是一段运行在浏览器后台的 JavaScript 代码,充当你的 App 和网络之间的"中间人"。它可以拦截网络请求、缓存资源,从而实现离线访问。你可以把它理解为一个 **"住在浏览器里的小管家"**,负责帮你存东西、取东西。 这是 PWA 的"灵魂"。它是一段运行在浏览器后台的 JavaScript 代码,充当你的 App 和网络之间的"中间人"。它可以拦截网络请求、缓存资源,从而实现离线访问。你可以把它理解为一个 **"住在浏览器里的小管家"**,负责帮你存东西、取东西。
![placeholder: 一张示意图,展示 PWA 三大核心技术的关系:HTTPS 是地基,Manifest 是门面,Service Worker 是引擎](images/image2.png) <!-- ![placeholder: 一张示意图,展示 PWA 三大核心技术的关系:HTTPS 是地基,Manifest 是门面,Service Worker 是引擎](images/image2.png) -->
## 1.3 为什么选择 PWA ## 1.3 为什么选择 PWA
@@ -113,7 +113,7 @@ PWA 需要图标才能被安装。我们至少需要两个尺寸:**192x192**
或者你也可以用任何设计工具(Figma、Canva)做一个你喜欢的图标,放到 `public/` 目录下。 或者你也可以用任何设计工具(Figma、Canva)做一个你喜欢的图标,放到 `public/` 目录下。
![placeholder: 两个 PWA 图标示例,一个 192x192,一个 512x512,蓝色渐变背景加白色字母](images/image3.png) <!-- ![placeholder: 两个 PWA 图标示例,一个 192x192,一个 512x512,蓝色渐变背景加白色字母](images/image3.png) -->
## 2.3 配置 vite-plugin-pwa ## 2.3 配置 vite-plugin-pwa
@@ -180,7 +180,7 @@ export default defineConfig({
* `display: 'standalone'`:安装后以独立窗口运行,没有浏览器地址栏,看起来像原生 App。 * `display: 'standalone'`:安装后以独立窗口运行,没有浏览器地址栏,看起来像原生 App。
* `workbox.globPatterns`:告诉 Service Worker 要缓存哪些类型的文件,这些文件在离线时也能访问。 * `workbox.globPatterns`:告诉 Service Worker 要缓存哪些类型的文件,这些文件在离线时也能访问。
![placeholder: vite.config.ts 文件的编辑器截图,展示 PWA 配置代码](images/image4.png) <!-- ![placeholder: vite.config.ts 文件的编辑器截图,展示 PWA 配置代码](images/image4.png) -->
## 2.4 给 App 添加一些内容 ## 2.4 给 App 添加一些内容
@@ -197,7 +197,7 @@ export default defineConfig({
这个 Todo 应用非常适合演示 PWA 的能力:即使断网,你依然可以添加和管理待办事项,因为数据存在本地,页面资源也被 Service Worker 缓存了。 这个 Todo 应用非常适合演示 PWA 的能力:即使断网,你依然可以添加和管理待办事项,因为数据存在本地,页面资源也被 Service Worker 缓存了。
![placeholder: Todo 应用的界面截图,展示输入框、待办列表和完成/删除按钮](images/image5.png) <!-- ![placeholder: Todo 应用的界面截图,展示输入框、待办列表和完成/删除按钮](images/image5.png) -->
# 第 3 章:本地体验 PWA # 第 3 章:本地体验 PWA
@@ -227,7 +227,7 @@ PWA 的 Service Worker 只在生产构建中生效(开发模式下不会注册
安装后的 PWA 看起来就像一个原生桌面应用——没有地址栏,没有标签页,有自己的窗口和图标。 安装后的 PWA 看起来就像一个原生桌面应用——没有地址栏,没有标签页,有自己的窗口和图标。
![placeholder: 两张对比截图:左边是浏览器中的安装提示,右边是安装后的独立窗口效果](images/image6.png) <!-- ![placeholder: 两张对比截图:左边是浏览器中的安装提示,右边是安装后的独立窗口效果](images/image6.png) -->
**macOS Safari 安装步骤:** **macOS Safari 安装步骤:**
@@ -246,7 +246,7 @@ PWA 的 Service Worker 只在生产构建中生效(开发模式下不会注册
你也可以打开 Chrome DevToolsF12)→ Application → Service Workers,查看 Service Worker 的运行状态和缓存的资源列表。 你也可以打开 Chrome DevToolsF12)→ Application → Service Workers,查看 Service Worker 的运行状态和缓存的资源列表。
![placeholder: Chrome DevTools 的 Application 面板截图,展示 Service Worker 状态和 Cache Storage 中缓存的文件列表](images/image7.png) <!-- ![placeholder: Chrome DevTools 的 Application 面板截图,展示 Service Worker 状态和 Cache Storage 中缓存的文件列表](images/image7.png) -->
# 第 4 章:部署上线 # 第 4 章:部署上线
@@ -276,7 +276,7 @@ PWA 必须运行在 HTTPS 上才能正常工作。好消息是,现在主流的
等待几十秒,Vercel 会自动构建并部署你的项目。完成后,你会得到一个类似 `https://my-pwa-app.vercel.app` 的 HTTPS 地址。 等待几十秒,Vercel 会自动构建并部署你的项目。完成后,你会得到一个类似 `https://my-pwa-app.vercel.app` 的 HTTPS 地址。
![placeholder: 终端中 Vercel 部署成功的截图,展示部署后的 URL](images/image8.png) <!-- ![placeholder: 终端中 Vercel 部署成功的截图,展示部署后的 URL](images/image8.png) -->
**第三步:验证 PWA** **第三步:验证 PWA**
@@ -311,7 +311,7 @@ base: '/my-pwa-app/'(替换为你的 GitHub 仓库名)
打开它,你会发现它以全屏模式运行,没有浏览器的地址栏和导航按钮,和原生 App 几乎一模一样。 打开它,你会发现它以全屏模式运行,没有浏览器的地址栏和导航按钮,和原生 App 几乎一模一样。
![placeholder: Android 手机上的安装流程截图:左边是 Chrome 中的安装提示,中间是确认对话框,右边是安装后桌面上的图标](images/image9.png) <!-- ![placeholder: Android 手机上的安装流程截图:左边是 Chrome 中的安装提示,中间是确认对话框,右边是安装后桌面上的图标](images/image9.png) -->
## 5.2 iPhone 安装 ## 5.2 iPhone 安装
@@ -324,7 +324,7 @@ iOS 上安装 PWA 只能通过 **Safari** 浏览器(其他浏览器不支持
从 iOS 26 开始,所有添加到主屏幕的网站都会默认以独立 App 模式打开,这是一个重大改进。 从 iOS 26 开始,所有添加到主屏幕的网站都会默认以独立 App 模式打开,这是一个重大改进。
![placeholder: iPhone 上的安装流程截图:左边是 Safari 的分享菜单,右边是添加到主屏幕的确认页面](images/image10.png) <!-- ![placeholder: iPhone 上的安装流程截图:左边是 Safari 的分享菜单,右边是添加到主屏幕的确认页面](images/image10.png) -->
> **iOS 的已知限制** > **iOS 的已知限制**
> * 推送通知需要 iOS 16.4 以上,且必须先将 PWA 添加到主屏幕 > * 推送通知需要 iOS 16.4 以上,且必须先将 PWA 添加到主屏幕
@@ -337,7 +337,7 @@ Google 提供了一个叫 **Lighthouse** 的工具,可以给你的 PWA 打分
一个合格的 PWA 应该在 PWA 评分上拿到满分。如果有扣分项,Lighthouse 会告诉你具体原因和修复建议。 一个合格的 PWA 应该在 PWA 评分上拿到满分。如果有扣分项,Lighthouse 会告诉你具体原因和修复建议。
![placeholder: Lighthouse 审计结果截图,展示 PWA 评分为满分,各项检查都通过](images/image11.png) <!-- ![placeholder: Lighthouse 审计结果截图,展示 PWA 评分为满分,各项检查都通过](images/image11.png) -->
# 第 6 章:写在最后 # 第 6 章:写在最后
@@ -16,7 +16,7 @@
想象一下:你打开一篇 5000 字的技术博客,点一下插件按钮,几秒钟后,一份精炼的中文摘要就出现在侧边栏里。这就是我们要构建的东西。 想象一下:你打开一篇 5000 字的技术博客,点一下插件按钮,几秒钟后,一份精炼的中文摘要就出现在侧边栏里。这就是我们要构建的东西。
![placeholder: 一张效果预览图,左边是一个长文章网页,右边是 Chrome 侧边栏中显示的 AI 生成的摘要](images/image1.png) <!-- ![placeholder: 一张效果预览图,左边是一个长文章网页,右边是 Chrome 侧边栏中显示的 AI 生成的摘要](images/image1.png) -->
## 1.2 Chrome 插件的基本架构 ## 1.2 Chrome 插件的基本架构
@@ -42,7 +42,7 @@ Chrome 插件(基于 Manifest V3)由几个核心部分组成,它们各司
→ Service Worker 把摘要发回侧边栏显示 → Service Worker 把摘要发回侧边栏显示
``` ```
![placeholder: 一张架构流程图,展示 Content Script、Service Worker、Side Panel 之间的消息传递关系](images/image2.png) <!-- ![placeholder: 一张架构流程图,展示 Content Script、Service Worker、Side Panel 之间的消息传递关系](images/image2.png) -->
## 1.3 两种 AI 方案:云端 API vs 浏览器内置 AI ## 1.3 两种 AI 方案:云端 API vs 浏览器内置 AI
@@ -147,7 +147,7 @@ AI 会帮你生成完整的项目骨架。让我们逐个看看每个文件的
* `scripting`:允许插件向页面注入脚本来读取内容 * `scripting`:允许插件向页面注入脚本来读取内容
* `sidePanel`:允许使用 Chrome 侧边栏 API * `sidePanel`:允许使用 Chrome 侧边栏 API
![placeholder: manifest.json 文件在编辑器中的截图](images/image2b.png) <!-- ![placeholder: manifest.json 文件在编辑器中的截图](images/image2b.png) -->
## 2.3 准备图标 ## 2.3 准备图标
@@ -170,7 +170,7 @@ Chrome 插件需要三个尺寸的图标:16x16、48x48、128x128。你可以
你会看到插件出现在列表中,右上角的工具栏也会多出一个图标。 你会看到插件出现在列表中,右上角的工具栏也会多出一个图标。
![placeholder: Chrome 扩展管理页面的截图,展示如何开启开发者模式并加载插件](images/image3.png) <!-- ![placeholder: Chrome 扩展管理页面的截图,展示如何开启开发者模式并加载插件](images/image3.png) -->
> **提示**:每次修改代码后,回到 `chrome://extensions/` 页面,点击插件卡片上的 **刷新按钮(🔄)** 即可更新。 > **提示**:每次修改代码后,回到 `chrome://extensions/` 页面,点击插件卡片上的 **刷新按钮(🔄)** 即可更新。
@@ -267,7 +267,7 @@ async function handleSummarize(tabId) {
} }
``` ```
![placeholder: background.js 代码在编辑器中的截图](images/image4.png) <!-- ![placeholder: background.js 代码在编辑器中的截图](images/image4.png) -->
## 3.3 侧边栏 UI:展示总结结果 ## 3.3 侧边栏 UI:展示总结结果
@@ -297,7 +297,7 @@ sidepanel.js
- "复制" 按钮使用 navigator.clipboard.writeText 复制文字 - "复制" 按钮使用 navigator.clipboard.writeText 复制文字
``` ```
![placeholder: 侧边栏 UI 效果截图,展示总结按钮、加载状态和摘要结果三种状态](images/image5.png) <!-- ![placeholder: 侧边栏 UI 效果截图,展示总结按钮、加载状态和摘要结果三种状态](images/image5.png) -->
## 3.4 设置页面:配置 API Key ## 3.4 设置页面:配置 API Key
@@ -315,7 +315,7 @@ sidepanel.js
> **安全提醒**API Key 存储在 `chrome.storage.local` 中,仅在本地设备上保存。但如果你要发布到 Chrome Web Store 供他人使用,更安全的做法是搭建一个后端代理服务器,避免 API Key 直接暴露在客户端。 > **安全提醒**API Key 存储在 `chrome.storage.local` 中,仅在本地设备上保存。但如果你要发布到 Chrome Web Store 供他人使用,更安全的做法是搭建一个后端代理服务器,避免 API Key 直接暴露在客户端。
![placeholder: 设置页面的截图,展示 AI 提供商选择和 API Key 输入框](images/image6.png) <!-- ![placeholder: 设置页面的截图,展示 AI 提供商选择和 API Key 输入框](images/image6.png) -->
# 第 4 章:使用 Chrome 内置 AI(无需 API Key # 第 4 章:使用 Chrome 内置 AI(无需 API Key
@@ -331,7 +331,7 @@ sidepanel.js
在 Chrome 地址栏输入 `chrome://flags`,搜索 `Summarization API`,确保它是 **Enabled** 状态。 在 Chrome 地址栏输入 `chrome://flags`,搜索 `Summarization API`,确保它是 **Enabled** 状态。
![placeholder: chrome://flags 页面截图,展示 Summarization API 的开关位置](images/image7.png) <!-- ![placeholder: chrome://flags 页面截图,展示 Summarization API 的开关位置](images/image7.png) -->
## 4.2 使用 Summarizer API ## 4.2 使用 Summarizer API
@@ -383,7 +383,7 @@ async function summarizeWithBuiltinAI(text) {
3. 当选择 OpenAI 或 Claude 时,显示 API Key 输入框 3. 当选择 OpenAI 或 Claude 时,显示 API Key 输入框
``` ```
![placeholder: 更新后的设置页面截图,展示三个 AI 提供商选项,选中 Chrome 内置 AI 时 API Key 输入框隐藏](images/image8.png) <!-- ![placeholder: 更新后的设置页面截图,展示三个 AI 提供商选项,选中 Chrome 内置 AI 时 API Key 输入框隐藏](images/image8.png) -->
# 第 5 章:测试与调试 # 第 5 章:测试与调试
@@ -406,7 +406,7 @@ async function summarizeWithBuiltinAI(text) {
2. 在 Console 面板中,点击左上角的下拉框,选择你的插件名称 2. 在 Console 面板中,点击左上角的下拉框,选择你的插件名称
3. 就能看到 Content Script 的 console 输出 3. 就能看到 Content Script 的 console 输出
![placeholder: Chrome DevTools 调试插件的截图,展示如何选择不同的执行上下文来调试不同组件](images/image9.png) <!-- ![placeholder: Chrome DevTools 调试插件的截图,展示如何选择不同的执行上下文来调试不同组件](images/image9.png) -->
## 5.2 常见问题排查 ## 5.2 常见问题排查
@@ -442,7 +442,7 @@ async function summarizeWithBuiltinAI(text) {
Google 会对提交的插件进行审核,通常需要几个工作日。权限越少、描述越清晰,审核通过越快。 Google 会对提交的插件进行审核,通常需要几个工作日。权限越少、描述越清晰,审核通过越快。
![placeholder: Chrome Web Store Developer Dashboard 的截图,展示插件上传和信息填写界面](images/image10.png) <!-- ![placeholder: Chrome Web Store Developer Dashboard 的截图,展示插件上传和信息填写界面](images/image10.png) -->
# 第 7 章:写在最后 # 第 7 章:写在最后