年末贡献--一个表单验证

目前网上的一些开源验证插件

嗯,怎么说呢,用起来非常非常不方便,很多时候你要看看他自定义的验证规则,跟原有的网站有冲突,而且很多时候他的样式都是自己定义好的,放在主文件里面,譬如,formvalidator--这个插件用了不少时间,bug多,样式不灵活,所以自己定制了一个表单验证插件。


/**
 * 这是自行定制的表单验证控件。网上的控件bug多,而且样式控制不灵活。没办法了。
 * 为什么不写成seajs?因为这个是全局的表单验证,而不是仅仅在seajs里面用的
 * 局部变量。
 * @edward
 * */

var formValidate={
    //--这个是default默认设置,你随时可以通过setDefault来改变这个变量的。
    defaultConfig:{
        showFocus:function(rulename,element,message){

        }//显示提示信息时候执行这个方法。
        ,showError:function(rulename,element,message){

        }//显示错误信息时候的显示方式。
        ,showSuccess:function(rulename,element,message){

        }//显示成功信息时候的显示方式。
        //--清空所有提示信息的方法,这里定义,当然,系统会给你一个默认的实现方式的。rulenames表示当前所有规则的集合数组
        //elements表示这个所有提示元素的集合数组。
        ,clearTips:function(rulenames,elements){

        }

    }
    ,setDefaultConfig:function(opts){
        var _this=this;
        _this.defaultConfig= $.extend({},_this.defaultConfig,opts);//这里是设置当前的默认规则。
    }
    ,init:function(opts){

        var _this=this;

        //--内部用的ajax任务列表。
        var ajaxQueue=function(theOpts){

            var aq_settings={
                queues:[] //任务列表
            };
            aq_settings= $.extend({},aq_settings,theOpts);

            var _aq_interval=null;

            var aq_return={
                run:function(callBack){
                    if(_aq_interval!=null){
                        //--已经执行了。。请等待。。
                        console.log("ajaxQueue正在执行中。。请等待。");
                        return;
                    }


                    var aqInnerData={
                        index:0
                        ,isBusy:false
                        ,isComplete:false
                    };

                    if(aq_settings.queues==undefined||aq_settings.queues.length<=0){
                        console.log("ajaxQueue error:queues没有任何任务。");
                        return;
                    }
                    var queueCtr={
                        break:function(){
                            aqInnerData.isComplete=true;
                        }
                    };
                    _aq_interval=setInterval(function(){
                        if(aqInnerData.isBusy==true){
                            return;
                        }
                        if(aqInnerData.isComplete){
                            clearInterval(_aq_interval);
                            _aq_interval=null;
                            if(callBack){
                                callBack();
                            }
                            return;
                        }

                        aqInnerData.isBusy=true;
                        var _task=aq_settings.queues[aqInnerData.index];
                        var _i_paras={};
                        if(_task.inner_paras){
                            _i_paras=_task.inner_paras;
                        }

                        var _ajax_opts={
                            url:_task.url
                            ,data:_task.data==undefined?{}:_task.data
                            ,dataType:_task.dataType
                            ,method:_task.method==undefined?"get":_task.method

                            ,success:function(_resutl){

                                if(_task.success){
                                    _task.success(_resutl,queueCtr,_i_paras);
                                }
                                aqInnerData.isBusy=false;
                                if(aqInnerData.index>=aq_settings.queues.length){
                                    aqInnerData.isComplete=true;
                                }
                            }
                            ,error:function(){

                                if(_task.error){
                                    _task.error(queueCtr,_i_paras);
                                }
                                aqInnerData.isBusy=false;
                                if(aqInnerData.index>=aq_settings.queues.length){
                                    aqInnerData.isComplete=true;
                                }
                            }
                        };
                        $.ajax(_ajax_opts);
                        aqInnerData.index++;

                    },10);
                }
            };


            return aq_return;
        };

        //--这个是当前初始化的表单验证器的默认设置---优先级比默认设置要高。
        var _defaults={
            showFocus:function(rulename,element,message){

            }//显示提示信息时候执行这个方法。
            ,showError:function(rulename,element,message){

            }//显示错误信息时候的显示方式。
            ,showSuccess:function(rulename,element,message){

            }//显示成功信息时候的显示方式。
            //--清空所有提示信息的方法,这里定义,当然,系统会给你一个默认的实现方式的。rulenames表示当前所有规则的集合数组
            //elements表示这个所有提示元素的集合数组。
            ,clearTips:function(rulenames,elements){

            }
            //---
            ,validate:{} //这个是验证对象。。格式如下:
            /**
             * "username":{
            tipsElement:$("#userTips")
                ,getValue:function(){
                    return $("#username").val();
                }//这是获取当前值的方式,是因为每次输入框等的值都会变,那么就只能用这种方式来了---而且你永远不知道具体要验证对象的取值方式。像现在网上那种组件徒增麻烦。按照网上的做法,假如是一个var innerData={t1:'nihao'};这种值,那么应该如何验证呢。
               ,errorMsg:"" //错误信息,请注意,假如functionvalidate和ajaxvalidate返回的是false,那么直接用这个errorMsg,否则,将采用返回的字符串作为错误信息。
               ,successMsg:""
                ,functionValidate:function(theValue){
                    if(util.checkEmpty(theValue)){
                        return "请输入用户名称";
                    }
                    if(util.isAccountString_includeChinese(theValue)){
                        return "用户名称只允许普通英文字母及中文!";
                    }
                    return true;
                }//一个functionValidate--我就不提供那些什么的compareValidator,funcValidator了,直接写代码吧。
                ,ajaxValidate:[]
                 ajaxValidator:[{
url:""
data:""
dataType:""
success:function(){}
error:function(){}
}]
                 异步验证方式,
                 请注意,
                 这里虽然用的是异步,
                 但是这个方法参数是经过封装的,
                 就是为了准确知道获取到url信息的时机,
                 所以它并非直接传到ajaxjquery的。。
                 为了完成这个,在error后面返回的必定是false---假如你真要返回true让验证通过我也无话可说。
                 在success里面返回的是true或者false或者错误信息。为了让他们可以按照队形一步一步执行下去而又不会锁住浏览器,
                 我用了一个队列来执行这个方法,依次执行完各个方法,只要有一个验证不通过,那么后面的都不会执行,不通过了。
                 functionValidate会比ajaxValidate先执行,假如functionValidate通过,那么会继续验证ajaxValidate
      */
        };
        //--显示方式优先级最高的是目前方法的opts,其次到全局的默认显示方式。
        _defaults= $.extend({},_defaults,_this.defaultConfig);
        _defaults= $.extend({},_defaults,opts);



        var returnObj={
            clearAllTips:function(){
                for(var key in _defaults.validate){
                    var item=_defaults.validate[key];
                    if(item.tipsElement!=undefined){
                        _defaults.clearTips(key,item.tipsElement);
                    }
                }
            }//--清除所有验证样式和提示。


            ,showFocus:function(ruleName,msg){
                var item=_defaults.validate[ruleName];
                if(item==undefined){
                    return;
                }
                if(item.tipsElement!=undefined){
                    _defaults.showFocus((ruleName,item.tipsElement,msg));
                }
            }
            ,clearTips:function(ruleName){
                var item=_defaults.validate[ruleName];
                if(item==undefined){
                    return;
                }
                if(item.tipsElement!=undefined){
                    _defaults.clearTips(ruleName,item.tipsElement);
                }
            }
            //--验证所有参数,验证成功或验证失败后会回调函数。
            ,validateAll:function(_innerOpts){
                var _child=this;
                var __innerSetting={
                    callback:function(validateRes){
                        //--validateRes是true或者false。
                    }
                };
                var ruleNames=[];
                for(var key in _defaults.validate){
                    ruleNames.push(key);
                }
                _child.validateMutiRules(ruleNames,_innerOpts);
            }
            //--验证多个规则。
            ,validateMutiRules:function(rules,_inneropts){


                var _child=this;
                var items=[];
                var innerSettings={
                    callback:function(){}
                };
                if(typeof(_inneropts)=="function"){
                    innerSettings.callback=function(){
                        _inneropts();
                    }
                }
                else{
                    innerSettings= $.extend({},innerSettings,_inneropts);
                }
                for(var ii=0;ii<rules.length;ii++){
                    var singleItem=_defaults.validate[rules[ii]];
                    if(singleItem==undefined){

                    }
                    else{
                        singleItem.taskName=rules[ii];
                        items.push(singleItem);
                    }
                }
                if(items.length<=0){
                    console.warn("任何需要验证的规则!!!!");
                    return;
                }
                //--内部用的任务列表执行器
                var taskQueue=function(theOpts){

                    var aq_settings={
                        queues:[] //任务列表
                    };
                    aq_settings= $.extend({},aq_settings,theOpts);

                    var m_aq_interval=null;

                    var aq_return={
                        run:function(callBack){
                            if(m_aq_interval!=null){
                                //--已经执行了。。请等待。。
                                console.warn("taskQueue正在执行中。。请等待。");
                                return;
                            }


                            var aqInnerData={
                                index:0
                                ,isBusy:false
                                ,isComplete:false
                            };

                            if(aq_settings.queues==undefined||aq_settings.queues.length<=0){
                                console.warn("ajaxQueue error:queues没有任何任务。");
                                return;
                            }
                            var _queueCtr={
                                break:function(){
                                    aqInnerData.isComplete=true;
                                }
                                ,setBusy:function(trueOrFalse){
                                    aqInnerData.isBusy=trueOrFalse;
                                }
                                ,increase:function(){
                                    aqInnerData.index++;
                                    if(aqInnerData.index>=aq_settings.queues.length){
                                        aqInnerData.isComplete=true;
                                    }
                                }
                            };
                            m_aq_interval=setInterval(function(){
                                if(aqInnerData.isBusy==true){
                                    console.log("muti interval控制器在忙。");
                                    return;
                                }
                                if(aqInnerData.isComplete){
                                    clearInterval(m_aq_interval);
                                    m_aq_interval=null;
                                    if(callBack){
                                        callBack();
                                    }
                                    return;
                                }

                                aqInnerData.isBusy=true;
                                var _task=aq_settings.queues[aqInnerData.index];
                                if(_task){
                                    var __data=_task.data;
                                    _task.run(_queueCtr,__data);
                                }
                            },20);
                        }
                    };


                    return aq_return;
                };
                var _queues=[];
                //--构造需要的队列参数。
                var __current_bool=true;
                for(var i2=0;i2<items.length;i2++ ){
                    _queues.push(
                        {
                            data:items[i2]
                            ,run:function(ctr,__data){
                            _child.validateRule(__data.taskName,function(result_res){
                                ctr.setBusy(false);
                                ctr.increase();
                                if(result_res){

                                }
                                else{
                                    __current_bool=false;
                                }
                            });
                        }
                        }
                    );
                }

                var _tqueue=taskQueue({
                    queues:_queues
                });
                _tqueue.run(function(){
                   if(innerSettings.callback){
                       innerSettings.callback(__current_bool);
                   }
                });


            }
            //--验证某个规则。
            ,validateRule:function(ruleName,__innerOpts){
                var __innerSetting={
                    callback:function(validateRes){

                    }
                };
               if(typeof(__innerOpts)=="function"){
                __innerSetting.callback=__innerOpts;
               }
                else{
                   __innerSetting= $.extend({},__innerSetting,__innerOpts);
               }
                var item=_defaults.validate[ruleName];
                if(item==undefined){
                    return;
                }

                var __theValue=item.getValue();
                var __validate_result=true;

                //--假如没有functionValidate及ajaxValidate的话,那么就为默认成功。
                if(item.functionValidate==undefined&&(item.ajaxValdiate==undefined||item.ajaxValidate.length<=0)){
                    _defaults.showSuccess(ruleName,item.tipsElement,item.successMsg);
                    if(__innerSetting.callback){
                        __innerSetting.callback(true);
                    }
                    return;
                }
                if(item.functionValidate!=undefined){
                    var res_bool=item.functionValidate(__theValue);
                    if(res_bool==false||typeof res_bool =="string"){
                        //--验证不通过。
                        var emsg=typeof(res_bool)=="string"?res_bool:item.errorMsg;
                        _defaults.showError(ruleName,item.tipsElement,emsg);
                        if(__innerSetting.callback){
                            __innerSetting.callback(false);
                        }
                        return;
                    }
                    if(item.ajaxValidate==undefined||item.ajaxValidate.length<=0){
                        _defaults.showSuccess(ruleName,item.tipsElement,item.successMsg);
                        if(__innerSetting.callback){
                            __innerSetting.callback(true);
                        }
                        return;
                    }
                }
                //--没有ajax的话,不验证。
                if(item.ajaxValidate==undefined||item.ajaxValidate.length<=0){
                    if(__innerSetting.callback){
                        __innerSetting.callback(true);
                    }

                    return;
                }
                //--构造 ajax 的queue的参数。
                var _queuelist=[];

                for(var ii=0;ii< item.ajaxValidate.length;ii++){
                    var _ajax_item=item.ajaxValidate[ii];
                    if($(item.tipsElement).length<=0){
                        console.warn(ruleName+"的提示元素不存在!");
                    }
                    var _a_opt={
                        url:_ajax_item.url
                        ,inner_paras:$.extend({},_ajax_item) //这是传进去的参数啊。
                        ,data:_ajax_item.data==undefined?{}:(typeof(_ajax_item.data)=="function"?_ajax_item.data():_ajax_item.data)
                        ,dataType:_ajax_item.dataType
                        ,method:_ajax_item.method==undefined?"get":_ajax_item.method
                        ,success:function(_resutl,ctr,_inner_option){


                            if(_inner_option.success){
                               var bool_res2= _inner_option.success(_resutl);
                                if(bool_res2==false||typeof (bool_res2)=="string"){
                                    ctr.break();
                                    var emsg=item.errorMsg;
                                    if(typeof(bool_res2)=="string"){
                                        emsg=bool_res2;
                                    }
                                    __validate_result=false;
                                    _defaults.showError(ruleName,item.tipsElement,emsg);
                                    return;
                                }
                                else{

                                }
                            }
                            else{
                                ctr.break();
                                __validate_result=false;
                                _defaults.showError(ruleName,item.tipsElement,item.errorMsg);
                                return;
                            }
                        }
                        ,error:function(ctr,__inner_option){
                            if(__inner_option.error){
                                var bool_res2= __inner_option.error();
                                if(bool_res2==false||typeof (bool_res2)=="string"){
                                    ctr.break();
                                    var emsg=item.errorMsg;
                                    if(typeof(bool_res2)=="string"){
                                        emsg=bool_res2;
                                    }
                                    __validate_result=false;
                                    _defaults.showError(ruleName,item.tipsElement,emsg);
                                    return;
                                }
                                else{

                                }
                            }
                            else{
                                ctr.break();
                                __validate_result=false;
                                _defaults.showError(ruleName,item.tipsElement,__inner_option.url+"无法响应.");
                                return;
                            }
                        }
                    };
                    _queuelist.push(_a_opt);
                }
                var _aqQueue=ajaxQueue({
                    queues:_queuelist
                });

                _aqQueue.run(function(){
                    if(__validate_result==true){
                        _defaults.showSuccess(ruleName,item.tipsElement,item.successMsg);
                    }
                    if(__innerSetting.callback){
                        __innerSetting.callback(__validate_result);
                    }
                });

            }
        };


        return returnObj;

    }
};



使用实例:


<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2015/2/3
  Time: 21:54
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="/static/lib/jquery-1.11.0.min.js"></script>
    <script type="text/javascript" src="/static/lib/util.min.js"></script>
    <script type="text/javascript" src="/static/lib/formValidate.js"></script>
    <link href="/static/components/component.css" rel="stylesheet" type="text/css" />

</head>
<body>

<div class="subnav">
    <div class="content-menu ib-a blue line-x">

    </div>
</div>
<div class="pad-10">
    <form action="" method="post" id="myform">
        <fieldset>
            <legend>基本信息</legend>
            <table width="100%" class="table_form">
                <tr>
                    <th width="80">帐号:</th>
                    <td class="y-bg">
                        <input id="txt_account" type="text" class="input-text validate[required]" size="30"  name="model.account" />
                        <span id="tips_account"></span> <!--tips for title-->
                    </td>
                </tr>
                <tr>
                    <th width="80">密码:</th>
                    <td class="y-bg">
                        <input id="txt_pwd" type="text" class="input-text validate[required]" size="30"  name="model.title" />
                        <span tipsfor="pwd"></span> <!--tips for title-->
                    </td>
                </tr>
                <tr>
                    <th width="80">确认密码:</th>
                    <td class="y-bg">
                        <input id="txt_confirm" type="text" class="input-text validate[required]" size="30"  name="model.title" />
                        <span id="tips_confirm"></span> <!--tips for title-->
                    </td>
                </tr>

                <tr>
                    <th width="80">标题:</th>
                    <td class="y-bg">
                        <input id="txt_title" type="text" class="input-text validate[required]" size="30"  name="model.title" />
                        <span tipsfor="title"></span> <!--tips for title-->
                    </td>
                </tr>


                <tr>
                    <th width="80">来源:</th>
                    <td class="y-bg">
                        <input id="txt_source" type="text" size="30"  name="model.source" />
                        <span tipsfor="source"></span> <!--tips for source-->
                    </td>
                </tr>


                <tr>
                    <th width="80">图片:</th>
                    <td class="y-bg">
                        <input  id="txt_logo" type="hidden" size="30"  name="model.logo" />
                    </td>
                </tr>


                <tr>
                    <th width="80">分类:</th>
                    <td class="y-bg">
                        <select id="sel_category" name="model.category" >
                            <option value="">--请选择分类--</option>
                        </select>

                        <span tipsfor="category"></span> <!--tips for category-->
                    </td>
                </tr>
                <tr>
                    <th width="80">时间:</th>
                    <td class="y-bg">
                        <input id="txt_publishdate" type="text"size="30"  name="model.publishdate" />
                        <span tipsfor="publishdate"></span> <!--tips for publishdate-->
                    </td>
                </tr>



                <tr>
                    <th width="80">简介:</th>
                    <td class="y-bg">
                        <textarea id="txt_description" type="text" class="input-text validate[]" cols="75" rows="5"  name="model.description" > </textarea>
                    </td>
                </tr>

                <tr>
                    <th width="80">详细内容:</th>
                    <td class="y-bg">

                     <textarea id="txt_memo" rows="15" cols="50"></textarea>

                        <span tipsfor="memo"></span> <!--tips for memo-->

                    </td>
                </tr>

            </table>
        </fieldset>
        <div class="bk15"></div>

        <input type="button" class="button" id="dosubmit" name="dosubmit"  value="保存"/>
        <div><input type="button" class="button" id="validate_account" name="dosubmit"  value="验证account"/></div>
        <div><input type="button" class="button" id="validate_muti" name="dosubmit"  value="验证muti"/></div>
    </form></div>
<script>
    formValidate.setDefaultConfig({
        showFocus:function(rulename,element,message){

            $(element).removeClass("validator_success");
            $(element).removeClass("validator_error");
            $(element).removeClass("validator_info");
            $(element).addClass("validator_info");
            $(element).text(message);

        }//显示提示信息时候执行这个方法。
        ,showError:function(rulename,element,message){
            $(element).removeClass("validator_success");
            $(element).removeClass("validator_error");
            $(element).removeClass("validator_info");
            $(element).addClass("validator_error");
            $(element).text(message);

        }//显示错误信息时候的显示方式。
        ,showSuccess:function(rulename,element,message){
            $(element).removeClass("validator_success");
            $(element).removeClass("validator_error");
            $(element).removeClass("validator_info");
            $(element).addClass("validator_success");
            $(element).text(message);
        }//显示成功信息时候的显示方式。
        //--清空所有提示信息的方法,这里定义,当然,系统会给你一个默认的实现方式的。rulenames表示当前所有规则的集合数组
        //elements表示这个所有提示元素的集合数组。
        ,clearTips:function(rulenames,elements){
            $(elements).removeClass("validator_success");
            $(elements).removeClass("validator_error");
            $(elements).removeClass("validator_info");
            $(elements).text("");
        }

    });
    var formV=formValidate.init({
        validate:{
            "model.account":{
                tipsElement:$("#tips_account")
                ,getValue:function(){
                    return $("#txt_account").val();
                }//这是获取当前值的方式,是因为每次输入框等的值都会变,那么就只能用这种方式来了---而且你永远不知道具体要验证对象的取值方式。像现在网上那种组件徒增麻烦。按照网上的做法,假如是一个var innerData={t1:'nihao'};这种值,那么应该如何验证呢。
                ,errorMsg:"格式错误" //错误信息,请注意,假如functionvalidate和ajaxvalidate返回的是false,那么直接用这个errorMsg,否则,将采用返回的字符串作为错误信息。
                ,successMsg:"填写正确-_-"
                ,functionValidate:function(theValue){
                    if(util.checkEmpty(theValue)){
                        return "请输入用户名称";
                    }
                    if(util.isAccountString_includeChinese(theValue)==false){
                        return "用户名称只允许普通英文字母及中文!";
                    }
                    return true;
                }//一个functionValidate--我就不提供那些什么的compareValidator,funcValidator了,直接写代码吧。

                ,ajaxValidate:[{
                    url:"json/validateTrue.jsp"
                    ,data:function(){
                        return {"account":$("#txt_account").val()};
                    }
                    ,dataType:"json"
                    ,success:function(data){
                        console.log(data);
                        return true;
                        return "第一次不让他过。。";

                        if(data.state==true){
                            return true;
                        }
                        return data.msg;
                    }
                    ,error:function(){
                        console.log("服务端错误!");
                     return "服务端验证失效";
                    }
                }
                   , {
                        url:"json/validateFalse.jsp"
                        ,data:function(){
                        return {"account":$("#txt_account").val()};
                    }
                        ,dataType:"json"
                        ,success:function(data){
                        console.log(data);

                            return true;
                        if(data.state==true){
                            return true;
                        }
                        return data.msg;
                    }
                        ,error:function(){
                        console.log("服务端错误!");
                        return "服务端验证失效";
                    }
                    }
                ]
            }
            ,"model.confirm":{
                tipsElement:$("#tips_confirm")
                ,getValue:function(){
                    return $("#txt_confirm").val();
                }//这是获取当前值的方式,是因为每次输入框等的值都会变,那么就只能用这种方式来了---而且你永远不知道具体要验证对象的取值方式。像现在网上那种组件徒增麻烦。按照网上的做法,假如是一个var innerData={t1:'nihao'};这种值,那么应该如何验证呢。
                ,errorMsg:"格式错误" //错误信息,请注意,假如functionvalidate和ajaxvalidate返回的是false,那么直接用这个errorMsg,否则,将采用返回的字符串作为错误信息。
                ,successMsg:"填写正确-_-"
                ,functionValidate:function(theValue){
                    if(util.checkEmpty(theValue)){
                        return "请确认密码";
                    }
                    if(theValue!=$("#txt_pwd").val()){
                        return "两次密码输入不一致。";
                    }
                    return true;
                }//一个functionValidate--我就不提供那些什么的compareValidator,funcValidator了,直接写代码吧。

                ,ajaxValidate:[{
                    url:"json/validateTrue.jsp"
                    ,data:function(){
                        return {"account":$("#txt_account").val()};
                    }
                    ,dataType:"json"
                    ,success:function(data){

                        return false;

                        if(data.state==true){
                            return true;
                        }
                        return "confirm error:"+data.msg;
                    }
                    ,error:function(){
                        console.log("服务端错误!");
                        return "服务端验证失效";
                    }
                }
                    , {
                        url:"json/validateFalse.jsp"
                        ,data:function(){
                            return {"account":$("#txt_account").val()};
                        }
                        ,dataType:"json"
                        ,success:function(data){
                            console.log(data);

                            return true;
                            if(data.state==true){
                                return true;
                            }

                            return data.msg;
                        }
                        ,error:function(){
                            console.log("服务端错误!");
                            return "服务端验证失效";
                        }
                    }
                ]
            }
        }
    });
    $("#validate_account").click(function(){
        formV.validateRule("model.account",{
            callback:function(result){
                alert("验证结果:"+result);
            }
        });
    });
    $("#validate_muti").click(function(){
       formV.validateMutiRules(["model.account","model.confirm"],{
            callback:function(result){
                alert("验证结果:"+result);
            }
        });
    });
</script>
</body>
</html>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值