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 (
+ <>
+ {/* 缩略图 */}
+
+
+
+ {/* 放大图标 */}
+
+
+
+
+
+
+
+ {/* 灯箱模态框 */}
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+/**
+ * 多图片轮播灯箱
+ */
+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,
+ },
+ }}
+ >
+
+
+ {/* 放大图标 */}
+
+
+
+
+
+
+ ))}
+
+
+ {/* 灯箱模态框(带轮播) */}
+
+
+
+ {/* 关闭按钮 */}
+ }
+ 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.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);
+}