Update templates/index.html
Browse files- templates/index.html +216 -0
templates/index.html
CHANGED
@@ -226,6 +226,70 @@
|
|
226 |
<div class="bg-white p-6 rounded-lg shadow-md">
|
227 |
<h2 class="text-xl font-semibold mb-4">股票批量分析</h2>
|
228 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
|
230 |
<!-- 添加市场类型选择 -->
|
231 |
<div class="mb-4">
|
@@ -957,6 +1021,158 @@
|
|
957 |
<!-- 添加 marked.js 用于解析 Markdown -->
|
958 |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
959 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
960 |
<script>
|
961 |
// 添加 Markdown 样式
|
962 |
function addMarkdownStyles() {
|
|
|
226 |
<div class="bg-white p-6 rounded-lg shadow-md">
|
227 |
<h2 class="text-xl font-semibold mb-4">股票批量分析</h2>
|
228 |
|
229 |
+
<!-- API配置部分 -->
|
230 |
+
<div class="mb-6 border-b pb-6">
|
231 |
+
<div class="flex items-center justify-between mb-4">
|
232 |
+
<h3 class="text-lg font-medium text-gray-700">API配置</h3>
|
233 |
+
<button id="toggleApiConfig" class="text-blue-600 hover:text-blue-800 text-sm flex items-center">
|
234 |
+
<span id="toggleApiConfigText">显示配置</span>
|
235 |
+
<svg id="toggleApiConfigIcon" class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
236 |
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
237 |
+
</svg>
|
238 |
+
</button>
|
239 |
+
</div>
|
240 |
+
|
241 |
+
<div id="apiConfigPanel" class="hidden space-y-4">
|
242 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
243 |
+
<div>
|
244 |
+
<label for="apiUrl" class="block text-sm font-medium text-gray-700 mb-1">API URL</label>
|
245 |
+
<input type="text" id="apiUrl"
|
246 |
+
class="w-full p-2 border rounded bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
247 |
+
placeholder="例如: https://api.openai.com"
|
248 |
+
value="{{ default_api_url }}"
|
249 |
+
oninput="updateFormattedUrl(this.value)">
|
250 |
+
<p id="formattedUrl" class="mt-1 text-sm text-gray-500 break-all"></p>
|
251 |
+
</div>
|
252 |
+
<div>
|
253 |
+
<label for="apiModel" class="block text-sm font-medium text-gray-700 mb-1">API 模型</label>
|
254 |
+
<input type="text" id="apiModel"
|
255 |
+
class="w-full p-2 border rounded bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
256 |
+
placeholder="例如: gpt-3.5-turbo"
|
257 |
+
value="{{ default_api_model }}">
|
258 |
+
</div>
|
259 |
+
</div>
|
260 |
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
261 |
+
<div>
|
262 |
+
<label for="apiKey" class="block text-sm font-medium text-gray-700 mb-1">API Key</label>
|
263 |
+
<input type="password" id="apiKey"
|
264 |
+
class="w-full p-2 border rounded bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
265 |
+
placeholder="输入您的API Key">
|
266 |
+
<p class="mt-1 text-sm text-gray-500">如不填写,将使用系统默认配置</p>
|
267 |
+
</div>
|
268 |
+
<div>
|
269 |
+
<label for="apiTimeout" class="block text-sm font-medium text-gray-700 mb-1">API 超时时间 (秒)</label>
|
270 |
+
<input type="number" id="apiTimeout"
|
271 |
+
class="w-full p-2 border rounded bg-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
272 |
+
placeholder="例如: 60"
|
273 |
+
value="{{ default_api_timeout }}" min="1" max="300">
|
274 |
+
<p class="mt-1 text-sm text-gray-500">请求超时时间,默认60秒</p>
|
275 |
+
</div>
|
276 |
+
</div>
|
277 |
+
<div class="flex justify-between">
|
278 |
+
<div class="flex items-center">
|
279 |
+
<input type="checkbox" id="saveApiConfig" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
|
280 |
+
<label for="saveApiConfig" class="ml-2 block text-sm text-gray-700">保存配置到本地</label>
|
281 |
+
</div>
|
282 |
+
<div>
|
283 |
+
<button id="resetApiConfig" class="text-gray-600 hover:text-gray-800 text-sm mr-3">
|
284 |
+
重置为默认
|
285 |
+
</button>
|
286 |
+
<button id="testApiConfig" class="bg-blue-100 text-blue-700 px-3 py-1 rounded hover:bg-blue-200 text-sm">
|
287 |
+
测试连接
|
288 |
+
</button>
|
289 |
+
</div>
|
290 |
+
</div>
|
291 |
+
</div>
|
292 |
+
</div>
|
293 |
|
294 |
<!-- 添加市场类型选择 -->
|
295 |
<div class="mb-4">
|
|
|
1021 |
<!-- 添加 marked.js 用于解析 Markdown -->
|
1022 |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
1023 |
|
1024 |
+
<!-- API配置相关脚本 -->
|
1025 |
+
<script>
|
1026 |
+
document.addEventListener('DOMContentLoaded', function() {
|
1027 |
+
// API配置面板切换
|
1028 |
+
const toggleApiConfig = document.getElementById('toggleApiConfig');
|
1029 |
+
const apiConfigPanel = document.getElementById('apiConfigPanel');
|
1030 |
+
const toggleApiConfigText = document.getElementById('toggleApiConfigText');
|
1031 |
+
const toggleApiConfigIcon = document.getElementById('toggleApiConfigIcon');
|
1032 |
+
const apiUrl = document.getElementById('apiUrl');
|
1033 |
+
const apiKey = document.getElementById('apiKey');
|
1034 |
+
const apiModel = document.getElementById('apiModel');
|
1035 |
+
const apiTimeout = document.getElementById('apiTimeout');
|
1036 |
+
const saveApiConfig = document.getElementById('saveApiConfig');
|
1037 |
+
const resetApiConfig = document.getElementById('resetApiConfig');
|
1038 |
+
const testApiConfig = document.getElementById('testApiConfig');
|
1039 |
+
|
1040 |
+
// 从localStorage加载保存的配置
|
1041 |
+
loadApiConfig();
|
1042 |
+
|
1043 |
+
// 切换API配置面板显示/隐藏
|
1044 |
+
toggleApiConfig.addEventListener('click', function() {
|
1045 |
+
// apiConfigPanel.classList.toggle('hidden');
|
1046 |
+
|
1047 |
+
// if (apiConfigPanel.classList.contains('hidden')) {
|
1048 |
+
// toggleApiConfigText.textContent = '显示配置';
|
1049 |
+
// toggleApiConfigIcon.innerHTML = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>';
|
1050 |
+
// } else {
|
1051 |
+
// toggleApiConfigText.textContent = '隐藏配置';
|
1052 |
+
// toggleApiConfigIcon.innerHTML = '<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 15l7-7 7 7"></path>';
|
1053 |
+
// }
|
1054 |
+
});
|
1055 |
+
|
1056 |
+
// 重置API配置
|
1057 |
+
resetApiConfig.addEventListener('click', function() {
|
1058 |
+
apiUrl.value = '{{ default_api_url }}';
|
1059 |
+
apiKey.value = '';
|
1060 |
+
apiModel.value = '{{ default_api_model }}';
|
1061 |
+
apiTimeout.value = '{{ default_api_timeout }}';
|
1062 |
+
saveApiConfig.checked = false;
|
1063 |
+
|
1064 |
+
// 清除localStorage中的配置
|
1065 |
+
localStorage.removeItem('apiConfig');
|
1066 |
+
|
1067 |
+
alert('已重置为默认配置');
|
1068 |
+
});
|
1069 |
+
|
1070 |
+
// 测试API连接
|
1071 |
+
testApiConfig.addEventListener('click', async function() {
|
1072 |
+
const url = apiUrl.value.trim();
|
1073 |
+
const key = apiKey.value.trim();
|
1074 |
+
const model = apiModel.value.trim();
|
1075 |
+
const timeout = apiTimeout.value.trim();
|
1076 |
+
|
1077 |
+
if (!url) {
|
1078 |
+
alert('请输入API URL');
|
1079 |
+
return;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
if (!key) {
|
1083 |
+
alert('请输入API Key');
|
1084 |
+
return;
|
1085 |
+
}
|
1086 |
+
|
1087 |
+
try {
|
1088 |
+
testApiConfig.disabled = true;
|
1089 |
+
testApiConfig.textContent = '测试中...';
|
1090 |
+
|
1091 |
+
const response = await fetch('/test_api_connection', {
|
1092 |
+
method: 'POST',
|
1093 |
+
headers: {
|
1094 |
+
'Content-Type': 'application/json',
|
1095 |
+
},
|
1096 |
+
body: JSON.stringify({
|
1097 |
+
api_url: url,
|
1098 |
+
api_key: key,
|
1099 |
+
api_model: model,
|
1100 |
+
api_timeout: timeout
|
1101 |
+
})
|
1102 |
+
});
|
1103 |
+
|
1104 |
+
const result = await response.json();
|
1105 |
+
|
1106 |
+
if (result.success) {
|
1107 |
+
alert(result.message);
|
1108 |
+
|
1109 |
+
// 如果勾选了保存配置,则保存到localStorage
|
1110 |
+
if (saveApiConfig.checked) {
|
1111 |
+
saveApiConfigToLocalStorage();
|
1112 |
+
}
|
1113 |
+
} else {
|
1114 |
+
alert(result.message);
|
1115 |
+
}
|
1116 |
+
} catch (error) {
|
1117 |
+
alert(error.message);
|
1118 |
+
} finally {
|
1119 |
+
testApiConfig.disabled = false;
|
1120 |
+
testApiConfig.textContent = '测试连接';
|
1121 |
+
}
|
1122 |
+
});
|
1123 |
+
|
1124 |
+
// 监听输入变化,自动保存配置
|
1125 |
+
[apiUrl, apiKey, apiModel, apiTimeout].forEach(input => {
|
1126 |
+
input.addEventListener('change', function() {
|
1127 |
+
if (saveApiConfig.checked) {
|
1128 |
+
saveApiConfigToLocalStorage();
|
1129 |
+
}
|
1130 |
+
});
|
1131 |
+
});
|
1132 |
+
|
1133 |
+
// 监听保存配置复选框��化
|
1134 |
+
saveApiConfig.addEventListener('change', function() {
|
1135 |
+
if (this.checked) {
|
1136 |
+
saveApiConfigToLocalStorage();
|
1137 |
+
} else {
|
1138 |
+
localStorage.removeItem('apiConfig');
|
1139 |
+
}
|
1140 |
+
});
|
1141 |
+
});
|
1142 |
+
|
1143 |
+
// 保存API配置到localStorage
|
1144 |
+
function saveApiConfigToLocalStorage() {
|
1145 |
+
const apiConfig = {
|
1146 |
+
url: document.getElementById('apiUrl').value.trim(),
|
1147 |
+
model: document.getElementById('apiModel').value.trim(),
|
1148 |
+
key: document.getElementById('apiKey').value.trim(),
|
1149 |
+
timeout: document.getElementById('apiTimeout').value.trim(),
|
1150 |
+
saveEnabled: true
|
1151 |
+
};
|
1152 |
+
|
1153 |
+
localStorage.setItem('apiConfig', JSON.stringify(apiConfig));
|
1154 |
+
}
|
1155 |
+
|
1156 |
+
// 从localStorage加载API配置
|
1157 |
+
function loadApiConfig() {
|
1158 |
+
const savedConfig = localStorage.getItem('apiConfig');
|
1159 |
+
|
1160 |
+
if (savedConfig) {
|
1161 |
+
try {
|
1162 |
+
const config = JSON.parse(savedConfig);
|
1163 |
+
|
1164 |
+
if (config.url) document.getElementById('apiUrl').value = config.url;
|
1165 |
+
if (config.model) document.getElementById('apiModel').value = config.model;
|
1166 |
+
if (config.key) document.getElementById('apiKey').value = config.key;
|
1167 |
+
if (config.timeout) document.getElementById('apiTimeout').value = config.timeout;
|
1168 |
+
|
1169 |
+
document.getElementById('saveApiConfig').checked = config.saveEnabled || false;
|
1170 |
+
} catch (error) {
|
1171 |
+
console.error('加载API配置时出错:', error);
|
1172 |
+
}
|
1173 |
+
}
|
1174 |
+
}
|
1175 |
+
</script>
|
1176 |
<script>
|
1177 |
// 添加 Markdown 样式
|
1178 |
function addMarkdownStyles() {
|