From 9e684f0afbfdae729829f07d3a221f577bceb83b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=93=A5=E5=A4=A7=E5=93=A5=E7=9A=84=E5=A4=A7?= =?UTF-8?q?=E5=93=A5=E5=93=A5?= Date: Mon, 20 Jul 2026 19:04:45 +0800 Subject: [PATCH] =?UTF-8?q?fix(tongji):=20=E6=81=A2=E5=A4=8D=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E8=BF=9B=E5=BA=A6=E5=B9=B6=E5=AE=8C=E5=96=84=E5=91=A8?= =?UTF-8?q?=E6=A6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TUICallKit-Vue3/.gitignore | 2 + TUICallKit-Vue3/TUICallKit | 1 + .../composables/useGamePlatform.js | 26 ++- .../tongji/endless-game/game-endless.scss | 6 + TUICallKit-Vue3/tongji/endless-game/index.vue | 168 +++++++++++++++++- server/app/api/controller/TcmController.php | 5 +- .../app/api/logic/tcm/GamePlatformLogic.php | 13 +- 7 files changed, 206 insertions(+), 15 deletions(-) create mode 120000 TUICallKit-Vue3/TUICallKit diff --git a/TUICallKit-Vue3/.gitignore b/TUICallKit-Vue3/.gitignore index 937db4ac..948de16f 100644 --- a/TUICallKit-Vue3/.gitignore +++ b/TUICallKit-Vue3/.gitignore @@ -22,3 +22,5 @@ unpackage/dist *.sw? TUICallKit +# 本工程的通话源码复用仓库内 ../wx/TUICallKit;保留相对软链接以便干净克隆后可直接构建。 +!TUICallKit diff --git a/TUICallKit-Vue3/TUICallKit b/TUICallKit-Vue3/TUICallKit new file mode 120000 index 00000000..792cbee8 --- /dev/null +++ b/TUICallKit-Vue3/TUICallKit @@ -0,0 +1 @@ +../wx/TUICallKit \ No newline at end of file diff --git a/TUICallKit-Vue3/tongji/endless-game/composables/useGamePlatform.js b/TUICallKit-Vue3/tongji/endless-game/composables/useGamePlatform.js index 7d30bd5c..ca4c5f7b 100644 --- a/TUICallKit-Vue3/tongji/endless-game/composables/useGamePlatform.js +++ b/TUICallKit-Vue3/tongji/endless-game/composables/useGamePlatform.js @@ -39,6 +39,7 @@ export function useGamePlatform(proxy, ensureLoggedIn) { const connected = ref(false) const loading = ref(false) const syncStatus = ref('idle') + const lastError = ref('') const leaderboard = ref({ ...EMPTY_BOARD }) const confirmedSessionLearned = ref(0) @@ -73,17 +74,19 @@ export function useGamePlatform(proxy, ensureLoggedIn) { } connected.value = true syncStatus.value = 'synced' + lastError.value = '' } async function refreshLeaderboard() { const res = await api({ url: '/api/tcm/gameWeeklyLeaderboard', - method: 'GET' + method: 'GET', + data: { session_key: sessionKey } }) if (res?.code !== 1 || !res.data) { throw new Error(res?.msg || '同行榜加载失败') } - applyLeaderboard(res.data) + applyLeaderboard(res.data, sessionKey) return res.data } @@ -112,9 +115,10 @@ export function useGamePlatform(proxy, ensureLoggedIn) { await refreshLeaderboard() if (queuedPayloads.length) flushProgress() return true - } catch (_) { + } catch (error) { connected.value = false syncStatus.value = 'offline' + lastError.value = String(error?.message || '平台连接失败,请点击重试') return false } finally { loading.value = false @@ -124,14 +128,21 @@ export function useGamePlatform(proxy, ensureLoggedIn) { return connectPromise } - function beginSession() { + function beginSession(existingSessionKey = '') { if (syncTimer) clearTimeout(syncTimer) - sessionKey = createSessionKey() + const restoredKey = String(existingSessionKey || '').trim() + sessionKey = /^[A-Za-z0-9_-]{16,64}$/.test(restoredKey) + ? restoredKey + : createSessionKey() confirmedSessionLearned.value = 0 syncStatus.value = queuedPayloads.length ? 'pending' : (connected.value ? 'synced' : 'offline') return sessionKey } + function getSessionKey() { + return sessionKey + } + function queueProgress(learnedCount, score, ended = false) { const nextPayload = { session_key: sessionKey, @@ -191,9 +202,10 @@ export function useGamePlatform(proxy, ensureLoggedIn) { || Number(item.ended) > Number(payload.ended) )) persistPendingPayloads() - } catch (_) { + } catch (error) { connected.value = false syncStatus.value = 'offline' + lastError.value = String(error?.message || '成绩暂未保存,联网后会自动重试') // 队首保留原绝对值,下次连接或打开榜单时安全重试。 persistPendingPayloads() } finally { @@ -237,10 +249,12 @@ export function useGamePlatform(proxy, ensureLoggedIn) { connected, loading, syncStatus, + lastError, leaderboard, confirmedSessionLearned, connect, beginSession, + getSessionKey, queueProgress, flushProgress, syncAndRefresh, diff --git a/TUICallKit-Vue3/tongji/endless-game/game-endless.scss b/TUICallKit-Vue3/tongji/endless-game/game-endless.scss index 9a8bb1d0..19f07c6e 100644 --- a/TUICallKit-Vue3/tongji/endless-game/game-endless.scss +++ b/TUICallKit-Vue3/tongji/endless-game/game-endless.scss @@ -337,6 +337,9 @@ .eg-weekly-list { display: flex; flex-direction: column; gap: 7rpx; margin-top: 15rpx; } .eg-weekly-row { display: flex; min-height: 68rpx; align-items: center; padding: 7rpx 14rpx; border: 2rpx solid transparent; border-radius: 19rpx; color: #345c50; background: rgba(255,255,255,.72); } .eg-weekly-row.is-me { border-color: #f2bd48; color: #174f3e; background: linear-gradient(90deg, #fff2bb, #fff9e3); box-shadow: 0 5rpx 14rpx rgba(153,102,17,.12); transform: scale(1.015); } +.eg-weekly-row.is-waiting { color: #8a9b94; border-style: dashed; border-color: #dbe8e2; background: rgba(247,251,249,.72); } +.eg-weekly-row.is-waiting .eg-weekly-avatar { color: #6e887e; border-color: #dce9e3; background: #edf4f1; box-shadow: none; } +.eg-weekly-row.is-waiting .eg-weekly-count { color: #9baba4; } .eg-weekly-place { width: 43rpx; color: #6b7d76; font-size: 27rpx; font-weight: 1000; text-align: center; } .eg-weekly-row:nth-child(1) .eg-weekly-place { color: #dd7b17; font-size: 31rpx; } .eg-weekly-avatar { display: flex; width: 52rpx; height: 52rpx; flex: 0 0 52rpx; align-items: center; justify-content: center; margin-left: 6rpx; border: 3rpx solid rgba(255,255,255,.9); border-radius: 50%; color: #fff; background: #5d9b84; box-shadow: 0 3rpx 9rpx rgba(30,78,61,.16); font-size: 24rpx; font-weight: 1000; } @@ -350,6 +353,9 @@ .eg-weekly-name { flex: 1; margin-left: 13rpx; overflow: hidden; font-size: 27rpx; font-weight: 850; text-overflow: ellipsis; white-space: nowrap; } .eg-weekly-me { margin-right: 8rpx; padding: 3rpx 9rpx; border-radius: 999rpx; color: #fff; background: #dd6b27; font-size: 18rpx; font-weight: 900; } .eg-weekly-count { min-width: 70rpx; color: #315b4d; font-size: 29rpx; font-weight: 1000; text-align: right; } +.eg-weekly-connection { display: flex; align-items: center; justify-content: space-between; gap: 12rpx; margin-top: 13rpx; padding: 12rpx 15rpx; border: 2rpx solid #e4d7b2; border-radius: 18rpx; color: #6b6655; background: #fff9e8; font-size: 21rpx; font-weight: 700; } +.eg-weekly-connection > text:first-child { flex: 1; } +.eg-weekly-retry { flex-shrink: 0; padding: 6rpx 12rpx; border-radius: 999rpx; color: #fff; background: #23765c; font-weight: 900; } .eg-cheer-card { margin-top: 16rpx; padding: 15rpx 17rpx 14rpx; border: 3rpx solid #f0d38d; border-radius: 23rpx; background: linear-gradient(135deg, #fff9d9, #fff1c2); } .eg-cheer-card.is-family { border-color: #d9c8ef; background: linear-gradient(135deg, #f8f2ff, #efe7ff); } .eg-cheer-card.is-bright { border-color: #f4c77b; background: linear-gradient(135deg, #fff8dc, #ffeec7); } diff --git a/TUICallKit-Vue3/tongji/endless-game/index.vue b/TUICallKit-Vue3/tongji/endless-game/index.vue index abb84c80..6e487031 100644 --- a/TUICallKit-Vue3/tongji/endless-game/index.vue +++ b/TUICallKit-Vue3/tongji/endless-game/index.vue @@ -224,7 +224,7 @@ v-for="player in weeklyRankRows" :key="player.id" class="eg-weekly-row" - :class="{ 'is-me': player.isMe }" + :class="{ 'is-me': player.isMe, 'is-waiting': player.isWaiting }" > {{ player.rank }} @@ -237,6 +237,11 @@ + + {{ platformConnectionHint }} + 点击重试 + + {{ currentCheer.source }} @@ -246,7 +251,7 @@ 亲友自定义内容,不作为医学判断 - 开始消除 + {{ restoredGame ? '继续上次游戏' : '开始消除' }} 使用平台昵称参加真实周榜,每周一重新分组;分享不会自动绑定家庭关系 @@ -300,7 +305,7 @@