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_symbolsfind_referencestrace_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 在哪些页面被 watchread
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

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

相关推荐
潘正翔1 小时前
DeepSeek Harness从0到1部署
人工智能·开发·codex·deepseek·harness·deepseekharness·cludecode
bulingg1 小时前
bert输入长度有限,如何处理超长文本?
人工智能·深度学习·bert
神奇小汤圆1 小时前
DeepSeek Harness 这波,搞得全世界都在安装 Node.js
人工智能
nanawinona2 小时前
2026年手工思路量化后,工具重点会怎样变化
人工智能·python
武子康2 小时前
DeepSeek Harness、Codex、Claude Code、LangGraph 应该怎么选:先判断你缺的是产品、底盘还是工作流
人工智能·llm·agent
美团技术团队2 小时前
美团搜索3.0:LLM 语义表征在排序模型的探索与应用
人工智能
爱学堂IT分享2 小时前
DeepSeek+SpringAI实战AI家庭医生应用-慕课网实战课程
人工智能
科技发布2 小时前
传播易整合商圈媒体,商场停车场灯箱广告高效落地
大数据·人工智能·媒体
今天AI了吗2 小时前
从聊天到委派:AI Agent 如何推进长期任务
数据库·人工智能·python·sql·rust
IvanCodes2 小时前
RAG 实战教程(三):向量数据库检索算法,KNN、IVF、HNSW 与 Faiss 实战
人工智能·算法·agent