CKEditor5富文本编辑器在vue中的使用

按照一般官网的集成方案安装CKEditor5,需要vue的版本在3.x及以上才能使用,但是,由于博主目前使用的是vue2.6.10,所以这里介绍一种源码集成方案。注意,使用源码集成手脚架(vue/cli)必须要3.x及以上版本。

一、安装ckeditor基础框架、一些基础功能和主题:

npm install --save @ckeditor/ckeditor5-vue2 @ckeditor/ckeditor5-dev-webpack-plugin @ckeditor/ckeditor5-dev-utils postcss-loader@3 raw-loader@0.5.1
npm install --save @ckeditor/ckeditor5-editor-classic @ckeditor/ckeditor5-essentials @ckeditor/ckeditor5-basic-styles @ckeditor/ckeditor5-link @ckeditor/ckeditor5-paragraph @ckeditor/ckeditor5-theme-lark @ckeditor/ckeditor5-heading

二、在vue.config.js文件中添加配置相关信息:
在这里插入图片描述

const path = require('path');
const CKEditorWebpackPlugin = require('@ckeditor/ckeditor5-dev-webpack-plugin');
const {styles} = require('@ckeditor/ckeditor5-dev-utils');

module.exports = {
  configureWebpack: {
    plugins: [
      new CKEditorWebpackPlugin({
        language: 'en',
        translationsOutputFile: /app/
      })
    ]
  },
  
  transpileDependencies: [
    /ckeditor5-[^/\\]+[/\\]src[/\\].+\.js$/,
  ],
  
  chainWebpack: config => {
    const svgRule = config.module.rule('svg');

    svgRule.exclude.add(path.join(__dirname, 'node_modules', '@ckeditor'));

    config.module
      .rule('cke-svg')
      .test(/ckeditor5-[^/\\]+[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/)
      .use('raw-loader')
      .loader('raw-loader');

    config.module
      .rule('cke-css')
      .test(/ckeditor5-[^/\\]+[/\\].+\.css$/)
      .use('postcss-loader')
      .loader('postcss-loader')
      .tap(() => {
        return styles.getPostCssConfig({
          themeImporter: {
            themePath: require.resolve('@ckeditor/ckeditor5-theme-lark'),
          },
          minify: true
        });
      });
  },
};

三、在需要使用ckeditor5的vue文件中进行引入使用:

<template>
  <div>
    <ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
  </div>
</template>

<script>
import CKEditor from '@ckeditor/ckeditor5-vue2'
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'

import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials'
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold'
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic'
import LinkPlugin from '@ckeditor/ckeditor5-link/src/link'
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph'
import Heading from '@ckeditor/ckeditor5-heading/src/heading'


export default {
  components: {
    ckeditor: CKEditor.component
  },
  data() {
    return {
      editorData: '',
      editor: ClassicEditor,
      editorConfig: {
        placeholder: '请填写内容',
        plugins: [
          EssentialsPlugin,
          BoldPlugin,
          ItalicPlugin,
          LinkPlugin,
          ParagraphPlugin,
          Heading
        ],
        toolbar: {
          items: [
            'heading',
            '|',
            'bold',
            'italic',
            'link',
            'undo',
            'redo'
          ]
        },
        heading: {
          options: [
            {model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph'},
            {model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1'},
            {model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2'},
            {model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3'}
          ]
        }
      }
    };
  }
}
</script>

<style>
  /*编辑框最低高度*/
  .ck-editor__editable{
    min-height: 400px;
  }
</style>

四、自定义拓展功能:
功能列表有许多CKEditor5提供的功能,点击名字就能查到详细的功能和对应的demo,以Font功能为例子(classic中没有的功能):
①首先,找到font功能,点击进入
在这里插入图片描述
②进入后往下滑可以看到demo,点击进入
在这里插入图片描述
③进入后即可看到如何使用:
在这里插入图片描述
首先,安装:

npm install --save @ckeditor/ckeditor5-font

接着,在vue文件中引入:

import FontColor from '@ckeditor/ckeditor5-font/src/fontcolor'
import FontBackgroundColor from '@ckeditor/ckeditor5-font/src/fontbackgroundcolor'
import FontFamily from '@ckeditor/ckeditor5-font/src/fontfamily'
import FontSize from '@ckeditor/ckeditor5-font/src/fontsize'

并在plugins,toolbar中配置上,有一些可以自定义的配置:

plugins: [ FontColor, FontBackgroundColor, FontFamily, FontSize, .. ],
toolbar: [ 'fontFamily', 'fontSize', 'fontColor', 'fontBackgroundColor', ... ]

效果图:
在这里插入图片描述
五、实现大部分功能的自定义ckeditor5完整示例:
ckeditor5虽然可以自定义实现非常多的功能,但是在实现一些功能时,有未能实现预期效果的情况,比如:
①把ckeditor放在某个组件中时,工具栏宽度不够放下所有的工具栏项目,默认的它会显示“Show more items” (⋮) 的按钮,此时,将shouldNotGroupWhenFull设置为true,工具栏将停止对项目进行分组,并让它们在没有足够空间在单行中显示时换行到下一行。默认情况下为false,此设置启用项目分组。
在这里插入图片描述
②通过链接的方式添加图片可以实现,但上传本地图片,需要使用Base64 图片上传适配器。(网上很多文章或者官网使用ckfinder、ckeditor5-easy-image、ckeditor5-image,本人尝试过后都未能实现预期效果)
在这里插入图片描述
③表格或图片样式被过滤,即:在ckeditor中画的表格,提取出来在另一个地方显示,却没有表格样式(表格线、颜色等),只有按照表格顺序显示的一堆内容。解决这个问题需要在显示的地方添加编辑器的style样式:(其中,addTemplateContentShow表示用来显示ckeditor中编辑的内容的容器,而addTemplateContent表示ckeditor中编辑的内容)

this.addTemplateContentShow = `
      <html lang="zh">
        <head>
          <style>:root {--ck-color-image-caption-background: hsl(0, 0%, 97%);--ck-color-image-caption-text: hsl(0, 0%, 20%);--ck-color-mention-background: hsla(341, 100%, 30%, 0.1);--ck-color-mention-text: hsl(341, 100%, 30%);--ck-color-table-caption-background: hsl(0, 0%, 97%);--ck-color-table-caption-text: hsl(0, 0%, 20%);--ck-highlight-marker-blue: hsl(201, 97%, 72%);--ck-highlight-marker-green: hsl(120, 93%, 68%);--ck-highlight-marker-pink: hsl(345, 96%, 73%);--ck-highlight-marker-yellow: hsl(60, 97%, 73%);--ck-highlight-pen-green: hsl(112, 100%, 27%);--ck-highlight-pen-red: hsl(0, 85%, 49%);--ck-image-style-spacing: 1.5em;--ck-inline-image-style-spacing: calc(var(--ck-image-style-spacing) / 2);--ck-todo-list-checkmark-size: 16px;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-block-align-left,.ck-content .image-style-block-align-right {max-width: calc(100% - var(--ck-image-style-spacing));}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-align-left,.ck-content .image-style-align-right {clear: none;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-side {float: right;margin-left: var(--ck-image-style-spacing);max-width: 50%;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-align-left {float: left;margin-right: var(--ck-image-style-spacing);}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-align-center {margin-left: auto;margin-right: auto;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-align-right {float: right;margin-left: var(--ck-image-style-spacing);}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-block-align-right {margin-right: 0;margin-left: auto;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-style-block-align-left {margin-left: 0;margin-right: auto;}/* ckeditor5-image/theme/imagestyle.css */.ck-content p + .image-style-align-left,.ck-content p + .image-style-align-right,.ck-content p + .image-style-side {margin-top: 0;}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-inline.image-style-align-left,.ck-content .image-inline.image-style-align-right {margin-top: var(--ck-inline-image-style-spacing);margin-bottom: var(--ck-inline-image-style-spacing);}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-inline.image-style-align-left {margin-right: var(--ck-inline-image-style-spacing);}/* ckeditor5-image/theme/imagestyle.css */.ck-content .image-inline.image-style-align-right {margin-left: var(--ck-inline-image-style-spacing);}/* ckeditor5-image/theme/imagecaption.css */.ck-content .image > figcaption {display: table-caption;caption-side: bottom;word-break: break-word;color: var(--ck-color-image-caption-text);background-color: var(--ck-color-image-caption-background);padding: .6em;font-size: .75em;outline-offset: -1px;}/* ckeditor5-font/theme/fontsize.css */.ck-content .text-tiny {font-size: .7em;}/* ckeditor5-font/theme/fontsize.css */.ck-content .text-small {font-size: .85em;}/* ckeditor5-font/theme/fontsize.css */.ck-content .text-big {font-size: 1.4em;}/* ckeditor5-font/theme/fontsize.css */.ck-content .text-huge {font-size: 1.8em;}/* ckeditor5-highlight/theme/highlight.css */.ck-content .marker-yellow {background-color: var(--ck-highlight-marker-yellow);}/* ckeditor5-highlight/theme/highlight.css */.ck-content .marker-green {background-color: var(--ck-highlight-marker-green);}/* ckeditor5-highlight/theme/highlight.css */.ck-content .marker-pink {background-color: var(--ck-highlight-marker-pink);}/* ckeditor5-highlight/theme/highlight.css */.ck-content .marker-blue {background-color: var(--ck-highlight-marker-blue);}/* ckeditor5-highlight/theme/highlight.css */.ck-content .pen-red {color: var(--ck-highlight-pen-red);background-color: transparent;}/* ckeditor5-highlight/theme/highlight.css */.ck-content .pen-green {color: var(--ck-highlight-pen-green);background-color: transparent;}/* ckeditor5-image/theme/imageresize.css */.ck-content .image.image_resized {max-width: 100%;display: block;box-sizing: border-box;}/* ckeditor5-image/theme/imageresize.css */.ck-content .image.image_resized img {width: 100%;}/* ckeditor5-image/theme/imageresize.css */.ck-content .image.image_resized > figcaption {display: block;}/* ckeditor5-image/theme/image.css */.ck-content .image {display: table;clear: both;text-align: center;margin: 0.9em auto;min-width: 50px;}/* ckeditor5-image/theme/image.css */.ck-content .image img {display: block;margin: 0 auto;max-width: 100%;min-width: 100%;}/* ckeditor5-image/theme/image.css */.ck-content .image-inline {/* * Normally, the .image-inline would have "display: inline-block" and "img { width: 100% }" (to follow the wrapper while resizing).; * Unfortunately, together with "srcset", it gets automatically stretched up to the width of the editing root. * This strange behavior does not happen with inline-flex. */display: inline-flex;max-width: 100%;align-items: flex-start;}/* ckeditor5-image/theme/image.css */.ck-content .image-inline picture {display: flex;}/* ckeditor5-image/theme/image.css */.ck-content .image-inline picture,.ck-content .image-inline img {flex-grow: 1;flex-shrink: 1;max-width: 100%;}/* ckeditor5-horizontal-line/theme/horizontalline.css */.ck-content hr {margin: 15px 0;height: 4px;background: hsl(0, 0%, 87%);border: 0;}/* ckeditor5-block-quote/theme/blockquote.css */.ck-content blockquote {overflow: hidden;padding-right: 1.5em;padding-left: 1.5em;margin-left: 0;margin-right: 0;font-style: italic;border-left: solid 5px hsl(0, 0%, 80%);}/* ckeditor5-block-quote/theme/blockquote.css */.ck-content[dir="rtl"] blockquote {border-left: 0;border-right: solid 5px hsl(0, 0%, 80%);}/* ckeditor5-basic-styles/theme/code.css */.ck-content code {background-color: hsla(0, 0%, 78%, 0.3);padding: .15em;border-radius: 2px;}/* ckeditor5-table/theme/table.css */.ck-content .table {margin: 0.9em auto;display: table;}/* ckeditor5-table/theme/table.css */.ck-content .table table {border-collapse: collapse;border-spacing: 0;width: 100%;height: 100%;border: 1px double hsl(0, 0%, 70%);}/* ckeditor5-table/theme/table.css */.ck-content .table table td,.ck-content .table table th {min-width: 2em;padding: .4em;border: 1px solid hsl(0, 0%, 75%);}/* ckeditor5-table/theme/table.css */.ck-content .table table th {font-weight: bold;background: hsla(0, 0%, 0%, 5%);}/* ckeditor5-table/theme/table.css */.ck-content[dir="rtl"] .table th {text-align: right;}/* ckeditor5-table/theme/table.css */.ck-content[dir="ltr"] .table th {text-align: left;}/* ckeditor5-table/theme/tablecaption.css */.ck-content .table > figcaption {display: table-caption;caption-side: top;word-break: break-word;text-align: center;color: var(--ck-color-table-caption-text);background-color: var(--ck-color-table-caption-background);padding: .6em;font-size: .75em;outline-offset: -1px;}/* ckeditor5-page-break/theme/pagebreak.css */.ck-content .page-break {position: relative;clear: both;padding: 5px 0;display: flex;align-items: center;justify-content: center;}/* ckeditor5-page-break/theme/pagebreak.css */.ck-content .page-break::after {content: '';position: absolute;border-bottom: 2px dashed hsl(0, 0%, 77%);width: 100%;}/* ckeditor5-page-break/theme/pagebreak.css */.ck-content .page-break__label {position: relative;z-index: 1;padding: .3em .6em;display: block;text-transform: uppercase;border: 1px solid hsl(0, 0%, 77%);border-radius: 2px;font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif;font-size: 0.75em;font-weight: bold;color: hsl(0, 0%, 20%);background: hsl(0, 0%, 100%);box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15);-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}/* ckeditor5-media-embed/theme/mediaembed.css */.ck-content .media {clear: both;margin: 0.9em 0;display: block;min-width: 15em;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list {list-style: none;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list li {margin-bottom: 5px;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list li .todo-list {margin-top: 5px;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label > input {-webkit-appearance: none;display: inline-block;position: relative;width: var(--ck-todo-list-checkmark-size);height: var(--ck-todo-list-checkmark-size);vertical-align: middle;border: 0;left: -25px;margin-right: -15px;right: 0;margin-left: 0;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label > input::before {display: block;position: absolute;box-sizing: border-box;content: '';width: 100%;height: 100%;border: 1px solid hsl(0, 0%, 20%);border-radius: 2px;transition: 250ms ease-in-out box-shadow, 250ms ease-in-out background, 250ms ease-in-out border;}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label > input::after {display: block;position: absolute;box-sizing: content-box;pointer-events: none;content: '';left: calc(var(--ck-todo-list-checkmark-size) / 3);top: calc(var(--ck-todo-list-checkmark-size) / 5.3);width: calc(var(--ck-todo-list-checkmark-size) / 5.3);height: calc(var(--ck-todo-list-checkmark-size) / 2.6);border-style: solid;border-color: transparent;border-width: 0 calc(var(--ck-todo-list-checkmark-size) / 8) calc(var(--ck-todo-list-checkmark-size) / 8) 0;transform: rotate(45deg);}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label > input[checked]::before {background: hsl(126, 64%, 41%);border-color: hsl(126, 64%, 41%);}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label > input[checked]::after {border-color: hsl(0, 0%, 100%);}/* ckeditor5-list/theme/todolist.css */.ck-content .todo-list .todo-list__label .todo-list__label__description {vertical-align: middle;}/* ckeditor5-language/theme/language.css */.ck-content span[lang] {font-style: italic;}/* ckeditor5-code-block/theme/codeblock.css */.ck-content pre {padding: 1em;color: hsl(0, 0%, 20.8%);background: hsla(0, 0%, 78%, 0.3);border: 1px solid hsl(0, 0%, 77%);border-radius: 2px;text-align: left;direction: ltr;tab-size: 4;white-space: pre-wrap;font-style: normal;min-width: 200px;}/* ckeditor5-code-block/theme/codeblock.css */.ck-content pre code {background: unset;padding: 0;border-radius: 0;}/* ckeditor5-mention/theme/mention.css */.ck-content .mention {background: var(--ck-color-mention-background);color: var(--ck-color-mention-text);}@media print {/* ckeditor5-page-break/theme/pagebreak.css */.ck-content .page-break {padding: 0;}/* ckeditor5-page-break/theme/pagebreak.css */.ck-content .page-break::after {display: none;}}</style>
        </head>
        <body>
          <div class="ck-content">` + this.addTemplateContent + `
          </div>
        </body>
      </html>`

基于以上,博主实现了绝大部分功能的自定义ckeditor示例如下:
效果图:
在这里插入图片描述

实现代码:
在这里插入图片描述

import CKEditor from '@ckeditor/ckeditor5-vue2'
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor'
import EssentialsPlugin from '@ckeditor/ckeditor5-essentials/src/essentials'
import BoldPlugin from '@ckeditor/ckeditor5-basic-styles/src/bold'
import ItalicPlugin from '@ckeditor/ckeditor5-basic-styles/src/italic'
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline'
import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough'
import Code from '@ckeditor/ckeditor5-basic-styles/src/code'
import Link from '@ckeditor/ckeditor5-link/src/link'
import ParagraphPlugin from '@ckeditor/ckeditor5-paragraph/src/paragraph'
import Heading from '@ckeditor/ckeditor5-heading/src/heading'
import FontColor from '@ckeditor/ckeditor5-font/src/fontcolor'
import FontBackgroundColor from '@ckeditor/ckeditor5-font/src/fontbackgroundcolor'
import FontFamily from '@ckeditor/ckeditor5-font/src/fontfamily'
import FontSize from '@ckeditor/ckeditor5-font/src/fontsize'
import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment'
import Table from '@ckeditor/ckeditor5-table/src/table'
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar'
import TableCaption from '@ckeditor/ckeditor5-table/src/tablecaption'
import TableProperties from '@ckeditor/ckeditor5-table/src/tableproperties'
import TableCellProperties from '@ckeditor/ckeditor5-table/src/tablecellproperties'
import ListStyle from '@ckeditor/ckeditor5-list/src/liststyle'
import HorizontalLine from '@ckeditor/ckeditor5-horizontal-line/src/horizontalline'
import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote'
import Indent from '@ckeditor/ckeditor5-indent/src/indent'
import IndentBlock from '@ckeditor/ckeditor5-indent/src/indentblock'
import EasyImage from '@ckeditor/ckeditor5-easy-image/src/easyimage'
import Image from '@ckeditor/ckeditor5-image/src/image'
import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize'
import CloudServicesPlugin from '@ckeditor/ckeditor5-cloud-services/src/cloudservices'
import ImageInsert from '@ckeditor/ckeditor5-image/src/imageinsert'
import SpecialCharacters from '@ckeditor/ckeditor5-special-characters/src/specialcharacters'
import SpecialCharactersEssentials from '@ckeditor/ckeditor5-special-characters/src/specialcharactersessentials'
import Base64UploadAdapter from '@ckeditor/ckeditor5-upload/src/adapters/base64uploadadapter'
components: {
  ckeditor: CKEditor.component
}

在这里插入图片描述

<ckeditor :editor="editor" v-model="addTemplateContent" :config="editorConfig"></ckeditor>

在这里插入图片描述

data () {
    return {
      editor: ClassicEditor,
      editorConfig: {
        placeholder: 'Type something',
        plugins: [
          EssentialsPlugin,
          BoldPlugin,
          ItalicPlugin,
          Underline,
          Strikethrough,
          Code,
          Link,
          ParagraphPlugin,
          Heading,
          FontColor,
          FontBackgroundColor,
          FontFamily,
          FontSize,
          Alignment,
          Table,
          TableToolbar,
          TableCaption,
          TableProperties,
          TableCellProperties,
          ListStyle,
          HorizontalLine,
          BlockQuote,
          EasyImage,
          Image,
          ImageResize,
          CloudServicesPlugin,
          ImageInsert,
          Indent,
          IndentBlock,
          SpecialCharacters,
          SpecialCharactersEssentials,
          Base64UploadAdapter
        ],
        toolbar: {
          shouldNotGroupWhenFull: true,
          items: [
            'heading',
            '|',
            'bold',
            'italic',
            'underline',
            'strikethrough',
            'code',
            'link',
            '|',
            'numberedList',
            'bulletedList',
            '|',
            'fontFamily',
            'fontSize',
            'fontColor',
            'fontBackgroundColor',
            '|',
            'outdent',
            'indent',
            '|',
            'blockQuote',
            'alignment',
            'insertImage',
            'insertTable',
            'horizontalLine',
            'specialCharacters',
            '|',
            'undo',
            'redo'
          ]
        },
        heading: {
          options: [
            { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
            { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
            { model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
            { model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' }
          ]
        },
        fontFamily: {
          options: [
            'default',
            'Ubuntu, Arial, sans-serif',
            'Ubuntu Mono, Courier New, Courier, monospace'
          ]
        }[添加链接描述](https://ckeditor.com/docs/ckeditor5/latest/features/toolbar/toolbar.html),
        fontSize: {
          options: [
            10,
            12,
            'default',
            16,
            18,
            20
          ],
          supportAllValues: true
        },
        alignment: {
          options: ['left', 'center', 'right']
        },
        table: {
          contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'toggleTableCaption', 'tableProperties', 'tableCellProperties']
        }
      },
      addTemplateContent: ''
    }
  }

有更多的疑问,可以查询:CKEditor5文档

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值