M2(容器+能力骨架+启动接线): CapabilityProvider/Registrar/AppModule + BridgeGameContainer 完整化 + Splash 接编排

T-M2-13 能力插件框架骨架:CapabilityProvider/CapabilityContext 接口、CapabilityRegistrar(批量注册+生命周期转发)、
        组装根 AppModule.buildCapabilities()(唯一知道全部能力处)、EchoSampleProvider 样板
T-M2-10 BridgeGameContainer 完整化:经 Registrar 注册能力(替换内联 handler)、首次进度 100% 推 appservice/setPostUrl、
        加载 params.entryUrl(回退 test_echo)、前后台 EventBus 联动、aboutToDisappear 全量清理;getContext→getHostContext 去弃用
SplashPage:进入即跑 StartupOrchestrator,完成 replace 进大厅、showmessage 阻断弹公告、进度条
内置测试大厅 rawfile/gamehall_builtin.zip(gamehall/index.html+data/test.json+version.xml,正斜杠标准 zip),
  作 M2 端到端 + V2(file:// XHR) 离线验证页;真实大厅由远程 zip 在生产下发

devecocli build 通过。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-25 18:36:59 +08:00
parent d2da223c8d
commit 2b0bd1f392
8 changed files with 254 additions and 39 deletions
+45 -12
View File
@@ -1,29 +1,62 @@
import { common } from '@kit.AbilityKit';
import { StartupOrchestrator, StartupResult, StartupStage } from 'domain_resource';
import { RouteName, BridgeGameParams } from '../routes/AppRoutes';
/**
* 启动引导页(对应 weclomeactivity1)。
* M0:仅路由壳,点击进入大厅容器。M2:接入 StartupOrchestrator配置/资源/app_data 注入)后再跳。
* 启动引导页(对应 weclomeactivity1,框架 §4/§8.1)。
* 进入即跑 StartupOrchestrator本地配置→远程配置→资源准备→app_data 注入)
* 完成后 replace 进大厅容器;被 showmessage 阻断时弹公告。
*/
@Component
export struct SplashPage {
pathStack: NavPathStack = new NavPathStack();
@State private stageText: string = '正在启动…';
@State private percent: number = 0;
@State private blocked: string = '';
private enterHall(): void {
const params: BridgeGameParams = { entryUrl: '', launchType: '0' };
this.pathStack.replacePathByName(RouteName.BRIDGE_GAME, params, false);
aboutToAppear(): void {
this.runStartup();
}
private async runStartup(): Promise<void> {
const ctx: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
const orchestrator = new StartupOrchestrator(ctx, (stage: StartupStage, percent: number) => {
this.stageText = stage;
this.percent = percent;
});
try {
const result: StartupResult = await orchestrator.run();
if (result.enter) {
const params: BridgeGameParams = { entryUrl: result.entryUrl, launchType: '0' };
this.pathStack.replacePathByName(RouteName.BRIDGE_GAME, params, false);
} else {
this.blocked = result.message;
}
} catch (e) {
const err = e as Error;
this.blocked = `启动失败:${err.message}`;
}
}
build() {
NavDestination() {
Column({ space: 16 }) {
Text('TSGame 启动引导')
.fontSize(22)
Text('TSGame')
.fontSize(28)
.fontWeight(FontWeight.Bold)
Text('M0 脚手架 · 路由壳')
.fontSize(14)
.fontColor(Color.Gray)
Button('进入大厅')
.onClick(() => this.enterHall())
if (this.blocked === '') {
Text(`${this.stageText} ${this.percent}%`)
.fontSize(14)
.fontColor(Color.Gray)
Progress({ value: this.percent, total: 100, type: ProgressType.Linear })
.width('60%')
} else {
Text(this.blocked)
.fontSize(16)
.fontColor(Color.Red)
.textAlign(TextAlign.Center)
.padding({ left: 24, right: 24 })
}
}
.width('100%')
.height('100%')