You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

75 lines
2.7 KiB

import 'package:device_plugin_interface/device_plugin_interface.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../data/models/agent_module.dart';
export '../data/models/assistant_directive.dart' show DirectiveHandler;
import '../data/models/assistant_directive.dart';
/// Agent 能力模块的描述符——**模块自带行为**,不再靠中心 switch。
///
/// 一个模块 = `lib/modules/<name>/module.dart` 里导出的一个描述符,
/// 在 [ModuleRegistry] 里登记一行即可:
/// - 卡片元数据(沿用 [AgentModule]:标题/副标题/图标/渐变)
/// - [pages]:模块自带的路由,`AppPages` 会把它们拼进总表
/// - [entryRoute] / [onLaunch]:卡片点击去哪(二选一,优先 onLaunch)
/// - [requiredCapabilities]:需要在线设备具备的能力,空 = 不依赖设备
/// - [directives]:本模块能落地的端侧指令
/// - [translations]:模块自带的文案(按 locale,如 `zh_CN` / `en_US`),
/// 与全局语言文件合并;新模块不必再去改 41 个语言文件
/// - [registerServices]:需要常驻服务时在这里 `Get.put`
///
/// `test/module_registry_test.dart` 守着:id 唯一、entryRoute 已注册、
/// 标题文案有落点。
class AgentModuleDescriptor extends AgentModule {
AgentModuleDescriptor({
required super.id,
required super.title,
super.subtitle,
required super.icon,
required super.gradient,
this.requiredCapabilities = const {},
super.comingSoon = false,
this.pages = const [],
this.entryRoute,
this.onLaunch,
this.directives = const {},
this.translations = const {},
this.registerServices,
super.bailianAppId,
}) : super(requiresDevice: requiredCapabilities.isNotEmpty);
/// 需要在线设备具备的能力;空集合 = 手机自己就能用
final Set<DeviceCapability> requiredCapabilities;
/// 模块自带的页面
final List<GetPage> pages;
/// 卡片点击跳转的路由(无 [onLaunch] 时用)
final String? entryRoute;
/// 卡片点击的自定义动作(带闸门/提示逻辑的模块用它)
final VoidCallback? onLaunch;
/// 端侧指令 → 处理器
final Map<String, DirectiveHandler> directives;
/// 模块自带文案:`{'zh_CN': {...}, 'en_US': {...}}`
final Map<String, Map<String, String>> translations;
/// 常驻服务注册钩子(InitialBinding 之后调用一次)
final void Function()? registerServices;
/// 卡片点击:优先 [onLaunch],其次 [entryRoute];都没有返回 false 让调用方兜底
bool launch() {
if (onLaunch != null) {
onLaunch!();
return true;
}
if (entryRoute != null) {
Get.toNamed(entryRoute!);
return true;
}
return false;
}
}