mirror of
https://github.com/olcubo/obsidian-cubox.git
synced 2026-07-22 05:43:25 +00:00
fix sync bug
This commit is contained in:
parent
cb81eac092
commit
be8ef81c63
4 changed files with 90 additions and 130 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import { Notice } from 'obsidian';
|
||||
import { formatISODateTime } from './utils';
|
||||
import { ALL_FOLDERS_ID } from './modal/folderSelectModal';
|
||||
import { ALL_TAGS_ID } from './modal/tagSelectModal';
|
||||
import { ALL_STATUS_ID } from './modal/statusSelectModal';
|
||||
|
|
@ -149,7 +148,7 @@ export class CuboxApi {
|
|||
const pageSize = 50;
|
||||
|
||||
if (params.lastCardId !== null && params.lastCardId.length > 0) {
|
||||
requestBody.lastCardId = params.lastCardId;
|
||||
requestBody.last_card_id = params.lastCardId;
|
||||
}
|
||||
|
||||
// 添加文件夹过滤
|
||||
|
|
|
|||
152
src/main.ts
152
src/main.ts
|
|
@ -3,7 +3,7 @@ import { CuboxApi } from './cuboxApi';
|
|||
import { TemplateProcessor, FRONT_MATTER_VARIABLES } from './templateProcessor';
|
||||
import { formatDateTime } from './utils';
|
||||
import { ALL_FOLDERS_ID, FolderSelectModal } from './modal/folderSelectModal';
|
||||
import { filenameTemplateInstructions, metadataVariablesInstructions, contentTemplateInstructions } from './templateInstructions';
|
||||
import { filenameTemplateInstructions, metadataVariablesInstructions, contentTemplateInstructions, cuboxDateFormat } from './templateInstructions';
|
||||
import { ALL_CONTENT_TYPES, TypeSelectModal } from './modal/typeSelectModal';
|
||||
import { StatusSelectModal } from './modal/statusSelectModal';
|
||||
import { ALL_TAGS_ID, TagSelectModal } from './modal/tagSelectModal';
|
||||
|
|
@ -47,7 +47,7 @@ const DEFAULT_SETTINGS: CuboxSyncSettings = {
|
|||
frontMatterVariables: ['id', 'cubox_url', 'url', 'tags'],
|
||||
contentTemplate: '# {{{title}}}\n\n{{{description}}}\n\n[Read in Cubox]({{{cubox_url}}})\n[Read Original]({{{url}}})\n\n{{#highlights.length}}\n## Annotations\n\n{{#highlights}}\n> {{{highlight_text}}}\n{{{highlight_note}}}\n[Link️]({{{highlight_url}}})\n\n{{/highlights}}\n{{/highlights.length}}',
|
||||
highlightInContent: true,
|
||||
dateFormat: 'YYYY-MM-dd',
|
||||
dateFormat: 'YYYY-MM-DD',
|
||||
lastSyncTime: 0,
|
||||
lastSyncCardId: null,
|
||||
syncing: false
|
||||
|
|
@ -58,6 +58,7 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
cuboxApi: CuboxApi;
|
||||
templateProcessor: TemplateProcessor;
|
||||
syncIntervalId: number;
|
||||
private statusBarItem: HTMLElement;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
|
@ -80,8 +81,8 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
ribbonIconEl.addClass('cubox-sync-ribbon-class');
|
||||
|
||||
// 添加状态栏
|
||||
const statusBarItemEl = this.addStatusBarItem();
|
||||
statusBarItemEl.setText(`上次同步: ${this.formatLastSyncTime()}`);
|
||||
this.statusBarItem = this.addStatusBarItem();
|
||||
this.statusBarItem.setText(`上次同步: ${this.formatLastSyncTime()}`);
|
||||
|
||||
// 添加同步命令
|
||||
this.addCommand({
|
||||
|
|
@ -115,8 +116,6 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
}
|
||||
|
||||
async saveSettings() {
|
||||
// 保存之前的设置,用于比较
|
||||
const oldSettings = { ...this.settings };
|
||||
|
||||
// 保存新设置
|
||||
await this.saveData(this.settings);
|
||||
|
|
@ -148,6 +147,7 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
async () => await this.syncCubox(),
|
||||
this.settings.syncFrequency * 60 * 1000
|
||||
);
|
||||
this.registerInterval(this.syncIntervalId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,8 +164,7 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
await this.saveSettings();
|
||||
|
||||
// 更新状态栏显示
|
||||
const statusBarItemEl = this.addStatusBarItem();
|
||||
statusBarItemEl.setText(`正在同步 Cubox...`);
|
||||
this.statusBarItem.setText(`正在同步 Cubox...`);
|
||||
|
||||
// 确保目标文件夹存在
|
||||
await this.ensureTargetFolder();
|
||||
|
|
@ -174,7 +173,7 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
let lastCardId: string | null = continueLastSync ? this.settings.lastSyncCardId : null;
|
||||
let hasMore = true;
|
||||
let syncCount = 0;
|
||||
|
||||
let errorCount = 0;
|
||||
// 分页获取所有文章
|
||||
while (hasMore) {
|
||||
// 获取文章列表,传递状态布尔值
|
||||
|
|
@ -199,87 +198,76 @@ export default class CuboxSyncPlugin extends Plugin {
|
|||
|
||||
// 处理每篇文章
|
||||
for (const article of articles) {
|
||||
// 获取文章内容
|
||||
const content = await this.cuboxApi.getArticleDetail(article.id);
|
||||
if (content === null) continue;
|
||||
try {
|
||||
// 获取文章内容
|
||||
const content = await this.cuboxApi.getArticleDetail(article.id);
|
||||
if (content === null) continue;
|
||||
|
||||
// 合并文章基本信息、内容和高亮
|
||||
const fullArticle = {
|
||||
...article,
|
||||
content: content
|
||||
};
|
||||
|
||||
// 处理文件名和内容
|
||||
const filename = this.templateProcessor.processFilenameTemplate(
|
||||
this.settings.filenameTemplate,
|
||||
fullArticle
|
||||
);
|
||||
|
||||
const frontMatter = this.templateProcessor.processFrontMatter(
|
||||
this.settings.frontMatterVariables,
|
||||
fullArticle
|
||||
);
|
||||
|
||||
// const contentTemplate = this.templateProcessor.processContentTemplate(
|
||||
// this.settings.contentTemplate,
|
||||
// fullArticle
|
||||
// );
|
||||
|
||||
// 组合最终内容
|
||||
let finalContent = '';
|
||||
if (frontMatter.length > 0) {
|
||||
finalContent = `---\n${frontMatter}\n---\n\n`;
|
||||
}
|
||||
finalContent += fullArticle.content;
|
||||
|
||||
// 创建或更新文件
|
||||
const filePath = `${this.settings.targetFolder}/${filename}.md`;
|
||||
await this.app.vault.adapter.write(filePath, finalContent);
|
||||
|
||||
syncCount++;
|
||||
|
||||
// 合并文章基本信息、内容和高亮
|
||||
const fullArticle = {
|
||||
...article,
|
||||
content: content
|
||||
};
|
||||
|
||||
// 处理文件名和内容
|
||||
const filename = this.templateProcessor.processFilenameTemplate(
|
||||
this.settings.filenameTemplate,
|
||||
fullArticle
|
||||
);
|
||||
|
||||
const frontMatter = this.templateProcessor.processFrontMatter(
|
||||
this.settings.frontMatterVariables,
|
||||
fullArticle
|
||||
);
|
||||
|
||||
// const contentTemplate = this.templateProcessor.processContentTemplate(
|
||||
// this.settings.contentTemplate,
|
||||
// fullArticle
|
||||
// );
|
||||
|
||||
// 组合最终内容
|
||||
let finalContent = '';
|
||||
if (frontMatter.length > 0) {
|
||||
finalContent = `---\n${frontMatter}\n---\n\n`;
|
||||
} catch (error) {
|
||||
errorCount++;
|
||||
console.error('同步 Cubox 数据失败:', error);
|
||||
}
|
||||
finalContent += fullArticle.content;
|
||||
|
||||
// 创建或更新文件
|
||||
const filePath = `${this.settings.targetFolder}/${filename}.md`;
|
||||
await this.app.vault.adapter.write(filePath, finalContent);
|
||||
|
||||
syncCount++;
|
||||
|
||||
// 更新状态栏显示同步进度
|
||||
statusBarItemEl.setText(`正在同步 Cubox: ${syncCount} 篇文章已同步`);
|
||||
}
|
||||
|
||||
// 更新分页参数
|
||||
hasMore = moreArticles;
|
||||
lastCardId = newLastCardId;
|
||||
|
||||
// 在每次分页循环后保存当前的同步状态
|
||||
this.settings.lastSyncCardId = lastCardId;
|
||||
this.settings.lastSyncTime = Date.now();
|
||||
await this.saveSettings();
|
||||
|
||||
// 只在 lastCardId 不为 null 时才继续分页
|
||||
if (lastCardId === null) {
|
||||
break;
|
||||
if (lastCardId !== null) {
|
||||
this.settings.lastSyncCardId = lastCardId;
|
||||
await this.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
// 同步完成后,清除 lastSyncCardId(表示完整同步已完成)
|
||||
this.settings.lastSyncCardId = null;
|
||||
this.settings.lastSyncTime = Date.now();
|
||||
|
||||
// 设置同步状态为 false
|
||||
this.settings.syncing = false;
|
||||
await this.saveSettings();
|
||||
|
||||
// 更新状态栏
|
||||
statusBarItemEl.setText(`上次同步: ${this.formatLastSyncTime()}`);
|
||||
|
||||
new Notice(`成功同步 ${syncCount} 篇 Cubox 文章`);
|
||||
const message = `Cubox sync completed: ${syncCount} articles synchronized${errorCount > 0 ? `, ${errorCount} errors` : ''}`;
|
||||
new Notice(message);
|
||||
this.statusBarItem.setText(`上次同步: ${this.formatLastSyncTime()} (成功)`);
|
||||
} catch (error) {
|
||||
console.error('同步 Cubox 数据失败:', error);
|
||||
new Notice('同步 Cubox 数据失败,请检查设置和网络连接');
|
||||
|
||||
// 出错时也要重置同步状态
|
||||
this.statusBarItem.setText(`上次同步: ${this.formatLastSyncTime()} (失败)`);
|
||||
} finally {
|
||||
this.settings.syncing = false;
|
||||
await this.saveSettings();
|
||||
|
||||
// 更新状态栏
|
||||
const statusBarItemEl = this.addStatusBarItem();
|
||||
statusBarItemEl.setText(`上次同步: ${this.formatLastSyncTime()} (失败)`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -638,20 +626,24 @@ class CuboxSyncSettingTab extends PluginSettingTab {
|
|||
this.display(); // 刷新显示
|
||||
}));
|
||||
|
||||
// 更新日期格式模板设置
|
||||
const dateFormatInstructionsFragment = document.createRange().createContextualFragment(cuboxDateFormat);
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Date Format')
|
||||
.setDesc(dateFormatInstructionsFragment)
|
||||
.addText(text => text
|
||||
.setPlaceholder('Enter date format')
|
||||
.setValue(this.plugin.settings.dateFormat)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.dateFormat = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
|
||||
// 状态部分
|
||||
containerEl.createEl('h3', {text: 'Status'});
|
||||
containerEl.createEl('p', {text: `Last sync: ${this.plugin.formatLastSyncTime()}`});
|
||||
|
||||
// 添加测试连接按钮
|
||||
new Setting(containerEl)
|
||||
.setName('Test Connection')
|
||||
.setDesc('Test your Cubox API connection')
|
||||
.addButton(button => button
|
||||
.setButtonText('Test')
|
||||
.onClick(async () => {
|
||||
await this.plugin.cuboxApi.testConnection();
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
// 添加一个方法来更新 API Key 设置的描述和状态
|
||||
|
|
|
|||
|
|
@ -72,4 +72,19 @@ Enter template for creating synced article content.
|
|||
</ul>
|
||||
<div class="cubox-reference">For more, refer to <a href="#" class="reference-link">reference</a>.</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export const cuboxDateFormat = `
|
||||
If date is used on above templates, enter the format date.
|
||||
|
||||
<div class="cubox-variables-container">
|
||||
<div class="cubox-variables-title">Available variables</div>
|
||||
<ul class="cubox-variables-list">
|
||||
<li>YYYY-MM-DD</li>
|
||||
<li>MM/DD/YYYY</li>
|
||||
<li>DD.MM.YYYY</li>
|
||||
<li>YYYY-MM-DD HH:MM:SS</li>
|
||||
</ul>
|
||||
<div class="cubox-reference">For more, refer to <a href="#" class="reference-link">reference</a>.</div>
|
||||
</div>
|
||||
`;
|
||||
50
src/utils.ts
50
src/utils.ts
|
|
@ -45,57 +45,11 @@ export const formatDateTime = (dateString: string, format: string = 'YYYY-MM-DD
|
|||
try {
|
||||
// 预处理输入的时间字符串,处理非标准格式
|
||||
let normalizedString = dateString;
|
||||
|
||||
// 处理类似 2024-04-23T14:30:42:780+08:00 格式(秒与毫秒之间用冒号)
|
||||
normalizedString = normalizedString.replace(/(\d{2}):(\d{2}):(\d{2}):(\d{3})/, '$1:$2:$3.$4');
|
||||
|
||||
return DateTime.fromISO(normalizedString).toFormat('yyyy-MM-dd HH:mm');
|
||||
|
||||
// // 检查日期是否有效
|
||||
// if (isNaN(date.getTime())) {
|
||||
// console.warn(`Invalid date string: ${dateString}`);
|
||||
// return dateString;
|
||||
// }
|
||||
|
||||
// // 提取日期各部分
|
||||
// const year = date.getFullYear();
|
||||
// const month = date.getMonth() + 1;
|
||||
// const day = date.getDate();
|
||||
// const hours = date.getHours();
|
||||
// const minutes = date.getMinutes();
|
||||
// const seconds = date.getSeconds();
|
||||
|
||||
// // 格式化各部分,补零
|
||||
// const YYYY = String(year);
|
||||
// const YY = String(year).slice(-2);
|
||||
// const MM = String(month).padStart(2, '0');
|
||||
// const DD = String(day).padStart(2, '0');
|
||||
// const HH = String(hours).padStart(2, '0');
|
||||
// const mm = String(minutes).padStart(2, '0');
|
||||
// const ss = String(seconds).padStart(2, '0');
|
||||
|
||||
// // 使用正则表达式替换格式字符串中的占位符
|
||||
// let result = format
|
||||
// .replace(/YYYY/g, YYYY)
|
||||
// .replace(/YY/g, YY)
|
||||
// .replace(/MM/g, MM)
|
||||
// .replace(/DD/g, DD)
|
||||
// .replace(/HH/g, HH)
|
||||
// .replace(/mm/g, mm)
|
||||
// .replace(/ss/g, ss);
|
||||
|
||||
// return result;
|
||||
return DateTime.fromISO(normalizedString).toFormat(format);
|
||||
} catch (error) {
|
||||
console.error('Error formatting date:', error);
|
||||
return dateString;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前时间的格式化字符串
|
||||
* @param format 格式化模式
|
||||
* @returns 格式化后的当前时间字符串
|
||||
*/
|
||||
export const getCurrentFormattedTime = (format: string = 'yyyy-MM-dd HH:mm'): string => {
|
||||
return formatDateTime(new Date().toISOString(), format);
|
||||
};
|
||||
};
|
||||
Loading…
Reference in a new issue