增加生成学校易耗品填写的转换程序

This commit is contained in:
wandering
2026-08-31 18:25:35 +08:00
parent 44496a54e6
commit 4fbb4c36ed
19 changed files with 777 additions and 365 deletions
+52 -14
View File
@@ -6,6 +6,15 @@
import { escapeHtml } from '../utils.js';
import { getChatMessages, scrollToBottom } from './renderer.js';
/**
* 判断用户是否在聊天底部附近(阈值 150px),用于流式传输时决定是否自动滚动
*/
function _isNearBottom() {
const el = getChatMessages();
if (!el) return true;
return el.scrollHeight - el.scrollTop - el.clientHeight < 150;
}
/**
* 当前活跃的 LLM 流式气泡状态
*/
@@ -108,7 +117,9 @@ function _appendLLMStreamChunk(text) {
llmStreamState.accumulated += text;
llmStreamState.textContent.textContent = llmStreamState.accumulated;
scrollToBottom();
if (_isNearBottom()) {
scrollToBottom();
}
}
/**
@@ -119,7 +130,9 @@ function _appendLLMStreamReasoning(text) {
llmStreamState.reasoningAccumulated += text;
llmStreamState.reasoningContent.textContent = llmStreamState.reasoningAccumulated;
scrollToBottom();
if (_isNearBottom()) {
scrollToBottom();
}
}
/**
@@ -239,19 +252,44 @@ function _buildExtractionSummary(data) {
const container = document.createElement('div');
container.className = 'extraction-summary';
// 全局状态
const statusSection = _summarySection('状态');
const submitOk = data.can_submit;
_summaryRow(statusSection, '可提交', submitOk ? '是' : '否');
if (data.suggestion) {
_summaryRow(statusSection, '建议', data.suggestion);
}
container.appendChild(statusSection);
// 判断类型:差旅 vs 普通
const isTravel = !!(data.basic_info?.travel_purpose || data.reimbursement_details?.transport_fee);
// 基本信息
if (data.basic_info) {
const bi = data.basic_info;
const section = _summarySection('基本信息');
_summaryRow(section, '出差事由', bi.travel_purpose || '');
_summaryRow(section, '出差地点', bi.travel_location || '');
const dates = bi.start_date && bi.end_date ? `${bi.start_date} 至 ${bi.end_date}` : (bi.start_date || bi.end_date || '');
_summaryRow(section, '出差日期', dates);
if (isTravel) {
_summaryRow(section, '出差事由', bi.travel_purpose || '');
_summaryRow(section, '出差地点', bi.travel_location || '');
const dates = bi.start_date && bi.end_date ? `${bi.start_date} 至 ${bi.end_date}` : (bi.start_date || bi.end_date || '');
_summaryRow(section, '出差日期', dates);
} else {
_summaryRow(section, '报销说明', bi.reimbursement_description || '');
}
container.appendChild(section);
}
// 交通费
if (data.reimbursement_details?.transport_fee?.length) {
// 报销汇总(普通模式)
if (!isTravel && data.reimbursement_details) {
const rd = data.reimbursement_details;
const section = _summarySection('报销汇总');
_summaryRow(section, '发票总份数', rd.total_invoices != null ? String(rd.total_invoices) : '');
_summaryRow(section, '总金额', rd.total_amount != null ? `¥${rd.total_amount.toFixed(2)}` : '');
container.appendChild(section);
}
// 交通费(差旅模式)
if (isTravel && data.reimbursement_details?.transport_fee?.length) {
const section = _summarySection('交通费');
const table = _summaryTable(['日期', '出发', '到达', '金额', '备注']);
for (const item of data.reimbursement_details.transport_fee) {
@@ -267,8 +305,8 @@ function _buildExtractionSummary(data) {
container.appendChild(section);
}
// 住宿费
if (data.reimbursement_details?.hotel_fee?.length) {
// 住宿费(差旅模式)
if (isTravel && data.reimbursement_details?.hotel_fee?.length) {
const section = _summarySection('住宿费');
const table = _summaryTable(['入住日期', '离店日期', '天数', '发票金额', '报销金额', '备注']);
for (const item of data.reimbursement_details.hotel_fee) {
@@ -285,8 +323,8 @@ function _buildExtractionSummary(data) {
container.appendChild(section);
}
// 会议/培训费
if (data.reimbursement_details?.conference_fee?.length) {
// 会议/培训费(差旅模式)
if (isTravel && data.reimbursement_details?.conference_fee?.length) {
const section = _summarySection('会议/培训费');
const table = _summaryTable(['日期', '金额', '备注']);
for (const item of data.reimbursement_details.conference_fee) {
@@ -316,8 +354,8 @@ function _buildExtractionSummary(data) {
container.appendChild(section);
}
// 补助
if (data.subsidy_list?.length) {
// 补助(差旅模式)
if (isTravel && data.subsidy_list?.length) {
const section = _summarySection('补助');
const table = _summaryTable(['姓名', '开始日期', '结束日期', '天数']);
for (const item of data.subsidy_list) {