Vue3使用vue-quill富文本编辑器

安装依赖

npm install @vueup/vue-quill quill quill-image-uploader

自定义字体

把自定义字体样式放入font.css中在main.js中导入

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
    content: "宋体";
    font-family: "SimSun";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
	content: "黑体";
	font-family: "SimHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
	content: "微软雅黑";
	font-family: "Microsoft YaHei";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
	content: "楷体";
	font-family: "KaiTi";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
	content: "仿宋";
	font-family: "FangSong";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
	content: "Arial";
	font-family: "Arial";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
	content: "Times New Roman";
	font-family: "Times New Roman";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
	content: "sans-serif";
	font-family: "sans-serif";
}
 
.ql-font-SimSun {
  	font-family: "SimSun";
}
.ql-font-SimHei {
  	font-family: "SimHei";
}
.ql-font-Microsoft-YaHei {
  	font-family: "Microsoft YaHei";
}
.ql-font-KaiTi {
  	font-family: "KaiTi";
}
.ql-font-FangSong {
  	font-family: "FangSong";
}
.ql-font-Arial {
  	font-family: "Arial";
}
.ql-font-Times-New-Roman {
  	font-family: "Times New Roman";
}
.ql-font-sans-serif {
  	font-family: "sans-serif";
}

注册自定义字体到quill

案例

<template>
  <div class="publish-form-container">
    <div class="publish-form">
      <form @submit.prevent="submitForm">
        <div class="form-group">
          <label for="content">内容</label>
          <QuillEditor v-model="content" :options="editorOption" class="quill-editor" />
        </div>
        <button type="submit" class="submit-btn">提交</button>
      </form>
    </div>
  </div>
</template>

<script>
import { QuillEditor, Quill } from '@vueup/vue-quill';
import ImageUploader from 'quill-image-uploader';
import '@vueup/vue-quill/dist/vue-quill.snow.css';

// 注册自定义字体到 Quill
const Font = Quill.import('formats/font');
Font.whitelist = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif'];
Quill.register(Font, true);

// 注册图片上传模块
Quill.register("modules/imageUploader", ImageUploader);

// 模拟上传API
const uploadFileAPI = async (fileData) => {
  // 模拟上传返回URL
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ data: { filePath: 'https://lalallalal.com/' + fileData.file.name } });
    }, 1000);
  });
};

// 将本地文件转换为URL
const getLocalImageURL = (file) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      resolve(e.target.result);
    };
    reader.readAsDataURL(file);
  });
};

export default {
  components: {
    QuillEditor,
  },
  data() {
    return {
      title: '',
      type: '',
      content: '',
      editorOption: {
        modules: {
          imageUploader: {
            upload: async (file) => {
              const localUrl = await getLocalImageURL(file);
              return localUrl; // 返回本地图片的 URL 进行预览
            },
          },
          toolbar: [
            [{ font: Font.whitelist }], // 字体
            ['bold', 'italic', 'underline', 'strike'], // 加粗,斜体,下划线,删除线
            ['blockquote', 'code-block'], // 引用,代码块
            [{ header: 1 }, { header: 2 }], // 标题1,标题2
            [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表,无序列表
            [{ script: 'sub' }, { script: 'super' }], // 上标,下标
            [{ indent: '-1' }, { indent: '+1' }], // 缩进
            [{ direction: 'rtl' }], // 文字方向
            [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
            [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题大小
            [{ color: [] }, { background: [] }], // 字体颜色,背景颜色
            [{ align: [] }], // 对齐
            ['clean'], // 清除格式
            ['link', 'image', 'video'], // 链接,图片,视频
          ],
        },
      },
    };
  },
  methods: {
    // 提交表单方法
    async submitForm() {
      // 创建虚拟 DOM 来解析内容
      const parser = new DOMParser();
      const doc = parser.parseFromString(this.content, 'text/html');

      // 查找所有的本地图片
      const images = doc.querySelectorAll('img');
      const imageUploadPromises = [];

      images.forEach((img) => {
        const localSrc = img.getAttribute('src');
        
        // 如果是本地图片,上传图片并替换URL
        if (localSrc.startsWith('data:')) {
          const uploadPromise = uploadFileAPI({ file: this.dataURLtoFile(localSrc, 'image.png') }).then((res) => {
            img.setAttribute('src', res.data.filePath); // 替换成服务器上的图片URL
          });
          imageUploadPromises.push(uploadPromise);
        }
      });

      // 等待所有图片上传完成后提交表单
      try {
        await Promise.all(imageUploadPromises);

        // 上传完成后,更新内容
        const updatedContent = doc.body.innerHTML;

        const payload = {
          title: this.title,
          content: updatedContent,
          type: this.type,
        };

        console.log("提交的内容:", payload);

        const response = await fetch("/api/posts", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(payload),
        });
        const data = await response.json();
        console.log("发布成功", data);
      } catch (error) {
        console.error("发布失败", error);
      }
    },

    // 将 dataURL 转换为 File 对象的辅助函数
    dataURLtoFile(dataurl, filename) {
      const arr = dataurl.split(',');
      const mime = arr[0].match(/:(.*?);/)[1];
      const bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, { type: mime });
    },
  },
};
</script>

<style lang="less" scoped>
//TODO
</style>

参考:在vue中Quill富文本编辑器的使用(主题、自定义工具栏、自定义字体选项、图片拖拽上传、图片改变大小)_quill-editor修改工具栏图标颜色-CSDN博客

Vue3使用vue-quill富文本编辑器并实现图片自定义上传替换默认base64格式图片_vue3 quill-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

path_provider插件的用法

文章目录 1. 概念介绍2. 实现方法3. 示例代码我们在上一章回中介绍了"如何实现本地存储"相关的内容,本章回中将介绍如何实现文件存储.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在上一章回中介绍的本地存储只能存储dart语言中基本类型的数值,如果遇到…

家政服务预约系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;客户管理&#xff0c;员工管理&#xff0c;家政服务管理&#xff0c;服务预约管理&#xff0c;员工风采管理&#xff0c;客户需求管理&#xff0c;接单信息管理 微信端账号功能包括&#xff1a;系统首…

后端(实例)08

设计一个前端在数据库调取数据的表格&#xff0c;并完成基础点击增删改查的功能&#xff1a; 1.首先写一个前端样式&#xff08;空壳&#xff09; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here&l…

深度学习之开发环境(CUDA、Conda、Pytorch)准备(4)

目录 1.CUDA 介绍 1.1 CUDA 的基本概念 1.2 CUDA 的工作原理 1.3 CUDA 的应用领域 2. 安装CUDA 2.1 查看GPU版本 2.2 升级驱动&#xff08;可选&#xff09; 2.3 查看CUDA版本驱动对应的支持的CUDA ToolKit工具包 2.4 下载Toolkit 2.5 安装&#xff08;省略&#xff0…

Docker从入门到精通_01 Docker:引领云计算的新浪潮

Docker从入门到精通_01 Docker&#xff1a;引领云计算的新浪潮 云计算作为信息技术领域的重要支柱&#xff0c;正以前所未有的速度发展。然而&#xff0c;传统的虚拟化架构在资源利用、部署效率、应用扩展等方面已逐渐显露出其局限性。在这样的背景下&#xff0c;容器云技术应…

零信任内网安全访问

随着互联网的持续发展&#xff0c;便捷的共享方式极大地提高了企业的生产力和工作效率&#xff0c;但随之也给企业内网带来了极大的安全隐患。企业内网承载大量的核心资产和机密数据&#xff0c;一旦受到攻击可能会造成大量损失&#xff0c;因此&#xff0c;如何通过零信任内网…

iOS 项目中的多主题颜色设计与实现

引言 在现代iOS应用中&#xff0c;用户对个性化体验的需求越来越高&#xff0c;除了功能上的满足&#xff0c;多样的视觉风格也是提升用户体验的重要手段之一。提供多主题颜色的切换功能不仅能满足用户的审美偏好&#xff0c;还可以让应用更具活力&#xff0c;适应不同场景下的…

一区黏菌算法+双向深度学习+注意力机制!SMA-BiTCN-BiGRU-Attention黏菌算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测

一区黏菌算法双向深度学习注意力机制&#xff01;SMA-BiTCN-BiGRU-Attention黏菌算法优化双向时间卷积双向门控循环单元融合注意力机制多变量回归预测 目录 一区黏菌算法双向深度学习注意力机制&#xff01;SMA-BiTCN-BiGRU-Attention黏菌算法优化双向时间卷积双向门控循环单元…

免费视频无损压缩工具+预览视频生成工具

视频无损压缩工具 功能与作用 &#xff1a;视频无损压缩工具是一种能够减少视频文件大小&#xff0c;但同时保持视频质量的工具。它通过先进的编码技术和算法&#xff0c;有效降低视频文件的存储空间&#xff0c;同时保证视频的清晰度和观感。这对于需要分享或存储大量视频内容…

力扣每日一题 公司命名 集合 找规律

Problem: 2306. 公司命名 &#x1f468;‍&#x1f3eb; 灵神题解 class Solution {public long distinctNames(String[] ideas) {// 创建一个大小为26的HashSet数组&#xff0c;用于存储每个首字母对应的字符串集合Set<String>[] groups new HashSet[26];Arrays.set…

QProgressDialog运行初始不显示的问题

我用的是qt手册上的示例代码&#xff0c;结果运行时却出现如下问题&#xff1a; 如图程序运行时&#xff0c;开始一段时间是不显示进度条、百分比之类的。 运行一段时间之后&#xff0c;到50%才显示。当时数字是2&#xff0c;总数是4。 我用了网上的方案&#xff0c;增加了一条…

众数信科AI智能体政务服务解决方案——寻知智能笔录系统

政务服务解决方案 寻知智能笔录方案 融合民警口供录入与笔录生成需求 2分钟内生成笔录并提醒错漏 助办案人员二次询问 提升笔录质量和效率 寻知智能笔录系统 众数信科AI智能体 产品亮点 分析、理解行业知识和校验规则 AI实时提醒用户文书需注意部分 全文校验格式、内…

【第3期】INFINI Easysearch 免费认证培训开放报名

探索 Easysearch 的无限可能&#xff0c;与 INFINI Labs 共赴搜索技术前沿&#xff01; 随着数字化转型的加速&#xff0c;搜索技术已成为企业数据洞察的核心。INFINI Labs 作为搜索创新技术的引领者&#xff0c;诚邀所有对 Easysearch 搜索引擎感兴趣的开发者、技术爱好者及合…

【笔记】光的衍射

一、 衍射现象 波遇到障碍物时&#xff0c;绕过障碍物 进入几何阴影区。 光偏离直线传播路径进入几何 阴影区&#xff0c;并形成光强非均匀稳 定分布。 二、菲涅耳原理 1、 惠更斯原理 波面上的每一点均为发 射子波的波源&#xff0c;这些子波的 包络面即新的波阵面 成功…

基于python+spark的外卖餐饮数据分析系统设计与实现(含论文)-Spark毕业设计选题推荐

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

Swagger 教程(笔记) Knife4j

假设获取到了整个项目&#xff0c;创建项目相应的结构 MySQL user 表 DROP DATABASE if EXISTS study; CREATE DATABASE study; USE study; CREATE TABLE users (id INT(10) NOT NULL AUTO_INCREMENT,username VARCHAR(255) NOT NULL COLLATE utf8_general_ci,password VARCHA…

Hbase日常运维

1 Hbase日常运维 1.1 监控Hbase运行状况 1.1.1 操作系统 1.1.1.1 IO 群集网络IO&#xff0c;磁盘IO&#xff0c;HDFS IO IO越大说明文件读写操作越多。当IO突然增加时&#xff0c;有可能&#xff1a;1.compact队列较大&#xff0c;集群正在进行大量压缩操作。 2.正在执行…

NTLM Relay攻击原理 + 工具使用

前言 仅仅是记录自己看《域内攻防指南》的体会&&理解&#xff0c;具体的知识学习建议看windows protocol &#xff08;✨&#xff09; ✅&#xff1a;NTLM是不依赖于上层协议的&#xff01;&#xff01;&#xff01;NTLM起到的就是认证&#xff0c;只认证Client的身份…

蓝桥杯15届C/C++B组省赛题目

问题描述 小蓝组织了一场算法交流会议&#xff0c;总共有 5050 人参加了本次会议。在会议上&#xff0c;大家进行了握手交流。按照惯例他们每个人都要与除自己以外的其他所有人进行一次握手 (且仅有一次)。但有 77 个人&#xff0c;这 77 人彼此之间没有进行握手 (但这 77 人与…

828华为云征文 | 在Huawei Cloud EulerOS系统中安装Docker的详细步骤与常见问题解决

前言 Docker是一种轻量级的容器技术&#xff0c;广泛用于应用程序的开发、部署和运维。在华为云的欧拉&#xff08;Huawei Cloud EulerOS&#xff09;系统上安装和运行Docker&#xff0c;虽然与CentOS有相似之处&#xff0c;但在具体实现过程中&#xff0c;可能会遇到一些系统…