AtomCode 跨端开发实战:Flutter 项目从原型到多端运行的 AI 驱动体验

文章目录

    • 每日一句正能量
    • 一、前言:跨端开发的"最后一公里"难题
    • [二、环境准备:AtomCode 与 Flutter 工具链](#二、环境准备:AtomCode 与 Flutter 工具链)
      • [2.1 安装 AtomCode](#2.1 安装 AtomCode)
      • [2.2 配置模型提供方](#2.2 配置模型提供方)
      • [2.3 确认 Flutter 环境](#2.3 确认 Flutter 环境)
    • 三、项目初始化:一句话生成跨端工程骨架
      • [3.1 创建项目目录并启动 AtomCode](#3.1 创建项目目录并启动 AtomCode)
      • [3.2 用自然语言描述需求](#3.2 用自然语言描述需求)
      • [3.3 AtomCode 的自动化执行流程](#3.3 AtomCode 的自动化执行流程)
    • [四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture](#四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture)
      • [4.1 Riverpod 3.x 代码生成版](#4.1 Riverpod 3.x 代码生成版)
      • [4.2 GoRouter 深层链接配置](#4.2 GoRouter 深层链接配置)
      • [4.3 离线优先的数据层](#4.3 离线优先的数据层)
    • 五、多端适配:一套代码,四种体验
      • [5.1 平台检测与自适应布局](#5.1 平台检测与自适应布局)
      • [5.2 桌面端多窗口支持(实验性)](#5.2 桌面端多窗口支持(实验性))
      • [5.3 Web 端优化](#5.3 Web 端优化)
    • [六、AI 驱动的 UI 开发:从描述到 Widget](#六、AI 驱动的 UI 开发:从描述到 Widget)
      • [6.1 生成任务卡片组件](#6.1 生成任务卡片组件)
      • [6.2 自动生成 Widget 测试](#6.2 自动生成 Widget 测试)
    • [七、代码图谱:理解大型 Flutter 项目的利器](#七、代码图谱:理解大型 Flutter 项目的利器)
      • [7.1 实战:安全重构 Task 模型](#7.1 实战:安全重构 Task 模型)
    • 八、项目指令文件:团队协作的规范基石
    • [九、CI/CD 与多端部署](#九、CI/CD 与多端部署)
      • [9.1 AtomGit CI 配置](#9.1 AtomGit CI 配置)
      • [9.2 本地预检脚本](#9.2 本地预检脚本)
    • [十、总结:AI 原生跨端开发的未来](#十、总结:AI 原生跨端开发的未来)

每日一句正能量

"烟火起,照人间,举杯敬此年。"

此年是旧年,也是即将成为旧年的新年。烟火一瞬,照亮人间,也照亮杯中的倒影。

一、前言:跨端开发的"最后一公里"难题

Flutter 作为 Google 开源的跨端 UI 框架,在 2026 年已经覆盖了 iOS、Android、Web、Windows、macOS、Linux 乃至嵌入式系统(如 2026 Toyota RAV4 车载系统、LG webOS 设备)。根据官方数据,Flutter 月活开发者已超过 150 万,pub.dev 生态在过去 30 天内产生了超过 13 亿次包下载。

然而,Flutter 的"一次编写,多端运行"愿景在实际落地中仍面临诸多挑战:

  • 项目结构复杂 :大型 Flutter 项目需要合理划分 lib/ 目录、管理状态层、路由层、网络层、数据层
  • 状态管理选型困难:BLoC、Riverpod、Provider、GetX 各有优劣,团队需要统一规范
  • 多端适配繁琐:移动端与桌面端的交互差异、Web 端的 SEO 和路由处理、各平台的主题适配
  • 测试覆盖不足:Widget 测试、集成测试、Golden 测试编写成本高,往往被忽略

AtomCode 的出现,为上述难题提供了系统性的解法。作为 MIT 开源的终端 AI 编码智能体,AtomCode 内置 21 个工具(含 8 个代码图谱工具),支持自主读取文件、编辑代码、运行命令、验证结果。更重要的是,AtomCode 能够调用 list_symbols、find_references、trace_callers 等代码图谱工具,真正"理解"大型 Flutter 代码库的依赖关系,而不仅仅是文本补全。

本文将以一个真实的**任务管理应用(TaskMaster)**为例,完整演示如何利用 AtomCode,从自然语言需求描述开始,生成可在 iOS、Android、Web、macOS 四端运行的 Flutter 项目。


二、环境准备:AtomCode 与 Flutter 工具链

2.1 安装 AtomCode

AtomCode 支持 macOS、Linux、Windows、HarmonyOS,包体小于 50MB,秒级启动:

bash 复制代码
# macOS / Linux 一键安装
curl -fsSL https://raw.atomgit.com/atomgit_atomcode/atomcode/raw/main/scripts/install.sh | sh

# 验证安装
atomcode --version
# 输出:atomcode v5.0.6

2.2 配置模型提供方

Flutter 开发涉及大量 UI 代码和状态管理逻辑,建议选用代码能力强的模型。本文使用 DeepSeek V3(编码能力较上一版本增强 30% 以上):

bash 复制代码
atomcode

> /provider
# 选择 DeepSeek,输入 API Key
# 模型选择 deepseek-v4-flash 或 deepseek-chat

2.3 确认 Flutter 环境

确保本地已安装 Flutter 3.47+ 和 Dart 3.12+:

bash 复制代码
flutter --version
# Flutter 3.47.0 • channel stable
# Dart 3.12.0

AtomCode 会自动检测当前目录结构,识别出这是一个 Flutter 项目环境,为后续任务规划做准备。


三、项目初始化:一句话生成跨端工程骨架

3.1 创建项目目录并启动 AtomCode

bash 复制代码
mkdir taskmaster && cd taskmaster
atomcode

3.2 用自然语言描述需求

在 AtomCode 交互界面中输入:

复制代码
帮我初始化一个 Flutter 跨端任务管理应用,要求:

1. 使用 Flutter 3.47 + Dart 3.12
2. 状态管理使用 Riverpod 3.x(代码生成版),支持自动缓存和依赖注入
3. 路由使用 GoRouter,支持深层链接和路由守卫
4. 网络层使用 Dio + Retrofit,支持请求拦截、错误处理和自动重试
5. 数据层使用 Hive 做本地缓存,支持离线优先
6. UI 使用 Material 3 设计规范,支持亮色/暗色主题切换
7. 项目结构遵循 Clean Architecture:presentation / domain / data 三层
8. 支持 iOS、Android、Web、macOS 四端运行
9. 初始化完成后运行 flutter analyze 和 flutter test,确保无错误

3.3 AtomCode 的自动化执行流程

AtomCode 收到指令后,会进入智能体循环(Smart Agent Loop),自动执行以下步骤:

规划 分析任务范围 → 拆解为 12 个子任务

读取 检测当前目录为空,确认从零开始

执行 运行 flutter create --platforms=ios,android,web,macos . 创建项目

执行 编辑 pubspec.yaml,添加 Riverpod、GoRouter、Dio、Retrofit、Hive 等依赖

执行 运行 flutter pub get 安装依赖

执行 生成 lib/ 目录下的 Clean Architecture 结构

执行 生成 Riverpod Provider 代码(含 @riverpod 注解和代码生成配置)

执行 生成 GoRouter 路由配置

执行 生成 Dio 网络层封装(含拦截器、错误处理)

执行 生成 Hive 本地存储适配器

执行 生成 Material 3 主题配置(支持亮/暗模式)

执行 生成示例页面(任务列表页、任务详情页、新增任务页)

运行 flutter pub run build_runner build 生成 Riverpod 代码

运行 flutter analyze 验证无静态错误

运行 flutter test 验证测试通过

整个过程无需人工干预,约 5-8 分钟即可完成。生成的项目结构如下:

复制代码
taskmaster/
├── .atomcode.md                    # 项目指令文件
├── pubspec.yaml
├── lib/
│   ├── main.dart
│   ├── app.dart                    # 应用入口,含 ProviderScope
│   ├── router.dart                 # GoRouter 配置
│   ├── theme.dart                  # Material 3 主题
│   ├── core/                       # 核心工具
│   │   ├── constants.dart
│   │   ├── errors/
│   │   │   └── exceptions.dart
│   │   └── utils/
│   │       └── date_formatter.dart
│   ├── presentation/               # 表现层
│   │   ├── pages/
│   │   │   ├── task_list_page.dart
│   │   │   ├── task_detail_page.dart
│   │   │   └── add_task_page.dart
│   │   ├── widgets/
│   │   │   ├── task_card.dart
│   │   │   ├── task_filter_chip.dart
│   │   │   └── empty_state.dart
│   │   └── providers/              # Riverpod Providers
│   │       ├── task_list_provider.dart
│   │       └── task_list_provider.g.dart
│   ├── domain/                     # 领域层
│   │   ├── entities/
│   │   │   └── task.dart
│   │   ├── repositories/
│   │   │   └── task_repository.dart
│   │   └── usecases/
│   │       ├── get_tasks.dart
│   │       ├── add_task.dart
│   │       └── toggle_task.dart
│   └── data/                       # 数据层
│       ├── models/
│       │   └── task_model.dart
│       ├── datasources/
│       │   ├── remote_task_datasource.dart
│       │   └── local_task_datasource.dart
│       └── repositories/
│           └── task_repository_impl.dart
├── test/
│   ├── widget/
│   │   └── task_list_page_test.dart
│   └── unit/
│       └── domain/
│           └── get_tasks_test.dart
└── macos/、ios/、android/、web/    # 平台目录

四、核心架构:Riverpod 3.x + GoRouter + Clean Architecture

4.1 Riverpod 3.x 代码生成版

Riverpod 3.x 在 2026 年已经成为 Flutter 状态管理的主流选择之一,其统一了 Ref API,支持自动重试和离线持久化。

AtomCode 生成的 Task 实体和 Provider:

dart 复制代码
// lib/domain/entities/task.dart
import 'package:freezed_annotation/freezed_annotation.dart';

part 'task.freezed.dart';
part 'task.g.dart';

@freezed
class Task with _$Task {
  const factory Task({
    required String id,
    required String title,
    String? description,
    required bool isCompleted,
    required DateTime createdAt,
    DateTime? dueDate,
    TaskPriority? priority,
  }) = _Task;

  factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
}

enum TaskPriority { low, medium, high }
dart 复制代码
// lib/presentation/providers/task_list_provider.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/domain/usecases/get_tasks.dart';

part 'task_list_provider.g.dart';

@riverpod
class TaskList extends _$TaskList {
  @override
  Future<List<Task>> build() async {
    // Riverpod 3.x 自动缓存,依赖变化时自动刷新
    final getTasks = ref.watch(getTasksProvider);
    return getTasks.call();
  }

  Future<void> addTask(String title, {String? description, DateTime? dueDate}) async {
    final addTask = ref.read(addTaskProvider);
    await addTask.call(title: title, description: description, dueDate: dueDate);
    
    // 使当前 Provider 失效,触发自动重取
    ref.invalidateSelf();
  }

  Future<void> toggleTask(String id) async {
    final toggleTask = ref.read(toggleTaskProvider);
    await toggleTask.call(id: id);
    ref.invalidateSelf();
  }
}

AtomCode 会自动配置 build_runner 并生成 .g.dart 文件,开发者无需手动处理代码生成。

4.2 GoRouter 深层链接配置

dart 复制代码
// lib/router.dart
import 'package:go_router/go_router.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'presentation/pages/task_list_page.dart';
import 'presentation/pages/task_detail_page.dart';
import 'presentation/pages/add_task_page.dart';

final routerProvider = Provider<GoRouter>((ref) {
  return GoRouter(
    initialLocation: '/',
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const TaskListPage(),
      ),
      GoRoute(
        path: '/task/:id',
        builder: (context, state) {
          final id = state.pathParameters['id']!;
          return TaskDetailPage(taskId: id);
        },
      ),
      GoRoute(
        path: '/add',
        builder: (context, state) => const AddTaskPage(),
      ),
    ],
    // 路由守卫:检查必要权限或状态
    redirect: (context, state) {
      // 可在此添加认证检查
      return null;
    },
  );
});

4.3 离线优先的数据层

AtomCode 生成的数据层实现了远程数据源 + 本地数据源 + 仓库模式:

dart 复制代码
// lib/data/repositories/task_repository_impl.dart
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/domain/repositories/task_repository.dart';
import 'package:taskmaster/data/datasources/remote_task_datasource.dart';
import 'package:taskmaster/data/datasources/local_task_datasource.dart';

class TaskRepositoryImpl implements TaskRepository {
  final RemoteTaskDataSource _remote;
  final LocalTaskDataSource _local;

  TaskRepositoryImpl(this._remote, this._local);

  @override
  Future<List<Task>> getTasks() async {
    try {
      // 优先从远程获取
      final tasks = await _remote.getTasks();
      // 缓存到本地
      await _local.cacheTasks(tasks);
      return tasks;
    } catch (e) {
      // 网络失败时回退到本地缓存
      return _local.getCachedTasks();
    }
  }

  @override
  Future<void> addTask(Task task) async {
    await _remote.addTask(task);
    await _local.cacheTask(task);
  }

  // ... 其他方法
}

五、多端适配:一套代码,四种体验

Flutter 的跨端能力不仅在于"能运行",更在于"体验原生"。AtomCode 在生成代码时会自动处理多端差异:

5.1 平台检测与自适应布局

dart 复制代码
// lib/presentation/pages/task_list_page.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class TaskListPage extends ConsumerWidget {
  const TaskListPage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final tasksAsync = ref.watch(taskListProvider);
    
    // 自适应布局:桌面端使用侧边栏,移动端使用底部导航
    final isDesktop = switch (defaultTargetPlatform) {
      TargetPlatform.macOS || TargetPlatform.windows || TargetPlatform.linux => true,
      _ => false,
    };

    return Scaffold(
      appBar: AppBar(
        title: const Text('TaskMaster'),
        centerTitle: !isDesktop,
        actions: [
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: () {
              // 切换主题
            },
          ),
        ],
      ),
      body: isDesktop
          ? _DesktopLayout(tasksAsync: tasksAsync)
          : _MobileLayout(tasksAsync: tasksAsync),
      floatingActionButton: isDesktop
          ? null  // 桌面端使用键盘快捷键或侧边栏按钮
          : FloatingActionButton(
              onPressed: () => context.push('/add'),
              child: const Icon(Icons.add),
            ),
    );
  }
}

5.2 桌面端多窗口支持(实验性)

Flutter 3.44 引入了实验性的多窗口 API,Canonical 作为桌面端的主要维护者,正在推进 Linux、Windows、macOS 的窗口管理功能。

AtomCode 可以为桌面端生成多窗口支持代码:

dart 复制代码
// 桌面端专用:弹出独立任务详情窗口
Future<void> openTaskDetailWindow(String taskId) async {
  if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) {
    // 使用 Flutter 3.44+ 的 Windowing API
    // 创建独立的子窗口显示任务详情
  } else {
    // 移动端使用路由导航
    // context.push('/task/$taskId');
  }
}

5.3 Web 端优化

对于 Web 端,AtomCode 会自动处理:

  • base-href 配置,确保部署到子路径时资源加载正确
  • prefers-reduced-motion 媒体查询,支持无障碍访问
  • 响应式布局,适配不同屏幕尺寸

六、AI 驱动的 UI 开发:从描述到 Widget

Flutter 的核心优势在于丰富的 Widget 系统。AtomCode 能够将自然语言 UI 描述转化为精确的 Widget 代码。

6.1 生成任务卡片组件

复制代码
创建一个 TaskCard 组件,要求:
1. 显示任务标题、描述(最多两行)、截止日期、优先级标签
2. 左侧有圆形复选框,点击切换完成状态
3. 优先级用颜色区分:low=绿色, medium=橙色, high=红色
4. 已完成的任务标题带删除线,整体透明度降低
5. 支持长按弹出菜单:编辑、删除
6. 使用 Material 3 的 Card 和 InkWell
7. 编写对应的 Widget 测试

AtomCode 生成的代码:

dart 复制代码
// lib/presentation/widgets/task_card.dart
import 'package:flutter/material.dart';
import 'package:taskmaster/domain/entities/task.dart';

class TaskCard extends StatelessWidget {
  final Task task;
  final ValueChanged<bool?> onToggle;
  final VoidCallback onEdit;
  final VoidCallback onDelete;

  const TaskCard({
    super.key,
    required this.task,
    required this.onToggle,
    required this.onEdit,
    required this.onDelete,
  });

  Color _getPriorityColor(TaskPriority priority) {
    return switch (priority) {
      TaskPriority.low => Colors.green,
      TaskPriority.medium => Colors.orange,
      TaskPriority.high => Colors.red,
    };
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final isCompleted = task.isCompleted;

    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
      child: InkWell(
        onLongPress: () => _showContextMenu(context),
        borderRadius: BorderRadius.circular(12),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Row(
            children: [
              Checkbox(
                value: isCompleted,
                onChanged: onToggle,
                shape: const CircleBorder(),
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      task.title,
                      style: theme.textTheme.titleMedium?.copyWith(
                        decoration: isCompleted ? TextDecoration.lineThrough : null,
                        color: isCompleted ? theme.colorScheme.onSurface.withOpacity(0.6) : null,
                      ),
                    ),
                    if (task.description != null) ...[
                      const SizedBox(height: 4),
                      Text(
                        task.description!,
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                        style: theme.textTheme.bodyMedium?.copyWith(
                          color: theme.colorScheme.onSurface.withOpacity(0.6),
                        ),
                      ),
                    ],
                    const SizedBox(height: 8),
                    Row(
                      children: [
                        if (task.priority != null)
                          Chip(
                            label: Text(
                              task.priority!.name.toUpperCase(),
                              style: const TextStyle(fontSize: 10),
                            ),
                            backgroundColor: _getPriorityColor(task.priority!).withOpacity(0.2),
                            side: BorderSide.none,
                            padding: EdgeInsets.zero,
                            labelPadding: const EdgeInsets.symmetric(horizontal: 8),
                          ),
                        const SizedBox(width: 8),
                        if (task.dueDate != null)
                          Icon(
                            Icons.calendar_today,
                            size: 14,
                            color: theme.colorScheme.onSurface.withOpacity(0.5),
                          ),
                      ],
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _showContextMenu(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) => SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(
              leading: const Icon(Icons.edit),
              title: const Text('编辑'),
              onTap: () {
                Navigator.pop(context);
                onEdit();
              },
            ),
            ListTile(
              leading: const Icon(Icons.delete, color: Colors.red),
              title: const Text('删除', style: TextStyle(color: Colors.red)),
              onTap: () {
                Navigator.pop(context);
                onDelete();
              },
            ),
          ],
        ),
      ),
    );
  }
}

6.2 自动生成 Widget 测试

dart 复制代码
// test/widget/task_card_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:taskmaster/domain/entities/task.dart';
import 'package:taskmaster/presentation/widgets/task_card.dart';

void main() {
  testWidgets('TaskCard displays task information correctly', (tester) async {
    final task = Task(
      id: '1',
      title: '完成 Flutter 文章',
      description: '撰写 AtomCode + Flutter 实战文章',
      isCompleted: false,
      createdAt: DateTime.now(),
      priority: TaskPriority.high,
    );

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: TaskCard(
            task: task,
            onToggle: (_) {},
            onEdit: () {},
            onDelete: () {},
          ),
        ),
      ),
    );

    expect(find.text('完成 Flutter 文章'), findsOneWidget);
    expect(find.text('HIGH'), findsOneWidget);
    expect(find.byType(Checkbox), findsOneWidget);
  });

  testWidgets('TaskCard shows strikethrough for completed task', (tester) async {
    final task = Task(
      id: '2',
      title: '已完成任务',
      isCompleted: true,
      createdAt: DateTime.now(),
    );

    await tester.pumpWidget(
      MaterialApp(
        home: Scaffold(
          body: TaskCard(
            task: task,
            onToggle: (_) {},
            onEdit: () {},
            onDelete: () {},
          ),
        ),
      ),
    );

    final text = tester.widget<Text>(find.text('已完成任务'));
    expect(text.style?.decoration, TextDecoration.lineThrough);
  });
}

AtomCode 生成测试后会自动运行 flutter test,确保所有用例通过。


七、代码图谱:理解大型 Flutter 项目的利器

当项目规模扩大时,理解 Widget 树、Provider 依赖图和路由结构变得困难。AtomCode 的 8 个代码图谱工具在此发挥关键作用:

工具 Flutter 项目应用场景
list_symbols 列出某文件中所有类、方法、变量,快速了解模块接口
find_references 查找某个 Provider 在哪些页面被 watch 或 read
trace_callers 追溯某个 API 调用是从哪个 UI 事件触发的
trace_callees 分析某个 UseCase 调用了哪些 Repository 方法
file_deps 分析 Dart 文件之间的 import 依赖,发现循环依赖
blast_radius 评估修改某个 Model 字段会影响多少 Widget 和测试

7.1 实战:安全重构 Task 模型

假设我们需要给 Task 实体新增 tags 字段,但不确定会影响多少地方。在 AtomCode 中输入:

复制代码
给 Task 实体新增 List<String> tags 字段,要求:
1. 使用 find_references 查找 Task 的所有引用位置
2. 使用 blast_radius 分析影响范围
3. 更新所有受影响的 Model、Provider、Widget 和测试
4. 确保 Hive 适配器同步更新
5. 运行所有测试验证

AtomCode 会自动调用代码图谱工具,按依赖顺序逐步修改:

  1. 修改 domain/entities/task.dart(Freezed 实体)
  2. 修改 data/models/task_model.dart(数据模型)
  3. 修改 data/datasources/local_task_datasource.dart(Hive 适配器)
  4. 修改 presentation/widgets/task_card.dart(UI 显示标签)
  5. 更新所有相关测试

这种影响范围分析 + 自动化重构的能力,在传统开发中需要开发者手动搜索和修改数十个文件,耗时且容易遗漏。


八、项目指令文件:团队协作的规范基石

在团队协作中,保持 Flutter 项目架构一致至关重要。AtomCode 支持通过 .atomcode.md 文件注入项目级上下文:

markdown 复制代码
# TaskMaster 项目指令

## 架构规范
- 严格遵循 Clean Architecture:Presentation → Domain → Data
- 状态管理统一使用 Riverpod 3.x,禁止混用 Provider / GetX
- 所有实体使用 Freezed + JSON Serializable,禁止手写 fromJson/toJson
- 网络请求统一封装在 data/datasources/ 中,使用 Dio 拦截器处理 Token 刷新

## UI 规范
- 所有页面使用 ConsumerWidget 或 ConsumerStatefulWidget
- 颜色不使用硬编码,必须从 Theme.of(context) 获取
- 间距使用 4 的倍数(4, 8, 12, 16, 24, 32)
- 图标使用 Material Symbols,不使用 Cupertino 图标(除平台特定场景外)

## 路由规范
- 所有路由定义在 router.dart 中,禁止在页面内直接 Navigator.push
- 深层链接路径使用小写 + 下划线,如 /task_detail/:id
- 路由守卫用于权限检查,禁止在页面内重复检查

## 测试规范
- 所有 Widget 必须编写 Widget 测试
- 所有 UseCase 必须编写单元测试
- 测试覆盖率不低于 70%
- 使用 golden_toolkit 进行 Golden 测试(关键页面)

## 多端适配规范
- 使用 defaultTargetPlatform 判断平台,禁止使用 dart:io 的 Platform.isXxx(Web 不支持)
- 桌面端布局使用 Row + Expanded,移动端使用 Column
- Web 端路由使用 --base-href 配置

## 常用命令
- 代码生成:flutter pub run build_runner build --delete-conflicting-outputs
- 运行测试:flutter test
- 静态分析:flutter analyze
- 运行 Web:flutter run -d chrome --web-port=8080
- 构建 macOS:flutter build macos

当新成员加入团队时,只需阅读 .atomcode.md 即可快速理解项目规范。而 AtomCode 在生成新代码时,会自动遵循这些规范,无需反复在 Prompt 中强调。


九、CI/CD 与多端部署

9.1 AtomGit CI 配置

Flutter 项目的 CI/CD 需要处理多平台构建。以下是在 AtomGit CI 中配置 Flutter 自动构建的示例:

yaml 复制代码
# .atomgit-ci.yml
stages:
  - analyze
  - test
  - build

variables:
  FLUTTER_VERSION: "3.47.0"

analyze:
  stage: analyze
  image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
  script:
    - flutter pub get
    - flutter pub run build_runner build --delete-conflicting-outputs
    - flutter analyze
    - flutter format --set-exit-if-changed lib/ test/

test:
  stage: test
  image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
  script:
    - flutter pub get
    - flutter test --coverage
  coverage: '/\s*(\d+\.\d+)%\s*of\s*all\s*lines/'
  artifacts:
    paths:
      - coverage/

build_web:
  stage: build
  image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
  script:
    - flutter pub get
    - flutter build web --release --base-href /taskmaster/
  artifacts:
    paths:
      - build/web/
  only:
    - main

9.2 本地预检脚本

在提交代码前,使用 AtomCode Headless 模式执行预检:

bash 复制代码
#!/bin/bash
# scripts/pre-commit.sh

echo "🚀 运行 AtomCode Flutter 预检..."

atomcode -p "检查当前 Flutter 项目的编译错误、静态分析问题,运行所有测试确保通过,然后格式化代码" --max-turns 20

if [ $? -ne 0 ]; then
  echo "❌ 预检失败,请修复问题后重新提交"
  exit 1
fi

echo "✅ 预检通过"

十、总结:AI 原生跨端开发的未来

通过本文的完整实践,我们见证了 AtomCode 如何重塑 Flutter 跨端开发的工作流:

  1. 初始化阶段:一句话生成支持 iOS、Android、Web、macOS 四端的完整项目骨架,省去数小时的配置时间
  2. 架构阶段:自动生成 Clean Architecture 分层、Riverpod 3.x 状态管理、GoRouter 路由配置
  3. 开发阶段:自然语言描述 UI 需求,AI 生成类型安全的 Widget 和测试
  4. 适配阶段:自动处理多端布局差异、主题切换、平台特定逻辑
  5. 维护阶段:代码图谱工具辅助理解大型代码库,安全重构影响范围可控
  6. 协作阶段 :.atomcode.md 项目指令文件确保团队规范一致
  7. 部署阶段:Headless 模式无缝接入 CI/CD,自动化构建多端产物

Flutter 的"一次编写,多端运行"愿景,在 AtomCode 的 AI 驱动下,真正从"能运行"进化到了"高效运行、规范运行、可持续维护"。对于跨端开发团队而言,这不仅是效率的提升,更是开发范式的转变------从"手写每一行 Dart 代码"到"描述需求、审查架构、验收多端产物"。

AtomCode 作为 MIT 开源项目,代码完全透明,社区活跃。如果你正在寻找一条高效、规范、可落地的 Flutter 跨端开发路径,不妨从 AtomCode 开始你的 AI 驱动之旅。


转载自:https://blog.csdn.net/sghtgjfhv/article/details/163862593

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
sell-cloud26 分钟前
Prompt Engineering要凉了?Fable 5.5能“猜“意图,但银行正在封杀AI Agent——企业AI的真正护城河是什么
人工智能·prompt
Navicat中国2 小时前
Navicat 18 内置 AI 助手让数据库开发从繁琐操作迈向智能协作
大数据·人工智能·数据库开发
4SAPI2 小时前
多模型请求路由怎么设计?成本、速度和能力如何平衡
人工智能·python·gateway·php
魔乐社区2 小时前
翼芯・智算测试与适配优化专区,让国产算力“选得准、跑得通、用得好“
人工智能·开源·大模型
XCDoris4 小时前
郴州logo设计机构
大数据·人工智能·python
Goboy5 小时前
一个人带三个Agent,我用全新TRAE从0到1搭了个资讯周刊站
人工智能·trae
俊哥V5 小时前
每日 AI 研究简报 · 2026-10-19
人工智能·ai
AI_AGENT_DEV_AI5 小时前
AI英语教培智能体的开发
人工智能
物联网软硬件开发-轨物科技5 小时前
【技术白皮书】光伏清检一体化机器人系统解决方案技术白皮书
大数据·运维·网络·人工智能·机器人
海宇数据5 小时前
零信任架构实战:基于海宇网上踪迹欺诈行为识别构建自动化信贷资信评估网关
运维·人工智能·架构·自动化