8.主题魔改:添加“待办清单”独立页面

8.主题魔改:添加“待办清单”独立页面

本指南将引导您为博客添加一个独立的“待办清单”页面。这个页面采用双栏布局,可以清晰地分类和展示您的各种待办事项。

警告: 这是一项涉及多个文件修改的“魔改”操作。在开始前,强烈建议您备份整个 themes/anzhiyu 文件夹,以便在出现问题时可以随时恢复。


第一步:创建并编辑您的待办事项数据

我们首先来准备清单页面的“内容数据”。

  1. 创建数据文件 (todolist.yml)
  • 在您博客根目录的 source/_data/ 文件夹内,新建一个名为 todolist.yml 的文件。如果 _data 文件夹不存在,请手动创建。
  1. 编辑 todolist.yml 文件

    • 将下面的模板完整复制到 todolist.yml 文件中,然后根据注释修改为您自己的待办事项
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    # seat: 控制该分类显示在左栏(left)还是右栏(right)
    # completed: 控制该事项是否已完成 (true 表示已完成,会显示对勾和删除线)

    - class_name: "学习计划"
    seat: left
    todo_list:
    - content: "深入学习 Vue 3 组合式 API"
    completed: false
    - content: "完成一个完整的 Node.js 项目"
    completed: true

    - class_name: "想看的书"
    seat: left
    todo_list:
    - content: "《代码整洁之道》"
    completed: true
    - content: "《你不知道的JavaScript》"
    completed: false

    - class_name: "想去的地方"
    seat: right
    todo_list:
    - content: "日本,京都"
    completed: false
    - content: "中国,新疆"
    completed: false

    - class_name: "想买的东西"
    seat: right
    todo_list:
    - content: "一把舒适的人体工学椅"
    completed: false
    - content: "降噪耳机"
    completed: true

第二步:创建新的页面布局与样式

现在,我们需要为这个新页面类型创建专属的模板和CSS样式。

  1. 创建 Pug 模板文件

    • 文件路径themes/anzhiyu/layout/includes/page/todolist.pug
    • 文件内容(请将以下代码完整复制进去):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    #todolist-box
    - let todo_background = page.top_background
    .author-content.author-content-item.todolist.single(style=`${todo_background ? `background: url(${todo_background}) top / cover no-repeat;` : ""}`)
    .card-content
    .author-content-item-tips Todo
    span.author-content-item-title 待办清单
    .content-bottom
    .tips
    i.fa-solid.fa-quote-left.fa-fw
    span 耽误太多时间,事情可就做不完了
    i.fa-solid.fa-quote-right.fa-fw
    .banner-button-group
    a.banner-button(onclick='pjax.loadUrl("/about/")')
    i.anzhiyufont.anzhiyu-icon-arrow-circle-right(style='font-size: 1.5rem')
    span.banner-button-text 我的更多

    #todolist-filter
    .filter-title
    i.fa-solid.fa-filter
    span 分类筛选
    .filter-buttons
    button.filter-btn.active(data-filter="all") 全部
    - let categories = []
    each i in site.data.todolist
    - if(!categories.includes(i.class_type)) categories.push(i.class_type || '未分类')
    each category in categories
    button.filter-btn(data-filter=category)= category

    #todolist-main.todolist-grid
    each i in site.data.todolist
    - const categoryClass = i.class_type ? `todo-category-${i.class_type}` : 'todo-category-undefined'
    .todolist-item(class=categoryClass, data-category=i.class_type || '未分类')
    h3.todolist-title
    //- 移除了旧的图标
    span= i.class_name
    .task-count
    - let completedCount = 0
    each item in i.todo_list
    - if(item.completed) completedCount++
    span= completedCount + '/' + i.todo_list.length
    ul.todolist-ul
    each item in i.todo_list
    //- 我们只需要设置 class,CSS 会自动创建复选框样式
    - var listItemClass = item.completed ? 'todolist-li-done' : 'todolist-li'
    li(class=listItemClass)
    span= item.content
    //- 移除了进度条

    #todolist-pagination
    .pagination-container
    button#prev-page.page-btn(disabled)
    i.fa-solid.fa-angle-left
    #page-numbers
    button#next-page.page-btn(disabled)
    i.fa-solid.fa-angle-right

    //- 下方是实现所有交互功能所需的完整JavaScript代码
    script.
    // 防止重复初始化的标志
    let todolistInitialized = false;

    // Todolist 初始化函数
    function initTodolist() {
    // 防止重复初始化
    if (todolistInitialized) return;

    // 检查必要的DOM元素是否存在
    const todolistBox = document.getElementById('todolist-box');
    if (!todolistBox) return;

    // 等待CSS加载完成
    const checkCSSLoaded = () => {
    const testElement = document.querySelector('.filter-btn');
    if (!testElement) return false;
    const computedStyle = window.getComputedStyle(testElement);
    return computedStyle.cursor === 'pointer';
    };

    // 如果CSS未加载完成,延迟初始化
    if (!checkCSSLoaded()) {
    setTimeout(initTodolist, 100);
    return;
    }

    console.log('Todolist 开始初始化...');

    // ========================================================================
    // 筛选与分页功能
    // ========================================================================
    const filterBtns = document.querySelectorAll('.filter-btn');
    const todoItems = document.querySelectorAll('.todolist-item');
    const itemsPerPage = 6;
    let currentPage = 1;
    let filteredItems = Array.from(todoItems);

    // 检查必要元素是否存在
    if (filterBtns.length === 0 || todoItems.length === 0) {
    console.warn('Todolist: 未找到必要的DOM元素');
    return;
    }

    function applyFilter(filter) {
    filteredItems = Array.from(todoItems);
    if (filter !== 'all') {
    filteredItems = filteredItems.filter(item => item.getAttribute('data-category') === filter);
    }
    todoItems.forEach(item => { item.style.display = 'none'; });
    setupPagination();
    goToPage(1);
    }

    function setupPagination() {
    const pageCount = Math.ceil(filteredItems.length / itemsPerPage);
    const pageNumbersContainer = document.getElementById('page-numbers');
    const paginationContainer = document.getElementById('todolist-pagination');

    if (!pageNumbersContainer || !paginationContainer) return;

    pageNumbersContainer.innerHTML = '';

    if (pageCount <= 1) {
    paginationContainer.style.display = 'none';
    showItems(filteredItems);
    return;
    }

    paginationContainer.style.display = 'flex';
    for (let i = 1; i <= pageCount; i++) {
    const btn = document.createElement('button');
    btn.classList.add('page-number');
    if (i === 1) btn.classList.add('active');
    btn.textContent = i;
    btn.addEventListener('click', () => goToPage(i));
    pageNumbersContainer.appendChild(btn);
    }

    const prevBtn = document.getElementById('prev-page');
    const nextBtn = document.getElementById('next-page');
    if (prevBtn) prevBtn.disabled = true;
    if (nextBtn) nextBtn.disabled = pageCount <= 1;
    }

    // 分页按钮事件监听
    const prevBtn = document.getElementById('prev-page');
    const nextBtn = document.getElementById('next-page');

    if (prevBtn) {
    prevBtn.addEventListener('click', () => {
    if (currentPage > 1) goToPage(currentPage - 1);
    });
    }

    if (nextBtn) {
    nextBtn.addEventListener('click', () => {
    const pageCount = Math.ceil(filteredItems.length / itemsPerPage);
    if (currentPage < pageCount) goToPage(currentPage + 1);
    });
    }

    function goToPage(page) {
    const startIndex = (page - 1) * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;
    const itemsToShow = filteredItems.slice(startIndex, endIndex);

    const pageButtons = document.querySelectorAll('.page-number');
    pageButtons.forEach((btn, index) => btn.classList.toggle('active', index + 1 === page));

    const prevBtn = document.getElementById('prev-page');
    const nextBtn = document.getElementById('next-page');
    if (prevBtn) prevBtn.disabled = page === 1;
    if (nextBtn) nextBtn.disabled = page === Math.ceil(filteredItems.length / itemsPerPage);

    todoItems.forEach(item => { item.style.display = 'none'; });
    showItems(itemsToShow);
    currentPage = page;
    }

    function showItems(items) {
    items.forEach(item => { item.style.display = 'block'; });
    }

    // 筛选按钮事件监听
    filterBtns.forEach(btn => {
    btn.addEventListener('click', function() {
    filterBtns.forEach(b => b.classList.remove('active'));
    this.classList.add('active');
    applyFilter(this.getAttribute('data-filter'));
    });
    });

    // ========================================================================
    // 清单项目的交互功能
    // ========================================================================
    const allListItems = document.querySelectorAll('.todolist-ul li');

    allListItems.forEach(li => {
    li.addEventListener('click', function() {
    // 切换被点击项目的视觉状态
    this.classList.toggle('todolist-li-done');

    // 找到父级卡片以更新其计数器
    const parentCard = this.closest('.todolist-item');
    if (parentCard) {
    // 在此卡片内重新计算任务数量
    const tasksInCard = parentCard.querySelectorAll('.todolist-ul li');
    const completedTasksInCard = parentCard.querySelectorAll('.todolist-ul li.todolist-li-done');
    const totalCount = tasksInCard.length;
    const completedCount = completedTasksInCard.length;

    // 更新计数器文本
    const counterSpan = parentCard.querySelector('.task-count span');
    if (counterSpan) {
    counterSpan.textContent = `${completedCount}/${totalCount}`;
    }
    }
    });
    });

    // 初始化加载
    setupPagination();
    goToPage(1);

    // 标记为已初始化
    todolistInitialized = true;
    console.log('Todolist 初始化完成');
    }

    // 多种初始化触发方式
    // 1. DOM加载完成时
    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initTodolist);
    } else {
    // 如果DOM已经加载完成,立即初始化
    setTimeout(initTodolist, 50);
    }

    // 2. PJAX完成时
    document.addEventListener('pjax:complete', () => {
    todolistInitialized = false; // 重置标志
    setTimeout(initTodolist, 100); // 延迟初始化以确保DOM更新完成
    });

    // 3. CSS加载完成时
    document.addEventListener('todolist-css-loaded', () => {
    if (!todolistInitialized) {
    setTimeout(initTodolist, 50);
    }
    });

    // 4. 页面完全加载时(备用)
    window.addEventListener('load', () => {
    if (!todolistInitialized) {
    setTimeout(initTodolist, 200);
    }
    });

    // 5. 兼容性检查 - 如果其他方式都失败了,定期检查
    let retryCount = 0;
    const maxRetries = 10;
    const retryInterval = setInterval(() => {
    if (todolistInitialized || retryCount >= maxRetries) {
    clearInterval(retryInterval);
    return;
    }

    if (document.querySelector('#todolist-box')) {
    initTodolist();
    }
    retryCount++;
    }, 500);
  2. 创建 CSS 样式文件

    • 文件路径themes/anzhiyu/source/custom/css/todolist.css
    • 文件内容(请将以下代码完整复制进去):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    /* Todolist 现代化扁平设计 - v4.0 */

    /* ==========================================================================
    基础布局与容器
    ========================================================================== */
    body[data-type="todolist"] #web_bg {
    background: var(--anzhiyu-background);
    }

    body[data-type="todolist"] #page {
    border: 0;
    box-shadow: none !important;
    padding: 0 !important;
    background: transparent !important;
    }

    body[data-type="todolist"] #page .page-title {
    display: none;
    }

    #todolist-box {
    margin: 0 auto;
    max-width: 1200px;
    padding: 0 15px;
    }

    /* 顶部内容区 */
    .author-content.todolist {
    margin-bottom: 20px;
    }
    .author-content .tips {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--anzhiyu-fontcolor);
    opacity: 0.75;
    }
    .author-content .tips i {
    color: var(--anzhiyu-theme);
    font-size: 0.8rem;
    }

    /* ==========================================================================
    筛选器
    ========================================================================== */
    #todolist-filter {
    margin: 20px 0;
    padding: 15px;
    background: var(--anzhiyu-card-bg);
    border-radius: 12px;
    box-shadow: var(--anzhiyu-shadow-border);
    }

    .filter-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 12px;
    color: var(--anzhiyu-fontcolor);
    font-weight: 600;
    }

    .filter-title i {
    color: var(--anzhiyu-theme);
    }

    .filter-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    }

    .filter-btn {
    background: var(--anzhiyu-card-bg);
    border: 1px solid var(--anzhiyu-card-border);
    color: var(--anzhiyu-fontcolor);
    border-radius: 8px; /* 更方正的圆角 */
    padding: 6px 15px;
    cursor: pointer;
    transition: all 0.3s ease;
    font-size: 0.9rem;
    /* 确保按钮可点击 */
    pointer-events: auto;
    user-select: none;
    }

    .filter-btn:hover {
    transform: translateY(-2px);
    border-color: var(--anzhiyu-theme);
    background: var(--anzhiyu-card-bg);
    }

    .filter-btn.active {
    background: var(--anzhiyu-theme);
    color: white;
    border-color: var(--anzhiyu-theme);
    }

    /* ==========================================================================
    主体布局与卡片 (核心重构区域)
    ========================================================================== */
    #todolist-main {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 20px;
    margin: 20px 0;
    }

    /* 卡片容器 - 简化 */
    .todolist-item {
    background: var(--anzhiyu-card-bg);
    border-radius: 12px;
    padding: 20px 25px;
    box-shadow: var(--anzhiyu-shadow-border);
    transition: all 0.3s ease;
    animation: fadeIn 0.5s ease forwards;
    }

    .todolist-item:hover {
    transform: translateY(-5px);
    box-shadow: var(--anzhiyu-shadow-main);
    }

    /* 标题样式 - 简化 */
    h3.todolist-title {
    margin: 0 0 1rem 0 !important;
    padding-bottom: 0.8rem;
    font-size: 1.2rem;
    color: var(--anzhiyu-fontcolor);
    border-bottom: 1px solid var(--anzhiyu-card-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    }

    /* 隐藏原标题图标 */
    h3.todolist-title i {
    display: none;
    }

    /* 任务计数器 */
    .task-count {
    background: var(--anzhiyu-secondbg);
    color: var(--anzhiyu-fontcolor);
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 0.8rem;
    font-weight: 500;
    }

    /* 移除进度条 */
    .progress-bar {
    display: none;
    }

    /* ==========================================================================
    清单列表项 (全新 Checkbox 样式)
    ========================================================================== */
    .todolist-ul {
    margin: 0;
    padding: 0;
    }

    .todolist-ul li {
    list-style: none;
    padding: 10px 0;
    margin: 0;
    display: grid;
    grid-template-columns: 20px auto; /* 复选框 | 文本 */
    align-items: center;
    gap: 15px;
    cursor: pointer;
    position: relative;
    /* 确保列表项可点击 */
    pointer-events: auto;
    user-select: none;
    }

    /* 隐藏原列表图标 */
    .todolist-ul li i {
    display: none;
    }

    /* 任务文本 */
    .todolist-ul li span {
    color: var(--anzhiyu-fontcolor);
    position: relative;
    transition: color 0.3s ease;
    line-height: 1.5;
    }

    /* 使用 ::before 伪元素创建自定义复选框的“框” */
    .todolist-ul li::before {
    content: "";
    width: 16px;
    height: 16px;
    border: 2px solid var(--anzhiyu-fontcolor);
    border-radius: 4px;
    transition: all 0.3s ease;
    position: relative;
    }

    /* 使用 ::after 伪元素创建自定义复选框的“勾” */
    .todolist-ul li::after {
    content: "";
    position: absolute;
    left: 6px;
    top: 13px;
    width: 4px;
    height: 8px;
    border: solid white;
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    opacity: 0;
    transition: opacity 0.3s ease;
    }

    /* ==========================================================================
    已完成状态 (交互动画)
    ========================================================================== */
    .todolist-ul li.todolist-li-done span {
    color: var(--anzhiyu-secondtext);
    }

    /* 复选框(框)的完成状态 */
    .todolist-ul li.todolist-li-done::before {
    background: var(--anzhiyu-blue);
    border-color: var(--anzhiyu-blue);
    animation: check-box 0.3s ease;
    }

    /* 复选框(勾)的完成状态 */
    .todolist-ul li.todolist-li-done::after {
    opacity: 1;
    }

    /* 文本删除线动画 */
    .todolist-ul li span::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--anzhiyu-secondtext);
    transition: width 0.4s ease;
    }

    .todolist-ul li.todolist-li-done span::before {
    width: 100%;
    }


    /* ==========================================================================
    分页与响应式
    ========================================================================== */
    #todolist-pagination {
    display: flex;
    justify-content: center;
    margin: 30px 0;
    }
    .pagination-container {
    display: flex;
    align-items: center;
    gap: 5px;
    }
    .page-btn, .page-number {
    min-width: 36px;
    height: 36px;
    border: 1px solid var(--anzhiyu-card-border);
    background: var(--anzhiyu-card-bg);
    border-radius: 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 0.3s ease;
    color: var(--anzhiyu-fontcolor);
    }
    .page-btn:hover:not(:disabled), .page-number:hover:not(.active) {
    border-color: var(--anzhiyu-theme);
    color: var(--anzhiyu-theme);
    }
    .page-number.active {
    background: var(--anzhiyu-theme);
    color: white;
    border-color: var(--anzhiyu-theme);
    }
    .page-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    }
    #page-numbers {
    display: flex;
    gap: 5px;
    }
    @media screen and (max-width: 768px) {
    #todolist-box {
    margin: 0;
    padding: 0 10px;
    }
    .todolist-item {
    padding: 15px;
    }
    h3.todolist-title {
    font-size: 1.1rem;
    }
    .filter-buttons {
    overflow-x: auto;
    padding-bottom: 5px;
    flex-wrap: nowrap;
    }
    }

    /* ==========================================================================
    动画定义
    ========================================================================== */
    @keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
    }

    @keyframes check-box {
    0% { transform: scale(0.8); }
    50% { transform: scale(1.1); }
    100% { transform: scale(1); }
    }

第三步:让主题识别“待办清单”页面类型

  1. 打开主布局文件themes/anzhiyu/layout/page.pug

  2. 添加 when 'todolist':在 case page.type 的逻辑判断中,添加一个新的分支,告诉主题当遇到 typetodolist 的页面时,应该使用我们刚刚创建的 todolist.pug 模板来渲染。

    修改指引:

    1
    2
    3
    4
    5
    6
          when 'music'
    include includes/page/music.pug
    + when 'todolist'
    + include includes/page/todolist.pug
    default
    include includes/page/default-page.pug

    (您只需在 when 'music' 代码块的下方,添加那两行以 + 开头的代码即可)


第四步:创建并配置“待办清单”页面本身

  1. 执行创建页面命令

    • (如果之前没创建过)在终端运行:
    1
    hexo new page todolist
  2. 修改页面 Front-matter

    • 打开 source/todolist/index.md 文件。
    • 确保其 type"todolist"
    1
    2
    3
    4
    5
    6
    7
    8
    ---
    title: 待办清单
    date: 2025-06-14 12:00:00
    type: "todolist"
    top_background: "/img/background.png" # 可选,页面顶部背景图
    comments: false
    aside: false
    ---

第五步:在主题配置中注入新样式

  1. 打开主题配置文件 (themes/anzhiyu/_config.yml)。
  2. 找到 inject: 配置项,在 head: 列表中添加我们新建的CSS文件。
1
2
3
4
inject:
head:
# - 其他 head 内容...
- '<link rel="stylesheet" href="/custom/css/todolist.css">'

3**.菜单项更新**

1
2
3
4
5
个人:
# 友人帐: /link/ || anzhiyu-icon-link
# 朋友圈: /fcircle/ || anzhiyu-icon-artstation
留言板: /comments/ || anzhiyu-icon-envelope
代办清单: /todolist/ || fas fa-check-double