Files
SimpleBreadcrumb/Plugin.php

429 lines
13 KiB
PHP
Raw Normal View History

2026-02-23 19:57:05 +08:00
<?php
/**
* 面包屑导航(没有适配版)
*
* @package SimpleBreadcrumb
* @author 石头厝
* @version 3.0.0
* @link https://www.shitoucuo.com/
*/
class SimpleBreadcrumb_Plugin implements Typecho_Plugin_Interface
{
/**
* 激活插件
*/
public static function activate()
{
Typecho_Plugin::factory('Widget_Archive')->footer = array('SimpleBreadcrumb_Plugin', 'footer');
return _t('面包屑导航插件已激活,请在文章页面使用 SimpleBreadcrumb_Plugin::show() 调用');
}
/**
* 禁用插件
*/
public static function deactivate()
{
return _t('面包屑导航插件已禁用');
}
/**
* 插件配置面板(简化版)
*/
public static function config(Typecho_Widget_Helper_Form $form)
{
// 是否显示面包屑
$showBreadcrumb = new Typecho_Widget_Helper_Form_Element_Radio(
'showBreadcrumb',
array(
'1' => _t('显示'),
'0' => _t('不显示')
),
'1',
_t('是否显示面包屑导航')
);
$form->addInput($showBreadcrumb);
// 首页文字
$homeText = new Typecho_Widget_Helper_Form_Element_Text(
'homeText',
NULL,
'首页',
_t('首页显示文字')
);
$form->addInput($homeText);
// 分隔符
$separator = new Typecho_Widget_Helper_Form_Element_Select(
'separator',
array(
'»' => '»',
'>' => '>',
'/' => '/',
'→' => '→'
),
'»',
_t('分隔符样式')
);
$form->addInput($separator);
// 是否显示当前页面
$showCurrent = new Typecho_Widget_Helper_Form_Element_Radio(
'showCurrent',
array(
'1' => _t('显示'),
'0' => _t('不显示')
),
'1',
_t('是否显示当前页面')
);
$form->addInput($showCurrent);
// 是否显示分类
$showCategory = new Typecho_Widget_Helper_Form_Element_Radio(
'showCategory',
array(
'1' => _t('显示'),
'0' => _t('不显示')
),
'1',
_t('文章页面是否显示分类')
);
$form->addInput($showCategory);
}
/**
* 个人配置面板
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form) {}
/**
* 输出面包屑导航(前端调用方法)
*/
public static function show($widget = null)
{
$options = Helper::options();
$config = $options->plugin('SimpleBreadcrumb');
// 检查是否显示
if (!$config->showBreadcrumb) {
return;
}
// 如果没有传递widget使用全局
if ($widget === null) {
$widget = Typecho_Widget::widget('Widget_Archive');
}
// 检查是否在首页且需要显示
if ($widget->is('index')) {
return;
}
// 获取面包屑HTML
$breadcrumb = self::generateBreadcrumb($widget, $config);
if (!empty($breadcrumb)) {
// 输出CSS和面包屑HTML
$html = '<style>' . self::getStyles() . '</style>';
$html .= '<div class="simple-breadcrumb">' . $breadcrumb . '</div>';
echo $html;
}
}
/**
* 生成面包屑HTML
*/
private static function generateBreadcrumb($widget, $config)
{
$breadcrumbs = array();
$options = Helper::options();
// 添加首页
$homeText = isset($config->homeText) ? $config->homeText : '首页';
$breadcrumbs[] = '<a href="' . $options->siteUrl . '" class="breadcrumb-home">' .
htmlspecialchars($homeText) . '</a>';
$separator = isset($config->separator) ? $config->separator : '»';
$showCurrent = isset($config->showCurrent) ? $config->showCurrent : '1';
$showCategory = isset($config->showCategory) ? $config->showCategory : '1';
// 分类页面
if ($widget->is('category')) {
$category = $widget->getArchiveTitle();
if ($showCurrent) {
$breadcrumbs[] = '<span class="breadcrumb-current">' . htmlspecialchars($category) . '</span>';
}
}
// 文章页面
elseif ($widget->is('post')) {
// 添加分类
if ($showCategory) {
$categories = $widget->categories;
if ($categories && count($categories) > 0) {
$category = current($categories);
$breadcrumbs[] = '<a href="' . $category['permalink'] . '" class="breadcrumb-category">' .
htmlspecialchars($category['name']) . '</a>';
}
}
// 添加当前文章
if ($showCurrent) {
$breadcrumbs[] = '<span class="breadcrumb-current">' . htmlspecialchars($widget->title) . '</span>';
}
}
// 独立页面
elseif ($widget->is('page')) {
// 处理父页面(如果有)
if ($widget->parent > 0) {
$parent = $widget->widget('Widget_Archive', "type=page&pageId={$widget->parent}");
if ($parent->have()) {
$breadcrumbs[] = '<a href="' . $parent->permalink . '" class="breadcrumb-parent">' .
htmlspecialchars($parent->title) . '</a>';
}
}
if ($showCurrent) {
$breadcrumbs[] = '<span class="breadcrumb-current">' . htmlspecialchars($widget->title) . '</span>';
}
}
// 标签页面
elseif ($widget->is('tag')) {
if ($showCurrent) {
$tag = $widget->getArchiveTitle();
$breadcrumbs[] = '<span class="breadcrumb-current">标签: ' . htmlspecialchars($tag) . '</span>';
}
}
// 作者页面
elseif ($widget->is('author')) {
if ($showCurrent) {
$author = $widget->getArchiveTitle();
$breadcrumbs[] = '<span class="breadcrumb-current">作者: ' . htmlspecialchars($author) . '</span>';
}
}
// 日期归档
elseif ($widget->is('archive') && !$widget->is('category') && !$widget->is('tag') && !$widget->is('author')) {
if ($showCurrent) {
$archive = $widget->getArchiveTitle();
$breadcrumbs[] = '<span class="breadcrumb-current">' . htmlspecialchars($archive) . '</span>';
}
}
// 搜索页面
elseif ($widget->is('search')) {
if ($showCurrent) {
$keywords = $widget->keywords;
$breadcrumbs[] = '<span class="breadcrumb-current">搜索: ' . htmlspecialchars($keywords) . '</span>';
}
}
// 如果没有面包屑内容(只有首页),根据设置决定是否显示
if (count($breadcrumbs) <= 1) {
return ''; // 只显示首页时不输出
}
// 组合HTML
$html = '<nav class="breadcrumb-nav" aria-label="面包屑导航">';
$html .= '<ol class="breadcrumb-list">';
$count = count($breadcrumbs);
foreach ($breadcrumbs as $index => $crumb) {
$html .= '<li class="breadcrumb-item">';
$html .= $crumb;
if ($index < $count - 1) {
$html .= '<span class="breadcrumb-separator">' . htmlspecialchars($separator) . '</span>';
}
$html .= '</li>';
}
$html .= '</ol>';
$html .= '</nav>';
return $html;
}
/**
* 输出CSS样式到footer保持空避免重复加载
*/
public static function footer()
{
// CSS已经在show()方法中内联输出
}
/**
* 获取CSS样式 - 简化版,专门适配.dark夜间模式
*/
private static function getStyles()
{
return '
/* Simple Breadcrumb Navigation CSS - v3.0.0 */
/* 基础样式 */
.simple-breadcrumb {
margin: 20px 0;
padding: 15px 0;
font-size: 14px;
line-height: 1.5;
clear: both;
text-align: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
/* 导航结构 */
.breadcrumb-nav {
display: inline-block;
max-width: 100%;
}
.breadcrumb-list {
list-style: none;
padding: 0;
margin: 0;
display: inline-flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
}
.breadcrumb-item {
display: inline-flex;
align-items: center;
margin: 5px 0;
}
.breadcrumb-item a {
text-decoration: none;
padding: 4px 8px;
border-radius: 4px;
transition: all 0.2s ease;
font-weight: 500;
color: #1e87f0;
background-color: rgba(30, 135, 240, 0.1);
}
.breadcrumb-item a:hover {
color: #0d6efd;
background-color: rgba(30, 135, 240, 0.2);
transform: translateY(-1px);
}
.breadcrumb-item span.breadcrumb-current {
font-weight: 600;
padding: 4px 8px;
border-radius: 4px;
color: #333;
background-color: rgba(0, 0, 0, 0.05);
}
.breadcrumb-separator {
margin: 0 10px;
opacity: 0.6;
font-weight: 300;
color: #666;
}
/* ========== .dark 夜间模式适配 ========== */
.dark .simple-breadcrumb {
background-color: #1a1d21;
border-radius: 8px;
padding: 15px 20px;
border: 1px solid #343a40;
}
.dark .breadcrumb-item a {
color: #4dabf7;
background-color: rgba(77, 171, 247, 0.1);
}
.dark .breadcrumb-item a:hover {
color: #339af0;
background-color: rgba(77, 171, 247, 0.2);
}
.dark .breadcrumb-item span.breadcrumb-current {
color: #e9ecef;
background-color: rgba(255, 255, 255, 0.05);
}
.dark .breadcrumb-separator {
color: #adb5bd;
}
/* ========== 响应式设计 ========== */
@media (max-width: 768px) {
.simple-breadcrumb {
margin: 15px 0;
padding: 12px 15px;
font-size: 13px;
text-align: left;
}
.breadcrumb-list {
justify-content: flex-start;
overflow-x: auto;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
padding-bottom: 5px;
}
.breadcrumb-item {
flex-shrink: 0;
}
.breadcrumb-separator {
margin: 0 8px;
}
.dark .simple-breadcrumb {
padding: 12px 15px;
}
}
@media (max-width: 480px) {
.simple-breadcrumb {
margin: 10px 0;
padding: 10px 12px;
font-size: 12px;
}
.breadcrumb-item a,
.breadcrumb-item span.breadcrumb-current {
padding: 3px 6px;
}
.breadcrumb-separator {
margin: 0 6px;
}
.dark .simple-breadcrumb {
padding: 10px 12px;
border-radius: 6px;
}
}
/* ========== 打印样式 ========== */
@media print {
.simple-breadcrumb {
display: none;
}
}
/* ========== 无障碍支持 ========== */
.breadcrumb-item a:focus {
outline: 2px solid #1e87f0;
outline-offset: 2px;
}
.dark .breadcrumb-item a:focus {
outline-color: #4dabf7;
}
';
}
}
?>