feat: 完善模块化 CLAUDE.md 文档体系
- 新增 admin/CLAUDE.md - 管理后台开发指导文档 - 修正技术栈为 React + TypeScript + shadcn/ui - 提供完整的管理后台架构设计 - 包含照片管理、分类管理、日志管理等核心功能 - 详细的开发环境配置和部署指南 - 新增 backend/CLAUDE.md - 后端开发指导文档 - 基于 Golang + Gin + GORM 技术栈 - 完整的 API 接口设计和数据库架构 - 包含认证、权限、文件存储等核心功能 - 详细的部署和监控配置 - 新增 ui/CLAUDE.md - UI 备份模块管理文档 - 支持组件备份和 A/B 测试功能 - 详细的同步策略和实验环境配置 - 完整的版本管理和协作流程 - 更新 CLAUDE.md 根目录文档 - 完善模块选择指南和协调机制 - 新增模块间通信和依赖关系说明 - 优化文档维护和使用建议 - 建立完整的模块化开发规范 通过模块化设计最大限度减少 AI 幻觉,提高开发效率。
This commit is contained in:
604
ui/CLAUDE.md
Normal file
604
ui/CLAUDE.md
Normal file
@ -0,0 +1,604 @@
|
||||
# UI 备份模块 - CLAUDE.md
|
||||
|
||||
此文件为 Claude Code 在 UI 备份模块工作时提供指导。
|
||||
|
||||
## 🎯 模块概览
|
||||
|
||||
UI 备份模块是主前端模块 (`frontend/`) 的备份和实验环境,用于保存稳定版本、测试新功能和组件开发。
|
||||
|
||||
### 模块用途
|
||||
- 🔄 主前端代码的备份版本
|
||||
- 🧪 新功能和组件的实验环境
|
||||
- 📦 组件库的独立维护
|
||||
- 🔧 A/B 测试和版本对比
|
||||
- 🛠️ 紧急回滚的备用版本
|
||||
|
||||
### 技术栈
|
||||
- **前端**: Next.js 15 + React 19 + TypeScript
|
||||
- **组件**: shadcn/ui + Radix UI
|
||||
- **样式**: Tailwind CSS
|
||||
- **构建**: Next.js 内置构建系统
|
||||
- **包管理**: pnpm (与主前端区分)
|
||||
|
||||
## 📁 目录结构
|
||||
|
||||
```
|
||||
ui/
|
||||
├── CLAUDE.md # 🔍 当前文件 - UI 备份模块指导
|
||||
├── app/ # Next.js 应用目录
|
||||
│ ├── globals.css # 全局样式
|
||||
│ ├── layout.tsx # 根布局
|
||||
│ └── page.tsx # 主页
|
||||
├── components/ # 组件目录
|
||||
│ ├── ui/ # shadcn/ui 组件
|
||||
│ │ ├── button.tsx # 按钮组件
|
||||
│ │ ├── card.tsx # 卡片组件
|
||||
│ │ ├── dialog.tsx # 对话框组件
|
||||
│ │ └── ... # 其他 UI 组件
|
||||
│ ├── about-view.tsx # 关于页面组件
|
||||
│ ├── contact-view.tsx # 联系页面组件
|
||||
│ ├── filter-bar.tsx # 过滤栏组件
|
||||
│ ├── loading-spinner.tsx # 加载组件
|
||||
│ ├── navigation.tsx # 导航组件
|
||||
│ ├── photo-gallery.tsx # 照片画廊组件
|
||||
│ ├── photo-modal.tsx # 照片弹窗组件
|
||||
│ ├── theme-provider.tsx # 主题提供器
|
||||
│ ├── timeline-stats.tsx # 时间线统计
|
||||
│ └── timeline-view.tsx # 时间线视图
|
||||
├── hooks/ # 自定义 Hook
|
||||
│ ├── use-mobile.tsx # 移动端检测
|
||||
│ └── use-toast.ts # 提示信息
|
||||
├── lib/ # 工具库
|
||||
│ └── utils.ts # 工具函数
|
||||
├── public/ # 静态资源
|
||||
│ ├── placeholder-logo.png # 占位图标
|
||||
│ ├── placeholder-user.jpg # 占位头像
|
||||
│ └── placeholder.jpg # 占位图片
|
||||
├── styles/ # 样式文件
|
||||
│ └── globals.css # 全局样式
|
||||
├── components.json # shadcn/ui 配置
|
||||
├── next.config.mjs # Next.js 配置
|
||||
├── package.json # 依赖配置
|
||||
├── pnpm-lock.yaml # pnpm 锁文件
|
||||
├── postcss.config.mjs # PostCSS 配置
|
||||
├── tailwind.config.ts # Tailwind 配置
|
||||
├── tsconfig.json # TypeScript 配置
|
||||
└── README.md # 模块说明
|
||||
```
|
||||
|
||||
## 🔄 与主前端的关系
|
||||
|
||||
### 同步策略
|
||||
```bash
|
||||
# 从主前端同步到 UI 备份
|
||||
# 1. 同步核心组件
|
||||
cp -r frontend/components/ui/* ui/components/ui/
|
||||
|
||||
# 2. 同步配置文件
|
||||
cp frontend/tailwind.config.ts ui/
|
||||
cp frontend/components.json ui/
|
||||
|
||||
# 3. 同步样式文件
|
||||
cp frontend/app/globals.css ui/app/
|
||||
cp frontend/styles/globals.css ui/styles/
|
||||
|
||||
# 4. 同步工具函数
|
||||
cp frontend/lib/utils.ts ui/lib/
|
||||
```
|
||||
|
||||
### 版本控制
|
||||
```bash
|
||||
# 创建备份分支
|
||||
git checkout -b ui-backup-v1.0.0
|
||||
|
||||
# 标记稳定版本
|
||||
git tag ui-v1.0.0
|
||||
|
||||
# 推送备份版本
|
||||
git push origin ui-backup-v1.0.0
|
||||
git push origin ui-v1.0.0
|
||||
```
|
||||
|
||||
## 🧪 实验环境配置
|
||||
|
||||
### 开发环境设置
|
||||
```bash
|
||||
# 进入 UI 备份目录
|
||||
cd ui/
|
||||
|
||||
# 安装依赖 (使用 pnpm)
|
||||
pnpm install
|
||||
|
||||
# 启动开发服务器
|
||||
pnpm dev
|
||||
|
||||
# 构建项目
|
||||
pnpm build
|
||||
|
||||
# 启动生产预览
|
||||
pnpm start
|
||||
```
|
||||
|
||||
### 环境变量配置
|
||||
```bash
|
||||
# .env.local
|
||||
NEXT_PUBLIC_API_URL=http://localhost:3001
|
||||
NEXT_PUBLIC_MOCK_API=true
|
||||
NEXT_PUBLIC_EXPERIMENTAL_FEATURES=true
|
||||
```
|
||||
|
||||
### 实验性功能开关
|
||||
```typescript
|
||||
// lib/experimental.ts
|
||||
export const experimentalFeatures = {
|
||||
// 新组件测试
|
||||
newPhotoGallery: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES === 'true',
|
||||
|
||||
// A/B 测试
|
||||
alternativeNavigation: false,
|
||||
|
||||
// 性能优化
|
||||
optimizedImages: true,
|
||||
|
||||
// 新主题
|
||||
darkModeV2: false,
|
||||
} as const
|
||||
|
||||
// 使用示例
|
||||
import { experimentalFeatures } from '@/lib/experimental'
|
||||
|
||||
export default function PhotoGallery() {
|
||||
if (experimentalFeatures.newPhotoGallery) {
|
||||
return <NewPhotoGallery />
|
||||
}
|
||||
|
||||
return <OriginalPhotoGallery />
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 组件库管理
|
||||
|
||||
### 组件分类
|
||||
```
|
||||
components/
|
||||
├── ui/ # 基础 UI 组件
|
||||
│ ├── button.tsx # 按钮 - 基础交互
|
||||
│ ├── input.tsx # 输入框 - 表单控件
|
||||
│ ├── card.tsx # 卡片 - 内容容器
|
||||
│ ├── dialog.tsx # 对话框 - 模态框
|
||||
│ ├── dropdown-menu.tsx # 下拉菜单 - 菜单控件
|
||||
│ ├── navigation-menu.tsx # 导航菜单 - 导航控件
|
||||
│ ├── tabs.tsx # 标签页 - 切换控件
|
||||
│ ├── toast.tsx # 提示信息 - 反馈组件
|
||||
│ └── ... # 其他基础组件
|
||||
├── business/ # 业务组件
|
||||
│ ├── photo-gallery.tsx # 照片画廊
|
||||
│ ├── photo-modal.tsx # 照片弹窗
|
||||
│ ├── timeline-view.tsx # 时间线视图
|
||||
│ ├── filter-bar.tsx # 过滤栏
|
||||
│ └── navigation.tsx # 站点导航
|
||||
├── layout/ # 布局组件
|
||||
│ ├── header.tsx # 页头
|
||||
│ ├── footer.tsx # 页脚
|
||||
│ └── sidebar.tsx # 侧边栏
|
||||
└── experimental/ # 实验性组件
|
||||
├── new-photo-gallery.tsx # 新照片画廊
|
||||
├── advanced-filter.tsx # 高级过滤器
|
||||
└── ai-search.tsx # AI 搜索
|
||||
```
|
||||
|
||||
### 组件开发规范
|
||||
```typescript
|
||||
// components/experimental/new-photo-gallery.tsx
|
||||
import { useState, useCallback } from 'react'
|
||||
import { Card, CardContent } from '@/components/ui/card'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
interface Photo {
|
||||
id: string
|
||||
src: string
|
||||
alt: string
|
||||
title: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
interface NewPhotoGalleryProps {
|
||||
photos: Photo[]
|
||||
onPhotoClick?: (photo: Photo) => void
|
||||
className?: string
|
||||
}
|
||||
|
||||
export function NewPhotoGallery({
|
||||
photos,
|
||||
onPhotoClick,
|
||||
className
|
||||
}: NewPhotoGalleryProps) {
|
||||
const [selectedPhoto, setSelectedPhoto] = useState<Photo | null>(null)
|
||||
|
||||
const handlePhotoClick = useCallback((photo: Photo) => {
|
||||
setSelectedPhoto(photo)
|
||||
onPhotoClick?.(photo)
|
||||
}, [onPhotoClick])
|
||||
|
||||
return (
|
||||
<div className={`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 ${className}`}>
|
||||
{photos.map((photo) => (
|
||||
<Card key={photo.id} className="overflow-hidden hover:shadow-lg transition-shadow">
|
||||
<CardContent className="p-0">
|
||||
<div
|
||||
className="relative aspect-square cursor-pointer"
|
||||
onClick={() => handlePhotoClick(photo)}
|
||||
>
|
||||
<img
|
||||
src={photo.src}
|
||||
alt={photo.alt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/0 hover:bg-black/20 transition-colors" />
|
||||
</div>
|
||||
{photo.title && (
|
||||
<div className="p-3">
|
||||
<h3 className="font-semibold text-sm">{photo.title}</h3>
|
||||
{photo.description && (
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
{photo.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 版本管理和同步
|
||||
|
||||
### 版本管理策略
|
||||
```bash
|
||||
# 1. 创建功能分支
|
||||
git checkout -b feature/new-component
|
||||
|
||||
# 2. 开发和测试
|
||||
# ... 组件开发 ...
|
||||
|
||||
# 3. 合并到 UI 备份主分支
|
||||
git checkout main
|
||||
git merge feature/new-component
|
||||
|
||||
# 4. 测试稳定后,同步到主前端
|
||||
cp ui/components/experimental/new-component.tsx frontend/components/
|
||||
```
|
||||
|
||||
### 自动同步脚本
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/sync-ui-to-frontend.sh
|
||||
|
||||
set -e
|
||||
|
||||
UI_DIR="ui"
|
||||
FRONTEND_DIR="frontend"
|
||||
|
||||
echo "🔄 开始同步 UI 备份到主前端..."
|
||||
|
||||
# 同步基础组件
|
||||
echo "📦 同步基础组件..."
|
||||
rsync -av --exclude='experimental' $UI_DIR/components/ui/ $FRONTEND_DIR/components/ui/
|
||||
|
||||
# 同步配置文件
|
||||
echo "⚙️ 同步配置文件..."
|
||||
cp $UI_DIR/tailwind.config.ts $FRONTEND_DIR/
|
||||
cp $UI_DIR/components.json $FRONTEND_DIR/
|
||||
|
||||
# 同步样式文件
|
||||
echo "🎨 同步样式文件..."
|
||||
cp $UI_DIR/app/globals.css $FRONTEND_DIR/app/
|
||||
cp $UI_DIR/styles/globals.css $FRONTEND_DIR/styles/
|
||||
|
||||
# 同步工具函数
|
||||
echo "🛠️ 同步工具函数..."
|
||||
cp $UI_DIR/lib/utils.ts $FRONTEND_DIR/lib/
|
||||
|
||||
echo "✅ 同步完成!"
|
||||
```
|
||||
|
||||
### 反向同步脚本
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# scripts/sync-frontend-to-ui.sh
|
||||
|
||||
set -e
|
||||
|
||||
FRONTEND_DIR="frontend"
|
||||
UI_DIR="ui"
|
||||
|
||||
echo "🔄 开始同步主前端到 UI 备份..."
|
||||
|
||||
# 创建备份
|
||||
echo "💾 创建备份..."
|
||||
timestamp=$(date +%Y%m%d_%H%M%S)
|
||||
cp -r $UI_DIR $UI_DIR.backup.$timestamp
|
||||
|
||||
# 同步核心文件
|
||||
echo "📦 同步核心文件..."
|
||||
rsync -av --exclude='experimental' --exclude='backup.*' $FRONTEND_DIR/ $UI_DIR/
|
||||
|
||||
# 保留实验性功能
|
||||
echo "🧪 保留实验性功能..."
|
||||
if [ -d "$UI_DIR.backup.$timestamp/components/experimental" ]; then
|
||||
cp -r $UI_DIR.backup.$timestamp/components/experimental $UI_DIR/components/
|
||||
fi
|
||||
|
||||
echo "✅ 同步完成!"
|
||||
```
|
||||
|
||||
## 🧪 A/B 测试和实验
|
||||
|
||||
### A/B 测试框架
|
||||
```typescript
|
||||
// lib/ab-testing.ts
|
||||
interface ABTest {
|
||||
name: string
|
||||
variants: {
|
||||
control: React.ComponentType<any>
|
||||
treatment: React.ComponentType<any>
|
||||
}
|
||||
percentage: number // 0-100
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
class ABTestManager {
|
||||
private tests: Map<string, ABTest> = new Map()
|
||||
|
||||
registerTest(test: ABTest) {
|
||||
this.tests.set(test.name, test)
|
||||
}
|
||||
|
||||
getVariant(testName: string): 'control' | 'treatment' | null {
|
||||
const test = this.tests.get(testName)
|
||||
if (!test || !test.enabled) return null
|
||||
|
||||
// 基于用户 ID 或 session 的一致性分组
|
||||
const hash = this.hashString(testName + this.getUserId())
|
||||
const percentage = hash % 100
|
||||
|
||||
return percentage < test.percentage ? 'treatment' : 'control'
|
||||
}
|
||||
|
||||
renderComponent(testName: string, props: any) {
|
||||
const test = this.tests.get(testName)
|
||||
if (!test) return null
|
||||
|
||||
const variant = this.getVariant(testName)
|
||||
if (variant === 'treatment') {
|
||||
return <test.variants.treatment {...props} />
|
||||
}
|
||||
return <test.variants.control {...props} />
|
||||
}
|
||||
|
||||
private hashString(str: string): number {
|
||||
let hash = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const char = str.charCodeAt(i)
|
||||
hash = ((hash << 5) - hash) + char
|
||||
hash = hash & hash // Convert to 32-bit integer
|
||||
}
|
||||
return Math.abs(hash)
|
||||
}
|
||||
|
||||
private getUserId(): string {
|
||||
// 实现用户 ID 获取逻辑
|
||||
return sessionStorage.getItem('userId') || 'anonymous'
|
||||
}
|
||||
}
|
||||
|
||||
export const abTestManager = new ABTestManager()
|
||||
|
||||
// 使用示例
|
||||
abTestManager.registerTest({
|
||||
name: 'photo-gallery-layout',
|
||||
variants: {
|
||||
control: OriginalPhotoGallery,
|
||||
treatment: NewPhotoGallery
|
||||
},
|
||||
percentage: 50,
|
||||
enabled: true
|
||||
})
|
||||
```
|
||||
|
||||
### 实验性功能管理
|
||||
```typescript
|
||||
// components/experimental/feature-flag.tsx
|
||||
import { experimentalFeatures } from '@/lib/experimental'
|
||||
|
||||
interface FeatureFlagProps {
|
||||
feature: keyof typeof experimentalFeatures
|
||||
children: React.ReactNode
|
||||
fallback?: React.ReactNode
|
||||
}
|
||||
|
||||
export function FeatureFlag({ feature, children, fallback = null }: FeatureFlagProps) {
|
||||
if (experimentalFeatures[feature]) {
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
return <>{fallback}</>
|
||||
}
|
||||
|
||||
// 使用示例
|
||||
<FeatureFlag feature="newPhotoGallery" fallback={<OriginalPhotoGallery />}>
|
||||
<NewPhotoGallery />
|
||||
</FeatureFlag>
|
||||
```
|
||||
|
||||
## 🚀 构建和部署
|
||||
|
||||
### 构建配置
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3002",
|
||||
"build": "next build",
|
||||
"start": "next start -p 3002",
|
||||
"lint": "next lint",
|
||||
"type-check": "tsc --noEmit",
|
||||
"export": "next build && next export",
|
||||
"sync-from-frontend": "./scripts/sync-frontend-to-ui.sh",
|
||||
"sync-to-frontend": "./scripts/sync-ui-to-frontend.sh"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Next.js 配置
|
||||
```typescript
|
||||
// next.config.mjs
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// 输出静态文件
|
||||
output: 'export',
|
||||
|
||||
// 基础路径 (用于部署到子路径)
|
||||
basePath: '/ui',
|
||||
|
||||
// 禁用图片优化 (静态导出)
|
||||
images: {
|
||||
unoptimized: true
|
||||
},
|
||||
|
||||
// 实验性功能
|
||||
experimental: {
|
||||
appDir: true,
|
||||
serverComponentsExternalPackages: []
|
||||
},
|
||||
|
||||
// 环境变量
|
||||
env: {
|
||||
NEXT_PUBLIC_UI_VERSION: process.env.npm_package_version || '1.0.0'
|
||||
}
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
```
|
||||
|
||||
### 部署配置
|
||||
```bash
|
||||
# 构建并部署到 UI 预览环境
|
||||
npm run build
|
||||
npm run export
|
||||
|
||||
# 部署到独立的 UI 预览域名
|
||||
rsync -av out/ user@server:/var/www/ui-preview/
|
||||
```
|
||||
|
||||
## 🔄 与其他模块的集成
|
||||
|
||||
### 与主前端的协作
|
||||
- 新功能在 UI 备份中实验和测试
|
||||
- 稳定后同步到主前端
|
||||
- 主前端的 bug 修复反向同步到 UI 备份
|
||||
|
||||
### 与管理后台的关系
|
||||
- 共享基础组件库
|
||||
- 管理后台可以复用 UI 备份中的组件
|
||||
- 保持设计系统的一致性
|
||||
|
||||
### 与后端的集成
|
||||
- 使用相同的 API 接口
|
||||
- 支持 Mock API 进行独立开发
|
||||
- 与后端版本保持兼容
|
||||
|
||||
## 🐛 问题排查
|
||||
|
||||
### 常见问题
|
||||
1. **组件不同步**: 检查同步脚本和版本控制
|
||||
2. **样式冲突**: 检查 Tailwind 配置和全局样式
|
||||
3. **依赖版本不一致**: 检查 package.json 和锁文件
|
||||
4. **构建失败**: 检查 TypeScript 配置和依赖
|
||||
|
||||
### 调试技巧
|
||||
```bash
|
||||
# 比较两个版本的差异
|
||||
diff -r frontend/components ui/components
|
||||
|
||||
# 检查依赖差异
|
||||
diff frontend/package.json ui/package.json
|
||||
|
||||
# 清理缓存
|
||||
rm -rf ui/.next ui/node_modules
|
||||
cd ui && pnpm install
|
||||
```
|
||||
|
||||
## 📊 监控和分析
|
||||
|
||||
### 性能监控
|
||||
```typescript
|
||||
// lib/performance.ts
|
||||
export function measurePerformance(name: string, fn: () => void) {
|
||||
const start = performance.now()
|
||||
fn()
|
||||
const end = performance.now()
|
||||
|
||||
console.log(`${name} took ${end - start} milliseconds`)
|
||||
|
||||
// 发送到分析服务
|
||||
if (typeof window !== 'undefined' && (window as any).gtag) {
|
||||
(window as any).gtag('event', 'timing_complete', {
|
||||
name: name,
|
||||
value: Math.round(end - start)
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 实验数据收集
|
||||
```typescript
|
||||
// lib/analytics.ts
|
||||
export function trackExperiment(testName: string, variant: string) {
|
||||
if (typeof window !== 'undefined' && (window as any).gtag) {
|
||||
(window as any).gtag('event', 'experiment_view', {
|
||||
experiment_id: testName,
|
||||
variant_id: variant
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function trackConversion(testName: string, variant: string, action: string) {
|
||||
if (typeof window !== 'undefined' && (window as any).gtag) {
|
||||
(window as any).gtag('event', 'experiment_conversion', {
|
||||
experiment_id: testName,
|
||||
variant_id: variant,
|
||||
action: action
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔮 未来规划
|
||||
|
||||
### 功能扩展
|
||||
- 🔧 可视化组件编辑器
|
||||
- 📊 实验结果分析面板
|
||||
- 🎨 设计系统自动化
|
||||
- 🤖 AI 辅助组件生成
|
||||
- 📱 响应式设计测试工具
|
||||
|
||||
### 工作流优化
|
||||
- 自动化同步流程
|
||||
- 持续集成测试
|
||||
- 可视化差异对比
|
||||
- 自动化 A/B 测试报告
|
||||
|
||||
## 📚 参考资料
|
||||
|
||||
- [Next.js 文档](https://nextjs.org/docs)
|
||||
- [React 19 新特性](https://react.dev/blog/2024/04/25/react-19)
|
||||
- [shadcn/ui 文档](https://ui.shadcn.com/)
|
||||
- [Tailwind CSS 文档](https://tailwindcss.com/docs)
|
||||
- [A/B 测试最佳实践](https://www.optimizely.com/optimization-glossary/ab-testing/)
|
||||
|
||||
---
|
||||
|
||||
💡 **使用提示**: UI 备份模块主要用于实验和备份,不建议在生产环境中直接使用。所有稳定的功能都应该同步到主前端模块。在进行实验时,请确保做好数据备份,避免影响主前端的稳定性。
|
||||
Reference in New Issue
Block a user