import React, { useEffect, useMemo, useState } from 'react'; import { View, StyleSheet, TouchableOpacity, Alert, ScrollView } from 'react-native'; import { useRouter, useLocalSearchParams } from 'expo-router'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { SafeAreaView } from 'react-native-safe-area-context'; import { spacing, borderRadius, shadows, useAppColors, type AppColors } from '../../theme'; import { Avatar, Text } from '../../components/common'; import * as hrefs from '../../navigation/hrefs'; import { routePayloadCache } from '../../stores'; import { groupService } from '@/services/message'; import { groupManager } from '../../stores/group'; import { userManager } from '../../stores/user'; import { GroupInfoSummaryCard, DecisionFooter } from './components/GroupRequestShared'; const GroupRequestDetailScreen: React.FC = () => { const colors = useAppColors(); const styles = useMemo(() => createGroupRequestDetailStyles(colors), [colors]); const router = useRouter(); const { messageId } = useLocalSearchParams<{ messageId?: string }>(); const message = messageId ? routePayloadCache.getSystemMessage(messageId) : undefined; if (!message) { return ( 无法加载该消息,请从通知列表重新打开。 router.back()} style={styles.backBtn}> 返回 ); } const { extra_data } = message; const [submitting, setSubmitting] = useState(false); const [memberCount, setMemberCount] = useState(null); const [loadingGroup, setLoadingGroup] = useState(false); const requestType = extra_data?.request_type; const requestStatus = extra_data?.request_status; const reviewerName = extra_data?.actor_name || extra_data?.operator_name || '管理员'; const canAction = requestStatus === 'pending' && (message.system_type === 'group_join_apply' || message.system_type === 'group_invite'); const processedText = requestStatus === 'accepted' ? `${reviewerName}已同意` : requestStatus === 'rejected' ? `${reviewerName}已拒绝` : '该请求已处理'; const applicantName = useMemo(() => { if (requestType === 'invite') { return extra_data?.target_user_name || '被邀请用户'; } return extra_data?.actor_name || '申请用户'; }, [requestType, extra_data]); const applicantAvatar = useMemo(() => { if (requestType === 'invite') { return extra_data?.target_user_avatar || ''; } return extra_data?.avatar_url || ''; }, [requestType, extra_data]); const applicantId = useMemo(() => { if (requestType === 'invite') { return extra_data?.target_user_id; } return extra_data?.actor_id_str; }, [requestType, extra_data]); useEffect(() => { const loadGroupInfo = async () => { if (!extra_data?.group_id) return; setLoadingGroup(true); try { const group = await groupManager.getGroup(String(extra_data.group_id)); setMemberCount(group.member_count ?? null); } catch { setMemberCount(null); } finally { setLoadingGroup(false); } }; loadGroupInfo(); }, [extra_data?.group_id]); const handleDecision = async (approve: boolean) => { const flag = extra_data?.flag; const groupId = extra_data?.group_id; if (!flag) { Alert.alert('提示', '缺少请求标识,无法处理'); return; } if (!groupId) { Alert.alert('提示', '缺少群组标识,无法处理'); return; } setSubmitting(true); try { if (message.system_type === 'group_invite') { await groupService.respondInvite(String(groupId), { flag, approve, }); } else { await groupService.reviewJoinRequest(String(groupId), { flag, approve, }); } Alert.alert('成功', approve ? '已同意申请' : '已拒绝申请', [ { text: '确定', onPress: () => router.back() }, ]); } catch (error) { Alert.alert('操作失败', '请稍后重试'); } finally { setSubmitting(false); } }; const handleOpenUser = async () => { if (!applicantId) return; const user = await userManager.getUserById(applicantId); if (user?.id) { router.push(hrefs.hrefUserProfile(String(user.id))); } }; return ( 用户信息 {applicantName} {requestType === 'invite' ? '被邀请加入' : '申请加入'} {applicantId ? ( ) : null} {requestType === 'invite' && ( 邀请人:{extra_data?.actor_name || '群成员'} )} handleDecision(false)} onApprove={() => handleDecision(true)} processedText={processedText} /> ); }; function createGroupRequestDetailStyles(colors: AppColors) { return StyleSheet.create({ container: { flex: 1, backgroundColor: colors.background.default, }, emptyWrap: { flex: 1, padding: spacing.lg, justifyContent: 'center', alignItems: 'center', gap: spacing.md, }, backBtn: { padding: spacing.sm, }, scrollView: { flex: 1, }, scrollContent: { padding: spacing.lg, paddingBottom: spacing.xl, }, card: { backgroundColor: colors.background.paper, borderRadius: borderRadius.lg, padding: spacing.lg, marginBottom: spacing.md, ...shadows.sm, }, sectionTitle: { marginBottom: spacing.sm, }, row: { flexDirection: 'row', alignItems: 'center', }, meta: { marginLeft: spacing.md, flex: 1, }, name: { marginBottom: 2, }, subDesc: { marginTop: spacing.sm, }, }); } export default GroupRequestDetailScreen;