|
@@ -1,27 +1,499 @@
|
|
|
-import React from 'react';
|
|
|
|
|
|
|
+import React, { useState } from 'react';
|
|
|
|
|
+import { useNavigate } from 'react-router-dom';
|
|
|
|
|
+import { useSilverWisdomData } from '../hooks/useSilverWisdomData';
|
|
|
|
|
+import { SilverWisdomItem } from '../data/mockSilverWisdomData';
|
|
|
|
|
+import {
|
|
|
|
|
+ MagnifyingGlassIcon,
|
|
|
|
|
+ UserIcon,
|
|
|
|
|
+ EyeIcon,
|
|
|
|
|
+ HeartIcon,
|
|
|
|
|
+ ChatBubbleLeftIcon,
|
|
|
|
|
+ ClockIcon,
|
|
|
|
|
+ TagIcon,
|
|
|
|
|
+ BookOpenIcon
|
|
|
|
|
+} from '@heroicons/react/24/outline';
|
|
|
|
|
+import { HeartIcon as HeartSolidIcon } from '@heroicons/react/24/solid';
|
|
|
|
|
+
|
|
|
|
|
+// 中国水墨风格色彩系统
|
|
|
|
|
+const COLORS = {
|
|
|
|
|
+ ink: {
|
|
|
|
|
+ light: '#f5f3f0', // 宣纸背景色
|
|
|
|
|
+ medium: '#d4c4a8', // 淡墨
|
|
|
|
|
+ dark: '#8b7355', // 浓墨
|
|
|
|
|
+ deep: '#3a2f26', // 焦墨
|
|
|
|
|
+ },
|
|
|
|
|
+ accent: {
|
|
|
|
|
+ red: '#a85c5c', // 朱砂
|
|
|
|
|
+ blue: '#4a6b7c', // 花青
|
|
|
|
|
+ green: '#5c7c5c', // 石绿
|
|
|
|
|
+ },
|
|
|
|
|
+ text: {
|
|
|
|
|
+ primary: '#2f1f0f', // 墨色文字
|
|
|
|
|
+ secondary: '#5d4e3b', // 淡墨文字
|
|
|
|
|
+ light: '#8b7355', // 极淡文字
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 字体样式
|
|
|
|
|
+const FONT_STYLES = {
|
|
|
|
|
+ title: 'font-serif text-3xl font-bold tracking-wide',
|
|
|
|
|
+ sectionTitle: 'font-serif text-2xl font-semibold tracking-wide',
|
|
|
|
|
+ body: 'font-sans text-base leading-relaxed',
|
|
|
|
|
+ caption: 'font-sans text-sm',
|
|
|
|
|
+ small: 'font-sans text-xs',
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 分类标签颜色映射
|
|
|
|
|
+const categoryColors: Record<string, string> = {
|
|
|
|
|
+ '健康养生': 'bg-green-50 text-green-800 border-green-200',
|
|
|
|
|
+ '认知训练': 'bg-blue-50 text-blue-800 border-blue-200',
|
|
|
|
|
+ '生活艺术': 'bg-purple-50 text-purple-800 border-purple-200',
|
|
|
|
|
+ '理财规划': 'bg-orange-50 text-orange-800 border-orange-200',
|
|
|
|
|
+ '艺术修养': 'bg-pink-50 text-pink-800 border-pink-200',
|
|
|
|
|
+ '科技应用': 'bg-indigo-50 text-indigo-800 border-indigo-200',
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 工具函数:格式化数字
|
|
|
|
|
+const formatNumber = (num: number) => {
|
|
|
|
|
+ if (num >= 1000) {
|
|
|
|
|
+ return (num / 1000).toFixed(1) + 'k';
|
|
|
|
|
+ }
|
|
|
|
|
+ return num.toString();
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 工具函数:格式化日期
|
|
|
|
|
+const formatDate = (dateString: string) => {
|
|
|
|
|
+ const date = new Date(dateString);
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const diffTime = Math.abs(now.getTime() - date.getTime());
|
|
|
|
|
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
+
|
|
|
|
|
+ if (diffDays === 1) return '昨天';
|
|
|
|
|
+ if (diffDays <= 7) return `${diffDays}天前`;
|
|
|
|
|
+ return date.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const SilverWisdomPage: React.FC = () => {
|
|
const SilverWisdomPage: React.FC = () => {
|
|
|
|
|
+ const navigate = useNavigate();
|
|
|
|
|
+ const [searchQuery, setSearchQuery] = useState('');
|
|
|
|
|
+ const [activeSearch, setActiveSearch] = useState('');
|
|
|
|
|
+
|
|
|
|
|
+ const {
|
|
|
|
|
+ wisdomItems,
|
|
|
|
|
+ categories,
|
|
|
|
|
+ selectedCategory,
|
|
|
|
|
+ setSelectedCategory,
|
|
|
|
|
+ stats,
|
|
|
|
|
+ isLoading,
|
|
|
|
|
+ isError,
|
|
|
|
|
+ error
|
|
|
|
|
+ } = useSilverWisdomData(activeSearch);
|
|
|
|
|
+
|
|
|
|
|
+ // 处理搜索
|
|
|
|
|
+ const handleSearch = () => {
|
|
|
|
|
+ if (searchQuery.trim()) {
|
|
|
|
|
+ setActiveSearch(searchQuery.trim());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ setActiveSearch('');
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
|
|
|
+ if (e.key === 'Enter') {
|
|
|
|
|
+ handleSearch();
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 清除搜索
|
|
|
|
|
+ const clearSearch = () => {
|
|
|
|
|
+ setSearchQuery('');
|
|
|
|
|
+ setActiveSearch('');
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 格式化数字
|
|
|
|
|
+ const formatNumber = (num: number) => {
|
|
|
|
|
+ if (num >= 1000) {
|
|
|
|
|
+ return (num / 1000).toFixed(1) + 'k';
|
|
|
|
|
+ }
|
|
|
|
|
+ return num.toString();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 格式化日期
|
|
|
|
|
+ const formatDate = (dateString: string) => {
|
|
|
|
|
+ const date = new Date(dateString);
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const diffTime = Math.abs(now.getTime() - date.getTime());
|
|
|
|
|
+ const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
|
+
|
|
|
|
|
+ if (diffDays === 1) return '昨天';
|
|
|
|
|
+ if (diffDays <= 7) return `${diffDays}天前`;
|
|
|
|
|
+ return date.toLocaleDateString('zh-CN', { month: 'long', day: 'numeric' });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="min-h-screen" style={{ backgroundColor: COLORS.ink.light }}>
|
|
|
|
|
+ {/* 头部导航 - 水墨风格 */}
|
|
|
|
|
+ <header
|
|
|
|
|
+ className="shadow-sm sticky top-0 z-10 border-b border-opacity-20 px-4 py-4"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: COLORS.ink.light,
|
|
|
|
|
+ borderColor: COLORS.ink.medium
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <div className="flex items-center justify-between">
|
|
|
|
|
+ <h1
|
|
|
|
|
+ className={FONT_STYLES.sectionTitle}
|
|
|
|
|
+ style={{ color: COLORS.text.primary }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 银龄智库
|
|
|
|
|
+ </h1>
|
|
|
|
|
+ <UserIcon
|
|
|
|
|
+ className="w-6 h-6 cursor-pointer transition-colors duration-300 hover:text-orange-600"
|
|
|
|
|
+ style={{ color: COLORS.ink.dark }}
|
|
|
|
|
+ onClick={() => navigate('/profile')}
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </header>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 搜索栏 */}
|
|
|
|
|
+ <div className="px-4 py-4">
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="flex items-center rounded-full px-4 py-3 shadow-sm border transition-all duration-300 focus-within:shadow-md"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.7)',
|
|
|
|
|
+ borderColor: COLORS.ink.medium
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <MagnifyingGlassIcon
|
|
|
|
|
+ className="w-5 h-5 mr-3"
|
|
|
|
|
+ style={{ color: COLORS.ink.dark }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <input
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ placeholder="搜索银龄智慧..."
|
|
|
|
|
+ value={searchQuery}
|
|
|
|
|
+ onChange={(e) => setSearchQuery(e.target.value)}
|
|
|
|
|
+ onKeyPress={handleKeyPress}
|
|
|
|
|
+ className="flex-1 bg-transparent outline-none font-sans"
|
|
|
|
|
+ style={{ color: COLORS.text.primary }}
|
|
|
|
|
+ />
|
|
|
|
|
+ {searchQuery && (
|
|
|
|
|
+ <button
|
|
|
|
|
+ onClick={clearSearch}
|
|
|
|
|
+ className="ml-2 text-sm"
|
|
|
|
|
+ style={{ color: COLORS.text.light }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 清除
|
|
|
|
|
+ </button>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 分类筛选 */}
|
|
|
|
|
+ <div className="px-4 mb-4">
|
|
|
|
|
+ <div className="flex space-x-2 overflow-x-auto pb-2 scrollbar-hide">
|
|
|
|
|
+ {categories.map((category) => (
|
|
|
|
|
+ <button
|
|
|
|
|
+ key={category.value}
|
|
|
|
|
+ onClick={() => setSelectedCategory(category.value)}
|
|
|
|
|
+ className={`px-4 py-2 rounded-full text-sm font-medium transition-all duration-300 whitespace-nowrap ${
|
|
|
|
|
+ selectedCategory === category.value
|
|
|
|
|
+ ? 'shadow-md'
|
|
|
|
|
+ : 'hover:shadow-md'
|
|
|
|
|
+ }`}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: selectedCategory === category.value
|
|
|
|
|
+ ? COLORS.ink.dark
|
|
|
|
|
+ : 'rgba(255,255,255,0.7)',
|
|
|
|
|
+ color: selectedCategory === category.value ? 'white' : COLORS.text.primary,
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {category.icon} {category.label}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 统计卡片 */}
|
|
|
|
|
+ <div className="px-4 mb-4">
|
|
|
|
|
+ <div className="grid grid-cols-4 gap-2">
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-xl p-3 text-center shadow-sm backdrop-blur-sm"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.8)',
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <BookOpenIcon className="w-6 h-6 mx-auto mb-1" style={{ color: COLORS.accent.blue }} />
|
|
|
|
|
+ <div className="font-serif text-lg font-bold" style={{ color: COLORS.accent.blue }}>
|
|
|
|
|
+ {stats.totalCount}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ 智慧文章
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-xl p-3 text-center shadow-sm backdrop-blur-sm"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.8)',
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <EyeIcon className="w-6 h-6 mx-auto mb-1" style={{ color: COLORS.accent.green }} />
|
|
|
|
|
+ <div className="font-serif text-lg font-bold" style={{ color: COLORS.accent.green }}>
|
|
|
|
|
+ {formatNumber(stats.totalViews)}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ 总阅读量
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-xl p-3 text-center shadow-sm backdrop-blur-sm"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.8)',
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <HeartIcon className="w-6 h-6 mx-auto mb-1" style={{ color: COLORS.accent.red }} />
|
|
|
|
|
+ <div className="font-serif text-lg font-bold" style={{ color: COLORS.accent.red }}>
|
|
|
|
|
+ {formatNumber(stats.totalLikes)}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ 喜欢数
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-xl p-3 text-center shadow-sm backdrop-blur-sm"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.8)',
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ <UserIcon className="w-6 h-6 mx-auto mb-1" style={{ color: COLORS.ink.dark }} />
|
|
|
|
|
+ <div className="font-serif text-lg font-bold" style={{ color: COLORS.ink.dark }}>
|
|
|
|
|
+ 6
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ 专家作者
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 主要内容区域 */}
|
|
|
|
|
+ <div className="px-4 pb-20">
|
|
|
|
|
+ {isLoading ? (
|
|
|
|
|
+ // 加载骨架屏
|
|
|
|
|
+ <div className="space-y-4">
|
|
|
|
|
+ {[...Array(3)].map((_, i) => (
|
|
|
|
|
+ <SilverWisdomSkeleton key={i} />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ) : isError ? (
|
|
|
|
|
+ // 错误状态
|
|
|
|
|
+ <div className="text-center py-16">
|
|
|
|
|
+ <BookOpenIcon className="w-16 h-16 mx-auto mb-4" style={{ color: COLORS.ink.medium }} />
|
|
|
|
|
+ <h3 className={`${FONT_STYLES.caption} font-semibold mb-2`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ 加载失败
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <p className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ {(error as Error)?.message || '请稍后重试'}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ) : wisdomItems.length > 0 ? (
|
|
|
|
|
+ // 知识列表
|
|
|
|
|
+ <div className="space-y-4">
|
|
|
|
|
+ {wisdomItems.map((item) => (
|
|
|
|
|
+ <WisdomCard
|
|
|
|
|
+ key={item.id}
|
|
|
|
|
+ item={item}
|
|
|
|
|
+ onClick={() => navigate(`/silver-wisdom/${item.id}`)}
|
|
|
|
|
+ />
|
|
|
|
|
+ ))}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ ) : (
|
|
|
|
|
+ // 空状态
|
|
|
|
|
+ <div className="text-center py-16">
|
|
|
|
|
+ <MagnifyingGlassIcon className="w-16 h-16 mx-auto mb-4" style={{ color: COLORS.ink.medium }} />
|
|
|
|
|
+ <h3 className={`${FONT_STYLES.caption} font-semibold mb-2`} style={{ color: COLORS.text.secondary }}>
|
|
|
|
|
+ {activeSearch ? '搜索结果为空' : '暂无相关内容'}
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <p className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ {activeSearch ? '尝试调整搜索关键词或分类' : '请稍后重试'}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 底部提示 */}
|
|
|
|
|
+ <div className="fixed bottom-20 left-0 right-0 px-4">
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-lg p-3 text-center text-sm font-sans"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(74, 107, 124, 0.1)',
|
|
|
|
|
+ color: COLORS.accent.blue,
|
|
|
|
|
+ border: `1px solid ${COLORS.accent.blue}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 💡 点击卡片查看详细内容,收藏您喜欢的智慧分享
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 知识卡片组件
|
|
|
|
|
+const WisdomCard: React.FC<{
|
|
|
|
|
+ item: SilverWisdomItem;
|
|
|
|
|
+ onClick: () => void;
|
|
|
|
|
+}> = ({ item, onClick }) => {
|
|
|
return (
|
|
return (
|
|
|
- <div className="min-h-screen bg-gray-50 p-4">
|
|
|
|
|
- <div className="text-center">
|
|
|
|
|
- <h1 className="text-2xl font-bold text-gray-900 mb-4">银龄智库</h1>
|
|
|
|
|
- <p className="text-gray-600">智慧分享,经验传承</p>
|
|
|
|
|
-
|
|
|
|
|
- <div className="mt-8 space-y-4">
|
|
|
|
|
- <div className="bg-white p-6 rounded-lg shadow">
|
|
|
|
|
- <h3 className="text-lg font-semibold mb-2">专家经验</h3>
|
|
|
|
|
- <p className="text-gray-600">汇集各行业专家的宝贵经验和知识</p>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div className="bg-white p-6 rounded-lg shadow">
|
|
|
|
|
- <h3 className="text-lg font-semibold mb-2">技能培训</h3>
|
|
|
|
|
- <p className="text-gray-600">提供专业技能培训和指导</p>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- <div className="bg-white p-6 rounded-lg shadow">
|
|
|
|
|
- <h3 className="text-lg font-semibold mb-2">分享交流</h3>
|
|
|
|
|
- <p className="text-gray-600">创建知识分享和交流的平台</p>
|
|
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="rounded-xl shadow-sm hover:shadow-lg transition-all duration-300 cursor-pointer overflow-hidden backdrop-blur-sm"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.8)',
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ onClick={onClick}
|
|
|
|
|
+ >
|
|
|
|
|
+ {/* 封面图片 */}
|
|
|
|
|
+ <div className="relative">
|
|
|
|
|
+ <img
|
|
|
|
|
+ src={item.coverImage}
|
|
|
|
|
+ alt={item.title}
|
|
|
|
|
+ className="w-full h-48 object-cover"
|
|
|
|
|
+ />
|
|
|
|
|
+ {item.isFeatured && (
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="absolute top-2 right-2 px-2 py-1 rounded text-xs font-medium"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: COLORS.accent.red,
|
|
|
|
|
+ color: 'white'
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ 精选
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+ <div
|
|
|
|
|
+ className="absolute bottom-2 left-2 px-2 py-1 rounded text-xs font-medium"
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.9)',
|
|
|
|
|
+ color: COLORS.text.primary
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {item.readTime}分钟阅读
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 内容区域 */}
|
|
|
|
|
+ <div className="p-4">
|
|
|
|
|
+ {/* 分类标签 */}
|
|
|
|
|
+ <div className="flex items-center justify-between mb-2">
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`px-2 py-1 rounded-full text-xs ${categoryColors[item.category] || 'bg-gray-100 text-gray-800 border-gray-200'}`}
|
|
|
|
|
+ >
|
|
|
|
|
+ {item.category}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ {item.publishDate}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 标题 */}
|
|
|
|
|
+ <h3
|
|
|
|
|
+ className={`${FONT_STYLES.body} font-bold line-clamp-2 mb-2`}
|
|
|
|
|
+ style={{ color: COLORS.text.primary }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {item.title}
|
|
|
|
|
+ </h3>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 简介 */}
|
|
|
|
|
+ <p
|
|
|
|
|
+ className={`${FONT_STYLES.caption} line-clamp-3 mb-3`}
|
|
|
|
|
+ style={{ color: COLORS.text.secondary }}
|
|
|
|
|
+ >
|
|
|
|
|
+ {item.content}
|
|
|
|
|
+ </p>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 作者信息 */}
|
|
|
|
|
+ <div className="flex items-center mb-3">
|
|
|
|
|
+ <img
|
|
|
|
|
+ src={item.author.avatar}
|
|
|
|
|
+ alt={item.author.name}
|
|
|
|
|
+ className="w-8 h-8 rounded-full border-2 mr-2"
|
|
|
|
|
+ style={{ borderColor: COLORS.ink.medium }}
|
|
|
|
|
+ />
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <p className={`${FONT_STYLES.small} font-medium`} style={{ color: COLORS.text.primary }}>
|
|
|
|
|
+ {item.author.name}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p className={`${FONT_STYLES.small}`} style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ {item.author.title}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 标签 */}
|
|
|
|
|
+ <div className="flex flex-wrap gap-1 mb-3">
|
|
|
|
|
+ {item.tags.slice(0, 3).map((tag, index) => (
|
|
|
|
|
+ <span
|
|
|
|
|
+ key={index}
|
|
|
|
|
+ className={`px-2 py-1 rounded-full text-xs ${categoryColors[item.category] || 'bg-gray-100 text-gray-800 border-gray-200'}`}
|
|
|
|
|
+ >
|
|
|
|
|
+ {tag}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ ))}
|
|
|
|
|
+ {item.tags.length > 3 && (
|
|
|
|
|
+ <span
|
|
|
|
|
+ className={`px-2 py-1 rounded-full text-xs`}
|
|
|
|
|
+ style={{
|
|
|
|
|
+ backgroundColor: COLORS.ink.light,
|
|
|
|
|
+ color: COLORS.text.secondary,
|
|
|
|
|
+ border: `1px solid ${COLORS.ink.medium}`
|
|
|
|
|
+ }}
|
|
|
|
|
+ >
|
|
|
|
|
+ +{item.tags.length - 3}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ {/* 统计信息 */}
|
|
|
|
|
+ <div className="flex items-center justify-between text-xs">
|
|
|
|
|
+ <div className="flex items-center space-x-3">
|
|
|
|
|
+ <span className="flex items-center" style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ <EyeIcon className="w-4 h-4 mr-1" />
|
|
|
|
|
+ {formatNumber(item.viewCount)}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="flex items-center" style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ <HeartIcon className="w-4 h-4 mr-1" />
|
|
|
|
|
+ {formatNumber(item.likeCount)}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span className="flex items-center" style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ <ChatBubbleLeftIcon className="w-4 h-4 mr-1" />
|
|
|
|
|
+ {formatNumber(item.commentCount)}
|
|
|
|
|
+ </span>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ <span className="flex items-center" style={{ color: COLORS.text.light }}>
|
|
|
|
|
+ <ClockIcon className="w-4 h-4 mr-1" />
|
|
|
|
|
+ {formatDate(item.publishDate)}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ );
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 加载骨架屏
|
|
|
|
|
+const SilverWisdomSkeleton: React.FC = () => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ <div className="rounded-xl overflow-hidden" style={{ backgroundColor: 'rgba(255,255,255,0.8)', border: `1px solid ${COLORS.ink.medium}` }}>
|
|
|
|
|
+ <div className="w-full h-48" style={{ backgroundColor: COLORS.ink.medium }}></div>
|
|
|
|
|
+ <div className="p-4">
|
|
|
|
|
+ <div className="h-4 rounded" style={{ backgroundColor: COLORS.ink.medium, width: '60%' }}></div>
|
|
|
|
|
+ <div className="mt-2 space-y-2">
|
|
|
|
|
+ <div className="h-3 rounded" style={{ backgroundColor: COLORS.ink.light }}></div>
|
|
|
|
|
+ <div className="h-3 rounded" style={{ backgroundColor: COLORS.ink.light, width: '80%' }}></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|