更新内容
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { BookOpen, ChevronDown, Layers3 } from 'lucide-react';
|
||||
import { ArrowLeft, BookOpen, Layers3 } from 'lucide-react';
|
||||
import { apiUrl } from '../api';
|
||||
|
||||
interface VocabEntry {
|
||||
@@ -38,7 +38,7 @@ const colorClassFor = (color: string) => {
|
||||
|
||||
export const VocabCards: React.FC = () => {
|
||||
const [cards, setCards] = useState<VocabCard[]>([]);
|
||||
const [expandedTerm, setExpandedTerm] = useState<string | null>(null);
|
||||
const [selectedCard, setSelectedCard] = useState<VocabCard | null>(null);
|
||||
const [status, setStatus] = useState<'loading' | 'ready' | 'error'>('loading');
|
||||
|
||||
useEffect(() => {
|
||||
@@ -68,20 +68,33 @@ export const VocabCards: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-y-auto bg-[#FAF9F6] px-2 py-3 lg:px-6 lg:pb-6">
|
||||
<div className="mx-auto max-w-4xl">
|
||||
<div className="mx-auto max-w-5xl">
|
||||
<div className="mb-3 flex items-center justify-between gap-3 rounded-xl border border-[#E8E4DE] bg-[#FDFCFB] px-4 py-3 shadow-sm">
|
||||
<div>
|
||||
<div className="flex items-center gap-2 font-serif text-lg font-bold text-[#2D2926]">
|
||||
<Layers3 className="h-5 w-5 text-[#8B7E74]" />
|
||||
单词卡片
|
||||
{selectedCard ? selectedCard.text : '单词卡片'}
|
||||
</div>
|
||||
<div className="mt-1 text-xs text-[#A69F92]">
|
||||
按词合并所有歌词注释
|
||||
{!selectedCard && (
|
||||
<div className="mt-1 text-xs text-[#A69F92]">
|
||||
按词合并所有歌词注释
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{selectedCard ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelectedCard(null)}
|
||||
className="flex items-center gap-1 rounded-full border border-[#E8E4DE] bg-white px-3 py-1.5 text-xs font-semibold text-[#8B7E74] hover:bg-[#FAF9F6]"
|
||||
>
|
||||
<ArrowLeft className="h-3.5 w-3.5" />
|
||||
返回
|
||||
</button>
|
||||
) : (
|
||||
<div className="rounded-full bg-[#8B7E74]/10 px-3 py-1 text-xs font-semibold text-[#8B7E74]">
|
||||
{cards.length} 词
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-full bg-[#8B7E74]/10 px-3 py-1 text-xs font-semibold text-[#8B7E74]">
|
||||
{cards.length} 词
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{status === 'loading' && (
|
||||
@@ -102,65 +115,48 @@ export const VocabCards: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
{cards.map((card) => {
|
||||
const isExpanded = expandedTerm === card.normalizedText;
|
||||
return (
|
||||
<article
|
||||
key={card.normalizedText}
|
||||
className="rounded-xl border border-[#E8E4DE] bg-[#FDFCFB] p-3 shadow-sm"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setExpandedTerm(isExpanded ? null : card.normalizedText)}
|
||||
className="flex w-full items-start justify-between gap-3 text-left"
|
||||
{status === 'ready' && selectedCard && (
|
||||
<div className="space-y-3">
|
||||
<div className={`rounded-xl border p-3 text-sm leading-relaxed ${colorClassFor(selectedCard.latestColor)}`}>
|
||||
{selectedCard.latestComment || '无释义内容'}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
{selectedCard.entries.map((entry, index) => (
|
||||
<div
|
||||
key={`${entry.fileName}-${entry.lineNumber}-${index}`}
|
||||
className="rounded-xl border border-[#E8E4DE]/70 bg-white p-3 shadow-sm"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<div className="font-serif text-xl font-bold text-[#2D2926]">
|
||||
{card.text}
|
||||
</div>
|
||||
<div className="mt-1 flex flex-wrap items-center gap-1.5 text-[11px] text-[#A69F92]">
|
||||
<span>{card.noteCount} 条注释</span>
|
||||
<span>·</span>
|
||||
<span className="truncate">{card.documentTitles.join(' / ')}</span>
|
||||
</div>
|
||||
<div className="mb-1 flex items-center gap-1.5 text-xs font-semibold text-[#8B7E74]">
|
||||
<BookOpen className="h-3.5 w-3.5" />
|
||||
{entry.documentTitle} · 行 {entry.lineNumber}
|
||||
</div>
|
||||
<div className="text-sm leading-relaxed text-[#2D2926]">
|
||||
{entry.lineText}
|
||||
</div>
|
||||
<div className={`mt-2 rounded-lg border px-2 py-1.5 text-sm ${colorClassFor(entry.color)}`}>
|
||||
{entry.comment}
|
||||
</div>
|
||||
<ChevronDown
|
||||
className={`mt-1 h-4 w-4 shrink-0 text-[#8B7E74] transition ${
|
||||
isExpanded ? 'rotate-180' : ''
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
|
||||
<div className={`mt-2 rounded-lg border p-2 text-sm leading-relaxed ${colorClassFor(card.latestColor)}`}>
|
||||
{card.latestComment || '无释义内容'}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isExpanded && (
|
||||
<div className="mt-3 space-y-2 border-t border-[#E8E4DE]/60 pt-3">
|
||||
{card.entries.map((entry, index) => (
|
||||
<div
|
||||
key={`${entry.fileName}-${entry.lineNumber}-${index}`}
|
||||
className="rounded-lg border border-[#E8E4DE]/70 bg-white p-2.5"
|
||||
>
|
||||
<div className="mb-1 flex items-center gap-1.5 text-[11px] font-semibold text-[#8B7E74]">
|
||||
<BookOpen className="h-3.5 w-3.5" />
|
||||
{entry.documentTitle} · 行 {entry.lineNumber}
|
||||
</div>
|
||||
<div className="text-xs leading-relaxed text-[#A69F92]">
|
||||
{entry.lineText}
|
||||
</div>
|
||||
<div className={`mt-2 rounded border px-2 py-1.5 text-sm ${colorClassFor(entry.color)}`}>
|
||||
{entry.comment}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{status === 'ready' && !selectedCard && (
|
||||
<div className="grid grid-cols-3 gap-1.5 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 xl:grid-cols-7">
|
||||
{cards.map((card) => (
|
||||
<button
|
||||
key={card.normalizedText}
|
||||
type="button"
|
||||
onClick={() => setSelectedCard(card)}
|
||||
className="min-h-14 rounded-xl border border-[#E8E4DE] bg-[#FDFCFB] px-2 py-2 text-center font-serif text-base font-bold leading-snug text-[#2D2926] shadow-sm transition hover:border-[#8B7E74]/50 hover:bg-white active:bg-[#E8E4DE]/30 sm:text-lg"
|
||||
>
|
||||
{card.text}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user