当前位置: 首页 > news >正文

quillEditor 禁用复制粘贴图片,以及class转style等问题

<template>
  <div>
    <div class="search-term">
      <el-form :inline="true" :model="searchInfo" class="demo-form-inline">
        <el-form-item label="案例标题">
          <el-input v-model="searchInfo.title" placeholder="请输入案例标题" />
        </el-form-item>
        <el-form-item label="项目名称">
          <el-input
            v-model="searchInfo.projectName"
            placeholder="请输入项目名称"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="openDialog('addArticle')">
            新增案例
          </el-button>
        </el-form-item>
      </el-form>
    </div>
    <el-table
      :data="tableData"
      @sort-change="sortChange"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column
        type="index"
        :index="indexMethod"
        label="序号"
        width="100"
      />
      <!-- <el-table-column label="ID" min-width="50" prop="id" /> -->

      <el-table-column label="标题与副标题" min-width="300">
        <template slot-scope="scope">
          <div><strong>ID:</strong> {{ scope.row.id }}</div>
          <div><strong>标题:</strong> {{ scope.row.title }}</div>
          <div><strong>副标题:</strong> {{ scope.row.subtitle }}</div>
        </template>
      </el-table-column>
      <!-- <el-table-column label="省份与城市" min-width="150">
        <template slot-scope="scope">
          <div><strong>省份:</strong> {{ scope.row.provinceName }}</div>
          <div><strong>城市:</strong> {{ scope.row.cityName }}</div>
        </template>
      </el-table-column> -->
      <el-table-column label="项目名称" min-width="150">
        <template slot-scope="scope">
          {{ getProjectName(scope.row.projectId) }}
        </template>
      </el-table-column>
      <el-table-column label="小区" min-width="150">
        <template slot-scope="scope">
          {{ getCommunityName(scope.row.communityId) }}
        </template>
      </el-table-column>
      <el-table-column label="风格" min-width="150">
        <template slot-scope="scope">
          {{ getStyleName(scope.row.seriesId) }}
        </template>
      </el-table-column>
      <el-table-column label="房型" min-width="150">
        <template slot-scope="scope">
          {{ getHouseTypeName(scope.row.houseTypeId) }}
        </template>
      </el-table-column>
      <el-table-column label="面积与标签" min-width="200">
        <template slot-scope="scope">
          <div><strong>面积:</strong> {{ scope.row.area }} 平方米</div>
          <div><strong>标签:</strong> {{ scope.row.tags }}</div>
        </template>
      </el-table-column>
      <el-table-column label="推荐" min-width="100" prop="isRecommend">
        <template slot-scope="scope">
          <el-tag
            v-if="scope.row.isRecommend === '0'"
            effect="dark"
            size="mini"
            type="info"
            >否</el-tag
          >
          <el-tag v-else effect="dark" size="mini" type="success">是</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="创建时间" min-width="100" prop="createdAt" />
      <el-table-column label="操作" width="250">
        <template slot-scope="scope">
          <el-button
            size="small"
            type="primary"
            icon="el-icon-edit"
            @click="editArticle(scope.row)"
          >
            编辑
          </el-button>
          <el-button
            size="small"
            type="danger"
            icon="el-icon-delete"
            @click="deleteArticle(scope.row)"
          >
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      :current-page="page"
      :page-size="pageSize"
      :page-sizes="[10, 30, 50, 100]"
      :style="{ float: 'right', padding: '20px' }"
      :total="total"
      layout="total, sizes, prev, pager, next, jumper"
      @current-change="handleCurrentChange"
      @size-change="handleSizeChange"
    />
    <el-dialog
      :before-close="closeDialog"
      :title="dialogTitle"
      :visible.sync="dialogFormVisible"
    >
      <el-form
        ref="articleForm"
        :inline="false"
        :model="form"
        :rules="rules"
        label-width="80px"
      >
        <el-tabs v-model="activeName" @tab-click="handleClick">
          <el-tab-pane label="基本信息" name="first">
            <el-form-item label="标题" prop="title">
              <el-input
                v-model="form.title"
                placeholder="请输入标题"
                required
              />
            </el-form-item>
            <el-form-item label="副标题" prop="title">
              <el-input v-model="form.subtitle" placeholder="请输入副标题" />
            </el-form-item>
            <el-form-item label="案例封面" prop="picUrl">
              <el-input
                v-model="form.picUrl"
                placeholder="http://"
                disabled
                style="display: none"
              />
              <QnEleUpload :image-url="form.picUrl" @oss-url="ossPicUrl" />
            </el-form-item>
            <el-form-item label="全景链接">
              <el-row style="padding-top: 0px">
                <el-col :span="4">
                  <el-select v-model="form.panoramaType" placeholder="请选择">
                    <el-option
                      v-for="item in panoramaList"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-col>
                <el-col :span="12" style="margin-left: 10px">
                  <el-input
                    v-model="form.panoramaUrl"
                    placeholder="请输入全景链接"
                  />
                </el-col>
              </el-row>
            </el-form-item>
            <el-form-item label="项目" required>
              <el-select
                v-model="projectId"
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="(item, index) in projectList"
                  :key="index"
                  :label="item.title"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
            <!-- <el-form-item label="地区" required>
              <div style="display: flex">
                <el-select
                  v-model="provinceId"
                  placeholder="请选择"
                  style="margin-right: 10px"
                >
                  <el-option
                    v-for="(item, index) in provinceList"
                    :key="index"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
                <el-select v-model="cityId" placeholder="请选择">
                  <el-option
                    v-for="(item, index) in cityList"
                    :key="index"
                    :label="item.name"
                    :value="item.id"
                  />
                </el-select>
              </div>
            </el-form-item> -->
            <el-form-item label="小区">
              <el-select
                v-model="communityId"
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="(item, index) in communityList"
                  :key="index"
                  :label="item.name"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="户型名称" required>
              <el-select
                v-model="houseTypeId"
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="(item, index) in houseTypeList"
                  :key="index"
                  :label="item.title"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="风格">
              <el-select
                v-model="seriesId"
                placeholder="请选择"
                style="width: 100%"
              >
                <el-option
                  v-for="(item, index) in seriesList"
                  :key="index"
                  :label="item.title"
                  :value="item.id"
                />
              </el-select>
            </el-form-item>
            <!-- <el-form-item label="案例视频" prop="videoUrl">
              <el-input v-model="form.videoUrl" placeholder="http://" />
              <QnEleUploadVedio :image-url="form.videoUrl" @oss-url="ossPicUrlVideo" />
              <i class="warning">为了更好的保持兼容性建议上传mp4格式</i>
            </el-form-item> -->
            <el-form-item label="标签" prop="tags">
              <el-input
                v-model="form.tags"
                placeholder="请输入标签,多个标签用 | 分割"
              />
            </el-form-item>
            <el-form-item label="面积" prop="area">
              <el-input v-model="form.area" placeholder="请输入面积" required>
                <template slot="append">平方米</template>
              </el-input>
            </el-form-item>
            <el-form-item label="是否推荐" prop="isRecommend">
              <el-switch
                v-model="form.isRecommend"
                :active-value="'1'"
                :inactive-value="'0'"
              />
            </el-form-item>
          </el-tab-pane>

          <el-tab-pane label="案例详情" name="second">
            <!-- <el-form-item label="案例详情">
              <el-input v-model="form.skill" type="textarea" maxlength="150" show-word-limit />
            </el-form-item> -->
            <div style="min-height: 500px">
              <QnEleUpload
                v-show="false"
                ref="upload"
                class="avatar-uploader"
                :image-url="form.avatar"
                @oss-url="onUploadHandler"
              />
              <quill-editor
                ref="myQuillEditor"
                v-model="form.detail"
                :options="editorOption"
                style="min-height: 300px"
              />
            </div>
          </el-tab-pane>
        </el-tabs>
      </el-form>

      <div slot="footer" class="dialog-footer">
        <el-button @click="closeDialog">取 消</el-button>
        <el-button type="primary" @click="enterDialog">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<style>
#editor—wrapper {
  border: 1px solid #ccc;
  z-index: 100; /* 按需定义 */
}
#toolbar-container {
  border-bottom: 1px solid #ccc;
}
#editor-container {
  height: 500px;
}
</style>
<script>
// 获取列表内容封装在mixins内部  getTableData方法 初始化已封装完成 条件搜索时候 请把条件安好后台定制的结构体字段 放到 this.searchInfo 中即可实现条件搜索

import {
  getArticleList,
  createArticle,
  updateArticle,
  deleteArticle
  // deleteArticlesByIds
} from '@/api/article'
import { getProjectList } from '@/api/project'

import { getCityList } from '@/api/city'
import { getCommunityList } from '@/api/community'
import { getSeriesList } from '@/api/series'

import infoList from '@/mixins/infoList'
import { toSQLLine } from '@/utils/stringFun'
import QnEleUpload from '@/components/oss/qiniu'
// import QnEleUploadVedio from '@/components/oss/qiniuVideo'
import * as Quill from 'quill'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
// 引用字号和字体css
import '@/utils/quillEditor.css'
// 设置字体大小
const fontSizeStyle = Quill.import('attributors/style/size') // 引入这个后会把样式写在style上
fontSizeStyle.whitelist = ['12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px']
Quill.register(fontSizeStyle, true)
// 设置字体样式
const Font = Quill.import('attributors/style/font') // 引入这个后会把样式写在style上
const fonts = [
  'SimSun',
  'SimHei',
  'Microsoft-YaHei',
  'KaiTi',
  'FangSong'
]
Font.whitelist = fonts // 将字体加入到白名单
Quill.register(Font, true)
// 设置文字水平方式
var Align = Quill.import('attributors/style/align')
Align.whitelist = ['right', 'center', 'justify']
Quill.register(Align, true)
const toolbarOptions = [
  ['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: ['12px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px'] }], // 字体大小
  [{ header: [1, 2, 3, 4, 5, 6] }], // 标题
  [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  // [{ font: ['songti'] }], // 字体种类
  [{ align: [] }], // 对齐方式
  ['clean'], // 清除文本格式
  ['image'] // 链接、图片,需要视频的可以加上video

]

// import * as Quill from 'quill'
// 调整上传图片大小
import ImageResize from 'quill-image-resize-module' // 引用
import { ImageDrop } from 'quill-image-drop-module'
// import { json } from 'body-parser'
Quill.register('modules/imageResize', ImageResize) // 注册
Quill.register('modules/imageDrop', ImageDrop)
import { getHouseTypeList } from '@/api/houseType'

export default {
  name: 'Article',
  // 注册组件
  components: {
    QnEleUpload
    // QnEleUploadVedio
  },
  filters: {},

  mixins: [infoList],
  data () {
    return {
      panoramaList: [{ value: 0, label: '酷家乐', prefix: 'http://pano478.p.kujiale.com/' }, { value: 1, label: '小红屋', prefix: 'http://pano478.p.xiaohongwu.com/' }],
      isRecommend: 0,
      cityList: [],
      provinceId: 0,
      provinceName: '',
      cityId: 0,
      cityName: '',
      projectList: [],
      projectId: '1',
      provinceList: [],
      communityList: [{ id: '0', name: '请选择' }],
      communityId: '0',
      seriesList: [],
      seriesId: 0,
      houseTypeList: [],
      houseTypeId: 0,
      content: '', // 双向数据绑定数据
      tags: '',
      editorOption: {
        modules: {
          // 重写剪贴板模块
          clipboard: {
            matchers: [
              [Node.ELEMENT_NODE, (node, delta) => {
                // 拦截图片标签
                if (node.tagName === 'IMG') {
                  // 返回空 Delta 阻止插入
                  return new Delta().retain(delta.length());
                }
                return delta;
              }]
            ]
          },
          toolbar: {
            container: toolbarOptions, // 工具栏
            handlers: {
              'image': function (value) {
                if (value) {
                  // 调用el-upload的click点击事件实现文件上传
                  document.querySelector('.avatar-uploader input').click()
                } else {
                  this.quill.format('image', false)
                }
              }
            }
          },
          // 调整图片大小
          imageResize: {
            displayStyles: {
              backgroundColor: 'black',
              border: 'none',
              color: 'white'
            },
            modules: ['Resize', 'DisplaySize', 'Toolbar']
          }

        },
        placeholder: '请输入案例详情'
      },
      activeName: 'first',
      deleteVisible: false,
      listApi: getArticleList,
      dialogFormVisible: false,
      dialogTitle: '新增案例',
      articles: [],
      form: {
        id: 0,
        isRecommend: 0,
        projectId: '1',
        title: '',
        subtitle: '',
        picUrl: '',
        sort: 1,
        detail: '',
        provinceId: 0,
        provinceName: '',
        cityId: 0,
        cityName: '',
        tags: '',
        communityId: '0',
        seriesId: 0,
        houseTypeId: 0,
        area: '',
        panoramaUrl: '',
        panoramaType: 0,
        panoramaPrefix: ''
      },
      tab: 'first',
      rules: {
        title: [{ required: true, message: '请选输入案例标题', trigger: 'blur' }],
        picUrl: [{ required: true, message: '请上传案例封面', trigger: 'blur' }],
        detail: [{ required: true, message: '案例详情不能为空', trigger: 'blur' }],
        area: [{ required: true, message: '面积不能为空', trigger: 'blur' }],
        // seriesId: [{ required: true, message: '系列不能为空', trigger: 'blur' }],
        houseTypeId: [{ required: true, message: '风格不能为空', trigger: 'blur' }],
        panoramaUrl: [{
          required: false,
          validator: this.validatePanoramaUrl,
          trigger: 'blur'
        }]

      }
    }
  },
  watch: {

    seriesId (val) {
      this.form.seriesId = val
    },
    communityId (val) {
      this.form.communityId = val
    },
    projectId (val) {
      this.form.projectId = this.projectId
    },
    houseTypeId (val) {
      this.form.houseTypeId = val
    },
    provinceId (val) {
      this.cityList = this.provinceList.find(item => item.id === val).children
      console.log(1112, this.cityList)
      this.provinceName = this.provinceList.find(item => item.id === val).name
      this.cityId = this.cityList[0].id
      this.form.cityId = this.cityList[0].id
      this.form.cityName = this.cityList[0].name
      this.form.provinceName = this.provinceName
      this.form.provinceId = val
    },
    cityId (val) {
      this.cityId = val
      this.form.cityId = val
      this.form.cityName = this.cityList.find(item => item.id === val).name
    }
    // isRecommend (val) {
    //   this.form.isRecommend = Number(val)
    // }
  },
  async created () {
    const params = this.$route.params
    this.searchInfo.projectName = params.projectName
    this.getTableData()
    this.initForm()
  },
  methods: {

    // 计算序号
    indexMethod (index) {
      return (this.page - 1) * this.pageSize + index + 1
    },
    validatePanoramaUrl (rule, value, callback) {
      if (value && !value.startsWith('http')) {
        callback(new Error('必须以http开头'))
      } else {
        callback()
      }
    },
    getProjectName (projectId) {
      console.log(111111, projectId)
      const project = this.projectList.find(item => item.id === projectId)
      return project ? project.title : '-'
    },
    getCommunityName (communityId) {
      const community = this.communityList.find(item => item.id === communityId)
      return community ? community.name : ''
    },
    getStyleName (seriesId) {
      const series = this.seriesList.find(item => item.id === seriesId)
      return series ? series.title : ''
    },
    getHouseTypeName (houseTypeId) {
      const houseType = this.houseTypeList.find(item => item.id === houseTypeId)
      return houseType ? houseType.title : ''
    },
    async getHouseTypeList () {
      const res = await getHouseTypeList({ page: 1, pageSize: 1000 })
      if (res.code === '0') {
        this.houseTypeList = res.data.list
        this.houseTypeId = this.houseTypeList[0].id
        this.form.houseTypeId = this.houseTypeId
      }
    },
    async getSeriesList () {
      const res = await getSeriesList({ page: 1, pageSize: 1000 })
      if (res.code === '0') {
        this.seriesList = res.data.list
        this.seriesId = this.seriesList[0].id
        this.form.seriesId = this.seriesId
      }
    },
    async getCommunityList () {
      const res = await getCommunityList({ page: 1, pageSize: 10000 })
      if (res.code === '0') {
        this.communityList = [{ id: '0', name: '请选择' }, ...res.data.list]
        // this.communityList = res.data.list
        this.communityId = this.communityList[0].id
        this.form.communityId = this.communityId
      }
    },
    async getProjectList () {
      const res = await getProjectList({ page: 1, pageSize: 1000 })
      if (res.code === '0') {
        this.projectList = res.data.list
        this.projectId = this.projectList[0].id
        this.form.projectId = this.projectId
      }
    },
    async getCityLists () {
      const res = await getCityList({})
      if (res.code === '0') {
        this.provinceList = res.data.list
        this.provinceId = this.provinceList[0].id
        this.provinceName = this.provinceList[0].name
        this.form.provinceId = this.provinceId
        this.form.provinceName = this.provinceName
        this.form.cityId = this.provinceList[0].children[0].id
        this.form.cityName = this.provinceList[0].children[0].name
      }
    },
    onEditorBlur (val) { }, // 失去焦点触发事件
    onEditorFocus () { }, // 获得焦点触发事件
    onEditorChange (val) { }, // 内容改变触发事件
    ossPicUrl (e) {
      this.form.picUrl = e.url
    },
    ossPicUrlVideo (e) {
      this.form.videoUrl = e.url
    },
    async onUploadHandler (e) {
      console.log(e)
      const imageUrl = e.url

      // 获取光标所在位置
      const quill = this.$refs.myQuillEditor.quill
      const length = quill.getSelection().index
      // 插入图片
      quill.insertEmbed(length, 'image', imageUrl)
      // 调整光标到最后
      quill.setSelection(length + 1)
      // this.content += url
    },
    async onUploadHandlerCaseDescription (e) {
      console.log(e)
      const imageUrl = e.url

      // 获取光标所在位置
      const quill = this.$refs.myQuillEditorCaseDescription.quill
      const length = quill.getSelection().index
      // 插入图片
      quill.insertEmbed(length, 'image', imageUrl)
      // 调整光标到最后
      quill.setSelection(length + 1)
      // this.content += url
    },
    handleClick (tab, event) {
      console.log(tab, event)
    },
    //  选中article
    handleSelectionChange (val) {
      this.articles = val
    },
    // async onDelete() {
    //   const ids = this.articles.map(item => item.id)
    //   const res = await deleteArticlesByIds({ ids })
    //   if (res.code === '0') {
    //     this.$message({
    //       type: 'success',
    //       message: res.message && '删除成功~'
    //     })
    //     if (this.tableData.length === ids.length && this.page > 1) {
    //       this.page--
    //     }
    //     this.deleteVisible = false
    //     this.getTableData()
    //   }
    // },
    // 排序
    sortChange ({ prop, order }) {
      if (prop) {
        this.searchInfo.orderKey = toSQLLine(prop)
        this.searchInfo.desc = order === 'descending'
      }
      this.getTableData()
    },
    // 条件搜索前端看此方法
    onSubmit () {
      this.page = 1
      this.pageSize = 10
      this.getTableData()
    },
    async initForm () {
      // this.$refs.articleForm.resetFields()
      this.form = {
        id: 0,
        isRecommend: 0,
        projectId: '1',
        title: '',
        subtitle: '',
        picUrl: '',
        sort: 1,
        detail: '',
        provinceId: 0,
        provinceName: '',
        cityId: 0,
        cityName: '',
        communityId: 0,
        seriesId: 0,
        houseTypeId: 0,
        area: '',
        panoramaType: 0,
        panoramaPrefix: ''
      }
      await this.getCityLists()
      await this.getProjectList()
      await this.getCommunityList()
      await this.getSeriesList()
      await this.getHouseTypeList()
    },
    closeDialog () {
      // this.initForm()
      this.dialogFormVisible = false
    },
    openDialog (type) {
      switch (type) {
        case 'addArticle':
          this.initForm()
          this.dialogTitle = '新增案例'
          break
        case 'edit':
          this.dialogTitle = '编辑案例'
          break
        default:
          break
      }
      this.activeName = 'first'
      this.type = type
      this.dialogFormVisible = true
    },
    async editArticle (row) {
      // const res = await getArticleById({ id: row.id })
      // if (res.code === '0') {
      //   this.form = res.data
      //   this.openDialog('edit')
      // }
      // this.initForm()

      console.log(2222, row)

      // this.$nextTick(() => {
      this.form = row
      this.communityId = row.communityId
      this.projectId = row.projectId
      this.provinceId = row.provinceId
      this.cityId = row.cityId
      this.houseTypeId = row.houseTypeId
      this.seriesId = row.seriesId
      this.isRecommend = Number(row.isRecommend)
      // this.form.isRecommend = Number(row.isRecommend)
      // this.form.isShow = Number(row.isShow)
      // this.openDialog('edit')
      // })
      this.openDialog('edit')
    },
    async deleteArticle (row) {
      this.$confirm(
        '此操作将永久删除该条记录, 是否继续?',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      )
        .then(async () => {
          const res = await deleteArticle({ id: row.id })
          if (res.code === '0') {
            this.$message({
              type: 'success',
              message: '删除成功!'
            })
            if (this.tableData.length === 1 && this.page > 1) {
              this.page--
            }
            this.getTableData()
          }
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          })
        })
    },
    async enterDialog () {
      this.$refs.articleForm.validate(async valid => {
        if (valid) {
          for (let i = 0; i < this.panoramaList.length; i++) {
            if (this.form.panoramaType == this.panoramaList[i].value) {
              this.form.panoramaPrefix = this.panoramaList[i].prefix
            }
          }
          // this.form.mentorId = Number(this.form.mentorId)
          switch (this.type) {
            case 'addArticle':
              {
                const res = await createArticle(this.form)
                if (res.code === '0') {
                  this.$message({
                    type: 'success',
                    message: '添加成功',
                    showClose: true
                  })
                }
                this.getTableData()
                this.closeDialog()
              }

              break
            case 'edit':
              {
                const res = await updateArticle(this.form)
                if (res.code === '0') {
                  this.$message({
                    type: 'success',
                    message: '编辑成功',
                    showClose: true
                  })
                }
                this.getTableData()
                this.closeDialog()
              }
              break
            default:
              // eslint-disable-next-line no-lone-blocks
              {
                this.$message({
                  type: 'error',
                  message: '未知操作',
                  showClose: true
                })
              }
              break
          }
        }
      })
    }
  }
}
</script>

<style scoped lang="scss">
.button-box {
  padding: 10px 20px;
  .el-button {
    float: right;
  }
}
.el-tag--mini {
  margin-left: 5px;
}
.warning {
  color: #dc143c;
}
.quill-editor {
  height: 400px;
}

.editor {
  line-height: normal !important;
  height: 400px;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12"]::before {
  content: "12px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14"]::before {
  content: "14px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16"]::before {
  content: "16px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18"]::before {
  content: "18px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20"]::before {
  content: "20px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22"]::before {
  content: "22px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24"]::before {
  content: "24px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28"]::before {
  content: "28px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32"]::before {
  content: "32px";
  vertical-align: top;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="36"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36"]::before {
  content: "36px";
  vertical-align: top;
}

/* 这个是字号数字对应的px值 */
.ql-editor .ql-size-12 {
  font-size: 12px;
}
.ql-editor .ql-size-14 {
  font-size: 14px;
}
.ql-editor .ql-size-16 {
  font-size: 16px;
}
.ql-editor .ql-size-18 {
  font-size: 18px;
}
.ql-editor .ql-size-20 {
  font-size: 20px;
}
.ql-editor .ql-size-22 {
  font-size: 22px;
}
.ql-editor .ql-size-24 {
  font-size: 24px;
}
.ql-editor .ql-size-28 {
  font-size: 28px;
}
.ql-editor .ql-size-32 {
  font-size: 32px;
}
.ql-editor .ql-size-36 {
  font-size: 36px;
}

/* 选择字号富文本字的大小 */
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12"]::before {
  font-size: 12px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14"]::before {
  font-size: 14px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16"]::before {
  font-size: 16px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18"]::before {
  font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20"]::before {
  font-size: 20px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22"]::before {
  font-size: 22px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24"]::before {
  font-size: 24px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28"]::before {
  font-size: 28px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32"]::before {
  font-size: 32px;
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36"]::before {
  font-size: 36px;
}
</style>

quillEditor.css

.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";
}

/* 字号设置 */
/* 默认字号 */
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="12px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="12px"]::before {
  content: "12px";
  font-size: 12px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
  content: "14px";
  font-size: 14px;
}

.ql-size-14px {
  font-size: 14px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
  content: "16px";
  font-size: 16px;
}

.ql-size-16px {
  font-size: 16px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
  content: "18px";
  font-size: 18px;
}

.ql-size-18px {
  font-size: 18px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
  content: "20px";
  font-size: 20px;
}

.ql-size-20px {
  font-size: 20px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="22px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="22px"]::before {
  content: "22px";
  font-size: 22px;
}

.ql-size-22px {
  font-size: 22px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="26px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="26px"]::before {
  content: "26px";
  font-size: 26px;
}

.ql-size-26px {
  font-size: 26px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="28px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="28px"]::before {
  content: "28px";
  font-size: 28px;
}

.ql-size-28px {
  font-size: 28px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="30px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="30px"]::before {
  content: "30px";
  font-size: 30px;
}

.ql-size-30px {
  font-size: 30px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="32px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="32px"]::before {
  content: "32px";
  font-size: 32px;
}

.ql-size-32px {
  font-size: 32px;
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="36px"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="36px"]::before {
  content: "36px";
  font-size: 36px;
}

.ql-size-36px {
  font-size: 36px;
}


config.js

export const titleConfig = [
  { Choice: '.ql-bold', title: '加粗' },
  { Choice: '.ql-italic', title: '斜体' },
  { Choice: '.ql-underline', title: '下划线' },
  { Choice: '.ql-header', title: '段落格式' },
  { Choice: '.ql-strike', title: '删除线' },
  { Choice: '.ql-blockquote', title: '块引用' },
  { Choice: '.ql-code', title: '插入代码' },
  { Choice: '.ql-code-block', title: '插入代码段' },
  { Choice: '.ql-font', title: '字体' },
  { Choice: '.ql-size', title: '字体大小' },
  { Choice: '.ql-list[value="ordered"]', title: '编号列表' },
  { Choice: '.ql-list[value="bullet"]', title: '项目列表' },
  { Choice: '.ql-direction', title: '文本方向' },
  { Choice: '.ql-header[value="1"]', title: 'h1标题' },
  { Choice: '.ql-header[value="2"]', title: 'h2标题' },
  { Choice: '.ql-align', title: '对齐方式' },
  { Choice: '.ql-color', title: '字体颜色' },
  { Choice: '.ql-background', title: '背景颜色' },
  { Choice: '.ql-image', title: '图像' },
  { Choice: '.ql-video', title: '视频' },
  { Choice: '.ql-link', title: '添加链接' },
  { Choice: '.ql-table', title: '添加表格' },
  { Choice: '.ql-formula', title: '插入公式' },
  { Choice: '.ql-clean', title: '清除字体格式' },
  { Choice: '.ql-script[value="sub"]', title: '下标' },
  { Choice: '.ql-script[value="super"]', title: '上标' },
  { Choice: '.ql-indent[value="-1"]', title: '向左缩进' },
  { Choice: '.ql-indent[value="+1"]', title: '向右缩进' },
  { Choice: '.ql-header .ql-picker-label', title: '标题大小' },
  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '标题一' },
  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '标题二' },
  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '标题三' },
  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '标题四' },
  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '标题五' },
  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '标题六' },
  { Choice: '.ql-header .ql-picker-item:last-child', title: '标准' },
  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '小号' },
  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '大号' },
  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '标准' },
  { Choice: '.ql-align', title: '文本对齐' },
  { Choice: '.ql-align .ql-picker-item:first-child', title: '居左对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
]

相关文章:

  • 【C++ 函数重载】—— 现代编译技术下的多态表达与性能优化
  • 【leetcode hot 100 56】合并区间
  • 【计算机网络】Socket
  • CSDN markdown 操作指令等
  • 动漫短剧开发公司,短剧小程序搭建快速上线
  • Springboot整合WebSocket+Redis以及微信小程序如何调用
  • 2000-2020年各省地方财政一般预算收入数据
  • 【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-附录B-严格模式
  • FastGPT 源码:基于 LLM 实现 Rerank (含Prompt)
  • 深度学习-142-Text2SQL之基于langchain的少量样本提示词模板FewShotPromptTemplate的应用基础(一)
  • maven推送jar包到nexus
  • 前端大文件上传
  • 鬼泣:项目前置设置杂项
  • 【每日学点HarmonyOS Next知识】Web Header更新、状态变量嵌套问题、自定义弹窗、stack圆角、Flex换行问题
  • C++第二十讲:C++11
  • 权限系统设计方案实践(Spring Security + RBAC 模型)
  • DeepSeek DeepEP学习(一)low latency dispatch
  • sa-token全局过滤器之写法优化(包含设置Order属性)
  • [密码学实战]Java实现TLS 1.2单向认证
  • k8s面试题总结(九)
  • 自己做蛋糕有什么网站吗/网络营销产品的首选产品
  • 白领兼职做网站/免费做网站怎么做网站吗
  • 做川菜的网站/百度网盘登录入口网页版
  • 做神马网站快速排/企业营销策划有限公司
  • 深圳福田有哪些公司/推广优化网站排名
  • 企业门户网站建设论文/关键词有哪几种