update pay function

This commit is contained in:
2025-11-23 18:11:48 +08:00
parent 05a2f62a42
commit fe47d3dcc6
9 changed files with 3229 additions and 91 deletions

View File

@@ -0,0 +1,386 @@
/**
* 创建预测话题模态框
* 用户可以发起新的预测市场话题
*/
import React, { useState } from 'react';
import {
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
ModalCloseButton,
Button,
VStack,
FormControl,
FormLabel,
Input,
Textarea,
Select,
HStack,
Text,
Box,
Icon,
Alert,
AlertIcon,
useToast,
} from '@chakra-ui/react';
import { Zap, Calendar, DollarSign } from 'lucide-react';
import { forumColors } from '@theme/forumTheme';
import { createTopic } from '@services/predictionMarketService';
import { getUserAccount, CREDIT_CONFIG } from '@services/creditSystemService';
import { useAuth } from '@contexts/AuthContext';
const CreatePredictionModal = ({ isOpen, onClose, onTopicCreated }) => {
const toast = useToast();
const { user } = useAuth();
// 表单状态
const [formData, setFormData] = useState({
title: '',
description: '',
category: 'stock',
deadline_days: 7,
});
const [isSubmitting, setIsSubmitting] = useState(false);
// 获取用户余额
const userAccount = user ? getUserAccount(user.id) : null;
// 处理表单变化
const handleChange = (field, value) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};
// 提交表单
const handleSubmit = async () => {
try {
setIsSubmitting(true);
// 验证
if (!formData.title.trim()) {
toast({
title: '请填写话题标题',
status: 'warning',
duration: 3000,
});
return;
}
if (!formData.description.trim()) {
toast({
title: '请填写话题描述',
status: 'warning',
duration: 3000,
});
return;
}
// 检查余额
if (userAccount.balance < CREDIT_CONFIG.CREATE_TOPIC_COST) {
toast({
title: '积分不足',
description: `创建话题需要${CREDIT_CONFIG.CREATE_TOPIC_COST}积分`,
status: 'error',
duration: 3000,
});
return;
}
// 计算截止时间
const deadline = new Date();
deadline.setDate(deadline.getDate() + parseInt(formData.deadline_days));
const settlement_date = new Date(deadline);
settlement_date.setDate(settlement_date.getDate() + 1);
// 创建话题
const newTopic = createTopic({
author_id: user.id,
author_name: user.name || user.username,
author_avatar: user.avatar,
title: formData.title,
description: formData.description,
category: formData.category,
deadline: deadline.toISOString(),
settlement_date: settlement_date.toISOString(),
});
toast({
title: '创建成功!',
description: `话题已发布,扣除${CREDIT_CONFIG.CREATE_TOPIC_COST}积分`,
status: 'success',
duration: 3000,
});
// 重置表单
setFormData({
title: '',
description: '',
category: 'stock',
deadline_days: 7,
});
// 通知父组件
if (onTopicCreated) {
onTopicCreated(newTopic);
}
onClose();
} catch (error) {
console.error('创建话题失败:', error);
toast({
title: '创建失败',
description: error.message,
status: 'error',
duration: 3000,
});
} finally {
setIsSubmitting(false);
}
};
return (
<Modal isOpen={isOpen} onClose={onClose} size="xl" isCentered>
<ModalOverlay backdropFilter="blur(4px)" />
<ModalContent
bg={forumColors.background.card}
borderRadius="xl"
border="1px solid"
borderColor={forumColors.border.default}
>
<ModalHeader
bg={forumColors.gradients.goldSubtle}
borderTopRadius="xl"
borderBottom="1px solid"
borderColor={forumColors.border.default}
>
<HStack spacing="2">
<Icon as={Zap} boxSize="20px" color={forumColors.primary[500]} />
<Text color={forumColors.text.primary}>发起预测话题</Text>
</HStack>
</ModalHeader>
<ModalCloseButton color={forumColors.text.primary} />
<ModalBody py="6">
<VStack spacing="5" align="stretch">
{/* 提示信息 */}
<Alert
status="info"
bg={forumColors.background.hover}
borderRadius="lg"
border="1px solid"
borderColor={forumColors.border.default}
>
<AlertIcon color={forumColors.primary[500]} />
<VStack align="start" spacing="1" flex="1">
<Text fontSize="sm" color={forumColors.text.primary} fontWeight="600">
创建预测话题
</Text>
<Text fontSize="xs" color={forumColors.text.secondary}>
创建费用{CREDIT_CONFIG.CREATE_TOPIC_COST}积分进入奖池
</Text>
<Text fontSize="xs" color={forumColors.text.secondary}>
作者不能参与自己发起的话题
</Text>
<Text fontSize="xs" color={forumColors.text.secondary}>
截止后由作者提交结果进行结算
</Text>
</VStack>
</Alert>
{/* 话题标题 */}
<FormControl isRequired>
<FormLabel fontSize="sm" color={forumColors.text.primary}>
话题标题
</FormLabel>
<Input
placeholder="例如:贵州茅台下周会涨吗?"
value={formData.title}
onChange={(e) => handleChange('title', e.target.value)}
bg={forumColors.background.main}
border="1px solid"
borderColor={forumColors.border.default}
color={forumColors.text.primary}
_placeholder={{ color: forumColors.text.tertiary }}
_hover={{ borderColor: forumColors.border.light }}
_focus={{
borderColor: forumColors.border.gold,
boxShadow: `0 0 0 1px ${forumColors.border.goldGlow}`,
}}
/>
</FormControl>
{/* 话题描述 */}
<FormControl isRequired>
<FormLabel fontSize="sm" color={forumColors.text.primary}>
话题描述
</FormLabel>
<Textarea
placeholder="详细描述预测的内容、判断标准、数据来源等..."
value={formData.description}
onChange={(e) => handleChange('description', e.target.value)}
rows={4}
bg={forumColors.background.main}
border="1px solid"
borderColor={forumColors.border.default}
color={forumColors.text.primary}
_placeholder={{ color: forumColors.text.tertiary }}
_hover={{ borderColor: forumColors.border.light }}
_focus={{
borderColor: forumColors.border.gold,
boxShadow: `0 0 0 1px ${forumColors.border.goldGlow}`,
}}
/>
</FormControl>
{/* 分类 */}
<FormControl>
<FormLabel fontSize="sm" color={forumColors.text.primary}>
分类
</FormLabel>
<Select
value={formData.category}
onChange={(e) => handleChange('category', e.target.value)}
bg={forumColors.background.main}
border="1px solid"
borderColor={forumColors.border.default}
color={forumColors.text.primary}
_hover={{ borderColor: forumColors.border.light }}
_focus={{
borderColor: forumColors.border.gold,
boxShadow: `0 0 0 1px ${forumColors.border.goldGlow}`,
}}
>
<option value="stock">股票行情</option>
<option value="index">指数走势</option>
<option value="concept">概念板块</option>
<option value="policy">政策影响</option>
<option value="event">事件预测</option>
<option value="other">其他</option>
</Select>
</FormControl>
{/* 截止时间 */}
<FormControl>
<FormLabel fontSize="sm" color={forumColors.text.primary}>
<HStack spacing="2">
<Icon as={Calendar} boxSize="16px" />
<Text>交易截止时间</Text>
</HStack>
</FormLabel>
<Select
value={formData.deadline_days}
onChange={(e) => handleChange('deadline_days', e.target.value)}
bg={forumColors.background.main}
border="1px solid"
borderColor={forumColors.border.default}
color={forumColors.text.primary}
_hover={{ borderColor: forumColors.border.light }}
_focus={{
borderColor: forumColors.border.gold,
boxShadow: `0 0 0 1px ${forumColors.border.goldGlow}`,
}}
>
<option value="1">1天后</option>
<option value="3">3天后</option>
<option value="7">7天后推荐</option>
<option value="14">14天后</option>
<option value="30">30天后</option>
</Select>
<Text fontSize="xs" color={forumColors.text.tertiary} mt="2">
截止后次日可提交结果进行结算
</Text>
</FormControl>
{/* 费用说明 */}
<Box
bg={forumColors.gradients.goldSubtle}
border="1px solid"
borderColor={forumColors.border.gold}
borderRadius="lg"
p="4"
>
<HStack justify="space-between">
<VStack align="start" spacing="1">
<Text fontSize="sm" fontWeight="600" color={forumColors.text.primary}>
创建费用
</Text>
<Text fontSize="xs" color={forumColors.text.secondary}>
将进入奖池奖励给获胜者
</Text>
</VStack>
<HStack spacing="1">
<Icon as={DollarSign} boxSize="20px" color={forumColors.primary[500]} />
<Text fontSize="2xl" fontWeight="bold" color={forumColors.primary[500]}>
{CREDIT_CONFIG.CREATE_TOPIC_COST}
</Text>
<Text fontSize="sm" color={forumColors.text.secondary}>
积分
</Text>
</HStack>
</HStack>
<Box mt="3" pt="3" borderTop="1px solid" borderColor={forumColors.border.default}>
<HStack justify="space-between" fontSize="sm">
<Text color={forumColors.text.secondary}>你的余额</Text>
<Text fontWeight="600" color={forumColors.text.primary}>
{userAccount?.balance || 0} 积分
</Text>
</HStack>
<HStack justify="space-between" fontSize="sm" mt="1">
<Text color={forumColors.text.secondary}>创建后</Text>
<Text
fontWeight="600"
color={
(userAccount?.balance || 0) >= CREDIT_CONFIG.CREATE_TOPIC_COST
? forumColors.success[500]
: forumColors.error[500]
}
>
{(userAccount?.balance || 0) - CREDIT_CONFIG.CREATE_TOPIC_COST} 积分
</Text>
</HStack>
</Box>
</Box>
</VStack>
</ModalBody>
<ModalFooter borderTop="1px solid" borderColor={forumColors.border.default}>
<HStack spacing="3">
<Button
variant="ghost"
onClick={onClose}
color={forumColors.text.secondary}
_hover={{ bg: forumColors.background.hover }}
>
取消
</Button>
<Button
bg={forumColors.gradients.goldPrimary}
color={forumColors.background.main}
fontWeight="bold"
onClick={handleSubmit}
isLoading={isSubmitting}
loadingText="创建中..."
isDisabled={(userAccount?.balance || 0) < CREDIT_CONFIG.CREATE_TOPIC_COST}
_hover={{
opacity: 0.9,
transform: 'translateY(-2px)',
}}
_active={{ transform: 'translateY(0)' }}
>
发布话题
</Button>
</HStack>
</ModalFooter>
</ModalContent>
</Modal>
);
};
export default CreatePredictionModal;