typecho通过自定义段不同模式前端按照不同模式显示分类不同

本来做导航的,想着如果是文章也能同时在首页分开显示就好了而不是都显示在一起,在首页因为公用一个分类导致文章也会进入导航的分类里面,这样显示的就不太好,下面的方式是通过js渲染的方法判断是导航还是文章然后对应的写进不同的区域,即同个分类包含两种模式显示,这样导航模式下分类全部显示导航的,文章区域全部显示文章的。

// 文章自定义字段
function themeFields($layout) {
    $url = new Typecho_Widget_Helper_Form_Element_Textarea('url', NULL, '', _t('跳转链接'), _t('请输入跳转URL,建议不用以 / 结尾。'));
    $layout->addItem($url);
    
    // 将单选框(Radio)改为下拉选择框(Select)
    $mode = new Typecho_Widget_Helper_Form_Element_Select(
        'mode',
        array(
            'navigation' => '导航模式',
            'article' => '文章模式',
        ),
        'navigation', // 默认选中项(字符串形式)
        '显示方式',
        '介绍:选择一种显示方式(导航模式、文章模式或网站关闭页面)'
    );
    $layout->addItem($mode);
}
<?php
// 1. 获取所有分类(保留原始顺序)
$categories = array();
$categoryWidget = $this->widget('Widget_Metas_Category_List');
if ($categoryWidget->have()) {
    while ($categoryWidget->next()) {
        $categories[] = array(
            'id' => $categoryWidget->mid,
            'name' => $categoryWidget->name,
            'permalink' => $categoryWidget->permalink
        );
    }
}

// 2. 获取所有文章
$posts = array();
$postWidget = $this->widget('Widget_Contents_Post_Recent', array(
    'order' => 'created',
    'desc' => true,
    'pageSize' => 9999
));

if ($postWidget->have()) {
    while ($postWidget->next()) {
        $posts[] = array(
            'cid' => $postWidget->cid,
            'title' => $postWidget->title,
            'permalink' => $postWidget->permalink,
            'url' => $postWidget->fields->url,
            'date' => $postWidget->date->format('Y-m-d H:i:s'),
            'excerpt' => $postWidget->excerpt,
            'mode' => trim($postWidget->fields->mode),
            'categories' => $postWidget->categories
        );
    }
}

// 3. 准备供JavaScript使用的数据(保留分类原始顺序)
$jsonData = json_encode(array(
    'categories' => $categories,
    'posts' => $posts
));
?>

<div class="container">
    <!-- 导航模式区域 -->
    <section class="navigation-section">
        <h2 class="section-title">导航链接</h2>
        <div id="navigation-container"></div>
        <p class="empty-message navigation-empty" style="display: none;">暂无导航链接</p>
    </section>

    <!-- 文章模式区域 -->
    <section class="article-section">
        <h2 class="section-title">最新文章</h2>
        <div id="article-container"></div>
        <p class="empty-message article-empty" style="display: none;">暂无文章内容</p>
    </section>
</div>

<script>
// 解析从PHP传递的数据
const data = <?php echo $jsonData; ?>;

// 组织数据:按分类和模式整理(保留分类原始顺序)
const organizedData = {};

// 初始化所有分类(按原始顺序)
data.categories.forEach(category => {
    organizedData[category.id] = {
        ...category,
        navigationPosts: [],
        articlePosts: []
    };
});

// 按模式分配文章到对应分类
data.posts.forEach(post => {
    const mode = post.mode || 'article'; // 默认文章模式
    
    if (post.categories && post.categories.length) {
        post.categories.forEach(cat => {
            const catId = cat.mid;
            
            // 如果分类不存在(可能是未在后台创建的分类),添加它
            if (!organizedData[catId]) {
                organizedData[catId] = {
                    id: catId,
                    name: cat.name,
                    permalink: cat.permalink,
                    navigationPosts: [],
                    articlePosts: []
                };
                // 添加到分类数组末尾
                data.categories.push(organizedData[catId]);
            }
            
            // 根据模式添加到对应数组
            if (mode === 'navigation') {
                organizedData[catId].navigationPosts.push(post);
            } else {
                organizedData[catId].articlePosts.push(post);
            }
        });
    }
});

// 渲染导航区域(按原始分类顺序)
function renderNavigation() {
    const container = document.getElementById('navigation-container');
    const emptyMsg = document.querySelector('.navigation-empty');
    let hasAnyContent = false;
    
    container.innerHTML = '';
    
    // 按原始顺序遍历所有分类
    data.categories.forEach(category => {
        const catData = organizedData[category.id];
        const hasContent = catData.navigationPosts.length > 0;
        
        if (hasContent) {
            hasAnyContent = true;
        }
        
        // 创建分类容器(即使没有内容也创建,可根据需求调整)
        const categoryDiv = document.createElement('div');
        categoryDiv.className = `navigation-category ${hasContent ? '' : 'empty-category'}`;
        
        // 分类标题
        categoryDiv.innerHTML = `
            <h3 class="category-title">
                <a href="${catData.permalink}">${catData.name}</a>
            </h3>
            <div class="navigation-list">
                ${hasContent ? catData.navigationPosts.map(post => {
                    const jumpUrl = post.url || post.permalink;
                    const target = jumpUrl !== post.permalink ? 'target="_blank"' : '';
                    return `
                        <div class="navigation-item">
                            <a href="${jumpUrl}" class="nav-link" ${target}>
                                ${post.title}
                            </a>
                        </div>
                    `;
                }).join('') : '<p class="category-empty">该分类下暂无导航链接</p>'}
            </div>
        `;
        
        container.appendChild(categoryDiv);
    });
    
    // 控制整体空状态显示
    container.style.display = hasAnyContent ? 'block' : 'none';
    emptyMsg.style.display = hasAnyContent ? 'none' : 'block';
}

// 渲染文章区域(按原始分类顺序)
function renderArticles() {
    const container = document.getElementById('article-container');
    const emptyMsg = document.querySelector('.article-empty');
    let hasAnyContent = false;
    
    container.innerHTML = '';
    
    // 按原始顺序遍历所有分类
    data.categories.forEach(category => {
        const catData = organizedData[category.id];
        const hasContent = catData.articlePosts.length > 0;
        
        if (hasContent) {
            hasAnyContent = true;
        }
        
        // 创建分类容器(即使没有内容也创建)
        const categoryDiv = document.createElement('div');
        categoryDiv.className = `article-category ${hasContent ? '' : 'empty-category'}`;
        
        // 分类内容
        categoryDiv.innerHTML = `
            <h3 class="category-title">
                <a href="${catData.permalink}">${catData.name}</a>
            </h3>
            <div class="article-list">
                ${hasContent ? catData.articlePosts.map(post => `
                    <article class="article-item">
                        <h3 class="article-title">
                            <a href="${post.permalink}">${post.title}</a>
                        </h3>
                        <div class="article-meta">
                            <time datetime="${new Date(post.date).toISOString()}">${post.date}</time>
                        </div>
                        <div class="article-content">
                            ${post.excerpt}
                        </div>
                        <a href="${post.permalink}" class="read-more">阅读全文 →</a>
                    </article>
                `).join('') : '<p class="category-empty">该分类下暂无文章</p>'}
            </div>
        `;
        
        container.appendChild(categoryDiv);
    });
    
    // 控制整体空状态显示
    container.style.display = hasAnyContent ? 'block' : 'none';
    emptyMsg.style.display = hasAnyContent ? 'none' : 'block';
}

// 页面加载完成后渲染内容
document.addEventListener('DOMContentLoaded', () => {
    renderNavigation();
    renderArticles();
});
</script>

这样的做法实现了在首页是按照自定义分类的不会受限于分类显示,如本身有大量文章配置此功能需要全部执行一遍更新,因为已发布的文章缺少mode字段值导致的。新发布的文章会正确保存mode字段(导航 / 文章模式),而旧文章可能没有这个字段,导致 JavaScript 无法正确识别其模式从而不显示,仅供测试,记录一下

------本页内容已结束,感谢您的观看------
© 版权声明
THE END
喜欢就支持以下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容