| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- /**
- * Document Store Module
- *
- * Zustand store for managing document state and operations.
- * Handles:
- * - Current document state (currentDocument)
- * - Document list with pagination
- * - Save status tracking
- * - CRUD operations for documents
- *
- * @module stores/documentStore
- */
- import { create } from 'zustand';
- import type { DocumentStoreState } from '../types/store';
- import type { Document, DocumentListFilters, CreateDocumentRequest } from '../types/document';
- import type { ListFilters } from '../types/api';
- import * as documentService from '../services/documentService';
- /**
- * Initial pagination state
- */
- const initialPagination = {
- page: 1,
- pageSize: 20,
- total: 0,
- totalPages: 0,
- };
- /**
- * Document store
- *
- * Manages document state and provides actions for document operations.
- * All async actions automatically handle errors and update the store state.
- *
- * @example
- * ```typescript
- * // Create a new document
- * await useDocumentStore.getState().createDocument({
- * title: 'My Document',
- * content: '# Hello World',
- * format: 'markdown',
- * source: 'chat',
- * });
- *
- * // Update current document content (local only)
- * useDocumentStore.getState().updateContent('# Updated content');
- *
- * // Fetch document list
- * await useDocumentStore.getState().fetchDocumentList({
- * source: 'chat',
- * sortBy: 'createdAt',
- * sortOrder: 'desc',
- * });
- * ```
- */
- export const useDocumentStore = create<DocumentStoreState>((set, get) => ({
- // ============ State ============
- currentDocument: null,
- documents: [],
- pagination: initialPagination,
- saveStatus: 'saved',
- // ============ Actions ============
- /**
- * Create a new document
- *
- * Creates a document via the API and sets it as the current document.
- * Save status is set to 'saved' after successful creation.
- *
- * @param req - Document creation request (userId, fileUrl, sessionId)
- * @throws {Error} When document creation fails
- */
- createDocument: async (req: CreateDocumentRequest) => {
- try {
- set({ saveStatus: 'saving' });
- // Call API to create document
- const response = await documentService.createDocument(req);
- // Fetch the full document to set as current
- const fullDocument = await documentService.getDocument(response.documentId);
- // Update state with new document
- set({
- currentDocument: fullDocument,
- saveStatus: 'saved',
- });
- // Refresh document list to include the new document
- await get().fetchDocumentList();
- } catch (error) {
- set({ saveStatus: 'error' });
- throw error;
- }
- },
- /**
- * Fetch a document by ID
- *
- * Retrieves a document from the API and sets it as the current document.
- * Optionally includes blocks array.
- *
- * @param id - Document ID to fetch
- * @param includeBlocks - Whether to include blocks in response
- * @throws {Error} When document fetch fails
- */
- fetchDocument: async (id: string, includeBlocks: boolean = false) => {
- try {
- const document = await documentService.getDocument(id, { includeBlocks });
- set({
- currentDocument: document,
- saveStatus: 'saved',
- });
- } catch (error) {
- set({ currentDocument: null });
- throw error;
- }
- },
- /**
- * Fetch document list with optional filters
- *
- * Retrieves a paginated list of documents from the API.
- * Updates the documents array and pagination info.
- *
- * @param filters - Optional filters for listing (source, sortBy, sortOrder, page, pageSize)
- * @throws {Error} When document list fetch fails
- */
- fetchDocumentList: async (filters?: ListFilters) => {
- try {
- // 转换前端的camelCase字段名为后端的snake_case
- const apiFilters: DocumentListFilters = {
- userId: 'default-user', // TODO: 从认证上下文获取
- page: filters?.page,
- pageSize: filters?.pageSize,
- sortBy: filters?.sortBy === 'createdAt' ? 'created_at' :
- filters?.sortBy === 'updatedAt' ? 'updated_at' :
- undefined,
- sortOrder: filters?.sortOrder,
- };
-
- const response = await documentService.listDocuments(apiFilters);
- set({
- documents: response.documents,
- pagination: response.pagination,
- });
- } catch (error) {
- set({ documents: [], pagination: initialPagination });
- throw error;
- }
- },
- /**
- * Delete documents by session ID
- *
- * Deletes all documents for a session via the API.
- * If any deleted document is the current document, clears the current document state.
- *
- * @param sessionId - Session ID whose documents to delete
- * @throws {Error} When document deletion fails
- */
- deleteDocumentsBySession: async (sessionId: string) => {
- await documentService.deleteDocuments(sessionId);
- // Clear current document if it belonged to this session
- const currentDoc = get().currentDocument;
- if (currentDoc && currentDoc.sessionId === sessionId) {
- set({ currentDocument: null, saveStatus: 'saved' });
- }
- // Refresh document list to reflect deletion
- await get().fetchDocumentList();
- },
- /**
- * Set current document
- *
- * Directly sets the current document in state (local only).
- * Used when document is already loaded.
- *
- * @param document - Document to set as current
- */
- setCurrentDocument: (document: Document | null) => {
- set({
- currentDocument: document,
- saveStatus: 'saved',
- });
- },
- /**
- * Set save status
- *
- * Manually updates the save status indicator.
- * Used by external components like auto-save hooks.
- *
- * @param status - New save status
- */
- setSaveStatus: (status) => {
- set({ saveStatus: status });
- },
- }));
- export default useDocumentStore;
|