Luckysheet 内网部署教程:后端生成 Excel,前端只读预览
Luckysheet 内网部署教程后端生成 Excel前端只读预览一、场景说明在企业后台管理系统中常见需求是后端根据业务数据生成 Excel 报表前端直接从接口下载该文件并进行在线预览用户只能查看、不能编辑。典型场景包括财务报表生成与查阅数据报表导出与审批系统日志导出查看用户数据报表预览本文聚焦于内网部署场景所有资源均为本地化不依赖外网 CDN。后端使用Spring Boot EasyExcel生成.xlsx文件前端使用Luckysheet Luckyexcel进行只读预览。二、整体架构与数据流┌─────────┐ 请求导出 ┌─────────────┐ 生成Excel ┌─────────────┐ │ 前端 │ ──────────────────▶ │ 后端接口 │ ──────────────────▶ │ Excel文件 │ │ (Vue3) │ │ (SpringBoot)│ │ (.xlsx) │ └─────────┘ └─────────────┘ └─────────────┘ │ │ │ │ │◀─────────────────────────────────│ │ │ 返回文件流(Blob) │ │ │ │ │ 接收Blob并解析 │ │ │ 使用Luckyexcel转换为Luckysheet格式│ │ │ 只读渲染预览 │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────────┐ ┌─────────────┐ │ 用户 │ │ Luckysheet │ │ Luckyexcel │ │ 查看 │ │ 只读预览 │ │ 解析xlsx │ └─────────┘ └─────────────┘ └─────────────┘核心流程前端发起导出请求→ 调用后端接口后端生成 Excel 文件→ 使用 EasyExcel 或 Apache POI 将数据写入.xlsx以文件流形式返回前端接收 Blob 数据→ 将二进制数据转换为File对象Luckyexcel 解析→ 将.xlsx转换为 Luckysheet 可识别的 JSON 数据只读渲染→ 以allowEdit: false模式展示表格用户仅可查看三、后端Spring Boot 生成 Excel3.1 添加依赖!-- Maven 依赖 --dependencygroupIdcom.alibaba/groupIdartifactIdeasyexcel/artifactIdversion3.3.4/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencyEasyExcel 是阿里开源的 Excel 处理库性能优于 Apache POI适合大量数据导出场景 。3.2 定义导出数据实体// UserExportVO.javapackagecom.example.excel.vo;importcom.alibaba.excel.annotation.ExcelProperty;importlombok.Data;DatapublicclassUserExportVO{ExcelProperty(value用户ID,index0)privateLonguserId;ExcelProperty(value用户名,index1)privateStringuserName;ExcelProperty(value手机号,index2)privateStringphone;ExcelProperty(value注册时间,index3)privateStringregisterTime;}3.3 后端导出接口// ExcelExportController.javapackagecom.example.excel.controller;importcom.alibaba.excel.EasyExcel;importcom.example.excel.vo.UserExportVO;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.servlet.http.HttpServletResponse;importjava.io.IOException;importjava.net.URLEncoder;importjava.util.ArrayList;importjava.util.List;RestControllerRequestMapping(/excel)publicclassExcelExportController{GetMapping(/export)publicvoidexportUserList(HttpServletResponseresponse)throwsIOException{// 1. 模拟数据实际从数据库获取ListUserExportVOdataListgetMockData();// 2. 设置响应头response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet);response.setCharacterEncoding(utf-8);// 处理中文文件名乱码StringfileNameURLEncoder.encode(用户数据报表,UTF-8).replaceAll(\\,%20);response.setHeader(Content-disposition,attachment;filename*utf-8fileName.xlsx);// 3. 写入 Excel 到响应输出流EasyExcel.write(response.getOutputStream(),UserExportVO.class).sheet(用户信息).doWrite(dataList);}privateListUserExportVOgetMockData(){ListUserExportVOlistnewArrayList();for(inti1;i10;i){UserExportVOusernewUserExportVO();user.setUserId((long)i);user.setUserName(用户i);user.setPhone(188888888String.format(%02d,i));user.setRegisterTime(2026-07-String.format(%02d,i));list.add(user);}returnlist;}}后端返回文件流的关键配置Content-Type必须设置为application/vnd.openxmlformats-officedocument.spreadsheetml.sheetContent-Disposition用于告知浏览器下载文件名 。四、前端Excel 只读预览4.1 资源本地化内网部署将 Luckysheet 和 Luckyexcel 的静态资源下载到项目的public/luckysheet/目录下public/luckysheet/ ├── css/ │ └── luckysheet.css ├── plugins/ │ ├── css/ │ │ └── pluginsCss.css │ └── plugins.js ├── assets/ │ └── iconfont/ ├── luckyexcel.umd.js └── luckysheet.umd.js4.2 在index.html中引入资源!DOCTYPEhtmlhtmlhead!-- 样式顺序固定 --linkrelstylesheethref/luckysheet/plugins/css/pluginsCss.css/linkrelstylesheethref/luckysheet/plugins/plugins.css/linkrelstylesheethref/luckysheet/css/luckysheet.css/linkrelstylesheethref/luckysheet/assets/iconfont/iconfont.css/!-- 脚本顺序固定 --scriptsrc/luckysheet/plugins/plugins.js/scriptscriptsrc/luckysheet/luckysheet.umd.js/script/head/html4.3 创建ExcelPreview.vue组件template div classpreview-wrapper !-- 加载状态 -- div v-ifloading classloading-overlay span classloading-spinner⏳/span p{{ loadingText }}/p /div !-- 预览工具栏 -- div v-ifhasData classtoolbar span classfile-name {{ fileName }}/span span classsheet-count{{ sheetCount }} 个工作表/span button classbtn-download clickhandleDownload 下载原始文件/button button classbtn-clear clickhandleClear清空/button /div !-- 空状态 -- div v-if!hasData !loading classempty-state div classempty-icon/div h3暂无数据/h3 p点击下方按钮从后端获取报表/p button classbtn-load clickfetchExcel加载报表/button /div !-- 表格容器 -- div refcontainerRef classsheet-container/div /div /template script setup import { ref, onBeforeUnmount, nextTick } from vue; import axios from axios; const props defineProps({ apiUrl: { type: String, default: /excel/export // 后端接口地址 }, height: { type: String, default: 600px } }); const emit defineEmits([loaded, error, downloaded]); const containerRef ref(null); const loading ref(false); const loadingText ref(正在生成报表...); const hasData ref(false); const fileName ref(); const sheetCount ref(0); let instance null; let currentBlob null; // 存储原始文件 Blob供下载使用 // 销毁表格 function destroySheet() { if (instance) { try { instance.destroy(); } catch (e) {} instance null; } if (window.luckysheet window.luckysheet.destroy) { try { window.luckysheet.destroy(); } catch (e) {} } } // 只读渲染 function renderSheet(exportJson, name) { if (!exportJson.sheets || exportJson.sheets.length 0) { emit(error, new Error(没有有效的工作表)); return; } destroySheet(); nextTick(() { if (!containerRef.value) return; // 关键只读预览配置 instance window.luckysheet.create({ container: containerRef.value, data: exportJson.sheets, title: name || 未命名, lang: zh, // 只读核心配置 allowEdit: false, // 禁止编辑 showtoolbar: false, // 隐藏工具栏 showinfobar: false, // 隐藏信息栏 sheetFormulaBar: false, // 隐藏公式栏 enableAddRow: false, // 禁止增加行 enableAddCol: false, // 禁止增加列 showstatisticBar: false, // 隐藏统计栏 showsheetbarConfig: { add: false, // 禁止新增 Sheet menu: false, sheet: true // 保留切换标签 }, contextMenu: [ { text: 复制, onclick: () {} } ], // 禁止编辑快捷键 hook: { cellMousedown() { return false; } } }); hasData.value true; fileName.value name; sheetCount.value exportJson.sheets.length; loading.value false; emit(loaded, { data: exportJson, name }); }); } // 从后端获取 Excel async function fetchExcel() { loading.value true; loadingText.value 正在生成报表...; hasData.value false; try { const response await axios.get(props.apiUrl, { responseType: blob, timeout: 60000 }); // 检查响应类型 const contentType response.headers[content-type] || ; if (!contentType.includes(sheet) !contentType.includes(octet-stream)) { const text await response.data.text(); const error JSON.parse(text); throw new Error(error.message || 导出失败); } // 从 Content-Disposition 提取文件名 const disposition response.headers[content-disposition] || ; let name 报表.xlsx; const match disposition.match(/filename\*(?:UTF-8|utf-8)(.)/); if (match) { name decodeURIComponent(match[1]); } else { const simpleMatch disposition.match(/filename(.)/); if (simpleMatch) { name decodeURIComponent(simpleMatch[1].replace(//g, )); } } currentBlob response.data; loadingText.value 正在解析文件...; // 将 Blob 转换为 File 对象 const file new File([response.data], name, { type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet }); // 使用 Luckyexcel 解析 if (!window.LuckyExcel) { // 如果未全局引入动态加载 const script document.createElement(script); script.src /luckysheet/luckyexcel.umd.js; script.onload () parseFile(file, name); document.head.appendChild(script); } else { parseFile(file, name); } } catch (error) { console.error(加载失败:, error); loading.value false; emit(error, new Error(获取报表失败: error.message)); } } function parseFile(file, name) { window.LuckyExcel.transformExcelToLucky( file, (exportJson) renderSheet(exportJson, name), (err) { console.error(解析失败:, err); loading.value false; emit(error, new Error(文件解析失败: err.message)); } ); } // 下载原始 Excel 文件 function handleDownload() { if (!currentBlob) return; const link document.createElement(a); link.href URL.createObjectURL(currentBlob); link.download fileName.value || 报表.xlsx; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(link.href); emit(downloaded, fileName.value); } function handleClear() { destroySheet(); hasData.value false; fileName.value ; sheetCount.value 0; currentBlob null; if (containerRef.value) containerRef.value.innerHTML ; } // 暴露方法 defineExpose({ fetchExcel, handleClear, destroySheet, hasData }); onBeforeUnmount(() { destroySheet(); }); /script style scoped .preview-wrapper { position: relative; width: 100%; background: #fff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 12px rgba(0,0,0,0.08); } /* 加载遮罩 */ .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.85); display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 10; } .loading-spinner { font-size: 48px; animation: spin 1.5s linear infinite; } keyframes spin { 100% { transform: rotate(360deg); } } .loading-overlay p { margin-top: 16px; color: #666; font-size: 16px; } /* 空状态 */ .empty-state { padding: 80px 20px; text-align: center; background: #fafafa; } .empty-icon { font-size: 64px; margin-bottom: 16px; } .empty-state h3 { font-size: 20px; color: #333; margin-bottom: 8px; } .empty-state p { color: #999; font-size: 14px; margin-bottom: 24px; } .btn-load { padding: 10px 32px; background: linear-gradient(135deg, #667eea, #764ba2); color: #fff; border: none; border-radius: 6px; font-size: 15px; cursor: pointer; transition: 0.3s; } .btn-load:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(102,126,234,0.4); } /* 工具栏 */ .toolbar { display: flex; align-items: center; gap: 16px; padding: 12px 20px; background: #fafafa; border-bottom: 1px solid #e8e8e8; font-size: 14px; color: #333; flex-wrap: wrap; } .file-name { font-weight: 500; color: #333; } .sheet-count { color: #999; font-size: 13px; } .toolbar .btn-download, .toolbar .btn-clear { margin-left: auto; padding: 4px 16px; border: 1px solid #d9d9d9; border-radius: 4px; background: #fff; cursor: pointer; font-size: 13px; color: #555; transition: 0.2s; } .toolbar .btn-download { margin-left: auto; } .toolbar .btn-download:hover { border-color: #667eea; color: #667eea; } .toolbar .btn-clear:hover { border-color: #ff4d4f; color: #ff4d4f; } .sheet-container { width: 100%; height: v-bind(height); min-height: 400px; background: #fff; } /style4.4 在页面中使用template div classpage h1 数据报表预览/h1 p classsubtitle报表由后端生成前端仅可查看/p ExcelPreview refpreviewRef api-url/excel/export height650px loadedonLoaded erroronError downloadedonDownloaded / div v-iferrorMsg classerror-message ⚠️ {{ errorMsg }} button clickerrorMsg classclose-btn×/button /div /div /template script setup import { ref } from vue; import ExcelPreview from /components/ExcelPreview.vue; const previewRef ref(null); const errorMsg ref(); function onLoaded(data) { console.log(✅ 报表加载成功:, data); errorMsg.value ; } function onError(err) { errorMsg.value err.message; console.error(❌ 加载失败:, err); } function onDownloaded(name) { console.log( 已下载:, name); } // 也可通过代码触发加载 function loadReport() { previewRef.value?.fetchExcel(); } /script style scoped .page { max-width: 1400px; margin: 0 auto; padding: 20px; } .page h1 { font-size: 24px; margin-bottom: 4px; } .subtitle { color: #999; font-size: 14px; margin-bottom: 20px; } .error-message { margin-top: 16px; padding: 12px 16px; background: #fff2f0; border: 1px solid #ffccc7; border-radius: 6px; color: #ff4d4f; display: flex; justify-content: space-between; align-items: center; } .close-btn { background: none; border: none; font-size: 20px; cursor: pointer; color: #999; } .close-btn:hover { color: #ff4d4f; } /style五、接口规范与配置详解5.1 后端导出接口规范项目说明请求方式GETURL/excel/export响应类型application/vnd.openxmlformats-officedocument.spreadsheetml.sheet响应头Content-Disposition: attachment;filename*utf-8报表名称.xlsx响应体Excel 文件二进制流5.2 只读预览核心配置配置项值作用allowEditfalse禁止所有编辑操作showtoolbarfalse隐藏顶部功能栏showinfobarfalse隐藏信息栏sheetFormulaBarfalse隐藏公式输入栏enableAddRow/enableAddColfalse禁止增删行列showsheetbarConfig.addfalse禁止新增工作表hook.cellMousedown() false禁止单元格点击编辑六、常见问题与解决方案6.1 文件名中文乱码问题下载的文件名显示为乱码。解决使用URLEncoder.encode()编码并替换为%20。StringfileNameURLEncoder.encode(用户报表,UTF-8).replaceAll(\\,%20);response.setHeader(Content-disposition,attachment;filename*utf-8fileName.xlsx);6.2 前端解析 Blob 失败问题LuckyExcel.transformExcelToLucky报错提示不是有效 xlsx。解决确保后端返回的 Content-Type 正确前端请求时添加responseType: blob。constresponseawaitaxios.get(apiUrl,{responseType:blob// 关键});6.3 大文件导出超时问题数据量大时请求超过默认超时时间。解决增加前端超时配置后端使用 EasyExcel 的流式写入。// 前端constresponseawaitaxios.get(apiUrl,{responseType:blob,timeout:120000// 120秒});6.4 内网资源加载失败问题浏览器控制台报 404找不到 CSS 或 JS 文件。解决确认资源已放入public/luckysheet/目录确认index.html中路径正确以/luckysheet/开头检查目录结构是否完整含assets/iconfont/字体文件七、总结本方案实现了后端生成 Excel → 前端只读预览的完整内网部署流程层级技术选型职责后端Spring Boot EasyExcel根据业务数据生成.xlsx文件流前端预览Luckysheet只读展示 Excel 内容文件解析Luckyexcel将 Blob 转换为 Luckysheet 数据格式传输方式REST API Blob文件流下载与前端解析核心要点后端返回文件流前端通过responseType: blob接收Luckyexcel 解析 Blob转为 Luckysheet 可识别的 JSON只读预览模式allowEdit: false是核心配置所有资源本地化适应内网部署场景这样就完整实现了后端渲染生成 Excel前端下载后只做预览的需求。

相关新闻

一键备份QQ空间:GetQzonehistory终极记忆守护者

一键备份QQ空间:GetQzonehistory终极记忆守护者

一键备份QQ空间:GetQzonehistory终极记忆守护者 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾担心那些珍贵的QQ空间说说会随着时间流逝而消失?GetQzon…

2026/7/29 21:25:47阅读更多 →
Instafel Updater使用教程:自动更新Instagram Alpha的最佳实践

Instafel Updater使用教程:自动更新Instagram Alpha的最佳实践

Instafel Updater使用教程:自动更新Instagram Alpha的最佳实践 【免费下载链接】instafel_release_arm64-v8a Instafel provides fast & up-to-date Instagram Alpha experience for everyone! 项目地址: https://gitcode.com/gh_mirrors/in/instafel_release…

2026/7/29 21:25:47阅读更多 →
24节气计算终极指南:cnlunar如何突破传统算法瓶颈?

24节气计算终极指南:cnlunar如何突破传统算法瓶颈?

24节气计算终极指南:cnlunar如何突破传统算法瓶颈? 【免费下载链接】cnlunar 农历,中国农历历法项目,无需数据库环境,以《钦定协纪辨方书》为核心的python3 农历、黄历、二十四节气、节假日、星次、每日凶煞、每日值神…

2026/7/29 21:25:47阅读更多 →
Soar:革命性Linux包管理器横空出世!轻量级设计如何让静态二进制文件安装提速10倍?

Soar:革命性Linux包管理器横空出世!轻量级设计如何让静态二进制文件安装提速10倍?

Soar:革命性Linux包管理器横空出世!轻量级设计如何让静态二进制文件安装提速10倍? 【免费下载链接】soar A fast, modern package manager for Static Binaries, Portable Formats (AppImage|AppBundle|FlatImage|Runimage) & More [main…

2026/7/29 22:38:36阅读更多 →
【C语言】《C 语言库函数源码级别的理解:模拟实现字符串与内存操作全系列(含最常用12个模拟实现)》

【C语言】《C 语言库函数源码级别的理解:模拟实现字符串与内存操作全系列(含最常用12个模拟实现)》

字符函数和字符串函数 引言 C语言开发过程中,最频繁的操作之一就是处理字符串。不管是用户输入、文件读取、还是网络数据解析,都绕不开各种字符串操作。C语言中对字符和字符串的处理非常频繁,但C语言本身没有字符串类型,字符串通…

2026/7/29 22:38:36阅读更多 →
Crow框架终极指南:构建高性能C++微服务架构的完整解决方案

Crow框架终极指南:构建高性能C++微服务架构的完整解决方案

Crow框架终极指南:构建高性能C微服务架构的完整解决方案 【免费下载链接】crow Crow is very fast and easy to use C micro web framework (inspired by Python Flask) 项目地址: https://gitcode.com/gh_mirrors/cr/crow 在当今高并发、低延迟的应用场景中…

2026/7/29 22:38:36阅读更多 →
问题是结果的“价值坐标系”

问题是结果的“价值坐标系”

一个结果有没有价值,不取决于它本身多复杂、多漂亮,而取决于它解决了什么问题、满足了什么需求、改变了什么现实。问题,决定了结果应该被如何衡量。第一层:什么叫“价值坐标系”? 坐标系的作用: 是确定一个…

2026/7/29 22:38:36阅读更多 →
没有问题,结果就失去意义

没有问题,结果就失去意义

结果本身不是价值,结果只是解决某个问题之后留下的证明。脱离问题的结果,往往只是形式,而不是价值。这句话揭示了一个现实规律:价值不是来自“做出了什么”,而是来自“为什么做、解决了什么、改变了什么”。第一层&…

2026/7/29 22:38:36阅读更多 →
为什么选择libipt?揭秘Intel处理器追踪技术的强大优势

为什么选择libipt?揭秘Intel处理器追踪技术的强大优势

为什么选择libipt?揭秘Intel处理器追踪技术的强大优势 【免费下载链接】libipt libipt - an Intel(R) Processor Trace decoder library 项目地址: https://gitcode.com/gh_mirrors/li/libipt libipt是一款专业的Intel处理器追踪(Intel Processor…

2026/7/29 22:36:36阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/29 4:31:51阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →