HTML组件

组件分类

  • 折叠类:下拉菜单、侧边菜单栏、折叠面板、树形控件
  • 提示反馈类:通知框-提示框-确认框-对话框-抽屉;遮罩型-非遮罩型-顶部型-临近型
  • 增强类:表单、表格、按钮、超链接
  • 布局类:卡片、布局
  • 组合类:面包屑、轮播图、放大镜、分页器、滚动条

ElementPlus引入

全局引入

import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
app.use(ElementPlus)

按需引入 

import 'element-plus/theme-chalk/base.css'
import 'element-plus/theme-chalk/el-button.css'
import { ElButton } from 'element-plus';

按需自动引入 

// vite.config.ts
import { defineConfig } from 'vite'

//AutoImport+Components能按需自动引入ElementPlus组件、src目录下自定义的组件
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default defineConfig({
  // ...
  plugins: [
    // ...

    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})


ELMessage等弹窗组件,要自行引入

AntDesign引入 

5.8.5版本,按需引入组件即可;样式会自动引入
import { Button } from 'antd';

表单

概述

  • 核心标签:form、button、input、错误格式提示框、icon图标
  • 验证组合:输入框名称+input框+icon图标+错误提示框
  • 验证组合功能:输入内容不符合格式,错误提示框会显示相应内容
  • form组件功能:统一收集所有input框的数据;统一验证所有input框的格式
  • 验证规则包括:官方提供的常用验证规则、自定义验证函数

代码1

<template>
  <div class="header">
    <h2>淘宝<br>TaoBao</h2>
    <p>网站无障碍<br><a>文档图标</a> "登陆界面"改进意见</p>
  </div>   
  <div class="main">
    <div class="left">
      <h2>淘宝APP<br>随时随地,想淘就淘</h2>
      <a>点击下载<i>箭头图标</i></a>
    </div>
    
    <form v-on:submit="submit">
      <div>
        <span>用户名:</span>
        <i  class="iconfont icon-yonghu" style="padding-top:3px"></i>
        <input type="text" v-model="userName.value" v-on:blur="validateUserName()">
      </div>
      <h6>{{ userName.errorMessage }}</h6>
      <div>
        <span>密码:</span>
        <i  class="iconfont icon-mima" style="padding-top:3px"></i>
        <input type="password" v-model="password.value" v-on:blur="validatePassword()">
      </div>
      <h6>{{ password.errorMessage }}</h6>
        
      <button type="submit">登陆</button>
    </form>
    </div>
</template>

<script setup>
  import {reactive} from 'vue'
  const userName=reactive({
    isTure:false,
    value:'',
    errorMessage:''
  })
  const password=reactive({
    isTure:false,
    value:'',
    errorMessage:''
  })
  function validateUserName(){
    const {value}=username
    if(value===''){
      username.errorMessage='请输入用户名'
      username.isTure=false
    }else{
      username.errorMessage=''
      username.isTure=true
    }
  }
  function validatePassword(){
    const {value}=password
    if(value===''){
      password.errorMessage='请输入密码'
      password.isTure=false
    }else{
      password.errorMessage=''
      password.isTure=true
    }
  }
  function submit(e){
    e.preventDefault()
    if(userName.isTure&&password.isTure){
      console.log('输入格式都正确')
    }
  }
</script>

<style lang='less' scoped>
  .header{
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 85px;
    width: 1365px;
    padding: 20px 50px;
    h2{
      font-weight: 800;
      font-size: 23px;
      color: #FF7828;
    }
    p{
      font-size: 12px;
      line-height: 24px;
    }
  }
  .main{
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 540px;
    width: 1365px;
    padding: 110px 100px 100px 130px;
    background-image: url('./images/登陆背景.jpg');
    background-repeat: no-repeat;
    background-size: 100% 100%;
    .left{
      color: #FFFFFD;
      h2{
        font-size: 23px;
        font-weight: 800;
      }
      a{
        font-size: 16px
      };
    }
    form{
      width: 300px;
      padding-right: 40px;
      padding-top: 40px;
      background-color: #E9E9F2;
      div{
        display: flex;
        justify-content: flex-end;
        span{
          margin-right: 10px;
        }
      }
      h6{
        height: 30px;
        padding-left: 80px;
        line-height: 30px;
        color: red;
      }
      button{
        margin-left: 80px;
        margin-bottom: 20px;
        height: 30px;
        width: 180px;
        border: 2px blue solid;
        border-radius: 10px;
        background-color: blue;
        color: #FFFFFF;
        font-size: 16px;
      }
    }
    
  }
</style>

效果图1

代码2

vue的双向数据绑定,能办到不依赖form组件,就能收集到数据

<template>
    <el-row class="login_container">

        基础的 24 分栏
        五个响应尺寸:xs、sm、md、lg 和 xl

        <el-col :span="12" :xs="0"></el-col>
        <el-col :span="12" :xs="24">

            model表单数据绑定的reactive对象
            rules表单验证规则

            <el-form class="login_form" :model="loginForm" :rules="rules" ref='form'>
                <h1>Hello</h1>
                <h2>欢迎来到硅谷甄选</h2>

                el-form-item包裹输入框,内嵌错误提示框
                prop属性对应验证规则rules中的属性
         
                <el-form-item prop="username">

                    prefix-icon属性可以内嵌图标组件

                    <el-input :prefix-icon="User" v-model:model-value="loginForm.username"></el-input>
                </el-form-item>
                <el-form-item prop="password">
                    <el-input type="password" :prefix-icon="Lock" v-model:model-value="loginForm.password" show-password></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" size="default" class="login_btn" @click="login">登陆</el-button>
                </el-form-item>
            </el-form>
        </el-col>
    </el-row>
</template>

<script setup lang='ts'>
import {User,Lock} from "@element-plus/icons-vue"
import {reactive,ref} from 'vue'
import useUserStore from '@/store/modules/user'
import {useRouter} from 'vue-router'
import {ElNotification} from 'element-plus'
import 'element-plus/theme-chalk/el-notification.css'
import {getTime} from '@/utils/times'

const userStore=useUserStore()
const $router=useRouter()
let form=ref()
let loginForm=reactive({
    username:'admin',
    password:'111111'
})

自定义验证方法
rule:绑定数据的key
value:绑定数据的value
callback:无参数代表验证通过;有参数代表不通过,参数的值就是错误提示信息

const validatorUsername=(rule,value,callback)=>{
    if(/^[0-9]+/.test(value)){
        callback("开头不能用数字")
    }
    callback()
}

验证规则
组件库提供的规则:require、min、max、pattern
自定义规则:validator
错误提示信息:message
验证触发条件:trigger

let rules=reactive({
    username:[
        {required:true,min:2,max:10, message:'用户名2~6位',trigger:'blur'},
        {validator:validatorUsername,trigger:'blur'}
    ],
    password:[
        {required:true,min:6,max:15, message:'密码6~15位',trigger:'blur'}
    ],
})



const login=async ()=>{
    await form.value.validate()
    try{
        await userStore.userLogin(loginForm)
        $router.push('/')
        ElNotification({
            title:'HI,'+getTime()+"好",
            type:'success',
            message:'欢迎回来'
        })
    }catch(error){
        ElNotification({
            type:'error',
            message:error
        })
    }
    
}
</script>

<style scoped lang='scss'>
    .login_container{
        width: 100%;
        height: 100vh;
        background: url("@/assets/images/background.jpg") no-repeat;
        background-size: cover;
    }
    .login_form{
        position: relative;
        top: 30vh;
        width: 80%;
        padding: 0 40px;
        background: url("@/assets/images/login_form.png");
        background-size: cover;
        h1{
            color: white;
            font-size: 40px;
        }
        h2{
            height: 50px;
            line-height: 50px;
            font-size: 20px;
            color: white;
        }
        .login_btn{
            width: 100%;
        }
    }
</style>

效果图2 

代码3

Form栅格:span<=>宽度;offset<=>左侧padding

import React,{useState} from 'react'
import Scss from './Login.module.scss'
import {Form,Input,Button} from 'antd'
import {UserOutlined} from "@ant-design/icons"

export default function Login() {
  const onFinish = (values) => {

    //values是一个对象,key是每一个input框的name属性,value是input框的内容
    console.log('Success:', values);
  };
  const onFinishFailed = (errorInfo) => {
    console.log('Failed:', errorInfo);
  };
  return (
    <div className={Scss.container}>
      <div className={Scss.header}>
        <img src="/src/assets/logo.png" />
        <div className="title">React项目——后台管理系统</div>
      </div>
      <div className={Scss.main}>

        <Form className={Scss.form} labelCol={{span:4,offset:0}}  
            onFinish={onFinish} onFinishFailed={onFinishFailed}
            >
            <h3 className={Scss.title}>用户登陆</h3>
          
            //name属性表示验证字段名称,rules定义验证规则
            <Form.Item label="用户名" name="username"  
                rules={[{required: true,min:2,max:6,message:'请输入2~6位用户名'}]}
                >
                <Input suffix={<UserOutlined />} placeholder="请输入用户名" />
            </Form.Item>
          
            //name属性表示验证字段名称,rules定义验证规则
            <Form.Item label="密码" name="password"    //name属性表示验证字段名称
                rules={[{required: true,min:6,max:16,message:'请输入6~16位密码'}]}
                >
                <Input.Password placeholder="请输入密码" visibilityToggle={true} />
            </Form.Item>
          
            //提交按钮:所有input框验证通过,调用onFinish;否则调用onFinishFailed
            <Button type="primary" className={Scss.btn}  htmlType="submit">登陆</Button>
        </Form>

      </div>
    </div>
  )
}

效果图3

上传控件upload

浏览器端没有fs模块,想要读取本地文件upload控件是首选

  1. 点击按钮弹出dialog对话框
  2. 选择需要上传的文件
  3. 调用beforeUpload函数,判断上传文件的属性是否合理
  4. 将上传文件发送给action属性指定的服务器
  5. 调用uploaded函数,处理服务器的响应

分页器

概述

  • 组成:前进按钮、后退按钮、页码按钮、输入页码框、商品总数、每页商品数
  • 核心功能:点击页码按钮,返回当前页码和每页商品数

代码

<template>
  <div>
    <span @click="currentPage=currentPage-1">向前一页</span>
    <span v-show="currentPage-2>=1" @click="currentPage=currentPage-2">{{currentPage-2}}</span>
    <span v-show="currentPage-1>=1" @click="currentPage=currentPage-1">{{currentPage-1}}</span>
    <span>{{currentPage}}</span>
    <span v-show="currentPage+1<=maxPage" @click="currentPage=currentPage+1">{{currentPage+1}}</span>
    <span v-show="currentPage+2<=maxPage" @click="currentPage=currentPage+2">{{currentPage+2}}</span>
    <span @click="currentPage=currentPage+1">向后一页</span>
    <span>前往 <input type="text" @blur="toPage"> 页</span> 
  </div>
</template>

<script>
  export default {
    data(){
      return {
        currentPage:1,
        totalItem:91,
        ItemsPerPage:5
      }
    },
    computed:{
      maxPage(){
        return Math.ceil(this.totalItem/this.ItemsPerPage) 
      }
    },
    methods:{
      toPage(e){
        let {value}=e.target
        value=value*1
        if(isNaN(value)){
          return
        }else{
          this.currentPage=value
        }
        e.target.value=''
      }
    },
    watch:{
      currentPage(newVal){
        if(newVal<1){
          this.currentPage=1
        }
        if(newVal>this.maxPage){
          this.currentPage=this.maxPage
        }
        console.log(newVal)
      }
    }
  }
</script>

<style lang='less' scoped>
  span{
    margin: 0 5px;
    border: 2px blue solid;
    border-radius: 2px;
    padding: 5px 10px;
  }
  input{
    width: 40px;
  }
</style>

效果演示

放大镜 

代码

<head>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .main{
            display: flex;
        }
        .sImgBox{
            position: relative;
            width: 400px;
            height: 400px;
            margin-right: 100px;
        }
        .sImgBox img{
            width: 100%;
            height: 100%;
        }
        .sImgBox .lens{
            display: none;
            position: absolute;
            left: 0;
            top: 0;
            height: 100px;
            width: 100px;
            background-color: gray;
            opacity: 0.5;
            pointer-events: none; //遮罩层不停闪动,可以添加这个属性

        }
        .bImgBox{
            display: none;
            position: relative;
            width: 400px;
            height: 400px;
            overflow: hidden;
        }
        .bImgBox img{
            position: absolute;
            left: 0;
            top: 0;
            width: 800px;
            height: 800px;
        }
    </style>
</head>
<body>
    <div class="main" id="main">
        <div class="sImgBox">
            <img src="./400图片.png" id="sImg">
            <span class="lens" id="Len"></span>
        </div>
        <div class="bImgBox" id="bImg">
            <img src="./400图片.png" id="pic">
        </div>
    </div>
    <script>
        let main=document.getElementById('main')
        let sImg=document.getElementById('sImg')
        let Len=document.getElementById('Len')
        let bImg=document.getElementById('bImg')
        let pic=document.getElementById('pic')
        sImg.addEventListener('mouseenter',(e)=>{
            Len.style.display='block'
            bImg.style.display='block'
        })
        sImg.addEventListener('mouseleave',(e)=>{
            Len.style.display='none'
            bImg.style.display='none'
        })
        sImg.onmousemove=function(e){
            let x=e.clientX-main.offsetLeft-Len.offsetWidth/2
            let y=e.clientY-main.offsetTop-Len.offsetHeight/2
            if(x<0){
                x=0
            }
            else if(x>sImg.offsetWidth-Len.offsetWidth){
                x=sImg.offsetWidth-Len.offsetWidth
            }
            if(y<0){
                y=0
            }
            else if(y>sImg.offsetHeight-Len.offsetHeight){
                y=sImg.offsetHeight-Len.offsetHeight
            }
            Len.style.left=x+'px'
            Len.style.top=y+'px'
            pic.style.left=-x*2+'px'
            pic.style.top=-y*2+'px'
        }
    </script>
</body>

效果

轮播图 

代码1

遮盖型轮播图

<head>
    <style>
        .slideshow {
            position: relative;
            margin: auto;
            width: 200px;
            height: 200px;
            overflow: hidden;
        }

        .slideshow img {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            opacity: 0;
            transition: opacity 1s ease-in-out;
        }

        .slideshow img.active {
            opacity: 1;
        }
    </style>
</head>
<body>
    <div class="slideshow">
        <img src="./用户头像.png" class="active">
        <img src="./游戏_填充.png">
        <img src="./直播.png">
    </div>
    <script>
        var images = document.querySelectorAll('.slideshow img');
        var currentImage = 0;
        setInterval(function () {
            images[currentImage].classList.remove('active');
            currentImage = (currentImage + 1) % images.length; 
            images[currentImage].classList.add('active');
        }, 3000);	
    </script>
</body>

代码2

移动型轮播图示例

<head>
    <title>移动型轮播图</title>
    <style>
        .container {
            position: relative;
            margin: auto;
            width: 200px;
            height: 200px;
            overflow: hidden;
        }

        .slider {
            position: absolute;
            top: 0;
            left: 0;
            width: 300%;
            height: 100%;
            display: flex;
            animation: slide 10s infinite;
        }

        .slide {
            flex: 1;
            height: 100%;
            background-color: #ccc;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 48px;
            color: #fff;
        }

        .slide:nth-child(1) {
            background-color: #f00;
        }

        .slide:nth-child(2) {
            background-color: #0f0;
        }

        .slide:nth-child(3) {
            background-color: #00f;
        }

        @keyframes slide {
            0% {
                transform: translateX(0);
            }

            33.33% {
                transform: translateX(-100%);
            }

            66.66% {
                transform: translateX(-200%);
            }

            100% {
                transform: translateX(0);
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="slider">
            <div class="slide">1</div>
            <div class="slide">2</div>
            <div class="slide">3</div>
        </div>
    </div>
</body>

代码3

  • 手动点击实现轮播图的跳转
  • 有左右两个buttton切换按钮
  • 每张图片对应一个的独有的小圆点
  • 切换时,具有动画效果
<head>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .container{
            position: relative;
            margin: auto;
            width: 200px;
            height: 200px;
            overflow: hidden;
        }
        #slider{
            display: flex;
            width: 600px;
            font-size: 20px;
            font-weight: 600;
            text-align: center;
            transition: all 2s;
        }
        .slide:nth-child(1){
            width: 200px;
            height: 200px;
            background-color: pink;
        }
        .slide:nth-child(2){
            width: 200px;
            height: 200px;
            background-color: blue;
        }
        .slide:nth-child(3){
            width: 200px;
            height: 200px;
            background-color: yellow;
        }
        #leftBtn{
            position: absolute;
            left: 0;
            top: 70px;
            height: 60px;
            width: 40px;
        }
        #rightBtn{
            position: absolute;
            left: 160px;
            top: 70px;
            height: 60px;
            width: 40px;
        }
        ul{
            display: flex;
            margin: auto;
        }
        li{
            margin: 0 10px;
            border: 1px solid blue;
            border-radius: 5px;
            height: 10px;
            width: 10px;
            list-style: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <div id="slider">
            <div class="slide">1</div>
            <div class="slide">2</div>
            <div class="slide">3</div>
        </div>
        <button id="leftBtn">左</button>
        <button id="rightBtn">右</button>
        <ul id="circles">
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
    <script>
        const slider=document.getElementById('slider')
        const leftBtn=document.getElementById('leftBtn')
        const rightBtn=document.getElementById('rightBtn')
        const circles=document.getElementById('circles')
        const circleLis=circles.getElementsByTagName('li')

        let translateX=0
        leftBtn.onclick=function(){
            if(translateX<0){
                translateX=translateX+200
                slider.style.transform=`translateX(${translateX}px)`
            }
        }
        rightBtn.onclick=function(){
            if(translateX>-400){
                translateX=translateX-200
                slider.style.transform=`translateX(${translateX}px)`
            }
        }
        for(let i=0;i<circleLis.length;i++){
            circleLis[i].onclick=function(){
                translateX=-200*i
                slider.style.transform=`translateX(${translateX}px)`
            }
        }

    </script>
</body>

效果图

侧边导航栏

概述

非叶组件

  • 能嵌套子组件
  • 点击可以折叠子组件
  • 标题内容和子组件两部分组成

叶组件

  • 不能嵌套子组件
  • 点击可以进行路由跳转

代码1

<template>
  <ul class="drawers">
    <li v-for="drawer in drawers">
        <h3 @click="drawer.showSubmenu=!drawer.showSubmenu">{{drawer.title}}</h3>
        <div 
            v-for="submenu in drawer.submenu" 
            v-show="drawer.showSubmenu">
            {{submenu}}
        </div>
    </li>
  </ul>
</template>

<script>
export default {
  data () {
    return {
        drawers:[
            {
                title:'一级标题一',
                submenu:['二级标题一','二级标题二','二级标题三'],
                showSubmenu:false
            },
            {
                title:'一级标题二',
                submenu:['二级标题一','二级标题二','二级标题三'],
                showSubmenu:false
            }
        ]
    };
  },
}
</script>

<style lang='less' scoped>
li{
    list-style: none;
}
</style>

代码2

element plus讲究标签嵌套

routes=[
	{
		title:'首页',
		icon:'HomeFilled',
		path:'/layout/home'
	},
	{
		title:'数据大屏',
		icon:'HomeFilled',
		path:'/bigscreen'
	},
	{
		title:'权限管理',
		icon:'HomeFilled',
		children:[
			{
				title:'用户管理',
				icon:'HomeFilled',
				path:'/layout/usermanager'
			},
			{
				title:'角色管理',
				icon:'HomeFilled',
				path:'/layout/rolemanager'
			},
			{
				title:'菜单管理',
				icon:'HomeFilled',
				path:'/layout/menumanager'
			},
		]
	},
	{
		title:'商品管理',
		icon:'HomeFilled',
		children:[
			{
				title:'品牌管理',
				icon:'HomeFilled',
				path:'/layout/brandmanager'
			},
			{
				title:'属性管理',
				icon:'HomeFilled',
				path:'/layout/attrmanager'
			},
			{
				title:'SPU管理',
				icon:'HomeFilled',
				path:'/layout/spumanager'
			},
			{
				title:'SKU管理',
				icon:'HomeFilled',
				path:'/layout/skumanager'
			}
		]
	},
]


<el-menu background-color="#001529" text-color="white">
    <Menu :menuList="routes"></Menu>
</el-menu>


Menu组件

<template>
    <template v-for="(item) in menuList" :key="item.path">
        <el-menu-item v-if="!item.children" :index="item.path" @click="goRoute">
            <el-icon>
                <component :is="item.icon"></component>
            </el-icon>
            <template #title>
                <span>{{ item.title }}</span>
            </template>
        </el-menu-item>
        <el-sub-menu v-else :index="item.title">
            <template #title>
                <el-icon>
                    <component :is="item.icon"></component>
                </el-icon>
                <span>{{ item.title }}</span>
            </template>
            <Menu :menuList="item.children"></Menu>
        </el-sub-menu>
    </template>
</template>

<script setup lang='ts'>
import { useRouter } from 'vue-router';
let $router=useRouter()
defineProps(['menuList'])
const goRoute=(item)=>{
    $router.push(item.index)
}
</script>

<script lang="ts">
export default {
    name: "Menu",
}
</script>

代码3

ant design偏向属性配置项

import React from 'react'
import { Layout, Menu } from 'antd'
const { Sider } = Layout
import Scss from './Sider.module.scss'
import {AppstoreOutlined,ContainerOutlined,
        DesktopOutlined,MailOutlined,MenuFoldOutlined,
        MenuUnfoldOutlined,PieChartOutlined
} from '@ant-design/icons';
import { useNavigate } from 'react-router';

const siderStyle = {
    textAlign: 'center',
    color: '#fff',
    backgroundColor: '#001529',
};
function getItem(label, key, icon, children, type) {
    return {key,icon,children,label,type}
}
const items = [
    getItem('首页', '', <PieChartOutlined />),
    getItem('用户管理', 'usermanager', <PieChartOutlined />),
    getItem('角色管理', 'rolemanager', <PieChartOutlined />),
    getItem('商品', 'sub1', <MailOutlined />, [
        getItem('品牌管理', 'brandmanager'),
        getItem('商品管理', 'goodsmanager'),
    ]),
    getItem('图形图表', 'sub2', <AppstoreOutlined />, [
        getItem('柱形图', 'bargraph'),
        getItem('折线图', 'linegraph'),
        getItem('饼图', 'piegraph'),
    ])
];

export default function () { 
    const navigate=useNavigate()
    const clickMenuItem=(value)=>{
        navigate('/layout/'+value.key)
    }
    return (
        <Sider style={siderStyle}>
            <h1 className={Scss.title}>
                <img src="/src/assets/logo.png" />
                <span>硅谷后台</span>
            </h1>
            <Menu
                style={{textAlign:'left'}} mode='inline' theme='dark'
                items={items}
                onClick={clickMenuItem}
            />
        </Sider>
    )
}
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

stealPigs-youth

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

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

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

打赏作者

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

抵扣说明:

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

余额充值