|
|
@@ -1,10 +1,10 @@
|
|
|
import React, { useState } from 'react';
|
|
|
import { useParams, useNavigate } from 'react-router-dom';
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
|
-import { useSilverWisdomDetail, wisdomCategories } from '@/client/mobile/hooks/useSilverWisdomData';
|
|
|
import { silverKnowledgeClient } from '@/client/api';
|
|
|
import { ChevronLeftIcon, HeartIcon, BookmarkIcon, ShareIcon, ArrowDownTrayIcon, EyeIcon } from '@heroicons/react/24/outline';
|
|
|
import { HeartIcon as HeartSolidIcon, BookmarkIcon as BookmarkSolidIcon } from '@heroicons/react/24/solid';
|
|
|
+import PdfPreview from '@/client/mobile/components/PdfPreview';
|
|
|
import dayjs from 'dayjs';
|
|
|
import 'dayjs/locale/zh-cn';
|
|
|
|
|
|
@@ -44,11 +44,22 @@ const SilverWisdomDetailPage: React.FC = () => {
|
|
|
const navigate = useNavigate();
|
|
|
const [isLiked, setIsLiked] = useState(false);
|
|
|
const [isBookmarked, setIsBookmarked] = useState(false);
|
|
|
- const [pdfLoading, setPdfLoading] = useState(false);
|
|
|
- const [pdfError, setPdfError] = useState(false);
|
|
|
- const [showPdfPreview, setShowPdfPreview] = useState(true);
|
|
|
|
|
|
- const { data, isLoading, error } = useSilverWisdomDetail(Number(id));
|
|
|
+ // 使用react query v5查询知识详情
|
|
|
+ const { data, isLoading, error } = useQuery({
|
|
|
+ queryKey: ['silver-wisdom-detail', id],
|
|
|
+ queryFn: async () => {
|
|
|
+ if (!id) throw new Error('ID is required');
|
|
|
+ const response = await silverKnowledgeClient[":id"].$get({
|
|
|
+ param: { id: Number(id) }
|
|
|
+ });
|
|
|
+ if (!response.ok) {
|
|
|
+ throw new Error('获取知识详情失败');
|
|
|
+ }
|
|
|
+ return response.json();
|
|
|
+ },
|
|
|
+ enabled: !!id
|
|
|
+ });
|
|
|
|
|
|
// 检查点赞和收藏状态
|
|
|
const checkInteractionStatus = async () => {
|
|
|
@@ -119,46 +130,6 @@ const SilverWisdomDetailPage: React.FC = () => {
|
|
|
return Math.ceil(wordCount / wordsPerMinute);
|
|
|
};
|
|
|
|
|
|
- const getCompatibilityMessage = () => {
|
|
|
- const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
|
- const isWechat = /MicroMessenger/i.test(navigator.userAgent);
|
|
|
- const isQQ = /QQ/i.test(navigator.userAgent);
|
|
|
-
|
|
|
- if (isWechat || isQQ) {
|
|
|
- return '微信/QQ内置浏览器暂不支持PDF预览,请使用系统浏览器打开';
|
|
|
- }
|
|
|
- if (isIOS && !checkPdfSupport()) {
|
|
|
- return '建议使用Safari浏览器获得最佳PDF预览体验';
|
|
|
- }
|
|
|
- return null;
|
|
|
- };
|
|
|
-
|
|
|
- // 移动端PDF兼容性检测
|
|
|
- const checkPdfSupport = () => {
|
|
|
- const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
|
- const isWechat = /MicroMessenger/i.test(navigator.userAgent);
|
|
|
- const isQQ = /QQ/i.test(navigator.userAgent);
|
|
|
-
|
|
|
- // 禁用微信、QQ内置浏览器的PDF预览
|
|
|
- if (isWechat || isQQ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // iOS Safari支持较好,但部分版本有问题
|
|
|
- if (isIOS) {
|
|
|
- return navigator.userAgent.includes('Safari') &&
|
|
|
- !navigator.userAgent.includes('CriOS') && // Chrome iOS
|
|
|
- !navigator.userAgent.includes('FxiOS'); // Firefox iOS
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- };
|
|
|
-
|
|
|
- const getResponsivePreviewHeight = () => {
|
|
|
- const screenHeight = window.innerHeight;
|
|
|
- return Math.min(320, screenHeight * 0.35); // 35%屏幕高度,最大320px
|
|
|
- };
|
|
|
-
|
|
|
const handleDownload = () => {
|
|
|
if (data?.attachment) {
|
|
|
// 创建临时链接下载,避免直接打开可能的安全问题
|
|
|
@@ -193,22 +164,6 @@ const SilverWisdomDetailPage: React.FC = () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const handlePdfPreview = () => {
|
|
|
- if (!data?.attachment) return;
|
|
|
-
|
|
|
- const isSupported = checkPdfSupport();
|
|
|
- if (!isSupported) {
|
|
|
- // 不支持的浏览器直接提供下载
|
|
|
- setShowPdfPreview(false);
|
|
|
- handleDownload();
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- setShowPdfPreview(true);
|
|
|
- setPdfLoading(true);
|
|
|
- setPdfError(false);
|
|
|
- };
|
|
|
-
|
|
|
// 处理加载状态
|
|
|
if (isLoading) {
|
|
|
return (
|
|
|
@@ -244,19 +199,6 @@ const SilverWisdomDetailPage: React.FC = () => {
|
|
|
// 解析标签
|
|
|
const tags = knowledge.tags ? String(knowledge.tags).split(',').map(tag => tag.trim()).filter(tag => tag) : [];
|
|
|
|
|
|
- // 使用useEffect检查PDF支持并设置预览状态
|
|
|
- React.useEffect(() => {
|
|
|
- if (knowledge.attachment && getFileExtension(knowledge.attachmentName || '') === 'pdf') {
|
|
|
- const isSupported = checkPdfSupport();
|
|
|
- setShowPdfPreview(isSupported);
|
|
|
- // 如果支持,初始化加载状态
|
|
|
- if (isSupported) {
|
|
|
- setPdfLoading(true);
|
|
|
- setPdfError(false);
|
|
|
- }
|
|
|
- }
|
|
|
- }, [knowledge.attachment, knowledge.attachmentName]);
|
|
|
-
|
|
|
return (
|
|
|
<div className="min-h-screen" style={{ backgroundColor: COLORS.ink.light }}>
|
|
|
{/* 头部导航 */}
|
|
|
@@ -394,92 +336,13 @@ const SilverWisdomDetailPage: React.FC = () => {
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- {/* 文件预览 - 仅对支持的格式显示 */}
|
|
|
+ {/* 文件预览 - 使用新的PDF预览组件 */}
|
|
|
{getFileExtension(knowledge.attachmentName || '') === 'pdf' && (
|
|
|
<div className="mt-4 border-t pt-4" style={{ borderColor: COLORS.ink.medium }}>
|
|
|
- {getCompatibilityMessage() && (
|
|
|
- <div className="p-3 rounded-lg mb-3"
|
|
|
- style={{ backgroundColor: 'rgba(255,248,220,0.8)', borderColor: COLORS.accent.red }}
|
|
|
- >
|
|
|
- <p className="text-xs" style={{ color: COLORS.accent.red }}>
|
|
|
- {getCompatibilityMessage()}
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- )}
|
|
|
-
|
|
|
- {showPdfPreview && (
|
|
|
- <>
|
|
|
- <div className="flex items-center justify-between mb-2">
|
|
|
- <p className="text-sm" style={{ color: COLORS.text.secondary }}>
|
|
|
- 文件预览:
|
|
|
- </p>
|
|
|
- <button
|
|
|
- onClick={handleDownload}
|
|
|
- className="text-xs px-2 py-1 rounded"
|
|
|
- style={{
|
|
|
- backgroundColor: COLORS.ink.medium,
|
|
|
- color: COLORS.text.primary
|
|
|
- }}
|
|
|
- >
|
|
|
- 下载查看
|
|
|
- </button>
|
|
|
- </div>
|
|
|
-
|
|
|
- {pdfLoading && (
|
|
|
- <div className="w-full h-48 flex items-center justify-center rounded-lg border"
|
|
|
- style={{ borderColor: COLORS.ink.medium, backgroundColor: 'rgba(255,255,255,0.5)' }}
|
|
|
- >
|
|
|
- <div className="text-center">
|
|
|
- <div className="animate-spin rounded-full h-6 w-6 border-b-2 mx-auto"
|
|
|
- style={{ borderColor: COLORS.ink.dark }}
|
|
|
- ></div>
|
|
|
- <p className="text-xs mt-2" style={{ color: COLORS.text.secondary }}>
|
|
|
- PDF加载中...
|
|
|
- </p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
-
|
|
|
- {pdfError && (
|
|
|
- <div className="w-full h-48 flex items-center justify-center rounded-lg border"
|
|
|
- style={{ borderColor: COLORS.ink.medium, backgroundColor: 'rgba(255,255,255,0.5)' }}
|
|
|
- >
|
|
|
- <div className="text-center">
|
|
|
- <p className="text-sm" style={{ color: COLORS.text.primary }}>
|
|
|
- 预览加载失败
|
|
|
- </p>
|
|
|
- <button
|
|
|
- onClick={handleDownload}
|
|
|
- className="text-xs mt-2 px-3 py-1 rounded"
|
|
|
- style={{
|
|
|
- backgroundColor: COLORS.ink.dark,
|
|
|
- color: 'white'
|
|
|
- }}
|
|
|
- >
|
|
|
- 下载查看
|
|
|
- </button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- )}
|
|
|
-
|
|
|
- {!pdfLoading && !pdfError && (
|
|
|
- <iframe
|
|
|
- src={knowledge.attachment}
|
|
|
- className="w-full rounded-lg border"
|
|
|
- style={{
|
|
|
- borderColor: COLORS.ink.medium,
|
|
|
- height: `${getResponsivePreviewHeight()}px`
|
|
|
- }}
|
|
|
- title={knowledge.attachmentName || 'PDF预览'}
|
|
|
- onLoad={() => setPdfLoading(false)}
|
|
|
- onError={() => {
|
|
|
- setPdfLoading(false);
|
|
|
- setPdfError(true);
|
|
|
- }}
|
|
|
- />
|
|
|
- )}
|
|
|
- </>
|
|
|
- )}
|
|
|
+ <PdfPreview
|
|
|
+ src={knowledge.attachment}
|
|
|
+ title={knowledge.attachmentName || 'PDF预览'}
|
|
|
+ />
|
|
|
</div>
|
|
|
)}
|
|
|
</div>
|