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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user