111
This commit is contained in:
@@ -1,8 +1,55 @@
|
||||
import {GET} from '@/utils/request'
|
||||
// api/room.js - 房间相关API
|
||||
import { GET, POST, PUT, DELETE } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 房间相关API
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 根据房间ID查询房间
|
||||
* @param {number} roomId 房间ID
|
||||
*/
|
||||
getRoomById(roomId) {
|
||||
return GET(`/system/room/id/${roomId}`)
|
||||
},
|
||||
|
||||
// 查询【请填写功能名称】详细
|
||||
export const getuser = (roomid) => {
|
||||
return GET('/system/roomuser/list',roomid)
|
||||
}
|
||||
/**
|
||||
* 根据创建者查询房间
|
||||
* @param {number} createUser 创建者ID
|
||||
*/
|
||||
getRoomsByCreateUser(createUser) {
|
||||
return GET(`/system/room/createUser/${createUser}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询房间列表
|
||||
* @param {Object} params 查询参数
|
||||
*/
|
||||
getRoomList(params) {
|
||||
return GET('/system/room/list', params)
|
||||
},
|
||||
|
||||
/**
|
||||
* 新增房间
|
||||
* @param {Object} roomData 房间数据
|
||||
*/
|
||||
addRoom(roomData) {
|
||||
return POST('/system/room', roomData)
|
||||
},
|
||||
|
||||
/**
|
||||
* 修改房间
|
||||
* @param {Object} roomData 房间数据
|
||||
*/
|
||||
updateRoom(roomData) {
|
||||
return PUT('/system/room', roomData)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除房间
|
||||
* @param {Array} roomIds 房间ID数组
|
||||
*/
|
||||
deleteRooms(roomIds) {
|
||||
return DELETE(`/system/room/${roomIds}`)
|
||||
}
|
||||
}
|
||||
47
scoring/api/roomDetail.js
Normal file
47
scoring/api/roomDetail.js
Normal file
@@ -0,0 +1,47 @@
|
||||
// api/roomDetail.js - 房间详情相关API
|
||||
import { GET, POST, PUT, DELETE } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 房间详情相关API
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 根据详情ID查询房间详情
|
||||
* @param {number} detailId 详情ID
|
||||
*/
|
||||
getRoomDetailById(detailId) {
|
||||
return GET(`/system/detail/${detailId}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询房间详情列表
|
||||
* @param {Object} params 查询参数
|
||||
*/
|
||||
getRoomDetailList(params) {
|
||||
return GET('/system/detail/list', params)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量新增房间详情
|
||||
* @param {Array} roomDetails 房间详情数据数组
|
||||
*/
|
||||
addRoomDetails(roomDetails) {
|
||||
return POST('/system/detail', roomDetails)
|
||||
},
|
||||
|
||||
/**
|
||||
* 修改房间详情
|
||||
* @param {Object} roomDetail 房间详情数据
|
||||
*/
|
||||
updateRoomDetail(roomDetail) {
|
||||
return PUT('/system/detail', roomDetail)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除房间详情
|
||||
* @param {Array} detailIds 详情ID数组
|
||||
*/
|
||||
deleteRoomDetails(detailIds) {
|
||||
return DELETE(`/system/detail/${detailIds}`)
|
||||
}
|
||||
}
|
||||
179
scoring/api/roomUser.js
Normal file
179
scoring/api/roomUser.js
Normal file
@@ -0,0 +1,179 @@
|
||||
// api/roomUser.js - 房间用户相关API
|
||||
import { GET, POST, PUT, DELETE } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 房间用户相关API
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 获取房间内所有用户及其详细对局记录(已修复)
|
||||
* @param {number} roomId 房间ID
|
||||
*/
|
||||
async getUserScoresWithDetails(roomId) {
|
||||
try {
|
||||
console.log('获取房间用户详情,房间ID:', roomId);
|
||||
|
||||
// 使用正确的API路径
|
||||
const response = await GET(`/system/score/room/user/user-details/${roomId}`);
|
||||
|
||||
console.log('房间用户详情API响应:', response);
|
||||
|
||||
// 处理不同的响应格式
|
||||
if (response.code === 200 || response.code === 0) {
|
||||
return response.data;
|
||||
} else if (response.success) {
|
||||
return response.data;
|
||||
} else {
|
||||
// 如果接口返回错误,尝试使用列表接口
|
||||
console.warn('主接口失败,尝试使用列表接口');
|
||||
return await this.getRoomUserList({ roomId });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取房间用户详情失败:', error);
|
||||
|
||||
// 降级方案1:使用列表接口
|
||||
try {
|
||||
console.log('尝试使用列表接口作为降级方案');
|
||||
const listResult = await this.getRoomUserList({ roomId });
|
||||
if (listResult) {
|
||||
return listResult;
|
||||
}
|
||||
} catch (listError) {
|
||||
console.error('列表接口也失败:', listError);
|
||||
}
|
||||
|
||||
// 降级方案2:返回空数据并提示
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据RoomUserId查询
|
||||
* @param {number} roomUserId 房间用户ID
|
||||
*/
|
||||
async getRoomUserById(roomUserId) {
|
||||
try {
|
||||
const response = await GET(`/system/score/room/user/RoomUserId/${roomUserId}`);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('获取房间用户信息失败:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据UserId查询
|
||||
* @param {number} userId 用户ID
|
||||
*/
|
||||
async getRoomUserByUserId(userId) {
|
||||
try {
|
||||
const response = await GET(`/system/score/room/user/userid/${userId}`);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('根据用户ID获取房间用户失败:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询房间用户列表
|
||||
* @param {Object} params 查询参数
|
||||
*/
|
||||
async getRoomUserList(params) {
|
||||
try {
|
||||
console.log('获取房间用户列表,参数:', params);
|
||||
const response = await GET('/system/score/room/user/list', params);
|
||||
console.log('房间用户列表响应:', response);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('获取房间用户列表失败:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 新增房间用户
|
||||
* @param {Object} roomUserData 房间用户数据
|
||||
*/
|
||||
async addRoomUser(roomUserData) {
|
||||
try {
|
||||
console.log('新增房间用户:', roomUserData);
|
||||
const response = await POST('/system/score/room/user', roomUserData);
|
||||
console.log('新增房间用户响应:', response);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('新增房间用户失败:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
async updateRoomUsersSafe(roomUsers) {
|
||||
try {
|
||||
console.log('安全更新房间用户得分:', roomUsers);
|
||||
|
||||
// 过滤和转换数据
|
||||
const safeUsers = roomUsers.map(user => {
|
||||
let userId = user.userId;
|
||||
|
||||
// 确保userId在int范围内
|
||||
if (userId > 2147483647 || userId < -2147483648) {
|
||||
console.warn('用户ID超出范围,进行转换:', userId);
|
||||
// 使用哈希值
|
||||
const strId = userId.toString();
|
||||
let hash = 0;
|
||||
for (let i = 0; i < strId.length; i++) {
|
||||
hash = ((hash << 5) - hash) + strId.charCodeAt(i);
|
||||
hash = hash & hash;
|
||||
}
|
||||
userId = Math.abs(hash) % 1000000;
|
||||
}
|
||||
|
||||
return {
|
||||
...user,
|
||||
userId: userId
|
||||
};
|
||||
});
|
||||
|
||||
const response = await PUT('/system/score/room/user', safeUsers);
|
||||
console.log('安全更新响应:', response);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('安全更新房间用户得分:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 批量更新用户得分
|
||||
* @param {Array} roomUsers 房间用户数据数组
|
||||
*/
|
||||
async updateRoomUsers(roomUsers) {
|
||||
|
||||
try {
|
||||
|
||||
|
||||
console.log('更新房间用户得分:', roomUsers);
|
||||
const response = await PUT('/system/score/room/user', roomUsers);
|
||||
console.log('更新房间用户得分响应:', response);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('更新房间用户得分:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除房间用户
|
||||
* @param {Array} roomUserIds 房间用户ID数组
|
||||
*/
|
||||
async deleteRoomUsers(roomUserIds) {
|
||||
try {
|
||||
const response = await DELETE(`/system/score/room/user/${roomUserIds}`);
|
||||
return response.data || response;
|
||||
} catch (error) {
|
||||
console.error('删除房间用户失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GET, POST } from '@/utils/request.js'
|
||||
import { GET, POST,PUT,DELETE } from '@/utils/request.js'
|
||||
|
||||
export const register = (userInfo) => {
|
||||
return POST('/system/score/user', userInfo);
|
||||
@@ -6,4 +6,60 @@ export const register = (userInfo) => {
|
||||
|
||||
export const login = (userInfo) => {
|
||||
return POST('/system/score/user/login', userInfo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 用户相关API
|
||||
*/
|
||||
export default {
|
||||
/**
|
||||
* 根据用户ID查询用户
|
||||
* @param {string} userId 用户ID
|
||||
*/
|
||||
getUserById(userId) {
|
||||
return GET(`/system/score/user/${userId}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 查询用户列表
|
||||
* @param {Object} params 查询参数
|
||||
*/
|
||||
getUserList(params) {
|
||||
return GET('/system/score/user/list', params)
|
||||
},
|
||||
|
||||
/**
|
||||
* 新增用户
|
||||
* @param {Object} userData 用户数据
|
||||
*/
|
||||
addUser(userData) {
|
||||
return POST('/system/score/user', userData)
|
||||
},
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
* @param {Object} userData 用户数据
|
||||
*/
|
||||
updateUser(userData) {
|
||||
return PUT('/system/score/user', userData)
|
||||
},
|
||||
|
||||
/**
|
||||
* 批量删除用户
|
||||
* @param {Array} userIds 用户ID数组
|
||||
*/
|
||||
deleteUsers(userIds) {
|
||||
return DELETE(`/system/score/user/${userIds}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param {Object} loginData 登录数据
|
||||
*/
|
||||
login(loginData) {
|
||||
return POST('/system/score/user/login', loginData)
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@
|
||||
},
|
||||
|
||||
{
|
||||
"path": "pages/settle/index", // 结算页面(新增注册)
|
||||
"path": "pages/settle/index",
|
||||
"style": { "navigationBarTitleText": "房间结算" }
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,38 +11,80 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 玩家信息表头 -->
|
||||
<view class="player-header">
|
||||
<view class="header-row">
|
||||
<view class="header-cell header-label">玩家 ({{ players.length }}位)</view>
|
||||
<view class="header-cell" v-for="player in players" :key="player.id">
|
||||
<view class="player-header-info">
|
||||
<image class="player-avatar" :src="player.avatar" mode="aspectFit"></image>
|
||||
<text class="player-name">{{ player.name }}</text>
|
||||
<!-- 玩家列表容器 - 添加滚动条功能 -->
|
||||
<view class="player-list-container">
|
||||
<!-- 水平滚动容器 -->
|
||||
<scroll-view
|
||||
class="player-scroll-view"
|
||||
scroll-x="true"
|
||||
:scroll-left="scrollLeft"
|
||||
@scroll="onScroll"
|
||||
:show-scrollbar="false"
|
||||
scroll-with-animation
|
||||
>
|
||||
<view class="player-list-content">
|
||||
<!-- 玩家信息表头 -->
|
||||
<view class="player-header">
|
||||
<view class="header-row">
|
||||
<view class="header-cell header-label">玩家 ({{ players.length }}位)</view>
|
||||
<view class="player-columns">
|
||||
<view class="player-column" v-for="player in players" :key="player.id">
|
||||
<view class="player-header-info">
|
||||
<!-- 统一头像容器样式 -->
|
||||
<view class="avatar-container">
|
||||
<image class="player-avatar" :src="player.avatar" mode="aspectFill"></image>
|
||||
</view>
|
||||
<text class="player-name">{{ player.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 对局详情表格 -->
|
||||
<view class="detail-table">
|
||||
<!-- 总分行 -->
|
||||
<view class="table-row">
|
||||
<view class="row-label">总分</view>
|
||||
<view class="row-cells">
|
||||
<view class="score-cell" v-for="player in players" :key="player.id">
|
||||
{{ formatScore(player.totalScore) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 每局得分行 -->
|
||||
<view class="table-row" v-for="(round, roundIndex) in gameRounds" :key="roundIndex">
|
||||
<view class="row-label">第{{ roundIndex + 1 }}局</view>
|
||||
<view class="row-cells">
|
||||
<view class="score-cell" v-for="player in players" :key="player.id">
|
||||
{{ formatScore(getPlayerRoundScore(roundIndex, player.id)) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 对局详情表格 -->
|
||||
<view class="detail-table">
|
||||
<!-- 总分行 -->
|
||||
<view class="table-row">
|
||||
<view class="row-label">总分</view>
|
||||
<view class="row-cells">
|
||||
<view class="score-cell" v-for="player in players" :key="player.id">
|
||||
{{ formatScore(player.totalScore) }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 每局得分行 -->
|
||||
<view class="table-row" v-for="(round, roundIndex) in gameRounds" :key="roundIndex">
|
||||
<view class="row-label">第{{ roundIndex + 1 }}局</view>
|
||||
<view class="row-cells">
|
||||
<view class="score-cell" v-for="player in players" :key="player.id">
|
||||
{{ formatScore(getPlayerRoundScore(roundIndex, player.id)) }}
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 自定义可拖动滚动条 -->
|
||||
<view class="custom-scrollbar" v-if="showScrollIndicator">
|
||||
<view
|
||||
class="scroll-track"
|
||||
@touchstart="onTrackTouchStart"
|
||||
@touchmove.prevent="onTrackTouchMove"
|
||||
@touchend="onTrackTouchEnd"
|
||||
:id="trackId"
|
||||
>
|
||||
<view
|
||||
class="scroll-thumb"
|
||||
:style="{
|
||||
left: thumbPosition + '%',
|
||||
width: thumbWidth + '%'
|
||||
}"
|
||||
@touchstart="onThumbTouchStart"
|
||||
@touchmove.prevent="onThumbTouchMove"
|
||||
@touchend="onThumbTouchEnd"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -55,13 +97,45 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, computed, nextTick, watch } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
|
||||
// 玩家数据
|
||||
const players = ref([])
|
||||
// 对局记录
|
||||
const gameRounds = ref([])
|
||||
|
||||
// 滚动条相关数据
|
||||
const scrollLeft = ref(0)
|
||||
const scrollWidth = ref(0)
|
||||
const scrollViewWidth = ref(0)
|
||||
const trackId = ref('scroll-track-' + Date.now())
|
||||
|
||||
// 滚动条拖动状态
|
||||
const isDragging = ref(false)
|
||||
const dragStartX = ref(0)
|
||||
const dragStartScrollLeft = ref(0)
|
||||
const trackRect = ref({ left: 0, width: 0 })
|
||||
|
||||
// 计算属性:是否显示滚动条指示器
|
||||
const showScrollIndicator = computed(() => {
|
||||
return scrollWidth.value > scrollViewWidth.value
|
||||
})
|
||||
|
||||
// 计算属性:滚动条滑块宽度
|
||||
const thumbWidth = computed(() => {
|
||||
if (scrollWidth.value === 0) return 100
|
||||
const widthRatio = (scrollViewWidth.value / scrollWidth.value) * 100
|
||||
return Math.max(20, Math.min(100, widthRatio)) // 最小宽度20%,最大100%
|
||||
})
|
||||
|
||||
// 计算属性:滚动条滑块位置
|
||||
const thumbPosition = computed(() => {
|
||||
if (scrollWidth.value === 0 || scrollWidth.value <= scrollViewWidth.value) return 0
|
||||
const maxScroll = scrollWidth.value - scrollViewWidth.value
|
||||
return (scrollLeft.value / maxScroll) * (100 - thumbWidth.value)
|
||||
})
|
||||
|
||||
// 格式化分数显示
|
||||
const formatScore = (score) => {
|
||||
if (score === 0) return '0'
|
||||
@@ -128,9 +202,154 @@ onMounted(() => {
|
||||
]
|
||||
calculateTotalScores()
|
||||
}
|
||||
|
||||
// 监听玩家数量变化
|
||||
watch(() => players.value.length, () => {
|
||||
setTimeout(() => {
|
||||
updateScrollDimensions()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
// 更新滚动区域尺寸
|
||||
setTimeout(() => {
|
||||
updateScrollDimensions()
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// 更新滚动区域
|
||||
setTimeout(() => {
|
||||
updateScrollDimensions()
|
||||
getTrackRect()
|
||||
}, 300)
|
||||
})
|
||||
|
||||
// 滚动事件处理
|
||||
const onScroll = (e) => {
|
||||
scrollLeft.value = e.detail.scrollLeft
|
||||
}
|
||||
|
||||
// 更新滚动区域尺寸
|
||||
const updateScrollDimensions = () => {
|
||||
console.log('开始更新滚动区域尺寸...')
|
||||
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery()
|
||||
query.select('.player-scroll-view').boundingClientRect()
|
||||
query.select('.player-list-content').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res[0] && res[1]) {
|
||||
scrollViewWidth.value = res[0].width
|
||||
scrollWidth.value = res[1].width
|
||||
|
||||
console.log('滚动区域计算完成:', {
|
||||
scrollViewWidth: scrollViewWidth.value,
|
||||
scrollWidth: scrollWidth.value,
|
||||
showScrollIndicator: scrollWidth.value > scrollViewWidth.value,
|
||||
playersCount: players.value.length
|
||||
})
|
||||
|
||||
// 强制更新显示状态
|
||||
if (scrollWidth.value > scrollViewWidth.value) {
|
||||
console.log('需要显示滚动条')
|
||||
}
|
||||
} else {
|
||||
console.error('获取滚动区域尺寸失败')
|
||||
}
|
||||
})
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 获取轨道位置信息
|
||||
const getTrackRect = () => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery()
|
||||
query.select('.custom-scrollbar .scroll-track').boundingClientRect()
|
||||
query.exec((res) => {
|
||||
if (res[0]) {
|
||||
trackRect.value = {
|
||||
left: res[0].left,
|
||||
width: res[0].width
|
||||
}
|
||||
resolve(trackRect.value)
|
||||
} else {
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
}, 100)
|
||||
})
|
||||
}
|
||||
|
||||
// 滚动条滑块触摸开始
|
||||
const onThumbTouchStart = async (e) => {
|
||||
isDragging.value = true
|
||||
dragStartX.value = e.touches[0].clientX
|
||||
dragStartScrollLeft.value = scrollLeft.value
|
||||
|
||||
await getTrackRect()
|
||||
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 滚动条滑块触摸移动
|
||||
const onThumbTouchMove = (e) => {
|
||||
if (!isDragging.value) return
|
||||
|
||||
const deltaX = e.touches[0].clientX - dragStartX.value
|
||||
const maxScroll = Math.max(0, scrollWidth.value - scrollViewWidth.value)
|
||||
|
||||
if (maxScroll > 0 && trackRect.value.width > 0) {
|
||||
const scrollPercent = deltaX / trackRect.value.width
|
||||
const newScrollLeft = dragStartScrollLeft.value + (scrollPercent * maxScroll)
|
||||
scrollLeft.value = Math.max(0, Math.min(maxScroll, newScrollLeft))
|
||||
}
|
||||
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 滚动条滑块触摸结束
|
||||
const onThumbTouchEnd = (e) => {
|
||||
isDragging.value = false
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 滚动条轨道触摸开始
|
||||
const onTrackTouchStart = async (e) => {
|
||||
const rect = await getTrackRect()
|
||||
if (!rect) return
|
||||
|
||||
const clickX = e.touches[0].clientX - rect.left
|
||||
const thumbWidthPx = (thumbWidth.value / 100) * rect.width
|
||||
const thumbCenter = (thumbPosition.value / 100) * rect.width + thumbWidthPx / 2
|
||||
|
||||
const maxScroll = Math.max(0, scrollWidth.value - scrollViewWidth.value)
|
||||
|
||||
if (maxScroll > 0) {
|
||||
if (clickX < thumbCenter) {
|
||||
scrollLeft.value = Math.max(0, scrollLeft.value - scrollViewWidth.value * 0.8)
|
||||
} else {
|
||||
scrollLeft.value = Math.min(maxScroll, scrollLeft.value + scrollViewWidth.value * 0.8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条轨道触摸移动
|
||||
const onTrackTouchMove = (e) => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 滚动条轨道触摸结束
|
||||
const onTrackTouchEnd = (e) => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
// 分享对局详情
|
||||
const shareDetail = () => {
|
||||
@@ -145,6 +364,7 @@ const shareDetail = () => {
|
||||
.game-detail-page {
|
||||
background-color: #fff;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 200rpx; /* 给底部按钮留出空间 */
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
@@ -169,27 +389,59 @@ const shareDetail = () => {
|
||||
}
|
||||
}
|
||||
|
||||
/* 玩家列表容器 */
|
||||
.player-list-container {
|
||||
padding: 0 30rpx 30rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 滚动视图样式 */
|
||||
.player-scroll-view {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
// 隐藏原生滚动条
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.player-list-content {
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.player-header {
|
||||
padding: 20rpx 30rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
|
||||
.header-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.header-cell {
|
||||
flex: 1;
|
||||
padding: 20rpx 0;
|
||||
|
||||
.header-label {
|
||||
width: 200rpx;
|
||||
flex: none;
|
||||
font-size: 28rpx;
|
||||
color: #000;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&.header-label {
|
||||
width: 200rpx;
|
||||
flex: none;
|
||||
font-size: 28rpx;
|
||||
color: #000;
|
||||
font-weight: 500;
|
||||
}
|
||||
align-items: center;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.player-columns {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.player-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 140rpx;
|
||||
flex-shrink: 0;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.player-header-info {
|
||||
@@ -197,24 +449,41 @@ const shareDetail = () => {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.player-avatar {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50%;
|
||||
/* 统一头像容器样式 */
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.player-avatar {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
border: 5rpx solid #fff;
|
||||
box-shadow: 0 6rpx 20rpx rgba(65, 71, 155, 0.3);
|
||||
background: linear-gradient(135deg, #41479b 0%, #8b91e2 100%);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.player-name {
|
||||
font-size: 24rpx;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
max-width: 120rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detail-table {
|
||||
padding: 0 30rpx;
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 20rpx 0;
|
||||
@@ -226,30 +495,70 @@ const shareDetail = () => {
|
||||
|
||||
.row-label {
|
||||
width: 200rpx;
|
||||
flex: none;
|
||||
font-size: 28rpx;
|
||||
color: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
.row-cells {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
|
||||
.score-cell {
|
||||
flex: 1;
|
||||
width: 140rpx;
|
||||
flex-shrink: 0;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 自定义可拖动滚动条样式 - 完全复制单人房间的样式 */
|
||||
.custom-scrollbar {
|
||||
margin-top: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.scroll-track {
|
||||
height: 12rpx;
|
||||
background-color: #f0f0f0;
|
||||
border-radius: 6rpx;
|
||||
position: relative;
|
||||
|
||||
// 添加点击区域扩展
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -10rpx;
|
||||
bottom: -10rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-thumb {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
background-color: #41479b;
|
||||
border-radius: 6rpx;
|
||||
transition: all 0.1s ease;
|
||||
|
||||
// 添加悬停效果
|
||||
&:active {
|
||||
background-color: #33367a;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,8 +23,14 @@
|
||||
<!-- 动态渲染每个玩家的结算结果 -->
|
||||
<view class="table-row" v-for="player in players" :key="player.id">
|
||||
<view class="player-info">
|
||||
<image class="player-avatar" :src="player.avatar" mode="aspectFit"></image>
|
||||
<!-- 修改头像容器,添加统一的大头像样式 -->
|
||||
<view class="avatar-container">
|
||||
<image class="player-avatar" :src="player.avatar" mode="aspectFill"></image>
|
||||
<!-- 如果是玩家自己,添加标识 -->
|
||||
<view v-if="player.isSelf" class="self-indicator"></view>
|
||||
</view>
|
||||
<text class="player-name">{{ player.name }}</text>
|
||||
<view v-if="player.isSelf" class="self-tag">自己</view>
|
||||
</view>
|
||||
<view class="win-lose">
|
||||
<view class="win-tag" v-if="player.totalScore > 0">胜利!</view>
|
||||
@@ -68,6 +74,9 @@ onMounted(() => {
|
||||
// 获取倍率
|
||||
rate.value = parseFloat(options.rate) || 1
|
||||
|
||||
// 获取当前用户信息
|
||||
const currentUserInfo = uni.getStorageSync('userInfo')
|
||||
|
||||
// 从本地存储获取玩家数据和对局记录
|
||||
const savedPlayers = uni.getStorageSync('players')
|
||||
const savedRounds = uni.getStorageSync('gameRounds')
|
||||
@@ -75,6 +84,12 @@ onMounted(() => {
|
||||
if (savedPlayers && savedRounds) {
|
||||
// 计算每个玩家的总分和倍率分
|
||||
players.value = savedPlayers.map(player => {
|
||||
// 检查是否是玩家自己
|
||||
const isSelf = currentUserInfo &&
|
||||
currentUserInfo.userId &&
|
||||
player.userId &&
|
||||
player.userId.toString() === currentUserInfo.userId.toString()
|
||||
|
||||
// 计算总分
|
||||
let totalScore = 0
|
||||
savedRounds.forEach(round => {
|
||||
@@ -90,7 +105,8 @@ onMounted(() => {
|
||||
return {
|
||||
...player,
|
||||
totalScore,
|
||||
rateScore
|
||||
rateScore,
|
||||
isSelf: isSelf || false // 添加isSelf字段
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@@ -101,7 +117,8 @@ onMounted(() => {
|
||||
name: '玩家80061',
|
||||
avatar: 'https://ts1.tc.mm.bing.net/th/id/OIP-C.QQG4bvcAR3CJ0WeQULA9UQAAAA?w=275&h=211&c=8&rs=1&qlt=90&o=6&cb=ucfimgc1&dpr=1.5&pid=3.1&rm=2',
|
||||
totalScore: 0,
|
||||
rateScore: 0
|
||||
rateScore: 0,
|
||||
isSelf: true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -181,13 +198,21 @@ const shareResult = () => {
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
|
||||
&:first-child {
|
||||
text-align: left;
|
||||
flex: 1.5; /* 调整玩家信息列宽度 */
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
align-items: center;
|
||||
padding: 25rpx 30rpx;
|
||||
border-bottom: 1rpx solid #ddd;
|
||||
background-color: #fff;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
@@ -196,18 +221,65 @@ const shareResult = () => {
|
||||
.player-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
flex: 1.5; /* 与表头对齐 */
|
||||
min-width: 200rpx;
|
||||
|
||||
.player-avatar {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 10rpx;
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
width: 110rpx; /* 容器比头像稍大 */
|
||||
height: 110rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.player-avatar {
|
||||
width: 100rpx; /* 增大头像尺寸 */
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
border: 5rpx solid #fff; /* 添加白色边框 */
|
||||
box-shadow: 0 6rpx 20rpx rgba(65, 71, 155, 0.3); /* 添加阴影效果 */
|
||||
background: linear-gradient(135deg, #41479b 0%, #8b91e2 100%); /* 添加渐变背景 */
|
||||
transition: all 0.3s ease;
|
||||
|
||||
/* 为虚拟玩家头像添加特殊样式 */
|
||||
&:not([src*="OIP-C"]) {
|
||||
/* 处理默认头像的特殊样式 */
|
||||
border: 5rpx solid #f0f0f0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 玩家自己头像的特殊标识 */
|
||||
.self-indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background-color: #4CAF50;
|
||||
border: 3rpx solid #fff;
|
||||
border-radius: 50%;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.player-name {
|
||||
font-size: 28rpx;
|
||||
color: #000;
|
||||
.player-name {
|
||||
font-size: 26rpx;
|
||||
color: #000;
|
||||
margin-right: 10rpx;
|
||||
font-weight: 500;
|
||||
/* 允许换行 */
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.self-tag {
|
||||
background-color: #007aff;
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 10rpx;
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,24 +293,27 @@ const shareResult = () => {
|
||||
background-color: #07c160;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
padding: 5rpx 15rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.lose-tag {
|
||||
background-color: #fa5151;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
padding: 5rpx 15rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.draw-tag {
|
||||
background-color: #10aeff;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
padding: 5rpx 15rpx;
|
||||
padding: 6rpx 20rpx;
|
||||
border-radius: 8rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,20 +321,28 @@ const shareResult = () => {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
color: #333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
/* 优化虚拟玩家头像的默认样式 */
|
||||
.player-avatar[src*="OIP-C"] {
|
||||
/* 虚拟玩家的默认头像样式 */
|
||||
border: 5rpx solid #e6e6ff !important;
|
||||
box-shadow: 0 6rpx 20rpx rgba(139, 145, 226, 0.3) !important;
|
||||
}
|
||||
|
||||
.detail-link {
|
||||
text-align: center;
|
||||
margin: 20rpx 0;
|
||||
padding: 20rpx;
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
font-size: 28rpx;
|
||||
color: #41479b;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -279,5 +362,12 @@ const shareResult = () => {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 40rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(255, 193, 7, 0.3);
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:active {
|
||||
background-color: #e6ac00;
|
||||
transform: translateY(2rpx);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
// api/request.js
|
||||
import { BASE_URL } from './CommonValues.js';
|
||||
import { loginSystem } from '@/api/login.js';
|
||||
|
||||
@@ -50,13 +51,50 @@ export async function SIMPLE(url, data, method) {
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: res => {
|
||||
if(res.data.code == '200' || res.data.statusCode == '200') {
|
||||
console.log(`API响应 ${url}:`, res);
|
||||
|
||||
// 更灵活的状态码判断
|
||||
let isSuccess = false;
|
||||
|
||||
// 检查HTTP状态码
|
||||
if (res.statusCode === 200) {
|
||||
// 检查响应数据
|
||||
if (res.data) {
|
||||
// 如果data是数组,直接认为是成功的
|
||||
if (Array.isArray(res.data)) {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果有code字段且为200
|
||||
else if (res.data.code === 200 || res.data.code === '200') {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果有statusCode字段且为200
|
||||
else if (res.data.statusCode === 200 || res.data.statusCode === '200') {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果没有code字段但有data字段
|
||||
else if (res.data.data !== undefined) {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果data是对象但不是错误结构
|
||||
else if (typeof res.data === 'object' && !res.data.errMsg) {
|
||||
isSuccess = true;
|
||||
}
|
||||
} else {
|
||||
// 没有data字段但状态码是200
|
||||
isSuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
resolve(res.data)
|
||||
} else {
|
||||
console.error('请求返回错误状态:', res.data);
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.error('请求失败:', err);
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
@@ -75,13 +113,50 @@ export function SIMPLE_TOKEN(url, data, token, method) {
|
||||
dataType: 'json',
|
||||
data: data,
|
||||
success: res => {
|
||||
if(res.data.code == '200' || res.data.statusCode == '200') {
|
||||
console.log(`API响应 ${url}:`, res);
|
||||
|
||||
// 更灵活的状态码判断
|
||||
let isSuccess = false;
|
||||
|
||||
// 检查HTTP状态码
|
||||
if (res.statusCode === 200) {
|
||||
// 检查响应数据
|
||||
if (res.data) {
|
||||
// 如果data是数组,直接认为是成功的
|
||||
if (Array.isArray(res.data)) {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果有code字段且为200
|
||||
else if (res.data.code === 200 || res.data.code === '200') {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果有statusCode字段且为200
|
||||
else if (res.data.statusCode === 200 || res.data.statusCode === '200') {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果没有code字段但有data字段
|
||||
else if (res.data.data !== undefined) {
|
||||
isSuccess = true;
|
||||
}
|
||||
// 如果data是对象但不是错误结构
|
||||
else if (typeof res.data === 'object' && !res.data.errMsg) {
|
||||
isSuccess = true;
|
||||
}
|
||||
} else {
|
||||
// 没有data字段但状态码是200
|
||||
isSuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess) {
|
||||
resolve(res.data)
|
||||
} else {
|
||||
console.error('请求返回错误状态:', res.data);
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
console.error('请求失败:', err);
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user