Files
youle_app_ohos/docs/superpowers/specs/2026-06-27-分享重构-design.md
T
lanterngamescnandClaude Opus 4.8 669d34918d docs: 分享 spec 修正——三端文本一律不含 url,systemLink 退役
微信/抖音 第二三层均不带 webpageUrl;webpageUrl 仅作 type4 本地视频路径;
系统分享统一 PLAIN_TEXT(title+description)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 12:36:53 +08:00

145 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 分享重构设计(微信/QQ/抖音去 SDK 化 + 剪贴板指引 + 内容对齐原工程)
- 日期:2026-06-27
- 范围:`ShareProvider` 分享链路重构;支付桩边界确认;**契约(handler/DTO)零改动**
- 关联:契约 §8.1 / §10.1 / §12`friendsSharetypeUrlToptitleDescript``sharesuccess``SharetypeBean`);框架 §6.3 / §6.5
## 1. 背景与动机
当前鸿蒙分享与原 Android 工程**没有对齐**
- 微信走 `@tencent/wechat_open_sdk`(网页/图片分享,缺缩略图)。
- QQ/抖音退化为纯 `systemShare` 系统面板,文本用统一 `joinText`(双换行、不含 url),与原工程逐渠道格式不符。
- 缺少原工程「复制内容到剪贴板 + 指引用户去对应 App 粘贴」的链路。
需求变更:三端统一改为「**优先拉起 App 分享界面 → 复制+指引 → 系统分享兜底**」,且微信不依赖 SDK。
## 2. 关键验证结论(决定方案)
经鸿蒙文档 + 各开放平台资料核实:
- 鸿蒙 NEXT **没有** Android `ACTION_SEND + setPackage` 那种「系统级带内容直分享到指定 App」的能力。
- 纯 scheme`weixin://` / `mqqapi://` / `snssdk1128://`)**只能打开 App 或某页面,不能携带分享内容发起分享**。
- 「拉起 App 分享界面 + 预填内容 + 选好友直接分享」**只能靠各家官方鸿蒙 SDK**:
- 微信 Open SDK(用户要求不使用 → 放弃直分享)
- QQ 互联 `@tencent/qq-open-sdk` v1.0.3+`shareToQQ` 可预填)
- 抖音开放平台 SDK(仅「拉起编辑/发布页发布作品」,**无选好友私信能力**)
- 三者均需 AppId 注册 / 签名指纹 / AppLinking 配置(属已登记的延期外部依赖)。
**决策(已确认)**:本期**不接任何分享 SDK**,三端统一走「**剪贴板 + 指引窗 → 系统分享**」,代码内预留 SDK 接入点;SDK 接入列为后续延期项。
## 3. 对外契约(零改动,铁律判据)
| 方向 | handler | 数据 | 说明 |
|---|---|---|---|
| 入站 | `friendsSharetypeUrlToptitleDescript` | JSON(`SharetypeBean`) | 触发分享 |
| 出站 | `sharesuccess` | `{success:int, type:int}` | **仅微信**success 2 成功 / 3 取消;type 1 好友 / 2 朋友圈 |
`SharetypeBean`(不变):
```jsonc
{
"sharefriend": "1", // "1" 弹面板选目标 / "2" 朋友圈直发微信
"type": "1", // "1" 网页/文本 / "2" Canvas截图 / "3" 图片链接 / "4" 视频(抖音)
"sharetype": "", // 截图子类型(canvasId)
"webpageUrl": "https://...",
"title": "标题",
"description": "描述"
}
```
## 4. 交互流程
```
H5 → friendsSharetypeUrlToptitleDescript(SharetypeBean)
├─ sharefriend=="2" → 微信渠道(朋友圈语义, 回传 type=2) → ShareGuideDialog(wechat)
└─ sharefriend=="1" → SharePanel(微信/QQ/抖音/取消)
└─ 选定渠道 → 按渠道+type 组装内容 + 写剪贴板 → ShareGuideDialog(platform)
├─「打开 微信/QQ/抖音」 canOpenLink + openLink(scheme) best-effort 打开 App,用户自行粘贴
├─「更多分享方式」 systemShare 系统面板(兜底)
└─「取消」
```
- `sharefriend=="1"` 弹自有 `SharePanel`(沿用现状);`=="2"` 不弹、直接微信指引窗。
- 指引窗对所有 `type` 都先把可分享内容写入剪贴板(文本/图片/视频 URI),再展示。
## 5. 内容组装(逐渠道对齐原工程)
文本拼接函数 `buildShareText(bean, platform)` —— **三端文本一律不含 `webpageUrl`**
| 渠道 | 文本(type1,3) 格式 | 备注 |
|---|---|---|
| 微信 | `title\ndescription` | 单换行、**不含 url**(第二/三层均不带);无缩略图概念 |
| QQ | `title\n\ndescription` | 双换行、不含 url(对齐原工程) |
| 抖音 | `title\ndescription` | 单换行、**不含 url**(第二/三层均不带) |
- 空字段跳过对应行,避免多余空行。三端差异仅在换行数(QQ 双、微信/抖音 单)。
- **`webpageUrl` 不再出现在任何文本/链接分享路径**;仅作 type4 的本地视频文件路径使用。
- `type "3"`(图片链接)按纯文本(`title`+`description`)处理,不带 url。
类型处理:
| type | 内容 | 剪贴板 | 系统分享兜底 |
|---|---|---|---|
| 1 网页/文本 | `buildShareText`(无 url | PLAIN_TEXT | `systemText`(PLAIN_TEXT, 无 url) |
| 2 Canvas 截图 | `captureCanvas(sharetype)``saveDataUrlToFile` 沙箱 | PIXELMAP | `systemImage` |
| 3 图片链接 | 同 type1(纯文本, 无 url | PLAIN_TEXT | `systemText` |
| 4 视频(抖音) | 本地视频 `webpageUrl` | 文件 URI | `systemVideo`;远程视频降级为 `systemText`(无 url) |
> 系统分享(第三层)统一用 `PLAIN_TEXT(title+description)`**不再使用 `systemLink`/HYPERLINK**(即不下发 url)。`systemLink` 退役。
## 6. `sharesuccess` 回传(仅微信,乐观)
- 用户在微信指引窗点「打开微信」或「更多分享方式」即视为已发起 → `callHandler('sharesuccess', {success:2, type})`
- `type = (sharefriend=='1') ? 1 : 2`
- 点「取消」 / 微信未安装且无法打开 → `{success:3, type}`
- QQ、抖音**不回传**(与契约一致)。
## 7. 组件与改动清单
### 7.1 重写 `feature_capabilities/.../providers/ShareProvider.ets`
- 保留:`FriendsShare` 注册、`PHOTO_UPLOAD``LocalUploadServer` 截图上传)链路 → 改为走微信指引窗(图片)。
- 新增:`sharefriend` 分流、`buildShareText` 逐渠道、`writeClipboard`(文本/PIXELMAP/URI)、`showGuide` 经事件投给 UI、`openAppByScheme``canOpenLink`+`openLink`)。
- 预留空分支:`qqSdkShare()` / `douyinSdkShare()`(注释 TODO,注册到位后接 SDK)。
- 复用:现有 `systemShare` 方法(`systemText/systemImage/systemVideo`**`systemLink` 退役不再使用**)、`saveDataUrlToFile``captureCanvas`
- 移除:对 `WeChatApi.sendShare` / `WXMediaMessage` / `WXWebpageObject` / `WXImageObject` / `SendMessageToWXReq` 的全部分享调用。
### 7.2 新增 `entry/.../components/ShareGuideDialog.ets`
- 自绘弹窗:渠道图标(复用 `share_wechat/share_qq/share_douyin`)+「内容已复制,请打开 XX 粘贴分享」+ 三按钮(打开 App / 更多分享方式 / 取消)。
-`EventBus`(仿 `SharePanel``SHOW_PANEL`/一次性回投模式)与 `BridgeGameContainer` 通信。
### 7.3 `feature_capabilities/.../wx/WeChatApi.ets`
- 删除 `sendShare``ShareRespCallback``routeResp``SendMessageToWXResp` 分支及其 import。
- **保留**授权登录路径(`sendAuth`/`handleWant`/`SendAuthResp`)。
### 7.4 `entry/src/main/module.json5`
- `querySchemes` 增加 `"mqqapi"``"snssdk1128"`(连同现有 `"weixin"`)。
### 7.5 依赖
- **保留** `@tencent/wechat_open_sdk`(登录仍依赖;登录代码不动)。
### 7.6 支付边界(确认现状已满足,无需删依赖)
- `PayStubProvider` 已是 void 空桩(`PayBrowser`/`GetGameplay` noop、不出站、无 SDK)。
- 全工程无独立支付依赖;module.json5 无支付 scheme。
- **结论**:支付「移除依赖和逻辑、留空桩」诉求**已天然满足**,本期不改支付代码;仅在 spec 记录该结论。
## 8. 不做(YAGNI / 延期)
- 不接微信/QQ/抖音任何分享 SDK(tier1 直分享、选好友)→ 后续延期项(依赖外部注册)。
- 不实现 QQ/抖音 `sharesuccess` 回传(契约允许其无回传)。
- 不新增任何对外 handler;不改 H5。
## 9. 测试与验收
- 单元测试(`entry/src/test`,纯逻辑):`buildShareText` 三渠道格式、空字段裁剪、`type` 分支映射。
- 设备验证(真机/模拟器):
- `friendsSharetypeUrlToptitleDescript``type`/`sharefriend` 组合弹窗正确、剪贴板内容正确、系统分享面板可拉起。
- 微信渠道 `sharesuccess` 乐观回传时机正确;QQ/抖音不回传。
- `devecocli build` 通过、`code-linter` 无新增告警。
- 验收基线:H5 调用全程不报错、不卡死(`DefaultHandler` 兜底仍在)。
## 10. 风险
- **拉起 App 仅"打开"不预填**`openLink(scheme)` 只能打开 App,用户需手动粘贴;体验弱于原工程微信 SDK,已与用户确认接受。
- **scheme 可用性**`mqqapi`/`snssdk1128` 能否 `canOpenLink` 取决于对方鸿蒙版注册情况;不可用时指引窗降级为纯文案提示,不报错。