自言自语

本教程基于anzhiyu二改,如果是小白建议先按照鱼佬文档教程 搭建好基本页面在看此教程相册支持Memos地址以及相册细节优化(type为2展示时间)album_listurl问题

初衷: 更新相册为了更方便一点,按照鱼的主题教程来搭建的目前只支持手动在 album.yml 文件中更新照片数据 更新完之后还需要在编译在提交博客到仓库,为了方便更新相册数据因此接入Memos,省去在博客中操作的繁琐步骤 让页面看起来更顺我心意,看不顺眼那就魔改一下下吧~

  1. 这里在详细说明一下关于 album_list的问题,在鱼佬的相册页面配置教程中,有一个album_list和一个url属性, 当album_listurl同时存在的时候,会将url中的数据覆盖掉album_list中的数据,所以我觉得要么就都展示,要么就严谨一点做个断言处理,如果url存在链接地址,将会直接忽略album_list 这个只是一个小问题,可以忽略,但是作为强迫症患者的我受不了一点...到时候在做修改吧

效果预览

效果预览

鱼佬效果

  1. 图片展示无时间显示 当 type为2时页面图片无时间展示 鱼佬效果图 但是 type为1时就有时间..... 本人强迫症看到此时此景非常的不爽,要么都有,要么都没有,这里忍不住吐槽一番吧~ 鱼佬效果图

修改后的效果 相册

  1. 图片展示时间 SerMs相册展示

  2. 接入Memos,前面四张一样的是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中代码块的写法,一样适用