maigamo_Daily-Task-Auto-Gen.../main.ts.bak
2025-04-16 16:46:40 +08:00

332 lines
No EOL
12 KiB
TypeScript

import { App, Plugin, PluginSettingTab, Setting, Notice, TFile, normalizePath } from 'obsidian';
interface DailyTaskSettings {
enabled: boolean;
targetFolder: string;
templateFile: string;
schedule: {
time: string;
days: string[];
};
autoOpen: boolean;
}
const DEFAULT_SETTINGS: DailyTaskSettings = {
enabled: true,
targetFolder: '每日任务',
templateFile: '模板/每日任务模板.md',
schedule: {
time: '06:00',
days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday']
},
autoOpen: true
};
export default class DailyTaskAutoGenerator extends Plugin {
settings: DailyTaskSettings;
timer: number | null = null;
async onload() {
await this.loadSettings();
this.addSettingTab(new DailyTaskSettingTab(this.app, this));
this.addRibbonIcon('calendar-plus', '生成今日任务', () => {
this.generateTodayTask();
});
this.addCommand({
id: 'generate-daily-task',
name: '生成今日任务',
callback: () => {
this.generateTodayTask();
}
});
// 设置定时任务
this.scheduleNextTask();
}
onunload() {
if (this.timer) {
window.clearTimeout(this.timer);
}
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
this.scheduleNextTask();
}
scheduleNextTask() {
if (this.timer) {
window.clearTimeout(this.timer);
this.timer = null;
}
if (!this.settings.enabled) {
return;
}
const now = new Date();
const [hours, minutes] = this.settings.schedule.time.split(':').map(Number);
const targetTime = new Date(now);
targetTime.setHours(hours, minutes, 0, 0);
// 如果目标时间已过,则设置为明天
if (targetTime <= now) {
targetTime.setDate(targetTime.getDate() + 1);
}
// 检查目标日期是否是设置的工作日
const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
let dayToAdd = 0;
while (!this.settings.schedule.days.includes(days[targetTime.getDay()])) {
targetTime.setDate(targetTime.getDate() + 1);
dayToAdd++;
// 防止无限循环
if (dayToAdd > 7) {
break;
}
}
const timeUntilTask = targetTime.getTime() - now.getTime();
this.timer = window.setTimeout(() => {
this.generateTodayTask();
this.scheduleNextTask();
}, timeUntilTask);
}
async generateTodayTask() {
if (!this.settings.enabled) {
new Notice('每日任务自动生成功能已禁用。');
return;
}
// 准备文件夹
const folderPath = normalizePath(this.settings.targetFolder);
try {
await this.ensureFolderExists(folderPath);
} catch (error) {
new Notice(`无法创建目标文件夹: ${error}`);
return;
}
// 生成今日日期格式
const today = new Date();
const fileName = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}.md`;
const filePath = `${folderPath}/${fileName}`;
// 检查文件是否已存在
if (await this.app.vault.exists(filePath)) {
if (this.settings.autoOpen) {
this.openFile(filePath);
}
new Notice('今日任务文件已存在。');
return;
}
// 读取模板
try {
const templatePath = normalizePath(this.settings.templateFile);
if (!await this.app.vault.exists(templatePath)) {
new Notice('模板文件不存在!');
return;
}
let templateContent = await this.app.vault.read(this.app.vault.getAbstractFileByPath(templatePath) as TFile);
// 替换模板内容中的日期变量
templateContent = this.replaceTemplateVariables(templateContent, today);
// 创建新的任务文件
await this.app.vault.create(filePath, templateContent);
new Notice('成功创建今日任务文件!');
// 自动打开文件
if (this.settings.autoOpen) {
this.openFile(filePath);
}
} catch (error) {
new Notice(`创建任务文件失败: ${error}`);
}
}
replaceTemplateVariables(content: string, date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
// 星期几(中文)
const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
const weekday = weekdays[date.getDay()];
// 替换模板变量
content = content.replace(/{{date}}/g, `${year}-${month}-${day}`);
content = content.replace(/{{year}}/g, year.toString());
content = content.replace(/{{month}}/g, month);
content = content.replace(/{{day}}/g, day);
content = content.replace(/{{weekday}}/g, weekday);
return content;
}
async ensureFolderExists(path: string): Promise<void> {
const folders = path.split('/');
let currentPath = '';
for (const folder of folders) {
if (!folder) continue;
currentPath = currentPath ? `${currentPath}/${folder}` : folder;
if (!(await this.app.vault.exists(currentPath))) {
await this.app.vault.createFolder(currentPath);
}
}
}
async openFile(path: string): Promise<void> {
const file = this.app.vault.getAbstractFileByPath(path);
if (file && file instanceof TFile) {
await this.app.workspace.getLeaf().openFile(file);
}
}
}
class DailyTaskSettingTab extends PluginSettingTab {
plugin: DailyTaskAutoGenerator;
constructor(app: App, plugin: DailyTaskAutoGenerator) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
containerEl.addClass('daily-task-settings');
new Setting(containerEl)
.setName('启用')
.setDesc('启用每日任务自动生成')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.enabled)
.onChange(async (value) => {
this.plugin.settings.enabled = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('目标文件夹')
.setDesc('指定任务文件将被创建的文件夹路径')
.addText(text => text
.setPlaceholder('例如: 任务/每日')
.setValue(this.plugin.settings.targetFolder)
.onChange(async (value) => {
this.plugin.settings.targetFolder = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('模板文件')
.setDesc('指定用于生成任务的模板文件路径')
.addText(text => text
.setPlaceholder('例如: 模板/每日任务模板.md')
.setValue(this.plugin.settings.templateFile)
.onChange(async (value) => {
this.plugin.settings.templateFile = value;
await this.plugin.saveSettings();
}));
new Setting(containerEl)
.setName('生成时间')
.setDesc('指定每日任务生成的时间 (24小时制)')
.addText(text => text
.setPlaceholder('HH:MM')
.setValue(this.plugin.settings.schedule.time)
.onChange(async (value) => {
this.plugin.settings.schedule.time = value;
await this.plugin.saveSettings();
}));
const daysContainer = containerEl.createDiv();
daysContainer.addClass('setting-item');
const daysHeading = daysContainer.createDiv();
daysHeading.addClass('setting-item-heading');
daysHeading.setText('生成日期');
const daysDescription = daysContainer.createDiv();
daysDescription.addClass('setting-item-description');
daysDescription.setText('选择哪些天生成任务');
const daysGrid = daysContainer.createDiv();
daysGrid.style.display = 'grid';
daysGrid.style.gridTemplateColumns = 'repeat(auto-fill, minmax(120px, 1fr))';
daysGrid.style.gap = '8px';
daysGrid.style.marginTop = '8px';
const days = [
{ id: 'monday', label: '周一' },
{ id: 'tuesday', label: '周二' },
{ id: 'wednesday', label: '周三' },
{ id: 'thursday', label: '周四' },
{ id: 'friday', label: '周五' },
{ id: 'saturday', label: '周六' },
{ id: 'sunday', label: '周日' }
];
days.forEach(day => {
const dayItem = daysGrid.createDiv();
dayItem.addClass('day-checkbox');
const checkbox = dayItem.createEl('input');
checkbox.type = 'checkbox';
checkbox.id = day.id;
checkbox.checked = this.plugin.settings.schedule.days.includes(day.id);
const label = dayItem.createEl('label');
label.htmlFor = day.id;
label.textContent = day.label;
label.style.marginLeft = '8px';
checkbox.addEventListener('change', async () => {
if (checkbox.checked) {
if (!this.plugin.settings.schedule.days.includes(day.id)) {
this.plugin.settings.schedule.days.push(day.id);
}
} else {
this.plugin.settings.schedule.days = this.plugin.settings.schedule.days.filter(d => d !== day.id);
}
await this.plugin.saveSettings();
});
});
new Setting(containerEl)
.setName('自动打开')
.setDesc('生成任务后自动打开文件')
.addToggle(toggle => toggle
.setValue(this.plugin.settings.autoOpen)
.onChange(async (value) => {
this.plugin.settings.autoOpen = value;
await this.plugin.saveSettings();
}));
const buttonContainer = containerEl.createDiv();
buttonContainer.style.marginTop = '24px';
buttonContainer.style.textAlign = 'center';
const generateButton = buttonContainer.createEl('button');
generateButton.addClass('daily-task-btn');
generateButton.textContent = '立即生成今日任务';
generateButton.addEventListener('click', () => {
this.plugin.generateTodayTask();
});
}
}