Files
1XJT/scoring/pages/single/single.vue
2025-12-01 12:13:03 +08:00

720 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="single">
<view class="single-lan">
<button @click="addplayer">
<uni-icons type="plus"></uni-icons>
<text>添加玩家</text>
</button>
<button @click="transfer">
<uni-icons type="person-filled"></uni-icons>
<text>转让计分员</text>
</button>
<view class="lan-switch">
<switch @change="" />
<text>语音播报</text>
</view>
<view class="lan-switch">
<switch @change="" />
<text>台版</text>
</view>
</view>
<view class="single-detail">
<text class="sing-detail-title">对局记录</text>
<text>点击对局分数进行修改</text>
</view>
<scroll-view class="single-score" scroll-x="true" >
<text style="color: red;" class="score-remind">
点击头像编辑自己的昵称和性别~
</text>
<view class="single-score-record">
<view class="tab-head">
<text class="tab-head-player">玩家</text>
<text class="tab-head-total">总分</text>
<view class="tab-head-detail" v-for="n in maxRounds" :key="n">
{{n}}
</view>
</view>
<view v-for="(item,index) in userScores" :key="item.userId" class="tab-body">
<view class="tab-body-player">
<image :src=item.avatars mode="widthFix"></image>
<text>{{item.nickName}}</text>
</view>
<view class="tab-total-score">
{{formatScore(item.totalScore)}}
</view>
<view v-for="detail in item.details" :key="detail.gameTime" class="round-score">
{{detail.detailScore}}
</view>
</view>
<!-- {{userScores}} -->
</view>
</scroll-view>
<view class="single-bottom">
<button
style="color: aliceblue;
background-color: rgb(55, 47, 172);"
@click="gotoNewPage1"
>
开局计分</button>
<button
@click="multiple"
>结算房间</button>
</view>
<l-popup v-model="isPopupVisible" :closeable="true">
<view class="popup-add">
<view class="tilte">
<text class="title">扫码加入房间</text>
</view>
<view class="line"></view>
<text class="small">邀请好友扫描下方二维码加入房间</text>
<image src="/static/logo.png" mode=""></image>
<button class="share">分享给好友邀请加入房间</button>
<button class="hand" @click="addvirtue">手动添加虚拟玩家</button>
</view>
</l-popup>
<l-popup v-model="isPopupVisible1" :closeable="true">
<view class="popup-add">
<view class="tilte">
<text class="title">提示</text>
</view>
<view class="line"></view>
<text class="small">房间内暂无扫码或分享加入房间的玩家暂时无法转让计分员</text>
<button @click="closetransfer">确定</button>
</view>
</l-popup>
<l-popup v-model="virtueplayer" :closeable="true">
<view class="popup-virtue">
<view class="tilte">
<text class="title">添加玩家</text>
</view>
<view class="line"></view>
<view class="lan-input">
<uni-easyinput v-model="newPlayerName" placeholder="请输入名称" style="width: 500rpx;" @confirm="confirmAddPlayer"></uni-easyinput>
</view>
<view class="lan-button">
<button @click="closevirtue">取消</button>
<button @click="confirmAddPlayer">确定</button>
</view>
</view>
</l-popup>
<l-popup v-model="isPopupVisible2" :closeable="true">
<view class="popup-virtue">
<view class="tilte">
<text class="title" style="font-weight: 600;">输入倍率快速结算</text>
</view>
<view class="line"></view>
<view class="lan-input">
<uni-easyinput v-model="oddvalue" placeholder="请输入倍率" style="width: 400rpx;"></uni-easyinput>
</view>
<view class="lan-button">
<button @click="closemultiple">取消</button>
<button @click="overmultiple">确定</button>
</view>
</view>
</l-popup>
<!-- 加载提示 -->
<uni-load-more v-if="isLoading" status="loading" />
</view>
</template>
<script setup>
import { ref, onMounted, computed} from 'vue';
import { GET, POST } from '../../utils/request';
import { onLoad } from '@dcloudio/uni-app';
import StaticValue from '@/utils/StaticValue.js';
//获取本地用户数据
const roomData = ref([]);
//加载动画
const isLoading = ref(false);
//添加玩家输入框
const newPlayerName = ref('');
//接收后端返回的表格数组
const userScores = ref([]);
//确认添加玩家按钮
const confirmAddPlayer = async () => {
//拿到本地用户所在的房间id
const response = await GET('/system/room/createUser/'+ roomData.value.userId);
//show信息
if(round.value < 2){
if (response.code === 200) {
uni.showToast({
title: '查询roomId成功',
icon: 'success'
});
const dataArray = response.data;
console.log('dataArray.roomId:', dataArray[0].roomId);
// 使用 trim() 去除前后空格
const trimmedName = newPlayerName.value.trim();
const userData = {
nickName: trimmedName, // 使用 trim() 处理后的名称
avatars: "https://q3.itc.cn/q_70/images03/20250110/1e71eecf56b34344bcae6a5b85c0bec2.jpeg",
openId: generateTenDigitRandom().toString(),
};
const userResponse = await POST('/system/score/user/add', userData);
if (userResponse.code === 200) {
// 关键修改正确获取后端返回的userId
const userId1 = userResponse.data.userId; // 从响应数据的data中获取
console.log('新创建的用户ID:', userId1);
// 2. 然后插入 score_room_user 表
const roomUserData = {
roomId: dataArray[0].roomId,
userId: userId1, // 使用后端返回的userId
totalScore: 0,
playerType: 'robot',
nickName: trimmedName,
avatars: "https://q3.itc.cn/q_70/images03/20250110/1e71eecf56b34344bcae6a5b85c0bec2.jpeg",
};
//插入room_user表中
const response = await POST('/system/score/room/user', roomUserData);
console.log("返回结果: ", response)
if (response.code === 200) {
// 2. 插入成功后立即刷新数据
fetchUserScores();
console.log('添加新玩家成功');
uni.showToast({
title: '添加成功',
icon: 'success'
});
virtueplayer.value = false;
}
}
}
}
else{
console.log("游戏已开始,不可添加新玩家:",round.value);
uni.showToast({
title: '游戏已开始',
icon: 'error'
});
virtueplayer.value = false;
}
}
// 生成10位随机数范围1000000000 - 9999999999
function generateTenDigitRandom() {
return Math.floor(Math.random() * 9000000000) + 1000000000;
}
// 计算最大局数(确保表头列数正确)
const maxRounds = computed(() => {
if (!userScores.value.length) return 0;
let max = 0;
userScores.value.forEach(user => {
if (user.details && user.details.length > 0) {
user.details.forEach(detail => {
if (detail.gameTime > max) max = detail.gameTime;
});
}
});
return max;
});
const round = computed(() => {
const rounds = maxRounds.value;
return isNaN(rounds) ? 0 : Math.max(0, rounds + 1);
});
// 分数格式化
const formatScore = (score) => {
return score > 0 ? `+${score}` : `${score}`;
};
// 获取分数数据的函数
const fetchUserScores = async () => {
try {
//拿到本地用户所在的房间id
const response2 = await GET('/system/room/createUser/'+ roomData.value.userId);
//show信息
const dataArray1 = response2.data;
console.log('获取分数数据房间号为:', dataArray1[0].roomId);
var roomId1 = dataArray1[0].roomId;
//加载详细数据
const response3 = await GET(`/system/score/room/user/user-details/${roomId1}`);
if (response3.code === 200) {
userScores.value = response3.data;
console.log('用户得分数据加载成功');
}
} catch (error) {
console.error('获取用户得分失败:', error);
}
};
onMounted(() => {
const getUserInfo = StaticValue.getUserInfo;
roomData.value = getUserInfo();
fetchUserScores();
reSubmitGet();
})
const reSubmitGet = async () => {
//拿到本地用户所在的房间id
const response2 = await GET('/system/room/createUser/'+ roomData.value.userId);
//show信息
const dataArray1 = response2.data;
console.log('当前房间号为:', dataArray1[0].roomId);
var roomId1 = dataArray1[0].roomId;
//再次发送get请求拿到当前roomId
const response4 = await GET('/system/score/room/user/list',{
roomId: roomId1,
userId: roomData.value.userId,
});
console.log("response4:",response4.rows.length);
if(response4.rows.length === 0)
{
const addlocaluser = await POST('/system/score/room/user',{
roomId: roomId1,
userId: roomData.value.userId,
totalScore: '0',
playerType: 'user',
nickName:'孤心',
avatars: 'https://img1.baidu.com/it/u=3612220943,2414740890&fm=253&app=138&f=JPEG?w=526&h=500',
})
console.log("addlocaluser:",addlocaluser);
fetchUserScores();
}
}
//跳转至user-detail
const gotoNewPage = () => {
wx.navigateTo({
url: '/pages/user-detail/user-detail'
})
}
//跳转至compute
const gotoNewPage1 = () => {
const roomUserData1 = ref(userScores);
const encodedPlayers = encodeURIComponent(JSON.stringify(roomUserData1.value));
const encodedRound = encodeURIComponent(JSON.stringify(round.value));
wx.navigateTo({
url: `/pages/compute/compute?players=${encodedPlayers}&round=${encodedRound}`
})
}
//添加玩家按钮弹窗
const isPopupVisible = ref(false);
const addplayer = ()=>{
isPopupVisible.value = true;
}
const closeplayer = ()=>{
isPopupVisible.value = false;
}
//添加虚拟玩家
const virtueplayer = ref(false);
const addvirtue = ()=>{
isPopupVisible.value = false;
virtueplayer.value = true;
}
const closevirtue = ()=>{
virtueplayer.value = false;
}
//转让计分员按钮弹窗
const isPopupVisible1 = ref(false);
const transfer = ()=>{
isPopupVisible1.value = true;
}
const closetransfer = ()=>{
isPopupVisible1.value = false;
}
//倍率结算按钮弹窗
const isPopupVisible2 = ref(false);
const multiple = ()=>{
oddvalue.value = undefined;
isPopupVisible2.value = true;
}
const closemultiple = ()=>{
isPopupVisible2.value = false;
}
//定义响应式变量odd
const oddvalue = ref();
//拿到倍率
const overmultiple = ()=>{
//拿到input响应式数据
console.log("输入的倍率为:",oddvalue.value);
//打包数据成url传输到over页面
const encodedMultiple = encodeURIComponent(JSON.stringify(oddvalue.value));
isPopupVisible2.value = false;
wx.redirectTo({
url: `/pages/over/over?multiple=${encodedMultiple}`
})
}
// const matchs = ref([
// {
// id: 1,
// gametime: 1,
// details: [
// {id: 101, score: "+"+10},
// {id: 102, score: "+"+20},
// {id: 103, score: "-"+30}
// ],
// },
// {
// id: 2,
// gametime: 2,
// details: [
// {id: 201, score: "+"+10},
// {id: 202, score: "+"+20},
// {id: 203, score: "-"+30}
// ]
// }
// ])
// const allscores = ref([
// {
// id: 301,
// allscore: "+"+ 20,
// },
// {
// id: 302,
// allscore: "+"+ 40,
// },
// { id: 303,
// allscore: "-"+ 60,
// }
// ])
// const details = ref(
// score[1,2,3]
// )
// const players = ref([
// {
// id: 401,
// name: '刘备',
// avatar: 'https://img1.baidu.com/it/u=3612220943,2414740890&fm=253&app=138&f=JPEG?w=526&h=500',
// playerType: 'user'
// },
// {
// id: 401,
// name: "赵云",
// avatar: 'https://q3.itc.cn/q_70/images03/20250110/1e71eecf56b34344bcae6a5b85c0bec2.jpeg',
// playerType: 'user'
// },
// {
// id: 401,
// name: "张飞",
// avatar: 'https://q1.itc.cn/q_70/images03/20241119/197701bb9ef34b20b6497720081a9972.jpeg',
// playerType: 'user'
// }
// ])
</script>
<style scoped lang="less">
.single{
.single-lan{
display: flex;
border-bottom: 1.5px solid rgb(237, 237, 237);
margin-top: 10rpx;
padding-bottom: 10rpx;
padding-right: 13rpx;
button::after {
border: none;
display: none;
}
button{
padding: 0;
font-size: 14.4px;
border: 0;
outline: none;
background-color: #fff;
text{
color: rgb(102, 102, 102);
}
}
.lan-switch{
display: flex;
align-items: center;
switch{
transform:scale(0.7);
}
text{
font-size: 14.4px;
color: rgb(102, 102, 102);
}
}
}
.single-detail{
display: flex;
align-items: center;
border-bottom: 1rpx solid rgb(237, 237, 237);
padding: 20rpx 0;
.sing-detail-title{
font-weight: 600;
font-size: 37rpx;
padding: 0 12rpx;
color: black;
}
text{
font-size: 29rpx;
color: rgb(102, 102, 102);
}
}
.single-score{
padding-top: 20rpx;
display: flex;
flex-direction: column;
.single-score-record{
display: flex;
margin-top: 20rpx;
.tab-head{
display: flex;
flex-direction: column;
margin-left: 20rpx;
margin-right: 30rpx;
width: 100rpx;
align-items: center;
.tab-head-player{
padding-top: 30rpx;
height: 90rpx;
width: 100rpx;
}
.tab-head-total{
padding-top: 20rpx;
width: 100rpx;
}
.tab-head-detail{
margin-top: 60rpx;
width: 100rpx;
}
}
.tab-body{
display: flex;
flex-direction: column;
align-items: center;
margin-right: 60rpx;
.tab-body-player{
display: flex;
flex-direction: column;
align-items: center;
height: 120rpx;
width: 100rpx;
image{
width: 80rpx;
}
text{
font-size: 30rpx;
}
}
.tab-total-score{
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20rpx;
}
.round-score{
display: flex;
flex-direction: column;
align-items: center;
margin-top: 60rpx;
}
}
}
.score-remind{
align-self: center;
font-size: 29rpx;
padding-bottom: 20rpx;
}
.score-record-player{
display: flex;
margin: 30rpx 0;
.score-head{
width: 90rpx;
align-self: center;
padding: 10rpx;
}
.player{
width: 160rpx;
display: flex;
flex-direction: column;
// margin: 0 35rpx;
align-items: center;
image{
width: 100rpx;
}
}
}
.score-record-all{
display: flex;
.score-head{
margin: 10rpx 0;
width: 90rpx;
align-self: center;
padding: 10rpx;
}
.all-score{
display: flex;
width: 160rpx;
align-items: center;
justify-content: center;
}
}
}
.single-bottom{
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
padding: 20rpx;
display: flex;
justify-content: center;
gap: 20rpx;
box-shadow: 0 -2rpx 10rpx rgba(0,0,0,0.1);
button{
width: 350rpx;
border: 2rpx solid rgb(55, 47, 172);
}
}
.popup-add{
width: 600rpx;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 20rpx;
padding-bottom: 25rpx;
.title{
font-size: 38rpx;
padding-bottom: 20rpx;
text{
padding: 0 100rpx;
}
}
.line{
width: 580rpx;
height: 0.1rpx;
background-color: RGB(211, 211, 211);
margin-top: 30rpx;
}
.small{
padding-top: 30rpx;
color: rgb(102, 102, 102);
width: 450rpx;
font-size: 28rpx;
margin-bottom: 10rpx;
}
.share{
margin-top: 30rpx;
}
image{
width: 400rpx;
height: 400rpx;
margin-top: 20rpx;
}
button{
margin-top: 15rpx;
width: 450rpx;
font-size: 30rpx;
margin-bottom: 15rpx;
background-color: rgb(55, 47, 172);
color: #fff;
}
}
.popup-virtue{
width: 600rpx;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 20rpx;
padding-bottom: 25rpx;
.title{
font-size: 38rpx;
padding-bottom: 20rpx;
margin-bottom: 20rpx;
text{
padding: 0 100rpx;
}
}
.line{
width: 580rpx;
height: 0.1rpx;
background-color: RGB(211, 211, 211);
margin-top: 30rpx;
margin-bottom: 50rpx;
}
.small{
padding-top: 30rpx;
color: rgb(102, 102, 102);
width: 450rpx;
font-size: 28rpx;
margin-bottom: 10rpx;
}
.share{
margin-top: 30rpx;
}
image{
width: 400rpx;
height: 400rpx;
margin-top: 20rpx;
}
uni-easyinput{
padding-top: 30rpx;
}
.lan-button{
padding-top: 50rpx;
display: flex;
}
button{
margin-top: 15rpx;
width: 260rpx;
margin: 0 12rpx;
font-size: 30rpx;
background-color: rgb(55, 47, 172);
color: #fff;
}
}
}
</style>