diff --git a/docs/superpowers/specs/2026-04-23-market-selection-export-design.md b/docs/superpowers/specs/2026-04-23-market-selection-export-design.md new file mode 100644 index 0000000..62db4e4 --- /dev/null +++ b/docs/superpowers/specs/2026-04-23-market-selection-export-design.md @@ -0,0 +1,183 @@ +# Market Selection Export Design + +## Goal + +Add row-level selection checkboxes to the market table so users can selectively export CSV data and submit batches for chosen creators, while preserving the existing export range workflow. + +## Confirmed Decisions + +- Add one checkbox column before each creator row. +- Add a header checkbox that selects or clears only the creators visible on the current page. +- Selection state persists across pagination. +- Selection affects both: + - CSV export + - batch submission +- If the current export range contains any selected creators, export and submit only those selected creators within that range. +- If the current export range contains no selected creators, fall back to all creators in the current export range. +- Keep the existing export range selector and current toolbar layout. +- Do not change the CSV column schema. +- Do not change the batch payload shape. Only change which records are included. + +## User Experience + +### Table Controls + +- Each creator row gets a checkbox at the far left. +- The table header gets a tri-state checkbox: + - unchecked: none of the current page creators are selected + - indeterminate: some but not all current page creators are selected + - checked: all current page creators are selected +- Clicking the header checkbox toggles selection for the current visible page only. + +### Export and Submit Behavior + +- Export still starts from the current range selector: + - current page + - first 5 pages + - custom pages + - all pages +- After range resolution: + - if any creators in that resolved range are selected, use only those selected creators + - if none are selected in that resolved range, use the full resolved range +- Batch submit uses the same filtered creator set as CSV export. + +### Status Feedback + +- Keep the existing export status area. +- Add lightweight selection feedback in the toolbar status text when helpful, for example: + - `已勾选 7 位达人` +- Do not add extra selection mode toggles or secondary panels. + +## Data Model + +Selection is UI state, not record data. + +- Maintain selection in the controller as a `Set` keyed by `authorId`. +- Do not store selection inside the CSV exporter. +- Do not mutate `MarketRecord` with persistent selection fields unless required for DOM wiring. +- Resolve selection against `authorId` only so sorting, filtering, and row reordering do not break checkbox state. + +## DOM Design + +### Synthetic Table + +- Insert a selectable header cell before the author column. +- Insert one checkbox cell per row. +- Expose the row checkbox and header checkbox through `MarketRowDom` and table DOM helpers. + +### Div Grid Table + +- Clone a narrow column before the native author column. +- Render checkbox cells aligned to each creator row. +- Render the header checkbox in the sticky header section. +- Reuse the existing plugin section insertion pattern so checkbox layout survives page refresh and plugin re-sync. + +## Controller Design + +### New Responsibilities + +- Track selected creator ids across page changes. +- Re-apply checkbox state after every DOM re-sync. +- Update header checkbox state after: + - row checkbox changes + - header checkbox changes + - pagination changes + - sorting and filtering changes + +### Export Flow + +Current flow: +- resolve export target +- collect `MarketRecord[]` +- build CSV + +New flow: +- resolve export target +- collect `MarketRecord[]` +- filter records by selection-with-fallback rule +- build CSV + +### Batch Flow + +Current flow: +- resolve export target +- collect `MarketRecord[]` +- build batch payload +- submit + +New flow: +- resolve export target +- collect `MarketRecord[]` +- filter records by selection-with-fallback rule +- build batch payload from filtered records +- submit + +## Filtering Rule + +Given the resolved export records: + +1. Find the subset whose `authorId` exists in the selection set. +2. If that subset is non-empty, use it. +3. If that subset is empty, use the original resolved records. + +This rule intentionally scopes selection to the chosen export range. For example: + +- If the user selected creators on page 1 and page 3 +- then exports `当前页` while viewing page 1 +- only page 1 selected creators are used +- page 3 selections remain stored for later exports + +## File Impact + +- Modify: `src/content/market/dom-sync.ts` + - checkbox column insertion + - row and header checkbox lookup + - checkbox state sync helpers +- Modify: `src/content/market/index.ts` + - selection state storage + - event handling + - export and batch record filtering +- Modify: `src/content/market/types.ts` + - minimal DOM type additions if needed +- Test: `tests/market-dom-sync.test.ts` + - checkbox column rendering + - header checkbox presence +- Test: `tests/market-content-entry.test.ts` + - row selection + - current page header select all + - cross-page selection persistence + - export fallback when no selected creators are inside the resolved range + - export filtering when selected creators exist in the resolved range + - batch submit uses the same filtered set + +## Risks and Mitigations + +### Risk: Selection breaks after reordering + +Mitigation: +- key selection only by `authorId` +- never key by row index or DOM order + +### Risk: Header checkbox selects hidden or unloaded rows + +Mitigation: +- limit header checkbox operations to current page visible row DOMs only + +### Risk: User expects selection to always override export range + +Mitigation: +- keep selection constrained to the resolved export range +- preserve current range selector semantics + +### Risk: Selection UI adds visual clutter + +Mitigation: +- use a narrow first column +- follow the host page checkbox look and spacing as closely as practical + +## Out of Scope + +- Bulk actions beyond export and batch submit +- Selection persistence across browser reloads +- Dedicated “selected only” mode in the toolbar +- Server-side storage of selected creators