// 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 => (
))}
{toast &&
setToast(null)} />}
);
}
Object.assign(window, { ContactsView });