feat: 增强 AI 入库预处理功能,支持联网补全和来源展示
This commit is contained in:
@@ -80,6 +80,10 @@
|
||||
<form method="post" id="quick-inbound-form" action="{% if box.box_type == 'bag' %}{{ url_for('add_bag_items_batch', box_id=box.id) }}{% else %}{{ url_for('quick_inbound', box_id=box.id) }}{% endif %}">
|
||||
<input type="hidden" id="ai-inbound-mode" value="{% if box.box_type == 'bag' %}bag{% else %}box{% endif %}">
|
||||
<textarea class="batch-input" id="quick-inbound-lines" name="lines" rows="8" placeholder="10K-0603, 电阻10K 0603, 500, 1%, 常用\n100nF-0603, 电容100nF 0603, 300, 50V X7R, 去耦"></textarea>
|
||||
<label>
|
||||
<input type="checkbox" id="ai-inbound-web-search" checked>
|
||||
联网补全(适合只有简短描述、来源非嘉立创的物料)
|
||||
</label>
|
||||
<p class="hint">建议: part_no 用厂家型号,name 用品类+型号,specification 只写关键参数。</p>
|
||||
<p class="hint" id="ai-inbound-status" aria-live="polite"></p>
|
||||
<section class="ai-preview" id="ai-inbound-preview" hidden>
|
||||
@@ -102,12 +106,24 @@
|
||||
</section>
|
||||
<div class="actions">
|
||||
<button class="btn btn-light" type="button" id="ai-inbound-parse-btn">AI预处理并预览</button>
|
||||
<button class="btn btn-light" type="button" id="ai-inbound-show-sources-btn" disabled>查看补全来源</button>
|
||||
<button class="btn btn-light" type="button" id="ai-inbound-export-invalid-btn" disabled>导出异常行</button>
|
||||
<button class="btn" type="submit">确认导入</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-backdrop" id="ai-inbound-sources-modal" hidden>
|
||||
<div class="modal-card panel" role="dialog" aria-modal="true" aria-labelledby="ai-inbound-sources-title">
|
||||
<div class="group-title-row">
|
||||
<h2 id="ai-inbound-sources-title">联网补全来源明细</h2>
|
||||
<button class="btn btn-light" type="button" id="close-ai-inbound-sources">关闭</button>
|
||||
</div>
|
||||
<p class="hint">仅作为补全参考,请以实物参数、数据手册或采购页面为准。</p>
|
||||
<div id="ai-inbound-sources-body" class="ai-source-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<aside class="entry-sidebar">
|
||||
@@ -242,15 +258,21 @@
|
||||
|
||||
(function () {
|
||||
var parseBtn = document.getElementById('ai-inbound-parse-btn');
|
||||
var showSourcesBtn = document.getElementById('ai-inbound-show-sources-btn');
|
||||
var sourcesModal = document.getElementById('ai-inbound-sources-modal');
|
||||
var closeSourcesBtn = document.getElementById('close-ai-inbound-sources');
|
||||
var sourcesBody = document.getElementById('ai-inbound-sources-body');
|
||||
var exportInvalidBtn = document.getElementById('ai-inbound-export-invalid-btn');
|
||||
var textarea = document.getElementById('quick-inbound-lines');
|
||||
var modeInput = document.getElementById('ai-inbound-mode');
|
||||
var webSearchInput = document.getElementById('ai-inbound-web-search');
|
||||
var status = document.getElementById('ai-inbound-status');
|
||||
var preview = document.getElementById('ai-inbound-preview');
|
||||
var previewBody = document.getElementById('ai-inbound-preview-body');
|
||||
var latestRows = [];
|
||||
var latestWebContext = [];
|
||||
|
||||
if (!parseBtn || !textarea || !status || !preview || !previewBody || !exportInvalidBtn) {
|
||||
if (!parseBtn || !textarea || !status || !preview || !previewBody || !exportInvalidBtn || !showSourcesBtn || !sourcesBody) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -302,6 +324,79 @@
|
||||
preview.hidden = false;
|
||||
}
|
||||
|
||||
function renderWebContext(contextRows) {
|
||||
latestWebContext = Array.isArray(contextRows) ? contextRows : [];
|
||||
showSourcesBtn.disabled = latestWebContext.length <= 0;
|
||||
|
||||
if (!latestWebContext.length) {
|
||||
sourcesBody.innerHTML = '<p class="hint">当前没有联网补全来源可展示。</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
var html = latestWebContext.map(function (lineRow) {
|
||||
var lineNo = lineRow.line_no || '-';
|
||||
var query = escapeHtml(lineRow.query || '');
|
||||
var sources = Array.isArray(lineRow.sources) ? lineRow.sources : [];
|
||||
var sourceHtml = sources.map(function (src) {
|
||||
var title = escapeHtml(src.title || '未命名来源');
|
||||
var snippet = escapeHtml(src.snippet || '');
|
||||
var url = (src.url || '').trim();
|
||||
var reliabilityLevel = (src.reliability_level || 'medium').toLowerCase();
|
||||
var reliabilityLabel = escapeHtml(src.reliability_label || '中可信');
|
||||
var reliabilityReason = escapeHtml(src.reliability_reason || '来源类型未知,建议人工确认');
|
||||
var domain = escapeHtml(src.domain || '未知域名');
|
||||
var link = url ? '<a href="' + escapeHtml(url) + '" target="_blank" rel="noopener">打开来源</a>' : '<span class="muted">无链接</span>';
|
||||
return '<li>'
|
||||
+ '<div class="source-head"><strong>' + title + '</strong><span class="source-badge source-' + reliabilityLevel + '">' + reliabilityLabel + '</span></div>'
|
||||
+ '<p>' + snippet + '</p>'
|
||||
+ '<p class="hint">依据: ' + reliabilityReason + '</p>'
|
||||
+ '<p class="hint">域名: ' + domain + '</p>'
|
||||
+ link
|
||||
+ '</li>';
|
||||
}).join('');
|
||||
|
||||
if (!sourceHtml) {
|
||||
sourceHtml = '<li><span class="muted">无可用来源</span></li>';
|
||||
}
|
||||
|
||||
return '<section class="panel">'
|
||||
+ '<h3>第 ' + escapeHtml(lineNo) + ' 行</h3>'
|
||||
+ '<p class="hint">检索词: ' + query + '</p>'
|
||||
+ '<ul class="ai-source-items">' + sourceHtml + '</ul>'
|
||||
+ '</section>';
|
||||
}).join('');
|
||||
|
||||
sourcesBody.innerHTML = html;
|
||||
}
|
||||
|
||||
function closeSourcesModal() {
|
||||
if (!sourcesModal) {
|
||||
return;
|
||||
}
|
||||
sourcesModal.hidden = true;
|
||||
document.body.classList.remove('modal-open');
|
||||
}
|
||||
|
||||
showSourcesBtn.addEventListener('click', function () {
|
||||
if (!sourcesModal || showSourcesBtn.disabled) {
|
||||
return;
|
||||
}
|
||||
sourcesModal.hidden = false;
|
||||
document.body.classList.add('modal-open');
|
||||
});
|
||||
|
||||
if (closeSourcesBtn) {
|
||||
closeSourcesBtn.addEventListener('click', closeSourcesModal);
|
||||
}
|
||||
|
||||
if (sourcesModal) {
|
||||
sourcesModal.addEventListener('click', function (event) {
|
||||
if (event.target === sourcesModal) {
|
||||
closeSourcesModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
parseBtn.addEventListener('click', function () {
|
||||
var lines = (textarea.value || '').trim();
|
||||
if (!lines) {
|
||||
@@ -311,6 +406,7 @@
|
||||
}
|
||||
|
||||
parseBtn.disabled = true;
|
||||
showSourcesBtn.disabled = true;
|
||||
exportInvalidBtn.disabled = true;
|
||||
status.textContent = '正在进行 AI 预处理...';
|
||||
status.classList.remove('ok');
|
||||
@@ -318,6 +414,7 @@
|
||||
var payload = new URLSearchParams();
|
||||
payload.set('lines', lines);
|
||||
payload.set('mode', modeInput ? modeInput.value : 'box');
|
||||
payload.set('use_web_search', webSearchInput && webSearchInput.checked ? '1' : '0');
|
||||
|
||||
fetch('{{ url_for('ai_inbound_parse') }}', {
|
||||
method: 'POST',
|
||||
@@ -334,6 +431,7 @@
|
||||
});
|
||||
}).then(function (data) {
|
||||
renderRows(data.rows || []);
|
||||
renderWebContext(data.web_context || []);
|
||||
if (data.normalized_lines) {
|
||||
textarea.value = data.normalized_lines;
|
||||
}
|
||||
@@ -416,6 +514,12 @@
|
||||
status.textContent = '已导出异常行 ' + invalidRows.length + ' 条';
|
||||
status.classList.add('ok');
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
if (event.key === 'Escape') {
|
||||
closeSourcesModal();
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user