Files
frontend/src/services/post/voteService.ts
lafay b2c3d5e54e
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
feat(content): add rich content rendering with @mentions and vote segments
- 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
2026-04-23 22:29:58 +08:00

135 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 投票服务
* 处理投票相关的API调用
*/
import { api } from '../core/api';
import { Post, VoteResultDTO, CreateVotePostRequest, MessageSegment } from '@/types';
// 投票响应
interface VoteResponse {
success: boolean;
message?: string;
}
// 更新投票选项响应
interface UpdateVoteOptionResponse {
success: boolean;
message?: string;
}
/**
* 投票服务类
*/
class VoteService {
/**
* 创建投票帖子(通过统一的 POST /posts 接口,投票选项作为 vote segment
*/
async createVotePost(data: CreateVotePostRequest): Promise<Post | null> {
if (!data.vote_options || data.vote_options.length < 2) {
console.error('[VoteService] 投票选项至少需要2个');
return null;
}
if (data.vote_options.length > 10) {
console.error('[VoteService] 投票选项最多10个');
return null;
}
// 构建 segments先放文本内容再放投票 segment
const segments: MessageSegment[] = [];
if (data.content) {
segments.push({ type: 'text', data: { text: data.content } });
}
segments.push({
type: 'vote',
data: {
options: data.vote_options.map((opt, i) => ({
id: `opt_${i + 1}`,
content: typeof opt === 'string' ? opt : opt.content,
})),
max_choices: 1,
is_multi_choice: false,
},
});
const response = await api.post<Post>('/posts', {
title: data.title,
content: data.content || '',
segments,
images: data.images,
channel_id: data.channel_id,
});
return response.data;
}
/**
* 获取投票结果
* @param postId 帖子ID
* @returns 投票结果或null
*/
async getVoteResult(postId: string): Promise<VoteResultDTO | null> {
try {
const response = await api.get<VoteResultDTO>(`/posts/${postId}/vote`);
return response.data;
} catch (error) {
console.error('[VoteService] 获取投票结果失败:', error);
return null;
}
}
/**
* 投票
* @param postId 帖子ID
* @param optionId 选项ID
* @returns 是否成功
*/
async vote(postId: string, optionId: string): Promise<boolean> {
try {
const response = await api.post<VoteResponse>(`/posts/${postId}/vote`, {
option_id: optionId,
});
return response.data.success;
} catch (error) {
console.error('[VoteService] 投票失败:', error);
return false;
}
}
/**
* 取消投票
* @param postId 帖子ID
* @returns 是否成功
*/
async unvote(postId: string): Promise<boolean> {
try {
const response = await api.delete<VoteResponse>(`/posts/${postId}/vote`);
return response.data.success;
} catch (error) {
console.error('[VoteService] 取消投票失败:', error);
return false;
}
}
/**
* 更新投票选项(作者权限)
* @param optionId 选项ID
* @param content 新内容
* @param postId 帖子ID
* @returns 是否成功
*/
async updateVoteOption(optionId: string, content: string, postId: string): Promise<boolean> {
try {
const response = await api.put<UpdateVoteOptionResponse>(
`/posts/${postId}/vote/options/${optionId}`,
{ content }
);
return response.data.success;
} catch (error) {
console.error('[VoteService] 更新投票选项失败:', error);
return false;
}
}
}
export const voteService = new VoteService();