Files
wasm-go/web/index.html
lychang 10905c0acc update
2026-05-21 01:57:25 +08:00

972 lines
37 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WASM企业分析工具套件</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
.container {
background-color: white;
border-radius: 15px;
padding: 40px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
margin-top: 20px;
}
header {
text-align: center;
margin-bottom: 40px;
}
h1 {
color: #2c3e50;
font-size: 2.5em;
margin-bottom: 10px;
}
.subtitle {
color: #7f8c8d;
font-size: 1.2em;
margin-bottom: 30px;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin: 40px 0;
}
.feature-card {
background: #f8f9fa;
border-radius: 10px;
padding: 20px;
text-align: center;
transition: transform 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}
.feature-icon {
font-size: 2.5em;
margin-bottom: 15px;
display: block;
}
.feature-title {
font-size: 1.3em;
color: #2c3e50;
margin-bottom: 10px;
}
.feature-desc {
color: #7f8c8d;
}
.section {
margin: 30px 0;
padding: 25px;
background: #e3f2fd;
border-radius: 10px;
}
label {
display: block;
margin-bottom: 12px;
font-weight: bold;
color: #34495e;
font-size: 1.1em;
}
input[type="text"], textarea, input[type="file"] {
width: 100%;
padding: 12px;
border: 2px solid #bbdefb;
border-radius: 8px;
font-size: 16px;
box-sizing: border-box;
transition: border-color 0.3s;
margin-bottom: 15px;
}
input[type="text"]:focus, textarea:focus {
outline: none;
border-color: #64b5f6;
}
button {
background: linear-gradient(45deg, #2196F3, #21CBF3);
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
margin-right: 10px;
margin-top: 10px;
transition: transform 0.2s, box-shadow 0.2s;
}
button:hover {
transform: scale(1.05);
box-shadow: 0 5px 15px rgba(33, 150, 243, 0.4);
}
button:disabled {
background: #b0bec5;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.result-section {
margin-top: 20px;
padding: 20px;
background-color: #e8f5e9;
border-radius: 10px;
display: none;
}
.result-section.show {
display: block;
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.result-item {
margin-bottom: 15px;
padding: 15px;
background-color: white;
border-radius: 8px;
border-left: 5px solid #4caf50;
}
.loading {
text-align: center;
padding: 20px;
display: none;
}
.loading.show {
display: block;
}
.error {
color: #f44336;
background-color: #ffebee;
padding: 15px;
border-radius: 8px;
margin-top: 15px;
display: none;
}
.error.show {
display: block;
}
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
border-radius: 8px 8px 0 0;
}
.tab button {
background: inherit;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 14px 16px;
transition: 0.3s;
font-size: 17px;
margin: 0;
box-shadow: none;
}
.tab button:hover {
background-color: #ddd;
}
.tab button.active {
background-color: #2196F3;
color: white;
}
.tabcontent {
display: none;
padding: 20px;
border: 1px solid #ccc;
border-top: none;
border-radius: 0 0 8px 8px;
background-color: white;
}
.config-btn {
background: inherit;
border: 1px solid #ccc;
border-radius: 8px;
padding: 10px 15px;
cursor: pointer;
font-size: 16px;
margin-left: 10px;
box-shadow: none;
}
.config-btn:hover {
background-color: #ddd;
}
.config-panel {
display: none;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.config-panel.active {
display: block;
}
footer {
text-align: center;
margin-top: 40px;
color: #95a5a6;
font-size: 0.9em;
}
.json-output {
background: rgba(0, 0, 0, 0.3);
padding: 15px;
border-radius: 5px;
font-family: monospace;
white-space: pre-wrap;
word-break: break-word;
max-height: 400px;
overflow-y: auto;
}
.config-btn {
background: rgba(255, 255, 255, 0.2);
color: white;
border: none;
padding: 10px 15px;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background 0.3s;
}
.config-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.config-panel {
display: none;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}
.config-panel.active {
display: block;
}
</style>
</head>
<body>
<header>
<h1>🚀 Excel转JSON工具</h1>
<p class="subtitle">基于WebAssembly的多功能企业数据分析平台</p>
</header>
<div class="container">
<!-- 顶部导航栏 -->
<div class="navbar">
<h1>🚀 Excel转JSON工具</h1>
<!-- LLM配置按钮 -->
<button id="llmConfigBtn" class="config-btn" onclick="toggleLLMConfig()">⚙️ LLM配置</button>
</div>
<!-- LLM配置面板 -->
<div id="llmConfigPanel" class="config-panel">
<div class="section">
<h3>🤖 LLM配置</h3>
<label for="llmProviderSelect">Provider:</label>
<select id="llmProviderSelect">
<option value="ollama">Ollama</option>
<option value="openai">OpenAI</option>
</select>
<label for="llmBaseUrlInput">Base URL:</label>
<input type="text" id="llmBaseUrlInput" placeholder="输入API基础URL" value="http://localhost:11434">
<label for="llmModelInput">Model:</label>
<input type="text" id="llmModelInput" placeholder="输入模型名称" value="qwen3.5:9b">
<label for="llmApiKeyInput">API Key:</label>
<input type="password" id="llmApiKeyInput" placeholder="输入API密钥(如果需要)">
<button id="saveLlmConfigBtn" class="btn">💾 保存配置</button>
<button id="closeLlmConfigBtn" class="btn cancel-btn" onclick="toggleLLMConfig()">❌ 关闭</button>
</div>
</div>
<!-- 标签页导航 -->
<div class="tab">
<button class="tablinks active" onclick="openTab(event, 'company')">企业行业分析</button>
<button class="tablinks" onclick="openTab(event, 'excel')">Excel解析</button>
<button class="tablinks" onclick="openTab(event, 'llm')">AI分析</button>
<button class="tablinks" onclick="openTab(event, 'tax')">税务健康</button>
</div>
<!-- 企业行业分析标签页 -->
<div id="company" class="tabcontent" style="display: block;">
<div class="section">
<label for="companyName">🔍 请输入企业全称:</label>
<input type="text" id="companyName" placeholder="例如:深圳市致远速联信息技术有限公司" value="深圳市致远速联信息技术有限公司">
<button id="analyzeCompanyBtn" disabled>分析企业行业</button>
</div>
</div>
<!-- Excel解析标签页 -->
<div id="excel" class="tabcontent">
<div class="section">
<label for="excelFile">📁 请选择Excel文件:</label>
<input type="file" id="excelFile" accept=".xlsx,.xls">
<button id="parseExcelBtn" disabled>解析Excel文件</button>
</div>
</div>
<!-- AI分析标签页 -->
<div id="llm" class="tabcontent">
<div class="section">
<label for="llmPrompt">💬 请输入分析提示:</label>
<textarea id="llmPrompt" rows="4" placeholder="请输入您想要分析的内容...">请分析以下企业数据并给出建议</textarea>
<button id="callLLMBtn" disabled>调用AI分析</button>
</div>
</div>
<!-- 税务健康标签页 -->
<div id="tax" class="tabcontent">
<div class="section">
<h3>📊 税务健康评估参数</h3>
<label for="companyNameInput">🏢 企业名称:</label>
<input type="text" id="companyNameInput" placeholder="请输入企业全称" value="企业名称">
<label for="periodInput">📅 测评周期:</label>
<select id="periodInput">
<option value="Q1">第一季度</option>
<option value="Q2">第二季度</option>
<option value="Q3">第三季度</option>
<option value="Q4">第四季度</option>
<option value="年度">年度</option>
</select>
<label for="yearInput">📅 报告期:</label>
<input type="number" id="yearInput" placeholder="年份" value="2025" min="1900" max="2100">
<label for="citInput">💰 企业所得税应纳税额合计 (万元):</label>
<input type="number" id="citInput" placeholder="单位:万元" value="100.0" step="0.01">
<label for="vatInput">💰 增值税应纳税额合计 (万元):</label>
<input type="number" id="vatInput" placeholder="单位:万元" value="50.0" step="0.01">
<label for="inputVatInput">💰 增值税进项税额 (万元):</label>
<input type="number" id="inputVatInput" placeholder="单位:万元" value="30.0" step="0.01">
<label for="outputVatInput">💰 增值税销项税额 (万元):</label>
<input type="number" id="outputVatInput" placeholder="单位:万元" value="80.0" step="0.01">
<label for="preCitInput">💰 上一期企业所得税应纳税额合计 (万元):</label>
<input type="number" id="preCitInput" placeholder="单位:万元" value="90.0" step="0.01">
<label for="preVatInput">💰 上一期增值税应纳税额合计 (万元):</label>
<input type="number" id="preVatInput" placeholder="单位:万元" value="45.0" step="0.01">
<label for="preInputVatInput">💰 上一期增值税进项税额 (万元):</label>
<input type="number" id="preInputVatInput" placeholder="单位:万元" value="25.0" step="0.01">
<label for="preOutputVatInput">💰 上一期增值税销项税额 (万元):</label>
<input type="number" id="preOutputVatInput" placeholder="单位:万元" value="70.0" step="0.01">
<label for="excelFileInput">📁 上传Excel财务报表 (可选):</label>
<input type="file" id="excelFileInput" accept=".xlsx,.xls">
<label for="taxJsonInput">📄 或者直接粘贴JSON数据:</label>
<textarea id="taxJsonInput" rows="4" placeholder='粘贴财务报表JSON数据'>{"LC0000003E_T0I0331": 741213833.14, "LC0000003E_T0I0101": 578064138.06}</textarea>
<button id="submitTaxBtn" disabled>提交税务评估</button>
<button id="queryResultBtn" disabled style="background: linear-gradient(45deg, #4CAF50, #8BC34A);">查询评估结果</button>
<div style="margin-top: 15px;">
<label for="orderNoInput">📋 订单号 (用于查询):</label>
<input type="text" id="orderNoInput" placeholder="输入订单号查询结果">
</div>
</div>
</div>
<div class="loading" id="loading">
<p>🔄 正在处理请求...请稍候</p>
</div>
<div class="error" id="error"></div>
<div class="result-section" id="resultSection">
<h2>📊 分析结果</h2>
<div id="resultContent"></div>
</div>
</div>
<footer>
<p>Powered by WebAssembly & Go | 企业分析工具套件 v1.0</p>
</footer>
<!-- 加载WASM运行时 -->
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
// WASM加载完成后启用所有按钮
document.getElementById('analyzeCompanyBtn').disabled = false;
document.getElementById('parseExcelBtn').disabled = false;
document.getElementById('callLLMBtn').disabled = false;
document.getElementById('submitTaxBtn').disabled = false;
document.getElementById('queryResultBtn').disabled = false;
console.log('WASM模块加载完成');
}).catch((err) => {
console.error('WASM加载失败:', err);
showError('WASM模块加载失败: ' + err.message);
});
// 获取DOM元素
const analyzeCompanyBtn = document.getElementById('analyzeCompanyBtn');
const parseExcelBtn = document.getElementById('parseExcelBtn');
const callLLMBtn = document.getElementById('callLLMBtn');
const companyNameInput = document.getElementById('companyName');
const excelFileInput = document.getElementById('excelFile');
const llmPromptInput = document.getElementById('llmPrompt');
const resultSection = document.getElementById('resultSection');
const resultContent = document.getElementById('resultContent');
const loadingDiv = document.getElementById('loading');
const errorDiv = document.getElementById('error');
// 企业行业分析按钮事件
analyzeCompanyBtn.addEventListener('click', async () => {
const companyName = companyNameInput.value.trim();
if (!companyName) {
showError('请输入企业名称');
return;
}
showLoading(true);
hideError();
resultSection.classList.remove('show');
try {
// 获取当前LLM配置
const llmConfig = getCurrentLLMConfig();
const result = await window.analyzeCompanyIndustryAsync(companyName, JSON.stringify(llmConfig));
if (result && result.error) {
showError(result.error);
} else {
displayResults('企业行业分析结果', result);
}
} catch (error) {
showError('分析过程中发生错误: ' + error.message);
} finally {
showLoading(false);
}
});
// Excel解析按钮事件
parseExcelBtn.addEventListener('click', async () => {
const file = excelFileInput.files[0];
if (!file) {
showError('请选择一个Excel文件');
return;
}
showLoading(true);
hideError();
resultSection.classList.remove('show');
try {
// 读取文件为ArrayBuffer
const arrayBuffer = await file.arrayBuffer();
// 调用WASM中的解析函数
const result = await window.parseExcelAsync(arrayBuffer);
if (result && result.error) {
showError(result.error);
} else {
displayResults('Excel解析结果', result);
}
} catch (error) {
showError('解析Excel过程中发生错误: ' + error.message);
} finally {
showLoading(false);
}
});
// AI分析按钮事件
callLLMBtn.addEventListener('click', async () => {
const prompt = llmPromptInput.value.trim();
if (!prompt) {
showError('请输入分析提示');
return;
}
showLoading(true);
hideError();
resultSection.classList.remove('show');
try {
// 获取当前LLM配置
const llmConfig = getCurrentLLMConfig();
// 调用大模型
const result = await window.callLLMAsync(prompt, JSON.stringify(llmConfig));
if (result && result.error) {
showError('调用大模型失败: ' + result.error);
} else {
// 显示结果
displayResults('大模型调用结果', result);
}
} catch (error) {
showError('AI分析过程中发生错误: ' + error.message);
} finally {
showLoading(false);
}
});
// 税务健康提交按钮事件
const submitTaxBtn = document.getElementById('submitTaxBtn');
const queryResultBtn = document.getElementById('queryResultBtn');
const taxCompanyNameInput = document.getElementById('companyNameInput');
const periodInput = document.getElementById('periodInput');
const yearInput = document.getElementById('yearInput');
const citInput = document.getElementById('citInput');
const vatInput = document.getElementById('vatInput');
const inputVatInput = document.getElementById('inputVatInput');
const outputVatInput = document.getElementById('outputVatInput');
const preCitInput = document.getElementById('preCitInput');
const preVatInput = document.getElementById('preVatInput');
const preInputVatInput = document.getElementById('preInputVatInput');
const preOutputVatInput = document.getElementById('preOutputVatInput');
const taxExcelFileInput = document.getElementById('excelFileInput');
const taxJsonInput = document.getElementById('taxJsonInput');
const orderNoInput = document.getElementById('orderNoInput');
submitTaxBtn.addEventListener('click', async () => {
// 收集所有输入的参数
const companyName = taxCompanyNameInput.value.trim();
const period = periodInput.value;
const year = yearInput.value;
const cit = parseFloat(citInput.value) || 0;
const vat = parseFloat(vatInput.value) || 0;
const inputVat = parseFloat(inputVatInput.value) || 0;
const outputVat = parseFloat(outputVatInput.value) || 0;
const preCit = parseFloat(preCitInput.value) || 0;
const preVat = parseFloat(preVatInput.value) || 0;
const preInputVat = parseFloat(preInputVatInput.value) || 0;
const preOutputVat = parseFloat(preOutputVatInput.value) || 0;
const jsonData = taxJsonInput.value.trim();
if (!companyName) {
showError('请输入企业名称');
return;
}
if (!year || isNaN(year)) {
showError('请输入有效的年份');
return;
}
showLoading(true);
hideError();
resultSection.classList.remove('show');
try {
// 构建请求数据
let requestData = {
req_no: 'REQ' + Date.now().toString(),
company_name: companyName,
period: period,
year: year.toString(),
cit: cit,
vat: vat,
input_vat: inputVat,
output_vat: outputVat,
pre_cit: preCit,
pre_vat: preVat,
pre_input_vat: preInputVat,
pre_output_vat: preOutputVat
};
// 处理Excel文件或JSON数据
if (taxExcelFileInput.files.length > 0) {
// 如果用户选择了Excel文件,需要先解析它并通过LLM转换为JSON
const file = taxExcelFileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// 获取期间参数
const period = periodInput.value;
// 获取当前LLM配置
const llmConfig = getCurrentLLMConfig();
// 使用新的函数将Excel数据通过LLM转换为JSON格式,传入期间参数和配置
const conversionResult = await window.convertExcelToJsonViaLLM(arrayBuffer, period, JSON.stringify(llmConfig));
// 检查转换结果是否包含错误
if (conversionResult && conversionResult.error) {
showError('Excel转JSON过程中发生错误: ' + conversionResult.error);
return;
}
if (conversionResult && conversionResult.error) {
showError('Excel转JSON过程中发生错误: ' + conversionResult.error);
return;
}
// 优先使用转换后的JSON数据
if (conversionResult.json_data) {
requestData.data = conversionResult.json_data;
} else if (conversionResult.parsed_json) {
// 如果有解析后的JSON字符串,尝试解析它
try {
requestData.data = JSON.parse(conversionResult.parsed_json);
} catch (e) {
console.warn('无法解析LLM返回的JSON,使用原始响应:', e);
// 如果解析失败,使用原始响应作为数据
requestData.data = conversionResult;
}
} else {
showError('Excel转JSON失败,未获得有效数据');
return;
}
} else if (jsonData) {
// 如果提供了JSON数据
try {
const parsedData = JSON.parse(jsonData);
requestData.data = parsedData;
} catch (e) {
showError('JSON数据格式不正确: ' + e.message);
return;
}
} else {
showError('请上传Excel文件或提供JSON数据');
return;
}
// 首先调用税务健康API获取订单号
const result = await window.callTaxHealthAsync(JSON.stringify(requestData));
if (result && result.error) {
showError(result.error);
return;
}
// 显示初始结果并开始轮询
displayResults('税务健康评估提交结果', result);
// 自动填充订单号到查询框
if (result.order_no) {
orderNoInput.value = result.order_no;
// 开始轮询查询结果
console.log('开始轮询查询结果...');
let attempts = 0;
const maxAttempts = 60; // 最多轮询60次
const pollForResult = async () => {
if (attempts >= maxAttempts) {
console.log('轮询超时');
return;
}
try {
const pollResult = await window.queryTaxResultAsync(result.order_no);
if (pollResult && pollResult.error) {
showError('查询结果时发生错误: ' + pollResult.error);
return;
}
const queryResponse = pollResult.query_response;
console.log(`轮询结果 - 状态码: ${queryResponse.code}, 订单状态: ${queryResponse.data.status}`);
// 根据状态码判断处理结果
switch (queryResponse.data.status) {
case 99: // 执行成功
console.log('税务评估已完成!');
displayResults('税务评估最终结果', pollResult);
// 显示结果文件地址
if (queryResponse.data.detail && queryResponse.data.detail.files) {
console.log('结果文件地址:', queryResponse.data.detail.files);
}
return;
case 0: // 正在执行
console.log(`任务仍在处理中... (${attempts + 1}/${maxAttempts})`);
attempts++;
setTimeout(pollForResult, 5000); // 5秒后再次查询
break;
case -1: // 无效订单
showError(`订单无效: ${queryResponse.data.detail?.error || '未知错误'}`);
return;
case 98: // 执行失败
showError(`任务执行失败: ${queryResponse.data.detail?.error || '未知错误'}`);
return;
default:
console.log(`未知状态码: ${queryResponse.data.status}`);
attempts++;
setTimeout(pollForResult, 5000);
break;
}
} catch (error) {
showError('轮询过程中发生错误: ' + error.message);
}
};
// 开始轮询
setTimeout(pollForResult, 5000);
}
} catch (error) {
showError('税务健康评估过程中发生错误: ' + error.message);
} finally {
showLoading(false);
}
});
// 查询税务评估结果按钮事件
queryResultBtn.addEventListener('click', async () => {
const orderNo = orderNoInput.value.trim();
if (!orderNo) {
showError('请输入订单号');
return;
}
showLoading(true);
hideError();
resultSection.classList.remove('show');
try {
const result = await window.queryTaxResultAsync(orderNo);
if (result && result.error) {
showError(result.error);
} else {
displayResults('税务评估查询结果', result);
}
} catch (error) {
showError('查询税务评估结果过程中发生错误: ' + error.message);
} finally {
showLoading(false);
}
});
// 显示加载状态
function showLoading(show) {
if (show) {
loadingDiv.classList.add('show');
// 禁用所有按钮以防止重复点击
analyzeCompanyBtn.disabled = true;
parseExcelBtn.disabled = true;
callLLMBtn.disabled = true;
submitTaxBtn.disabled = true;
queryResultBtn.disabled = true;
} else {
loadingDiv.classList.remove('show');
// 重新启用按钮(但保持初始状态由WASM加载决定)
// 这里简单地重新启用
setTimeout(() => {
analyzeCompanyBtn.disabled = false;
parseExcelBtn.disabled = false;
callLLMBtn.disabled = false;
submitTaxBtn.disabled = false;
queryResultBtn.disabled = false;
}, 100);
}
}
// 显示错误信息
function showError(message) {
errorDiv.textContent = message;
errorDiv.classList.add('show');
}
// 隐藏错误信息
function hideError() {
errorDiv.classList.remove('show');
}
// 显示结果
function displayResults(title, result) {
if (!result) {
showError('未能获取分析结果');
return;
}
let html = `<div class="result-item"><h3>${title}</h3>`;
// 格式化输出结果
html += '<pre>' + JSON.stringify(result, null, 2) + '</pre>';
html += '</div>';
resultContent.innerHTML = html;
resultSection.classList.add('show');
}
// 切换LLM配置面板显示/隐藏
function toggleLLMConfig() {
const panel = document.getElementById('llmConfigPanel');
const isActive = panel.classList.contains('active');
if (isActive) {
panel.classList.remove('active');
} else {
panel.classList.add('active');
}
}
// 保存LLM配置
document.addEventListener('DOMContentLoaded', function() {
const saveLlmConfigBtn = document.getElementById('saveLlmConfigBtn');
if (saveLlmConfigBtn) {
saveLlmConfigBtn.addEventListener('click', function() {
const provider = document.getElementById('llmProviderSelect').value;
const baseUrl = document.getElementById('llmBaseUrlInput').value;
const model = document.getElementById('llmModelInput').value;
const apiKey = document.getElementById('llmApiKeyInput').value;
// 保存配置到localStorage
const llmConfig = {
provider: provider,
base_url: baseUrl,
model: model,
api_key: apiKey
};
localStorage.setItem('llmConfig', JSON.stringify(llmConfig));
alert('LLM配置已保存!');
});
}
});
// 从localStorage加载LLM配置
function loadLLMConfig() {
const savedConfig = localStorage.getItem('llmConfig');
if (savedConfig) {
try {
const config = JSON.parse(savedConfig);
if (document.getElementById('llmProviderSelect')) {
document.getElementById('llmProviderSelect').value = config.provider || 'ollama';
}
if (document.getElementById('llmBaseUrlInput')) {
document.getElementById('llmBaseUrlInput').value = config.base_url || 'http://localhost:11434';
}
if (document.getElementById('llmModelInput')) {
document.getElementById('llmModelInput').value = config.model || 'qwen3.5:9b';
}
if (document.getElementById('llmApiKeyInput')) {
document.getElementById('llmApiKeyInput').value = config.api_key || '';
}
} catch (e) {
console.error('加载LLM配置失败:', e);
}
}
}
// 在页面加载完成后初始化LLM配置
document.addEventListener('DOMContentLoaded', function() {
loadLLMConfig();
});
// 获取当前LLM配置
function getCurrentLLMConfig() {
const savedConfig = localStorage.getItem('llmConfig');
if (savedConfig) {
try {
return JSON.parse(savedConfig);
} catch (e) {
console.error('解析LLM配置失败:', e);
}
}
// 返回默认配置
return {
provider: 'ollama',
base_url: 'http://localhost:11434',
model: 'qwen3.5:9b',
api_key: ''
};
}
// 标签页功能
function openTab(evt, tabName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
document.getElementById(tabName).style.display = "block";
evt.currentTarget.className += " active";
}
// 回车键触发当前活动标签页的分析
document.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
const activeTab = document.querySelector('.tabcontent[style*="block"]');
if (activeTab.id === 'company') {
analyzeCompanyBtn.click();
} else if (activeTab.id === 'llm') {
callLLMBtn.click();
} else if (activeTab.id === 'tax') {
submitTaxBtn.click();
}
}
});
</script>
</body>
</html>