| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 'use client';
- import { useState } from 'react';
- import { MapPin, ChevronDown, ChevronUp, Calendar } from 'lucide-react';
- // 1. 引入 Hook
- import { useLanguage } from '@/lib/i18n/LanguageContext';
- import { CardData } from '@/types/card';
- const getImageUrl = (fidString: string | null) => {
- if (!fidString) return null;
- const firstFid = fidString.split(' ')[0];
- return `/api/resource/download_file?fid=${firstFid}`;
- };
- export default function KnowledgeCard({ data }: { data: CardData }) {
- // 2. 获取翻译函数和当前语言
- const { t, lang } = useLanguage();
-
- const [expanded, setExpanded] = useState(false);
- const imageUrl = getImageUrl(data.image);
- // 3. 根据语言格式化日期
- const formattedDate = new Date(data.created_at).toLocaleDateString(
- lang === 'zh' ? 'zh-CN' : 'en-US',
- { year: 'numeric', month: 'short', day: 'numeric' }
- );
- return (
- <div className="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden hover:shadow-md transition-all duration-300 flex flex-col">
-
- {/* 图片区域 */}
- {imageUrl && (
- <div className="h-48 w-full bg-slate-100 relative overflow-hidden group flex-shrink-0">
- <img
- src={imageUrl}
- alt={data.title}
- className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-105"
- loading="lazy"
- />
- <div className="absolute top-3 left-3 flex gap-2">
- <span className="bg-black/60 text-white text-xs px-2 py-1 rounded backdrop-blur-sm flex items-center gap-1">
- <MapPin size={10} /> {data.country}
- </span>
- {data.label && (
- <span className="bg-blue-600/80 text-white text-xs px-2 py-1 rounded backdrop-blur-sm">
- {data.label}
- </span>
- )}
- </div>
- </div>
- )}
- <div className="p-5 flex flex-col">
- {/* 标题 */}
- <h3 className="text-lg font-bold text-slate-900 mb-3 line-clamp-2 leading-tight group-hover:text-blue-600 transition-colors">
- {data.title}
- </h3>
- {/* 内容预览 (HTML) */}
- <div
- className={`
- text-sm text-slate-600 leading-relaxed overflow-hidden transition-all duration-500 ease-in-out
- ${expanded ? 'max-h-[1000px]' : 'max-h-[80px] line-clamp-3'}
-
- /* === 样式修复:Tailwind Prose === */
- [&_a]:text-blue-600 [&_a]:underline [&_a]:font-medium hover:[&_a]:text-blue-800
- [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-2
- [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-2
- [&_p]:mb-2 last:[&_p]:mb-0
- [&_img]:max-w-full [&_img]:rounded-lg [&_img]:my-2
- `}
- dangerouslySetInnerHTML={{ __html: data.content }}
- />
- {/* 底部信息 & 展开按钮 */}
- <div className="mt-4 pt-4 flex items-center justify-between border-t border-slate-50">
- <div className="flex items-center text-xs text-slate-400 gap-1">
- <Calendar size={12} />
- {formattedDate}
- </div>
-
- <button
- onClick={(e) => {
- e.stopPropagation();
- setExpanded(!expanded);
- }}
- className="text-xs font-medium text-blue-600 hover:text-blue-800 flex items-center gap-1 bg-blue-50 px-2 py-1 rounded transition-colors select-none"
- >
- {expanded ? (
- <>{t('knowledge.collapse')} <ChevronUp size={14} /></>
- ) : (
- <>{t('knowledge.read_more')} <ChevronDown size={14} /></>
- )}
- </button>
- </div>
- </div>
- </div>
- );
- }
|