安知鱼主题友链朋友圈的设置备忘录

今天给自己的博客布置友链朋友圈,使用的是 Friend-Circle-Lite:轻量友链朋友圈 ,感兴趣的朋友可以去看一看这篇文章,介绍的非常好,我安装的时候后端基本上有很多问题,而且问题都挺大,特别是安知鱼主题的修改,幸好博主 梦爱吃鱼 给出了安知鱼主题的修改,做一个整理分享。

1.创建 friend.json 文件

在博客根目录下面,创建一个 link.js 文件,将下面的代码粘贴进去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const YML = require('yamljs')
const fs = require('fs')
const blacklist = ["友站名称1", "友站名称2"]; // 排除的友站
let friends = [],
data_f = YML.parse(fs.readFileSync('source/_data/link.yml').toString().replace(/(?<=rss:)\s*\n/g, ' ""\n'));
data_f.forEach((entry, index) => {
let lastIndex = 2;
if (index < lastIndex) {
const filteredLinkList = entry.link_list.filter(linkItem => !blacklist.includes(linkItem.name));
friends = friends.concat(filteredLinkList);
}
});
const friendData = {
friends: friends.map(item => {
return [item.name, item.link, item.avatar];
})
};
const friendJSON = JSON.stringify(friendData, null, 2);
fs.writeFileSync('./source/friend.json', friendJSON);
console.log('friend.json 文件已生成。');

按照需求修改其中的黑名单,该黑名单可以用于排除一些采集站之类的灌水文章,其中填写对应站点的名称。

1.2.生成 friend.json

设置好 link.js 文件之后,在博客根目录下面的 Git Bash 对话框中输入并运行如下代码

1
2
npm install yamljs --save
node link.js

此时会在博客根目录下的 /source/ 文件夹中,生成 friend.json 文件,这个文件就是我们需要查询的博客链接的索引文件。

2.后端设置

Friend-Circle-Lite:轻量友链朋友圈 项目,是可以借助 Github Action 来运行的,但是我个人观点,受网络影响比较大,虽然现在已经有很多选择方案,我还是比较喜欢部署到自己的网络空间,相互调用起来方便一些,所以在这里不在介绍 Github Action 的安装,感兴趣的可以自己去查看教程。

2.1.进入服务器 SSH 链接

进入准备安装 Friend-Circle-Lite:轻量友链朋友圈 项目的网站目录,注意,Git 拉取的文件自带 Friend-Circle-Lite 文件夹,所以

1
cd /www/wwwroot/网站根目录

只需进入

1
cd /www/wwwroot/

即可,最后就会形成

1
/www/wwwroot/Friend-Circle-Lite

的文件路径。

2.2.克隆项目文件

1
2
git clone https://github.com/willow-god/Friend-Circle-Lite.git
cd Friend-Circle-Lite

2.3.下载服务相关包

1
2
pip install -r ./requirements.txt
pip install -r ./server/requirements-server.txt

安装服务相关包的时候,需要使用Python,所以建议大家先创建虚拟环境,然后在进行安装,很多的 SSH 会给出相关的建议,按照 SSH 的建议进行安装。

2.4.部署 API 设置

如果环境配置完毕,你可以进入目录路径后直接运行 deploy.sh 脚本启动 API 服务:

1
2
chmod +x ./deploy.sh
./deploy.sh

第一行代码是对 deploy.sh 文件进行赋予权限,第二行 ./deploy.sh 是运行 deploy.sh 脚本,只需要按照提示进行操作就可以。

2.5.程序测试

脚本运行过程中,其中的注释应该是较为详细的,如果部署成功你可以使用以下命令进行测试,如果获取到了 首页html 内容则成功:

1
curl 127.0.0.1:1223

其中的端口号可以修改,在 server.py 最后一行修改数字即可,如果你想删除该 API 服务,找到对应进程并使用Kill 命令杀死进程:

1
2
ps aux | grep python
kill -9 [这里填写上面查询结果中对应的进程号]

2.6.生成必须文件

此时我们进入安装项目的文件夹,会发现里面有一个 all.json 文件,这个文件,就是我们前端必须要调用的文件。

2.7宝塔面板添加计划任务

宝塔面板侧边栏点击计划任务,然后是新建任务,名称和时间自己设置,但是脚本任务中添加如下代码:

1
2
cd /www/wwwroot/Friend-Circle-Lite
python3 run.py

到这里,我们基本上完成了后端设置,下面我们来看是创建一个网站,主要是用这个网站的域名来调用 all.json 文件。

3.网站创建

我们需要一个域名来指向调用 all.json 文件,就需要创建一个网站,宝塔面板的相关设置如下:

在这多说一句,我借助豆包,设置了网站的伪静态

进入网站设置—–伪静态,输入下面的代码:

1
2
3
4
5
6
7
8
9
10
# 根地址重定向到 all.json
location = / {
rewrite ^/$ /all.json permanent;
}
# 放行 json 文件,解决跨域
location ~* \.json$ {
add_header Access-Control-Allow-Origin *;
add_header Content-Type application/json;
expires 10m;
}

主要因素是新建的网站没有主页,此时我们访问绑定的域名,会出现 403 错误,我们需要把网站根目录的 all.json 文件调用出来,所以把 json 文件当成网站的主页文件,此时我们测试一下,输入

1
https://quanzi.example.com/all.json

如果能够显示调用的数据,就成功了。当然,也需要给这个网站添加 ssl 验证。到这里,后端设置基本完成。

4.主题修改

我们虽然能够调用 all.json 文件,但是还需要把这个文件添加到安知鱼主题之中,所以还需要修改安知鱼主题的部分文件。

4.1.创建页面

Hexo 博客根目录下打开终端,输入

1
hexo new page fcircle

打开 \source\fcircle\index.md 文件,在其中添加一行

1
type: "fcircle"

最终效果为

1
2
3
4
5
6
7
---
title: 朋友圈
comments: false
aside: false
top_img: false
type: "fcircle"
---

主题配置文件中开启 menu 中友链,导航栏朋友圈,注意缩进!!!

4.2.替换 fcircle.pug 文件

文件目录 themes/anzhiyu/layout/includes/page/ 文件夹中,找到 fcircle.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
if theme.friends_lite.enable
link(rel="stylesheet", href=theme.friends_lite.fclite_css_url)
style.
#random-article {
display: none!important;
}
.card:hover,
#random-article:hover {
border: var(--style-border-hover)!important;
}
#modal-author-name-link,
.modal-article .modal-article-title:hover,
.card-title:hover{
color: var(--anzhiyu-theme)!important;
}
.modal-article,
#modal-articles-container {
border-top-color: var(--anzhiyu-theme)!important;
border-bottom-color: var(--anzhiyu-theme)!important;
}
#load-more-btn:hover {
background: var(--anzhiyu-theme)!important;
}
.fcircle_page
.author-content.author-content-item.fcirclePage.single(style=`background: url(${theme.friends_lite.top_background}) center / cover no-repeat !important;`)
.card-content
.author-content-item-tips 朋友圈
span.author-content-item-title 最新文章订阅
.content-bottom
.tips= theme.friends_lite.top_tips
.banner-button-group
a.banner-button(onclick='pjax.loadUrl("/about")')
i.anzhiyufont.anzhiyu-icon-arrow-circle-right(style='font-size: 22px; margin-right: 0.25rem')
span.banner-button-text 关于本人
.title-h2-a
.title-h2-a-left
h2(style='padding-top:0;margin:.6rem 0 .6rem') 🎣 钓鱼
a.random-post-start(href='javascript:fetchRandomPost();')
i.anzhiyufont.anzhiyu-icon-arrow-rotate-right
.title-h2-a-right
a.random-post-all(href='/link/') 全部友链
#random-post
.title-h2-a
.title-h2-a-left
h2 🐟 鱼塘
#friend-circle-lite-root

script.
if (typeof UserConfig === 'undefined') {
var UserConfig = {
private_api_url: '#{theme.friends_lite.private_api_url}',
page_turning_number: #{theme.friends_lite.page_turning_number},
error_img: '#{theme.friends_lite.error_img}'
}
}
script(src=theme.friends_lite.fclite_js_url)
script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))

4.3.替换 random_friends_post.js 文件

在博客文件目录 themes/anzhiyu/source/js/anzhiyu/ 文件夹中,找到 random_friends_post.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
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
var fdata = { defaultFish: 100, hungryFish: 100 };
if (typeof fdataUser !== "undefined") {
for (var key in fdataUser) {
if (fdataUser[key]) fdata[key] = fdataUser[key];
}
}

var randomPostTimes = 0;
var randomPostWorking = false;
var randomPostTips = [
"钓到了绝世好文!",
"在河边打了个喷嚏,吓跑了",
"你和小伙伴抢夺着",
"你击败了巨龙,在巢穴中发现了",
"挖掘秦始皇坟时找到了",
"在路边闲逛的时候随手买了一个",
"从学校班主任那拿来了孩子上课偷偷看的",
"你的同桌无情的从你的语文书中撕下了那篇你最喜欢的",
"考古学家近日发现了",
"外星人降临地球学习地球文化,落地时被你塞了",
"从图书馆顶层的隐秘角落里发现了闪着金光的",
"徒弟修炼走火入魔,为师立刻掏出了",
"在大山中唱山歌,隔壁的阿妹跑来了,带着",
"隔壁家的孩子数学考了满分,都是因为看了",
"隔壁家的孩子英语考了满分,都是因为看了",
"小米研发了全新一代MIX手机,据说灵感",
"修炼渡劫成功,还好提前看了",
"库克坐上了苹果CEO的宝座,因为他面试的时候看了",
"阿里巴巴大喊芝麻开门,映入眼帘的就是",
"师傅说练武要先炼心,然后让我好生研读",
"科考队在南极大陆发现了被冰封的",
"飞机窗户似乎被一张纸糊上了,仔细一看是",
"历史上满写的仁义道德四个字,透过字缝里却全是",
"十几年前的录音机似乎还能够使用,插上电发现正在播的是",
"新版语文书拟增加一篇熟读并背诵的",
"经调查,99%的受访者都没有背诵过",
"今年的高考满分作文是",
"唐僧揭开了佛祖压在五指山上的",
"科学家发现能够解决衰老的秘密,就是每日研读",
"英特尔发布了全新的至强处理器,其芯片的制造原理都是",
"新的iPhone产能很足,新的进货渠道是",
"今年亩产突破了八千万斤,多亏了",
"陆隐一统天上宗,在无数祖境高手的目光下宣读了",
"黑钻风跟白钻风说道,吃了唐僧肉能长生不老,他知道是因为看了",
"上卫生间没带纸,直接提裤跑路也不愿意玷污手中",
"种下一篇文章就会产生很多很多文章,我种下了",
"三十年河东,三十年河西,莫欺我没有看过",
"踏破铁血无觅处,得来全靠",
"今日双色球中了两千万,预测全靠",
"因为卷子上没写名字,老师罚抄",
"为了抗议世间的不公,割破手指写下了",
"在艺术大街上被贴满了相同的纸,走近一看是",
"这区区迷阵岂能难得住我?其实能走出来多亏了",
"今日被一篇文章顶上了微博热搜,它是",
"你送给乞丐一个暴富秘籍,它是",
"UZI一个走A拿下五杀,在事后采访时说他当时回想起了",
"科学家解刨了第一个感染丧尸病毒的人,发现丧尸抗体存在于",
"如果你有梦想的话,就要努力去看",
"决定我们成为什么样人的,不是我们的能力,而是是否看过",
"有信心不一定会成功,没信心就去看",
"你真正是谁并不重要,重要的是你看没看过",
"玄天境重要的是锻体,为师赠你此书,好好修炼去吧,这是",
"上百祖境高手在天威湖大战三天三夜为了抢夺",
"这化仙池水乃上古真仙对后人的考校,要求熟读并背诵",
"庆氏三千年根基差点竟被你小子毁于一旦,能够被我拯救全是因为我看了",
"我就是神奇宝贝大师!我这只皮卡丘可是",
"我就是神奇宝贝大师!我这只小火龙可是",
"我就是神奇宝贝大师!我这只可达鸭可是",
"我就是神奇宝贝大师!我这只杰尼龟可是",
"上古遗迹中写道,只要习得此书,便得成功。你定睛一看,原来是",
"奶奶的,玩阴的是吧,我就是双料特工代号穿山甲,",
"你的背景太假了,我的就逼真多了,学到这个技术全是因为看了",
"我是云南的,云南怒江的,怒江芦水市,芦水市六库,六库傈僳族,傈僳族是",
"我真的栓Q了,我真的会谢如果你看",
"你已经习得退退退神功,接下来的心法已经被记录在",
"人生无常大肠包小肠,小肠包住了",
"你抽到了普通文章,它是",
"你收到了稀有文章,它是",
"你抽到了金色普通文章,它是",
"你抽到了金色稀有文章,它是",
"你抽到了传说文章!它是",
"哇!金色传说!你抽到了金色传说文章,它是",
"报告!侦察兵说在前往300米有一个男子在偷偷看一本书,上面赫然写着",
"芷莲姑娘大摆擂台,谁若是能读完此书,便可娶了她。然后从背后掏出了",
"请问你的梦想是什么?我的梦想是能读到",
"读什么才能增智慧?当然是读",
"纳兰嫣然掏出了退婚书,可是发现出门带错了,结果拿出了一本",
"你要尽全力保护你的梦想。那些嘲笑你的人,他们必定会失败,他们想把你变成和他们一样的人。如果你有梦想的话,就要努力去读",
"走人生的路就像爬山一样,看起来走了许多冤枉的路,崎岖的路,但终究需要读完",
"游戏的规则就是这么的简单,你听懂了吗?管你听没听懂,快去看",
];

var randomPostClick = 0;

function fetchRandomPost() {
if (!document.getElementById("random-post")) return;
if (randomPostWorking) return;
randomPostWorking = true;

let randomRotate = randomPostTimes * 360;
let randomPostTipsItem = randomPostTips[Math.floor(Math.random() * randomPostTips.length)];
let randomPostLevel = getRandomPostLevel(randomPostTimes);

document.getElementById("random-post").innerHTML = randomPostTimes >= 5 ?
`钓鱼中... (Lv.` + randomPostTimes + ` 当前称号:` + randomPostLevel + `)` :
`钓鱼中...`;

let randomTime = randomPostTimes == 0 ? 0 : randomNum(1000, 3000);

document.querySelector(".random-post-start").style.opacity = "0.2";
document.querySelector(".random-post-start").style.transitionDuration = "0.3s";
document.querySelector(".random-post-start").style.transform = "rotate(" + randomRotate + "deg)";

if (randomPostClick * fdata.hungryFish + fdata.defaultFish < randomPostTimes && Math.round(Math.random()) == 0) {
document.getElementById("random-post").innerHTML =
"因为只钓鱼不吃鱼,过分饥饿导致本次钓鱼失败...(点击任意一篇钓鱼获得的文章即可恢复)";
randomPostWorking = false;
} else {
fetch(UserConfig.private_api_url + 'all.json')
.then(res => res.json())
.then(json => {
let randomArticle = json.article_data[Math.floor(Math.random() * json.article_data.length)];
let { title, link, author } = randomArticle;
window.setTimeout(() => {
document.getElementById("random-post").innerHTML =
randomPostTipsItem +
`来自友链 <b>` +
author +
`</b> 的文章:<a class="random-friends-post" onclick="randomClickLink()" target="_blank" href="` +
link +
`" rel="external nofollow">` +
title +
`</a>`;
randomPostTimes += 1;
localStorage.setItem("randomPostTimes", randomPostTimes);
document.querySelector(".random-post-start").style.opacity = "1";
}, randomTime);
})
.catch(error => {
console.error('Error fetching data:', error);
document.getElementById("random-post").innerHTML = "获取文章失败,请稍后再试。";
})
.finally(() => {
randomPostWorking = false;
});
}
}

function initRandomPost() {
if (localStorage.randomPostTimes) {
randomPostTimes = parseInt(localStorage.randomPostTimes);
randomPostClick = parseInt(localStorage.randomPostClick);
document.querySelector(".random-post-start").style.transitionDuration = "0.3s";
document.querySelector(".random-post-start").style.transform = "rotate(" + 360 * randomPostTimes + "deg)";
}
fetchRandomPost();
}

function randomClickLink() {
randomPostClick += 1;
localStorage.setItem("randomPostClick", randomPostClick);
}

function randomNum(minNum, maxNum) {
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
}

function getRandomPostLevel(times) {
if (times > 10000) return "愿者上钩";
if (times > 1000) return "俯览天下";
if (times > 100) return "绝世渔夫";
if (times > 75) return "钓鱼王者";
if (times > 50) return "钓鱼宗师";
if (times > 20) return "钓鱼专家";
if (times > 5) return "钓鱼高手";
return "钓鱼新手";
}

initRandomPost();

4.4.适配友链钓鱼

文件目录 themes/anzhiyu/layout/includes/page/ 文件夹下,找到 flink.pug 文件,在这个文件夹里搜索 .banner-button-group 找到如下代码:

1
2
.banner-button-group
if (theme.friends_vue.apiurl)

将上面的代码修改为

1
2
.banner-button-group
if (theme.friends_lite.private_api_url)

继续搜索 #random-post 会找到如下代码:

1
2
#random-post
script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))

将搜索到的代码,修改为如下代码:

1
2
3
4
5
6
7
8
9
10
#random-post
script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))
script.
if (typeof UserConfig === 'undefined') {
var UserConfig = {
private_api_url: '#{theme.friends_lite.private_api_url}',
page_turning_number: #{theme.friends_lite.page_turning_number},
error_img: '#{theme.friends_lite.error_img}'
}
}

需要注意的是,pug 文件需要较好的缩进,如果不能缩进对齐,会代码混乱,可以用我替换好的文件把 flink.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
#article-container
if theme.linkPageTop && theme.linkPageTop.enable
#flink-banners
.banner-top-box
.flink-banners-title
.banners-title-small=_p('flink.title')
.banners-title-big=theme.linkPageTop ? theme.linkPageTop.title : _p('flink.title')
.banner-button-group
if (theme.friends_lite.private_api_url)
a.banner-button.secondary.no-text-decoration(onclick="friendChainRandomTransmission()")
i.anzhiyufont.anzhiyu-icon-paper-plane1
span.banner-button-text=_p('flink.random_visit')
if theme.linkPageTop.addFriendPlaceholder && theme.comments.use == 'Twikoo' && theme.twikoo.envId
a.banner-button.no-text-decoration(onclick="anzhiyu.addFriendLink()")
i.anzhiyufont.anzhiyu-icon-arrow-circle-right
span.banner-button-text=_p('flink.apply_link')
#skills-tags-group-all
.tags-group-wrapper
- function getAvatarWithoutExclamationMark(url) {
- const index = url.indexOf('!');
- return index !== -1 ? url.substring(0, index) : url;
- }
each y in [1,2]
each i, index in site.data.link.slice(0, 15)
- const link_list = i.link_list.slice()
- const hundredSuffix = i.hundredSuffix ? i.hundredSuffix : ""
- const evenNum = link_list.filter((x, index) => index % 2 === 0);
- const oddNum = link_list.filter((x, index) => index % 2 === 1);
each item, index2 in link_list.slice(0, Math.min(evenNum.length, oddNum.length))
- const index = index2 * 2
if (index <= 15 && typeof evenNum[index] !== 'undefined' && typeof oddNum[index] !== 'undefined')
- let oddNumAvatar = getAvatarWithoutExclamationMark(oddNum[index].avatar);
- let evenNumAvatar = getAvatarWithoutExclamationMark(evenNum[index].avatar);
.tags-group-icon-pair
a.tags-group-icon.no-text-decoration(href=url_for(evenNum[index].link), title=evenNum[index].name)
img.no-lightbox(title=evenNum[index].name, src=url_for(evenNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=evenNum[index].name)
a.tags-group-icon.no-text-decoration(href=url_for(oddNum[index].link), title=oddNum[index].name)
img.no-lightbox(title=oddNum[index].name, src=url_for(oddNumAvatar + hundredSuffix) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=oddNum[index].name)
if theme.friends_vue && theme.friends_vue.enable
.title-h2-a
.title-h2-a-left
h2(style='padding-top:0;margin:.6rem 0 .6rem')=_p('flink.fishing')
a.random-post-start.no-text-decoration(href='javascript:fetchRandomPost();')
i.anzhiyufont.anzhiyu-icon-arrow-rotate-right
.title-h2-a-right
a.random-post-all.no-text-decoration(href='/link/')=_p('flink.all_links')
#random-post
script(defer data-pjax src=url_for(theme.asset.random_friends_post_js))
script.
if (typeof UserConfig === 'undefined') {
var UserConfig = {
private_api_url: '#{theme.friends_lite.private_api_url}',
page_turning_number: #{theme.friends_lite.page_turning_number},
error_img: '#{theme.friends_lite.error_img}'
}
}

.flink
if site.data.link
each i in site.data.link
if i.class_name
h2!= i.class_name + "(" + i.link_list.length + ")"
if i.class_desc
.flink-desc!=i.class_desc
if i.flink_style === 'anzhiyu'
div(class=i.lost_contact ? 'anzhiyu-flink-list cf-friends-lost-contact' : 'anzhiyu-flink-list')
if i.link_list
each item in i.link_list
- let color = item.color || ""
- let tag = item.tag || ""

.flink-list-item
if color == "vip" && tag
span.site-card-tag.vip #[=tag]
i.light
else if color == "speed" && tag
span.site-card-tag.speed #[=tag]
else if tag
span.site-card-tag(style=`background-color: ${color}`) #[=tag]
else if item.recommend
span.site-card-tag=_p('flink.recommend')
if i.lost_contact
a.cf-friends-link(href=url_for(item.link) title=item.name target="_blank")
if theme.lazyload.enable
img.no-lightbox(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
else
img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
.flink-item-info
.flink-item-name.cf-friends-name-lost-contact= item.name
else
a.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) title=item.name target="_blank")
if theme.lazyload.enable
img.cf-friends-avatar.no-lightbox(data-lazy-src=url_for(item.avatar), cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
else
img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
.flink-item-info
.flink-item-name.cf-friends-name= item.name
.flink-item-desc(title=item.descr)= item.descr

else if i.flink_style === 'telescopic'
.telescopic-site-card-group
each item in i.link_list
- let color = item.color || ""
- let tag = item.tag || ""
- let siteshot = item.siteshot || `https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/${item.link}` || theme.default_img
.site-card
if color == "vip" && tag
span.site-card-tag.vip #[=tag]
i.light
else if color == "speed" && tag
span.site-card-tag.speed #[=tag]
else if tag
span.site-card-tag(style=`background-color: ${color}`) #[=tag]
else if item.recommend
span.site-card-tag=_p('flink.recommend')
a.img.no-text-decoration(target='_blank', title=`${item.name}`, href=`${item.link}`, rel='external nofollow')
img.flink-avatar(data-lazy-src=siteshot, onerror=`this.onerror=null;this.src='${theme.default_img}'`, alt=item.name, style="pointer-events: none;", src=`${siteshot}`)
a.info.cf-friends-link.no-text-decoration(target='_blank', title=`${item.name}`, href=`${item.link}`, cf-href=url_for(item.link), rel='external nofollow')
.site-card-avatar
img.flink-avatar.cf-friends-avatar.no-fancybox(data-lazy-src=item.avatar, cf-src=url_for(item.avatar), onerror=`this.onerror=null;this.src='${theme.default_img}'`, alt=item.name, src=item.avatar)
.site-card-text
span.title.cf-friends-name #[=item.name]
span.desc(title=`${item.descr}`) #[=item.descr]
else if i.flink_style === 'flexcard'
.flexcard-flink-list
each item in i.link_list
a.flink-list-card.cf-friends-link(href=url_for(item.link) cf-href=url_for(item.link) target='_blank' data-title=item.descr)
.wrapper.cover
- var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link
if theme.lazyload.enable
img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='cover' )
else
img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='cover' )
.info
if theme.lazyload.enable
img.cf-friends-avatar.no-lightbox.flink-avatar(data-lazy-src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='cover' )
else
img.cf-friends-avatar.no-lightbox(src=url_for(item.avatar) cf-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='cover' )
span.flink-sitename.cf-friends-name= item.name
!= page.content

4.5.添加配置项

主题配置文件中搜索 friends_vue ,会找到如下代码:

1
2
3
4
5
6
7
# 朋友圈配置
friends_vue:
enable: false
vue_js: https://npm.elemecdn.com/anzhiyu-theme-static@1.1.1/friends/index.4f887d95.js
apiurl: # 朋友圈后端地址
top_tips: 使用 友链朋友圈 订阅友链最新文章
top_background:

将其全部替换为:

1
2
3
4
5
6
7
8
9
10
# Lite朋友圈配置
friends_lite:
enable: true
fclite_css_url: https://fc.bsgun.cn/main/fclite.css # 轻量朋友圈的CSS
fclite_js_url: https://fc.bsgun.cn/main/fclite.js # 轻量朋友圈的js
private_api_url: https://fc.bsgun.cn/ # 获取json的API URL
page_turning_number: 20 # 每页显示的文章数量
error_img: https://cdn.bsgun.cn/Hexo-static/img/error-404.avif # 404图片 URL
top_background: https://cdn.bsgun.cn/Hexo-static/img/essay-bg.avif # 顶部背景图片 URL
top_tips: 使用 轻量友链朋友圈 订阅友链最新文章 # 顶部提示文本

5.内容出处

5.1柳神博客

5.2梦爱吃鱼

6.检查效果生成

最后 Hexo 三连(hexo c && hexo g && hexo s)就可以看到文章中第二张图调用的效果。

写这篇文章,纯粹是为了做一个纪念,因为我布置好后端之后,发现前端的问题也不少,幸好找到了教程,分享给大家,更主要是帮助自己,日后博客又问什么问题可以更好地恢复过来。