Initial commit
This commit is contained in:
655
src/views/Profile/ProfilePage.js
Normal file
655
src/views/Profile/ProfilePage.js
Normal file
@@ -0,0 +1,655 @@
|
||||
// src/views/Profile/ProfilePage.js
|
||||
import React, { useState, useRef } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Container,
|
||||
VStack,
|
||||
HStack,
|
||||
Text,
|
||||
Heading,
|
||||
Avatar,
|
||||
Button,
|
||||
Input,
|
||||
Textarea,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
SimpleGrid,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
Stat,
|
||||
StatLabel,
|
||||
StatNumber,
|
||||
StatHelpText,
|
||||
Badge,
|
||||
Divider,
|
||||
Select,
|
||||
useToast,
|
||||
IconButton,
|
||||
Flex,
|
||||
Progress,
|
||||
Tag,
|
||||
TagLabel,
|
||||
TagCloseButton,
|
||||
Wrap,
|
||||
WrapItem,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure
|
||||
} from '@chakra-ui/react';
|
||||
import { EditIcon, CheckIcon, CloseIcon, AddIcon } from '@chakra-ui/icons';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
|
||||
export default function ProfilePage() {
|
||||
const { user, updateUser } = useAuth();
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [newTag, setNewTag] = useState('');
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const fileInputRef = useRef();
|
||||
const toast = useToast();
|
||||
|
||||
// 表单数据状态
|
||||
const [formData, setFormData] = useState({
|
||||
nickname: user?.nickname || '',
|
||||
bio: user?.bio || '',
|
||||
location: user?.location || '',
|
||||
gender: user?.gender || '',
|
||||
birth_date: user?.birth_date || '',
|
||||
trading_experience: user?.trading_experience || '',
|
||||
investment_style: user?.investment_style || '',
|
||||
risk_preference: user?.risk_preference || '',
|
||||
investment_amount: user?.investment_amount || '',
|
||||
preferred_markets: user?.preferred_markets ? user.preferred_markets.split(',') : [],
|
||||
creator_tags: user?.creator_tags ? user.creator_tags.split(',') : []
|
||||
});
|
||||
|
||||
const handleInputChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSaveProfile = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
// 这里应该调用后端API更新用户信息
|
||||
const updatedData = {
|
||||
...formData,
|
||||
preferred_markets: formData.preferred_markets.join(','),
|
||||
creator_tags: formData.creator_tags.join(',')
|
||||
};
|
||||
|
||||
// 模拟API调用
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
updateUser(updatedData);
|
||||
setIsEditing(false);
|
||||
|
||||
toast({
|
||||
title: "个人资料更新成功",
|
||||
status: "success",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
} catch (error) {
|
||||
toast({
|
||||
title: "更新失败",
|
||||
description: error.message,
|
||||
status: "error",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAvatarUpload = (event) => {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
// 这里应该上传文件到服务器
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
updateUser({ avatar_url: e.target.result });
|
||||
toast({
|
||||
title: "头像更新成功",
|
||||
status: "success",
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
};
|
||||
|
||||
const addMarketTag = () => {
|
||||
if (newTag && !formData.preferred_markets.includes(newTag)) {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
preferred_markets: [...prev.preferred_markets, newTag]
|
||||
}));
|
||||
setNewTag('');
|
||||
}
|
||||
};
|
||||
|
||||
const removeMarketTag = (tagToRemove) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
preferred_markets: prev.preferred_markets.filter(tag => tag !== tagToRemove)
|
||||
}));
|
||||
};
|
||||
|
||||
const getProgressColor = (score) => {
|
||||
if (score >= 800) return 'green';
|
||||
if (score >= 500) return 'blue';
|
||||
if (score >= 200) return 'yellow';
|
||||
return 'red';
|
||||
};
|
||||
|
||||
return (
|
||||
<Container maxW="container.xl" py={8}>
|
||||
<VStack spacing={8} align="stretch">
|
||||
{/* 页面标题 */}
|
||||
<HStack justify="space-between">
|
||||
<Heading size="lg" color="gray.800">个人资料</Heading>
|
||||
{!isEditing ? (
|
||||
<Button
|
||||
leftIcon={<EditIcon />}
|
||||
colorScheme="blue"
|
||||
onClick={() => setIsEditing(true)}
|
||||
>
|
||||
编辑资料
|
||||
</Button>
|
||||
) : (
|
||||
<HStack>
|
||||
<Button
|
||||
leftIcon={<CheckIcon />}
|
||||
colorScheme="green"
|
||||
onClick={handleSaveProfile}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
<Button
|
||||
leftIcon={<CloseIcon />}
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setFormData({
|
||||
nickname: user?.nickname || '',
|
||||
bio: user?.bio || '',
|
||||
location: user?.location || '',
|
||||
gender: user?.gender || '',
|
||||
birth_date: user?.birth_date || '',
|
||||
trading_experience: user?.trading_experience || '',
|
||||
investment_style: user?.investment_style || '',
|
||||
risk_preference: user?.risk_preference || '',
|
||||
investment_amount: user?.investment_amount || '',
|
||||
preferred_markets: user?.preferred_markets ? user.preferred_markets.split(',') : [],
|
||||
creator_tags: user?.creator_tags ? user.creator_tags.split(',') : []
|
||||
});
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</HStack>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<SimpleGrid columns={{ base: 1, lg: 3 }} spacing={8}>
|
||||
{/* 左侧:基本信息 */}
|
||||
<Box gridColumn={{ base: "1", lg: "1 / 3" }}>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<Heading size="md">基本信息</Heading>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<VStack spacing={6}>
|
||||
{/* 头像和基本信息 */}
|
||||
<HStack spacing={6} align="start" w="full">
|
||||
<VStack>
|
||||
<Avatar
|
||||
size="2xl"
|
||||
src={user?.avatar_url}
|
||||
name={user?.nickname || user?.username}
|
||||
/>
|
||||
{isEditing && (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
>
|
||||
更换头像
|
||||
</Button>
|
||||
)}
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
style={{ display: 'none' }}
|
||||
onChange={handleAvatarUpload}
|
||||
/>
|
||||
</VStack>
|
||||
|
||||
<VStack flex="1" align="start" spacing={4}>
|
||||
<HStack w="full">
|
||||
<Badge colorScheme="blue" variant="subtle">
|
||||
用户名: {user?.username}
|
||||
</Badge>
|
||||
{user?.is_verified && (
|
||||
<Badge colorScheme="green">已实名认证</Badge>
|
||||
)}
|
||||
{user?.has_wechat && (
|
||||
<Badge colorScheme="green">微信已绑定</Badge>
|
||||
)}
|
||||
{user?.is_creator && (
|
||||
<Badge colorScheme="purple">创作者</Badge>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<SimpleGrid columns={2} spacing={4} w="full">
|
||||
<FormControl>
|
||||
<FormLabel>昵称</FormLabel>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
name="nickname"
|
||||
value={formData.nickname}
|
||||
onChange={handleInputChange}
|
||||
placeholder="请输入昵称"
|
||||
/>
|
||||
) : (
|
||||
<Text>{user?.nickname || '未设置'}</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>性别</FormLabel>
|
||||
{isEditing ? (
|
||||
<Select
|
||||
name="gender"
|
||||
value={formData.gender}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="">请选择</option>
|
||||
<option value="male">男</option>
|
||||
<option value="female">女</option>
|
||||
<option value="other">其他</option>
|
||||
</Select>
|
||||
) : (
|
||||
<Text>
|
||||
{user?.gender === 'male' ? '男' :
|
||||
user?.gender === 'female' ? '女' :
|
||||
user?.gender === 'other' ? '其他' : '未设置'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>所在地</FormLabel>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
name="location"
|
||||
value={formData.location}
|
||||
onChange={handleInputChange}
|
||||
placeholder="请输入所在地"
|
||||
/>
|
||||
) : (
|
||||
<Text>{user?.location || '未设置'}</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>生日</FormLabel>
|
||||
{isEditing ? (
|
||||
<Input
|
||||
name="birth_date"
|
||||
type="date"
|
||||
value={formData.birth_date}
|
||||
onChange={handleInputChange}
|
||||
/>
|
||||
) : (
|
||||
<Text>{user?.birth_date || '未设置'}</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
</SimpleGrid>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>个人简介</FormLabel>
|
||||
{isEditing ? (
|
||||
<Textarea
|
||||
name="bio"
|
||||
value={formData.bio}
|
||||
onChange={handleInputChange}
|
||||
placeholder="介绍一下自己..."
|
||||
rows={3}
|
||||
/>
|
||||
) : (
|
||||
<Text color="gray.600">
|
||||
{user?.bio || '这个人很懒,什么都没留下...'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
</VStack>
|
||||
</HStack>
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* 投资偏好 */}
|
||||
<Box w="full">
|
||||
<Heading size="sm" mb={4}>投资偏好</Heading>
|
||||
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={4}>
|
||||
<FormControl>
|
||||
<FormLabel>交易经验</FormLabel>
|
||||
{isEditing ? (
|
||||
<Select
|
||||
name="trading_experience"
|
||||
value={formData.trading_experience}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="">请选择</option>
|
||||
<option value="beginner">新手 (0-1年)</option>
|
||||
<option value="intermediate">中级 (1-3年)</option>
|
||||
<option value="advanced">高级 (3-5年)</option>
|
||||
<option value="expert">专家 (5年以上)</option>
|
||||
</Select>
|
||||
) : (
|
||||
<Text>
|
||||
{user?.trading_experience === 'beginner' ? '新手 (0-1年)' :
|
||||
user?.trading_experience === 'intermediate' ? '中级 (1-3年)' :
|
||||
user?.trading_experience === 'advanced' ? '高级 (3-5年)' :
|
||||
user?.trading_experience === 'expert' ? '专家 (5年以上)' : '未设置'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>投资风格</FormLabel>
|
||||
{isEditing ? (
|
||||
<Select
|
||||
name="investment_style"
|
||||
value={formData.investment_style}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="">请选择</option>
|
||||
<option value="conservative">保守型</option>
|
||||
<option value="moderate">稳健型</option>
|
||||
<option value="aggressive">积极型</option>
|
||||
<option value="speculative">投机型</option>
|
||||
</Select>
|
||||
) : (
|
||||
<Text>
|
||||
{user?.investment_style === 'conservative' ? '保守型' :
|
||||
user?.investment_style === 'moderate' ? '稳健型' :
|
||||
user?.investment_style === 'aggressive' ? '积极型' :
|
||||
user?.investment_style === 'speculative' ? '投机型' : '未设置'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>风险偏好</FormLabel>
|
||||
{isEditing ? (
|
||||
<Select
|
||||
name="risk_preference"
|
||||
value={formData.risk_preference}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="">请选择</option>
|
||||
<option value="low">低风险</option>
|
||||
<option value="medium">中等风险</option>
|
||||
<option value="high">高风险</option>
|
||||
</Select>
|
||||
) : (
|
||||
<Text>
|
||||
{user?.risk_preference === 'low' ? '低风险' :
|
||||
user?.risk_preference === 'medium' ? '中等风险' :
|
||||
user?.risk_preference === 'high' ? '高风险' : '未设置'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
|
||||
<FormControl>
|
||||
<FormLabel>投资金额</FormLabel>
|
||||
{isEditing ? (
|
||||
<Select
|
||||
name="investment_amount"
|
||||
value={formData.investment_amount}
|
||||
onChange={handleInputChange}
|
||||
>
|
||||
<option value="">请选择</option>
|
||||
<option value="under_10k">1万以下</option>
|
||||
<option value="10k_50k">1-5万</option>
|
||||
<option value="50k_100k">5-10万</option>
|
||||
<option value="100k_500k">10-50万</option>
|
||||
<option value="over_500k">50万以上</option>
|
||||
</Select>
|
||||
) : (
|
||||
<Text>
|
||||
{user?.investment_amount === 'under_10k' ? '1万以下' :
|
||||
user?.investment_amount === '10k_50k' ? '1-5万' :
|
||||
user?.investment_amount === '50k_100k' ? '5-10万' :
|
||||
user?.investment_amount === '100k_500k' ? '10-50万' :
|
||||
user?.investment_amount === 'over_500k' ? '50万以上' : '未设置'}
|
||||
</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
</SimpleGrid>
|
||||
|
||||
{/* 偏好市场标签 */}
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>偏好市场</FormLabel>
|
||||
<Wrap>
|
||||
{formData.preferred_markets.map((market, index) => (
|
||||
<WrapItem key={index}>
|
||||
<Tag size="md" variant="solid" colorScheme="blue">
|
||||
<TagLabel>{market}</TagLabel>
|
||||
{isEditing && (
|
||||
<TagCloseButton onClick={() => removeMarketTag(market)} />
|
||||
)}
|
||||
</Tag>
|
||||
</WrapItem>
|
||||
))}
|
||||
{isEditing && (
|
||||
<WrapItem>
|
||||
<HStack>
|
||||
<Input
|
||||
size="sm"
|
||||
placeholder="添加市场"
|
||||
value={newTag}
|
||||
onChange={(e) => setNewTag(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && addMarketTag()}
|
||||
/>
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={<AddIcon />}
|
||||
onClick={addMarketTag}
|
||||
/>
|
||||
</HStack>
|
||||
</WrapItem>
|
||||
)}
|
||||
</Wrap>
|
||||
{formData.preferred_markets.length === 0 && !isEditing && (
|
||||
<Text color="gray.500" fontSize="sm">暂未设置偏好市场</Text>
|
||||
)}
|
||||
</FormControl>
|
||||
</Box>
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Box>
|
||||
|
||||
{/* 右侧:统计数据 */}
|
||||
<VStack spacing={6}>
|
||||
{/* 社区统计 */}
|
||||
<Card w="full">
|
||||
<CardHeader>
|
||||
<Heading size="md">社区统计</Heading>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<VStack spacing={4}>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>用户等级</StatLabel>
|
||||
<StatNumber color="blue.500">Lv.{user?.user_level || 1}</StatNumber>
|
||||
</Stat>
|
||||
|
||||
<SimpleGrid columns={2} spacing={4} w="full">
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>声誉分数</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.reputation_score || 0}</StatNumber>
|
||||
</Stat>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>贡献点数</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.contribution_point || 0}</StatNumber>
|
||||
</Stat>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>发帖数</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.post_count || 0}</StatNumber>
|
||||
</Stat>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>评论数</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.comment_count || 0}</StatNumber>
|
||||
</Stat>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>关注者</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.follower_count || 0}</StatNumber>
|
||||
</Stat>
|
||||
<Stat textAlign="center">
|
||||
<StatLabel>关注中</StatLabel>
|
||||
<StatNumber fontSize="lg">{user?.following_count || 0}</StatNumber>
|
||||
</Stat>
|
||||
</SimpleGrid>
|
||||
|
||||
<Box w="full">
|
||||
<Text fontSize="sm" color="gray.600" mb={2}>声誉等级</Text>
|
||||
<Progress
|
||||
value={(user?.reputation_score || 0) / 10}
|
||||
colorScheme={getProgressColor(user?.reputation_score || 0)}
|
||||
borderRadius="md"
|
||||
/>
|
||||
<Text fontSize="xs" color="gray.500" mt={1}>
|
||||
{user?.reputation_score || 0} / 1000
|
||||
</Text>
|
||||
</Box>
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
{/* 账户信息 */}
|
||||
<Card w="full">
|
||||
<CardHeader>
|
||||
<Heading size="md">账户信息</Heading>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<VStack spacing={3} align="start">
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">邮箱</Text>
|
||||
<VStack align="end" spacing={0}>
|
||||
<Text fontSize="sm">{user?.email}</Text>
|
||||
{user?.email_confirmed && (
|
||||
<Badge size="xs" colorScheme="green">已验证</Badge>
|
||||
)}
|
||||
</VStack>
|
||||
</HStack>
|
||||
|
||||
{user?.phone && (
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">手机号</Text>
|
||||
<VStack align="end" spacing={0}>
|
||||
<Text fontSize="sm">{user.phone}</Text>
|
||||
{user?.phone_confirmed && (
|
||||
<Badge size="xs" colorScheme="green">已验证</Badge>
|
||||
)}
|
||||
</VStack>
|
||||
</HStack>
|
||||
)}
|
||||
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">微信</Text>
|
||||
{user?.has_wechat ? (
|
||||
<Badge size="xs" colorScheme="green">已绑定</Badge>
|
||||
) : (
|
||||
<Badge size="xs" colorScheme="gray">未绑定</Badge>
|
||||
)}
|
||||
</HStack>
|
||||
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">注册时间</Text>
|
||||
<Text fontSize="sm">
|
||||
{user?.created_at ? new Date(user.created_at).toLocaleDateString() : '未知'}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">最后活跃</Text>
|
||||
<Text fontSize="sm">
|
||||
{user?.last_seen ? new Date(user.last_seen).toLocaleDateString() : '未知'}
|
||||
</Text>
|
||||
</HStack>
|
||||
|
||||
<HStack justify="space-between" w="full">
|
||||
<Text fontSize="sm" color="gray.600">账户状态</Text>
|
||||
<Badge colorScheme={user?.status === 'active' ? 'green' : 'gray'}>
|
||||
{user?.status === 'active' ? '正常' : '未激活'}
|
||||
</Badge>
|
||||
</HStack>
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
{/* 实名认证 */}
|
||||
{!user?.is_verified && (
|
||||
<Card w="full">
|
||||
<CardHeader>
|
||||
<Heading size="md">实名认证</Heading>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<VStack spacing={4}>
|
||||
<Text fontSize="sm" color="gray.600" textAlign="center">
|
||||
完成实名认证,获得更高权限和信任度
|
||||
</Text>
|
||||
<Button colorScheme="orange" size="sm" onClick={onOpen}>
|
||||
立即认证
|
||||
</Button>
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)}
|
||||
</VStack>
|
||||
</SimpleGrid>
|
||||
</VStack>
|
||||
|
||||
{/* 实名认证模态框 */}
|
||||
<Modal isOpen={isOpen} onClose={onClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>实名认证</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody pb={6}>
|
||||
<VStack spacing={4}>
|
||||
<FormControl>
|
||||
<FormLabel>真实姓名</FormLabel>
|
||||
<Input placeholder="请输入真实姓名" />
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>身份证号</FormLabel>
|
||||
<Input placeholder="请输入身份证号" />
|
||||
</FormControl>
|
||||
<Text fontSize="sm" color="gray.500">
|
||||
您的个人信息将严格保密,仅用于身份验证
|
||||
</Text>
|
||||
<Button colorScheme="blue" w="full">
|
||||
提交认证
|
||||
</Button>
|
||||
</VStack>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user