AI文献综述工具:提升学术写作效率300%的智能方案
2026/7/27 9:37:12
在快节奏的都市生活中,一盆绿植不仅是窗台的点缀,更是心灵的慰藉。然而,“忘记浇水”或“过度溺爱”常常让我们的植物伙伴悄然枯萎。
🌐 加入社区 欢迎加入开源鸿蒙跨平台开发者社区,获取最新资源与技术支持: 👉开源鸿蒙跨平台开发者社区
完整效果
该 App 围绕三个关键体验构建:
🌿技术不应冰冷,而应成为连接人与自然的桥梁。
Plant类classPlant{finalStringname;finalStringtype;// 观叶/多肉/开花finalint waterInterval;// 浇水周期(天)finalDateTimelastWatered;finalDateTimeplantedDate;finaldouble growthStage;// 0.0(幼苗)→ 1.0(成熟)boolgetneedsWater{...}// 是否需要浇水?StringgethealthStatus{...}// 健康状态描述IconDatagetplantIcon{...}// 动态图标}DateTime.now().difference(lastWatered)计算“口渴程度”;growthStage模拟真实植物生命周期。💡浇水 ≠ 机械操作:每次浇水有50%概率促进生长,模拟“精心照料带来回报”的自然法则。
AnimatedSwitcher(transitionBuilder:(child,animation)=>RotationTransition(...),child:Icon(plant.plantIcon,key:ValueKey(plant.growthStage)),)growthStage变化时,图标自动切换(🌱 → 🌿 → 🌸);local_florist(开花/多肉)、eco(观叶)。LinearProgressIndicator(value:daysSinceWater/waterInterval,color:needsWater?Colors.red:Colors.green,)
- 进度从绿渐变至红,直观展示“距离下次浇水还有多久”;
- 超过100%时保持红色,强调“急需关注”。
finalplantNames=['薄荷','绿萝','芦荟',...];finaltypes=['观叶','多肉','开花'];// 自动分配合理浇水间隔info_outline图标;| 状态 | 条件 | 用户感受 |
|---|---|---|
| 需浇水 | 超过浇水间隔 | 紧迫感,需立即行动 |
| 状态良好 | 距离下次浇水 > 50% | 安心,维持现状 |
| 茁壮成长 | 刚浇完水 | 成就感,被认可 |
🌱 文字比颜色更能传递情感——“茁壮成长”比“健康”更有生命力。
| 元素 | 设计说明 |
|---|---|
| 主色调 | Colors.green+ 深绿 AppBar (#2E7D32) —— 自然、专业 |
| 背景色 | #FCFDFC—— 接近纸张的米白,柔和不刺眼 |
| 卡片圆角 | 20—— 比常规更大,模拟“花盆”轮廓 |
| 空状态 | 绿色描边圆形 +local_florist图标,引导明确 |
| FAB 按钮 | 绿底白加号,符合 Material 规范 |
🎨 整体风格宁静、有机、无干扰,让用户专注于植物本身。
| 技术点 | 应用说明 |
|---|---|
AnimatedSwitcher+RotationTransition | 实现图标切换的流畅旋转动画 |
ValueKey(plant.growthStage) | 确保动画在growthStage变化时触发 |
min(1.0, progress) | 防止进度条溢出,保持 UI 稳定 |
DateTime.now().millisecondsSinceEpoch | 生成唯一 ID,简单可靠 |
copyWith模式 | 安全更新植物状态,避免直接修改 |
当前版本已具备完整核心体验,可进一步拓展:
hive保存植物数据,重启不丢失;flutter_local_notifications,缺水时推送;arkit_flutter_plugin)。这个植物养护 App 的真正价值,不在于它多么“智能”,而在于它唤醒了我们对生命的关注。
当你看到“小绿”的进度条变红,点击“立即浇水”,看着它图标旋转、状态变为“茁壮成长”——那一刻,你不是在操作一个 App,而是在履行一份对生命的承诺。
完整代码
import'package:flutter/material.dart';import'dart:math';voidmain(){runApp(const PlantCareApp());}class PlantCareApp extends StatelessWidget{const PlantCareApp({super.key});@override Widget build(BuildContext context){returnMaterialApp(debugShowCheckedModeBanner: false, title:'🌿 植物养护', theme: ThemeData(brightness: Brightness.light, primarySwatch: Colors.green, scaffoldBackgroundColor: const Color(0xFFFCFDFC), appBarTheme: const AppBarTheme(backgroundColor: Colors.transparent, foregroundColor: const Color(0xFF2E7D32), elevation:0,), floatingActionButtonTheme: const FloatingActionButtonThemeData(backgroundColor: Colors.green, foregroundColor: Colors.white,),), home: const PlantCareScreen(),);}}// 植物数据模型 class Plant{final Stringid;final String name;final Stringtype;// 多肉/观叶/开花 final int waterInterval;// 浇水间隔(天) final DateTime lastWatered;final DateTime plantedDate;final double growthStage;//0.0-1.0 生长阶段 Plant({required this.id, required this.name, required this.type, required this.waterInterval, required this.lastWatered, required this.plantedDate, this.growthStage=0.0,});// 计算是否需要浇水 bool get needsWater{final daysSinceWater=DateTime.now().difference(lastWatered).inDays;returndaysSinceWater>=waterInterval;}// 计算健康状态 String get healthStatus{if(needsWater)return'需浇水';final daysSinceWater=DateTime.now().difference(lastWatered).inDays;if(daysSinceWater<=waterInterval ~/2)return'茁壮成长';return'状态良好';}// 获取植物图标(根据类型和生长阶段) IconData get plantIcon{if(growthStage<0.3)returnIcons.spa;if(type=='开花')returnIcons.local_florist;if(type=='多肉')returnIcons.local_florist;returnIcons.eco;}// 创建新实例(用于状态更新) Plant copyWith({DateTime? lastWatered, double? growthStage,}){returnPlant(id: id, name: name, type: type, waterInterval: waterInterval, lastWatered: lastWatered ?? this.lastWatered, plantedDate: plantedDate, growthStage: growthStage ?? this.growthStage,);}}class PlantCareScreen extends StatefulWidget{const PlantCareScreen({super.key});@override State<PlantCareScreen>createState()=>_PlantCareScreenState();}class _PlantCareScreenState extends State<PlantCareScreen>{// 初始植物数据 List<Plant>_plants=[Plant(id:'1', name:'小绿', type:'观叶', waterInterval:3, lastWatered: DateTime.now().subtract(const Duration(days:4)), plantedDate: DateTime.now().subtract(const Duration(days:30)), growthStage:0.7,), Plant(id:'2', name:'仙人球', type:'多肉', waterInterval:14, lastWatered: DateTime.now().subtract(const Duration(days:10)), plantedDate: DateTime.now().subtract(const Duration(days:60)), growthStage:0.9,), Plant(id:'3', name:'茉莉花', type:'开花', waterInterval:2, lastWatered: DateTime.now().subtract(const Duration(days:1)), plantedDate: DateTime.now().subtract(const Duration(days:15)), growthStage:0.4,),];final Random _random=Random();// 浇水操作 void _waterPlant(String plantId){setState((){ _plants=_plants.map((plant){ if(plant.id==plantId){//更新浇水时间 final newPlant=plant.copyWith(lastWatered:DateTime.now());// 随机促进生长(50%概率)if(_random.nextDouble()>0.5&&newPlant.growthStage<1.0){final growthIncrement=0.1+ _random.nextDouble()*0.15;returnnewPlant.copyWith(growthStage: min(1.0, newPlant.growthStage + growthIncrement),);}returnnewPlant;}returnplant;}).toList();});// 显示反馈 final plant=_plants.firstWhere((p)=>p.id==plantId);ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text('${plant.name} 已浇水!${plant.growthStage>=1.0?"已成熟!":""}'),duration:const Duration(seconds:2),),);}//添加新植物 void _addNewPlant(){ final plantNames=['薄荷','绿萝','芦荟','吊兰','虎皮兰','长寿花','蟹爪兰'];final types=['观叶','多肉','开花'];final intervals=[2,3,5,7,10,14];final name=plantNames[_random.nextInt(plantNames.length)];final type=types[_random.nextInt(types.length)];final interval=intervals[_random.nextInt(intervals.length)];final newPlant=Plant(id:DateTime.now().millisecondsSinceEpoch.toString(),name:name,type:type,waterInterval:interval,lastWatered:DateTime.now(),plantedDate:DateTime.now(),);setState((){ _plants.add(newPlant);});ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text('欢迎新成员:$name')),);}// 删除植物 void _deletePlant(String plantId){final plantToDelete=_plants.firstWhere((p)=>p.id==plantId);setState((){ _plants.removeWhere((p)=>p.id==plantId);});ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text('${plantToDelete.name} 已移除'),action:SnackBarAction(label:'撤销',onPressed:(){ setState((){ _plants.insert(0,plantToDelete);});},),),);} @override Widget build(BuildContext context){ return Scaffold(appBar:AppBar(title:const Text('我的植物',style:TextStyle(fontSize:22,fontWeight:FontWeight.bold),),centerTitle:true,actions:[ IconButton(icon:const Icon(Icons.info_outline,size:24),onPressed:_showCareTips,),],),body:_plants.isEmpty?_buildEmptyState():ListView.builder(padding:const EdgeInsets.only(top:16,bottom:90),itemCount:_plants.length,itemBuilder:(context,index){ return _buildPlantCard(_plants[index]);},),floatingActionButton:FloatingActionButton(onPressed:_addNewPlant,child:const Icon(Icons.add),tooltip:'添加新植物',),);} Widget _buildEmptyState(){ return Center(child:Padding(padding:const EdgeInsets.all(32),child:Column(mainAxisAlignment:MainAxisAlignment.center,children:[ Container(padding:const EdgeInsets.all(24),decoration:BoxDecoration(color:Colors.green.withOpacity(0.1),shape:BoxShape.circle,),child:const Icon(Icons.local_florist,size:64,color:Colors.green,),),const SizedBox(height:24),const Text('还没有植物伙伴',style:TextStyle(fontSize:20,fontWeight:FontWeight.bold),),const SizedBox(height:8),const Text('点击下方按钮添加你的第一株植物',textAlign:TextAlign.center,style:TextStyle(color:Colors.grey,height:1.5),),],),),);} Widget _buildPlantCard(Plant plant){ final isNeedingWater=plant.needsWater;final healthColor=isNeedingWater?Colors.red:Colors.green;return Card(margin:const EdgeInsets.symmetric(horizontal:16,vertical:12),elevation:2,shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(20)), child: Padding(padding: const EdgeInsets.all(16), child: Row(children:[// 植物图标(带动画) Container(width:70, height:70, decoration: BoxDecoration(color: Colors.green.withOpacity(0.1), borderRadius: BorderRadius.circular(16),), child: AnimatedSwitcher(duration: const Duration(milliseconds:500), transitionBuilder:(Widget child, Animation<double>animation){returnRotationTransition(turns: Tween<double>(begin:0, end:1).animate(animation), child: child,);}, child: Icon(plant.plantIcon, key: ValueKey(plant.growthStage), size:40, color: Colors.green.shade700,),),), const SizedBox(width:16), // 植物信息 Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children:[// 名称和类型 Row(children:[Expanded(child: Text(plant.name, style: const TextStyle(fontSize:18, fontWeight: FontWeight.bold,), maxLines:1, overflow: TextOverflow.ellipsis,),), GestureDetector(onTap:()=>_deletePlant(plant.id), child: const Icon(Icons.delete_outline, size:20, color: Colors.grey,),),],), const SizedBox(height:4), Text('${plant.type} · 种植${DateTime.now().difference(plant.plantedDate).inDays}天', style: const TextStyle(color: Colors.grey, fontSize:14),), const SizedBox(height:12), // 健康状态 Row(children:[Container(width:12, height:12, decoration: BoxDecoration(color: healthColor, shape: BoxShape.circle,),), const SizedBox(width:8), Text(plant.healthStatus, style: TextStyle(color: healthColor, fontWeight: FontWeight.w600),),],), const SizedBox(height:8), // 浇水进度条 LinearProgressIndicator(value: min(1.0, DateTime.now().difference(plant.lastWatered).inDays / plant.waterInterval,), backgroundColor: Colors.grey.shade200, color: isNeedingWater ? Colors.red:Colors.green, minHeight:6, borderRadius: BorderRadius.circular(3),),],),), const SizedBox(width:16), // 浇水按钮 ElevatedButton(onPressed:()=>_waterPlant(plant.id), style: ElevatedButton.styleFrom(backgroundColor: isNeedingWater ? Colors.red:Colors.green, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), padding: const EdgeInsets.symmetric(vertical:12, horizontal:16),), child: Text(isNeedingWater ?'立即浇水':'浇水', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold),),),],),),);}void_showCareTips(){showDialog(context: context, builder:(context)=>AlertDialog(title: const Text('🌱 养护小贴士'), content: SingleChildScrollView(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: const[Text('• 观叶植物:保持土壤微湿,避免阳光直射'), SizedBox(height:8), Text('• 多肉植物:宁干勿湿,充足光照'), SizedBox(height:8), Text('• 开花植物:花期需充足水分和磷钾肥'), SizedBox(height:16), Divider(), SizedBox(height:8), Text('浇水提示:当进度条变红时,请及时浇水!', style: TextStyle(color: Colors.red),),],),), actions:[TextButton(onPressed: Navigator.of(context).pop, child: const Text('知道了'),),],),);}}