M3(T-M3-13): 分享面板对齐原工程——微信SDK + QQ/抖音系统分享

对齐 Android SharePanelHelper 流程:H5 friendsSharetypeUrlToptitleDescript →
原生弹自定义面板(微信/QQ/抖音) → 按所选平台分享。

- common ShareEvents:SHOW_PANEL + SharePanelRequest/Result;ShareProvider 经一次性
  resultEvent 与 entry 容器一对一解耦(双槽实例隔离,避免广播串扰)
- ShareProvider 重构:微信走 SDK(type2 Canvas截图→WXImageObject / 其他→WXWebpageObject;
  scene 好友/朋友圈;回传 sharesuccess);QQ/抖音走 @kit.ShareKit 系统分享(文本/图片/链接/视频,
  不集成对应 SDK、不回传);截图失败统一降级
- 截图:CapabilityContext.captureCanvas(WebSlot 用 controller.runJavaScript 取 canvas
  toDataURL,非激活/出错返回空);FileSystem.writeBytes 落盘;fileUri 给 WXImageObject/系统分享
- entry SharePanel 组件 + BridgeGameContainer 顶层叠加;重复面板/销毁均取消回投防 once 悬挂

真机验证项:微信开放平台注册后的真分享、系统分享面板拉起、canvas 截图

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
lanterngamescn
2026-06-26 08:00:03 +08:00
co-authored by Claude Opus 4.8
parent 01e4c0e99e
commit 5cbe5d4dd0
8 changed files with 478 additions and 21 deletions
@@ -6,9 +6,10 @@ import { ConfigManager, ResourceManager, AppDataInjector, AppDataValues } from '
import { KvStore, LocalUploadServer } from 'platform';
import { OutboundHandlers } from 'contracts';
import { AppEnv, EventBus, EventPayload, NavEvents, OpenGenericWebPayload, SwitchGamePayload,
BackGamePayload, Logger } from 'common';
BackGamePayload, ShareEvents, SharePanelRequest, SharePanelResult, Logger } from 'common';
import { BridgeGameParams, GenericWebParams, GenericWebResult, RouteName, AppEvents } from '../routes/AppRoutes';
import { WebSlot } from '../web/WebSlot';
import { SharePanel } from '../components/SharePanel';
/**
* 大厅/子游戏容器(对应 webviewActivity,框架 §7.1/§7.5)。**双 Web 槽模型**
@@ -34,6 +35,10 @@ export struct BridgeGameContainer {
private cancels: Array<() => void> = [];
/** 非空 → 子游戏 Web 显示(路径 A 切换)。 */
@State private subgameUrl: string = '';
/** 分享面板显隐(叠在 Stack 顶层,对齐 Android SharePanelHelper)。 */
@State private sharePanelVisible: boolean = false;
/** 当前分享面板的一次性回投事件名(用户选定平台后 emit 回 ShareProvider)。 */
private shareResultEvent: string = '';
aboutToAppear(): void {
if (AppEnv.isDebug()) {
@@ -99,6 +104,32 @@ export struct BridgeGameContainer {
this.cancels.push(EventBus.on(NavEvents.OPEN_GENERIC_WEB, (p?: EventPayload) => this.openGenericWeb(p)));
this.cancels.push(EventBus.on(NavEvents.SWITCH_GAME, (p?: EventPayload) => this.switchGame(p)));
this.cancels.push(EventBus.on(NavEvents.BACK_GAME, (p?: EventPayload) => this.backToLobby(p)));
this.cancels.push(EventBus.on(ShareEvents.SHOW_PANEL, (p?: EventPayload) => this.showSharePanel(p)));
}
/** 收到 ShareProvider 的 SHOW_PANEL:记下一次性回投事件名并弹出面板。 */
private showSharePanel(p?: EventPayload): void {
if (p === undefined) {
return;
}
// 已有面板未关闭:先按取消回投旧请求,避免上一个 once 永不触发致 ShareProvider 悬挂。
if (this.sharePanelVisible && this.shareResultEvent !== '') {
this.emitShareResult('cancel');
}
const req = p as SharePanelRequest;
this.shareResultEvent = req.resultEvent;
this.sharePanelVisible = true;
}
/** 用户选定平台/取消:回投并关闭面板。 */
private emitShareResult(platform: string): void {
const ev: string = this.shareResultEvent;
this.shareResultEvent = '';
this.sharePanelVisible = false;
if (ev !== '') {
const result: SharePanelResult = { platform };
EventBus.emit(ev, result);
}
}
/** 路径 B:打开通用网页容器;关闭回传 → 当前激活槽 callHandler('getWebdata')。 */
@@ -211,9 +242,22 @@ export struct BridgeGameContainer {
})
.onRenderExited((event: OnRenderExitedEvent) => this.slotS?.onRenderExited(event.renderExitReason))
}
// 分享面板(顶层叠加;用户选平台/取消 → 一次性回投 ShareProvider
if (this.sharePanelVisible) {
SharePanel({ onPick: (platform: string) => this.emitShareResult(platform) })
}
}
.width('100%').height('100%')
}
.hideTitleBar(true)
.onBackPressed(() => {
// 分享面板打开时,返回键关闭面板并按取消回投(对齐 Android 点空白关闭)
if (this.sharePanelVisible) {
this.emitShareResult('cancel');
return true;
}
return false;
})
}
}