(function(){
const root = dv.el("div","");
root.style.fontFamily = "inherit";
root.style.margin = "6px 0";
try {
if (typeof dv === "undefined") {
// 极少数情况 dv 不存在(表示 Dataview 没启用或 codeblock 未被执行)
const msg = "Dataview 环境 (dv) 未找到。请确认已安装并启用 Dataview 插件,且在预览模式查看此笔记。";
root.innerHTML = `<span style="color:red">${msg}</span>`;
return;
}
if (typeof moment === "undefined") {
root.innerHTML = `<span style="color:red">moment.js 未找到(Dataview 应提供)。请检查插件。</span>`;
return;
}
// —— 从 frontmatter 读取(优先),支持字段名变体:
// abstract-deadline / abstractDeadline / abstract
// submit-deadline / submitDeadline / submit
const fm = dv.current() || {};
const abstractStr = fm["abstract-deadline"] || fm.abstractDeadline || fm.abstract || "2025-10-07 23:59:59";
const submitStr = fm["submit-deadline"] || fm.submitDeadline || fm.submit || "2025-10-14 23:59:59";
const parseMoment = s => {
if (!s) return null;
if (moment.isMoment(s)) return s;
if (s instanceof Date) return moment(s);
// 优先严格格式,再 fallback
let m = moment(String(s), "YYYY-MM-DD HH:mm:ss", true);
if (!m.isValid()) m = moment(String(s));
return m.isValid() ? m : null;
};
const abstractM = parseMoment(abstractStr);
const submitM = parseMoment(submitStr);
if (!abstractM || !submitM) {
root.innerHTML = `<span style="color:red">无法解析 deadline(请检查 frontmatter 或格式)。示例 frontmatter:<pre>abstract-deadline: 2025-10-15 23:59:59\nsubmit-deadline: 2025-11-01 23:59:59</pre></span>`;
return;
}
const rowA = dv.el("div", "", root);
const rowS = dv.el("div", "", root);
rowA.style.color = "#d97706"; // 橙
rowS.style.color = "#059669"; // 绿
function getParts(target) {
const now = moment();
const diff = target.diff(now);
if (diff <= 0) return { expired: true };
let t = Math.floor(diff / 1000);
const days = Math.floor(t / 86400); t %= 86400;
const hours = Math.floor(t / 3600); t %= 3600;
const minutes = Math.floor(t / 60);
const seconds = t % 60;
return { expired:false, days, hours, minutes, seconds };
}
function render() {
const a = getParts(abstractM);
const s = getParts(submitM);
if (a.expired) rowA.innerHTML = `✅ <strong>Abstract Deadline</strong>:已过`;
else rowA.innerHTML = `⏳ <strong>Abstract Deadline</strong>:${String(a.days).padStart(2,"0")} 天 ${String(a.hours).padStart(2,"0")}:${String(a.minutes).padStart(2,"0")}:${String(a.seconds).padStart(2,"0")}`;
if (s.expired) rowS.innerHTML = `✅ <strong>Submit Deadline</strong>:已过`;
else rowS.innerHTML = `⏳ <strong>Submit Deadline</strong>:${String(s.days).padStart(2,"0")} 天 ${String(s.hours).padStart(2,"0")}:${String(s.minutes).padStart(2,"0")}:${String(s.seconds).padStart(2,"0")}`;
}
// 清理旧的 interval(防止 Dataview 反复渲染导致多重计时器)
if (!window.__obsidian_countdown_ids) window.__obsidian_countdown_ids = [];
window.__obsidian_countdown_ids.forEach(id=>clearInterval(id));
window.__obsidian_countdown_ids.length = 0;
render();
const id = setInterval(render, 1000);
window.__obsidian_countdown_ids.push(id);
} catch (err) {
root.innerHTML = `<div style="color:red"><strong>脚本异常:</strong>${String(err)}</div>`;
console.error(err);
}
})();