refactor: restructure core architecture and responsive system
This commit implements a major architectural refactor to improve modularity, type safety, and maintainability across the codebase.
Key changes include:
- **Responsive System Refactor**: Migrated from a monolithic `useResponsive` hook to a set of specialized, granular hooks (`useBreakpoint`, `useOrientation`, `usePlatform`, etc.) located in `src/presentation/hooks/responsive`. This reduces unnecessary re-renders and improves developer experience.
- **Core Service Restructuring**: Introduced a new directory structure for services, including dedicated folders for `datasources`, `mappers`, and domain-specific types (`message`, `post`).
- **Data Layer Improvements**:
- Centralized JSON parsing logic in `src/database/core/jsonUtils.ts`.
- Cleaned up repository implementations by removing redundant local utility functions.
- Refactored `MessageMapper` to use the new centralized JSON utility.
- **Type System Cleanup**:
- Decomposed the large `src/types/dto.ts` into a modular `src/types/dto/` directory.
- Simplified `src/types/index.ts` and introduced backward-compatible aliases for core entities.
- **Utility Consolidation**:
- Created a centralized `src/utils/formatTime.ts` to replace fragmented date formatting logic across various screens and components.
- Removed deprecated responsive utility files in favor of the new hook-based system.
- **Service Logic Refinement**: Refactored `ApiClient` and `WebSocketService` to use a centralized `showVerificationModal` service, removing duplicated state management for verification prompts.
This commit is contained in:
129
src/services/mappers/PostMapper.ts
Normal file
129
src/services/mappers/PostMapper.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 帖子数据映射器
|
||||
* 负责 Post 模型与 API 响应之间的转换
|
||||
*/
|
||||
|
||||
import { PostModel, UserModel } from '../models';
|
||||
import type { PostDTO } from '../../types/dto';
|
||||
|
||||
export class PostMapper {
|
||||
static fromApiResponse(response: PostDTO): PostModel {
|
||||
return {
|
||||
id: String(response.id || ''),
|
||||
authorId: String(response.user_id || ''),
|
||||
author: response.author ? this.mapAuthorFromApi(response.author) : undefined,
|
||||
title: response.title || '',
|
||||
content: response.content || '',
|
||||
images: response.images?.map(img => img.url) || [],
|
||||
likeCount: response.likes_count || 0,
|
||||
commentCount: response.comments_count || 0,
|
||||
shareCount: response.shares_count || 0,
|
||||
viewCount: response.views_count || 0,
|
||||
favoriteCount: response.favorites_count || 0,
|
||||
isLiked: response.is_liked || false,
|
||||
isFavorited: response.is_favorited || false,
|
||||
isTop: response.is_pinned || false,
|
||||
status: (response.status || 'published') as 'published' | 'draft' | 'deleted',
|
||||
channelId: response.channel_id,
|
||||
channel:
|
||||
response.channel && response.channel.id
|
||||
? { id: String(response.channel.id), name: String(response.channel.name || '') }
|
||||
: undefined,
|
||||
tags: [],
|
||||
createdAt: new Date(response.created_at || Date.now()),
|
||||
// 空字符串/缺省时用 created_at,避免误用 Date.now() 导致全部显示「刚修改」
|
||||
updatedAt: new Date(
|
||||
response.updated_at ||
|
||||
response.created_at ||
|
||||
Date.now()
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 API 响应数组转换为应用模型数组
|
||||
*/
|
||||
static fromApiResponseList(responses: PostDTO[]): PostModel[] {
|
||||
return responses.map(r => this.fromApiResponse(r));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将应用模型转换为 API 请求数据
|
||||
*/
|
||||
static toApiRequest(model: Partial<PostModel>): Record<string, any> {
|
||||
const request: Record<string, any> = {};
|
||||
|
||||
if (model.title !== undefined) {
|
||||
request.title = model.title;
|
||||
}
|
||||
if (model.content !== undefined) {
|
||||
request.content = model.content;
|
||||
}
|
||||
if (model.images !== undefined) {
|
||||
request.images = model.images;
|
||||
}
|
||||
if (model.channelId !== undefined) {
|
||||
request.channel_id = model.channelId;
|
||||
}
|
||||
if (model.tags !== undefined) {
|
||||
request.tags = model.tags;
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建帖子请求
|
||||
*/
|
||||
static createPostRequest(
|
||||
title: string,
|
||||
content: string,
|
||||
images?: string[],
|
||||
channelId?: string
|
||||
): Record<string, any> {
|
||||
const request: Record<string, any> = {
|
||||
title,
|
||||
content,
|
||||
};
|
||||
if (images && images.length > 0) {
|
||||
request.images = images;
|
||||
}
|
||||
if (channelId) {
|
||||
request.channel_id = channelId;
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新帖子请求
|
||||
*/
|
||||
static updatePostRequest(
|
||||
title?: string,
|
||||
content?: string,
|
||||
images?: string[]
|
||||
): Record<string, any> {
|
||||
const request: Record<string, any> = {};
|
||||
if (title !== undefined) {
|
||||
request.title = title;
|
||||
}
|
||||
if (content !== undefined) {
|
||||
request.content = content;
|
||||
}
|
||||
if (images !== undefined) {
|
||||
request.images = images;
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 映射作者信息
|
||||
*/
|
||||
private static mapAuthorFromApi(author: any): UserModel {
|
||||
return {
|
||||
id: String(author.id || ''),
|
||||
username: author.username || '',
|
||||
nickname: author.nickname,
|
||||
avatar: author.avatar,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user