欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

一、项目概述

运行效果图

image-20260405115222347

image-20260405115227211

image-20260405115235467

image-20260405115240908

image-20260405115245267

image-20260405115249331

1.1 应用简介

DIY教程应用是一款专注于手工制作教学的移动应用,旨在为用户提供丰富多样的DIY教程内容,涵盖手工制作、家居装饰、美食烘焙、园艺绿植、服饰改造、电子制作等多个领域。应用以粉色为主色调,传递温暖、创意的品牌形象。

应用构建了六大核心分类体系,收录了毛线围巾编织、北欧风挂画、手工曲奇、多肉盆栽、旧衣改造、LED小夜灯等精品教程。通过清晰的步骤指导、详尽的材料清单、直观的进度追踪,帮助用户轻松掌握各种手工技能,体验动手创造的乐趣。

1.2 核心功能

功能模块 功能描述 实现方式
分类浏览 六大手工分类展示 横向滚动卡片
教程列表 全部教程展示筛选 列表+筛选
教程详情 步骤指导材料清单 滚动页面
进度追踪 学习进度实时追踪 步骤勾选
收藏管理 收藏喜欢的教程 收藏列表

1.3 教程分类

序号 分类名称 特点描述 代表教程
1 手工制作 编织刺绣折纸 毛线围巾编织
2 家居装饰 挂画摆件收纳 北欧风挂画
3 美食烘焙 曲奇蛋糕面包 手工曲奇饼干
4 园艺绿植 多肉盆栽花艺 多肉组合盆栽
5 服饰改造 旧衣改造配饰 牛仔裤改包包
6 电子制作 LED智能家居 简易LED小夜灯

1.4 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
目标平台 鸿蒙OS / Web API 21+

1.5 项目结构

lib/
└── main_diy_tutorial.dart
    ├── DIYTutorialApp          # 应用入口
    ├── Tutorial                # 教程数据模型
    ├── TutorialStep            # 步骤数据模型
    ├── DIYCategory             # 分类数据模型
    ├── MainHomePage            # 主页面(底部导航)
    ├── HomePage                # 首页
    ├── TutorialsPage           # 教程列表页面
    ├── TutorialDetailPage      # 教程详情页面
    ├── FavoritesPage           # 收藏页面
    └── ProfilePage             # 个人中心页面

二、系统架构

2.1 整体架构图

Data Layer

Presentation Layer

主页面
MainHomePage

首页

教程列表

收藏页

个人中心

分类展示

热门教程

搜索入口

筛选功能

教程列表

收藏列表

学习统计

作品管理

Tutorial
教程模型

TutorialStep
步骤模型

DIYCategory
分类模型

2.2 类图设计

manages

manages

displays

lists

shows

contains

DIYTutorialApp

+Widget build()

Tutorial

+String id

+String title

+String category

+String difficulty

+int duration

+String coverEmoji

+List<String> materials

+List<TutorialStep> steps

+String description

+int likes

+int views

+bool isFavorite

TutorialStep

+int stepNumber

+String title

+String description

+String emoji

+int duration

DIYCategory

+String name

+IconData icon

+Color color

+String emoji

MainHomePage

-int _currentIndex

-List<Widget> _pages

+Widget build()

HomePage

+Widget build()

TutorialsPage

-String selectedCategory

+Widget build()

TutorialDetailPage

+Tutorial tutorial

-int _currentStep

+Widget build()

FavoritesPage

+Widget build()

ProfilePage

+Widget build()

2.3 页面导航流程

首页

教程

收藏

我的

应用启动

主页面

底部导航

首页展示

教程列表页面

收藏页面

个人中心页面

点击教程卡片

教程详情页

筛选教程分类

点击教程列表项

查看收藏列表

步骤进度追踪

完成教程

返回上一页

2.4 数据流向图

详情页 列表 筛选器 教程列表页 用户 详情页 列表 筛选器 教程列表页 用户 进入教程列表 显示全部教程 选择分类 过滤教程 显示筛选结果 点击教程 跳转详情页 加载教程信息 展示步骤指导 完成步骤 更新进度 显示进度条

三、核心模块设计

3.1 数据模型设计

3.1.1 教程模型 (Tutorial)
class Tutorial {
  final String id;              // 唯一标识
  final String title;           // 教程标题
  final String category;        // 所属分类
  final String difficulty;      // 难度等级
  final int duration;           // 预计时长(分钟)
  final String coverEmoji;      // 封面表情
  final List<String> materials; // 材料清单
  final List<TutorialStep> steps; // 制作步骤
  final String description;     // 教程简介
  final int likes;              // 点赞数
  final int views;              // 浏览量
  bool isFavorite;              // 是否收藏
}
3.1.2 步骤模型 (TutorialStep)
class TutorialStep {
  final int stepNumber;     // 步骤序号
  final String title;       // 步骤标题
  final String description; // 步骤描述
  final String emoji;       // 步骤图标
  final int duration;       // 预计时长
}
3.1.3 分类模型 (DIYCategory)
class DIYCategory {
  final String name;      // 分类名称
  final IconData icon;    // 图标
  final Color color;      // 主题色
  final String emoji;     // 表情标识
}
3.1.4 教程分布
50% 33% 17% 教程难度分布 初级 中级 高级

3.2 页面结构设计

3.2.1 主页面布局

MainHomePage

IndexedStack

首页

教程列表

收藏页

个人中心

NavigationBar

首页 Tab

教程 Tab

收藏 Tab

我的 Tab

3.2.2 首页结构

首页

头部区域

分类展示

热门教程

渐变背景

搜索入口

横向滚动卡片

六大分类

教程卡片列表

点击跳转详情

3.2.3 教程详情页结构

详情页

头部封面

基本信息

材料清单

制作步骤

进度追踪

渐变背景

教程图标

难度等级

预计时长

步骤数量

材料标签列表

时间轴展示

步骤卡片

进度条

完成按钮

3.3 筛选功能设计

手工制作

家居装饰

美食烘焙

园艺绿植

服饰改造

电子制作

全部教程

选择分类

显示手工教程

显示装饰教程

显示烘焙教程

显示园艺教程

显示服饰教程

显示电子教程

过滤结果


四、UI设计规范

4.1 配色方案

应用采用粉色为主色调,传递温暖、创意的品牌形象:

颜色类型 色值 用途
主色 #E91E63 (Pink) 导航、强调元素
渐变起始 #E91E63 头部渐变
渐变结束 #9C27B0 头部渐变
分类手工 #E91E63 手工制作
分类家居 #9C27B0 家居装饰
分类美食 #FF5722 美食烘焙
分类园艺 #4CAF50 园艺绿植
分类服饰 #2196F3 服饰改造
分类电子 #607D8B 电子制作

4.2 字体规范

元素 字号 字重 颜色
页面标题 20px Medium #000000
教程名称 16px Bold #000000
分类名称 14px Medium 分类色
步骤标题 16px Bold #000000
步骤描述 14px Regular #757575

4.3 组件规范

4.3.1 分类卡片
┌─────────────────────┐
│                     │
│    🎨              │
│                     │
│   手工制作          │
│   编织·刺绣·折纸    │
│                     │
└─────────────────────┘
4.3.2 教程卡片
┌─────────────────────────────────────────┐
│ ┌────┐  手工编织毛线围巾            >   │
│ │ 🧣 │  [手工制作] [初级]                │
│ │    │  ⏱ 120分钟  👁 5678  ❤ 1234      │
│ └────┘                                   │
└─────────────────────────────────────────┘
4.3.3 步骤卡片
┌─────────────────────────────────────────┐
│  ① ──── 起针 ──────────────── 10分钟   │
│  │                                      │
│  │   用毛线在编织针上起40针,           │
│  │   保持松紧适度...                    │
│  │                                      │
│  ↓                                      │
│  ② ──── 编织主体 ───────────── 80分钟  │
│  │                                      │
│  │   采用平针编织法,每行正反           │
│  │   交替编织...                        │
│                                          │
└─────────────────────────────────────────┘

五、核心功能实现

5.1 分类展示实现

Widget _buildCategoryCard(DIYCategory category) {
  return Container(
    width: 100,
    margin: const EdgeInsets.only(right: 12),
    child: InkWell(
      onTap: () {},
      borderRadius: BorderRadius.circular(16),
      child: Container(
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: category.color.withValues(alpha: 0.1),
          borderRadius: BorderRadius.circular(16),
          border: Border.all(color: category.color.withValues(alpha: 0.3)),
        ),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(category.emoji, style: const TextStyle(fontSize: 28)),
            const SizedBox(height: 8),
            Text(
              category.name,
              style: TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.w500,
                color: category.color,
              ),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    ),
  );
}

5.2 筛选功能实现

Widget _buildFilterBar() {
  return Container(
    height: 50,
    padding: const EdgeInsets.symmetric(horizontal: 16),
    child: ListView(
      scrollDirection: Axis.horizontal,
      children: [
        FilterChip(
          label: const Text('全部'),
          selected: selectedCategory == null,
          onSelected: (selected) {
            setState(() {
              selectedCategory = null;
            });
          },
        ),
        const SizedBox(width: 8),
        ...categories.map((category) => Padding(
          padding: const EdgeInsets.only(right: 8),
          child: FilterChip(
            label: Text(category.name),
            selected: selectedCategory == category.name,
            onSelected: (selected) {
              setState(() {
                selectedCategory = selected ? category.name : null;
              });
            },
          ),
        )),
      ],
    ),
  );
}

5.3 教程详情页实现

Widget _buildStepItem(TutorialStep step, int index) {
  final isCompleted = index < _currentStep;
  final isCurrent = index == _currentStep;
  
  return Row(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Column(
        children: [
          GestureDetector(
            onTap: () {
              setState(() {
                if (isCurrent) {
                  _currentStep++;
                } else if (isCompleted) {
                  _currentStep = index;
                }
              });
            },
            child: Container(
              width: 40,
              height: 40,
              decoration: BoxDecoration(
                color: isCompleted
                    ? Colors.green
                    : isCurrent
                        ? category.color
                        : Colors.grey.shade300,
                shape: BoxShape.circle,
              ),
              child: Center(
                child: isCompleted
                    ? const Icon(Icons.check, color: Colors.white, size: 20)
                    : Text(
                        '${step.stepNumber}',
                        style: TextStyle(
                          color: isCurrent ? Colors.white : Colors.grey.shade600,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
              ),
            ),
          ),
          if (index < _tutorial.steps.length - 1)
            Container(
              width: 3,
              height: 80,
              color: isCompleted ? Colors.green : Colors.grey.shade300,
            ),
        ],
      ),
      const SizedBox(width: 16),
      Expanded(
        child: Container(
          margin: const EdgeInsets.only(bottom: 16),
          padding: const EdgeInsets.all(16),
          decoration: BoxDecoration(
            color: isCurrent ? category.color.withValues(alpha: 0.1) : Colors.grey.shade50,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Text(step.emoji, style: const TextStyle(fontSize: 24)),
                  const SizedBox(width: 8),
                  Expanded(
                    child: Text(
                      step.title,
                      style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16),
                    ),
                  ),
                  Text('${step.duration}分钟', style: TextStyle(fontSize: 12, color: Colors.grey.shade600)),
                ],
              ),
              const SizedBox(height: 8),
              Text(step.description, style: TextStyle(color: Colors.grey.shade700, height: 1.5)),
            ],
          ),
        ),
      ),
    ],
  );
}

5.4 进度追踪实现

Widget _buildProgressBar() {
  return Container(
    padding: const EdgeInsets.all(16),
    decoration: BoxDecoration(
      color: Colors.white,
      boxShadow: [
        BoxShadow(color: Colors.black.withValues(alpha: 0.1), blurRadius: 10),
      ],
    ),
    child: SafeArea(
      child: Row(
        children: [
          Expanded(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('进度', style: TextStyle(fontSize: 12, color: Colors.grey.shade600)),
                const SizedBox(height: 4),
                Row(
                  children: [
                    Expanded(
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(4),
                        child: LinearProgressIndicator(
                          value: _currentStep / _tutorial.steps.length,
                          backgroundColor: Colors.grey.shade200,
                          valueColor: AlwaysStoppedAnimation<Color>(category.color),
                          minHeight: 8,
                        ),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Text(
                      '$_currentStep/${_tutorial.steps.length}',
                      style: const TextStyle(fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ],
            ),
          ),
          const SizedBox(width: 16),
          if (_currentStep < _tutorial.steps.length)
            FilledButton.icon(
              onPressed: () {
                setState(() {
                  _currentStep++;
                });
              },
              icon: const Icon(Icons.check),
              label: const Text('完成此步骤'),
            )
          else
            FilledButton.icon(
              onPressed: () {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('🎉 恭喜完成教程!'), backgroundColor: Colors.green),
                );
              },
              icon: const Icon(Icons.celebration),
              label: const Text('完成教程'),
            ),
        ],
      ),
    ),
  );
}

5.5 收藏功能实现

IconButton(
  icon: Icon(_tutorial.isFavorite ? Icons.favorite : Icons.favorite_border),
  onPressed: () {
    setState(() {
      _tutorial.isFavorite = !_tutorial.isFavorite;
    });
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(_tutorial.isFavorite ? '已添加到收藏' : '已取消收藏'),
        duration: const Duration(seconds: 1),
      ),
    );
  },
)

六、交互设计

6.1 筛选交互流程

列表 状态 筛选栏 用户 列表 状态 筛选栏 用户 点击分类标签 更新selectedCategory 过滤教程数据 显示筛选结果

6.2 详情页导航

点击教程

跳转详情页

加载教程信息

显示封面区域

显示材料清单

显示步骤列表

用户学习

完成步骤?

更新进度

最后一步?

完成教程

返回上一页

6.3 步骤进度状态

点击开始

完成步骤

完成最后一步

进度 0%

进度 1%~99%

进度 100%


七、扩展功能规划

7.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 分类展示 教程列表 详情页面 进度追踪 收藏功能 搜索功能 用户系统 视频教程 社区分享 AI推荐 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 DIY教程应用开发计划

7.2 功能扩展建议

7.2.1 视频教程支持

增强教学体验:

  • 集成视频播放器
  • 支持倍速播放
  • 添加字幕说明
7.2.2 社区互动功能

用户交流平台:

  • 作品分享展示
  • 评论点赞互动
  • 关注好友动态
7.2.3 材料购买功能

电商整合:

  • 一键购买材料包
  • 材料价格对比
  • 优惠券领取

八、注意事项

8.1 开发注意事项

  1. 数据模型:Tutorial模型包含完整教程信息和步骤列表

  2. 筛选逻辑:使用where方法过滤教程列表

  3. 导航传参:详情页通过构造函数接收Tutorial对象

  4. 进度管理:使用_currentStep变量追踪当前步骤

8.2 常见问题

问题 原因 解决方案
筛选不生效 状态未更新 调用setState刷新
详情页空白 数据未传递 检查构造函数参数
进度不更新 变量未修改 检查_currentStep赋值
颜色显示异常 Color类型错误 使用withValues方法

8.3 使用提示

🛠️ DIY教程使用小贴士 🛠️

准备材料:开始前确保所有材料准备齐全。
阅读步骤:先通读所有步骤再开始操作。
注意安全:使用工具时注意安全防护。
享受过程:慢慢来,享受动手的乐趣。


九、运行说明

9.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

9.2 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_diy_tutorial.dart --web-port 8097

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_diy_tutorial.dart

# 运行到Windows
flutter run -d windows -t lib/main_diy_tutorial.dart

# 代码分析
flutter analyze lib/main_diy_tutorial.dart

十、总结

DIY教程应用通过系统化的手工教程展示,为手工爱好者提供了一个便捷的学习平台。应用构建了六大核心分类体系,收录了毛线围巾编织、北欧风挂画、手工曲奇、多肉盆栽、旧衣改造、LED小夜灯等精品教程,帮助用户全面掌握手工技能。

核心功能涵盖分类展示、教程列表、教程详情、进度追踪、收藏管理五大模块。分类展示以横向滚动卡片形式呈现六大手工领域;教程列表支持按分类筛选,列表展示教程基本信息;教程详情页完整呈现材料清单和步骤指导,支持实时进度追踪;收藏管理帮助用户快速访问喜欢的教程。

应用采用Material Design 3设计规范,以粉色为主色调,界面温暖亲切。通过本应用,希望能够帮助用户体验动手创造的乐趣,感受工匠精神的魅力。

动手创造美好生活


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐