angEditor – 支持word上傳的富文本編輯器,WANGEDITOR實現WORD圖片自動轉存,JAVA中將WORD轉換為HTML導入到WANGEDITOR編輯器中(解決圖片問題,樣式,非常完美),wangEditor如何導入word文檔,如何實現導入WORD文檔到WANGEDITOR編輯器中?WANGEDITOR導入WORD文檔 WANGEDITOR WORD導入插件,HTML富文本編輯器導入WORD,Web富文本編輯器導入WORD,WANGEDITOR富文本編輯器導入WORD,WANGEDITOR導入WORD,WANGEDITORWORD導入編輯,wangEditor集成word導入功能,
之前在網上也搜索過相關資料,
網上一般的方案都是在JS中解壓ZIP,然后解析文檔。
后端是用的JAVA,SpringBoot框架,實際上前端在集成的時候是不關心后端具體是用什么語言實現的。
它這個版本有幾個wangEditor3,wangEditor4,wangEditor5,好用的是就3和4,5不支持插入HTML。但是用戶用插入HTML這個功能用的比較多。
vue-cli-wangEditor3,vue3-cli-wangEditor4集成word導入功能。在VUE框架下面集成了WORD導入功能。
用戶選擇word文件后,自動轉換成html,自動將word里面的圖片上傳到服務器中,自動將HTML添加到編輯器中。
主要的方案就是提供一個轉換接口,轉換接口使用RESTful協議,這樣的話兼容性更好一點,其它的平臺用起來的話更方便簡單一點,而且測試起來也方便。
現有項目需要為TinyMCE增加導入word文件的功能,導入后word文件里面的圖片自動上傳到服務器中,返回圖片和文字HTML,word里面的文本樣式保留
用戶一般在發新聞和發文章時用到,算是一個高頻使用功能,用戶體驗上來講確實是很好,和以前的發新聞或者發文章的體驗比起來要方便許多,用戶用的更爽。1.下載示例
https://gitee.com/xproer/zyoffice-vue3-cli-wang-editor4
2.引入組件
3.添加按鈕
4.配置轉換接口
效果
開發文檔:https://drive.weixin.qq.com/s?k=ACoAYgezAAwsDazDKJ
產品比較:https://drive.weixin.qq.com/s?k=ACoAYgezAAwh8oq8Zf
產品源代碼:https://drive.weixin.qq.com/s?k=ACoAYgezAAwjJM8412
報價單:https://drive.weixin.qq.com/s?k=ACoAYgezAAwsfyDdrf
給大家分享一個好用的富文本編輯器
前后端分離
前端 vue3+typescript+wangEditor+axios
后端 springboot+mybatis-plus+swagger
項目精簡 不引入過多框架
1. 自定義圖片上傳
2. 自定義視頻上傳(wangEditor 有默認配置 但要返回response body有格式要求 故自己編寫后端自定義實現)
3. 后端 對于html的處理 轉義安全字符 解義
4. 文章的保存
5. 文章的查詢
<script setup lang="ts">
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
import {
onBeforeUnmount,
ref,
shallowRef,
onMounted,
reactive
} from "vue";
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
import { IEditorConfig } from "@wangeditor/core";
import { uploadPic, deleteFile, uploadVideo, toSaveArticleAndFile ,toQueryArticleApi} from "./request/api";
import { resourceUrl } from "./common/path";
import {
IWangEPic,
IWangEVid,
IRichData,
IToSaveAricle,
IReQueryArticle
} from "./pageTs/index";
//圖片 視頻 類型聲明
const richData=reactive(new IRichData());
const saveArticleData=reactive(new IToSaveAricle());
// 編輯器實例,必須用 shallowRef
const editorRef=shallowRef();
// 內容 HTML
const valueHtml=ref("");
// 模擬 axios 異步獲取內容
onMounted(()=> {
setTimeout(()=> {
valueHtml.value="<p>大大帥將軍 小小怪下士</p>";
}, 1500);
});
//編輯器初始化
const toolbarConfig={};
const editorConfig: Partial<IEditorConfig>={ MENU_CONF: {} };
// 編輯器創建完畢時的回調函數。
const handleCreated=(editor: any)=> {
editorRef.value=editor; // 記錄 editor 實例,重要!
};
//圖片類型定義
type InsertPicType=(url: string)=> void;
//圖片上傳
editorConfig.MENU_CONF!["uploadImage"]={
// 自定義上傳 InsertFnType
async customUpload(richPic: File, insertFn: InsertPicType) {
//圖片上傳接口調用
uploadPic(richPic).then((res)=> {
console.log(res.data);
//返回給編輯器 圖片地址
insertFn(resourceUrl + res.data);
//上傳成功后 記錄圖片地址
richData.preFileList.push(res.data);
});
},
};
//上傳視頻 url 視頻地址 poster 視頻展示圖片地址
type InsertVidType=(url: string, poster: string)=> void;
editorConfig.MENU_CONF!["uploadVideo"]={
// 自定義上傳
async customUpload(file: File, insertFn: InsertVidType) {
//視頻上傳接口調用
uploadVideo(file).then((res)=> {
console.log(res.data);
//返回給編輯器 圖片地址
insertFn(resourceUrl + res.data, "/src/assets/bg.png");
//上傳成功后 記錄視頻地址
richData.preFileList.push(res.data);
});
},
};
// 組件銷毀時,也及時銷毀編輯器
onBeforeUnmount(()=> {
const editor=editorRef.value;
if (editor==null) return;
editor.destroy();
});
//保存文章
const toSaveArcitle=()=> {
const editor=editorRef.value;
// 1.獲取最后保存的文章圖片 視頻 list數組
editor.getElemsByType("image").forEach((item: IWangEPic)=> {
//排除掉外部資源
if(item.src.indexOf(resourceUrl) !=-1){
richData.articleFileUrl.push(item.src);
}
});
editor.getElemsByType("video").forEach((item: IWangEVid)=> {
if(item.src.indexOf(resourceUrl) !=-1){
richData.articleFileUrl.push(item.src);
}
});
//2.對于全部圖片 視頻 對比 獲取已刪除圖片
richData.preFileList.forEach((item)=> {
//articleFileList 數組展示的是圖片完全路徑
//preFileList 保存的是圖片部分路徑
//所以要通過添加resourceUrl常量進行對比
if (richData.articleFileUrl.indexOf(resourceUrl + item)==-1) {
//保存到需刪除的數組中
richData.deleteFileList.push(item);
}else{
//保存需要存入數據庫的數組
saveArticleData.articleFileUrl.push(item);
}
});
//3.調后臺接口 刪除圖片 視頻
deleteFile(richData.deleteFileList).catch((err)=> {
console.log(err.msg);
});
//4.調后臺接口保存文章
//參數賦值
saveArticleData.articleName=richData.articleName;
saveArticleData.articleAuthor=richData.articleAuthor;
saveArticleData.articleContent=valueHtml.value;
toSaveArticleAndFile(saveArticleData).then(res=>{
console.log("保存文章成功");
//保存文章后 所有數據清空
valueHtml.value="";
richData.articleAuthor="";
richData.articleName="";
})
};
//文章查詢
const queryArticle=reactive(new IReQueryArticle());
const toQueryArticle=()=>{
toQueryArticleApi(1566944471915032576n).then(res=>{
console.log(res.data);
queryArticle.articleAuthor=res.data.articleAuthor;
queryArticle.articleContent=res.data.articleContent;
queryArticle.articleId=res.data.articleId;
queryArticle.gmtUpdate=res.data.gmtUpdate;
queryArticle.articleName=res.data.articleName;
})
}
</script>
<template>
<div>
文章名稱:<input
class="demoInput"
type="text"
v-model="richData.articleName"
placeholder="請輸入文章名稱"
/>
</div>
<div>
文章作者:<input
class="demoInput"
type="text"
v-model="richData.articleAuthor"
placeholder="請輸入文章作者"
/>
</div>
<div style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="richData.model"
/>
<Editor
style="height: 550px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
:mode="richData.model"
@onCreated="handleCreated"
/>
</div>
<button @click="toSaveArcitle">保存</button>
<div>==========================================</div>
<button @click="toQueryArticle">查詢文章</button>
<div v-if="queryArticle!=null">
<h1>{{queryArticle.articleName}}</h1>
<h5>{{queryArticle.articleAuthor}}</h5>
<h6>{{queryArticle.gmtUpdate}}</h6>
<div v-html="queryArticle.articleContent">
</div>
</div>
</template>
<style lang="scss" scoped>
.demoInput {
outline-style: none;
border: 1px solid #ccc;
border-radius: 3px;
padding: 13px 14px;
width: 320px;
font-size: 14px;
font-weight: 320;
margin: 20px;
font-family: "Microsoft soft";
}
.demoInput:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px rgba(102, 175, 233, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px rgba(102, 175, 233, 0.6);
}
</style>
/**
* <p>
* 服務實現類
* </p>
*
* @author 小王八
* @since 2022-09-05
*/
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {
@Autowired
private ArticleMapper articleMapper;
@Autowired
private ArticleFileService articleFileService;
@Override
@Transactional(rollbackFor=Exception.class)
public String toSaveArticle(ToSaveArticle toSaveArticle) {
//1.生成文章id 插入圖片article_id
long articleId=IdUtil.getSnowflakeNextId();
//2.文章內容轉換
//過濾HTML文本,防止XSS攻擊 可用 會清理掉html元素標簽 只留下文本
//String articleContent=HtmlUtil.filter(toSaveArticle.getArticleContent());
//html=>安全字符
String escape=HtmlUtil.escape(toSaveArticle.getArticleContent());
//3.文章入數據庫
save(new Article()
.setPkId(articleId)
.setArticleName(toSaveArticle.getArticleName())
.setArticleAuthor(toSaveArticle.getArticleAuthor())
.setArticleContent(escape)
);
//4.文章資源入數據庫
if (ObjectUtil.isNotEmpty(toSaveArticle.getArticleFileUrl())){
articleFileService.toSaveFile(toSaveArticle.getArticleFileUrl(),articleId);
}
return "文章保存成功";
}
@Override
public ReShowArticle toShowArticle(Long articleId) {
return ReShowArticle.toReShow(getById(articleId));
}
關于功能的動態詳細展示
我專門錄制的一期B站視頻 作為講解
具體源碼
放在視頻簡介(gitee 前后端地址都有)
【一款好用的富文本編輯器 wangEditor 前后端 vue3+springboot】
B站視頻鏈接
制作不易 還望大家三連支持
?
TML富文本編輯器導入WORD,Web富文本編輯器導入WORD,WANGEDITOR富文本編輯器導入WORD,WANGEDITOR導入WORD,WANGEDITORWORD導入編輯,wangEditor集成word導入功能,
它這個版本有幾個wangEditor3,wangEditor4,wangEditor5,好用的是就3和4,5不支持插入HTML。但是用戶用插入HTML這個功能用的比較多。
vue-cli-wangEditor3,vue3-cli-wangEditor4集成word導入功能。在VUE框架下面集成了WORD導入功能。
用戶選擇word文件后,自動轉換成html,自動將word里面的圖片上傳到服務器中,自動將HTML添加到編輯器中。
主要的方案就是提供一個轉換接口,轉換接口使用RESTful協議,這樣的話兼容性更好一點,其它的平臺用起來的話更方便簡單一點,而且測試起來也方便。
現有項目需要為TinyMCE增加導入word文件的功能,導入后word文件里面的圖片自動上傳到服務器中,返回圖片和文字HTML,word里面的文本樣式保留
用戶一般在發新聞和發文章時用到,算是一個高頻使用功能,用戶體驗上來講確實是很好,和以前的發新聞或者發文章的體驗比起來要方便許多,用戶用的更爽。
1.下載示例
https://gitee.com/xproer/zyoffice-vue3-cli-wang-editor4
2.引入組件
3.添加按鈕
4.配置轉換接口
效果
*請認真填寫需求信息,我們會在24小時內與您取得聯系。