打开/关闭菜单
6629
8
8126
OGAS数据中枢
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

Widget:Countdown:修订间差异

来自OGAS数据中枢
imported>弃权者
创建页面,内容为“<noinclude>仅供{{tl|Countdown}}使用。</noinclude><includeonly><!--{if !isset($wgCountdown) || !$wgCountdown}--><!--{assign var="wgCountdown" value=true scope="global"}--><script> "use strict"; window.RLQ = window.RLQ || []; window.RLQ.push(async () => { await mw.loader.using("moment"); const fromNow = (then, before, after, on) => { const now = moment(); const isBefore = then.isBefore(now); const monthsHave31Days = [0, 2, 4,…”
 
无编辑摘要
 
(未显示2个用户的9个中间版本)
第1行: 第1行:
<noinclude>仅供{{tl|Countdown}}使用。</noinclude><includeonly><!--{if !isset($wgCountdown) || !$wgCountdown}--><!--{assign var="wgCountdown" value=true scope="global"}--><script>
<noinclude>仅供{{tl|Countdown}}使用。</noinclude><includeonly><script>
"use strict";
"use strict";
window.RLQ = window.RLQ || [];
(function() {
window.RLQ.push(async () => {
    // 等候网页基础内容加载完毕再动手,防止找不到元素
    await mw.loader.using("moment");
    if (document.readyState === 'loading') {
     const fromNow = (then, before, after, on) => {
        document.addEventListener('DOMContentLoaded', setupCountdown);
        const now = moment();
    } else {
        const isBefore = then.isBefore(now);
        setupCountdown();
        const monthsHave31Days = [0, 2, 4, 6, 7, 9, 11]; // 月份从0开始
     }
        let year = isBefore ? now.year() - then.year() : then.year() - now.year(),
 
             month = isBefore ? now.month() - then.month() : then.month() - now.month(),
    function setupCountdown() {
            day = isBefore ? now.date() - then.date() : then.date() - now.date(),
        // 核心计算逻辑:完全使用原生 Date 对象替代 moment.js
            hour = isBefore ? now.hour() - then.hour() : then.hour() - now.hour(),
        const fromNow = (then, before, after, on) => {
            minute = isBefore ? now.minute() - then.minute() : then.minute() - now.minute(),
            const now = new Date();
            second = isBefore ? now.second() - then.second() : then.second() - now.second();
            const isBefore = then.getTime() < now.getTime();
        if (second < 0) {
 
            minute--;
            // 为了方便做减法,把大的时间放前面
            second += 60;
            const t1 = isBefore ? now : then;
        }
             const t2 = isBefore ? then : now;
        if (minute < 0) {
 
            hour--;
            let year = t1.getFullYear() - t2.getFullYear(),
            minute += 60;
                month = t1.getMonth() - t2.getMonth(),
        }
                day = t1.getDate() - t2.getDate(),
        if (hour < 0) {
                hour = t1.getHours() - t2.getHours(),
            day--;
                minute = t1.getMinutes() - t2.getMinutes(),
            hour += 24;
                second = t1.getSeconds() - t2.getSeconds();
        }
 
        if (day < 0) {
            // 借位计算(
            month--;
            if (second < 0) { minute--; second += 60; }
            if (monthsHave31Days.includes((isBefore ? then : now).month())) {
            if (minute < 0) { hour--; minute += 60; }
                 day += 31;
            if (hour < 0) { day--; hour += 24; }
             } else if ((isBefore ? then : now).month() === 1) {
            if (day < 0) {
                if ((isBefore ? then : now).year() % 4 === 0) {
                month--;
                    day += 29;
                // 获取上个月到底有多少天来补齐
                } else {
                let prevMonthDays = new Date(t1.getFullYear(), t1.getMonth(), 0).getDate();
                    day += 28;
                 day += prevMonthDays;
                 }
             }
            if (month < 0) { year--; month += 12; }
 
            // 组装最终显示的文字
            let result = "";
            if (year > 0) result += year + "年";
            if (month > 0) result += month + "月"; else if (result !== "") result += "0月";
            if (day > 0) result += day + "日"; else if (result !== "") result += "0日";
            if (hour > 0) result += hour + "小时"; else if (result !== "") result += "0小时";
            if (minute > 0) result += minute + "分"; else if (result !== "") result += "0分";
            if (second > 0) result += second + "秒"; else if (result !== "") result += "0秒";
 
            return (result === "" ? on : isBefore ? before : after).replace("$1", result);
        };
 
        // 第一步:把网页上所有的倒计时盒子找出来,并给它们分配好时间
        document.querySelectorAll(".countdownNode").forEach(ele => {
            const timeStr = ele.dataset.target || ele.getAttribute("data-target");
            if (!timeStr) return;
           
            // 兼容性处理:把横杠换成斜杠,防止苹果设备报错
            const safeTimeStr = timeStr.replace(/-/g, '/');
            const time = new Date(safeTimeStr);
           
            if (isNaN(time.getTime())) {
                ele.classList.add("error", "disabled");
                 ele.textContent = "(时间格式解析错误!)";
             } else {
             } else {
                 day += 30;
                 ele._countdownTarget = time;
             }
             }
        }
        if (month < 0) {
            year--;
            month += 12;
        }
        let result = "";
        if (year > 0) {
            result += `${year}年`;
        }
        if (month > 0) {
            result += `${month}月`;
        } else if (result !== "") {
            result += `${0}月`;
        }
        if (day > 0) {
            result += `${day}日`;
        } else if (result !== "") {
            result += `${0}日`;
        }
        if (hour > 0) {
            result += `${hour}小时`;
        } else if (result !== "") {
            result += `${0}小时`;
        }
        if (minute > 0) {
            result += `${minute}分`;
        } else if (result !== "") {
            result += `${0}分`;
        }
        if (second > 0) {
            result += `${second}秒`;
        } else if (result !== "") {
            result += `${0}秒`;
        }
        return (result === "" ? on : isBefore ? before : after).replace("$1", result.replace(/(\d) /g, "$1"));
    };
    const run = () => {
        $(".countdownNode:not(.disabled)").each((_, ele) => {
            const self = $(ele);
            self.text(fromNow(self.data("target"), ele.dataset.before || "$1前", ele.dataset.after || "还剩$1", ele.dataset.on || "就是现在!"));
         });
         });
    };
 
    $(".countdownNode").each((_, ele) => {
        // 第二步:执行更新的动作
        const self = $(ele),
        const run = () => {
            time = moment(ele.dataset.target);
            document.querySelectorAll(".countdownNode:not(.disabled)").forEach(ele => {
        if (!time || !time.isValid()) {
                const time = ele._countdownTarget;
            self.addClass("error disabled").text("(发生了致命错误");
                if (time && !isNaN(time.getTime())) {
             return;
                    ele.textContent = fromNow(
         }
                        time,
         self.data("target", time);
                        ele.dataset.before || "$1前",
    });
                        ele.dataset.after || "还剩$1",
    run();
                        ele.dataset.on || "就是现在!"
    window.setInterval(run, 1000);
                    );
});
                }
</script><!--{/if}--></includeonly>
             });
         };
 
         // 马上显示一次,然后每隔 1000 毫秒(1秒)跳动一次
        run();
        window.setInterval(run, 500);
    }
})();
</script></includeonly>

2026年3月4日 (三) 13:27的最新版本

仅供{{Countdown}}使用。