Files
smart-crop-ui/crop-x/docs/开发项目规范.md

427 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 开发项目规范
## pathland-information/archive/statisticsname统计分析页面开发经验
### 总体开发经验总结
在实现统计分析页面过程中我们遵循了以下8条核心开发规范确保代码质量、可维护性和用户体验的一致性。
### 1. shadcn 样式系统优先原则
**经验总结:**
- 优先使用shadcn的语义化颜色类`bg-card``bg-background`替代硬编码的Tailwind CSS颜色
- 避免使用 `bg-red-500` 等具体颜色值,改用 `bg-red-50 dark:bg-red-950` 等语义化类
- 统计卡片使用 `bg-green-50 dark:bg-green-950` 等主题感知的背景色
**最佳实践:**
```tsx
// ✅ 推荐写法
<Card className="p-4 bg-green-50 dark:bg-green-950">
<Card className="bg-card hover:bg-muted">
// ❌ 避免写法
<Card className="p-4 bg-green-100">
<Card className="bg-white hover:bg-gray-100">
```
### 2. 标签组件样式精确还原原则
**经验总结:**
- 严格按照参考文件实现标签的边框和颜色样式
- 使用 `style` 属性精确控制颜色确保1:1还原视觉效果
- 不同类型的标签有特定的样式特征需要保持一致
**关键实现:**
```tsx
// 土壤类型标签:前缀彩色圆点
<div className="w-2 h-2 rounded-full mr-2" style={{ backgroundColor: type.color }} />
// 种植模式标签前缀emoji + 固定绿色边框
<span className="mr-1">{mode.emoji}</span>
style={{
backgroundColor: filters.plantingModes.includes(mode.key) ? '#16a34a' : 'transparent',
borderColor: '#16a34a',
}}
// 自定义标签:纯色边框背景
style={{
backgroundColor: filters.tags.includes(tag.name) ? tag.color : 'transparent',
borderColor: tag.color,
}}
```
### 3. 最小化修改原则
**经验总结:**
- 严格遵循参考文件的功能边界,不添加多余功能
- 保持与原有系统的功能一致性
- 避免过度设计,专注核心功能实现
**实施要点:**
- 只实现参考文件中明确展示的功能
- 保持相同的用户交互流程
- 维持原有的数据结构和逻辑
### 4. 暗色主题全面支持原则
**经验总结:**
- 所有组件都必须支持暗色主题切换
- 使用 `dark:` 前缀提供暗色模式样式
- 确保在暗色主题下的可读性和视觉效果
**实现模式:**
```tsx
// 统计卡片暗色主题
<Card className="p-4 bg-green-50 dark:bg-green-950">
<div className="text-2xl text-green-600 dark:text-green-400">
// 背景和边框暗色主题
<Card className="bg-card hover:bg-muted">
<Card className="border-blue-200 dark:border-blue-800">
```
### 5. useReducer 状态管理架构原则
**经验总结:**
- 使用useReducer实现复杂状态管理避免prop drilling
- 通过dispatch实现跨组件状态同步
- 集中化状态逻辑,提高代码可维护性
**架构模式:**
```tsx
// Reducer定义
export interface LandStatisticsState {
fields: Land[];
filters: FilterCondition;
statistics: StatisticsResult | null;
chartType: 'bar' | 'pie';
}
// Action类型定义
export type LandStatisticsAction =
| { type: 'SET_FIELDS'; payload: Land[] }
| { type: 'UPDATE_FILTER'; payload: { key: keyof FilterCondition; value: any } }
| { type: 'SET_STATISTICS'; payload: StatisticsResult | null };
// 状态同步使用
const handleFilterChange = (key: keyof FilterCondition, value: any) => {
dispatch({ type: 'UPDATE_FILTER', payload: { key, value } });
};
```
### 6. 模块化组件架构原则
**经验总结:**
- 每个页面建立独立的components文件夹
- 按功能职责拆分组件,确保单一职责
- 组件间通过props和回调函数通信
**目录结构示例:**
```
src/app/(app)/land-information/archive/statistics/
├── page.tsx # 主页面
└── components/
├── landStatisticsReducer.tsx # 状态管理
├── FilterPanel.tsx # 筛选面板
├── StatisticsResults.tsx # 统计结果
└── UsageExamples.tsx # 使用示例
```
### 7. 完整依赖引用实现原则
**经验总结:**
- 仔细分析参考文件的import依赖确保完整实现
- 将所有引用的组件都实现在components目录中
- 保持与参考文件相同的组件结构和功能
**依赖检查清单:**
- UI组件Card, Button, Badge, Input, Label等
- 图标组件lucide-react图标
- 图表组件recharts相关组件
- 工具函数toast通知等
### 8. 1:1 功能还原实现原则
**经验总结:**
- 严格按照参考文件的功能逻辑实现
- 保持相同的用户交互体验
- 确保数据流和业务逻辑的一致性
**关键实现要点:**
- 筛选条件的多选逻辑
- 数据统计的计算方法
- 图表切换和显示逻辑
- 数据导出功能
## 开发工具和最佳实践
### 推荐工具链
- **状态管理**React useReducer
- **UI组件库**shadcn/ui
- **样式系统**Tailwind CSS + 语义化颜色
- **图表库**Recharts
- **图标库**Lucide React
- **通知系统**Sonner
### 代码质量保证
- TypeScript严格类型检查
- ESLint代码规范检查
- 组件props类型定义完整
- 状态管理逻辑清晰可维护
### 测试数据管理
- localStorage数据持久化
- 完整的测试数据覆盖所有业务场景
- 数据初始化和清理机制完善
通过遵循这些开发规范,我们可以确保代码的一致性、可维护性和用户体验的统一性。
---
## pathland-information/archive/statisticsname统计分析页面开发经验与问题解决
### 问题1图表横轴显示不完整
**问题描述:**
- 初始实现中,图表只显示有数据的土壤类型和种植模式
- 没有数据的项目在横轴上不显示,导致图表看起来不完整
**原始需求分析:**
- 土壤类型分布应显示所有定义的土壤类型即使数量为0
- 种植模式分布应显示所有定义的种植模式,提供完整的分类视图
**解决方案:**
- 修改数据计算逻辑,从"基于筛选结果生成数据"改为"基于所有定义的分类生成数据"
- 使用 `state.soilTypes.map()``state.plantingModes.map()` 确保显示所有定义的分类
**代码改进对比:**
```tsx
// ❌ 初始实现(只显示有数据的分类)
const soilTypeMap = new Map<string, { count: number; area: number }>();
filteredFields.forEach(f => {
const current = soilTypeMap.get(f.soilType) || { count: 0, area: 0 };
soilTypeMap.set(f.soilType, {
count: current.count + 1,
area: current.area + f.area,
});
});
const soilTypeDistribution = Array.from(soilTypeMap.entries()).map(([key, value]) => ({
name: state.soilTypes.find(s => s.key === key)?.name || key,
count: value.count,
area: value.area,
color: state.soilTypes.find(s => s.key === key)?.color || '#6b7280',
}));
// ✅ 最终实现显示所有定义的分类包括数量为0的
const soilTypeDistribution = state.soilTypes.map(soilType => {
const count = filteredFields.filter(f => f.soilType === soilType.key).length;
const area = filteredFields
.filter(f => f.soilType === soilType.key)
.reduce((sum, f) => sum + f.area, 0);
return {
name: soilType.name,
count,
area,
color: soilType.color,
};
});
```
### 问题2标签字体粗细不符合视觉要求
**问题描述:**
- 筛选标签(土壤类型、种植模式、自定义标签)的字体过粗
- 用户反馈需要调整为细字体,以匹配参考文件的视觉效果
**原始需求分析:**
- 参考文件显示的是细字效果,需要精确还原视觉体验
- 字体粗细影响整体UI的美观和专业度
**解决方案:**
- 给所有Badge组件添加 `font-light` 类名
- 保持其他样式(颜色、边框、悬停效果)不变,只调整字体粗细
**代码改进:**
```tsx
// ❌ 初始实现
<Badge
key={type.id}
variant={filters.soilTypes.includes(type.key) ? 'default' : 'outline'}
className="cursor-pointer"
style={{ backgroundColor: filters.soilTypes.includes(type.key) ? type.color : 'transparent' }}
>
{type.name}
</Badge>
// ✅ 最终实现(添加字体细体)
<Badge
key={type.id}
variant={filters.soilTypes.includes(type.key) ? 'default' : 'outline'}
className="cursor-pointer font-light"
style={{ backgroundColor: filters.soilTypes.includes(type.key) ? type.color : 'transparent' }}
>
{type.name}
</Badge>
```
### 问题3测试数据覆盖不完整影响演示效果
**问题描述:**
- localStorage中存在旧数据导致某些土壤类型和种植模式没有对应的地块数据
- 部分图表项目显示为空或缺失,影响演示效果和用户体验
**原始需求分析:**
- 所有土壤类型和种植模式都应该有对应的测试数据
- 确保图表能完整展示所有分类的统计数据即使是0也要显示
- 为用户提供完整的演示环境
**解决方案:**
- 创建完整的测试数据集覆盖所有7种土壤类型和5种种植模式
-`loadData` 函数中初始化这些测试数据,确保首次访问时有完整数据
- 通过localStorage持久化确保数据在页面刷新后仍然存在
**测试数据设计原则:**
```tsx
const testFields = [
{
id: '1',
code: 'TD001',
name: '东区沙质土试验田',
area: 85.5,
location: '东区1号地块',
soilType: 'sandy', // 沙质土
plantingMode: 'conventional', // 传统种植
tags: ['有机种植', '高产示范', '滴灌设施'],
// ...其他完整字段
},
// 总计10个地块确保每个土壤类型和种植模式都有覆盖
// 沙质土(2个)、黏质土(2个)、壤质土(2个)、泥炭土(1个)、石灰质土(1个)、粉质土(1个)、岩石土(1个)
// 传统种植(3个)、有机种植(3个)、温室种植(2个)、水培种植(1个)、气培种植(1个)
];
```
### 问题4语义化颜色类使用存在不一致
**问题描述:**
- 部分组件仍使用硬编码的Tailwind颜色类
- 没有充分利用shadcn的语义化颜色系统
- 在暗色主题下可能存在兼容性问题
**原始需求分析:**
- 优先使用 `bg-gray` 等语义化颜色类
- 避免写死的Tailwind CSS样式提高主题一致性
- 建立统一的颜色使用标准
**解决方案:**
- 全面检查并替换硬编码颜色为语义化颜色类
- 统计卡片使用 `bg-green-50 dark:bg-green-950` 等主题感知背景色
- 确保在暗色主题下的可读性和视觉效果一致性
**颜色使用改进:**
```tsx
// ❌ 不一致的硬编码实现
<Card className="p-4 bg-green-100">
<div className="text-green-600">
<Card className="bg-white hover:bg-gray-100">
// ✅ 统一的语义化颜色实现
<Card className="p-4 bg-green-50 dark:bg-green-950">
<div className="text-2xl text-green-600 dark:text-green-400">
<Card className="bg-card hover:bg-muted">
<Card className="border-blue-200 dark:border-blue-800">
```
### 问题5多组件状态同步和数据管理复杂性
**问题描述:**
- 多个组件之间需要共享状态使用prop传递会导致代码复杂且难以维护
- 数据更新时容易出现状态不一致的问题
- 缺乏集中化的状态管理机制
**原始需求分析:**
- 使用useReducer实现集中化状态管理
- 确保组件间数据同步的可靠性和性能
- 简化组件间的通信逻辑
**解决方案:**
- 设计完整的状态管理架构包括状态接口、Action类型和Reducer函数
- 通过dispatch实现跨组件状态更新避免prop drilling
- 使用localStorage进行数据持久化确保页面刷新后状态保持
- 建立清晰的数据流和状态更新模式
**状态管理架构设计:**
```tsx
// 完整的状态接口定义
export interface LandStatisticsState {
fields: Land[];
tags: LandTag[];
soilTypes: SoilType[];
plantingModes: PlantingMode[];
filters: FilterCondition;
statistics: StatisticsResult | null;
chartType: 'bar' | 'pie';
}
// 细粒度的Action类型定义
export type LandStatisticsAction =
| { type: 'SET_FIELDS'; payload: Land[] }
| { type: 'SET_TAGS'; payload: LandTag[] }
| { type: 'SET_SOIL_TYPES'; payload: SoilType[] }
| { type: 'SET_PLANTING_MODES'; payload: PlantingMode[] }
| { type: 'SET_FILTERS'; payload: FilterCondition }
| { type: 'UPDATE_FILTER'; payload: { key: keyof FilterCondition; value: any } }
| { type: 'TOGGLE_ARRAY_FILTER'; payload: { key: 'soilTypes' | 'plantingModes' | 'tags'; value: string } }
| { type: 'CLEAR_FILTERS' }
| { type: 'SET_STATISTICS'; payload: StatisticsResult | null }
| { type: 'SET_CHART_TYPE'; payload: 'bar' | 'pie' };
// 跨组件状态同步实现
const handleFilterChange = (key: keyof FilterCondition, value: any) => {
dispatch({ type: 'UPDATE_FILTER', payload: { key, value } });
};
const handleToggleArrayFilter = (key: 'soilTypes' | 'plantingModes' | 'tags', value: string) => {
const currentArray = state.filters[key];
const newArray = currentArray.includes(value)
? currentArray.filter(v => v !== value)
: [...currentArray, value];
dispatch({ type: 'TOGGLE_ARRAY_FILTER', payload: { key, value } });
};
```
## 开发经验对比总结
### 与原始要求的差异分析
| 原始要求 | 实际实现 | 差异说明 | 解决过程 |
|---------|---------|---------|---------|
| 使用shadcn语义化样式 | 完全实现 + 统一规范 | 需要建立统一的使用标准 | 全面替换硬编码颜色,建立语义化颜色使用指南 |
| 1:1还原标签样式 | 精确还原 + 字体优化 | 字体粗细需要调整以匹配视觉 | 添加font-light类名保持样式一致性 |
| 不动无关内容 | 完全遵循 | 严格保持功能边界,不添加多余功能 | 只实现参考文件中的明确功能 |
| 暗色主题支持 | 全面支持 | 需要系统化处理所有UI组件 | 使用dark:前缀系统化处理暗色主题 |
| useReducer状态管理 | 架构实现 + 最佳实践 | 需要设计状态同步机制和数据持久化 | 建立完整的状态管理架构和同步机制 |
| 模块化组件 | 完全拆分 | 需要合理的组件职责划分和通信机制 | 按功能领域拆分组件通过props和回调通信 |
| 完整依赖引用 | 1:1还原 | 需要仔细分析引用关系和依赖完整性 | 建立依赖检查清单,确保所有引用组件完整实现 |
| 1:1功能还原 | 完整实现 | 需要精确还原业务逻辑和用户体验 | 严格对照参考文件实现所有功能 |
### 关键学习点和改进
1. **数据完整性思维**:不仅要实现功能,还要考虑数据的完整性和演示效果的完整性
- 学会了从用户体验角度思考数据展示的完整性
- 理解了即使count为0也应该显示的重要性
2. **细节精确把控**:字体粗细、颜色、边框等视觉细节需要精确还原
- 培养了对UI细节的敏感度
- 掌握了通过用户反馈快速迭代优化的方法
3. **状态管理设计**useReducer不仅是技术选择更是架构设计决策
- 深入理解了状态管理的架构设计原则
- 掌握了跨组件状态同步的最佳实践
4. **渐进式优化**:在开发过程中根据反馈不断调整和改进
- 学会了灵活应对开发过程中的需求变化
- 建立了基于反馈的快速响应机制
5. **文档化习惯**:将开发过程中的经验和教训记录下来,形成知识积累
- 认识到文档化对团队协作和知识传承的重要性
- 建立了完整的开发规范文档体系