d3+jQuery横向树图,可展开

效果图

在这里插入图片描述

实现:

<!doctype html>
<html>
<head>
    <meta charset="utf-8">

    <link rel="stylesheet" type="text/css" href="gqct.css">
    <title>d3+jQuery横向树图</title>
    <script src="https://cdn.bootcss.com/d3/3.2.7/d3.min.js"></script>
    <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script>
</head>

<body>
<div class="container" id="treecontainer">
    <div class="menu">
        <div id="product_tree"></div>
    </div>
</div>
</body>
<script type="text/javascript">
    var container;
    var zoom;
    var rootData;
    var depthInfo;
    var rootName;//根节点名称

    jQuery(document).ready(function () {
        /* resizeScreen();*/

        //selectChange();
        var child=document.getElementById("product_tree");
        child.innerHTML = '';
        getData();
    });

    var getData =function() {
        // 测试内容
        rootData = {
            "downward": {
                "direction": "downward",
                "name": "origin",
                "children": [
                    {
                        "name": "金科城有限公司",
                        "amount": "100",
                        "ratio": "55%",
                        "hasHumanholding":true,
                        "hasChildren":true,
                        "isExpand": false,
                        "children": [
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            }
                        ]
                    },
                    {
                        "name": "大鹅普测有限公司",
                        "amount": "100",
                        "ratio": "55%",
                        "hasHumanholding":true,
                        "hasChildren":true,
                        "isExpand": false,
                        "children": [
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            }
                        ]
                    },
                    {
                        "name": "北京多彩有限公司",
                        "amount": "100",
                        "ratio": "55%",
                        "hasHumanholding":true,
                        "hasChildren":true,
                        "isExpand": false,
                        "children": [
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司名字",
                                "hasHumanholding":false,
                                "hasChildren":true,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            }
                        ]
                    },
                    {
                        "name": "哈尔滨维斯特科技发展有限公司",
                        "hasHumanholding":false,
                        "hasChildren":true,
                        "amount": "100",
                        "ratio": "55%",
                        "children": []
                    },
                    {
                        "name": "哈尔滨维斯特科技发展有限公司",
                        "hasHumanholding":false,
                        "hasChildren":true,
                        "isExpand": false,
                        "amount": "100",
                        "ratio": "55%",
                        "children": [
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            },
                            {
                                "name": "公司或股东名字",
                                "hasHumanholding":false,
                                "amount": "100",
                                "ratio": "55%",
                                "children": []
                            }
                        ]
                    }
                ]
            }
        }
        rootName = '北京伴学科技有限公司';
        drawing();
    };
    var	drawing = function() {
        var _this = this;
        // var rootName = ''; //根节点的名字
        var rootRectWidth = 0; //根节点rect的宽度
        var forUpward = true;

        var treeChart = function(d3Object) {
            this.d3 = d3Object;
            this.directions = ['downward'];
        };


        treeChart.prototype.drawChart = function() {
            // First get tree data for both directions.
            this.treeData = {};
            var self = this;
            self.directions.forEach(function(direction) {
                self.treeData[direction] = _this.rootData[direction];
            });
            // rootName = '北京伴学科技有限公司';
            rootRectWidth = _this.rootName.length * 15;
            self.graphTree(self.getTreeConfig());
        };

        treeChart.prototype.getTreeConfig = function() {
            var treeConfig = {
                'margin': {
                    'top': 10,
                    'right': 5,
                    'bottom': 0,
                    'left': 5
                }
            }

            treeConfig.chartWidth = (1600 - treeConfig.margin.right - treeConfig.margin.left);
            treeConfig.chartHeight = (800 - treeConfig.margin.top - treeConfig.margin.bottom);
            treeConfig.centralHeight = treeConfig.chartHeight / 2;
            treeConfig.centralWidth = treeConfig.chartWidth / 6;
            treeConfig.linkLength = 300;
            treeConfig.duration = 500; //动画时间
            return treeConfig;
        };

        treeChart.prototype.graphTree = function(config) {


            var self = this;
            var d3 = this.d3;
            var linkLength = config.linkLength;
            var duration = config.duration;
            var hasChildNodeArr = [];
            var id = 0;
            var diagonal = d3.svg.diagonal()
                .projection(function(d) {
                    return [d.y, d.x];
                });
            var pathFunc;
            if (false) {
                pathFunc = diagonal;
            } else {
                pathFunc = funLine;
            }
            var zoom = d3.behavior.zoom()
                .scaleExtent([0.5, 2])
                .on('zoom', redraw);
            var svg = d3.select('#product_tree')
                .append('svg')
                .attr('width', config.chartWidth + config.margin.right + config.margin.left)
                .attr('height', config.chartHeight + config.margin.top + config.margin.bottom)
                .attr('xmlns','http://www.w3.org/2000/svg')
                .on('mousedown', disableRightClick)
                .call(zoom)
                .on('dblclick.zoom', null);
            var treeG = svg.append('g')
                .attr('class', 'gbox')
                .attr('transform', 'translate(' + config.margin.left + ',' + config.margin.top + ')');

            //箭头
            var markerDown = svg.append("marker")
                .attr("id", "resolvedDown")
                .attr("markerUnits", "strokeWidth") //设置为strokeWidth箭头会随着线的粗细发生变化
                .attr("markerUnits", "userSpaceOnUse")
                .attr("viewBox", "0 -5 10 10") //坐标系的区域
                .attr("refX", 0) //箭头坐标
                .attr("refY", 0)
                .attr("markerWidth", 12) //标识的大小
                .attr("markerHeight", 12)
                .attr("orient", "0") //绘制方向,可设定为:auto(自动确认方向)和 角度值
                .attr("stroke-width", 2) //箭头宽度
                .append("path")
                .attr("d", "M0,-5L10,0L0,5") //箭头的路径
                .attr('fill', '#000'); //箭头颜色

            // Initialize the tree nodes and update chart.

            for(var d in this.directions) {
                var direction = this.directions[d];
                var data = self.treeData[direction];
                if (typeof(data) != "undefined") {
                    data.x0 = config.centralHeight;
                    data.y0 = config.centralWidth;
                    data.children.forEach(collapse);
                    update(data, data, treeG);
                }
            }
            function update(source, originalData, g) {
                console.log(source)
                var direction = originalData['direction'];
                var node_class = direction + 'Node';
                var link_class = direction + 'Link';
                var downwardSign =1;
                var nodeColor = '#8b4513';

                var isExpand = false;
                var nodeSpace = 160;
                var tree = d3.layout.tree().sort(sortByDate).nodeSize([nodeSpace, 0]);
                var nodes = tree.nodes(originalData);
                var links = tree.links(nodes);
                var offsetY = -config.centralHeight;

                nodes.forEach(function(d) {
                    d.y = downwardSign * (d.depth * linkLength) + config.centralWidth;
                    d.x = d.x - offsetY;
                    if(d.name == 'origin') {
                        d.x = config.centralHeight;
                        d.y += downwardSign * 0; // 左右两树图根节点之间的距离
                    }
                });

                // Update the node.
                var node = g.selectAll('g.' + node_class)
                    .data(nodes, function(d) {
                        return d.id || (d.id = ++id);
                    });
                var nodeEnter = node.enter().append('g')

                    .attr('class', node_class)
                    //			.classed('alink',true)//为选择名称而添加的统一class
                    .attr('data-text', function(d) {
                        return d.name;
                    })
                    .attr('transform', function(d) {
                        return 'translate(' + source.y0 + ',' + source.x0 + ')';
                    })

                    .style('cursor', function(d) {
                        return(d.name == 'origin') ? '' : (d.children || d._children) ? 'pointer' : '';
                    });
                // .on('click', click);


                nodeEnter.append("svg:rect")
                    .attr("x", function(d) {
                        return(d.name == 'origin') ? -(rootRectWidth / 2) : 95;
                    })
                    .attr("y", function(d) {
                        return(d.name == 'origin') ? -20 : -16;
                    })
                    .attr("width", function(d) {
                        return(d.name == 'origin') ? rootRectWidth : 150;
                    })
                    .attr("height", 40)
                    .attr("rx", 10)
                    .style("stroke", function(d) {
                        return(d.name == 'origin') ? "#0505ee" : "#CCC";//外边框颜色
                    })
                    .style("fill", function(d) {
                        return(d.name == 'origin') ? "#0080E3" :  "#FFF";//节点背景色
                    });

                nodeEnter.append('circle')
                    .attr('r', 1e-6);
                nodeEnter.append("text")
                    .attr("class", "linkname")
                    .attr("x",function(d) {
                        return(d.name == 'origin') ? '0' : '170';
                    })
                    .attr('dy', function(d) {
                        return(d.name == 'origin') ? '.35em' : '-3';
                    })
                    .attr("text-anchor",'middle')
                    .attr('fill', '#337ab7')
                    .text(function(d) {
                        if(d.name == 'origin') {
                            // return ((forUpward) ? '根节点TOP' : '根节点Bottom');
                            return _this.rootName;
                        }
                        if(d.repeated) {
                            return '[Recurring] ' + d.name;
                        }
                        return(d.name.length > 10) ? d.name.substr(0, 10) : d.name;
                    })
                    .style({
                        'fill-opacity': 1e-6,
                        'fill': function(d) {
                            if(d.name == 'origin') {
                                return '#fff';
                            }
                        },
                        'font-size': function(d) {
                            return(d.name == 'origin') ? 14 : 13;
                        },
                        'cursor': "pointer"
                    })
                    .on('click', Change_modal);

                nodeEnter.append("text")
                    .attr("class", "linkname")
                    .attr("x",function(d) {
                        return(d.name == 'origin') ? '0' : '170';
                    })
                    .attr("dy", function(d) {
                        return(d.name == 'origin') ? '0' :'9';
                    })
                    .attr("text-anchor",'middle')
                    .text(function(d) {
                        return d.name.substr(10, d.name.length);
                    })
                    .style({
                        'fill': '#337ab7',
                        'font-size': function(d) {
                            return(d.name == 'origin') ? 14 : 13;
                        },
                        'cursor': "pointer"
                    });
                // .on('click', Change_modal);
                nodeEnter.append("text")
                    .attr("x",function(d) {
                        return(d.name == 'origin') ? '0' : '170';
                    })
                    .attr("dy", function(d) {
                        return(d.name == 'origin') ? '.35em' :  '20';
                    })
                    .attr("text-anchor",'middle')
                    .attr("class", "linkname")
                    .style("fill", "#7F7F7F")
                    .style('font-size', 10)
                    .text(function(d) {
                        var str = (d.name == 'origin') ? '' :"认缴金额:"+ d.amount +"万";
                        return(str.length > 13) ? str.substr(0, 13) + ".." : str;
                    });
                nodeEnter.append("text")
                    .attr("x", "30")
                    .attr("dy", function(d) {
                        return(d.name == 'origin') ? '.35em' :'-5';
                    })
                    .attr("text-anchor", "start")
                    .attr("class", "linkname")
                    .style("fill", "green")
                    .style('font-size', 10)
                    .text(function(d) {
                        return(d.name == 'origin') ? "" : d.ratio;
                    });

                nodeEnter.append("text")
                    .attr("x", '35')
                    .attr("dy", function(d) {
                        return(d.name == 'origin') ? '.35em' :'15';
                    })
                    .attr("text-anchor", "start")
                    .attr("class", "linkname")
                    .style("fill", "#0ba4ec")
                    .style('font-size', 10)
                    .text(function(d) {
                        return(d.name == 'origin'||parseFloat(d.ratio.substring(0,3)) <= 50) ? "" : '控股';
                    });


                // Transition nodes to their new position.原有节点更新到新位置
                var nodeUpdate = node.transition()
                    .duration(duration)
                    .attr('transform', function(d) {
                        return 'translate(' + d.y + ',' + d.x + ')';
                    });
                nodeUpdate.select('circle')
                    .attr('r', function(d) {
                        return(d.name == 'origin') ? 0 : (hasChildNodeArr.indexOf(d) == -1) ? 0 : 6;
                    })
                    .attr('cx', function(d) {
                        return(d.name == 'origin') ? -20 : 251;
                    })
                    .style('fill', function(d) {
                        return hasChildNodeArr.indexOf(d) != -1 ? "#fff" : "";
                        // if (d._children || d.children) { return "#fff"; } else { return "rgba(0,0,0,0)"; }
                    })
                    .style('stroke', function(d) {
                        return hasChildNodeArr.indexOf(d) != -1 ? "#8b4513" : "";
                        // if (d._children || d.children) { return "#8b4513"; } else { return "rgba(0,0,0,0)"; }
                    })
                    .style('fill-opacity', function(d) {
                        if(d.children) {
                            return 0.35;
                        }
                    })
                    // Setting summary node style as class as mass style setting is
                    // not compatible to circles.
                    .style('stroke-width', function(d) {
                        if(d.repeated) {
                            return 5;
                        }
                    });
                //代表是否展开的+-号
                nodeEnter.append("svg:text")
                    .attr("class", "isExpand")
                    .attr("x", "251")
                    .attr("dy", function(d) {
                        return 3;
                    })
                    .attr("text-anchor", "middle")
                    .style("fill", "#000")
                    .text(function(d) {
                        if(d.name == 'origin') {
                            return '';
                        }
                        return hasChildNodeArr.indexOf(d) != -1 ? "+" : "";
                        /* if (d._children || d.children) {
                          return "+";
                        } */
                    })
                    .on('click',click);

                nodeUpdate.select('text').style('fill-opacity', 1);

                var nodeExit = node.exit().transition()
                    .duration(duration)
                    .attr('transform', function(d) {
                        return 'translate(' + source.y + ',' + source.x + ')';
                    })
                    .remove();
                nodeExit.select('circle')
                    .attr('r', 1e-6);
                nodeExit.select('text')
                    .style('fill-opacity', 1e-6);

                var link = g.selectAll('path.' + link_class)
                    .data(links, function(d) {
                        return d.target.id;
                    });

                link.enter().insert('path', 'g')
                    .attr('class', link_class)
                    .attr('stroke',function(d){
                        return '#8b4513';
                    })
                    .attr('fill',"none")
                    .attr('stroke-width','1px')
                    .attr('opacity', 0.5)
                    .attr('d', function(d) {
                        var o = {
                            x: source.x0,
                            y: source.y0
                        };
                        return pathFunc({
                            source: o,
                            target: o
                        });
                    })
                    .attr("marker-end", function(d) {
                        return "url(#resolvedDown)";
                    }) //根据箭头标记的id号标记箭头;
                    .attr("id", function(d, i) {
                        return "mypath" + i;
                    });
                link.transition()
                    .duration(duration)
                    .attr('d', pathFunc);
                link.exit().transition()
                    .duration(duration)
                    .attr('d', function(d) {
                        var o = {
                            x: source.x,
                            y: source.y
                        };
                        return pathFunc({
                            source: o,
                            target: o
                        });
                    })
                    .remove();
                nodes.forEach(function(d) {
                    d.x0 = d.x;
                    d.y0 = d.y;
                });



                function Change_modal () {
                    _this.Modal = true
                }
                function click(d) {
                    if(forUpward) {

                    } else {
                        if(d._children) {
                            console.log('对外投资--ok')
                        } else {
                            console.log('对外投资--no')
                        }
                    }
                    isExpand = !isExpand;
                    if(d.name == 'origin') {
                        return;
                    }
                    if(d.children) {
                        d._children = d.children;
                        d.children = null;
                        d3.select(this).text('+')
                    } else {
                        d.children = d._children;
                        d._children = null;
                        // expand all if it's the first node
                        if(d.name == 'origin') {
                            d.children.forEach(expand);
                        }
                        d3.select(this).text('-')
                    }
                    update(d, originalData, g);
                }
            }

            function expand(d) {
                if(d._children) {
                    d.children = d._children;
                    d.children.forEach(expand);
                    d._children = null;
                }
            }


            function collapse(d) {
                if(d.children && d.children.length != 0) {
                    d._children = d.children;
                    d._children.forEach(collapse);
                    d.children = null;
                    hasChildNodeArr.push(d);
                }
            }


            function redraw() {
                treeG.attr('transform', 'translate(' + d3.event.translate + ')' +
                    ' scale(' + d3.event.scale + ')');
            }

            function disableRightClick() {
                // stop zoom
                if(d3.event.button == 2) {
                    console.log('No right click allowed');
                    d3.event.stopImmediatePropagation();
                }
            }


            function sortByDate(a, b) {
                var aNum = a.name.substr(a.name.lastIndexOf('(') + 1, 4);
                var bNum = b.name.substr(b.name.lastIndexOf('(') + 1, 4);
                return d3.ascending(aNum, bNum) ||
                    d3.ascending(a.name, b.name) ||
                    d3.ascending(a.id, b.id);
            }
        };

        var d3GenerationChart = new treeChart(d3);
        d3GenerationChart.drawChart();

    };
    var funLine = function(obj) {  //折线
        var s = obj.source;
//			console.log('获取折线对象1:'+s.y);
        var sy = (s.name == 'origin' ? s.y+60 :s.y+260);
//			console.log('获取折线对象2:'+sy);
        var t = obj.target;
        var ty = (t.name == 'origin' ? t.y+90 :t.y+85);
        return "M"+sy+","+s.x+"L"+(sy+(ty-sy)/2)+","+s.x+"L"+(sy+(ty-sy)/2)+","+t.x+"L"+ty+","+t.x;
    }

    var downloadfun = function() { //下载

        // 注释该方法为svg 直接下载
        //  var SvgSaver = require('svgsaver');                 // if using CommonJS environment
        //  var svgsaver = new SvgSaver();                      // creates a new instance
        //  var svg = document.querySelector('#product_tree');         // find the SVG element
        //  svgsaver.asSvg(svg);                                // save as SVG

        var g = document.getElementById('product_tree').getElementsByTagName('g')[0].getBBox();
        var gbox = document.getElementById('product_tree').getElementsByClassName('gbox')[0];
        var x = -g.x;//计算偏移位置
        var y = -g.y;
        gbox.style.transform = "translate(" + x + 'px' + "," + y + "px" + ")  scale(1)"; //偏移位置
        var svgbox = $('#product_tree svg')
        var boxwidth = svgbox.width;
        var boxheight = svgbox.height;
        svgbox.attr('width', g.width)
        svgbox.attr('height', g.height)
        var canvas = document.createElement("canvas");
        var c = canvas.getContext('2d');
        //新建Image对象
        //svg内容
        var svg = document.getElementById('product_tree').innerHTML;
        var img = new Image();

        img.src = 'data:image/svg+xml,' + unescape(encodeURIComponent(svg));//svg内容中可以有中文字符
        img.src = 'data:image/svg+xml,' + svg;//svg内容中不能有中文字符
        img.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(svg)));
        //图片初始化完成后调用
        img.onload = function() {
            //将canvas的宽高设置为图像的宽高
            canvas.width = img.width;
            canvas.height = img.height+60;
            c.fillStyle = "#fff";
            c.fillRect(0, 0, canvas.width, canvas.height);
            c.drawImage(img, 0, 30);
            //canvas画图片

            var a = document.createElement("a");
            a.download = "png";
            a.href= canvas.toDataURL("image/png");
            a.click();
        }
        //图片转换为base64后 传给后端 发邮件
        gbox.style.transform = ''
        // svgbox.attr('width',boxwidth)
        // svgbox.attr('height',boxheight)
        svgbox.attr('width',1100)
        svgbox.attr('height',600)

        // 结束
    }

</script>
</html>

当然这些数据可以动态的从后台拿

在SpringBoot中动态页面是放在templates文件夹,需要引入thymeleaf

首先,pom.xml中导入thymeleaf的依赖:

<!--引入thymeleaf的依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

在资源配置文件中加入thymeleaf相关配置:

##############################################
#
# thymeleaf静态资源配置
#
##############################################
# 默认路径
spring.thymeleaf.prefix=classpath:/templates/
# 后缀
spring.thymeleaf.suffix=.html
# 模板格式
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.cache=false

这个连接是关于static和templates文件夹的说明,有兴趣可以看看
springBoot项目中的static和templates文件夹
这个连接是关于SpringBoot整合thymeleaf的说明,有兴趣可以看看
SpringBoot整合thymeleaf

好了,废话不多说,下面这张图的数据就是我数据从后台拿的(这个demo是SpringBoot的):

在这里插入图片描述

百度网盘地址:

链接:https://pan.baidu.com/s/1d_qJu8NFlP57vqrtxSkesw
提取码:9dvf

其它下载地址:https://download.csdn.net/download/weixin_43085797/12368917

找到一个非常好用的jQuery插件库 :地址

上面的代码也是这个插件库里的,放出来让更多人知道这个好用的地址,不然像我一样找了一上午,太浪费时间了,我就直接贴过来了,节省大家时间。上面的地址:d3+jQuery横向树图

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你好!对于Vue和D3的组件开发,你可以使用Vue的生命周期钩子函数将D3与Vue组件集成起来。以下是一个简单的示例,展示如何使用Vue和D3创建一个treemap(树图)组件: 首先,安装必要的依赖: ```bash npm install d3 ``` 接下来,创建一个名为Treemap.vue的Vue组件,并在其中引入D3库: ```vue <template> <div ref="treemap"></div> </template> <script> import * as d3 from 'd3'; export default { mounted() { this.drawTreemap(); }, methods: { drawTreemap() { // 获取DOM元素的引用 const container = this.$refs.treemap; // 创建数据数组 const data = [ { name: 'A', value: 10 }, { name: 'B', value: 20 }, { name: 'C', value: 30 }, // ... ]; // 创建treemap布局 const treemapLayout = d3.treemap() .size([500, 300]) .padding(1); // 转换数据为适用于treemap的层次结构 const root = d3.hierarchy({ children: data }) .sum(d => d.value) .sort((a, b) => b.value - a.value); // 根据treemap布局计算节点位置和大小 treemapLayout(root); // 创建矩形元素并绑定数据 const rects = d3.select(container) .selectAll('rect') .data(root.leaves()); // 更新已存在的矩形 rects.attr('x', d => d.x0) .attr('y', d => d.y0) .attr('width', d => d.x1 - d.x0) .attr('height', d => d.y1 - d.y0) .attr('fill', 'steelblue'); // 创建新的矩形 rects.enter() .append('rect') .attr('x', d => d.x0) .attr('y', d => d.y0) .attr('width', d => d.x1 - d.x0) .attr('height', d => d.y1 - d.y0) .attr('fill', 'steelblue'); // 移除多余的矩形 rects.exit().remove(); } } } </script> ``` 以上代码演示了如何使用D3的treemap布局来创建一个简单的树图(treemap),你可以根据实际需求进行进一步的定制和样式调整。 希望这个示例能对你有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值