为啥要搞这个
作为后端程序员,平时喜欢写技术博客。前阵子又把那个好久没管的公众号捡起来了。
写东西嘛,总得有个趁手的编辑器。自己也撸过一个 Markdown 编辑器,勉强能用,但界面交互不好,加个功能还得跟 CSS 死磕半天,效率贼低。后来在 GitHub 上发现了xiaobox/mdeditor,用了一下就爱上了:主题好看、操作流畅、能一键复制公众号格式、所见即所得——这不就是我想要的吗?
现在 AI 正火,对创作者提效也是很有帮助,普通 MD 工具经常得在编辑器、ChatGPT、标题生成器、配图工具之间切来切去,写作节奏全被打乱了。
所以我就想:能不能把这些 AI 能力直接塞进编辑器里? 咱就是搞这个的啊,写个 API 转发那是老本行。说干就干,基于原项目 fork 出来做了扩展,就成了现在这个项目。
项目地址:sqking-coke/mdeditor-ai
都有啥功能
在原版 Markdown 编辑器的基础上,我加了四个 AI 功能,全部通过顶部菜单里的「AI 助手」来用:
1. AI 润色
选中一段文字 → 点「AI 润色」→ 输入你的要求(比如“更正式”、“更简洁”)→ AI 给你结果 → 一键替换原文。

2. AI 生成标题
AI 自动读完你的全文,给你 5 个标题备选。点一下就直接插到文章开头。

3. AI 生成摘要
自动提取文章的核心内容,给你 2-3 句话的摘要,可以一键插到文章末尾。

4. AI 生成配图
输入图片描述 → AI 帮你生图 → 预览 → 插入 Markdown 图片语法。

咋设计的
为什么非要有后端?
你可能会问:前端直接调 AI API 不就行了吗?
行是行,但不安全。在浏览器里调用 API 会暴露你的 API Key。就算用了环境变量,打包之后 Key 还是能在前端代码里找到。
所以我用了「前端 → Java 后端 → AI 服务」的代理模式:
●●●code 浏览器 (Vue 3) Java 后端 (Spring Boot) AI 服务 │ │ │ │ POST /api/ai/polish │ │ │ Header: X-Text-Api-Key │ │ │ Body: { content, model } │ │ │ ──────────────────────────────► │ POST DeepSeek API │ │ │ Authorization: Bearer │ │ │ ──────────────────────► │ │ │ │ │ │ ◄────────────────────── │ │ ◄────────────────────────────── │ 返回润色结果 │
API Key 怎么管
核心原则:后端不存、不记、不留任何用户的密钥。
●用户在前端设置面板自己填 API Key
●Key 存在浏览器的localStorage里
●每次请求通过 HTTP Header 传给后端
●后端只做转发,用完就扔
模型选择也交给用户:文本模型名、图片模型名都在设置面板里自己配,后端啥都不用管。

技术选型
前端:Vue 3 组合式 API
所有 AI 功能的状态通过useAI()这个 composable 集中管理:
●●●js // src/composables/useAI.jsexportfunctionuseAI() {const { getTextApiKey, getTextModel } = useAISettings()asyncfunctionpolishText(content, instructions) {const data = awaitpostAI('/polish', { content, instructions, model: getTextModel() }, { 'X-Text-Api-Key': getTextApiKey() })return data.polishedText }// ...}
编辑器交互通过useSharedEditorView这个单例,让不同组件共享同一个 CodeMirror 实例,就能拿到选中文本、替换文本这些操作了。
后端:Spring Boot 3.5 + Java 21
就四个 REST 接口,统一返回{ code, data, message }:
POST /api/ai/polish | |
POST /api/ai/title | |
POST /api/ai/summary | |
POST /api/ai/image |
用了 Java Records 定义 DTO,Lombok 去掉样板代码,@RestControllerAdvice统一处理异常。
HTTP 客户端选型踩坑
一开始用的SimpleClientHttpRequestFactory(底层是HttpsURLConnection),调 DeepSeek 直接报SSLHandshakeException。查了半天发现是 JDK 内置的 TLS 协商跟 DeepSeek 服务端不兼容。
解决方式:换成JdkClientHttpRequestFactory(JDK HttpClient),SSL 兼容性好多了,顺便配了个系统代理支持:
●●●java HttpClient httpClient = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(60)) .proxy(ProxySelector.getDefault()) // 读取系统代理,兼容 VPN .build();
一键启动
项目启动很方便:
●●●bash # 克隆项目git clone https://github.com/sqking-coke/mdeditor-ai.gitcd mdeditor-ai# 安装前端依赖npm install# 一键启动前后端(需要 Java 21 + Maven)npm run dev:all# 或者分别启动npm run dev # 前端 :3000npm run server # 后端 :8080
生产环境的话,把前端构建产物丢到后端static/目录里,打包成一个 Fat Jar 就能单进程部署了。
最后说两句
做这个项目的初衷就是“让写作更流畅”——不出编辑器就能搞定润色、标题、摘要、配图这些事。
目前功能还不算多,后面打算加上:
●流式响应(SSE),润色结果一个字一个字地出来
●更多 AI 模型(Claude、通义千问 等)
●自定义 Prompt 模板
●AI 续写功能
项目完全开源,欢迎 Star 和 PR。
源码地址:https://github.com/sqking-coke/mdeditor-ai
基于xiaobox/mdeditor改造,感谢原作者的优秀作品。
夜雨聆风