// =========================================================
// FBIF 资讯订阅 · 标签管理 (Tag manager)
// Tags are user-defined labels applied to SOURCES. Here you
// create/delete tags, toggle their visibility in the sidebar,
// and manage which sources carry each tag.
// =========================================================
const SWATCHES = ['#E8542E', '#8A5A2B', '#1F8A5B', '#3DA35D', '#2A6FDB', '#7A4FBB', '#C0392B', '#0F8B8D', '#B45F00', '#555E6B', '#1456F0', '#646A73'];
// popover: pick which sources carry this tag (checkboxes + search + count)
const SourcePickPopover = ({ tag, sources, anchorRef, onToggleSourceTag, onClose }) => {
const [q, setQ] = React.useState('');
const list = sources.filter(s => s.name.includes(q));
const count = sources.filter(s => s.tags.includes(tag.id)).length;
return (
哪些来源属于「{tag.name}」已选 {count}
setQ(e.target.value)} width="100%" height={30} />
{list.map(s => {
const on = s.tags.includes(tag.id);
return (
onToggleSourceTag(s.id, tag.id)}
label={{s.name}}
right={{on && }} />
);
})}
{list.length === 0 && 无匹配来源
}
);
};
const TagRow = ({ tag, data, onToggleSub, onDelete, onToggleSourceTag }) => {
const [hover, setHover] = React.useState(false);
const [pickOpen, setPickOpen] = React.useState(false);
const pickBtnRef = React.useRef(null);
const used = data.SOURCES.filter(s => s.tags.includes(tag.id));
const articleCount = used.filter(s => s.subscribed).reduce((a, s) => a + (s.article_count || 0), 0);
return (
setHover(true)} onMouseLeave={() => setHover(false)}
style={{ display: 'flex', alignItems: 'center', gap: 12, padding: '0 16px', height: 56, borderBottom: '1px solid #EDEFF2', background: hover ? '#F7F8FA' : '#fff' }}>
{used.length} 个来源
{articleCount} 条资讯
{pickOpen && setPickOpen(false)} />}
侧栏显示
onToggleSub(tag)} />
);
};
const TagManager = ({ data, onCreateTag, onDeleteTag, onToggleTagSub, onToggleSourceTag, onClose }) => {
useLucide();
const [name, setName] = React.useState('');
const [color, setColor] = React.useState(SWATCHES[0]);
const create = () => { const v = name.trim(); if (!v) return; onCreateTag(v, color); setName(''); };
return (
标签管理
标签是你给「来源」打的组织标签。一个来源可有多个标签,时间线可按标签筛选。
{/* 新建标签 */}
新建标签
{!name.trim() &&
输入标签名称后即可创建(同名标签会被拦截)。
}
{/* tag list */}
全部标签
{data.TAGS.length}
标签
关联来源
资讯数
侧栏
{data.TAGS.map(t => (
))}
{data.TAGS.length === 0 &&
暂无标签,先创建一个
}
);
};
Object.assign(window, { TagManager });