v1.7.0 历史记录标注调用者/调用方式 + 每次提取自动按月归档原始HTML + 修复agent-browser HTML JSON转义bug
- 历史记录新增 caller(调用者: 游客/项目名) 与 call_method(调用方式: web/api)
* 请求体 caller 或请求头 X-Caller/X-Project/X-App 标识调用者, 默认游客
* 请求体 call_method 或 X-From 标识方式, 缺省按 Referer 自动判定(本前端=web, 否则api)
* 前端提取请求带 X-From:web / X-Caller:游客; news-tracker 调用带 caller=news-tracker
- 每次提取后自动保存最原始 HTML 到 data/html/<YYYY-MM>/ 按月目录归档
* screenshot/html/text/smart 四种动作均顺带抓取原始HTML并落盘
* 历史详情新增 📄原始HTML文件 链接(GET /api/history/<id>/html), 删除记录连带删文件
- 修复: agent-browser 后端 html 提取返回 JSON 转义文本(非最原始HTML)的bug, 现解码为干净HTML
This commit is contained in:
+34
-4
@@ -370,6 +370,16 @@
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.badge-api {
|
||||
background: #ede7f6;
|
||||
color: #5e35b1;
|
||||
}
|
||||
|
||||
.badge-web {
|
||||
background: #e0f7fa;
|
||||
color: #00695c;
|
||||
}
|
||||
|
||||
.history-url {
|
||||
max-width: 280px;
|
||||
overflow: hidden;
|
||||
@@ -556,7 +566,9 @@
|
||||
.history-table th:nth-child(2),
|
||||
.history-table td:nth-child(2),
|
||||
.history-table th:nth-child(3),
|
||||
.history-table td:nth-child(3) {
|
||||
.history-table td:nth-child(3),
|
||||
.history-table th:nth-child(4),
|
||||
.history-table td:nth-child(4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -693,6 +705,8 @@
|
||||
<tr>
|
||||
<th>时间</th>
|
||||
<th>类型</th>
|
||||
<th>调用者</th>
|
||||
<th>方式</th>
|
||||
<th>网址</th>
|
||||
<th>标题</th>
|
||||
<th>状态</th>
|
||||
@@ -717,7 +731,8 @@
|
||||
<li>⏱️ <strong>页面加载等待</strong>:某些网站需要验证过程(如 Cloudflare),请设置较长时间(10000-30000ms)</li>
|
||||
<li>🔄 <strong>滚动次数</strong>:用于加载动态内容(如微博、推特等),建议 3-5 次</li>
|
||||
<li>🎯 <strong>全页截图</strong>:滚动加载后建议开启此选项</li>
|
||||
<li>📜 <strong>提取历史</strong>:每次提取自动入库,支持分页浏览、按类型筛选、搜索与删除</li>
|
||||
<li>📜 <strong>提取历史</strong>:每次提取自动入库,支持分页浏览、按类型筛选、搜索与删除;每条记录会标注<strong>调用者</strong>(游客/项目名)与<strong>调用方式</strong>(web/api),并自动把<strong>最原始 HTML</strong> 按月归档到 <code>data/html/<月份>/</code>(详情里可点「📄 原始HTML文件」查看)</li>
|
||||
<li>👤 <strong>API 调用方标识</strong>:请求体带 <code>caller</code>(或请求头 <code>X-Caller</code>/<code>X-Project</code>)即可在历史里显示项目名;带 <code>call_method</code> 或 <code>X-From</code> 标注调用方式,缺省按 Referer 自动判定 web/api</li>
|
||||
</ul>
|
||||
<p style="margin-top: 15px;"><strong>API 调用:</strong></p>
|
||||
<pre><code>POST /api/capture
|
||||
@@ -729,6 +744,8 @@
|
||||
"scroll_delay": 1000, // 可选:滚动间隔
|
||||
"full_page": true, // 可选:全页截图
|
||||
"backend": "playwright", // 可选:playwright / agent-browser
|
||||
"caller": "news-tracker", // 可选:调用者标识(历史记录里显示,默认游客)
|
||||
"call_method": "api", // 可选:调用方式 web/api(缺省自动判定)
|
||||
"viewport": {"width":1280,"height":700},
|
||||
"smart_config": { // 可选:临时覆盖按需截图 LLM 配置
|
||||
"base_url": "https://www.autodl.art/api/v1",
|
||||
@@ -957,7 +974,9 @@ DELETE /api/history/<id> // 删除历史</code></pre>
|
||||
const response = await fetch('/api/capture', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
'X-From': 'web',
|
||||
'X-Caller': '游客'
|
||||
},
|
||||
body: JSON.stringify(currentData)
|
||||
});
|
||||
@@ -1111,9 +1130,14 @@ DELETE /api/history/<id> // 删除历史</code></pre>
|
||||
const statusText = r.status === 'failed'
|
||||
? `<span style="color:#c62828;" title="${escapeHtml(r.error || '')}">失败</span>`
|
||||
: '<span style="color:#2e7d32;">成功</span>';
|
||||
const callerText = r.caller || '游客';
|
||||
const methodText = r.call_method || 'api';
|
||||
const methodBadge = methodText === 'web' ? 'badge-web' : 'badge-api';
|
||||
return `<tr>
|
||||
<td style="white-space:nowrap;">${escapeHtml(r.created_at)}</td>
|
||||
<td><span class="badge ${escapeHtml(badgeClass)}">${badgeText}</span></td>
|
||||
<td><span class="history-title" title="${escapeHtml(callerText)}">${escapeHtml(callerText)}</span></td>
|
||||
<td><span class="badge ${methodBadge}" style="font-size:11px;padding:2px 8px;">${escapeHtml(methodText)}</span></td>
|
||||
<td><a class="history-url" href="${escapeHtml(r.url)}" target="_blank" rel="noopener">${escapeHtml(r.url)}</a></td>
|
||||
<td><span class="history-title" title="${escapeHtml(r.title || '')}">${escapeHtml(r.title || '—')}</span></td>
|
||||
<td>${statusText}</td>
|
||||
@@ -1173,11 +1197,17 @@ DELETE /api/history/<id> // 删除历史</code></pre>
|
||||
document.getElementById('modalTitle').textContent = (r.title || r.url || '记录详情');
|
||||
const badgeClass = r.status === 'failed' ? 'badge-failed' : ('badge-' + r.action);
|
||||
const badgeText = r.status === 'failed' ? '❌ 失败' : ({screenshot: '📸 截图', html: '📄 HTML', text: '📝 文本'}[r.action] || r.action);
|
||||
const htmlLink = r.html_path
|
||||
? `<span><a href="/api/history/${r.id}/html" target="_blank" style="color:#667eea;font-weight:600;" title="${escapeHtml(r.html_path)}">📄 原始HTML文件</a></span>`
|
||||
: '';
|
||||
document.getElementById('modalMeta').innerHTML =
|
||||
`<span>类型:<span class="badge ${badgeClass}">${badgeText}</span></span>` +
|
||||
`<span>时间:${escapeHtml(r.created_at)}</span>` +
|
||||
`<span>调用者:${escapeHtml(r.caller || '游客')}</span>` +
|
||||
`<span>方式:${escapeHtml(r.call_method || 'api')}</span>` +
|
||||
`<span>后端:${escapeHtml(r.backend || '—')}</span>` +
|
||||
`<span>状态:${r.status === 'failed' ? '<span style="color:#c62828;">失败</span>' : '<span style="color:#2e7d32;">成功</span>'}</span>`;
|
||||
`<span>状态:${r.status === 'failed' ? '<span style="color:#c62828;">失败</span>' : '<span style="color:#2e7d32;">成功</span>'}</span>` +
|
||||
htmlLink;
|
||||
|
||||
const body = document.getElementById('modalBody');
|
||||
if (r.status === 'failed') {
|
||||
|
||||
Reference in New Issue
Block a user