一、为什么要改主题代码?

我用 BeaconNav 搭了一个导航站,平时放各种链接。唯独“推特关注列表”这个分类比较特殊——它不是网站链接卡片,而是一个表格。如果也用卡片展示,信息密度太低,需要反复切换,浏览起来极不方便。

所以核心需求只有两条:

  1. 在指定页面直接开一个完整的表格面板。

  2. 一键更新:如果有表格变动,我不应该去手动敲代码修改,而是用Excel格式转换,粘贴数据到文章。


二、修改 index.php

2.1 关键修改点

原主题代码在导航标签<ul class="nav nav-tabs">之后,直接就是卡片循环<div class="nav-list row">。

所以干脆在它们之间插入了条件判断分支。

代码片段 1:条件判断 + 自定义面板输出

<!-- 自定义面板 -->
<?php 
// 智能识别指定的分类(菜单)关键词,支持大小写模糊匹配
$catName = strtolower($this->category);
if ($this->is('category', 'x-twitter') || 
    strpos($catName, '推特') !== false || 
    strpos($catName, '关注列表') !== false || 
    strpos($catName, 'follow') !== false) : 
?>
    <div class="x-custom-block mt-3 text-white">
        <div class="x-custom-wrapper">
            <?php if ($this->have()) : ?>
                <?php while ($this->next()) : ?>
                    <?php 
                        // 直接查数据库取文章正文(text 字段)
                        $db = Typecho_Db::get();
                        $postData = $db->fetchRow($db->select('text')->from('table.contents')->where('cid = ?', $this->cid));
                        $rawHtml = $postData['text'];
                        // 去掉 Typecho 自动加的 Markdown 标记
                        if (strpos($rawHtml, '<!--markdown-->') === 0) {
                            $rawHtml = substr($rawHtml, 15);
                        }
                        // 解码实体,直接输出 HTML
                        echo htmlspecialchars_decode($rawHtml); 
                    ?>
                <?php endwhile; ?>
            <?php else : ?>
                <div class="text-center opacity-50"><?php _e('暂无列表数据,请先在后台发布一篇该分类下的文章。'); ?></div>
            <?php endif; ?>
        </div>
    </div>
<?php else : ?>
    <!-- 原卡片列表(不变) -->
    <div class="nav-list row">
        ...
    </div>
<?php endif; ?>

代码解释

  • 第 4~7 行:只要当前分类缩略名是 x-twitter,或分类缩略名包含“推特/关注列表/follow”(不区分大小写),就触发自定义面板。

  • 第 11~16 行:遍历该分类下的文章。从数据库 table.contents 表中读取 text 字段(即文章正文)。

  • 第 18~19 行:因为文章是用 Markdown 写的,Typecho 会在内容前加上 <!--markdown-->,必须截掉,否则会显示在页面上。

  • 第 21 行:htmlspecialchars_decode 把 &lt; 之类的实体转回 <,这样表格 HTML 才能被浏览器解析。


代码片段 2:配套的 CSS(让面板好看且能滚动)

<style>
    .x-custom-block {
        display: block !important;
        width: 100% !important;
        margin-top: 0 !important;
    }
    .x-custom-wrapper {
        background: rgba(255, 255, 255, 0.12) !important;
        backdrop-filter: blur(10px) !important;      /* 毛玻璃效果 */
        -webkit-backdrop-filter: blur(10px) !important;
        border: 1px solid rgba(255, 255, 255, 0.15) !important;
        border-radius: 12px !important;
        padding: 24px !important;
        box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.25) !important;
        
        /* 关键:限制高度,长表格内部滚动 */
        max-height: 65vh !important;
        overflow-y: auto !important;
    }
    /* 表格样式 */
    .x-table {
        width: 100% !important;
        border-collapse: collapse !important;
        color: #fff !important;
    }
    .x-table th {
        background: #70ad47 !important;   /* 表头绿色高亮 */
        color: #ffffff !important;
        font-weight: 600 !important;
    }
    .x-table tr:hover {
        background: rgba(255, 255, 255, 0.08) !important;
    }
    .x-link-btn {
        background: rgba(255, 255, 255, 0.18) !important;
        color: #fff !important;
        padding: 5px 12px !important;
        border-radius: 6px !important;
        text-decoration: none !important;
    }
    /* 美化滚动条 */
    .x-custom-wrapper::-webkit-scrollbar { width: 6px; }
    .x-custom-wrapper::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.2); border-radius: 4px; }
</style>

三、表格转换工具

分类下的内容来自文章正文,但我不能每次更新关注列表都手写标签来更新吧?太反人类了。所以我写了一个独立的HTML工具,放在网站根目录,用来把文本表格转成方便复制的 HTML 代码。

3.1 核心逻辑代码片段(JS 解析部分)

function generateHTML() {
    const textVal = document.getElementById('rawText').value.trim();
    if (!textVal) return alert('好歹说点什么啊喂!');

    // 获取当前(或手动冻结的)时间
    let finalTime = document.getElementById('updateTime').innerText.trim();
    if (finalTime.length > 16) finalTime = finalTime.substring(0, 16);

    const lines = textVal.split('\n').map(line => line.trim()).filter(line => line !== '');
    
    // 智能分割:支持 Tab、竖线 |、或多个连续空格
    function splitLine(str) {
        return str.split(/\t|\|| {2,}/).map(item => item.trim()).filter(item => item !== '');
    }

    const headerCols = splitLine(lines[0]);  // 首行作表头
    let html = `<div class="x-table-container"><table class="x-table"><thead><tr>`;
    headerCols.forEach(h => { html += `<th>${h}</th>`; });
    html += `</tr></thead><tbody>`;

    for (let i = 1; i < lines.length; i++) {
        let cols = splitLine(lines[i]);
        if (cols.length === 0) continue;
        while (cols.length < headerCols.length) cols.push(''); // 补全空位

        html += `<tr>`;
        cols.forEach((cell, index) => {
            if (index === 0) {
                html += `<td><strong>${cell}</strong></td>`;  // 第一列加粗
            } else if (cell.startsWith('http://') || cell.startsWith('https://')) {
                html += `<td><a class="x-link-btn" href="${cell}" target="_blank">直达网页</a></td>`;
            } else {
                html += `<td>${cell}</td>`;
            }
        });
        html += `</tr>`;
    }
    html += `</tbody></table></div>`;
    
    // 去掉所有换行符,压缩成一行,防止 Markdown 捣乱
    document.getElementById('outputHtml').value = html.replace(/\r?\n|\r/g, "");
    document.getElementById('resultBox').style.display = 'block';
    document.getElementById('outputHtml').select();
}

3.2 这个工具还帮我做了什么?

  • 时间戳管理:自动显示当前时区时间,支持手动“冻结/修改”,方便自定义数据更新时间。

  • 时区切换:下拉菜单支持全球主流的24时区,以适配不同的工作环境。

  • 智能链接识别:只要单元格里是 http:// 或 https:// 开头的,就会变成方形按钮,简约美观且便携。


四、列表维护流程

以后想更新“关注列表”,只需三步:

  1. 整理数据:先在 Excel 里把数据整理好,连带首行复制出来。

  2. 打开工具:访问 /tools.html或点击右上角的更新数据,粘贴表格内容,确认更新时间,点击生成文章格式代码,复制输出的代码。

  3. 更新文章:在Typecho后台找到该分类下的关注列表文章,全选粘贴替换掉旧文章代码,发布。


五、注意事项

  1. 特殊分类只发一篇文章:如果发多篇文章,while ($this->next()) 会循环输出多次,页面会叠好几层面板。

  2. 关闭 Markdown 解析:工具生成的已经是纯 HTML。如果你后台有Markdown插件,记得在模板里用 substr 去掉 <!--markdown--> 标记,或者禁用 Markdown的插件。

  3. 分隔符建议用 Tab:肉眼对不齐的空格容易导致分割错位,Excel默认Tab分隔最稳。

  4. 样式前缀:所有自定义 CSS 都加了 x- 前缀,这样不会和主题原有样式冲突。