refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* ProcessPostUseCase - 处理帖子用例
|
|
|
|
|
|
* 处理帖子的业务逻辑,协调 Repository 和状态管理
|
|
|
|
|
|
* 纯业务逻辑,无UI依赖
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
import { postRepository } from '../../data/repositories/PostRepository';
|
|
|
|
|
|
import type { Post } from '../entities/Post';
|
|
|
|
|
|
import type {
|
|
|
|
|
|
GetPostsParams,
|
|
|
|
|
|
CreatePostData,
|
|
|
|
|
|
UpdatePostData,
|
|
|
|
|
|
PostsResult,
|
|
|
|
|
|
SearchPostsParams,
|
|
|
|
|
|
} from '../../data/repositories/interfaces/IPostRepository';
|
|
|
|
|
|
import { PaginationStateManager } from '../../infrastructure/pagination/PaginationStateManager';
|
|
|
|
|
|
import type { PaginationState } from '../../infrastructure/pagination/types';
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 事件类型定义 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 帖子用例事件类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
export type PostUseCaseEventType =
|
|
|
|
|
|
| 'posts_loaded'
|
|
|
|
|
|
| 'post_created'
|
|
|
|
|
|
| 'post_updated'
|
|
|
|
|
|
| 'post_deleted'
|
|
|
|
|
|
| 'post_liked'
|
|
|
|
|
|
| 'post_unliked'
|
|
|
|
|
|
| 'post_favorited'
|
|
|
|
|
|
| 'post_unfavorited'
|
|
|
|
|
|
| 'loading_changed'
|
|
|
|
|
|
| 'error_occurred'
|
|
|
|
|
|
| 'state_changed';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 帖子用例事件
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface PostUseCaseEvent {
|
|
|
|
|
|
type: PostUseCaseEventType;
|
|
|
|
|
|
payload: any;
|
|
|
|
|
|
timestamp: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 事件订阅者类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
export type PostUseCaseSubscriber = (event: PostUseCaseEvent) => void;
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 状态类型定义 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 帖子列表状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface PostsState {
|
|
|
|
|
|
/** 帖子列表 */
|
|
|
|
|
|
posts: Post[];
|
|
|
|
|
|
/** 是否正在加载 */
|
|
|
|
|
|
isLoading: boolean;
|
|
|
|
|
|
/** 是否正在刷新 */
|
|
|
|
|
|
isRefreshing: boolean;
|
|
|
|
|
|
/** 是否有更多数据 */
|
|
|
|
|
|
hasMore: boolean;
|
|
|
|
|
|
/** 错误信息 */
|
|
|
|
|
|
error: string | null;
|
2026-03-23 03:58:26 +08:00
|
|
|
|
/** 当前游标(cursor 模式) */
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
cursor: string | null;
|
2026-03-23 03:58:26 +08:00
|
|
|
|
/** 当前页码(page 模式) */
|
|
|
|
|
|
currentPage: number;
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
/** 最后加载时间 */
|
|
|
|
|
|
lastLoadTime: number | null;
|
2026-03-23 03:58:26 +08:00
|
|
|
|
/** 上次请求的参数(用于加载更多和刷新) */
|
|
|
|
|
|
lastParams?: GetPostsParams;
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 帖子详情状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface PostDetailState {
|
|
|
|
|
|
/** 帖子详情 */
|
|
|
|
|
|
post: Post | null;
|
|
|
|
|
|
/** 是否正在加载 */
|
|
|
|
|
|
isLoading: boolean;
|
|
|
|
|
|
/** 错误信息 */
|
|
|
|
|
|
error: string | null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 默认配置 ====================
|
|
|
|
|
|
|
|
|
|
|
|
const DEFAULT_PAGE_SIZE = 20;
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== ProcessPostUseCase 类 ====================
|
|
|
|
|
|
|
|
|
|
|
|
class ProcessPostUseCase {
|
|
|
|
|
|
// 单例实例
|
|
|
|
|
|
private static instance: ProcessPostUseCase;
|
|
|
|
|
|
|
|
|
|
|
|
// 订阅者管理
|
|
|
|
|
|
private subscribers: Set<PostUseCaseSubscriber> = new Set();
|
|
|
|
|
|
|
|
|
|
|
|
// 状态管理
|
|
|
|
|
|
private postsState: Map<string, PostsState> = new Map();
|
|
|
|
|
|
private postDetailState: Map<string, PostDetailState> = new Map();
|
|
|
|
|
|
|
|
|
|
|
|
// 分页状态管理器
|
|
|
|
|
|
private paginationManager: PaginationStateManager;
|
|
|
|
|
|
|
|
|
|
|
|
// 当前用户ID
|
|
|
|
|
|
private currentUserId: string | null = null;
|
|
|
|
|
|
|
2026-03-24 01:19:09 +08:00
|
|
|
|
private readonly mergePerfWarnThresholdMs = 12;
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
// 私有构造函数
|
|
|
|
|
|
private constructor() {
|
|
|
|
|
|
this.paginationManager = new PaginationStateManager();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取单例实例
|
|
|
|
|
|
*/
|
|
|
|
|
|
static getInstance(): ProcessPostUseCase {
|
|
|
|
|
|
if (!ProcessPostUseCase.instance) {
|
|
|
|
|
|
ProcessPostUseCase.instance = new ProcessPostUseCase();
|
|
|
|
|
|
}
|
|
|
|
|
|
return ProcessPostUseCase.instance;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 初始化和销毁 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 初始化用例
|
|
|
|
|
|
* @param currentUserId 当前用户ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
initialize(currentUserId: string | null = null): void {
|
|
|
|
|
|
this.currentUserId = currentUserId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 销毁用例
|
|
|
|
|
|
*/
|
|
|
|
|
|
destroy(): void {
|
|
|
|
|
|
this.subscribers.clear();
|
|
|
|
|
|
this.postsState.clear();
|
|
|
|
|
|
this.postDetailState.clear();
|
|
|
|
|
|
this.paginationManager.clear();
|
|
|
|
|
|
this.currentUserId = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 订阅机制 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 订阅事件
|
|
|
|
|
|
* @param subscriber 订阅者函数
|
|
|
|
|
|
* @returns 取消订阅函数
|
|
|
|
|
|
*/
|
|
|
|
|
|
subscribe(subscriber: PostUseCaseSubscriber): () => void {
|
|
|
|
|
|
this.subscribers.add(subscriber);
|
|
|
|
|
|
return () => {
|
|
|
|
|
|
this.subscribers.delete(subscriber);
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 通知所有订阅者
|
|
|
|
|
|
* @param event 事件对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
private notifySubscribers(event: PostUseCaseEvent): void {
|
|
|
|
|
|
this.subscribers.forEach((subscriber) => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
subscriber(event);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('[ProcessPostUseCase] 订阅者执行失败:', error);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 通知状态变化
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
private notifyStateChanged(key: string): void {
|
|
|
|
|
|
const state = this.getPostsState(key);
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'state_changed',
|
|
|
|
|
|
payload: { key, state },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 状态管理 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取帖子列表状态
|
|
|
|
|
|
* @param key 列表键(默认为 'default')
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPostsState(key: string = 'default'): PostsState {
|
|
|
|
|
|
let state = this.postsState.get(key);
|
|
|
|
|
|
if (!state) {
|
|
|
|
|
|
state = {
|
|
|
|
|
|
posts: [],
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
isRefreshing: false,
|
|
|
|
|
|
hasMore: true,
|
|
|
|
|
|
error: null,
|
|
|
|
|
|
cursor: null,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
currentPage: 1,
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
lastLoadTime: null,
|
|
|
|
|
|
};
|
|
|
|
|
|
this.postsState.set(key, state);
|
|
|
|
|
|
}
|
|
|
|
|
|
return state;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取帖子详情状态
|
|
|
|
|
|
* @param postId 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPostDetailState(postId: string): PostDetailState {
|
|
|
|
|
|
let state = this.postDetailState.get(postId);
|
|
|
|
|
|
if (!state) {
|
|
|
|
|
|
state = {
|
|
|
|
|
|
post: null,
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: null,
|
|
|
|
|
|
};
|
|
|
|
|
|
this.postDetailState.set(postId, state);
|
|
|
|
|
|
}
|
|
|
|
|
|
return state;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新帖子列表状态
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
* @param partialState 部分状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
private updatePostsState(key: string, partialState: Partial<PostsState>): void {
|
|
|
|
|
|
const currentState = this.getPostsState(key);
|
|
|
|
|
|
this.postsState.set(key, {
|
|
|
|
|
|
...currentState,
|
|
|
|
|
|
...partialState,
|
|
|
|
|
|
});
|
|
|
|
|
|
this.notifyStateChanged(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 01:19:09 +08:00
|
|
|
|
private getEntityId(item: unknown): string | null {
|
|
|
|
|
|
if (!item || typeof item !== 'object') {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
const maybeId = (item as { id?: unknown }).id;
|
|
|
|
|
|
if (typeof maybeId === 'string' || typeof maybeId === 'number') {
|
|
|
|
|
|
return String(maybeId);
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private mergePostListWithFastPath(previousInput: Post[] | null | undefined, incomingInput: Post[] | null | undefined): Post[] {
|
|
|
|
|
|
const previous = Array.isArray(previousInput) ? previousInput : [];
|
|
|
|
|
|
const incoming = Array.isArray(incomingInput) ? incomingInput : [];
|
|
|
|
|
|
if (incoming.length === 0) {
|
|
|
|
|
|
return previous;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (previous.length === 0) {
|
|
|
|
|
|
return incoming;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const lastPrevId = this.getEntityId(previous[previous.length - 1]);
|
|
|
|
|
|
const firstIncomingId = this.getEntityId(incoming[0]);
|
|
|
|
|
|
if (lastPrevId && firstIncomingId && lastPrevId !== firstIncomingId) {
|
|
|
|
|
|
const prevIdSet = new Set(previous.map((item) => this.getEntityId(item)).filter(Boolean) as string[]);
|
|
|
|
|
|
if (!prevIdSet.has(firstIncomingId)) {
|
|
|
|
|
|
return [...previous, ...incoming];
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const merged = [...previous];
|
|
|
|
|
|
const indexById = new Map<string, number>();
|
|
|
|
|
|
for (let i = 0; i < merged.length; i += 1) {
|
|
|
|
|
|
const id = this.getEntityId(merged[i]);
|
|
|
|
|
|
if (id) {
|
|
|
|
|
|
indexById.set(id, i);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (const post of incoming) {
|
|
|
|
|
|
const id = this.getEntityId(post);
|
|
|
|
|
|
if (!id) {
|
|
|
|
|
|
merged.push(post);
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
const existingIndex = indexById.get(id);
|
|
|
|
|
|
if (existingIndex === undefined) {
|
|
|
|
|
|
indexById.set(id, merged.length);
|
|
|
|
|
|
merged.push(post);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
merged[existingIndex] = post;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return merged;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private mergeRefreshWindow(previousInput: Post[] | null | undefined, latestInput: Post[] | null | undefined): Post[] {
|
|
|
|
|
|
const previous = Array.isArray(previousInput) ? previousInput : [];
|
|
|
|
|
|
const latest = Array.isArray(latestInput) ? latestInput : [];
|
|
|
|
|
|
if (latest.length === 0) {
|
|
|
|
|
|
return previous;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (previous.length === 0) {
|
|
|
|
|
|
return latest;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const latestIdSet = new Set(
|
|
|
|
|
|
latest.map((item) => this.getEntityId(item)).filter(Boolean) as string[]
|
|
|
|
|
|
);
|
|
|
|
|
|
const remaining = previous.filter((item) => {
|
|
|
|
|
|
const id = this.getEntityId(item);
|
|
|
|
|
|
return !id || !latestIdSet.has(id);
|
|
|
|
|
|
});
|
|
|
|
|
|
return [...latest, ...remaining];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 更新帖子详情状态
|
|
|
|
|
|
* @param postId 帖子ID
|
|
|
|
|
|
* @param partialState 部分状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
private updatePostDetailState(postId: string, partialState: Partial<PostDetailState>): void {
|
|
|
|
|
|
const currentState = this.getPostDetailState(postId);
|
|
|
|
|
|
this.postDetailState.set(postId, {
|
|
|
|
|
|
...currentState,
|
|
|
|
|
|
...partialState,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-24 05:21:46 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 分享计数上报成功后,同步各列表与详情中的分享数
|
|
|
|
|
|
*/
|
|
|
|
|
|
applyShareCountUpdate(postId: string, sharesCount: number): void {
|
|
|
|
|
|
this.postsState.forEach((state, key) => {
|
|
|
|
|
|
const index = state.posts.findIndex((p) => p.id === postId);
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
const newPosts = [...state.posts];
|
|
|
|
|
|
const cur = newPosts[index];
|
|
|
|
|
|
newPosts[index] = {
|
|
|
|
|
|
...cur,
|
|
|
|
|
|
sharesCount,
|
|
|
|
|
|
shares_count: sharesCount,
|
|
|
|
|
|
};
|
|
|
|
|
|
this.updatePostsState(key, { posts: newPosts });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
const detail = this.getPostDetailState(postId);
|
|
|
|
|
|
if (detail.post) {
|
|
|
|
|
|
this.updatePostDetailState(postId, {
|
|
|
|
|
|
post: {
|
|
|
|
|
|
...detail.post,
|
|
|
|
|
|
sharesCount,
|
|
|
|
|
|
shares_count: sharesCount,
|
|
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
// ==================== 帖子列表操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取帖子列表
|
|
|
|
|
|
* @param params 查询参数
|
|
|
|
|
|
* @param key 列表键(用于区分不同的列表)
|
|
|
|
|
|
*/
|
|
|
|
|
|
async fetchPosts(params?: GetPostsParams, key: string = 'default'): Promise<PostsResult> {
|
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
|
this.updatePostsState(key, { isLoading: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 默认传递空字符串 cursor 来启动 cursor 模式
|
|
|
|
|
|
// 注意:cursor 要放在 ...params 后面,这样只有在 params 没有传 cursor 时才使用默认值
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
const queryParams: GetPostsParams = {
|
|
|
|
|
|
pageSize: params?.pageSize || DEFAULT_PAGE_SIZE,
|
|
|
|
|
|
...params,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
cursor: params?.cursor !== undefined ? params.cursor : '', // 默认使用空字符串启动 cursor 模式
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const result = await postRepository.getPosts(queryParams);
|
|
|
|
|
|
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 判断是否为 cursor 模式(有 next_cursor 返回)
|
|
|
|
|
|
const isCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态(保存请求参数以便加载更多时使用)
|
2026-03-24 01:19:09 +08:00
|
|
|
|
const mergeStart = Date.now();
|
|
|
|
|
|
const currentState = this.getPostsState(key);
|
|
|
|
|
|
const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
|
|
|
|
|
|
const mergedPosts = this.mergeRefreshWindow(currentState.posts, incomingPosts);
|
|
|
|
|
|
const mergeCost = Date.now() - mergeStart;
|
|
|
|
|
|
if (mergeCost >= this.mergePerfWarnThresholdMs) {
|
|
|
|
|
|
console.log('[PostPerf] fetchPosts merge cost', { key, costMs: mergeCost, prev: currentState.posts.length, next: incomingPosts.length });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
this.updatePostsState(key, {
|
2026-03-24 01:19:09 +08:00
|
|
|
|
posts: mergedPosts,
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
hasMore: result.hasMore,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
cursor: isCursorMode ? result.nextCursor : null, // cursor 模式保存 cursor,否则设为 null 表示 page 模式
|
|
|
|
|
|
currentPage: isCursorMode ? undefined : 1, // page 模式从第 1 页开始
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
isLoading: false,
|
|
|
|
|
|
lastLoadTime: Date.now(),
|
2026-03-23 03:58:26 +08:00
|
|
|
|
lastParams: params, // 保存请求参数
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'posts_loaded',
|
2026-03-24 01:19:09 +08:00
|
|
|
|
payload: { key, posts: incomingPosts, hasMore: result.hasMore },
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '获取帖子列表失败';
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { key, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 刷新帖子列表
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
async refreshPosts(key: string = 'default'): Promise<PostsResult> {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
const state = this.getPostsState(key);
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
// 更新刷新状态
|
|
|
|
|
|
this.updatePostsState(key, { isRefreshing: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 使用保存的请求参数(如 post_type)进行刷新
|
|
|
|
|
|
// 默认传递空字符串 cursor 来启动 cursor 模式
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
const result = await postRepository.getPosts({
|
|
|
|
|
|
pageSize: DEFAULT_PAGE_SIZE,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
...state.lastParams,
|
|
|
|
|
|
cursor: state.lastParams?.cursor !== undefined ? state.lastParams.cursor : '', // 默认使用空字符串启动 cursor 模式
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 判断是否为 cursor 模式(有 next_cursor 返回)
|
|
|
|
|
|
const isCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
// 更新状态
|
2026-03-24 01:19:09 +08:00
|
|
|
|
const mergeStart = Date.now();
|
|
|
|
|
|
const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
|
|
|
|
|
|
const mergedPosts = this.mergeRefreshWindow(state.posts, incomingPosts);
|
|
|
|
|
|
const mergeCost = Date.now() - mergeStart;
|
|
|
|
|
|
if (mergeCost >= this.mergePerfWarnThresholdMs) {
|
|
|
|
|
|
console.log('[PostPerf] refreshPosts merge cost', { key, costMs: mergeCost, prev: state.posts.length, next: incomingPosts.length });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
this.updatePostsState(key, {
|
2026-03-24 01:19:09 +08:00
|
|
|
|
posts: mergedPosts,
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
hasMore: result.hasMore,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
cursor: isCursorMode ? result.nextCursor : null,
|
|
|
|
|
|
currentPage: isCursorMode ? undefined : 1,
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
isRefreshing: false,
|
|
|
|
|
|
lastLoadTime: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 重置分页状态
|
|
|
|
|
|
this.paginationManager.reset(key);
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '刷新帖子列表失败';
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
isRefreshing: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载更多帖子
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
async loadMorePosts(key: string = 'default'): Promise<PostsResult> {
|
|
|
|
|
|
const state = this.getPostsState(key);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否还有更多数据
|
|
|
|
|
|
if (!state.hasMore) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
posts: [],
|
|
|
|
|
|
hasMore: false,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否正在加载
|
|
|
|
|
|
if (state.isLoading) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
posts: [],
|
|
|
|
|
|
hasMore: state.hasMore,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
|
this.updatePostsState(key, { isLoading: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 判断使用哪种分页模式:cursor 不为 null 表示使用 cursor 模式
|
|
|
|
|
|
const useCursorMode = state.cursor !== null && state.cursor !== undefined;
|
|
|
|
|
|
|
|
|
|
|
|
// 必须先展开 lastParams,再由本次分页字段覆盖。
|
|
|
|
|
|
// lastParams 来自首次 fetch(通常含 page:1),若写在展开之前会把 nextPage/cursor 覆盖掉,导致永远请求第 1 页、无法加载第 3 页及以后。
|
|
|
|
|
|
const base = { ...(state.lastParams ?? {}) } as GetPostsParams;
|
|
|
|
|
|
let queryParams: GetPostsParams;
|
|
|
|
|
|
|
|
|
|
|
|
if (useCursorMode) {
|
|
|
|
|
|
delete base.page;
|
|
|
|
|
|
queryParams = {
|
|
|
|
|
|
...base,
|
|
|
|
|
|
pageSize: DEFAULT_PAGE_SIZE,
|
|
|
|
|
|
cursor: state.cursor!,
|
|
|
|
|
|
};
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const nextPage = (state.currentPage || 1) + 1;
|
|
|
|
|
|
delete base.cursor;
|
|
|
|
|
|
queryParams = {
|
|
|
|
|
|
...base,
|
|
|
|
|
|
pageSize: DEFAULT_PAGE_SIZE,
|
|
|
|
|
|
page: nextPage,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
|
|
|
|
|
|
const result = await postRepository.getPosts(queryParams);
|
|
|
|
|
|
|
|
|
|
|
|
// 合并新数据
|
2026-03-24 01:19:09 +08:00
|
|
|
|
const mergeStart = Date.now();
|
|
|
|
|
|
const incomingPosts = Array.isArray(result.posts) ? result.posts : [];
|
|
|
|
|
|
const newPosts = this.mergePostListWithFastPath(state.posts, incomingPosts);
|
|
|
|
|
|
const mergeCost = Date.now() - mergeStart;
|
|
|
|
|
|
if (mergeCost >= this.mergePerfWarnThresholdMs) {
|
|
|
|
|
|
console.log('[PostPerf] loadMore merge cost', { key, costMs: mergeCost, prev: state.posts.length, incoming: incomingPosts.length, merged: newPosts.length });
|
|
|
|
|
|
}
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
|
2026-03-23 03:58:26 +08:00
|
|
|
|
// 判断响应是否为 cursor 模式(有 next_cursor 返回)
|
|
|
|
|
|
const responseIsCursorMode = result.nextCursor !== undefined && result.nextCursor !== null;
|
|
|
|
|
|
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
// 更新状态
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
posts: newPosts,
|
|
|
|
|
|
hasMore: result.hasMore,
|
2026-03-23 03:58:26 +08:00
|
|
|
|
cursor: responseIsCursorMode ? result.nextCursor : null,
|
|
|
|
|
|
currentPage: useCursorMode ? state.currentPage : ((state.currentPage || 1) + 1),
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
isLoading: false,
|
|
|
|
|
|
lastLoadTime: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
2026-03-24 01:19:09 +08:00
|
|
|
|
posts: incomingPosts,
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
hasMore: result.hasMore,
|
|
|
|
|
|
nextCursor: result.nextCursor,
|
|
|
|
|
|
};
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '加载更多帖子失败';
|
2026-03-23 03:58:26 +08:00
|
|
|
|
console.error('[ProcessPostUseCase] Load more error:', errorMessage);
|
refactor: migrate post operations to use case architecture with differential updates
Migrate post-related operations from direct service/store calls to a new use case architecture featuring differential updates. Key changes include: (1) introduce ProcessPostUseCase to handle like, unlike, favorite, unfavorite, delete, and fetch operations with proper state management, (2) add useDifferentialPosts hook for efficient list rendering with minimal re-renders, (3) add PostDiffCalculator and PostUpdateBatcher in infrastructure layer for incremental updates, (4) deprecate NotificationItem component in favor of SystemMessageItem, (5) remove deprecated interactive methods from userStore, (6) add posts_cache table to local datasource, (7) clean up legacy MessageDTO and ConversationDTO types, (8) remove deprecated hook useBreakpointCheck, (9) refactor MessageBubble to use measureInWindow directly for better React Native compatibility
2026-03-21 20:55:36 +08:00
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 帖子详情操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取单个帖子详情
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async fetchPostById(id: string): Promise<Post | null> {
|
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
|
this.updatePostDetailState(id, { isLoading: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.getPostById(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
|
|
this.updatePostDetailState(id, {
|
|
|
|
|
|
post,
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '获取帖子详情失败';
|
|
|
|
|
|
this.updatePostDetailState(id, {
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 帖子CRUD操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建帖子
|
|
|
|
|
|
* @param data 创建数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
async createPost(data: CreatePostData): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.createPost(data);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_created',
|
|
|
|
|
|
payload: { post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 更新所有列表(新帖子应该出现在列表顶部)
|
|
|
|
|
|
this.postsState.forEach((state, key) => {
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
posts: [post, ...state.posts],
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '创建帖子失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'create', error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新帖子
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
* @param data 更新数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
async updatePost(id: string, data: UpdatePostData): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.updatePost(id, data);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情状态
|
|
|
|
|
|
this.updatePostDetailState(id, { post });
|
|
|
|
|
|
|
|
|
|
|
|
// 更新列表中的帖子
|
|
|
|
|
|
this.updatePostInLists(id, post);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_updated',
|
|
|
|
|
|
payload: { postId: id, post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '更新帖子失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'update', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除帖子
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async deletePost(id: string): Promise<void> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await postRepository.deletePost(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 从详情状态中移除
|
|
|
|
|
|
this.postDetailState.delete(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 从所有列表中移除
|
|
|
|
|
|
this.postsState.forEach((state, key) => {
|
|
|
|
|
|
const filteredPosts = state.posts.filter((post) => post.id !== id);
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
posts: filteredPosts,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_deleted',
|
|
|
|
|
|
payload: { postId: id },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '删除帖子失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'delete', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 互动操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 点赞帖子
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async likePost(id: string): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.likePost(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情状态
|
|
|
|
|
|
this.updatePostDetailState(id, { post });
|
|
|
|
|
|
|
|
|
|
|
|
// 更新列表中的帖子
|
|
|
|
|
|
this.updatePostInLists(id, post);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_liked',
|
|
|
|
|
|
payload: { postId: id, post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '点赞失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'like', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 取消点赞
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async unlikePost(id: string): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.unlikePost(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情状态
|
|
|
|
|
|
this.updatePostDetailState(id, { post });
|
|
|
|
|
|
|
|
|
|
|
|
// 更新列表中的帖子
|
|
|
|
|
|
this.updatePostInLists(id, post);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_unliked',
|
|
|
|
|
|
payload: { postId: id, post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '取消点赞失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'unlike', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 收藏帖子
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async favoritePost(id: string): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.favoritePost(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情状态
|
|
|
|
|
|
this.updatePostDetailState(id, { post });
|
|
|
|
|
|
|
|
|
|
|
|
// 更新列表中的帖子
|
|
|
|
|
|
this.updatePostInLists(id, post);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_favorited',
|
|
|
|
|
|
payload: { postId: id, post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '收藏失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'favorite', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 取消收藏
|
|
|
|
|
|
* @param id 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async unfavoritePost(id: string): Promise<Post> {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const post = await postRepository.unfavoritePost(id);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新详情状态
|
|
|
|
|
|
this.updatePostDetailState(id, { post });
|
|
|
|
|
|
|
|
|
|
|
|
// 更新列表中的帖子
|
|
|
|
|
|
this.updatePostInLists(id, post);
|
|
|
|
|
|
|
|
|
|
|
|
// 通知订阅者
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'post_unfavorited',
|
|
|
|
|
|
payload: { postId: id, post },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return post;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '取消收藏失败';
|
|
|
|
|
|
this.notifySubscribers({
|
|
|
|
|
|
type: 'error_occurred',
|
|
|
|
|
|
payload: { operation: 'unfavorite', postId: id, error: errorMessage },
|
|
|
|
|
|
timestamp: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 搜索操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 搜索帖子
|
|
|
|
|
|
* @param params 搜索参数
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
async searchPosts(params: SearchPostsParams, key: string = 'search'): Promise<PostsResult> {
|
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
|
this.updatePostsState(key, { isLoading: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await postRepository.searchPosts(params);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
posts: result.posts,
|
|
|
|
|
|
hasMore: result.hasMore,
|
|
|
|
|
|
cursor: result.nextCursor || null,
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
lastLoadTime: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '搜索帖子失败';
|
|
|
|
|
|
this.updatePostsState(key, {
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 用户帖子操作 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户发布的帖子
|
|
|
|
|
|
* @param userId 用户ID
|
|
|
|
|
|
* @param params 查询参数
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
async fetchPostsByUser(
|
|
|
|
|
|
userId: string,
|
|
|
|
|
|
params?: GetPostsParams,
|
|
|
|
|
|
key?: string
|
|
|
|
|
|
): Promise<PostsResult> {
|
|
|
|
|
|
const listKey = key || `user_${userId}`;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新加载状态
|
|
|
|
|
|
this.updatePostsState(listKey, { isLoading: true, error: null });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const result = await postRepository.getPostsByUser(userId, params);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新状态
|
|
|
|
|
|
this.updatePostsState(listKey, {
|
|
|
|
|
|
posts: result.posts,
|
|
|
|
|
|
hasMore: result.hasMore,
|
|
|
|
|
|
cursor: result.nextCursor || null,
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
lastLoadTime: Date.now(),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
const errorMessage = error instanceof Error ? error.message : '获取用户帖子失败';
|
|
|
|
|
|
this.updatePostsState(listKey, {
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
error: errorMessage,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
throw error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 辅助方法 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新所有列表中的帖子
|
|
|
|
|
|
* @param postId 帖子ID
|
|
|
|
|
|
* @param updatedPost 更新后的帖子
|
|
|
|
|
|
*/
|
|
|
|
|
|
private updatePostInLists(postId: string, updatedPost: Post): void {
|
|
|
|
|
|
this.postsState.forEach((state, key) => {
|
|
|
|
|
|
const index = state.posts.findIndex((post) => post.id === postId);
|
|
|
|
|
|
if (index !== -1) {
|
|
|
|
|
|
const newPosts = [...state.posts];
|
|
|
|
|
|
newPosts[index] = updatedPost;
|
|
|
|
|
|
this.updatePostsState(key, { posts: newPosts });
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清除指定列表的状态
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
clearPostsState(key: string = 'default'): void {
|
|
|
|
|
|
this.postsState.delete(key);
|
|
|
|
|
|
this.paginationManager.reset(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清除帖子详情状态
|
|
|
|
|
|
* @param postId 帖子ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
clearPostDetailState(postId: string): void {
|
|
|
|
|
|
this.postDetailState.delete(postId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 清除所有状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
clearAllStates(): void {
|
|
|
|
|
|
this.postsState.clear();
|
|
|
|
|
|
this.postDetailState.clear();
|
|
|
|
|
|
this.paginationManager.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前用户ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
getCurrentUserId(): string | null {
|
|
|
|
|
|
return this.currentUserId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置当前用户ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
setCurrentUserId(userId: string | null): void {
|
|
|
|
|
|
this.currentUserId = userId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 分页状态管理集成 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取分页状态
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPaginationState(key: string): PaginationState {
|
|
|
|
|
|
return this.paginationManager.getState(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 重置分页状态
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
resetPagination(key: string): void {
|
|
|
|
|
|
this.paginationManager.reset(key);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否正在加载
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
isLoading(key: string = 'default'): boolean {
|
|
|
|
|
|
return this.getPostsState(key).isLoading;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 检查是否有错误
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
hasError(key: string = 'default'): boolean {
|
|
|
|
|
|
return this.getPostsState(key).error !== null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取错误信息
|
|
|
|
|
|
* @param key 列表键
|
|
|
|
|
|
*/
|
|
|
|
|
|
getError(key: string = 'default'): string | null {
|
|
|
|
|
|
return this.getPostsState(key).error;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 导出 ====================
|
|
|
|
|
|
|
|
|
|
|
|
// 导出单例实例
|
|
|
|
|
|
export const processPostUseCase = ProcessPostUseCase.getInstance();
|
|
|
|
|
|
export default processPostUseCase;
|