7 Commits

Author SHA1 Message Date
浪子 57aeb81c62 1.2.3
fix 随机文章跳转
fix 无说说时无评论框的bug
2025-08-04 19:46:24 +08:00
浪子 4dcaefb291 1.2.3
使用评论实现说说的功能
2025-08-04 17:00:37 +08:00
浪子 0017693c81 1.2.2
增加一个随机阅读的独立页面
2025-08-02 14:29:25 +08:00
浪子 d268bd10bb 1.2.2
fix 标签
2025-08-02 14:01:18 +08:00
浪子 b416e58596 1.2.2
增加全局侧边栏的显示开关
2025-08-02 10:50:39 +08:00
浪子 5d67235be0 1.2.2
先解析短代码再解析markdown
2025-08-01 10:58:21 +08:00
浪子 134bb0d66c 1.2.1
增加了多条公告的功能 并修改了相关描述
2025-07-27 13:39:53 +08:00
17 changed files with 694 additions and 411 deletions
+2
View File
@@ -1 +1,3 @@
*.html
/.vercel
page-talks copy.php
+24 -1
View File
@@ -39,12 +39,14 @@
- 将表情短代码(如 :smile:)自动解析为图片表情,集成到主题评论内容输出中。
- 2025.07.08
- 1.1.6
- 修复头像区域背景的bug
- 优化php8.3兼容性
- 1.1.8
- 优化github链接的正则表达式,只解析主仓库链接(如 https://github.com/用户名/仓库名),不再解析子路径(如 /tree/、/blob/ 等)为卡片。
- 实现文章内容图片懒加载,自动将常见图片格式(jpg、jpeg、png、webp)的<img>标签替换为带懒加载属性的格式。
- 修正getPostCover函数,确保只从原始内容中提取第一张真实图片地址,不受懒加载替换影响,避免首页首图变成load.svg。
@@ -56,4 +58,25 @@
- 1.2.0
- 新增支持首页登录
- 新增支持首页登录
- 2025.08.02
- 1.2.2
- 增加侧边栏显示的全局开关
- 修复代码块中的短代码解析问题
- 新增一个随机文章阅读的独立页面
- 2025.08.03
- 1.2.3
- 修复随机页面在 PJAX 模式下的缓存问题
- 在随机页面添加缓存控制头,防止 PJAX 缓存
- 在 JavaScript 中添加随机页面检测,强制刷新确保获取新文章
- 修复后端登录验证问题,确保密码错误时返回正确的错误信息
- 重新设计随机页面模板,添加完整的页面结构和加载动画
- 修复随机页面重定向问题,使用 JavaScript 跳转避免缓存
- 修复随机页面 JavaScript 错误,移除不存在的 InstantClick.preload 方法调用
- 优化随机页面跳转逻辑,确保在 PJAX 模式下也能正常自动跳转
+14 -4
View File
@@ -3,10 +3,16 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit;
$this->need('header.php');
?>
<div class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div class="col-lg-8 col-md-12 animated fadeInLeft ">
<div class="animated fadeInLeft ">
<?php else: ?>
<div class="col-lg-12 col-md-12">
<div class="row box-plr15">
<?php endif; ?>
<div> <!--文章列表-->
<div id="posts">
<?php if ($this->options->listmodel): ?>
<div class=" mr-0 ml-0">
<?php while ($this->next()): ?>
<?php
@@ -61,8 +67,8 @@ $coverImage = getPostCover($this->content, $this->cid);
</article>
<?php endwhile; ?>
</div>
<div class="mt20 p-flex-s-right" data-no-instant>
<?php $this->pageNav('&laquo;', '&raquo;', 1, '...', array(
<div class="mt20 p-flex-s-right" data-no-instant>
<?php $this->pageNav('&laquo;', '&raquo;', 1, '...', array(
'wrapTag' => 'ul',
'wrapClass' => 'pagination comment-ajax-load',
'itemTag' => 'li',
@@ -71,11 +77,15 @@ $coverImage = getPostCover($this->content, $this->cid);
'prevClass' => 'prev',
'nextClass' => 'next'
)); ?>
</div>
</div>
<?php else: ?>
<?php $this->need('card.php'); ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
+1 -1
View File
@@ -171,7 +171,7 @@
<?php endif; ?>
</div>
<div class="t-sm c-sub">
<span><?php $comments->date('Y-m-d H:i:s'); ?></span>
<span><?php echo friendly_date($comments->created); ?></span>
<a rel="nofollow" class="hide-info animated bounceIn c-sub-a t-sm ml-1 comment-reply" href="javascript:void(0);" data-coid="<?php echo $comments->coid; ?>"><span class="comment-reply-text"><i class="fa fa-share-from-square"></i>回复</span></a>
</div>
</div>
+1 -1
View File
@@ -68,7 +68,7 @@
&copy; <?php echo date('Y'); ?> <a href="<?php $this->options->siteUrl(); ?>"><?php $this->options->title(); ?></a>
<div class="fs12 mt10 c-sub">
<span> &nbsp;Theme by
<a target="_blank" class="c-sub" title="Puock v2.8.14" href="https://github.com/jkjoy/typecho-theme-puock">Puock</a>
<a target="_blank" class="c-sub" title="Puock v1.2.2" href="https://github.com/jkjoy/typecho-theme-puock">Puock</a>
</span>
<span> &nbsp;Powered by
<a target="_blank" class="c-sub" title="Typecho" href="https://typecho.org">Typecho</a> <p><a target="_blank" class="c-sub" title="老孙博客" href="https://imsun.org">老孙博客</a>制作</p>
+283 -210
View File
@@ -33,13 +33,13 @@ function themeConfig($form)
$form->addInput($cmsmodel);
$friendlink = new Typecho_Widget_Helper_Form_Element_Radio('friendlink',
array('0'=> _t('否'), '1'=> _t('是')),
'0', _t('友情链接'), _t('选择"是"在首页显示友情链接。开启前请安装"Links"插件。链接分类需设置为home,默认关闭'));
'0', _t('友情链接'), _t('选择"是"在首页显示友情链接。开启前请安装"Links"插件。链接分类需设置为<b>home</b>,默认关闭'));
$form->addInput($friendlink);
$social = new Typecho_Widget_Helper_Form_Element_Radio('social',
array('0'=> _t('否'), '1'=> _t('是')),
'0', _t('社交分享显示'), _t('选择"是"在文章页面显示社交分享。需要搭配插件使用,默认关闭'));
$form->addInput($social);
$gonggao = new Typecho_Widget_Helper_Form_Element_Textarea('gonggao', NULL, NULL, _t('站点公告'), _t('支持HTML'));
$gonggao = new Typecho_Widget_Helper_Form_Element_Textarea('gonggao', NULL, NULL, _t('站点公告'), _t('<b style=color:red>使用格式: </b><b>标题|链接|图标</b><br>多条公告回车分隔.链接和图标可以为空.图标使用Font Awesome,如: fa-regular fa-bell'));
$form->addInput($gonggao);
$adlisttop = new Typecho_Widget_Helper_Form_Element_Textarea('adlisttop', NULL, NULL, _t('文章列表上方广告位'), _t('支持HTML'));
$form->addInput($adlisttop);
@@ -51,14 +51,24 @@ function themeConfig($form)
$form->addInput($articlemid);
$articlefoot = new Typecho_Widget_Helper_Form_Element_Textarea('articlefoot', NULL, NULL, _t('文章页底部广告位'), _t('支持HTML'));
$form->addInput($articlefoot);
$addhead = new Typecho_Widget_Helper_Form_Element_Textarea('addhead', NULL, NULL, _t('网站验证代码'), _t('若开启无刷新加载,请在标签上加上data-instant属性'));
$addhead = new Typecho_Widget_Helper_Form_Element_Textarea('addhead', NULL, '<link rel="stylesheet" href="https://cdnjs.imsun.org/lxgw-wenkai-screen-webfont/style.css"></link>
<style>* {font-family: -apple-system, BlinkMacSystemFont,"LXGW WenKai Screen", sans-serif;}</style>', _t('网站验证代码'), _t('若开启无刷新加载,请在标签上加上data-instant属性'));
$form->addInput($addhead);
$tongji = new Typecho_Widget_Helper_Form_Element_Textarea('tongji', NULL, NULL, _t('网站统计代码'), _t('支持HTML'));
$tongji = new Typecho_Widget_Helper_Form_Element_Textarea('tongji', NULL, '<script async defer src="https://0tz.top/tracker.js" data-website-id="Puock"></script>', _t('网站统计代码'), _t('支持HTML'));
$form->addInput($tongji);
$footerinfo = new Typecho_Widget_Helper_Form_Element_Textarea('footerinfo', NULL, NULL, _t('底部关于我们'), _t('支持HTML'));
$footerinfo = new Typecho_Widget_Helper_Form_Element_Textarea('footerinfo', NULL, '<a href="/feed" target="_blank"><i class="fa-solid fa-rss fa-2x"></i></a>
<a href="https://jiong.us/@sun" target="_blank"><i class="fa-brands fa-mastodon fa-2x"></i></a>
<a href="https://discord.gg/RUUcPEQKNt" target="_blank"><i class="fa-brands fa-discord fa-2x"></i></a>
<a href="https://t.me/imsunpw" target="_blank"><i class="fa-brands fa-telegram fa-2x"></i></a>
<a href="mailto:imsunpw@gmail.com" target="_blank"><i class="fa-solid fa-envelope fa-2x"></i></a>
<a href="/sitemap.xml" target="_blank"><i class="fa-solid fa-sitemap fa-2x"></i></a>', _t('底部关于我们'), _t('支持HTML'));
$form->addInput($footerinfo);
$footercopyright = new Typecho_Widget_Helper_Form_Element_Textarea('footercopyright', NULL, NULL, _t('底部版权信息'), _t('支持HTML'));
$footercopyright = new Typecho_Widget_Helper_Form_Element_Textarea('footercopyright', NULL, '<b>版权所有 转载请注明出处</b>', _t('底部版权信息'), _t('支持HTML'));
$form->addInput($footercopyright);
$showsidebar = new Typecho_Widget_Helper_Form_Element_Radio('showsidebar',
array('0'=> _t('关闭'), '1'=> _t('显示')),
'0', _t('全局侧边栏显示'), _t('<p style=color:red>注意!</p>如果选择关闭侧边栏则下方的侧边栏显示设置将无效'));
$form->addInput($showsidebar);
$sidebarBlock = new \Typecho\Widget\Helper\Form\Element\Checkbox(
'sidebarBlock',
[
@@ -72,7 +82,6 @@ function themeConfig($form)
['ShowSearch', 'ShowAdmin', 'ShowRecentPosts', 'ShowHotPosts', 'ShowRecentComments', 'ShowTags'],
_t('侧边栏显示')
);
$form->addInput($sidebarBlock->multiMode());
}
@@ -83,6 +92,16 @@ function themeFields($layout) {
$layout->addItem($cover);
}
/** 头像镜像加速全局设置
* @param $email
* @param $size
* @param $default
* @return string
*/
$options = Typecho_Widget::widget('Widget_Options');
$gravatarPrefix = empty($options->cnavatar) ? 'https://cravatar.cn/avatar/' : $options->cnavatar;
define('__TYPECHO_GRAVATAR_PREFIX__', $gravatarPrefix);
/*
* 文章浏览数统计
*/
@@ -313,92 +332,93 @@ function getBrowsersInfo($userAgent) {
"version" => "",
"device" => "PC"
];
$match = [
// 浏览器 - 国外浏览器
"Safari" => strstr($userAgent, 'Safari') != false ,
"Chrome" => strstr($userAgent, 'Chrome') != false || strstr($userAgent, 'CriOS') != false ,
"IE" => strstr($userAgent, 'MSIE') != false || strstr($userAgent, 'Trident') != false ,
"Edge" => strstr($userAgent, 'Edge') != false || strstr($userAgent, 'Edg/') != false || strstr($userAgent, 'EdgA') != false || strstr($userAgent, 'EdgiOS') != false,
"Firefox" => strstr($userAgent, 'Firefox') != false || strstr($userAgent, 'FxiOS') != false ,
"Firefox Focus" => strstr($userAgent, 'Focus') != false,
"Chromium" => strstr($userAgent,'Chromium') != false,
"Opera" => strstr($userAgent,'Opera') != false || strstr($userAgent,'OPR') != false,
"Vivaldi" => strstr($userAgent,'Vivaldi') != false,
"Yandex" => strstr($userAgent,'YaBrowser') != false,
"Arora" => strstr($userAgent,'Arora') != false,
"Lunascape" => strstr($userAgent,'Lunascape') != false,
"QupZilla" => strstr($userAgent,'QupZilla') != false,
"Coc Coc" => strstr($userAgent,'coc_coc_browser') != false,
"Kindle" => strstr($userAgent,'Kindle') != false || strstr($userAgent,'Silk/') != false,
"Iceweasel" => strstr($userAgent,'Iceweasel') != false,
"Konqueror" => strstr($userAgent,'Konqueror') != false,
"Iceape" => strstr($userAgent,'Iceape') != false,
"SeaMonkey" => strstr($userAgent,'SeaMonkey') != false,
"Epiphany" => strstr($userAgent,'Epiphany') != false,
"Safari" => strstr($userAgent, 'Safari') !== false,
"Chrome" => strstr($userAgent, 'Chrome') !== false || strstr($userAgent, 'CriOS') !== false,
"IE" => strstr($userAgent, 'MSIE') !== false || strstr($userAgent, 'Trident') !== false,
"Edge" => strstr($userAgent, 'Edge') !== false || strstr($userAgent, 'Edg/') !== false || strstr($userAgent, 'EdgA') !== false || strstr($userAgent, 'EdgiOS') !== false,
"Firefox" => strstr($userAgent, 'Firefox') !== false || strstr($userAgent, 'FxiOS') !== false,
"Firefox Focus" => strstr($userAgent, 'Focus') !== false,
"Chromium" => strstr($userAgent, 'Chromium') !== false,
"Opera" => strstr($userAgent, 'Opera') !== false || strstr($userAgent, 'OPR') !== false,
"Vivaldi" => strstr($userAgent, 'Vivaldi') !== false,
"Yandex" => strstr($userAgent, 'YaBrowser') !== false,
"Arora" => strstr($userAgent, 'Arora') !== false,
"Lunascape" => strstr($userAgent, 'Lunascape') !== false,
"QupZilla" => strstr($userAgent, 'QupZilla') !== false,
"Coc Coc" => strstr($userAgent, 'coc_coc_browser') !== false,
"Kindle" => strstr($userAgent, 'Kindle') !== false || strstr($userAgent, 'Silk/') !== false,
"Iceweasel" => strstr($userAgent, 'Iceweasel') !== false,
"Konqueror" => strstr($userAgent, 'Konqueror') !== false,
"Iceape" => strstr($userAgent, 'Iceape') !== false,
"SeaMonkey" => strstr($userAgent, 'SeaMonkey') !== false,
"Epiphany" => strstr($userAgent, 'Epiphany') !== false,
// 浏览器 - 国内浏览器
"360" => strstr($userAgent,'QihooBrowser') != false || strstr($userAgent,'QHBrowser') != false,
"360EE" => strstr($userAgent,'360EE') != false,
"360SE" => strstr($userAgent,'360SE') != false,
"UC" => strstr($userAgent,'UCBrowser') != false || strstr($userAgent,' UBrowser') != false || strstr($userAgent,'UCWEB') != false,
"QQBrowser" => strstr($userAgent,'QQBrowser') != false,
"QQ" => strstr($userAgent,'QQ/') != false,
"Baidu" => strstr($userAgent,'Baidu') != false || strstr($userAgent,'BIDUBrowser') != false || strstr($userAgent,'baidubrowser') != false || strstr($userAgent,'baiduboxapp') != false || strstr($userAgent,'BaiduHD') != false,
"Maxthon" => strstr($userAgent,'Maxthon') != false,
"Sogou" => strstr($userAgent,'MetaSr') != false || strstr($userAgent,'Sogou') != false,
"Liebao" => strstr($userAgent,'LBBROWSER') != false || strstr($userAgent,'LieBaoFast') != false,
"2345Explorer" => strstr($userAgent,'2345Explorer') != false || strstr($userAgent,'Mb2345Browser') != false || strstr($userAgent,'2345chrome') != false,
"115Browser" => strstr($userAgent,'115Browser') != false,
"TheWorld" => strstr($userAgent,'TheWorld') != false,
"Quark" => strstr($userAgent,'Quark') != false,
"Qiyu" => strstr($userAgent,'Qiyu') != false,
"360" => strstr($userAgent, 'QihooBrowser') !== false || strstr($userAgent, 'QHBrowser') !== false,
"360EE" => strstr($userAgent, '360EE') !== false,
"360SE" => strstr($userAgent, '360SE') !== false,
"UC" => strstr($userAgent, 'UCBrowser') !== false || strstr($userAgent, ' UBrowser') !== false || strstr($userAgent, 'UCWEB') !== false,
"QQBrowser" => strstr($userAgent, 'QQBrowser') !== false,
"QQ" => strstr($userAgent, 'QQ/') !== false,
"Baidu" => strstr($userAgent, 'Baidu') !== false || strstr($userAgent, 'BIDUBrowser') !== false || strstr($userAgent, 'baidubrowser') !== false || strstr($userAgent, 'baiduboxapp') !== false || strstr($userAgent, 'BaiduHD') !== false,
"Maxthon" => strstr($userAgent, 'Maxthon') !== false,
"Sogou" => strstr($userAgent, 'MetaSr') !== false || strstr($userAgent, 'Sogou') !== false,
"Liebao" => strstr($userAgent, 'LBBROWSER') !== false || strstr($userAgent, 'LieBaoFast') !== false,
"2345Explorer" => strstr($userAgent, '2345Explorer') !== false || strstr($userAgent, 'Mb2345Browser') !== false || strstr($userAgent, '2345chrome') !== false,
"115Browser" => strstr($userAgent, '115Browser') !== false,
"TheWorld" => strstr($userAgent, 'TheWorld') !== false,
"Quark" => strstr($userAgent, 'Quark') !== false,
"Qiyu" => strstr($userAgent, 'Qiyu') !== false,
// 浏览器 - 手机厂商
"XiaoMi" => strstr($userAgent,'MiuiBrowser') != false,
"Huawei" => strstr($userAgent,'HuaweiBrowser') != false || strstr($userAgent,'HUAWEI/') != false || strstr($userAgent,'HONOR') != false || strstr($userAgent,'HBPC/') != false,
"Vivo" => strstr($userAgent,'VivoBrowser') != false,
"OPPO" => strstr($userAgent,'HeyTapBrowser') != false,
"XiaoMi" => strstr($userAgent, 'MiuiBrowser') !== false,
"Huawei" => strstr($userAgent, 'HuaweiBrowser') !== false || strstr($userAgent, 'HUAWEI/') !== false || strstr($userAgent, 'HONOR') !== false || strstr($userAgent, 'HBPC/') !== false,
"Vivo" => strstr($userAgent, 'VivoBrowser') !== false,
"OPPO" => strstr($userAgent, 'HeyTapBrowser') !== false,
// 浏览器 - 客户端
"Wechat" => strstr($userAgent,'MicroMessenger') != false,
"WechatWork" => strstr($userAgent,'wxwork/') != false,
"Taobao" => strstr($userAgent,'AliApp(TB') != false,
"Alipay" => strstr($userAgent,'AliApp(AP') != false,
"Weibo" => strstr($userAgent,'Weibo') != false,
"Douban" => strstr($userAgent,'com.douban.frodo') != false,
"Suning" => strstr($userAgent,'SNEBUY-APP') != false,
"iQiYi" => strstr($userAgent,'IqiyiApp') != false,
"DingTalk" => strstr($userAgent,'DingTalk') != false,
"Douyin" => strstr($userAgent,'aweme') != false,
"Wechat" => strstr($userAgent, 'MicroMessenger') !== false,
"WechatWork" => strstr($userAgent, 'wxwork/') !== false,
"Taobao" => strstr($userAgent, 'AliApp(TB') !== false,
"Alipay" => strstr($userAgent, 'AliApp(AP') !== false,
"Weibo" => strstr($userAgent, 'Weibo') !== false,
"Douban" => strstr($userAgent, 'com.douban.frodo') !== false,
"Suning" => strstr($userAgent, 'SNEBUY-APP') !== false,
"iQiYi" => strstr($userAgent, 'IqiyiApp') !== false,
"DingTalk" => strstr($userAgent, 'DingTalk') !== false,
"Douyin" => strstr($userAgent, 'aweme') !== false,
// 系统或平台
"Windows" => strstr($userAgent,'Windows') != false,
"Linux" => strstr($userAgent,'Linux') != false || strstr($userAgent,'X11') != false,
"Mac OS" => strstr($userAgent,'Macintosh') != false,
"Android" => strstr($userAgent,'Android') != false || strstr($userAgent,'Adr') != false,
"HarmonyOS" => strstr($userAgent,'HarmonyOS') != false,
"Ubuntu" => strstr($userAgent,'Ubuntu') != false,
"FreeBSD" => strstr($userAgent,'FreeBSD') != false,
"Debian" => strstr($userAgent,'Debian') != false,
"Windows Phone" => strstr($userAgent,'IEMobile') != false || strstr($userAgent,'Windows Phone') != false,
"BlackBerry" => strstr($userAgent,'BlackBerry') != false || strstr($userAgent,'RIM') != false,
"MeeGo" => strstr($userAgent,'MeeGo') != false,
"Symbian" => strstr($userAgent,'Symbian') != false,
"iOS" => strstr($userAgent,'like Mac OS X') != false,
"Chrome OS" => strstr($userAgent,'CrOS') != false,
"WebOS" => strstr($userAgent,'hpwOS') != false,
"Windows" => strstr($userAgent, 'Windows') !== false,
"Linux" => strstr($userAgent, 'Linux') !== false || strstr($userAgent, 'X11') !== false,
"Mac OS" => strstr($userAgent, 'Macintosh') !== false,
"Android" => strstr($userAgent, 'Android') !== false || strstr($userAgent, 'Adr') !== false,
"HarmonyOS" => strstr($userAgent, 'HarmonyOS') !== false,
"Ubuntu" => strstr($userAgent, 'Ubuntu') !== false,
"FreeBSD" => strstr($userAgent, 'FreeBSD') !== false,
"Debian" => strstr($userAgent, 'Debian') !== false,
"Windows Phone" => strstr($userAgent, 'IEMobile') !== false || strstr($userAgent, 'Windows Phone') !== false,
"BlackBerry" => strstr($userAgent, 'BlackBerry') !== false || strstr($userAgent, 'RIM') !== false,
"MeeGo" => strstr($userAgent, 'MeeGo') !== false,
"Symbian" => strstr($userAgent, 'Symbian') !== false,
"iOS" => strstr($userAgent, 'like Mac OS X') !== false,
"Chrome OS" => strstr($userAgent, 'CrOS') !== false,
"WebOS" => strstr($userAgent, 'hpwOS') !== false,
// 设备
"Mobile" => strstr($userAgent,'Mobi') != false || strstr($userAgent,'iPh') != false || strstr($userAgent,'480') != false,
"Tablet" => strstr($userAgent,'Tablet') != false || strstr($userAgent,'Pad') != false || strstr($userAgent,'Nexus 7') != false,
"Mobile" => strstr($userAgent, 'Mobi') !== false || strstr($userAgent, 'iPh') !== false || strstr($userAgent, '480') !== false,
"Tablet" => strstr($userAgent, 'Tablet') !== false || strstr($userAgent, 'Pad') !== false || strstr($userAgent, 'Nexus 7') !== false,
];
// 部分修正 | 因typecho评论数据只存储了ua的信息,所以不能完全进行修正尤其是360相关浏览器
// 部分修正
if ($match['Baidu'] && $match['Opera']) $match['Baidu'] = false;
if ($match['iOS']) $match['Safari'] = true;
// 基本信息
$baseInfo = [
"browser" => [
'Safari', 'Chrome', 'Edge', 'IE', 'Firefox', 'Firefox Focus', 'Chromium',
'Opera', 'Vivaldi', 'Yandex', 'Arora', 'Lunascape','QupZilla', 'Coc Coc',
'Kindle', 'Iceweasel', 'Konqueror', 'Iceape','SeaMonkey', 'Epiphany', 'XiaoMi',
'Vivo', 'OPPO', '360', '360SE','360EE', 'UC', 'QQBrowser', 'QQ', 'Huawei', 'Baidu',
'Opera', 'Vivaldi', 'Yandex', 'Arora', 'Lunascape', 'QupZilla', 'Coc Coc',
'Kindle', 'Iceweasel', 'Konqueror', 'Iceape', 'SeaMonkey', 'Epiphany', 'XiaoMi',
'Vivo', 'OPPO', '360', '360SE', '360EE', 'UC', 'QQBrowser', 'QQ', 'Huawei', 'Baidu',
'Maxthon', 'Sogou', 'Liebao', '2345Explorer', '115Browser', 'TheWorld', 'Quark', 'Qiyu',
'Wechat', 'WechatWork', 'Taobao', 'Alipay', 'Weibo', 'Douban', 'Suning', 'iQiYi', 'DingTalk', 'Douyin'
],
@@ -409,17 +429,15 @@ function getBrowsersInfo($userAgent) {
],
"device" => ['Mobile', 'Tablet'],
];
foreach ($baseInfo as $k => $v) {
foreach ($v as $xv) {
if ($match[$xv]) $deviceInfo[$k] = $xv;
}
}
// 操作系统版本信息
$windowsVersion = [
'10' => "10",
'6.4' => '10',
'6.3' => '8.1',
'6.2' => '8',
'6.1' => '7',
@@ -428,29 +446,58 @@ function getBrowsersInfo($userAgent) {
'5.1' => 'XP',
'5.0' => '2000',
];
$wv = pregMatch("/^Mozilla\/\d.0 \(Windows NT ([\d.]+)[;)].*$/", $userAgent);
// Extract Windows NT version and build number
if (preg_match("/\(Windows NT ([\d.]+)(?:;[^)]*Build\/(\d+))?(?:;[^)]*)?\)/i", $userAgent, $matches)) {
$ntVersion = $matches[1];
$buildNumber = isset($matches[2]) ? (int)$matches[2] : 0;
if ($ntVersion === '10.0') {
// Check build number for Windows 11
if ($buildNumber >= 22000) {
$deviceInfo['systemVersion'] = '11';
} else {
// Fallback heuristic: Check Edge version (Windows 11 requires Edge >= 91)
if ($deviceInfo['browser'] === 'Edge' && preg_match("/Edg\/([\d.]+)/", $userAgent, $edgeMatch)) {
$edgeVersion = (float)$edgeMatch[1];
if ($edgeVersion >= 91) {
$deviceInfo['systemVersion'] = '11'; // Assume Windows 11 for modern Edge
} else {
$deviceInfo['systemVersion'] = '10';
}
} else {
$deviceInfo['systemVersion'] = '10';
// Log ambiguous case for debugging
error_log("Ambiguous Windows version (NT 10.0, no build number): $userAgent");
}
}
} else {
$deviceInfo['systemVersion'] = $windowsVersion[$ntVersion] ?? $ntVersion;
}
}
$HarmonyOSVersion = [
10 => "2",
12 => "3"
];
$systemVersion = [
"Windows" => $windowsVersion[$wv] ?? $wv,
"Android" => pregMatch("/^.*Android ([\d.]+);.*$/", $userAgent),
"HarmonyOS" => $HarmonyOSVersion[pregMatch("/^Mozilla.*Android ([\d.]+)[;)].*$/", $userAgent)] ?? '',
"iOS" => preg_replace("/_/", '.', pregMatch("/^.*OS ([\d_]+) like.*$/", $userAgent)),
"Debian" => pregMatch("/^.*Debian\/([\d.]+).*$/", $userAgent),
"Windows Phone" => pregMatch("/^.*Windows Phone( OS)? ([\d.]+);.*$/", $userAgent),
"Mac OS" => preg_replace("/_/", '.',pregMatch("/^.*Mac OS X ([\d_]+).*$/", $userAgent)),
"WebOS" => pregMatch("/^.*hpwOS\/([\d.]+);.*$/", $userAgent)
"Windows" => $deviceInfo['systemVersion'], // Already set above
"Android" => preg_match("/Android ([\d.]+);/", $userAgent, $matches) ? $matches[1] : '',
"HarmonyOS" => preg_match("/Android ([\d.]+)[;)]/", $userAgent, $matches) ? ($HarmonyOSVersion[(int)$matches[1]] ?? '') : '',
"iOS" => preg_match("/OS ([\d_]+) like/", $userAgent, $matches) ? str_replace('_', '.', $matches[1]) : '',
"Debian" => preg_match("/Debian\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Windows Phone" => preg_match("/Windows Phone( OS)? ([\d.]+);/", $userAgent, $matches) ? $matches[2] : '',
"Mac OS" => preg_match("/Mac OS X ([\d_]+)/", $userAgent, $matches) ? str_replace('_', '.', $matches[1]) : '',
"WebOS" => preg_match("/hpwOS\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''
];
if (isset($deviceInfo['system']) && $deviceInfo['system'] !== "" && isset($systemVersion[$deviceInfo['system']])) {
$deviceInfo['systemVersion'] = $systemVersion[$deviceInfo['system']];
if ($deviceInfo['systemVersion'] == $userAgent) {
$deviceInfo['systemVersion'] = '';
}
$deviceInfo['systemVersion'] = $systemVersion[$deviceInfo['system']];
if ($deviceInfo['systemVersion'] == $userAgent) {
$deviceInfo['systemVersion'] = '';
}
}
// 浏览器版本信息
$browsers_360SE = [
108 => '14.0',
@@ -475,7 +522,7 @@ function getBrowsersInfo($userAgent) {
30 => '7.5',
];
$browsers_liebao = [
57 => '6.5',
57 => '6.5',
49 => '6.0',
46 => '5.9',
42 => '5.3',
@@ -487,82 +534,81 @@ function getBrowsersInfo($userAgent) {
$browsers_2345 = [
69 => '10.0',
55 => '9.9',
69 => '10.0',
55 => '9.9',
69 => '10.0',
55 => '9.9'
];
$chromeVersion = pregMatch('/^.*Chrome\/([\d]+).*$/', $userAgent);
$chromeVersion = preg_match('/Chrome\/([\d]+)/', $userAgent, $matches) ? (int)$matches[1] : 0;
$browsersVersion = [
"Safari" => pregMatch("/^.*Version\/([\d.]+).*$/", $userAgent),
"Chrome" => pregMatch("/^.*Chrome\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*CriOS\/([\d.]+).*$/", $userAgent),
"IE" => pregMatch("/^.*MSIE ([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*rv:([\d.]+).*$/", $userAgent),
"Edge" => pregMatch("/^.*Edge\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*Edg\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*EdgA\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*EdgiOS\/([\d.]+).*$/", $userAgent),
"Firefox" => pregMatch("/^.*Firefox\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*FxiOS\/([\d.]+).*$/", $userAgent),
"Firefox Focus" => pregMatch("/^.*Focus\/([\d.]+).*$/", $userAgent),
"Chromium" => pregMatch("/^.*Chromium\/([\d.]+).*$/", $userAgent),
"Opera" => pregMatch("/^.*Opera\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*OPR\/([\d.]+).*$/", $userAgent),
"Vivaldi" => pregMatch("/^.*Vivaldi\/([\d.]+).*$/", $userAgent),
"Yandex" => pregMatch("/^.*YaBrowser\/([\d.]+).*$/", $userAgent),
"Brave" => pregMatch("/^.*Chrome\/([\d.]+).*$/", $userAgent),
"Arora" => pregMatch("/^.*Arora\/([\d.]+).*$/", $userAgent),
"Lunascape" => pregMatch("/^.*Lunascape[\/\s]([\d.]+).*$/", $userAgent),
"QupZilla" => pregMatch("/^.*QupZilla[\/\s]([\d.]+).*$/", $userAgent),
"Coc Coc" => pregMatch("/^.*coc_coc_browser\/([\d.]+).*$/", $userAgent),
"Kindle" => pregMatch("/^.*Version\/([\d.]+).*$/", $userAgent),
"Iceweasel" => pregMatch("/^.*Iceweasel\/([\d.]+).*$/", $userAgent),
"Konqueror" => pregMatch("/^.*Konqueror\/([\d.]+).*$/", $userAgent),
"Iceape" => pregMatch("/^.*Iceape\/([\d.]+).*$/", $userAgent),
"SeaMonkey" => pregMatch("/^.*SeaMonkey\/([\d.]+).*$/", $userAgent),
"Epiphany" => pregMatch("/^.*Epiphany\/([\d.]+).*$/", $userAgent),
"360" => pregMatch("/^.*QihooBrowser(HD)?\/([\d.]+).*$/", $userAgent),
"Maxthon" => pregMatch("/^.*Maxthon\/([\d.]+).*$/", $userAgent),
"QQBrowser" => pregMatch("/^.*QQBrowser\/([\d.]+).*$/", $userAgent),
"QQ" => pregMatch("/^.*QQ\/([\d.]+).*$/", $userAgent),
"Baidu" => pregMatch("/^.*BIDUBrowser[\s\/]([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*baiduboxapp\/([\d.]+).*$/", $userAgent),
"UC" => pregMatch("/^.*UC?Browser\/([\d.]+).*$/", $userAgent),
"Sogou" => pregMatch("/^.*SE ([\d.X]+).*$/", $userAgent) ?? pregMatch("/^.*SogouMobileBrowser\/([\d.]+).*$/", $userAgent),
"115Browser" => pregMatch("/^.*115Browser\/([\d.]+).*$/", $userAgent),
"TheWorld" => pregMatch("/^.*TheWorld ([\d.]+).*$/", $userAgent),
"XiaoMi" => pregMatch("/^.*MiuiBrowser\/([\d.]+).*$/", $userAgent),
"Vivo" => pregMatch("/^.*VivoBrowser\/([\d.]+).*$/", $userAgent),
"OPPO" => pregMatch("/^.*HeyTapBrowser\/([\d.]+).*$/", $userAgent),
"Quark" => pregMatch("/^.*Quark\/([\d.]+).*$/", $userAgent),
"Qiyu" => pregMatch("/^.*Qiyu\/([\d.]+).*$/", $userAgent),
"Wechat" => pregMatch("/^.*MicroMessenger\/([\d.]+).*$/", $userAgent),
"WechatWork" => pregMatch("/^.*wxwork\/([\d.]+).*$/", $userAgent),
"Taobao" => pregMatch("/^.*AliApp\(TB\/([\d.]+).*$/", $userAgent),
"Alipay" => pregMatch("/^.*AliApp\(AP\/([\d.]+).*$/", $userAgent),
"Weibo" => pregMatch("/^.*weibo__([\d.]+).*$/", $userAgent),
"Douban" => pregMatch("/^.*com.douban.frodo\/([\d.]+).*$/", $userAgent),
"Suning" => pregMatch("/^.*SNEBUY-APP([\d.]+).*$/", $userAgent),
"iQiYi" => pregMatch("/^.*IqiyiVersion\/([\d.]+).*$/", $userAgent),
"DingTalk" => pregMatch("/^.*DingTalk\/([\d.]+).*$/", $userAgent),
"Douyin" => pregMatch("/^.*app_version\/([\d.]+).*$/", $userAgent),
"Huawei" => pregMatch("/^.*Version\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*HuaweiBrowser\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*HBPC\/([\d.]+).*$/", $userAgent),
"360SE" => $browsers_360SE[$chromeVersion] ?? '',
"360EE" => $browsers_360EE[$chromeVersion] ?? '',
"Liebao" => pregMatch("/^.*LieBaoFast\/([\d.]+).*$/", $userAgent) ?? $browsers_liebao[$chromeVersion],
"2345Explorer" => $browsers_2345[$chromeVersion] ?? pregMatch("/^.*2345Explorer\/([\d.]+).*$/", $userAgent) ?? pregMatch("/^.*Mb2345Browser\/([\d.]+).*$/", $userAgent),
"Safari" => preg_match("/Version\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Chrome" => preg_match("/Chrome\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/CriOS\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"IE" => preg_match("/MSIE ([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/rv:([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"Edge" => preg_match("/Edge\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/Edg\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/EdgA\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/EdgiOS\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''))),
"Firefox" => preg_match("/Firefox\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/FxiOS\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"Firefox Focus" => preg_match("/Focus\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Chromium" => preg_match("/Chromium\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Opera" => preg_match("/Opera\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/OPR\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"Vivaldi" => preg_match("/Vivaldi\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Yandex" => preg_match("/YaBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Brave" => preg_match("/Chrome\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Arora" => preg_match("/Arora\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Lunascape" => preg_match("/Lunascape[\/\s]([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"QupZilla" => preg_match("/QupZilla[\/\s]([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Coc Coc" => preg_match("/coc_coc_browser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Kindle" => preg_match("/Version\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Iceweasel" => preg_match("/Iceweasel\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Konqueror" => preg_match("/Konqueror\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Iceape" => preg_match("/Iceape\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"SeaMonkey" => preg_match("/SeaMonkey\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Epiphany" => preg_match("/Epiphany\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"360" => preg_match("/QihooBrowser(HD)?\/([\d.]+)/", $userAgent, $matches) ? $matches[2] : '',
"Maxthon" => preg_match("/Maxthon\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"QQBrowser" => preg_match("/QQBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"QQ" => preg_match("/QQ\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Baidu" => preg_match("/BIDUBrowser[\s\/]([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/baiduboxapp\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"UC" => preg_match("/UC?Browser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Sogou" => preg_match("/SE ([\d.X]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/SogouMobileBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : ''),
"115Browser" => preg_match("/115Browser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"TheWorld" => preg_match("/TheWorld ([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"XiaoMi" => preg_match("/MiuiBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Vivo" => preg_match("/VivoBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"OPPO" => preg_match("/HeyTapBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Quark" => preg_match("/Quark\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Qiyu" => preg_match("/Qiyu\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Wechat" => preg_match("/MicroMessenger\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"WechatWork" => preg_match("/wxwork\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Taobao" => preg_match("/AliApp\(TB\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Alipay" => preg_match("/AliApp\(AP\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Weibo" => preg_match("/weibo__([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Douban" => preg_match("/com.douban.frodo\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Suning" => preg_match("/SNEBUY-APP([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"iQiYi" => preg_match("/IqiyiVersion\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"DingTalk" => preg_match("/DingTalk\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Douyin" => preg_match("/app_version\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '',
"Huawei" => preg_match("/Version\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/HuaweiBrowser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/HBPC\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : '')),
"360SE" => isset($browsers_360SE[$chromeVersion]) ? $browsers_360SE[$chromeVersion] : '',
"360EE" => isset($browsers_360EE[$chromeVersion]) ? $browsers_360EE[$chromeVersion] : '',
"Liebao" => preg_match("/LieBaoFast\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (isset($browsers_liebao[$chromeVersion]) ? $browsers_liebao[$chromeVersion] : ''),
"2345Explorer" => preg_match("/2345Explorer\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (preg_match("/Mb2345Browser\/([\d.]+)/", $userAgent, $matches) ? $matches[1] : (isset($browsers_2345[$chromeVersion]) ? $browsers_2345[$chromeVersion] : '')),
];
if (isset($deviceInfo['browser'], $browsersVersion[$deviceInfo['browser']])) {
$deviceInfo['version'] = $browsersVersion[$deviceInfo['browser']];
if ($deviceInfo['version'] == $userAgent) {
$deviceInfo['version'] = '';
}
$deviceInfo['version'] = $browsersVersion[$deviceInfo['browser']];
if ($deviceInfo['version'] == $userAgent) {
$deviceInfo['version'] = '';
}
}
// 修正浏览器版本信息
$chrome = pregMatch('/\S+Browser/', $userAgent);
if ($deviceInfo['browser'] == 'Chrome' && $chrome) {
$deviceInfo['browser'] = $chrome;
$deviceInfo['version'] = pregMatch('/^.*Browser\/([\d.]+).*$/', $userAgent);
if (preg_match('/\S+Browser/', $userAgent, $matches)) {
$chrome = $matches[0];
if ($deviceInfo['browser'] == 'Chrome' && $chrome !== 'Chrome') {
$deviceInfo['browser'] = $chrome;
if (preg_match('/Browser\/([\d.]+)/', $userAgent, $matches)) {
$deviceInfo['version'] = $matches[1];
}
}
}
return $deviceInfo;
}
@@ -984,7 +1030,8 @@ function parse_smiley_shortcode($content) {
/**
* 短代码实现
*/
function get_article_info($atts) {
function get_article_info($atts)
{
$default_atts = array('id' => '');
$atts = array_merge($default_atts, $atts);
$db = Typecho_Db::get();
@@ -996,7 +1043,6 @@ function get_article_info($atts) {
if (!$post) {
return '未找到文章';
}
// 获取文章对象,避免permalink警告
$post = Typecho_Widget::widget('Widget_Abstract_Contents')->push($post);
$permalink = $post['permalink'];
$title = htmlspecialchars($post['title']);
@@ -1011,17 +1057,37 @@ function get_article_info($atts) {
return $output;
}
// 创建一个新的类来处理内容过滤
class ContentFilter
{
/**
* 过滤内容中的短代码
*
* @param string $content 内容
* @param object $widget 小工具对象
* @param array $lastResult 上一次结果
* @return string 处理后的内容
*/
public static function filterContent($content, $widget, $lastResult)
{
// 先做github短代码和链接替换
// Step 1: 保护代码块
$codeBlocks = [];
$content = preg_replace_callback(
'/```[\s\S]*?```/m', // 匹配 Markdown 代码块(包括多行)
function ($matches) use (&$codeBlocks) {
$placeholder = '<!--CODEBLOCK_' . count($codeBlocks) . '-->';
$codeBlocks[$placeholder] = $matches[0]; // 存储原始代码块内容
return $placeholder;
},
$content
);
// Step 2: 执行现有的短代码处理
// GitHub 短代码替换
$content = preg_replace_callback('/\[github=([\w\-\.]+\/[\w\-\.]+)\]/i', function($matches) {
$repo = htmlspecialchars($matches[1]);
return '<div class="github-card text-center" data-repo="' . $repo . '"><div class="spinner-grow text-primary"></div></div>';
}, $content);
// 只匹配主仓库链接,后面只能是空格、标点、换行或结尾
$content = preg_replace_callback(
'#https://github\.com/([\w\-\.]+/[\w\-\.]+)(?=[\s\.,;:!\?\)\]\}\"\'\n]|$)#i',
function($matches) {
@@ -1031,10 +1097,7 @@ class ContentFilter
$content
);
// 再进行 Markdown 解析
$content = empty($lastResult) ? $widget->markdown($content) : $lastResult;
// alert类短代码批量替换
// alert 类短代码
$alertShortcodes = [
'success' => 'success',
'primary' => 'primary',
@@ -1051,12 +1114,12 @@ class ContentFilter
);
}
// 其他短代码处理
// article 短代码
$content = preg_replace_callback('/\[article\s+([^\]]+)\]/', function($matches) {
$atts = self::parse_atts($matches[1]);
return get_article_info($atts);
}, $content);
// 懒加载图片替换
$themeUrl = Helper::options()->themeUrl;
$loadSvg = $themeUrl . '/assets/img/load.svg';
@@ -1069,7 +1132,8 @@ class ContentFilter
},
$content
);
// collapse折叠面板短代码
// collapse 折叠面板短代码
static $collapseIndex = 0;
$content = preg_replace_callback(
'/\[collapse\s+title=(?:\'([^\']*)\'|\"([^\"]*)\")\](.*?)\[\/collapse\]/is',
@@ -1082,7 +1146,8 @@ class ContentFilter
},
$content
);
// download下载短代码
// download 短代码
$content = preg_replace_callback(
'/\[download\s+file=(?:\'([^\']*)\'|\"([^\"]*)\")\s+size=(?:\'([^\']*)\'|\"([^\"]*)\")\](.*?)\[\/download\]/is',
function($matches) {
@@ -1097,17 +1162,16 @@ class ContentFilter
},
$content
);
// 回复可见短代码
// reply 短代码
$content = preg_replace_callback(
'/\[reply\](.*?)\[\/reply\]/is',
function($matches) use ($widget) {
$show = false;
// 仅在文章页生效
if ($widget instanceof Widget_Archive && $widget->is('single')) {
$user = Typecho_Widget::widget('Widget_User');
$db = Typecho_Db::get();
if ($user->hasLogin) {
// 登录用户,判断是否有通过审核的评论
$hasComment = $db->fetchRow($db->select()->from('table.comments')
->where('cid = ?', $widget->cid)
->where('mail = ?', $user->mail)
@@ -1115,7 +1179,6 @@ class ContentFilter
);
if ($hasComment) $show = true;
} else {
// 未登录,判断IP
$hasComment = $db->fetchRow($db->select()->from('table.comments')
->where('cid = ?', $widget->cid)
->where('status = ?', 'approved')
@@ -1132,9 +1195,19 @@ class ContentFilter
},
$content
);
// Step 3: 恢复代码块
foreach ($codeBlocks as $placeholder => $code) {
$content = str_replace($placeholder, $code, $content);
}
// Step 4: 进行 Markdown 解析
$content = empty($lastResult) ? $widget->markdown($content) : $lastResult;
return $content;
}
// 解析短代码属性
// 解析短代码属性(保持不变)
private static function parse_atts($text) {
$atts = array();
$pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
@@ -1156,7 +1229,8 @@ class ContentFilter
return $atts;
}
}
// 注册钩子,自动处理所有内容输出
// 注册钩子
Typecho_Plugin::factory('Widget_Abstract_Contents')->content = array('ContentFilter', 'filterContent');
Typecho_Plugin::factory('Widget_Abstract_Contents')->contentEx = array('ContentFilter', 'filterContent');
@@ -1373,26 +1447,25 @@ function get_site_statistics() {
];
}
// Typecho AJAX 登录接口,支持前端 AJAX 提交并返回 JSON
//if (!empty($_GET['ajaxLogin']) && $_GET['ajaxLogin'] == 1) {
// header('Content-Type: application/json; charset=utf-8');
// if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
// echo json_encode(['success' => false, 'msg' => '请求方式错误']);
// exit;
// }
// $name = isset($_POST['name']) ? trim($_POST['name']) : '';
// $password = isset($_POST['password']) ? $_POST['password'] : '';
// $referer = isset($_POST['referer']) ? $_POST['referer'] : '/';
// if (!$name || !$password) {
// echo json_encode(['success' => false, 'msg' => '用户名或密码不能为空']);
// exit;
// }
// $user = Typecho_Widget::widget('Widget_User');
// try {
// $user->login($name, $password, isset($_POST['remember']) ? 1 : 0);
// echo json_encode(['success' => true, 'msg' => '登录成功', 'redirect' => $referer]);
// } catch (Typecho_Exception $e) {
// echo json_encode(['success' => false, 'msg' => $e->getMessage()]);
// }
// exit;
//}
/**
* 友好时间显示函数
* @param $timestamp
* @return string
*/
function friendly_date($timestamp) {
$time = is_numeric($timestamp) ? $timestamp : strtotime($timestamp);
$diff = time() - $time;
if ($diff < 60) {
return '刚刚';
} elseif ($diff < 3600) {
return floor($diff / 60) . '分钟前';
} elseif ($diff < 86400) {
return floor($diff / 3600) . '小时前';
} elseif ($diff < 2592000) {
return floor($diff / 86400) . '天前';
} elseif ($diff < 31536000) {
return floor($diff / 2592000) . '月前';
} else {
return date('Y-m-d H:i:s', $time);
}
}
+28 -6
View File
@@ -177,12 +177,34 @@
<div data-swiper="init" data-swiper-class="global-top-notice-swiper" data-swiper-args='{"direction":"vertical","autoplay":{"delay":3000,"disableOnInteraction":false},"loop":true}'>
<div class="swiper global-top-notice-swiper">
<div class="swiper-wrapper">
<div class="swiper-slide t-line-1">
<a class="ta3" data-no-instant href="javascript:void(0)">
<span class="notice-icon"><i class="fa-regular fa-bell"></i></span>
<span><?php $this->options->gonggao(); ?></span>
</a>
</div>
<?php
// 获取公告内容
$gonggao = $this->options->gonggao;
if ($gonggao) {
// 按行分割
$lines = explode("\n", $gonggao);
foreach ($lines as $line) {
$parts = explode('|', $line);
// 只处理格式正确的行
if (count($parts) >= 3) {
$title = trim($parts[0]);
$url = trim($parts[1]);
$icon = trim($parts[2]);
// 链接为空时使用 javascript:void(0)
$href = $url !== '' ? htmlspecialchars($url) : 'javascript:void(0)';
// 图标为空时使用默认
$icon_class = $icon !== '' ? $icon : 'fa-regular fa-bell';
// 输出 HTML
echo '<div class="swiper-slide t-line-1">';
echo '<a class="ta3" data-no-instant href="' . $href . '">';
echo '<span class="notice-icon"><i class="' . $icon_class . '"></i></span>';
echo '<span>' . htmlspecialchars($title) . '</span>';
echo '</a>';
echo '</div>';
}
}
}
?>
</div>
</div>
</div>
+10 -2
View File
@@ -1,10 +1,11 @@
<?php
/**
* Pouck theme for Typecho
*
* 老孙移植
*
* @package Typecho Pouck Theme
* @author 老孙博客
* @version 1.2.0
* @version 1.2.3
* @link http://www.imsun.org
*/
@@ -13,8 +14,13 @@ $this->need('header.php');
$this->need('sticky.php');
?>
<div class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div class="col-lg-8 col-md-12 animated fadeInLeft ">
<div class="animated fadeInLeft ">
<?php else: ?>
<div class="col-lg-12 col-md-12">
<div class="row box-plr15">
<?php endif; ?>
<div> <!--文章列表-->
<div id="posts">
<?php if ($this->options->listmodel): ?>
@@ -96,5 +102,7 @@ if ($pageprev == '1' && $this->have()):
</div>
</div>
</div>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
+1 -1
View File
@@ -16,7 +16,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
</div>
<div id="page">
<div class="row row-cols-1">
<div id="posts" class="col-12 animated fadeInLeft ">
<div id="posts" class="col-12">
<div class="puock-text no-style">
<p><?php $this->content(); ?></p>
</div>
+118
View File
@@ -0,0 +1,118 @@
<?php
/**
* 随机阅读
*
* @package custom
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
// 防止 PJAX 缓存,确保每次都是随机文章
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');
header('X-InstantClick: no-cache');
// 获取随机文章
function getRandomPost() {
$db = Typecho_Db::get();
// 统计符合条件的文章总数
$countSql = $db->select('COUNT(*) AS count')
->from('table.contents')
->where('status = ?', 'publish')
->where('type = ?', 'post')
->where('created <= ?', time());
$countResult = $db->fetchRow($countSql);
$total = $countResult['count'];
if ($total > 0) {
// 随机选择一个偏移量
$offset = mt_rand(0, $total - 1);
// 根据偏移量获取一篇文章
$sql = $db->select()
->from('table.contents')
->where('status = ?', 'publish')
->where('type = ?', 'post')
->where('created <= ?', time())
->limit(1)
->offset($offset);
$result = $db->fetchRow($sql);
if (!empty($result)) {
$target = Typecho_Widget::widget('Widget_Abstract_Contents')->filter($result);
return $target['permalink'];
}
}
return false;
}
// 获取随机文章链接
$randomPostUrl = getRandomPost();
$this->need('header.php');
?>
<div id="breadcrumb" class="animated fadeInUp">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a class="a-link" href="<?php $this->options->siteUrl(); ?>">首页</a></li>
<li class="breadcrumb-item active" aria-current="page">随机阅读</li>
</ol>
</nav>
</div>
<div id="page-empty">
<div id="page" class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div id="post-main" class="col-lg-8 col-md-12 animated fadeInLeft">
<?php else: ?>
<div id="post-main" class="col-lg-12 col-md-12">
<?php endif; ?>
<div class="p-block">
<div>
<h1 id="post-title" class="mb-0 puock-text t-xxl">随机阅读</h1>
</div>
<div class="mt20 puock-text entry-content show-link-icon">
<div class="text-center">
<div class="mb-4">
<i class="fa fa-random fa-3x text-primary mb-3"></i>
<h3>正在为您随机选择一篇文章...</h3>
<p class="text-muted">请稍候,正在跳转中...</p>
</div>
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
</div>
</div>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
</div>
</div>
<script>
// 立即执行的跳转函数
function performRandomRedirect() {
setTimeout(function() {
<?php if ($randomPostUrl): ?>
// 跳转到随机文章
window.location.href = '<?php echo $randomPostUrl; ?>';
<?php else: ?>
// 如果没有文章,跳转到首页
window.location.href = '<?php $this->options->siteUrl(); ?>';
<?php endif; ?>
}, 1500);
}
// 在 DOMContentLoaded 和页面加载完成后都执行
document.addEventListener('DOMContentLoaded', performRandomRedirect);
window.addEventListener('load', performRandomRedirect);
// 立即执行一次,确保在 PJAX 模式下也能工作
performRandomRedirect();
</script>
<?php $this->need('footer.php'); ?>
+8 -2
View File
@@ -17,7 +17,11 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $commenters = getAllCommenters(); ?>
<div id="page-reads">
<div id="page" class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div id="posts" class="col-lg-8 col-md-12 animated fadeInLeft ">
<?php else: ?>
<div id="posts" class="col-lg-12 col-md-12">
<?php endif; ?>
<div class="p-block puock-text">
<h2 class="t-lg"><?php $this->title() ?></h2>
<div class="mt20 row pd-links">
@@ -44,5 +48,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
</div>
</div>
</div>
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
+182
View File
@@ -0,0 +1,182 @@
<?php
/**
* 说说页面
* @package custom
* @author 老孙
* @version 1.0
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
$this->need('header.php');
?>
<div id="breadcrumb" class="animated fadeInUp">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a class="a-link" href="<?php $this->options->siteUrl(); ?>">首页</a></li>
<li class="breadcrumb-item active" aria-current="page"><?php $this->title() ?></li>
</ol>
</nav>
</div>
<div id="page-moments">
<div class="row">
<?php if ($this->options->showsidebar): ?>
<div id="comments" class="col-lg-8 col-md-12 animated fadeInLeft">
<?php else: ?>
<div id="comments" class="col-lg-12 col-md-12">
<?php endif; ?>
<?php
// 登录状态检测
if ($this->user->hasLogin()) {
$GLOBALS['isLogin'] = true;
} else {
$GLOBALS['isLogin'] = false;
}
// 评论回调函数
function threadedComments($comments, $options) {
$mail = $comments->mail;
$mailHash = md5(strtolower(trim($mail)));
$purl = $comments->url;
$nickname = $comments->author;
$cnavatar = Helper::options()->cnavatar ? Helper::options()->cnavatar : 'https://cravatar.cn/avatar/';
$avatarurl = rtrim($cnavatar, '/') . '/' . $mailHash . '?s=80&d=identicon';
$loadingImg = Helper::options()->themeUrl . '/assets/img/load.svg';
?>
<div class="mb20 puock-text moments-item">
<div class="row">
<div class="col-12 col-md-1">
<a class="meta ta3" href="<?php echo $purl; ?>" target="_blank">
<div class="avatar mb10">
<img src='<?php echo $loadingImg; ?>'
class='lazy md-avatar mt-1'
data-src='<?php echo $avatarurl; ?>'
>
</div>
<div class="t-line-1 info fs12"><?php echo $nickname; ?></div>
</a>
</div>
<div class="col-12 col-md-11">
<div class="p-block moment-content-box"> <span class="al"></span>
<div class="mt10 moment-content entry-content show-link-icon">
<?php if ($comments->parent) {echo getPermalinkFromCoid($comments->parent);} echo parse_smiley_shortcode($comments->content);?>
</div>
<div class="mt10 moment-footer p-flex-s-right">
<span class="t-sm c-sub">
<span class="mr-2"><i class="fa-regular fa-clock mr-1"></i><?php echo friendly_date($comments->created); ?></span>
</span>
</div>
</div>
</div>
</div>
</div>
<?php } ?>
<?php $this->comments()->to($comments); ?>
<?php if ($this->user->hasLogin() && $this->user->group == 'administrator') : ?>
<div class="p-block">
<input type="hidden" value="<?php $this->commentUrl() ?>">
<div>
<span class="t-lg border-bottom border-primary puock-text pb-2">
<i class="fa-regular fa-comments mr-1"></i>有什么新鲜事
</span>
</div>
<div class="mt20 clearfix" id="comment-form-box">
<form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" class="mt10" role="form">
<div class="form-group">
<textarea rows="4" name="text" id="comment" class="form-control form-control-sm t-sm" placeholder="发表您的新鲜事儿..." required><?php $this->remember('text'); ?></textarea>
</div>
<input type="hidden" value="<?php $this->user->screenName(); ?>" name="author" />
<input type="hidden" value="<?php $this->user->mail(); ?>" name="mail" />
<input type="hidden" value="<?php $this->options->siteUrl(); ?>" name="url" />
<input type="hidden" name="_" value="<?php Typecho_Widget::widget('Widget_Security')->to($security);
echo $security->getToken($this->request->getRequestUrl()); ?>">
<div class="p-flex-sbc mt10">
<div class="form-foot">
<?php if($this->options->social): ?>
<button id="comment-insert-image" class="btn btn-outline-secondary btn-ssm pk-modal-toggle" type="button" title="插入图片">
<i class="fa-solid fa-image"></i>
</button>
<button id="comment-smiley" class="btn btn-outline-secondary btn-ssm pk-modal-toggle" type="button" title="表情" data-once-load="true"
data-url="<?php echo get_correct_url('/emoji/'); ?>">
<i class="fa-regular fa-face-smile t-md"></i>
</button>
<?php endif; ?>
<button type="submit" class="btn btn-primary btn-ssm"><i class="fa-regular fa-paper-plane"></i> 立即发表</button>
</div>
</div>
</form>
</div>
</div>
<?php endif; ?>
<?php if ($comments->have()): ?>
<!-- 评论列表 -->
<?php while ($comments->next()): ?>
<?php threadedComments($comments, $this->options); ?>
<?php endwhile; ?>
<!-- 分页导航 -->
<div class="mt20 p-flex-s-right" data-no-instant>
<?php $comments->pageNav('&laquo;', '&raquo;', 1, '...', array(
'wrapTag' => 'ul',
'wrapClass' => 'pagination comment-ajax-load',
'itemTag' => 'li',
'textTag' => 'span',
'currentClass' => 'active',
'prevClass' => 'prev',
'nextClass' => 'next'
)); ?>
</div>
</div>
<?php endif; ?>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
</div>
</div>
<?php $this->need('footer.php'); ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
var btn = document.getElementById('comment-insert-image');
if (!btn) return;
btn.addEventListener('click', function() {
let modal = document.createElement('div');
modal.innerHTML = `
<div id="img-insert-modal" style="position:fixed;z-index:9999;left:0;top:0;width:100vw;height:100vh;background:rgba(0,0,0,0.3);display:flex;align-items:center;justify-content:center;">
<div style="background:#fff;padding:24px 32px;border-radius:8px;min-width:320px;box-shadow:0 2px 16px rgba(0,0,0,0.15);">
<div style="font-size:18px;font-weight:bold;margin-bottom:12px;">插入图片</div>
<div style="margin-bottom:10px;">
<label style="display:block;font-size:14px;margin-bottom:4px;">标题(可选)</label>
<input id="img-insert-title" type="text" style="width:100%;padding:6px 8px;border:1px solid #ccc;border-radius:4px;">
</div>
<div style="margin-bottom:10px;">
<label style="display:block;font-size:14px;margin-bottom:4px;">图片地址 <span style="color:red">*</span></label>
<input id="img-insert-url" type="text" style="width:100%;padding:6px 8px;border:1px solid #ccc;border-radius:4px;" required>
</div>
<div style="text-align:right;">
<button id="img-insert-cancel" style="margin-right:10px;padding:6px 16px;">取消</button>
<button id="img-insert-confirm" style="background:#007bff;color:#fff;padding:6px 16px;border:none;border-radius:4px;">插入</button>
</div>
</div>
</div>`;
document.body.appendChild(modal);
document.getElementById('img-insert-cancel').onclick = function() {
document.body.removeChild(modal);
};
document.getElementById('img-insert-confirm').onclick = function() {
let url = document.getElementById('img-insert-url').value.trim();
let title = document.getElementById('img-insert-title').value.trim();
if (!url) {
alert('图片地址不能为空!');
return;
}
let tag = `<img src=\"${url}\"` + (title ? ` alt=\"${title}\" title=\"${title}\"` : '') + ` />`;
let textarea = document.getElementById('comment');
if (textarea) {
let start = textarea.selectionStart, end = textarea.selectionEnd;
let val = textarea.value;
textarea.value = val.substring(0, start) + tag + val.substring(end);
textarea.focus();
textarea.selectionStart = textarea.selectionEnd = start + tag.length;
}
document.body.removeChild(modal);
};
});
});
</script>
+9 -14
View File
@@ -16,20 +16,21 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
</div>
<div id="page-tags">
<div id="page" class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div id="posts" class="col-lg-8 col-md-12 animated fadeInLeft">
<?php else: ?>
<div id="posts" class="col-lg-12 col-md-12">
<?php endif; ?>
<div class="puock-text p-block no-style pb-2">
<?php
// 获取所有标签
$tags = Typecho_Widget::widget('Widget_Metas_Tag_Cloud');
// 准备字母数组
$letters = range('A', 'Z');
$letters[] = '0';
$letters[] = '0';
// 获取所有存在的首字母
$existingLetters = array();
$tagsArray = array();
$tagsArray = array();
while ($tags->next()) {
$firstChar = getFirstChar($tags->name);
if (!in_array($firstChar, $existingLetters)) {
@@ -41,7 +42,6 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
'count' => $tags->count
);
}
// 对每个字母下的标签按名称排序
foreach ($tagsArray as &$letterTags) {
usort($letterTags, function($a, $b) {
@@ -49,7 +49,6 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
});
}
?>
<!-- 字母导航 -->
<ul class='pl-0' id='tags-main-index'>
<?php foreach ($letters as $letter): ?>
@@ -63,13 +62,11 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<li class='t'><?php echo $i; ?></li>
<?php endfor; ?>
</ul>
<!-- 标签列表 -->
<ul id='tags-main-box' class='pl-0'>
<?php
// 按字母顺序排序
ksort($tagsArray);
foreach ($tagsArray as $letter => $tags): ?>
<li class='n' id='<?php echo $letter; ?>'>
<h4 class='tag-name'><span class='t-lg c-sub'>#</span><?php echo $letter; ?></h4>
@@ -81,9 +78,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
</ul>
</div>
</div>
<?php
?>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php $this->need('footer.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
-168
View File
@@ -1,168 +0,0 @@
<?php
/**
* 说说页面
*
* @package custom
*/
if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
<?php $this->need('header.php'); ?>
<div id="breadcrumb" class="animated fadeInUp">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a class="a-link" href="<?php $this->options->siteUrl(); ?>">首页</a></li>
<li class="breadcrumb-item active " aria-current="page"><?php $this->title() ?></li>
</ol>
</nav>
<div id="page-moments">
<div class="row">
<div id="posts" class="col-lg-8 col-md-12 animated fadeInLeft ">
<?php $tooot = $this->fields->tooot ? $this->fields->tooot : 'https://www.imsun.org/toot.json'; ?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/15.0.12/marked.min.js" integrity="sha512-rCQgmUulW6f6QegOvTntKKb5IAoxTpGVCdWqYjkXEpzAns6XUFs8NKVqWe+KQpctp/EoRSFSuykVputqknLYMg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.5/css/lightbox.min.css" integrity="sha512-xtV3HfYNbQXS/1R1jP53KbFcU9WXiSA1RFKzl5hRlJgdOJm4OxHCWYpskm6lN0xp0XtKGpAfVShpbvlFH3MDAA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.11.5/js/lightbox.min.js" integrity="sha512-KbRFbjA5bwNan6DvPl1ODUolvTTZ/vckssnFhka5cG80JVa5zSlRPCr055xSgU/q6oMIGhZWLhcbgIC0fyw3RQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="tooot"></div>
</div>
<script>
function fetchAndDisplayToots() {
let offset = 0;
const limit = 20;
function formatHTML(toots) {
let htmlString = '';
toots.forEach(toot => {
const isReblog = toot.reblog && toot.reblog.content;
const content = isReblog ? toot.reblog.content : toot.content;
const url = isReblog ? toot.reblog.url : toot.url;
const account = isReblog ? toot.reblog.account : toot.account;
const created_at = isReblog ? toot.reblog.created_at : toot.created_at;
const media_attachments = isReblog ? toot.reblog.media_attachments : toot.media_attachments;
let mediaHTML = '';
if (media_attachments && media_attachments.length > 0) {
media_attachments.forEach(attachment => {
if (attachment.type === 'image') {
mediaHTML += `<a href="${attachment.url}" target="_blank" data-lightbox="image-set"><img src="${attachment.preview_url}" class="thumbnail-image img" ></a>`;
}
});
}
const htmlContent = marked.parse(content || '');
htmlString += `
<div class="mb20 puock-text moments-item">
<div class="row">
<div class="col-12 col-md-1">
<a class="meta ta3" href="${account.url}" target="_blank" rel="nofollow">
<div class="avatar mb10">
<img src='${account.avatar}'
class='lazy md-avatar mt-1'
data-src='${account.avatar}'
alt="${account.display_name}" title="${account.display_name}">
</div>
<div class="t-line-1 info fs12">${account.display_name}</div>
</a>
</div>
<div class="col-12 col-md-11">
<div class="p-block moment-content-box"> <span class="al"></span>
<div class="mt10 moment-content entry-content show-link-icon">
<p>${htmlContent}</p>
<div class="resimg">${mediaHTML}</div>
</div>
<div class="mt10 moment-footer p-flex-s-right"> <span class="t-sm c-sub">
<a class="c-sub-a" href="${url}">
<span class="mr-2"><i class="fa-regular fa-clock mr-1"></i>${new Date(created_at).toLocaleString()}</span>
</a>
</span>
</div>
</div>
</div>
</div>
</div>
`;
});
return htmlString;
}
function fetchToots() {
return fetch('<?php echo $tooot; ?>')
.then(response => response.json())
.catch(error => {
console.error('Error fetching toots:', error);
return [];
});
}
const memosContainer = document.getElementById('tooot');
if (memosContainer) memosContainer.innerHTML = '';
fetchToots().then(data => {
if (!Array.isArray(data)) {
console.error('toot.json is not an array:', data);
return;
}
const tootsToShow = data.slice(offset, offset + limit);
if (memosContainer) memosContainer.innerHTML += formatHTML(tootsToShow);
});
}
// 保证首次和 pjax 都能调用
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", fetchAndDisplayToots);
} else {
fetchAndDisplayToots();
}
document.addEventListener('pjax:end', fetchAndDisplayToots);
</script>
<style>
div pre code {
white-space: pre-wrap;
word-wrap: break-word;
overflow-wrap: break-word;
word-break: break-all;
word-break: break-word;
}
div p a {
word-break: break-all;
word-break: break-word;
}
.resimg {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 10px;
row-gap: 10px;
}
/* 单个缩略图的样式 */
.thumbnail-image {
width: 100%; /* 确保其宽度填满父容器 */
height: 200px; /* 固定高度 */
display: flex; /* 使用 flexbox 居中 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
overflow: hidden; /* 确保容器内的多余内容不会显示出来 */
border-radius: 4px; /* 圆角 */
transition: transform .3s ease; /* 鼠标悬停时的过渡效果 */
cursor: zoom-in; /* 鼠标指针变为放大镜 */
}
img {
object-fit: cover; /* 保持图片的纵横比,但会将图片裁剪以填充容器 */
object-position: center; /* 保证中央部分 */
}
/* 缩略图内的图片样式 */
.thumbnail-image img {
width: 100%;
min-height: 200px;
}
/* 当屏幕宽度小于732px时 */
@media (max-width: 732px) {
.resimg {
grid-template-columns: repeat(2, 1fr); /* 修改为两列 */
}
}
/* 当屏幕宽度小于400px时 */
@media (max-width: 400px) {
.resimg {
grid-template-columns: 1fr; /* 修改为一列 */
}
.thumbnail-image img {
width: 100%;
height: 480px;
}
}
</style>
<?php $this->need('sidebar.php'); ?>
</div>
</div>
<?php $this->need('footer.php'); ?>
+6
View File
@@ -10,7 +10,11 @@
</div>
<div id="page-empty">
<div id="page" class="row row-cols-1">
<?php if ($this->options->showsidebar): ?>
<div id="post-main" class="col-lg-8 col-md-12 animated fadeInLeft ">
<?php else: ?>
<div id="post-main" class="col-lg-12 col-md-12">
<?php endif; ?>
<div class="p-block"><div>
<h1 id="post-title" class="mb-0 puock-text t-xxl"><?php $this->title() ?></h1>
</div>
@@ -60,5 +64,7 @@ if($days > 180){
<?php $this->need('comments.php'); ?>
<?php endif; ?>
</div>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
+6
View File
@@ -15,7 +15,11 @@
<div class="puock-text p-block t-md ad-page-top"><?php $this->options->articletop(); ?></div>
<?php endif; ?>
<div class="row row-cols-1 post-row">
<?php if ($this->options->showsidebar): ?>
<div id="post-main" class="col-lg-8 col-md-12 animated fadeInLeft ">
<?php else: ?>
<div id="post-main" class="col-lg-12 col-md-12">
<?php endif; ?>
<div class="p-block"><div>
<h1 id="post-title" class="mb-0 puock-text t-xxl"><?php $this->title() ?></h1>
</div>
@@ -216,5 +220,7 @@ if($days > 180){
<div class="puock-text p-block t-md ad-comment-top"><?php $this->options->articlefoot(); ?></div>
<?php endif; ?>
</div>
<?php if ($this->options->showsidebar): ?>
<?php $this->need('sidebar.php'); ?>
<?php endif; ?>
<?php $this->need('footer.php'); ?>
+1 -1
View File
@@ -109,7 +109,7 @@
<div class="pk-widget p-block">
<div>
<span class="t-lg border-bottom border-primary puock-text pb-2">
<i class="fa fa-chart-simple mr-1"></i>热门文章
<i class="fa-solid fa-fire"></i> 热门文章
</span>
</div>
<div class="mt20">