feat: P0f 会话分享链接 + 全栈验证

- 后端: POST /sessions/:id/share 生成 HMAC 签名分享令牌
- 后端: GET /sandbox/shared/:token 公开查看分享会话
- 前端: sandbox/page.tsx 新增「复制分享链接」按钮
- 前端: /sandbox/share?token=xxx 分享查看页面
- 全栈: 后端 build + 前端 61 页 + 92 tests 全部通过
This commit is contained in:
yuzhiran-dev
2026-05-18 10:43:25 +08:00
parent f2a6bb93f9
commit cba785e6bd
9 changed files with 187 additions and 4 deletions
+20 -1
View File
@@ -224,6 +224,21 @@ export default function SandboxPage() {
return `${d.getMonth() + 1}/${d.getDate()} ${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
}
async function shareSessionLink() {
if (!getToken() || !currentSessionId) { alert('请先登录'); return; }
try {
const tk = getToken();
const res = await fetch(`${API_BASE}/sandbox/sessions/${currentSessionId}/share`, {
method: 'POST', headers: { Authorization: `Bearer ${tk}` },
});
const data = await res.json();
if (data.shareUrl) {
await navigator.clipboard.writeText(data.shareUrl);
alert('链接已复制');
}
} catch { alert('生成分享链接失败'); }
}
function shareToCommunity(content: string, title?: string) {
if (!getToken()) { alert('请先登录'); return; }
apiFetch('/community/posts', {
@@ -421,7 +436,11 @@ export default function SandboxPage() {
</div>
)}
{!sending && messages.length > 2 && (
<div className="flex justify-end">
<div className="flex justify-end gap-2">
<button onClick={shareSessionLink}
className="text-xs text-brand-600 hover:underline">
{t.sandbox.copyShareLink}
</button>
<button onClick={() => {
const lastAssistantMsg = [...messages].reverse().find(m => m.role === 'assistant');
if (lastAssistantMsg) shareToCommunity(lastAssistantMsg.content);