feat(content): add rich content rendering with @mentions and vote segments
Some checks failed
Frontend CI / build-and-push-web (push) Failing after 8m30s
Frontend CI / ota-android (push) Successful in 10m43s
Frontend CI / build-android-apk (push) Successful in 1h24m38s

- Add PostContentRenderer component for rendering posts/comments with segments
- Add PostMentionInput component for @mention support in post/comment creation
- Add VoteSegmentData and vote segment type for unified post creation API
- Update post and comment services to support segments in API requests
- Fix auth service to clear tokens before login/register
- Improve database initialization with proper close/retry logic
- Add verification check before allowing post creation
- Add metro web shims for react-native-webrtc full package and requireNativeComponent
- Update build config with git hash based version numbers
This commit is contained in:
lafay
2026-04-23 22:29:58 +08:00
parent eb4e1c080d
commit b2c3d5e54e
23 changed files with 797 additions and 127 deletions

View File

@@ -1,4 +1,4 @@
/**
/**
* 发帖页 CreatePostScreen响应式适配
* 威友 - 发布新帖子
* 参考微博发帖界面设计
@@ -38,8 +38,10 @@ import { channelService, postService, showPrompt, voteService } from '../../serv
import { ApiError } from '@/services/core';
import { uploadService } from '@/services/upload';
import VoteEditor from '../../components/business/VoteEditor';
import PostMentionInput from '../../components/business/PostMentionInput';
import { useResponsive, useResponsiveValue } from '../../hooks';
import * as hrefs from '../../navigation/hrefs';
import { MessageSegment } from '../../types';
// Props 接口
interface CreatePostScreenProps {
@@ -106,6 +108,7 @@ export const CreatePostScreen: React.FC<CreatePostScreenProps> = (props) => {
const [title, setTitle] = useState('');
const [content, setContent] = useState('');
const [segments, setSegments] = useState<MessageSegment[]>([]);
const [images, setImages] = useState<{ uri: string; uploading?: boolean }[]>([]);
const [channelOptions, setChannelOptions] = useState<ChannelOption[]>([]);
const [selectedChannelId, setSelectedChannelId] = useState<string | null>(null);
@@ -402,6 +405,7 @@ export const CreatePostScreen: React.FC<CreatePostScreenProps> = (props) => {
const updated = await postService.updatePost(editPostID, {
title: title.trim(),
content: content.trim(),
segments: segments.length > 0 ? segments : undefined,
images: imageUrls,
});
if (!updated) {
@@ -415,10 +419,10 @@ export const CreatePostScreen: React.FC<CreatePostScreenProps> = (props) => {
});
router.replace(hrefs.hrefHome());
} else {
// 创建普通帖子
await postService.createPost({
title: title.trim(),
content: content.trim(),
segments: segments.length > 0 ? segments : undefined,
images: imageUrls,
channel_id: selectedChannelId || undefined,
});
@@ -598,22 +602,18 @@ export const CreatePostScreen: React.FC<CreatePostScreenProps> = (props) => {
maxLength={MAX_TITLE_LENGTH}
/>
{/* 正文输入 */}
<TextInput
ref={contentInputRef}
{/* 正文输入(支持 @提及) */}
<PostMentionInput
value={content}
onChangeText={setContent}
onSegmentsChange={setSegments}
placeholder="分享新鲜事..."
maxLength={MAX_CONTENT_LENGTH}
minHeight={contentInputMinHeight}
style={[
styles.contentInput,
isWideScreen && styles.contentInputWide,
{ minHeight: contentInputMinHeight },
]}
value={content}
onChangeText={setContent}
placeholder="分享新鲜事..."
placeholderTextColor={colors.text.hint}
multiline
textAlignVertical="top"
maxLength={MAX_CONTENT_LENGTH}
onSelectionChange={(e) => setSelection(e.nativeEvent.selection)}
/>
{/* 作为正文容器的子模块,追加在文本后面 */}