blob: 4e2b5dca7d59060726260197291089c9c22e5abd [file] [log] [blame] [edit]
import React, { useState, useEffect } from 'react';
import {
Card,
Tabs,
Button,
Table,
Modal,
Form,
Input,
Select,
Upload,
message,
Tag,
Space,
Popconfirm,
Row,
Col,
Radio,
InputNumber,
Image
} from 'antd';
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
EyeOutlined,
UploadOutlined,
HeartOutlined,
LoadingOutlined
} from '@ant-design/icons';
import { useNavigate } from 'react-router-dom';
import {
getMyPosts,
getMyFavorites,
publishPost,
updatePost,
deletePost,
getAvailableTags,
uploadImage,
deleteImage,
getPromotionPlans,
createPayment,
getPromotionStatus,
confirmPayment,
cancelPayment
} from '@/services/post';
import PostCard from '../PostCenter/PostCard';
import styles from './index.module.css';
const { TabPane } = Tabs;
const { TextArea } = Input;
const { Option } = Select;
interface PostFormData {
title: string;
content: string;
summary: string;
tags: string[] | string;
promotionPlan?: number;
coverImage?: string;
}
interface PromotionPlan {
id: number;
name: string;
description: string;
price: number;
duration: number;
}
interface PaymentRecord {
paymentId: number;
postId: number;
planId: number;
userId: number;
amount: number;
paymentStatus: string;
paymentTime: string;
}
const UserCenter: React.FC = () => {
const navigate = useNavigate();
const [activeTab, setActiveTab] = useState('myPosts');
const [publishModalVisible, setPublishModalVisible] = useState(false);
const [editModalVisible, setEditModalVisible] = useState(false);
const [paymentModalVisible, setPaymentModalVisible] = useState(false);
const [myPosts, setMyPosts] = useState<API.Post.PostInfo[]>([]);
const [favorites, setFavorites] = useState<API.Post.PostInfo[]>([]);
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const [editForm] = Form.useForm();
const [selectedPromotion, setSelectedPromotion] = useState<PromotionPlan | null>(null);
const [currentEditPost, setCurrentEditPost] = useState<API.Post.PostInfo | null>(null);
const [availableTags, setAvailableTags] = useState<API.Post.PostTag[]>([]);
const [promotionPlans, setPromotionPlans] = useState<PromotionPlan[]>([]);
const [uploadLoading, setUploadLoading] = useState(false);
const [editUploadLoading, setEditUploadLoading] = useState(false);
const [coverImageUrl, setCoverImageUrl] = useState<string>('');
const [editCoverImageUrl, setEditCoverImageUrl] = useState<string>('');
const [currentPayment, setCurrentPayment] = useState<PaymentRecord | null>(null);
const [isEditingPromotion, setIsEditingPromotion] = useState(false);
const [currentPublishingPostId, setCurrentPublishingPostId] = useState<number | null>(null); // 跟踪当前正在发布的帖子ID
useEffect(() => {
if (activeTab === 'myPosts') {
fetchMyPosts();
} else if (activeTab === 'favorites') {
fetchFavorites();
}
}, [activeTab]);
useEffect(() => {
fetchAvailableTags();
fetchPromotionPlans();
}, []);
const fetchMyPosts = async () => {
setLoading(true);
try {
const response = await getMyPosts({ pageNum: 1, pageSize: 100 });
if (response.code === 200) {
setMyPosts(response.rows || []);
} else {
message.error(response.msg || '获取我的帖子失败');
}
} catch (error) {
message.error('获取我的帖子失败');
} finally {
setLoading(false);
}
};
const fetchFavorites = async () => {
setLoading(true);
try {
const response = await getMyFavorites({ pageNum: 1, pageSize: 100 });
if (response.code === 200) {
setFavorites(response.rows || []);
} else {
message.error(response.msg || '获取收藏列表失败');
}
} catch (error) {
message.error('获取收藏列表失败');
} finally {
setLoading(false);
}
};
const fetchAvailableTags = async () => {
try {
const response = await getAvailableTags();
if (response.code === 200) {
setAvailableTags(response.data || []);
} else {
message.error(response.msg || '获取可用标签失败');
}
} catch (error) {
message.error('获取可用标签失败');
}
};
const fetchPromotionPlans = async () => {
try {
const response = await getPromotionPlans();
if (response.code === 200) {
setPromotionPlans(response.data || []);
}
} catch (error) {
console.error('获取推广计划失败:', error);
}
};
const handlePublishPost = async (values: PostFormData) => {
try {
// 如果选择了推广计划
if (values.promotionPlan) {
const selectedPlan = promotionPlans.find(p => p.id === values.promotionPlan);
if (selectedPlan) {
setSelectedPromotion(selectedPlan);
let postId = currentPublishingPostId;
// 如果还没有创建帖子,先创建帖子
if (!postId) {
const postData = {
title: values.title,
content: values.content,
summary: values.summary,
tags: Array.isArray(values.tags) ? values.tags.join(',') : values.tags,
coverImage: coverImageUrl || undefined
// 注意:这里不包含promotionPlan,等支付成功后再更新
};
const publishResponse = await publishPost(postData);
if (publishResponse.code === 200) {
postId = publishResponse.data?.postId;
if (postId) {
setCurrentPublishingPostId(postId); // 保存已创建的帖子ID
} else {
message.error('帖子发布成功但无法获取帖子ID');
return;
}
} else {
message.error(publishResponse.msg || '帖子发布失败');
return;
}
}
// 使用帖子ID创建支付记录
if (postId) {
const paymentResponse = await createPayment({
postId: postId,
planId: selectedPlan.id,
amount: selectedPlan.price
});
if (paymentResponse.code === 200) {
setCurrentPayment(paymentResponse.data);
setPaymentModalVisible(true);
return;
} else {
message.error(paymentResponse.msg || '创建支付记录失败');
return;
}
}
} else {
message.error('无效的推广计划');
return;
}
}
// 直接发布帖子(没有选择推广)
await submitPost(values);
} catch (error) {
message.error('发布帖子失败');
}
};
const submitPost = async (values: PostFormData) => {
try {
// 处理标签格式
const tagsString = Array.isArray(values.tags) ? values.tags.join(',') : values.tags;
// 如果有选择的推广计划,使用推广计划ID,否则使用表单中的值
const promotionPlanId = selectedPromotion?.id || values.promotionPlan;
const postData = {
title: values.title,
content: values.content,
summary: values.summary,
tags: tagsString,
promotionPlan: promotionPlanId,
coverImage: coverImageUrl || undefined
};
const response = await publishPost(postData);
if (response.code === 200) {
message.success('帖子发布成功');
setPublishModalVisible(false);
form.resetFields();
setSelectedPromotion(null);
setCoverImageUrl('');
fetchMyPosts();
} else {
message.error(response.msg || '发布帖子失败');
}
} catch (error) {
message.error('发布帖子失败');
}
};
const handleEditPost = async (post: API.Post.PostInfo) => {
setCurrentEditPost(post);
const tagsArray = post.tags ? (typeof post.tags === 'string' ? post.tags.split(',') : post.tags) : [];
// 检查推广状态
try {
const promotionResponse = await getPromotionStatus(post.postId || post.id || 0);
if (promotionResponse.code === 200) {
const { hasPromotion, promotionPlanId } = promotionResponse.data;
setIsEditingPromotion(hasPromotion);
editForm.setFieldsValue({
title: post.title,
content: post.content,
summary: post.summary,
tags: tagsArray,
promotionPlan: hasPromotion ? promotionPlanId : undefined
});
}
} catch (error) {
console.error('获取推广状态失败:', error);
editForm.setFieldsValue({
title: post.title,
content: post.content,
summary: post.summary,
tags: tagsArray,
promotionPlan: post.promotionPlanId
});
}
setEditCoverImageUrl(post.coverImage || '');
setEditModalVisible(true);
};
const handleUpdatePost = async (values: any) => {
if (!currentEditPost) return;
try {
// 处理标签格式
const tagsString = Array.isArray(values.tags) ? values.tags.join(',') : values.tags;
// 检查是否选择了新的推广计划
const hasNewPromotion = values.promotionPlan && !isEditingPromotion;
if (hasNewPromotion) {
// 如果选择了新的推广计划,需要先创建支付记录
const selectedPlan = promotionPlans.find(p => p.id === values.promotionPlan);
if (selectedPlan) {
setSelectedPromotion(selectedPlan);
// 创建支付记录
const paymentResponse = await createPayment({
postId: currentEditPost.postId || currentEditPost.id || 0,
planId: selectedPlan.id,
amount: selectedPlan.price
});
if (paymentResponse.code === 200) {
setCurrentPayment(paymentResponse.data);
setPaymentModalVisible(true);
return; // 等待支付完成后再更新帖子
} else {
message.error(paymentResponse.msg || '创建支付记录失败');
return;
}
}
}
// 直接更新帖子(没有新推广或已有推广)
await updatePostDirectly(values, tagsString);
} catch (error) {
message.error('更新帖子失败');
}
};
const updatePostDirectly = async (values: any, tagsString: string) => {
if (!currentEditPost) return;
const updateData = {
...currentEditPost,
title: values.title,
content: values.content,
summary: values.summary,
tags: tagsString,
coverImage: editCoverImageUrl || currentEditPost.coverImage,
promotionPlanId: values.promotionPlan
};
const response = await updatePost(updateData);
if (response.code === 200) {
message.success('帖子更新成功');
setEditModalVisible(false);
editForm.resetFields();
setCurrentEditPost(null);
setEditCoverImageUrl('');
setIsEditingPromotion(false);
fetchMyPosts();
} else {
message.error(response.msg || '更新帖子失败');
}
};
const handleDeletePost = async (postId: number) => {
try {
const response = await deletePost(postId);
if (response.code === 200) {
message.success('帖子删除成功');
fetchMyPosts();
} else {
message.error(response.msg || '删除帖子失败');
}
} catch (error) {
message.error('删除帖子失败');
}
};
const handleViewPost = (postId: number) => {
navigate(`/post-detail/${postId}`);
};
const handlePaymentConfirm = async () => {
if (!currentPayment) return;
try {
const response = await confirmPayment(currentPayment.paymentId);
if (response.code === 200) {
message.success('支付成功,推广已生效');
setPaymentModalVisible(false);
setCurrentPayment(null);
// 如果是编辑模式,完成帖子更新
if (editModalVisible && currentEditPost) {
const values = editForm.getFieldsValue();
const tagsString = Array.isArray(values.tags) ? values.tags.join(',') : values.tags;
await updatePostDirectly(values, tagsString);
} else if (publishModalVisible) {
// 如果是发布模式,支付成功后关闭所有弹窗,刷新帖子列表,清空状态
setPublishModalVisible(false);
form.resetFields();
setCoverImageUrl('');
setCurrentPublishingPostId(null); // 清空已创建的帖子ID
fetchMyPosts();
}
setSelectedPromotion(null);
} else {
message.error(response.msg || '支付确认失败');
}
} catch (error) {
message.error('支付确认失败');
}
};
const handlePaymentCancel = async () => {
if (!currentPayment) return;
try {
await cancelPayment(currentPayment.paymentId);
message.info('支付已取消');
setPaymentModalVisible(false);
setCurrentPayment(null);
setSelectedPromotion(null);
// 如果是发布模式,支付取消后返回发布页面(不关闭发布弹窗)
// 保持currentPublishingPostId,用户可以重新支付
// 如果是编辑模式,关闭编辑弹窗
if (editModalVisible) {
setEditModalVisible(false);
editForm.resetFields();
setCurrentEditPost(null);
setEditCoverImageUrl('');
setIsEditingPromotion(false);
}
} catch (error) {
console.error('取消支付失败:', error);
setPaymentModalVisible(false);
setCurrentPayment(null);
setSelectedPromotion(null);
}
};
const handleImageUpload = async (file: any) => {
setUploadLoading(true);
try {
const formData = new FormData();
formData.append('file', file);
const response = await uploadImage(formData);
if (response.code === 200 && response.data) {
setCoverImageUrl(response.data.url);
message.success('图片上传成功');
return false; // 阻止自动上传
} else {
message.error(response.msg || '图片上传失败');
}
} catch (error) {
message.error('图片上传失败');
} finally {
setUploadLoading(false);
}
return false;
};
const handleDeleteImage = async () => {
if (coverImageUrl) {
try {
const filename = coverImageUrl.split('/').pop();
if (filename) {
await deleteImage(filename);
}
setCoverImageUrl('');
message.success('图片删除成功');
} catch (error) {
message.error('图片删除失败');
}
}
};
const handleCancelPublish = async () => {
// 如果有已创建的帖子但还没有支付成功,需要删除这个帖子
if (currentPublishingPostId) {
try {
await deletePost(currentPublishingPostId);
message.info('已取消发布并删除草稿帖子');
} catch (error) {
console.error('删除草稿帖子失败:', error);
message.warning('取消发布成功,但删除草稿帖子失败');
}
}
// 如果有上传的图片但没有发布帖子,删除图片
if (coverImageUrl) {
try {
const filename = coverImageUrl.split('/').pop();
if (filename) {
await deleteImage(filename);
}
} catch (error) {
console.error('删除图片失败:', error);
}
}
setPublishModalVisible(false);
form.resetFields();
setSelectedPromotion(null);
setCoverImageUrl('');
setCurrentPublishingPostId(null); // 清空已创建的帖子ID
};
const uploadButton = (
<div>
{uploadLoading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>上传封面</div>
</div>
);
const handleEditImageUpload = async (file: any) => {
setEditUploadLoading(true);
try {
const formData = new FormData();
formData.append('file', file);
const response = await uploadImage(formData);
if (response.code === 200 && response.data) {
// 如果有旧图片,删除它
if (editCoverImageUrl) {
const oldFilename = editCoverImageUrl.split('/').pop();
if (oldFilename) {
await deleteImage(oldFilename);
}
}
setEditCoverImageUrl(response.data.url);
message.success('图片上传成功');
return false;
} else {
message.error(response.msg || '图片上传失败');
}
} catch (error) {
message.error('图片上传失败');
} finally {
setEditUploadLoading(false);
}
return false;
};
const handleDeleteEditImage = async () => {
if (editCoverImageUrl) {
try {
const filename = editCoverImageUrl.split('/').pop();
if (filename) {
await deleteImage(filename);
}
setEditCoverImageUrl('');
message.success('图片删除成功');
} catch (error) {
message.error('图片删除失败');
}
}
};
const editUploadButton = (
<div>
{editUploadLoading ? <LoadingOutlined /> : <PlusOutlined />}
<div style={{ marginTop: 8 }}>上传封面</div>
</div>
);
const myPostsColumns = [
{
title: '标题',
dataIndex: 'title',
key: 'title',
render: (text: string, record: API.Post.PostInfo) => (
<a onClick={() => handleViewPost(record.postId || record.id || 0)}>{text}</a>
),
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
render: (status: string) => {
const statusMap: Record<string, { color: string; text: string }> = {
'0': { color: 'orange', text: '待审核' },
'1': { color: 'green', text: '已发布' },
'2': { color: 'red', text: '已拒绝' },
'3': { color: 'gray', text: '已下架' }
};
const statusInfo = statusMap[status] || { color: 'gray', text: '未知' };
return <Tag color={statusInfo.color}>{statusInfo.text}</Tag>;
},
},
{
title: '浏览量',
dataIndex: 'views',
key: 'views',
},
{
title: '评论数',
dataIndex: 'comments',
key: 'comments',
},
{
title: '收藏数',
dataIndex: 'favorites',
key: 'favorites',
},
{
title: '点赞数',
dataIndex: 'likes',
key: 'likes',
},
{
title: '发布时间',
dataIndex: 'publishTime',
key: 'publishTime',
},
{
title: '操作',
key: 'action',
render: (text: any, record: API.Post.PostInfo) => (
<Space size="middle">
<Button
type="link"
icon={<EyeOutlined />}
onClick={() => handleViewPost(record.postId || record.id || 0)}
>
查看
</Button>
<Button
type="link"
icon={<EditOutlined />}
onClick={() => handleEditPost(record)}
>
编辑
</Button>
<Popconfirm
title="确定要删除这篇帖子吗?"
onConfirm={() => handleDeletePost(record.postId || record.id || 0)}
okText="确定"
cancelText="取消"
>
<Button type="link" danger icon={<DeleteOutlined />}>
删除
</Button>
</Popconfirm>
</Space>
),
},
];
return (
<div className={styles.userCenterContainer}>
<Card title="个人中心" className={styles.userCenterCard}>
<Tabs activeKey={activeTab} onChange={setActiveTab}>
<TabPane tab="我的帖子" key="myPosts">
<div className={styles.tabContent}>
<div className={styles.tabHeader}>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => setPublishModalVisible(true)}
>
发布新帖子
</Button>
</div>
<Table
columns={myPostsColumns}
dataSource={myPosts}
loading={loading}
rowKey="id"
pagination={{
pageSize: 10,
showTotal: (total) => `共 ${total} 条记录`,
}}
/>
</div>
</TabPane>
<TabPane tab="我的收藏" key="favorites">
<div className={styles.tabContent}>
<Row gutter={[24, 24]}>
{favorites.map((post: any) => {
// 确保post对象有正确的id字段
const formattedPost = {
...post,
id: post.postId || post.id,
tags: post.tags ? (Array.isArray(post.tags) ? post.tags : post.tags.split(',')) : []
};
return (
<Col xs={24} sm={12} md={8} key={formattedPost.id}>
<PostCard post={formattedPost} />
</Col>
);
})}
</Row>
{favorites.length === 0 && !loading && (
<div className={styles.emptyState}>
<HeartOutlined style={{ fontSize: 48, color: '#ccc' }} />
<p>暂无收藏的帖子</p>
</div>
)}
</div>
</TabPane>
</Tabs>
</Card>
{/* 发布帖子弹窗 */}
<Modal
title="发布新帖子"
open={publishModalVisible}
onCancel={handleCancelPublish}
footer={null}
width={800}
>
<Form
form={form}
layout="vertical"
onFinish={handlePublishPost}
>
<Form.Item
name="title"
label="帖子标题"
rules={[{ required: true, message: '请输入帖子标题' }]}
>
<Input placeholder="请输入帖子标题" />
</Form.Item>
<Form.Item
name="summary"
label="帖子摘要"
rules={[{ required: true, message: '请输入帖子摘要' }]}
>
<TextArea rows={3} placeholder="请输入帖子摘要" />
</Form.Item>
<Form.Item
name="content"
label="帖子内容"
rules={[{ required: true, message: '请输入帖子内容' }]}
>
<TextArea rows={8} placeholder="请输入帖子内容" />
</Form.Item>
<Form.Item
name="coverImage"
label="封面图片(可选)"
>
<Upload
listType="picture-card"
showUploadList={false}
beforeUpload={handleImageUpload}
>
{coverImageUrl ? (
<Image
src={coverImageUrl}
alt="封面"
width="100%"
height="100%"
style={{ objectFit: 'cover' }}
/>
) : (
uploadButton
)}
</Upload>
{coverImageUrl && (
<Button
type="link"
onClick={handleDeleteImage}
style={{ padding: 0, marginTop: 8 }}
>
删除图片
</Button>
)}
</Form.Item>
<Form.Item
name="tags"
label="标签"
rules={[{ required: true, message: '请选择标签' }]}
>
<Select
mode="multiple"
placeholder="请选择标签"
allowClear
style={{ width: '100%' }}
>
{availableTags.map(tag => (
<Select.Option key={tag.tagId} value={tag.tagName}>
<Tag color={tag.tagColor}>{tag.tagName}</Tag>
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="promotionPlan"
label="推广选项(可选)"
>
<Radio.Group>
<Space direction="vertical">
<Radio value={undefined}>不选择推广</Radio>
{promotionPlans.map(plan => (
<Radio key={plan.id} value={plan.id}>
<div>
<strong>{plan.name}</strong> - ¥{plan.price} ({plan.duration}天)
<br />
<span style={{ color: '#666', fontSize: '12px' }}>
{plan.description}
</span>
</div>
</Radio>
))}
</Space>
</Radio.Group>
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
{selectedPromotion ? '选择支付方式' : '发布帖子'}
</Button>
<Button onClick={handleCancelPublish}>
取消
</Button>
</Space>
</Form.Item>
</Form>
</Modal>
{/* 编辑帖子弹窗 */}
<Modal
title="编辑帖子"
open={editModalVisible}
onCancel={() => {
setEditModalVisible(false);
editForm.resetFields();
setCurrentEditPost(null);
setEditCoverImageUrl('');
setIsEditingPromotion(false);
}}
footer={null}
width={800}
>
<Form
form={editForm}
layout="vertical"
onFinish={handleUpdatePost}
>
<Form.Item
name="title"
label="帖子标题"
rules={[{ required: true, message: '请输入帖子标题' }]}
>
<Input placeholder="请输入帖子标题" />
</Form.Item>
<Form.Item
name="summary"
label="帖子摘要"
rules={[{ required: true, message: '请输入帖子摘要' }]}
>
<TextArea rows={3} placeholder="请输入帖子摘要" />
</Form.Item>
<Form.Item
name="content"
label="帖子内容"
rules={[{ required: true, message: '请输入帖子内容' }]}
>
<TextArea rows={8} placeholder="请输入帖子内容" />
</Form.Item>
<Form.Item
name="coverImage"
label="封面图片"
>
<Upload
listType="picture-card"
showUploadList={false}
beforeUpload={handleEditImageUpload}
>
{editCoverImageUrl ? (
<Image
src={editCoverImageUrl}
alt="封面"
width="100%"
height="100%"
style={{ objectFit: 'cover' }}
/>
) : (
editUploadButton
)}
</Upload>
{editCoverImageUrl && (
<Button
type="link"
onClick={handleDeleteEditImage}
style={{ padding: 0, marginTop: 8 }}
>
删除图片
</Button>
)}
</Form.Item>
<Form.Item
name="tags"
label="标签"
rules={[{ required: true, message: '请选择标签' }]}
>
<Select
mode="multiple"
placeholder="请选择标签"
allowClear
style={{ width: '100%' }}
>
{availableTags.map(tag => (
<Select.Option key={tag.tagId} value={tag.tagName}>
<Tag color={tag.tagColor}>{tag.tagName}</Tag>
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name="promotionPlan"
label="推广选项(可选)"
>
<Radio.Group disabled={isEditingPromotion}>
<Space direction="vertical">
<Radio value={undefined}>不选择推广</Radio>
{isEditingPromotion && (
<div style={{ color: '#ff4d4f', fontSize: '12px', marginBottom: 8 }}>
该帖子已购买推广,无法更改推广选项
</div>
)}
{promotionPlans.map(plan => (
<Radio key={plan.id} value={plan.id} disabled={isEditingPromotion}>
<div>
<strong>{plan.name}</strong> - ¥{plan.price} ({plan.duration}天)
<br />
<span style={{ color: '#666', fontSize: '12px' }}>
{plan.description}
</span>
</div>
</Radio>
))}
</Space>
</Radio.Group>
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
更新帖子
</Button>
<Button onClick={() => {
setEditModalVisible(false);
editForm.resetFields();
setCurrentEditPost(null);
setEditCoverImageUrl('');
setIsEditingPromotion(false);
}}>
取消
</Button>
</Space>
</Form.Item>
</Form>
</Modal>
{/* 支付弹窗 */}
<Modal
title="支付推广费用"
open={paymentModalVisible}
onCancel={handlePaymentCancel}
footer={null}
width={400}
>
<div className={styles.paymentModal}>
{selectedPromotion && (
<>
<div className={styles.paymentInfo}>
<h3>{selectedPromotion.name}</h3>
<p>{selectedPromotion.description}</p>
<p>费用: <strong>¥{selectedPromotion.price}</strong></p>
<p>时长: {selectedPromotion.duration}天</p>
</div>
<div className={styles.qrCode}>
<div className={styles.qrCodePlaceholder}>
<p>支付二维码</p>
<p style={{ fontSize: '12px', color: '#666' }}>
请使用支付宝扫描二维码支付
</p>
<div className={styles.mockQrCode}>
<p>模拟二维码</p>
<p>¥{selectedPromotion.price}</p>
</div>
</div>
</div>
<div className={styles.paymentActions}>
<Button
type="primary"
onClick={handlePaymentConfirm}
style={{ width: '100%', marginBottom: 8 }}
>
我已完成支付
</Button>
<Button
onClick={handlePaymentCancel}
style={{ width: '100%' }}
>
取消支付
</Button>
</div>
</>
)}
</div>
</Modal>
</div>
);
};
export default UserCenter;