yjweb-editor
v1.0.5
Published
A configurable Vue 3 rich text editor workbench for article editing and publishing.
Maintainers
Readme
yjweb-editor
一个基于 Vue 3 + TipTap 的文章编辑组件,支持:
- 自动识别新增 / 编辑
- 文章详情加载
- 保存、发布、上传接口完全自定义
- 自动携带
Authorization: Bearer ${token} - 图片插入后拖拽手柄缩放
- 图片插入后会保留前后可输入区域
- 封面上传后支持预览与自定义裁剪
- 表格插入、行列增删、表头切换、单元格合并/拆分
docx导入支持内嵌图片显示- 底部保存 / 发布按钮栏支持
footerslot 自定义 - 通过组件事件接管错误和成功反馈,不再使用
alert
安装
npm install yjweb-editor基础使用
<template>
<YjEditor
:config="config"
@error="handleEditorError"
@save="handleEditorSave"
@publish="handleEditorPublish"
/>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router'
import YjEditor from 'yjweb-editor'
import 'yjweb-editor/style.css'
const route = useRoute()
const token = 'your-token'
const config = {
initialData: {
route: {
params: route.params,
query: route.query,
keys: ['id', 'articleId'],
},
},
api: {
enabled: true,
baseUrl: 'https://api.example.com',
token,
endpoints: {
articleCreate: '/cms/article/create',
articleUpdate: '/cms/article/update/:id',
articleDetail: '/cms/article/detail/:id',
publish: '/cms/article/publish',
upload: '/cms/file/upload',
},
},
}
const handleEditorError = (payload: unknown) => {
console.log('editor error', payload)
}
const handleEditorSave = (payload: unknown) => {
console.log('editor saved', payload)
}
const handleEditorPublish = (payload: unknown) => {
console.log('editor published', payload)
}
</script>新增与编辑逻辑
- 如果能从
initialData.articleId获取到 id,则自动走详情接口并进入编辑模式。 - 如果没有
articleId,则自动进入新增模式。 save:- 新增模式调用新增接口
- 编辑模式调用编辑接口
publish始终调用发布接口
从 params / query 取 id
initialData: {
route: {
params: route.params,
query: route.query,
keys: ['id', 'articleId'],
},
}也可以直接传:
initialData: {
articleId: 'article_001',
}API 配置
默认端点配置
api: {
enabled: true,
token: 'your-token',
endpoints: {
articleCreate: '/cms/article/create',
articleUpdate: '/cms/article/update/:id',
articleDetail: '/cms/article/detail/:id',
publish: '/cms/article/publish',
upload: '/cms/file/upload',
},
}组件请求会自动追加:
headers['Authorization'] = `Bearer ${token}`完全自定义请求结构
你可以对每个动作单独配置:
urlmethodheadersparamsquerybody
api: {
enabled: true,
token: 'your-token',
requests: {
detail: {
url: '/cms/article/detail/:id',
method: 'GET',
query: ({ articleId }) => ({
articleId,
}),
},
create: {
url: '/cms/article/save',
method: 'POST',
body: ({ payload }) => ({
title: payload?.meta.title,
author: payload?.meta.author,
html: payload?.content,
coverUrl: payload?.meta.cover,
sourceUrl: payload?.originLink,
}),
},
update: {
url: '/cms/article/save/:id',
method: 'PUT',
params: ({ articleId }) => ({
id: articleId,
}),
body: ({ articleId, payload }) => ({
articleId,
title: payload?.meta.title,
author: payload?.meta.author,
html: payload?.content,
}),
},
publish: {
url: '/cms/article/publish',
method: 'POST',
body: ({ payload }) => ({
articleId: payload?.id,
title: payload?.meta.title,
html: payload?.content,
}),
},
upload: {
url: '/cms/file/upload',
method: 'POST',
},
},
}字段映射
如果你不想完全自定义 body,也可以只配映射:
api: {
mapping: {
article: {
id: 'data.articleId',
title: 'data.articleTitle',
author: 'data.writerName',
cover: 'data.coverUrl',
content: 'data.html',
updatedAt: 'data.updateTime',
originLink: 'data.sourceUrl',
},
publish: {
id: 'data.articleId',
publishedAt: 'data.publishTime',
message: 'data.msg',
title: 'articleTitle',
author: 'writerName',
cover: 'coverUrl',
content: 'html',
originLink: 'sourceUrl',
},
upload: {
fileFieldName: 'uploadFile',
typeFieldName: 'bizType',
id: 'data.fileId',
url: 'data.fileUrl',
name: 'data.fileName',
type: 'data.mediaType',
},
},
}事件
组件不再使用 alert,统一通过事件抛出:
<YjEditor
@error="handleEditorError"
@save="handleEditorSave"
@publish="handleEditorPublish"
/>error 事件结构:
{
action: 'detail' | 'create' | 'update' | 'publish' | 'upload' | 'import',
message: string,
error: unknown,
}自定义底部按钮栏
默认底部会显示保存、发布按钮。你也可以通过 footer slot 接管按钮栏,slot 会把当前富文本值、元信息和默认保存 / 发布方法传出来:
<YjEditor :config="config">
<template #footer="{ content, payload, getPayload, save, publish }">
<div class="my-editor-footer">
<span>当前正文长度:{{ content.length }}</span>
<button @click="console.log(getPayload())">查看提交值</button>
<button @click="save">保存草稿</button>
<button @click="publish">发布文章</button>
</div>
</template>
</YjEditor>slot 可用参数包括:
content:当前富文本 HTMLpayload:当前文章提交结构getPayload():先同步编辑器,再返回最新提交结构meta、originLink、isDirty、isSaving、isPublishingsave()、publish():组件默认保存 / 发布方法
图片缩放
上传图片后,图片会作为编辑器图片节点插入正文区域。
图片右下角有拖拽手柄,可以直接拖动调整宽度。
图片插入时会自动补充可输入段落,方便继续在图片前后编辑正文。
封面裁剪
上传封面后会先显示裁剪弹窗,可以直接拖动裁剪框,也可以拖拽四边和四个角调整裁剪范围。确认后组件会把裁剪后的封面图片上传,并在封面上传区域和左侧预览中显示。
文档导入
支持 .docx、.txt、.md、.html、.htm。其中 .docx 里的内嵌图片会转换为可显示的图片内容。
注意
- 保存和发布前,组件会强制从编辑器实例同步最新 HTML,避免提交时正文仍然是
<p></p>。 - 如果你使用
vue-router,建议把route.params和route.query传给组件,这样 id 判定最稳定。
