refactor: 收口公开详情点赞意图
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
- 决策:新增 `src/components/platform-entry/platformPublicWorkDetailFlow.ts`,以 `getPlatformPublicWorkDetailKind`、`resolvePlatformPublicWorkDetailOpenStrategy`、`resolvePlatformPublicWorkActionMode`、`resolvePlatformPublicWorkDetailOpenDecision` 和 `resolveActivePlatformPublicWorkAuthorEntry` 收口公开作品详情 Strategy。`PlatformEntryFlowShellImpl.tsx` 只按 Strategy 调用现有详情读取 / 直接展示 Adapter,并保留作者请求竞态控制;启动、点赞、remix 和编辑副作用暂不抽走。
|
||||
- 追加决策:公开详情 entry 映射与公开详情反推玩法 work 摘要也归入 `platformPublicWorkDetailFlow.ts`,包括 RPG、拼图、大鱼吃小鱼、方洞挑战、视觉小说、跳一跳、敲木鱼和汪汪声浪的通用映射。抓大鹅 `mapMatch3DWorkToPublicWorkDetail` 归入 `platformMatch3DRuntimeProfile.ts`,继续委托 `normalizeMatch3DWorkForRuntimeUi` 做素材归一和背景资产提升,避免把 Match3D 运行态规则复制到公开详情 Flow Module。
|
||||
- 追加决策:拼图公开详情封面解锁数由 `resolveVisiblePuzzleDetailCoverCount(entry, run)` 收口;非拼图、无当前 run 或 run 不匹配当前公开详情时只展示首图,匹配当前公开详情时按 `clearedLevelCount + 1` 解锁且至少为 1。`PlatformWorkDetailView` 只接收 `visibleCoverCount` 展示,不读取 run。
|
||||
- 追加决策:公开详情点赞能力矩阵由 `resolvePlatformPublicWorkLikeIntent(entry)` 收口;Module 只返回大鱼吃小鱼、拼图、旧 RPG gallery fallback 或不可用文案,壳层仍执行鉴权、API 调用、缓存同步、错误展示和 busy 状态。
|
||||
- 影响范围:统一作品详情入口、公开详情打开策略、自有公开作品编辑 / 改造动作模式,以及后续新增玩法公开详情接入。
|
||||
- 验证方式:`npm run test -- src/components/platform-entry/platformPublicWorkDetailFlow.test.ts`、`npm run test -- src/components/platform-entry/platformMatch3DRuntimeProfile.test.ts`、公开详情壳层交互回归、`npm run typecheck`、`npm run check:encoding`。
|
||||
- 关联文档:`docs/technical/【前端架构】PlatformPublicWorkDetailFlow收口计划-2026-06-03.md`。
|
||||
|
||||
@@ -41,7 +41,7 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
|
||||
|
||||
平台入口公开作品身份、跨玩法去重、推荐运行态 kind 判定和最新排序收口到 `src/components/platform-entry/platformPublicGalleryFlow.ts`,规则见 [【前端架构】平台入口PublicGalleryFlowModule收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91%E5%B9%B3%E5%8F%B0%E5%85%A5%E5%8F%A3PublicGalleryFlowModule%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
||||
|
||||
统一作品详情页的玩法 kind、详情打开策略、自有作品动作模式和公开详情映射收口到 `src/components/platform-entry/platformPublicWorkDetailFlow.ts`;抓大鹅公开详情映射的素材归一仍归 `platformMatch3DRuntimeProfile.ts`,规则见 [【前端架构】PlatformPublicWorkDetailFlow收口计划-2026-06-03.md](./technical/【前端架构】PlatformPublicWorkDetailFlow收口计划-2026-06-03.md)。
|
||||
统一作品详情页的玩法 kind、详情打开策略、自有作品动作模式、点赞意图和公开详情映射收口到 `src/components/platform-entry/platformPublicWorkDetailFlow.ts`;抓大鹅公开详情映射的素材归一仍归 `platformMatch3DRuntimeProfile.ts`,规则见 [【前端架构】PlatformPublicWorkDetailFlow收口计划-2026-06-03.md](./technical/【前端架构】PlatformPublicWorkDetailFlow收口计划-2026-06-03.md)。
|
||||
|
||||
创作中心作品架打开动作由 `CreationWorkShelfItem.actions.open` 统一承载,生产 Hub 只接收 `CreationWorkShelfItem[]` 与 UI 状态,不再接收各玩法 raw items 和回调列阵,规则见 [【前端架构】WorkShelfModule收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91WorkShelfModule%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- `getPlatformPublicWorkDetailKind(entry)`
|
||||
- `resolvePlatformPublicWorkDetailOpenStrategy(entry)`
|
||||
- `resolvePlatformPublicWorkActionMode(entry, viewerUserId)`
|
||||
- `resolvePlatformPublicWorkLikeIntent(entry)`
|
||||
- `resolvePlatformPublicWorkDetailOpenDecision(entry, deps)`
|
||||
- `resolveActivePlatformPublicWorkAuthorEntry(args)`
|
||||
- `map*WorkToPublicWorkDetail(...)`
|
||||
@@ -32,6 +33,7 @@
|
||||
- 大鱼吃小鱼、抓大鹅、方洞挑战、汪汪声浪、宝贝识物和其它可直接展示的公开 entry 返回 `use-entry` strategy。
|
||||
- RPG 返回 `load-rpg-detail` strategy,由壳层 Adapter 继续调用 RPG 详情读取流程。
|
||||
- `resolvePlatformPublicWorkActionMode` 只比较 `entry.ownerUserId` 与当前 viewer user id;当前用户拥有该公开作品时返回 `edit`,否则返回 `remix`。
|
||||
- `resolvePlatformPublicWorkLikeIntent` 只表达公开作品点赞意图:大鱼吃小鱼、拼图和旧 RPG gallery fallback 返回可执行 intent;宝贝识物、汪汪声浪、方洞挑战和视觉小说返回不可用文案。壳层只按 intent 调用 API、写缓存和展示错误,不再持有这组能力矩阵。
|
||||
- `resolvePlatformPublicWorkDetailOpenDecision` 只表达直接展示公开详情的打开 / 阻断结果、错误文案、目标 stage 与可写入历史的路径;真正执行 setter、push history 的副作用仍由壳层 Adapter 执行。
|
||||
- `resolveActivePlatformPublicWorkAuthorEntry` 只在 `work-detail` 阶段选择统一公开详情 entry,在 RPG `detail` 阶段只选择非 draft 的 RPG 详情 entry;作者请求、竞态 request key 和缓存仍留壳层。
|
||||
- `map*WorkToPublicWorkDetail` 只把各玩法已存在的 work / gallery summary 映射为统一详情 entry;公开码、封面、统计与标题字段继续复用 `rpgEntryWorldPresentation.ts` 的平台公开卡片映射。
|
||||
@@ -41,7 +43,7 @@
|
||||
|
||||
## Depth / Leverage / Locality
|
||||
|
||||
- **Depth**:壳层传入公开作品 entry、玩法 work summary、当前用户 id 或当前拼图 run,即可得到详情打开策略、动作模式、统一详情映射和封面可见数;玩法判定与 DTO 默认值藏在 Module Implementation 内。
|
||||
- **Depth**:壳层传入公开作品 entry、玩法 work summary、当前用户 id 或当前拼图 run,即可得到详情打开策略、动作模式、点赞意图、统一详情映射和封面可见数;玩法判定、能力矩阵与 DTO 默认值藏在 Module Implementation 内。
|
||||
- **Leverage**:新增玩法公开详情时先补 Strategy / Mapping 单测,再接壳层 Adapter,不必在多个 JSX / callback 位置重复 sourceType 判断或 DTO 回填。
|
||||
- **Locality**:公开作品详情入口的纯策略与通用映射集中到一个小 Module;Match3D 素材归一仍在 Match3D Module;启动运行态、点赞、改造、编辑等副作用仍留在壳层,避免伪 Seam。
|
||||
|
||||
|
||||
@@ -532,6 +532,7 @@ import {
|
||||
resolvePlatformPublicWorkActionMode,
|
||||
resolvePlatformPublicWorkDetailOpenDecision,
|
||||
resolvePlatformPublicWorkDetailOpenStrategy,
|
||||
resolvePlatformPublicWorkLikeIntent,
|
||||
resolveVisiblePuzzleDetailCoverCount,
|
||||
} from './platformPublicWorkDetailFlow';
|
||||
import {
|
||||
@@ -10778,11 +10779,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
setIsPublicWorkDetailBusy(true);
|
||||
setPublicWorkDetailError(null);
|
||||
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
void likeBigFishGalleryWork(entry.profileId)
|
||||
const intent = resolvePlatformPublicWorkLikeIntent(entry);
|
||||
|
||||
if (intent.type === 'like-big-fish') {
|
||||
void likeBigFishGalleryWork(intent.profileId)
|
||||
.then((response) => {
|
||||
const updatedWork = response.items.find(
|
||||
(item) => item.sourceSessionId === entry.profileId,
|
||||
(item) => item.sourceSessionId === intent.profileId,
|
||||
);
|
||||
if (!updatedWork) {
|
||||
return;
|
||||
@@ -10817,8 +10820,8 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
void likePuzzleGalleryWork(entry.profileId)
|
||||
if (intent.type === 'like-puzzle') {
|
||||
void likePuzzleGalleryWork(intent.profileId)
|
||||
.then((response) => {
|
||||
const updatedWork = response.item;
|
||||
setPuzzleGalleryEntries((current) =>
|
||||
@@ -10851,31 +10854,13 @@ export function PlatformEntryFlowShellImpl({
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEdutainmentGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('宝贝识物点赞将在后续版本开放。');
|
||||
if (intent.type === 'unsupported') {
|
||||
setPublicWorkDetailError(intent.errorMessage);
|
||||
setIsPublicWorkDetailBusy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('汪汪声浪点赞将在后续版本开放。');
|
||||
setIsPublicWorkDetailBusy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isSquareHoleGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('方洞挑战点赞将在后续版本开放。');
|
||||
setIsPublicWorkDetailBusy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisualNovelGalleryEntry(entry)) {
|
||||
setPublicWorkDetailError('视觉小说点赞将在后续版本开放。');
|
||||
setIsPublicWorkDetailBusy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
void likeRpgEntryWorldGallery(entry.ownerUserId, entry.profileId)
|
||||
void likeRpgEntryWorldGallery(intent.ownerUserId, intent.profileId)
|
||||
.then((updatedEntry) => {
|
||||
setSelectedDetailEntry((current) =>
|
||||
current?.profileId === updatedEntry.profileId
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
resolvePlatformPublicWorkActionMode,
|
||||
resolvePlatformPublicWorkDetailOpenDecision,
|
||||
resolvePlatformPublicWorkDetailOpenStrategy,
|
||||
resolvePlatformPublicWorkLikeIntent,
|
||||
resolveVisiblePuzzleDetailCoverCount,
|
||||
} from './platformPublicWorkDetailFlow';
|
||||
|
||||
@@ -651,6 +652,49 @@ test('platform public work detail flow resolves edit mode only for owned works',
|
||||
expect(resolvePlatformPublicWorkActionMode(entry, null)).toBe('remix');
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves like intent', () => {
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('big-fish'))).toEqual(
|
||||
{
|
||||
type: 'like-big-fish',
|
||||
profileId: 'big-fish-profile',
|
||||
},
|
||||
);
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('puzzle'))).toEqual({
|
||||
type: 'like-puzzle',
|
||||
profileId: 'puzzle-profile',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildRpgEntry())).toEqual({
|
||||
type: 'like-rpg-gallery',
|
||||
ownerUserId: 'user-1',
|
||||
profileId: 'rpg-profile',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('match3d'))).toEqual(
|
||||
{
|
||||
type: 'like-rpg-gallery',
|
||||
ownerUserId: 'user-1',
|
||||
profileId: 'match3d-profile',
|
||||
},
|
||||
);
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('edutainment'))).toEqual({
|
||||
type: 'unsupported',
|
||||
errorMessage: '宝贝识物点赞将在后续版本开放。',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('bark-battle'))).toEqual(
|
||||
{
|
||||
type: 'unsupported',
|
||||
errorMessage: '汪汪声浪点赞将在后续版本开放。',
|
||||
},
|
||||
);
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('square-hole'))).toEqual({
|
||||
type: 'unsupported',
|
||||
errorMessage: '方洞挑战点赞将在后续版本开放。',
|
||||
});
|
||||
expect(resolvePlatformPublicWorkLikeIntent(buildTypedEntry('visual-novel'))).toEqual({
|
||||
type: 'unsupported',
|
||||
errorMessage: '视觉小说点赞将在后续版本开放。',
|
||||
});
|
||||
});
|
||||
|
||||
test('platform public work detail flow resolves direct open decision', () => {
|
||||
const entry = buildTypedEntry('match3d', {
|
||||
publicWorkCode: ' M3D-001 ',
|
||||
|
||||
@@ -81,6 +81,25 @@ export type PlatformPublicWorkDetailOpenStrategy =
|
||||
|
||||
export type PlatformPublicWorkActionMode = 'edit' | 'remix';
|
||||
|
||||
export type PlatformPublicWorkLikeIntent =
|
||||
| {
|
||||
type: 'like-big-fish';
|
||||
profileId: string;
|
||||
}
|
||||
| {
|
||||
type: 'like-puzzle';
|
||||
profileId: string;
|
||||
}
|
||||
| {
|
||||
type: 'like-rpg-gallery';
|
||||
ownerUserId: string;
|
||||
profileId: string;
|
||||
}
|
||||
| {
|
||||
type: 'unsupported';
|
||||
errorMessage: string;
|
||||
};
|
||||
|
||||
export type PlatformPublicWorkDetailOpenDecision =
|
||||
| {
|
||||
type: 'blocked';
|
||||
@@ -455,6 +474,58 @@ export function resolvePlatformPublicWorkActionMode(
|
||||
: 'remix';
|
||||
}
|
||||
|
||||
export function resolvePlatformPublicWorkLikeIntent(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
): PlatformPublicWorkLikeIntent {
|
||||
if (isBigFishGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'like-big-fish',
|
||||
profileId: entry.profileId,
|
||||
};
|
||||
}
|
||||
|
||||
if (isPuzzleGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'like-puzzle',
|
||||
profileId: entry.profileId,
|
||||
};
|
||||
}
|
||||
|
||||
if (isEdutainmentGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '宝贝识物点赞将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isBarkBattleGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '汪汪声浪点赞将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isSquareHoleGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '方洞挑战点赞将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
if (isVisualNovelGalleryEntry(entry)) {
|
||||
return {
|
||||
type: 'unsupported',
|
||||
errorMessage: '视觉小说点赞将在后续版本开放。',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'like-rpg-gallery',
|
||||
ownerUserId: entry.ownerUserId,
|
||||
profileId: entry.profileId,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolvePlatformPublicWorkDetailOpenDecision(
|
||||
entry: PlatformPublicGalleryCard,
|
||||
deps: PlatformPublicWorkDetailOpenDecisionDeps = {},
|
||||
|
||||
Reference in New Issue
Block a user