diff --git a/.env.production b/.env.production index 8c9c6644..d10ff9d9 100644 --- a/.env.production +++ b/.env.production @@ -14,8 +14,8 @@ REACT_APP_ENABLE_MOCK=false REACT_APP_ENABLE_DEBUG=false # 后端 API 地址(生产环境) -# 使用相对路径,CDN 会通过回源规则转发到后端服务器 -REACT_APP_API_URL= +# 使用单独的 API 域名,静态资源走 CDN,API 走专用域名 +REACT_APP_API_URL=https://api.valuefrontier.cn # PostHog 分析配置(生产环境) # PostHog API Key(从 PostHog 项目设置中获取) diff --git a/nginx-110.42.32.207.conf b/nginx-110.42.32.207.conf index 5790917b..0dbd9985 100644 --- a/nginx-110.42.32.207.conf +++ b/nginx-110.42.32.207.conf @@ -21,7 +21,7 @@ map $http_upgrade $connection_upgrade { # ============================================================================ server { listen 80; - server_name 110.42.32.207; + server_name api.valuefrontier.cn 110.42.32.207; # Let's Encrypt 验证 location /.well-known/acme-challenge/ { @@ -38,7 +38,7 @@ server { # ============================================================================ server { listen 443 ssl http2; - server_name 110.42.32.207; + server_name api.valuefrontier.cn 110.42.32.207; # SSL 证书配置 # 方式1: 使用 IP 证书(需要购买) @@ -50,8 +50,8 @@ server { # -keyout /etc/nginx/ssl/server.key \ # -out /etc/nginx/ssl/server.crt \ # -subj "/CN=110.42.32.207" - ssl_certificate /etc/nginx/ssl/server.crt; - ssl_certificate_key /etc/nginx/ssl/server.key; + ssl_certificate /etc/nginx/ssl/api.valuefrontier.cn/fullchain.pem; + ssl_certificate_key /etc/nginx/ssl/api.valuefrontier.cn/privkey.pem; # SSL 优化 ssl_protocols TLSv1.2 TLSv1.3; diff --git a/src/components/EventDetailPanel/RelatedConceptsSection/index.js b/src/components/EventDetailPanel/RelatedConceptsSection/index.js index f617634a..aeb6ee1f 100644 --- a/src/components/EventDetailPanel/RelatedConceptsSection/index.js +++ b/src/components/EventDetailPanel/RelatedConceptsSection/index.js @@ -21,6 +21,7 @@ import SimpleConceptCard from './SimpleConceptCard'; import DetailedConceptCard from './DetailedConceptCard'; import TradingDateInfo from './TradingDateInfo'; import { logger } from '@utils/logger'; +import { getApiBase } from '@utils/apiConfig'; /** * 相关概念区组件 @@ -109,13 +110,14 @@ const RelatedConceptsSection = ({ trade_date: formattedTradeDate }; + const apiUrl = `${getApiBase()}/concept-api/search`; console.log('[RelatedConceptsSection] 发送请求', { - url: '/concept-api/search', + url: apiUrl, requestBody }); logger.debug('RelatedConceptsSection', '搜索概念', requestBody); - const response = await fetch('/concept-api/search', { + const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/src/services/categoryService.ts b/src/services/categoryService.ts index 417c89e6..4edc9a87 100644 --- a/src/services/categoryService.ts +++ b/src/services/categoryService.ts @@ -61,7 +61,7 @@ export const fetchCategoryTree = async ( ): Promise => { try { const response = await fetch( - `/category-api/api/category-tree?source=${source}&max_depth=${maxDepth}`, + `${getApiBase()}/category-api/api/category-tree?source=${source}&max_depth=${maxDepth}`, { method: 'GET', headers: { @@ -98,7 +98,7 @@ export const fetchCategoryNode = async ( try { const encodedPath = encodeURIComponent(path); const response = await fetch( - `/category-api/api/category-tree/node?path=${encodedPath}&source=${source}&max_depth=${maxDepth}`, + `${getApiBase()}/category-api/api/category-tree/node?path=${encodedPath}&source=${source}&max_depth=${maxDepth}`, { method: 'GET', headers: { @@ -160,7 +160,7 @@ export const searchMetrics = async ( if (source) params.append('source', source); if (frequency) params.append('frequency', frequency); - const response = await fetch(`/category-api/api/search?${params.toString()}`, { + const response = await fetch(`${getApiBase()}/category-api/api/search?${params.toString()}`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -261,7 +261,7 @@ export const fetchMetricData = async ( if (startDate) params.append('start_date', startDate); if (endDate) params.append('end_date', endDate); - const response = await fetch(`/category-api/api/metric-data?${params.toString()}`, { + const response = await fetch(`${getApiBase()}/category-api/api/metric-data?${params.toString()}`, { method: 'GET', headers: { 'Content-Type': 'application/json', diff --git a/src/views/Community/components/HeroPanel.js b/src/views/Community/components/HeroPanel.js index 3c957fe0..7a1ba32c 100644 --- a/src/views/Community/components/HeroPanel.js +++ b/src/views/Community/components/HeroPanel.js @@ -28,6 +28,7 @@ import { import { AlertCircle, Clock, TrendingUp, Info, RefreshCw } from 'lucide-react'; import ReactECharts from 'echarts-for-react'; import { logger } from '@utils/logger'; +import { getApiBase } from '@utils/apiConfig'; import { useIndexQuote } from '@hooks/useIndexQuote'; // 定义动画 @@ -77,7 +78,7 @@ const fetchIndexKline = async (indexCode) => { */ const fetchPopularConcepts = async () => { try { - const response = await fetch('/concept-api/search', { + const response = await fetch(`${getApiBase()}/concept-api/search`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: '', size: 60, page: 1, sort_by: 'change_pct' }) diff --git a/src/views/EventDetail/components/RelatedConcepts.js b/src/views/EventDetail/components/RelatedConcepts.js index 34c53232..eb4c4fe4 100644 --- a/src/views/EventDetail/components/RelatedConcepts.js +++ b/src/views/EventDetail/components/RelatedConcepts.js @@ -33,6 +33,7 @@ import { FaEye, FaExternalLinkAlt, FaChartLine, FaCalendarAlt } from 'react-icon import dayjs from 'dayjs'; import tradingDayUtils from '../../../utils/tradingDayUtils'; // 引入交易日工具 import { logger } from '../../../utils/logger'; +import { getApiBase } from '../../../utils/apiConfig'; import { PROFESSIONAL_COLORS } from '../../../constants/professionalTheme'; // 增强版 ConceptCard 组件 - 展示更多数据细节 @@ -347,7 +348,7 @@ const RelatedConcepts = ({ eventTitle, eventTime, eventId, loading: externalLoad logger.debug('RelatedConcepts', '搜索概念', requestBody); - const response = await fetch('/concept-api/search', { + const response = await fetch(`${getApiBase()}/concept-api/search`, { method: 'POST', headers: { 'Content-Type': 'application/json',