前段时间把 WordPress 文章归档页面、网站分类、文章标签以及导航菜单等进行了优化,但目前在实际使用过程中仍觉得“分类”不够清晰。思来想去,还是觉得用“标签归档”来作为分类导航比较直观。于是 Kevin 着手创建一个新的 WordPress 标签归档页面…嗯,还是觉得原来 Tiny 主题用的标签页好看,扒下来吧。
可以打开咱新建的标签归档页面看看效果。如上图所示,WordPress 标签按照英文字母排序(中文字符提取了首字母),右侧是浮动的导航键盘。以下是实现该页面效果的核心程序和样式表:
// 新发表文章/修改文章时清理文章归档、标签归档缓存。此函数必须循环进 func.php,否则不生效
function clear_archives_tags_caches() {
//update_option('zww_db_cache_archives_list', ''); // 刷新 文章归档页面缓存
update_option('specs_tags_list', ''); // 清空 specs_tags_list
}
add_action('save_post', 'clear_archives_tags_caches');
// 标签归档页面所需函数开始,注释为 AI 生成
// 获取字符串的首个字符
function specs_getfirstchar($s0) {
$fchar = ord($s0[0]);
if ($fchar >= ord("A") and $fchar <= ord("z")) return strtoupper($s0[0]);
// 尝试进行编码转换
$s1 = @iconv("UTF-8//IGNORE", "GBK//IGNORE", $s0);
$s2 = iconv("GBK", "UTF-8", $s1);
if ($s2 == $s0) {
$s = $s1;
} else {
$s = $s0;
}
// 根据 ASCII 码判断并返回对应的首个大写英文字母
$asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
// 接下来是一系列的中文编码的范围,用于确定首字母
if ($asc >= -20319 and $asc <= -20284) return "A";
// ... 省略了其他的判断
return null; // 如果都不符合上述条件,则返回 null
}
// 将中文转换为拼音首字母
function specs_pinyin($zh) {
$ret = "";
// 进行编码转换并获取第一个字符
$s1 = @iconv("UTF-8//IGNORE", "GBK//IGNORE", $zh);
$s2 = iconv("GBK", "UTF-8", $s1);
if ($s2 == $zh) {
$zh = $s1;
}
// 循环处理字符串中的每个字符
$i = 0;
while ($i < strlen($zh)) {
$s1 = substr($zh, $i, 1);
$p = ord($s1);
if ($p > 160) {
// 如果字符 ASCII 码大于 160,则认为是中文字符,并获取对应的首字母
$s2 = substr($zh, $i++, 2);
$ret .= specs_getfirstchar($s2);
} else {
// 否则,直接返回该字符
$ret .= $s1;
}
}
return strtoupper($ret); // 全部转为大写并返回
}
// 展示标签的函数
function specs_show_tags() {
// 尝试从选项中获取缓存的标签列表
if (!$output = get_option('specs_tags_list')) {
// 获取所有标签,并按照文章数量排序
$categories = get_terms('post_tag', array(
'orderby' => 'count',
'hide_empty' => 1
));
$r = array(); // 初始化数组,避免后面使用时未定义
foreach ($categories as $v) {
$letter = specs_pinyin($v->name); // 获取标签名的首字母
if (ctype_alpha($letter)) { // 判断是否是字母
$r[$letter][] = $v; // 按字母存放到数组中
}
}
if (!empty($r)) {
ksort($r); // 如果数组不为空,则进行排序
}
// 接下来的代码生成了 HTML 输出内容,其中包括所有标签的链接列表
// ...
// 将生成的标签列表内容更新到选项中
update_option('specs_tags_list', $output);
}
echo $output; // 输出标签列表
}
// 根据标签获取文章数量的函数
function specs_post_count_by_tag($arg, $type = 'include') {
$args = array(
$type => $arg,
);
$tags = get_tags($args);
if ($tags) {
foreach ($tags as $tag) {
return $tag->count; // 返回标签下文章的数量
}
}
return 0; // 如果没有找到标签,返回 0
}
// 页面所需函数结束
.layoutSecondary {
float: right;
box-sizing: border-box;
padding-left: 30px;
width: 260px;
}
#tag-letter, .category-filter {
position: fixed;
width: 220px;
}
#tag-letter li {
display: inline-block;
}
#tag-letter li a {
display: inline-block;
margin: 3px 5px;
width: 24px;
height: 32px;
border: 1px solid #ddd;
border-radius: 3px;
background: #fff;
text-align: center;
font-size: 16px;
line-height: 32px;
}
#tag-letter li a.none {
color: #ddd;
cursor: not-allowed;
}
#all-tags li {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px dashed #eee;
max-width: 70%;
}
#all-tags .tag-name {
font-style: italic;
font-size: 28px;
}
#all-tags .tag-list {
margin-left: 24px;
}
#all-tags .tag-list a {
display: inline-block;
margin-right: 20px;
}
#all-tags .number {
display: inline-block;
margin-left: 3px;
font-size: 12px;
-webkit-transform: translateY(-10px);
transform: translateY(-10px);
}
#all-tags .tag-list a:hover .number {
font-size: 14px;
}
.layoutPrimary ul{list-style: none;}
将以上主函数循环仅主题function.php
中,将以上样式表添加进主题 CSS 中,然后复制一个主题的页面模板并修改Template Name
为自定义页面名称,接着在合适的位置插入<?php specs_show_tags(); ?>
,最后新建页面并且使用这个模板即可。为了省事儿和减少开销,我将以上除清除缓存部分的代码直接添加进了页面模板文件中,以下是我完整的 PHP 文件,给您各位作个参考:
<?php
/*
Template Name: Tags Page
*
* @version 1.0
* @author 牧羊人
* @URI https://www.shephe.com/
*/
get_header();
the_post();
impeka_grve_print_header_title( 'page' );
impeka_grve_print_header_breadcrumbs( 'page' );
impeka_grve_print_anchor_menu( 'page' );
// 页面所需函数开始
function specs_getfirstchar($s0){
$fchar = ord($s0[0]);
if($fchar >= ord("A") and $fchar <= ord("z") )return strtoupper($s0[0]);
//$s1 = iconv("UTF-8","gb2312", $s0);
//$s2 = iconv("gb2312","UTF-8", $s1);
$s1 = @iconv("UTF-8//IGNORE","GBK//IGNORE", $s0);
$s2 = iconv("GBK","UTF-8", $s1);
if($s2 == $s0){$s = $s1;}else{$s = $s0;}
$asc = ord($s[0]) * 256 + ord($s[1]) - 65536;
if($asc >= -20319 and $asc <= -20284) return "A";
if($asc >= -20283 and $asc <= -19776) return "B";
if($asc >= -19775 and $asc <= -19219) return "C";
if($asc >= -19218 and $asc <= -18711) return "D";
if($asc >= -18710 and $asc <= -18527) return "E";
if($asc >= -18526 and $asc <= -18240) return "F";
if($asc >= -18239 and $asc <= -17923) return "G";
if($asc >= -17922 and $asc <= -17418) return "H";
if($asc >= -17417 and $asc <= -16475) return "J";
if($asc >= -16474 and $asc <= -16213) return "K";
if($asc >= -16212 and $asc <= -15641) return "L";
if($asc >= -15640 and $asc <= -15166) return "M";
if($asc >= -15165 and $asc <= -14923) return "N";
if($asc >= -14922 and $asc <= -14915) return "O";
if($asc >= -14914 and $asc <= -14631) return "P";
if($asc >= -14630 and $asc <= -14150) return "Q";
if($asc >= -14149 and $asc <= -14091) return "R";
if($asc >= -14090 and $asc <= -13319) return "S";
if($asc >= -13318 and $asc <= -12839) return "T";
if($asc >= -12838 and $asc <= -12557) return "W";
if($asc >= -12556 and $asc <= -11848) return "X";
if($asc >= -11847 and $asc <= -11056) return "Y";
if($asc >= -11055 and $asc <= -10247) return "Z";
return null;
}
function specs_pinyin($zh){
$ret = "";
//$s1 = iconv("UTF-8","gb2312", $zh);
//$s2 = iconv("gb2312","UTF-8", $s1);
$s1 = @iconv("UTF-8//IGNORE","GBK//IGNORE", $zh);
$s2 = iconv("GBK","UTF-8", $s1);
if($s2 == $zh){$zh = $s1;}
$i = 0;
$s1 = substr($zh,$i,1);
$p = ord($s1);
if($p > 160){
$s2 = substr($zh,$i++,2);
$ret .= specs_getfirstchar($s2);
}else{
$ret .= $s1;
}
return strtoupper($ret);
}
function specs_show_tags() {
if(!$output = get_option('specs_tags_list')){
$categories = get_terms('post_tag', array(
'orderby' => 'count',
'hide_empty' => 1
));
$r = array(); // 初始化数组,避免后面使用时未定义
foreach ($categories as $v){
for ($i = 65; $i <= 90; $i++){
if (specs_pinyin($v->name) == chr($i)){
$r[chr($i)][] = $v;
}
}
for ($i = 48; $i <= 57; $i++){
if (specs_pinyin($v->name) == chr($i)){
$r[chr($i)][] = $v;
}
}
}
if (!empty($r)) {
ksort($r); // 排序前确保 $r 不为空
}
$output = "<div class='layoutSecondary fontJH'><ul id='tag-letter'>";
for ($i = 65; $i <= 90; $i++){
if (isset($r[chr($i)])){
$tagi = $r[chr($i)];
$output .= "<li><a href='#".chr($i)."'>".chr($i)."</a></li>";
}else{
$output .= "<li><a class='none' href='javascript:;'>".chr($i)."</a></li>";
}
}
for ($i = 48; $i <= 57; $i++){
if (isset($r[chr($i)])){
$tagi = $r[chr($i)];
$output .= "<li><a href='#".chr($i)."'>".chr($i)."</a></li>";
}else{
$output .= "<li><a class='none' href='javascript:;'>".chr($i)."</a></li>";
}
}
$output .= "</ul></div>";
$output .= "<div class='layoutPrimary'><ul id='all-tags'>";
for ($i = 65; $i <= 90; $i++){
if (isset($r[chr($i)])){
$tagi = $r[chr($i)];
$output .= "<li id='".chr($i)."'><h4 class='tag-name'>".chr($i)."</h4><div class='tag-list clearfix'>";
foreach ($tagi as $tag){
$output .= "<a href='".get_tag_link($tag->term_id)."' target='_blank'>".$tag->name."<span class='number'>".specs_post_count_by_tag($tag->term_id)."</span></a>";
}
$output .= '</div></li>';
}
}
for ($i = 48; $i <= 57; $i++){
if (isset($r[chr($i)])){
$tagi = $r[chr($i)];
$output .= "<li id='".chr($i)."'><h4 class='tag-name'>".chr($i)."</h4><div class='tag-list clearfix'>";
foreach ($tagi as $tag){
$output .= "<a href='".get_tag_link($tag->term_id)."' target='_blank'>".$tag->name."<span class='number'>".specs_post_count_by_tag($tag->term_id)."</span></a>";
}
$output .= '</div></li>';
}
}
$output .= "</ul></div>";
update_option('specs_tags_list', $output);
}
echo $output;
}
function specs_post_count_by_tag ( $arg ,$type = 'include'){
$args=array(
$type => $arg,
);
$tags = get_tags($args);
if ($tags) {
foreach ($tags as $tag) {
return $tag->count;
}
}
}
// 页面所需函数结束
if ( 'yes' == impeka_grve_post_meta( '_impeka_grve_disable_content' ) ) {
get_footer();
} else {
?>
<style>
.layoutSecondary {
float: right;
box-sizing: border-box;
padding-left: 30px;
width: 260px;
}
#tag-letter, .category-filter {
position: fixed;
width: 220px;
}
#tag-letter li {
display: inline-block;
}
#tag-letter li a {
display: inline-block;
margin: 3px 5px;
width: 24px;
height: 32px;
border: 1px solid #ddd;
border-radius: 3px;
background: #fff;
text-align: center;
font-size: 16px;
line-height: 32px;
}
#tag-letter li a.none {
color: #ddd;
cursor: not-allowed;
}
#all-tags li {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px dashed #eee;
max-width: 70%;
}
#all-tags .tag-name {
font-style: italic;
font-size: 28px;
}
#all-tags .tag-list {
margin-left: 24px;
}
#all-tags .tag-list a {
display: inline-block;
margin-right: 20px;
}
#all-tags .number {
display: inline-block;
margin-left: 3px;
font-size: 12px;
-webkit-transform: translateY(-10px);
transform: translateY(-10px);
}
#all-tags .tag-list a:hover .number {
font-size: 14px;
}
.layoutPrimary ul{list-style: none;}
</style>
<div class="grve-single-wrapper">
<div id="grve-content" <?php impeka_grve_content_class(); ?>>
<div class="grve-content-wrapper">
<div id="grve-main-content">
<div class="grve-main-content-wrapper clearfix">
<div id="page-<?php the_ID(); ?>" <?php post_class(); ?>>
<?php the_content(); ?>
<!-- 自定义开始 -->
<div class="grve-container">
<?php specs_show_tags(); ?>
</div>
<!-- 自定义结束 -->
<?php wp_link_pages(); ?>
</div>
</div>
</div>
<?php get_sidebar(); ?>
</div>
</div>
<?php
/**
* impeka_grve_singular_after_content hook
*
* @hooked impeka_grve_print_singular_navigation - 10
* @hooked impeka_grve_print_singular_comments_section - 20
*/
do_action( 'impeka_grve_singular_after_content' );
?>
</div>
<?php get_footer();
}
//Omit closing PHP tag to avoid accidental whitespace output errors.
收藏一下,过天折腾下看看