Last active
September 22, 2025 00:37
-
-
Save dongfg/fc230b33241583d488b929331d101c3a to your computer and use it in GitHub Desktop.
scriptable 每日任务组件
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const widget = new ListWidget(); | |
const STORAGE_KEY_PREFIX = "douyinCheckinStatus"; | |
function storageKey() { | |
const date = new Date().toLocaleDateString('zh-CN', { | |
year: 'numeric', | |
month: '2-digit', | |
day: '2-digit' | |
}); | |
return STORAGE_KEY_PREFIX + date; | |
} | |
function loadStatus() { | |
if (Keychain.contains(storageKey())) { | |
const value = Keychain.get(storageKey()); | |
return value === "true"; | |
} else { | |
Keychain.set(storageKey(), "false"); | |
return false; | |
} | |
} | |
function saveStatus(completed) { | |
Keychain.set(storageKey(), completed.toString()); | |
} | |
function signDays() { | |
const startDateStr = args.widgetParameter; | |
const targetDate = new Date(startDateStr).getTime(); | |
const currentDate = new Date().setHours(0, 0, 0, 0); | |
const dayDiff = Math.abs(Math.floor((targetDate - currentDate) / (1000 * 60 * 60 * 24))); | |
console.log(dayDiff); | |
return dayDiff + ""; | |
} | |
function buildWidget() { | |
const status = loadStatus(); | |
widget.backgroundColor = new Color("#e3f2fd"); | |
widget.setPadding(16, 10, 16, 10); | |
const textColor = status ? new Color("#2e7d32") : new Color("#d32f2f") | |
const title = widget.addText("抖音 365 签到"); | |
title.font = Font.boldSystemFont(16); | |
title.textColor = textColor; | |
title.centerAlignText(); | |
widget.addSpacer(); | |
const dayCount = widget.addText(signDays()); | |
dayCount.font = Font.boldSystemFont(36); | |
dayCount.textColor = textColor; | |
dayCount.centerAlignText(); | |
widget.addSpacer(); | |
const statusText = widget.addText(status ? "任务已完成" : "任务未完成"); | |
statusText.font = Font.systemFont(16); | |
statusText.textColor = textColor; | |
statusText.centerAlignText(); | |
} | |
if (config.runsInWidget) { | |
buildWidget(); | |
Script.setWidget(widget); | |
Script.complete(); | |
} else { | |
const fm = FileManager.local(); | |
const lockFilePath = fm.joinPath(fm.temporaryDirectory(), "widget_lock.txt"); | |
const lockTimeout = 2000; // 锁定时长:2秒 (2000毫秒) | |
// 检查锁文件是否存在且是否在锁定时长内 | |
if (fm.fileExists(lockFilePath)) { | |
const modificationDate = fm.modificationDate(lockFilePath); | |
const timeSinceModified = new Date().getTime() - modificationDate.getTime(); | |
if (timeSinceModified < lockTimeout) { | |
Script.complete(); | |
return; // 必须 return 来停止后续代码 | |
} | |
} | |
fm.writeString(lockFilePath, new Date().toISOString()); | |
const alert = new Alert(); | |
alert.title = "更新状态"; | |
alert.message = "请选择当前签到状态"; | |
alert.addAction("已完成"); | |
alert.addAction("未完成"); | |
alert.addCancelAction("取消"); | |
alert.presentAlert().then(async (result) => { | |
if (result !== -1) { | |
saveStatus(result === 0); | |
const confirmationAlert = new Alert(); | |
confirmationAlert.title = "更新成功"; | |
confirmationAlert.message = "状态已保存。主屏幕小组件将在片刻后自动刷新。"; | |
confirmationAlert.addAction("好的"); | |
await confirmationAlert.present(); | |
} | |
Script.complete(); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment