wangeditor 使用

富文本编辑器官网:
https://www.wangeditor.com
文档地址:
https://doc.wangeditor.com

# 安装wangeditor
npm i wangeditor --save# 引入
import E from "wangeditor"# 初始化
const editor = new E("#div1");# 创建
editor.create();# 获取元素
editor.txt.html();
注:要注意创建的优先级,举个例子:如果富文本编辑器在表单中,
首先表单要创建完成后,才能创建富文本

使用案例:

<template><a-layout><a-layout-content:style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"><a-row :gutter="24"><a-col :span="8"><p><a-form layout="inline" :model="param"><a-form-item><a-button type="primary" @click="handleQuery()">查询</a-button></a-form-item><a-form-item><a-button type="primary" @click="add()">新增</a-button></a-form-item></a-form></p><a-tablev-if="level1.length > 0":columns="columns":row-key="record => record.id":data-source="level1":loading="loading":pagination="false"size="small":defaultExpandAllRows="true"><template #name="{ text, record }">{{record.sort}} {{text}}</template><template v-slot:action="{ text, record }"><a-space size="small"><a-button type="primary" @click="edit(record)" size="small">编辑</a-button><a-popconfirmtitle="删除后不可恢复,确认删除?"ok-text="是"cancel-text="否"@confirm="handleDelete(record.id)"><a-button type="danger" size="small">删除</a-button></a-popconfirm></a-space></template></a-table></a-col><a-col :span="16"><p><a-form layout="inline" :model="param"><a-form-item><a-button type="primary" @click="handleSave()">保存</a-button></a-form-item></a-form></p><a-form :model="doc" layout="vertical"><a-form-item><a-input v-model:value="doc.name" placeholder="名称"/></a-form-item><a-form-item><a-tree-selectv-model:value="doc.parent"style="width: 100%":dropdown-style="{ maxHeight: '400px', overflow: 'auto' }":tree-data="treeSelectData"placeholder="请选择父文档"tree-default-expand-all:replaceFields="{title: 'name', key: 'id', value: 'id'}"></a-tree-select></a-form-item><a-form-item><a-input v-model:value="doc.sort" placeholder="顺序"/></a-form-item><a-form-item><a-button type="primary" @click="handlePreviewContent()"><EyeOutlined /> 内容预览</a-button></a-form-item><a-form-item><div id="content"></div></a-form-item></a-form></a-col></a-row><a-drawer width="900" placement="right" :closable="false" :visible="drawerVisible" @close="onDrawerClose"><div class="wangeditor" :innerHTML="previewHtml"></div></a-drawer></a-layout-content></a-layout><!--<a-modal--><!--  title="文档表单"--><!--  v-model:visible="modalVisible"--><!--  :confirm-loading="modalLoading"--><!--  @ok="handleModalOk"--><!--&gt;--><!--  --><!--</a-modal>-->
</template><script lang="ts">import { defineComponent, onMounted, ref, createVNode } from 'vue';import axios from 'axios';import {message, Modal} from 'ant-design-vue';import {Tool} from "@/util/tool";import {useRoute} from "vue-router";import ExclamationCircleOutlined from "@ant-design/icons-vue/ExclamationCircleOutlined";import E from 'wangeditor'export default defineComponent({name: 'AdminDoc',setup() {const route = useRoute();console.log("路由:", route);console.log("route.path:", route.path);console.log("route.query:", route.query);console.log("route.param:", route.params);console.log("route.fullPath:", route.fullPath);console.log("route.name:", route.name);console.log("route.meta:", route.meta);const param = ref();param.value = {};const docs = ref();const loading = ref(false);// 因为树选择组件的属性状态,会随当前编辑的节点而变化,所以单独声明一个响应式变量const treeSelectData = ref();treeSelectData.value = [];const columns = [{title: '名称',dataIndex: 'name',slots: { customRender: 'name' }},{title: 'Action',key: 'action',slots: { customRender: 'action' }}];/*** 一级文档树,children属性就是二级文档* [{*   id: "",*   name: "",*   children: [{*     id: "",*     name: "",*   }]* }]*/const level1 = ref(); // 一级文档树,children属性就是二级文档level1.value = [];/*** 数据查询**/const handleQuery = () => {loading.value = true;// 如果不清空现有数据,则编辑保存重新加载数据后,再点编辑,则列表显示的还是编辑前的数据level1.value = [];axios.get("/doc/all/" + route.query.ebookId).then((response) => {loading.value = false;const data = response.data;if (data.success) {docs.value = data.content;console.log("原始数组:", docs.value);level1.value = [];level1.value = Tool.array2Tree(docs.value, 0);console.log("树形结构:", level1);// 父文档下拉框初始化,相当于点击新增treeSelectData.value = Tool.copy(level1.value) || [];// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});} else {message.error(data.message);}});};// -------- 表单 ---------const doc = ref();doc.value = {ebookId: route.query.ebookId};const modalVisible = ref(false);const modalLoading = ref(false);const editor = new E('#content');editor.config.zIndex = 0;const handleSave = () => {modalLoading.value = true;doc.value.content = editor.txt.html();axios.post("/doc/save", doc.value).then((response) => {modalLoading.value = false;const data = response.data; // data = commonRespif (data.success) {// modalVisible.value = false;message.success("保存成功!");// 重新加载列表handleQuery();} else {message.error(data.message);}});};/*** 将某节点及其子孙节点全部置为disabled*/const setDisable = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("disabled", node);// 将目标节点设置为disablednode.disabled = true;// 遍历所有子节点,将所有子节点全部都加上disabledconst children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {setDisable(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {setDisable(children, id);}}}};const deleteIds: Array<string> = [];const deleteNames: Array<string> = [];/*** 查找整根树枝*/const getDeleteIds = (treeSelectData: any, id: any) => {// console.log(treeSelectData, id);// 遍历数组,即遍历某一层节点for (let i = 0; i < treeSelectData.length; i++) {const node = treeSelectData[i];if (node.id === id) {// 如果当前节点就是目标节点console.log("delete", node);// 将目标ID放入结果集ids// node.disabled = true;deleteIds.push(id);deleteNames.push(node.name);// 遍历所有子节点const children = node.children;if (Tool.isNotEmpty(children)) {for (let j = 0; j < children.length; j++) {getDeleteIds(children, children[j].id)}}} else {// 如果当前节点不是目标节点,则到其子节点再找找看。const children = node.children;if (Tool.isNotEmpty(children)) {getDeleteIds(children, id);}}}};/*** 内容查询**/const handleQueryContent = () => {axios.get("/doc/find-content/" + doc.value.id).then((response) => {const data = response.data;if (data.success) {editor.txt.html(data.content)} else {message.error(data.message);}});};/*** 编辑*/const edit = (record: any) => {// 清空富文本框editor.txt.html("");modalVisible.value = true;doc.value = Tool.copy(record);handleQueryContent();// 不能选择当前节点及其所有子孙节点,作为父节点,会使树断开treeSelectData.value = Tool.copy(level1.value);setDisable(treeSelectData.value, record.id);// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});};/*** 新增*/const add = () => {// 清空富文本框editor.txt.html("");modalVisible.value = true;doc.value = {ebookId: route.query.ebookId};treeSelectData.value = Tool.copy(level1.value) || [];// 为选择树添加一个"无"treeSelectData.value.unshift({id: 0, name: '无'});};const handleDelete = (id: number) => {// console.log(level1, level1.value, id)// 清空数组,否则多次删除时,数组会一直增加deleteIds.length = 0;deleteNames.length = 0;getDeleteIds(level1.value, id);Modal.confirm({title: '重要提醒',icon: createVNode(ExclamationCircleOutlined),content: '将删除:【' + deleteNames.join(",") + "】删除后不可恢复,确认删除?",onOk() {// console.log(ids)axios.delete("/doc/delete/" + deleteIds.join(",")).then((response) => {const data = response.data; // data = commonRespif (data.success) {// 重新加载列表handleQuery();} else {message.error(data.message);}});},});};// ----------------富文本预览--------------const drawerVisible = ref(false);const previewHtml = ref();const handlePreviewContent = () => {const html = editor.txt.html();previewHtml.value = html;drawerVisible.value = true;};const onDrawerClose = () => {drawerVisible.value = false;};onMounted(() => {handleQuery();editor.create();});return {param,// docs,level1,columns,loading,handleQuery,edit,add,doc,modalVisible,modalLoading,handleSave,handleDelete,treeSelectData,drawerVisible,previewHtml,handlePreviewContent,onDrawerClose,}}});
</script><style scoped>img {width: 50px;height: 50px;}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

html-简单验证、滑块、搜索框

一、简单验证 <!-- 邮件验证 --><p> 邮箱:<input type"email" name"email"></p><!-- url --><p> URL:<input type"url" name"url"></p><!-- 数字 --><p> 数字:&l…

【从入门到放弃-Java】并发编程-线程安全

概述 并发编程&#xff0c;即多条线程在同一时间段内“同时”运行。 在多处理器系统已经普及的今天&#xff0c;多线程能发挥出其优势&#xff0c;如&#xff1a;一个8核cpu的服务器&#xff0c;如果只使用单线程的话&#xff0c;将有7个处理器被闲置&#xff0c;只能发挥出服…

Kubernetes事件离线工具kube-eventer正式开源

前言 监控是保障系统稳定性的重要组成部分&#xff0c;在Kubernetes开源生态中&#xff0c;资源类的监控工具与组件百花齐放。除了社区自己孵化的metrics-server&#xff0c;还有从CNCF毕业的Prometheus等等&#xff0c;开发者可选的方案有很多。但是&#xff0c;只有资源类的…

国内首家,腾讯云云开发“全家桶”来了

作者 | 胡巍巍出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;虽然程序员这行加班多&#xff0c;但不要认为加班就该是常态。有些班&#xff0c;原本可以不加&#xff1b;有些夜&#xff0c;其实可以不熬。俗话说&#xff0c;工具不对&#xff0c;努力白费。如果有…

validation 参数校验和统一异常处理

文章目录1. 引入依赖2. 校验规则3. 规则使用4. 自定义异常类5. 统一返回对象封装6. 统一异常对象7. 统一异常枚举8. 前端form表单输入&#xff0c;自动触发校验1. 引入依赖 <!--参数校验--><dependency><groupId>org.springframework.boot</groupId>&l…

html-表单的应用

<!-- readonly 只读 --><p>名字: <input type"text" name"username1" value"wang洪亮" readonly></p><!-- disabled 禁用 &#xff0c; 按钮等地方也能用 --><p>性别:<input type"radio" v…

阿里研究员吴翰清:世界需要什么样的智能系统?

阿里妹导读&#xff1a;吴翰清&#xff0c;被大家亲切地称为“小黑”“道哥”。他是阿里巴巴研究员&#xff0c;更是一位“白帽黑客”。15岁&#xff0c;考入西安交大少年班&#xff0c;毕业后应聘阿里。23岁&#xff0c;成为阿里最年轻的高级技术专家。32岁&#xff0c;被评选…

咱们从头到尾说一次 Java 垃圾回收

之前上学的时候有这个一个梗&#xff0c;说在食堂里吃饭&#xff0c;吃完把餐盘端走清理的&#xff0c;是 C 程序员&#xff0c;吃完直接就走的&#xff0c;是 Java 程序员。 确实&#xff0c;在 Java 的世界里&#xff0c;似乎我们不用对垃圾回收那么的专注&#xff0c;很多初…

Ant Design Vue页面数据复制

页面编辑时复制对象&#xff0c;修改表单时&#xff0c;不影响列表数据 /*** 空校验 null或""都返回true*/public static isEmpty (obj: any) {if ((typeof obj string)) {return !obj || obj.replace(/\s/g, "") ""} else {return (!obj || …

html-表单初级验证

<!-- placeholder 输入框 提示信息required 非空判断pattern 正则表达式--><p>名字: <input type"text" name"username1" placeholder"请输入名字" required></p><!-- pattern 正则表达式常用正则表达式…

如何将Elasticsearch的快照备份至OSS

前言 Elasticsearch 是一个开源的分布式 RESTful 搜索和分析引擎。它可以在近实时条件下&#xff0c;存储&#xff0c;查询和分析海量的数据。它还支持将快照备份至HDFS/S3上面&#xff0c;而阿里云OSS兼容S3的API&#xff0c;本文将介绍如何使用ES的Repository-S3插件将快照备…

你公司的虚拟机还闲着?基于 Jenkins 和 Kubernetes 的持续集成测试实践了解一下!...

作者 | 刘春明责编 | Carol出品 | CSDN 云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;封图| CSDN下载于视觉中国目前公司为了降低机器使用成本&#xff0c;对所有的AWS虚拟机进行了盘点&#xff0c;发现利用率低的机器中&#xff0c;有一部分是测试团队用作Jenkins S…

Ant Design Vue 表格数据按树型展示

/*** 使用递归将数组转为树形结构* 父ID属性为parent*/public static array2Tree (array: any, parentId: number) {if (Tool.isEmpty(array)) {return [];}const result [];for (let i 0; i < array.length; i) {const c array[i];// console.log(Number(c.parent), Num…

长脸了!阿里云这位英雄拿下了世界第一

阿里云数据库又被顶级机构点名了&#xff01; 近日&#xff0c;全球最知名的数据管理系统评测标准化TPC组织公布了数据库领域分析性能基准测试最新排名&#xff0c;阿里云超大规模分析型数据库AnalyticDB登上榜首&#xff0c;是全球首个通过TPC严格审计认证的云数据库产品。 …

css-第一个CSS

建议使用分离写法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><!-- <style>可以编写css的代码&#xff0c;每一个声明&#xff0c;最好使用分号结尾语法:选择器 {声…

跟面试官侃了半小时 MySQL 事务,把原子性、一致性、持久性的实现都讲完了

来源 | 阿丸笔记封图| CSDN下载于视觉中国提到MySQL的事务&#xff0c;我相信对MySQL有了解的同学都能聊上几句&#xff0c;无论是面试求职&#xff0c;还是日常开发&#xff0c;MySQL的事务都跟我们息息相关。而事务的ACID&#xff08;即原子性Atomicity、一致性Consistency、…

阿里云Link TEE获得全球首款GlobalPlatform TEE全配置安全认证

2019年7月12日&#xff0c;阿里云Link TEE正式获得由国际标准组织GlobalPlatform&#xff08;以下简称GP&#xff09;颁发的TEE安全评估认证证书&#xff0c;也成为全球首款获得GP TEE全配置&#xff08;支持TEE Time and Rollback PP-Module和TEE Debug PP-Module&#xff09;…

vue-cli多环境配置

# 创建多环境配置文件 .env.dev添加内容&#xff1a; NODE_ENVdevelopment VUE_APP_SERVERhttp://localhost:8080.env.pord添加内容&#xff1a; NODE_ENVproduction VUE_APP_SERVERhttp://gblfy.com:8080在package.json修改如下 "scripts": {"serve-dev":…

阿里云 EMAS HTTPDNS 联合函数计算重磅推出 SDNS 服务,三大能力获得突破

阿里云 EMAS HTTPDNS 联合函数计算重磅推出 SDNS 服务&#xff0c;三大能力获得突破 1. 什么是 HTTPDNS &#xff1f; 传统的 DNS&#xff08;Domain Name System&#xff09;使开发者常面临着域名劫持、调度不精准的问题。 HTTPDNS 使用 HTTP 协议替换常用的 UDP 协议&#…

css-四种css导入方式

一、行内样式 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <!-- 行内样式&#xff1a;在标签元素中&#xff0c;编写一个style属性&#xff0…