相册接入Memos实现自动更新
自言自语
本教程基于anzhiyu二改,如果是小白建议先按照鱼佬文档教程 搭建好基本页面在看此教程相册支持Memos
地址以及相册细节优化(type为2展示时间)album_list
和url
问题
初衷: 更新相册为了更方便一点,按照鱼的主题教程来搭建的目前只支持手动在 album.yml
文件中更新照片数据 更新完之后还需要在编译、 在提交博客到仓库,为了方便更新相册数据因此接入Memos,省去在博客中操作的繁琐步骤 让页面看起来更顺我心意,看不顺眼那就魔改一下下吧~
这里在详细说明一下关于
album_list
的问题,在鱼佬的相册页面配置教程中,有一个album_list
和一个url
属性, 当album_list
和url
同时存在的时候,会将url
中的数据覆盖掉album_list
中的数据,所以我觉得要么就都展示,要么就严谨一点做个断言处理,如果url存在链接地址,将会直接忽略album_list
这个只是一个小问题,可以忽略,但是作为强迫症患者的我受不了一点...到时候在做修改吧
效果预览
效果预览
鱼佬效果
图片展示无时间显示 当
type
为2时页面图片无时间展示 但是type
为1时就有时间..... 本人强迫症看到此时此景非常的不爽,要么都有,要么都没有,这里忍不住吐槽一番吧~
修改后的效果 相册
图片展示时间
接入Memos,前面四张一样的是memos做测试用的
前提说明
本文不对Memos
搭建做说明,如果您还未搭建自己的Memos
地址请移步到 教程 也可以使用可以使用小N和杜老师维护的公益服务:memos纯公益代部署服务
修改步骤
修改main.js
文件地址 themes/anzhiyu/source/js/main.js
,搜代码justified-gallery 圖庫排版
,改动较多建议直接全部复制替换这个方法
/**
* justified-gallery 圖庫排版
*/
const runJustifiedGallery = function (ele) {
const htmlStr = arr => {
let str = "";
const replaceDq = str => str.replace(/"/g, """); // replace double quotes to "
arr.forEach(i => {
const alt = i.alt ? `alt="${replaceDq(i.alt)}"` : "";
const title = i.title ? `title="${replaceDq(i.title)}"` : "";
const dateTime = i.date ? `${new Date(i.date).toISOString()}` : "";
const address = i.address ? i.address : "";
const galleryItem = `
<div class="fj-gallery-item" id="serms-fj-gallery-item">
${address ? `<div class="tag-address">${address}</div>` : ""}
<img src="${i.url}" ${alt + title} class="card_cover">
<div class="serms-album-info-time">
<time class="datatime" datatime=${i.date} style="display: inline;">${i.date}</time>
</div>
</div>
`;
str += galleryItem;
});
return str;
};
const lazyloadFn = (i, arr, limit) => {
const loadItem = Number(limit);
const arrLength = arr.length;
if (arrLength > loadItem) i.insertAdjacentHTML("beforeend", htmlStr(arr.splice(0, loadItem)));
else {
i.insertAdjacentHTML("beforeend", htmlStr(arr));
i.classList.remove("lazyload");
}
window.lazyLoadInstance && window.lazyLoadInstance.update();
return arrLength > loadItem ? loadItem : arrLength;
};
function imageInfo(input) {
const lines = input.split('\n').filter(line => line.trim() !== ''); // 分割成每行,并过滤掉空行
const result = [];
lines.forEach(line => {
const regex = /\!\[(.*?)\]\((.*?)\)/;
const match = line.match(regex);
if (match) {
const [, titlePart, url] = match;
const [, date, address, title] = titlePart.trim().match(/(\d{4}-\d{2}-\d{2})\s(.*?)\s(.*)/);
const infoObject = {
"url": url.trim(),
"address": address.trim(),
"date": date.trim(),
"title": title.trim(),
};
result.push(infoObject);
}
});
return result;
}
const fetchUrl = async url => {
try {
const [dUrl, mUrl] = url.split("https://").slice(1);
const [dUrlResponse, mUrlResponse] = await Promise.all([
fetch(`https://${dUrl}`),
fetch(`https://${mUrl}`)
]);
if (!dUrlResponse.ok || !mUrlResponse.ok) {
throw new Error('Network response was not ok');
}
const [dUrlData, mUrlData] = await Promise.all([
dUrlResponse.json(),
mUrlResponse.json()
]);
const mUrlArryData = imageInfo(mUrlData[0].content);
return mUrlArryData.concat(dUrlData);
} catch (error) {
console.error('Error occurred:', error);
return []; // 返回空数组或者其他错误处理策略
}
};
const runJustifiedGallery = (item, arr) => {
const limit = item.getAttribute("data-limit") ?? arr.length;
if (!item.classList.contains("lazyload") || arr.length < limit) {
// 不懒加载
item.innerHTML = htmlStr(arr);
item.nextElementSibling.style.display = "none";
} else {
if (!item.classList.contains("btn_album_detail_lazyload") || item.classList.contains("page_img_lazyload")) {
// 滚动懒加载
lazyloadFn(item, arr, limit);
const clickBtnFn = () => {
const lastItemLength = lazyloadFn(item, arr, limit);
fjGallery(
item,
"appendImages",
item.querySelectorAll(`.fj-gallery-item:nth-last-child(-n+${lastItemLength})`)
);
anzhiyu.loadLightbox(item.querySelectorAll("img"));
if (lastItemLength < Number(limit)) {
observer.unobserve(item.nextElementSibling);
}
};
// 创建IntersectionObserver实例
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
// 如果元素进入视口
if (entry.isIntersecting) {
// 执行clickBtnFn函数
setTimeout(clickBtnFn(), 100);
}
});
});
observer.observe(item.nextElementSibling);
} else {
// 相册详情 按钮懒加载
lazyloadFn(item, arr, limit);
const clickBtnFn = () => {
const lastItemLength = lazyloadFn(item, arr, limit);
fjGallery(
item,
"appendImages",
item.querySelectorAll(`.fj-gallery-item:nth-last-child(-n+${lastItemLength})`)
);
anzhiyu.loadLightbox(item.querySelectorAll("img"));
lastItemLength < limit && item.nextElementSibling.removeEventListener("click", clickBtnFn);
};
item.nextElementSibling.addEventListener("click", clickBtnFn);
}
}
anzhiyu.initJustifiedGallery(item);
anzhiyu.loadLightbox(item.querySelectorAll("img"));
window.lazyLoadInstance && window.lazyLoadInstance.update();
};
const addJustifiedGallery = () => {
ele.forEach(item => {
item.classList.contains("url") ? fetchUrl(item.textContent).then(res => {
runJustifiedGallery(item, res);
})
: runJustifiedGallery(item, JSON.parse(item.textContent));
});
};
if (window.fjGallery) {
addJustifiedGallery();
return;
}
getCSS(`${GLOBAL_CONFIG.source.justifiedGallery.css}`);
getScript(`${GLOBAL_CONFIG.source.justifiedGallery.js}`).then(addJustifiedGallery);
};
修改album_detail.css
文件地址 themes/anzhiyu/source/css/_extra/album/album_detail.css
,新增以下代码
.fj-gallery-item > .serms-album-info-time{
display: flex;
position: absolute;
left: 8px;
bottom: 10px;
padding: 4px 6px;
border-radius: 8px;
background: var(--anzhiyu-black-op);
font-size: 12px;
color: var(--anzhiyu-white);
transition: 0.3s;
z-index: 1;
user-select: none;
}
#serms-fj-gallery-item:hover {
cursor: pointer;
z-index: 2;
transform: scale(1.5) translateZ(0);
filter: saturate(1.2) contrast(1);
}
修改album_detail.pug
文件地址 themes/anzhiyu/layout/includes/page/album_detail.pug
, 只需新增带+
号的代码即可
可在此文件中搜全局搜 else if type == 2 请不要复制这行到代码中
else if type == 2
.type-gallery
- const rowHeight = i.rowHeight != "undefined" ? i.rowHeight : 220
- const limit = i.limit != "undefined" ? i.limit : 10
- const lazyload = i.lazyload != "undefined" ? i.lazyload : true
- const lazyloadClass = lazyload == true ? "lazyload" : "";
- const btn = i.btnLazyload != "undefined" ? i.btnLazyload : false
- const btnLazyloadClass = btn == true ? " btn_album_detail_lazyload" : "";
- const imgType = i.url ? " url" : " data";
- let dataStr = []
- const durl = i.url ?? false
+ - const murl = i.murl ?? false
each item, index in i.album_list
each iten, indey in item.image
- let obj = {}
- obj.url = iten
- obj.alt = item.content
- obj.title = item.content
- obj.address = item.address
- obj.date = item.date
- dataStr.push(obj)
.gallery
.fj-gallery(data-rowHeight=rowHeight data-limit=limit class=`${lazyloadClass + btnLazyloadClass + imgType}`)
if durl
span.gallery-data=durl
else
span.gallery-data=JSON.stringify(dataStr)
+ if murl
+ span.gallery-data=murl
if btn
button.gallery-load-more
span=_p('load_more')
i.anzhiyufont.anzhiyu-icon-arrow-down
else
#album_detail_gallery_load_more
最后在album.yml添加murl即可
文件地址 source/_data/album.yml
- class_name: 世界各地夕阳与风景
path_name: /wordScenery
type: 2
description: 因为到不了世界各地,所以请网友们发来了各地的夕阳与风景🌇。
cover: https://bu.dusays.com/2023/10/09/6523a7789ed31.jpg
top_background: https://jsd.onmicrosoft.cn/gh/Ser-MingShao/HexoPublicStaiciImg/serms/202303271231748.jpg
rowHeight: 260
limit: 10
lazyload: false
btnLazyload: false
url: https://img.serms.top/static/js/wordScenery.json
+ murl: https://memos.serms.top/api/v1/memo?creatorId=1&tag=wordScenery (这里添加你自己的memos地址)
top_link: /album
top_btn_text: 返回
album_list:
- date: 2022/10/26 01:00:00
content: 湘潭的一角。
address: 湖南湘潭
from: 再吃一口就减肥
image:
- https://bu.dusays.com/2023/04/09/64329399db122.webp
- date: 2022-10-25
content: 洛阳暴雨后的天空。
address: 河南洛阳
from: SerMs
image:
- https://bu.dusays.com/2023/04/09/64329399db122.webp
- https://bu.dusays.com/2023/04/09/64329399db2e1.webp
memos演示
我这里是有三个细分相册,所以创建memostag
的时候根据细分相册名称来定义的,这里没有强制性要求,自己自定义即可 书写格式如上,将你的memosApi放入{% span red , album.yaml%}文件中,在上文中有说明 如果不想让图片在memos上展示,可以使用Markdown中代码块的写法,一样适用
- 感谢你赐予我前进的力量