普通视图

发现新文章,点击刷新页面。
昨天以前首页
  • ✇新锐博客
  • 子比主题文章归档页面美化版莫忘
    前言 因为自己喜欢倒腾,所以从Corenext换成了子比,但不代表Corenext不好,Corenext主题绝对是做博客的首选。 我换成子比是为了倒腾一些小玩意,今天就给大家带来自己弄的一个美化版的文章归档页面 展示 教程 在子比主题的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) {
     

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

作者 莫忘
2025年3月15日 19:25

前言

因为自己喜欢倒腾,所以从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的问题了,便有了如下对话。 但是其他人都可以,为啥就我不行呢?有没有办法解决呢? 幸好现在有强大的AI,于是我就去deepseek官网,将之前的回复他人评论邮件通知的代码发给AI,并且提问为何不生效。 AI回复我可能是因为由于其他插件的缘故,导致回复他人邮件通知的功能被屏蔽掉了。于是我就想到了提高此功能的优先级。 我便让AI帮我把功能的优先级提高了。 最终有了新的代码,当然我也让AI美化了一下界面。 传送门
     

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

作者 莫忘
2025年3月13日 00:48

前言

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

记录

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

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

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

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

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

图片[1]-新锐博客

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

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

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

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

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

传送门

  • ✇新锐博客
  • 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(
     

WordPress解决feed文件首行换行

作者 莫忘
2025年3月2日 12:40

前言

访问各个大佬博客的时候,有个类似开往的项目,名为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);
  • ✇新锐博客
  • 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
     

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

作者 莫忘
2025年2月24日 02:31

前言

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

教程

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

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

  • ✇新锐博客
  • Docker 搭建Github文件加速莫忘
    前言 之前是nginx反代github,但是那样要解析很多个子域名,而有些人只需要下载加速就行了 截图 开源地址 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.反代设置完成,可以通过网站访问了。
     

Docker 搭建Github文件加速

作者 莫忘
2025年2月10日 23:15

前言

之前是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.反代设置完成,可以通过网站访问了。

  • ✇新锐博客
  • appicon forge - 图标制作莫忘
    前言 上一篇文章教大家如何制作缩略图,这篇文章教大家如何制作icon 截图 开源地址 github:https://github.com/zhangyu1818/appicon-forge 教程 1.下载项目文件到本地 2.cd到项目文件夹 3.运行以下内容 pnpm install 4.打包文件 pnpm build 5.上传out文件夹里的文件到网站根目录即可
     
  • ✇新锐博客
  • Mini Cover - 简易的封面设计莫忘
    前言 访问本站的各位应该都看到了文章的缩略图,而这种缩略图该怎么制作呢 开源地址 Github:https://github.com/JLinMr/Mini-Cover 截图 教程 1.将项目文件下载到安装了nodejs环境的服务器或电脑中 2.修改.env和src/config.js两个文件里的内容 3.运行如下命令 npm install 4.打包程序 npm run build 5.将dist文件夹下的程序主体上传到网站根目录下即可
     

Mini Cover - 简易的封面设计

作者 莫忘
2025年1月17日 18:18

前言

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

开源地址

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.打开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即可访问网站
     

Docker 部署文本处理工具箱

作者 莫忘
2025年1月13日 18:53

前言

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

截图

图片[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即可访问网站

  • ✇新锐博客
  • 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; // 如果没有父评论,直接返回 } // 获取父评论对象 $pa
     

WordPress添加回复评论邮件通知

作者 莫忘
2025年1月11日 00:27

前言

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

教程

将如下代码放到子主题的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);
  • ✇新锐博客
  • 飞牛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
     

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

作者 莫忘
2025年1月1日 14:35

前言

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),选择镜像文件,其他文件都默认即可 3.制作启动盘结束以后插入到需要安装飞牛OS的电脑,然后在电脑启动刚开始的时候按DEL键(按照提示来,没有提示的就百度搜对应主板进入bios的方法) 4.设置启动项为U盘启动,然后就会提示你选择制作方式,选择第一个 Graphical Install ,如果有其他提示则选择第二个。 5.我在安装的时候提示了452报错,最终在我重新制作启动盘之后解决了这个问题,你们如果遇到其他情况也可以重新制作启动盘 6.进入到设置界面选择系统盘,建议是64G,而我选择的是20G,swap选择4G就差不多了 7.确认安装就可以了然后等待安装结束后确认网卡无误就能进入系统了 8.进入到指定的url地址就可以设置账户和密码了,这样就可以开启飞牛os之旅了,是不是很简单。
     

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

作者 莫忘
2024年12月30日 17:01

前言

之前有一个旧电脑放在那没用,于是就想着用弄个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之旅了,是不是很简单。

  • ✇新锐博客
  • 解决CMD控制台CD无响应莫忘
    前言 因为要构建一个项目,所以要用到cmd但是一直CD没反应 教程 首先要CD到需要CD的目录所在盘符,例如 cd d: 如果不跳转到D盘,就再次输入以下代码 d: 最后再CD到你需要CD的目录就行了
     
  • ✇新锐博客
  • 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 >=
     

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

作者 莫忘
2024年12月7日 13:58

前言

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

开源地址

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.首先在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] 即可。
     

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

作者 莫忘
2024年12月5日 18:19

前言

今天有个群友要在网站底部添加页面生成时间和数据库查询次数,虽然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] 即可。

  • ✇新锐博客
  • 给自己网站添加多语言功能莫忘
    前言 群里有朋友需要网站适配多语言,但其实一个引用就可以搞定这个问题 开源地址 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">&
     

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

作者 莫忘
2024年11月28日 23:47

前言

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

开源地址

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 / 检查根目录的大小
     

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

作者 莫忘
2024年11月27日 13:01

前言

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

教程

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 / 检查根目录的大小

  • ✇新锐博客
  • Docker 搭建Mtab书签导航程序莫忘
    前言 在跨设备的时候,浏览器收藏夹可能不能同步,所以这时候就需要导航或书签程序 文档 官方地址:https://www.mtab.cc/document.html 教程 手动安装 1.进入宝塔面板找到Docker,并且安装Docker管理器 。 2.找到镜像,点击从仓库中拉取。 3.选择官方镜像库,输入: itushan/mtab ,接着等待获取成功。 4.找到容器,并且创建新的容器,镜像选择刚刚获取成功的镜像。 5.容器端口输入80,服务器端口自定义。 命令安装 docker run -itd --name mtab -p 9200:80 -v /opt/mtab:/app itushan/mtab docker-compose 新建文件名为docker-compose.yaml  并且添加如下代码 #请确保您的docker-compose.yml所创建的文件夹有足够的权限,否则可能会失败, services: mysql8: image: mysql:8.0 container_name: mtab_sql #请不要修改 ports: -
     

Docker 搭建Mtab书签导航程序

作者 莫忘
2024年11月11日 10:25

前言

在跨设备的时候,浏览器收藏夹可能不能同步,所以这时候就需要导航或书签程序

文档

官方地址:https://www.mtab.cc/document.html

教程

手动安装

1.进入宝塔面板找到Docker,并且安装Docker管理器 。

2.找到镜像,点击从仓库中拉取。

3.选择官方镜像库,输入: itushan/mtab ,接着等待获取成功。

4.找到容器,并且创建新的容器,镜像选择刚刚获取成功的镜像。

5.容器端口输入80,服务器端口自定义。

命令安装

 docker run -itd --name mtab -p 9200:80 -v /opt/mtab:/app itushan/mtab

docker-compose

新建文件名为docker-compose.yaml  并且添加如下代码

#请确保您的docker-compose.yml所创建的文件夹有足够的权限,否则可能会失败,
services:
  mysql8:
    image: mysql:8.0
    container_name: mtab_sql #请不要修改
    ports:
      - "9201:3306"
    volumes:
      - ./mysql8:/var/lib/mysql #如有必要请修改为其他路径,请连同mTab配置一同修改
    environment:
      MYSQL_ROOT_PASSWORD: mtab #mysql的root密码
      MYSQL_DATABASE: mtab #数据库名
      MYSQL_USER: mtab #数据库用户名
      MYSQL_PASSWORD: mtab #数据库密码
      TZ: Asia/Shanghai
      CHARACTER_SET_SERVER: utf8mb4
      COLLATION_SERVER: utf8mb4_general_ci
    restart: always
    networks:
      - my-network
  mTab:
    image: itushan/mtab
    container_name: mTabServer
    ports:
      - "9200:80"
    volumes:
      - ./mtab:/app
    environment:
      MYSQL_HOST: mtab_sql #mysql的容器名请不要修改
      MYSQL_USER: mtab #数据库用户名
      MYSQL_PORT: 3306 #数据库端口
      MYSQL_PASSWORD: mtab #数据库密码
      MYSQL_DATABASE: mtab #数据库名
      ADMIN_USER: admin # 安装后默认管理员账号 可以安装后修改
      ADMIN_PASSWORD: 123456 # 安装后默认管理员密码 可以安装后修改
    restart: always
    depends_on:
      - mysql8
    entrypoint: [ "sh", "-c", "sleep 30 && ./start.sh" ] # 延迟启动,等待mysql启动
    networks:
      - my-network
networks:
  my-network:
    driver: bridge

执行命令docker-compose up -d

  • ✇新锐博客
  • linux服务器打包编译node.js项目莫忘
    前言 有个项目是node.js的,但是作者写的时候没有直接写适合PHP环境的版本,只适合部署在vercel中 教程 因为centos7.9版本太旧,所以本次教程基于ubuntu 1.首先大部分服务器是没有npm的需要安装 sudo apt install npm 2.安装pnpm npm install -g pnpm 3.cd到项目目录中 cd /www/wwwroot/xxxx/ 4.开始编译项目 pnpm install pnpm build
     

linux服务器打包编译node.js项目

作者 莫忘
2024年11月6日 03:13

前言

有个项目是node.js的,但是作者写的时候没有直接写适合PHP环境的版本,只适合部署在vercel中

教程

因为centos7.9版本太旧,所以本次教程基于ubuntu

1.首先大部分服务器是没有npm的需要安装

sudo apt install npm

2.安装pnpm

npm install -g pnpm

3.cd到项目目录中

cd  /www/wwwroot/xxxx/

4.开始编译项目

pnpm install
pnpm build
  • ✇新锐博客
  • 国内linux服务器安装npm莫忘
    前言 npm服务使用github上的脚本安装很慢 教程 方法一:使用包管理器 对于 Debian/Ubuntu 系统,可以使用以下命令: sudo apt update sudo apt install -y nodejs npm 对于 CentOS/RHEL 系统,可以使用: sudo yum install -y epel-release sudo yum install -y nodejs npm 方法 2:使用 NodeSource 仓库 NodeSource 提供了最新版本的 Node.js,可以使用以下步骤安装: curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs  对于 CentOS/RHEL: curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash - sudo yum install -y node 最后确认安装 node -v npm -v
     

国内linux服务器安装npm

作者 莫忘
2024年11月6日 01:39

前言

npm服务使用github上的脚本安装很慢

教程

方法一:使用包管理器

对于 Debian/Ubuntu 系统,可以使用以下命令:

sudo apt update 
sudo apt install -y nodejs npm

对于 CentOS/RHEL 系统,可以使用:

sudo yum install -y epel-release 
sudo yum install -y nodejs npm

方法 2:使用 NodeSource 仓库

NodeSource 提供了最新版本的 Node.js,可以使用以下步骤安装:

curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs

 对于 CentOS/RHEL:

curl -fsSL https://rpm.nodesource.com/setup_16.x | sudo bash - 
sudo yum install -y node

最后确认安装

node -v 
npm -v
  • ✇新锐博客
  • WordPress侧边栏添加欢迎语莫忘
    前言 今天逛博客看到一个好玩的东西,分享给大家 参考 原地址:https://blog.shiguang666.eu.org/2024/10/25/479d38b5fc12/ 教程 1.首先去青桔API申请key,目前我们使用到的API是完全免费且无次数限制的。 2.访问api接口:https://api.76.al/api/ip/query?key=your_key 3.将如下代码添加到WordPress小工具中的自定义html内 <div id="announcement-widget"> <div class="card-widget card-ip-info"> <div class="announcement_content"> <div id="welcome-info" style="display: none;"> <div class="loading-spinner"></div> </
     

WordPress侧边栏添加欢迎语

作者 莫忘
2024年11月1日 15:59

前言

今天逛博客看到一个好玩的东西,分享给大家

参考

原地址:https://blog.shiguang666.eu.org/2024/10/25/479d38b5fc12/

教程

1.首先去青桔API申请key,目前我们使用到的API是完全免费且无次数限制的。

2.访问api接口:https://api.76.al/api/ip/query?key=your_key

3.将如下代码添加到WordPress小工具中的自定义html内

<div id="announcement-widget">
    <div class="card-widget card-ip-info">
        <div class="announcement_content">
            <div id="welcome-info" style="display: none;">
                <div class="loading-spinner"></div>
            </div>
        </div>
    </div>
</div>

<style>
    #welcome-info {
        display: flex;
        justify-content: center;
        align-items: center;
        height: auto;
    }
    .loading-spinner {
        width: 50px;
        height: 50px;
        border: 3px solid rgba(0, 0, 0, 0.1);
        border-radius: 50%;
        border-top: 3px solid #3498db;
        animation: spin 1s linear infinite;
    }
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
</style>

<script>
    const createAnnouncementComponent = () => {
        const ipInfoElement = document.createElement('div');
        ipInfoElement.className = "card-widget card-ip-info";
        ipInfoElement.innerHTML = `
            <div class="announcement_content">
                <div id="welcome-info">
                    <div class="loading-spinner"></div>
                </div>
            </div>
        `;
        return ipInfoElement;
    };

    const fetchIpInfo = () => {
        fetch('https://api.76.al/api/ip/query?key=your_key')
            .then(response => response.ok ? response.json() : Promise.reject('Network response was not ok'))
            .then(data => showWelcome(data))
            .catch(() => showErrorMessage());
    };

    const getDistance = (e1, n1, e2, n2) => {
        const R = 6371; // Earth radius
        const toRadians = (degree) => degree * (Math.PI / 180);
        const a = Math.sin(toRadians(n1)) * Math.sin(toRadians(n2)) +
                  Math.cos(toRadians(n1)) * Math.cos(toRadians(n2)) *
                  Math.cos(toRadians(e1 - e2));
        return Math.round(R * Math.acos(a));
    };

    const showWelcome = (ipLocationData) => {
        if (!ipLocationData || !ipLocationData.data) {
            return showErrorMessage();
        }

        // 修改为你自己的经纬度 
            const myLng = 121.38206; //经度
            const myLat = 31.11325; //维度
        const { lng, lat, country, prov, city, district } = ipLocationData.data; // 获取区的信息
        const dist = getDistance(myLng, myLat, lng, lat);
        const pos = country === "中国" ? `${prov} ${city} ${district}` : `${city}, ${district}`; // 包含区的信息

        const welcomeInfoElement = document.getElementById("welcome-info");
        welcomeInfoElement.style.display = 'block';
        welcomeInfoElement.innerHTML = `
            💖 欢迎来自 <b><span style="color:#3390ff;">${pos}</span></b> 的朋友<br>
            📏 您距博主约 <b><span style="color: #3390ff;">${dist}</span></b> 公里<br>
        `;
    };

    const showErrorMessage = () => {
        const welcomeInfoElement = document.getElementById("welcome-info");
        welcomeInfoElement.style.display = 'block';
        welcomeInfoElement.innerHTML = `<p>获取IP信息失败,请检查网络.</p>`;
    };

    const initialize = () => {
        document.body.appendChild(createAnnouncementComponent());
        fetchIpInfo();
    };

    window.onload = initialize;
</script>

4.将其中的your_key改为你自己申请的key

5.访问api接口,将其中的lat和lng替换代码中的经纬度

// 修改为你自己的经纬度  
const myLng = 121.38206; //经度
const myLat = 31.11325; //维度

6.访问主页就可以看到了

  • ✇新锐博客
  • 利用uptimerobot检测站点状态并且部署监控页面莫忘
    前言 之前介绍过如何使用哪吒监控监控自己的服务器和站点,但那是需要服务器的。 今天教大家如何不用服务器监控自己的站点。 教程 1.首先打开uptimerobot官网,点击右上角的Register fo FREE注册一个账号 2.找到页面中的Add New monitor添加自己的网站 3.输入网站,可以选择邮件通知或其他通知方式,当你网站访问不了的时候它就会通知你 4.添加完网站就去首页的Integrations & API中找到API 5.新建一个Read-only API key,这样别人就不能通过你的API捣乱了 6.访问https://github.com/Qikaile/uptime-status项目 7.Fork到自己的仓库然后更改config.js文件里的内容 8.打开Vercel,然后添加刚刚fork的项目等待部署完成 9.到项目的setting中找到domain,然后填写自己准备好的域名即可
     

利用uptimerobot检测站点状态并且部署监控页面

作者 莫忘
2024年10月27日 15:17

前言

之前介绍过如何使用哪吒监控监控自己的服务器和站点,但那是需要服务器的。

今天教大家如何不用服务器监控自己的站点。

教程

1.首先打开uptimerobot官网,点击右上角的Register fo FREE注册一个账号

2.找到页面中的Add New monitor添加自己的网站

3.输入网站,可以选择邮件通知或其他通知方式,当你网站访问不了的时候它就会通知你

4.添加完网站就去首页的Integrations & API中找到API

5.新建一个Read-only API key,这样别人就不能通过你的API捣乱了

6.访问https://github.com/Qikaile/uptime-status项目

7.Fork到自己的仓库然后更改config.js文件里的内容

8.打开Vercel,然后添加刚刚fork的项目等待部署完成

9.到项目的setting中找到domain,然后填写自己准备好的域名即可

  • ✇新锐博客
  • 无需服务器利用vercel搭建typecho博客莫忘
    前言 众所周知,vercel可以搭建静态内容,但是不知道的是也可以搭建typecho博客吧。 教程 准备工作 Github账号,Vercel账号,域名 开始 1.首先访问https://github.com/zycwer/vercel-typecho/并且fork到自己的仓库(最好是下载然后上传到自己仓库) 2.为了防止数据库的泄露,最好将仓库变成私有 3.上传主题文件到usr/theme文件夹下,上传插件到usr/plugins文件夹下 4.使用github登录vercel,点击页面右上角的ADD NEW中的Project 5.找到刚刚fork的项目或者上传的项目点击import并且点击deploy等待部署完成 6.找到项目中的storage,再点击Connect Database,选择其中的Postgres,剩下的直接点右下角的确定就行了, 7.找到项目中的settings,再点击Domains,输入框中输入自己的域名再点击ADD 8.到域名服务商处添加cname解析,记录为cname.vercel-dns.com 9.访问域名,会跳转到typecho安装,数据库选择Po驱动pos
     

无需服务器利用vercel搭建typecho博客

作者 莫忘
2024年10月24日 12:17

前言

众所周知,vercel可以搭建静态内容,但是不知道的是也可以搭建typecho博客吧。

教程

准备工作

Github账号,Vercel账号,域名

开始

1.首先访问https://github.com/zycwer/vercel-typecho/并且fork到自己的仓库(最好是下载然后上传到自己仓库)

2.为了防止数据库的泄露,最好将仓库变成私有

3.上传主题文件到usr/theme文件夹下,上传插件到usr/plugins文件夹下

4.使用github登录vercel,点击页面右上角的ADD NEW中的Project

5.找到刚刚fork的项目或者上传的项目点击import并且点击deploy等待部署完成

6.找到项目中的storage,再点击Connect Database,选择其中的Postgres,剩下的直接点右下角的确定就行了,

7.找到项目中的settings,再点击Domains,输入框中输入自己的域名再点击ADD

8.到域名服务商处添加cname解析,记录为cname.vercel-dns.com

9.访问域名,会跳转到typecho安装,数据库选择Po驱动postgres数据库

10.数据库的地址是刚刚创建的postgres数据库中的@后面以及:5432前面的内容

11.数据库用户名是default,数据库密码是default:后面到@前面的内容,数据库名是verceldb

12.它会提示你到在github仓库中创建一个名为config.inc.php的文件,然后将代码填写到其中。

13.等待vercel重新部署完成,期间不要动任何东西,然后点击我已创建,开始安装。

14.之后就是填写管理员账号和密码就可以了。至此typecho就创建成功了。

问题

本项目的最大问题就是有些主题和插件会更改文件内容,不仅仅是更改数据库的内容,比如handsome主题插件,所以很多主题是用不了的,这就要我们一个个试。

 

  • ✇新锐博客
  • WordPress利用function屏蔽搜索并且跳转到指定页面莫忘
    前言 我们平时弄网站的时候会出现各种搜索词,其中包括不少敏感词,这时候就可以使用function屏蔽某些敏感词 教程 将如下代码添加到子主题的function.php中 function block_sensitive_search_terms($query) { if ($query->is_search && !is_admin()) { $file_path = ABSPATH . '/api/minganci/blocked_terms.txt'; if (file_exists($file_path)) { $blocked_terms = file($file_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } else { $blocked_terms = array(); } // 获取搜索查询词 $search_query = $quer
     

WordPress利用function屏蔽搜索并且跳转到指定页面

作者 莫忘
2024年10月20日 21:41

前言

我们平时弄网站的时候会出现各种搜索词,其中包括不少敏感词,这时候就可以使用function屏蔽某些敏感词

教程

将如下代码添加到子主题的function.php中

function block_sensitive_search_terms($query) {
    if ($query->is_search && !is_admin()) {
        $file_path = ABSPATH . '/api/minganci/blocked_terms.txt';
        if (file_exists($file_path)) {
            $blocked_terms = file($file_path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        } else {
            $blocked_terms = array();
        }
        // 获取搜索查询词
        $search_query = $query->query_vars['s'];

        // 检查搜索查询是否包含任何敏感词
        foreach ($blocked_terms as $blocked_term) {
            if (stripos($search_query, trim($blocked_term)) !== false) {
                // 跳转到404页面
                header("Location: /404");
                exit; // 确保脚本停止执行
            }
        }
    }
}
add_action('pre_get_posts', 'block_sensitive_search_terms');

其中ABSPATH . '/api/minganci/blocked_terms.txt' 是我列举的所有敏感词,你可以替换成自己的。

具体的敏感词可以访问https://www.xrbk.cn/api/minganci/blocked_terms.txt 来获取。

 

  • ✇新锐博客
  • 使用function和php实现外链跳转莫忘
    前言 之前外链跳转使用的是果核的插件,现在不想用插件了,于是自己弄了个代码 教程 首先在子主题的function.php中添加如下代码 //外链跳转 function convert_external_links_to_base64($content) { // 使用正则表达式找到所有外部链接 $pattern = '/<as+href=["'](http[s]?://[^"']+)["']/i'; $content = preg_replace_callback($pattern, function($matches) { $url = $matches[1]; // 对 URL 进行 Base64 编码 $base64_url = base64_encode($url); // 返回新的链接,指向中间页 return str_replace($url, site_url('/redirect.php?url=' . $base64_url), $matches[0]);
     

使用function和php实现外链跳转

作者 莫忘
2024年10月18日 14:41

前言

之前外链跳转使用的是果核的插件,现在不想用插件了,于是自己弄了个代码

教程

首先在子主题的function.php中添加如下代码

//外链跳转
function convert_external_links_to_base64($content) {
    // 使用正则表达式找到所有外部链接
    $pattern = '/<as+href=["'](http[s]?://[^"']+)["']/i';
    $content = preg_replace_callback($pattern, function($matches) {
        $url = $matches[1];
        // 对 URL 进行 Base64 编码
        $base64_url = base64_encode($url);
        // 返回新的链接,指向中间页
        return str_replace($url, site_url('/redirect.php?url=' . $base64_url), $matches[0]);
    }, $content);
    
    return $content;
}

// 将函数应用于文章和页面内容
add_filter('the_content', 'convert_external_links_to_base64');

再在网站根目录新建一个php文件命名为redirect.php ,并且添加如下代码

<?php
if (isset($_GET['url'])) {
    $link = base64_decode($_GET['url']);
}
?>
<!doctype html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" type="text/css" href="static/css/style.css">
    <link rel="icon" href="https://www.xrbk.cn/favicon.png" type="image/x-icon"/><!--favicon图片地址-->
    <title>新锐博客 - 安全中心</title><!--修改文字-->
</head>

<body>
  <div class="go-wild-box">
    <div class="go-wild-container">
     <a href="https://www.xrbk.cn/">
     <img alt="新锐博客" src="/wp-content/uploads/f4a9f982d722de858fd133baf4ff14b7.webp" class="logo-img" /><!--修改Logo地址-->
      </a>
     <div class="tips-title">您即将离开新锐博客,跳转到第三方链接</div><!--修改文字-->
        <div class="address"><?php echo htmlspecialchars($link); ?></div>
      <div class="tips-subtitle">请注意您的账号和财产安全</div>
      <div class="btn-groups">
        <button onclick="try { window.close(); } catch(e) { alert('请手动关闭此页面'); }" type="button" class="ant-btn ant-btn-default">取消访问</button>
        <a href="<?php echo htmlspecialchars($link); ?>" rel="nofollow">
          <button type="button" class="ant-btn ant-btn-primary">继续访问</button>
        </a>
      </div>
    </div>
  </div>
</body>
</html>
<style>
body { 
    margin: 0; font-family: 'PingFangSC', sans-serif; background-color: #EFF4FA; }
.go-wild-box { display: flex; justify-content: center; align-items: center; height: 100vh; }
.go-wild-container { width: 770px; height: 330px; max-width: 90%; padding: 90px 15px; background-color: #fff; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); text-align: center; }
.logo-img { width: 120px; height: auto; }
.tips-title { margin: 20px 0; font-size: 22px; color: #2a3c59; font-weight: 500; }
.address { margin-bottom: 20px; padding: 15px; background-color: #EFF4FA; border-radius: 8px; color: #2a3c59; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: 80%; max-width: 600px; margin: 0 auto; }
.tips-subtitle { font-size: 14px; color: #2a3c59; margin-bottom: 30px;margin-top: 20px; }
.btn-groups { display: flex; justify-content: center; gap: 10px; margin-top: 60px; }
.ant-btn { width: 152px; height: 44px; line-height: 44px; border-radius: 20px; border: none; cursor: pointer; font-size: 14px; transition: all 0.3s ease; }
.ant-btn-primary { background: linear-gradient(152deg, #07C160 0%, #07c183 100%); color: #fff; }
.ant-btn-default { background-color: #fff; color: #2a3c59; border: 1px solid #ccc; }
.ant-btn-default:hover { background-color: #fff; border-color: #07C160; color: #07C160; }
</style>

结语

这样访问文章和页面中的外部链接就可以跳转到中间页了

  • ✇新锐博客
  • python项目关闭终端照样运行的方法莫忘
    前言 因为想使用一个python项目,所以经历了以下事件并且成功部署好了项目 过程 首先项目就两件事一个是安装环境,另一个就是启动python脚本。 但是呢当我用pip install -r requirements.txt 安装环境的时候,提示pip不存在,突然想到之前遇到过这种情况是版本不对,于是将pip改为pip3就行了。 安装好后就是需要启动python脚本了,于是我就用finalshell连接了服务器,用CD到目录,然后同样的将python改为python3执行了python脚本。 虽然脚本运行起来了,但是我发现只要我关闭了终端,任务好像就停止了。 于是我就百度如何关闭终端不停止任务,最后发现了一个方法。 使用nohup python3 your_script.py & 这个命令就好了。 这样哪怕关闭终端也可以运行了。
     

python项目关闭终端照样运行的方法

作者 莫忘
2024年10月17日 02:29

前言

因为想使用一个python项目,所以经历了以下事件并且成功部署好了项目

过程

首先项目就两件事一个是安装环境,另一个就是启动python脚本。

但是呢当我用pip install -r requirements.txt 安装环境的时候,提示pip不存在,突然想到之前遇到过这种情况是版本不对,于是将pip改为pip3就行了。

安装好后就是需要启动python脚本了,于是我就用finalshell连接了服务器,用CD到目录,然后同样的将python改为python3执行了python脚本。

虽然脚本运行起来了,但是我发现只要我关闭了终端,任务好像就停止了。

于是我就百度如何关闭终端不停止任务,最后发现了一个方法。

使用nohup python3 your_script.py & 这个命令就好了。

这样哪怕关闭终端也可以运行了。

  • ✇新锐博客
  • 记一次数据库查询操作莫忘
    前言 前两天有群友找到我想让我给他把一个美化插件改一下,插件本来只显示注册用户,浏览量,运行天数等信息。 他想给插件添加一个vip用户数量的信息,所以让我看看能不能搞。 过程 首先我想到的是用数据库来查询,但是需要一个关键词。 我在WordPress后台查看的时候发现虽然会员被区分为黄金会员和钻石会员,但是它们共同的点是都是永久的。 于是我打算从永久这一点来入手,而子比赋予永久会员的值为Permanent ,我就去数据库查找这个词。 在wp_usermeta这个数据表中有一个vip_exp_date 的参数的值就是Permanent 。 我就用AI帮我写了一个php代码,查询到Permanent 的数量一共为73个,而WordPress后台显示的黄金会员和钻石会员的总数为70个。 经过查询发现有三个普通会员也被赋予了永久会员这一身份,所以得出结论,无论是普通会员还是黄金会员亦或者钻石会员都可以被赋予永久会员这一身份。 看来只能找其他的值来区别这一点了,最后让我发现vip_level 这一参数的值要么没有要么就是1或2,于是我就认为1代表黄金会员2则代表钻石会员。 想做就做,我就用AI帮
     

记一次数据库查询操作

作者 莫忘
2024年10月12日 11:25

前言

前两天有群友找到我想让我给他把一个美化插件改一下,插件本来只显示注册用户,浏览量,运行天数等信息。

他想给插件添加一个vip用户数量的信息,所以让我看看能不能搞。

过程

首先我想到的是用数据库来查询,但是需要一个关键词。

我在WordPress后台查看的时候发现虽然会员被区分为黄金会员和钻石会员,但是它们共同的点是都是永久的。

于是我打算从永久这一点来入手,而子比赋予永久会员的值为Permanent ,我就去数据库查找这个词。

wp_usermeta这个数据表中有一个vip_exp_date 的参数的值就是Permanent 。

我就用AI帮我写了一个php代码,查询到Permanent 的数量一共为73个,而WordPress后台显示的黄金会员和钻石会员的总数为70个。

经过查询发现有三个普通会员也被赋予了永久会员这一身份,所以得出结论,无论是普通会员还是黄金会员亦或者钻石会员都可以被赋予永久会员这一身份。

看来只能找其他的值来区别这一点了,最后让我发现vip_level 这一参数的值要么没有要么就是1或2,于是我就认为1代表黄金会员2则代表钻石会员。

想做就做,我就用AI帮我写了一段PHP代码,贴在下面了。

<?php
global $wpdb;
// 查询用户数量
$vipusers = $wpdb->get_var(
    $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->usermeta} WHERE meta_key = %s AND meta_value IN (%d, %d)",
        'vip_level', 1, 2
    )
);

可以看到是在wp_usermeta这个表中查询了关于vip_level为1或2的数量,最后显示的结果是70。

结语

搭建网站的时候不可避免的需要用到数据库,所以我们得学习好怎么操作数据库才行。

  • ✇新锐博客
  • IP签名档优化修改版莫忘
    前言 之前发过一次ip签名档的文章,但是其作者不知道是谁,这次的IP签名档,是由我的友链广然笔记修改并且修复的。 更新 新增IPv6地址识别 新增随机显示背景图 修复网站添加CDN获取不到IP地址问题 修改一些样式的显示方式 修复较长地址显示和系统信息显示重叠的问题 新增两张背景图片 修复一些其他显示问题 教程 1.下载并且解压到网站目录下 2.注册高德开发平台和腾讯位置服务Web服务应用,获得两个 Key。 3.修改index.php中的代码。 下载地址 IP签名档-修复版下载
     

IP签名档优化修改版

作者 莫忘
2024年10月6日 16:01

前言

之前发过一次ip签名档的文章,但是其作者不知道是谁,这次的IP签名档,是由我的友链广然笔记修改并且修复的。

更新

  • 新增IPv6地址识别
  • 新增随机显示背景图
  • 修复网站添加CDN获取不到IP地址问题
  • 修改一些样式的显示方式
  • 修复较长地址显示和系统信息显示重叠的问题
  • 新增两张背景图片
  • 修复一些其他显示问题

教程

1.下载并且解压到网站目录下

2.注册高德开发平台腾讯位置服务Web服务应用,获得两个 Key。

3.修改index.php中的代码。

下载地址

IP签名档-修复版
  • ✇新锐博客
  • WordPress侧边栏添加信息统计莫忘
    前言 刚刚写了一篇统计文章字数的文章,现在就教大家如何在侧边栏添加信息统计 教程 在子主题的function.php中添加如下代码 function display_site_stats() { // 获取统计数据 $total_posts = wp_count_posts()->publish; $site_uptime = get_site_uptime(); $last_update = get_last_update_time(); $total_word_count = get_total_word_count(); // 输出HTML $stats = [ '文章数目' => ['value' => $total_posts, 'class' => 'purple'], '存活天数' => ['value' => $site_uptime, 'class' => 'violet'], '上次更新' => ['value'
     

WordPress侧边栏添加信息统计

作者 莫忘
2024年10月4日 13:22

前言

刚刚写了一篇统计文章字数的文章,现在就教大家如何在侧边栏添加信息统计

教程

在子主题的function.php中添加如下代码

function display_site_stats() {
    // 获取统计数据
    $total_posts = wp_count_posts()->publish;
    $site_uptime = get_site_uptime();
    $last_update = get_last_update_time();
    $total_word_count = get_total_word_count();

    // 输出HTML
    $stats = [
        '文章数目' => ['value' => $total_posts, 'class' => 'purple'],
        '存活天数' => ['value' => $site_uptime, 'class' => 'violet'],
        '上次更新' => ['value' => $last_update, 'class' => 'red'],
        '文章字数' => ['value' => $total_word_count . ' 万', 'class' => 'red']
    ];

    $output = '<div style="background: #fff; padding: 10px; border-radius: 5px; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);">';
    foreach ($stats as $text => $data) {
        $output .= sprintf(
            '<div style="display: flex; align-items: center; margin-bottom: 10px;">
                <span style="flex: 1;">%s</span>
                <span style="background: %s; color: #fff; padding: 2px 8px; border-radius: 12px; font-size: 0.9em;">%s</span>
            </div>',
            esc_html($text),
            esc_attr(get_badge_color($data['class'])),
            esc_html($data['value'])
        );
    }
    $output .= '</div>';

    return $output; // 返回输出的HTML
}

function get_badge_color($class) {
    switch ($class) {
        case 'purple':
            return '#9c27b0';
        case 'violet':
            return '#7e57c2';
        case 'red':
            return '#e53935';
        default:
            return '#e0e0e0';
    }
}

function get_site_uptime() {
    $start_date = new DateTime('2023-04-05'); // 替换为你的网站创建日期
    $interval = $start_date->diff(new DateTime());
    return $interval->days . '天'; // 直接返回存活的天数
}

function get_last_update_time() {
    $last_post = wp_get_recent_posts(['numberposts' => 1])[0];
    $time_difference = time() - strtotime($last_post['post_date']);

    if ($time_difference < 60) return '刚刚';
    if ($time_difference < 3600) return floor($time_difference / 60) . '分钟前';
    if ($time_difference < 86400) return floor($time_difference / 3600) . '小时前';
    return floor($time_difference / 86400) . '天前';
}

function get_total_word_count() {
    $posts = get_posts(['numberposts' => -1]);
    $total_word_count = array_sum(array_map(function($post) {
        return str_word_count(strip_tags($post->post_content));
    }, $posts));
    return round($total_word_count / 10000, 2); // 返回万字数
}

// 注册短代码
add_shortcode('xrbk-cbls', 'display_site_stats');

然后在WordPress小工具中添加文本,里面输入[xrbk-cbls]

截图

图片[1]-新锐博客

  • ✇新锐博客
  • WordPress添加所有文章内容字数统计莫忘
    前言 突发奇想,想要知道自己更新了多少字数的内容,于是就有了下面的教程。 教程 如果有子主题,请将如下代码添加到子主题的function.php中 //获取所有文章字数 function count_all_posts_word_count() { // 获取所有文章 $args = array( 'post_type' => 'post', 'posts_per_page' => -1, // 获取所有文章 ); $query = new WP_Query($args); $total_word_count = 0; // 循环遍历每篇文章 if ($query->have_posts()) { while ($query->have_posts()) { $query->the_post(); // 获取文章内容 $content = get_the_content
     

WordPress添加所有文章内容字数统计

作者 莫忘
2024年10月4日 11:52

前言

突发奇想,想要知道自己更新了多少字数的内容,于是就有了下面的教程。

教程

如果有子主题,请将如下代码添加到子主题的function.php中

//获取所有文章字数
function count_all_posts_word_count() {
    // 获取所有文章
    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => -1, // 获取所有文章
    );

    $query = new WP_Query($args);
    $total_word_count = 0;

    // 循环遍历每篇文章
    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            // 获取文章内容
            $content = get_the_content();
            // 计算字数
            $word_count = str_word_count(strip_tags($content));
            $total_word_count += $word_count;
        }
        // 重置查询
        wp_reset_postdata();
    }

    return $total_word_count;
}

// 将字数转换为以千为单位的格式
function format_word_count($count) {
    if ($count >= 1000) {
        return round($count / 1000, 1) . 'k'; // 保留一位小数
    }
    return $count; // 小于1000的直接返回
}

// 使用短代码显示字数
function display_total_word_count() {
    $total_words = count_all_posts_word_count();
    $formatted_words = format_word_count($total_words);
    return "所有文章的总字数: " . $formatted_words;
}
add_shortcode('total_word_counts', 'display_total_word_count');
?>

然后去想要显示的地方添加[total_word_counts]

结语

如果想要添加到侧边栏的话可以使用文本小工具。

❌
❌