fix: 生产环境使用相对路径由nginx代理到后端

This commit is contained in:
肖应宇 2026-03-23 12:00:31 +08:00
parent eb2a09b82f
commit 3028484949
13 changed files with 41 additions and 32 deletions

View File

@ -66,7 +66,7 @@ async function uploadToMistral(fileToProcess, mistralKey) {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getMistralUrl('/v1/files') ? window.ProxyConfig.getMistralUrl('/v1/files')
: 'http://localhost:3456/api/mistral/v1/files'; : (window.PBX_PROXY_BASE_URL || '/api') + '/mistral/v1/files';
const response = await fetch(proxyUrl, { const response = await fetch(proxyUrl, {
method: 'POST', method: 'POST',
@ -99,9 +99,7 @@ async function uploadFileToOssViaProxy(fileToProcess, fileName) {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getOssUploadUrl() ? window.ProxyConfig.getOssUploadUrl()
: (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' : (window.PBX_PROXY_BASE_URL || '/api') + '/upload/oss';
? 'http://localhost:3456/api/upload/oss'
: '/api/upload/oss');
const response = await fetch(proxyUrl, { const response = await fetch(proxyUrl, {
method: 'POST', method: 'POST',
@ -133,7 +131,7 @@ async function getMistralSignedUrl(fileId, mistralKey) {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getMistralUrl(`/v1/files/${fileId}/url?expiry=24`) ? window.ProxyConfig.getMistralUrl(`/v1/files/${fileId}/url?expiry=24`)
: `http://localhost:3456/api/mistral/v1/files/${fileId}/url?expiry=24`; : (window.PBX_PROXY_BASE_URL || '/api') + `/mistral/v1/files/${fileId}/url?expiry=24`;
const response = await fetch(proxyUrl, { const response = await fetch(proxyUrl, {
method: 'GET', method: 'GET',
@ -162,7 +160,7 @@ async function callMistralOcr(signedUrl, mistralKey) {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getMistralUrl('/v1/ocr') ? window.ProxyConfig.getMistralUrl('/v1/ocr')
: 'http://localhost:3456/api/mistral/v1/ocr'; : (window.PBX_PROXY_BASE_URL || '/api') + '/mistral/v1/ocr';
const response = await fetch(proxyUrl, { const response = await fetch(proxyUrl, {
method: 'POST', method: 'POST',
@ -202,7 +200,7 @@ async function deleteMistralFile(fileId, apiKey) {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const deleteUrl = (typeof window !== 'undefined' && window.ProxyConfig) const deleteUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getMistralUrl(`/v1/files/${fileId}`) ? window.ProxyConfig.getMistralUrl(`/v1/files/${fileId}`)
: `http://localhost:3456/api/mistral/v1/files/${fileId}`; : (window.PBX_PROXY_BASE_URL || '/api') + `/mistral/v1/files/${fileId}`;
try { try {
const response = await fetch(deleteUrl, { const response = await fetch(deleteUrl, {

View File

@ -162,7 +162,7 @@
const proxyBaseUrl = options.proxyBaseUrl || const proxyBaseUrl = options.proxyBaseUrl ||
(typeof window !== 'undefined' && window.ProxyConfig ? window.ProxyConfig.getProxyUrl() : null) || (typeof window !== 'undefined' && window.ProxyConfig ? window.ProxyConfig.getProxyUrl() : null) ||
(typeof window !== 'undefined' && window.PBX_PROXY_BASE_URL ? window.PBX_PROXY_BASE_URL : null) || (typeof window !== 'undefined' && window.PBX_PROXY_BASE_URL ? window.PBX_PROXY_BASE_URL : null) ||
'http://localhost:3456'; '/api';
const provider = options.provider || 'openai'; const provider = options.provider || 'openai';
// 获取当前选择的模型ID如果有模型检测模块 // 获取当前选择的模型ID如果有模型检测模块

View File

@ -140,7 +140,7 @@
const useProxy = globalProxyMode === 'proxy'; const useProxy = globalProxyMode === 'proxy';
const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'); : (window.PBX_PROXY_BASE_URL || '/api');
// 确定提供商(从模型 ID 或配置推断) // 确定提供商(从模型 ID 或配置推断)
let provider = 'openai'; let provider = 'openai';

View File

@ -447,7 +447,7 @@ async function sendChatbotMessage(userInput, updateChatbotUI, externalConfig = n
const useProxy = globalProxyMode === 'proxy'; const useProxy = globalProxyMode === 'proxy';
const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'); : (window.PBX_PROXY_BASE_URL || '/api');
// 在使用代理服务器模式时API Key 在后端配置,前端可以没有 API Key // 在使用代理服务器模式时API Key 在后端配置,前端可以没有 API Key
// 否则,检查前端是否配置了有效的 API Key // 否则,检查前端是否配置了有效的 API Key
@ -1740,7 +1740,7 @@ async function singleChunkSummary(sysPrompt, userInput, config, apiKey) {
const useProxy = globalProxyMode === 'proxy'; const useProxy = globalProxyMode === 'proxy';
const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyBaseUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'); : (window.PBX_PROXY_BASE_URL || '/api');
// 只做单轮整理,不带历史 // 只做单轮整理,不带历史
let apiConfig; let apiConfig;

View File

@ -808,7 +808,7 @@ async function executeMinerUStructuredTranslation() {
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
const PROXY_BASE = (typeof window !== 'undefined' && window.ProxyConfig) const PROXY_BASE = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'); : (window.PBX_PROXY_BASE_URL || '/api');
// 获取翻译配置 // 获取翻译配置
const settings = typeof loadSettings === 'function' ? loadSettings() : {}; const settings = typeof loadSettings === 'function' ? loadSettings() : {};

View File

@ -800,7 +800,7 @@ const fileType = fileToProcess.name.split('.').pop().toLowerCase();
provider: selectedTranslationModelName, provider: selectedTranslationModelName,
proxyBase: (typeof window !== 'undefined' && window.ProxyConfig) proxyBase: (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'), : (window.PBX_PROXY_BASE_URL || '/api'),
// 允许从设置自定义重试,若无则用默认 // 允许从设置自定义重试,若无则用默认
maxRetries: (typeof loadSettings === 'function' ? (loadSettings().structuredMaxRetries || undefined) : undefined), maxRetries: (typeof loadSettings === 'function' ? (loadSettings().structuredMaxRetries || undefined) : undefined),
retryDelay: (typeof loadSettings === 'function' ? (loadSettings().structuredRetryDelayMs || undefined) : undefined) retryDelay: (typeof loadSettings === 'function' ? (loadSettings().structuredRetryDelayMs || undefined) : undefined)

View File

@ -717,7 +717,7 @@ ${jsonContent}
const proxyBase = options.proxyBase || const proxyBase = options.proxyBase ||
(typeof window !== 'undefined' && window.ProxyConfig ? window.ProxyConfig.getProxyUrl() : null) || (typeof window !== 'undefined' && window.ProxyConfig ? window.ProxyConfig.getProxyUrl() : null) ||
(typeof window !== 'undefined' && window.PBX_PROXY_BASE_URL ? window.PBX_PROXY_BASE_URL : null) || (typeof window !== 'undefined' && window.PBX_PROXY_BASE_URL ? window.PBX_PROXY_BASE_URL : null) ||
'http://localhost:3456'; '/api';
const provider = options.provider || 'aliyun'; const provider = options.provider || 'aliyun';
// 后端代理端点映射 // 后端代理端点映射
@ -836,7 +836,7 @@ ${jsonContent}
// 前端发出的请求源头 // 前端发出的请求源头
const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig) const proxyUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: (window.PBX_PROXY_BASE_URL || 'http://localhost:3456'); : (window.PBX_PROXY_BASE_URL || '/api');
const predefinedConfigs = { const predefinedConfigs = {
'proxy': { 'proxy': {
endpoint: `${proxyUrl}/api/llm/aliyun/v1/chat/completions`, endpoint: `${proxyUrl}/api/llm/aliyun/v1/chat/completions`,

View File

@ -12,13 +12,13 @@ class MistralOcrAdapter extends OcrAdapter {
this.currentKeyIndex = 0; this.currentKeyIndex = 0;
// 使用统一配置获取代理地址 // 使用统一配置获取代理地址
// 优先级config.baseUrl > window.ProxyConfig > 默认值 // 优先级config.baseUrl > window.ProxyConfig > PBX_PROXY_BASE_URL > 默认相对路径
if (config.baseUrl && config.baseUrl !== 'https://api.mistral.ai') { if (config.baseUrl && config.baseUrl !== 'https://api.mistral.ai') {
this.baseUrl = config.baseUrl.replace(/\/+$/, ''); this.baseUrl = config.baseUrl.replace(/\/+$/, '');
} else if (typeof window !== 'undefined' && window.ProxyConfig) { } else if (typeof window !== 'undefined' && window.ProxyConfig) {
this.baseUrl = window.ProxyConfig.getMistralUrl(); this.baseUrl = window.ProxyConfig.getMistralUrl();
} else { } else {
this.baseUrl = 'http://localhost:3456/api/mistral'; this.baseUrl = (window.PBX_PROXY_BASE_URL || '/api') + '/mistral';
} }
} }

View File

@ -97,7 +97,7 @@ class OcrManager {
// 使用统一配置获取默认 workerUrl // 使用统一配置获取默认 workerUrl
const mineruDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) const mineruDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: 'http://localhost:3456'; : (window.PBX_PROXY_BASE_URL || '/api');
return { return {
engine: 'mineru', engine: 'mineru',
token: localStorage.getItem('ocrMinerUToken') || '', token: localStorage.getItem('ocrMinerUToken') || '',
@ -113,7 +113,7 @@ class OcrManager {
// 使用统一配置获取默认 workerUrl // 使用统一配置获取默认 workerUrl
const doc2xDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) const doc2xDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getProxyUrl() ? window.ProxyConfig.getProxyUrl()
: 'http://localhost:3456'; : (window.PBX_PROXY_BASE_URL || '/api');
return { return {
engine: 'doc2x', engine: 'doc2x',
token: localStorage.getItem('ocrDoc2XToken') || '', token: localStorage.getItem('ocrDoc2XToken') || '',

View File

@ -705,7 +705,7 @@ async function translateMarkdown(
// 所有翻译请求都指向后端代理,由后端决定使用哪个模型 // 所有翻译请求都指向后端代理,由后端决定使用哪个模型
endpoint: (typeof window !== 'undefined' && window.ProxyConfig) endpoint: (typeof window !== 'undefined' && window.ProxyConfig)
? window.ProxyConfig.getLLMProxyUrl('tongyi', '/v1/chat/completions') ? window.ProxyConfig.getLLMProxyUrl('tongyi', '/v1/chat/completions')
: ((window.PBX_PROXY_BASE_URL || 'http://localhost:3456') + '/api/llm/tongyi/v1/chat/completions'), : ((window.PBX_PROXY_BASE_URL || '/api') + '/llm/tongyi/v1/chat/completions'),
modelName: '通义百炼', modelName: '通义百炼',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
bodyBuilder: (sys, user) => { bodyBuilder: (sys, user) => {

View File

@ -125,7 +125,8 @@ class OcrSettingsManager {
this.elements.mineruToken.value = localStorage.getItem(this.keys.mineruToken) || ''; this.elements.mineruToken.value = localStorage.getItem(this.keys.mineruToken) || '';
} }
if (this.elements.mineruWorkerUrl) { if (this.elements.mineruWorkerUrl) {
this.elements.mineruWorkerUrl.value = localStorage.getItem(this.keys.mineruWorkerUrl) || 'http://localhost:3456'; const defaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
this.elements.mineruWorkerUrl.value = localStorage.getItem(this.keys.mineruWorkerUrl) || defaultUrl;
} }
if (this.elements.mineruEnableOcr) { if (this.elements.mineruEnableOcr) {
this.elements.mineruEnableOcr.checked = localStorage.getItem(this.keys.mineruEnableOcr) !== 'false'; this.elements.mineruEnableOcr.checked = localStorage.getItem(this.keys.mineruEnableOcr) !== 'false';
@ -151,7 +152,8 @@ class OcrSettingsManager {
this.elements.doc2xToken.value = localStorage.getItem(this.keys.doc2xToken) || ''; this.elements.doc2xToken.value = localStorage.getItem(this.keys.doc2xToken) || '';
} }
if (this.elements.doc2xWorkerUrl) { if (this.elements.doc2xWorkerUrl) {
this.elements.doc2xWorkerUrl.value = localStorage.getItem(this.keys.doc2xWorkerUrl) || 'http://localhost:3456'; const defaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
this.elements.doc2xWorkerUrl.value = localStorage.getItem(this.keys.doc2xWorkerUrl) || defaultUrl;
} }
if (this.elements.doc2xFormulaMode) { if (this.elements.doc2xFormulaMode) {
this.elements.doc2xFormulaMode.value = localStorage.getItem(this.keys.doc2xFormulaMode) || 'dollar'; this.elements.doc2xFormulaMode.value = localStorage.getItem(this.keys.doc2xFormulaMode) || 'dollar';
@ -514,10 +516,11 @@ class OcrSettingsManager {
} }
case 'mineru': case 'mineru':
const mineruDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
return { return {
engine: 'mineru', engine: 'mineru',
token: localStorage.getItem(this.keys.mineruToken) || '', token: localStorage.getItem(this.keys.mineruToken) || '',
workerUrl: (localStorage.getItem(this.keys.mineruWorkerUrl) || 'http://localhost:3456').replace(/\/+$/, ''), // 去掉末尾斜杠 workerUrl: (localStorage.getItem(this.keys.mineruWorkerUrl) || mineruDefaultUrl).replace(/\/+$/, ''), // 去掉末尾斜杠
authKey: localStorage.getItem(this.keys.workerAuthKey) || '', authKey: localStorage.getItem(this.keys.workerAuthKey) || '',
tokenMode: localStorage.getItem(this.keys.mineruTokenMode) || 'backend', // 默认后端转发模式 tokenMode: localStorage.getItem(this.keys.mineruTokenMode) || 'backend', // 默认后端转发模式
enableOcr: localStorage.getItem(this.keys.mineruEnableOcr) !== 'false', enableOcr: localStorage.getItem(this.keys.mineruEnableOcr) !== 'false',
@ -527,10 +530,11 @@ class OcrSettingsManager {
}; };
case 'doc2x': case 'doc2x':
const doc2xDefaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
return { return {
engine: 'doc2x', engine: 'doc2x',
token: localStorage.getItem(this.keys.doc2xToken) || '', token: localStorage.getItem(this.keys.doc2xToken) || '',
workerUrl: (localStorage.getItem(this.keys.doc2xWorkerUrl) || 'http://localhost:3456').replace(/\/+$/, ''), // 去掉末尾斜杠 workerUrl: (localStorage.getItem(this.keys.doc2xWorkerUrl) || doc2xDefaultUrl).replace(/\/+$/, ''), // 去掉末尾斜杠
authKey: localStorage.getItem(this.keys.workerAuthKey) || '', authKey: localStorage.getItem(this.keys.workerAuthKey) || '',
tokenMode: localStorage.getItem(this.keys.doc2xTokenMode) || 'backend', // 默认后端转发模式 tokenMode: localStorage.getItem(this.keys.doc2xTokenMode) || 'backend', // 默认后端转发模式
formulaMode: localStorage.getItem(this.keys.doc2xFormulaMode) || 'dollar', formulaMode: localStorage.getItem(this.keys.doc2xFormulaMode) || 'dollar',

View File

@ -60,7 +60,8 @@
*/ */
function renderMinerUConfig(container) { function renderMinerUConfig(container) {
// 从 localStorage 加载配置 // 从 localStorage 加载配置
const workerUrl = localStorage.getItem('ocrMinerUWorkerUrl') || 'http://localhost:3456'; const defaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
const workerUrl = localStorage.getItem('ocrMinerUWorkerUrl') || defaultUrl;
const authKey = localStorage.getItem('ocrWorkerAuthKey') || ''; const authKey = localStorage.getItem('ocrWorkerAuthKey') || '';
const tokenMode = localStorage.getItem('ocrMinerUTokenMode') || 'backend'; const tokenMode = localStorage.getItem('ocrMinerUTokenMode') || 'backend';
const token = localStorage.getItem('ocrMinerUToken') || ''; const token = localStorage.getItem('ocrMinerUToken') || '';
@ -336,7 +337,8 @@
*/ */
function renderDoc2XConfig(container) { function renderDoc2XConfig(container) {
// 从 localStorage 加载配置 // 从 localStorage 加载配置
const workerUrl = localStorage.getItem('ocrDoc2XWorkerUrl') || 'http://localhost:3456'; const defaultUrl = (typeof window !== 'undefined' && window.ProxyConfig) ? window.ProxyConfig.getProxyUrl() : '/api';
const workerUrl = localStorage.getItem('ocrDoc2XWorkerUrl') || defaultUrl;
const authKey = localStorage.getItem('ocrWorkerAuthKey') || ''; const authKey = localStorage.getItem('ocrWorkerAuthKey') || '';
const tokenMode = localStorage.getItem('ocrDoc2XTokenMode') || 'backend'; const tokenMode = localStorage.getItem('ocrDoc2XTokenMode') || 'backend';
const token = localStorage.getItem('ocrDoc2XToken') || ''; const token = localStorage.getItem('ocrDoc2XToken') || '';

View File

@ -864,10 +864,13 @@
<!-- Phase 3.5: 性能优化配置(必须在所有 chatbot 模块之前加载) --> <!-- Phase 3.5: 性能优化配置(必须在所有 chatbot 模块之前加载) -->
<script src="../../js/chatbot/config/performance-config.js"></script> <script src="../../js/chatbot/config/performance-config.js"></script>
<!-- 历史页 Chatbot 代理配置:使用阿里云百炼平台,保护 API Key --> <!-- 历史页 Chatbot 代理配置:使用阿里云百炼平台,保护 API Key -->
<script src="../../js/config/proxy-config.js"></script>
<script> <script>
// 全局配置:启用代理模式,使用本地代理服务器 // 全局配置:启用代理模式,使用 ProxyConfig 自动检测环境
window.PBX_PROXY_MODE = "proxy"; window.PBX_PROXY_MODE = "proxy";
window.PBX_PROXY_BASE_URL = "http://localhost:3456"; // PBX_PROXY_BASE_URL 由 proxy-config.js 自动设置:
// - 本地开发: http://localhost:3456
// - 生产环境: /api (相对路径)
// 使用阿里云百炼平台 // 使用阿里云百炼平台
window.PBX_LLM_PROVIDER = "aliyun"; window.PBX_LLM_PROVIDER = "aliyun";
// 默认模型qwen-plus推荐其他可选qwen-turbo、qwen-max、qwen-long-context // 默认模型qwen-plus推荐其他可选qwen-turbo、qwen-max、qwen-long-context
@ -879,10 +882,10 @@
window.PBX_LLM_MODEL, window.PBX_LLM_MODEL,
); );
</script> </script>
<!-- 直接向 localhost:3456 发送对话消息的函数 --> <!-- 通过代理发送对话消息的函数 -->
<script> <script>
/** /**
* 直接向 http://localhost:3456 发送对话消息 * 通过代理服务器发送对话消息
* @param {string} userMessage - 用户消息内容 * @param {string} userMessage - 用户消息内容
* @param {Array} [conversationHistory=[]] - 对话历史 [{role, content}, ...] * @param {Array} [conversationHistory=[]] - 对话历史 [{role, content}, ...]
* @param {Object} [options={}] - 可选配置 * @param {Object} [options={}] - 可选配置
@ -893,7 +896,8 @@
conversationHistory = [], conversationHistory = [],
options = {}, options = {},
) { ) {
const endpoint = "http://localhost:3456/v1/chat/completions"; const baseUrl = window.PBX_PROXY_BASE_URL || '/api';
const endpoint = `${baseUrl}/v1/chat/completions`;
const model = options.model || window.PBX_LLM_MODEL || "qwen-plus"; const model = options.model || window.PBX_LLM_MODEL || "qwen-plus";
const temperature = options.temperature || 0.7; const temperature = options.temperature || 0.7;
const maxTokens = options.maxTokens || 2048; const maxTokens = options.maxTokens || 2048;
@ -951,7 +955,8 @@
onChunk, onChunk,
options = {}, options = {},
) { ) {
const endpoint = "http://localhost:3456/v1/chat/completions"; const baseUrl = window.PBX_PROXY_BASE_URL || '/api';
const endpoint = `${baseUrl}/v1/chat/completions`;
const model = options.model || window.PBX_LLM_MODEL || "qwen-plus"; const model = options.model || window.PBX_LLM_MODEL || "qwen-plus";
const temperature = options.temperature || 0.7; const temperature = options.temperature || 0.7;
const maxTokens = options.maxTokens || 2048; const maxTokens = options.maxTokens || 2048;