通过代码获取接口文档工具

通过代码获取接口文档工具

介绍

1.通过前后端代码来生成规格化的接口文档

2.支持拖拽上传或点击选择文件,可以一次选择多个文件或选择文件夹

3.用户选择前后端代码,工具调用GPT解析,得到规范化的接口文档

4.接口文档为markdown格式,可在线预览,也可以将文档导出

使用到的技术

1.vue3

2.v-md-editor

3.通义千问的接口

4.代码由mastergo设计页面,trae进一步调整代码

使用说明

需要配置sk,可在阿里云申请;然后替换代码 util/util.js 的sk

核心源码

App.vue

html 复制代码
<script setup>
import {nextTick, ref} from 'vue'
import Message from './utils/message.js'
import {callGpt} from "@/utils/util";

// 存储选中的文件
const selectedFiles = ref([])
// 预览的markdown内容
const previewContent = ref('')
// 控制预览对话框显示
const showPreview = ref(false)

// 处理文件拖拽
const handleDrop = (e) => {
  e.preventDefault()
  const files = e.dataTransfer.files
  handleFiles(files)
}

const fileInputLoading = ref(false);
const fileInput = ref();

// 处理文件选择
const handleFileSelect = (e) => {
  const files = e.target.files
  handleFiles(files)
  nextTick(() => {
    fileInputLoading.value = true;
  });
}

const selectBtn = () => {
  fileInputLoading.value = false;
  nextTick(() => {
    fileInput.value.click()
  });
}

const selectDirBtn = async () => {
  try {
    const dirHandle = await window.showDirectoryPicker()
    // 清空已选择的文件
    selectedFiles.value = []
    // 递归处理文件夹
    await processDirectory(dirHandle, '')
    Message.success('文件夹导入成功')
  } catch (err) {
    if (err.name !== 'AbortError') {
      Message.error('选择文件夹失败')
      console.error(err)
    }
  }
}

// 递归处理文件夹
const processDirectory = async (dirHandle, path) => {
  for await (const entry of dirHandle.values()) {
    if (entry.kind === 'file') {
      const file = await entry.getFile()
      selectedFiles.value.push({
        file: file,
        relativePath: path ? `${path}/${file.name}` : file.name
      })
    } else if (entry.kind === 'directory') {
      const newPath = path ? `${path}/${entry.name}` : entry.name
      await processDirectory(entry, newPath)
    }
  }
}

// 处理文件
const handleFiles = (files) => {
  for (let file of files) {
    // 检查文件类型
    if (!isValidFileType(file)) {
      Message.warning(`不支持的文件类型: ${file.name}`)
      continue
    }
    selectedFiles.value.push({
      file: file,
      relativePath: file.name
    })
  }
}

// 检查文件类型
const isValidFileType = (file) => {
  const validTypes = ['.java', '.py', '.js', '.ts', '.go', '.cpp', '.c', '.h', '.txt', '.json']
  return validTypes.some(type => file.name.toLowerCase().endsWith(type))
}

// 清空文件列表
const clearFiles = () => {
  selectedFiles.value = []
  Message.info('文件列表已清空')
}

// 移除单个文件
const removeFile = (index) => {
  selectedFiles.value.splice(index, 1)
}

// 生成接口文档
const generateDocs = async () => {
  if (selectedFiles.value.length === 0) {
    Message.warning('请先选择文件');
    return;
  }

  try {
    // 读取所有文件内容
    const fileContents = await Promise.all(
        selectedFiles.value.map(async (item) => {
          const content = await item.file.text();
          return {
            path: item.relativePath,
            content: content
          };
        })
    );

    // 构建提示词
    const prompt = `请帮我分析以下代码文件,生成一份完整的接口文档,接口文档要规范化,要包含请求和返回示例:\n\n${
        fileContents.map(file =>
            `文件路径:${file.path}\n文件内容:\n${file.content}\n---\n`
        ).join('\n')
    }`;

    Message.info('正在生成文档...');
    previewContent.value = ''; // 清空之前的内容
    showPreview.value = true;

    await callGpt(prompt, (content) => {
      // 实时更新预览内容
      previewContent.value = content;
    }, ()=> {
      Message.success('文档生成成功');
    });
  } catch (error) {
    Message.error('文档生成失败');
    console.error(error);
  }
}

// 导出markdown文档
const exportMarkdown = () => {
  const blob = new Blob([previewContent.value], { type: 'text/markdown' })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = 'api-docs.md'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
  Message.success('文档导出成功')
}
</script>

<template>
  <div class="bg-gray-50" style="width: 100%; height: 100%">
    <div class="w-[1200px] mx-auto">
      <nav class="h-16 bg-white shadow-sm flex items-center justify-between px-8">
        <div class="flex items-center space-x-2">
          <span class="text-2xl font-['Pacifico'] text-primary">logo</span>
          <span class="text-lg font-medium">接口文档生成器</span>
        </div>
        <button class="w-10 h-10 rounded-button flex items-center justify-center hover:bg-gray-100 transition-colors">
          <i class="fas fa-sun text-gray-600"></i>
        </button>
      </nav>

      <main class="px-8 py-12">
        <div class="max-w-3xl mx-auto">
          <div class="bg-white rounded-lg shadow-sm p-8">
            <div id="dropArea"
                 class="drag-area rounded-lg p-12 text-center"
                 @drop="handleDrop"
                 @dragover.prevent
                 @dragenter.prevent>
              <input v-if="!fileInputLoading"
                     ref="fileInput"
                     type="file"
                     id="fileInput"
                     class="file-input"
                     multiple
                     @change="handleFileSelect">
              <div class="space-y-4">
                <div class="w-20 h-20 mx-auto bg-gray-50 rounded-full flex items-center justify-center">
                  <i class="fas fa-cloud-upload-alt text-4xl text-gray-400"></i>
                </div>
                <div>
                  <h3 class="text-lg font-medium">拖拽文件到这里,或</h3>
                  <button @click="selectBtn"
                          class="mt-2 px-6 py-2 bg-primary text-white rounded-button hover:bg-primary/90 button-hover whitespace-nowrap">
                    点击选择文件
                  </button>
                  <button @click="selectDirBtn"
                          class="ml-4 mt-2 px-6 py-2 bg-primary text-white rounded-button hover:bg-primary/90 button-hover whitespace-nowrap">
                    点击选择文件夹
                  </button>
                </div>
                <p class="text-sm text-gray-500">
                  支持的文件格式:.java, .py, .js, .ts, .go, .cpp, .c, .h, .txt, .json
                </p>
              </div>
            </div>

            <div id="fileList" class="mt-8 space-y-4" :class="selectedFiles.length > 0 ? '' : ' hidden'">
              <div class="text-lg font-medium mb-4">已选择的文件</div>
              <div class="space-y-3">
                <template v-for="(item, index) in selectedFiles" :key="index">
                  <div class="flex items-center justify-between p-3 bg-gray-50 rounded-md">
                    <div class="flex items-center">
                      <i class="fas fa-file-code text-primary mr-3"></i>
                      <span class="text-gray-600 text-sm mr-2">{{ item.relativePath }}</span>
                      <span>{{ item.file.name }}</span>
                    </div>
                    <button class="text-red-500 hover:text-red-700" @click="removeFile(index)">
                      <i class="fas fa-times"></i>
                    </button>
                  </div>
                </template>
              </div>
              <div class="flex justify-end space-x-3 mt-6">
                <button @click="clearFiles"
                        class="px-6 py-2 text-gray-600 bg-gray-100 rounded-button hover:bg-gray-200 button-hover whitespace-nowrap">
                  清空列表
                </button>
                <button @click="generateDocs"
                        class="px-6 py-2 text-white bg-primary rounded-button hover:bg-primary/90 button-hover whitespace-nowrap">
                  生成接口文档
                </button>
              </div>
            </div>
          </div>

          <div class="mt-12 bg-white rounded-lg shadow-sm p-8">
            <h2 class="text-xl font-medium mb-6">使用说明</h2>
            <div class="space-y-4 text-gray-600">
              <div class="flex items-start space-x-3">
                <div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <i class="fas fa-check text-sm text-primary"></i>
                </div>
                <p>支持拖拽上传或点击选择文件,可以一次选择多个文件或选择文件夹</p>
              </div>
              <div class="flex items-start space-x-3">
                <div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <i class="fas fa-check text-sm text-primary"></i>
                </div>
                <p>在选择文件夹时会将之前选择的文件列表清空,请注意操作</p>
              </div>
              <div class="flex items-start space-x-3">
                <div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <i class="fas fa-check text-sm text-primary"></i>
                </div>
                <p>用户选择前后端代码,工具调用GPT解析,得到规范化的接口文档</p>
              </div>
              <div class="flex items-start space-x-3">
                <div class="w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0 mt-0.5">
                  <i class="fas fa-check text-sm text-primary"></i>
                </div>
                <p>接口文档为markdown格式,可在线预览,也可以将文档导出</p>
              </div>
            </div>
          </div>
        </div>
      </main>
    </div>
  </div>

  <!-- 添加预览对话框 -->
  <div v-if="showPreview" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
    <div class="bg-white w-4/5 h-4/5 rounded-lg p-6 flex flex-col">
      <div class="flex justify-between items-center mb-4">
        <h3 class="text-xl font-medium">接口文档预览</h3>
        <div class="space-x-2">
          <button @click="exportMarkdown" class="px-4 py-2 bg-primary text-white rounded-button hover:bg-primary/90">
            导出文档
          </button>
          <button @click="showPreview = false" class="px-4 py-2 bg-gray-100 text-gray-600 rounded-button hover:bg-gray-200">
            关闭
          </button>
        </div>
      </div>
      <div class="flex-1 overflow-auto preview">
        <v-md-editor v-model="previewContent" mode="preview"></v-md-editor>
      </div>
    </div>
  </div>
</template>

<style>
body {
  min-height: 100vh;
}

#app {
  min-height: 100vh;
}

body::-webkit-scrollbar {
  width: 15px;
}

body::-webkit-scrollbar-track {
  background: #f1f5f9;
  border-radius: 8px;
}

body::-webkit-scrollbar-thumb {
  background: #6366f1;
  border-radius: 8px;
  border: 2px solid #f1f5f9;
}

body::-webkit-scrollbar-thumb:hover {
  background: #4f46e5;
}

.drag-area {
  border: 2px dashed #E5E7EB;
  transition: all 0.3s ease;
}

.drag-area:hover {
  border-color: #4F46E5;
}

.file-input {
  display: none;
}

.button-hover {
  transition: transform 0.2s ease;
}

.button-hover:active {
  transform: translateY(2px);
}

.preview::-webkit-scrollbar {
  width: 15px;
}

.preview::-webkit-scrollbar-track {
  background: #f1f5f9;
  border-radius: 8px;
}

.preview::-webkit-scrollbar-thumb {
  background: #6366f1;
  border-radius: 8px;
  border: 2px solid #f1f5f9;
}

.preview::-webkit-scrollbar-thumb:hover {
  background: #4f46e5;
}
</style>

演示截图

1.工具首页

2.操作页面-选择文件

3.生成接口文档页面1

4.生成接口文档页面2

工具源码

接口文档工具

相关推荐
暗暗那20 分钟前
【面试】什么是回流和重绘
前端·css·html
小宁爱Python23 分钟前
用HTML和CSS绘制佩奇:我不是佩奇
前端·css·html
weifexie1 小时前
ruby可变参数
开发语言·前端·ruby
王磊鑫1 小时前
重返JAVA之路-初识JAVA
java·开发语言
千野竹之卫1 小时前
3D珠宝渲染用什么软件比较好?渲染100邀请码1a12
开发语言·前端·javascript·3d·3dsmax
sunbyte1 小时前
初识 Three.js:开启你的 Web 3D 世界 ✨
前端·javascript·3d
半兽先生1 小时前
WebRtc 视频流卡顿黑屏解决方案
java·前端·webrtc
liuluyang5302 小时前
C语言C11支持的结构体嵌套的用法
c语言·开发语言·算法·编译·c11
凌叁儿2 小时前
python保留关键字详解
开发语言·python
南星沐2 小时前
Spring Boot 常用依赖介绍
java·前端·spring boot