iFlyCode企业版编程智能体及MCP,正式上线!欢迎体验!

iFlyCode企业版编程智能体及MCP,现已全面上线!这标志着人机协同的重心,从人本身逐渐过渡到机器本身。同时,通过工程化手段,增强模型自主思考、自主规划能力,iFlyCode可完成从需求理解,到代码实现的全流程开发,真正实现了一键根据需求自动生成可运行代码

图片

01

应用价值

在开发过程中,编程智能体依托MCP提供的多语言环境和丰富的资源库,能够更好地发挥其智能代码生成、语法检查和优化建议等功能。例如,在多语言项目中,编程智能体可以根据当前所选语言的特性,生成符合该语言规范的高质量代码;而MCP则借助编程智能体的智能能力,为开发者提供更加贴心、个性化的服务。

在团队协作方面,编程智能体可以帮助团队成员,快速发现和解决代码中的问题,提高协作效率;同时,MCP的项目管理功能又能确保整个团队在统一的框架下高效运作,实现项目目标。

话不多说,飞小码用一个真实案例为你展开说说。

02

案例-利用智能体

实现前端上传组件

总体思路

1、在前端项目工程中,通过编码助手识别工程信息,提供已有接口信息和要求,由编程智能体直接生成相关文件和代码,并自动纠错

2、对于智能体未解决的少部分错误,通过智能编辑和智能补全进行调整。

准备环境

一、前端项目工程

创建一个简单的vue前端工程,这个可以交给编程智能体实现,具体过程就不在这里说明了。

项目采用vue3+element-plus+axios

以下是工程结构:

图片

二、后端服务和接口文档

如果后端服务还没有实现,可以通过编程智能体基于node生成一个服务,并让智能体根据代码生成接口文档。

下面是智能体生成的基于Node的文件上传服务的代码:


    import express from 'express'import multer from 'multer'import path from 'path'import fs from 'fs'import { fileURLToPath } from 'url'import { dirname } from 'path'const __filename fileURLToPath(import.meta.url)const __dirname dirname(__filename)const app express()const PORT 3000// 确保temp目录存在const tempDir = path.join(__dirname, 'temp')if (!fs.existsSync(tempDir)) {  fs.mkdirSync(tempDir)}// 文件存储配置const storage = multer.diskStorage({  destination: function (req, file, cb) {    cb(null, tempDir)  },  filename: function (req, file, cb) {    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)    cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname))  }})const upload multer({ storage: storage })// 中间件app.use(express.json())app.use(express.urlencoded({ extended: true }))// 普通文件上传app.post('/upload', upload.single('file'), (req, res) => {  if (!req.file) {    return res.status(400).json({ error: 'No file uploaded' })  }  // 这里可以添加文件验证逻辑  const { originalname, size } = req.file  res.json({    message: 'File uploaded successfully',    fileName: originalname,    fileSize: size  })})// 分片上传app.post('/upload/chunk', upload.single('file'), (req, res) => {  if (!req.file || !req.body.chunkIndex || !req.body.totalChunks) {    return res.status(400).json({ error: 'Missing required fields' })  }  const { chunkIndex, totalChunks, fileName } = req.body  const chunkDir = path.join(tempDir, fileName.split('.')[0])  // 创建分片临时目录  if (!fs.existsSync(chunkDir)) {    fs.mkdirSync(chunkDir)  }  // 重命名分片文件  const chunkPath = path.join(chunkDir, `${chunkIndex}.chunk`)  fs.renameSync(req.file.path, chunkPath)  res.json({    message: 'Chunk uploaded successfully',    chunkIndex,    totalChunks  })})// 合并分片app.post('/upload/merge', (req, res) => {  const { fileName, fileSize, totalChunks } = req.body  if (!fileName || !fileSize || !totalChunks) {    return res.status(400).json({ error: 'Missing required fields' })  }  const chunkDir = path.join(tempDir, fileName.split('.')[0])  const filePath = path.join(__dirname, 'uploads', fileName)  // 确保uploads目录存在  if (!fs.existsSync(path.join(__dirname, 'uploads'))) {    fs.mkdirSync(path.join(__dirname, 'uploads'))  }  // 创建可写流  const writeStream = fs.createWriteStream(filePath)  // 合并所有分片  for (let i = 0; i < totalChunks; i++) {    const chunkPath = path.join(chunkDir, `${i}.chunk`)    const chunkData = fs.readFileSync(chunkPath)    writeStream.write(chunkData)    fs.unlinkSync(chunkPath) // 删除分片  }  writeStream.end()  // 删除分片目录  fs.rmdirSync(chunkDir)  res.json({    message: 'File merged successfully',    fileName,    fileSize  })})// 取消上传/删除文件app.delete('/upload/:uid', (req, res) => {  const { uid } = req.params  if (!uid) {    return res.status(400).json({ error: 'Missing file uid' })  }  // 示例删除逻辑 - 实际项目中需要根据存储实现调整  try {    // 1. 删除已上传的分片文件    // 示例: fs.rmdirSync(`./uploads/temp/${uid}`, { recursive: true })    // 2. 删除已合并的完整文件 (如果存在)    // 示例: fs.unlinkSync(`./uploads/${uid}_${fileName}`)    res.json({      success: true,      message: 'File deleted successfully',      uid    })  } catch (err) {    console.error('Delete error:', err)    res.status(500).json({      error: 'Failed to delete file',      details: err.message    })  }})// 启动服务器app.listen(PORT, () => {  console.log(`Server running on http://localhost:${PORT}`)})
    

    下面是根据代码生成的接口文档

      # 文件上传服务API文档
      ## 基础信息- 服务地址: `http://localhost:3000`- 文件临时目录: `./server/temp`- 最终存储目录: `./server/uploads`
      ## API列表
      ### 1. 普通文件上传- **方法**: POST- **路径**: `/upload`- **Content-Type**: `multipart/form-data`- **请求参数**:  - `file`: 要上传的文件 (表单字段名必须为"file")- **成功响应**:  ```json  {    "message": "File uploaded successfully",    "fileName": "original-filename.ext",    "fileSize": 1024  }  ```- **错误响应**:  - 400: 没有上传文件  ```json  {    "error": "No file uploaded"  }  ```
      ### 2. 分片上传- **方法**: POST- **路径**: `/upload/chunk`- **Content-Type**: `multipart/form-data`- **请求参数**:  - `file`: 分片文件 (表单字段名必须为"file")  - `chunkIndex`: 当前分片索引 (从0开始)  - `totalChunks`: 总分片数  - `fileName`: 原始文件名- **成功响应**:  ```json  {    "message": "Chunk uploaded successfully",    "chunkIndex": 0,    "totalChunks": 5  }  ```- **错误响应**:  - 400: 缺少必要字段  ```json  {    "error": "Missing required fields"  }  ```
      ### 3. 合并分片- **方法**: POST- **路径**: `/upload/merge`- **Content-Type**: `application/json`- **请求体**:  ```json  {    "fileName": "original-filename.ext",    "fileSize": 1024,    "totalChunks": 5  }  ```- **成功响应**:  ```json  {    "message": "File merged successfully",    "fileName": "original-filename.ext",    "fileSize": 1024  }  ```- **错误响应**:  - 400: 缺少必要字段  ```json  {    "error": "Missing required fields"  }  ```
      ### 4. 删除文件- **方法**: DELETE- **路径**: `/upload/:uid`- **URL参数**:  - `uid`: 文件唯一标识符- **成功响应**:  ```json  {    "success": true,    "message": "File deleted successfully",    "uid": "file-uid"  }  ```- **错误响应**:  - 400: 缺少文件UID  ```json  {    "error": "Missing file uid"  }  ```  - 500: 删除失败  ```json  {    "error": "Failed to delete file",    "details": "Error message"  }  ```
      ## 使用示例
      ### 普通文件上传```bashcurl -X POST http://localhost:3000/upload \  -F "file=@test.jpg"```
      ### 分片上传```bashcurl -X POST http://localhost:3000/upload/chunk \  -F "file=@chunk1.bin" \  -F "chunkIndex=0" \  -F "totalChunks=5" \  -F "fileName=large-file.zip"```
      ### 合并分片```bashcurl -X POST http://localhost:3000/upload/merge \  -H "Content-Type: application/json" \  -d '{    "fileName": "large-file.zip",    "fileSize": 5242880,    "totalChunks": 5  }'```
      ### 删除文件```bashcurl -X DELETE http://localhost:3000/upload/file-123```

      实现功能

      一、初步生成

      1、选择智能体,然后选中我们生成的接口文档,也可以直接把接口信息复制进去,然后输入我们的要求:

      提示语:

      根据接口信息,基于elementPlus封装一个自定义上传组件, 功能设计如下:

      1、文件可以多选并实现拖拽

      2、文件格式支持pdf、word, 其中pdf文件不超过100M,word不超过20M

      3、总文件个数不超过10个, 总文件大小不超过1G

      4、文件采用自动上传功能,且文件大于10M的进行分片上传, 分片大小自定义

      5、增加上传进度显示

      6、文件可以进行删除,同时需要取消文件上传接口请求(包含切片), 并调用服务器文件删除接口

      上下文:选择API_DOCUMENTACTION.md接口文档

      图片

      以下是生成结果:

      图片

      下面是生成的代码

        <template>  <div class="upload-container">    <el-upload      ref="uploadRef"      v-model:file-list="fileList"      class="upload-demo"      drag      multiple      :auto-upload="true"      :limit="10"      :on-exceed="handleExceed"      :before-upload="beforeUpload"      :on-change="handleChange"      :on-remove="handleRemove"      :http-request="customUpload"    >      <i class="el-icon-upload"></i>      <div class="el-upload__text">        将文件拖到此处,或<em>点击选择</em>      </div>      <template#tip>        <div class="el-upload__tip">          支持PDF(≤100M)和Word(≤20M)文件,总大小不超过1G        </div>      </template>    </el-upload>    <div v-if="uploading" class="progress-container">      <div v-for="(file, index) in uploadingFiles" :key="index" class="file-progress">        <div class="file-info">          {{ file.name }} ({{ formatFileSize(file.size) }})        </div>        <el-progress          :percentage="file.percentage || 0"          :status="file.status"          :stroke-width="16"        />        <el-button          v-if="file.status !== 'success'"          size="small"          type="danger"          @click="cancelUpload(file)"        >          取消        </el-button>      </div>    </div>  </div></template><script lang="ts" setup>import { ref, computed } from 'vue'import { ElMessage } from 'element-plus'import axios from 'axios'interface UploadFile {  name: string  percentage?: number  status?: 'success' | 'exception' | 'normal'  size: number  uid: string  raw: File  controller?: AbortController}const MAX_TOTAL_SIZE = 1024 * 1024 * 1024// 1Gconst CHUNK_SIZE = 10 * 1024 * 1024// 10MB分片const API_BASE = 'http://localhost:3000'const uploadRef = ref()const fileList = ref<UploadFile[]>([])const uploadingFiles = ref<UploadFile[]>([])const uploading = computed(() => uploadingFiles.value.length > 0)const allowedTypes = ['application/pdf','application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document']const formatFileSize = (size: number) => {if (size < 1024return `${size} B`if (size < 1024 * 1024return `${(size / 1024).toFixed(1)} KB`if (size < 1024 * 1024 * 1024return `${(size / (1024 * 1024)).toFixed(1)} MB`return `${(size / (1024 * 1024 * 1024)).toFixed(1)} GB`}const handleExceed = () => {  ElMessage.warning('最多只能上传10个文件')}const beforeUpload = (file: File) => {const isAllowedType = allowedTypes.includes(file.type)const isPDF = file.type === 'application/pdf' && file.size <= 100 * 1024 * 1024const isWord = (file.type === 'application/msword' ||                file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') &&                file.size <= 20 * 1024 * 1024if (!isAllowedType) {    ElMessage.error('只能上传PDF或Word文件')returnfalse  }if (!isPDF && !isWord) {    ElMessage.error(`PDF文件不能超过100M,Word文件不能超过20M`)returnfalse  }const totalSize = fileList.value.reduce((sum, f) => sum + f.size, 0) + file.sizeif (totalSize > MAX_TOTAL_SIZE) {    ElMessage.error('总文件大小不能超过1G')returnfalse  }returntrue}const handleChange = () => {if (fileList.value.length > 10) {    fileList.value = fileList.value.slice(010)    ElMessage.warning('最多只能上传10个文件')  }}const handleRemove = async (file: UploadFile) => {if (file.controller) {    file.controller.abort()  }try {    await axios.delete(`${API_BASE}/upload/${file.uid}`)    ElMessage.success('文件删除成功')  } catch {    ElMessage.error('文件删除失败')  }}const cancelUpload = (file: UploadFile) => {if (file.controller) {    file.controller.abort()    uploadingFiles.value = uploadingFiles.value.filter(f => f.uid !== file.uid)    ElMessage.info('上传已取消')  }}const uploadChunk = async (file: UploadFile, chunk: Blob, chunkIndex: number, totalChunks: number) => {const formData = new FormData()  formData.append('file', chunk)  formData.append('chunkIndex'String(chunkIndex))  formData.append('totalChunks'String(totalChunks))  formData.append('fileName', file.name)const controller = new AbortController()  file.controller = controllertry {    await axios.post(`${API_BASE}/upload/chunk`, formData, {      signal: controller.signal,      onUploadProgress: (progressEvent) => {if (progressEvent.total) {const chunkProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total)const overallProgress = Math.round(            (chunkIndex * 100 + chunkProgress) / totalChunks          )          file.percentage = overallProgress        }      }    })  } catch (err) {if (axios.isCancel(err)) {throw err    }thrownew Error('分片上传失败')  }}const mergeChunks = async (file: UploadFile, totalChunks: number) => {try {    await axios.post(`${API_BASE}/upload/merge`, {      fileName: file.name,      fileSize: file.size,      totalChunks    })    file.status = 'success'    ElMessage.success(`${file.name} 上传成功`)  } catch (error) {    file.status = 'exception'thrownew Error('文件合并失败')  }}const customUpload = async (options: { file: File, onProgress?: (event: any) => void }) => {const file: UploadFile = {    name: options.file.name,    size: options.file.size,    uid: generateUID(),    raw: options.file,    percentage: 0,    status: 'normal'  }  uploadingFiles.value.push(file)try {if (file.size > CHUNK_SIZE) {// 分片上传const totalChunks = Math.ceil(file.size / CHUNK_SIZE)for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {const start = chunkIndex * CHUNK_SIZEconst end = Math.min(file.size, start + CHUNK_SIZE)const chunk = options.file.slice(start, end)        await uploadChunk(file, chunk, chunkIndex, totalChunks)        file.percentage = Math.round(((chunkIndex + 1) * 100) / totalChunks)      }      await mergeChunks(file, totalChunks)    } else {// 普通上传const formData = new FormData()      formData.append('file', options.file)const controller = new AbortController()      file.controller = controller      await axios.post(`${API_BASE}/upload`, formData, {        signal: controller.signal,        onUploadProgress: (progressEvent) => {if (progressEvent.total) {            file.percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total)          }        }      })      file.status = 'success'      ElMessage.success(`${file.name} 上传成功`)    }  } catch (error) {if (!axios.isCancel(error)) {      file.status = 'exception'const errorMsg = error instanceof Error ? error.message : '上传失败'      ElMessage.error(`${file.name} 上传失败: ${errorMsg}`)    }  } finally {    uploadingFiles.value = uploadingFiles.value.filter(f => f.uid !== file.uid)  }}const generateUID = () => {return Date.now().toString(36) + Math.random().toString(36).substr(2)}</script><style scoped>.upload-container {  width100%;  max-width800px;  margin0auto;}.progress-container {  margin-top20px;}.file-progress {  margin-bottom15px;}.file-info {  margin-bottom5px;  font-size14px;  color#606266;}</style>
        

        2、第一步生成的代码可能会有一些问题,检查发现有两个错误提示。

        图片

        接下来借助编码助手的修复功能进行处理。

        图片

        助手给了我们三种处理方式,为了后面的问题排查比较方便,我们采用第二种处理方式,把错误日志打印出来。

        图片

        第二个简单点,直接禁用该行的规则。

        图片

        3.组件没问题后,我们把组件在页面上使用起来。

        提示语:在App.vue里面使用这个组件

        上下文:选择AdvancedUpload.vue文件

        图片

        执行完后的代码

        
        
          <script setup lang="ts">import AdvancedUpload from './components/AdvancedUpload.vue'</script>
          <template>  <AdvancedUpload /></template>
          <style scoped></style>

          图片

          二、启动服务

          1、先启动服务,前端由于跨域问题,所以我们需要把服务代理配置下,我们通过智能体帮我们处理。

          提示语:修改项目设置,根据当前终端的服务添加代理,并修改文件上传组件的请求地址。

          上下文:终端Terminal和文件上传组件

          图片

          配置修改:

          图片

          请求地址修改:

          图片

          现在整个调整就完成了

          图片

          2、启动项目并进行验证。如果你不知道项目怎么启动的话,这一步也可以通过智能体帮我们处理。

          提示语:启动当前项目

          图片

          3、以下是启动后的界面,只有了上传组件

          图片

          三、验证优化

          1、初步验证,功能都满足条件,接下来进行一些优化

          图片

          2、当前文件选择器会展示所有文件,选择后才会提示不允许,让智能体帮我们处理下

          提示语:修改组件配置,限制文件选择器可查看的文件类型

          上下文:选择AdvancedUpload.vue文件

          图片

          总结

          本次任务主要分为前期环境准备和功能实现两个阶段,两个阶段都还比较顺畅。

          1、node生成的文件服务一次性直接生成,由于没有对接口做过多要求,满足当前使用场景就直接采用了。

          2、前端工程的生成,也是智能体直接调用命令生成,自己在对项目进行了简化处理,删除了一部分代码。

          3、功能组件的生成,也是一次性就创建完成,只是对两个lint错误进行了调整处理,后面再对功能进行了一点优化。

          总体上来说,大大减少了开发工作量。

          不使用iFlyCode的话,要实现上面的功能和问题解决的话,用时需要1人日左右,而本次使用iFlyCode的智能体能力,总体用时只有2小时不到,提效70%以上。

          评论
          成就一亿技术人!
          拼手气红包6.0元
          还能输入1000个字符
           
          红包 添加红包
          表情包 插入表情
           条评论被折叠 查看
          添加红包

          请填写红包祝福语或标题

          红包个数最小为10个

          红包金额最低5元

          当前余额3.43前往充值 >
          需支付:10.00
          成就一亿技术人!
          领取后你会自动成为博主和红包主的粉丝 规则
          hope_wisdom
          发出的红包
          实付
          使用余额支付
          点击重新获取
          扫码支付
          钱包余额 0

          抵扣说明:

          1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
          2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

          余额充值