quill-editor扩展的正确姿势

2023-05-16

一、无关的插曲
曾几何时,风云万里,万海桑田。耕耘于代码堆里多年。做过android移动端,做过web端,做过java后端和.net,也做过python数据分析。但真正扩展源码的亦有亦无。如今更趋向与智能化,重复的机器可代替,如此节约时间甚好。我们努力前行,我们都在路上,我们有自己的最求和向往,但任凭达到何等境地,都无法避免的一个,那就是终结陨落。所以在陨落之前,有的人擅长了独门绝技,有的人擅长多种技术柔和。反正天外有天,人外有人。兴趣决定了我们的高度。敲代码,是最穷的,但敲代码是最有创意的,如此甚好!

二、需求场景
最近前端的需求是要求一个富文本编辑器,里面可插入音频,视频和图片等。。。然后就飞发发的查资料去了,有国产wangEditor,齐全但臃肿的百度UEditor,有文档齐全的Kindeditor,也有不错的Tinymce。感觉各有优缺点吧!最终还是选择vue-quill-editor,就是图它的方便,扩展性好,如此而已。

三、插入图片
在文本编辑器中插入图片,直接使用插件中就有的功能就行,至于图片可拖动和大小变化,在文件里分别引入一下模块即可:

import * as Quill from 'quill'

import ImageResize from 'quill-image-resize-module' //调节图片大小
Quill.register('modules/imageResize', ImageResize)
import { ImageDrop } from 'quill-image-drop-module' // 图片可拖动
Quill.register('modules/imageDrop', ImageDrop)

到此还不行,还得配置quill-editor的options

editorOption: {
  placeholder: '请输入',
  theme: 'snow', // or 'bubble' 
  modules: {
    toolbar: {
      container: '#toolbar',
      handlers: handlers
    },
    imageDrop: true,
    imageResize: {
      displayStyles: {
        backgroundColor: 'black',
        border: 'none',
        color: 'white'
      },
      modules: ['Resize', 'DisplaySize', 'Toolbar']
    }
  }
}

关键在这里哟:

imageDrop: true,
imageResize: {
  displayStyles: {
    backgroundColor: 'black',
    border: 'none',
    color: 'white'
  },
  modules: ['Resize', 'DisplaySize', 'Toolbar']
}

这样图片我们差不多处理好了

四、视频的处理
由于quill-editor原生提供的视频会插入iframe,可能会导致其他终端无法正常播放,所以我们得扩展一下,让其直接插入video。
1、新建video.js文件:

import { Quill } from 'vue-quill-editor'

// 源码中是import直接倒入,这里要用Quill.import引入
const BlockEmbed = Quill.import('blots/block/embed')
const Link = Quill.import('formats/link')

const ATTRIBUTES = ['height', 'width']

class Video extends BlockEmbed {
  static create (value) {
    const node = super.create(value)
    // 添加video标签所需的属性
    node.setAttribute('controls', 'controls')
    node.setAttribute('type', 'video/mp4')
    node.setAttribute('src', this.sanitize(value))
    return node
  }

  static formats (domNode) {
    return ATTRIBUTES.reduce((formats, attribute) => {
      if (domNode.hasAttribute(attribute)) {
        formats[attribute] = domNode.getAttribute(attribute)
      }
      return formats
    }, {})
  }

  static sanitize (url) {
    return Link.sanitize(url) // eslint-disable-line import/no-named-as-default-member
  }

  static value (domNode) {
    return domNode.getAttribute('src')
  }

  format (name, value) {
    if (ATTRIBUTES.indexOf(name) > -1) {
      if (value) {
        this.domNode.setAttribute(name, value)
      } else {
        this.domNode.removeAttribute(name)
      }
    } else {
      super.format(name, value)
    }
  }

  html () {
    const { video } = this.value()
    return `<a href="${video}">${video}</a>`
  }
}
Video.blotName = 'video' // 这里不用改,楼主不用iframe,直接替换掉原来,如果需要也可以保留原来的,这里用个新的blot
Video.className = 'ql-video'
Video.tagName = 'video' // 用video标签替换iframe

export default Video

	2、在插件页面引入新建的video.js:
import Video from './video'
Quill.register(Video, true)

五、插入音频
插入的音频跟视频的一样,复制一份video.js,将其改为audio.js,然后将里面video改成audio就行。

六、完整的quill-edittor如下

<template>
  <div>
    <el-card style="height: 610px;">
      <quill-editor v-model="content"
                    ref="myQuillEditor"
                    style="height: 500px;"
                    :options="editorOption">
        <!-- 自定义toolar -->
        <div id="toolbar"
             slot="toolbar">
          <!-- Add a bold button -->
          <button class="ql-bold"
                  title="加粗">Bold</button>
          <button class="ql-italic"
                  title="斜体">Italic</button>
          <button class="ql-underline"
                  title="下划线">underline</button>
          <button class="ql-strike"
                  title="删除线">strike</button>
          <button class="ql-blockquote"
                  title="引用"></button>
          <button class="ql-code-block"
                  title="代码"></button>
          <button class="ql-header"
                  value="1"
                  title="标题1"></button>
          <button class="ql-header"
                  value="2"
                  title="标题2"></button>
          <!--Add list -->
          <button class="ql-list"
                  value="ordered"
                  title="有序列表"></button>
          <button class="ql-list"
                  value="bullet"
                  title="无序列表"></button>
          <!-- Add font size dropdown -->
          <select class="ql-header"
                  title="段落格式">
            <option selected>段落</option>
            <option value="1">标题1</option>
            <option value="2">标题2</option>
            <option value="3">标题3</option>
            <option value="4">标题4</option>
            <option value="5">标题5</option>
            <option value="6">标题6</option>
          </select>
          <select class="ql-size"
                  title="字体大小">
            <option value="10px">10px</option>
            <option value="12px">12px</option>
            <option value="14px">14px</option>
            <option value="16px"
                    selected>16px</option>
            <option value="18px">18px</option>
            <option value="20px">20px</option>
          </select>
          <select class="ql-font"
                  title="字体">
            <option value="SimSun">宋体</option>
            <option value="SimHei">黑体</option>
            <option value="Microsoft-YaHei">微软雅黑</option>
            <option value="KaiTi">楷体</option>
            <option value="FangSong">仿宋</option>
            <option value="Arial">Arial</option>
          </select>
          <!-- Add subscript and superscript buttons -->
          <select class="ql-color"
                  value="color"
                  title="字体颜色"></select>
          <select class="ql-background"
                  value="background"
                  title="背景颜色"></select>
          <select class="ql-align"
                  value="align"
                  title="对齐"></select>
          <button class="ql-clean"
                  title="还原"></button>
          <button class="ql-image"
                  title="图片"></button>
          <!-- <button class="ql-video"
                  title="视频"
                  @click="spClick"></button> -->
          <!-- You can also add your own -->
          <button id="custom-button"
                  @click.prevent="fnOpenUploadVideo('video','添加视频')"
                  title="视频">
            <i class="el-icon-film"></i>
          </button>
          <button id="custom-button"
                  @click.prevent="fnOpenUploadVideo('audio','添加音频')"
                  title="音频">
            <i class="el-icon-headset"></i>
          </button>
        </div>
      </quill-editor>
    </el-card>
    <el-dialog append-to-body
               :title="title"
               width="30%"
               :visible.sync="dialogFnOpenUpload"
               :close-on-click-modal="false">
      <!-- <file-upload accept="https://www.imflea.cn/ZeroFile/flea/file/upload" :data_extra="data_extra" @fnUploadSucess="fnUploadSucess" @fnCloseDialog="dialogFnOpenUpload = false" ref="fileUpload"></file-upload> -->
      <el-upload class="avatar-uploader"
                 action="https://www.imflea.cn/ZeroFile/flea/file/upload"
                 :on-success="fnUploadSucess"
                 :before-upload="beforeAvatarUpload"
                 ref="fileUpload">
        <i class="el-icon-upload avatar-uploader-icon"></i>
      </el-upload>
    </el-dialog>
  </div>
</template>

<script>
import * as Quill from 'quill'
import {
  quillEditor
} from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import BMF from 'browser-md5-file'
import ImageResize from 'quill-image-resize-module' //调节图片大小
import { ImageDrop } from 'quill-image-drop-module' // 图片可拖动
// 这里引入修改过的video模块并注册
import Video from './video'
import Audio from './audio'

Quill.register(Video, true)
Quill.register(Audio, true)

Quill.register('modules/imageResize', ImageResize)
Quill.register('modules/imageDrop', ImageDrop)

const bmf = new BMF()

// 自定义字体大小
let Size = Quill.import('attributors/style/size')
Size.whitelist = ['10px', '12px', '14px', '16px', '18px', '20px']
Quill.register(Size, true)

// 自定义字体类型
var fonts = ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif',
  '宋体', '黑体'
]
var Font = Quill.import('formats/font')
Font.whitelist = fonts
Quill.register(Font, true)

const uploadConfig = {
  fileRead: '', // 图片读取地址
  action: '',  // 必填参数 图片上传地址
  methods: 'POST',  // 必填参数 图片上传方式
  token: '',  // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
  name: 'img',  // 必填参数 文件的参数名
  size: 500,  // 可选参数   图片大小,单位为Kb, 1M = 1024Kb
  accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon'  // 可选 可上传的图片格式
}

function handle (file, callback) {
  bmf.md5(
    file,
    (err, md5) => {
      callback(md5)
    }
  )
}

const handlers = {
  image: function image () {
    var selft = this
    var fileInput = this.container.querySelector('input.ql-image[type=file]')
    if (fileInput === null) {
      fileInput = document.createElement('input')
      fileInput.setAttribute('type', 'file')
      // 设置图片参数名
      if (uploadConfig.name) {
        fileInput.setAttribute('name', uploadConfig.name)
      }
      // 可设置上传图片的格式
      fileInput.setAttribute('accept', uploadConfig.accept)
      fileInput.classList.add('ql-image')
      // 监听选择文件
      fileInput.addEventListener('change', function () {
        var file = fileInput.files[0]
        // 创建formData
        var formData = new FormData()
        var md5 = ''
        handle(file, r => {
          md5 = r
          var size = file.size
          // formData.append(uploadConfig.name, file)
          formData.append('md5', md5)
          formData.append('fileSize', size)
          formData.append('userId', '00000000000000000000000000000000')
          formData.append('businessSysCode', '1000000010000000000000000000')
          formData.append('businessSysModuleCode', '0000000000000000000000000000002')
          formData.append('businessId', 'B00000000000000000000000000000001')
          formData.append('name', file.name)
          formData.append('type', file.type)
          formData.append('lastModified', file.lastModified)
          formData.append('lastModifiedDate', file.lastModifiedDate)
          formData.append('size', size)
          formData.append('file', file)
          // 如果需要token且存在token
          if (uploadConfig.token) {
            formData.append('token', uploadConfig.token)
          }

          // 图片上传
          var xhr = new XMLHttpRequest()

          xhr.open(uploadConfig.methods, uploadConfig.action, true)
          xhr.setRequestHeader('Access-Control-Allow-Headers', '*')
          xhr.setRequestHeader('Access-Control-Allow-Origin', '*')
          // 上传数据成功,会触发
          xhr.onload = function () {
            if (xhr.status === 200) {
              var res = JSON.parse(xhr.responseText)
              let length = selft.quill.getSelection(true).index
              //这里很重要,你图片上传成功后,img的src需要在这里添加,res.path就是你服务器返回的图片链接。            
              selft.quill.insertEmbed(length, 'image', uploadConfig.fileRead + res.model.data.id)
              selft.quill.setSelection(length + 1)
            }
            fileInput.value = ''
          }
          // 开始上传数据
          xhr.upload.onloadstart = function () {
            fileInput.value = ''
          }
          // 当发生网络异常的时候会触发,如果上传数据的过程还未结束
          xhr.upload.onerror = function () {
          }
          // 上传数据完成(成功或者失败)时会触发
          xhr.upload.onloadend = function () {
            // console.log('上传结束')
          }
          xhr.send(formData)
        })
      })
      this.container.appendChild(fileInput)
    }
    fileInput.click();
  }
};

export default {
  name: 'ui-quill-editor',
  components: {
    quillEditor
  },
  props: {
    value: {
      type: String
    }
  },
  watch: {
    // 监听prop传的value,如果父级有变化了,将子组件的myValue也跟着变,达到父变子变的效果
    value (newVal) {
      this.content = newVal
    },
    // 监听content,如果子组件中的内容变化了,通知父级组件,将新的值告诉父级组件,我更新了,父级组件接受到值后页就跟着变了
    // 参考官网:https://cn.vuejs.org/v2/guide/components-custom-events.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84-v-model
    content (newVal) {
      this.$emit('input', newVal)
    }
  },
  data () {
    return {
      content: this.value,
      type: null,
      editorOption: {
        placeholder: '请输入',
        theme: 'snow', // or 'bubble' 
        modules: {
          toolbar: {
            container: '#toolbar',
            handlers: handlers
          },
          imageDrop: true,
          imageResize: {
            displayStyles: {
              backgroundColor: 'black',
              border: 'none',
              color: 'white'
            },
            modules: ['Resize', 'DisplaySize', 'Toolbar']
          }
        }
      },
      uploadType: '',
      title: '',
      dialogFnOpenUpload: false
    }
  },
  computed: {
    editor () {
      return this.$refs.myQuillEditor.quill
    }
  },
  methods: {
    beforeAvatarUpload (file) {
      if (this.uploadType === 'video') {
        this.type = file.type
        const isJPG = file.type === 'video/mp4'
        if (!isJPG) {
          this.$message.error('上传视频只能是 mp4 格式!')
        }
        return isJPG
      } else {
        this.type = file.type
        const isJPG = file.type === 'audio/mp3'
        if (!isJPG) {
          this.$message.error('上传音频只能是 mp3 格式!')
        }
        return isJPG
      }
    },
    spClick () {
      setTimeout(() => {
        let qlEditing = document.getElementsByClassName('ql-editing')
        if (qlEditing) {
          qlEditing[0].style.left = null
          qlEditing[0].style.right = '4px'
          qlEditing[0].style.top = '-6px'
        }
      }, 10)
    },
    fnOpenUploadVideo (type, title) {
      this.uploadType = type
      // this.accept = config.accept.video
      this.title = title
      this.dialogFnOpenUpload = true
    },
    fnUploadSucess (res) {
      this.editor.focus()
      let url = uploadConfig.fileRead + res.model.data.id
      let length = this.editor.getSelection().index
      this.editor.insertEmbed(length, this.uploadType, url)
      this.editor.setSelection(length + 1)
      this.dialogFnOpenUpload = false
    }
  }
}
</script>

<style less>
.ql-editor .ql-video {
  width: 340px;
  height: 180px;
}
.ql-size-small {
  font-size: 0.8rem;
}
.ql-size-normal {
  font-size: 1rem;
}
.ql-size-large {
  font-size: 1.2rem;
}
.ql-size-huge {
  font-size: 1.5rem;
  font-weight: bold;
}
.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';
}
.avatar-uploader {
  text-align: center;
}
.avatar-uploader-icon {
  font-size: 67px;
  color: #c0c4cc;
  margin: 20px 0 26px;
  line-height: 50px;
}
</style>

六、总结
很懒,什么也没有留下

七、参考文档

1、添加链接描述
2、添加链接描述
3、添加链接描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

quill-editor扩展的正确姿势 的相关文章

  • 使用Visual Studio 2010开发nodejs

    是否可以使用VS2010开发NodeJS应用程序 我说的是普通的 Javascript 而不是 Azure 或任何类似的花哨的东西 我只是想使用 VS2010 作为 Javascript 编辑器 因为我有 NET 背景 而且我对它非常满意
  • CSS 编辑器,可扩展编辑时的单行声明

    是否有一个 CSS 编辑器可以自动将单行声明扩展为焦点上的多行声明 为了澄清我的想法 请参阅下面的示例 原始CSS div main color orange margin 1em 0 border 1px solid black 但是当关
  • GWT 编辑器框架

    有没有办法获取编辑器正在编辑的代理 正常的工作流程是 public class Class implments Editor
  • Dreamweaver 的替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 首先 好几年来我都严格在 Dreamweaver 的代码视图中进行所有编码 我could在记事本中完成
  • 有没有办法在 Vim 中模拟 ReSharper 的“扩展选择”功能?

    ReSharper 有一个很好的功能 称为 扩展选择 通过按CTRL W 我认为这是默认设置 反复地 您从当前插入符号位置中选择越来越多的内容 首先它是一个单词 然后是越来越多的单词 一行 内部然后外部的行块 例如 if 块 然后是一个函数
  • Unity不序列化int?场地

    我有一个类想要在编辑器中更改其属性 所以我创建了我的类 System Serializable 并将我希望能够更改的变量公开 就像这样 System Serializable public class UIOptionsRing publi
  • 刚习惯在 OS X 上的 emacs 中进行 paredit - 为什么 C-) 不起作用?

    我最近在 Mac OS X Leopard 中设置了 Common Lisp 编程环境 我发现 paredit 是一个不可或缺的 emacs 模块 Paredit 正在尽力帮助我更轻松地处理我的 Lisp 代码 但我遇到了一些陷阱 C 必然
  • Docker 开发环境中的丰富编辑器

    所以我和我的团队已经购买了 Docker 它对于部署和测试来说非常棒 我真正的问题是如何建立良好的开发人员体验 特别是围绕编写 Python 应用程序 但这个问题可以推广到 Nodejs Java 等 问题 在编写 Python 应用程序时
  • 因此更改了 Git 的默认编辑器,现在我如何从 Git bash 调用它?

    我通过将以下内容应用于 Git 的全局配置来更改 Git 的默认编辑器 core editor C Program Files Notepad notepad exe multiInst notabbar nosession noPlugi
  • 是否可以创建具有复杂子结构的自定义格式/印迹?

    我正在调查 Quill 在项目中的使用 我需要知道是否可以创建比单个元素和单个参数更复杂的自定义格式 印迹 我想要的布局之一的示例是 span class format container span class format info pa
  • 在 Visual Studio Code 中设置语法突出显示的语言

    在混乱开始之前 这个问题是关于 Code 新的轻量级 Visual Studio 编辑器 您可以从这里获取它 https code visualstudio com https code visualstudio com I have a
  • JavaScript 调试器[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道有一个非常好的调试 JavaScript 的编辑器 除了 Visual Studio 2008
  • 使用 Emacs 或 VIM 的 Colemak 键盘 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我一直在待办事项清单上划掉一些事情 我最近拿起了 Colemak 接下来我想学习Vim或Emacs 我倾向于 Vim 但它的好处之一是坚持主行 有了
  • 如何将对齐按钮添加到 Quill 的工具栏?

    我正在尝试将对齐按钮添加到 Quill 编辑器工具栏 工具栏文档 https quilljs com docs modules toolbar 不是很详细 它展示了如何选择对齐选项 但我想要一组并排的切换按钮 这可能吗 你可以做align
  • MS Dynamics CRM 2012:脚本编辑器增强功能

    我一直在尝试查找有关下一个 Microsoft Dynamics CRM 产品 2012 6 的更多信息 我主要对脚本编辑器的任何增强感兴趣 版本 4 和版本 5 2011 之间有很大的改进 最受我欢迎的是跨表单 字段事件共享脚本函数的能力
  • 如何在 Visual Studio Code for Mac 中向上或向下移动一行

    我熟悉如何在其他编辑器 例如 Atom 和 Sublime 中上下移动一行 在 Visual Studio Code for Mac 中这是如何完成的 在 Visual Studio Code for Mac 中 To move a lin
  • 在 IntelliJ Idea IDE 中禁用单击、拖动、剪切和粘贴

    在我的 IntelliJ Idea 13 1 2 IDE 中 我不断遇到通过笔记本电脑触摸板单击并拖动进行选择的情况 我总是不小心点击并拖动文本和剪切线 我在选项和设置面板中搜索了 单击和拖动 一词 但我没有找到关闭此功能的方法 Intel
  • Quill.js 格式()方法有什么作用?

    我正在尝试为 Quill js 实现自定义样式 该样式允许文本中嵌套和 希望 重叠区域 我还不确定如何进行重叠 但嵌套似乎是可能的 我已经完成了通常的印迹扩展 在打字稿中 let Inline Quill import blots inli
  • 如何关闭 IntelliJ 编辑器中的无限空白?

    如何删除 IntelliJ 中行尾后移动光标的功能 文件菜单 gt 设置 gt 编辑器 gt 常规 gt 虚拟空间并取消选中 允许在行尾后放置插入符号 您还可以取消选中 虚拟空间 面板中的其他选项
  • 带有 Viper 和 Vimpulse 的 Emacs 缺少哪些 Vim 功能?

    Emacs 的一些重要功能在 Vim 中是缺失的 例如 comint 模式 并且没有脚本 插件可以替代它们 与 Emacs 相比 Vim 也有一些优点 例如模式编辑和通常更好的默认快捷键 然而 Viper 模式让我两者兼而有之 Vimpul

随机推荐

  • Codeforces Contest #1553 A : Digit Sum 题解

    题目链接 Digit Sum 题面 将上面一大坨翻译一下 xff0c 就是 xff1a 定义函数的数字和 给出 求有多少个满足且 若模余 xff0c 则成立 一开始想是输出的下取整 xff0c 最后的结果 xff1a 没有考虑到的情况 xf
  • Atcoder Beginner Contest 100 - 题解

    A 原题 Happy Birthday 本题其实很水 只需要输入这两个整数 xff0c 如果中有一个大于 就输出 xff0c 否则输出 Yay include lt bits stdc 43 43 h gt using namespace
  • ubuntu 18.04 server 扩容(LVM)磁盘 解决磁盘不足的情况 (亲测)

    因为发现我的本地server出现磁盘满了的情况 所以进行lvm的扩容 截图的都是扩容后的 所以忽略容量 1 查看磁盘情况 df span class hljs attribute h span 原本发现 dev mapper ubuntu
  • 欢迎使用CSDN-markdown编辑器

    欢迎使用Markdown编辑器写博客 本Markdown编辑器使用StackEdit修改而来 xff0c 用它写博客 xff0c 将会带来全新的体验哦 xff1a Markdown和扩展Markdown简洁的语法代码块高亮图片链接和图片上传
  • 工作一年,辞职复习半年,考杭电计算机的经验分享

    工作一年 xff0c 辞职复习半年 xff0c 考杭电计算机的经验分享 如果 xff0c 毕业了工作顺利的人大概率是不会去考研的 xff0c 去考研的人 xff0c 大概率是想改变的 题记 2019 4 6 关于我 纠结的人生 为什么考研
  • CSS表格样式

    文章目录 CSS表格样式caption side 标题位置border collapse 边框合并border spacing 边框间距css样式 xff08 推荐使用 xff09 CSS表格样式 caption side 标题位置 语法
  • Android使用Annotations注解优化代码

    文章目录 Android使用Annotations注解优化代码Null 注解Typedef 注解Resource Type 注解Threading 注解Value Constraints 注解Overriding Methods 注解Ret
  • C语言strstr函数

    函数strstr定义 xff1a char strstr const char str1 const char str2 xff1b 位于头文件 string h 中 作用 xff1a strstr函数用于判断字符串str2是否为字符串st
  • Linux下串口读写通信

    span class token keyword int span fd span class token operator 61 span span class token number 0 span span class token p
  • kubernetes最新版安装单机版v1.21.5

    kubernetes最新版安装单机版v1 21 5 k8s集群由Master节点和Node xff08 Worker xff09 节点组成 今天我在这里给大家只用1台机器 xff0c 安装kubernetes 1 安装前置环境 root 6
  • 双系统、多系统快速切换

    前言 装双系统甚至多系统 xff0c 是为了满足不同需求 每个操作系统都有自身的特点 xff0c 因为这样那样的原因 xff0c 很多人选择双系统 双系统满足了不同需求 xff0c 但是每次需要手动选择所要进入的系统 xff0c 切换系统也
  • ROS::CmakeList 例子

    ROS CmakeList 例子 span class token function cmake minimum required span span class token punctuation span VERSION span cl
  • ROS:静态TF发布

    ROS xff1a 静态TF发布 方式1 xff1a span class token tag span class token tag span class token punctuation lt span launch span sp
  • ROS::线程锁

    ROS xff1a xff1a 线程锁 boost span class token operator span mutex mutex span class token punctuation span span class token
  • 无人机智能飞行类库设计构思

    搭建无人机 智能飞行类库的主要目的就在于 xff1a 便于无人机路径规划各种算法的实施 xff0c 便于飞行仿真以及便于今后在硬件上实现算法 完整做到这些需要做三方面做工作 xff1a 一 计算几何 计算几何问题主要用于路径优化 避障等 x
  • STL教程:C++ STL快速入门

    目录 1 STL引言 2 STL是什么 xff08 STL简介 xff09 3 STL历史 4 STL组件 5 STL基本结构 6 STL 使用方法 7 STL目录 网址 xff1a STL教程 xff1a C 43 43 STL快速入门
  • vue使用sortablejs插件的时候报Sortable: `el` must be an HTMLElement

    最近因为项目需要很灵活自定义查询 xff0c 故使用了vue和element ui组件库 xff0c 其中el table需要行和列拖拽排序 故使用到了sortable插件 一 报错的排查 首先对 xff1a const tbody 61
  • 记一次Linux 4.15.0-65-generic安装Elasticsearch成功的过程

    一 xff0c 操作系统和安装的应用 xff1a 1 操作系统 xff1a Linux version 4 15 0 65 generic buildd 64 lgw01 amd64 006 gcc version 7 4 0 Ubuntu
  • [docker]笔记-镜像 管理

    1 镜像管理 docker search xxxx 查找镜像 例如查找httpd root 64 localhost docker search httpd 下载镜像 docker pull xxxx root 64 localhost d
  • quill-editor扩展的正确姿势

    一 无关的插曲 曾几何时 xff0c 风云万里 xff0c 万海桑田 耕耘于代码堆里多年 做过android移动端 xff0c 做过web端 xff0c 做过java后端和 net xff0c 也做过python数据分析 但真正扩展源码的亦