2025-11-11 17:07:13 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="singleplay">
|
|
|
|
|
|
<!-- 顶部功能区 -->
|
|
|
|
|
|
<view class="top-functions">
|
|
|
|
|
|
<view class="function-btn" @click="addPlayer">
|
|
|
|
|
|
<image src="/static/add.png" class="btn-icon" mode="aspectFill"></image>
|
|
|
|
|
|
<text>添加玩家</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="function-btn" @click="transferScorer">
|
|
|
|
|
|
<image src="/static/transfer.png" class="btn-icon" mode="aspectFill"></image>
|
|
|
|
|
|
<text>转让计分员</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="switch-group">
|
|
|
|
|
|
<text>语音播报</text>
|
|
|
|
|
|
<switch :checked="voiceBroadcast" @change="voiceBroadcast = $event.detail.value" color="#007aff" />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="switch-group">
|
|
|
|
|
|
<text>台板</text>
|
|
|
|
|
|
<switch :checked="tableMode" @change="tableMode = $event.detail.value" color="#007aff" />
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 对局记录区域 -->
|
|
|
|
|
|
<view class="game-record">
|
|
|
|
|
|
<view class="record-title">
|
|
|
|
|
|
对局记录
|
|
|
|
|
|
<text class="hint">点击对局分数进行修改</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 用户信息区域 -->
|
|
|
|
|
|
<view class="user-section">
|
|
|
|
|
|
<text class="user-hint">点击自己头像编辑用户头像和昵称~</text>
|
|
|
|
|
|
<view class="user-info" @click="editUserInfo">
|
|
|
|
|
|
<image class="user-avatar" :src="currentUser.avatar" mode="aspectFill"></image>
|
|
|
|
|
|
<view class="user-details">
|
|
|
|
|
|
<view class="user-name">
|
|
|
|
|
|
{{ currentUser.name }}
|
|
|
|
|
|
<text class="self-tag">自己</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 玩家列表 -->
|
|
|
|
|
|
<view class="players-section">
|
|
|
|
|
|
<view class="section-header">
|
|
|
|
|
|
<text class="header-title">玩家</text>
|
|
|
|
|
|
<text class="player-count">({{ players.length }}位)</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
<!-- 玩家表格(表头在左侧) -->
|
|
|
|
|
|
<view class="players-table-container vertical">
|
|
|
|
|
|
<view class="players-table vertical">
|
|
|
|
|
|
<!-- 表头行 -->
|
|
|
|
|
|
<view class="table-row header-row">
|
|
|
|
|
|
<!-- 固定表头:玩家 -->
|
|
|
|
|
|
<view class="header-cell player-column">玩家</view>
|
|
|
|
|
|
<!-- 每个玩家作为一列 -->
|
|
|
|
|
|
<view v-for="(player, index) in displayPlayers" :key="player.id" class="data-cell">
|
|
|
|
|
|
<view class="player-info">
|
|
|
|
|
|
<image :src="player.avatar" mode="aspectFill"></image>
|
|
|
|
|
|
<text>{{ player.name }}</text>
|
|
|
|
|
|
</view>
|
2025-11-11 17:07:13 +08:00
|
|
|
|
</view>
|
2025-11-24 16:01:45 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 总分行 -->
|
|
|
|
|
|
<view class="table-row">
|
|
|
|
|
|
<view class="header-cell score-column">总分</view>
|
|
|
|
|
|
<view v-for="(player, index) in displayPlayers" :key="player.id" class="data-cell score-display" >
|
2025-11-11 17:07:13 +08:00
|
|
|
|
{{ player.score }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-24 16:01:45 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 每局分数行 -->
|
|
|
|
|
|
<view v-for="(round, roundIndex) in rounds" :key="round" class="table-row">
|
|
|
|
|
|
<view class="header-cell score-column">第{{ round }}局</view>
|
|
|
|
|
|
<view @click="editScore(index)" v-for="(player, playerIndex) in displayPlayers" :key="player.id" class="data-cell score-display">
|
|
|
|
|
|
{{ player.roundScores[roundIndex] || 0 }}
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-11 17:07:13 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-24 16:01:45 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
<!-- 底部操作按钮 -->
|
|
|
|
|
|
<view class="bottom-buttons">
|
|
|
|
|
|
<button class="start-btn" type="primary" @click="startScoring">开局计分</button>
|
|
|
|
|
|
<button class="settle-btn" type="default" @click="settleRoom">结算房间</button>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
2025-11-24 16:01:45 +08:00
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
2025-11-24 16:01:45 +08:00
|
|
|
|
import { ref, computed, onMounted, onUnmounted, toRaw } from 'vue'
|
2025-12-09 10:54:56 +08:00
|
|
|
|
import { GET,POST,PUT } from '../../../utils/request'
|
2025-11-24 16:01:45 +08:00
|
|
|
|
import { BASE_URL } from '../../../utils/CommonValues.js';
|
2025-12-09 10:54:56 +08:00
|
|
|
|
const roomuser=ref({
|
|
|
|
|
|
roomId: '',
|
|
|
|
|
|
userId: '',
|
|
|
|
|
|
score:'',
|
|
|
|
|
|
playerType:'0',
|
|
|
|
|
|
nickName:'',
|
|
|
|
|
|
avatar:''
|
|
|
|
|
|
})
|
2025-11-24 16:01:45 +08:00
|
|
|
|
const res=ref(null)
|
2025-12-09 10:54:56 +08:00
|
|
|
|
const scoreuser=ref({
|
|
|
|
|
|
openId: '',
|
|
|
|
|
|
nickName: '',
|
|
|
|
|
|
avatar: 'scoring\static\avatar14.png'
|
|
|
|
|
|
})
|
|
|
|
|
|
const room=ref({
|
|
|
|
|
|
createUser:'1',
|
|
|
|
|
|
odds:1,
|
|
|
|
|
|
room_status:0,
|
|
|
|
|
|
bossId:'1',
|
|
|
|
|
|
roomName:'',
|
|
|
|
|
|
})
|
|
|
|
|
|
const detailscore=ref({
|
|
|
|
|
|
roomId: '',
|
|
|
|
|
|
userId: '',
|
|
|
|
|
|
score:'',
|
|
|
|
|
|
gameTime:'',
|
|
|
|
|
|
detailType:'0',
|
|
|
|
|
|
|
|
|
|
|
|
})
|
2025-11-24 16:01:45 +08:00
|
|
|
|
|
|
|
|
|
|
const getuserinfo =()=>{
|
2025-12-09 10:54:56 +08:00
|
|
|
|
// 错误1:GET参数后多了多余逗号 → 已删除
|
|
|
|
|
|
GET('/score/info/list',null).then(res=>{
|
2025-11-24 16:01:45 +08:00
|
|
|
|
console.log('获取用户信息成功:', res.data)
|
|
|
|
|
|
|
|
|
|
|
|
// 检查API返回数据结构
|
|
|
|
|
|
if(res.data && res.data.code === 200 && Array.isArray(res.data.rows)) {
|
|
|
|
|
|
const userList = res.data.rows;
|
|
|
|
|
|
|
|
|
|
|
|
// 清空现有的玩家列表(保留自己)
|
|
|
|
|
|
const selfPlayer = players.value.find(p => p.id === 'self');
|
|
|
|
|
|
players.value = selfPlayer ? [selfPlayer] : [];
|
|
|
|
|
|
|
|
|
|
|
|
// 将API返回的用户信息添加到玩家列表
|
|
|
|
|
|
userList.forEach(user => {
|
|
|
|
|
|
if(user.nickName) {
|
|
|
|
|
|
// 处理头像URL:如果是相对路径则与BASE_URL拼接
|
|
|
|
|
|
let avatarUrl = user.avatars;
|
|
|
|
|
|
if (avatarUrl) {
|
|
|
|
|
|
// 检查是否是相对路径(以/开头)
|
|
|
|
|
|
if (avatarUrl.startsWith('/')) {
|
|
|
|
|
|
avatarUrl = `${BASE_URL}${avatarUrl}`;
|
|
|
|
|
|
} else if (!avatarUrl.startsWith('http://') && !avatarUrl.startsWith('https://')) {
|
|
|
|
|
|
// 不是绝对URL也不是以/开头的相对路径,拼接完整路径
|
|
|
|
|
|
avatarUrl = `${BASE_URL}/${avatarUrl}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 如果没有头像则使用默认头像
|
|
|
|
|
|
avatarUrl = '/static/avatar14.png';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const newPlayer = {
|
2025-12-09 10:54:56 +08:00
|
|
|
|
id: user.userId, // 使用后端返回的userId作为玩家id
|
2025-11-24 16:01:45 +08:00
|
|
|
|
name: user.nickName, // 使用API返回的nickName作为玩家名称
|
|
|
|
|
|
avatar: avatarUrl, // 使用处理后的头像URL
|
|
|
|
|
|
score: 0,
|
2025-12-09 10:54:56 +08:00
|
|
|
|
roundScores: [],
|
|
|
|
|
|
roomId: roomId.value // 当前房间ID
|
2025-11-24 16:01:45 +08:00
|
|
|
|
};
|
|
|
|
|
|
players.value.push(newPlayer);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log('玩家列表更新完成:', players.value);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `成功添加${userList.length}位玩家`,
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('API返回数据结构异常:', res.data);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '获取玩家信息失败,数据结构异常',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}).catch(err=>{
|
|
|
|
|
|
console.error('获取用户信息失败:', err);
|
|
|
|
|
|
// 使用request.js中提供的友好错误信息
|
|
|
|
|
|
const errorMsg = err.userFriendlyMsg || '获取玩家信息失败';
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: errorMsg,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
duration: 2000
|
|
|
|
|
|
});
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-12-09 10:54:56 +08:00
|
|
|
|
const UserId=ref('')
|
|
|
|
|
|
const postuserinfo = () => {
|
|
|
|
|
|
POST('/score/info', scoreuser.value).then(r => {
|
|
|
|
|
|
console.log('用户信息上传成功:', r);
|
|
|
|
|
|
UserId.value = r.data.data.userId;
|
|
|
|
|
|
console.log('用户ID:', UserId.value);
|
|
|
|
|
|
room.value.createUser = UserId.value;
|
|
|
|
|
|
room.value.bossId = UserId.value;
|
|
|
|
|
|
postroom();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有临时玩家ID,更新到players数组中
|
|
|
|
|
|
if (tempPlayerId.value) {
|
|
|
|
|
|
const playerIndex = players.value.findIndex(p => p.id === tempPlayerId.value)
|
|
|
|
|
|
if (playerIndex !== -1) {
|
|
|
|
|
|
// 更新玩家的id为真实的用户ID
|
|
|
|
|
|
players.value[playerIndex].id = UserId.value
|
|
|
|
|
|
// 清空临时ID
|
|
|
|
|
|
tempPlayerId.value = ''
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '用户信息上传成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('用户信息上传失败:', err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '用户信息上传失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
// 清空临时ID,避免影响后续操作
|
|
|
|
|
|
tempPlayerId.value = ''
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
// 全局房间ID变量,从本地存储恢复
|
|
|
|
|
|
const roomId=ref(uni.getStorageSync('roomId') || '')
|
|
|
|
|
|
const postroom = () => {
|
|
|
|
|
|
POST('/score/room', room.value).then(r => {
|
|
|
|
|
|
console.log('房间信息上传成功:', r);
|
|
|
|
|
|
// 检查API响应结构
|
|
|
|
|
|
console.log('API响应数据:', r.data);
|
|
|
|
|
|
const receivedRoomId = r.data.data.roomId || '';
|
|
|
|
|
|
console.log('房间ID:', receivedRoomId);
|
|
|
|
|
|
roomId.value = receivedRoomId;
|
|
|
|
|
|
// 保存roomId到本地存储
|
|
|
|
|
|
uni.setStorageSync('roomId', receivedRoomId);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新所有玩家的roomId
|
|
|
|
|
|
players.value.forEach(player => {
|
|
|
|
|
|
player.roomId = receivedRoomId
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
postroomuser();
|
|
|
|
|
|
|
|
|
|
|
|
// 为每个玩家调用postroomdetail(即postdetailscore)函数,提交玩家与房间的关联信息
|
|
|
|
|
|
players.value.forEach(player => {
|
|
|
|
|
|
// 创建玩家与房间关联的详细数据
|
|
|
|
|
|
const playerRoomDetail = {
|
|
|
|
|
|
roomId: receivedRoomId,
|
|
|
|
|
|
userId: player.id,
|
|
|
|
|
|
userName: player.name,
|
|
|
|
|
|
userAvatar: player.avatar,
|
|
|
|
|
|
score: player.score
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 调用postdetailscore函数提交数据
|
|
|
|
|
|
postdetailscore(playerRoomDetail);
|
|
|
|
|
|
console.log('玩家与房间关联信息上传成功:', playerRoomDetail);
|
|
|
|
|
|
console.log('房间ID:', roomId.value);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间信息上传成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('房间信息上传失败:', err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间信息上传失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
const postroomuser = () => {
|
|
|
|
|
|
roomuser.value.roomId = roomId.value;
|
|
|
|
|
|
roomuser.value.userId = UserId.value;
|
|
|
|
|
|
roomuser.value.nickName = scoreuser.value.nickName;
|
|
|
|
|
|
POST('/score/player', roomuser.value).then(r => {
|
|
|
|
|
|
console.log('房间用户信息上传成功:', r);
|
|
|
|
|
|
const roomUserId = r.data.data.roomUserId;
|
|
|
|
|
|
console.log('获取到的roomUserId:', roomUserId);
|
|
|
|
|
|
uni.setStorageSync('roomUserId', roomUserId);
|
|
|
|
|
|
roomuser.value.roomUserId = roomUserId;
|
|
|
|
|
|
// 同时更新putscore对象的roomUserId属性,确保数据一致性
|
|
|
|
|
|
putscore.value.roomUserId = Number(roomUserId);
|
|
|
|
|
|
console.log('更新后的putscore对象:', putscore.value);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户信息上传成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('房间用户信息上传失败:', err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户信息上传失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
const postdetailscore = (scoreData) => {
|
|
|
|
|
|
const dataToSubmit = scoreData || detailscore.value;
|
|
|
|
|
|
console.log('提交数据:', dataToSubmit);
|
|
|
|
|
|
console.log('房间ID:', roomId.value);
|
|
|
|
|
|
if (!dataToSubmit.roomId) {
|
|
|
|
|
|
dataToSubmit.roomId = roomId.value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
POST('/score/roomdetail', dataToSubmit).then(r => {
|
|
|
|
|
|
console.log('房间用户详细信息上传成功:', r);
|
|
|
|
|
|
if (!scoreData || dataToSubmit.userId === UserId.value || dataToSubmit.userId === 'self') {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户详细信息上传成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('房间用户详细信息上传失败:', err);
|
|
|
|
|
|
if (!scoreData || dataToSubmit.userId === UserId.value || dataToSubmit.userId === 'self') {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户详细信息上传失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
const putscore=ref({
|
|
|
|
|
|
roomUserId:0,
|
|
|
|
|
|
allscore:0
|
|
|
|
|
|
})
|
|
|
|
|
|
const putroomuser = () => {
|
|
|
|
|
|
console.log('开始执行putroomuser函数');
|
|
|
|
|
|
const roomUserId = uni.getStorageSync('roomUserId');
|
|
|
|
|
|
console.log('从本地存储获取的roomUserId:', roomUserId);
|
|
|
|
|
|
|
|
|
|
|
|
// 从players数组中获取当前用户的总分
|
|
|
|
|
|
console.log('当前UserId.value:', UserId.value);
|
|
|
|
|
|
console.log('players数组内容:', players.value);
|
|
|
|
|
|
|
|
|
|
|
|
const currentPlayer = players.value.find(p => p.id === UserId.value);
|
|
|
|
|
|
if (currentPlayer) {
|
|
|
|
|
|
putscore.value.allscore = currentPlayer.score;
|
|
|
|
|
|
console.log('获取到的当前用户总分:', currentPlayer.score);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.error('未找到当前用户的总分数据');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置roomUserId,并转换为数字类型
|
|
|
|
|
|
putscore.value.roomUserId = Number(roomUserId);
|
|
|
|
|
|
console.log('准备发送的putscore数据:', putscore.value);
|
|
|
|
|
|
|
|
|
|
|
|
PUT('/score/player', putscore.value).then(r => {
|
|
|
|
|
|
console.log('房间用户信息上传成功响应:', r);
|
|
|
|
|
|
console.log('响应数据:', r.data);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户信息上传成功',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
});
|
|
|
|
|
|
}).catch(err => {
|
|
|
|
|
|
console.error('房间用户信息上传失败:', err);
|
|
|
|
|
|
console.error('错误详情:', err.errMsg || err);
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '房间用户信息上传失败',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 状态管理
|
|
|
|
|
|
const voiceBroadcast = ref(false)
|
|
|
|
|
|
const tableMode = ref(false)
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 当前用户信息 - 从本地存储获取
|
|
|
|
|
|
const storedUserInfo = uni.getStorageSync('userInfo');
|
2025-11-11 17:07:13 +08:00
|
|
|
|
const currentUser = ref({
|
2025-12-09 10:54:56 +08:00
|
|
|
|
id:self,
|
|
|
|
|
|
name: storedUserInfo?.name||'acd' ,
|
2025-11-24 16:01:45 +08:00
|
|
|
|
avatar: storedUserInfo?.avatar ||'/static/logo.png' })
|
|
|
|
|
|
|
|
|
|
|
|
// 局数信息
|
|
|
|
|
|
const rounds = ref([]) // 存储每局信息,每个元素是局数编号
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 玩家列表(初始包含自己)
|
|
|
|
|
|
const players = ref([
|
|
|
|
|
|
{
|
2025-12-09 10:54:56 +08:00
|
|
|
|
id:self,
|
|
|
|
|
|
name: currentUser.value.name ||'acd',
|
2025-11-24 16:01:45 +08:00
|
|
|
|
avatar: currentUser.value.avatar||'/static/logo.png',
|
|
|
|
|
|
score: 0,
|
2025-12-09 10:54:56 +08:00
|
|
|
|
roundScores: [], // 存储每局的分数
|
|
|
|
|
|
roomId: '' // 当前房间ID
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
// 台板玩家对象
|
|
|
|
|
|
const tablePlayer = {
|
|
|
|
|
|
id: 'table',
|
|
|
|
|
|
name: '台板',
|
|
|
|
|
|
avatar: '/static/robot.png',
|
2025-11-24 16:01:45 +08:00
|
|
|
|
score: 0,
|
|
|
|
|
|
roundScores: [] // 存储每局的分数
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算属性:动态返回包含或不包含台板玩家的列表
|
|
|
|
|
|
const displayPlayers = computed(() => {
|
|
|
|
|
|
if (tableMode.value) {
|
|
|
|
|
|
// 检查台板玩家是否已存在,避免重复添加
|
|
|
|
|
|
const hasTablePlayer = players.value.some(player => player.id === 'table')
|
|
|
|
|
|
if (hasTablePlayer) {
|
|
|
|
|
|
return players.value
|
|
|
|
|
|
}
|
|
|
|
|
|
// 添加台板玩家
|
|
|
|
|
|
return [...players.value, tablePlayer]
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 移除台板玩家
|
|
|
|
|
|
return players.value.filter(player => player.id !== 'table')
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
2025-12-09 10:54:56 +08:00
|
|
|
|
// 保存当前正在添加的玩家临时ID
|
|
|
|
|
|
const tempPlayerId = ref('')
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 添加玩家
|
|
|
|
|
|
const addPlayer = () => {
|
|
|
|
|
|
console.log('添加玩家')
|
|
|
|
|
|
|
|
|
|
|
|
// 生成默认玩家名
|
|
|
|
|
|
const defaultPlayerName = '请输入玩家名称'
|
|
|
|
|
|
|
|
|
|
|
|
// 弹出对话框让用户输入玩家名称
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '添加玩家',
|
|
|
|
|
|
editable: true,
|
|
|
|
|
|
placeholderText: defaultPlayerName,
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
confirmText: '添加',
|
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
|
autofocus: true, // 微信小程序下自动聚焦输入框
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
// 获取用户输入的名称,如果为空则使用默认名称
|
|
|
|
|
|
const playerName = res.content && res.content.trim() !== '' ? res.content.trim() : defaultPlayerName
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新玩家
|
|
|
|
|
|
const newPlayer = {
|
|
|
|
|
|
id: `player_${Date.now()}`,
|
|
|
|
|
|
name: playerName,
|
2025-11-24 16:01:45 +08:00
|
|
|
|
avatar: '/static/avatar14.png',
|
|
|
|
|
|
score: 0,
|
|
|
|
|
|
roundScores: [] // 存储每局的分数
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
2025-12-09 10:54:56 +08:00
|
|
|
|
scoreuser.value.openId=newPlayer.id
|
|
|
|
|
|
scoreuser.value.nickName=newPlayer.name
|
|
|
|
|
|
// 保存临时ID,用于后续更新真实ID
|
|
|
|
|
|
tempPlayerId.value = newPlayer.id
|
|
|
|
|
|
postuserinfo()
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 添加到玩家列表
|
|
|
|
|
|
players.value.push(newPlayer)
|
|
|
|
|
|
|
|
|
|
|
|
// 语音提示或普通提示(如果开启)
|
|
|
|
|
|
if (voiceBroadcast.value) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `已添加玩家 ${newPlayer.name}`,
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
// 这里可以添加语音播报逻辑
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `已添加玩家 ${newPlayer.name}`,
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('添加玩家失败:', err)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 转让计分员
|
|
|
|
|
|
const transferScorer = () => {
|
|
|
|
|
|
console.log('转让计分员')
|
|
|
|
|
|
|
|
|
|
|
|
// 显示提示对话框
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '提示',
|
|
|
|
|
|
content: '房间内暂无扫码或分享加入房间的玩家,无法转让计分员。',
|
|
|
|
|
|
showCancel: false,
|
|
|
|
|
|
// #ifdef MP-WEIXIN
|
|
|
|
|
|
confirmText: '确定',
|
|
|
|
|
|
// #endif
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
console.log('用户确认提示')
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('显示提示失败:', err)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 编辑用户信息 - 跳转到change页面
|
|
|
|
|
|
const editUserInfo = () => {
|
|
|
|
|
|
console.log('跳转到用户信息编辑页面')
|
|
|
|
|
|
|
|
|
|
|
|
// 跳转到change页面,并传递当前用户信息
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: `/pages/index/singleplay/change?userData=${encodeURIComponent(JSON.stringify(currentUser.value))}`
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新用户数据 - 从change页面返回时调用
|
|
|
|
|
|
const updateUserData = (updatedUser) => {
|
|
|
|
|
|
console.log('更新用户数据', updatedUser)
|
|
|
|
|
|
|
|
|
|
|
|
// 更新当前用户信息
|
|
|
|
|
|
currentUser.value = { ...updatedUser }
|
|
|
|
|
|
|
|
|
|
|
|
// 更新玩家列表中的用户信息
|
|
|
|
|
|
const selfPlayerIndex = players.value.findIndex(p => p.id === 'self')
|
|
|
|
|
|
if (selfPlayerIndex !== -1) {
|
|
|
|
|
|
players.value[selfPlayerIndex] = {
|
|
|
|
|
|
...players.value[selfPlayerIndex],
|
|
|
|
|
|
name: updatedUser.name,
|
|
|
|
|
|
avatar: updatedUser.avatar
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 将更新后的用户信息保存到本地存储
|
|
|
|
|
|
uni.setStorageSync('userInfo', updatedUser)
|
|
|
|
|
|
uni.setStorageSync('currentUserInfo', updatedUser)
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 编辑分数 - 点击分数时调用
|
|
|
|
|
|
const editScore = (playerIndex) => {
|
|
|
|
|
|
console.log('编辑分数,玩家索引:', playerIndex)
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前选中的玩家
|
|
|
|
|
|
const selectedPlayer = displayPlayers.value[playerIndex]
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否有局数记录
|
|
|
|
|
|
if (rounds.value.length === 0) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '暂无局数记录,无法编辑分数',
|
|
|
|
|
|
icon: 'none'
|
2025-11-11 17:07:13 +08:00
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 获取当前局数
|
|
|
|
|
|
const currentRound = rounds.value.length
|
|
|
|
|
|
|
|
|
|
|
|
// 准备要传递的玩家数据
|
|
|
|
|
|
const playersToPass = [...displayPlayers.value]
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到临时存储,用于页面间数据传递
|
|
|
|
|
|
uni.setStorageSync('currentPlayers', JSON.stringify(playersToPass))
|
|
|
|
|
|
// 保存当前局数
|
|
|
|
|
|
uni.setStorageSync('currentRound', currentRound)
|
|
|
|
|
|
// 保存选中的玩家索引
|
|
|
|
|
|
uni.setStorageSync('selectedPlayerIndex', playerIndex)
|
|
|
|
|
|
|
|
|
|
|
|
// 跳转到计分页面进行分数编辑
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: '/pages/index/singleplay/scoring'
|
2025-11-11 17:07:13 +08:00
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开局计分
|
|
|
|
|
|
const startScoring = () => {
|
|
|
|
|
|
console.log('开局计分')
|
2025-12-09 10:54:56 +08:00
|
|
|
|
room.value.roomStatus=1
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 检查是否有足够的玩家(至少需要2个玩家才能开始计分)
|
|
|
|
|
|
if (displayPlayers.value.length < 2) {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '玩家数不超过两个人时无法点击进行开始计分',
|
|
|
|
|
|
icon: 'none'
|
|
|
|
|
|
})
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 新增一局
|
|
|
|
|
|
const newRound = rounds.value.length + 1
|
|
|
|
|
|
rounds.value.push(newRound)
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 准备要传递的玩家数据
|
|
|
|
|
|
const playersToPass = [...displayPlayers.value]
|
|
|
|
|
|
|
|
|
|
|
|
// 保存到临时存储,用于页面间数据传递
|
|
|
|
|
|
uni.setStorageSync('currentPlayers', JSON.stringify(playersToPass))
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 保存当前局数
|
|
|
|
|
|
uni.setStorageSync('currentRound', newRound)
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 跳转到计分页面
|
|
|
|
|
|
uni.navigateTo({
|
|
|
|
|
|
url: '/pages/index/singleplay/scoring'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 结算房间
|
|
|
|
|
|
const settleRoom = () => {
|
|
|
|
|
|
console.log('结算房间')
|
|
|
|
|
|
|
|
|
|
|
|
// 显示结算结果,使用displayPlayers确保包含台板玩家
|
|
|
|
|
|
let result = '结算结果:\n'
|
|
|
|
|
|
displayPlayers.value.forEach(player => {
|
|
|
|
|
|
result += `${player.name}: ${player.score}分\n`
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
uni.showModal({
|
|
|
|
|
|
title: '结算',
|
|
|
|
|
|
content: result,
|
|
|
|
|
|
confirmText: '保存记录',
|
|
|
|
|
|
cancelText: '关闭',
|
|
|
|
|
|
success: (res) => {
|
|
|
|
|
|
if (res.confirm) {
|
|
|
|
|
|
// 这里可以保存记录到数据库
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: '记录已保存',
|
|
|
|
|
|
icon: 'success'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
2025-12-09 10:54:56 +08:00
|
|
|
|
const number = ref('')
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 生命周期
|
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
|
console.log('单人模式页面加载完成')
|
|
|
|
|
|
// 可以在这里初始化数据或加载用户信息
|
2025-11-24 16:01:45 +08:00
|
|
|
|
getuserinfo();
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
2025-12-09 10:54:56 +08:00
|
|
|
|
// 生成四位数字
|
|
|
|
|
|
number.value = Math.floor(1000 + Math.random() * 9000).toString()
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 动态设置导航栏标题
|
2025-12-09 10:54:56 +08:00
|
|
|
|
const pageTitle = `单人 - ${number.value}号房间`;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
uni.setNavigationBarTitle({
|
2025-12-09 10:54:56 +08:00
|
|
|
|
title: pageTitle
|
2025-11-11 17:07:13 +08:00
|
|
|
|
})
|
2025-12-09 10:54:56 +08:00
|
|
|
|
room.value.roomName = pageTitle
|
|
|
|
|
|
|
|
|
|
|
|
// 更新当前用户的roomId
|
|
|
|
|
|
const selfPlayer = players.value.find(p => p.id === 'self')
|
|
|
|
|
|
if (selfPlayer) {
|
|
|
|
|
|
selfPlayer.roomId = roomId.value
|
|
|
|
|
|
}
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
|
|
|
|
|
// 监听页面返回事件,用于接收从计分页面传回的更新后的分数
|
|
|
|
|
|
const updateListener = () => {
|
|
|
|
|
|
// 尝试获取更新后的玩家数据
|
|
|
|
|
|
const updatedPlayers = uni.getStorageSync('updatedPlayers')
|
|
|
|
|
|
if (updatedPlayers) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const parsedPlayers = JSON.parse(updatedPlayers)
|
|
|
|
|
|
console.log('收到更新的玩家数据:', parsedPlayers)
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 获取当前局数
|
|
|
|
|
|
const currentRound = uni.getStorageSync('currentRound') || 1
|
|
|
|
|
|
const roundIndex = currentRound - 1
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 更新玩家列表中的分数
|
|
|
|
|
|
parsedPlayers.forEach(updatedPlayer => {
|
|
|
|
|
|
// 查找对应的玩家
|
|
|
|
|
|
const playerIndex = players.value.findIndex(p => p.id === updatedPlayer.id)
|
|
|
|
|
|
if (playerIndex !== -1) {
|
2025-11-24 16:01:45 +08:00
|
|
|
|
if (players.value[playerIndex].roundScores.length <= roundIndex) {
|
|
|
|
|
|
players.value[playerIndex].roundScores.length = roundIndex + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
// 保存当前局的分数
|
|
|
|
|
|
players.value[playerIndex].roundScores[roundIndex] = updatedPlayer.score
|
|
|
|
|
|
// 计算总分:所有局分数的总和
|
|
|
|
|
|
players.value[playerIndex].score = players.value[playerIndex].roundScores.reduce((sum, score) => sum + (score || 0), 0)
|
2025-12-09 10:54:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 为每个玩家设置单局分数和局次,并提交到后端
|
|
|
|
|
|
// 创建临时的detailscore对象,避免多个玩家数据互相覆盖
|
|
|
|
|
|
const tempDetailScore = {
|
|
|
|
|
|
roomId: players.value[playerIndex].roomId, // 当前玩家的roomId
|
|
|
|
|
|
userId: players.value[playerIndex].id, // 当前玩家ID
|
|
|
|
|
|
score: updatedPlayer.score, // 当前局的分数
|
|
|
|
|
|
gameTime: currentRound, // 当前局次
|
|
|
|
|
|
detailType: '0'
|
|
|
|
|
|
}
|
|
|
|
|
|
postdetailscore(tempDetailScore)
|
|
|
|
|
|
putroomuser()
|
2025-11-11 17:07:13 +08:00
|
|
|
|
} else if (updatedPlayer.id === 'table') {
|
2025-11-24 16:01:45 +08:00
|
|
|
|
if (tablePlayer.roundScores.length <= roundIndex) {
|
|
|
|
|
|
tablePlayer.roundScores.length = roundIndex + 1
|
|
|
|
|
|
}
|
|
|
|
|
|
tablePlayer.roundScores[roundIndex] = updatedPlayer.score
|
|
|
|
|
|
// 计算总分:所有局分数的总和
|
|
|
|
|
|
tablePlayer.score = tablePlayer.roundScores.reduce((sum, score) => sum + (score || 0), 0)
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
// 清除临时存储的数据
|
|
|
|
|
|
uni.removeStorageSync('updatedPlayers')
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('解析更新的玩家数据失败:', error)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 监听页面显示事件
|
|
|
|
|
|
uni.$on('updatePlayers', updateListener)
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
// 监听用户数据更新事件(来自change页面)
|
|
|
|
|
|
const userDataListener = (updatedUser) => {
|
|
|
|
|
|
updateUserData(updatedUser)
|
|
|
|
|
|
}
|
|
|
|
|
|
uni.$on('userDataUpdated', userDataListener)
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
// 监听页面显示生命周期
|
|
|
|
|
|
uni.onShow(() => {
|
|
|
|
|
|
updateListener()
|
2025-11-24 16:01:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 从本地存储获取最新的用户信息
|
|
|
|
|
|
try {
|
|
|
|
|
|
const storedUserInfo = uni.getStorageSync('userInfo');
|
|
|
|
|
|
if (storedUserInfo) {
|
|
|
|
|
|
console.log('从本地存储加载用户信息:', storedUserInfo);
|
|
|
|
|
|
// 更新当前用户信息
|
|
|
|
|
|
currentUser.value = { ...storedUserInfo };
|
|
|
|
|
|
|
|
|
|
|
|
// 更新玩家列表中的用户信息
|
|
|
|
|
|
const selfPlayerIndex = players.value.findIndex(p => p.id === 'self');
|
|
|
|
|
|
if (selfPlayerIndex !== -1) {
|
|
|
|
|
|
players.value[selfPlayerIndex] = {
|
|
|
|
|
|
...players.value[selfPlayerIndex],
|
|
|
|
|
|
name: storedUserInfo.name,
|
|
|
|
|
|
avatar: storedUserInfo.avatar
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('从本地存储获取用户信息失败:', error);
|
|
|
|
|
|
}
|
2025-11-11 17:07:13 +08:00
|
|
|
|
})
|
2025-12-09 10:54:56 +08:00
|
|
|
|
}); // 补充onMounted的闭合括号+花括号 → 原代码此处也缺失
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
onUnmounted(() => {
|
|
|
|
|
|
// 移除事件监听器
|
|
|
|
|
|
uni.$off('updatePlayers');
|
|
|
|
|
|
uni.$off('userDataUpdated');
|
2025-12-09 10:54:56 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script><style lang="less" scoped>
|
2025-11-11 17:07:13 +08:00
|
|
|
|
.singleplay {
|
|
|
|
|
|
width: 750rpx;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background-color: #f8f8f8;
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
|
|
|
|
/* #ifdef MP-WEIXIN */
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
/* #endif */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 顶部功能区 */
|
|
|
|
|
|
.top-functions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
//padding: 10rpx 15rpx;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
|
|
|
|
|
|
.function-btn {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 5rpx;
|
|
|
|
|
|
padding: 8rpx 8rpx;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
margin: 0 8rpx;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 图标样式
|
|
|
|
|
|
.btn-icon {
|
|
|
|
|
|
width: 30rpx;
|
|
|
|
|
|
height: 30rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 文本样式
|
|
|
|
|
|
text {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 微信小程序特有点击反馈
|
|
|
|
|
|
/* #ifdef MP-WEIXIN */
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
opacity: 0.8;
|
|
|
|
|
|
transform: scale(0.95);
|
|
|
|
|
|
}
|
|
|
|
|
|
/* #endif */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.switch-group {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 6rpx;
|
|
|
|
|
|
margin: 0 8rpx;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
|
|
|
|
|
|
text {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch {
|
|
|
|
|
|
transform: scale(0.75);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 对局记录区域 */
|
|
|
|
|
|
.game-record {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-radius: 20rpx;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
padding-bottom: 20rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.record-title {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
margin-bottom: 10rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.hint {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
font-weight: normal;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
margin-left: 10rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 用户信息区域 */
|
|
|
|
|
|
.user-section {
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.user-hint {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #fa5d5d;
|
|
|
|
|
|
margin-bottom: 15rpx;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 15rpx;
|
|
|
|
|
|
padding: 10rpx;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
background-color: #f0f8ff;
|
|
|
|
|
|
|
|
|
|
|
|
.user-avatar {
|
|
|
|
|
|
width: 80rpx;
|
|
|
|
|
|
height: 80rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.user-details {
|
|
|
|
|
|
.user-name {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
|
|
.self-tag {
|
|
|
|
|
|
background-color: #007aff;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-size: 20rpx;
|
|
|
|
|
|
padding: 2rpx 10rpx;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
margin-left: 8rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 玩家列表区域 */
|
|
|
|
|
|
.players-section {
|
|
|
|
|
|
.section-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
align-items: center;
|
2025-11-24 16:01:45 +08:00
|
|
|
|
justify-content: center;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
margin-bottom: 15rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.header-title {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #333;
|
2025-11-24 16:01:45 +08:00
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.player-count {
|
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
margin-left: 10rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
/* 玩家表格容器 - 实现横向滚动 */
|
|
|
|
|
|
.players-table-container {
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
-webkit-overflow-scrolling: touch;
|
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
|
border: 1rpx solid #e0e0e0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 垂直表格容器 - 实现垂直滚动和横向滑动 */
|
|
|
|
|
|
.players-table-container.vertical {
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
max-height: 500rpx;
|
|
|
|
|
|
-webkit-overflow-scrolling: touch; /* 优化移动端滚动体验 */
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-11 17:07:13 +08:00
|
|
|
|
/* 玩家表格 */
|
|
|
|
|
|
.players-table {
|
2025-11-24 16:01:45 +08:00
|
|
|
|
min-width: 100%;
|
|
|
|
|
|
overflow: visible;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 垂直表格样式 */
|
|
|
|
|
|
.players-table.vertical {
|
|
|
|
|
|
.table-row {
|
2025-11-11 17:07:13 +08:00
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
border-bottom: 1rpx solid #e0e0e0;
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
&:last-child {
|
|
|
|
|
|
border-bottom: none;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
2025-11-24 16:01:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-row {
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.header-cell {
|
|
|
|
|
|
width: 150rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
padding: 15rpx;
|
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
border-right: 1rpx solid #e0e0e0;
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.player-column {
|
|
|
|
|
|
justify-content: flex-start;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.score-column {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.data-cell {
|
|
|
|
|
|
min-width: 120rpx;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
padding: 15rpx;
|
|
|
|
|
|
border-right: 1rpx solid #e0e0e0;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
/* 最后一列不需要右边框 */
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
border-right: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.player-info {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
image {
|
|
|
|
|
|
width: 60rpx;
|
|
|
|
|
|
height: 60rpx;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
text {
|
|
|
|
|
|
font-size: 24rpx;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
color: #333;
|
|
|
|
|
|
text-align: center;
|
2025-11-24 16:01:45 +08:00
|
|
|
|
word-break: break-word;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-24 16:01:45 +08:00
|
|
|
|
.score-display {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #007aff;
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background-color: #f0f8ff;
|
2025-11-11 17:07:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 底部操作按钮 */
|
|
|
|
|
|
.bottom-buttons {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
/* #ifdef MP-WEIXIN */
|
|
|
|
|
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|
|
|
|
|
/* #endif */
|
|
|
|
|
|
|
|
|
|
|
|
.start-btn,
|
|
|
|
|
|
.settle-btn {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
height: 90rpx;
|
|
|
|
|
|
font-size: 32rpx;
|
|
|
|
|
|
line-height: 90rpx;
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.start-btn {
|
|
|
|
|
|
background-color: #007aff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.settle-btn {
|
|
|
|
|
|
border: 1rpx solid #007aff;
|
|
|
|
|
|
color: #007aff;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 适配不同屏幕尺寸 */
|
|
|
|
|
|
@media screen and (max-width: 375px) {
|
|
|
|
|
|
.singleplay {
|
|
|
|
|
|
padding: 15rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.top-functions {
|
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
|
|
|
|
|
|
|
.function-btn {
|
|
|
|
|
|
padding: 1rpx 1rpx;
|
|
|
|
|
|
|
|
|
|
|
|
text {
|
|
|
|
|
|
font-size: 22rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|