highcharts插件使用总结和开发中遇到的问题及解决办法

highcharts插件使用总结和开发中遇到的问题及解决办法
关键词:highcharts 插件 使用 总结 开发 中 遇到 问题 解决办法
在js p中使用highchart的步骤:
第一步:引入highchart必需的js 文件

<! -- jqueryjs 要在引入highchart插件的js 之前引入 --> 
<script 
src="<%=basepath%>js /highcharts3.0.8/jquery -1.8.3.js ">
</script>
<!-- 实现highchart核心功能的js  -->
<script 
src="<%=basepath%>js /highcharts3.0.8/highcharts.js ">
</script>
<!--
导出和打印相关的js  ,因为这里修改过的exporting.js 包含中文,使用
charset="utf-8" 进行指定
-->
<script 
src="<%=basepath%>js /highcharts3.0.8/exporting.js " charset="utf-8">
</script>

view code
开发开发过程 遇到的问题:
1) js 的引入顺序错了,导致highchart的图表出不来,
highchart插件中用到了jquery ,当时jquery -1.8.3.js 的引入顺序放到了highchart插件js 的下面,
导致当加载highchart插件用到的js 时,找不到jquery 的js ,报出某个js 的函数不合法
因此 jquery 的js 要在引入highchart的js 之前引入
2) exporting.js 打印下载的js 中,提示的都是英文,
这里写图片描述
要显示中文,这里采用的开发方法 是修改exporting.js
p(s.lang,{printchart:”打印报表 “,downloadpng:”下载为png格式图片”,downloadjpeg:”下载为jpeg格式图片”,
downloadpdf:”下载为pdf格式文档”,downloadsvg:”下载为svg格式矢量图片”,contextbuttontitle:”打印 下载”});
修改后的效果:
这里写图片描述

当修改了exporting.js 后,当保存时,没法保存js ,提示编码问题
解决方法 是:
window>>preferences>>general>>content types
在右边的窗口中打开列表,选中”javascript”,在下面的”default encoding”右边的输入框中输入”utf-8”,再点”update”按钮
这里写图片描述
单击打印下载时,显示的下拉框在大部分的ie浏览器中显示的很难看,火狐下正常
这里写图片描述
原因: 上面的下拉框显示很长,是由于hr标签的原因,导致hr的宽度按照 100%进行了显示
解决方法 :
在显示highchart图标的js p页面中,添加hr的样式

<style>
   hr{height: 0;margin: 0;padding: 0;width: 0;}
</style>

第二步:组装添加显示highchart图表所用的数据

显示highchart图标的js 代码

  $(function () {
    //填充数据使用,使用jquery 来获取隐藏域的值
    var xaxistimeinfo = $("#xaxistime").val();
    var totalrecordinfo = $("#totalrecord").val();
    var totalrecordhyinfo = $("#totalrecordhy").val();
    var totalrecordljinfo = $("#totalrecordlj").val();

        $('#container').highcharts({
            chart: {
                type: 'spline'
            },
            title: {
                text: '每月订单数量统计'
            },
            subtitle: {
                text: ''
            },
            exporting:{ 
                filename:"订单统计", //下载显示的文件名称
                sourcewidth: 1000,     //下载图片的宽度
                sourceheight: 550,  //下载图片的高度
 //指定下载图片的url,这里使用的本地的java代码,没有使用官网的代码(那//样会受到highchart官网的网络限制,这里的java代码是结合的struts 1来//实现的,在java代码解决了导出图片中中文乱码的问题以及下载文件名乱码//的问题,详见java代码中说明)              
                url:'<%=basepath%>shop/neword er/orderpre/exportimage.do'//这里是一个重点哦,也可以修改exporting.js 中对应的url  
            },
            /**
             * 去掉图标的右下角hightcharts.com 的图标
             */
            credits: {
              enabled : false, //设置false就不会显示右下角的官网链接
              //右下角连接的显示位置         
              position:{ align: 'right',x: -8, verticalalign: 'bottom',y: -390 },
              //右下角链接的地址href:'<%=basepath%>shop/neword er/orderpre/ordersearch4highcharts.do?type=1',
             text:'区域图表',//右下角连接的名字
             style : {cursor:'pointer',color:'#909090',fontsize:'20px'}
            },
           xaxis: {
                categories: eval(xaxistimeinfo)
            },
           yaxis: {
                min: 0,
                title: {
                    text: '单位  (个)'
                }
            },
          //鼠标旁边的提示框的样式
          //1. point.y:.0f 提示框中显示的y轴单位的小数点位数
          //2. style="width:160px;height:50px" 提示框的宽高
          //3. point.key 坐标的x轴的值
           tooltip: {
                headerformat: '<span style="font-size:20px;">{point.key}</span><table style="width:160px;height:50px">',
           pointformat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.0f}  </b></td></tr>',
           footerformat: '</table>',
           shared: true,
           usehtml: true
           },
           plotoptions: {
                column: {
                    pointpadding: 0.2,
                    borderwidth: 0
                }
            },

            //图例的显示名称和数据
            //这里使用了eval函数处理一下,使用jquery 获取到的隐藏域的值
            //否则不会显示
          series: [{
                name: '裸机数量',
                data: eval(totalrecordljinfo)

            }, {
                name: '订单总量',
                data: eval(totalrecordinfo)

            },  {
                name: '合约机数量',
                data: eval(totalrecordhyinfo)

            }]
        });
}); 

view code
基本的highchart显示的数据格式是:
x轴数据信息
这里写图片描述
图例和显示数据的格式:
这里写图片描述
**因此我们要做的就是根据需求,在java后台组装好上面的数据,填充到highchart的js 代码中即可
导出的java后台代码 (使用的是struts 1)没有在struts 的配置文件中配置,直接是在js p中url请求
struts 1版的结合highchart导出图片的java代码
使用highchart调用本地的java类导出图片时,用到的jar包
batik-all-1.6.jar fop.jar xerces-2.9.0.jar**

/**
     * 配合highchart插件导出图片
     * @param mapping
     * @param form
     * @param request
     * @param response
     * @return
     * @throws exception
     */
    public actionforward exportimage (actionmapping mapping, actionform form,
            httpservlet开发 request request, httpservlet开发 response response)
            throws exception {
        log.info("图片导出................");
        request.setcharacterencoding("gb2312");//设置编码,解决乱码问题
        string type = request.getparameter("type");
        string svg = request.getparameter("svg");
        response.setcharacterencoding("gb2312");//设置编码,解决乱码问题
        string filename = request.getparameter("filename");
        filename = filename==null?"chart":filename;
        servlet开发 outputstream out = response.getoutputstream();
        log.info("type            :"+type+"                    filename:"+filename);
        if (null != type && null != svg) {
            svg = svg.replaceall(":rect", "rect");
            string ext = "";
            transcoder t = null;
            if (type.equals("image/png")) {
                ext = "png";
                t = new pngtranscoder();
            } else if (type.equals("image/jpeg")) {
                ext = "jpg";
                t = new jpegtranscoder();
            }else if (type.equals("application/pdf")) {  
                ext = "pdf";  
                t =(transcoder) new pdftranscoder();  
            }else if(type.equals("image/svg+xml")) 
                ext = "svg";   
//解决下载文件的文件名的乱码
            response.addheader("content-disposition", "attachment; filename="+ new string (filename.getbytes("gb2312"),"Iphone 苹果 ios -8859-1") + "."+ext);
            response.addheader("content-type", type);

            if (null != t) {
                transcoderinput input = new transcoderinput(new stringreader(svg));
                transcoderoutput output = new transcoderoutput(out);

                try {
                    t.transcode(input, output);
                } catch (transcoderexception e) {
                    out.print("problem transcoding stream. see the web logs for more details.");
                    e.printstacktrace();
                }
            } else if (ext.equals("svg")) {
                outputstreamwriter writer = new outputstreamwriter(out, "utf-8");
                writer.append(svg);
                writer.close();
            } else 
                out.print("invalid type: " + type);
        } else {
            response.addheader("content-type", "text/html");
            out.println("usage:\n\tparameter [svg]: the dom element to be converted." +
                    "\n\tparameter [type]: the destination mime type for the elment to be transcoded.");
        }
        out.flush();
        out.close();

        return null;  

} 

view code
使用highchart生成报表 信息的部分后台java代码
开发中遇到的问题
在开发中使用了webservice,在dao层的java代码中使用了map,但是map在webservice中并不支持,
解决方法 就是,在dao层的java代码中把map中的数据使用js on-lib插件转换成了js on
然后在action层中再使用js on-lib插件转换成map
java代码片段

dao层的代码片段,查询数据封装成map,然后把map数据放到list中,然后在把list放到map中,调用js on-lib插件转换成js on数据
list lthy = findsql(dto, sqlhy.tostring(), list.toarray());
list adminsqltotalhy = new arraylist();

//使用的linkedhashmap,放到map中的数据使用顺序的

map<string ,string> totalrecordhymap = new linkedhashmap<string ,string>();
for (int i = 0; lthy!=null && i < lthy.size(); i++) {
    object[] obj = (object[]) lthy.get(i);
                totalrecordhymap.put(obj[0]!=null?string.valueof(obj[0]):""    ,obj[1]!=null? string.valueof(obj[1]):"");
}

adminsqltotalhy.add(totalrecordhymap);


//保存到map中
map recordinfo = new linkedhashmap();
recordinfo.put("record_total", adminsqltotallist);
recordinfo.put("record_lj", adminsqltotallj);
recordinfo.put("record_hy", adminsqltotalhy);

//把map数据转化为js on数据
js onobject js onobjectfrommap =js onobject.fromobject(recordinfo); 

dto.setaddress(js onobjectfrommap.tostring()); 

view code

action层代码
/**
     * 1. 构造highchart的x轴用到的每月时间数据信息 (月份不足两位的没有补0,直接放在request中)<p/>
     * 2. 返回值map中月份不足2位的,进行了补0,该map在构造每月订单数量统计时使用
     * @throws parseexception
     */
    private map extracthighchartxaxisinfo(httpservlet开发 request request) throws parseexception {
        simpledateformat simpledateformat = new simpledateformat("yyyy-mm-dd");
        calendar curr = calendar.getinstance();
        calendar curr2 = curr;
        date beginpaydate = curr.gettime(); // 传进来的当前时间
        curr2.add(calendar.year, -1);
        curr2.add(calendar.month, 1);
        date endpaydate = curr2.gettime(); // 上一年的时间

        gregoriancalendar[] ga=getdate(simpledateformat.format(endpaydate), simpledateformat.format(beginpaydate));
        //循环数组
        stringbuffer stringbuffer = new stringbuffer();

        map initmap = new linkedhashmap();
        stringbuffer.append("[");
        for(gregoriancalendar e:ga)
        {
            stringbuffer.append("'"+modifytimeanthor(e)+"',");
            initmap.put(modifytime(e), 0);
        }
        //当ga数组中有数据时才删除末尾的   逗号
        if(stringbuffer.length()>1){
            stringbuffer.deletecharat(stringbuffer.length()-1);
        }
        stringbuffer.append("]");
        log.info("x轴用到的每月时间数据信息 (月份不足两位的没有补0)      "+stringbuffer.tostring());
        request.setattribute("highchartxaxisinfo", stringbuffer.tostring());
        return initmap;
    }

view code

/**
     * 
     * @param starttime
     * @param endtime
     * @return 返回开始时间和结束时间之间的每一个月
*  如:2013.1 2013.2 2013.3 2013.4 2013.5 2013.6 2013.7
     * @throws parseexception
     */
    public static gregoriancalendar[]  getdate(string starttime,string endtime) throws parseexception
    {
        vector<gregoriancalendar> v=new vector<gregoriancalendar>();
        simpledateformat  sdf=new simpledateformat("yyyy-mm");
        gregoriancalendar gc1=new gregoriancalendar(),gc2=new gregoriancalendar();
        gc1.settime(sdf.parse(starttime));
        gc2.settime(sdf.parse(endtime));
        do{
            gregoriancalendar gc3=(gregoriancalendar)gc1.clone();
            v.add(gc3);
            gc1.add(calendar.month, 1);             
         }while(!gc1.after(gc2));
        return v.toarray(new gregoriancalendar[v.size()]);
    }    

    //按格式获取时间,月份不足两位的补0
    public static string modifytime(gregoriancalendar e){
            string curdate = e.get(calendar.year)+"";
           if((e.get(calendar.month)+1)<10){
             curdate = curdate+".0" +(e.get(calendar.month)+1);
         }else {
             curdate = curdate+"."+(e.get(calendar.month)+1);
         }
           return curdate;
   }


    //按格式获取时间,月份不足两位的没有补0
    public static string modifytimeanthor(gregoriancalendar e){
            string curdate = e.get(calendar.year)+"";
            curdate = curdate+"."+(e.get(calendar.month)+1);
           return curdate;
   }

    /**
     * 1. 传递查询时间段的日期信息<p/>
     * 2. 要求查询当月以及向前倒推11个月(总共12的月)的数据<p/>
     * 3. 如当前日期是 2014.01,则构造开始时间2013.02,结束时间2014.02,都是由于oracle的between  and  
     * @param mulorderdto
     */
    private void passdateinfo(tmulordercountdto mulorderdto) {
        //传递月份信息
        simpledateformat simpledateformat = new simpledateformat("yyyy-mm");
        calendar curr = calendar.getinstance();
        //注意这里把curr变量的引用赋值给了curr2,当curr的值变化时,会影响到curr2的值
        calendar curr2 = curr;
        curr.add(calendar.month, 1);
        date beginpaydate = curr.gettime(); // 传进来的当前时间
        curr2.add(calendar.year, -1);
        date endpaydate = curr2.gettime(); // 上一年的时间
        mulorderdto.setbeginpaydate(simpledateformat.format(endpaydate));
        mulorderdto.setendpaydate(simpledateformat.format(beginpaydate));
    } 
view code


/**
     * 构造每个月  订单总量、合约机总量、裸机总量的字符串信息,用于填充highchart插件 
     * @param request
     * @param str
     */
    @suppresswarnings("unchecked")
    private void extracthighchartrecordinfo(httpservlet开发 request request,
            string str,map initmap) {
//接受最初传进来的map,使用了linkedhashmap的构造开发方法 ,参数为map
//由于数据的显示问题,这里构造了初始化的linkedhashmap(带顺序)
        map originaltotalmap = new linkedhashmap(initmap);
        map originaltotalljmap = new linkedhashmap(initmap);
        map originaltotalhymap = new linkedhashmap(initmap);
//把js on数据重新转换为map数据
        map<string, object> m = parsejs on2map(str);
//遍历map,拿到map的key的集合的迭代对象
         iterator<map.entry<string,object>> iterator = m.entryset().iterator();
            while(iterator.hasnext()){
//拿到当前的迭代对象
                map.entry<string, object> me = iterator.next();
//拿到当前迭代对象的key(可以看做map的key)
                string key = me.getkey();
                string keyw = key.substring(key.indexof("_")+1);
                if("lj".equals(keyw)){
//拿到当前迭代对象的value,是list对象,取第一个元素拿到map
                    list li = (list) me.getvalue();
                    //拿到map
                    map map = (map) li.get(0);
//覆盖一下初始化map的数据
                    originaltotalljmap.putall(map);
//拿到实际上保存数据的map集合,如保存每月裸机订单数据的map
                    iterator<map.entry<string,object>> iterator1 = originaltotalljmap.entryset().iterator();
                    stringbuffer stringbufferlj = new stringbuffer();
                    stringbufferlj.append("["); 
                    log.info("解析每月裸机数据..................................................");
                    while(iterator1.hasnext()){
                        map.entry<string, object> mea = iterator1.next();
//这里的getkey获取到是月份 如:2013.1
                        string keya = mea.getkey();
                        log.info(keya+"               "+mea.getvalue());
// getvalue()是获取当月的订单数量,保存到stringbuffer中,并处理//stringbuffer数据使得满足highchart插件的要求
                        stringbufferlj.append(mea.getvalue()+",");
                    }
                    //当iterator1中有数据时才删除掉末尾的逗号
                    if(stringbufferlj.length()>1){
                        stringbufferlj.deletecharat(stringbufferlj.length()-1);
                    }
                    stringbufferlj.append("]");
                    log.info("裸机订单数量                                                                                                                              :"+stringbufferlj.tostring());
                    request.setattribute("totalrecordlj", stringbufferlj.tostring());

                }
                if("hy".equals(keyw)){
                    list li = (list) me.getvalue();
                    //拿到map
                    map map = (map) li.get(0);
                    originaltotalhymap.putall(map);
                    iterator<map.entry<string,object>> iterator1 = originaltotalhymap.entryset().iterator();
                    stringbuffer stringbufferhy = new stringbuffer();
                    stringbufferhy.append("[");
                    log.info("解析每月合约机数据..................................................");
                    while(iterator1.hasnext()){
                        map.entry<string, object> mea = iterator1.next();
                        string keya = mea.getkey();
                        stringbufferhy.append(mea.getvalue()+",");
                        log.info(keya+"               "+mea.getvalue());
                    }

                    //当iterator1中有数据时才删除掉末尾的逗号
                    if(stringbufferhy.length()>1){
                        stringbufferhy.deletecharat(stringbufferhy.length()-1);
                    }
                    stringbufferhy.append("]");
                    log.info("合约机订单数量                                                                                 :"+stringbufferhy.tostring());
                    request.setattribute("totalrecordhy", stringbufferhy.tostring());

                } 
                if("total".equals(keyw)){
                    list li = (list) me.getvalue();
                    //拿到map
                    map map = (map) li.get(0);
                    originaltotalmap.putall(map);
                    iterator<map.entry<string,object>> iterator1 = originaltotalmap.entryset().iterator();
                    stringbuffer stringbuffertotal = new stringbuffer();
                    stringbuffertotal.append("[");
                    log.info("解析每月订单总量数据..................................................");
                    while(iterator1.hasnext()){
                        map.entry<string, object> mea = iterator1.next();
                        string keya = mea.getkey();
                        stringbuffertotal.append(mea.getvalue()+",");
                        log.info(keya+"               "+mea.getvalue());
                    }

                    //当iterator1中有数据时才删除掉末尾的逗号
                    if(stringbuffertotal.length()>1){
                        stringbuffertotal.deletecharat(stringbuffertotal.length()-1);
                    }
                    stringbuffertotal.append("]");

                    log.info("总订单数量                                                                                                             :"+stringbuffertotal.tostring());
                    request.setattribute("totalrecord", stringbuffertotal.tostring());

                }
            }
    } 

view code
highcharts效果图
这里写图片描述
附上js p的代码

<%@ page language="java" import="java.util.*" pageencoding="gbk"%>
<%
string path = request.getcontextpath();
string basepath = request.getscheme()+"://"+request.getservername()+":"+request.getserverport()+path+"/";
%>
<head>
<script src="<%=basepath%>js /highcharts3.0.8/jquery -1.8.3.js "></script>

<script src="<%=basepath%>js /highcharts3.0.8/highcharts.js "></script>
<script src="<%=basepath%>js /highcharts3.0.8/exporting.js " charset="utf-8"></script>
<style>
    hr{height: 0;margin: 0;padding: 0;width: 0;}
</style>
   <script>
      $(function () {
    var xaxistimeinfo = $("#xaxistime").val();
    var totalrecordinfo = $("#totalrecord").val();
    var totalrecordhyinfo = $("#totalrecordhy").val();
    var totalrecordljinfo = $("#totalrecordlj").val();

        $('#container').highcharts({
            chart: {
                type: 'column'
            },
            title: {
                text: '每月订单数量统计'
            },
            subtitle: {
                text: ''
            },
        exporting:{
                filename:"订单统计",
                sourcewidth: 1000,
                sourceheight: 550,
                url:'<%=basepath%>shop/neword er/orderpre/exportimage.do'//这里是一个重点哦,也可以修改exporting.js 中对应的url  
            },
            /**
             * 去掉图标的右下角hightcharts.com 的图标
             */
       credits: {
             enabled : false,
        position:{ align: 'right',x: -8, verticalalign: 'bottom',y: -390 },
        href:'<%=basepath%>shop/neword er/orderpre/ordersearch4highcharts.do?type=1',
        text:'区域图表',
        style : {cursor:'pointer',color:'#909090',fontsize:'20px'}
           },
            xaxis: {
                categories: eval(xaxistimeinfo)


            },
            yaxis: {
                min: 0,
                title: {
                    text: '单位  (个)'
                }
            },

            tooltip: {
                headerformat: '<span style="font-size:20px;">{point.key}</span><table style="width:160px;height:50px">',
                pointformat: '<tr><td style="padding:0">{series.name}: </td>' +
                    '<td style="padding:0"><b>{point.y:.0f}  </b></td></tr>',
                footerformat: '</table>',
                shared: true,
                usehtml: true

            },
            plotoptions: {
                column: {
                    pointpadding: 0.2,
                    borderwidth: 0
                }
            },
            series: [{
                name: '裸机数量',
                data: eval(totalrecordljinfo)

            }, {
                name: '订单总量',
                data: eval(totalrecordinfo)

            },  {
                name: '合约机数量',
                data: eval(totalrecordhyinfo)

            }]
        });
});

    function showareaview(){
           window.document.location.href="<%=basepath%>shop/neword er/orderpre/ordersearch4highcharts.do?viewtype=1"
   }

    function showlineview(){
           window.document.location.href="<%=basepath%>shop/neword er/orderpre/ordersearch4highcharts.do?viewtype=3"
   }
   </script>


</head>

<body>

<span onclick="showareaview();" style="cursor: pointer">区域图显示</span>&nbsp;&nbsp;|&nbsp;&nbsp;
<span onclick="showlineview();" style="cursor: pointer">曲线图显示</span>&nbsp;&nbsp;|&nbsp;&nbsp;
<span  style="font-weight: 900;color: red;cursor: default">柱状图</span>
   <div id="container" style="min-width:90%;height:90%;"></div>
<input type="hidden" id="totalrecordlj" value="${totalrecordlj}"></input>
<input type="hidden" id="totalrecordhy" value="${totalrecordhy}"></input>
<input type="hidden" id="totalrecord" value="${totalrecord}"></input>
<input type="hidden" id="xaxistime" value="${highchartxaxisinfo}"></input>
</body>
</<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue使用Highcharts的热力图需要安装Highcharts和Vue-highcharts插件。可以通过以下命令进行安装: ```bash npm install highcharts --save npm install vue-highcharts --save ``` 接下来,在Vue组件引入Vue-highcharts并注册Highcharts组件。然后,在template使用`<highcharts>`标签来渲染热力图。以下是一个示例: ```vue <template> <div> <highcharts :options="chartOptions"></highcharts> </div> </template> <script> import VueHighcharts from 'vue-highcharts' import Highcharts from 'highcharts' import HighchartsHeatmap from 'highcharts/modules/heatmap' HighchartsHeatmap(Highcharts) export default { components: { highcharts: VueHighcharts }, data() { return { chartOptions: { chart: { type: 'heatmap' }, title: { text: 'Monthly Sales Data' }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] }, yAxis: { categories: ['Product A', 'Product B', 'Product C'], title: null }, colorAxis: { min: 0, minColor: '#FFFFFF', maxColor: Highcharts.getOptions().colors[0] }, series: [{ name: 'Sales', borderWidth: 1, data: [[0, 0, 100], [0, 1, 50], [0, 2, 75], [1, 0, 60], [1, 1, 90], [1, 2, 80], [2, 0, 70], [2, 1, 40], [2, 2, 85]] }] } } } } </script> ``` 在上面的代码,首先引入了VueHighchartsHighchartsHeatmap。然后,在组件的data选项定义了chartOptions对象,该对象包含了热力图的配置选项。最后,在template使用`<highcharts>`标签来渲染热力图,并将chartOptions对象传递给它的options属性。 注意,这里要先注册HighchartsHeatmap模块,然后在chartOptions指定chart类型为heatmap。最后,在series指定热力图的数据。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值