Просмотр исходного кода

♻️ refactor(category): 重构分类滚动组件布局

- 移除滚动功能,改为固定2行4列网格布局
- 移除useScrollIndicator和useTouchScroll钩子依赖
- 优化可见分类逻辑,最多显示8个分类
- 添加空白占位符确保网格布局完整
- 当分类超过8个时显示数量提示
- 调整按钮尺寸和布局样式以适应固定网格

💄 style(category): 优化分类项样式

- 调整分类项宽度为100%并设置最大宽度
- 使用aspectRatio替代固定高度,保持一致比例
- 优化网格间隙和整体布局
- 调整文字大小和权重,提升可读性
yourname 7 месяцев назад
Родитель
Сommit
2ea600523b
1 измененных файлов с 63 добавлено и 80 удалено
  1. 63 80
      src/client/mobile/components/CategoryScroll.tsx

+ 63 - 80
src/client/mobile/components/CategoryScroll.tsx

@@ -1,5 +1,4 @@
-import React, { useRef } from 'react';
-import { useScrollIndicator, useTouchScroll } from '../hooks/useScrollIndicator';
+import React from 'react';
 import { INK_COLORS } from '../styles/colors';
 import { FONT_STYLES } from '../styles/typography';
 
@@ -15,93 +14,77 @@ interface CategoryScrollProps {
 }
 
 export const CategoryScroll: React.FC<CategoryScrollProps> = ({ categories, onNavigate }) => {
-  const scrollContainerRef = useRef<HTMLDivElement>(null);
-  const { showIndicator } = useScrollIndicator({ 
-    containerRef: scrollContainerRef, 
-    threshold: 0.1 
-  });
-  const { handleTouchStart, handleTouchEnd, handleTouchMove } = useTouchScroll();
-
   if (categories.length === 0) return null;
 
+  // 2行布局,每行4个图标,总共显示8个图标
   const itemsPerRow = 4;
   const totalRows = 2;
-  const visibleItems = Math.min(itemsPerRow * totalRows, categories.length);
+  const maxVisibleItems = itemsPerRow * totalRows;
+  const visibleCategories = categories.slice(0, maxVisibleItems);
 
   return (
-    <div className="relative">
-      <div 
-        ref={scrollContainerRef}
-        className="overflow-x-auto pb-2 scroll-container"
-        style={{ 
-          WebkitOverflowScrolling: 'touch',
-          height: '200px',
-          cursor: 'grab'
-        }}
-        onTouchStart={handleTouchStart}
-        onTouchEnd={handleTouchEnd}
-        onTouchMove={handleTouchMove}
-      >
-        <div 
-          className="grid gap-3"
-          style={{ 
-            gridTemplateColumns: `repeat(${Math.max(8, categories.length)}, 1fr)`,
-            gridTemplateRows: 'repeat(2, 1fr)',
-            minWidth: `${Math.max(categories.length * 82, 340)}px`,
-            width: 'max-content',
-            height: '100%',
-            paddingRight: '30px'
-          }}
-        >
-          {categories.map((category, index) => (
-            <button
-              key={index}
-              onClick={() => onNavigate(category.path || '/')}
-              className="category-item flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-300 hover:shadow-lg backdrop-blur-sm cursor-pointer touch-feedback"
-              style={{
-                backgroundColor: 'rgba(255,255,255,0.7)',
-                border: `1px solid ${INK_COLORS.ink.medium}`,
-                color: INK_COLORS.text.primary,
-                width: '75px',
-                height: '85px'
-              }}
+    <div className="w-full">
+      {/* 2行固定网格布局 */}
+      <div className="grid grid-cols-4 gap-3">
+        {visibleCategories.map((category, index) => (
+          <button
+            key={index}
+            onClick={() => onNavigate(category.path || '/')}
+            className="category-item flex flex-col items-center justify-center p-2 rounded-xl transition-all duration-300 hover:shadow-lg backdrop-blur-sm cursor-pointer touch-feedback"
+            style={{
+              backgroundColor: 'rgba(255,255,255,0.7)',
+              border: `1px solid ${INK_COLORS.ink.medium}`,
+              color: INK_COLORS.text.primary,
+              width: '100%',
+              aspectRatio: '1/1.2',
+              maxWidth: '80px'
+            }}
+          >
+            <div
+              className="w-12 h-12 rounded-full flex items-center justify-center shadow-sm mb-1"
+              style={{ backgroundColor: INK_COLORS.accent.blue, color: 'white' }}
             >
-              <div
-                className="w-12 h-12 rounded-full flex items-center justify-center shadow-sm mb-1"
-                style={{ backgroundColor: INK_COLORS.accent.blue, color: 'white' }}
-              >
-                <img
-                  src={category.image || '/images/placeholder.jpg'}
-                  alt={category.name}
-                  className="w-7 h-7 object-cover rounded-full"
-                  onError={(e) => {
-                    (e.target as HTMLImageElement).style.display = 'none';
-                    (e.target as HTMLImageElement).parentElement!.innerHTML = '📱';
-                  }}
-                />
-              </div>
-              <span 
-                className={`${FONT_STYLES.caption} text-xs text-center line-clamp-2`}
-                style={{ fontSize: '11px', fontWeight: 500 }}
-              >
-                {category.name}
-              </span>
-            </button>
-          ))}
-        </div>
-      </div>
-      
-      {/* 智能滚动指示器 */}
-      {showIndicator && categories.length > visibleItems && (
-        <div className="absolute right-0 top-0 bottom-0 flex items-center pointer-events-none">
-          <div className="w-8 h-full bg-gradient-to-l from-ink-light via-ink-light/80 to-transparent"></div>
-          <div className="absolute right-1 top-1/2 -translate-y-1/2">
-            <div className="w-6 h-6 rounded-full bg-white shadow-lg flex items-center justify-center scroll-indicator">
-              <svg className="w-3 h-3 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
-                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
-              </svg>
+              <img
+                src={category.image || '/images/placeholder.jpg'}
+                alt={category.name}
+                className="w-7 h-7 object-cover rounded-full"
+                onError={(e) => {
+                  (e.target as HTMLImageElement).style.display = 'none';
+                  (e.target as HTMLImageElement).parentElement!.innerHTML = '📱';
+                }}
+              />
             </div>
+            <span 
+              className={`${FONT_STYLES.caption} text-xs text-center line-clamp-2`}
+              style={{ fontSize: '11px', fontWeight: 500 }}
+            >
+              {category.name}
+            </span>
+          </button>
+        ))}
+        
+        {/* 如果图标不足8个,填充空白占位符 */}
+        {Array.from({ length: Math.max(0, maxVisibleItems - visibleCategories.length) }).map((_, index) => (
+          <div
+            key={`placeholder-${index}`}
+            className="flex flex-col items-center justify-center p-2"
+            style={{ opacity: 0, pointerEvents: 'none' }}
+          >
+            <div className="w-12 h-12 rounded-full"></div>
+            <span className="text-xs text-center mt-1"></span>
           </div>
+        ))}
+      </div>
+      
+      {/* 如果分类超过8个,显示提示 */}
+      {categories.length > maxVisibleItems && (
+        <div className="text-center mt-2">
+          <span 
+            className={`${FONT_STYLES.caption} text-xs`}
+            style={{ color: INK_COLORS.text.light }}
+          >
+            还有 {categories.length - maxVisibleItems} 个分类
+          </span>
         </div>
       )}
     </div>