Skip to content

主要思路:

(1)利用node+ali-oss读取阿里云bucket信息

(2)hexo页面请求数据进行渲染

hexo操作

引入文件

在自定义help.js文件内添加如下代码,并利用Inject插入到hexo中

javascript
/*
 * @Description:
 * @Date: 2023-05-18 16:28:45
 * @LastEditTime: 2023-05-18 19:41:55
 */

/* 阿里云相册流自定义函数 起点 */
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);
}
// imgStatus 判断图片是否加载进来了
!(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);
})();

// https://tokinx.github.io/lately/ 判断距今时间
!(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,
    };
  })();
})();

/* 阿里云相册流自定义函数 终点 */

页面内代码

新建相册页面hexo new page lifePhotos,粘贴如下代码

markdown
---
title: 我的生活
date: 2022-06-28 21:15:13
aside: false
---

<div class="gallery-photos page">
</div>

<style>
#article-container a img {margin: 0; border-radius:0;}
.gallery-photos{width:100%;margin-top: 10px;}
.gallery-photo{min-height:5rem;width:24.97%;padding:4px;position: relative;}
.gallery-photo a{border-radius:8px;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-time{display:none}
	.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;}}
.layout{
	max-width:90% !important;
}
</style>

自定义js

自定义js插入如下内容

javascript
// 适配pjax
function whenDOMReady() {
  if (location.pathname == "/lifePhotos/") photos();
}
whenDOMReady();
document.addEventListener("pjax:complete", whenDOMReady);

// 自适应
window.onresize = () => {
  if (location.pathname == "/lifePhotos/") waterfall(".gallery-photos");
};

// 函数
function photos() {
  fetch("http://139.224.188.129:4545/")
    .then((res) => res.json())
    .then((data) => {
      // // 记得修改memos地址
      let html = "";
      data.forEach((item) => {
        let img = item.url,
          title = item.title || ''
          time = item.time.substr(0,4) + '-' + item.time.substr(4,2) + '-' + item.time.substr(6,2) || '';
        html += `<div class="gallery-photo"><a href="${img}" data-fancybox="gallery" class="fancybox" data-thumb="${img}"><img class="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();
}

后端操作

生成express文件

yaml
npm i express-generator -g -save
cd #到相应目录
express -e "瀑布流相册"
cd "瀑布流相册"
npm i

安装阿里云和跨域库

yaml
npm i ali-oss cors --save

使用app.use(cors)允许跨域请求

读取阿里云bucket相册列表

routes/index.js中修改如下代码:

javascript
var express = require('express');
var router = express.Router();
let OSS = require('ali-oss');

/* GET home page. */
router.get('/', function(req, res, next) {
  let client = new OSS({
    // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
    region: 'oss-cn-hangzhou',
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。
    accessKeyId: 'LTAI5tSnEj7ZKnBqLJVNaHTf',
    accessKeySecret: 'pE46MOV90fKnZkbd0Yp4OooK1JImFY',
    bucket: 'jyh-img'
  });
  client.listV2({
    prefix:'life/', //相册位置
    'max-keys': 1000 //限制个数
  }).then(dataList => {
    dataList.objects.shift()
    let photoList = []
    dataList.objects.forEach(item => {
        let time = item.name.split('life/')[1].split('.jpg')[0].split('-')[0]
        let title = item.name.split('life/')[1].split('.jpg')[0].split('-')[1]
        let url = item.url
        photoList.push({time,title,url})
    })
    res.send(photoList.reverse())
  }).catch(err => {
    res.send(err)
  })
});

module.exports = router;

Released under the MIT License.