# 引言

Shoka 主题添加文章实效性提示 —— 文章发表时间过久,部分内容实际上可能以及过时,需要在显眼处给出浏览者实效性提示。

# 主题集成

需要修改的文件列表如下,相对于 Shoka 主题根目录

# theme/shoka shoka 主题目录
├── _config.yml
├── languages
│    ├── en.yml
│    ├── ja.yml
│    ├── zh-CN.yml
│    ├── zh-HK.yml
│    └── zh-TW.yml
├── layout
│    └── _partials
│         └── layout.njk
├── scripts
│    └── generaters
│         └── script.js
└── source
     └── js
         └── _app
             ├── global.js
             └── pjax.js

# 修改 _config.yml

添加相关控制变量

# 文章是否失效
isOutdated:
    # 是否启用文章实效性提示
    enable: true
    # 实效性天数,默认 30 天
    days: 30

# 修改多语言字段信息

添加实效性对应文本串,引入格式串文本,多语言适配

zh-CN.yaml
isOutdated:
    format_year_as_prefix: '{{year}}年'
    format_month_as_prefix: '{{month}}个月'
    format_month_as_suffix: '零{{month}}个月'
    format_day_as_prefix: '{{day}}天'
    format_day_as_suffix: '零{{day}}天'
    template: <div class='note warning'><p><span class='label warning'>时效性提示</span><br>这是一篇发布于 <span class='pink'>{{publish}}</span> 前,最后一次更新距今已经 <span class='pink'>{{updated}}</span> 的文章,部分内容可能已经过时,请注意甄别。</p></div>
zh-HK.yaml
isOutdated:
    format_year_as_prefix: '{{year}}年'
    format_month_as_prefix: '{{month}}個月'
    format_month_as_suffix: '零{{month}}個月'
    format_day_as_prefix: '{{day}}天'
    format_day_as_suffix: '零{{day}}天'
    template: <div class='note warning'><p><span class='label warning'>時效性提示</span><br>這是一篇發佈於 <span class='pink'>{{publish}}</span> 前,最後一次更新距今已經 <span class='pink'>{{updated}}</span> 的文章,部分內容可能已經過時,請注意甄別。</p></div>
zh-TW.yaml
isOutdated:
    format_year_as_prefix: '{{year}}年'
    format_month_as_prefix: '{{month}}個月'
    format_month_as_suffix: '零{{month}}個月'
    format_day_as_prefix: '{{day}}天'
    format_day_as_suffix: '零{{day}}天'
    template: <div class='note warning'><p><span class='label warning'>時效性提示</span><br>這是一篇發佈於 <span class='pink'>{{publish}}</span> 前,最後一次更新距今已經 <span class='pink'>{{updated}}</span> 的文章,部分內容可能已經過時,請注意甄別。</p></div>
en.yaml
isOutdated:
    format_year_as_prefix: '{{year}}'
    format_month_as_prefix: '{{month}} month'
    format_month_as_suffix: 'and {{month}} months'
    format_day_as_prefix: '{{day}} days'
    format_day_as_suffix: 'and {{day}} days'
    template: <div class='note warning'><p><span class='label warning'>Timeliness Alert</span><br>This is an article published <span class='pink'>{{publish}}</span> ago and last updated <span class='pink'>{{updated}}</span> days ago. Some information may be outdated, please pay attention to screening.</p></div>
ja.yaml
isOutdated:
    format_year_as_prefix: '{{year}}'
    format_month_as_prefix: '{{month}} 月'
    format_month_as_suffix: 'ゼロ {{month}} か月'
    format_day_as_prefix: '{{day}} 日'
    format_day_as_suffix: 'ゼロ {{day}} 日'
    template: <div class='note warning'><p><span class='label warning'>適時性の警告</span><br> <span class='pink'>{{publish}}</span> 前に公開され、 <span class='pink'>{{updated}}</span> 前に最終更新された記事です。一部のコンテンツは時代遅れかもしれません、スクリーニングに注意してください。</p></div>

# source/js/_app/global.js 添加全局处理函数

const isOutdated = function() {
    if (CONFIG.isOutdated.enable && LOCAL.isOutdated) {
        var times = document.getElementsByTagName("time");
        if (times.length === 0) {
            return;
        }
        var posts = document.getElementsByClassName("body md");
        if (posts.length === 0) {
            return;
        }
        var now = Date.now(); // 当前时间戳
        var pubTime = new Date(times[0].dateTime); // 文章发布时间戳
        if (times.length === 1) {
            var updateTime = pubTime; // 文章发布时间亦是最后更新时间
        } else {
            var updateTime = new Date(times[1].dateTime); // 文章最后更新时间戳
        }
        var interval = parseInt(now - updateTime); // 时间差
        var days = parseInt(CONFIG.isOutdated.days) || 30; // 设置时效,默认硬编码 30 天
        // 最后一次更新时间超过 days 天(毫秒)
        var dayLevelValue = 24 * 60 * 60 * 1000;
        if (interval > days * dayLevelValue) {
            var monthLevelValue = 30 * 24 * 60 * 60 * 1000;
            var yearLevelValue = 365 * 24 * 60 * 60 * 1000;
            function getDifference(period) {
                /******* 计算出时间差中的年、月、日 *******/
                function getYear(period) {
                    return parseInt(period) / yearLevelValue;
                }
                function getMonth(period) {
                    return parseInt(period) / monthLevelValue;
                }
                function getDay(period) {
                    return parseInt(period) / dayLevelValue;
                }
                function isEmpty(obj){
                    if(typeof obj == "undefined" || obj == null || obj == ""){
                        return true;
                    }else{
                        return false;
                    }
                }
                var year = parseInt(getYear(period));
                var month = parseInt(getMonth(period - year * yearLevelValue));
                var day = parseInt(getDay(period - year * yearLevelValue - month * monthLevelValue));
                var result = "";
                if (year != 0) {
                    result += LOCAL.format_year_as_prefix.replace("{{year}}", year)
                }
                if (month != 0) {
                    if (isEmpty(result)) {
                        result += LOCAL.format_month_as_prefix.replace("{{month}}", month)
                    } else {
                        result += LOCAL.format_month_as_suffix.replace("{{month}}", month)
                    }
                }
                if (day != 0) {
                    if (isEmpty(result)) {
                        result += LOCAL.format_day_as_prefix.replace("{{day}}", day)
                    } else {
                        result += LOCAL.format_day_as_suffix.replace("{{day}}", day)
                    }
                }
                return result;
            }
            var publish = getDifference(now - pubTime);
            var updated = getDifference(interval);
            var template = LOCAL.template.replace("{{publish}}", publish).replace("{{updated}}", updated);
            posts[0].insertAdjacentHTML("afterbegin", template);
        }
    }
};

# source/js/_app/pjax.jssiteRefresh 函数的最后一行 调用全局函数处理

cardActive()
lazyload.observe()
// 新增部分 begin
isOutdated() // 判断文章时效性
// 新增部分 end

# scripts/generaters/script.jssiteConfig 添加变量 (随便选一行后面插入就行,案例写在了 valine 的上面)

loader: theme.loader,
search : null,
// 新增部分 begin
isOutdated: theme.isOutdated,
// 新增部分 end
valine: theme.valine,

# layout/_partials/layout.njkLOCAL 变量添加实效性相关变量

<script data-config type="text/javascript">
    var LOCAL = {
        // ...
        // 新增部分 begin
        {%- if page.isOutdated === false %}
            isOutdated: false,
        {%- else %}
            isOutdated: true,
            format_year_as_prefix: "{{ __('isOutdated.format_year_as_prefix') }}",
            format_month_as_prefix: "{{ __('isOutdated.format_month_as_prefix') }}",
            format_month_as_suffix: "{{ __('isOutdated.format_month_as_suffix') }}",
            format_day_as_prefix: "{{ __('isOutdated.format_day_as_prefix') }}",
            format_day_as_suffix: "{{ __('isOutdated.format_day_as_suffix') }}",
            template: "{{ __('isOutdated.template') }}",
        {%- endif %}
        // 新增部分 end
        // ...
        ignores: [
            function (uri) {
                return uri.includes('#');
            },
            function (uri) {
                return new RegExp(LOCAL.path + "$").test(uri);
            }{%- if theme.quicklink.ignores %},
                {{ theme.quicklink.ignores|safedump }}
            {%- endif %}
        ]
    };
</script>

# Front-matter 控制

默认文章实效性检查是启用的,对于不想启用文章实效性的文章

可以在文章头部的 Front-matter 信息强制指定关闭实效性检测

---
isOutdated: false  #关闭检查文章实效性
---

# 效果预览

时效性提示
这是一篇发布于 x 天前,最后一次更新距今已经 y 天的文章,部分内容可能已经过时,请注意甄别。

或者您看到本文时,本文正文顶部已经出现了实效性提示。

更新于 阅读次数