在vue中使用图片编辑插件ToastUI Image Editor

2023-11-04

简介

ToastUI Image Editor 是一个基于 HTML5 Canvas 的图片编辑器,它使用起来非常简单,而且内置了丰富的图片编辑功能。它支持原生 JavaScript、Vue 组件 和  React 组件三种使用方式。

官网地址 https://nhn.github.io/tui.image-editor/latest/ 

git地址    http://nhn.github.io/tui.image-editor/latest/ImageEditor#loadImageFromURL

安装

cnpm  i tui-image-editor --save

引入

import 'tui-image-editor/dist/tui-image-editor.css'
import 'tui-color-picker/dist/tui-color-picker.css'
const ImageEditor = require('tui-image-editor')

使用

添加配置前

// 使用编辑组件
this.instance = new ImageEditor(
  document.querySelector('#tui-image-editor'),
  {
    includeUI: { // 表示使用它内置的 UI 控件
      loadImage: {
        path: url,// 照片路径
        name: this.imageName //图片名称
      }, // 默认加载的图片
      initMenu: 'draw', // 表示编辑器加载后,第一个被选中的操作菜单功能
      menu: [
        'crop', // 裁切
        'flip', // 翻转
        'rotate', // 旋转
        'draw', // 添加绘画
        'shape', // 添加形状
        'icon', // 添加图标
        'text', // 添加文本
        'mask', // 添加覆盖
        'filter' // 添加滤镜
      ], // 支持的菜单
      locale: localeZh, // 国际化对照字段
      theme: customTheme,// 自定义的主题配置
      usageStatistics: false, 
      menuBarPosition: 'left'// 菜单位置栏的位置,有四个选项可选:'top', 'bottom', 'left', 'right'
    },
    cssMaxWidth: 1100, // 编辑器 Canvas 的最大宽度
    cssMaxHeight: 500, // 编辑器 Canvas 的最大高度
    selectionStyle: {
      cornerSize: 20,
      rotatingPointOffset: 70
    }
  })

可以汉化标签,对应的翻译对照字段如下

  const localeZh = {
    // override default English locale to your custom
    Crop: '裁剪',
    ZoomIn: '放大',
    ZoomOut: '缩小',
    Hand: '拖拽',
    History: '历史记录',
    DeleteAll: '全部删除',
    Delete: '删除',
    Undo: '撤销',
    Redo: '反撤销',
    Reset: '重置',
    Flip: '镜像',
    Rotate: '旋转',
    Draw: '画',
    Shape: '形状标注',
    Icon: '图标标注',
    Text: '文字标注',
    Mask: '遮罩',
    Filter: '滤镜',
    Bold: '加粗',
    Italic: '斜体',
    Underline: '下划线',
    Left: '左对齐',
    Center: '居中',
    Right: '右对齐',
    Color: '颜色',
    'Text size': '字体大小',
    Custom: '自定义',
    Square: '正方形',
    Apply: '应用',
    Cancel: '取消',
    'Flip X': 'X 轴',
    'Flip Y': 'Y 轴',
    Range: '区间',
    Stroke: '描边',
    Fill: '填充',
    Circle: '圆',
    Triangle: '三角',
    Rectangle: '矩形',
    Free: '曲线',
    Straight: '直线',
    Arrow: '箭头',
    'Arrow-2': '箭头2',
    'Arrow-3': '箭头3',
    'Star-1': '星星1',
    'Star-2': '星星2',
    Polygon: '多边形',
    Location: '定位',
    Heart: '心形',
    Bubble: '气泡',
    'Custom icon': '自定义图标',
    'Load Mask Image': '加载蒙层图片',
    Grayscale: '灰度',
    Blur: '模糊',
    Sharpen: '锐化',
    Emboss: '浮雕',
    'Remove White': '除去白色',
    Distance: '距离',
    Brightness: '亮度',
    Noise: '噪音',
    'Color Filter': '彩色滤镜',
    Sepia: '棕色',
    Sepia2: '棕色2',
    Invert: '负片',
    Pixelate: '像素化',
    Threshold: '阈值',
    Tint: '色调',
    Multiply: '正片叠底',
    Blend: '混合色'
    // etc...
  }

自定义的主题配置如下

  const customTheme = {
    // image 左上角度图片
    'common.bi.image': '', // 在这里换上你喜欢的logo图片
    'common.bisize.width': '0px',
    'common.bisize.height': '0px',
    'common.backgroundImage': 'none',
    'common.backgroundColor': '#f3f4f6',
    'common.border': '1px solid #444',

    // header
    'header.backgroundImage': 'none',
    'header.backgroundColor': '#f3f4f6',
    'header.border': '0px',
    'header.display': 'none',

    // load button
    'loadButton.backgroundColor': '#fff',
    'loadButton.border': '1px solid #ddd',
    'loadButton.color': '#222',
    'loadButton.fontFamily': 'NotoSans, sans-serif',
    'loadButton.fontSize': '12px',
    'loadButton.display': 'none', // 可以直接隐藏掉

    // download button
    'downloadButton.backgroundColor': '#fdba3b',
    'downloadButton.border': '1px solid #fdba3b',
    'downloadButton.color': '#fff',
    'downloadButton.fontFamily': 'NotoSans, sans-serif',
    'downloadButton.fontSize': '12px',
    'downloadButton.display': 'none', // 可以直接隐藏掉

    // icons default
    'menu.normalIcon.color': '#8a8a8a',
    'menu.activeIcon.color': '#555555',
    'menu.disabledIcon.color': '#434343',
    'menu.hoverIcon.color': '#e9e9e9',
    'submenu.normalIcon.color': '#8a8a8a',
    'submenu.activeIcon.color': '#e9e9e9',

    'menu.iconSize.width': '24px',
    'menu.iconSize.height': '24px',
    'submenu.iconSize.width': '32px',
    'submenu.iconSize.height': '32px',

    // submenu primary color
    'submenu.backgroundColor': '#1e1e1e',
    'submenu.partition.color': '#858585',

    // submenu labels
    'submenu.normalLabel.color': '#858585',
    'submenu.normalLabel.fontWeight': 'lighter',
    'submenu.activeLabel.color': '#fff',
    'submenu.activeLabel.fontWeight': 'lighter',

    // checkbox style
    'checkbox.border': '1px solid #ccc',
    'checkbox.backgroundColor': '#fff',

    // rango style
    'range.pointer.color': '#fff',
    'range.bar.color': '#666',
    'range.subbar.color': '#d1d1d1',

    'range.disabledPointer.color': '#414141',
    'range.disabledBar.color': '#282828',
    'range.disabledSubbar.color': '#414141',

    'range.value.color': '#fff',
    'range.value.fontWeight': 'lighter',
    'range.value.fontSize': '11px',
    'range.value.border': '1px solid #353535',
    'range.value.backgroundColor': '#151515',
    'range.title.color': '#fff',
    'range.title.fontWeight': 'lighter',

    // colorpicker style
    'colorpicker.button.border': '1px solid #1e1e1e',
    'colorpicker.title.color': '#fff'
  }

图片位置置顶

 // 图片位置指定
document.getElementsByClassName('tui-image-editor-main')[0].style.top = 0
 // 隐藏删除按钮
document.getElementsByClassName('tie-btn-delete tui-image-editor-item help')[0].style.display = 'none'

加载一个图片

this.instance.loadImageFromURL('http://url/testImage.png', 'lena').then(result => {
     console.log('old : ' + result.oldWidth + ', ' + result.oldHeight);
     console.log('new : ' + result.newWidth + ', ' + result.newHeight);
});
// 根据url加载一个新的图片

添加保存功能


 // 保存图片
uploadImg () {
  const base64String = this.instance.toDataURL()
  const data = window.atob(base64String.split(',')[1])
  const ia = new Uint8Array(data.length)
  for (let i = 0; i < data.length; i++) {
    ia[i] = data.charCodeAt(i)
  }
  // 将图片转换成二进制形式发送给后台
  const blob = new Blob([ia], { type: 'image/png' })
  const fd = new FormData()
  fd.append('file', blob)
  // 获取上传需要的参数
  // 调用上传接口
  let params = { name: this.imageName, rid: this.entity.rid, file: fd }
  this.loading.isLoading = true
  this.serverApi({
    loading: this.loading,
    params: params,
    interface: this.$https.uploadEditedImage,
    tips: true,
    success: () => {
        console.log('保存成功')
    }
  })
},

最终效果

整个代码文件如下(其中有封装的方法和组件部分)

<template>
  <div>
    <info-dialog
      v-if="isShowDialog"
      id="previewImage"
      v-loading="loading.isLoading"
      :title="$t('messages.previewImage')"
      width="80%"
      height="calc(100vh - 0px)"
      :isShowDialog="isShowDialog"
      :dialogOperates="dialogOperates"
      @closeDialog="closeDialog"
      @confirmDialog="closeDialog"
    >
      <div
        v-if="isShowEditImage"
        class="container"
      >
        <div
          id="tui-image-editor"
        />
      </div>
      <el-image
        v-for="(item, index) in urls"
        :key="index"
        style="width: 80px; height: 80px;padding: 10px"
        fit="fill"
        :src="item"
        @click="editImage(item)"
      />
      <!--      <el-carousel
        type="card"
        arrow="always"
        :loop="false"
        :initial-index="1"
        indicator-position="none"
        :autoplay="false"
      >
        <el-carousel-item
          v-for="(items, index) in item.userInfo1"
          :key="index"
        >
          <div class="div2">
            <div>
              <div
                v-show="item.state===0 || item.state===1"
                style="position: absolute;"
              >
                <img
                  src="http://192.168.1.81:9000/sink/image/2018-0.tif_0.80?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minio%2F20210312%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20210312T031818Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=272e8a2bd75d22cf4c9fdb3f55fdc2fd7f0cbd0610b34e07da5cfa7a02addf43"
                  class="deleteStyle"
                  @click="deleteImg(items,item)"
                >
              </div>
              <img
                :src="items.b_img.url"
                class="headImgStyle"
              >
            </div>
            <div class="nickname">
              {{ items.b_nickname }}
            </div>
          </div>
        </el-carousel-item>
      </el-carousel>-->
    </info-dialog>
  </div>
</template>
<script>
  import 'tui-image-editor/dist/tui-image-editor.css'
  import 'tui-color-picker/dist/tui-color-picker.css'

  const ImageEditor = require('tui-image-editor')
  const localeZh = {
    // override default English locale to your custom
    Crop: '裁剪',
    ZoomIn: '放大',
    ZoomOut: '缩小',
    Hand: '拖拽',
    History: '历史记录',
    DeleteAll: '全部删除',
    Delete: '删除',
    Undo: '撤销',
    Redo: '反撤销',
    Reset: '重置',
    Flip: '镜像',
    Rotate: '旋转',
    Draw: '画',
    Shape: '形状标注',
    Icon: '图标标注',
    Text: '文字标注',
    Mask: '遮罩',
    Filter: '滤镜',
    Bold: '加粗',
    Italic: '斜体',
    Underline: '下划线',
    Left: '左对齐',
    Center: '居中',
    Right: '右对齐',
    Color: '颜色',
    'Text size': '字体大小',
    Custom: '自定义',
    Square: '正方形',
    Apply: '应用',
    Cancel: '取消',
    'Flip X': 'X 轴',
    'Flip Y': 'Y 轴',
    Range: '区间',
    Stroke: '描边',
    Fill: '填充',
    Circle: '圆',
    Triangle: '三角',
    Rectangle: '矩形',
    Free: '曲线',
    Straight: '直线',
    Arrow: '箭头',
    'Arrow-2': '箭头2',
    'Arrow-3': '箭头3',
    'Star-1': '星星1',
    'Star-2': '星星2',
    Polygon: '多边形',
    Location: '定位',
    Heart: '心形',
    Bubble: '气泡',
    'Custom icon': '自定义图标',
    'Load Mask Image': '加载蒙层图片',
    Grayscale: '灰度',
    Blur: '模糊',
    Sharpen: '锐化',
    Emboss: '浮雕',
    'Remove White': '除去白色',
    Distance: '距离',
    Brightness: '亮度',
    Noise: '噪音',
    'Color Filter': '彩色滤镜',
    Sepia: '棕色',
    Sepia2: '棕色2',
    Invert: '负片',
    Pixelate: '像素化',
    Threshold: '阈值',
    Tint: '色调',
    Multiply: '正片叠底',
    Blend: '混合色'
    // etc...
  }
  const customTheme = {
    // image 左上角度图片
    'common.bi.image': '', // 在这里换上你喜欢的logo图片
    'common.bisize.width': '0px',
    'common.bisize.height': '0px',
    'common.backgroundImage': 'none',
    'common.backgroundColor': '#f3f4f6',
    'common.border': '1px solid #444',

    // header
    'header.backgroundImage': 'none',
    'header.backgroundColor': '#f3f4f6',
    'header.border': '0px',
    'header.display': 'none',

    // load button
    'loadButton.backgroundColor': '#fff',
    'loadButton.border': '1px solid #ddd',
    'loadButton.color': '#222',
    'loadButton.fontFamily': 'NotoSans, sans-serif',
    'loadButton.fontSize': '12px',
    'loadButton.display': 'none', // 可以直接隐藏掉

    // download button
    'downloadButton.backgroundColor': '#fdba3b',
    'downloadButton.border': '1px solid #fdba3b',
    'downloadButton.color': '#fff',
    'downloadButton.fontFamily': 'NotoSans, sans-serif',
    'downloadButton.fontSize': '12px',
    'downloadButton.display': 'none', // 可以直接隐藏掉

    // icons default
    'menu.normalIcon.color': '#8a8a8a',
    'menu.activeIcon.color': '#555555',
    'menu.disabledIcon.color': '#434343',
    'menu.hoverIcon.color': '#e9e9e9',
    'submenu.normalIcon.color': '#8a8a8a',
    'submenu.activeIcon.color': '#e9e9e9',

    'menu.iconSize.width': '24px',
    'menu.iconSize.height': '24px',
    'submenu.iconSize.width': '32px',
    'submenu.iconSize.height': '32px',

    // submenu primary color
    'submenu.backgroundColor': '#1e1e1e',
    'submenu.partition.color': '#858585',

    // submenu labels
    'submenu.normalLabel.color': '#858585',
    'submenu.normalLabel.fontWeight': 'lighter',
    'submenu.activeLabel.color': '#fff',
    'submenu.activeLabel.fontWeight': 'lighter',

    // checkbox style
    'checkbox.border': '1px solid #ccc',
    'checkbox.backgroundColor': '#fff',

    // rango style
    'range.pointer.color': '#fff',
    'range.bar.color': '#666',
    'range.subbar.color': '#d1d1d1',

    'range.disabledPointer.color': '#414141',
    'range.disabledBar.color': '#282828',
    'range.disabledSubbar.color': '#414141',

    'range.value.color': '#fff',
    'range.value.fontWeight': 'lighter',
    'range.value.fontSize': '11px',
    'range.value.border': '1px solid #353535',
    'range.value.backgroundColor': '#151515',
    'range.title.color': '#fff',
    'range.title.fontWeight': 'lighter',

    // colorpicker style
    'colorpicker.button.border': '1px solid #1e1e1e',
    'colorpicker.title.color': '#fff'
  }
  export default {
    name: 'PreviewImage',
    data () {
      return {
        imageName: '', // 保存图片时候的名称
        entity: {}, // 当前数据
        instance: null, // 编辑图片实例
        isShowEditImage: false,
        loading: { isLoading: false },
        urls: [], // 图片路径
        isShowDialog: false, // 显示弹框
        dialogOperates: [{
          label: 'save',
          type: 'primary',
          plain: true,
          method: () => {
            this.uploadImg()
          }
        }, {
          label: 'cancel',
          type: 'primary',
          plain: true,
          method: () => {
            this.closeDialog('history')
          }
        }]
      }
    },
    methods: {
      // 保存图片
      uploadImg () {
        const base64String = this.instance.toDataURL()
        const data = window.atob(base64String.split(',')[1])
        const ia = new Uint8Array(data.length)
        for (let i = 0; i < data.length; i++) {
          ia[i] = data.charCodeAt(i)
        }
        const blob = new Blob([ia], { type: 'image/png' })
        const fd = new FormData()
        fd.append('file', blob)
        // 获取上传需要的参数
        // 调用上传接口
        let params = { name: this.imageName, rid: this.entity.rid, file: fd }
        this.loading.isLoading = true
        this.serverApi({
          loading: this.loading,
          params: params,
          interface: this.$https.uploadEditedImage,
          tips: true,
          success: () => {
          }
        })
      },
      // 编辑图片
      editImage (url) {
        // 根据图片路径获取图片名称
        let route = url.split('?')[0]
        let name = route.split('/')
        this.imageName = name[name.length - 1]
        // 显示图片
        this.isShowEditImage = true
        // 使用编辑组件
        this.instance = new ImageEditor(
          document.querySelector('#tui-image-editor'),
          {
            includeUI: { // 表示使用它内置的 UI 控件
              loadImage: {
                path: url,
                name: this.imageName
              }, // 默认加载的图片
              initMenu: 'draw', // 表示编辑器加载后,第一个被选中的操作菜单功能
              menu: [
                'crop', // 裁切
                'flip', // 翻转
                'rotate', // 旋转
                'draw', // 添加绘画
                'shape', // 添加形状
                'icon', // 添加图标
                'text', // 添加文本
                'mask', // 添加覆盖
                'filter' // 添加滤镜
              ], // 支持的菜单
              locale: localeZh,
              theme: customTheme,
              usageStatistics: false,
              menuBarPosition: 'left'// 菜单位置栏的位置,有四个选项可选:'top', 'bottom', 'left', 'right'
            },
            cssMaxWidth: 1100, // 编辑器 Canvas 的最大宽度
            cssMaxHeight: 500, // 编辑器 Canvas 的最大高度
            selectionStyle: {
              cornerSize: 20,
              rotatingPointOffset: 70
            }
          })
        document.getElementsByClassName('tui-image-editor-main')[0].style.top = 0
        // 隐藏删除按钮
        document.getElementsByClassName('tie-btn-delete tui-image-editor-item help')[0].style.display = 'none'
      },
      // 显示弹框
      showDialog (rid) {
        this.isShowEditImage = false
        this.loading.isLoading = true
        // 获取指定rid数据信息
        this.serverApi({
          loading: this.loading,
          params: rid,
          interface: this.$https.overviewImage,
          success: (res) => {
            this.isShowDialog = true
            this.entity = res
            // 显示查询结果的url
            this.urls = res?.urls.map(item => {
              return this.decrypt(item)
            })
            this.editImage(this.urls[0])
          }
        })
      },
      // 关闭弹框
      closeDialog () {
        this.isShowDialog = false
      }
    }
  }
</script>
<style lang="scss" scoped>
  #previewImage {
    .container {
      height: calc(100vh - 400px);
    }
  }
</style>

 

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

在vue中使用图片编辑插件ToastUI Image Editor 的相关文章

  • ios sdk 穿山甲_iOS 穿山甲广告 SDK 的使用

    信息流广告 自定义使用时 相关类的使用 BUAdSlot 广告位类 加载广告时需要设置的广告位描述信息 传入广告的主要请求 ID 广告类型 位置等 BUMaterialMeta 广告数据的载体类 访问可以获取所有的广告属性 主要属性名 数据

随机推荐

  • LevelDB源码阅读-key

    levelDB中的key 前言 在levelDB中有五种不同的key 在正式分析memtable之前我们先介绍一下这5中不同的key user key ParsedInternalKey InternalKey LookupKey Memt
  • 7.4 初等矩阵和可逆性

    初等矩阵和可逆性 初等矩阵 对单位矩阵 进行 一次 初等变换 得到 初等矩阵一定是可逆的 gt 因为初等变换是可逆的 所以初等矩阵是可逆的 对于一般矩阵 如果可逆的话 怎样得到逆矩阵呢 根据之前的分析 gt 如果矩阵A可逆的话 即存在一系列
  • java输入只有一行_即三个整数_中间用空格隔开_蓝桥杯 算法训练 排序

    问题描述 编写一个程序 读入一组整数 这组整数是按照从小到大的顺序排列的 它们的个数N也是由用户输入的 最多不会超过20 然后程序将对这个数组进行统计 把出现次数最多的那个数组元素值打印出来 如果有两个元素值出现的次数相同 即并列第一 问题
  • 注解@Autowired是如何实现的

    1 Autowired注解用法 2 Autowired注解的作用到底是什么 Autowired这个注解我们经常在使用 现在 我想问的是 它的作用到底是什么呢 首先 我们从所属范围来看 事实上这个注解是属于spring的容器配置的一个注解 与
  • MySQL高级篇_第10章_索引优化与查询优化

    都有哪些维度可以进行数据库调优 简言之 索引失效 没有充分利用到索引 索引建立 关联查询太多JOIN 设计缺陷或不得已的需求 SQL优化 服务器调优及各个参数设置 缓冲 线程数等 调整my cnf 数据过多 分库分表 关于数据库调优的知识点
  • 如何看服务器请求信息,如何看服务器请求信息

    如何看服务器请求信息 内容精选 换一换 请求URI由如下部分组成 URI scheme Endpoint resource path query string 例如您需要获取华北 北京四区域设备管理服务的accessToken 查询到的En
  • LambdaQueryWrapper中常用方法

    LambdaQueryWrapper中常用方法 LambdaQueryWrapper实例1 2 链式查询 3 排序查询以及between and查询 4 修改
  • 微信记账小程序

    第1章 绪论 1 1 研究背景与意义 随着网络时代的到来 互联网的优势和普及时刻影响并改变着人们的生活方式 在信息技术迅速发展的今天 计算机技术已经遍及全球 使社会发生了巨大的变革 为了不受时间和地点的限制 智能手机用户可以通过移动网络访问
  • 量化投资学习-39:股市里看人生

    1 股市 1 1 股市就是一个舞台 股市就是一个大舞台 在这个舞台上 每天上演着无数的人生悲喜故事 股市上的每只股票背后都是一种人的人生故事 有大起大落 有平淡无奇 有蓄势待发 有气势如虹 有高楼起 有楼塌了 起起伏伏 跌跌宕宕才是规律 1
  • CGI环境变量

    CGI环境变量 所有的CGI程序都接收以下的环境变量 这些变量在CGI程序中发挥了重要的作用 变量名 描述 CONTENT TYPE 这个环境变量的值指示所传递来的信息的MIME类型 目前 环境变量CONTENT TYPE一般都是 appl
  • [Python Scrapy爬虫] 二.翻页爬取农产品信息并保存本地

    前面 Python爬虫之Selenium Phantomjs CasperJS 介绍了很多Selenium基于自动测试的Python爬虫程序 主要利用它的xpath语句 通过分析网页DOM树结构进行爬取内容 同时可以结合Phantomjs模
  • DNS基本指南,域名解析,A记录,MX,CNAME,URL Redirect(301),URL frame,ns,TXT Record

    DNS 基本指南 DNS DNS 是 Domain Name System 域名系统 的缩写 此系统用于管理和识别域名 DNS 的最基本功能是为域的一个或多个 IP 地址提供名称 例如 可以将域名 wolf example com转换为 1
  • 面试python常见问题_Python干货Python常见面试问题

    Python干货Python常见面试问题 人工智能的火热进一步带动了求职市场上对Python程序员需求量不断增加 对于很多Python程序员而言 面试过程能不能更好的发挥自己展示自己 最终也会影响到能不能拿到心仪的薪酬 能不能通过面试 为此
  • 6.1-操作系统上的进程

    复习 操作系统内核的启动 CPU Reset Firmware Boot loader Kernel start 本次课回答的问题 Q1 操作系统启动后到底做了什么 Q2 操作系统如何管理程序 进程 本次课主要内容 虚拟化 操作系统上的进程
  • C++中通过派生类调用第二基类的普通成员函数时this指针的调整

    我们都知道 C 编译器对于普通的类成员函数的编译 会将其编译成非成员函数 即普通全局函数 并且对函数名进行name mangling 加入this指针作为该函数的第一参数 这个this指针的类型是本类类型 即 class A privagt
  • -477. 汉明距离总和

    题目描述 两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量 计算一个数组中 任意两个数之间汉明距离的总和 样例 输入 4 14 2 输出 6 解释 在二进制表示中 4表示为0100 14表示为1110 2表示为0010 这样
  • mybatis-plus教程-Mybatis-Plus增删改查

    完整代码 https github com pbteach mybatis plus test Mybatis plus增删改查 通过前面的学习 我们了解到通过继承BaseMapper就可以获取到各种各样的单表操作 接下来我们将详细讲解这些
  • 【100%通过率 】【华为OD机试c++】去除多余空格【 2023 Q1

    华为OD机试 题目列表 2023Q1 点这里 2023华为OD机试 刷题指南 点这里 题目描述 去除多余空格 去除文本多余空格 但不去除配对单引号之间的多余空格 给出关键词的起始和结束下标 去除多余空格后刷新关键词的起始和结束下标
  • java long格式化输出,java格式化输出

    importjava text DecimalFormat publicclassTestNumberFormat publicstaticvoidmain String args doublepi 3 1415927 圆周率 取一位整数
  • 在vue中使用图片编辑插件ToastUI Image Editor

    简介 ToastUI Image Editor 是一个基于 HTML5 Canvas 的图片编辑器 它使用起来非常简单 而且内置了丰富的图片编辑功能 它支持原生 JavaScript Vue 组件 和 React 组件三种使用方式 官网地址