阅读视图

发现新文章,点击刷新页面。

子比主题文章归档页面美化版

前言

因为自己喜欢倒腾,所以从Corenext换成了子比,但不代表Corenext不好,Corenext主题绝对是做博客的首选。

我换成子比是为了倒腾一些小玩意,今天就给大家带来自己弄的一个美化版的文章归档页面

展示

图片[1]-新锐博客
图片[2]-新锐博客

教程

在子比主题的pages目录下创建一个新的php,名字随便命名,然后将如下代码放入进去

<?php
/**
 * Template name: 新锐-文章归档
 * Description: 文章归档页面,包含统计数据和文章列表
 */

// 获取分类统计信息并缓存
function get_category_statistics() {
    return get_cached_data('category_stats', function() {
        $categories = get_categories(['hide_empty' => false]);
        $data = [];
        foreach ($categories as $category) {
            $data[] = ['value' => $category->count, 'name' => $category->name];
        }
        return json_encode($data);
    });
}

// 获取最近一年每月的文章数量并缓存
function get_monthly_post_data() {
    return get_cached_data('monthly_post_data', function() {
        global $wpdb;
        $query = "
            SELECT DATE_FORMAT(post_date, '%Y-%m') AS month, COUNT(*) AS count
            FROM {$wpdb->posts}
            WHERE post_type = 'post' AND post_status = 'publish'
              AND post_date >= DATE_SUB(CURDATE(), INTERVAL 1 YEAR)
            GROUP BY month
            ORDER BY month ASC
        ";
        $results = $wpdb->get_results($query, ARRAY_A);

        $monthly_data = [];
        foreach ($results as $result) {
            $monthly_data[] = [
                'month' => $result['month'],
                'count' => $result['count']
            ];
        }
        return json_encode($monthly_data);
    });
}

// 缓存处理函数
function get_cached_data($transient_key, $callback) {
    if (false === ($data = get_transient($transient_key))) {
        $data = call_user_func($callback);
        set_transient($transient_key, $data, 12 * HOUR_IN_SECONDS);
    }
    return $data;
}

// 统计小工具
function render_archives_widgets($type = 'day') {
    $icons = [
        'day' => ['icon' => 'fa fa-calendar', 'color' => 'c-blue', 'title' => '运营时间'],
        'post' => ['icon' => 'fa fa-file-text', 'color' => 'c-green', 'title' => '文章总数'],
        'comment' => ['icon' => 'fa fa-comments', 'color' => 'c-purple', 'title' => '评论总数'],
        'user' => ['icon' => 'fa fa-users', 'color' => 'c-orange', 'title' => '注册用户']
    ];

    switch ($type) {
        case 'day':
            $first_post = get_posts(['numberposts' => 1, 'order' => 'ASC']);
            $start_time = !empty($first_post) ? strtotime($first_post[0]->post_date) : time();
            $statistic = round((time() - $start_time) / DAY_IN_SECONDS) . ' 天';
            break;
        case 'post':
            $statistic = wp_count_posts()->publish;
            break;
        case 'comment':
            $statistic = get_comment_count()['total_comments'];
            break;
        case 'user':
            $statistic = count_users()['total_users'];
            break;
        default: return;
    }

    echo '<div class="stats-widget">';
    echo '<div class="stats-header">'.$icons[$type]['title'].'</div>';
    echo '<div class="stats-content">';
    echo '<div class="stats-icon"><i class="'.$icons[$type]['icon'].' '.$icons[$type]['color'].'"></i></div>';
    echo '<div class="stats-value">'.$statistic.'</div>';
    echo '</div></div>';
}

// 注册脚本
function grace_archives_scripts() {
  
    wp_enqueue_script('echarts', 'https://cdn.jsdmirror.com/npm/echarts@5.4.0/dist/echarts.min.js', [], null, true);
     wp_enqueue_script('archives-script', get_template_directory_uri().'/js/archives.js', ['echarts', 'jquery'], null, true);
    
    // 将数据传递给 JavaScript
    wp_localize_script('archives-script', 'graceData', [
        'postData' => json_decode(get_category_statistics()),
        'monthlyPostData' => json_decode(get_monthly_post_data()),
        'ajaxUrl' => admin_url('admin-ajax.php')
    ]);
}
add_action('wp_enqueue_scripts', 'grace_archives_scripts');

// AJAX 处理翻页请求
function load_more_posts() {
    $paged = isset($_POST['page']) ? intval($_POST['page']) : 1;
    $posts_per_page = 20;

    $query = new WP_Query([
        'posts_per_page' => $posts_per_page,
        'paged' => $paged,
        'orderby' => 'post_date',
        'order' => 'DESC',
        'post_status' => 'publish'
    ]);

    if ($query->have_posts()) :
        $organized = [];
        while ($query->have_posts()) : $query->the_post();
            $year = get_the_time('Y');
            $month = get_the_time('m');
            $organized[$year][$month][] = $post;
        endwhile;

        ob_start();
        foreach ($organized as $year => $months) : ?>
            <div class="archive-year">
                <h2 class="year-title"><?php echo $year; ?></h2>
                <?php foreach ($months as $month => $posts) : ?>
                    <div class="archive-month">
                        <h3 class="month-title"><?php echo date('n月', mktime(0, 0, 0, $month, 1)); ?></h3>
                        <ul class="post-list">
                            <?php foreach ($posts as $post) : setup_postdata($post); ?>
                                <li>
                                    <time><?php the_time('m-d'); ?></time>
                                    <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
                                        <?php the_title(); ?>
                                        <?php if (get_comments_number()) : ?>
                                            <span class="comment-count">(<?php echo get_comments_number(); ?>)</span>
                                        <?php endif; ?>
                                    </a>
                                </li>
                            <?php endforeach; ?>
                        </ul>
                    </div>
                <?php endforeach; ?>
            </div>
        <?php endforeach;

        // 生成新的分页链接
        $pagination = paginate_links([
            'total' => $query->max_num_pages,
            'current' => $paged,
            'prev_next' => true,
            'prev_text' => __('« 上一页'),
            'next_text' => __('下一页 »'),
            'echo' => false
        ]);

        $output = ob_get_clean();
        wp_send_json_success([
            'data' => $output,
            'pagination' => $pagination
        ]);
    else :
        wp_send_json_error('No more posts');
    endif;
    wp_reset_postdata();
    wp_die();
}
add_action('wp_ajax_load_more_posts', 'load_more_posts');
add_action('wp_ajax_nopriv_load_more_posts', 'load_more_posts');

get_header();
?>

<main class="grace-archives">
    <div class="archive-container">
        <div class="archive-main">
            <article class="archive-article">
                <header class="archive-header">
                    <h1><?php the_title(); ?></h1>
                    <!-- 统计小工具 -->
                    <div class="stats-grid">
                        <?php 
                        render_archives_widgets('day');
                        render_archives_widgets('post');
                        render_archives_widgets('comment');
                        render_archives_widgets('user');
                        ?>
                    </div>
                </header>
                
                <!-- 图表区域 -->
                <div class="charts-container">
                    <div class="chart-box" id="postChart"></div>
                    <div class="chart-box" id="monthlyPostChart"></div>
                </div>

                <!-- 文章列表 -->
                <div class="archives-list">
                    <?php
                    // 获取当前页码
                    $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
                    $posts_per_page = 20;
                    
                    $query = new WP_Query([
                        'posts_per_page' => $posts_per_page,
                        'paged' => $paged,
                        'orderby' => 'post_date',
                        'order' => 'DESC',
                        'post_status' => 'publish'
                    ]);

                    if ($query->have_posts()) :
                        $organized = [];
                        while ($query->have_posts()) : $query->the_post();
                            $year = get_the_time('Y');
                            $month = get_the_time('m');
                            $organized[$year][$month][] = $post;
                        endwhile;

                        foreach ($organized as $year => $months) : ?>
                            <div class="archive-year">
                                <h2 class="year-title"><?php echo $year; ?></h2>
                                <?php foreach ($months as $month => $posts) : ?>
                                    <div class="archive-month">
                                        <h3 class="month-title"><?php echo date('n月', mktime(0, 0, 0, $month, 1)); ?></h3>
                                        <ul class="post-list">
                                            <?php foreach ($posts as $post) : setup_postdata($post); ?>
                                                <li>
                                                    <time><?php the_time('m-d'); ?></time>
                                                    <a href="<?php the_permalink(); ?>" title="<?php the_title(); ?>">
                                                        <?php the_title(); ?>
                                                        <?php if (get_comments_number()) : ?>
                                                            <span class="comment-count">(<?php echo get_comments_number(); ?>)</span>
                                                        <?php endif; ?>
                                                    </a>
                                                </li>
                                            <?php endforeach; ?>
                                        </ul>
                                    </div>
                                <?php endforeach; ?>
                            </div>
                        <?php endforeach; 
                    else :
                        echo '<p>暂无文章</p>';
                    endif;
                    wp_reset_postdata();
                    ?>
                </div>

                <!-- 传统分页 -->
<div class="archive-pagination">
    <?php
    echo paginate_links([
        'total'     => $query->max_num_pages,
        'current'   => $paged,
        'prev_next' => true,
        'prev_text' => __('« 上一页'),
        'next_text' => __('下一页 »'),
        'type'      => 'plain', // 修改这里
        'mid_size'  => 2 // 控制显示页码数量
    ]);
    ?>
</div>
            </article>
        </div>
    </div>
</main>


<script>
// 仅保留图表初始化代码
jQuery(document).ready(function($) {
    // 初始化 ECharts 图表
    const postChart = echarts.init(document.getElementById('postChart'));
    const monthlyPostChart = echarts.init(document.getElementById('monthlyPostChart'));

    postChart.setOption({
        title: { text: '文章分类分布' },
        tooltip: { trigger: 'item' },
        series: [{
            type: 'pie',
            data: graceData.postData
        }]
    });

    monthlyPostChart.setOption({
        title: { text: '每月发文数量' },
        tooltip: { trigger: 'axis' },
        xAxis: {
            type: 'category',
            data: graceData.monthlyPostData.map(item => item.month)
        },
        yAxis: { type: 'value' },
        series: [{
            type: 'line',
            data: graceData.monthlyPostData.map(item => item.count)
        }]
    });
});
</script>

<style>
.grace-archives {
    padding: 2rem 20px;
    background: #f8f9fa;
    min-height: 100vh;
}
/* 分页容器 */
.archive-pagination {
    margin-top: 3rem;
    text-align: center;
}

/* 分页链接基础样式 */
.archive-pagination a, 
.archive-pagination span {
    display: inline-block;
    padding: 8px 16px;
    margin: 0 4px;
    border: 1px solid #e0e0e0;
    border-radius: 4px;
    color: #3498db;
    text-decoration: none;
    transition: all 0.3s;
}

/* 当前页样式 */
.archive-pagination span.current {
    background: #3498db;
    color: white;
    border-color: #3498db;
}

/* 悬停效果 */
.archive-pagination a:hover {
    background: #f8f9fa;
    border-color: #3498db;
}

/* 移动端适配 */
@media (max-width: 480px) {
    .archive-pagination a, 
    .archive-pagination span {
        padding: 6px 12px;
        margin: 2px;
        font-size: 14px;
    }
}
.archive-container {
    max-width: 1400px;
    margin: 0 auto;
}

.archive-main {
    background: #fff;
    border-radius: 12px;
    padding: 2rem;
    box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}

.archive-header {
    margin-bottom: 2rem;
    border-bottom: 2px solid #f0f0f0;
    padding-bottom: 1.5rem;
}

.archive-header h1 {
    font-size: 2.2rem;
    color: #2c3e50;
    margin: 0 0 1.5rem;
}

/* 统计小工具 */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 1.5rem;
    margin: 2rem 0;
}

.stats-widget {
    background: #ffffff;
    border: 1px solid #eaeaea;
    padding: 1.5rem;
    border-radius: 10px;
    transition: transform 0.3s ease;
}

.stats-widget:hover {
    transform: translateY(-3px);
    box-shadow: 0 6px 16px rgba(0,0,0,0.1);
}

.stats-header {
    color: #7f8c8d;
    font-size: 0.95rem;
    margin-bottom: 0.8rem;
    font-weight: 500;
}

.stats-content {
    display: flex;
    align-items: center;
    gap: 1.2rem;
}

.stats-icon i {
    font-size: 2rem;
    width: 50px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
}

.stats-value {
    font-size: 1.8rem;
    font-weight: 600;
    color: #2c3e50;
}

/* 颜色定义 */
.c-blue { background: #e3f2fd; color: #2196f3; }
.c-green { background: #e8f5e9; color: #4caf50; }
.c-purple { background: #f3e5f5; color: #9c27b0; }
.c-orange { background: #fff3e0; color: #ff9800; }

/* 图表容器 */
.charts-container {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 1.5rem;
    margin: 3rem 0;
}

.chart-box {
    height: 400px;
    background: #fff;
    border: 1px solid #eee;
    border-radius: 10px;
    padding: 1rem;
}

/* 文章列表 */
.archives-list {
    margin-top: 2rem;
}

.archive-year {
    margin-bottom: 3rem;
    background: #fafafa;
    border-radius: 8px;
    padding: 1.5rem;
}

.year-title {
    font-size: 1.8rem;
    color: #2c3e50;
    margin: 0 0 1.5rem;
    padding-bottom: 0.8rem;
    border-bottom: 2px solid #eee;
}

.archive-month {
    margin-bottom: 2rem;
    background: #fff;
    border-radius: 6px;
    padding: 1rem;
    box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}

.month-title {
    font-size: 1.4rem;
    color: #34495e;
    margin: 0 0 1rem;
    padding-left: 0.5rem;
}

.post-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.post-list li {
    padding: 1rem 1.2rem;
    border-bottom: 1px solid #f5f5f5;
    display: flex;
    align-items: center;
    gap: 1.5rem;
    transition: background 0.3s;
}

.post-list li:hover {
    background: #f8f9fa;
}

.post-list time {
    color: #7f8c8d;
    min-width: 70px;
    font-family: monospace;
    font-size: 0.95rem;
}

.post-list a {
    color: #2c3e50;
    transition: color 0.3s;
    flex-grow: 1;
    text-decoration: none;
    font-weight: 500;
}

.post-list a:hover {
    color: #3498db;
}

.comment-count {
    color: #95a5a6;
    font-size: 0.85em;
    margin-left: 0.8rem;
    font-weight: normal;
}

/* 分页样式 */
.archive-pagination {
    margin-top: 3rem;
    text-align: center;
    padding: 1.5rem 0;
}

.archive-pagination .page-numbers {
    display: inline-block;
    padding: 8px 16px;
    margin: 0 5px;
    border: 1px solid #e0e0e0;
    border-radius: 6px;
    color: #3498db;
    text-decoration: none;
    transition: all 0.3s;
}

.archive-pagination .page-numbers.current {
    background: #3498db;
    color: #fff;
    border-color: #3498db;
}

.archive-pagination .page-numbers:hover:not(.current) {
    background: #f8f9fa;
    border-color: #3498db;
}

/* 加载提示 */
.loading {
    text-align: center;
    padding: 1.5rem;
    color: #7f8c8d;
    font-size: 0.95rem;
}

/* 响应式设计 */
@media (max-width: 1200px) {
    .charts-container {
        grid-template-columns: 1fr;
    }
    .chart-box {
        height: 350px;
    }
}

@media (max-width: 768px) {
    .stats-grid {
        grid-template-columns: repeat(2, 1fr);
        gap: 1rem;
    }
    
    .stats-value {
        font-size: 1.6rem;
    }
    
    .archive-main {
        padding: 1.5rem;
    }
    
    .year-title {
        font-size: 1.6rem;
    }
}

@media (max-width: 480px) {
    .stats-grid {
        grid-template-columns: 1fr;
    }
    
    .stats-content {
        gap: 1rem;
    }
    
    .archive-pagination .page-numbers {
        padding: 6px 12px;
        margin: 3px;
    }
    
    .post-list li {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
        padding: 1rem;
    }
    
}
</style>
<?php get_footer(); ?>

再到子比主题根目录里的JS文件夹里创建一个archives.js的文件,然后将如下代码放进去

// archives.js 完整代码

document.addEventListener('DOMContentLoaded', function() {
    
     const chartContainers = [
        'postChart', 
        'monthlyPostChart'
    ];

    chartContainers.forEach(id => {
        const el = document.getElementById(id);
        if (!el) {
            console.warn(`图表容器 #${id} 未找到`);
            return;
        }
        
        try {
            // 初始化图表代码...
        } catch (error) {
            console.error(`初始化图表 ${id} 失败:`, error);
        }
    });
    // 获取图表容器
    const postChartEl = document.getElementById('postChart');
    const monthlyChartEl = document.getElementById('monthlyPostChart');
    
    // 检查元素是否存在
    if (!postChartEl || !monthlyChartEl) {
        console.warn('图表容器未找到,请检查元素ID是否正确');
        return;
    }

    // 初始化图表实例
    const postChart = echarts.init(postChartEl);
    const monthlyPostChart = echarts.init(monthlyChartEl);

    // 配置分类分布饼图
    postChart.setOption({
        title: { text: '文章分类分布', left: 'center' },
        tooltip: { trigger: 'item' },
        series: [{
            type: 'pie',
            radius: '55%',
            data: graceData.postData,
            emphasis: {
                itemStyle: {
                    shadowBlur: 10,
                    shadowOffsetX: 0,
                    shadowColor: 'rgba(0, 0, 0, 0.5)'
                }
            }
        }]
    });

    // 配置月度趋势折线图
    monthlyPostChart.setOption({
        title: { text: '月度发文趋势', left: 'center' },
        tooltip: { trigger: 'axis' },
        xAxis: {
            type: 'category',
            data: graceData.monthlyPostData.map(item => item.month),
            axisLabel: { rotate: 45 }
        },
        yAxis: { type: 'value' },
        series: [{
            type: 'line',
            smooth: true,
            data: graceData.monthlyPostData.map(item => item.count),
            areaStyle: { color: 'rgba(52, 152, 219, 0.2)' }
        }],
        grid: { containLabel: true }
    });

    // 窗口大小变化时自适应
    window.addEventListener('resize', function() {
        postChart.resize();
        monthlyPostChart.resize();
    });
});

最后再到页面中选择新锐-文章归档模版即可

记一次function代码无法生效的情况

前言

本人喜欢瞎搞,所以子主题的function.php文件中弄了不少东西,然后也就没太在意某些代码

记录

今天有人在前一篇文章进行了留言,然后我就想要回复他,突然想到之前在function中部署了关于WordPress回复他人邮件通知的功能。

但是一直没有试验有没有部署成功,因为同款主题的其他站长确定部署成功了,我就心血来潮的想要去测试一番。

于是我就在留言板回复了自己的留言,但是一直没有收到邮件,我就知道我没有部署成功。

接着,我就找到了同款主题的其他站长询问,因为安装了wpopt插件,而插件有评论站长收到邮件通知的功能。

所以自然而然就觉得是wpopt的问题了,便有了如下对话。

图片[1]-新锐博客

但是其他人都可以,为啥就我不行呢?有没有办法解决呢?

幸好现在有强大的AI,于是我就去deepseek官网,将之前的回复他人评论邮件通知的代码发给AI,并且提问为何不生效。

AI回复我可能是因为由于其他插件的缘故,导致回复他人邮件通知的功能被屏蔽掉了。于是我就想到了提高此功能的优先级。

我便让AI帮我把功能的优先级提高了。

最终有了新的代码,当然我也让AI美化了一下界面。

传送门

宝塔网站加速插件 - 让WordPress加载更快速

前言

WordPress是一个动态博客框架,所以加载的时候就会很慢,就需要类似wp-super-cache这类插件让网站静态化

我发现wp-super-cache加上宝塔的网站加速插件能让加载变得更加快速

教程

1.宝塔面板的软件商店下载堡塔网站加速插件

图片[1]-新锐博客

2.打开网站加速插件,并且启用想要加速网站的开关

图片[2]-新锐博客

3.专属规则可以选择WordPress

4.在不缓存url地址中添加/wp-admin

图片[3]-新锐博客

5.至此配置完成了,享受网站加速的快感吧

WordPress解决feed文件首行换行

前言

访问各个大佬博客的时候,有个类似开往的项目,名为blogsclub,站点地址:https://www.blogsclub.org/

过程

闲来无事就加入了其中,它有个功能是通过WordPress的feed抓取文章,但是我设置了feed却提示没有抓取成功
随后就收到了他们官方发出的邮件,提示feed文件首行出现了换行,众所周知,feed是由WordPress自行生成的,不像sitemap可以通过插件来生成
所以遇到此类麻烦就很难受,于是只能由最新大热的deepseek来解决,AI告诉我,需要检查各种php文件来确保之前并没有出现换行或空格
但是那样就很麻烦,所以我就让deepseek帮我把feed顶部的空格直接删掉就行了。
于是就有了以下教程

教程

将如下代码放到主题的function.php文件中

function remove_xml_declaration_whitespace() {
    // 检查当前页面是否是 feed 页面
    if (is_feed()) {
        // 清空所有现有的输出缓冲区
        while (ob_get_level() > 0) {
            ob_end_clean();
        }

        // 启动一个新的输出缓冲区,并指定回调函数
        ob_start(function($buffer) {
            // 使用正则表达式删除 XML 声明前的所有空格和换行符
            return preg_replace('/^s*(<?xml)/', '$1', $buffer);
        });
    }
}

// 将函数挂载到 WordPress 的 'wp' 动作上,优先级为 1
add_action('wp', 'remove_xml_declaration_whitespace', 1);

Seelen UI - Windows桌面美化

前言

一直看一种事物都会造成视觉疲劳,所以就需要Windows桌面美化程序来解决这一问题

项目地址

Github:https://github.com/eythaann/Seelen-UI

截图

图片[1]-新锐博客

软件特色

  • Seelen UI 提供多种主题和布局选项,可以自由调整菜单、小部件等元素,打造独特的个性化桌面。无论你喜欢简约风格还是复杂布局,都能找到适合自己的设置。
  • 内置媒体模块,支持主流音乐播放器,无需打开额外窗口就能控制音乐播放。这个功能特别适合在工作时听音乐的用户,方便快捷。
  • 简单的设置,让新手也能轻松上手

教程

1.首先打开项目地址,然后到releases下载最新的安装包

2.打开并且安装程序

3.根据自己的爱好设置软件

WordPress解决用户名枚举漏洞禁用REST API

前言

今天群里有人说会通过某个地址泄露用户名导致有被爆破的风险,并且给出了解决方案

教程

首先检查一下自己的网站有没有这个漏洞,访问如下网站即可

https://博客域名.com/wp-json/wp/v2/users/

如果有就到主题的function.php文件中添加如下代码

add_filter('rest_authentication_errors', function ($access) { return new wp_error('rest_cannot_access', 'REST API不再提供访问', ['status' => 403]); });

此代码禁用了REST API

零成本使用cloudflare和vercel部署AI文章摘要

前言

搭建网站的各位朋友应该都听说过AI摘要,而其中最出名的就是Tianli,但是呢,五万就需要10米,对我来说还是有点多,穷人一个。

所以就想着研究一下有没有免费的AI摘要项目,今天逛博客的时候就遇到了一个

博客地址

Floatsheep:https://blog.hesiy.cn/posts/qwen-summary

项目地址

Github:https://github.com/FloatSheep/Qwen-Post-Summary/

教程

1.首先将项目地址fork到自己的github中

2.登录并且找到cloudflare的workers,选择LLM APP模版创建,一定要选择此模版

3.编辑代码,将workers.js的代码放到里面并且部署

4.记录好cloudflare提供的域名,然后到vercel中部署

5.部署好以后,找到项目的storage,然后新建一个数据库

6.有kv的选择kv没有kv的数据库选择Upstash for Redis

7.重新部署项目

8.然后到 FloatBlog / cfai.html 或者 client 找到相应的js和css代码部署到网站中即可

Docker 搭建Github文件加速

前言

之前是nginx反代github,但是那样要解析很多个子域名,而有些人只需要下载加速就行了

截图

图片[1]-新锐博客

开源地址

Github:https://github.com/sky22333/hub-proxy

教程

命令安装

打开SSH链接并且输入如下代码安装docker容器

docker run -d 
  --name ghproxy 
  -p 5000:5000 
  --restart always 
  ghcr.io/sky22333/hub-proxy

设置反代

1.宝塔新建网站,PHP版本选择纯静态。

2.找到反向代理,添加反向代理,URL为ip+端口

3.反代设置完成,可以通过网站访问了。

nginx反向代理github

前言

因为众所周知的缘故,github时常访问不了,于是就想着反代一下,刚好有台华为云的香港服务器,于是火毅盾的负责人就给了我以下代码

此反代除了登录其他基本没啥问题

教程

1.打开宝塔面板,找到网站的反向代理,设置代理地址为https://github.com,发送域名为$host,然后确定之后可以看到有个配置文件,将如下代码放进去

location ^~ / {
    # 将请求代理到 GitHub
    proxy_pass https://github.com;

    # 设置转发到后端服务器的请求头
    proxy_set_header Host github.com;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_http_version 1.1;

    # 清空 Accept-Encoding 头,防止后端返回压缩内容
    proxy_set_header Accept-Encoding "";

    # 替换响应内容中的字符串
    sub_filter "github.githubassets.com" "assets-github.xrbk.cn";
    sub_filter "github.com" "github.xrbk.cn";
    sub_filter "api.github.com" "api-github.xrbk.cn";
    sub_filter 'raw.githubusercontent.com' 'raw.github.xrbk.cn';
    sub_filter_once off;
    sub_filter_types *;

    # 处理 302 重定向中的地址替换
    proxy_redirect ~^https://raw.githubusercontent.com(.*)$ https://raw.github.xrbk.cn$1;

    # 隐藏后端服务器返回的 Content-Security-Policy 头
    proxy_hide_header Content-Security-Policy;

    # 添加自定义的 Content-Security-Policy 头
    add_header Content-Security-Policy "default-src 'self'; img-src *; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'";

    # 静态文件缓存设置
    set $static_fileHbPPNEua 0;
    if ($uri ~* ".(gif|png|jpg|css|js|woff|woff2)$") {
        set $static_fileHbPPNEua 1;
        expires 1m;
    }
    if ($static_fileHbPPNEua = 0) {
        add_header Cache-Control no-cache;
    }
}

2.其中为xrbk.cn的后缀都需要更改为你的域名

3.在宝塔的网站里比如github.xrbk.cn中再添加其他例如api-github.xrbk.cn的域名

4.去服务商那解析这几个子域名即可

Mini Cover - 简易的封面设计

前言

访问本站的各位应该都看到了文章的缩略图,而这种缩略图该怎么制作呢

开源地址

Github:https://github.com/JLinMr/Mini-Cover

截图

图片[1]-新锐博客

教程

1.将项目文件下载到安装了nodejs环境的服务器或电脑中

2.修改.env和src/config.js两个文件里的内容

3.运行如下命令

npm install

4.打包程序

npm run build

5.将dist文件夹下的程序主体上传到网站根目录下即可

Docker 部署文本处理工具箱

前言

日常生活中,我们需要处理一些文本内容,这时候就需要用到一些工具了

截图

图片[1]-新锐博客

教程

1.打开SSH终端,cd到网站根目录,运行如下代码

git clone https://github.geekery.cn/https://github.com/zkeq/ai-markdown-text-toolkit.git

2.打开网站根目录并且把名为ai-markdown-text-toolkit 文件夹里的内容移到网站根目录里

3,打开名为docker-compose.yml  的文件,将其中的PASSWORD 后面的密码内容改为你自己设定的密码

4.然后去SSH终端输入以下命令启动docker

docker-compose up -d

5.访问ip+3030即可访问网站

飞牛OS使用一段时间的感受

前言

因为有旧电脑,所以就弄了个飞牛OS,浅说一下使用感受

感受

1.界面UI个人非常喜欢,但是因为是网页版,所以还是有点美中不足的,要是有电脑端的软件就好了

2.之前说过因为没有公网IP,所以进行了frp内网穿透,在使用的过程中感觉还是不错的,但是受制于服务端的带宽,有时候会出现加载慢的情况,这也是没办法的事情

3.其实飞牛os目前我使用最多的还是相册,美中不足的就是无法设置相册的缩略图

4.常见的应用已经不少,但是对于我来说还是有点不够,而且大部分都依托于docker

5.手机APP无法操作docker,只能网页版操作,这点还是很难受的

6.最后就是功耗了,因为使用的是旧电脑,CPU还是i3 7100,所以功耗还是有点大的

结语

目前来说飞牛OS对于我这种刚玩nas的人非常友好,界面好看且操作简单。

本文只是阐述我最近几天使用飞牛OS的感受,记录一下,大佬勿喷。

如果你有想玩nas的想法,还是买个小主机然后装个飞牛os就行了。

WordPress添加回复评论邮件通知

前言

之前就想要弄这个功能了,但是主题不支持,今天果核更新了主题终于支持了

教程

将如下代码放到子主题的function.php 中即可

/**
 * 新评论回复邮件通知函数(带按钮,美化界面)
 */
function comment_mail_notify($comment_id) {
    // 获取评论对象
    $comment = get_comment($comment_id);
    if (!$comment || $comment->comment_approved === 'spam') {
        return; // 如果评论不存在或标记为垃圾评论,直接返回
    }

    // 获取父评论 ID
    $parent_id = $comment->comment_parent ? $comment->comment_parent : '';
    if (empty($parent_id)) {
        return; // 如果没有父评论,直接返回
    }

    // 获取父评论对象
    $parent_comment = get_comment($parent_id);
    if (!$parent_comment || empty($parent_comment->comment_author_email)) {
        return; // 如果父评论不存在或邮箱为空,直接返回
    }

    // 获取收件人邮箱
    $to = trim($parent_comment->comment_author_email);

    // 构造邮件内容
    $wp_email = 'no-reply@' . preg_replace('#^www.#', '', strtolower($_SERVER['SERVER_NAME']));
    $subject  = '您在 [' . get_option("blogname") . '] 的留言有了回复';
    $comment_link = get_comment_link($comment_id);
    $message  = '
    <div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px; background-color: #f9f9f9;">
        <h2 style="color: #333; font-size: 24px; margin-bottom: 20px;">' . trim($parent_comment->comment_author) . ', 您好!</h2>
        <p style="color: #555; font-size: 16px; line-height: 1.6;">
            您曾在文章《' . get_the_title($comment->comment_post_ID) . '》中留言:
        </p>
        <blockquote style="margin: 20px 0; padding: 10px 20px; background-color: #fff; border-left: 4px solid #0073aa; color: #666; font-style: italic;">
            ' . trim($parent_comment->comment_content) . '
        </blockquote>
        <p style="color: #555; font-size: 16px; line-height: 1.6;">
            ' . trim($comment->comment_author) . ' 给您的回复:
        </p>
        <blockquote style="margin: 20px 0; padding: 10px 20px; background-color: #fff; border-left: 4px solid #0073aa; color: #666; font-style: italic;">
            ' . trim($comment->comment_content) . '
        </blockquote>
        <p style="color: #555; font-size: 16px; line-height: 1.6; text-align: center;">
            点击下方按钮查看完整回复内容:
        </p>
        <div style="text-align: center; margin: 20px 0;">
            <a href="' . $comment_link . '" style="display: inline-block; padding: 12px 24px; font-size: 16px; color: #fff; background-color: #0073aa; border-radius: 4px; text-decoration: none;">
                查看回复
            </a>
        </div>
        <p style="color: #555; font-size: 16px; line-height: 1.6;">
            感谢您对 ' . get_option('blogname') . ' 的支持!
        </p>
        <p style="color: #999; font-size: 14px; margin-top: 20px; text-align: center;">
            此邮件由系统自动发送,请勿直接回复。
        </p>
    </div>';

    // 设置邮件头
    $headers = [
        'From: "' . get_option('blogname') . '" <' . $wp_email . '>',
        'Content-Type: text/html; charset=' . get_option('blog_charset'),
    ];

    // 发送邮件
    wp_mail($to, $subject, $message, $headers);
}

// 挂载钩子
add_action('comment_post', 'comment_mail_notify', 5, 1);
add_action('wp_insert_comment', 'comment_mail_notify', 5, 1);

HEU_KMS_Activator 系统激活工具

前言

因为喜欢折腾,所以有时候要安装系统,这时候就需要激活新系统

简介

HEU KMS Activator,简洁高效的全能KMS/OEM激活工具,适用所有windows, office版本,无需联网即可一键激活,支持UEFI的KMS激活工具。KMS服务是微软对Windows, Office等产品的批量许可服务,利用KMS可以激活局域网内的产品。该工具利用KMS机制在系统搭建KMS服务器,从而实现在线或离线激活。

功能介绍

1、智能激活:智能识别最佳的激活方式

优先顺序依次为数字许可证/KMS38/OEM/KMS

自动识别并跳过已经永久激活的Windows/Office

2、KMS激活

安装/卸载自动续期功能,两种模式可供选择[1]自动续订模式(默认 [2]任务计划模式

清除KMS客户端信息:清除KMS服务器地址、端口、激活时间间隔、续订时间间隔等

搭建KMS服务器[手动激活]:KMS服务器地址/端口

3、数字激活(数字许可证激活、KMS38激活)

添加/解除KMS38保护,免受180天激活影响,除非解除保护,否则不能使用KMS38激活

查看当前系统信息:网络状态/激活状态,描述便于快速查看是否支持数字许可证/KMS38

4、OEM激活(提供6种模式)

卸载OEM激活信息:清除动态加载的SLIC等信息,OEM激活将失效

生产$OEM$文件夹:可将该文件夹置于ISO镜像source文件夹下,以集成OEM激活功能

5、更改Windows 10版本、激活信息备份还原、Microsoft Office 零售版转换批量授权版

6、Windows/Office密钥管理功能:安装密钥、卸载密钥、查看密钥、清除Office许可证

7、智能激活、激活成功率高、支持静默参数、几乎支持所有 Windows/Office 所有版本

8、Windows 7上无需依赖.NET Framework、能够离线激活,也能连接网络服务器激活

软件下载

HEU_KMS_Activator_系统激活工具

阿里云服务器SWAP导致的硬盘读取爆满问题

前言

因为本人喜欢折腾,所以在建立博客之后不久就使用了umami统计

过程

在2024年购入了这台阿里云99计划的云服务器,当时认为这台云服务器性价比很高。

毕竟在服务商日益内卷的情况下,99一年就能拥有2h2g 3m 40g硬盘无限流量的服务商也是不多了。

经过了一段时间的使用感觉也是还可以的,搭配CDN,网站访问速度也是不错的。

但是每隔一段时间服务器的就莫名的硬盘读取达到117mb/s,而写入却仅有几十kb/s。

后来经过排查发现可能是umami的问题,因为除了umami是docker部署的以外,其他程序也仅仅只有WordPress了

而本站也是个小博客,日访问量仅有100,访问人数也就二三十,哪怕有人攻击CDN那边也会有日志。

但是离奇的就是cdn也没有日志,硬盘却爆满了,于是我就怀疑是umami的问题。

那为啥标题会是阿里云服务器SWAP导致的硬盘读取爆满问题呢?

因为在别人的服务器哪怕是配置比我低一点的腾讯云服务器上别人也不会有硬盘读取高达117mb/s的问题

严重怀疑是因为网站一直处于访问的状态,所以umami就一直在记录东西,然后内存占用就会高起来,而我服务器配置也不高并且内存占用就已经达到70%了。

所以一旦umami使内存高起来后,服务器就会启用swap也就是虚拟内存。而虚拟内存使用的就是硬盘,但是阿里云的硬盘读取上限为117mb/s。

达到这个上限后就会一直卡着连服务器都连接不了只能重启,而同样配置甚至低一点配置的腾讯云就没遇到过我这种情况。

现在我已经将umami迁移到其他服务器上一个礼拜了,也没遇到过硬盘读取爆高的情况,之前两三天就会遇到一次。

飞牛OS利用FRP进行远程访问

前言

NAS外网访问是一个很让人头疼的问题,解决方法有两个,一个是运营商那里申请公网IP,另一个则是内网穿透

但是一般的内网穿透要么就需要设置路由器,对于小白来说很困难,另一个则是需要绑定域名很麻烦。

所以今天教大家如何使用FRP来访问自己的飞牛OS

教程

1.首先拥有一台能够外网访问的服务器,这里可以使用之前教大家领取的华为云服务器

2.安装FRP服务端,找到GITHUB中的地址下载对应的程序包,CD到文件夹然后输入如下命令

chmod +x ./frps

3.再输入如下代码

nohup ./frps -c ./frps.toml > frps.log 2>&1 &

这样程序就可以常驻在后台,哪怕关闭终端也可以运行了

4.到飞牛OS中的应用中心下载FRP客户端

5.打开配置文件,并且修改serverAddr 的ip为你服务器的ip

6.下方的如下代码块

[[proxies]]
name = "text-tcp"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000     

如需增加其他端口的映射,就按照这样来添加,实测proxies不可更改否则会启动失败

name:服务名(随意填写),type:传输类型(一般为tcp),localip:无需修改,localport:需要映射的端口,remoteport:需要访问的远程端口

7.启动客户端,然后服务器IP+端口即可。

适合小白的NAS系统飞牛OS安装教程

前言

之前有一个旧电脑放在那没用,于是就想着用弄个nas系统来玩玩

教程

1.首先在可以联网的电脑上下载飞牛os的镜像包和写盘软件,写盘软件上一篇文章已经介绍了

2.打开写盘软件rufus,选择U盘(至少8G),选择镜像文件,其他文件都默认即可

image-20240826144432487

3.制作启动盘结束以后插入到需要安装飞牛OS的电脑,然后在电脑启动刚开始的时候按DEL键(按照提示来,没有提示的就百度搜对应主板进入bios的方法)

4.设置启动项为U盘启动,然后就会提示你选择制作方式,选择第一个 Graphical Install ,如果有其他提示则选择第二个。

img_v3_02eb_e43e6332-03f4-46ba-bbb7-873970e5e62g

5.我在安装的时候提示了452报错,最终在我重新制作启动盘之后解决了这个问题,你们如果遇到其他情况也可以重新制作启动盘

6.进入到设置界面选择系统盘,建议是64G,而我选择的是20G,swap选择4G就差不多了

img_v3_02e4_c9914569-6898-4134-bfa8-21094f7ca10g

7.确认安装就可以了然后等待安装结束后确认网卡无误就能进入系统了

image-20240823180036795

8.进入到指定的url地址就可以设置账户和密码了,这样就可以开启飞牛os之旅了,是不是很简单。

Rufus - 轻松创建 USB 启动盘

前言

因为家里有个旧电脑,于是就想着装个系统玩一下,于是就用到了系统启动盘

官网

https://rufus.ie/zh/

简介

Rufus 是一款格式化和创建 USB 启动盘的辅助工具。

本软件适用于以下场景:

  • 需要将可引导 ISO (Windows、Linux、UEFI 等) 刻录到 USB 安装媒介的情况
  • 需要处理未安装操作系统的设备的情况
  • 需要在 DOS 环境下刷写 BIOS 或其他固件的情况
  • 需要运行低级工具的情况

Rufus 麻雀虽小,但五脏俱全!

截图

图片[1]-新锐博客

下载地址

RufusV4.6

PixPro-支持三种存储的图床程序

前言

今天给大家带来一个小巧简洁的图床程序

开源地址

github:https://github.com/JLinMr/PixPro/

简介

一款专为个人需求设计的高效图床解决方案,集成了强大的图片压缩功能与优雅的前台后台管理界面。

项目结构精简高效,提供自定义图片压缩率与尺寸设置,有效降低存储与带宽成本。

支持上传JPEG、PNG、GIF格式图片并转换为WEBP格式,支持上传SVG、WEBP图片。

支持本地储存,阿里云OSS储存,S3存储。可通过把储存桶挂载到本地的方式解锁更多储存方式。

简洁美观的前端,支持点击、拖拽、粘贴、URL、批量上传。

瀑布流管理后台,便捷查看图片信息,支持图片灯箱、AJAX无加载刷新。

支持自定义压缩率,默认60。支持设置每日上传限制,单次上传限制,文件大小限制

演示站点

 

前端:https://dev.ruom.top/

后台:https://dev.ruom.top/admin/

安装教程

 

首先下载源码ZIP,将文件上传到网站根目录,访问网址 ,填写相关信息,即可完成安装。

运行环境

 

推荐PHP 8.1 + MySQL >= 5.7

本程序依赖PHP的 Fileinfo 、 Imagick 、 exif拓展,需要自行安装。依赖 pcntl 扩展(宝塔PHP默认已安装)

要求 pcntl_signal 和 pcntl_alarm 函数可用(需主动解除禁用)

WordPress底部添加页面生成时间和数据库查询次数

前言

今天有个群友要在网站底部添加页面生成时间和数据库查询次数,虽然wpopt插件可以实现这个功能,但是仅能管理员查看

效果图

图片[1]-新锐博客

教程

1.首先在function.php 文件中添加如下代码,有子主题可以添加到子主题中

function display_query_count_with_timer() {
    $query_count = get_num_queries();
    $query_time = timer_stop(0, 3);
    $output = "<p>本次数据库查询" . $query_count . "次,页面生成花费".$query_time."秒</p>";
    return $output;
}
add_shortcode('query_timer', 'display_query_count_with_timer');

2.如果想添加在底部可以使用WordPress的小工具中的文本,只需要输入[query_timer] 即可。

XTerminal-更好用的开发工具

前言

SSH连接工具有很多种,XTerminal就是其中之一

简介

‌Xterminal‌是一款功能强大的SSH客户端,适用于多种操作系统,包括Windows、macOS和Linux。它提供了丰富的功能,如本地控制台、多级分组、命令补全、AI智能提示等,旨在帮助用户更高效地进行代码开发和系统管理‌。

截图

图片[1]-新锐博客

软件官网

下载地址以及官网:https://www.terminal.icu/

给自己网站添加多语言功能

前言

群里有朋友需要网站适配多语言,但其实一个引用就可以搞定这个问题

开源地址

gitee:https://gitee.com/mail_osc/translate

教程

在需要的地方添加如下代码

<!-- 增加语言选择的下拉框 -->
<select id="language-select" onchange="changeLanguage()">
    <option value="english">English</option>
    <option value="chinese_simplified">简体中文</option>
    <option value="chinese_traditional">繁體中文</option>
</select>

<!-- 引入多语言切换的js -->
<script src="https://cdn.staticfile.net/translate.js/3.2.1/translate.js"></script>
<script>
    translate.selectLanguageTag.show = false; // 不出现的select的选择语言
    translate.service.use('client.edge'); // 设置机器翻译服务通道

    function changeLanguage() {
        const selectedLanguage = document.getElementById('language-select').value;
        translate.changeLanguage(selectedLanguage);
        translate.execute();
        localStorage.setItem('selectedLanguage', selectedLanguage); // 保存选择的语言
    }

    // 页面加载时设置选择框的值和语言
    document.addEventListener('DOMContentLoaded', function() {
        const savedLanguage = localStorage.getItem('selectedLanguage') || 'english'; // 默认选择英文
        document.getElementById('language-select').value = savedLanguage; // 设置选择框的值
        translate.changeLanguage(savedLanguage); // 设置翻译语言
        translate.execute(); // 执行翻译
    });
</script>

结语

两行代码就解决了网站需要多语言的问题

部分linux服务器硬盘未挂载解决方法

前言

类似雨云等服务器可扩容云盘,但是重装系统的时候云盘会挂载失败,导致根目录就默认大小。

教程

1.首先用finalshell等SSH连接工具,连接云服务器

2.终端输入df -h / 查看根目录的大小,如果大小不是你扩容云盘后的大小按以下步骤做

3.终端输入fdisk -l 可以查看所有硬盘的容量大小

4.终端输入fdisk /dev/sda ,其中/dev/sda改成没有挂载硬盘的名字

5.输入d再输入1删除当前分区,再输入n创建新分区,再输入p创建主分区

6.默认起始扇区为2048,结束扇区为默认即可

7.再输入p查看新分区大小,正常情况下就没问题了

8.输入w保存分区信息,再输入reboot 重启云服务器

9.重启完成后,再输入resize2fs /dev/sda1 即可完成挂载

10.最后输入df -h / 检查根目录的大小

华为云白嫖13个月Flexus服务器

前言

现在许多厂家都有免费送券的活动,今天就介绍一个华为云的送卷活动

教程

活动地址

华为云:https://developer.huaweicloud.com/space/program/list

1.打开活动地址然后登录账号

2.然后在沃土云创中申请计划

图片[1]-新锐博客

3.就可以在激励管理中领取卷了

图片[2]-新锐博客

4.华为云上方搜索Flexus L服务器然后选购2H1G的香港服务器

5.千万不要选择一年而是要选择9个月,然后再续费就可以白嫖十三个月的服务器了,当然多花五块钱是可以多白嫖一个月的。

❌