|
|
@@ -1,66 +1,113 @@
|
|
|
import { useState, useMemo } from 'react';
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
-import { mockSilverWisdomData, SilverWisdomItem, wisdomCategories } from '../data/mockSilverWisdomData';
|
|
|
+import { silverKnowledgeClient } from '@/client/api';
|
|
|
+import type { InferResponseType } from 'hono/client';
|
|
|
|
|
|
-export const useSilverWisdomData = (searchQuery?: string, category?: string) => {
|
|
|
- const [selectedCategory, setSelectedCategory] = useState<string>(category || 'all');
|
|
|
+// 定义移动端银龄智库数据结构,基于实体定义
|
|
|
+export interface SilverWisdomItem {
|
|
|
+ id: number;
|
|
|
+ title: string;
|
|
|
+ content: string;
|
|
|
+ category: string;
|
|
|
+ categoryId: number;
|
|
|
+ author: string;
|
|
|
+ status: number;
|
|
|
+ viewCount: number;
|
|
|
+ likeCount: number;
|
|
|
+ coverImage: string | null;
|
|
|
+ tags: string | null;
|
|
|
+ attachment: string | null;
|
|
|
+ attachmentName: string | null;
|
|
|
+ createdAt: string;
|
|
|
+ updatedAt: string;
|
|
|
+ readTime?: number; // 计算字段
|
|
|
+ commentCount?: number; // 可选字段
|
|
|
+ isFeatured?: boolean; // 可选字段
|
|
|
+}
|
|
|
|
|
|
- // 使用模拟数据的查询
|
|
|
- const { data, isLoading, isError, error } = useQuery({
|
|
|
- queryKey: ['silver-wisdom', searchQuery, selectedCategory],
|
|
|
- queryFn: async () => {
|
|
|
- // 模拟API延迟
|
|
|
- await new Promise(resolve => setTimeout(resolve, 800));
|
|
|
-
|
|
|
- let filteredData = mockSilverWisdomData;
|
|
|
+// 定义分类
|
|
|
+export const wisdomCategories = [
|
|
|
+ { value: 'all', label: '全部', icon: '📚' },
|
|
|
+ { value: 1, label: '健康养生', icon: '🏥' },
|
|
|
+ { value: 2, label: '认知训练', icon: '🧠' },
|
|
|
+ { value: 3, label: '生活艺术', icon: '🎨' },
|
|
|
+ { value: 4, label: '理财规划', icon: '💰' },
|
|
|
+ { value: 5, label: '艺术修养', icon: '🎭' },
|
|
|
+ { value: 6, label: '科技应用', icon: '📱' }
|
|
|
+];
|
|
|
|
|
|
- // 按分类筛选
|
|
|
- if (selectedCategory && selectedCategory !== 'all') {
|
|
|
- filteredData = filteredData.filter(item => item.category === selectedCategory);
|
|
|
- }
|
|
|
+// 从API响应提取类型
|
|
|
+type SilverKnowledgeResponse = InferResponseType<typeof silverKnowledgeClient.$get, 200>;
|
|
|
+type SilverKnowledgeItem = SilverKnowledgeResponse['data'][0];
|
|
|
|
|
|
- // 按搜索关键词筛选
|
|
|
- if (searchQuery?.trim()) {
|
|
|
- const query = searchQuery.toLowerCase();
|
|
|
- filteredData = filteredData.filter(item =>
|
|
|
- item.title.toLowerCase().includes(query) ||
|
|
|
- item.content.toLowerCase().includes(query) ||
|
|
|
- item.author.name.toLowerCase().includes(query) ||
|
|
|
- item.tags.some(tag => tag.toLowerCase().includes(query)) ||
|
|
|
- item.category.toLowerCase().includes(query)
|
|
|
- );
|
|
|
- }
|
|
|
+export const useSilverWisdomData = (searchQuery?: string, categoryId?: number) => {
|
|
|
+ const [selectedCategory, setSelectedCategory] = useState<number | string>(categoryId || 'all');
|
|
|
|
|
|
- // 按精选和发布时间排序
|
|
|
- return filteredData.sort((a, b) => {
|
|
|
- if (a.isFeatured !== b.isFeatured) {
|
|
|
- return a.isFeatured ? -1 : 1;
|
|
|
+ // 使用真实API数据
|
|
|
+ const { data, isLoading, isError, error } = useQuery({
|
|
|
+ queryKey: ['silver-wisdom', searchQuery, selectedCategory],
|
|
|
+ queryFn: async () => {
|
|
|
+ const response = await silverKnowledgeClient.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 100,
|
|
|
+ keyword: searchQuery || undefined,
|
|
|
+ ...(selectedCategory !== 'all' && { filters: JSON.stringify({ categoryId: selectedCategory }) })
|
|
|
}
|
|
|
- return new Date(b.publishDate).getTime() - new Date(a.publishDate).getTime();
|
|
|
});
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('获取数据失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await response.json();
|
|
|
+ return result.data;
|
|
|
},
|
|
|
- staleTime: 5 * 60 * 1000, // 5分钟
|
|
|
- gcTime: 10 * 60 * 1000, // 10分钟
|
|
|
+ staleTime: 5 * 60 * 1000,
|
|
|
+ gcTime: 10 * 60 * 1000,
|
|
|
});
|
|
|
|
|
|
+ // 转换API数据为移动端格式
|
|
|
+ const wisdomItems: SilverWisdomItem[] = useMemo(() => {
|
|
|
+ if (!data) return [];
|
|
|
+
|
|
|
+ return data.map((item: SilverKnowledgeItem) => ({
|
|
|
+ id: item.id,
|
|
|
+ title: item.title,
|
|
|
+ content: item.content,
|
|
|
+ category: item.category?.name || '未分类',
|
|
|
+ categoryId: item.categoryId,
|
|
|
+ author: item.author,
|
|
|
+ status: item.status,
|
|
|
+ viewCount: item.viewCount,
|
|
|
+ likeCount: item.likeCount,
|
|
|
+ coverImage: item.coverImage,
|
|
|
+ tags: item.tags,
|
|
|
+ attachment: item.attachment,
|
|
|
+ attachmentName: item.attachmentName,
|
|
|
+ createdAt: item.createdAt,
|
|
|
+ updatedAt: item.updatedAt,
|
|
|
+ // 计算阅读时间(按每分钟200字估算)
|
|
|
+ readTime: Math.max(1, Math.ceil(item.content.length / 200)),
|
|
|
+ // 评论数暂用0,后续可扩展
|
|
|
+ commentCount: 0,
|
|
|
+ // 精选规则:浏览量>1000且点赞率>5%
|
|
|
+ isFeatured: item.viewCount > 1000 && (item.likeCount / item.viewCount) > 0.05
|
|
|
+ }));
|
|
|
+ }, [data]);
|
|
|
+
|
|
|
// 统计信息
|
|
|
const stats = useMemo(() => {
|
|
|
- const items = data || mockSilverWisdomData;
|
|
|
return {
|
|
|
- totalCount: items.length,
|
|
|
- categoryCounts: wisdomCategories.reduce((acc, cat) => {
|
|
|
- if (cat.value !== 'all') {
|
|
|
- acc[cat.value] = items.filter(item => item.category === cat.value).length;
|
|
|
- }
|
|
|
- return acc;
|
|
|
- }, {} as Record<string, number>),
|
|
|
- totalViews: items.reduce((sum, item) => sum + item.viewCount, 0),
|
|
|
- totalLikes: items.reduce((sum, item) => sum + item.likeCount, 0)
|
|
|
+ totalCount: wisdomItems.length,
|
|
|
+ totalViews: wisdomItems.reduce((sum, item) => sum + item.viewCount, 0),
|
|
|
+ totalLikes: wisdomItems.reduce((sum, item) => sum + item.likeCount, 0),
|
|
|
+ expertCount: new Set(wisdomItems.map(item => item.author)).size
|
|
|
};
|
|
|
- }, [data]);
|
|
|
+ }, [wisdomItems]);
|
|
|
|
|
|
return {
|
|
|
- wisdomItems: data || [],
|
|
|
+ wisdomItems,
|
|
|
categories: wisdomCategories,
|
|
|
selectedCategory,
|
|
|
setSelectedCategory,
|
|
|
@@ -76,12 +123,16 @@ export const useSilverWisdomDetail = (id: number) => {
|
|
|
return useQuery({
|
|
|
queryKey: ['silver-wisdom-detail', id],
|
|
|
queryFn: async () => {
|
|
|
- await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
- const item = mockSilverWisdomData.find(item => item.id === id);
|
|
|
- if (!item) {
|
|
|
- throw new Error('知识内容不存在');
|
|
|
+ const response = await silverKnowledgeClient[':id'].$get({
|
|
|
+ param: { id: id.toString() }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('获取详情失败');
|
|
|
}
|
|
|
- return item;
|
|
|
+
|
|
|
+ const result = await response.json();
|
|
|
+ return result;
|
|
|
}
|
|
|
});
|
|
|
};
|
|
|
@@ -91,16 +142,48 @@ export const useRecommendedWisdom = (excludeId?: number) => {
|
|
|
return useQuery({
|
|
|
queryKey: ['recommended-wisdom', excludeId],
|
|
|
queryFn: async () => {
|
|
|
- await new Promise(resolve => setTimeout(resolve, 500));
|
|
|
- let items = [...mockSilverWisdomData];
|
|
|
+ const response = await silverKnowledgeClient.$get({
|
|
|
+ query: {
|
|
|
+ page: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ ...(excludeId && { filters: JSON.stringify({ id: { gt: 0 } }) })
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('获取推荐失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ const result = await response.json();
|
|
|
+ let items = result.data || [];
|
|
|
|
|
|
if (excludeId) {
|
|
|
- items = items.filter(item => item.id !== excludeId);
|
|
|
+ items = items.filter((item: SilverKnowledgeItem) => item.id !== excludeId);
|
|
|
}
|
|
|
|
|
|
return items
|
|
|
- .sort((a, b) => b.viewCount - a.viewCount)
|
|
|
- .slice(0, 4);
|
|
|
+ .sort((a: SilverKnowledgeItem, b: SilverKnowledgeItem) => b.viewCount - a.viewCount)
|
|
|
+ .slice(0, 4)
|
|
|
+ .map((item: SilverKnowledgeItem) => ({
|
|
|
+ id: item.id,
|
|
|
+ title: item.title,
|
|
|
+ content: item.content,
|
|
|
+ category: item.category?.name || '未分类',
|
|
|
+ categoryId: item.categoryId,
|
|
|
+ author: item.author,
|
|
|
+ status: item.status,
|
|
|
+ viewCount: item.viewCount,
|
|
|
+ likeCount: item.likeCount,
|
|
|
+ coverImage: item.coverImage,
|
|
|
+ tags: item.tags,
|
|
|
+ attachment: item.attachment,
|
|
|
+ attachmentName: item.attachmentName,
|
|
|
+ createdAt: item.createdAt,
|
|
|
+ updatedAt: item.updatedAt,
|
|
|
+ readTime: Math.max(1, Math.ceil(item.content.length / 200)),
|
|
|
+ commentCount: 0,
|
|
|
+ isFeatured: item.viewCount > 1000 && (item.likeCount / item.viewCount) > 0.05
|
|
|
+ }));
|
|
|
}
|
|
|
});
|
|
|
};
|