鸿蒙应用开发- Pocket Tool:分支管理与协作体验升级【跨平台技术在开源鸿蒙中的使用】

一、阶段目标与实现总结

1.1 项目迭代背景

此前已完成仓库详情查看、基础搜索及个人仓库列表等核心功能,实现了数据的流畅加载与展示。随着用户使用场景的深入,单一的仓库浏览已无法满足协作开发需求,本次迭代重点实现分支管理核心功能,支撑多人协作场景。

最终实现:

"仓库详情"页面:新增分支列表入口及管理面板
"协作中心"页面:新增分支创建、切换、删除及合并请求发起功能

二、核心实现详解

2.1 Branch模型的状态与关联处理

位置: lib/models/branch.dart

factory Branch.fromJson(Map<String, dynamic> json, String repoFullName) {
  // 解析分支基础信息
  final name = json['name']?.toString() ?? '';
  final commit = json['commit'] as Map<String, dynamic>;
  final commitSha = commit['sha']?.toString() ?? '';
  final commitMessage = commit['commit']['message']?.toString() ?? '无提交信息';

  // 处理分支保护状态(核心协作属性)
  bool isProtected = false;
  if (json.containsKey('protection')) {
    isProtected = json['protection']['enabled'] as bool? ?? false;
  }

  // 关联仓库信息(用于后续API请求)
  final List<String> repoParts = repoFullName.split('/');
  String owner = '';
  String repoName = '';
  if (repoParts.length >= 2) {
    owner = repoParts.sublist(0, repoParts.length - 1).join('/');
    repoName = repoParts.last;
  }

  // 解析提交时间
  final updatedAt = _parseDateTime(commit['commit']['committer']['date']);

  return Branch(
    name: name,
    repoOwner: owner,
    repoName: repoName,
    commitSha: commitSha,
    commitMessage: commitMessage,
    isProtected: isProtected,
    updatedAt: updatedAt,
    isDefault: json['default'] as bool? ?? false
  );
}

// 辅助解析方法
static DateTime? _parseDateTime(String? dateStr) {
  if (dateStr == null) return null;
  try {
    return DateTime.parse(dateStr);
  } catch (_) {
    return null;
  }
}

代码说明:

关联关系设计:

通过仓库全名拆分获取所有者和仓库名,建立分支与仓库的强关联,为后续分支操作API提供必要参数。支持嵌套命名空间场景(如gh_mirrors/op/OpenManus)的拆分处理。

协作属性强化:

重点解析分支保护状态(isProtected),为后续删除/合并操作提供权限判断依据;默认分支标识(isDefault)用于界面突出显示,提升用户识别效率。

2.2 分支列表与操作面板实现

位置: lib/pages/repository_detail_page.dart - _BranchListState

// 分支列表构建(支持下拉刷新)
Widget _buildBranchList() {
  return RefreshIndicator(
    onRefresh: _fetchBranches,
    child: ListView.separated(
      padding: const EdgeInsets.all(16),
      itemCount: _branches.length,
      separatorBuilder: (context, index) => const Divider(height: 8),
      itemBuilder: (context, index) {
        final branch = _branches[index];
        return ListTile(
          leading: branch.isDefault 
              ? const Icon(Icons.star, color: Colors.amber)
              : const Icon(Icons.code_branch),
          title: Text(branch.name),
          subtitle: Text(
            '${branch.commitSha.substring(0, 7)} · ${branch.commitMessage}',
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
          trailing: _buildBranchActionButtons(branch),
          onTap: () => _switchBranch(branch),
        );
      },
    ),
  );
}

// 分支操作按钮(根据保护状态动态显示)
Widget _buildBranchActionButtons(Branch branch) {
  return Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      IconButton(
        icon: const Icon(Icons.merge),
        onPressed: () => _showMergeRequestDialog(branch),
        tooltip: '发起合并请求',
      ),
      IconButton(
        icon: const Icon(Icons.delete),
        onPressed: branch.isProtected || branch.isDefault
            ? null // 保护分支/默认分支禁用删除
            : () => _confirmDeleteBranch(branch),
        tooltip: branch.isProtected ? '分支已保护' : '删除分支',
        disabledColor: Colors.grey[300],
      ),
    ],
  );
}

2.3 分支管理API服务层

位置: lib/services/api_service.dart

/// 获取仓库分支列表
static Future<List<Map<String, dynamic>>> getRepoBranches(String owner, String repo) async {
  final url = Uri.parse('$baseUrl/repos/$owner/$repo/branches');
  final response = await _get(url);
  if (response.statusCode == 200) {
    final dynamic data = json.decode(response.body);
    if (data is List) {
      return data.cast<Map<String, dynamic>>();
    }
    throw Exception('Unexpected branches list format.');
  }
  throw Exception('Failed to get branches: ${response.statusCode} - ${response.body}');
}

/// 创建新分支
static Future<Map<String, dynamic>> createBranch(String owner, String repo, String branchName, String baseSha) async {
  final url = Uri.parse('$baseUrl/repos/$owner/$repo/branches');
  final body = json.encode({
    'branch': branchName,
    'ref': baseSha // 基于指定提交创建分支
  });
  final response = await _post(url, body: body);
  if (response.statusCode == 201) {
    return json.decode(response.body) as Map<String, dynamic>;
  }
  throw Exception('Failed to create branch: ${response.statusCode} - ${response.body}');
}

/// 删除分支
static Future<void> deleteBranch(String owner, String repo, String branchName) async {
  final url = Uri.parse('$baseUrl/repos/$owner/$repo/branches/$branchName');
  final response = await _delete(url);
  if (response.statusCode != 204) {
    throw Exception('Failed to delete branch: ${response.statusCode} - ${response.body}');
  }
}

代码说明:

完整生命周期覆盖:

提供分支查询、创建、删除全流程API封装,支持基于指定提交SHA创建分支,满足精准分支管理需求。

权限兼容处理:

通过HTTP状态码精准判断操作结果,针对保护分支删除等非法操作返回明确错误信息,便于前端提示。

2.4 合并请求核心功能

位置: lib/pages/merge_request_page.dart

合并请求作为分支协作的核心环节,实现以下关键功能:

  1. 分支选择器: 支持源分支与目标分支的联动选择,默认选中当前分支作为源分支,主分支作为目标分支

  2. 冲突检测: 提交前调用API预检测分支冲突,冲突时显示冲突文件列表及解决方案提示

  3. 请求详情: 支持填写合并标题、描述、指定审核人,关联相关Issue

  4. 状态跟踪: 实时展示合并请求状态(待审核、已通过、已拒绝、合并中、已合并)

三、体验优化

  1. **操作反馈强化:**分支创建/删除成功后显示顶部Toast提示,3秒后自动消失

  2. 冲突检测结果以高亮卡片展示,提供"查看冲突文件"快捷入口

  3. 长时间操作(如分支创建)显示加载对话框,防止重复提交

  4. **列表优化:**默认分支添加星标标识,保护分支添加盾牌图标,提升视觉识别效率

  5. 分支列表按更新时间倒序排列,最新操作的分支优先展示

  6. 支持分支搜索过滤,输入关键词实时匹配分支名称

  7. **异常处理:**网络错误时显示重试按钮,点击可重新执行操作

  8. 权限不足操作时显示明确提示,并提供"申请权限"跳转入口

  9. 删除分支时增加二次确认对话框,防止误操作

在这里插入图片描述

四、后续优化方向

  1. **分支可视化:**添加分支历史时间线,直观展示分支创建、合并、删除记录

  2. 实现分支网络拓扑图,展示多分支间的关联关系

  3. **协作效率提升:**支持分支权限精细化管理(如指定人员可合并到主分支)

  4. 添加合并请求模板,规范提交内容

  5. 实现合并请求审核通知(站内信+推送)

  6. **离线能力增强:**支持分支列表离线缓存,无网络时可查看历史分支信息

  7. 离线操作记录本地存储,网络恢复后自动同步

五、测试结果

测试场景 测试用例 测试结果
分支管理 创建/删除普通分支、默认分支、保护分支 通过(保护分支/默认分支删除已禁用)
合并请求 无冲突合并、有冲突检测、指定审核人 通过(冲突检测准确,状态跟踪正常)
异常场景 网络中断、权限不足、重复创建同名分支 通过(错误提示清晰,支持重试)
性能测试 100+分支列表加载、批量删除分支 通过(加载耗时<1s,无卡顿)

在这里插入图片描述
在这里插入图片描述

六、总结

本次迭代完成了分支管理全流程功能开发,核心实现了分支的创建、查询、删除及合并请求发起与跟踪,通过精细化的权限控制和直观的操作反馈,显著提升了协作开发体验。从单一的仓库浏览工具,向轻量级协作平台迈出了关键一步。

后续将重点优化分支可视化和审核流程自动化,进一步提升团队协作效率。深夜的代码终于有了成果,期待明天用户的反馈!
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐