refactor(private-zone): use canonical product name
This commit is contained in:
@@ -63,7 +63,7 @@ Authorization: Bearer <TOKEN>
|
||||
2. `isActive=true`;
|
||||
3. `capabilities.chat=true`。
|
||||
|
||||
服务端目录决定角色是否可聊天及排序;本地目录继续提供 slug、图片、文案和 Tip 能力。`privateZoom` 只有在本地能力和服务端 `privateContent` 同时开启时可用。
|
||||
服务端目录决定角色是否可聊天及排序;本地目录继续提供 slug、图片、文案和 Tip 能力。`privateZone` 只有在本地能力和服务端 `privateContent` 同时开启时可用。
|
||||
|
||||
远端目录返回前,生产环境只使用 Elio 作为临时目录;非生产环境可使用完整本地目录。远端目录加载成功后,以合并结果为准。
|
||||
|
||||
@@ -72,7 +72,7 @@ Authorization: Bearer <TOKEN>
|
||||
```text
|
||||
/characters/{slug}/splash
|
||||
/characters/{slug}/chat
|
||||
/characters/{slug}/private-zoom
|
||||
/characters/{slug}/private-zone
|
||||
/characters/{slug}/tip
|
||||
```
|
||||
|
||||
@@ -81,11 +81,11 @@ Authorization: Bearer <TOKEN>
|
||||
```text
|
||||
/splash -> /characters/elio/splash
|
||||
/chat -> /characters/elio/chat
|
||||
/private-zoom -> /characters/elio/private-zoom
|
||||
/private-zone -> /characters/elio/private-zone
|
||||
/tip -> /characters/elio/tip
|
||||
```
|
||||
|
||||
Chat Provider 以 `characterId` 为边界,路由角色变化时创建新的 Actor。Private Zoom 的角色边界由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。
|
||||
Chat Provider 以 `characterId` 为边界,路由角色变化时创建新的 Actor。Private Zone 的角色边界由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。
|
||||
|
||||
## 3. Chat HTTP 协议
|
||||
|
||||
@@ -308,7 +308,7 @@ conversationKey = {ownerKey}::character:{encodeURIComponent(characterId)}
|
||||
|
||||
## 7. 关联业务边界
|
||||
|
||||
- Private Zoom 的相册、解锁、Gallery 和支付回跳由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。
|
||||
- Private Zone 的相册、解锁、Gallery 和支付回跳由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。
|
||||
- Tip 的角色归属、订单轮询和支付回跳由 [Payment 权威协议](./FRONTEND_PAYMENT_API.md) 定义;Chat 只保存解锁所需的原角色回跳地址。
|
||||
- 登录、支付和解锁回跳保存原角色动态 URL,不能降级为通用 `/chat`。
|
||||
- Analytics 可以使用 `characterId`,聊天正文不属于路由或身份协议的一部分。
|
||||
|
||||
@@ -224,7 +224,7 @@ payChannel = ezpay
|
||||
subscriptionType = vip | topup | tip
|
||||
giftCategory(仅 Tip,可空)
|
||||
giftPlanId(仅 Tip,可空)
|
||||
returnTo = chat | private-zoom | profile(可选)
|
||||
returnTo = chat | private-zone | profile(可选)
|
||||
characterSlug(可选)
|
||||
createdAt
|
||||
```
|
||||
@@ -238,7 +238,7 @@ Tip -> /characters/{slug}/tip?category=...&planId=...&payChannel=ezpay&
|
||||
|
||||
恢复页面只接受与当前 `paymentType` 相同的待处理订单。带有 `paymentReturn=1` 时派发 `PaymentReturned` 并继续轮询;普通进入支付页时会清理同类型的旧待处理订单。订单进入 paid、failed 或 expired 后清理持久化记录。缺少 Gift 字段的旧记录由最新目录默认选择第一件商品,不再读取 `coffee_type`。
|
||||
|
||||
无效或未知 `characterSlug` 回退到默认角色 slug。有效角色回跳必须保留原角色,不能统一返回 Elio。`returnTo=private-zoom` 的最终页面行为由 [Private Zoom 权威协议](./FRONTEND_PRIVATE_ZOOM_API.md) 定义。
|
||||
无效或未知 `characterSlug` 回退到默认角色 slug。有效角色回跳必须保留原角色,不能统一返回 Elio。`returnTo=private-zone` 的最终页面行为由 [Private Zone 权威协议](./FRONTEND_PRIVATE_ZONE_API.md) 定义。
|
||||
|
||||
## 8. 成功后的跨域同步
|
||||
|
||||
|
||||
+26
-26
@@ -1,4 +1,4 @@
|
||||
# CozSweet Private Zoom 权威协议
|
||||
# CozSweet Private Zone 权威协议
|
||||
|
||||
## 1. 状态与范围
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
| 边界 | 实现位置 |
|
||||
| --- | --- |
|
||||
| API 路径与方法 | `src/data/services/api/api_contract.json` |
|
||||
| 请求与响应字段 | `src/data/schemas/private-zoom` |
|
||||
| API 与 Repository | `src/data/services/api/private_zoom_api.ts`、`src/data/repositories/private_zoom_repository.ts` |
|
||||
| Private Zoom 状态机 | `src/stores/private-zoom` |
|
||||
| 页面、Gallery 与导航 | `src/app/private-zoom` |
|
||||
| 角色 Provider | `src/providers/private-zoom-route-provider.tsx` |
|
||||
| 请求与响应字段 | `src/data/schemas/private-zone` |
|
||||
| API 与 Repository | `src/data/services/api/private_zone_api.ts`、`src/data/repositories/private_zone_repository.ts` |
|
||||
| Private Zone 状态机 | `src/stores/private-zone` |
|
||||
| 页面、Gallery 与导航 | `src/app/private-zone` |
|
||||
| 角色 Provider | `src/providers/private-zone-route-provider.tsx` |
|
||||
|
||||
修改上述实现时必须在同一变更中更新本文,不能再新增按相册列表、解锁或 Gallery 拆分的并行协议。
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
标准路由:
|
||||
|
||||
```text
|
||||
/characters/{characterSlug}/private-zoom
|
||||
/characters/{characterSlug}/private-zone
|
||||
```
|
||||
|
||||
旧地址保留为默认角色重定向,并保留查询参数:
|
||||
|
||||
```text
|
||||
/private-zoom -> /characters/elio/private-zoom
|
||||
/private-zone -> /characters/elio/private-zone
|
||||
```
|
||||
|
||||
URL 使用角色 `slug`,API 和 Actor 使用角色业务 `id`:
|
||||
@@ -39,14 +39,14 @@ URL 使用角色 `slug`,API 和 Actor 使用角色业务 `id`:
|
||||
| `maya-tan` | `maya` |
|
||||
| `nayeli-cervantes` | `nayeli` |
|
||||
|
||||
角色必须同时存在于本地目录且 `capabilities.privateZoom=true`。该能力由本地配置和角色目录响应的 `privateContent` 共同决定;能力关闭或 slug 未知时路由返回 Not Found。
|
||||
角色必须同时存在于本地目录且 `capabilities.privateZone=true`。该能力由本地配置和角色目录响应的 `privateContent` 共同决定;能力关闭或 slug 未知时路由返回 Not Found。
|
||||
|
||||
`PrivateZoomProvider` 以 `characterId` 为输入和 React key。切换角色会销毁旧 Actor 并创建空状态,不能复用上一角色的相册、余额或解锁请求。
|
||||
`PrivateZoneProvider` 以 `characterId` 为输入和 React key。切换角色会销毁旧 Actor 并创建空状态,不能复用上一角色的相册、余额或解锁请求。
|
||||
|
||||
## 3. 相册列表
|
||||
|
||||
```http
|
||||
GET <API_BASE_URL>/api/private-zoom/albums?characterId=maya-tan&limit=20
|
||||
GET <API_BASE_URL>/api/private-zone/albums?characterId=maya-tan&limit=20
|
||||
Authorization: Bearer <TOKEN>
|
||||
```
|
||||
|
||||
@@ -55,7 +55,7 @@ Authorization: Bearer <TOKEN>
|
||||
| `characterId` | 是 | 当前角色业务 ID |
|
||||
| `limit` | 否 | 当前固定为 20 |
|
||||
|
||||
前端当前只加载第一页,不实现 Private Zoom 分页,也不把相册列表写入本地缓存。初始化、手动刷新或登录身份变化时重新请求网络。
|
||||
前端当前只加载第一页,不实现 Private Zone 分页,也不把相册列表写入本地缓存。初始化、手动刷新或登录身份变化时重新请求网络。
|
||||
|
||||
标准响应数据:
|
||||
|
||||
@@ -105,7 +105,7 @@ album.locked || !album.unlocked || album.lockDetail.locked
|
||||
用户点击锁定相册后,前端先展示确认 Dialog。只有待确认 `albumId` 仍存在于当前 Actor 的 `items` 中,才会发起请求。
|
||||
|
||||
```http
|
||||
POST <API_BASE_URL>/api/private-zoom/albums/{albumId}/unlock
|
||||
POST <API_BASE_URL>/api/private-zone/albums/{albumId}/unlock
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer <TOKEN>
|
||||
```
|
||||
@@ -177,25 +177,25 @@ Schema 同时允许未知字符串,未知失败原因使用通用错误文案
|
||||
|
||||
## 5. 身份与支付导航
|
||||
|
||||
Private Zoom 初始化会复用 Guest 登录引导。Auth 尚未初始化或正在加载时不请求列表;`notLoggedIn` 完成 Guest bootstrap 后再进入列表加载。Guest 和正式用户都可以读取后端允许的相册列表。
|
||||
Private Zone 初始化会复用 Guest 登录引导。Auth 尚未初始化或正在加载时不请求列表;`notLoggedIn` 完成 Guest bootstrap 后再进入列表加载。Guest 和正式用户都可以读取后端允许的相册列表。
|
||||
|
||||
积分不足生成 Paywall 请求后:
|
||||
|
||||
| 当前身份 | 导航 |
|
||||
| --- | --- |
|
||||
| Guest 或 Not Logged In | 打开 Auth,redirect 为当前角色 Private Zoom |
|
||||
| 已认证用户 | 打开 Top-up,`returnTo=private-zoom`,保留当前角色来源 |
|
||||
| Guest 或 Not Logged In | 打开 Auth,redirect 为当前角色 Private Zone |
|
||||
| 已认证用户 | 打开 Top-up,`returnTo=private-zone`,保留当前角色来源 |
|
||||
|
||||
Paywall 导航发起后立即消费当前请求,避免 React 重渲染重复导航。支付回跳和订单恢复遵循 [Payment 权威协议](./FRONTEND_PAYMENT_API.md)。
|
||||
|
||||
解锁成功后 `unlockSuccessNonce` 递增,页面桥接到 `UserFetch`,刷新当前积分和权益。Private Zoom 不自行修改 User Store 余额。
|
||||
解锁成功后 `unlockSuccessNonce` 递增,页面桥接到 `UserFetch`,刷新当前积分和权益。Private Zone 不自行修改 User Store 余额。
|
||||
|
||||
## 6. Gallery URL 协议
|
||||
|
||||
解锁相册使用查询参数打开页内 Gallery:
|
||||
|
||||
```text
|
||||
/characters/{slug}/private-zoom?album={albumId}&image={zeroBasedIndex}
|
||||
/characters/{slug}/private-zone?album={albumId}&image={zeroBasedIndex}
|
||||
```
|
||||
|
||||
解析规则:
|
||||
@@ -208,7 +208,7 @@ Paywall 导航发起后立即消费当前请求,避免 React 重渲染重复
|
||||
|
||||
任一条件不满足时,页面通过 replace 删除 `album` 和 `image`,并保留其他查询参数。
|
||||
|
||||
页面内点击九宫格缩略图时,Gallery 从该图片的后端数组原始索引打开。关闭操作优先使用浏览器 back;直接刷新或外部分享 Gallery URL 时,关闭操作使用 replace 返回当前角色 Private Zoom。
|
||||
页面内点击九宫格缩略图时,Gallery 从该图片的后端数组原始索引打开。关闭操作优先使用浏览器 back;直接刷新或外部分享 Gallery URL 时,关闭操作使用 replace 返回当前角色 Private Zone。
|
||||
|
||||
Gallery 只浏览 `locked=false` 且 URL 非空的图片,但 URL 中的 `image` 仍使用原始数组索引。横向拖动时图片跟随指针,达到视口宽度 18%(最低 56px),或达到 0.45px/ms 且至少移动 24px 时切换;首尾越界拖动使用 0.28 阻尼且不循环。松手后使用 240ms 横向吸附动画,键盘方向键和左右按钮复用相同切换逻辑。Escape 关闭;`prefers-reduced-motion` 下取消吸附过渡。
|
||||
|
||||
@@ -222,17 +222,17 @@ Gallery 只浏览 `locked=false` 且 URL 非空的图片,但 URL 中的 `image
|
||||
- 超过 9 张时卡片显示前九张,末格显示 `+N`,Gallery 仍可浏览全部有效图片;
|
||||
- Gallery 只挂载当前图片和相邻图片,避免多图相册同时解码全部原图;
|
||||
- `creditBalance` 是当前列表/解锁响应快照,不替代 User Store 权益;
|
||||
- Private Zoom 不使用 Chat 的 `conversationKey`、消息缓存或媒体缓存;
|
||||
- Private Zoom 不持有 Payment Actor,Top-up 通过路由级导航进入独立 Payment Provider。
|
||||
- Private Zone 不使用 Chat 的 `conversationKey`、消息缓存或媒体缓存;
|
||||
- Private Zone 不持有 Payment Actor,Top-up 通过路由级导航进入独立 Payment Provider。
|
||||
|
||||
## 8. 变更验收
|
||||
|
||||
Private Zoom 协议相关变更至少验证:
|
||||
Private Zone 协议相关变更至少验证:
|
||||
|
||||
1. `src/data/schemas/private-zoom/__tests__`;
|
||||
2. `src/data/services/api/__tests__/multi_character_api.test.ts` 中的 Private Zoom 请求;
|
||||
3. `src/stores/private-zoom/__tests__`;
|
||||
4. `src/app/private-zoom/__tests__` 与组件测试;
|
||||
1. `src/data/schemas/private-zone/__tests__`;
|
||||
2. `src/data/services/api/__tests__/multi_character_api.test.ts` 中的 Private Zone 请求;
|
||||
3. `src/stores/private-zone/__tests__`;
|
||||
4. `src/app/private-zone/__tests__` 与组件测试;
|
||||
5. Elio、Maya、Nayeli 列表互不串联;
|
||||
6. 登录身份变化会刷新当前角色列表;
|
||||
7. 成功、余额不足、价格变化、重复解锁、退款失败和 not found 分支;
|
||||
Reference in New Issue
Block a user