import { useState } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { Plus, Trash2 } from 'lucide-react'; import { deleteDimension, deleteTaxonomy, listDimensions, listTaxonomy, upsertDimension, upsertTaxonomy } from '@/lib/api'; import { Button, Card, CardHeader, Confirm, Input, useToast } from '@/components/ui'; const PALETTE = ['#3056d3', '#7c3aed', '#0891b2', '#16a34a', '#d97706', '#dc2626', '#db2777', '#64748b']; export function TaxonomyPage() { return (

字典驱动录入表单中的下拉选项;维度是自定义的成长分类轴,一条记录可挂多个维度。

); } function TaxonomyCard({ kind, title, description }: { kind: string; title: string; description: string }) { const qc = useQueryClient(); const toast = useToast(); const taxQ = useQuery({ queryKey: ['taxonomy-all'], queryFn: () => listTaxonomy() }); const items = (taxQ.data?.items ?? []).filter(t => t.kind === kind).sort((a, b) => a.sort - b.sort); const [draft, setDraft] = useState(''); const [deleting, setDeleting] = useState<{ id: number; value: string } | null>(null); const upMut = useMutation({ mutationFn: upsertTaxonomy, onSuccess: () => void qc.invalidateQueries({ queryKey: ['taxonomy-all'] }) }); const delMut = useMutation({ mutationFn: (id: number) => deleteTaxonomy(id), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['taxonomy-all'] }); toast('success', '已删除'); setDeleting(null); }, onError: (e: Error) => { toast('error', e.message); setDeleting(null); } }); return ( {description}} />
{items.map((t, i) => (
upMut.mutate({ id: t.id, kind, value: t.value, color: e.target.value, sort: t.sort })} /> {}} onBlur={e => { const v = e.target.value.trim(); if (v && v !== t.value) upMut.mutate({ id: t.id, kind, value: v, color: t.color, sort: t.sort }); }} key={t.value} defaultValue={t.value} /> #{t.sort} {!t.is_builtin ? ( ) : ( 内置 )}
))}
setDraft(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && draft.trim()) { upMut.mutate({ kind, value: draft.trim(), sort: (items.at(-1)?.sort ?? 0) + 10 }); setDraft(''); } }} />
setDeleting(null)} onOk={() => deleting && delMut.mutate(deleting.id)} />
); } function DimensionCard() { const qc = useQueryClient(); const toast = useToast(); const dimsQ = useQuery({ queryKey: ['dimensions'], queryFn: listDimensions }); const items = [...(dimsQ.data?.items ?? [])].sort((a, b) => a.sort - b.sort); const [draft, setDraft] = useState(''); const [deleting, setDeleting] = useState<{ id: number; name: string } | null>(null); const upMut = useMutation({ mutationFn: upsertDimension, onSuccess: () => void qc.invalidateQueries({ queryKey: ['dimensions'] }) }); const delMut = useMutation({ mutationFn: (id: number) => deleteDimension(id), onSuccess: () => { void qc.invalidateQueries({ queryKey: ['dimensions'] }); toast('success', '已删除'); setDeleting(null); }, onError: (e: Error) => { toast('error', e.message); setDeleting(null); } }); return ( 如:学业深造 / 职业发展 / 兴趣生活} />
{items.map((d, i) => (
{ const v = e.target.value.trim(); if (v && v !== d.name) upMut.mutate({ id: d.id, name: v, color: d.color, sort: d.sort }); }} />
))} {!items.length && (
尚未配置维度
)}
setDraft(e.target.value)} onKeyDown={e => { if (e.key === 'Enter' && draft.trim()) { upMut.mutate({ name: draft.trim(), sort: (items.at(-1)?.sort ?? 0) + 10 }); setDraft(''); } }} />
setDeleting(null)} onOk={() => deleting && delMut.mutate(deleting.id)} />
); }