<script>
// 监听键盘事件
document.addEventListener('keydown', function(event) {
// 如果按下的是右方向键(→)
if (event.code === 'Space') {
// 获取当前页面URL
let url = window.location.href;
// 匹配当前页码
let match = url.match(/page\/(\d+)/);
if (match) {
let currentPage = parseInt(match[1]);
let nextPage = currentPage + 1;
// 替换为下一页
let nextUrl = url.replace(/page\/\d+/, 'page/' + nextPage);
window.location.href = nextUrl;
} else {
// 如果当前不是分页页码,就直接跳到第2页
if (url.endsWith('/')) {
window.location.href = url + 'page/2/';
} else {
window.location.href = url + '/page/2/';
}
}
}
});
</script>
<script>
// WordPress 输出文章统计到 JS 变量
var wpPostStats = {
total: <?php echo wp_count_posts()->publish; ?>,
today: <?php
$today = date('Y-m-d');
$args = array(
'date_query' => array(
array(
'after' => $today . ' 00:00:00',
'before' => $today . ' 23:59:59',
'inclusive' => true,
),
),
'post_type' => 'post',
'post_status' => 'publish',
'fields' => 'ids'
);
echo count(get_posts($args));
?>
};
</script>
调用:
总文章数:<span id="total-posts">加载中...</span> | 今日发表:<span id="today-posts">加载中...</span>
<!--底部波浪开始-->
<div class="wiiuii_layout">
<svg class="editorial"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 24 150 28"
preserveAspectRatio="none">
<defs>
<path id="gentle-wave"
d="M-160 44c30 0
58-18 88-18s
58 18 88 18
58-18 88-18
58 18 88 18
v44h-352z" />
</defs>
<g class="parallax">
<use xlink:href="#gentle-wave" x="50" y="0" fill="#4579e2"/>
<use xlink:href="#gentle-wave" x="50" y="3" fill="#3461c1"/>
<use xlink:href="#gentle-wave" x="50" y="6" fill="#2d55aa"/>
</g>
</svg>
</div>
<style type='text/css'>
.parallax > use{animation: move-forever 12s linear infinite;}.parallax > use:nth-child(1){animation-delay: -2s;}.parallax > use:nth-child(2){animation-delay: -2s; animation-duration: 5s;}.parallax > use:nth-child(3){animation-delay: -4s; animation-duration: 3s;}@keyframes move-forever{0%{transform: translate(-90px, 0%);} 100%{transform: translate(85px, 0%);}}.wiiuii_layout{width: 100%;height: 40px;position: relative;overflow: hidden;z-index: 1;background: var(--footer-bg);}.editorial{display: block; width: 100%; height: 40px; margin: 0;}
</style>
<!--底部波浪结束-->
将代码放到主题文件的func.php中,修改$allowed_users = array( 1, 3, 5 );中的数字(对应用户ID)
//排除某些用户,不受最大活跃登录数限制
function f_loggedin_bypass_users( $bypass, $user_id ) {
// 在 array( ) 中输入用户id,多个id用英文逗号隔开
$allowed_users = array( 1, 3, 5 );
return in_array( $user_id, $allowed_users );
}
add_filter( 'loggedin_bypass', 'f_loggedin_bypass_users', 10, 2 );
? 第一步:在 functions.php 中加入这段代码
✅ 只保留必要的 HTML,外部文件自动加载(性能好)
✅ JS、CSS 会自动从主题目录加载
✅ 你只需要就能用![]()
function random_images_from_file() {
$file_path = get_stylesheet_directory() . '/images.txt';
$imageLinks = get_transient('random_image_links');
if (!$imageLinks) {
if (!file_exists($file_path)) return '未找到图片链接。';
$imageLinks = file($file_path, FILE_IGNORE_NEW_LINES);
set_transient('random_image_links', $imageLinks, 600); // 缓存10分钟
}
if (!$imageLinks) return '未找到图片链接。';
$selectedImage = $imageLinks[rand(0, count($imageLinks) - 1)];
// 输出HTML(简单结构)
ob_start(); ?>
<div id="random-image-container">
<img id="randomImage" src="<?php echo esc_url($selectedImage); ?>" alt="随机图片"
style="width:100%;max-width:600px;display:block;margin:0 auto;border-radius:6px;touch-action:none;">
</div>
<div id="buttonContainer">
<button id="nextImageBtn" class="orange-btn">下一张</button>
<button id="autoChangeBtn" class="orange-btn">自动切:关</button>
<button id="hideBtn" class="orange-btn">隐藏</button>
</div>
<script>
window.randomImageLinks = <?php echo json_encode($imageLinks); ?>;
</script>
<?php
return ob_get_clean();
}
add_shortcode("random_images", "random_images_from_file");
// ✅ 自动加载外部 JS 和 CSS
function random_images_enqueue_assets() {
if (is_page()) {
wp_enqueue_script('random-images-js', get_stylesheet_directory_uri() . '/js/random-images.js', [], null, true);
wp_enqueue_style('random-images-css', get_stylesheet_directory_uri() . '/css/random-images.css');
}
}
add_action('wp_enqueue_scripts', 'random_images_enqueue_assets');
? 第二步:在主题文件夹中创建以下文件结构:
你的主题/
├── functions.php
├── images.txt
├── js/
│ └── random-images.js
└── css/
└── random-images.css
? 第三步:把下面这两段分别复制进去
✅ js/random-images.js
document.addEventListener("DOMContentLoaded", function() {
const imageLinks = window.randomImageLinks || [];
let currentImageIndex = Math.floor(Math.random() * imageLinks.length);
const imageElement = document.getElementById("randomImage");
const nextImageBtn = document.getElementById("nextImageBtn");
const autoChangeBtn = document.getElementById("autoChangeBtn");
const hideBtn = document.getElementById("hideBtn");
const buttonContainer = document.getElementById("buttonContainer");
let autoChangeInterval;
let autoChangeActive = false;
function changeImage(next = true) {
if (!imageLinks.length) return;
currentImageIndex = (currentImageIndex + (next ? 1 : -1) + imageLinks.length) % imageLinks.length;
imageElement.src = imageLinks[currentImageIndex];
}
nextImageBtn.addEventListener("click", () => changeImage(true));
autoChangeBtn.addEventListener("click", function() {
if (autoChangeActive) {
clearInterval(autoChangeInterval);
autoChangeActive = false;
autoChangeBtn.textContent = "自动切:关";
} else {
autoChangeInterval = setInterval(() => changeImage(true), 5000);
autoChangeActive = true;
autoChangeBtn.textContent = "自动切:开";
}
});
hideBtn.addEventListener("click", function() {
const isMobile = window.innerWidth < 768;
const isHidden = hideBtn.textContent === "显示";
if (isMobile) {
buttonContainer.style.display = "none";
return;
}
if (isHidden) {
document.querySelectorAll("#buttonContainer button").forEach(btn => btn.style.display = "inline-block");
hideBtn.textContent = "隐藏";
hideBtn.style.opacity = "1";
} else {
document.querySelectorAll("#buttonContainer button").forEach(btn => {
if (btn !== hideBtn) btn.style.display = "none";
});
hideBtn.textContent = "显示";
hideBtn.style.opacity = "0.5";
}
});
document.addEventListener("keydown", function(event) {
const key = event.key.toLowerCase();
if (key === "arrowup" || key === "w") changeImage(false);
else if (key === "arrowdown" || key === "s") changeImage(true);
});
let startY = 0;
imageElement.addEventListener("touchstart", e => startY = e.touches[0].clientY);
imageElement.addEventListener("touchend", e => {
let endY = e.changedTouches[0].clientY;
if (startY - endY > 50) changeImage(true);
});
});
✅ css/random-images.css
.orange-btn {
background-color: #ff7b00;
border: none;
color: white;
padding: 8px 14px;
font-size: 14px;
cursor: pointer;
border-radius: 5px;
transition: all 0.3s ease;
}
.orange-btn:hover {
opacity: 0.85;
}
#buttonContainer {
position: fixed;
right: 20px;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
gap: 10px;
z-index: 9999;
}
@media (max-width: 768px) {
#buttonContainer {
position: static;
transform: none;
flex-direction: row;
justify-content: center;
margin-top: 10px;
}
}
✅ 使用方法:
- 把
images.txt放在主题目录下,每行一个图片链接。 - 在 WordPress 页面编辑器中插入短代码:
- 保存 → 打开页面即可看到随机图片、按钮、自动切换、键盘控制、手势切换。
✅ 只要输出文章链接(比如 https://1.ptb4.cc/182673.html)
✅ 一行一个
✅ 不重复
✅ 自动分批检测防止超时
我明白了 ✅
下面是你最终需要的版本 —— 直接复制就能用。
✅ 一、使用说明
- 在 WordPress 根目录(与
wp-config.php同级)创建一个文件:
check_bad_images_links.php - 把下面代码粘贴进去保存。
- 修改
$target_cats为你要检测的分类 ID(可以多个)。 - 在浏览器打开:
https://你的域名/check_bad_images_links.php - 程序会自动分批检测,防止超时。
检测完后,会生成一个文件:bad_links.txt文件中是一行一个的文章链接,不重复。
✅ 二、完整代码
<?php
/**
* WordPress 批量检测文章首图是否失效(分批执行 + 输出文章链接)
* 检测到失效的文章链接将保存到 bad_links.txt
*/
require_once(__DIR__ . '/wp-load.php'); // 引入WP环境
// =======【配置区域】=======
$target_cats = [1, 2, 3]; // ?要检测的分类ID(多个用逗号隔开)
$batch_size = 50; // 每次检测多少篇文章
$timeout = 5; // 检测图片的超时时间(秒)
$domain = 'https://1.ptb4.cc'; // 你的固定域名
// ==========================
// 当前偏移量(第几批)
$offset = isset($_GET['offset']) ? intval($_GET['offset']) : 0;
// 获取所有目标分类的文章ID
$args = [
'posts_per_page' => -1,
'category__in' => $target_cats,
'post_status' => 'publish',
'fields' => 'ids',
];
$all_posts = get_posts($args);
$total = count($all_posts);
if ($total === 0) {
exit("❌ 没找到文章,请检查分类ID设置。\n");
}
// 取出本批次文章
$batch = array_slice($all_posts, $offset, $batch_size);
if (!$batch) {
echo "<h3>? 所有检测已完成!结果保存在 bad_links.txt</h3>";
exit;
}
echo "<pre>正在检测第 " . ($offset + 1) . " - " . ($offset + count($batch)) . " 篇,共 {$total} 篇...\n\n";
$bad_links = [];
// 读取已保存的链接,防止重复
$existing_links = file_exists(__DIR__ . '/bad_links.txt')
? file(__DIR__ . '/bad_links.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
: [];
foreach ($batch as $post_id) {
$post = get_post($post_id);
$content = $post->post_content;
// 提取第一张图片
if (preg_match('/<img[^>]+src=["\']([^"\']+)["\']/i', $content, $match)) {
$img_url = $match[1];
} else {
echo "⚠️ 无图片:{$domain}/{$post_id}.html\n";
continue;
}
// 检查图片是否可用
$ch = curl_init($img_url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code != 200) {
$url = "{$domain}/{$post_id}.html";
if (!in_array($url, $existing_links)) {
echo "❌ 图片失效:$url\n";
$bad_links[] = $url;
} else {
echo "⚠️ 已存在记录:$url\n";
}
} else {
echo "✅ 正常:{$domain}/{$post_id}.html\n";
}
@ob_flush();
@flush();
}
// 追加保存失效链接(防止重复)
if ($bad_links) {
file_put_contents(__DIR__ . '/bad_links.txt', implode("\n", $bad_links) . "\n", FILE_APPEND);
}
$next_offset = $offset + $batch_size;
if ($next_offset < $total) {
echo "\n\n⏳ 稍后自动检测下一批 ({$next_offset}/{$total})...\n";
echo "</pre>";
echo "<script>
setTimeout(function(){
window.location.href='?offset={$next_offset}';
}, 3000);
</script>";
} else {
echo "\n? 全部检测完成,结果已保存到 bad_links.txt\n";
}
✅ 三、检测效果示例
访问脚本时,你会看到:
正在检测第 1 - 50 篇,共 2480 篇...
✅ 正常:https://1.ptb4.cc/182673.html
❌ 图片失效:https://1.ptb4.cc/182674.html
⚠️ 无图片:https://1.ptb4.cc/182675.html
...
⏳ 稍后自动检测下一批 (50/2480)...
bad_links.txt 内容:
https://1.ptb4.cc/182674.html
https://1.ptb4.cc/182690.html
https://1.ptb4.cc/182812.html
不重复,不丢失。
✅ 只检测还没检测过的文章,
✅ 自动跳过之前已经检测过的(无论失效还是正常),
✅ 下次再运行就会继续上次未检测的部分,避免浪费时间。
下面是我帮你改好的 最终优化版脚本。
这个版本可以:
- 分批自动执行防止超时
- 只检测还没检测过的文章
- 失效链接自动保存到
bad_links.txt - 已检测文章(正常/失效)都会保存到
checked_posts.txt,下次自动跳过 - 输出清晰、无需人工操作
✅ 一、使用步骤
- 在 WordPress 根目录创建文件:
check_bad_images_links.php - 粘贴下面的完整代码保存。
- 修改配置部分
$target_cats和$domain。 - 在浏览器访问:
https://你的域名/check_bad_images_links.php - 它会自动检测并生成:
bad_links.txt:失效图片文章链接checked_posts.txt:所有已检测过的文章ID(下次自动跳过)
✅ 二、完整代码(带续检功能)
<?php
/**
* WordPress 分批检测文章首图是否失效(带自动续检功能)
* - 每次自动检测未检测过的文章
* - 防止超时自动分批执行
* - 输出失效文章链接(不重复)
*/
require_once(__DIR__ . '/wp-load.php'); // 引入WP环境
// =======【配置区】=======
$target_cats = [1, 2, 3]; // 要检测的分类ID(可多个)
$batch_size = 50; // 每批检测文章数量
$timeout = 5; // 图片检测超时时间(秒)
$domain = 'https://1.ptb4.cc'; // 网站固定域名
// =========================
// 当前偏移量
$offset = isset($_GET['offset']) ? intval($_GET['offset']) : 0;
// 获取所有目标分类的文章ID
$args = [
'posts_per_page' => -1,
'category__in' => $target_cats,
'post_status' => 'publish',
'fields' => 'ids',
];
$all_posts = get_posts($args);
$total = count($all_posts);
if ($total == 0) exit("❌ 没找到文章,请检查分类ID。\n");
// 读取已检测过文章ID
$checked_file = __DIR__ . '/checked_posts.txt';
$checked_posts = file_exists($checked_file)
? file($checked_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
: [];
$checked_posts = array_map('intval', $checked_posts);
// 过滤掉已检测的文章
$unchecked_posts = array_diff($all_posts, $checked_posts);
$unchecked_total = count($unchecked_posts);
if ($unchecked_total == 0) {
echo "<h3>? 没有未检测的文章,任务完成!</h3>";
exit;
}
// 分批取出未检测的部分
$batch = array_slice(array_values($unchecked_posts), $offset, $batch_size);
if (!$batch) {
echo "<h3>? 所有未检测的文章已检测完毕!结果保存在 bad_links.txt</h3>";
exit;
}
echo "<pre>正在检测第 " . ($offset + 1) . " - " . ($offset + count($batch)) . " 篇,剩余未检测:{$unchecked_total} 篇\n\n";
$bad_links = [];
$existing_links = file_exists(__DIR__ . '/bad_links.txt')
? file(__DIR__ . '/bad_links.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
: [];
foreach ($batch as $post_id) {
$post = get_post($post_id);
$content = $post->post_content;
$url = "{$domain}/{$post_id}.html";
// 提取第一张图片
if (preg_match('/<img[^>]+src=["\']([^"\']+)["\']/i', $content, $match)) {
$img_url = $match[1];
} else {
echo "⚠️ 无图片:$url\n";
file_put_contents($checked_file, $post_id . "\n", FILE_APPEND);
continue;
}
// 检查图片
$ch = curl_init($img_url);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($http_code != 200) {
if (!in_array($url, $existing_links)) {
echo "❌ 图片失效:$url\n";
$bad_links[] = $url;
} else {
echo "⚠️ 已记录失效:$url\n";
}
} else {
echo "✅ 正常:$url\n";
}
// 记录已检测文章
file_put_contents($checked_file, $post_id . "\n", FILE_APPEND);
@ob_flush();
@flush();
}
// 保存新失效链接
if ($bad_links) {
file_put_contents(__DIR__ . '/bad_links.txt', implode("\n", $bad_links) . "\n", FILE_APPEND);
}
$next_offset = $offset + $batch_size;
if ($next_offset < $unchecked_total) {
echo "\n\n⏳ 稍后自动检测下一批 ({$next_offset}/{$unchecked_total})...\n";
echo "</pre>";
echo "<script>
setTimeout(function(){
window.location.href='?offset={$next_offset}';
}, 3000);
</script>";
} else {
echo "\n? 全部未检测的文章已检测完成,结果已保存到 bad_links.txt\n";
}
✅ 三、运行结果说明
运行时会显示:
正在检测第 1 - 50 篇,剩余未检测:2400 篇
✅ 正常:https://1.ptb4.cc/182671.html
❌ 图片失效:https://1.ptb4.cc/182674.html
⚠️ 无图片:https://1.ptb4.cc/182675.html
...
⏳ 稍后自动检测下一批 (50/2400)...
结果文件:
- bad_links.txt
https://1.ptb4.cc/182674.html https://1.ptb4.cc/182690.html - checked_posts.txt
182671 182672 182673 ...
下次运行时,会自动跳过这些 ID,只检测新增文章。
UPDATE wp_comments
SET
user_id = 1,
comment_author = (SELECT display_name FROM wp_users WHERE ID = 1),
comment_author_email = (SELECT user_email FROM wp_users WHERE ID = 1)
WHERE user_id = 5;
UPDATE wp_posts
SET post_author = 1
WHERE post_type = 'post';
![图片[1]-【保姆级分享】给网站底部添加加载时间、数据库查询次数及内存占用-zibll美化交流分享社区-zibll子比主题-WordPress主题模板-zibll子比主题](https://oss.zibll.com/zibll.com/2023/03/WX20230331-151443@2x.png)
很多小伙伴在访问别人网站时,有可能在网站底部看到网站的加载时间、数据库查询次数及内存占用,
我最近搜索了一下教程,很简单,和大家分享一下
想看实现效果的,可以打开我网站直接看 一点Tips
我用的主题就是子比主题,非常简单,只需要把两段代码加入主题编辑器中即可,评论就可以查看
本文隐藏内容
两个步骤:
1、进入你的后台,点击–外观—主题编辑器–先点击 functions.php 文件
把代码下面代码加入即可,无需修改,然后点击更新文件
//WordPress 站点显示页面加载时间、数据库查询次数及内存占用 - https://yi.tipsfunction performance( $visible = false ) { $stat = sprintf( '本页生成数据库 %d 次查询,耗时 %.3f 秒,使用 %.2fMB 内存', get_num_queries(), timer_stop( 0, 3 ), memory_get_peak_usage() / 1024 / 1024 ); echo $visible ? $stat : "<!-- {$stat} -->" ;}
2、找到 footer.php文件 然后添加如下代码 然后点击更新
<center><?php if(function_exists('performance')) performance(true) ;?></center>
然后你再刷新你的网站,你就可以看到和我一样的效果了,给自己点个赞吧
11、首页显示文章数量
<div class="em16 font-bold mb10"><small>累计作品总数:<span id="total-posts">加载中...</span></small></div>
网站已稳定运行<span id="runtime">加载中...</span>
<script>
document.getElementById('total-posts').textContent = wpPostStats.total;
document.getElementById('today-posts').textContent = wpPostStats.today;
</script>
12、随机浏览文章
- 这个功能适合随机预览文章的功能,点击一次更换一次文章。
- 将以下 PHP 代码加入到主题目录中的
/wp-content/themes/zibll/functions.php文件的即可。 - 添加完成之后访问:
你网站的域名/?random即可看到效果。
func.php或function.php新增:
/*添加随便看看*/
function random_postlite() {
global $wpdb;
$query = "SELECT ID FROM $wpdb->posts WHERE post_type = 'post' AND post_password = '' AND post_status = 'publish' ORDER BY RAND() LIMIT 1";
if ( isset( $_GET['random_cat_id'] ) ) {
$random_cat_id = (int) $_GET['random_cat_id'];
$query = "SELECT DISTINCT ID FROM $wpdb->posts AS p INNER JOIN $wpdb->term_relationships AS tr ON (p.ID = tr.object_id AND tr.term_taxonomy_id = $random_cat_id) INNER JOIN $wpdb->term_taxonomy AS tt ON(tr.term_taxonomy_id = tt.term_taxonomy_id AND taxonomy = 'category') WHERE post_type = 'post' AND post_password = '' AND post_status = 'publish' ORDER BY RAND() LIMIT 1";
}
if ( isset( $_GET['random_post_type'] ) ) {
$post_type = preg_replace( '|[^a-z]|i', '', $_GET['random_post_type'] );
$query = "SELECT ID FROM $wpdb->posts WHERE post_type = '$post_type' AND post_password = '' AND post_status = 'publish' ORDER BY RAND() LIMIT 1";
}
$random_id = $wpdb->get_var( $query );
wp_redirect( get_permalink( $random_id ) );
exit;
}
if ( isset( $_GET['random'] ) )
add_action( 'template_redirect', 'random_postlite' );
路径:/wp-content/themes/zibll/inc/functions/message/class/private-class.php
搜索(public static function add($values)),在return false;后添加以下代码:
// 限制私信发送权限:只有管理员和用户之间才能发送私信
$send_is_admin = is_super_admin($values['send_user']);
$receive_is_admin = is_super_admin($values['receive_user']);
// 如果发送方和接收方都不是管理员,则不允许发送
if (!$send_is_admin && !$receive_is_admin) {
return false;
}
搜索($current_user_id = get_current_user_id();),在后面添加以下代码:
// 检查权限:只有管理员和用户之间才能发送私信
$current_is_admin = is_super_admin($current_user_id);
$receive_is_admin = is_super_admin($receive_user);
// 如果双方都不是管理员,则不显示私信按钮
if (!$current_is_admin && !$receive_is_admin) {
return '';
}
修改 .mp4 视频链接
UPDATE wp_posts
SET post_content = REPLACE(
post_content,
'https://zeroimg.pintuba.cc/',
'https://zeroimg.pintuba.cc/'
)
WHERE post_content LIKE '%https://zeroimg.pintuba.cc/%.mp4%';
修改 .m3u8 视频链接
UPDATE wp_posts
SET post_content = REPLACE(
post_content,
'https://zeroimg.pintuba.cc/',
'https://zeroimg.pintuba.cc/'
)
WHERE post_content LIKE '%https://zeroimg.pintuba.cc/%.m3u8%';
15、自动选择cf或frp路线
在主题的footer.php中的</body>前加以下代码
<script>
(function () {
if (!window.PTB_IMG_ROUTE || !window.PTB_IMG_ROUTE.hostMap) return;
const HOST_MAP = window.PTB_IMG_ROUTE.hostMap;
const DEBUG = window.PTB_IMG_ROUTE.debug || false;
const CF_THRESHOLD = window.PTB_IMG_ROUTE.cfThreshold || 650;
const COOKIE_NAME = 'img_route';
const COOKIE_TIME_NAME = 'img_route_time';
const EXPIRE_HOURS = 24;
const TEST_TIMEOUT = 2500;
const TEST_PATH = '/ping/ping.webp';
const INTERVAL_HOURS = 1; // ✅ 间隔1小时才再次检测
function log(...args) {
if (DEBUG) console.log('[IMG_ROUTE]', ...args);
}
function setCookie(name, value, hours) {
const d = new Date();
d.setTime(d.getTime() + (hours * 60 * 60 * 1000));
document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + d.toUTCString() + "; path=/";
}
function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for (let i = 0; i < ca.length; i++) {
let c = ca[i].trim();
if (c.indexOf(nameEQ) === 0) {
return decodeURIComponent(c.substring(nameEQ.length));
}
}
return null;
}
// ✅ 是否需要重新测速
function shouldRetest() {
const t = getCookie(COOKIE_TIME_NAME);
if (!t) return true;
const diff = Date.now() - parseInt(t, 10);
return diff > INTERVAL_HOURS * 60 * 60 * 1000; // 超过间隔1小时才重测
}
function testHost(host, timeout = TEST_TIMEOUT) {
return new Promise((resolve) => {
const img = new Image();
const start = performance.now();
let done = false;
const timer = setTimeout(() => {
if (!done) {
done = true;
resolve({ host, time: 999999, ok: false, reason: 'timeout' });
}
}, timeout);
img.onload = function () {
if (!done) {
done = true;
clearTimeout(timer);
resolve({ host, time: performance.now() - start, ok: true, reason: 'load' });
}
};
img.onerror = function () {
if (!done) {
done = true;
clearTimeout(timer);
resolve({ host, time: performance.now() - start, ok: false, reason: 'error' });
}
};
img.src = host + TEST_PATH + '?t=' + Date.now() + Math.random();
});
}
async function runTest() {
try {
const currentRoute = getCookie(COOKIE_NAME);
const needRetest = shouldRetest();
log('当前线路 Cookie:', currentRoute, '是否需要重测:', needRetest);
// ✅ 已有结果且未超过1小时间隔,不重复测速
if (currentRoute && !needRetest) {
if (currentRoute === 'cf') {
quickReplaceCurrentPageToCF(HOST_MAP);
attachImageFallbackToFRP(HOST_MAP);
}
return;
}
// 测 Cloudflare 是否够快
const cfTestHost = 'https://zeroimg.pintuba.cc';
const cfResult = await testHost(cfTestHost);
log('Cloudflare测速结果', cfResult, '阈值:', CF_THRESHOLD + 'ms');
let best = 'frp'; // 默认 FRP
if (cfResult.ok && cfResult.time < CF_THRESHOLD) {
best = 'cf';
}
setCookie(COOKIE_NAME, best, EXPIRE_HOURS);
setCookie(COOKIE_TIME_NAME, Date.now().toString(), EXPIRE_HOURS);
log('最终选择线路:', best);
// 当前页原本是 FRP,如果判定 CF,则当前页立即尽量切成 CF
if (best === 'cf') {
quickReplaceCurrentPageToCF(HOST_MAP);
attachImageFallbackToFRP(HOST_MAP);
}
} catch (e) {
log('测速异常', e);
}
}
/**
* 当前页面从 FRP 切到 Cloudflare
*/
function quickReplaceCurrentPageToCF(hostMap) {
function replaceUrl(url) {
if (!url) return url;
for (const [frpHost, cfHost] of Object.entries(hostMap)) {
if (url.indexOf(frpHost) === 0) {
return url.replace(frpHost, cfHost);
}
if (url.indexOf(frpHost) !== -1) {
return url.replaceAll(frpHost, cfHost);
}
}
return url;
}
document.querySelectorAll('img').forEach(img => {
if (img.src) img.src = replaceUrl(img.src);
if (img.srcset) img.srcset = replaceUrl(img.srcset);
if (img.dataset) {
if (img.dataset.src) img.dataset.src = replaceUrl(img.dataset.src);
if (img.dataset.lazySrc) img.dataset.lazySrc = replaceUrl(img.dataset.lazySrc);
if (img.dataset.original) img.dataset.original = replaceUrl(img.dataset.original);
if (img.dataset.srcset) img.dataset.srcset = replaceUrl(img.dataset.srcset);
if (img.dataset.thumb) img.dataset.thumb = replaceUrl(img.dataset.thumb);
if (img.dataset.image) img.dataset.image = replaceUrl(img.dataset.image);
if (img.dataset.bg) img.dataset.bg = replaceUrl(img.dataset.bg);
}
});
document.querySelectorAll('source').forEach(source => {
if (source.src) source.src = replaceUrl(source.src);
if (source.srcset) source.srcset = replaceUrl(source.srcset);
});
document.querySelectorAll('a').forEach(a => {
if (a.href) a.href = replaceUrl(a.href);
});
document.querySelectorAll('[style]').forEach(el => {
const style = el.getAttribute('style');
if (style) {
el.setAttribute('style', replaceUrl(style));
}
});
log('当前页面图片域名已从 FRP 切换为 Cloudflare');
}
/**
* Cloudflare 某张图失败时回退到 FRP
*/
function attachImageFallbackToFRP(hostMap) {
document.addEventListener('error', function (e) {
const target = e.target;
if (!target || target.tagName !== 'IMG') return;
const src = target.currentSrc || target.src;
if (!src) return;
for (const [frpHost, cfHost] of Object.entries(hostMap)) {
if (src.indexOf(cfHost) === 0 && !target.dataset.routeFallbackDone) {
target.dataset.routeFallbackDone = '1';
target.src = src.replace(cfHost, frpHost);
if (target.srcset) {
target.srcset = target.srcset.replaceAll(cfHost, frpHost);
}
log('Cloudflare图片加载失败,已回退到 FRP:', target.src);
break;
}
}
}, true);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', runTest);
} else {
runTest();
}
})();
</script>
在主题的func.php中加上以下代码:
/**
* 图片域名智能分流(适配“原始图片就是 FRP 域名”)
*
* 你的当前网站状态:
* - 原始图片域名是 b1 / b2 / b3
* - 默认继续走 FRP
* - 如果 Cloudflare 延迟 < 300ms,则切换为 zeroimg / zeroimg2 / zeroimg3
*/
// ===== 调试模式(测试时可改 true) =====
define('PTB_IMG_ROUTE_DEBUG', true);
/**
* 域名映射
* 左边:FRP 域名(你网站当前原始域名)
* 右边:Cloudflare 域名
*/
function ptb_get_img_host_map() {
return [
'https://b1.pintuba.cc:8' => 'https://zeroimg.pintuba.cc',
'https://b2.pintuba.cc:8' => 'https://zeroimg2.pintuba.cc',
'https://b3.pintuba.cc:8' => 'https://zeroimg3.pintuba.cc',
];
}
/**
* 判断是否启用
*/
function ptb_should_enable_img_route() {
if (is_admin()) return false;
if (defined('DOING_AJAX') && DOING_AJAX) return false;
if (defined('REST_REQUEST') && REST_REQUEST) return false;
if (is_feed()) return false;
return true;
}
/**
* 获取用户线路
* 返回:frp / cf
* 默认 frp
*/
function ptb_get_user_img_route() {
if (!isset($_COOKIE['img_route'])) {
return 'frp';
}
$route = sanitize_text_field($_COOKIE['img_route']);
if (!in_array($route, ['cf', 'frp'], true)) {
return 'frp';
}
return $route;
}
/**
* 开启输出缓冲
*/
function ptb_img_route_buffer_start() {
if (!ptb_should_enable_img_route()) {
return;
}
ob_start('ptb_img_route_replace_html');
}
add_action('template_redirect', 'ptb_img_route_buffer_start', 0);
/**
* 核心:替换页面输出中的图片域名
*
* 当前逻辑:
* - 默认 frp:不替换(保持原始 b1/b2/b3)
* - route=cf:把 b1/b2/b3 替换成 zeroimg/zeroimg2/zeroimg3
*/
function ptb_img_route_replace_html($html) {
$route = ptb_get_user_img_route();
$host_map = ptb_get_img_host_map();
if (empty($host_map) || !is_array($host_map)) {
return $html;
}
// 默认 FRP,不替换
if ($route !== 'cf') {
if (PTB_IMG_ROUTE_DEBUG) {
$html .= "\n<!-- img_route: frp -->";
}
return $html;
}
// 只有 CF 才替换成 Cloudflare 域名
foreach ($host_map as $frp_host => $cf_host) {
if (!empty($frp_host) && !empty($cf_host) && $frp_host !== $cf_host) {
$html = str_replace($frp_host, $cf_host, $html);
}
}
if (PTB_IMG_ROUTE_DEBUG) {
$html .= "\n<!-- img_route: cf -->";
}
return $html;
}
/**
* 输出给前端 JS 的配置
*/
function ptb_output_img_route_config() {
if (!ptb_should_enable_img_route()) {
return;
}
$host_map = ptb_get_img_host_map();
?>
<script>
window.PTB_IMG_ROUTE = {
hostMap: <?php echo wp_json_encode($host_map, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>,
debug: <?php echo PTB_IMG_ROUTE_DEBUG ? 'true' : 'false'; ?>,
cfThreshold: 650
};
</script>
<?php
}
add_action('wp_head', 'ptb_output_img_route_config', 1);
