docs: revise zotero import spec for modal flow

This commit is contained in:
Saberlve 2026-04-15 12:04:51 +08:00
parent 0c0c773e61
commit 2566508b48

View File

@ -2,43 +2,45 @@
## Overview ## Overview
This design upgrades the current left-panel import area from two temporary flows: This design replaces the current crowded import area with a lighter flow:
- import current selection from a bridge snapshot - the main page keeps project, cards, and writing views visible
- text-search fallback import - the import UI moves into a modal opened from a single `导入文献` button
into one unified Zotero collection importer. The modal visualizes the user's current Zotero collection hierarchy, lets the user browse collections, displays the literature under the selected collection and all descendants, remembers cross-collection checkbox state for the current browser session, and batch-imports selected items into the current project.
The new importer must visualize the user's current Zotero collection hierarchy, let the user browse collections, display the literature under the selected collection, remember cross-collection checkbox state, and batch-import selected items into the current project.
This work is intentionally scoped to the import surface only. The project card panel and writing panel remain in place. This work is intentionally scoped to the import surface only. The project card panel and writing panel remain in place.
## Goals ## Goals
- Replace the current left-panel import widgets with one unified `Import From Zotero` section - Replace the current import widgets with one `导入文献` button that opens an import modal
- Visualize Zotero collections as a tree in the left panel - Visualize Zotero collections as a tree inside the modal
- When a collection is selected, show the literature under that collection and all descendant collections - When a collection is selected, show the literature under that collection and all descendant collections
- Support checkbox-based multi-selection across collection switches - Support checkbox-based multi-selection across collection switches
- Remember previous selection state while the page remains open - Remember previous selection state while the page remains open, even if the modal is closed and reopened
- Support bulk actions: - Support bulk actions:
- select all items from the current collection plus descendants - select all items from the current collection plus descendants
- clear all selected items - clear all selected items
- import selected items into the current project - import selected items into the current project
- Keep the item list compact by default:
- show checkbox and title only
- show abstract only after hover delay
- Preserve the existing project panel, card panel, and writing panel structure - Preserve the existing project panel, card panel, and writing panel structure
## Non-Goals ## Non-Goals
- Full drag-and-drop tree editing - Full drag-and-drop tree editing
- Editing Zotero collections - Editing Zotero collections
- Multi-pane import wizard - Multi-step import wizard
- Persisting import selections across browser restarts or across different users - Persisting import selections across browser restarts or across different users
- Replacing the bridge-based current-selection import flow at the API level - Replacing the bridge-based current-selection import flow at the API level
- Showing abstract text inline for every row by default
The bridge-based import endpoint may remain available, but it is no longer the main UI path. The bridge-based import endpoint may remain available, but it is no longer the main UI path.
## Product Scope ## Product Scope
The importer is a left-panel replacement only. The importer is a modal-based subflow launched from the main page.
### Unchanged Areas ### Unchanged Areas
@ -58,41 +60,61 @@ The current pair of sections:
will be removed and replaced with: will be removed and replaced with:
- `从 Zotero 导入` - one `导入文献` button on the main page
- one `Import From Zotero` modal
## User Flow ## User Flow
1. The user selects a project 1. The user selects a project or leaves the page without selecting one yet
2. The user browses the Zotero collection tree 2. The user clicks `导入文献`
3. The user clicks one collection 3. The modal opens
4. The UI loads all literature from that collection and all descendants 4. The user browses the Zotero collection tree
5. The user checks items to import 5. The user clicks one collection
6. The user may switch to a different collection and continue selecting 6. The UI loads all literature from that collection and all descendants
7. Previously selected items remain selected 7. The user checks items to import
8. The user clicks `导入所选到当前项目` 8. The user may switch to a different collection and continue selecting
9. The backend imports all selected items into the current project 9. Previously selected items remain selected
10. The card panel refreshes with the newly imported cards 10. The user clicks `导入所选到当前项目`
11. The backend imports all selected items into the current project
12. The card panel refreshes with the newly imported cards
13. The modal closes on success
## Layout ## Layout
The page stays three-column. The page stays three-column.
### Left Panel ### Main Page
The left panel contains: The left panel contains:
1. `创建项目` 1. `创建项目`
2. `项目列表` 2. `项目列表`
3. `从 Zotero 导入` 3. `导入文献`
### Import Section Structure The collection tree and collection item list are no longer rendered inline on the main page.
The import section has three internal regions: ### Import Modal
1. collection tree The modal has three internal regions:
2. collection item list
1. modal header
2. modal body
3. sticky action bar 3. sticky action bar
#### Modal Header
- title
- current project name or an explicit "未选择项目" state
- selected count
- close button
#### Modal Body
- desktop: two-column layout
- left: collection tree
- right: collection item list
- narrow screens: automatically stack into top and bottom sections
#### Collection Tree #### Collection Tree
- tree view with expand/collapse state - tree view with expand/collapse state
@ -107,9 +129,7 @@ The import section has three internal regions:
- each row contains: - each row contains:
- checkbox - checkbox
- title - title
- year - year, item type, and abstract are not shown inline by default
- item type
- compact metadata
- rows already selected in other collections remain checked when shown again - rows already selected in other collections remain checked when shown again
#### Sticky Action Bar #### Sticky Action Bar
@ -119,10 +139,28 @@ The import section has three internal regions:
- `清空选择` - `清空选择`
- `导入所选到当前项目` - `导入所选到当前项目`
The action bar remains visible while scrolling within the import section. The action bar remains visible while scrolling within the modal.
## Interaction Semantics ## Interaction Semantics
### Modal Open And Close
Clicking `导入文献` opens the modal.
The modal can be closed by:
- clicking the close button
- clicking the overlay
- pressing `Esc`
Closing the modal does not clear:
- `selectedCollectionKey`
- `expandedCollectionKeys`
- `selectedItemKeys`
Reopening the modal restores the previous browsing and selection state for the current page session.
### Collection Selection ### Collection Selection
Clicking a collection: Clicking a collection:
@ -162,26 +200,66 @@ This means:
`导入所选到当前项目` means: `导入所选到当前项目` means:
- require a currently selected project - require a currently selected project
- remain disabled when no project is selected
- submit the full selected item key set to the backend - submit the full selected item key set to the backend
- keep the active collection and tree expansion state - keep the active collection and tree expansion state
- clear the selected item set on success - clear the selected item set on success
- close the modal on success
- refresh the project card list - refresh the project card list
## Abstract Preview Behavior
The item list stays compact by default.
### Desktop
- hovering an item row starts a 3 second timer
- if the pointer is still on the row after 3 seconds, an abstract preview popover appears
- if the abstract is empty, no popover appears
- moving the pointer away before 3 seconds cancels the timer
- moving the pointer away after the popover appears closes it
- only one preview popover may be open at a time
### Mobile And Narrow-Screen Fallback
Hover is not reliable on touch devices, so the UI must degrade to an explicit preview trigger such as a small details button per row.
This fallback:
- opens the same abstract preview content
- does not rely on hover timing
- does not change batch-selection behavior
### Preview Cancellation Rules
The preview timer or popover closes immediately when:
- the user leaves the row
- the user scrolls the item list
- the user changes collection
- the user clicks a checkbox
## Frontend State Model ## Frontend State Model
The page should maintain these state keys: The page should maintain these state keys:
- `isImportModalOpen`
- `selectedCollectionKey` - `selectedCollectionKey`
- `expandedCollectionKeys` - `expandedCollectionKeys`
- `selectedItemKeys` - `selectedItemKeys`
- `visibleCollectionItems` - `visibleCollectionItems`
- `hoveredItemKey`
- `hoverTimerId`
- `previewItemKey`
### State Rules ### State Rules
- `isImportModalOpen` changes when the user opens or closes the modal
- `selectedCollectionKey` changes when the user clicks a tree node - `selectedCollectionKey` changes when the user clicks a tree node
- `expandedCollectionKeys` changes when nodes are opened or closed - `expandedCollectionKeys` changes when nodes are opened or closed
- `selectedItemKeys` persists across collection switches during the current browser session - `selectedItemKeys` persists across collection switches and modal reopen during the current browser session
- `visibleCollectionItems` updates whenever the active collection changes - `visibleCollectionItems` updates whenever the active collection changes
- `hoveredItemKey`, `hoverTimerId`, and `previewItemKey` control delayed abstract preview
`selectedItemKeys` is the source of truth for checkbox rendering and batch import. `selectedItemKeys` is the source of truth for checkbox rendering and batch import.
@ -256,12 +334,13 @@ The reader should continue to ignore attachment, note, and annotation rows as im
### No Project Selected ### No Project Selected
- disable import submission or return a clear UI error - allow the modal to open and load Zotero data
- disable import submission with a clear UI message
- do not clear selected checkboxes - do not clear selected checkboxes
### Collection Tree Load Failure ### Collection Tree Load Failure
- show error state in the import section - show error state inside the modal
- do not affect cards or writing sections - do not affect cards or writing sections
### Empty Collection ### Empty Collection
@ -276,7 +355,7 @@ The reader should continue to ignore attachment, note, and annotation rows as im
### Missing Local Zotero Data ### Missing Local Zotero Data
- show import section unavailable - disable or error the modal content clearly
- preserve the rest of the application - preserve the rest of the application
## Testing Strategy ## Testing Strategy
@ -295,7 +374,11 @@ The reader should continue to ignore attachment, note, and annotation rows as im
### UI Tests ### UI Tests
The index template must include: The main page must include:
- import-modal trigger button
The modal must include:
- collection tree container - collection tree container
- collection item list container - collection item list container
@ -304,8 +387,20 @@ The index template must include:
- clear-selection button - clear-selection button
- import-selected button - import-selected button
UI behavior must cover:
- modal can open without a selected project
- import action is disabled when no project is selected
- closing and reopening the modal preserves selected items during the session
- import success closes the modal and refreshes cards
- abstract preview appears only after the hover delay on desktop
## Constraints And Tradeoffs ## Constraints And Tradeoffs
### Why Modal Instead Of Left-Panel Inline Import
The inline importer works functionally but makes the main page too crowded. A modal keeps import as a focused subtask and preserves the readability of the project, cards, and writing columns.
### Why Tree + Side List Instead Of Tree-Mixed Items ### Why Tree + Side List Instead Of Tree-Mixed Items
The user explicitly chose: The user explicitly chose:
@ -315,22 +410,29 @@ The user explicitly chose:
This keeps scanning manageable for large libraries and avoids turning the tree itself into an overloaded mixed node structure. This keeps scanning manageable for large libraries and avoids turning the tree itself into an overloaded mixed node structure.
### Why Title-Only Rows By Default
The user explicitly wanted a lighter list. Showing only the title in the default list keeps density under control, while delayed preview preserves access to abstracts when needed.
### Why Session-Scoped Selection Memory ### Why Session-Scoped Selection Memory
The user explicitly asked to remember previous selection state, but not to store durable drafts of import batches. Session-scoped state is enough for the workflow and avoids backend persistence complexity. The user explicitly asked to remember previous selection state, but not to store durable drafts of import batches. Session-scoped state is enough for the workflow and avoids backend persistence complexity.
### Why Keep Cards And Writing Panels Unchanged ### Why Keep Cards And Writing Panels Unchanged
The import feature is a left-panel responsibility. Expanding it into a page-level mode would create unnecessary layout churn and broaden the implementation risk. The import feature is a subflow. Expanding it into a permanent page layout would create unnecessary layout churn and broaden the implementation risk.
## Acceptance Criteria ## Acceptance Criteria
This feature is complete when: This feature is complete when:
- the old `导入当前选中` and `后备导入` UI sections are gone - the old `导入当前选中` and `后备导入` UI sections are gone
- the left panel shows a collection tree and descendant-aware collection item list - the main page shows a `导入文献` button instead of an inline importer
- selecting items survives collection switches during the session - clicking the button opens a modal with collection tree and descendant-aware item list
- selecting items survives collection switches and modal reopen during the session
- the user can select all items from a collection plus descendants - the user can select all items from a collection plus descendants
- the user can clear all current selections - the user can clear all current selections
- the user can batch-import the selected items into the active project - the user can batch-import the selected items into the active project
- the import button is disabled when no project is selected
- the project card area refreshes after a successful import - the project card area refreshes after a successful import
- abstract preview appears only through the delayed preview interaction, not inline by default