DeepCodeGenius-vscode/doc/文档tab页.md
jiajun.song 59a7854aa3 文档支持从工作区获取
补全文档tab页开发文档关键代码记录
2025-05-06 18:05:25 +08:00

6.9 KiB

文档页面开发记录

文档页面实现功能

  1. 文档分页获取文件为markdown格式 代码示例

     ```html
     <!-- webview\src\components\DocCodePanel.vue -->
     <template>
         <MarkdownViewer :file-path="filePath"/>
     </template>
     <script>
         // 文档路径
         // const filePath = ref('__localWebViewPath/ruanjian.md')
         const filePath = ref('__localWorkspacePath/ruanjian.md')
     </script>
     ```
    
    • 文件支持的路径及修改方式
      1. 支持插件自身目录 filePath的值以 __localWebViewPath/ 开头
      2. 支持工作区目录 filePath的值以 __localWorkspacePath/ 开头
  2. 布局: alt 布局

    • 左侧为标题目录
      1. 支持折叠展开
      2. 支持点击时 右侧文档滚动到对应位置
    • 右侧为文档主题
      1. 支持展示图片

      2. 支持特殊标记实现点击时打开工作区内文件中的某个函数 目前暂定格式与示例
        示例: 打开vscode中的src/test.js:testFunction 格式: 显示文字 关键代码:

            ///webview\src\components\MarkdownViewer.vue
        
            /// ...
            const renderLink = renderer.link
            const handleDelegateClick = (event) => {
                // 通过事件冒泡捕获目标元素
                const target = event.target.closest('.openFileAndGoToFunction')
                if (target) {
                    const { filepath, functionname } = target.dataset
                    console.log(filepath, functionname, '_**=== filepath, functionname');
                    console.log(target.dataset, '_**=== target.dataset');
                    if (window.acquireVsCodeApi && window.vscodeApi) {
                        window.vscodeApi.postMessage({
                            type: 'openFileAndGoToFunction',
                            filePath: filepath,
                            functionName: functionname
                        });
                    }
                }
            }
        
            renderer.link = function (src) {
                // 工作区跳转
                if (src.href.startsWith("__workspace/")) {
                    const { href, title, tokens } = src
                    const text = renderer.parser.parseInline(tokens);
                    // const cleanHref = cleanUrl(href);
                    const titleTip = href.slice("__workspace/".length);
                    const [filePath, functionName] = titleTip.split('?functionName=')
                    console.log(filePath, functionName, '_**=== filePath, functionName');
                    return `<a href="javascript:void 0" class="openFileAndGoToFunction" title="点击打开关联文件函数: ${titleTip}" data-href="${href}" data-filepath="${filePath}" data-functionname="${functionName}">${text}</a>`
                }
                return renderLink.call(renderer, src);
            }
        
        // src\extension\ChatViewProvider.ts
        async openFileAndGoToFunction(message: ListenerParam): Promise<void | false> {
            if (message.type !== 'openFileAndGoToFunction') { return false };
            const rootUri = vscode.workspace.workspaceFolders?.[0]?.uri;
            const filePath = message.filePath; // 确保路径正确,相对于工作区
            this._logger(rootUri + '#####' + filePath)
            const targetFunc = message.functionName
            if (!filePath || !targetFunc) {
            vscode.window.showWarningMessage(`未提供文件: ${filePath} 或函数: ${targetFunc}`)
            return
            }
            try {
            // 打开文件
            const docInfo = await this.openWorkspaceFile(filePath);
            if (!docInfo) {
                vscode.window.showWarningMessage(`无法打开或创建文件: ${filePath}`)
                return
            }
            const { editor, document } = docInfo
            // 获取文档符号
            const symbols = await vscode.commands.executeCommand<vscode.DocumentSymbol[]>(
                'vscode.executeDocumentSymbolProvider',
                document.uri
            )
        
            if (symbols) {
                const funcSymbol = this.findFunction(symbols, targetFunc)
                if (funcSymbol) {
                // 跳转到目标位置
                editor.revealRange(funcSymbol.range, vscode.TextEditorRevealType.InCenter)
                editor.selection = new vscode.Selection(funcSymbol.range.start, funcSymbol.range.end)
                } else {
                vscode.window.showWarningMessage(`未找到函数 ${targetFunc}`)
                }
            }
            } catch (error) {
            vscode.window.showErrorMessage(`无法打开文件: ${error}`)
            }
        }
        // 打开工作区的文件
        async openWorkspaceFile(relativePath: string) {
            // 1. 获取工作区根路径
            const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri;
            if (!workspaceRoot) {
            vscode.window.showErrorMessage(" 未检测到工作区");
            return;
            }
        
            // 2. 拼接完整路径(自动处理跨平台路径)
            const targetUri = vscode.Uri.joinPath(workspaceRoot, relativePath);
        
            // 3. 文件存在性检测
            try {
            await vscode.workspace.fs.stat(targetUri);
            } catch {
            const createNew = await vscode.window.showInformationMessage(
                "文件不存在,是否创建?",
                "创建", "取消"
            );
            if (createNew === "创建") {
                await vscode.workspace.fs.writeFile(targetUri, Buffer.from(""));
            } else {
                return;
            }
            }
            this._logger(targetUri + ':::targetUri')
            // 4. 打开文件编辑器
            const document = await vscode.workspace.openTextDocument(targetUri);
            const editor = await vscode.window.showTextDocument(document);
            return { document, editor }
        }
        
  3. 插件信息与修改: 若需要改为标题或列表, 修改 renderer 的对应方法以及触发跳转, 渲染的元素添加类名

    marked使用文档 alt text