实验摘要

依据当前归档元数据整理;正文中的历史验证记录保留原有时间与口径。

模型 / 档位
MiniMax M2 · unknown
任务版本 / 轮次
v1 · 01
实验 / 归档日期
2025-11 / 未记录
输入留存
输入留存不完整
执行模式
执行模式未记录
工具
未记录
截图评分
83/100 · 规则 v3
费用
费用未记录
耗时
耗时未记录
人工修改
查看 5 条修改记录V2 归档:构建使用相对 base,静态产物提交至 previews;保留原有依赖与页面逻辑。;图片地址使用 Vite BASE_URL,补充 vite/client 类型声明,适配 Pages 子路径。;移除原始模板中不存在的 /vite.svg 引用,消除 Pages 404。;2026-10-12: 通过本地 HTTP 预览补拍代表性桌面截图 preview-2026-10-12.png;实验源码和原始输入未修改。;维护者于 2026-10-22 按 v3 对本轮桌面、手机及补充状态逐图重评并绑定 captures 证据;旧截图和 v2 评分见 catalog/score-reviews/2026-10-21-v3-source.json。未重跑模型或改写实验源码,截图不证明完整功能、算法、手势或性能。

查看完整原始输入 →

小蓝书 - 瀑布流图片展示

一个仿小红书的瀑布流图片展示页面,使用 React 18 + TypeScript 开发。

功能特性

  • ✨ 响应式瀑布流布局(移动端2列、平板3列、桌面4列)
  • 🖼️ 图片懒加载优化
  • ❤️ 点赞功能与动画效果
  • 🔍 顶部搜索栏
  • 📱 移动端优化
  • 🎨 清新简洁的 UI 设计
  • 🔄 无限滚动加载
  • ✨ 流畅的动画效果

技术栈

  • React 18 - 前端框架
  • TypeScript - 类型安全
  • Vite - 构建工具
  • Tailwind CSS - 样式框架
  • Zustand - 状态管理
  • react-lazyload - 图片懒加载
  • Lucide React - 图标库

快速开始

安装依赖

npm install

开发模式

npm run dev

构建生产版本

npm run build

预览生产版本

npm run preview

项目结构

├── public/
│   └── images/             # 图片资源(35张)
├── src/
│   ├── components/         # 组件目录
│   │   ├── SearchBar.tsx   # 搜索栏组件
│   │   ├── WaterfallGrid.tsx # 瀑布流网格组件
│   │   ├── PostCard.tsx    # 帖子卡片组件
│   │   └── LoadingSpinner.tsx # 加载动画组件
│   ├── store/              # 状态管理
│   │   └── useStore.ts     # Zustand store
│   ├── data/               # 数据层
│   │   └── mockData.ts     # Mock 数据
│   ├── App.tsx             # 主应用组件
│   ├── main.tsx            # 应用入口
│   └── index.css           # 全局样式
├── index.html              # HTML 模板
├── vite.config.ts          # Vite 配置
├── tailwind.config.js      # Tailwind 配置
└── tsconfig.json           # TypeScript 配置

设计亮点

  1. 响应式布局:根据屏幕尺寸自动调整列数
  2. 懒加载:图片进入视口时才开始加载,提升性能
  3. 交互动画:
    • 卡片hover上浮效果
    • 点击按压反馈
    • 点赞红心放大缩小动画
  4. 文字头像:根据用户名首字母生成彩色圆形头像
  5. 图片容错:图片加载失败时显示友好提示

主题色

  • 主色调:#fe2c55(小红书红)
  • 背景色:#f5f5f5
  • 卡片背景:纯白色,圆角 8px

浏览器支持

  • Chrome (>=88)
  • Firefox (>=85)
  • Safari (>=14)
  • Edge (>=88)

图片资源管理

Q: 构建时图片文件是如何自动拷贝到 dist 目录的?

A: 通过 Vite 配置实现(vite.config.ts:6-17):

build: {
  assetsInclude: ['**/*.jpg', '**/*.jpeg', '**/*.png', '**/*.gif'],
  rollupOptions: {
    output: {
      assetFileNames: (assetInfo) => {
        if (assetInfo.name && /\.(jpg|jpeg|png|gif)$/i.test(assetInfo.name)) {
          return 'images/[name][extname]'  // 图片输出到 dist/images/
        }
        return 'assets/[name]-[hash][extname]'  // 其他资源带hash
      }
    }
  }
}

效果: public/images/1.jpg → dist/images/1.jpg(自动拷贝,保持原名)


Q: 瀑布流布局是如何实现的?

A: 使用 CSS columns 属性(WaterfallGrid.tsx:59):

<div className="columns-2 sm:columns-3 lg:columns-4 gap-3">
  {posts.map((post) => (
    <PostCard key={post.id} post={post} />
  ))}
</div>

原理: 响应式列数 - 移动端2列、平板3列、桌面4列,CSS自动排列内容。


Q: 无限滚动是如何实现的?

A: 使用 IntersectionObserver 监听底部元素(WaterfallGrid.tsx:16-31):

useEffect(() => {
  const observer = new IntersectionObserver(
    (entries) => {
      const firstEntry = entries[0]
      if (firstEntry.isIntersecting && !loading && hasMore) {
        loadMorePosts()
      }
    },
    { threshold: 0.1 }
  )

  if (loaderRef.current) {
    observer.observe(loaderRef.current)
  }

  return () => observer.disconnect()
}, [loading, hasMore, page])

效果: 当底部加载指示器进入视口时自动加载下一页数据。


Q: 文字头像是如何生成的?

A: 基于用户ID生成彩色圆形头像(PostCard.tsx:26-27):

const DEFAULT_AVATAR_COLORS = [
  'bg-red-100', 'bg-blue-100', 'bg-yellow-100',
  'bg-green-100', 'bg-purple-100', 'bg-pink-100',
  'bg-indigo-100',
]

const avatarColor = DEFAULT_AVATAR_COLORS[post.id % DEFAULT_AVATAR_COLORS.length]
const avatarText = post.author.charAt(0)  // 取用户名首字母

效果: 8种颜色循环 + 姓氏首字母,无需外部头像图片。


Q: 点赞动画是如何实现的?

A: CSS Keyframes + 状态控制(tailwind.config.js:22-27 + PostCard.tsx:83-86):

// 1. 定义动画(tailwind.config.js)
'heart-beat': 'heartBeat 0.6s ease-in-out'
heartBeat: {
  '0%': { transform: 'scale(1)' },
  '25%': { transform: 'scale(1.3)' },  // 放大
  '50%': { transform: 'scale(1)' },    // 还原
  '100%': { transform: 'scale(1)' },
}

// 2. 应用动画(PostCard.tsx)
<Heart className={`heart ${showHeartAnimation ? 'animate-heart-beat' : ''}`} />

效果: 点击红心 → 放大1.3倍 → 回到原大小,持续0.6秒。


Q: 图片懒加载是如何实现的?

A: 使用 react-lazyload 库(PostCard.tsx:48-62):

<LazyLoad height={200} offset={100}>
  {!imageError ? (
    <img
      src={post.imageUrl}
      onError={() => setImageError(true)}
      loading="lazy"
    />
  ) : (
    <div className="fallback">图片加载失败</div>
  )}
</LazyLoad>

配置: 高度200px预加载,提前100px开始加载,失败时显示提示。

许可证

MIT

当前归档信息(自动生成)

  • 实验 ID:bluebook--minimax-m2-unknown-r01
  • 模型:MiniMax M2;推理档位:unknown
  • 类型:app;预览:build;网络:required
  • 完整原始输入快照 · 主题与其他版本
  • 输入记录:已保留历史文档;后续多轮输入、上下文和参考资料未完整留存。
  • 工具:未记录。来自历史实验说明;未记录的设置不作推测。
  • 运行方式:在本目录 npm ci 后 npm run dev;Pages 使用根目录 previews 中已提交的构建产物。
  • 主页面

部署适配记录

  • V2 归档:构建使用相对 base,静态产物提交至 previews;保留原有依赖与页面逻辑。
  • 图片地址使用 Vite BASE_URL,补充 vite/client 类型声明,适配 Pages 子路径。
  • 移除原始模板中不存在的 /vite.svg 引用,消除 Pages 404。
  • 2026-10-12: 通过本地 HTTP 预览补拍代表性桌面截图 preview-2026-10-12.png;实验源码和原始输入未修改。
  • 维护者于 2026-10-22 按 v3 对本轮桌面、手机及补充状态逐图重评并绑定 captures 证据;旧截图和 v2 评分见 catalog/score-reviews/2026-10-21-v3-source.json。未重跑模型或改写实验源码,截图不证明完整功能、算法、手势或性能。

本页目录 ↑