后端核心变更: - API 层: 新增 AppError 枚举统一错误类型,替代散落的 (StatusCode, String) - Agent 工具域: 重组为 astro/system/ 和 astro/research/ 两级域,新增 ProcessPaperTool 流水线工具 - 安全: 新增 SSRF 双层防护 (同步字符串级 + 异步 DNS 解析级),覆盖 IPv4/IPv6 私网段 - 弱密码检测: 扩展弱密码列表并增加最小长度检查 - LLM 客户端: 新增 ChatCompleter/Embedder trait,支持依赖注入与批量向量化 embed_batch - 批量处理: AssetBatch 从串行改为 Semaphore 并发池 (BATCH_CONCURRENCY=3) - 分块器: 重写为三阶段结构化管线 (章节解析→短节合并→带标题路径子块) - RAG: embedding 计算移出事务,RetrievalResult 新增 headings/section_index 字段 - 检索: ADS/arXiv 并行检索 (tokio::join!),去重改用 HashSet,本地库回填批量 IN 查询 - 天体查询: Sesame API 升级到 v4,新增视差误差/自行/视向速度/多波段测光字段 - 迁移: 14 个增量文件合并为单一 init.sql,支持 sqlx::migrate! 内存库集成测试 - 测试: circuit_breaker/hooks/task_board/session/memory/streaming_executor 新增修正 15+ 测试 前端架构重构: - 目录重组: features/ → pages/ + components/ + hooks/ 三层分离 - App.tsx 从 1181 行压缩至 ~174 行 (逻辑抽入 9 个自定义 Hook) - Agent 面板拆分为 AgentSessionSidebar/AgentMessageList/AgentInputArea 子组件 - 新增 GlobalDialog/PaperDetailModal/UncachedPaperModal 通用对话框组件 - 工具函数抽取: celestial.ts (天体坐标格式), paper.tsx (文献信息渲染)
75 lines
5.2 KiB
TypeScript
75 lines
5.2 KiB
TypeScript
// dashboard/src/components/sync/BookmarkletToolCard.tsx
|
||
import { useRef, useEffect } from 'react';
|
||
|
||
// 书签代码常量
|
||
const BOOKMARKLET_CODE = `javascript:(async function(){try{let defaultBib='';try{const res=await fetch('http://localhost:8000/api/active_bibcode',{credentials:'include'});if(res.ok){const data=await res.json();if(data&&data.bibcode)defaultBib=data.bibcode;}}catch(e){}const b=prompt('请输入文献的 Bibcode / doi / arxiv_id :',defaultBib);if(!b||!b.trim())return;const bib=b.trim();if(window.location.protocol==='file:'){alert('[ERR] 浏览器安全策略限制:书签脚本无法直接读取本地磁盘 file://。\\n\\n提示:对于本地 PDF/HTML 文件,请直接在 AstroResearch 的文献详情页点击“上传 PDF/HTML”按钮导入。');return;}let blob,type='html',ext='.html';const isPDF=document.contentType==='application/pdf'||window.location.pathname.toLowerCase().endsWith('.pdf')||document.title.toLowerCase().endsWith('.pdf');if(isPDF){try{const res=await fetch(window.location.href);if(!res.ok)throw new Error('HTTP '+res.status);blob=await res.blob();type='pdf';ext='.pdf';}catch(err){alert('[ERR] 无法读取该 PDF 数据。\\n(错误: '+err.message+')');return;}}else{blob=new Blob([document.documentElement.outerHTML],{type:'text/html'});}const fd=new FormData();fd.append('bibcode',bib);fd.append('type',type);fd.append('file',blob,bib+ext);const r=await fetch('http://localhost:8000/api/upload',{method:'POST',body:fd,credentials:'include'});if(r.ok){const d=await r.json();alert('[OK] '+(d.title||bib));}else{const t=await r.text();alert('[ERR '+r.status+'] '+t);}}catch(e){alert('[FAIL] '+e.message);}})();void(0);`;
|
||
|
||
export function BookmarkletToolCard() {
|
||
const linkRef = useRef<HTMLAnchorElement | null>(null);
|
||
|
||
useEffect(() => {
|
||
if (linkRef.current) {
|
||
linkRef.current.setAttribute('href', BOOKMARKLET_CODE);
|
||
}
|
||
}, []);
|
||
|
||
const handleCopyCode = () => {
|
||
navigator.clipboard.writeText(BOOKMARKLET_CODE);
|
||
alert('书签代码已成功复制到剪贴板!');
|
||
};
|
||
|
||
return (
|
||
<div className="console-panel p-6 rounded-xl border border-slate-200 bg-white space-y-4 shadow-xs">
|
||
<div className="flex flex-col gap-1 border-b border-slate-100 pb-2 select-none">
|
||
<h3 className="text-xs font-bold text-slate-900 flex items-center gap-2">
|
||
<span className="w-2 h-2 rounded-full bg-sky-500 animate-pulse" />
|
||
<span>浏览器快捷直推书签导入工具</span>
|
||
</h3>
|
||
<p className="text-slate-500 text-xs mt-1 leading-relaxed">
|
||
无需手动保存和拖拽上传!在您自己真实的浏览器上突破 Cloudflare/WAF 人机验证或在学校内网成功打开 PDF/HTML 页面后,点击此书签即可将文献直接推送同步到本地 AstroResearch 数据库与文献馆中。
|
||
</p>
|
||
</div>
|
||
|
||
<div className="space-y-3.5 text-xs text-slate-700">
|
||
<div className="space-y-1.5 font-bold select-none">
|
||
<span className="text-slate-500">第一步:安装书签到您的浏览器</span>
|
||
<p className="text-[11px] text-slate-400 font-normal mt-1 leading-relaxed">
|
||
将下方的按钮直接拖拽到浏览器的书签栏中;或者新建一个浏览器书签,将其 URL 设为复制的 JavaScript 代码(点击右侧按钮复制):
|
||
</p>
|
||
|
||
<div className="flex flex-wrap items-center gap-3 mt-2 select-none">
|
||
{/* 可直接拖拽的链接按钮 */}
|
||
<a
|
||
ref={linkRef}
|
||
className="px-4 py-2 bg-gradient-to-r from-sky-500 to-indigo-500 hover:from-sky-650 hover:to-indigo-650 text-white rounded-lg text-xs font-bold transition-all shadow-sm cursor-move flex items-center gap-1.5"
|
||
title="拖拽我到您的书签栏中"
|
||
onClick={(e) => e.preventDefault()}
|
||
>
|
||
<span style={{ position: 'absolute', width: '1px', height: '1px', overflow: 'hidden', opacity: 0, pointerEvents: 'none' }}>
|
||
导入AstroResearch
|
||
</span>
|
||
<span>添加导入书签</span>
|
||
</a>
|
||
|
||
<button
|
||
onClick={handleCopyCode}
|
||
className="px-3 py-2 bg-slate-100 hover:bg-slate-200 text-slate-700 rounded-lg text-[11px] font-bold transition-all cursor-pointer"
|
||
>
|
||
复制 JavaScript 书签代码
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="space-y-1.5 font-bold mt-4 select-none">
|
||
<span className="text-slate-500">第二步:如何使用书签直推?</span>
|
||
<ol className="list-decimal list-inside text-[11px] text-slate-500 font-normal pl-1 space-y-1.5 mt-1 leading-relaxed">
|
||
<li>点击详情弹窗内的 <span className="font-bold text-slate-750">BIBCODE / DOI / arXiv ID 链接</span>;</li>
|
||
<li>页面跳转至文献原始网页后,直接<span className="font-bold text-slate-750">点击该浏览器书签</span>;</li>
|
||
<li>书签脚本会自动读取并<span className="font-bold text-slate-750">自动填充好 Bibcode</span>,您只需点击确认,文件即可秒级自动上传录入至系统!</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|