This commit is contained in:
root
2026-03-04 00:23:03 +08:00
commit 6136d791f2
611 changed files with 65539 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
<?php
/**
* 面包屑
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-1-20 13:02:19
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<ul class="breadcrumb mb-0 p-0 pb-2">
<li>
<a href="<?php $this->options->siteUrl(); ?>" class="link" title="首页">首页</a>
</li>
<?php if (count($this->categories) > 0): ?>
<li>
<a class="link" href="<?php echo $this->categories[0]['permalink']; ?>"
title="<?php echo $this->categories[0]['name']; ?>"><?php echo $this->categories[0]['name']; ?></a>
</li>
<?php endif; ?>
<li><span>正文</span></li>
</ul>

View File

@@ -0,0 +1,165 @@
<?php
/**
* 评论主体内容
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
function threadedComments($comments, $options) {
// 评论层级样式
$commentLevelClass = $comments->levels > 0 ? ' comment-child' : ' comment-parent';
?>
<li id="li-<?php $comments->theId(); ?>" class="comment<?php echo $commentLevelClass; ?> p-1">
<div id="<?php $comments->theId(); ?>" class="comment-body d-flex flex-column p-1">
<div class="comment-author d-flex flex-row">
<?php
$email = $comments->mail;
$imgUrl = getGravatar($email);
echo '<img class="lazy" src="'.getAvatarLazyload(false).'" data-original="'.$imgUrl.'" alt="'.$comments->author.'">';
?>
<div class="comment-header">
<div class="comment-name">
<?php CommentAuthor($comments); ?>
<?php if ($comments->authorId == 1): ?>
<span class="comment-author-ua">博主</span>
<?php endif; ?>
</div>
<time class="comment-time" title="<?php $comments->date('c'); ?>"><?php echo ueTime($comments->date); ?></time>
<span class="comment-ua"><?php echo getOs($comments->agent); ?></span>
<span class="comment-ua"><?php echo getBrowser($comments->agent); ?></span>
<?php if ($comments->status === 'waiting'): ?>
<em class="comment-ua">评论审核中...</em>
<?php endif; ?>
</div>
<div class="reply comment-footer">
<span class="comment-reply-link">
<?php $comments->reply('<i class="iconfont icon-pinglun"></i>'); ?>
</span>
</div>
</div>
<div class="comment-card flex-grow-1">
<div class="comment-content ml-3 ml-md-5">
<?php echo getCommentAt($comments->coid); ?> <?php echo formatEmoji($comments->content); ?>
</div>
</div>
</div>
<?php if ($comments->children): ?>
<?php $comments->threadedComments($options); ?>
<?php endif; ?>
</li>
<?php
}
$this->comments()->to($comments);
if ($this->allow('comment')): ?>
<div class="card my-2 p-2 p-md-3 my-md-3">
<div id="comments">
<div id="<?php $this->respondId(); ?>" class="respond flex-grow-1 w-100">
<form method="post" action="<?php $this->commentUrl()?>" id="comment-form" role="form">
<?php if ($this->user->hasLogin()): ?>
<div class="mb-3"><?php echo '当前用户: '; ?><a
href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a>.
<a href="<?php $this->options->logoutUrl(); ?>" title="Logout"><?php echo '退出'; ?> &raquo;</a>
</div>
<?php else: ?>
<ul class="row comment-form-info">
<li class="col-12 col-md-4 col-xl-4 mb-2">
<input type="text" name="author" id="author" class="form-control" placeholder="昵称"
value="<?php $this->remember('author'); ?>" required />
</li>
<li class="col-12 col-md-4 col-xl-4 mb-2">
<input type="email" name="mail" id="mail" class="form-control" placeholder="Email"
value="<?php $this->remember('mail'); ?>" <?php if ($this->options->commentsRequireMail): ?>
required<?php endif; ?> />
</li>
<li class="col-12 col-md-4 col-xl-4 mb-2">
<input type="url" name="url" id="url" class="form-control" placeholder="http(s)://"
value="<?php $this->remember('url'); ?>" <?php if ($this->options->commentsRequireURL): ?>
required<?php endif; ?> />
</li>
</ul>
<?php endif; ?>
<div class="com-body comment-textarea">
<textarea name="text" id="textarea" class="form-control" rows="5" placeholder="请填写真实邮箱方便站长联系,并回复有效的内容!"
required><?php $this->remember('text'); ?></textarea>
</div>
<div class="com-footer d-flex flex-wrap justify-content-between align-items-center my-2">
<div class="com-tool-list d-flex flex-row align-items-center">
<div class="px-2 py-1 com-tool-item com-emoji">
<a id="emoji-btn" class="" href="javascript:void(0);" role="button"><i
class="iconfont icon-biaoqing"></i></a>
<div class="emoji-box"></div>
</div>
</div>
<div class="form-submit text-right">
<button id="cancel-comment-reply-link" class="btn btn-card mr-2" style="display:none"
onclick="return TypechoComment.cancelReply();">取消回复</button>
<button type="submit" class="btn btn-card px-2 py-1">提交评论</button>
</div>
</div>
</form>
</div>
<!-- 评论列表主体st -->
<?php if ($comments->have()): ?>
<p><?php $this->commentsNum('暂无评论', '仅有一条评论', '全部 %d 条评论'); ?></p>
<?php $comments->listComments(); ?>
<div class="comment-pagination">
<?php $comments->pageNav('<i class="iconfont icon-shangyiye"></i>', '<i class="iconfont icon-xiayiye"></i>', '2', '...', array('wrapClass' => 'd-flex justify-content-center mt-3', 'prevClass' => 'com-prev', 'nextClass' => 'com-next')); ?>
</div>
<?php else: ?>
<div class="no-comments d-flex flex-column align-items-center">
<svg viewBox="0 0 1462 1024" height="7rem">
<path d="M673.192229 403.426743v241.7664l300.163657 129.316571V485.902629l-300.163657-82.475886z"
fill="#ACACAD"></path>
<path d="M428.383086 472.210286v303.264914l245.160228-131.262171V403.704686L428.383086 472.210286z"
fill="#C2C1C1"></path>
<path
d="M823.881143 124.679314a29.257143 29.257143 0 0 0-41.252572 41.311086c11.395657 11.381029 42.993371 24.488229 54.403658 13.165714S835.291429 136.045714 823.881143 124.679314zM911.36 209.393371c-11.395657-11.395657-42.993371-24.502857-54.403657-13.092571s1.696914 43.008 13.092571 54.403657A29.257143 29.257143 0 0 0 911.36 209.393371z"
fill="#CDD6E3" opacity=".4"></path>
<path
d="M846.687086 159.758629a23.669029 23.669029 0 0 0-23.698286 23.698285v26.682515h26.755657a23.669029 23.669029 0 0 0 23.698286-23.698286v-26.682514z"
fill="#A6B5C3"></path>
<path
d="M814.160457 173.780114l5.637852-5.636388 41.240868 41.240868-5.637851 5.637852zM830.071954 160.506149l5.637852-5.636389 41.240868 41.240869-5.637851 5.637851z"
fill="#DCE4F1"></path>
<path d="M428.383086 472.751543v302.299428l300.163657 129.316572V568.0128l-300.163657-95.261257z"
fill="#E6E7E8"></path>
<path d="M724.289829 568.0128v336.354743l250.5728-129.316572V485.536914l-250.5728 82.475886z" fill="#D8D8D8">
</path>
<path
d="M974.160457 485.332114l-248.992914 82.037029 88.7808 148.918857 257.082514-101.317486-96.8704-129.6384z"
fill="#E5E5E5"></path>
<path
d="M428.017371 472.049371l-83.909485 130.896458 295.716571 113.342171 86.396343-149.0944-298.203429-95.144229z"
fill="#D3D3D3"></path>
<path
d="M894.1568 140.434286a3.657143 3.657143 0 0 1-0.687543 0 2.925714 2.925714 0 0 1-2.165028-3.525486L895.268571 120.246857a2.925714 2.925714 0 1 1 5.690515 1.360457l-3.949715 16.559543a2.925714 2.925714 0 0 1-2.852571 2.267429zM899.466971 146.826971a2.925714 2.925714 0 0 1-0.980114-5.675885l16.091429-5.705143a2.925714 2.925714 0 0 1 1.960228 5.514971l-16.091428 5.705143a2.925714 2.925714 0 0 1-0.980115 0.160914z"
fill="#CCCCCC"></path>
<path
d="M881.415314 133.251657a21.211429 21.211429 0 1 0 21.240686 21.211429 21.226057 21.226057 0 0 0-21.240686-21.211429z"
fill="#8897A5"></path>
<path
d="M923.062857 390.948571a7.489829 7.489829 0 1 0 14.965029 0v-17.451885H923.062857zM319.093029 453.485714a39.906743 39.906743 0 1 0 39.906742 39.906743A40.0384 40.0384 0 0 0 319.093029 453.485714z m0 64.848457a24.941714 24.941714 0 1 1 24.941714-24.941714 24.693029 24.693029 0 0 1-24.941714 25.000229zM937.998629 341.065143a7.489829 7.489829 0 0 0-14.965029 0v17.466514h14.965029zM1087.648914 403.426743a34.9184 34.9184 0 1 0 34.9184 34.903771 34.698971 34.698971 0 0 0-34.9184-34.903771z m0 59.860114a24.941714 24.941714 0 1 1 24.868572-24.956343 24.707657 24.707657 0 0 1-24.868572 24.956343z"
fill="#D8D8D8"></path>
<path
d="M473.717029 343.771429h-29.915429v19.953371h29.915429a9.976686 9.976686 0 1 0 0-19.953371zM393.918171 343.771429a9.976686 9.976686 0 0 0 0 19.953371h29.930058V343.771429zM955.465143 358.531657h-49.883429a7.489829 7.489829 0 1 0 0 14.965029h49.883429a7.489829 7.489829 0 0 0 0-14.965029zM326.7584 204.0832a24.941714 24.941714 0 1 0 24.868571 24.941714 24.693029 24.693029 0 0 0-24.868571-24.941714z m0 39.906743a14.965029 14.965029 0 1 1 14.965029-14.965029 14.628571 14.628571 0 0 1-14.965029 14.965029z"
fill="#E5E5E5"></path>
<path
d="M443.8016 313.885257a9.976686 9.976686 0 1 0-19.953371 0v79.798857a9.976686 9.976686 0 1 0 19.953371 0v-79.798857z"
fill="#D8D8D8"></path>
</svg>
<p style="color: var(--main-muted-color1);">暂无评论</p>
</div>
<?php endif; ?>
<!-- 评论列表主体end -->
</div>
</div>
<?php else: ?>
<div class="mb-3"></div>
<?php endif; ?>

View File

@@ -0,0 +1,118 @@
<?php
/**
* 底部footer主体内容
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php
$footercontent = $this->options->footerContent; // 自定义底部内容
/**
* 生成动态版权信息
*/
function generateCopyright($siteCreationDate = '') {
$currentYear = date('Y');
if (empty($siteCreationDate) || ! strtotime($siteCreationDate)) {
return "$currentYear";
}
$creationYear = date('Y', strtotime($siteCreationDate));
if ($creationYear == $currentYear) {
return "$creationYear";
}
return "$creationYear-$currentYear";
}
?>
<footer class="footer py-2">
<div class="container d-flex justify-content-between align-items-center">
<?php if ($footercontent): ?>
<?php echo $footercontent; ?>
<?php else: ?>
<div class="footer-left">
<div class="footer-copyright py-2">
<div>© <?php echo generateCopyright($this->options->sitedate); ?> Designed by <a
href="<?php $this->options->siteUrl(); ?>" title="<?php $this->options->title()?>"
target="_blank"><?php $this->options->title()?></a> &Iota; <a href="/privacy.html"
title="<?php $this->options->title()?>隐私政策" target="_blank">隐私政策</a> &Iota; <a
href="/copyright-license.html" title="<?php $this->options->title()?>版权协议" target="_blank">版权协议</a> &Iota;
<a href="/sitemap.xml" title="<?php $this->options->title()?>站点地图" target="_blank">站点地图</a> &Iota; <a
href="<?php $this->options->feedUrl(); ?>" title="<?php $this->options->title()?>RSS"
target="_blank">RSS</a>
</div>
<div></div>
<div>Powered
by <a href="//typecho.org/" title="Typecho" target="_blank">Typecho</a> & <a href="/harmonyhues.html"
title="Harmony Hues 主题" target="_self">Harmony Hues</a><?php $this->options->icp(); ?> &Iota;
<a href="https://ipw.cn/ipv6webcheck/?site=<?php $this->options->siteUrl(); ?>" title="本站支持IPv6访问"
target='_blank'>本站支持IPv6访问</a> &Iota; <a
href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans" title="CC BY-NC-SA 4.0"
target="_blank">CC-BY-NC-SA 4.0</a>
</div>
</div>
</div>
<div class="footer-right d-flex flex-column">
<div class="d-flex align-items-center justify-content-center p-1 theme-toggle">
<button type="button" title="浅色模式" class="px-2 py-1 active"><i class="iconfont icon-qiansemoshi"></i></button>
<button type="button" title="跟随系统" class="px-2 py-1"><i class="iconfont icon-gensuixitong"></i></button>
<button type="button" title="深色模式" class="px-2 py-1"><i class="iconfont icon-shensemoshi"></i></button>
</div>
<div class="d-flex align-items-center justify-content-center mt-2 social-info-list" style="gap: 0.5rem;">
<?php if ($this->options->socialInfo): ?>
<?php echo socialInfo(); ?>
<?php else: ?>
<a href="mailto:<?php $this->author('mail'); ?>" title="mail" target="_blank"><i
class="iconfont icon-youxiang"></i></a>
<a href="/feed/" title="SRR" target="_blank"><i class="iconfont icon-rss"></i></a>
<?php endif; ?>
</div>
</div>
</div>
<?php endif; ?>
</footer>
<!--手机导航栏-->
<div id="mobile-nav"></div>
<!--搜索框-->
<?php $this->need('components/search.php'); ?>
<?php if ($this->is('post') || $this->is('page')): ?>
<!-- 文章或者页面 -->
<script type="text/javascript" src="<?php getAssets('assets/lib/prism/prism.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/js/codecopy.min.js?v='.getVersion()); ?>"></script>
<script type="text/javascript">
var _ARTICLE_URL = "<?php $this->permalink(); ?>";
var _ARTICLE_NAME = "<?php $this->title(); ?>";
var _ARTICLE_COVER_URL = "<?php echo getImgLink($this); ?>";
var _WXQR = "<?php $this->options->wechatQrCode(); ?>";
var _ZFBQR = "<?php $this->options->alipayQrCode(); ?>";
</script>
<script type="text/javascript" src="<?php getAssets('assets/lib/viewimage/view-image.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/lib/html-to-image/html-to-image.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/lib/jquery/jquery.qrcode.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/js/article-toc.min.js?v='.getVersion()); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/js/comment-tools.min.js?v='.getVersion()); ?>"></script>
<?php endif; ?>
<script type="text/javascript" src="<?php getAssets('assets/js/harmonyhues.min.js?v='.getVersion()); ?>"></script>
<script type="text/javascript">
<?php $this->options->customScript(); ?>
console.log("%c © Harmony Hues主题 | Version: <?php echo getVersion(); ?> | https://biibii.cn",
"color:#000; background: linear-gradient(270deg, #FFB6C1, #FFF0F5, #FFC0CB); padding: 8px 15px; border-radius: 8px");
console.log("%c © BIIBII.CN | 内容均为原创或授权转发,请勿盗用",
"color:#000; background: linear-gradient(270deg, #87CEFA, #F0F8FF, #87CEEB); padding: 8px 15px; border-radius: 8px");
console.log("%c页面加载耗时<?php endCountTime(); ?>",
"color:#fff; background: linear-gradient(270deg, #986fee, #8695e6, #68b7dd, #18d7d3); padding: 8px 15px; border-radius: 8px"
);
</script>
<?php $this->options->customBodyEnd()?>
<?php $this->options->zztj(); ?>
</body>
</html>

View File

@@ -0,0 +1,94 @@
<?php
/**
* 顶部head主体内容
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<!DOCTYPE HTML>
<html lang="zh-CN" data-theme="<?php echo getThemeMode(); ?>">
<head>
<meta charset="<?php $this->options->charset(); ?>">
<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
<meta name="renderer" content="webkit">
<?php if ($this->options->isCSP): ?>
<meta http-equiv="Content-Security-Policy" content="<?php $this->options->contentCSP(); ?>">
<?php endif; ?>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
<?php if ($this->is('single')): ?>
<meta name="keywords" content="<?php echo $this->fields->keywords ?: htmlspecialchars($this->_keywords); ?>" />
<meta name="description"
content="<?php echo $this->fields->description ?: htmlspecialchars($this->_description); ?>" />
<?php $this->header('keywords=&description='); ?>
<?php else: ?>
<?php $this->header(); ?>
<?php endif; ?>
<?php if ($this->options->favicon): ?>
<link rel="shortcut icon" href="<?php $this->options->favicon(); ?>">
<?php else: ?>
<link rel="shortcut icon" href="<?php getAssets('assets/images/favicon.webp'); ?>">
<?php endif; ?>
<title><?php if ($this->_currentPage > 1) {
echo '第 '.$this->_currentPage.' 页 - ';
}
?><?php $this->archiveTitle(array(
'category' => _t('分类 %s 下的文章'),
'search' => _t('包含关键字 %s 的文章'),
'tag' => _t('标签 %s 下的文章'),
'author' => _t('%s 发布的文章'),
), '', ' - '); ?><?php $this->options->title(); ?><?php if ($this->is('index')): ?> -
<?php $this->options->description(); ?><?php endif; ?></title>
<!-- IE Out -->
<script>
if (false || (!!window.MSInputMethodContext && !!document.documentMode))
window.location.href =
'https://support.dmeng.net/upgrade-your-browser.html?referrer=' +
encodeURIComponent(window.location.href);
</script>
<!-- bootstrap -->
<link rel="stylesheet" href="<?php getAssets('assets/lib/bootstrap4/bootstrap.min.css'); ?>" type="text/css"
media="all">
<!-- iconfont -->
<link rel="stylesheet" href="<?php getAssets('assets/lib/iconfont/iconfont.min.css?v='.getVersion()); ?>"
type="text/css" media="all">
<link rel="stylesheet" href="<?php $this->options->iconfont()?>" type="text/css" media="all">
<!-- 自定义css -->
<link rel="stylesheet" href="<?php getAssets('assets/css/style.min.css?v='.getVersion()); ?>" type="text/css"
media="all">
<link rel="stylesheet" href="<?php getAssets('assets/css/widgets.min.css?v='.getVersion()); ?>" type="text/css"
media="all">
<?php if ($this->is('post') || $this->is('page')): ?>
<!-- Md样式 -->
<link rel="stylesheet" href="<?php getAssets('assets/css/markdown-style.min.css'); ?>" type="text/css" media="all">
<!--代码高亮-->
<link rel="stylesheet" href="<?php getAssets('assets/lib/prism/prism-one-dark.min.css'); ?>" type="text/css"
media="all">
<?php endif; ?>
<!-- jQuery -->
<script type="text/javascript" src="<?php getAssets('assets/lib/jquery/jquery.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/lib/jquery/jquery.lazyload.min.js'); ?>"></script>
<script type="text/javascript" src="<?php getAssets('assets/js/svg-icon.min.js?v='.getVersion()); ?>"></script>
<!-- 轮播图js+css -->
<?php if ( ! empty($this->options->indexBlock) && in_array('ShowSwiper', $this->options->indexBlock) && $this->is('index')): ?>
<link rel="stylesheet" href="<?php getAssets('assets/lib/swiper3/swiper-3.4.2.min.css'); ?>" type="text/css"
media="all">
<script type="text/javascript" src="<?php getAssets('assets/lib/swiper3/swiper-3.4.2.jquery.min.js'); ?>"></script>
<?php endif; ?>
<!-- 自定义style -->
<style>
<?php $this->options->customStyle();
?>
</style>
<?php $this->options->customHeadEnd(); ?>
</head>
<body>
<?php $this->need('components/navbar.php'); ?>
<div class="nav-fixed"></div>

View File

@@ -0,0 +1,83 @@
<?php
/**
* 顶部导航栏
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-1-6 20:05:37
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<header id="navbar" class="navbar p-2<?php echo $this->options->navStyle == 'mini' ? ' nav-ui-two' : ' nav-ui-one'; ?>">
<div class="container navbar-box p-1 p-md-2">
<div class="navbar-logo flex-shrink-0">
<a id="logo" href="<?php $this->options->siteUrl(); ?>" title="<?php $this->options->title()?>">
<?php if ($this->options->logoUrl): ?>
<img src="<?php $this->options->logoUrl(); ?>" alt="<?php $this->options->title()?>"
class="d-inline-block logo-light" />
<?php else: ?>
<span><?php $this->options->title()?></span>
<?php endif; ?>
</a>
</div>
<nav class="d-none d-md-block nav-inner">
<ul class="d-flex flex-column flex-md-row nav-menu m-0">
<li class="nav-item"><a class="nav-a <?php echo $this->is('index') ? 'active' : '' ?>"
href="<?php $this->options->siteUrl(); ?>" title="<?php $this->options->title(); ?>">首页</a></li>
<!-- 默认导航 -->
<?php $this->widget('Widget_Metas_Category_List')->to($category); ?>
<?php while ($category->next()): if ($category->levels === 0): ?>
<?php $children = $category->getAllChildren($category->mid); ?>
<?php if (empty($children)): ?>
<li class="nav-item"><a class="nav-a <?php echo $this->is('category', $category->slug) ? 'active' : '' ?>"
href="<?php $category->permalink(); ?>" target="_self"
title="<?php $category->name(); ?>"><?php $category->name(); ?></a></li>
<?php else: ?>
<li class="nav-item">
<a class="nav-a <?php echo( ! $this->is('index') && isParentActive($this->category, $category, $children)) ? 'active' : ''; ?>"
href="<?php $category->permalink(); ?>" title="<?php $category->name(); ?>"
target="_self"><?php $category->name(); ?><i class="iconfont nav-icon icon-xiala"></i></a>
<div class="pt-md-4 sub-menu">
<ul class="d-md-flex flex-md-wrap p-md-2">
<?php foreach ($children as $mid) {?>
<?php $child = $category->getCategory($mid); ?>
<li class="p-2 <?php echo $this->is('category', $child['slug']) ? ' active' : ''; ?>">
<a href="<?php echo $child['permalink'] ?>" target="_self"
title="<?php echo $child['name']; ?>"><?php echo $child['name']; ?></a>
</li>
<?php }?>
</ul>
</div>
</li>
<?php endif;
endif; ?>
<?php endwhile; ?>
<!-- 添加自定义菜单 -->
<?php echo getCustomMenu($this->request->getRequestUrl()); ?>
</ul>
</nav>
<div class="d-flex flex-row navbar-icon">
<?php if ( ! empty($this->options->indexBlock) && in_array('ShowTravelling', $this->options->indexBlock)): ?>
<div>
<a class="nav-top-item" href="https://www.travellings.cn/go.html" target="_blank" title="开往-友链接力"><i
class="iconfont icon-huoche"></i></a>
</div>
<?php endif; ?>
<div>
<a class="nav-top-item" href="<?php $this->options->siteUrl(); ?>?random=true" target="_self"
title="随机进入一篇文章"><i class="iconfont icon-random"></i></a>
</div>
<div id="search-btn" title="站内搜索"><i class="iconfont icon-search"></i></div>
<div class="flex-column align-items-center justify-content-center back-to-top" style="display: none;">
<a id="nav-backtop" class="nav-top-item" href="javascript:void(0);" role="button" title="回到顶部">
<span class="top-to-icon">回到顶部</span>
<span class="top-to-text">0</span>
</a>
</div>
<div id="menu-line" class="d-block d-md-none" title="手机端菜单栏"><i class="iconfont icon-caidan"></i></div>
</div>
</div>
</header>

View File

@@ -0,0 +1,100 @@
<?php
/**
* 文章内容
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-1-20 12:58:35
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<!-- 文章st -->
<div id="post" class="post card mt-2">
<div class="card-body">
<!-- 文章信息 -->
<div class="post-header mb-4">
<h1 class="h4 post-title font-weight-bold mb-4"><?php $this->title()?></h1>
<?php if ( ! $this->is('page')): ?>
<div class="meta d-flex align-items-center text-muted">
<div class="author-left">
<name class="d-inline-block mr-md-2"><i class="iconfont icon-zuozhe mr-1"></i><a
href="<?php $this->author->permalink(); ?>" title="由<?php $this->author(); ?>发布"
rel="author"><?php $this->author(); ?></a></name>
<time datetime="<?php $this->date('c'); ?>" class="d-inline-block"><i
class="iconfont icon-shijian mr-1"></i><?php $this->date(); ?></time>
</div>
<div class="author-right ml-auto text-sm">
<a title="浏览量" role="button"><i class="iconfont icon-liulanjilu mr-1"></i><?php PostViewCount($this); ?></a>
<a class="mx-1" href="<?php $this->permalink()?>#comments" title="评论" role="button"><i
class="iconfont icon-pinglun1 mr-1"></i><?php $this->commentsNum('0', '1', '%d'); ?></a>
</div>
</div>
<?php endif; ?>
<div class="border-theme bg-primary"></div>
</div>
<!-- 文章内容 -->
<div class="post-content markdown-body" itemprop="articleBody" view-image>
<?php $this->content(); ?>
</div>
<?php if ( ! $this->is('page')): ?>
<div class="post-end d-flex align-items-center justify-content-center my-4">THE END</div>
<!-- 文章标签+分类 -->
<div class="category-and-tags d-flex flex-wrap align-items-center">
<div class="post-category d-flex flex-wrap align-items-center mt-2">
<span class="ct-title">分类:</span><?php $this->category('', true, ''); ?>
</div>
<div class="post-tags d-flex flex-wrap align-items-center mt-2">
<?php if (count($this->tags) != 0): ?>
<span class="ct-title">标签:</span><?php $this->tags('', true, ''); ?>
<?php endif; ?>
</div>
</div>
<!-- 分享+赞助 -->
<div class="post-tools d-flex justify-content-center mt-4">
<div class="post-tools-item d-flex flex-column align-items-center">
<button class="btn" id="poster-btn" title="文章海报"><i class="iconfont icon-haibao"></i></button>
<span class="post-tools-title">海报</span>
</div>
<div class="post-tools-item d-flex flex-column align-items-center">
<button class="btn" id="reward-btn" title="赞赏作者"><i class="iconfont icon-zanshangma"></i></button>
<span class="post-tools-title">赞赏</span>
</div>
<div class="post-tools-item d-flex flex-column align-items-center">
<button class="btn" id="share-btn" title="分享文章"><i class="iconfont icon-fenxiang1"></i></button>
<span class="post-tools-title">分享</span>
</div>
</div>
<!-- 版权声明 -->
<div class="post-copyright mt-4 p-3">
<div class="copyright-content">
<div class="copyright-title">&#169版权申明</div>
<p class="copyright-desc"><span class="ml-3"></span>- 本文由作者 <a href="<?php $this->author->permalink(); ?>"
title="<?php $this->author(); ?>">@<?php $this->author(); ?></a>
原创发布在<?php $this->options->title(); ?>站点。未经许可,禁止转载。</p>
</div>
<div class="copyright-svgname animated-signature svg-name">
<?php $this->options->svgName(); ?>
</div>
</div>
<?php endif; ?>
</div>
</div>
<!-- 文章en -->
<!-- 下一篇、上一篇 -->
<?php if ( ! $this->is('page')): ?>
<div class="post-next-prev d-flex justify-content-between my-4">
<div class="post-next card p-2 p-md-3 text-left">
<div class="next-prev-title text-webkit-mask font-weight-bold">上一篇</div>
<?php $this->thePrev('%s', '没有了'); ?>
</div>
<div class="post-prev card p-2 p-md-3 text-right">
<div class="next-prev-title text-webkit-mask font-weight-bold">下一篇</div>
<?php $this->theNext('%s', '没有了'); ?>
</div>
</div>
<?php endif; ?>
<!--文章评论-->
<?php $this->need('components/comments.php'); ?>

View File

@@ -0,0 +1,173 @@
<?php
/**
* 文章列表
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php
/** 文章置顶 */
$sticky = $this->options->sticky;
if ($sticky && $this->is('index') || $this->is('front')) {
$sticky_cids = explode(',', $sticky); //分割文本
$cid_count = count($sticky_cids);
$sticky_html = "<span style='color:red'>[置顶] </span>"; //置顶标题的 html
$db = Typecho_Db::get(); // 获取数据库
$pageSize = $this->parameter->pageSize - $cid_count; // 每页显示文章数
$select1 = $this->select()->where('type = ?', 'post'); // 获取文章1
$select2 = $this->select()->where('type = ? && status = ? && created < ?', 'post', 'publish', time()); // 获取文章2
//清空原有文章的列队
$this->row = array();
$this->stack = array();
$this->length = 0;
$order = '';
foreach ($sticky_cids as $i => $cid) {
if ($i == 0) {
$select1->where('cid = ?', $cid);
} else {
$select1->orWhere('cid = ?', $cid);
}
$order .= " when $cid then $i";
$select2->where('table.contents.cid != ?', $cid); //避免重复
}
if ($order) {
$select1->order('', "(case cid$order end)");
}
//置顶文章的顺序 按 $sticky 中 文章ID顺序
if ($this->_currentPage == 1 || $this->currentPage == 1) {
foreach ($db->fetchAll($select1) as $sticky_post) { //首页第一页才显示
$sticky_post['sticky'] = $sticky_html;
$this->push($sticky_post); //压入列队
}
}
$uid = $this->user->uid; //登录时,显示用户各自的私密文章
if ($uid) {
$select2->orWhere('authorId = ? && status = ?', $uid, 'private');
}
$sticky_posts = $db->fetchAll($select2->order('table.contents.created', Typecho_Db::SORT_DESC)->page($this->_currentPage, $pageSize));
foreach ($sticky_posts as $sticky_post) {
$this->push($sticky_post);
}
//压入列队
$this->setTotal($this->getTotal()); //置顶文章不计算在所有文章内
} ?>
<div class="post-main">
<div class="row no-gutters post-list">
<?php while ($this->next()): ?>
<div class="col-6 col-md-4 col-xl-4 d-flex">
<div class="post-item d-flex flex-column m-1 m-md-2 p-0">
<div class="post-cover">
<a href="<?php $this->permalink() ?>" title="<?php $this->title() ?>">
<img class="lazy" src="<?php getLazyload(); ?>" data-original="<?php echo getImgLink($this); ?>"
alt="<?php $this->title() ?>" />
</a>
</div>
<div class="post-info d-flex flex-column align-content-center justify-content-between p-1 p-md-2">
<div class="post-head">
<a href="<?php $this->permalink() ?>"
title="<?php $this->title() ?>"><?php $this->sticky() ?><?php $this->title() ?></a>
<div class="post-description">
<?php echo $this->fields->abstract ?: $this->excerpt(100, '...'); ?>
</div>
</div>
<div class="post-meta-wrap d-flex justify-content-between">
<div class="author-name"><?php $this->category('/'); ?></div>
<div class="post-meta">
<time datetime="<?php $this->date('c'); ?>"
class="post-meta-item"><?php echo ueTimeMini($this->date); ?></time>
</div>
</div>
</div>
</div>
</div>
<?php endwhile; ?>
</div>
<!-- 分页 -->
<nav class="mt-4">
<?php
ob_start();
$this->pageNav(
'<i class="iconfont icon-shangyiye"></i>',
'<i class="iconfont icon-xiayiye"></i>',
1,
'',
array(
'wrapTag' => 'ul',
'wrapClass' => 'pagination justify-content-center',
'itemTag' => 'li',
'textTag' => 'span',
'currentClass' => 'active',
'prevClass' => 'prev',
'nextClass' => 'next',
)
);
$content = ob_get_contents();
ob_end_clean();
// 删除省略号等无内容项
$content = preg_replace("/<li><span>(.*?)<\/span><\/li>/sm", '<li class="page-item"><span class="page-link p-0 w-100 h-100 d-flex align-items-center justify-content-center">...</span></li>', $content);
// 规范化分页项类名
$content = preg_replace(array(
"/<li class=\"active\">(.*?)<\/li>/sm",
"/<li class=\"prev\">(.*?)<\/li>/sm",
"/<li class=\"next\">(.*?)<\/li>/sm",
"/<li>(.*?)<\/li>/sm",
), array(
'<li class="page-item active">$1</li>',
'<li class="page-item prev">$1</li>',
'<li class="page-item next">$1</li>',
'<li class="page-item">$1</li>',
), $content);
// 智能生成 title 的核心逻辑
$content = preg_replace_callback(
"/<a href=\"(.*?)\">(.*?)<\/a>/sm",
function ($matches) {
$href = $matches[1];
$linkContent = $matches[2];
// 判断链接类型
if (strpos($linkContent, 'icon-shangyiye') !== false) {
$title = '上一页';
} elseif (strpos($linkContent, 'icon-xiayiye') !== false) {
$title = '下一页';
} else {
// 从 URL 中提取页码(适配 /page/2/ 格式)
preg_match('/\/page\/(\d+)\/$/', $href, $pageMatch);
$page = $pageMatch[1] ?? 1;
$title = "第{$page}页";
}
// 构建安全的 title 属性
$safeTitle = htmlspecialchars($title, ENT_QUOTES);
// 返回优化后的 HTML
return sprintf(
'<a class="page-link p-0 w-100 h-100 d-flex align-items-center justify-content-center" href="%s" title="%s">%s</a>',
$href,
$safeTitle,
$linkContent
);
},
$content
);
echo $content;
?>
</nav>
</div>

View File

@@ -0,0 +1,43 @@
<?php
/**
* 搜索框
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-5-30 12:57:51
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<div class="main-search">
<div class="site-search d-flex justify-content-center">
<div class="pop-tool-box search-box card no-animation p-3">
<div class="search-name mb-4">
<h5>搜索</h5>
</div>
<div class="search-form">
<form id="search" method="post" action="<?php $this->options->siteUrl(); ?>" role="search">
<input type="text" id="s" name="s" class="form-control" placeholder="<?php _e('输入关键字搜索'); ?>" />
<button type="submit" class="btn p-0 site-search-btn"><i class="iconfont icon-sousuo"></i></button>
</form>
</div>
<div class="category-and-tags">
<div class="post-tags d-flex flex-wrap mt-4">
<?php $this->widget('Widget_Metas_Tag_Cloud', 'ignoreZeroCount=1&limit=15')->to($tags); ?>
<?php if ($tags->have()): ?>
<?php while ($tags->next()): ?>
<a href="<?php $tags->permalink(); ?>" rel="tag" title="<?php $tags->count(); ?> 个话题"><?php $tags->name(); ?>
(<?php $tags->count(); ?>)</a>
<?php endwhile; ?>
<?php else: ?>
<div><?php _e('没有任何标签'); ?></div>
<?php endif; ?>
</div>
</div>
<div id="search-close-btn" class="close-btn"><i id="close-btn" class="iconfont icon-guanbi"></i></div>
</div>
</div>
<div class="pop-tool-overlay-bg"></div>
</div>

View File

@@ -0,0 +1,35 @@
<?php
/**
* 侧边栏
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if ( ! isMobile()): ?>
<div class="main-sidebar col-lg-3 pt-2 pl-lg-3 pl-xl-3 pr-lg-2 pr-xl-2 d-none d-lg-block">
<?php if ($this->is('post') || $this->is('page')): ?>
<?php require_once 'widgets/widget-blogger.php'; ?>
<?php require_once 'widgets/widget-hotposts.php'; ?>
<div class="sidebar-list sticky-top sidebar-sticky mt-3">
<?php require_once 'widgets/widget-articletoc.php'; ?>
</div>
<?php else: ?>
<?php require_once 'widgets/widget-yiyan.php'; ?>
<?php require_once 'widgets/widget-weather.php'; ?>
<?php require_once 'widgets/widget-blogsignage.php'; ?>
<?php require_once 'widgets/widget-devileyes.php'; ?>
<div class="sticky-top sidebar-sticky mt-3">
<?php //require_once 'widgets/widget-blogger.php';
?>
<?php require_once 'widgets/widget-hotposts.php'; ?>
<?php require_once 'widgets/widget-newreply.php'; ?>
</div>
<?php endif; ?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,26 @@
<?php
/**
* 文章目录
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php $tocData = getCatalog();
if ($this->is('post') && $tocData): ?>
<!-- 文章目录 -->
<div class="hh-widget widget-toc-main mt-3 p-3">
<div class="widget-title mb-2">
<div class="widget-title-top-bg" style="background:var(--atoc-h-bg);"></div>
<i class="iconfont icon-mulu mr-1"></i>文章目录
</div>
<div class="atoc-content ml-2">
<?php echo $tocData; ?>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,61 @@
<?php
/**
* 博主信息
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if (! empty($this->options->sidebarBlock) && in_array('ShowAboutMe', $this->options->sidebarBlock)): ?>
<?php $stat = Typecho_Widget::widget('Widget_Stat'); ?>
<?php $isOnline = isAdminOnline(); // 是否在线
?>
<!-- 博主信息 -->
<div class="hh-widget">
<div class="author-content p-3 d-flex flex-column justify-content-center">
<div class="author-info-avatar">
<img class="avatar-img widget-lazy" src="<?php getLazyload(); ?>"
data-original="<?php echo getGravatar($this->authorId ? $this->author->mail : $this->user->mail) ?>"
alt="<?php $this->authorId ? $this->author->screenName() : $this->user->screenName(); ?>" />
<span class="author-oneline<?php echo $isOnline ? '' : ' author-offline' ?>"
title="博主今天<?php echo $isOnline ? '在线' : '离线' ?>"></span>
</div>
<div class="d-flex flex-column my-2">
<span
class="author-nickname text-center"><?php $this->authorId ? $this->author->screenName() : $this->user->screenName(); ?></span>
<span class="author-text text-center"><?php $this->options->blogmeabout(); ?></span>
</div>
<div class="row blog-count-box no-gutters">
<div class="col-3">
<div class="blog-count-item d-flex flex-column align-items-center justify-content-center">
<span>文章</span>
<span><?php $stat->publishedPostsNum() ?></span>
</div>
</div>
<div class="col-3">
<div class="blog-count-item d-flex flex-column align-items-center justify-content-center">
<span>分类</span>
<span><?php $stat->categoriesNum() ?></span>
</div>
</div>
<div class="col-3">
<div class="blog-count-item d-flex flex-column align-items-center justify-content-center">
<span>评论</span>
<span><?php $stat->publishedCommentsNum() ?></span>
</div>
</div>
<div class="col-3">
<div class="blog-count-item d-flex flex-column align-items-center justify-content-center">
<span>标签</span>
<span><?php $stat->TagsNum() ?></span>
</div>
</div>
</div>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,27 @@
<?php
/**
* 博客路牌
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-9-22 14:39:24
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if ( ! empty($this->options->sidebarBlock) && in_array('ShowBlogSignage', $this->options->sidebarBlock)): ?>
<!-- 博客路牌 -->
<div class="hh-widget mt-3">
<div class="blogsignage-widget">
<div class="blogsignage-head d-flex justify-content-center align-items-center font-weight-bold">
<?php $this->options->blogSignageText(); ?></div>
<div class="blogsignage-foot p-2 d-flex justify-content-between align-items-center">
<div class="blogsignage-foot-west"><i class="iconfont icon-xiala"></i>西</div>
<div class="blogsignage-foot-center"><?php $this->options->title(); ?>站</div>
<div class="blogsignage-foot-east">东<i class="iconfont icon-xiala"></i></div>
</div>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,29 @@
<?php
/**
* 恶魔之眼
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-5-29 16:36:08
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if (! empty($this->options->sidebarBlock) && in_array('ShowDevilEyes', $this->options->sidebarBlock)): ?>
<!-- 恶魔之眼 -->
<div class="hh-widget mt-3">
<div class="devil-widget py-2">
<div class="devil-content d-flex flex-row align-items-center justify-content-around">
<div class="devil-eye-left px-2">
<div class="devil-eye-o"></div>
</div>
<div class="devil-eye-right px-2">
<div class="devil-eye-o"></div>
</div>
</div>
<div class="devil-text text-center">小恶魔已巡视站点<?php echo getWebsiteAgeInDays($this->options->sitedate); ?>天</div>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,30 @@
<?php
/**
* 首页底部Hello
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if (! empty($this->options->indexBlock) && in_array('ShowHello', $this->options->indexBlock) && $this->is('index')): ?>
<?php $helloTxt = $this->options->helloText; ?>
<div class="hh-widget mb-3">
<div class="hello-widget">
<img class="widget-lazy" src="<?php getLazyload(); ?>" data-original="<?php getRandImg(); ?>"
alt="<?php echo $helloTxt ?>" />
<div class="hello-content d-flex flex-column justify-content-center align-items-center">
<span class="hello-text"><?php echo $helloTxt; ?></span>
</div>
<div class="hello-btn-group">
<a href="/harmonyhues.html" class="py-1 px-2 hello-btn-item" title="关于主题" target="_self">@主题</a>
<a href="/about.html" class="py-1 px-2 hello-btn-item" title="关于博主" target="_self">@博主</a>
<a href="/links.html" class="py-1 px-2 hello-btn-item" title="友情链接" target="_self">@朋友</a>
</div>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,52 @@
<?php
/**
* 热门文章
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if ( ! empty($this->options->sidebarBlock) && in_array('ShowHotPosts', $this->options->sidebarBlock)): ?>
<?php
function getHotPostsCid($limit = 10) {
$db = Typecho_Db::get();
$select = $db->select('cid')
->from('table.contents')
->where('type = ?', 'post')
->where('status = ?', 'publish')
->order('views', Typecho_Db::SORT_DESC)
->limit($limit);
$posts = $db->fetchAll($select);
return $posts;
}
$hotPostsCid = getHotPostsCid(6);
?>
<!-- 热门文章 -->
<div class="hh-widget mt-3 p-3">
<div class="widget-title mb-3">
<div class="widget-title-top-bg" style="background:var(--hotposts-h-bg);"></div>
<i class="iconfont icon-remen mr-1"></i>热门文章
</div>
<div class="widget-content hotposts-widget scroll-cover">
<ul class="hotposts-list">
<?php foreach ($hotPostsCid as $index => $postcid): ?>
<?php $post = Helper::widgetById('Contents', $postcid['cid']); ?>
<?php $postTitle = htmlspecialchars($post->title); ?>
<li class="hotposts-item">
<a class="hotposts-title" href="<?php $post->permalink(); ?>" title="<?php echo $postTitle; ?>">
<span class="hotposts-number mr-1"><?php echo $index + 1; ?></span><?php echo $postTitle; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,58 @@
<?php
/**
* 最新评论
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if ( ! empty($this->options->sidebarBlock) && in_array('ShowSidebarComments', $this->options->sidebarBlock) && ! $this->is('post')): ?>
<?php
function parseCommentContens($content) {
$content = parseContens($content);
$content = preg_replace('#<br>#si', '', $content); // 去除换行
return $content;
}
?>
<!-- 最新评论 -->
<div class="hh-widget mt-3 p-3">
<div class="widget-title mb-3">
<div class="widget-title-top-bg" style="background:var(--newreply-h-bg);"></div>
<i class="iconfont icon-pinglun1 mr-1"></i>最新评论
</div>
<div class="widget-content newreply-widget scroll-cover">
<!-- 评论项模板 -->
<?php $this->widget('Widget_Comments_Recent', 'ignoreAuthor=true&pageSize=5')->to($item); ?>
<?php if ($item->have()): ?>
<?php while ($item->next()): ?>
<div class="newreply-item mb-2">
<div class="comment-info d-flex align-items-center">
<div class="comment-avatar">
<img class="avatar-img widget-lazy" src="<?php getLazyload(); ?>"
data-original="<?php echo getGravatar($item->mail); ?>" alt="<?php $item->author(false)?>">
</div>
<div class="comment-name ml-2">
<a href="<?php $item->url()?>" title="<?php $item->author(false)?>"
target="_blank"><?php $item->author(false)?></a>
</div>
</div>
<div class="comment-content mt-1 p-2">
<a href="<?php echo $item->permalink; ?>" title="<?php echo $item->title.'评论' ?>">
<div class="comment-content-text"><?php echo parseCommentContens($item->content); ?></div>
</a>
</div>
</div>
<?php endwhile; ?>
<?php else: ?>
<div class="empty text-center">人气很差!一条回复都没有!</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,101 @@
<?php
/**
* 轮播幻灯片
*
* @author 星语社长
* @link https://biibii.cn
* @update 2025-2-11 17:12:15
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if (! empty($this->options->indexBlock) && in_array('ShowSwiper', $this->options->indexBlock) && $this->is('index')): ?>
<?php
function slidesHtml($content)
{
// 预处理输入内容
$cleanedContent = trim($content ?? '');
if ($cleanedContent === '') {
echo '幻灯片的数据为空或格式无效';
return;
}
$slidesHtml = '';
foreach (preg_split('/\r?\n|\r/', $cleanedContent) as $line) {
// 忽略空行
$line = trim($line);
if ($line === '') {
continue;
}
// 分割并处理字段
$parts = explode('|', $line);
if (count($parts) !== 5) {
continue;
}
// 字段处理管道
$fields = array_map(function ($field) {
$field = trim($field);
return $field === 'NULL' ? '' : $field;
}, $parts);
$title = @htmlspecialchars($fields[0]);
$description = @htmlspecialchars($fields[1]);
$label = @htmlspecialchars($fields[2]);
$image = @htmlspecialchars($fields[3] ?: getRandImg(false));
$link = @htmlspecialchars($fields[4]);
// 获取文件扩展名
$extension = strtolower(pathinfo($image, PATHINFO_EXTENSION));
// 生成HTML
$slidesHtml .= '<div class="swiper-slide">';
$slidesHtml .= '<a href="' . $link . '" target="_blank" title="' . ($title ?: $description) . ' - 点击前往">';
if ($extension === 'mp4') {
$slidesHtml .= '<video class="swiper-slide-video" autoplay loop muted playsinline>';
$slidesHtml .= '<source src="' . $image . '" type="video/mp4">';
$slidesHtml .= '</video>';
} else {
$slidesHtml .= '<img class="swiper-lazy" src="' . getLazyload(false) . '" data-src="' . $image . '" alt="' . ($title ?: $description) . '图片">';
}
$slidesHtml .= empty($label) ? '' : '<div class="px-2 py-1 swiper-slide-label">' . $label . '</div>';
if (! empty($title) || ! empty($description)) {
$slidesHtml .= '<div class="swiper-slide-content px-2 pb-2">';
$slidesHtml .= empty($title) ? '' : '<div class="swiper-slide-title font-weight-bold" data-swiper-parallax-x="-200" data-swiper-parallax-duration="1200">' . $title . '</div>';
$slidesHtml .= empty($description) ? '' : '<p class="swiper-slide-description m-0" data-swiper-parallax-x="-210" data-swiper-parallax-duration="1200">' . $description . '</p>';
$slidesHtml .= '</div>';
}
$slidesHtml .= '</a></div>';
}
// 检查生成的HTML是否为空
if ($slidesHtml === '') {
echo '幻灯片的数据为空或格式无效';
return;
}
echo $slidesHtml;
}
$swiperText = $this->options->swiperText;
?>
<!-- 轮播幻灯片 -->
<div class="card w-auto m-1 m-md-2 swiper-widget">
<div class="swiper-container">
<div class="swiper-wrapper"><?php slidesHtml($swiperText) ?></div>
<div class="swiper-pagination d-flex align-items-center mx-1"></div>
<div class="d-flex justify-content-center align-items-center m-2 swiper-button-wrapper">
<div class="swiper-button-prev d-flex justify-content-center align-items-center" title="上一张"><i
class="iconfont icon-shangyizhang p-1"></i></div>
<div class="swiper-button-next d-flex justify-content-center align-items-center" title="下一张"><i
class="iconfont icon-xiayizhang p-1"></i></div>
</div>
</div>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,144 @@
<?php
/**
* 首页底部时间之旅
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if (! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if (! empty($this->options->indexBlock) && in_array('ShowTimeJourney', $this->options->indexBlock) && $this->is('index')): ?>
<?php
// 获取建站日期比如2023-08-20
$siteCreationDate = new DateTime($this->options->sitedate);
/**
* 计算日期进度(已过去天数、剩余天数、百分比)
*/
function calculateDateProgress(DateTime $startDate, DateTime $endDate, DateTime $currentDate): array
{
// 计算从开始日期到结束日期的总时间间隔
$totalInterval = $startDate->diff($endDate);
// 获取总天数
$totalDays = $totalInterval->days;
// 计算从开始日期到当前日期的时间间隔
$passedInterval = $startDate->diff($currentDate);
// 获取已过去的天数
$passedDays = $passedInterval->days;
// 计算剩余的天数
$remainingDays = $totalDays - $passedDays;
// 计算已过去的天数占总天数的百分比
$passedPercentage = ($passedDays / $totalDays) * 100;
// 计算剩余的天数占总天数的百分比
$remainingPercentage = ($remainingDays / $totalDays) * 100;
// 返回一个包含所有计算结果的数组
return array(
'total_days' => $totalDays, // 总天数
'passed_days' => $passedDays, // 已过去的天数
'remaining_days' => $remainingDays, // 剩余的天数
'passed_percentage' => round($passedPercentage, 0), // 已过去的天数百分比,四舍五入到整数
'remaining_percentage' => round($remainingPercentage, 0), // 剩余的天数百分比,四舍五入到整数
);
}
/**
* 替换字符串中的占位符
*/
function replacePlaceholders(string $description, float $remainingPercentage, float $passedPercentage): string
{
// 替换剩余百分比占位符
$description = str_replace('{remainingPercentage}', $remainingPercentage, $description);
// 替换已过去百分比占位符
$description = str_replace('{progressPercentage}', $passedPercentage, $description);
return $description;
}
/**
* 处理输入字符串并返回处理后的结果
*/
function processEventString(string $input, DateTime $siteCreationDate)
{
// 分割字符串
$parts = explode('|', $input);
// 检查是否分割为4个部分
if (count($parts) !== 4) {
return false; // 输入格式不正确
}
// 提取并验证日期部分
$eventDate = trim($parts[0]);
if (! preg_match('/^\d{4}-\d{2}-\d{2}$/', $eventDate)) {
return false; // 日期格式不正确
}
// 将事件日期转换为 DateTime 对象
$eventDate = new DateTime($eventDate);
// 获取当前日期
$currentDate = new DateTime();
// 计算日期进度
$progress = calculateDateProgress($siteCreationDate, $eventDate, $currentDate);
// 替换描述中的占位符
$description = $parts[3];
$description = replacePlaceholders($description, $progress['remaining_percentage'], $progress['passed_percentage']);
// 返回处理后的结果
return array(
'date' => $eventDate->format('Y-m-d'),
'unit' => trim($parts[1]),
'title' => trim($parts[2]),
'description' => $description,
'progress' => $progress,
);
}
// 例如2025-03-26|天|星际旅行|{remainingPercentage|progressPercentage}
$timeJourneyText = $this->options->timeJourneyText;
$processedEvent = processEventString($timeJourneyText, $siteCreationDate);
// 测试->输出处理后的结果
// echo '事件日期: '.$processedEvent['date']."\n";
// echo '单位: '.$processedEvent['unit']."\n";
// echo '标题: '.$processedEvent['title']."\n";
// echo '描述: '.$processedEvent['description']."\n";
// echo '总天数: '.$processedEvent['progress']['total_days']."\n";
// echo '已过去天数: '.$processedEvent['progress']['passed_days']."\n";
// echo '剩余天数: '.$processedEvent['progress']['remaining_days']."\n";
// echo '已过去百分比: '.$processedEvent['progress']['passed_percentage']."%\n";
// echo '剩余百分比: '.$processedEvent['progress']['remaining_percentage']."%\n";
?>
<div class="hh-widget mb-3">
<?php if ($processedEvent): ?>
<?php $passedPercentage = $processedEvent['progress']['passed_percentage']; ?>
<div class="timejourney-widget">
<div id="timejourney-progress" class="timejourney-progress d-flex align-items-center justify-content-end p-2"
data-percentage="<?php echo $passedPercentage; ?>">
<?php echo $passedPercentage . '%'; ?>
</div>
<div class="timejourney-content px-2 py-1">
<div class="timejourney-text">
<span class="timejourney-day"><?php echo $processedEvent['progress']['passed_days']; ?></span>
<span class="timejourney-unit"><?php echo $processedEvent['unit']; ?></span>
</div>
<div class="timejourney-desc"><?php echo $processedEvent['title'] . ' | '; ?>
<?php echo $processedEvent['description']; ?></div>
</div>
</div>
<?php else: ?>
<div class="text-center">时间之旅格式不正确或日期验证失败。请输入正确的格式例如2025-03-26|天|星际旅行|本站服务器燃料剩余{remainingPercentage}%</div>
<?php endif; ?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,111 @@
<?php
/**
* 天气小部件
*
* @author 星语社长
* @link https://biibii.cn
* @update 2026-03-03
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
// 只有在侧边栏开启且不是文章页面时显示
if ( ! empty($this->options->sidebarBlock) && in_array('ShowSidebarWeather', $this->options->sidebarBlock) && ! $this->is('post')): ?>
<?php
// 获取配置信息
$city = trim($this->options->weatherCity ?: 'Beijing');
$apiKey = trim($this->options->weatherApiKey ?: '');
$cacheFile = dirname(__DIR__, 2) . '/assets/weather_cache.json';
// 缓存机制:记录城市和时间,过期 1 小时,城市变更时自动失效
function hh_fetch_weather($city, $apiKey, $cacheFile) {
if (file_exists($cacheFile)) {
$raw = @file_get_contents($cacheFile);
$cached = $raw ? json_decode($raw, true) : null;
// 缓存结构:{"city":"xxx","timestamp":12345678,"data":{…}}
if ($cached && isset($cached['city'], $cached['timestamp'], $cached['data'])) {
if ($cached['city'] === $city && time() - $cached['timestamp'] < 3600) {
return $cached['data'];
}
}
}
if (empty($apiKey) || empty($city)) {
return null;
}
$url = 'https://api.openweathermap.org/data/2.5/weather?q=' . urlencode($city)
. '&appid=' . $apiKey . '&units=metric&lang=zh_cn';
$json = @file_get_contents($url);
if ($json) {
$payload = json_encode([
'city' => $city,
'timestamp' => time(),
'data' => json_decode($json, true),
]);
@file_put_contents($cacheFile, $payload);
return json_decode($json, true);
}
return null;
}
$weather = hh_fetch_weather($city, $apiKey, $cacheFile);
// 用于调试:在 HTML 注释中输出参数和值,方便查看
$reqUrl = 'https://api.openweathermap.org/data/2.5/weather?q=' . urlencode($city)
. '&appid=' . $apiKey . '&units=metric&lang=zh_cn';
?>
<!-- weather widget debug: city=<?php echo htmlspecialchars($city, ENT_QUOTES); ?>, key_len=<?php echo strlen($apiKey); ?>, url=<?php echo htmlspecialchars($reqUrl, ENT_QUOTES); ?>, allow_url_fopen=<?php echo ini_get('allow_url_fopen') ? 'on' : 'off'; ?>, last_err=<?php $e = error_get_last(); echo $e ? htmlspecialchars($e['message'], ENT_QUOTES) : 'none'; ?> -->
<div class="hh-widget mt-3 weather-widget" style="font-size:0.9rem;line-height:1.4;">
<?php if ($weather && isset($weather['weather'][0])): ?>
<?php
// 语言友好的城市显示(中英文互译)
function hh_display_city($inputCity, $weather) {
static $map = [
'Beijing' => '北京',
'Guangzhou' => '广州',
'Shenzhen' => '深圳',
'Shanghai' => '上海',
'Chengdu' => '成都',
// 可根据需要继续添加
];
if (isset($map[$inputCity])) {
return $map[$inputCity];
}
if (isset($map[$weather['name']])) {
return $map[$weather['name']];
}
return $weather['name'];
}
$displayCity = hh_display_city($city, $weather);
$w = $weather['weather'][0];
$m = $weather['main'];
$wind = $weather['wind'] ?? [];
$iconUrl = 'https://openweathermap.org/img/wn/' . $w['icon'] . '@2x.png';
?>
<div class="weather-header" style="display:flex;align-items:center;justify-content:center;">
<img src="<?php echo $iconUrl; ?>"
alt="<?php echo htmlspecialchars($w['description'], ENT_QUOTES); ?>"
style="width:48px;height:48px;margin-right:8px;">
<div style="text-align:left;">
<p style="margin:0;font-weight:bold;line-height:1;"><?php echo $displayCity; ?></p>
<p style="margin:0;line-height:1;"><?php echo $w['description']; ?> <?php echo $m['temp']; ?>°C</p>
</div>
</div>
<div class="weather-details" style="font-size:0.85rem;color:#555;text-align:center;margin-top:4px;">
<p style="margin:0;">体感:<?php echo $m['feels_like']; ?>°C湿度<?php echo $m['humidity']; ?>%;气压:<?php echo $m['pressure']; ?> hPa</p>
<?php if (!empty($wind)): ?>
<p style="margin:0;">风速:<?php echo $wind['speed']; ?> m/s<?php
if (isset($wind['deg'])) echo ',方向:' . $wind['deg'] . '°'; ?></p>
<?php endif; ?>
</div>
<?php elseif ($weather && isset($weather['cod']) && $weather['cod'] != 200): ?>
<p>天气接口错误:<?php echo htmlspecialchars($weather['message'] ?? '未知', ENT_QUOTES); ?></p>
<?php else: ?>
<p>天气获取失败</p>
<?php endif; ?>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,80 @@
<?php
/**
* 一言
*
* @author 星语社长
* @link https://biibii.cn
* @update 2024-7-6 18:00:04
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
?>
<?php if ( ! empty($this->options->sidebarBlock) && in_array('ShowSidebarYiyan', $this->options->sidebarBlock) && ! $this->is('post')): ?>
<?php
function getYiyan() {
// 主题根目录绝对路径(本文件在 components/widgets
$themeRoot = dirname(__DIR__, 2);
// 获取句子文件的本地路径,避免通过 HTTP 请求
$filePath = $themeRoot . '/assets/yiyan/yiyan.txt';
// 读取文件内容,忽略空行
$lines = @file($filePath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if ($lines) {
// 随机选择一句
$randomLine = $lines[array_rand($lines)];
return explode('——', $randomLine);
} else {
return array('一言为空或读取失败。', '——');
}
}
function getGreeting() {
// 获取当前时间的小时数24 小时制)
$hour = date('H');
// 根据时间判断问候语
if ($hour >= 5 && $hour < 9) {
return '早上好!';
} elseif ($hour >= 9 && $hour < 12) {
return '上午好!';
} elseif ($hour >= 12 && $hour < 14) {
return '中午好!';
} elseif ($hour >= 14 && $hour < 18) {
return '下午好!';
} elseif ($hour >= 18 && $hour < 23) {
return '晚上好!';
} else {
return '夜深了,早点休息哦!';
}
}
// 随机一言图
$randImg = getAssets('assets/yiyan/'.rand(1, 20).'.webp', false);
?>
<!-- 一言 -->
<div class="hh-widget mt-3">
<div class="yiyan-widget">
<div class="yiyan-date p-2">
<p class="m-0"><?php echo getGreeting(); ?></p>
<p class="m-0"><span class="yiyan-day"><?php echo date('d'); ?></span>/<span
class="yiyan-month"><?php echo date('m'); ?></span></p>
</div>
<div class="yiyan-refresh-btn" title="刷新一言"><i onclick="location.reload()" class="iconfont icon-yuan"></i></div>
<div class="yiyan-content d-flex flex-column justify-content-between">
<div class="yiyan-cover">
<img data-original="<?php echo $randImg; ?>" src="<?php getLazyload(); ?>" alt="一言壁纸"
class="yiyan-img widget-lazy" />
</div>
<?php $yiyan = getYiyan(); ?>
<div class="yiyan-text p-2">
<p class="yiyan-quote m-0" title="<?php echo $yiyan[0]; ?>"><?php echo $yiyan[0]; ?></p>
<p class="yiyan-author text-right m-0" title="<?php echo $yiyan[1]; ?>">——<?php echo $yiyan[1]; ?></p>
</div>
</div>
</div>
</div>
<?php endif; ?>