整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          wangEditor – 支持word上傳的富文本編

          wangEditor – 支持word上傳的富文本編輯器

          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. 文章的查詢


          資源介紹



          swagger接口文檔




          編輯器功能展示




          項目目錄講解


          前端



          后端



          部分代碼展示


          前端 富文本編輯器頁面App.vue


          <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>
          



          后端 文章查詢保存 serviceImpl


          /**
           * <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.配置轉換接口

          效果


          主站蜘蛛池模板: 日本一区二区在线免费观看| 亚洲国产精品一区| 亚洲Av高清一区二区三区| 一区二区三区四区在线视频| 久久久无码一区二区三区| 国产视频一区二区| 久久一区二区三区精华液使用方法 | 国产综合一区二区在线观看| 亚洲一区二区久久| 久久精品视频一区| 国产在线乱子伦一区二区| 亚洲综合一区二区精品导航| 性色AV一区二区三区| 免费一区二区三区| 在线观看国产一区二三区| 欧美日韩综合一区二区三区| 极品尤物一区二区三区| 日韩高清一区二区三区不卡 | 国产日韩一区二区三区| 加勒比无码一区二区三区| 午夜视频在线观看一区二区| 精品国产日韩亚洲一区| 色窝窝无码一区二区三区| 一色一伦一区二区三区| 日韩精品一区二区三区影院| 在线精品亚洲一区二区| 一区二区中文字幕在线观看| 国产亚洲3p无码一区二区| 久久久国产精品无码一区二区三区| 国产综合视频在线观看一区| 国产伦精品一区二区三区在线观看| 中文字幕一区二区三区在线不卡| 亚洲男女一区二区三区| 国产91精品一区二区麻豆亚洲| 日韩人妻精品一区二区三区视频 | 日韩一区二区三区免费体验| 久久精品综合一区二区三区| 精品国产一区二区三区不卡| 亚洲综合无码精品一区二区三区| 亚洲午夜一区二区三区| 无码人妻品一区二区三区精99 |