diff --git a/src/components/ImageLightbox/index.js b/src/components/ImageLightbox/index.js new file mode 100644 index 00000000..13811a8e --- /dev/null +++ b/src/components/ImageLightbox/index.js @@ -0,0 +1,309 @@ +/** + * 图片灯箱组件 + * 点击图片放大查看 + */ + +import React, { useState } from 'react'; +import { + Modal, + ModalOverlay, + ModalContent, + ModalBody, + ModalCloseButton, + Image, + Box, + IconButton, + HStack, + useDisclosure, +} from '@chakra-ui/react'; +import { ChevronLeft, ChevronRight, X, ZoomIn } from 'lucide-react'; +import { motion, AnimatePresence } from 'framer-motion'; + +const MotionBox = motion(Box); + +/** + * 单图片灯箱 + */ +export const ImageLightbox = ({ src, alt, ...props }) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + <> + {/* 缩略图 */} + + {alt} + + {/* 放大图标 */} + + + + + + + + {/* 灯箱模态框 */} + + + + + + + {alt} + + + + + + ); +}; + +/** + * 多图片轮播灯箱 + */ +export const ImageGalleryLightbox = ({ images, initialIndex = 0, ...props }) => { + const { isOpen, onOpen, onClose } = useDisclosure(); + const [currentIndex, setCurrentIndex] = useState(initialIndex); + + const handleOpen = (index) => { + setCurrentIndex(index); + onOpen(); + }; + + const handlePrev = () => { + setCurrentIndex((prev) => (prev === 0 ? images.length - 1 : prev - 1)); + }; + + const handleNext = () => { + setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1)); + }; + + const handleKeyDown = (e) => { + if (e.key === 'ArrowLeft') handlePrev(); + if (e.key === 'ArrowRight') handleNext(); + if (e.key === 'Escape') onClose(); + }; + + return ( + <> + {/* 缩略图网格 */} + + {images.map((image, index) => ( + handleOpen(index)} + _hover={{ + '& .zoom-icon': { + opacity: 1, + }, + }} + > + {image.alt + + {/* 放大图标 */} + + + + + + + ))} + + + {/* 灯箱模态框(带轮播) */} + + + + {/* 关闭按钮 */} + } + position="fixed" + top="4" + right="4" + size="lg" + color="white" + bg="blackAlpha.600" + _hover={{ bg: 'blackAlpha.800' }} + borderRadius="full" + zIndex={2} + onClick={onClose} + /> + + + {/* 左箭头 */} + {images.length > 1 && ( + } + position="absolute" + left="4" + top="50%" + transform="translateY(-50%)" + size="lg" + color="white" + bg="blackAlpha.600" + _hover={{ bg: 'blackAlpha.800' }} + borderRadius="full" + zIndex={2} + onClick={handlePrev} + /> + )} + + {/* 图片 */} + + + {images[currentIndex].alt + + + + {/* 右箭头 */} + {images.length > 1 && ( + } + position="absolute" + right="4" + top="50%" + transform="translateY(-50%)" + size="lg" + color="white" + bg="blackAlpha.600" + _hover={{ bg: 'blackAlpha.800' }} + borderRadius="full" + zIndex={2} + onClick={handleNext} + /> + )} + + {/* 图片计数 */} + {images.length > 1 && ( + + {currentIndex + 1} / {images.length} + + )} + + + + + ); +}; + +export default ImageLightbox; diff --git a/src/index.js b/src/index.js index 0c8db5ae..9c520b75 100755 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,9 @@ import { BrowserRouter as Router } from 'react-router-dom'; // 导入 Brainwave 样式(空文件,保留以避免错误) import './styles/brainwave.css'; +// 导入 Select 下拉框颜色修复样式 +import './styles/select-fix.css'; + // 导入 Bytedesk 客服系统 z-index 覆盖样式(必须在所有样式之后导入) import './styles/bytedesk-override.css'; diff --git a/src/styles/select-fix.css b/src/styles/select-fix.css new file mode 100644 index 00000000..be912986 --- /dev/null +++ b/src/styles/select-fix.css @@ -0,0 +1,89 @@ +/** + * 修复 Chakra UI Select 组件的下拉选项颜色问题 + * 黑金主题下,下拉选项需要深色背景和白色文字 + */ + +/* 所有 select 元素的 option 样式 */ +select option { + background-color: #1A1A1A !important; /* 深色背景 */ + color: #FFFFFF !important; /* 白色文字 */ + padding: 8px !important; +} + +/* 选中的 option */ +select option:checked { + background-color: #2A2A2A !important; + color: #FFC107 !important; /* 金色高亮 */ +} + +/* hover 状态的 option (某些浏览器支持) */ +select option:hover { + background-color: #222222 !important; + color: #FFD700 !important; +} + +/* 禁用的 option */ +select option:disabled { + color: #808080 !important; + background-color: #151515 !important; +} + +/* Firefox 特殊处理 */ +@-moz-document url-prefix() { + select option { + background-color: #1A1A1A !important; + color: #FFFFFF !important; + } +} + +/* Webkit/Chrome 特殊处理 */ +select { + /* 自定义下拉箭头颜色 */ + color-scheme: dark; +} + +/* 修复 Chakra UI Select 组件的特定样式 */ +.chakra-select { + background-color: #1A1A1A !important; + color: #FFFFFF !important; + border-color: #333333 !important; +} + +.chakra-select:hover { + border-color: #404040 !important; +} + +.chakra-select:focus { + border-color: #FFC107 !important; + box-shadow: 0 0 0 1px rgba(255, 193, 7, 0.3) !important; +} + +/* 下拉箭头图标 */ +.chakra-select__icon-wrapper { + color: #FFFFFF !important; +} + +/* 修复所有表单 select 元素 */ +select[class*="chakra-select"], +select[class*="select"] { + background-color: #1A1A1A !important; + color: #FFFFFF !important; +} + +/* 自定义滚动条 (适用于下拉列表) */ +select::-webkit-scrollbar { + width: 8px; +} + +select::-webkit-scrollbar-track { + background: #0A0A0A; +} + +select::-webkit-scrollbar-thumb { + background: #333333; + border-radius: 4px; +} + +select::-webkit-scrollbar-thumb:hover { + background: #FFC107; +} diff --git a/src/theme/forumTheme.js b/src/theme/forumTheme.js index 269da961..9b4cd366 100644 --- a/src/theme/forumTheme.js +++ b/src/theme/forumTheme.js @@ -217,6 +217,32 @@ export const forumComponentStyles = { }, }, + // Select下拉框样式(修复白色文字问题) + Select: { + baseStyle: { + field: { + bg: forumColors.background.card, + color: forumColors.text.primary, + borderColor: forumColors.border.default, + _hover: { + borderColor: forumColors.border.light, + }, + _focus: { + borderColor: forumColors.border.gold, + boxShadow: `0 0 0 1px ${forumColors.border.goldGlow}`, + }, + // 修复下拉选项颜色 + option: { + bg: forumColors.background.card, + color: forumColors.text.primary, + }, + }, + icon: { + color: forumColors.text.primary, + }, + }, + }, + // 标签样式 Tag: { variants: { diff --git a/verify-prediction-market.js b/verify-prediction-market.js new file mode 100644 index 00000000..de9394cc --- /dev/null +++ b/verify-prediction-market.js @@ -0,0 +1,184 @@ +/** + * 预测市场功能验证脚本 + * 检查所有必需的文件和配置是否正确 + */ + +const fs = require('fs'); +const path = require('path'); + +console.log('🔍 开始验证预测市场功能...\n'); + +let errors = 0; +let warnings = 0; + +// 颜色输出 +const colors = { + green: '\x1b[32m', + red: '\x1b[31m', + yellow: '\x1b[33m', + blue: '\x1b[34m', + reset: '\x1b[0m', +}; + +function success(msg) { + console.log(`${colors.green}✅ ${msg}${colors.reset}`); +} + +function error(msg) { + console.log(`${colors.red}❌ ${msg}${colors.reset}`); + errors++; +} + +function warning(msg) { + console.log(`${colors.yellow}⚠️ ${msg}${colors.reset}`); + warnings++; +} + +function info(msg) { + console.log(`${colors.blue}ℹ️ ${msg}${colors.reset}`); +} + +// 1. 检查必需文件 +console.log('📂 检查文件结构...\n'); + +const requiredFiles = [ + 'src/services/creditSystemService.js', + 'src/services/predictionMarketService.js', + 'src/views/ValueForum/index.js', + 'src/views/ValueForum/PredictionTopicDetail.js', + 'src/views/ValueForum/components/PredictionTopicCard.js', + 'src/views/ValueForum/components/CreatePredictionModal.js', + 'src/views/ValueForum/components/TradeModal.js', + 'src/theme/forumTheme.js', + 'src/routes/lazy-components.js', + 'src/routes/routeConfig.js', +]; + +requiredFiles.forEach(file => { + const fullPath = path.join(__dirname, file); + if (fs.existsSync(fullPath)) { + success(`${file}`); + } else { + error(`文件不存在: ${file}`); + } +}); + +// 2. 检查主题文件 +console.log('\n🎨 检查主题配置...\n'); + +const themeFile = path.join(__dirname, 'src/theme/forumTheme.js'); +if (fs.existsSync(themeFile)) { + const content = fs.readFileSync(themeFile, 'utf8'); + + const requiredColors = ['success:', 'error:', 'warning:', 'info:', 'primary:']; + requiredColors.forEach(color => { + if (content.includes(color)) { + success(`主题包含 ${color} 定义`); + } else { + error(`主题缺少 ${color} 定义`); + } + }); + + // 检查具体的颜色值 + if (content.includes('500: \'#4CAF50\'') || content.includes('500: "#4CAF50"')) { + success('success[500] 颜色已定义'); + } else { + error('success[500] 颜色缺失'); + } + + if (content.includes('500: \'#F44336\'') || content.includes('500: "#F44336"')) { + success('error[500] 颜色已定义'); + } else { + error('error[500] 颜色缺失'); + } +} + +// 3. 检查路由配置 +console.log('\n🛣️ 检查路由配置...\n'); + +const routeConfigFile = path.join(__dirname, 'src/routes/routeConfig.js'); +if (fs.existsSync(routeConfigFile)) { + const content = fs.readFileSync(routeConfigFile, 'utf8'); + + if (content.includes('value-forum/prediction/:topicId')) { + success('预测话题详情路由已配置'); + } else { + error('预测话题详情路由未配置'); + } +} + +const lazyComponentsFile = path.join(__dirname, 'src/routes/lazy-components.js'); +if (fs.existsSync(lazyComponentsFile)) { + const content = fs.readFileSync(lazyComponentsFile, 'utf8'); + + if (content.includes('PredictionTopicDetail')) { + success('PredictionTopicDetail 懒加载已配置'); + } else { + error('PredictionTopicDetail 懒加载未配置'); + } +} + +// 4. 检查依赖 +console.log('\n📦 检查npm依赖...\n'); + +const packageJsonFile = path.join(__dirname, 'package.json'); +if (fs.existsSync(packageJsonFile)) { + const packageJson = JSON.parse(fs.readFileSync(packageJsonFile, 'utf8')); + const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; + + const requiredDeps = [ + '@chakra-ui/react', + 'react', + 'react-router-dom', + 'framer-motion', + 'lucide-react', + ]; + + requiredDeps.forEach(dep => { + if (deps[dep]) { + success(`${dep}: ${deps[dep]}`); + } else { + error(`缺少依赖: ${dep}`); + } + }); +} + +// 5. 检查ES配置 +console.log('\n🔌 检查Elasticsearch配置...\n'); + +const esServiceFile = path.join(__dirname, 'src/services/elasticsearchService.js'); +if (fs.existsSync(esServiceFile)) { + const content = fs.readFileSync(esServiceFile, 'utf8'); + + if (content.includes('222.128.1.157:19200')) { + success('ES开发环境地址已配置: 222.128.1.157:19200'); + } else { + warning('ES地址可能已修改,请检查配置'); + } + + if (content.includes('forum_posts')) { + success('ES索引 forum_posts 已定义'); + } +} + +// 6. 输出总结 +console.log('\n' + '='.repeat(50)); +console.log(`\n📊 验证结果总结:\n`); + +if (errors === 0 && warnings === 0) { + console.log(`${colors.green}🎉 所有检查通过!预测市场功能已正确配置。${colors.reset}\n`); + console.log(`${colors.blue}👉 下一步: 运行 npm start 启动应用${colors.reset}\n`); + process.exit(0); +} else { + if (errors > 0) { + console.log(`${colors.red}❌ 发现 ${errors} 个错误${colors.reset}`); + } + if (warnings > 0) { + console.log(`${colors.yellow}⚠️ 发现 ${warnings} 个警告${colors.reset}`); + } + + console.log(`\n${colors.blue}📚 查看故障排除指南:${colors.reset}`); + console.log(` cat TROUBLESHOOTING.md\n`); + + process.exit(errors > 0 ? 1 : 0); +}