Files
oneapp_docs/app_car/app_avatar.md
2025-09-24 14:08:54 +08:00

15 KiB
Raw Permalink Blame History

App Avatar - 虚拟形象模块文档

模块概述

app_avatar 是 OneApp 的虚拟形象管理模块为用户提供个性化的虚拟车载助手服务。该模块集成了语音克隆技术、3D 虚拟形象渲染、支付服务等功能,让用户可以创建和定制自己的专属虚拟助手。

基本信息

目录结构

app_avatar/
├── lib/
│   ├── app_avatar.dart           # 主导出文件
│   └── src/                      # 源代码目录
│       ├── avatar/               # 虚拟形象核心功能
│       │   ├── pages/           # 页面组件
│       │   │   ├── avatar_building/    # 形象生成页面
│       │   │   ├── avatar_copy/        # 形象复制页面
│       │   │   ├── avatar_display/     # 形象展示页面
│       │   │   ├── no_avatar/          # 未生成形象页面
│       │   │   ├── prepare_resource_page/ # 资源准备页面
│       │   │   ├── pta_camera/         # 拍照相机页面
│       │   │   ├── pta_sex_check/      # 性别确认页面
│       │   │   ├── rename/             # 重命名页面
│       │   │   └── server_data_dress_up/ # 捏脸界面
│       │   ├── provide_external/       # 对外提供组件
│       │   └── util/                   # 工具类
│       ├── common_import.dart          # 通用导入
│       └── route_export.dart           # 路由导出
├── assets/                             # 静态资源
├── pubspec.yaml                        # 依赖配置
└── README.md                           # 项目说明

核心功能模块

1. 主导出模块

文件: lib/app_avatar.dart

library app_avatar;
import 'package:basic_modular/modular.dart';
import 'package:basic_modular_route/basic_modular_route.dart';
import 'src/route_export.dart';

// 导出路由和对外组件
export 'src/route_export.dart';
export 'src/avatar/provide_external/in_use_avatar_icon.dart';
export 'src/avatar/provide_external/avatar_header.dart';
export 'src/avatar/util/config.dart';
export 'src/avatar/util/avatar_engine_manage.dart';

/// App Avatar 模块定义
class AppAvatarModule extends Module with RouteObjProvider {
  @override
  List<Module> get imports => [];

  @override
  List<Bind> get binds => [];

  @override
  List<ModularRoute> get routes {
    // 获取路由元数据
    final r1 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyHome);
    final r4 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiAvatarDisplayPage);
    final r7 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiPtaAvatarCamera);
    final r8 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiBuilding);
    final r10 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiDressUpServerDataPage);
    final r11 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiNonAvatar);
    final r12 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiRename);
    final r13 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiStep2GenderCheck);
    final r14 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiAvatarCopy);
    final r15 = RouteCenterAPI.routeMetaBy(AvatarRouteExport.keyAvatarUiPrepareResourcePage);
    
    // 返回子路由列表
    return [
      ChildRoute(r1.path, child: (_, args) => r1.provider(args).as()),
      ChildRoute(r4.path, child: (_, args) => r4.provider(args).as()),
      ChildRoute(r7.path, child: (_, args) => r7.provider(args).as()),
      ChildRoute(r8.path, child: (_, args) => r8.provider(args).as()),
      ChildRoute(r10.path, child: (_, args) => r10.provider(args).as()),
      ChildRoute(r11.path, child: (_, args) => r11.provider(args).as()),
      ChildRoute(r12.path, child: (_, args) => r12.provider(args).as()),
      ChildRoute(r13.path, child: (_, args) => r13.provider(args).as()),
      ChildRoute(r14.path, child: (_, args) => r14.provider(args).as()),
      ChildRoute(r15.path, child: (_, args) => r15.provider(args).as()),
    ];
  }
}

2. 路由导出管理

核心功能与实现

1. 页面路由系统

app_avatar 模块基于真实的路由系统实现,主要包含以下功能页面:

核心页面组件

  • AvatarReplaceChild: 虚拟形象展示页面
  • PtaAvatarCamera: 拍照相机页面
  • AvatarBuildingPage: 形象生成页面
  • DressUpServerDataPage: 捏脸编辑页面
  • AvatarCopy: 形象复制页面
  • NonAvatar: 非形象页面

页面导航实现

// 页面跳转示例
class AvatarNavigationHelper {
  // 跳转到虚拟形象展示页面
  static void gotoAvatarDisplay() {
    Modular.to.pushNamed('/avatar/avatarDisplayPage');
  }
  
  // 跳转到拍照创建页面
  static void gotoPtaCamera() {
    Modular.to.pushNamed('/avatar/PtaAvatarCamera');
  }
  
  // 跳转到捏脸编辑页面
  static void gotoDressUp() {
    Modular.to.pushNamed('/avatar/DressUpServerDataPage');
  }
  
  // 跳转到形象生成页面
  static void gotoAvatarBuilding({
    required String sex,
    required String name,
    required String photoPath,
  }) {
    Modular.to.pushNamed('/avatar/AvatarBuildingPage', arguments: {
      'sex': sex,
      'name': name,
      'photoPath': photoPath,
    });
  }
}

2. 模块架构设计

基本模块结构

// 模块入口点
class AppAvatarModule extends Module implements RouteObjProvider {
  @override
  List<Bind> get binds => [
    // 依赖注入配置将在这里定义
  ];
  
  @override
  List<ModularRoute> get routes => [
    // 路由配置通过 AvatarRouteExport 管理
  ];
  
  @override
  RouteCenterAPI? get routeObj => RouteCenterAPI(
    routeExporter: AvatarRouteExport(),
  );
}

页面状态管理

// 简化的页面状态管理
class AvatarPageState {
  final bool isLoading;
  final String? errorMessage;
  final Map<String, dynamic> data;
  
  const AvatarPageState({
    this.isLoading = false,
    this.errorMessage,
    this.data = const {},
  });
  
  AvatarPageState copyWith({
    bool? isLoading,
    String? errorMessage,
    Map<String, dynamic>? data,
  }) {
    return AvatarPageState(
      isLoading: isLoading ?? this.isLoading,
      errorMessage: errorMessage ?? this.errorMessage,
      data: data ?? this.data,
    );
  }
}

3. 核心功能实现

虚拟形象创建流程

虚拟形象创建遵循以下步骤:

  1. 用户拍照: 通过 PtaAvatarCamera 页面获取用户照片
  2. 信息确认: 收集用户基本信息(姓名、性别等)
  3. 形象生成: AvatarBuildingPage 显示生成进度
  4. 结果展示: AvatarReplaceChild 展示最终形象

形象管理功能

  • 形象展示: 3D/2D 虚拟形象渲染展示
  • 形象编辑: 通过捏脸系统进行外观定制
  • 形象切换: 支持多个虚拟形象间的切换
  • 形象分享: 虚拟形象内容的分享功能

4. 数据模型定义

基础数据结构

// 虚拟形象基本信息
class AvatarInfo {
  final String id;
  final String name;
  final String sex;
  final String photoPath;
  final DateTime createdAt;
  final Map<String, dynamic> customData;
  
  const AvatarInfo({
    required this.id,
    required this.name,
    required this.sex,
    required this.photoPath,
    required this.createdAt,
    this.customData = const {},
  });
  
  Map<String, dynamic> toMap() {
    return {
      'id': id,
      'name': name,
      'sex': sex,
      'photoPath': photoPath,
      'createdAt': createdAt.toIso8601String(),
      'customData': customData,
    };
  }
  
  factory AvatarInfo.fromMap(Map<String, dynamic> map) {
    return AvatarInfo(
      id: map['id'] ?? '',
      name: map['name'] ?? '',
      sex: map['sex'] ?? '',
      photoPath: map['photoPath'] ?? '',
      createdAt: DateTime.parse(map['createdAt'] ?? DateTime.now().toIso8601String()),
      customData: map['customData'] ?? const {},
    );
  }
}

// 形象配置信息
class AvatarConfiguration {
  final String avatarId;
  final Map<String, dynamic> appearanceConfig;
  final Map<String, dynamic> behaviorConfig;
  final DateTime updatedAt;
  
  const AvatarConfiguration({
    required this.avatarId,
    required this.appearanceConfig,
    required this.behaviorConfig,
    required this.updatedAt,
  });
}

5. UI 组件实现

通用 UI 组件

// 形象展示组件
class AvatarDisplayWidget extends StatelessWidget {
  final AvatarInfo avatarInfo;
  final VoidCallback? onTap;
  
  const AvatarDisplayWidget({
    Key? key,
    required this.avatarInfo,
    this.onTap,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        width: 200,
        height: 300,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(10),
          border: Border.all(color: Colors.grey.shade300),
        ),
        child: Column(
          children: [
            Expanded(
              child: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.vertical(top: Radius.circular(10)),
                  image: avatarInfo.photoPath.isNotEmpty
                    ? DecorationImage(
                        image: FileImage(File(avatarInfo.photoPath)),
                        fit: BoxFit.cover,
                      )
                    : null,
                ),
                child: avatarInfo.photoPath.isEmpty
                  ? Center(child: Icon(Icons.person, size: 50, color: Colors.grey))
                  : null,
              ),
            ),
            Container(
              padding: EdgeInsets.all(8),
              child: Text(
                avatarInfo.name,
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// 操作按钮组件
class AvatarActionButton extends StatelessWidget {
  final String label;
  final IconData icon;
  final VoidCallback onPressed;
  final bool isLoading;
  
  const AvatarActionButton({
    Key? key,
    required this.label,
    required this.icon,
    required this.onPressed,
    this.isLoading = false,
  }) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: isLoading ? null : onPressed,
      icon: isLoading 
        ? SizedBox(
            width: 16, 
            height: 16, 
            child: CircularProgressIndicator(strokeWidth: 2)
          )
        : Icon(icon),
      label: Text(label),
      style: ElevatedButton.styleFrom(
        padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    );
  }
}

6. 错误处理与异常管理

异常定义

// 虚拟形象相关异常
abstract class AvatarException implements Exception {
  final String message;
  const AvatarException(this.message);
  
  @override
  String toString() => 'AvatarException: $message';
}

class AvatarCreationException extends AvatarException {
  const AvatarCreationException(String message) : super(message);
}

class AvatarLoadException extends AvatarException {
  const AvatarLoadException(String message) : super(message);
}

class AvatarSaveException extends AvatarException {
  const AvatarSaveException(String message) : super(message);
}

错误处理机制

// 错误处理工具类
class AvatarErrorHandler {
  static void handleError(
    BuildContext context,
    Exception error, {
    VoidCallback? onRetry,
  }) {
    String message = '发生未知错误';
    
    if (error is AvatarException) {
      message = error.message;
    }
    
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('错误'),
        content: Text(message),
        actions: [
          if (onRetry != null)
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
                onRetry();
              },
              child: Text('重试'),
            ),
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('确定'),
          ),
        ],
      ),
    );
  }
}

技术架构与设计模式

1. 模块化架构

app_avatar 模块采用标准的 OneApp 模块化架构:

  • 模块定义: AppAvatarModule 继承自 Module 并实现 RouteObjProvider
  • 路由管理: 通过 AvatarRouteExport 统一管理所有路由
  • 依赖注入: 使用 basic_modular 的依赖注入机制
  • 页面组织: 按功能分组的页面结构

2. 核心功能实现

虚拟形象创建流程

  1. 拍照页面: 用户使用相机拍摄照片
  2. 信息填写: 确认性别和姓名信息
  3. 形象生成: 后台处理生成虚拟形象
  4. 形象展示: 展示生成结果

形象管理功能

  • 形象展示: 3D/2D 虚拟形象渲染
  • 形象编辑: 捏脸和装扮功能
  • 形象复制: 形象模板复制功能
  • 重命名: 形象名称管理

3. 与其他模块集成

// 集成示例 - 从其他模块跳转到虚拟形象相关页面
class AvatarNavigationHelper {
  // 跳转到虚拟形象展示页面
  static void gotoAvatarDisplay() {
    Modular.to.pushNamed('/avatar/avatarDisplayPage');
  }
  
  // 跳转到拍照创建页面
  static void gotoPtaCamera() {
    Modular.to.pushNamed('/avatar/PtaAvatarCamera');
  }
  
  // 跳转到捏脸编辑页面
  static void gotoDressUp() {
    Modular.to.pushNamed('/avatar/DressUpServerDataPage');
  }
}

依赖管理与技术栈

核心依赖

  • basic_modular: 模块化框架
  • basic_modular_route: 路由管理
  • flutter: Flutter 框架

UI 组件

  • Material Design: 基础 UI 组件
  • Custom Widgets: 虚拟形象专用组件

数据存储

  • SharedPreferences: 配置信息本地存储
  • 文件系统: 图片和资源文件存储

最佳实践与规范

1. 代码组织

  • 页面文件统一放在 src/avatar/pages/ 目录
  • 按功能模块分别组织(拍照、生成、编辑、展示)
  • 对外组件放在 provide_external 目录

2. 路由管理

  • 采用 RouteExporter 接口统一路由导出
  • 使用 RouteMeta 配置路由元数据
  • 支持路由参数传递和嵌套路由

3. 用户体验优化

  • 流畅的页面转场动画
  • 友好的加载进度提示
  • 响应式布局适配不同屏幕

4. 性能优化

  • 合理的资源加载和释放
  • 动画性能优化
  • 内存使用管理