el - 上传组件

<template>
<div class="freePic">
<!--  -->
	<el-upload
        class="avatar-uploader"
        :list-type="uploadType"
        :action="fileuploadUrl"
        :file-list="fileList"
        :before-upload="fileChange"
        :on-success="uploadSuccess"
        :on-error="uploadFiled"
        :on-exceed="overfileuploadNumber"
        :beforeRemove="fileBerofeRemove"
        :on-remove="fileRemove"
        :limit="limit"
        :disabled="!isShow"
        :on-preview="handlePictureCardPreview"
        :class="{hide:hideUpload}"
	>
    <i class="el-icon-upload"  v-if="isShow" style="font-size: 50px;line-height: 1.5;"><p style="font-size: 19px;font-weight: lighter">点击上传</p></i>
<!--    <el-button style="margin-left: 10px;" size="mini"  type="success" v-if="isShow" >点击上传</el-button>-->
	</el-upload>
  <div slot="tip" v-if="isShow" class="el-upload__tip">【请上传 {{this.suffixList.join('、')}} 文件, {{fileSize?'单个文件最大'+fileSize+'MB,':''}}<span style="color: red"> 上传{{limit?'最多'+limit:'可多'}}个</span>】</div>
    <!-- 图片放大展示 -->
    <el-dialog :visible.sync="dialogVisible">
        <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
</div>
</template>
<script>
import fileApi from '@/api/file-api';
export default {
	/* 图片展示 upload */
	name: "upload-pic-card",
    props: {
        /* v-model绑定的值 */
        value: {
            type: Array,
            default: () => []
        },
        /* 上传文件类型*/
        uploadType:{
          type: String,
          default: ''
        },
        //上传文件位置URL路径-分类
        uploadUrl: {
            type: String
        },
        /* 限制上传数量*/
        limit: {
            type: Number,
            default: null
        },
        /* 允许上传文件的后缀类型 */
        suffixList:{
          type:Array,
          default(){
            return []
          }
        },
        /* 允许上传文件的-大小 */
        fileSize:{
          type:Number,
          default: null
        },
        /* 是否服务端删除图片 */
        serverdel: {
            type: Boolean,
            default: true
        },
      disabled: {
        type: Boolean,
        default: false
      },
      isShow:{
        type: Boolean,
        default: false
      }
    },
	data() {
		return {
			dialogImageUrl: "",//展示地址链接
			dialogVisible: false,
      fileList: this.value,
      fileuploadUrl: fileApi.uploadFiles( `uploadChildPath=${this.uploadUrl}`), // 上传文件地址
		};
	},
  computed: {
    // 上传张数大于限制张数的时候将上传框隐藏
    hideUpload() {
      return !this.isShow;
    }
  },
     watch: {
        value: function(n) {
            this.fileList = n
            // 修改 v-model 数据
            this.$emit('input', n)
        },
    },
  methods: {
        //放大展示
		handlePictureCardPreview(file) {
			// this.dialogImageUrl = file.url;
			// this.dialogVisible = true;
      this.$emit("preview",file.url);
		},
         // 上传文件 改变时
         // 文件上传成功
        uploadSuccess(response, file, fileList) {
		      this.$emit("warrantySuccess",response)
          this.$emit('repairSuccess',response)
          this.$emit('upkeepSuccess',response)
            const { raw } = file
            const { data,  success} = response
            const { type } = raw;
            if(success && data) {
              data.map(item=>this.fileList.push({name: item.fileName, url: item.url, type: 'image'}))
                // this.fileList.push({name: data[0].fileName, url: data[0].url, type: 'image'})
                this.$message({message: '文件上传成功', type: 'success',duration: 2000})
            } else {
                this.$message({message: '文件上传失败', type: 'warning',duration: 2000})
                fileList.pop()
            }
            // this.loading = false
            // 修改 v-model 数据
            this.$emit('input', this.fileList)
            if (this.limit&&this.fileList.length >= this.limit) {
              document.getElementsByClassName('el-upload--picture-card')[0].style.display = 'none';
            }
        },
        // 图片改变时大小类型验证
        fileChange(file) {
            // if(file.status === "ready") {
                // 文件准备就绪未上传
                /*
                    image/jpeg
                    image/png
                    const isJPG = file.type === 'image/jpeg';
                */
                const FileExt = file.name.replace(/.+\./, "");
                const isLt5M = this.fileSize?file.size / 1024 / 1024 > this.fileSize:false;
                if (this.suffixList.length>0&&this.suffixList.toString().toLowerCase().indexOf(FileExt.toLowerCase()) === -1) {
                  this.$message({
                    type: 'warning',
                    message: `请上传后缀名为${this.suffixList.join(',')}文件!`
                  });
                  return false;
                }else {
                    if(isLt5M) {
                        this.$notify.error({
                            title: '异常',
                            message: `上传图片大小不能超过 ${this.fileSize}MB!`,
                            duration: 2000
                        });
                        return false
                    }else {
                      return true
                    }
                }
            // }
        },
        // 文件超出上传个数
        overfileuploadNumber(file, fileList) {
            this.$notify.error({
                title: '异常',
                message: `文件最多上传${fileList.length}个`,
                duration: 2000
            });
        },
        // 文件在列表被移除前
        async fileBerofeRemove(file, fileList) {
            if(file.status === 'success') {
              // console.log(!this.serverdel)
                return new Promise((resvole, reject) => {
                    if(!this.serverdel) {
                        resvole()
                        return
                    }
                    this.$confirm('该操作删除文件后不可找回,请谨慎操作?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).then(res =>{
                        Promise.all([fileApi.delServerFile({url: file.url}), file.id? fileApi.delete({id: file.id}):'']).then(res => {
                            const [resOne, resTwo] = res;
                            this.$message({type: 'success', message: '文件删除成功',duration: 2000})
                            resvole()
                        }).catch(err => {
                            this.$message({type: 'error', message: '文件删除失败',duration: 2000})
                            reject()
                        })
                    }).catch(err => console.log(err))
                })
            }
            if(file.status === "uploading") {
                this.$message({type: 'warning', message: '文件上传被取消',duration: 2000})
                // this.loading = false
            }
        },
         // 文件在列表被移除后
        fileRemove(file, fileList) {
          // this.fileList = this.fileList.filter(item => item.uid !== file.uid); // 删除时候过滤掉被删除的内容
            /*const index = this.fileList.findIndex(item => item.uid === file.uid)
            this.fileList.splice(index, 1)*/
            this.fileList=fileList
            // 修改 v-model 数据
            this.$emit('input', this.fileList)
            if (this.fileList.length>0&&this.fileList.length < this.limit) {
              document.getElementsByClassName('el-upload--picture-card')[0].style.display='';
            }
        },
        // 文件上传失败
        uploadFiled(err, file, fileList) {
            this.$message({message: '文件上传失败', type: 'warning',duration: 2000})
            this.loading = false
        },
        //获取文件名称
        getFileName(url) {
          let name = "";
          if (url && url !== "") {
            name = url.substring(url.lastIndexOf("/") + 1);
          } else {
            name = "无";
          }
          return name;
        },

	},
};
</script>
<style lang="scss" scoped>

.freePic ::v-deep .hide .el-upload--picture-card {
  display: none;
}
  .avatar-uploader .el-upload {
      border: 1px dashed #d9d9d9;
      border-radius: 6px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
      border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 100px;
    height: 100px;
    line-height: 100px;
    text-align: center;
  }
  .avatar {
    width: 100px;
    height: 100px;
    display: block;
  }
</style>

2. 调用

<uploadPicAcard uploadUrl="userDows/goods/test" v-model="goodsImgUrlList" :fileSize="5" :suffixList="suffixList_1" :uploadType="'picture-card'" :limit="8" :isShow="viewType" @preview="preview"/>

 // 文件预览组件 
 <FilePreviewComp ref="fpc"></FilePreviewComp>


import FilePreviewComp from "@/components/file-preview";
export default {
    name: 'goods-info-page',
    data() {
        return {
            suffixList_1:['jpg','png'],
             /* 货物图片 */
            goodsImgUrlList: [],
            viewType:false,
components: {FilePreviewComp },

    methods: {
      //文件预览 (1. 需要添加class:【message_box_alert】)
      preview(val){
        this.$refs.fpc.preview(val);
      },
    }

 3. 预览组件 (创建组件)

<style>
.el-dialog--center .el-dialog__body{
  padding: 0 30px;
}
.el-dialog__body {
  padding: 0;
  overflow-y: auto;
  height: calc(100vh - 50px) !important;
}
</style>

<template>
	<div v-if="typeS == '1'">
    <el-dialog
        :visible.sync="dialogFormVisible"
        :close-on-click-modal="false"
        :destroy-on-close="dialogDestroy"
        :fullscreen="true"
        width="100%"
        center>
      <h1 slot="title" class="title-h1">{{title}}</h1>
      <iframe width="100%" height="98%" :src="previewUrl"/>
    </el-dialog>
	</div>

  <div v-else-if="typeS == '2'">
    <viewimg-comp ref="viewimgcomp" :options="{image: previewUrl, smallImgShow: false, imgHeight: '40px'}" ></viewimg-comp>
  </div>

  <div v-else>
    <el-dialog
        :visible.sync="dialogFormVisible"
        :close-on-click-modal="false"
        :destroy-on-close="dialogDestroy"
        :fullscreen="true"
        center
    >
      <h1 slot="title" class="title-h1">{{title}}</h1>
      <iframe width="100%" height="98%" :src="previewUrl"/>
    </el-dialog>
  </div>
</template>



<script>

import {matchType} from "@/utils/utils";
import fileApi from "@/api/file-api";

export default {
  props:{
   /* previewUrl: {
      type: String,
      default: ''
    },*/
  },
  data(){
    return {
      title:'文件预览',
      typeS:'0',
      dialogDestroy:true,
      dialogFormVisible: false,
      previewUrl:'',
    }
  },
  mounted() {
  },
  methods: {
  /*  preview(val){
      // 这里需要取下 html 的高度,因为浏览器有默认的 margin
      const html = document.body.parentElement
      const scrollHeight = `${html ? html.scrollHeight-130 : document.body.scrollHeight-130}px`
      // const scrollWidth = `${html ? html.scrollWidth : document.body.scrollWidth}px`
      this.$alert(`<iframe style="padding: 0;margin: 0" width="100%" height="${scrollHeight}" src="${fileApi.onlinePreview(val)}"/>` , '预览', {
        dangerouslyUseHTMLString: true,
        customClass:'message_box_alert'
      });
    },*/
    // 文件预览
    preview(val){
      if (matchType(val) === "pdf"){
        this.typeS='1'
        this.previewUrl=val;
      }else if (matchType(val) === "image"){
        this.typeS='2'
        this.previewUrl=val;
        // 调用子组件的方法
        setTimeout(() => {
          return this.$refs.viewimgcomp.show()
        }, 100);
      }else {
        this.previewUrl=`https://view.officeapps.live.com/op/view.aspx?src=${val}`
      }
      this.dialogFormVisible = true
    }
  }
}


</script>
<style lang="scss" scoped>
/*.message_box_alert {
  word-break: break-all !important;
  width: 100%;
}*/
.title-h1{
  font-size: 17px;
  color: #000000;
}
</style>

/*根据文件名后缀区分 文件类型*/
export const matchType = fileName => {
    // 后缀获取
    var suffix = '';
    // 获取类型结果
    var result = '';
    try {
        var flieArr = fileName.split('.');
        suffix = flieArr[flieArr.length - 1].toLowerCase();
    } catch (err) {
        suffix = '';
    }
    // fileName无后缀返回 false
    if (!suffix) {
        result = false;
        return result;
    }
    // 图片格式
    var imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
    // 进行图片匹配
    result = imglist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'image';
        return result;
    };
    // 匹配txt
    var txtlist = ['txt'];
    result = txtlist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'txt';
        return result;
    };
    // 匹配 excel
    var excelist = ['xls', 'xlsx'];
    result = excelist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'excel';
        return result;
    };
    // 匹配 word
    var wordlist = ['doc', 'docx'];
    result = wordlist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'word';
        return result;
    };
    // 匹配 pdf
    var pdflist = ['pdf'];
    result = pdflist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'pdf';
        return result;
    };
    // 匹配 ppt
    var pptlist = ['ppt'];
    result = pptlist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'ppt';
        return result;
    };
    // 匹配 视频
    var videolist = ['mp4', 'm2v', 'mkv'];
    result = videolist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'video';
        return result;
    };
    // 匹配 音频
    var radiolist = ['mp3', 'wav', 'wmv'];
    result = radiolist.some(function (item) {
        return item == suffix;
    });
    if (result) {
        result = 'radio';
        return result;
    }
    // 其他 文件类型
    result = 'other';
    return result;
}

<think>我们正在寻找关于el-editor组件的使用文档或常见问题解决方案。根据用户提供的引用内容,虽然引用中提到了quill-editor(vue-quill-editor)的使用,但用户实际询问的是el-editor。注意:el-editor可能是Element UI库中的富文本编辑器组件,但Element UI官方并没有名为el-editor的组件,而是有一个名为el-form-item的组件用于表单,而富文本编辑器通常是第三方组件或自定义组件。在Element UI中,官方并没有提供内置的富文本编辑器,因此用户可能指的是某个特定的第三方组件或者可能是用户自己命名的组件。 然而,在用户提供的引用中,我们看到引用了vue-quill-editor(一个基于Quill的Vue富文本编辑器组件)的使用示例。因此,我们推测用户可能混淆了组件名称,或者实际上想使用的是vue-quill-editor(在Element UI项目中常用)而不是el-editor。 考虑到这一点,我们将按照以下步骤处理: 1. 澄清组件名称:Element UI没有el-editor组件,但可能有其他名称的组件或用户自定义组件。但根据引用,用户之前的问题可能是在询问富文本编辑器,而引用中多次提到quill-editor,所以很可能用户指的是vue-quill-editor(在Element UI项目中使用时,可能会被注册为自定义组件并命名为el-editor,但这并不常见)。 2. 如果用户确实指的是Element UI官方组件,那么需要指出Element UI没有内置富文本编辑器,但可以集成第三方编辑器如vue-quill-editor。 3. 如果用户指的是vue-quill-editor(即Quill编辑器在Vue中的封装),那么我们可以提供使用文档和常见问题。 根据引用内容,引用[2][3][4]都是关于vue-quill-editor的使用,因此我们假设用户实际想了解的是vue-quill-editor(Quill编辑器)的使用。 因此,我们将提供关于vue-quill-editor(Quill编辑器)的使用文档和常见问题解决方案。 ### 回答结构 1. 介绍vue-quill-editor 2. 安装和基本使用 3. 配置选项(特别是工具栏配置) 4. 常见问题(如图片上传、自定义模块等) 5. 参考引用 ### 回答内容 # vue-quill-editor 富文本编辑器的使用 vue-quill-editor 是一个基于 Quill 的 Vue 富文本编辑器组件。它允许我们在 Vue 项目中轻松集成 Quill 编辑器。下面将介绍其基本使用方法和常见问题解决方案。 ## 安装 首先,安装 `vue-quill-editor` 和其依赖的 Quill 包: ```bash npm install vue-quill-editor quill --save ``` ## 基本使用 在 Vue 组件中引入并使用: ```vue <template> <div class="quill-editor-example"> <quill-editor v-model="content" :options="editorOption" /> </div> </template> <script> import { quillEditor } from 'vue-quill-editor' import 'quill/dist/quill.core.css' import 'quill/dist/quill.snow.css' import 'quill/dist/quill.bubble.css' export default { components: { quillEditor }, data() { return { content: '', editorOption: { modules: { toolbar: [ ['bold', 'italic', 'underline'], ['blockquote', 'code-block'], [{ 'header': 1 }, { 'header': 2 }], [{ 'list': 'ordered'}, { 'list': 'bullet' }], ['link', 'image'] ] }, placeholder: '请输入内容...' } } } } </script> ``` ## 配置选项 `editorOption` 对象用于配置编辑器,其中 `modules` 用于配置模块,最常用的是 `toolbar` 工具栏模块。你可以根据需要自定义工具栏按钮。 ## 常见问题解决方案 ### 1. 图片上传 Quill 默认的图片处理是 base64 编码,这样会导致内容很长。通常我们需要实现图片上传到服务器,然后插入图片链接。 我们可以通过重写图片处理模块来实现上传功能。以下是一个结合 Element UI 的 el-upload 组件实现图片上传的示例: ```vue <template> <div> <quill-editor ref="quillEditor" v-model="content" :options="editorOption" /> <!-- 隐藏的图片上传按钮 --> <el-upload ref="uploadImg" class="upload-img" action="your_image_upload_api" :before-upload="beforeUpload" :on-success="handleSuccess" :show-file-list="false" style="display: none" > <button ref="uploadButton" style="display: none">上传图片</button> </el-upload> </div> </template> <script> import { quillEditor } from 'vue-quill-editor' export default { components: { quillEditor }, data() { return { content: '', editorOption: { modules: { toolbar: { container: [ // ... 工具栏配置 ['image'] // 添加图片按钮 ], handlers: { // 重写图片按钮的处理函数 'image': function() { // 触发隐藏的el-upload组件 this.$refs.uploadButton.click(); }.bind(this) } } } } } }, methods: { beforeUpload(file) { // 上传前的处理,比如检查文件类型和大小 }, handleSuccess(response, file) { // 上传成功后,获取图片URL const url = response.data.url; // 获取当前编辑器光标位置 const quill = this.$refs.quillEditor.quill; const range = quill.getSelection(); // 在光标位置插入图片 quill.insertEmbed(range.index, 'image', url); } } } </script> ``` 注意:上述代码中,我们重写了工具栏中图片按钮的点击事件,使其触发隐藏的el-upload组件上传按钮。上传成功后,将返回的图片URL插入到编辑器中。 ### 2. 自定义模块 如果需要扩展编辑器的功能,可以通过自定义模块实现。Quill 提供了强大的模块扩展机制。具体可参考 Quill 官方文档。 ### 3. 编辑器内容变化事件 使用 `@change` 事件可以监听编辑器内容的变化: ```vue <quill-editor v-model="content" @change="onChange" /> ``` ## 总结 vue-quill-editor 是一个功能丰富的富文本编辑器,通过合理的配置可以满足大部分需求。对于图片上传等高级功能,可以通过自定义处理函数实现。如果遇到问题,建议查阅 [Quill 官方文档](https://quilljs.com/docs/) 和 [vue-quill-editor 的 GitHub 仓库](https://github.com/surmon-china/vue-quill-editor)。 [^1]: 在封装组件时,如何设计可扩展的配置参数是一个值得思考的问题。如果将来需要增加新的配置项,我们可以通过提供插槽或者使用透传属性(如 `v-bind="$attrs"`)的方式来解决,这样就能在不修改组件内部的情况下扩展配置。 [^2]: 在配置工具栏时,我们可以通过 `modules` 选项来定义工具栏的按钮和布局,同时也可以为工具栏按钮添加自定义处理函数。 [^3]: 使用 vue-quill-editor 需要引入相应的 CSS 文件,否则编辑器样式可能不正常。 [^4]: 结合 Element UI 的上传组件可以实现图片上传功能,通过隐藏的上传按钮触发上传操作,并在上传成功后插入图片链接。 §§相关问题§§ 1. 如何解决 vue-quill-editor 在表单中提交内容时格式问题? 2. vue-quill-editor 如何实现自定义字体和字号? 3.vue-quill-editor 中如何实现图片和视频的自定义上传?</think>基于您提供的引用内容,我将为您整理 `el-editor`(实际应为 `quill-editor`)的使用文档和常见问题解决方案。从引用内容看,您可能混淆了组件名称(Element UI 无内置 `el-editor`),实际需求是 **Vue 富文本编辑器 vue-quill-editor** 的使用方法。 --- ### 🧩 一、vue-quill-editor 基础使用 #### 1. 安装与引入 ```bash npm install vue-quill-editor quill --save ``` ```vue <template> <quill-editor v-model="content" :options="editorOption" @blur="onEditorBlur" /> </template> <script> import { quillEditor } from "vue-quill-editor"; import "quill/dist/quill.core.css"; import "quill/dist/quill.snow.css"; // 主题样式 import "quill/dist/quill.bubble.css"; export default { components: { quillEditor }, data() { return { content: "", // 绑定编辑器内容 editorOption: { modules: { toolbar: [ // 配置工具栏 ["bold", "italic", "underline"], [{ list: "ordered" }, { list: "bullet" }], ["link", "image", "video"] ] }, placeholder: "请输入内容...", } }; }, methods: { onEditorBlur() { /* 失去焦点处理 */ } } }; </script> ``` #### 2. 核心配置项 | 参数 | 说明 | 示例 | |---------------|----------------------------------------------------------------------|------------------------------------------| | `v-model` | 双向绑定编辑器内容 | `v-model="htmlContent"` | | `modules` | 功能模块配置(工具栏/快捷键等) | `toolbar: [['bold'], ['image']]` | | `placeholder` | 空白提示文本 | `placeholder: "编辑正文..."` | | `theme` | 编辑器主题(默认 `snow`) | `theme: "bubble"` | --- ### ⚠️ 二、常见问题解决方案 #### 1. 图片上传自定义(核心难点) 需重写图片处理逻辑,结合 `el-upload`: ```vue <template> <quill-editor :options="editorOption"/> <!-- 隐藏的上传组件 --> <el-upload class="upload-img" action="/api/upload" :before-upload="beforeUpload" :on-success="handleSuccess" :show-file-list="false" > <div id="hidden-upload-btn" style="display:none"></div> </el-upload> </template> <script> export default { data() { return { editorOption: { modules: { toolbar: { container: [["image"]], handlers: { // 关键!重写图片按钮点击事件 image: () => { document.getElementById("hidden-upload-btn").click(); } } } } } }; }, methods: { beforeUpload(file) { // 校验图片类型/大小 const isImage = file.type.includes("image/"); return isImage; }, handleSuccess(res) { // 获取Quill实例 const quill = this.$refs.editor.quill; // 插入图片到光标位置 const index = quill.getSelection().index; quill.insertEmbed(index, "image", res.data.url); } } }; </script> ``` #### 2. 工具栏配置不生效 **原因**:`modules.toolbar` 格式错误 ✅ 正确格式: ```js modules: { toolbar: [ ["bold", "italic"], // 组1: 基础样式 [{ header: 1 }, { header:2 }], // 组2: 标题 ["image", "code-block"] // 组3: 媒体 ] } ``` #### 3. 内容改变监听 通过 `@change` 事件获取内容变化: ```vue <quill-editor @change="(content, delta, source) => handleChange(content)"/> ``` --- ### 🔧 三、高级功能扩展 #### 1. 自定义工具栏按钮 ```js handlers: { // 添加自定义按钮 customButton: function() { alert("自定义功能"); } }, toolbar: [ [{ 'custom': ['customButton'] }] // 使用自定义按钮 ] ``` #### 2. 内容高度自适应 ```css .ql-editor { min-height: 300px; max-height: 600px; overflow-y: auto; } ``` --- ### 📚 四、官方资源参考 1. [Quill 官方文档](https://quilljs.com/docs/configuration/) 2. [vue-quill-editor GitHub](https://github.com/surmon-china/vue-quill-editor) 3. [Element Upload 组件文档](https://element.eleme.io/#/zh-CN/component/upload) > 提示:图片上传需后端配合,推荐使用阿里云OSS/腾讯云COS直传方案[^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

oh LAN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值