最后更新于 2023 年 10 月 06 日
231006 更新:适配本地静态数据部署
效果预览 创建数据 创建 [blogRoot]/source/project/index.md
页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 --- title: 清单 date: 2023-04-20 11:56:42 type: project top_img: false aside: false top_ page: truetop_bg: https://img.meuicat.com/banner top_ item: 待办top_title: 生活清单 top_ tips: 原来我有这么多想要做的事情comments: false --- <!-- 页面内容 -->
修改 [blogRoot]/themes/butterfly/layout/page.pug
来使页面匹配 ( + 号直接删除 即是正常缩进) 1 2 3 4 5 6 when 'categories' include includes/page/categories.pug + when 'project' + include includes/page/project.pug default include includes/page/default-page.pug
新建 [blogRoot]/themes/butterfly/layout/includes/page/project.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 if page.memos_url #todolist .todolist-bottom p Powered by a(target="_blank" href="https://github.com/usememos/memos" rel="noopener external nofollow") Memos else if site.data.project #todolist - let result = "" each i in site.data.project - let className = i.class_name - let listResult = "" - let state = "" - let strikethrough = "" each j in i.project_list - if (j.state) { state = `fa-circle-check` strikethrough = `class="achieve"` } else { state = `fa-circle` strikethrough = `` } listResult += ` <li ${strikethrough}> <i style="margin-right: 5px;" class="fa-regular ${state}"></i>${j.content} </li>` - - result += `<div class="list_item"><h3>${className}</h3><ul>${listResult}</ul></div>` != result .todolist-bottom p Powered by a(target="_blank" href="https://github.com/usememos/memos" rel="noopener external nofollow") Memos
新建 [blogRoot]/source/css/project.css
样式文件,并新增以下内容 (也可以在自建的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 #todolist { display : flex; flex-wrap : wrap; margin-top : 1rem ; } .list_item { display : inline-block; width : calc (33.333% - .5rem ); background : #ffe3dd ; border-radius : 12px ; border : var (--style-border-always); box-shadow : var (--icat-shadow-border); padding : 10px 1rem 1.2rem ; border : 2px dashed #f7a796 ; --todo-border : 1px solid #f7a796 ; margin-right : 1rem ; margin-bottom : 1rem ; } .list_item h3 { margin : 0 ; color : #333 ; border-bottom : var (--todo-border); } .list_item ul { font-size : 17px ; padding : 0 !important ; margin : 0 ; } .list_item li { margin : 0 !important ; color : #333 ; border-bottom : var (--todo-border); } .list_item li ::marker {content : none;} li .achieve { opacity : .8 ; text-decoration : line-through; } .bottom { line-height : 1.5 ; text-align : right; } .bottom p { margin : 0 !important ; } .bottom a { font-weight : 700 ; color : var (--font-color) !important ; } [data-theme="dark" ] .list_item { border : 2px solid var (--icat-card-border) !important ; } @media screen and (max-width : 900px ) { div #todolist { margin : 1rem 5px 0 ; } } @media screen and (max-width : 768px ) { .list_item { width : 100% ; } .bottom { text-align : center; } }
创建 [blogRoot]/source/js/memos/waterfall.min.js
文件,并新增以下内容,用来处理Memos清单页的瀑布流 (在前几节的即刻短文和上一节的Memos动态相册教程里都有此js步骤,如果有了那么这一步就可以跳过) 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 function waterfall (a ) { function b (a, b ) { var c = window .getComputedStyle (b); return parseFloat (c["margin" + a]) || 0 } function c (a ) { return a + "px" } function d (a ) { return parseFloat (a.style .top ) } function e (a ) { return parseFloat (a.style .left ) } function f (a ) { return a.clientWidth } function g (a ) { return a.clientHeight } function h (a ) { return d (a) + g (a) + b ("Bottom" , a) } function i (a ) { return e (a) + f (a) + b ("Right" , a) } function j (a ) { a = a.sort (function (a, b ) { return h (a) === h (b) ? e (b) - e (a) : h (b) - h (a) }) } function k (b ) { f (a) != t && (b.target .removeEventListener (b.type , arguments .callee ), waterfall (a)) } "string" == typeof a && (a = document .querySelector (a)); var l = [].map .call (a.children , function (a ) { return a.style .position = "absolute" , a }); a.style .position = "relative" ; var m = []; l.length && (l[0 ].style .top = "0px" , l[0 ].style .left = c (b ("Left" , l[0 ])), m.push (l[0 ])); for (var n = 1 ; n < l.length ; n++) { var o = l[n - 1 ], p = l[n], q = i (o) + f (p) <= f (a); if (!q) break ; p.style .top = o.style .top , p.style .left = c (i (o) + b ("Left" , p)), m.push (p) } for (; n < l.length ; n++) { j (m); var p = l[n], r = m.pop (); p.style .top = c (h (r) + b ("Top" , p)), p.style .left = c (e (r)), m.push (p) } j (m); var s = m[0 ]; a.style .height = c (h (s) + b ("Bottom" , s)); var t = f (a); window .addEventListener ? window .addEventListener ("resize" , k) : document .body .onresize = k }
在 _config.butterfly.yml
主题配置文件中 inject
下的 head
和 bottom
分别引入 project.css
waterfall.min.js
1 2 3 4 5 6 7 8 9 ··· inject: head: - <link rel="stylesheet" href="/css/project.css"> bottom: - <script type="text/javascript" src="/js/memos/waterfall.min.js"></script> ···
部署数据文件 创建 [blogRoot]/source/_data/project.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 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 - class_name: 近期计划 project_list: - content: 工作项目顺利收尾完工 state: true - content: 返深 state: true - content: 抽空处理分享describe state: true - content: 考虑转行 state: false - class_name: 要处理的项目 project_list: - content: 做一款阅读类博客主题 state: false - content: 导航页 state: false - content: 个人主页 state: false - content: 简历页 state: false - content: 重构 iCat 布柒糖FM state: true - content: 重构 iCat 卡布奇诺 state: true - content: 二次重构优化 iCat爱吃肉的猫 V2.0 state: true - content: 布柒糖FM 项目铺展 state: false - class_name: 自我提升 project_list: - content: 每月至少阅读一本书 state: true - content: 养成定点喝水的习惯 state: true - content: 每日刮胡子 state: true - content: 定期护肤 state: false - content: 专升本 state: false - content: 坚持健身 state: false - class_name: 想学的技术 project_list: - content: CSS进阶 state: true - content: Javascript进阶 state: false - content: 微信小程序 state: true - content: 单片机 state: false - content: Node state: true - content: Docker state: true - content: Webpack state: false - content: Photoshop state: true - content: Illustrator state: false - content: EJS state: true - class_name: 想买的东西 project_list: - content: 奥林巴斯 EM-5 III state: false - content: SONY A7R3A state: false - content: DJI Mini 3 Pro state: false - content: MacBook Pro state: true - content: Apple Watch Series 7 state: true - content: 换WD 移动硬盘 2TB state: false
创建 [blogRoot]/source/js/memos/project.js
文件,并新增以下内容,用来处理本地清单的瀑布流响应布局 (或写在自建的公共 js 中也可以) 1 2 3 4 5 6 7 8 9 function whenDOMReady ( ) { window .addEventListener ('load' , function ( ) { if (location.pathname == '/project/' ) waterfall ('#todolist' ); }); } whenDOMReady ()document .addEventListener ("pjax:complete" , whenDOMReady)
在 _config.butterfly.yml
主题配置文件中 inject
下的 bottom
引入 project.js
文件 1 2 3 4 5 6 7 8 9 ··· inject: head: ··· bottom: - <script type="text/javascript" src="/js/memos/project.js"></script> ···
如果没有服务器可以搭建memos,可以使用iCat自用的memos服务:iCat - Memos
新增 [blogRoot]/source/project/index.md
页面的 Post Front-matter
配置项 memos_url
为 true
1 2 3 4 5 6 7 --- ··· memos_url: true --- <!-- 文章内容 -->
创建 [blogRoot]/source/js/memos/project.js
文件,并新增以下内容,用来处理Memos清单的函数 (或写在自建的公共 js 中也可以) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 todolist ();function todolist ( ) { fetch ('你的memos地址/api/v1/memo?creatorId=用户ID&tag=清单' ).then (res => res.json ()).then (data => { data.forEach (item => { let content = item.content , title = content.match (/\[(.*?)\]/g )[0 ].replace (/\[(.*?)\]/ , '$1' ); content = content.replace (/#.*\s/g , '' ).replace (/(-\s\[\s\]\s)(.*)/g , `<li><i style="margin-right: 5px;" class="fa-regular fa-circle"></i>$2</li>` ).replace (/(-\s\[x\]\s)(.*)/g , `<li class="achieve"><i style="margin-right: 5px;" class="fa-regular fa-circle-check"></i>$2</li>` ); let div = document .createElement ('div' ); div.className = 'list_item' ; div.innerHTML = `<h3>${title} </h3><ul>${content} </ul>` ; document .getElementById ('todolist' ).appendChild (div); }); waterfall ('#todolist' ); }).catch () }
Memos1.4.0以上版本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 todolist ();function todolist ( ) { fetch ('你的memos地址/api/memo?creatorId=用户ID&tag=清单' ).then (res => res.json ()).then (data => { data = data.data let box = document .getElementById ('todolist' ) data.forEach (item => { let content = item.content , title = content.match (/\[(.*?)\]/g )[0 ].replace (/\[(.*?)\]/ ,'$1' ); content = content.replace (/#.*\s/g , '' ).replace (/(-\s\[\s\]\s)(.*)/g , `<li><i style="margin-right: 5px;" class="fa-regular fa-circle"></i>$2</li>` ).replace (/(-\s\[x\]\s)(.*)/g , `<li class="achieve"><i style="margin-right: 5px;" class="fa-regular fa-circle-check"></i>$2</li>` ); let div = document .createElement ('div' ); div.className = 'list_item' ; div.innerHTML = `<h3>${title} </h3><ul>${content} </ul>` ; box.appendChild (div); }); waterfall ('#todolist' ); }).catch () }
在 _config.butterfly.yml
主题配置文件中 inject
下的 bottom
引入 project.js
文件 1 2 3 4 5 6 7 8 9 ··· inject: head: ··· bottom: - <script type="text/javascript" src="/js/memos/project.js"></script> ···
1 2 3 #清单 [我是标题栏] - [ ] 我是内容1- [x] 我是内容2
注意: 前面的 #清单 是固定的 标题用中括号包起来 已完成的将括号内的空格改成 x 即可