1.sakura/layout/analytics.ejs

<div class="pattern-center-blank">
</div>
<div class="pattern-center ">
    <div class="pattern-attachment-img">
        <img src="https://cdn.jsdelivr.net/gh/drew233/cdn/20200303155335.webp" data-src="<%= page.photos %>"
            class="lazyload" onerror="imgError(this,3)"
            style="width: 100%; height: 100%; object-fit: cover; pointer-events: none;">
    </div>
    <style type="text/css">
        #contentss {
            position: relative;
            width: 800px;
            height: 900px;
            max-height: 1200px;
            text-align: center;
            border: 0;
            color: rgba(0, 0, 0, .87);
            background: rgba(255, 255, 255, .8);
            background-size: cover;
            margin: 0 auto;
        }
    </style>
    <header class="pattern-header ">
        <h1 class="entry-title">
            文章数据统计</h1>
    </header>
</div>
<div id="contentss">
    <%- partial('_widget/post-charts') %>
</div>

2.sakura/layout/_widget/post-charts

<style type="text/css">
    #posts-chart,
    #categories-chart,
    #tags-chart {
        width: 100%;
        height: 300px;
        margin: 0.5rem auto;
        padding: 0.5rem;
    }
</style>

<div id="postCharts" class="post-charts">
    <div class="title center-align" data-aos="zoom-in-up">
    </div>
    <div class="row">
        <div class="chart col s12 m6 l4" data-aos="zoom-in-up">
            <div id="posts-chart"></div>
        </div>

        <div class="chart col s12 m6 l4" data-aos="zoom-in-up">
            <div id="categories-chart"></div>
        </div>

        <div class="chart col s12 m6 l4" data-aos="zoom-in-up">
            <div id="tags-chart"></div>
        </div>
    </div>
</div>

<script type="text/javascript" src="<%= theme.libs.js.echarts %>"></script>
<script>
    var postsChart = echarts.init(document.getElementById('posts-chart'));
    var categoriesChart = echarts.init(document.getElementById('categories-chart'));
    var tagsChart = echarts.init(document.getElementById('tags-chart'));

    <%
    /* calculate postsOption data. */
    var startDate = moment().subtract(1, 'years').startOf('month');
    var endDate = moment().endOf('month');

    var monthMap = new Map();
    var dayTime = 3600 * 24 * 1000;
    for (var time = startDate; time <= endDate; time += dayTime) {
        var month = moment(time).format('YYYY-MM');
        if (!monthMap.has(month)) {
            monthMap.set(month, 0);
        }
    }

    // post and count map.
    site.posts.forEach(function (post) {
        var month = post.date.format('YYYY-MM');
        if (monthMap.has(month)) {
            monthMap.set(month, monthMap.get(month) + 1);
        }
    });

    // xAxis data and yAxis data.
    var monthArr = JSON.stringify([...monthMap.keys()]);
    var monthValueArr = JSON.stringify([...monthMap.values()]); %>

    var postsOption = {
        title: {
            text: '文章发布统计图',
            top: 0,
            x: 'center'
        },
        tooltip: {
            trigger: 'axis'
        },
        xAxis: {
            type: 'category',
            data: <%- monthArr %>
        },
        yAxis: {
            type: 'value',
        },
        series: [{
            name: '<%- __("postsNumberName")  %>',
            type: 'line',
            color: ['#6772e5'],
            data: <%- monthValueArr %> ,
            markPoint: {
                symbolSize: 45,
                color: ['#fa755a', '#3ecf8e', '#82d3f4'],
                data: [{
                    type: 'max',
                    itemStyle: {
                        color: ['#3ecf8e']
                    },
                    name: '<%- __("maximum")  %>'
                }, {
                    type: 'min',
                    itemStyle: {
                        color: ['#fa755a']
                    },
                    name: '<%- __("minimum")  %>'
                }]
            },
            markLine: {
                itemStyle: {
                    color: ['#ab47bc']
                },
                data: [{
                    type: 'average',
                    name: '<%- __("average")  %>'
                }]
            }
        }]
    };

    <%
    /* calculate categoriesOption data. */
    var categoryArr = [];
    site.categories.map(function (category) {
        categoryArr.push({
            'name': category.name,
            'value': category.length
        })
    });

    var categoryArrJson = JSON.stringify(categoryArr); %>

    var categoriesOption = {
        title: {
            text: '文章分类统计图',
            top: 1,
            x: 'center'
        },
        tooltip: {
            trigger: 'item',
            formatter: "{a} <br/>{b} : {c} ({d}%)"
        },
        series: [{
            name: '<%- __("categories")  %>',
            type: 'pie',
            radius: '50%',
            color: ['#6772e5', '#ff9e0f', '#fa755a', '#3ecf8e', '#82d3f4', '#ab47bc', '#525f7f', '#f51c47',
                '#26A69A'
            ],
            data: <%- categoryArrJson %> ,
            itemStyle: {
                emphasis: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
            }
        }]
    };

    <%
    /* calculate tagsOption data. */
    // get all tags name and count,then order by length desc.
    var tagArr = [];
    site.tags.map(function (tag) {
        tagArr.push({
            'name': tag.name,
            'value': tag.length
        });
    });
    tagArr.sort((a, b) => {
        return b.value - a.value
    });

    // get Top 10 tags name and count.
    var tagNameArr = [];
    var tagCountArr = [];
    for (var i = 0, len = Math.min(tagArr.length, 10); i < len; i++) {
        tagNameArr.push(tagArr[i].name);
        tagCountArr.push(tagArr[i].value);
    }

    var tagNameArrJson = JSON.stringify(tagNameArr);
    var tagCountArrJson = JSON.stringify(tagCountArr); %>

    var tagsOption = {
        title: {
            text: 'Top10标签统计图 ',
            top: 2,
            x: 'center'
        },
        tooltip: {},
        xAxis: [{
            type: 'category',
            data: <%- tagNameArrJson %>
        }],
        yAxis: [{
            type: 'value'
        }],
        series: [{
            type: 'bar',
            color: ['#82d3f4'],
            barWidth: 18,
            data: <%- tagCountArrJson %> ,
            markPoint: {
                symbolSize: 45,
                data: [{
                    type: 'max',
                    itemStyle: {
                        color: ['#3ecf8e']
                    },
                    name: '<%- __("maximum")  %>'
                }, {
                    type: 'min',
                    itemStyle: {
                        color: ['#fa755a']
                    },
                    name: '<%- __("minimum")  %>'
                }],
            },
            markLine: {
                itemStyle: {
                    color: ['#ab47bc']
                },
                data: [{
                    type: 'average',
                    name: '<%- __("average")  %>'
                }]
            }
        }]
    };

    // render the charts
    postsChart.setOption(postsOption);
    categoriesChart.setOption(categoriesOption);
    tagsChart.setOption(tagsOption);
</script>

3.hexo new page analytics

layout设置成analytics

在主题配置文件中导航栏加入path: /analytics

4.添加echart.js的引用

在主题配置文件的最后加上,因为post-charts.ejs引用到了echart的js代码

libs:
  css:
    googlefonts: https://fonts.googleapis.com/css?family=Noto+SerifMerriweather|Merriweather+Sans|Source+Code+Pro|Ubuntu:400,700|Noto+Serif+SC
    style: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/style.css #/css/style.css # 
    lib: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/lib.min.css
    font: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/font.css
    insight: /css/insight.css
    tags: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/tags.css
    fancybox: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/jquery.fancybox.min.css
    sharejs: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/sharejs.css
    tocbot: https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.4.2/tocbot.css
    live2d_widget: https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css
    logo:
      enable: true # 自定义logo
      logo: https://cdn.jsdelivr.net/gh/cungudafa/cdn/css/logo.css
      logo_fonts: https://cdn.jsdelivr.net/gh/cungudafa/cdn/fonts/LOGO/logo.css
  js:
    jquery: https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js
    linkcard: /js/linkcard.js
    lib: https://cdn.jsdelivr.net/gh/cungudafa/cdn/js/lib.min.js
    clipboard: https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js
    InsightSearch: https://cdn.jsdelivr.net/gh/cungudafa/cdn/js/InsightSearch.js
    sakura_app: https://cdn.jsdelivr.net/gh/cungudafa/cdn/js/sakura-app.js  #/js/sakura-app.js
    busuanzi: https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js 
    fancybox: https://cdn.jsdelivr.net/gh/cungudafa/cdn/js/jquery.fancybox.min.js
    echarts: https://cdn.jsdelivr.net/gh/cungudafa/cdn/js/echarts.min.js
    valine: https://unpkg.com/valine/dist/Valine.min.js
    sakura_petal: https://cdn.jsdelivr.net/gh/wallleap/cdn@latest/js/sakura.js #other
    hititle: https://cdn.jsdelivr.net/gh/wallleap/cdn@latest/js/hititle.js 
    KeyBlock: https://cdn.jsdelivr.net/gh/wallleap/cdn@latest/js/noSomeKey.js #按键屏蔽,不能F12调试和查看源代码
    sakura_petals: https://cdn.jsdelivr.net/gh/wallleap/cdn@latest/js/sakura.js  #仅在首页花瓣飘落(大内存)
    snow_petals: https://cdn.jsdelivr.net/gh/Yafine/cdn@2.5/source/js/snow1.js
    piao: https://cdn.jsdelivr.net/gh/wallleap/cdn@latest/js/piao.js #飘动彩带
    live2d_widget: https://cdn.jsdelivr.net/gh/cungudafa/cdn/live2d-widget/autoload.js
    word: https://cdn.jsdelivr.net/gh/wallleap/cdn/js/shehuizhuyi.js #点击出现字效
    love: https://cdn.jsdelivr.net/gh/wallleap/cdn/js/love.js #点击出现爱心
    cursor: https://cdn.jsdelivr.net/gh/cungudafa/cdn@2.1.2/js/cursor.js # 星星跟随坠落(大内存)

Be Water, My Friend.