每次更改或新增代码后,一定要及时查看控制台是否有报错,使用PC和移动端多次访问确保无误!!!
网站设置
网站后台设置基于宝塔面板。
备份设置
需要备份的东西都直接在宝塔后台备份就行,备份网站程序和数据库两个压缩包文件就行了。如果重装网站后更改了数据库账号密码,那么就直接在Typecho
程序根目录下的config.inc.php
文件中第56行更改数据库连接设置就行了:
/** 定义数据库参数 */
$db->addServer(array (
'host' => 'localhost',
'user' => '****',
'password' => '******',
'charset' => 'utf8',
'port' => '*******',
'database' => '******',
), Typecho_Db::READ | Typecho_Db::WRITE);
网站所有都调整完毕后,可以在宝塔后台安装七牛云官方备份程序:
可以自动将程序备份至七牛云账户。
伪静态设置
在宝塔网站设置中添加伪静态规则:
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php$1 last;
}
然后在Typecho后台设置地址重写:
CDN加速
将主题下的assets
文件夹全部复制至七牛云CDN,使用CDN加速全部主题资源。
本站主题资源assets
资源已全部放入七牛云CDN,如果需要进行文件修改,修改后需要在七牛云CDN中的刷新预取
中刷新文件链接才会完成文件更新。
使用自制404页面
在宝塔后台打开网站配置文件,取消注释第28行:
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
error_page 404 /404.html;
然后在站点根目录重写404.html
。
流量限制
后台登陆加密
SQL语句学习
将cid=1651
的文章评论全部转移至cid=1561
的文章下面:
update typecho_comments set cid=1561 where cid=1651;
在typecho_contents
表中选择cid=1390
的文章:
SELECT * FROM `typecho_contents` WHERE cid=1390;
插件设置
ExSearch
第一次使用该插件需要重建索引。
该插件中不能引入JQuery
,因为在主题中已经引入,如果再次引入,博客主页会出现空白。
Meting
问题:网易云歌单只能解析第一首歌曲,网易云无论是自己收藏的歌单还是公开歌单,均只能获取第一首,歌手与专辑正常。
解决方案:插件后台填写网易云音乐Cookie。获取方法:打开 https://music.163.com/ ,F12-网络-再次刷新找到 music.163.com项,点击进去找到 cookie的值复制。
如果网站开启PJAX局部刷新,需要设置重载函数:
loadMeting(); // 跳转页面后重新解析播放器
if (typeof aplayers !== 'undefined') { // 跳转页面后暂停播放
for (var i = 0; i < aplayers.length; i++) {
try {
aplayers[i].destroy()
} catch (e) {}
}
}
解决(APlayer-Typecho)插件失效问题:可以通过替换插件中的include/Meting.php
解决。访问地址:https://github.com/metowolf/Meting,然后复制src/Meting.php
代码到插件中QQ音乐即可恢复。原因是插件中的Meting版本为(1.5.2)太过老旧,更换为最新的Meting(1.5.11)即可。
音乐播放提示:
// Meting 音乐播放提示
$('.aplayer-body').each(function () {
// 单曲模块播放
$(this).find('div.aplayer-pic').click(function () {
let songTitle = $(this).next().find('.aplayer-title').text(),
songAuthor = $(this).next().find('.aplayer-author').text();
if (!$(this).find("*").eq(0).hasClass('aplayer-play')) {
VOID.alert('开始播放<b>' + songAuthor + '</b>的<b>《' + songTitle + '》</b>~')
} else {
VOID.alert('音乐已暂停~')
}
})
// 歌单列表播放模块
$(this).next().find('ol>li').click(function () {
let songTitle = $(this).find('.aplayer-list-title').text(),
songAuthor = $(this).next().find('.aplayer-list-author').text();
VOID.alert('开始播放<b>' + songAuthor + '</b>的<b>《' + songTitle + '》</b>~')
})
})
Sticky
美化代码:
<style>
.pin-top {
color: red;
color: white;
padding: 4px 26px;
background: red;
z-index: 99999999;
position: absolute;
right: 0;
top: 0;
transform: rotate(45deg) translate(25%, -45%);
transform-origin: center;
font-weight: 700;
font-size: larger
}
</style>
<span class="pin-top">[置顶]
</span>
网站美化与优化
前期也写过一些关于网站前端美化的文章,加载了自己以前的调整代码:
OwO表情按钮及弹窗
#comments form .comment-buttons .OwO .OwO-body {
min-width: 294px
}
.OwO-body {
z-index: 24!important
}
.OwO .OwO-body .OwO-items .OwO-item {
padding: 0;
}
#comments form .comment-buttons .OwO .OwO-body .OwO-items-image .OwO-item {
max-width: calc(25% - 10px)!important
}
#comments form .comment-buttons .OwO {
left: 12px;
width: auto;
top: -60px
}
设置小齿轮位置调整
@media screen and (max-width: 767.5px) {
.setting-panel-show #setting-panel {
top: 133px
}
}
评论区调整
如果文章禁止评论,那么直接评论区什么也不输出:
数据库支持Emoji表情
原生Typecho的数据库编码是utf8,不支持直接插入Emoji表情。要想数据库支持Emoji表情,就得使用utf8mb4编码来支持,于是我们需要修改已有数据库的编码格式,好消息是utf8mb4是utf-8的超集,完全兼容utf-8,修改后,不会影响现有数据。
首先修改MySQL数据库编码,连接数据库:
mysql -u root -p
切换到Typecho数据库:
use 数据库名;
然后执行以下SQL语句:
alter table typecho_comments convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_contents convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_fields convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_metas convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_options convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_relationships convert to character set utf8mb4 collate utf8mb4_general_ci;
alter table typecho_users convert to character set utf8mb4 collate utf8mb4_general_ci;
然后修改网站配置文件修改config.inc.php:
'charset' => 'utf8mb4', # 修改编码为 utf8mb4
测试:?️??????????❤️。
不要忘了每次使用phpMyAdmin
操作数据的时候,也要把服务器连接排序规则设置为utf8mb4
。
经过实际操作,发现虽然这样可以使得数据库中存入Emoji表情,但是当数据库文件导出后,里面的Emoji表情就全部变成了问号……,暂时还没有找到解决办法~
词义化时间
在Typecho的后台,很多地方都是用这种 “XX前” 的词义化时间显示的,简单明了。从这里我们就可以得出,后台是有相关函数,我们只要找到,然后直接使用就可以了—— var/Typecho/I18n.php
。但是官方提供的代码没有“周”和“月”,所以动手完善了一下代码,添加了“周”和“月”,只有1年以及1年以上的时间才会显示完整时间。这样可能比较好点吧。
/**
* 词义化时间
*
* @access public
* @param string $from 起始时间
* @param string $now 终止时间
* @return string
*/
public static function dateWord($from, $now)
{
$between = $now - $from;
/** 如果是一天 */
if ($between >= 0 && $between < 86400 && date('d', $from) == date('d', $now)) {
/** 如果是一小时 */
if ($between < 3600) {
/** 如果是一分钟 */
if ($between < 60) {
if (0 == $between) {
return _t('刚刚');
} else {
return str_replace('%d', $between, _n('刚刚', '%d秒前', $between));
}
}
$min = floor($between / 60);
return str_replace('%d', $min, _n('1分钟前', '%d分钟前', $min));
}
$hour = floor($between / 3600);
return str_replace('%d', $hour, _n('1小时前', '%d小时前', $hour));
}
/** 如果是昨天 */
if ($between > 0 && $between < 172800
&& (date('z', $from) + 1 == date('z', $now) // 在同一年的情况
|| date('z', $from) + 1 == date('L') + 365 + date('z', $now))) { // 跨年的情况
return _t('昨天 %s', date('H:i', $from));
}
/** 如果是一个星期以内 */
if ($between > 0 && $between < 604800) {
$day = floor($between / 86400);
return str_replace('%d', $day, _n('1天前', '%d天前', $day));
}
/** 如果是一个星期以上 */
if ($between > 0 && $between < 2592000){
$week = floor($between / 648000);
return str_replace('%d', $week, _n('1周前', '%d周前', $week));
}
/** 如果是一年以内 */
if ($between > 0 && $between < 31557600){
$month = floor($between / 2629800);
return str_replace('%d', $month, _n('1个月前', '%d个月前', $month));
}
/** 如果是一年以上 */
if (date('Y', $from) == date('Y', $now)) {
return date(_t('Y年n月j日 H:i'), $from);
}
return date(_t('Y年m月d日 H:i'), $from);
}
然后在需要输出的地方调用即可,例如:
<?php $comments->dateWord(); ?>
VOID主题在libs/Comments.php
文件中第150行,将原来的:
<timedatetime="<?php $this->date('c'); ?>">
<?php $singleCommentOptions->beforeDate();
echo date('Y-m-d H:i', $this->created);
$singleCommentOptions->afterDate(); ?></time>
修改为:
<?php $this->dateWord(); ?>
即可实现评论时间的词义化。
网站用户标识
在评论区区分回头客、老顾客、忠实用户、站长等,站长logo学习了百度网盘会员网站logo的样式?。
在主题functions.php
文件中增加查询数据库并返回顾客等级的函数:
function get_user_level($mail = '')
{
$db = Typecho_Db::get();
if ($mail) {
$count = $db->fetchRow(
$db->select('COUNT(*)')
->from('table.comments')
->where('status = ?', 'approved')
->where('mail = ?', $mail)
);
$commentnum = $count['COUNT(*)'];
if ($commentnum <= 1) {
return '';
} elseif ($commentnum <= 2) {
return '二进宫';
} elseif ($commentnum <= 3) {
return '三回头';
} elseif ($commentnum <= 5) {
return '老油条';
} else {
return 'OnlyFans';
}
} else { // 如果没有输入Email,那么返回评论数据表中所有评论数
$count = $db->fetchRow(
$db->select('COUNT(*)')
->from('table.comments')
->where('status = ?', 'approved')
);
return $count['COUNT(*)'];
}
}
在主题comments.php
适当位置插入:
<!-- 增加博主标识 -->
<?php
echo '<span class="user-logo';
if ($this->authorId) {
if ($this->authorId == $this->ownerId) {
echo ' webmaster">站长'; // 站长增加一个class类名
}
} else {
if (get_user_level($this->mail)) {
echo '">' . get_user_level($this->mail); // 普通用户仅有一个user-logo类名
} else {
echo '" style="display:none;">'; // php函数返回值为空,说明该用户仅有一条评论,那么久不输出标识
}
}
echo '</span>';
?>
然后根据设置的类名,写出对应的css即可:
.webmaster {
background: linear-gradient(90deg,#ffeccc,#ffd080);
color: #64360d !important;
}
.user-logo {
font-size: 80%;
display: inline-block;
background-color: #20b8d4;
padding: 1px 4px;
color: white;
border-radius: 3px;
}
快捷键提交评论
为评论框添加onkeydown
事件,当按下快捷键Ctrl+Enter的时候,JS模拟点击评论表单的提交按钮。
<textarea aria-label="评论输入框" class="input-area" rows="5" name="text" id="textarea"
placeholder="输入评论:"
style="resize:none;" onkeydown="if(event.ctrlKey&&event.keyCode==13){document.getElementById('comment-submit-button').click();return false};"></textarea>
评论框背景
评论框样式来源于Handsome主题。
添加css
属性即可:
#textarea {
background-image: #ffffff url('背景图片url地址') no-repeat right;
transition: all 0.25s ease-in-out 0s;
background-size: contain;
}
#textarea:focus {
background-position-y: 150px;
border-color: #448bff;
box-shadow: 0 0 0 .2rem rgba(68,139,255,.25);
}
评论框随机昵称
JS部分:
// 随机昵称实现
var a = null,
b = ["大名鼎鼎", "躲闪", "骄傲", "挺胸", "不知名", "知名", "刚下飞机", "看透一切", "小有名气", "潜心学习"],
c = ["大黄", "匿名人士", "高质量男性", "女士", "人士", "男孩", "女孩", "贫僧", "道士", "学生", "打工人", "路人甲", "炮灰已", "流氓丙", "土匪丁", "龙套戊"];
$("#get-nickname").on("click", function () {
const d = $(this);
$(this).removeClass("shake"),
$(this).addClass("shake"),
null != a && (clearTimeout(a), a = null),
a = setTimeout(function () {
d.removeClass("shake")
}, 500),
_tmp = b[Math.floor(Math.random() * b.length)] + "的" + c[Math.floor(Math.random() * c.length)],
$(this).prev().val(_tmp)
}
)
前端css动画:
.shake {
animation-name: shake;
animation-duration: .1s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
display: inherit;
transform-origin: center;
}
@keyframes shake {
2% {
transform: translate(-1.5px, calc(-50% + .5px)) rotate(1.5deg);
}
4% {
transform: translate(2.5px, calc(-50% + .5px)) rotate(-.5deg);
}
6% {
transform: translate(1.5px, calc(-50% + 1.5px)) rotate(1.5deg);
}
8% {
transform: translate(1.5px, calc(-50% + .5px)) rotate(1.5deg);
}
10% {
transform: translate(-.5px, calc(-50% - .5px)) rotate(.5deg);
}
12% {
transform: translate(-1.5px, calc(-50% - 1.5px)) rotate(-.5deg);
}
14% {
transform: translate(2.5px, calc(-50% + 1.5px)) rotate(1.5deg);
}
16% {
transform: translate(-.5px, calc(-50% - .5px)) rotate(1.5deg);
}
18% {
transform: translate(-1.5px, calc(-50% - .5px)) rotate(.5deg);
}
20% {
transform: translate(-.5px, calc(-50% + 1.5px)) rotate(.5deg);
}
22% {
transform: translate(2.5px, calc(-50% + 2.5px)) rotate(1.5deg);
}
24% {
transform: translate(-.5px, calc(-50% + 1.5px)) rotate(-.5deg);
}
26% {
transform: translate(.5px, calc(-50% - .5px)) rotate(.5deg);
}
28% {
transform: translate(1.5px, calc(-50% + .5px)) rotate(.5deg);
}
30% {
transform: translate(1.5px, calc(-50% + 2.5px)) rotate(1.5deg);
}
32% {
transform: translate(-1.5px, calc(-50% - .5px)) rotate(.5deg);
}
34% {
transform: translate(.5px, calc(-50% + 1.5px)) rotate(.5deg);
}
36% {
transform: translate(-1.5px, calc(-50% + .5px)) rotate(-.5deg);
}
38% {
transform: translate(1.5px, calc(-50% - .5px)) rotate(-.5deg);
}
40% {
transform: translate(2.5px, calc(-50% - .5px)) rotate(.5deg);
}
42% {
transform: translate(2.5px, calc(-50% + 1.5px)) rotate(1.5deg);
}
44% {
transform: translate(.5px, calc(-50% + 1.5px)) rotate(1.5deg);
}
46% {
transform: translate(.5px, calc(-50% + 1.5px)) rotate(.5deg);
}
48% {
transform: translate(-1.5px, calc(-50% - 1.5px)) rotate(-.5deg);
}
50% {
transform: translate(-.5px, calc(-50% - .5px)) rotate(-.5deg);
}
52% {
transform: translate(-1.5px, calc(-50% - .5px)) rotate(-.5deg);
}
54% {
transform: translate(1.5px, calc(-50% + 1.5px)) rotate(.5deg);
}
56% {
transform: translate(.5px, calc(-50% - 1.5px)) rotate(-.5deg);
}
58% {
transform: translate(-.5px, calc(-50% - 2.5px)) rotate(1.5deg);
}
60% {
transform: translate(2.5px, calc(-50% + 1.5px)) rotate(-.5deg);
}
62% {
transform: translate(2.5px, calc(-50% - 1.5px)) rotate(-.5deg);
}
64% {
transform: translate(-.5px, calc(-50% - 2.5px)) rotate(1.5deg);
}
66% {
transform: translate(1.5px, calc(-50% - .5px)) rotate(1.5deg);
}
68% {
transform: translate(.5px, calc(-50% - 1.5px)) rotate(1.5deg);
}
70% {
transform: translate(.5px, calc(-50% - .5px)) rotate(1.5deg);
}
72% {
transform: translate(2.5px, calc(-50% - .5px)) rotate(.5deg);
}
74% {
transform: translate(-.5px, calc(-50% + 2.5px)) rotate(1.5deg);
}
76% {
transform: translate(1.5px, calc(-50% - .5px)) rotate(.5deg);
}
78% {
transform: translate(2.5px, calc(-50% - .5px)) rotate(1.5deg);
}
80% {
transform: translate(1.5px, calc(-50% + 2.5px)) rotate(-.5deg);
}
82% {
transform: translate(-1.5px, calc(-50% + .5px)) rotate(-.5deg);
}
84% {
transform: translate(.5px, calc(-50% - .5px)) rotate(-.5deg);
}
86% {
transform: translate(-1.5px, calc(-50% + .5px)) rotate(.5deg);
}
88% {
transform: translate(2.5px, calc(-50% + .5px)) rotate(.5deg);
}
90% {
transform: translate(1.5px, calc(-50% + 2.5px)) rotate(.5deg);
}
92% {
transform: translate(-1.5px, calc(-50% + 1.5px)) rotate(-.5deg);
}
94% {
transform: translate(-.5px, calc(-50% + 2.5px)) rotate(1.5deg);
}
96% {
transform: translate(1.5px, calc(-50% + .5px)) rotate(.5deg);
}
98% {
transform: translate(1.5px, calc(-50% - .5px)) rotate(-.5deg);
}
0%,
100% {
transform: translate(0, -50%) rotate(0);
}
}
注意,这里使用了一种特征的CSS写法,即百分比与px
单位同时出现,需要使用语法例如calc(10% - 5px)
。之所以这样搞是因为div
定位使用了transform: translateY(-50%);
,如果你的div
没有使用这个属性,那你不需要使用这种写法。
前端html:
<div class="get-nickname">?</div>
评论框placeholder动态变化
// placehold变化
$("#textarea").focus(function () {
$(this).attr("placeholder", "说点什么吧~")
});
$("#textarea").blur(function () {
$(this).attr("placeholder", "居然什么也不说,哼~")
});
评论框随机头像
在主题functions.php
文件中增加返回随机图片地址的函数:
function local_random_avatar()
{
$options = Typecho_Widget::widget('Widget_Options');
$thumb = 'https://cdn.manyacan.com/blog/random_avatar/' . rand(1, 60) . '.png';
// $avatar = "<img alt='用户头像' src='{$thumb}' class='avatar avatar-50 photo' />";
echo $thumb;
}
由函数可得,其实就是产生一个随机数,然后把文件路径中的图片全部按顺序命名为数字即可,在合适的地方调用:
<img class="author-avatar" src="<?php local_random_avatar();?>">
替换Gravatar头像为Cravatar头像
Cravatar是Gravatar在中国的完美替代方案,你可以在https://cravatar.cn更新你的头像。
define('__TYPECHO_GRAVATAR_PREFIX__', 'https://cravatar.cn/avatar/');
Cravatar可以默认直接对QQ邮箱解析QQ头像,YYDS!
然后对var/Typecho/Common.php
文件中的函数进行修改(932行),增加一个请求参数,当评论用户既没有Gravatar头像也没用QQ邮箱时,解析为随机头像:
public static function gravatarUrl($mail, $size, $rating, $default, $isSecure = false)
{
if (defined('__TYPECHO_GRAVATAR_PREFIX__')) {
$url = __TYPECHO_GRAVATAR_PREFIX__;
} else {
$url = $isSecure ? 'https://secure.gravatar.com' : 'http://www.gravatar.com';
$url .= '/avatar/';
}
if (!empty($mail)) {
$url .= md5(strtolower(trim($mail)));
}
$url .= '?s=' . $size;
$url .= '&r=' . $rating;
$url .= '&d=' . $default;
// return $url;
return $url .='retro'; // 增加参数
}
显示评论IP归属地
方法一:直接引入JS文件解析IP地址。
<small style="color: rgba(0,0,0,.8)">来自<span id="ip-<?php $this->theId(); ?>"></span></small>
<script referrerpolicy="no-referrer" src="https://whois.pconline.com.cn/jsDom.jsp?level=3&domId=ip-<?php $this->theId(); ?>&ip=<?php echo $this->ip; ?>"></script>
不支持Pjax刷新,不知道怎么改代码。
方法二:在网站根目录下上传qqwry.dat
文件,然后在主题functions.php
文件中添加函数:
function convertip($ip)
{
$ip1num = 0;
$ip2num = 0;
$ipAddr1 = "";
$ipAddr2 = "";
$dat_path = './qqwry.dat';
if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
return 'IP 数据库路径不对';
}
if (!$fd = @fopen($dat_path, 'rb')) {
return 'IP 数据库路径不正确';
}
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
$DataBegin = fread($fd, 4);
$DataEnd = fread($fd, 4);
$ipbegin = implode('', unpack('L', $DataBegin));
if ($ipbegin < 0)
$ipbegin += pow(2, 32);
$ipend = implode('', unpack('L', $DataEnd));
if ($ipend < 0)
$ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = 0;
$EndNum = $ipAllNum;
while ($ip1num > $ipNum || $ip2num < $ipNum) {
$Middle = intval(($EndNum + $BeginNum) / 2);
fseek($fd, $ipbegin + 7 * $Middle);
$ipData1 = fread($fd, 4);
if (strlen($ipData1) < 4) {
fclose($fd);
return 'System Error';
}
$ip1num = implode('', unpack('L', $ipData1));
if ($ip1num < 0)
$ip1num += pow(2, 32);
if ($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
$DataSeek = fread($fd, 3);
if (strlen($DataSeek) < 3) {
fclose($fd);
return 'System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
fseek($fd, $DataSeek);
$ipData2 = fread($fd, 4);
if (strlen($ipData2) < 4) {
fclose($fd);
return 'System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if ($ip2num < 0)
$ip2num += pow(2, 32);
if ($ip2num < $ipNum) {
if ($Middle == $BeginNum) {
fclose($fd);
return 'Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fd, 1);
if ($ipFlag == chr(1)) {
$ipSeek = fread($fd, 3);
if (strlen($ipSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
fseek($fd, $ipSeek);
$ipFlag = fread($fd, 1);
}
if ($ipFlag == chr(2)) {
$AddrSeek = fread($fd, 3);
if (strlen($AddrSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipFlag = fread($fd, 1);
if ($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if (strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while (($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
fseek($fd, $AddrSeek);
while (($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fd, -1, SEEK_CUR);
while (($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fd, 1);
if ($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if (strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while (($char = fread($fd, 1)) != chr(0)) {
$ipAddr2 .= $char;
}
}
fclose($fd);
if (preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88.NET/is', '', $ipaddr);
$ipaddr = preg_replace('/^s*/is', '', $ipaddr);
$ipaddr = preg_replace('/s*$/is', '', $ipaddr);
if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = '可能来自火星';
}
$ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr);
return $ipaddr;
}
然后在需要comments.php
文件中需要输出的位置使用:
<?php echo convertip($this->ip); ?>
或者:
<?php echo convertip($comments->ip); ?>
即可将评论者IP地址转化为物理位置。
获取站长最后更新时间
根据文章数据表table.contents
、评论数据表table.comments
查询站长最后修改文章、新建文章、评论的最新评论,然后获取最后离开的时间。
在主题文件functions.php
中添加函数(需要手动填入站长邮箱):
// 获取站长最后来网站的时间(创建文章、修改文章、发表说说)
function get_last_update()
{
$now = time();
$db = Typecho_Db::get();
$prefix = $db->getPrefix();
$create = $db->fetchRow($db->select('created')->from('table.contents')->limit(1)->order('created', Typecho_Db::SORT_DESC)); // 最后创建文章的时间
$update = $db->fetchRow($db->select('modified')->from('table.contents')->limit(1)->order('modified', Typecho_Db::SORT_DESC)); // 最后修改文章的时间
$comment_create = $db->fetchRow($db->select('created')->from('table.comments')->limit(1)->order('created', Typecho_Db::SORT_DESC)->where('author = ?', 'Yacan Man')); // 站长最后评论的时间
$max_timer = max($create['created'], $update['modified'], $comment_create['created']);
echo Typecho_I18n::dateWord($max_timer, $now);
}
然后在需要输出的地方调用即可:
<?php echo get_last_update(); ?>
文章热度排行
无意间从百度热搜看到的热度排行样式,感觉还不错,偷过来学习一下。
在主题下的funtions.php
中写入函数:
function getHotComments($limit = 10)
{
$db = Typecho_Db::get();
$result = $db->fetchAll(
$db->select()->from('table.contents')
->where('status = ?', 'publish')
->where('type = ?', 'post')
->where('created <= unix_timestamp(now())', 'post') //添加这一句避免未达到时间的文章提前曝光
->limit($limit)
->order('viewsNum', Typecho_Db::SORT_DESC)
);
if ($result) {
foreach ($result as $val) {
$val = Typecho_Widget::widget('Widget_Abstract_Contents')->push($val);
$post_title = htmlspecialchars($val['title']);
$permalink = $val['permalink'];
if ($val['commentsNum'] >= 10) {
echo '<li class="hot">';
} else {
echo '<li>';
}
// 为什么最后要多输出一个<i>标签?为了换行时伪元素能够被挤下去到第二行
echo '<a href="' . $permalink . '" title="' . $post_title . '" target="_self">' . $val['title'] . '</a> <small>阅读' . $val['viewsNum'] . ' / 评论' . $val['commentsNum'] . '</small><i></i></li>';
}
}
}
然后再在主题文件夹下的Archives.php
文件中的合适地方调用该函数:
<!--PHP输出热门文章-->
<div class=".popular-articles yue float-up">
<h2>热门文章排行</h2>
<ol>
<?php getHotComments('20');?>
</ol>
</div>
最后增加css美化:
.popular-articles ol>li:first-child {
color: #FE2D46;
}
.popular-articles ol>li:nth-of-type(2) {
color: #F60;
}
.popular-articles ol>li:nth-of-type(3) {
color: #FAA90E;
}
.popular-articles ol>li.hot i::after {
content: '热';
color: #fafafa;
position: absolute;
background-color: #F60;
display: inline-block;
border-radius: 5px;
padding: 0 3px;
right: -1.7em;
transform: translateY(-50%);
top: 50%;
font-style: normal;
font-size: 80%;
}
.popular-articles ol>li.hot i {
position: relative;
}
统计全部文章阅读数
public static function getViewNum()
{
$db= Typecho_Db::get();
$query= $db->select('sum(viewsNum)')->from('table.contents');
$result = $db->fetchAll($query);
return $result[0]['sum(`viewsNum`)'];
}
然后在合适的地方输出即可:
<?php echo get_sum_view_num(); ?>
文章页末尾调整
首先是PHP判断,只有文章是post
类型的时候输出,独立页面不输出:
<?php if ($this->is('post')) : ?>
// ...
<?php endif; ?>
文章结束END提示:
<div style="margin: 20px auto;width: fit-content;">----- <span style="color: white;background-color: black;padding: 0 5px;font-size: .7rem;">END</span> -----</div>
版权信息:
<p class="notice" style="text-indent:0em">
本文作者:<a href="<?php $this->author->permalink(); ?>" rel="author"> <?php $this->author(); ?></a><br>
本文链接:<a href="<?php $this->permalink(); ?>"><?php $this->permalink(); ?></a><br>
版权声明:本文章采用<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/"><i> <strong>知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 </strong></i></a>。
</p>
标签云和点赞调整(使用flex布局):
.tag-and-reward {
flex: 2;
display: flex;
justify-content: space-around;
border-top: 1px solid #ccc;
padding: 1rem 0;
border-bottom: 1px solid #ccc;
margin: 1rem 0;
}
@media screen and (max-width:767px) {
.tag-and-reward {
flex-direction: column;
}
.tag-and-reward>div:nth-of-type(1) {
margin: 0 auto 1rem;
}
.tag-and-reward>div:nth-of-type(2) {
display: none;
}
}
.tag-and-reward>div:nth-of-type(1) {
border: 1px dotted #ccc;
height: 70%;
padding: .3rem .2rem;
width: fit-content
}
.tag-and-reward>div:nth-of-type(1)>a {
margin-bottom: unset;
}
.tag-and-reward>div:nth-of-type(1)>a:nth-last-of-type(1) {
margin-right: unset;
}
.tag-and-reward>div:nth-of-type(2) {
width: 1px;
background-color: #ccc;
}
.tag-and-reward>div:nth-of-type(3) {
padding: unset;
border: unset;
text-align: center;
}
.tag-and-reward>div:nth-of-type(3)>a {
margin-bottom: unset
}
.tag-and-reward>div:nth-of-type(3)>a:nth-of-type(3) {
margin-right: unset
}
上一篇文章与下一篇文章更改:
<?php if ($prev) : ?>
<div class="prev">
<a href="<?php $prev->permalink(); ?>">
<h2><?php $prev->title(); ?></h2>
</a>
<!-- 如果有摘要就输出摘要,没有摘要输出一段文字 -->
<?php
if ($prev->fields->excerpt != '') {
echo "<p>{$prev->fields->excerpt}</p>";
} else {
// 移动端少输出一点字
if (Utils::isMobile())
$prev->excerpt(60);
else
$prev->excerpt(80);
}
?>
</div>
<?php else : ?>
<div class="prev">
<h2>考古结束~</h2>
</div>
<?php endif; ?>
[...]第一次建立本站的时候,应该是大一的暑假吧,18岁,时间可真是太快了。🅱️ 博客由来在2017年之前,我在互联网上的冲浪环境主要是贴吧。由于以前是NOKIA的铁粉(我、诺记吧、诺基亚和微软),因此主要活动在诺记吧。我第一次知道博客这个东西,还是当时一位吧友(我只记得贴吧ID是@哒哒哒哒)当时在群里展示他的个人博客主页。那个时候,我突然觉得拥有一个以自己姓名为网址的个人博客,并且全世界任何一个接入互联[...]
牛啊 牛啊!!!1
牛!博主请问一下文章头部“中秋节网站重新上线~”双引号样式是怎么实现的
直接插入以下代码:
<!-- 文章最前面显示文章摘要 --> <p <?php if ($this->fields->excerpt == '' || !$setting['showHeadlineInPost']) echo 'hidden' ?> class="headline" itemprop="headline"><?php if ($this->fields->excerpt != '') echo $this->fields->excerpt; else $this->excerpt(30); ?></p>感谢!!
不客气,欢迎常来~
牛是真的牛哇 不过你这个评论上方显示信息图片没教怎么整 ?
右键看下,图片地址是一个API,可以自动生成,你直接图片地址调用API就行。
你好你好,好喜欢你的这个主题,github下载的主题应用报错,想问下typecho对应哪个版本呀
Typecho1.1,建议你还是现在作者的原版主题,然后自己对着我的代码一点点改吧,我这个改的地方有点多,代码也有点乱了。
博主你好,你的博客主题非常nice! 想问一下typecho1.1运行的php和数据库具体版本是多少?
牛的老哥,这就拿去用
记得改之前要备份~