惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
Know Your Adversary
Know Your Adversary
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
Cloudbric
Cloudbric
Scott Helme
Scott Helme
C
CERT Recently Published Vulnerability Notes
Latest news
Latest news
P
Privacy International News Feed
S
Schneier on Security
Simon Willison's Weblog
Simon Willison's Weblog
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
AI
AI
MyScale Blog
MyScale Blog
T
Threat Research - Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
AWS News Blog
AWS News Blog
Webroot Blog
Webroot Blog
C
Cisco Blogs
博客园 - 聂微东
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
P
Privacy & Cybersecurity Law Blog
D
DataBreaches.Net
博客园_首页
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Project Zero
Project Zero
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Blog of Author Tim Ferriss
雷峰网
雷峰网
V2EX - 技术
V2EX - 技术
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
InfoQ
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
V
V2EX
I
Intezer
美团技术团队
TaoSecurity Blog
TaoSecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Cyberwarzone
Cyberwarzone
Google DeepMind News
Google DeepMind News
Microsoft Security Blog
Microsoft Security Blog
G
GRAHAM CLULEY

爱吃肉的猫

那就,再相逢 Butterfly的魔改教程:最新评论页 离歌不夜天 前端分享 - 滑动阻尼效果 Butterfly的魔改教程:右键菜单 音乐分享 - doi微醺氛围 近况记事 - 11 微信公众号:Ai大模型让回复更具智能化 近况记事 - 10 PWA:让你的网站变成桌面应用APP Healthy Love Butterfly的魔改教程:关于本站 近况记事 - 9 Butterfly的魔改教程:待办清单 TrollStore - 不掉签助手 近况记事 - 8 Twikoo评论回复邮件模版 过一个很特别的七夕 The Young Boy and the Sea
Butterfly的魔改教程:动态相册页
亦小封 · 2024-02-12 · via 爱吃肉的猫

240410 更新:调整Bar配置问题,修复多个相册页面造成的问题

240112 更新:新增Bar条切换相册分类;修复Bar栏重复点击的问题

如果没有服务器可以搭建memos,可以使用iCat自用的memos服务

引用站外地址,注意辨别

效果预览

引用站外地址,注意辨别

创建数据

  • 新建 [blogRoot]/themes/butterfly/layout/includes/page/photo.pug 页面,并新增以下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if page.bar
.icat-status-bar
.status-bar-tips= page.bar.tips || '类别'
.status-bar
#bar-box
each item in page.bar.list
- const content = item.split(' || ')
.status-bar-item
a(onclick="photos('" + content[0] + "')") #{content[1]}
#status-bar-button(onclick="statusbar()")
i.iconfont.icat-chevron-too
if page.bar.more
- const contents = page.bar.more.split(' || ')
if contents[0].startsWith('/')
a.status-bar-more(href="javascript:void(0)" onclick="pjax.loadUrl('" + contents[0] + "')") #{contents[1]}
else
a.status-bar-more(href=contents[0]) #{contents[1]}
div.gallery-photos.page
img(src="https://img.meuicat.com/blog/loading.svg" style="margin:auto")
  • 修改 [blogRoot]/themes/butterfly/layout/page.pug 来使页面匹配
    + 号直接删除 即是正常缩进)
1
2
3
4
5
6
      when 'categories'
include includes/page/categories.pug
+ when 'photo'
+ include includes/page/photo.pug
default
include includes/page/default-page.pug
  • 新建 [blogRoot]/themes/butterfly/source/css/_page/photo.styl 样式文件,并新增以下内容
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
.icat-status-bar
margin: 16px 0
display: flex
white-space: nowrap
align-items: center
background: var(--icat-card-bg)
border-radius: 8px
padding: 0 12px
border: var(--style-border)
transition: .6s
box-shadow: var(--icat-shadow-border)

&:hover
border-color: var(--icat-blue)
box-shadow: var(--icat-shadow-blue)

.status-bar
padding: 0.4rem 0 0.4rem 0.4rem
white-space: nowrap
overflow: hidden
transition: .3s
width: 100%
justify-content: space-between
user-select: none
display: flex
align-items: center
font-size: 15px

#bar-box
white-space: nowrap
overflow-x: scroll
overflow-y: hidden
display: flex
border-radius: 8px
align-items: center
height: 30px

.status-bar-item
a
padding: 0.1rem 0.5rem
margin-right: 10px
font-weight: 700
border-radius: 8px
display: flex
align-items: center
height: 30px
color: var(--icat-fontcolor)
opacity: .8
transition: .6s

&:hover
background: var(--icat-blue)
opacity: 1
color: var(--icat-white)

&.selected
a
background: var(--icat-blue) !important
opacity: 1 !important
color: var(--icat-white) !important

#status-bar-button
margin-left: 12px
cursor: pointer
height: 22px
display: flex
align-items: center
transition: .6s

&:hover
color: var(--icat-blue)

.status-bar-more
margin-left: 12px
font-weight: 400
color: var(--icat-fontcolor)
opacity: .8
transition: .6s

&:hover
color: var(--icat-blue)

#bar-box::-webkit-scrollbar
display: none

.gallery-photos
width: 100%
text-align: center
animation: slide-in .6s .4s backwards

.gallery-photo
min-height: 5rem
width: 24.99%
padding: 4px
position: relative
animation: slide-in 0.6s 0.4s backwards

+maxWidth1024()
width: 33.3%

+maxWidth768()
width: 49.9%
padding: 3px

+minWidth2000()
width: 20%

&:hover
img
transform: scale(1.1)

a
border-radius: 8px
border: var(--style-border)
box-shadow: var(--icat-shadow-border)
display: block
overflow: hidden
transition: .6s

&:hover
border-color: var(--icat-blue)
box-shadow: var(--icat-shadow-blue)

img
display: block
width: 100%
animation: fadeIn 1s
cursor: pointer
transition: all .4s ease-in-out

.photo-title,
.photo-time
max-width: calc(100% - 7px)
line-height: 1.8
position: absolute
left: 4px
font-size: 14px
background: rgba(0,0,0,0.3)
padding: 0px 8px
color: #fff
animation: fadeIn 1s

.photo-title
bottom:4px
border-radius: 0 8px 0 8px

+maxWidth768()
font-size: 12px
left: 3px
bottom: 3px

.photo-time
top:4px
border-radius: 8px 0 8px 0
可选CSS样式,bg,color
  • 新建 [blogRoot]/source/css/photo.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
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
.icat-status-bar {
margin: 16px 0;
display: flex;
white-space: nowrap;
align-items: center;
background: var(--icat-card-bg);
border-radius: 8px;
padding: 0 12px;
border: var(--style-border);
transition: 0.6s;
box-shadow: var(--icat-shadow-border);
}
.icat-status-bar:hover {
border-color: var(--icat-blue);
box-shadow: var(--icat-shadow-blue);
}
.icat-status-bar .status-bar {
padding: 0.4rem 0 0.4rem 0.4rem;
white-space: nowrap;
overflow: hidden;
transition: 0.3s;
width: 100%;
justify-content: space-between;
user-select: none;
display: flex;
align-items: center;
font-size: 15px;
}
.icat-status-bar .status-bar #bar-box {
white-space: nowrap;
overflow-x: scroll;
overflow-y: hidden;
display: flex;
border-radius: 8px;
align-items: center;
height: 30px;
}
.icat-status-bar .status-bar #bar-box .status-bar-item a {
padding: 0.1rem 0.5rem;
margin-right: 10px;
font-weight: 700;
border-radius: 8px;
display: flex;
align-items: center;
height: 30px;
color: var(--icat-fontcolor);
opacity: 0.8;
transition: 0.6s;
}
.icat-status-bar .status-bar #bar-box .status-bar-item a:hover {
background: var(--icat-blue);
opacity: 1;
-ms-filter: none;
filter: none;
color: var(--icat-white);
}
.icat-status-bar .status-bar #bar-box .status-bar-item.selected a {
background: var(--icat-blue) !important;
opacity: 1 !important;
-ms-filter: none !important;
filter: none !important;
color: var(--icat-white) !important;
}
.icat-status-bar #status-bar-button {
margin-left: 12px;
cursor: pointer;
height: 22px;
display: flex;
align-items: center;
transition: 0.6s;
}
.icat-status-bar #status-bar-button:hover {
color: var(--icat-blue);
}
.icat-status-bar .status-bar-more {
margin-left: 12px;
font-weight: 400;
color: var(--icat-fontcolor);
opacity: 0.8;
transition: 0.6s;
}
.icat-status-bar .status-bar-more:hover {
color: var(--icat-blue);
}
#bar-box::-webkit-scrollbar {
display: none;
}



.gallery-photos {
width:100%;
margin-top:16px;
text-align: center;
}
.gallery-photo {
min-height:5rem;
width:24.99%;
padding:4px;
position:relative;
}
.gallery-photo a {
border-radius:8px;
border: var(--style-border-always);
box-shadow: var(--icat-shadow-border);
display:block;
overflow:hidden;
}
.gallery-photo img {
display:block;
width:100%;
animation:fadeIn 1s;
cursor:pointer;
transition:all .4s ease-in-out !important;
}
.gallery-photo span.photo-title,.gallery-photo span.photo-time {
max-width:calc(100% - 7px);
line-height:1.8;
position:absolute;
left:4px;
font-size:14px;
background:rgba(0,0,0,0.3);
padding:0px 8px;
color:#fff;
animation:fadeIn 1s;
}
.gallery-photo span.photo-title {
bottom:4px;
border-radius:0 8px 0 8px;
}
.gallery-photo span.photo-time {
top:4px;
border-radius:8px 0 8px 0;
}
.gallery-photo:hover img {
transform:scale(1.1);
}
@media screen and (max-width:1100px) {
.gallery-photo {
width:33.3%;
}
}@media screen and (max-width:768px) {
.gallery-photo {
width:49.9%;
padding:3px
}




.gallery-photo span.photo-title {
font-size:12px
}
.gallery-photo span.photo-title {
left:3px;
bottom:3px;
}
@keyframes fadeIn {
0% {
opacity:0;
}
100% {
opacity:1;
}
}


  • _config.butterfly.yml 主题配置文件中 inject 下的 head 引入 photo.css
1
2
3
4
5
6
7
8
9
  ···

inject:
head:
- <link rel="stylesheet" href="/css/photo.css">
bottom:
- ···

···
  • 创建 [blogRoot]/source/js/memos/photo.js 文件,并新增以下内容,用来处理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
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
function whenDOMReady() {
if (location.pathname == '/photos/') photos('相册');
}
whenDOMReady()
document.addEventListener("pjax:complete", whenDOMReady)



window.onresize = () => {
if (location.pathname == '/photos/') waterfall('.gallery-photos');
};



function photos(tag) {
let apiUrl = `你的memos地址/api/v1/memo?creatorId=用户UID&tag=${tag}`;

fetch(apiUrl).then(res => res.json()).then(data => {
let html = '',
imgs = []
data.forEach(item => {
let ls = item.content.match(/\!\[.*?\]\(.*?\)/g)
if (ls) imgs = imgs.concat(ls)
if (item.resourceList.length) {
item.resourceList.forEach(t => {
if (t.externalLink) imgs.push(`![](${t.externalLink})`)
else imgs.push(`![](${url}/o/r/${t.id}/${t.publicId}/${t.filename})`)
})
}
})

if (imgs) imgs.forEach(item => {
let img = item.replace(/!\[.*?\]\((.*?)\)/g, '$1'),
time, title, tat = item.replace(/!\[(.*?)\]\(.*?\)/g, '$1')
if (tat.indexOf(' ') != -1) {
time = tat.split(' ')[0]
title = tat.split(' ')[1]
} else title = tat

html += `<div class="gallery-photo"><a href="${img}" data-fancybox="gallery" class="fancybox" data-thumb="${img}"><img class="no-lazyload photo-img" loading='lazy' decoding="async" src="${img}"></a>`
title ? html += `<span class="photo-title">${title}</span>` : ''
time ? html += `<span class="photo-time">${time}</span>` : ''
html += `</div>`
})

document.querySelector('.gallery-photos.page').innerHTML = html
imgStatus.watch('.photo-img', () => { waterfall('.gallery-photos') })
window.Lately && Lately.init({ target: '.photo-time' })
}).catch()

if (document.querySelector(".icat-status-bar")) {
var statusBarItemItems = document.querySelectorAll('.status-bar-item');
let firstElement = statusBarItemItems[1];
firstElement.classList.add('selected');

Array.from(statusBarItemItems).forEach(function (element) {
element.onclick = function (event) {
var selectedElements = document.querySelectorAll('.status-bar-item.selected');
Array.from(selectedElements).forEach(function (selectedElement) {
selectedElement.classList.remove('selected');
});
element.classList.add('selected');

event.stopPropagation();
event.preventDefault();
return false;
};
});
}
}



function statusbar() {
var e;
var t = document.getElementById("bar-box");
var o = document.getElementById("status-bar-button");
var n = t.clientWidth;
if (t) {
if (t.scrollLeft + t.clientWidth >= t.scrollWidth - 8) {
t.scroll({ left: 0, behavior: "smooth" });
} else {
t.scrollBy({ left: n, behavior: "smooth" });
}
t.addEventListener("scroll", function n() {
clearTimeout(e);
e = setTimeout(function () {
o.style.transform =
t.scrollLeft + t.clientWidth >= t.scrollWidth - 8 ? "rotate(180deg)" : "";
t.removeEventListener("scroll", n);
}, 150);
});
}
};


  • 创建 [blogRoot]/source/js/memos/imgStatus.min.js 文件,并新增以下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
! function() {
this.loaded = 0, this.failed = 0, this.total = 0, this.watch = function(a, b) {
var c = document.querySelectorAll(a);
if (!c.length) return console.log("[imgStatus]: There aren't any images associated with this selector (" + a + ")!");
this.total = c.length;
for (var d = 0; d < this.total; d++) isCached(c[d].src) ? this._setLoaded(b) : c[d].addEventListener ? (c[d].addEventListener("load", this._setLoaded.bind(this, b)), c[d].addEventListener("error", this._setFailed.bind(this, b))) : (c[d].attachEvent("onload", this._setLoaded.bind(this, b)), c[d].attachEvent("onerror", this._setFailed.bind(this, b)))
}, this.isCached = function(a) {
var b = new Image;
return b.src = a, b.complete
}, this._setFailed = function(a, b) {
++this.failed, "function" == typeof a && a(this)
}, this._setLoaded = function(a, b) {
++this.loaded, "function" == typeof a && a(this)
}, this.isDone = function() {
return this.loaded + this.failed === this.total ? !0 : !1
}, "object" == typeof window && (window.imgStatus = this)
}();


  • 创建 [blogRoot]/source/js/memos/lately.min.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
! function() {
window.Lately = new function() {
var t = this;
this.lang = {
second: "秒",
minute: "分钟",
hour: "小时",
day: "天",
month: "个月",
year: "年",
ago: "前",
error: "NaN"
};
var e = function(e) {
e = new Date(n(e));
var r = new function() {
this.second = (Date.now() - e.getTime()) / 1e3, this.minute = this.second / 60, this.hour = this.minute / 60, this.day = this.hour / 24, this.month = this.day / 30, this.year = this.month / 12
}, i = Object.keys(r).reverse().find(function(t) {
return r[t] >= 1
});
return (i ? function(t, e) {
return Math.floor(t) + e
}(r[i], t.lang[i]) : t.lang.error) + t.lang.ago
}, n = function(t) {
return t = new Date(t && ("number" == typeof t ? t : t.replace(/-/g, "/").replace("T", " "))), !isNaN(t.getTime()) && t.getTime()
};
return {
init: function() {
var r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, i = r.target,
a = void 0 === i ? "time" : i,
o = r.lang;
o && (t.lang = o);
var u = !0,
h = !1,
l = void 0;
try {
for (var s, c = document.querySelectorAll(a)[Symbol.iterator](); !(u = (s = c.next()).done); u = !0) {
var f = s.value,
g = n(f.dateTime) || n(f.title) || n(f.innerHTML) || 0;
if (!g) return;
f.title = new Date(g).toLocaleString(), f.innerHTML = e(g)
}
} catch (t) {
h = !0, l = t
} finally {
try {
!u && c.
return &&c.
return ()
} finally {
if (h) throw l
}
}
},
format: e
}
}
}();






  • 创建 [blogRoot]/source/js/memos/waterfall.min.js 文件,并新增以下内容,用来处理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 下的 headbottom 分别引入 waterfall.min.js lately.min.js imgStatus.min.js photo.js
1
2
3
4
5
6
7
8
9
10
11
12
  ···

inject:
head:
- ···
bottom:
- <script type="text/javascript" src="/js/memos/waterfall.min.js"></script>
- <script type="text/javascript" src="/js/memos/imgStatus.min.js"></script>
- <script type="text/javascript" src="/js/memos/lately.min.js"></script>
- <script type="text/javascript" src="/js/memos/photo.js"></script>

···
  • 创建并修改 [blogRoot]/source/photos/index.md 页面
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
---
title: 生活相册
date: 2023-03-14 21:47:47
type: photo
top_img: false
aside: false
top_page: true
top_bg: https://img.meuicat.com/banner
top_item: 相册
top_title: 快门の色彩瞬间
top_tips: 活在当下 热烈且自由
comments: false
bar:
tips: 年份类别
list:
- 相册 || 全部
- 2023 || 2023
- 2022 || 2022
- 2021 || 2021
- 2020 || 2020
- 2019 || 2019
- 2018 || 2018
- 2017 || 2017
more: /album/ || 影集
---

<!-- 页面内容 -->
参数 类型 释义
bar 可选 是否使用Bar分类栏
bar.tips 可选 Bar分类栏的提示文字
bar.list 必选 Bar分类栏的tag和显示文字,第一个参数为tag;第二个参数为需要显示的文字
bar.more 可选 Bar分类栏更多按钮的跳转链接和显示文字,第一个参数为跳转链接地址(支持/album/https://meuicat.com这种格式,不支持不带头标的meuicat.com格式;第二个参数为需要显示的文字

使用参数

1
2
3
4
5
6
7
8
9
#相册
<!-- 写法就是markdown的写法,中括号里先写时间再写标题,中间使用空格隔开 -->
![2023-01-29 我是标题](图片链接)
<!-- 若不想要时间只写标题即可 -->
![我是标题](图片链接)
<!-- 若不想要标题只写时间即可,只不过后面需要添加空格 -->
![2023-01-29 ](图片链接)
<!-- 也可以只填写图片链接 -->
![](图片链接)
  • memos 内的写法
1
2
3
4
5
#相册
![2023-02-09 ](https://s11.ax1x.com/2023/03/16/pp3jQ3V.jpg)
![ 犹豫没要微信](https://s11.ax1x.com/2023/03/17/ppGlZid.jpg)
![2022-10-12 可可爱爱没有脑袋](https://s11.ax1x.com/2023/03/16/pp34dpj.jpg)
![](https://s11.ax1x.com/2023/03/15/pp39iRI.jpg)

魔改适配

已适配Solitude主题,具体魔改教程可前往下方文章查看

引用站外地址,注意辨别

Solitude魔改教程:iCat同款动态相册页

用照片来定格住最好的自己;是时光流逝的见证者,亦是记录者

Butterfly的魔改教程:动态相册页

此文章版权归 MeuiCat 所有,完整转载,请注明来源!