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-uploadref="uploadRef"v-model:file-list="fileList"class="upload-demo"dragmultiple: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-buttonv-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: stringpercentage?: numberstatus?: 'success' | 'exception' | 'normal'size: numberuid: stringraw: Filecontroller?: 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 < 1024) return `${size} B`if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`if (size < 1024 * 1024 * 1024) return `${(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(0, 10)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 = controllerawait 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 {width: 100%;max-width: 800px;margin: 0auto;}.progress-container {margin-top: 20px;}.file-progress {margin-bottom: 15px;}.file-info {margin-bottom: 5px;font-size: 14px;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%以上。
1741

被折叠的 条评论
为什么被折叠?



