打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
imported>弃权者
无编辑摘要
无编辑摘要
 
(未显示2个用户的6个中间版本)
第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";
(function() {
(function() {
     if (typeof mw !== 'undefined' && mw.loader) {
    // 等候网页基础内容加载完毕再动手,防止找不到元素
        mw.loader.using('moment').then(() => {
     if (document.readyState === 'loading') {
            initCountdown();
         document.addEventListener('DOMContentLoaded', setupCountdown);
         }).catch(() => {
            document.querySelectorAll('.countdownNode').forEach(el => {
                el.textContent = '(无法加载时间库)';
                el.classList.add('error');
            });
        });
     } else {
     } else {
         document.querySelectorAll('.countdownNode').forEach(el => {
         setupCountdown();
            el.textContent = '(MediaWiki环境异常)';
            el.classList.add('error');
        });
     }
     }
   
 
     function initCountdown() {
     function setupCountdown() {
        // 核心计算逻辑:完全使用原生 Date 对象替代 moment.js
         const fromNow = (then, before, after, on) => {
         const fromNow = (then, before, after, on) => {
             const now = moment();
             const now = new Date();
             const isBefore = then.isBefore(now);
             const isBefore = then.getTime() < now.getTime();
             const monthsHave31Days = [0, 2, 4, 6, 7, 9, 11];
 
             let year = isBefore ? now.year() - then.year() : then.year() - now.year(),
            // 为了方便做减法,把大的时间放前面
                 month = isBefore ? now.month() - then.month() : then.month() - now.month(),
             const t1 = isBefore ? now : then;
                 day = isBefore ? now.date() - then.date() : then.date() - now.date(),
             const t2 = isBefore ? then : now;
                 hour = isBefore ? now.hour() - then.hour() : then.hour() - now.hour(),
 
                 minute = isBefore ? now.minute() - then.minute() : then.minute() - now.minute(),
            let year = t1.getFullYear() - t2.getFullYear(),
                 second = isBefore ? now.second() - then.second() : then.second() - now.second();
                 month = t1.getMonth() - t2.getMonth(),
             if (second < 0) {
                 day = t1.getDate() - t2.getDate(),
                minute--;
                 hour = t1.getHours() - t2.getHours(),
                second += 60;
                 minute = t1.getMinutes() - t2.getMinutes(),
            }
                 second = t1.getSeconds() - t2.getSeconds();
             if (minute < 0) {
 
                hour--;
            // 借位计算(
                minute += 60;
             if (second < 0) { minute--; second += 60; }
            }
             if (minute < 0) { hour--; minute += 60; }
             if (hour < 0) {
             if (hour < 0) { day--; hour += 24; }
                day--;
                hour += 24;
            }
             if (day < 0) {
             if (day < 0) {
                 month--;
                 month--;
                 if (monthsHave31Days.includes((isBefore ? then : now).month())) {
                 // 获取上个月到底有多少天来补齐
                    day += 31;
                let prevMonthDays = new Date(t1.getFullYear(), t1.getMonth(), 0).getDate();
                } else if ((isBefore ? then : now).month() === 1) {
                 day += prevMonthDays;
                    if ((isBefore ? then : now).year() % 4 === 0) {
                        day += 29;
                    } else {
                        day += 28;
                    }
                 } else {
                    day += 30;
                }
            }
            if (month < 0) {
                year--;
                month += 12;
             }
             }
            if (month < 0) { year--; month += 12; }
            // 组装最终显示的文字
             let result = "";
             let result = "";
             if (year > 0) {
             if (year > 0) result += year + "年";
                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 {
                ele._countdownTarget = time;
             }
             }
            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 = () => {
         const run = () => {
             $(".countdownNode:not(.disabled)").each((_, ele) => {
             document.querySelectorAll(".countdownNode:not(.disabled)").forEach(ele => {
                 const self = $(ele);
                 const time = ele._countdownTarget;
                 self.text(fromNow(self.data("target"), ele.dataset.before || "$1前", ele.dataset.after || "还剩$1", ele.dataset.on || "就是现在!"));
                 if (time && !isNaN(time.getTime())) {
                    ele.textContent = fromNow(
                        time,  
                        ele.dataset.before || "$1前",  
                        ele.dataset.after || "还剩$1",  
                        ele.dataset.on || "就是现在!"
                    );
                }
             });
             });
         };
         };
       
 
         $(() => {
         // 马上显示一次,然后每隔 1000 毫秒(1秒跳动一次
            $(".countdownNode").each((_, ele) => {
        run();
                const self = $(ele),
        window.setInterval(run, 500);
                    time = moment(ele.dataset.target);
                if (!time || !time.isValid()) {
                    self.addClass("error disabled").text("(发生了致命错误!");
                    return;
                }
                self.data("target", time);
            });
            run();
            window.setInterval(run, 1000);
        });
     }
     }
})();
})();
</script><!--{/if}--></includeonly>
</script></includeonly>

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

仅供{{Countdown}}使用。