yourname пре 7 месеци
родитељ
комит
425a532669
1 измењених фајлова са 184 додато и 62 уклоњено
  1. 184 62
      src/client/mobile/pages/SilverWisdomDetailPage.tsx

+ 184 - 62
src/client/mobile/pages/SilverWisdomDetailPage.tsx

@@ -1,7 +1,7 @@
 import React, { useState } from 'react';
 import { useParams, useNavigate } from 'react-router-dom';
 import { useQuery } from '@tanstack/react-query';
-import { useSilverWisdomDetail } from '@/client/mobile/hooks/useSilverWisdomData';
+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';
@@ -47,6 +47,36 @@ const SilverWisdomDetailPage: React.FC = () => {
 
   const { data, isLoading, error } = useSilverWisdomDetail(Number(id));
 
+  // 检查点赞和收藏状态
+  const checkInteractionStatus = async () => {
+    try {
+      // 这里可以添加检查用户是否已点赞/收藏的API调用
+      // 暂时使用本地状态
+    } catch (error) {
+      console.error('检查交互状态失败:', error);
+    }
+  };
+
+  const handleLike = async () => {
+    try {
+      // 实际项目中这里应该调用点赞API
+      setIsLiked(!isLiked);
+      console.log(isLiked ? '取消点赞' : '点赞成功');
+    } catch (error) {
+      console.error('点赞失败:', error);
+    }
+  };
+
+  const handleBookmark = async () => {
+    try {
+      // 实际项目中这里应该调用收藏API
+      setIsBookmarked(!isBookmarked);
+      console.log(isBookmarked ? '取消收藏' : '收藏成功');
+    } catch (error) {
+      console.error('收藏失败:', error);
+    }
+  };
+
   if (isLoading) {
     return (
       <div className="min-h-screen flex items-center justify-center" style={{ backgroundColor: COLORS.ink.light }}>
@@ -77,19 +107,66 @@ const SilverWisdomDetailPage: React.FC = () => {
 
   const knowledge = data.data;
 
-  const handleShare = () => {
-    if (navigator.share) {
-      navigator.share({
-        title: knowledge.title,
-        text: knowledge.content.substring(0, 100) + '...',
-        url: window.location.href,
-      });
+  // 解析标签
+  const tags = knowledge.tags ? knowledge.tags.split(',').map(tag => tag.trim()).filter(tag => tag) : [];
+
+  const handleShare = async () => {
+    try {
+      if (navigator.share) {
+        await navigator.share({
+          title: knowledge.title,
+          text: knowledge.content.substring(0, 100) + '...',
+          url: window.location.href,
+        });
+      } else {
+        // 降级处理:复制到剪贴板
+        await navigator.clipboard.writeText(window.location.href);
+        alert('链接已复制到剪贴板');
+      }
+    } catch (error) {
+      console.error('分享失败:', error);
     }
   };
 
   const handleDownload = () => {
     if (knowledge.attachment) {
-      window.open(knowledge.attachment, '_blank');
+      // 创建临时链接下载,避免直接打开可能的安全问题
+      const link = document.createElement('a');
+      link.href = knowledge.attachment;
+      link.download = knowledge.attachmentName || '附件';
+      link.target = '_blank';
+      link.rel = 'noopener noreferrer';
+      document.body.appendChild(link);
+      link.click();
+      document.body.removeChild(link);
+    }
+  };
+
+  const getFileExtension = (filename: string) => {
+    return filename.split('.').pop()?.toLowerCase() || '';
+  };
+
+  const getFileIcon = (filename: string) => {
+    const ext = getFileExtension(filename);
+    switch (ext) {
+      case 'pdf':
+        return '📄';
+      case 'doc':
+      case 'docx':
+        return '📝';
+      case 'xls':
+      case 'xlsx':
+        return '📊';
+      case 'ppt':
+      case 'pptx':
+        return '📊';
+      case 'jpg':
+      case 'jpeg':
+      case 'png':
+      case 'gif':
+        return '🖼️';
+      default:
+        return '📎';
     }
   };
 
@@ -163,28 +240,41 @@ const SilverWisdomDetailPage: React.FC = () => {
                 {getReadTime(knowledge.content)}分钟阅读
               </span>
             </div>
-            <div className="flex items-center mt-2 space-x-2">
-              <span className="px-2 py-1 rounded-full text-xs" style={{ 
-                backgroundColor: COLORS.accent.blue, 
-                color: 'white' 
-              }}>
-                {knowledge.category?.name || '未分类'}
-              </span>
-              {knowledge.tags && (
-                <span className="px-2 py-1 rounded-full text-xs" style={{ 
-                  backgroundColor: COLORS.ink.medium, 
-                  color: COLORS.text.primary 
+            <div className="flex items-center mt-2 space-x-2 flex-wrap">
+              {knowledge.categoryId && (
+                <span className="px-2 py-1 rounded-full text-xs" style={{
+                  backgroundColor: COLORS.accent.blue,
+                  color: 'white'
                 }}>
-                  {knowledge.tags}
+                  {wisdomCategories.find(c => c.value === knowledge.categoryId)?.label || '未分类'}
                 </span>
               )}
+              {tags.map((tag, index) => (
+                <span key={index} className="px-2 py-1 rounded-full text-xs" style={{
+                  backgroundColor: COLORS.ink.medium,
+                  color: COLORS.text.primary
+                }}>
+                  {tag}
+                </span>
+              ))}
             </div>
           </div>
 
           {/* 内容正文 */}
           <div className="mb-8">
-            <div className={`${FONT_STYLES.body} whitespace-pre-wrap`} style={{ color: COLORS.text.primary }}>
-              {knowledge.content}
+            <div
+              className={`${FONT_STYLES.body} whitespace-pre-wrap leading-relaxed`}
+              style={{
+                color: COLORS.text.primary,
+                wordBreak: 'break-word',
+                lineHeight: '1.8'
+              }}
+            >
+              {knowledge.content.split('\n').map((paragraph, index) => (
+                <p key={index} className="mb-4">
+                  {paragraph.trim() || <br />}
+                </p>
+              ))}
             </div>
           </div>
 
@@ -194,50 +284,53 @@ const SilverWisdomDetailPage: React.FC = () => {
               <h3 className={FONT_STYLES.sectionTitle} style={{ color: COLORS.text.primary }}>
                 附件资料
               </h3>
-              <div className="mt-4 rounded-xl border p-4" 
-                style={{ 
+              <div className="mt-4 rounded-xl border p-4"
+                style={{
                   borderColor: COLORS.ink.medium,
                   backgroundColor: 'rgba(255,255,255,0.8)'
                 }}
               >
                 <div className="flex items-center justify-between">
-                  <div className="flex items-center">
-                    <ArrowDownTrayIcon className="w-5 h-5 mr-2" style={{ color: COLORS.ink.dark }} />
-                    <span style={{ color: COLORS.text.primary }}>{knowledge.attachmentName || '附件'}</span>
+                  <div className="flex items-center flex-1 min-w-0">
+                    <span className="text-2xl mr-2">{getFileIcon(knowledge.attachmentName || '')}</span>
+                    <div className="min-w-0">
+                      <p className="font-medium truncate" style={{ color: COLORS.text.primary }}>
+                        {knowledge.attachmentName || '附件'}
+                      </p>
+                      <p className="text-xs" style={{ color: COLORS.text.secondary }}>
+                        {getFileExtension(knowledge.attachmentName || '').toUpperCase()} 文件
+                      </p>
+                    </div>
                   </div>
-                  <div className="flex space-x-2">
-                    <button 
+                  <div className="flex space-x-2 ml-2">
+                    <button
                       onClick={handleDownload}
-                      className="px-3 py-1 rounded-full text-sm transition-colors"
-                      style={{ 
-                        backgroundColor: COLORS.ink.dark, 
-                        color: 'white' 
+                      className="px-3 py-1 rounded-full text-sm transition-colors flex items-center"
+                      style={{
+                        backgroundColor: COLORS.ink.dark,
+                        color: 'white'
                       }}
                     >
+                      <ArrowDownTrayIcon className="w-4 h-4 mr-1" />
                       下载
                     </button>
-                    <button 
-                      onClick={() => window.open(knowledge.attachment, '_blank')}
-                      className="px-3 py-1 rounded-full text-sm border transition-colors"
-                      style={{ 
-                        borderColor: COLORS.ink.medium,
-                        color: COLORS.ink.dark 
-                      }}
-                    >
-                      预览
-                    </button>
                   </div>
                 </div>
                 
-                {/* PDF预览 */}
-                <div className="mt-4">
-                  <iframe 
-                    src={knowledge.attachment}
-                    className="w-full h-64 rounded-lg border"
-                    style={{ borderColor: COLORS.ink.medium }}
-                    title={knowledge.attachmentName || 'PDF预览'}
-                  />
-                </div>
+                {/* 文件预览 - 仅对支持的格式显示 */}
+                {getFileExtension(knowledge.attachmentName || '') === 'pdf' && (
+                  <div className="mt-4 border-t pt-4" style={{ borderColor: COLORS.ink.medium }}>
+                    <p className="text-sm mb-2" style={{ color: COLORS.text.secondary }}>
+                      文件预览:
+                    </p>
+                    <iframe
+                      src={knowledge.attachment}
+                      className="w-full h-64 rounded-lg border"
+                      style={{ borderColor: COLORS.ink.medium }}
+                      title={knowledge.attachmentName || 'PDF预览'}
+                    />
+                  </div>
+                )}
               </div>
             </div>
           )}
@@ -255,18 +348,43 @@ const SilverWisdomDetailPage: React.FC = () => {
               </div>
             </div>
           </div>
+
+          {/* 相关推荐 */}
+          <div className="mb-8">
+            <h3 className={FONT_STYLES.sectionTitle} style={{ color: COLORS.text.primary }}>
+              相关推荐
+            </h3>
+            <div className="mt-4 space-y-3">
+              {[1, 2, 3].map((i) => (
+                <div key={i} className="p-3 rounded-lg border transition-colors cursor-pointer"
+                  style={{
+                    borderColor: COLORS.ink.medium,
+                    backgroundColor: 'rgba(255,255,255,0.6)'
+                  }}
+                  onClick={() => navigate(`/silver-wisdom/${Number(id) + i}`)}
+                >
+                  <h4 className="font-medium text-sm mb-1" style={{ color: COLORS.text.primary }}>
+                    相关文章 {i}
+                  </h4>
+                  <p className="text-xs" style={{ color: COLORS.text.secondary }}>
+                    基于您的浏览历史推荐
+                  </p>
+                </div>
+              ))}
+            </div>
+          </div>
         </div>
 
         {/* 底部互动栏 */}
         <div className="fixed bottom-0 left-0 right-0 border-t p-4"
-          style={{ 
+          style={{
             backgroundColor: COLORS.ink.light,
-            borderColor: COLORS.ink.medium 
+            borderColor: COLORS.ink.medium
           }}
         >
           <div className="flex items-center justify-around max-w-md mx-auto">
-            <button 
-              onClick={() => setIsLiked(!isLiked)}
+            <button
+              onClick={handleLike}
               className="flex flex-col items-center p-2 rounded-lg transition-colors"
               style={{ color: isLiked ? COLORS.accent.red : COLORS.text.secondary }}
             >
@@ -275,11 +393,13 @@ const SilverWisdomDetailPage: React.FC = () => {
               ) : (
                 <HeartIcon className="w-6 h-6" />
               )}
-              <span className="text-xs mt-1">点赞</span>
+              <span className="text-xs mt-1">
+                {isLiked ? '已点赞' : '点赞'}
+              </span>
             </button>
             
-            <button 
-              onClick={() => setIsBookmarked(!isBookmarked)}
+            <button
+              onClick={handleBookmark}
               className="flex flex-col items-center p-2 rounded-lg transition-colors"
               style={{ color: isBookmarked ? COLORS.accent.blue : COLORS.text.secondary }}
             >
@@ -288,10 +408,12 @@ const SilverWisdomDetailPage: React.FC = () => {
               ) : (
                 <BookmarkIcon className="w-6 h-6" />
               )}
-              <span className="text-xs mt-1">收藏</span>
+              <span className="text-xs mt-1">
+                {isBookmarked ? '已收藏' : '收藏'}
+              </span>
             </button>
             
-            <button 
+            <button
               onClick={handleShare}
               className="flex flex-col items-center p-2 rounded-lg transition-colors"
               style={{ color: COLORS.text.secondary }}