From 40f7be5200659b1846d03370789ba506b5a1009b Mon Sep 17 00:00:00 2001 From: richarjiang Date: Thu, 14 May 2026 16:55:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5=E6=88=91=E5=8F=82?= =?UTF-8?q?=E4=B8=8E=E7=9A=84=E6=8C=91=E6=88=98=E6=8E=A5=E5=8F=A3=E4=BB=A5?= =?UTF-8?q?=E5=8F=8AUI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/prefabs/PagePKData.prefab | 346 ++++++++++++++++++++------- assets/prefabs/PagePKData.ts | 166 ++++++++++++- assets/prefabs/PagePKDetail.ts | 16 +- assets/scripts/config/ApiConfig.ts | 1 + assets/scripts/types/ApiTypes.ts | 12 + assets/scripts/utils/ShareManager.ts | 28 +++ 6 files changed, 470 insertions(+), 99 deletions(-) diff --git a/assets/prefabs/PagePKData.prefab b/assets/prefabs/PagePKData.prefab index bb5b28a..1a2ea33 100644 --- a/assets/prefabs/PagePKData.prefab +++ b/assets/prefabs/PagePKData.prefab @@ -37,20 +37,20 @@ "__id__": 180 }, { - "__id__": 266 + "__id__": 272 } ], "_active": true, "_components": [ { - "__id__": 282 + "__id__": 288 }, { - "__id__": 284 + "__id__": 290 } ], "_prefab": { - "__id__": 286 + "__id__": 292 }, "_lpos": { "__type__": "cc.Vec3", @@ -4347,20 +4347,20 @@ "__id__": 197 }, { - "__id__": 257 + "__id__": 263 } ], "_active": true, "_components": [ { - "__id__": 263 + "__id__": 269 }, { "__id__": 194 } ], "_prefab": { - "__id__": 265 + "__id__": 271 }, "_lpos": { "__type__": "cc.Vec3", @@ -4417,7 +4417,7 @@ } ], "_prefab": { - "__id__": 256 + "__id__": 262 }, "_lpos": { "__type__": "cc.Vec3", @@ -4724,11 +4724,11 @@ "_active": true, "_components": [ { - "__id__": 253 + "__id__": 259 } ], "_prefab": { - "__id__": 255 + "__id__": 261 }, "_lpos": { "__type__": "cc.Vec3", @@ -4937,27 +4937,27 @@ { "__id__": 206 }, - { - "__id__": 230 - }, { "__id__": 236 }, { "__id__": 242 + }, + { + "__id__": 248 } ], "_active": true, "_components": [ { - "__id__": 248 + "__id__": 254 }, { - "__id__": 250 + "__id__": 256 } ], "_prefab": { - "__id__": 252 + "__id__": 258 }, "_lpos": { "__type__": "cc.Vec3", @@ -5005,19 +5005,22 @@ }, { "__id__": 219 + }, + { + "__id__": 225 } ], "_active": true, "_components": [ { - "__id__": 225 + "__id__": 231 }, { - "__id__": 227 + "__id__": 233 } ], "_prefab": { - "__id__": 229 + "__id__": 235 }, "_lpos": { "__type__": "cc.Vec3", @@ -5456,6 +5459,165 @@ "targetOverrides": null, "nestedPrefabInstanceRoots": null }, + { + "__type__": "cc.Node", + "_name": "RankNumber", + "_objFlags": 0, + "__editorExtras__": {}, + "_parent": { + "__id__": 206 + }, + "_children": [], + "_active": false, + "_components": [ + { + "__id__": 226 + }, + { + "__id__": 228 + } + ], + "_prefab": { + "__id__": 230 + }, + "_lpos": { + "__type__": "cc.Vec3", + "x": -9.887, + "y": 0, + "z": 0 + }, + "_lrot": { + "__type__": "cc.Quat", + "x": 0, + "y": 0, + "z": 0, + "w": 1 + }, + "_lscale": { + "__type__": "cc.Vec3", + "x": 2.387, + "y": 2.387, + "z": 2.387 + }, + "_mobility": 0, + "_layer": 1073741824, + "_euler": { + "__type__": "cc.Vec3", + "x": 0, + "y": 0, + "z": 0 + }, + "_id": "" + }, + { + "__type__": "cc.UITransform", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 225 + }, + "_enabled": true, + "__prefab": { + "__id__": 227 + }, + "_contentSize": { + "__type__": "cc.Size", + "width": 65.615234375, + "height": 136 + }, + "_anchorPoint": { + "__type__": "cc.Vec2", + "x": 0.5, + "y": 0.5 + }, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "afc2A9N6FGc7UuXiK197iF" + }, + { + "__type__": "cc.Label", + "_name": "", + "_objFlags": 0, + "__editorExtras__": {}, + "node": { + "__id__": 225 + }, + "_enabled": true, + "__prefab": { + "__id__": 229 + }, + "_customMaterial": null, + "_srcBlendFactor": 2, + "_dstBlendFactor": 4, + "_color": { + "__type__": "cc.Color", + "r": 236, + "g": 236, + "b": 236, + "a": 255 + }, + "_string": "4", + "_horizontalAlign": 1, + "_verticalAlign": 1, + "_actualFontSize": 100, + "_fontSize": 100, + "_fontFamily": "Arial", + "_lineHeight": 100, + "_overflow": 0, + "_enableWrapText": true, + "_font": null, + "_isSystemFontUsed": true, + "_spacingX": 0, + "_isItalic": false, + "_isBold": true, + "_isUnderline": false, + "_underlineHeight": 2, + "_cacheMode": 0, + "_enableOutline": true, + "_outlineColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_outlineWidth": 5, + "_enableShadow": false, + "_shadowColor": { + "__type__": "cc.Color", + "r": 0, + "g": 0, + "b": 0, + "a": 255 + }, + "_shadowOffset": { + "__type__": "cc.Vec2", + "x": 2, + "y": 2 + }, + "_shadowBlur": 2, + "_id": "" + }, + { + "__type__": "cc.CompPrefabInfo", + "fileId": "59LYxrApZB/bVeRXmT+WzJ" + }, + { + "__type__": "cc.PrefabInfo", + "root": { + "__id__": 1 + }, + "asset": { + "__id__": 0 + }, + "fileId": "afXTpxGqpP+IgoyzMhucMS", + "instance": null, + "targetOverrides": null, + "nestedPrefabInstanceRoots": null + }, { "__type__": "cc.UITransform", "_name": "", @@ -5466,7 +5628,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 226 + "__id__": 232 }, "_contentSize": { "__type__": "cc.Size", @@ -5494,7 +5656,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 228 + "__id__": 234 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -5554,14 +5716,14 @@ "_active": true, "_components": [ { - "__id__": 231 + "__id__": 237 }, { - "__id__": 233 + "__id__": 239 } ], "_prefab": { - "__id__": 235 + "__id__": 241 }, "_lpos": { "__type__": "cc.Vec3", @@ -5598,15 +5760,15 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 230 + "__id__": 236 }, "_enabled": true, "__prefab": { - "__id__": 232 + "__id__": 238 }, "_contentSize": { "__type__": "cc.Size", - "width": 490, + "width": 549.0625, "height": 88.2 }, "_anchorPoint": { @@ -5626,11 +5788,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 230 + "__id__": 236 }, "_enabled": true, "__prefab": { - "__id__": 234 + "__id__": 240 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -5642,15 +5804,15 @@ "b": 29, "a": 255 }, - "_string": "西瓜太郎的挑战", - "_horizontalAlign": 1, + "_string": "西瓜太郎12", + "_horizontalAlign": 0, "_verticalAlign": 1, "_actualFontSize": 70, "_fontSize": 70, "_fontFamily": "Arial", "_lineHeight": 70, - "_overflow": 0, - "_enableWrapText": true, + "_overflow": 1, + "_enableWrapText": false, "_font": { "__uuid__": "fb4acba6-6bc7-4eb3-be34-8f2ac9823a80", "__expectedType__": "cc.TTFFont" @@ -5716,14 +5878,14 @@ "_active": true, "_components": [ { - "__id__": 237 + "__id__": 243 }, { - "__id__": 239 + "__id__": 245 } ], "_prefab": { - "__id__": 241 + "__id__": 247 }, "_lpos": { "__type__": "cc.Vec3", @@ -5760,11 +5922,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 236 + "__id__": 242 }, "_enabled": true, "__prefab": { - "__id__": 238 + "__id__": 244 }, "_contentSize": { "__type__": "cc.Size", @@ -5788,11 +5950,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 236 + "__id__": 242 }, "_enabled": true, "__prefab": { - "__id__": 240 + "__id__": 246 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -5852,14 +6014,14 @@ "_active": true, "_components": [ { - "__id__": 243 + "__id__": 249 }, { - "__id__": 245 + "__id__": 251 } ], "_prefab": { - "__id__": 247 + "__id__": 253 }, "_lpos": { "__type__": "cc.Vec3", @@ -5896,11 +6058,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 242 + "__id__": 248 }, "_enabled": true, "__prefab": { - "__id__": 244 + "__id__": 250 }, "_contentSize": { "__type__": "cc.Size", @@ -5924,11 +6086,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 242 + "__id__": 248 }, "_enabled": true, "__prefab": { - "__id__": 246 + "__id__": 252 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -6012,7 +6174,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 249 + "__id__": 255 }, "_contentSize": { "__type__": "cc.Size", @@ -6040,7 +6202,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 251 + "__id__": 257 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -6098,7 +6260,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 254 + "__id__": 260 }, "_contentSize": { "__type__": "cc.Size", @@ -6154,14 +6316,14 @@ "_active": true, "_components": [ { - "__id__": 258 + "__id__": 264 }, { - "__id__": 260 + "__id__": 266 } ], "_prefab": { - "__id__": 262 + "__id__": 268 }, "_lpos": { "__type__": "cc.Vec3", @@ -6198,11 +6360,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 257 + "__id__": 263 }, "_enabled": true, "__prefab": { - "__id__": 259 + "__id__": 265 }, "_contentSize": { "__type__": "cc.Size", @@ -6226,11 +6388,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 257 + "__id__": 263 }, "_enabled": true, "__prefab": { - "__id__": 261 + "__id__": 267 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -6288,7 +6450,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 264 + "__id__": 270 }, "_contentSize": { "__type__": "cc.Size", @@ -6329,26 +6491,26 @@ }, "_children": [ { - "__id__": 267 + "__id__": 273 } ], "_active": true, "_components": [ - { - "__id__": 273 - }, - { - "__id__": 275 - }, - { - "__id__": 277 - }, { "__id__": 279 + }, + { + "__id__": 281 + }, + { + "__id__": 283 + }, + { + "__id__": 285 } ], "_prefab": { - "__id__": 281 + "__id__": 287 }, "_lpos": { "__type__": "cc.Vec3", @@ -6385,20 +6547,20 @@ "_objFlags": 0, "__editorExtras__": {}, "_parent": { - "__id__": 266 + "__id__": 272 }, "_children": [], "_active": true, "_components": [ { - "__id__": 268 + "__id__": 274 }, { - "__id__": 270 + "__id__": 276 } ], "_prefab": { - "__id__": 272 + "__id__": 278 }, "_lpos": { "__type__": "cc.Vec3", @@ -6435,11 +6597,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 267 + "__id__": 273 }, "_enabled": true, "__prefab": { - "__id__": 269 + "__id__": 275 }, "_contentSize": { "__type__": "cc.Size", @@ -6463,11 +6625,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 267 + "__id__": 273 }, "_enabled": true, "__prefab": { - "__id__": 271 + "__id__": 277 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -6547,11 +6709,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 266 + "__id__": 272 }, "_enabled": true, "__prefab": { - "__id__": 274 + "__id__": 280 }, "_contentSize": { "__type__": "cc.Size", @@ -6575,11 +6737,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 266 + "__id__": 272 }, "_enabled": true, "__prefab": { - "__id__": 276 + "__id__": 282 }, "_customMaterial": null, "_srcBlendFactor": 2, @@ -6620,11 +6782,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 266 + "__id__": 272 }, "_enabled": true, "__prefab": { - "__id__": 278 + "__id__": 284 }, "_alignFlags": 20, "_target": null, @@ -6656,11 +6818,11 @@ "_objFlags": 0, "__editorExtras__": {}, "node": { - "__id__": 266 + "__id__": 272 }, "_enabled": true, "__prefab": { - "__id__": 280 + "__id__": 286 }, "clickEvents": [], "_interactable": true, @@ -6700,7 +6862,7 @@ "_duration": 0.1, "_zoomScale": 1.2, "_target": { - "__id__": 266 + "__id__": 272 }, "_id": "" }, @@ -6731,7 +6893,7 @@ }, "_enabled": true, "__prefab": { - "__id__": 283 + "__id__": 289 }, "_contentSize": { "__type__": "cc.Size", @@ -6759,10 +6921,10 @@ }, "_enabled": true, "__prefab": { - "__id__": 285 + "__id__": 291 }, "backBtn": { - "__id__": 266 + "__id__": 272 }, "createdListContent": { "__id__": 54 @@ -6770,6 +6932,12 @@ "createdListItemTemplate": { "__id__": 63 }, + "participatedListContent": { + "__id__": 196 + }, + "participatedListItemTemplate": { + "__id__": 205 + }, "_id": "" }, { diff --git a/assets/prefabs/PagePKData.ts b/assets/prefabs/PagePKData.ts index 451ff7b..cda0070 100644 --- a/assets/prefabs/PagePKData.ts +++ b/assets/prefabs/PagePKData.ts @@ -1,7 +1,7 @@ import { _decorator, Node, Button, instantiate, Label, ScrollView, UITransform, Sprite, SpriteFrame, Texture2D, ImageAsset, assetManager } from 'cc'; import { BaseView } from 'db://assets/scripts/core/BaseView'; import { ViewManager } from 'db://assets/scripts/core/ViewManager'; -import { CreatedShareItem, ShareParticipantRankSummary } from 'db://assets/scripts/types/ApiTypes'; +import { CreatedShareItem, ParticipatedShareItem, ShareParticipantRankSummary } from 'db://assets/scripts/types/ApiTypes'; import { ShareManager } from 'db://assets/scripts/utils/ShareManager'; import { ToastManager } from 'db://assets/scripts/utils/ToastManager'; const { ccclass, property } = _decorator; @@ -11,6 +11,9 @@ export class PagePKData extends BaseView { private static readonly CREATED_ITEM_TOP_PADDING = 20; private static readonly CREATED_ITEM_BOTTOM_PADDING = 20; private static readonly CREATED_ITEM_SPACING = 20; + private static readonly PARTICIPATED_ITEM_TOP_PADDING = 20; + private static readonly PARTICIPATED_ITEM_BOTTOM_PADDING = 20; + private static readonly PARTICIPATED_ITEM_SPACING = 20; @property({ type: Node, tooltip: '返回按钮' }) backBtn: Node | null = null; @@ -21,8 +24,16 @@ export class PagePKData extends BaseView { @property({ type: Node, tooltip: '我创建的挑战列表条目模板 FriendsPKRankListItem' }) createdListItemTemplate: Node | null = null; + @property({ type: Node, tooltip: '我参与的挑战列表 content 节点' }) + participatedListContent: Node | null = null; + + @property({ type: Node, tooltip: '我参与的挑战列表条目模板 MyPKListItem' }) + participatedListItemTemplate: Node | null = null; + private _createdShares: CreatedShareItem[] = []; + private _participatedShares: ParticipatedShareItem[] = []; private _createdItemNodes: Node[] = []; + private _participatedItemNodes: Node[] = []; private _createdButtonBindings: Array<{ node: Node; handler: () => void }> = []; private _isLoading: boolean = false; private _renderVersion: number = 0; @@ -33,36 +44,44 @@ export class PagePKData extends BaseView { this.backBtn.on(Button.EventType.CLICK, this._onBackClick, this); } this._hideCreatedItemTemplate(); + this._hideParticipatedItemTemplate(); } onViewShow(): void { this._resolveNodes(); - void this._loadCreatedShares(); + void this._loadShareLists(); } onViewHide(): void { + this._renderVersion++; } private _onBackClick(): void { ViewManager.instance.back(); } - private async _loadCreatedShares(): Promise { + private async _loadShareLists(): Promise { if (this._isLoading) { return; } this._isLoading = true; try { - const items = await ShareManager.instance.fetchCreatedShares(); - if (!items) { + const [createdItems, participatedItems] = await Promise.all([ + ShareManager.instance.fetchCreatedShares(), + ShareManager.instance.fetchParticipatedShares(), + ]); + + if (!createdItems || !participatedItems) { ToastManager.instance.show('获取挑战列表失败,请稍后重试'); - return; } - this._createdShares = items; + this._createdShares = createdItems ?? []; + this._participatedShares = participatedItems ?? []; console.log('[PagePKData] 我创建的挑战列表:', this._createdShares); + console.log('[PagePKData] 我参与的挑战列表:', this._participatedShares); this._renderCreatedShares(); + this._renderParticipatedShares(); } finally { this._isLoading = false; } @@ -73,6 +92,7 @@ export class PagePKData extends BaseView { this.backBtn.off(Button.EventType.CLICK, this._onBackClick, this); } this._clearCreatedItems(); + this._clearParticipatedItems(); } private _resolveNodes(): void { @@ -87,12 +107,25 @@ export class PagePKData extends BaseView { ?? this.createdListContent?.getChildByName('FriendsPKRankListItem') ?? null; + const participatedList = this.node.getChildByName('MyPKList'); + const participatedView = participatedList?.getChildByName('view'); + this.participatedListContent = this.participatedListContent ?? participatedView?.getChildByName('content') ?? null; + this.participatedListItemTemplate = this.participatedListItemTemplate + ?? this.participatedListContent?.getChildByName('MyPKListItem') + ?? null; + if (!this.createdListContent) { console.warn('[PagePKData] 未找到 FriendsPKRankList/content 节点'); } if (!this.createdListItemTemplate) { console.warn('[PagePKData] 未找到 FriendsPKRankListItem 模板节点'); } + if (!this.participatedListContent) { + console.warn('[PagePKData] 未找到 MyPKList/content 节点'); + } + if (!this.participatedListItemTemplate) { + console.warn('[PagePKData] 未找到 MyPKListItem 模板节点'); + } } private _renderCreatedShares(): void { @@ -119,6 +152,29 @@ export class PagePKData extends BaseView { this._scrollCreatedListToTop(); } + private _renderParticipatedShares(): void { + this._clearParticipatedItems(); + + if (!this.participatedListContent || !this.participatedListItemTemplate) { + return; + } + + this._layoutParticipatedList(this._participatedShares.length); + this._hideParticipatedItemTemplate(); + + this._participatedShares.forEach((share, index) => { + const item = instantiate(this.participatedListItemTemplate!); + item.name = `MyPKListItem_${index + 1}`; + item.active = true; + this.participatedListContent!.addChild(item); + this._participatedItemNodes.push(item); + this._positionParticipatedItem(item, index); + this._applyParticipatedShare(item, share); + }); + + this._scrollParticipatedListToTop(); + } + private _applyCreatedShare(item: Node, share: CreatedShareItem, version: number): void { this._setLabel(this._findLabelIn(item, 'Name'), share.title || '未命名挑战'); this._setLabel(this._findLabelIn(item, 'ParticipateLabel'), `共${share.participantCount ?? 0}人参与`); @@ -146,6 +202,12 @@ export class PagePKData extends BaseView { } } + private _applyParticipatedShare(item: Node, share: ParticipatedShareItem): void { + this._setLabel(this._findLabelIn(item, 'ChallangeName'), share.title || '未命名挑战'); + this._setLabel(this._findLabelIn(item, 'ParticipateLabel'), `共${share.participantCount ?? 0}人参与`); + this._applyParticipatedRank(item, share.userRank); + } + private _openShareDetail(share: CreatedShareItem): void { if (!share.shareCode) { ToastManager.instance.show('挑战数据异常,请稍后重试'); @@ -200,6 +262,34 @@ export class PagePKData extends BaseView { ); } + private _layoutParticipatedList(itemCount: number): void { + if (!this.participatedListContent || !this.participatedListItemTemplate) { + return; + } + + const contentTransform = this.participatedListContent.getComponent(UITransform); + const viewTransform = this.participatedListContent.parent?.getComponent(UITransform) ?? null; + const itemTransform = this.participatedListItemTemplate.getComponent(UITransform); + if (!contentTransform || !viewTransform || !itemTransform) { + return; + } + + const contentHeight = Math.max( + viewTransform.height, + PagePKData.PARTICIPATED_ITEM_TOP_PADDING + + PagePKData.PARTICIPATED_ITEM_BOTTOM_PADDING + + itemCount * itemTransform.height + + Math.max(0, itemCount - 1) * PagePKData.PARTICIPATED_ITEM_SPACING, + ); + + contentTransform.setContentSize(contentTransform.width, contentHeight); + this.participatedListContent.setPosition( + this.participatedListContent.position.x, + viewTransform.height / 2, + this.participatedListContent.position.z, + ); + } + private _positionCreatedItem(item: Node, index: number): void { const itemTransform = item.getComponent(UITransform); if (!itemTransform) { @@ -212,11 +302,55 @@ export class PagePKData extends BaseView { item.setPosition(0, y, item.position.z); } + private _positionParticipatedItem(item: Node, index: number): void { + const itemTransform = item.getComponent(UITransform); + if (!itemTransform) { + return; + } + + const y = -PagePKData.PARTICIPATED_ITEM_TOP_PADDING + - itemTransform.height / 2 + - index * (itemTransform.height + PagePKData.PARTICIPATED_ITEM_SPACING); + item.setPosition(0, y, item.position.z); + } + private _scrollCreatedListToTop(): void { const scrollView = this.node.getChildByName('FriendsPKRankList')?.getComponent(ScrollView); scrollView?.scrollToTop(0); } + private _scrollParticipatedListToTop(): void { + const scrollView = this.node.getChildByName('MyPKList')?.getComponent(ScrollView); + scrollView?.scrollToTop(0); + } + + private _applyParticipatedRank(item: Node, rank: number | null): void { + const rankRoot = this._findChild(item, 'Rank'); + if (!rankRoot) { + return; + } + + const rank1Badge = this._findChild(rankRoot, 'rank1badge'); + const rank2Badge = this._findChild(rankRoot, 'rank2badge'); + const rank3Badge = this._findChild(rankRoot, 'rank3badge'); + const rankNumberNode = this._findChild(rankRoot, 'RankNumber'); + const normalizedRank = rank && rank > 0 ? rank : null; + + if (rank1Badge) { + rank1Badge.active = normalizedRank === 1; + } + if (rank2Badge) { + rank2Badge.active = normalizedRank === 2; + } + if (rank3Badge) { + rank3Badge.active = normalizedRank === 3; + } + if (rankNumberNode) { + rankNumberNode.active = normalizedRank !== 1 && normalizedRank !== 2 && normalizedRank !== 3; + this._setLabel(rankNumberNode.getComponent(Label), normalizedRank ? `${normalizedRank}` : '-'); + } + } + private _findAvatarSprite(item: Node): Sprite | null { const headNode = this._findChild(item, 'Head'); return headNode?.children[0]?.getComponent(Sprite) ?? headNode?.getComponent(Sprite) ?? null; @@ -256,6 +390,18 @@ export class PagePKData extends BaseView { this._hideCreatedItemTemplate(); } + private _clearParticipatedItems(): void { + for (const item of this._participatedItemNodes) { + if (item.isValid) { + item.removeFromParent(); + item.destroy(); + } + } + + this._participatedItemNodes = []; + this._hideParticipatedItemTemplate(); + } + private _unbindCreatedButtons(): void { for (const binding of this._createdButtonBindings) { if (binding.node.isValid) { @@ -271,6 +417,12 @@ export class PagePKData extends BaseView { } } + private _hideParticipatedItemTemplate(): void { + if (this.participatedListItemTemplate?.isValid) { + this.participatedListItemTemplate.active = false; + } + } + private _setLabel(label: Label | null, text: string): void { if (label) { label.string = text; diff --git a/assets/prefabs/PagePKDetail.ts b/assets/prefabs/PagePKDetail.ts index 7ae514a..2f276af 100644 --- a/assets/prefabs/PagePKDetail.ts +++ b/assets/prefabs/PagePKDetail.ts @@ -178,7 +178,7 @@ export class PagePKDetail extends BaseView { return; } - this._setLabel(this._findLabelIn(panel, 'UserName'), this._getParticipantName(champion) || '暂无参与'); + this._setLabel(this._findLabelIn(panel, 'UserName'), this._getParticipantDisplayName(champion, '暂无参与')); this._setLabel(this._findLabelIn(panel, 'RightInfo'), this._formatCorrectText(champion, shareInfo)); this._setLabel(this._findLabelIn(panel, 'UsedTime'), this._formatTimeText(champion, shareInfo)); this._loadAvatar(champion?.avatarUrl ?? '', this._findAvatarSprite(panel), version); @@ -222,7 +222,7 @@ export class PagePKDetail extends BaseView { this._setLabel(rankNumberNode.getComponent(Label), rank > 0 ? `${rank}` : '-'); } - this._setLabel(this._findLabelIn(item, 'UserName'), this._getParticipantName(participant) || '微信用户'); + this._setLabel(this._findLabelIn(item, 'UserName'), this._getParticipantDisplayName(participant, '微信用户')); this._setLabel(this._findLabelIn(item, 'RightInfo'), this._formatCorrectText(participant, null)); this._setLabel(this._findLabelIn(item, 'UsedTime'), this._formatTimeText(participant)); this._loadAvatar(participant.avatarUrl ?? '', this._findAvatarSprite(item), version); @@ -312,13 +312,23 @@ export class PagePKDetail extends BaseView { return participant?.nickname || participant?.nickName || ''; } + private _getParticipantDisplayName( + participant: ShareParticipantRankSummary | null, + emptyParticipantFallback: string, + ): string { + if (!participant) { + return emptyParticipantFallback; + } + + return this._getParticipantName(participant) || '微信用户'; + } + private _loadAvatar(url: string, sprite: Sprite | null, version: number): void { if (!sprite) { return; } if (!url) { - sprite.spriteFrame = null; return; } diff --git a/assets/scripts/config/ApiConfig.ts b/assets/scripts/config/ApiConfig.ts index bcafb3b..372bf89 100644 --- a/assets/scripts/config/ApiConfig.ts +++ b/assets/scripts/config/ApiConfig.ts @@ -19,6 +19,7 @@ export const API_ENDPOINTS = { /** 分享相关 */ SHARE_CREATE: `${API_BASE}/share`, SHARE_CREATED: `${API_BASE}/share/created`, + SHARE_PARTICIPATED: `${API_BASE}/share/participated`, /** 用户信息 */ USER_INFO: `${API_BASE}/user/info`, /** 用户所有已通关的关卡(成就墙 / 关卡回看) */ diff --git a/assets/scripts/types/ApiTypes.ts b/assets/scripts/types/ApiTypes.ts index 6114b4b..9bc3d14 100644 --- a/assets/scripts/types/ApiTypes.ts +++ b/assets/scripts/types/ApiTypes.ts @@ -194,6 +194,18 @@ export interface CreatedShareListData { items: CreatedShareItem[]; } +/** 我参与的分享挑战条目 */ +export interface ParticipatedShareItem { + title: string; + participantCount: number; + userRank: number | null; +} + +/** 我参与的分享挑战列表响应 */ +export interface ParticipatedShareListData { + items: ParticipatedShareItem[]; +} + /** 分享挑战详情响应 */ export interface ShareDetailData { id: string; diff --git a/assets/scripts/utils/ShareManager.ts b/assets/scripts/utils/ShareManager.ts index 98e7ff7..341241c 100644 --- a/assets/scripts/utils/ShareManager.ts +++ b/assets/scripts/utils/ShareManager.ts @@ -9,6 +9,8 @@ import { ShareLevelData, CreatedShareItem, CreatedShareListData, + ParticipatedShareItem, + ParticipatedShareListData, ShareDetailData, SubmitShareData, SubmitShareLevel, @@ -31,6 +33,7 @@ export class ShareManager { private _shareTitle: string = ''; private _shareCode: string | null = null; private _createdShares: CreatedShareItem[] = []; + private _participatedShares: ParticipatedShareItem[] = []; /** 图片缓存:URL -> SpriteFrame */ private _imageCache: Map = new Map(); @@ -52,6 +55,10 @@ export class ShareManager { return [...this._createdShares]; } + get participatedShares(): ParticipatedShareItem[] { + return [...this._participatedShares]; + } + get shareCode(): string | null { return this._shareCode; } @@ -158,6 +165,27 @@ export class ShareManager { } } + async fetchParticipatedShares(): Promise { + try { + const response = await HttpUtil.get>( + API_ENDPOINTS.SHARE_PARTICIPATED, + API_TIMEOUT.DEFAULT, + ); + + if (!response.success || !response.data) { + console.error('[ShareManager] 获取我参与的挑战列表失败:', response.message); + return null; + } + + this._participatedShares = response.data.items ?? []; + console.log(`[ShareManager] 获取我参与的挑战列表成功: ${this._participatedShares.length} 条`); + return this.participatedShares; + } catch (err) { + console.error('[ShareManager] 获取我参与的挑战列表异常:', err); + return null; + } + } + async fetchShareDetail(code: string): Promise { try { const response = await HttpUtil.get>(