// Contacts.jsx — 通讯录 · 人际关系(合作者 / 工作 / 朋友 / 粉丝 / 家人 + 本子分类) const { useState: useStateCT } = React; // 导入演示(微信 / Instagram —— 假流程,仅提示) function ImportToast({ text, onDone }) { React.useEffect(() => { const t = setTimeout(onDone, 2200); return () => clearTimeout(t); }, []); return (
{text}
); } function ContactCard({ c, onOpenNote }) { const books = c.books || []; return (
{c.name.slice(0, 1)}
{c.name}· {SOURCE_LABEL[c.src] || 'Popor'}
{c.prof}
{(c.rel || []).map(r => { const m = relMeta(r); return {m.label}; })}
{books.length > 0 && (
{books.join(' · ')}
)}
擅长 {(c.skills || []).map(s => {s})}
{c.note && ( )}
{c.id} {c.phone && {c.phone}}
); } function ContactsView({ onClose, onOpenNote }) { const [filter, setFilter] = useStateCT('all'); const [toast, setToast] = useStateCT(null); // 本子分组(数据里出现过的) const books = []; CONTACTS.forEach(c => (c.books || []).forEach(b => { if (books.indexOf(b) < 0) books.push(b); })); const list = CONTACTS.filter(c => { if (filter === 'all') return true; if (filter.indexOf('book:') === 0) return (c.books || []).indexOf(filter.slice(5)) >= 0; return (c.rel || []).indexOf(filter) >= 0; }); function count(pred) { return CONTACTS.filter(pred).length; } return (
{ if (e.target.classList.contains('sheet')) onClose(); }}>
通讯录{CONTACTS.length} 位 · 你的人脉网络
{RELATION_TYPES.map(r => { const n = count(c => (c.rel || []).indexOf(r.id) >= 0); if (!n) return null; return ( ); })} 按本子 {books.map(b => ( ))}
{list.map(c => )}
{toast && setToast(null)} />}
); } Object.assign(window, { ContactsView });