feat(v2.7): 接入协作治理前端体验
This commit is contained in:
79
apps/web/stores/useCommentStore.ts
Normal file
79
apps/web/stores/useCommentStore.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
'use client';
|
||||
|
||||
import { create } from 'zustand';
|
||||
import { api } from '@/lib/api';
|
||||
import type { CommentEntityType } from '@/components/comment/CommentPanel';
|
||||
|
||||
export interface CommentRecord {
|
||||
id: string;
|
||||
entityType: CommentEntityType;
|
||||
entityId: string;
|
||||
entityVersionId?: string | null;
|
||||
authorId: string;
|
||||
content: string;
|
||||
mentionedMemberIds?: string[];
|
||||
createdAt: string;
|
||||
deletedAt?: string | null;
|
||||
}
|
||||
|
||||
interface CreateCommentInput {
|
||||
actorId: string;
|
||||
entityType: CommentEntityType;
|
||||
entityId: string;
|
||||
entityVersionId?: string | null;
|
||||
productId?: string | null;
|
||||
projectId?: string | null;
|
||||
versionId?: string | null;
|
||||
content: string;
|
||||
mentionMemberIds?: string[];
|
||||
}
|
||||
|
||||
interface CommentState {
|
||||
commentsByKey: Record<string, CommentRecord[]>;
|
||||
loadingKeys: string[];
|
||||
fetchComments: (entityType: CommentEntityType, entityId: string) => Promise<void>;
|
||||
createComment: (input: CreateCommentInput) => Promise<void>;
|
||||
deleteComment: (entityType: CommentEntityType, entityId: string, id: string, actorId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export function commentKey(entityType: CommentEntityType, entityId: string) {
|
||||
return `${entityType}:${entityId}`;
|
||||
}
|
||||
|
||||
export const useCommentStore = create<CommentState>((set, get) => ({
|
||||
commentsByKey: {},
|
||||
loadingKeys: [],
|
||||
|
||||
fetchComments: async (entityType, entityId) => {
|
||||
const key = commentKey(entityType, entityId);
|
||||
set({ loadingKeys: [...get().loadingKeys.filter((item) => item !== key), key] });
|
||||
const params = new URLSearchParams({ entityType, entityId });
|
||||
const rows = await api.get<CommentRecord[]>(`/comments?${params.toString()}`);
|
||||
set({
|
||||
commentsByKey: { ...get().commentsByKey, [key]: rows },
|
||||
loadingKeys: get().loadingKeys.filter((item) => item !== key),
|
||||
});
|
||||
},
|
||||
|
||||
createComment: async (input) => {
|
||||
const row = await api.post<CommentRecord>('/comments', input);
|
||||
const key = commentKey(input.entityType, input.entityId);
|
||||
set({
|
||||
commentsByKey: {
|
||||
...get().commentsByKey,
|
||||
[key]: [...(get().commentsByKey[key] ?? []), row],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
deleteComment: async (entityType, entityId, id, actorId) => {
|
||||
const row = await api.deleteWithBody<CommentRecord>(`/comments/${id}`, { actorId });
|
||||
const key = commentKey(entityType, entityId);
|
||||
set({
|
||||
commentsByKey: {
|
||||
...get().commentsByKey,
|
||||
[key]: (get().commentsByKey[key] ?? []).map((item) => item.id === id ? row : item).filter((item) => !item.deletedAt),
|
||||
},
|
||||
});
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user