// DetailView.jsx — 笔记详情:时空坐标 + 正文(markdown) + 墨吞占位 const { useState: useStateDV } = React; // —— 轻量 markdown 渲染 —— // function mdInline(text) { // 转义 + 行内:**粗** *斜* `代码` [链](url) const parts = []; let key = 0; const re = /(\*\*[^*]+\*\*|\*[^*]+\*|`[^`]+`|\[[^\]]+\]\([^)]+\))/g; let last = 0, m; while ((m = re.exec(text)) !== null) { if (m.index > last) parts.push(text.slice(last, m.index)); const tok = m[0]; if (tok.startsWith('**')) parts.push({tok.slice(2, -2)}); else if (tok.startsWith('`')) parts.push({tok.slice(1, -1)}); else if (tok.startsWith('[')) { const mm = /\[([^\]]+)\]\(([^)]+)\)/.exec(tok); parts.push( e.preventDefault()}>{mm[1]}); } else parts.push({tok.slice(1, -1)}); last = m.index + tok.length; } if (last < text.length) parts.push(text.slice(last)); return parts; } function Markdown({ src }) { const lines = src.split('\n'); const out = []; let i = 0, key = 0; while (i < lines.length) { const line = lines[i]; if (line.startsWith('```')) { const buf = []; i++; while (i < lines.length && !lines[i].startsWith('```')) { buf.push(lines[i]); i++; } i++; out.push(
{buf.join('\n')}
); continue; } if (line.startsWith('### ')) { out.push(

{mdInline(line.slice(4))}

); i++; continue; } if (line.startsWith('## ')) { out.push(

{mdInline(line.slice(3))}

); i++; continue; } if (line.startsWith('# ')) { out.push(

{mdInline(line.slice(2))}

); i++; continue; } if (line.startsWith('---')) { out.push(
); i++; continue; } if (line.startsWith('> ')) { const buf = []; while (i < lines.length && lines[i].startsWith('>')) { buf.push(lines[i].replace(/^>\s?/, '')); i++; } out.push(
{buf.filter(Boolean).map((b, j) =>

{mdInline(b)}

)}
); continue; } if (/^[-*] /.test(line)) { const buf = []; while (i < lines.length && /^[-*] /.test(lines[i])) { buf.push(lines[i].slice(2)); i++; } out.push(); continue; } if (line.startsWith('|') && lines[i + 1] && /^\|[\s:|-]+\|/.test(lines[i + 1])) { const head = line.split('|').slice(1, -1).map(s => s.trim()); i += 2; const rows = []; while (i < lines.length && lines[i].startsWith('|')) { rows.push(lines[i].split('|').slice(1, -1).map(s => s.trim())); i++; } out.push( {head.map((hc, j) => )}{rows.map((r, j) => {r.map((c, k) => )})}
{mdInline(hc)}
{mdInline(c)}
); continue; } if (line.trim() === '') { i++; continue; } out.push(

{mdInline(line)}

); i++; } return
{out}
; } // —— 数字凭证(哈希确权 · 可展开折叠)—— // function DigitalSeal({ note }) { const [open, setOpen] = useStateDV(false); const stamp = note.date + ' ' + (note.time || '00:00') + ' UTC+8'; const hash = poporHash(note.id + '|' + note.date + note.time + '|' + note.body); const keyline = (note.body.match(/^>\s?(.+)$/m) || [null, note.preview])[1].slice(0, 40); return (
{open && (
确权时间{stamp}
内容哈希{hash}
留存此句“{keyline}”
时间戳与哈希一同写入,作为这页文字、图像与创意属于你的数字证据。
)}
); } // —— 这一页的来历与去向 · 整合(怎么写成的 / 变成作品 / 数字凭证)—— // function PageAfterword({ note }) { const ids = (typeof noteSkillStack === 'function') ? noteSkillStack(note) : []; const [shared, setShared] = useStateDV(false); const [results, setResults] = useStateDV([]); const [busy, setBusy] = useStateDV(null); const [sealOpen, setSealOpen] = useStateDV(false); const stamp = note.date + ' ' + (note.time || '00:00') + ' UTC+8'; const hash = poporHash(note.id + '|' + note.date + note.time + '|' + note.body); const keyline = (note.body.match(/^>\s?(.+)$/m) || [null, note.preview])[1].slice(0, 40); function run(tool) { if (busy) return; setBusy(tool.id); const rid = Date.now(); setResults(r => [{ rid, tool, status: 'gen' }, ...r]); setTimeout(() => { setResults(r => r.map(x => x.rid === rid ? Object.assign({}, x, { status: 'done' }) : x)); setBusy(null); }, 1100); } return (
{/* 1 · 怎么写成的 */}
怎么写成的 {ids.length > 0 && ( )}
{ids.length > 0 ? (
{ids.map((id, i) => { const s = skillById(id); if (!s) return null; return ( {i > 0 && } {s.name.split(' · ')[0]} ); })}
) :
还没有技能足迹。
} {shared &&
朋友打开这篇时,可一键把这套配方装进自己的本子 —— 内容与技能,分开分享。
}
{/* 2 · 变成作品 */}
变成作品 让创意从文字,走向数字化生成
{MOTUN_TOOLS.map(tl => { const C = GIcon[tl.ico]; return ( ); })}
{results.length > 0 && (
{results.map(r => { const C = GIcon[r.tool.ico]; return (
{r.tool.name} {r.status === 'gen' ? 生成中 : {r.tool.label}}
{r.status === 'gen' ?
: }
); })}
)}
{/* 3 · 数字凭证 */} {sealOpen && (
确权时间{stamp}
内容哈希{hash}
留存此句“{keyline}”
时间戳与哈希一同写入,作为这页文字、图像与创意属于你的数字证据。
)}
); } // —— 详情页 —— // function DetailView({ note, notebook, onBack, onWrite, onShare }) { if (!note) return null; return (

{note.title} {note.en}

制作 {note.date} 导入 {note.imported} {note.city} {note.scene} {note.gps}
{note.cat} {note.notes.map(t => {t})} {note.locs.map(t => {t})}

{note.img ? ( {'原始手写照片 { e.target.style.display = 'none'; }} /> ) : note.hasPhoto ? (
原始手写照片 · {note.title}
) : null} {/* 来历与去向 · 整合:怎么写成的 / 变成作品 / 数字凭证 */}
); } Object.assign(window, { DetailView, Markdown });