/** * API配置文件 * 统一管理所有API地址,方便部署时修改 * 支持环境变量覆盖配置 */ // 环境配置类型 interface ApiConfig { // 主API基础URL(FastAPI后端地址,包含Dify代理) baseUrl: string; // 文档服务URL documentUrl: string; // 文档上传API URL uploadUrl: string; // Collabora Online 服务器地址 collaboraUrl: string; // 应用基础URL(用于 WOPI 回调) appUrl: string; // OAuth2.0配置 oauth: { // IDaaS服务器地址 serverUrl?: string; // OAuth2应用Client ID clientId?: string; // OAuth2应用Client Secret clientSecret?: string; // 回调地址 redirectUri?: string; // 应用ID(用于登出) appId?: string; }; // Dify 知识库检索配置 dify: { // Reranking 模型提供商 rerankingProviderName: string; // Reranking 模型名称 rerankingModelName: string; }; } // 端口特定配置映射 // 根据不同端口提供不同的API配置 const portConfigs: Record> = { // 主要 // 梅州 '51703': { // baseUrl: 'http://172.16.0.56:8073', // documentUrl: 'http://172.16.0.56:8073/docauditai/', // uploadUrl: 'http://172.16.0.56:8073/api/v2/documents', // collaboraUrl: 'http://172.16.0.81:9980', // appUrl: 'http://172.16.0.34:51703', baseUrl: 'http://10.79.96.233:8000', documentUrl: 'http://10.79.96.233:8000/docauditai/', uploadUrl: 'http://10.79.96.233:8000/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51703', oauth: { redirectUri: 'http://10.79.96.233:51703/callback' } }, // 云浮 '51704': { // baseUrl: 'http://172.16.0.55:8001', // documentUrl: 'http://172.16.0.55:8001/docauditai/', // uploadUrl: 'http://172.16.0.55:8001/api/v2/documents', // collaboraUrl: 'http://172.16.0.81:9980', // appUrl: 'http://172.16.0.34:51704', baseUrl: 'http://10.79.96.233:8001', documentUrl: 'http://10.79.96.233:8001/docauditai/', uploadUrl: 'http://10.79.96.233:8001/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51704', oauth: { redirectUri: 'http://10.79.96.233:51704/callback' } }, // 揭阳 '51705': { baseUrl: 'http://10.79.96.233:8002', documentUrl: 'http://10.79.96.233:8002/docauditai/', uploadUrl: 'http://10.79.96.233:8002/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51705', oauth: { redirectUri: 'http://10.79.96.233:51705/callback' } }, // 潮州 '51706': { baseUrl: 'http://10.79.96.233:8003', documentUrl: 'http://10.79.96.233:8003/docauditai/', uploadUrl: 'http://10.79.96.233:8003/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51706', oauth: { redirectUri: 'http://10.79.96.233:51706/callback' } }, // 省局 '51707': { // baseUrl: 'http://172.16.0.55:8866', // documentUrl: 'http://172.16.0.55:8866/docauditai/', // uploadUrl: 'http://172.16.0.55:8866/api/v2/documents', // collaboraUrl: 'http://172.16.0.81:9980', // appUrl: 'http://172.16.0.34:51707', // 正式环境 baseUrl: 'http://10.79.96.233:8866', documentUrl: 'http://10.79.96.233:8866/docauditai/', uploadUrl: 'http://10.79.96.233:8866/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51707', oauth: { redirectUri: 'http://10.79.96.233:51707/callback' } }, //test '51708': { baseUrl: 'http://10.79.96.233:8005', documentUrl: 'http://10.79.96.233:8005/docauditai/', uploadUrl: 'http://10.79.96.233:8005/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51708' }, }; // 不同环境的默认配置 // 由于合同模板的上传,后续的的uploadUrl都不需要/upload,直接写/api/v2/documents,由程序自动添加/upload或/upload_contract_template const configs: Record = { // 开发环境 development: { // baseUrl: 'http://172.16.0.58:8073', // FastAPI后端(包含/dify代理) // documentUrl: 'http://172.16.0.58:8073/docauditai/', // uploadUrl: 'http://172.16.0.58:8073/api/v2/documents', baseUrl: 'http://172.16.0.55:8073', // FastAPI后端(包含/dify代理) documentUrl: 'http://172.16.0.55:8073/docauditai/', uploadUrl: 'http://172.16.0.55:8073/api/v2/documents', collaboraUrl: 'http://172.16.0.81:9980', appUrl: 'http://172.16.0.34:5173', oauth: { serverUrl: 'http://10.79.112.85', // IDaaS服务器地址 clientId: 'none', clientSecret: 'none', // 需要替换为实际的Client Secret redirectUri: 'http://10.79.96.233/', // 回调地址 appId: 'idaasoauth2' // 应用ID,用于登出 }, dify: { rerankingProviderName: 'langgenius/tongyi/tongyi', rerankingModelName: 'gte-rerank' } }, // 测试环境 testing: { baseUrl: 'http://172.16.0.55:8073', // FastAPI后端(包含/dify代理) documentUrl: 'http://172.16.0.55:8073/docauditai/', uploadUrl: 'http://172.16.0.55:8073/api/v2/documents', collaboraUrl: 'http://172.16.0.81:9980', // appUrl: 'http://10.79.96.233:51703', appUrl: 'http://172.16.0.34:5183', oauth: { serverUrl: 'http://10.79.112.85', // IDaaS服务器地址 clientId: '54d2a619fe5c81ae1250434c441fccccqMtKwh7H4fO', clientSecret: 'placeholder', // 需要替换为实际的Client Secret redirectUri: 'http://10.79.96.233/', // 回调地址 appId: 'idaasoauth2' // 应用ID,用于登出 }, dify: { rerankingProviderName: 'langgenius/tongyi/tongyi', rerankingModelName: 'gte-rerank' } }, // 生产环境 production: { baseUrl: 'http://10.79.96.233:8000', // FastAPI后端(包含/dify代理) // minio documentUrl: 'http://10.76.244.156:9000/docauditai/', // 文件上传 uploadUrl: 'http://10.79.96.233:8000/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://10.79.96.233:51703', oauth: { clientId: '54d2a619fe5c81ae1250434c441fccccqMtKwh7H4fO', serverUrl: 'http://10.79.112.85', // IDaaS服务器地址(测试) // serverUrl: 'http://10.79.97.252', // IDaaS服务器地址(生产) // ⚠️ 安全警告:clientSecret 不应该硬编码在代码中 // 请在生产环境使用环境变量 OAUTH_CLIENT_SECRET clientSecret: 'placeholder', // 占位符,实际值从环境变量获取 redirectUri: 'http://10.79.96.233/', // 回调地址 appId: 'idaasoauth2' // 应用ID,用于登出 }, dify: { rerankingProviderName: 'langgenius/tongyi/tongyi', rerankingModelName: 'gte-rerank' } }, // 备用配置 (可以根据需要添加更多环境) staging: { baseUrl: 'http://172.16.0.119:9000/admin', // FastAPI后端(包含/dify代理) documentUrl: 'http://nas.7bm.co:9000/docauditai/', uploadUrl: 'http://172.16.0.119:8000/api/v2/documents', collaboraUrl: 'http://10.79.96.233:9980', appUrl: 'http://172.16.0.119:3000', oauth: { serverUrl: 'http://10.79.112.85', // IDaaS服务器地址 clientId: 'none', // 需要替换为实际的Client ID clientSecret: 'your_client_secret', // 需要替换为实际的Client Secret redirectUri: 'http://172.16.0.119:3000/callback', // 回调地址 appId: 'idaasoauth2' // 应用ID,用于登出 }, dify: { rerankingProviderName: 'langgenius/tongyi/tongyi', rerankingModelName: 'gte-rerank' } } }; // 获取当前环境,默认为development const getCurrentEnvironment = (): string => { // 在服务器端,优先使用PM2设置的环境变量 if (typeof window === 'undefined') { // 服务器端:直接使用process.env.NODE_ENV const nodeEnv = process.env.NODE_ENV; console.log('🔧 服务器端环境检测:', { NODE_ENV: nodeEnv, result: nodeEnv || 'development' }); return nodeEnv || 'development'; } // 客户端:优先使用NEXT_PUBLIC_前缀的环境变量 const nextPublicNodeEnv = process.env.NEXT_PUBLIC_NODE_ENV; const nodeEnv = process.env.NODE_ENV; const result = nextPublicNodeEnv || nodeEnv || 'development'; console.log('🔧 客户端环境检测:', { NEXT_PUBLIC_NODE_ENV: nextPublicNodeEnv, NODE_ENV: nodeEnv, result: result }); return result; }; // 从环境变量获取配置,如果环境变量不存在则使用默认配置 const getConfigFromEnv = (defaultConfig: ApiConfig): ApiConfig => { return { baseUrl: process.env.NEXT_PUBLIC_API_BASE_URL || defaultConfig.baseUrl, documentUrl: process.env.NEXT_PUBLIC_DOCUMENT_URL || defaultConfig.documentUrl, uploadUrl: process.env.NEXT_PUBLIC_UPLOAD_URL || defaultConfig.uploadUrl, collaboraUrl: defaultConfig.collaboraUrl || '', appUrl: defaultConfig.appUrl || '', oauth: { serverUrl: process.env.NEXT_PUBLIC_OAUTH_SERVER_URL || defaultConfig.oauth.serverUrl, clientId: process.env.NEXT_PUBLIC_OAUTH_CLIENT_ID || defaultConfig.oauth.clientId, // ⚠️ 注意:clientSecret 不应该使用 NEXT_PUBLIC_ 前缀 // 应该只在服务器端通过 process.env.OAUTH_CLIENT_SECRET 访问 clientSecret: process.env.OAUTH_CLIENT_SECRET || defaultConfig.oauth.clientSecret, redirectUri: process.env.NEXT_PUBLIC_OAUTH_REDIRECT_URI || defaultConfig.oauth.redirectUri, appId: process.env.NEXT_PUBLIC_OAUTH_APP_ID || defaultConfig.oauth.appId }, dify: defaultConfig.dify }; }; /** * 获取当前端口号 * 优先从浏览器location获取,然后从环境变量获取 */ const getCurrentPort = (): string => { // 在客户端,优先从浏览器location获取端口 let windowPort = ''; if (typeof window !== 'undefined') { windowPort = window.location.port || ''; } // 在服务器端,优先使用运行时端口检测 if (typeof window === 'undefined') { const runtimePort = getRuntimePort(); if (runtimePort) { console.log('🔧 服务器端运行时端口检测:', runtimePort); return runtimePort; } } // 优先使用环境变量中的端口配置 const nextPublicApiPortConfig = process.env.NEXT_PUBLIC_API_PORT_CONFIG; const nextPublicPort = process.env.NEXT_PUBLIC_PORT; const apiPortConfig = process.env.API_PORT_CONFIG; const portEnv = process.env.PORT; // 优先级:windowPort > NEXT_PUBLIC_API_PORT_CONFIG > NEXT_PUBLIC_PORT > API_PORT_CONFIG > PORT环境变量 const result = windowPort || nextPublicApiPortConfig || nextPublicPort || apiPortConfig || portEnv || ''; // console.log('🔧 端口检测:', { // windowPort: windowPort, // NEXT_PUBLIC_API_PORT_CONFIG: nextPublicApiPortConfig, // NEXT_PUBLIC_PORT: nextPublicPort, // API_PORT_CONFIG: apiPortConfig, // PORT: portEnv, // result: result // }); return result; }; /** * 运行时端口检测 - 从服务器启动参数或环境变量获取实际端口 * 这个方法只在服务器端运行,用于动态获取实际运行端口 */ const getRuntimePort = (): string => { if (typeof window !== 'undefined') { return ''; // 客户端不执行此逻辑 } // 尝试从进程参数中获取端口 const args = process.argv; for (let i = 0; i < args.length; i++) { if (args[i] === '--port' && i + 1 < args.length) { return args[i + 1]; } if (args[i].startsWith('--port=')) { return args[i].split('=')[1]; } } // 从环境变量获取 return process.env.PORT || ''; }; /** * 获取当前配置 * 支持根据端口动态切换API配置 */ const getCurrentConfig = (): ApiConfig => { const env = getCurrentEnvironment(); const port = getCurrentPort(); console.log('🔧 配置调试信息:', { environment: env, port: port, hasPortConfig: !!(port && portConfigs[port]), portConfig: port ? portConfigs[port] : null }); // 获取基础配置 let defaultConfig = configs[env] || configs.development; // 如果有端口特定配置,则合并配置 if (port && portConfigs[port]) { console.log(`🔧 使用端口特定配置: ${port}`); const portConfig = portConfigs[port]; defaultConfig = { ...defaultConfig, ...portConfig, // 如果端口配置中有oauth,需要深度合并oauth配置 oauth: portConfig.oauth ? { ...defaultConfig.oauth, ...portConfig.oauth } : defaultConfig.oauth }; console.log(`🔧 使用端口特定配置---深度合并后: ${JSON.stringify(defaultConfig.oauth)}`) } else { console.log(`🔧 使用环境配置: ${env}`, defaultConfig); } // 只有在明确设置了环境变量的情况下才覆盖配置 const hasEnvOverrides = process.env.NEXT_PUBLIC_API_BASE_URL || process.env.NEXT_PUBLIC_DOCUMENT_URL || process.env.NEXT_PUBLIC_UPLOAD_URL; if (hasEnvOverrides) { console.log('🔧 检测到环境变量覆盖,使用环境变量配置'); return getConfigFromEnv(defaultConfig); } console.log('🔧 最终配置:', defaultConfig); return defaultConfig; }; // 导出当前环境的配置 export const apiConfig = getCurrentConfig(); // 导出具体的配置项,方便使用 export const { baseUrl: API_BASE_URL, documentUrl: DOCUMENT_URL, uploadUrl: UPLOAD_URL, collaboraUrl: COLLABORA_URL, appUrl: APP_URL, oauth: OAUTH_CONFIG, dify: DIFY_CONFIG } = apiConfig; /** * 🔓 客户端安全的 OAuth 配置(不包含 clientSecret) * 可以安全地在客户端代码中使用 */ export const CLIENT_OAUTH_CONFIG = { serverUrl: OAUTH_CONFIG.serverUrl as string, clientId: OAUTH_CONFIG.clientId as string, redirectUri: OAUTH_CONFIG.redirectUri as string, appId: OAUTH_CONFIG.appId as string, // 客户端不需要 clientSecret }; // 导出所有配置,供调试使用 export { configs }; // 工具函数:设置环境(主要用于测试) export const setEnvironment = (env: string): ApiConfig => { return configs[env] || configs.development; }; /** * 工具函数:获取当前端口配置信息(用于调试) */ export const getCurrentPortConfig = () => { const port = getCurrentPort(); const env = getCurrentEnvironment(); return { currentPort: port, currentEnvironment: env, hasPortConfig: !!(port && portConfigs[port]), portConfig: port ? portConfigs[port] : null }; }; // 调试信息(仅在开发环境显示) if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'testing') { console.log('📦 API配置信息:', { environment: getCurrentEnvironment(), currentEnv: process.env.NODE_ENV, port: getCurrentPort(), config: { ...apiConfig, oauth: { ...apiConfig.oauth, clientSecret: '***' // 隐藏敏感信息 } }, }); } /** * 交叉评查专属模式配置 * 当为 true 且端口为 51707 时,首页只显示交叉评查入口 */ export const CROSS_CHECKING_ONLY_MODE = process.env.CROSS_CHECKING_ONLY_MODE === 'true'; /** * 交叉评查专属模式的目标端口 */ export const CROSS_CHECKING_ONLY_PORT = '51707'; /** * 获取当前端口(服务端使用) */ export { getCurrentPort };