新闻详情

新闻详情

首页 / 资讯中心 / 详情

CKEDITOR从Word粘贴图片并上传的完整解决方案

发布时间:2026/9/10 3:23:13来源:尧图网络
CKEDITOR从Word粘贴图片并上传的完整解决方案
做OA系统开发这些年几乎每隔一段时间就会有人问我同一个问题从Word里复制一张图片粘到CKEDITOR编辑器里怎么就那么费劲要么显示一个红叉要么整个图直接消失要么提交的时候表单里拖着一长串base64字符串把后台接口都干超时了。这个需求听起来很小真正动手做的时候才发现它牵扯到剪贴板数据结构、浏览器粘贴事件、图片上传服务、富文本内容回插整整一条链路。我在公司OA系统的公文管理模块里完整落地过这个“从Word图片粘贴到CKEDITOR的示例化方案”踩过不少坑也积累了一些可以直接抄作业的代码和思路今天就一次性整理出来。1. 先搞清楚Word粘贴图片到底难在哪1.1 剪贴板里的数据不是一张图那么简单很多人在做图片粘贴功能时第一反应是“我监听paste事件拿到图片文件上传搞定”。真做起来发现拿到的数据根本不是你想象的那么规整。当你在Word里CtrlC复制一张图片时写到系统剪贴板里的不是单一文件而是一份多格式的复合数据。它可能同时包含HTML片段、纯文本、RTF格式、位图数据还有Word特有的WMF/EMF矢量格式。浏览器在触发paste事件时会把这份复合数据暴露在clipboardData对象里。Chrome和Firefox下你可以通过event.clipboardData.items遍历每一项每项有kind和type两个属性。kind为file时就说明这一项是一个文件类型的数据你通常能在type里看到image/png、image/jpeg、image/bmp这类值。麻烦在于Word图片在Windows环境下很可能会附带image/wmf或image/emf类型而这两个格式浏览器根本不认识。这就是第一道坎你以为用户粘贴的是“一张图片”实际上他粘贴的是一堆格式的混合体。你必须自己判断哪一份数据是浏览器能处理的哪一份只能忽略。1.2 CKEDITOR默认行为为什么救不了你CKEDITOR作为一个老牌富文本编辑器本身提供了基础的粘贴过滤机制。默认情况下从Word复制内容粘贴进来文字、表格样式会被它的pasteFilter清理和转换一遍图片如果带的是有效网络URL可以正常显示。但问题恰恰在于从Word复制到浏览器的图片在Chrome里通常不会带有可访问的远程URL而是以Blob对象或本地路径形式存在。如果你什么都不做直接粘贴大概率看到两种结果一种是图片直接变成叉号或者灰块因为浏览器尝试渲染一个临时本地路径但这个路径对网页来说根本不合法另一种是图片内容被转成了超长的data:image/png;base64,xxxxx插入的时候编辑器能显示等到你提交整个表单后台拿到这个超大字段转JSON、存数据库、再回显到页面每一环都可能出问题。CKEDITOR也不会主动帮你去上传图片。它的核心是编辑能力不是资源存储能力。所以想让Word图片粘贴后真正“示例化”——也就是变成服务器上一个可访问的图片文件并且在编辑器里稳定展示必须自己做一套粘贴处理逻辑。1.3 示例化的目标到底是什么在动手写代码之前我习惯先把目标拆清楚。这里的“示例化”简单说就是把剪贴板里的本地图片数据转成线上可访问的图片文件再把对应的URL回插到编辑器里让最终保存到数据库的富文本内容里是一串干净规范的img srchttps://...而不是一堆base64垃圾或者本地无效路径。拆出来就三个动作提取图片文件、上传文件到服务器、把返回的URL写回编辑器的光标位置。听起来很暴力但每步都有细节后面逐个讲。2. 整体方案选型三条技术路线怎么取舍2.1 方案A粘贴即上传回插远程URL这个方案的核心是在CKEDITOR的paste事件里拦截图片数据取到File对象后立刻通过XMLHttpRequest或fetch上传到服务器服务器返回图片路径前端再把路径拼接成img标签插入到当前光标位置。用户看到的效果是粘贴图片先占个位过几百毫秒图片加载出来随后正常保存。这条路线的好处是编辑器内容里永远只有URL不携带大量二进制数据提交速度快数据库干净且图片上传后可以复用你OA系统里已有的附件管理、权限控制、CDN加速等能力。缺点是要写的代码稍微多得处理异步顺序和失败回滚。2.2 方案Bbase64直接入编辑器这是最偷懒的路线监听粘贴把图片转成base64字符串直接insertHtml塞进去。当时测试环境里试了小图标、小截图确实能用几十KB的base64插入编辑器后视觉上没有任何问题。但只要图片稍微大一点比如Word里复制一张1MB的截图粘贴后内容区里可能出现四五百万字符的base64编辑器的操作流畅度立刻下降。更严重的是OA系统表单提交到后端很多框架默认对请求体大小有限制Tomcat默认的maxPostSize可能只有2MB一张图就直接把整个表单提交打挂。后续即使调大限制存数据库、列表页回显、导出PDF每一步都可能成为性能瓶颈。所以方案B我只建议用在个人工具或者内网临时系统生产环境OA系统不建议。2.3 方案C依赖第三方插件CKEDITOR社区里有过一些粘贴图片插件比如pasteimage、imagepaste之类的封装了粘贴上传逻辑。但我在实际项目里试用下来有两个问题一是老版本CKEDITOR我们OA用的4.x和这些插件的兼容性时好时坏二是插件默认上传接口、字段名、返回值格式往往跟公司内部的后端规范对不上配置起来反而要花更多时间去读插件源码。如果你们OA系统用的是新版CKEDITOR 5官方其实有更好的内置上传能力但很多老企业OA系统还停留在CKEditor 4时代直接升级编辑器成本太高所以自己动手写一套反而最可控。2.4 为什么最终选了方案A我们最终确定了方案A核心原因有三点第一贴合OA系统的真实使用场景。办公系统里粘贴的图片多数是业务截图、公文附件图、合同扫描件图片尺寸通常不小base64根本不现实。第二可以复用公司现有的文件上传服务和安全校验机制不用为编辑器单独开一套存储。第三代码粒度可控出问题能监控、能排查、能回滚这在企业项目里非常重要。3. 核心代码实现从粘贴事件到图片回插3.1 第一步监听粘贴事件并提取图片文件不管前端框架是什么第一步都是拿到编辑器实例然后绑定paste事件。我以CKEDITOR 4.x为例因为大多数OA系统用的就是这个版本。CKEDITOR.replace(content, { // 其他配置 }); var editor CKEDITOR.instances.content; editor.on(paste, function(e) { var clipboardData e.data e.data.$ ? e.data.$.clipboardData : null; if (!clipboardData) { return; } var items clipboardData.items; if (!items) { return; } var imageFiles []; for (var i 0; i items.length; i) { var item items[i]; if (item.kind file) { var file item.getAsFile(); if (file file.type file.type.indexOf(image/) 0) { imageFiles.push(file); } } } if (imageFiles.length 0) { e.data.preventDefault(); handlePastedImages(editor, imageFiles); } });这里有几个关键点需要解释。e.data.$是CKEDITOR包装的粘贴事件里暴露原生事件对象的入口很多人只盯着e.data.dataTransfer但实际上原生clipboardData在微信内置浏览器、老Edge等场景下才是兼容性更好的来源。item.getAsFile()在Chrome和Firefox下都能拿到File对象拿到之后判断file.type前缀是否为image/这样可以过滤掉剪贴板里那些不相关的文本文件或者其他类型数据。注意我调用了e.data.preventDefault()目的是阻止CKEDITOR默认的粘贴行为。如果不阻止编辑器又会把原始数据里的base64图片插入进来你就拿到两份图片了。这份代码还有一个隐藏的兼容点在Safari和旧版浏览器里clipboardData.items可能不存在这时候需要走clipboardData.getData(text/html)这条分支从HTML字符串里提取img标签的base64数据再转换上传。这一段逻辑我放在后面的兼容性章节详细展开。3.2 第二步可复用的图片上传封装拿到File数组之后接下来就是上传。上传接口我建议封装成一个独立函数不要耦合在粘贴逻辑里这样以后不管是粘贴上传还是手动选择图片上传都能复用同一套逻辑。function uploadImage(file) { return new Promise(function(resolve, reject) { var formData new FormData(); formData.append(file, file, file.name || (paste_ Date.now() .png)); var xhr new XMLHttpRequest(); xhr.open(POST, /api/oa/file/upload, true); // 如果OA系统有登录token校验这里带上 xhr.setRequestHeader(Authorization, localStorage.getItem(oa_token) || ); xhr.onreadystatechange function() { if (xhr.readyState 4) { if (xhr.status 200 xhr.status 300) { try { var res JSON.parse(xhr.responseText); if (res.code 0 res.data res.data.url) { resolve(res.data); } else { reject(new Error(res.msg || upload failed)); } } catch (err) { reject(err); } } else { reject(new Error(HTTP xhr.status)); } } }; xhr.onerror function() { reject(new Error(network error)); }; // 注意上传大图时可能会超时OA系统网络慢的情况下要适当延长 xhr.timeout 30000; xhr.ontimeout function() { reject(new Error(upload timeout)); }; xhr.send(formData); }); }这段代码有几个值得注意的细节。第一formData.append(file, file, file.name || paste_xxx.png)为什么一定要传第三个参数文件名因为很多后端框架尤其是Java的Spring MVC在接收MultipartFile时如果前端不提供文件名部分版本会直接报错或者把文件名置为null后续保存文件时就会踩坑。我从粘贴事件里拿到的File对象在Chrome里通常有类似image.png这样的名字但有些场景下name为空所以必须给一个默认名。第二设置超时时间。OA系统内网环境通常还行但如果你们的服务器在异地机房或者用户网络状态差一张几MB的Word粘贴图上传可能要好几秒30秒超时是比较稳妥的配置。第三请求头里的Authorization字段是示例实际项目按你们公司的认证方式调整。如果你用jQuery或者axios写法略有不同但思路一样。3.3 第三步上传成功后把图片回插到编辑器上传只是前半程真正决定用户体验的是后半程的回插。这里最忌讳的操作是简单粗暴地拼接HTML字符串然后insertHtml因为一旦图片里包含特殊字符或者上传返回的URL带了参数拼接出来的字符串可能被编辑器二次解析出问题。更稳妥的做法是创建DOM元素再插入。function handlePastedImages(editor, imageFiles) { var pendingCount imageFiles.length; if (pendingCount 0) return; imageFiles.forEach(function(file, index) { uploadImage(file) .then(function(data) { var imgUrl data.url; // 兼容相对路径和绝对路径 if (imgUrl.indexOf(http) -1 imgUrl.indexOf(/) ! 0) { imgUrl / imgUrl; } var imgElement CKEDITOR.dom.element.createFromHtml( img src imgUrl stylemax-width:100%; / ); // 多图粘贴时需要按原顺序插入不能靠forEach的完成顺序 insertImageByIndex(editor, index, imgElement); }) .catch(function(err) { console.error(图片上传失败, err); alert(图片上传失败请重试或插入本地图片); }) .finally(function() { pendingCount--; if (pendingCount 0) { // 全部上传完成可以做一些收尾动作比如恢复编辑 } }); }); }这里最关键的坑在于多图顺序。用户从Word里复制两张图for循环里两个uploadImage同时发出可能第二张图的小文件先返回如果直接用editor.insertElement()插入图片顺序就反了。所以我在代码里保留了一个index参数所有图片上传完成后按index排序再依次插入。排序插入的实现可以用一个小小的辅助函数把待插入的图片暂存到一个数组等全部完成再一次性插入或者按index做延迟插入。var pendingImages []; function insertImageByIndex(editor, index, imgElement) { pendingImages.push({ index: index, element: imgElement }); // 在当前实现里我们等所有请求都结束之后再统一处理 // 更简单的方式每次push完都检查是否已全部到达 if (pendingImages.length totalCount) { pendingImages.sort(function(a, b) { return a.index - b.index; }); pendingImages.forEach(function(item) { editor.insertElement(item.element); }); pendingImages []; } }注意这个简单的实现要求每个索引只允许一个元素且调用insertImageByIndex的次数必须等于totalCount。如果你在实现里混入了其他插入逻辑需要调整判完成的条件。还有一个细节插入图片时加上stylemax-width:100%保证超大图片不会把编辑器撑爆页面布局也不会被撑破。OA系统里用户粘贴的截图经常是1920分辨率不加这个限制的话编辑区和预览区都会惨不忍睹。3.4 第四步后端上传接口示例前端写得再华丽后端接口不配合也白搭。我以Java Spring Boot为例给一个最基础的上传接口。绝大多数OA系统的后端都是Java技术栈接口签名也大同小异。PostMapping(/api/oa/file/upload) ResponseBody public Result uploadFile(RequestParam(file) MultipartFile file, HttpServletRequest request) { if (file null || file.isEmpty()) { return Result.error(文件不能为空); } String originalFilename file.getOriginalFilename(); String ext StringUtils.getFilenameExtension(originalFilename); // 只允许图片类型防止用户上传恶意文件 if (!Arrays.asList(jpg, jpeg, png, gif, bmp, webp) .contains(ext.toLowerCase())) { return Result.error(仅支持图片格式); } // 限制文件大小比如最大10MB if (file.getSize() 10 * 1024 * 1024) { return Result.error(图片不能超过10MB); } try { String relativePath uploadService.store(file); // 构建可访问的URL这里用相对路径还是绝对路径需要跟前端约定好 String url /upload/ relativePath; // 如果是前后端分离部署需要拼接完整域名 // String url request.getScheme() :// request.getServerName() // : request.getServerPort() /upload/ relativePath; return Result.success(ImmutableMap.of(url, url)); } catch (Exception e) { log.error(上传失败, e); return Result.error(上传失败 e.getMessage()); } }后端这里有两个点值得强调。一个是文件类型白名单校验不能信任前端传过来的文件类型因为攻击者可以伪造multipart内容白名单校验主要靠扩展名和文件头魔数双重校验生产环境建议至少做一层魔数校验。另一个是返回URL的约定我见过很多前端后端因为相对路径、绝对路径的问题来回扯皮所以在开发前就需要和前端对齐返回的url是相对路径如/upload/xxx.png还是完整路径如https://cdn.domain.com/upload/xxx.png。我自己更推荐返回完整可访问URL因为OA系统往往有多个域名入口纯相对路径容易在代理环境下拼错前缀。4. 多图并发、顺序控制和格式过滤4.1 多图片粘贴的顺序保证前面代码里已经提到了顺序问题但实际场景比想象中更复杂。用户可能一次性从Word复制了三张图加两段文字粘贴过来后文字和图片在剪贴板里的顺序需要被还原。因为我们的方案是拦截整个粘贴事件只提取图片文件然后异步上传而文字内容仍然走CKEDITOR默认的粘贴逻辑所以文字可能先于图片出现在编辑器里导致最终内容的排版顺序跟用户Word里的不一致。解决思路有两种。一种是完全接管粘贴事件把图片和文字都拿过来自己拼好顺序后再整体插入编辑器。这种控制度最高但实现难度也高因为要把Word的HTML内容做深度清洗CKEDITOR官方做了十几年过滤器自己再造轮子不现实。另一种是我采用的折中方案在paste事件里先不阻止默认行为让CKEDITOR先把文字和图片的HTML插入编辑器然后我们再遍历编辑器内容找到那些src为base64或本地路径的img标签提取出来上传上传成功后再把对应的img标签src替换成远程URL。这个方案能天然保证顺序因为图片本来就已经在正确的位置了我们做的只是“替换”。第二种方案的代码思路更清晰editor.on(paste, function(e) { // 不preventDefault让CKEDITOR先把内容插进来 // 等编辑器的DOM更新之后再扫描img标签 setTimeout(function() { var images editor.document.find(img).toArray(); images.forEach(function(img) { var src img.getAttribute(src) || ; if (src.indexOf(data:) 0) { uploadBase64Image(editor, img, src); } else if (src.indexOf(file://) 0) { // 部分浏览器会把本地图片路径暴露成file://这种基本无法上传 // 只能提示用户重新选择图片 img.remove(); alert(检测到本地图片请使用图片上传按钮重新插入); } }); }, 0); });这种方案有个小问题就是用户编辑过程中编辑器里其他已存在的图片也可能被扫描到并重复上传。所以扫描时一定要加一个标记判断比如img标签上带有>function compressImage(file, maxWidth, quality) { return new Promise(function(resolve) { var reader new FileReader(); reader.onload function(e) { var img new Image(); img.onload function() { var scale img.width maxWidth ? maxWidth / img.width : 1; var canvas document.createElement(canvas); canvas.width Math.round(img.width * scale); canvas.height Math.round(img.height * scale); var ctx canvas.getContext(2d); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); canvas.toBlob(function(blob) { resolve(blob); }, image/jpeg, quality); }; img.src e.target.result; }; reader.readAsDataURL(file); }); }这个函数在图片小于阈值时也会正常输出只是scale为1。实际使用中建议对1MB的图片执行压缩压缩后体积能减少百分之五六十上传更快编辑器也更流畅。压缩后的图片文件没有原始文件名所以调用uploadImage时要注意传一个合法的默认文件名比如compressed_12345.jpg。这里还需要注意canvas和图片加载的跨域问题。如果剪贴板里的图片本身来自其他域名canvas.toBlob可能因为污染canvas而抛错。好在粘贴进来的图片基本都是本地文件不涉及跨域但如果你们OA系统允许用户从浏览器里直接拖拽跨域图片进来压缩逻辑就要小心。5. 实战中遇到的那些坑排查与解决方案5.1 常见问题速查表这里整理一份我在项目交付、维护过程中遇到的高频问题对照表按优先级排序列了出来。问题现象可能原因解决方案粘贴图片后编辑器里什么都没有控制台无报错过滤条件把WMF/EMF或type为空的File丢掉了放宽过滤条件检测到image类型但getAsFile取不到时退回提取text/html图片显示但保存后刷新就没了src是base64或本地file协议没走上传逻辑用扫描img标签替换src的方案确保所有本地图片都被上传并替换多张图片粘贴后顺序错乱异步上传的完成顺序跟图片顺序不一致用index标记全部完成后按index排序再插入或改用扫描替换方案图片上传成功但编辑器里还是叉号服务器返回的相对路径被前端拼接错后端返回完整可访问URL前端处理时兼容http开头和/开头点击粘贴后页面卡死数秒大图在粘贴瞬间触发了base64转换增加压缩环节限制图片最大宽度和体积某些用户反馈在Word里复制截图粘贴无效用户电脑上Office版本生成的剪贴板格式特殊提示用户通过编辑器自带图片上传按钮插入或引导先粘贴到画图工具另存上传接口报400FormData没带文件名或后端token校验失败给append传第三个参数默认文件名检查Authorization头5.2 案例复盘图片回显404有一次部署到测试环境粘贴上传都正常编辑内容也能保存但刷新页面后图片全部404。查了半天发现后端返回的url是/upload/2024/03/xxx.png而OA系统的Web应用部署在/oa这个context path下前端页面访问的富文本回显地址却是相对当前的页面路径去解析的。编辑页在/oa/notice/edit所以图片地址被解析成了/oa/notice/upload/2024/03/xxx.png自然404。这个问题的本质是前端把相对路径当成当前页面相对路径去解析了。最终我要求后端接口统一返回全路径即http://host:port/upload/...并且让CKEDITOR在处理回显时如果img的src是相对路径就自动拼上服务器配置的静态资源前缀。这个修复上线后再也没有出现过回显404的情况。5.3 案例复盘粘贴后整个页面卡死有个用户反馈从Word复制一张系统截图后粘贴到编辑器页面整个浏览器标签页卡死只能强制关闭。排查后确认那张截图尺寸是4K分辨率粘贴时浏览器在把图片转base64插入编辑器导致主线程被阻塞了好几秒然后CKEDITOR内部再对这个超大字符串做过滤清洗又卡了一波。这个案例给我一个教训不要把图片转base64这种重操作放在主线程里做。后来我在粘贴事件里不再把图片转成dataURL而是直接用File对象上传上传成功后只插入一个远程URL整个过程中根本没有大字符串产生卡顿问题彻底解决。如果你的场景里必须要base64比如某些旧浏览器不支持FormData上传那至少要用Web Worker来做base64编码避免阻塞UI线程。5.4 兼容性老版本IE和国产浏览器很多OA系统用户还在用Windows 7自带的IE8、IE9或者360浏览器的兼容模式。说实话这类环境想完美支持Word图片自动粘贴上传基本不可能。IE不支持clipboardData.items也不支持FormData上传文件开发成本极高且收益几乎为零。我的做法是在页面初始化时做环境检测如果识别到老IE内核就直接禁用富文本编辑器里的粘贴快捷键改为提示用户使用Chrome内核浏览器访问OA系统。这个方案对业务影响最小也省去了一堆无谓的兼容代码。如果你想兼顾国产浏览器的极速模式一般是Chrome内核那上面的代码是可以直接跑通的。只有兼容模式IE内核才需要特殊处理。6. 结尾一点个人的落地体会这个功能做完我在公司内部做了一次分享很多人问我“能不能直接抄代码”。代码当然可以抄但我更想说的是动手之前先花半天时间把你项目里的浏览器兼容矩阵、后端上传接口规范、编辑器版本摸清楚。这三件事不确认代码写得再漂亮落地的时候大概率还是要返工。尤其是CKEDITOR的版本差异4.x和5.x的事件模型完全不同网上搜到的很多教程都是基于5.x的直接套到老项目里根本跑不起来。如果你也正在做类似的功能建议你先从第3章那段最简单的粘贴提取代码开始跑通单图上传再逐步加入多图顺序、压缩、格式过滤这些增强逻辑。一步一步来效果比一口气全写完再调试要好得多。这个功能后续还可以扩展类似“粘贴时自动OCR识别图片里的文字”“粘贴时自动压缩并添加水印”这些玩法等你们基础版稳定之后可以有更多想象空间。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Java网络编程新选择:轻量AIO框架smart-socket的实战解析 2026/9/10 4:08:19

Java网络编程新选择:轻量AIO框架smart-socket的实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
永磁同步电机对拖实验台:算法落地的物理验证平台 2026/9/10 4:08:19

永磁同步电机对拖实验台:算法落地的物理验证平台

1. 这不是普通电机台架,而是一套“算法显微镜”——永磁同步电机对拖控制实验台到底在验证什么?你手头那台标着“永磁同步电机对拖控制实验台”的设备,绝不是两台电机面对面转起来那么简单。它本质上是一台高精度、可复现、全链路闭环的机电系…

阅读更多 →
同城社区家政系统开发,会员预约功能开发 2026/9/10 4:08:19

同城社区家政系统开发,会员预约功能开发

同城社区家政系统开发,会员预约功能开发同城社区家政服务的核心竞争力,除了上门服务的质量与效率,更在于用户留存与复购能力。当下多数同城家政服务商,基础的在线预约、工单派单功能已经普及,但会员预约体系普遍存在功…

阅读更多 →
CANN/ge获取告警信息V3 2026/9/10 4:08:19

CANN/ge获取告警信息V3

GEGetWarningMsgV3 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorF…

阅读更多 →
PIC24F16KA101-I/SS采购避坑指南:封装、工艺与低功耗实测验证 2026/9/10 4:08:19

PIC24F16KA101-I/SS采购避坑指南:封装、工艺与低功耗实测验证

1. 为什么说 PIC24F16KA101-I/SS 是“小脚数低功耗 MCU 采购里最容易翻车的型号之一” 你手头正赶一个电池供电的便携式传感器节点项目,主控芯片选型卡在最后一步:要够小、够省电、够便宜,还要能快速量产。这时候工程师群里有人甩出一句&…

阅读更多 →
CANN/ge注册回调函数API 2026/9/10 4:05:19

CANN/ge注册回调函数API

RegisterCallBackFunc 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、Tens…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞