diff --git a/src/zotero_kb/templates/index.html b/src/zotero_kb/templates/index.html
index 0231bf9..1754173 100644
--- a/src/zotero_kb/templates/index.html
+++ b/src/zotero_kb/templates/index.html
@@ -586,6 +586,15 @@
elements.selectedCount.textContent = `已选 ${state.selectedItemKeys.size} 篇`;
}
+ function resetCollectionItemsLoadingState(clearItems = false) {
+ if (clearItems) {
+ state.visibleCollectionItems = [];
+ }
+ state.collectionItemsLoaded = false;
+ state.loadingCollectionKey = null;
+ state.activeCollectionItemsRequestToken = 0;
+ }
+
function syncCurrentProjectLabels() {
if (state.currentProjectName) {
const label = `当前项目:${state.currentProjectName}`;
@@ -724,7 +733,9 @@
return;
}
if (!state.collectionItemsLoaded) {
- elements.collectionItems.innerHTML = '
正在加载当前 collection 文献。
';
+ elements.collectionItems.innerHTML = state.loadingCollectionKey === state.selectedCollectionKey
+ ? '正在加载当前 collection 文献。
'
+ : '当前 collection 文献尚未加载。
';
updateImportActionState();
return;
}
@@ -768,8 +779,7 @@
return;
}
state.visibleCollectionItems = [];
- state.collectionItemsLoaded = false;
- state.loadingCollectionKey = null;
+ resetCollectionItemsLoadingState();
renderCollectionItems();
setStatus(elements.collectionStatus, "");
}
@@ -780,9 +790,7 @@
}
state.selectedCollectionKey = collectionKey;
if (normalizeSelectedCollectionKey() !== collectionKey) {
- state.visibleCollectionItems = [];
- state.collectionItemsLoaded = false;
- state.loadingCollectionKey = null;
+ resetCollectionItemsLoadingState(true);
renderCollectionTree();
renderCollectionItems();
setStatus(elements.collectionStatus, state.selectedCollectionKey ? "已切换到可用 collection。" : "");
@@ -794,26 +802,34 @@
ensureSelectedCollectionExpanded();
persistImportSessionState();
renderCollectionTree();
- state.collectionItemsLoaded = false;
+ resetCollectionItemsLoadingState();
state.loadingCollectionKey = collectionKey;
const requestToken = state.nextCollectionItemsRequestToken + 1;
state.nextCollectionItemsRequestToken = requestToken;
state.activeCollectionItemsRequestToken = requestToken;
renderCollectionItems();
setStatus(elements.collectionStatus, "正在加载文献...");
- const payload = await api(`/api/zotero/collections/${collectionKey}/items`);
- if (state.activeCollectionItemsRequestToken !== requestToken || state.selectedCollectionKey !== collectionKey) {
- return;
+ try {
+ const payload = await api(`/api/zotero/collections/${collectionKey}/items`);
+ if (state.activeCollectionItemsRequestToken !== requestToken || state.selectedCollectionKey !== collectionKey) {
+ return;
+ }
+ state.visibleCollectionItems = Array.isArray(payload.items) ? payload.items : [];
+ state.collectionItemsLoaded = true;
+ state.loadingCollectionKey = null;
+ renderCollectionItems();
+ const visibleCount = state.visibleCollectionItems.length;
+ setStatus(
+ elements.collectionStatus,
+ visibleCount ? `当前目录及子目录共 ${visibleCount} 篇文献。` : "当前目录及子目录下没有可导入文献。"
+ );
+ } catch (error) {
+ if (state.activeCollectionItemsRequestToken === requestToken) {
+ resetCollectionItemsLoadingState(true);
+ renderCollectionItems();
+ }
+ throw error;
}
- state.visibleCollectionItems = Array.isArray(payload.items) ? payload.items : [];
- state.collectionItemsLoaded = true;
- state.loadingCollectionKey = null;
- renderCollectionItems();
- const visibleCount = state.visibleCollectionItems.length;
- setStatus(
- elements.collectionStatus,
- visibleCount ? `当前目录及子目录共 ${visibleCount} 篇文献。` : "当前目录及子目录下没有可导入文献。"
- );
}
function toggleItemSelection(itemKey) {
diff --git a/tests/test_ui.py b/tests/test_ui.py
index f595b7a..ee2ff68 100644
--- a/tests/test_ui.py
+++ b/tests/test_ui.py
@@ -41,11 +41,7 @@ def test_index_contains_import_modal_controls(tmp_path) -> None:
assert 'id="item-preview-popover"' in html
assert 'const ABSTRACT_PREVIEW_DELAY_MS = 3000;' in html
assert 'isImportModalOpen: false' in html
- assert "currentProjectName: null" in html
- assert "collectionItemsLoaded: false" in html
- assert "nextCollectionItemsRequestToken: 0" in html
assert "function openImportModal()" in html
assert "function closeImportModal()" in html
assert "function updateImportActionState()" in html
- assert "function normalizeSelectedCollectionKey()" in html
assert 'document.body.classList.toggle("modal-open"' in html