dapaijizhang3/pages/game/play/play.js

566 lines
13 KiB
JavaScript
Raw Permalink Normal View History

2025-11-20 16:42:59 +08:00
// pages/game/play/play.js
import request from '../../../utils/request'
Page({
data: {
sessionId: null,
session: null,
players: [],
detailPlayers: [],
scoreboard: [],
recentRecords: [],
historyRecords: [],
currentRound: 1,
// 快速记账
selectedScore: 0,
customScore: '',
canSubmitQuick: false,
// 详细记账
showDetailMode: false,
totalBalance: 0,
// 历史记录
showHistory: false,
// 刷新定时器
refreshTimer: null
},
onLoad(options) {
if (!options.id) {
wx.showToast({
title: '参数错误',
icon: 'none'
})
setTimeout(() => {
wx.navigateBack()
}, 1500)
return
}
this.setData({ sessionId: options.id })
// 加载数据
this.loadSessionData()
this.loadRecentRecords()
// 设置自动刷新
this.startAutoRefresh()
},
onUnload() {
if (this.data.refreshTimer) {
clearInterval(this.data.refreshTimer)
}
},
// 启动自动刷新
startAutoRefresh() {
const timer = setInterval(() => {
this.loadSessionData(true)
this.loadRecentRecords(true)
}, 10000) // 每10秒刷新一次
this.setData({ refreshTimer: timer })
},
// 加载牌局数据
async loadSessionData(silent = false) {
if (!silent) {
wx.showLoading({ title: '加载中...' })
}
try {
// 获取牌局详情
const sessionData = await request.get(`/rooms/${this.data.sessionId}`)
// 获取当前积分和局数
const chips = await request.get(`/records/session/${this.data.sessionId}/chips`)
// 准备玩家数据(用于快速记账)
const players = sessionData.players.map(p => ({
id: p.player_id,
nickname: p.nickname,
avatar_url: p.avatar_url,
selected: false, // 是否选为赢家
losing: false // 是否选为输家
}))
// 准备详细记账玩家数据
const detailPlayers = sessionData.players.map(p => ({
id: p.player_id,
nickname: p.nickname,
avatar_url: p.avatar_url,
current_chips: chips.chips[p.player_id] || 0,
chips_change: 0
}))
// 准备积分榜数据
const scoreboard = sessionData.players.map(p => ({
id: p.player_id,
nickname: p.nickname,
avatar_url: p.avatar_url,
total_chips: chips.chips[p.player_id] || 0
})).sort((a, b) => b.total_chips - a.total_chips)
this.setData({
session: sessionData.session,
players,
detailPlayers,
scoreboard,
currentRound: chips.total_rounds + 1
})
if (!silent) {
wx.hideLoading()
}
} catch (error) {
if (!silent) {
wx.hideLoading()
wx.showToast({
title: error.message || '加载失败',
icon: 'none'
})
}
}
},
// 加载最近记录
async loadRecentRecords(silent = false) {
try {
const recordsData = await request.get(`/records/session/${this.data.sessionId}`, {
page: 1,
pageSize: 5
})
// 格式化记录
const recentRecords = (recordsData.list || []).map(record => {
const time = new Date(record.created_at * 1000)
const now = Date.now()
const diff = now - record.created_at * 1000
return {
id: record.id,
round_number: record.round_number,
scores: record.playerScores || [],
timeText: this.formatRecordTime(time),
can_undo: diff < 300000 // 5分钟内可撤销
}
})
this.setData({ recentRecords })
} catch (error) {
if (!silent) {
console.error('加载记录失败:', error)
}
}
},
// 格式化时间
formatRecordTime(time) {
const now = new Date()
const diff = now - time
if (diff < 60000) {
return '刚刚'
} else if (diff < 3600000) {
return `${Math.floor(diff / 60000)}分钟前`
} else {
return `${time.getHours()}:${String(time.getMinutes()).padStart(2, '0')}`
}
},
// 切换赢家
toggleWinner(e) {
const playerId = e.currentTarget.dataset.id
const players = this.data.players.map(p => {
if (p.id === playerId) {
p.selected = !p.selected
// 赢家不能同时是输家
if (p.selected) p.losing = false
}
return p
})
this.setData({ players })
this.checkCanSubmitQuick()
},
// 切换输家
toggleLoser(e) {
const playerId = e.currentTarget.dataset.id
const players = this.data.players.map(p => {
if (p.id === playerId) {
p.losing = !p.losing
// 输家不能同时是赢家
if (p.losing) p.selected = false
}
return p
})
this.setData({ players })
this.checkCanSubmitQuick()
},
// 设置分数
setScore(e) {
const score = parseInt(e.currentTarget.dataset.score)
this.setData({
selectedScore: score,
customScore: ''
})
this.checkCanSubmitQuick()
},
// 输入自定义分数
onScoreInput(e) {
const score = parseInt(e.detail.value) || 0
this.setData({
customScore: e.detail.value,
selectedScore: score
})
this.checkCanSubmitQuick()
},
// 检查是否可以提交快速记账
checkCanSubmitQuick() {
const { players, selectedScore } = this.data
const winners = players.filter(p => p.selected)
const losers = players.filter(p => p.losing)
const canSubmit = winners.length > 0 && losers.length > 0 && selectedScore > 0
this.setData({ canSubmitQuick: canSubmit })
},
// 提交快速记账
async submitQuickEntry() {
const { players, selectedScore, currentRound } = this.data
const winners = players.filter(p => p.selected)
const losers = players.filter(p => p.losing)
if (winners.length === 0 || losers.length === 0 || selectedScore <= 0) {
wx.showToast({
title: '请完整填写信息',
icon: 'none'
})
return
}
// 计算分数变化
const winnerShare = Math.floor(selectedScore * losers.length / winners.length)
const loserShare = selectedScore
const scores = {}
winners.forEach(w => {
scores[w.id] = winnerShare
})
losers.forEach(l => {
scores[l.id] = -loserShare
})
// 未参与的玩家分数为0
players.forEach(p => {
if (!scores[p.id]) {
scores[p.id] = 0
}
})
wx.showLoading({ title: '提交中...' })
try {
await request.post('/records/create', {
session_id: this.data.sessionId,
round_number: currentRound,
scores
})
wx.hideLoading()
wx.showToast({
title: '记账成功',
icon: 'success'
})
// 重置选择
const resetPlayers = players.map(p => ({
...p,
selected: false,
losing: false
}))
this.setData({
players: resetPlayers,
selectedScore: 0,
customScore: '',
canSubmitQuick: false,
currentRound: currentRound + 1
})
// 刷新数据
this.loadSessionData()
this.loadRecentRecords()
} catch (error) {
wx.hideLoading()
wx.showToast({
title: error.message || '提交失败',
icon: 'none'
})
}
},
// 切换详细记账模式
toggleDetailMode() {
this.setData({
showDetailMode: !this.data.showDetailMode
})
},
// 详细分数输入
onDetailScoreInput(e) {
const playerId = e.currentTarget.dataset.id
const value = parseInt(e.detail.value) || 0
const detailPlayers = this.data.detailPlayers.map(p => {
if (p.id === playerId) {
p.chips_change = value
}
return p
})
// 计算总平衡
const totalBalance = detailPlayers.reduce((sum, p) => sum + p.chips_change, 0)
this.setData({
detailPlayers,
totalBalance
})
},
// 提交详细记账
async submitDetailEntry() {
const { detailPlayers, totalBalance, currentRound } = this.data
if (totalBalance !== 0) {
wx.showToast({
title: '分数需要平衡',
icon: 'none'
})
return
}
// 检查是否有变化
const hasChange = detailPlayers.some(p => p.chips_change !== 0)
if (!hasChange) {
wx.showToast({
title: '请输入分数变化',
icon: 'none'
})
return
}
// 构建分数对象
const scores = {}
detailPlayers.forEach(p => {
scores[p.id] = p.chips_change
})
wx.showLoading({ title: '提交中...' })
try {
await request.post('/records/create', {
session_id: this.data.sessionId,
round_number: currentRound,
scores
})
wx.hideLoading()
wx.showToast({
title: '记账成功',
icon: 'success'
})
// 重置详细记账
const resetPlayers = detailPlayers.map(p => ({
...p,
chips_change: 0
}))
this.setData({
detailPlayers: resetPlayers,
totalBalance: 0,
showDetailMode: false,
currentRound: currentRound + 1
})
// 刷新数据
this.loadSessionData()
this.loadRecentRecords()
} catch (error) {
wx.hideLoading()
wx.showToast({
title: error.message || '提交失败',
icon: 'none'
})
}
},
// 撤销记录
async undoRecord(e) {
const recordId = e.currentTarget.dataset.id
wx.showModal({
title: '撤销记录',
content: '确定要撤销这条记录吗?',
success: async (res) => {
if (res.confirm) {
wx.showLoading({ title: '撤销中...' })
try {
await request.delete(`/records/${recordId}`)
wx.hideLoading()
wx.showToast({
title: '已撤销',
icon: 'success'
})
// 刷新数据
this.loadSessionData()
this.loadRecentRecords()
} catch (error) {
wx.hideLoading()
wx.showToast({
title: error.message || '撤销失败',
icon: 'none'
})
}
}
}
})
},
// 查看历史记录
async viewHistory() {
wx.showLoading({ title: '加载中...' })
try {
const recordsData = await request.get(`/records/session/${this.data.sessionId}`, {
page: 1,
pageSize: 50
})
const historyRecords = (recordsData.list || []).map(record => {
const time = new Date(record.created_at * 1000)
return {
...record,
timeText: `${time.getMonth() + 1}/${time.getDate()} ${time.getHours()}:${String(time.getMinutes()).padStart(2, '0')}`
}
})
this.setData({
historyRecords,
showHistory: true
})
wx.hideLoading()
} catch (error) {
wx.hideLoading()
wx.showToast({
title: '加载失败',
icon: 'none'
})
}
},
// 关闭历史记录
closeHistory() {
this.setData({
showHistory: false
})
},
// 暂停游戏
pauseGame() {
wx.showModal({
title: '暂停游戏',
content: '确定要暂停游戏吗?',
success: async (res) => {
if (res.confirm) {
try {
await request.post(`/rooms/${this.data.sessionId}/pause`)
wx.showToast({
title: '已暂停',
icon: 'success'
})
setTimeout(() => {
wx.navigateBack()
}, 1500)
} catch (error) {
wx.showToast({
title: error.message || '操作失败',
icon: 'none'
})
}
}
}
})
},
// 结束游戏
endGame() {
wx.showModal({
title: '结束牌局',
content: '确定要结束牌局吗?结束后将无法继续记账',
confirmColor: '#ff4444',
success: async (res) => {
if (res.confirm) {
wx.showLoading({ title: '处理中...' })
try {
await request.post(`/rooms/${this.data.sessionId}/end`)
wx.hideLoading()
wx.showToast({
title: '牌局已结束',
icon: 'success'
})
// 跳转到统计页
setTimeout(() => {
wx.redirectTo({
url: `/pages/stats/session/session?id=${this.data.sessionId}`
})
}, 1500)
} catch (error) {
wx.hideLoading()
wx.showToast({
title: error.message || '操作失败',
icon: 'none'
})
}
}
}
})
},
// 下拉刷新
onPullDownRefresh() {
Promise.all([
this.loadSessionData(),
this.loadRecentRecords()
]).then(() => {
wx.stopPullDownRefresh()
})
}
})