pk优化版

This commit is contained in:
2026-02-26 13:15:19 +08:00
parent d4c0dcf6b1
commit 5c1911314f
22 changed files with 742 additions and 386 deletions

View File

@@ -71,111 +71,100 @@
</div>
<!-- 列表和聊天区域 -->
<el-splitter class="pk-splitter">
<el-splitter-panel>
<el-splitter>
<!-- 列表面板 -->
<el-splitter-panel :size="70" :resizable="false">
<div class="list-panel">
<div
v-infinite-scroll="loadMore"
:infinite-scroll-distance="100"
:infinite-scroll-disabled="loading || noMore"
class="pk-list"
>
<div
v-for="(item, index) in pkList"
:key="index"
class="pk-card"
:class="{ selected: selectedItem === item }"
@click="handleItemClick(item)"
>
<!-- 头像 -->
<div class="pk-avatar">
<img :src="item.anchorIcon" alt="" />
</div>
<div class="pk-info">
<!-- 个人信息 -->
<div class="pk-personal">
<span class="pk-name">{{ item.disPlayId }}</span>
<span class="pk-gender" :class="item.sex === 1 ? 'male' : 'female'">
{{ item.sex === 1 ? '男' : '女' }}
</span>
<span class="pk-country">{{ item.country }}</span>
</div>
<!-- 时间 -->
<div class="pk-time">PK时间本地时间: {{ formatTime(item.pkTime * 1000) }}</div>
<!-- PK信息 -->
<div class="pk-stats">
<img class="stat-icon" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/gold.png" alt="" />
<span>金币: {{ item.coin }}K</span>
<img class="stat-icon session-icon" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/session.png" alt="" />
<span>场次: {{ item.pkNumber }}</span>
</div>
<!-- 备注 -->
<div class="pk-remark">{{ item.remark }}</div>
</div>
</div>
<div class="content-area">
<!-- 列表面板 -->
<div class="list-panel">
<div
v-infinite-scroll="loadMore"
:infinite-scroll-distance="100"
:infinite-scroll-disabled="loading || noMore"
class="pk-list"
>
<div
v-for="(item, index) in pkList"
:key="index"
class="pk-card"
:class="{ selected: selectedItem === item }"
@click="handleItemClick(item)"
>
<!-- 头像 -->
<div class="pk-avatar">
<img :src="item.anchorIcon" alt="" />
</div>
<div class="pk-info">
<!-- 个人信息 -->
<div class="pk-personal">
<span class="pk-name">{{ item.disPlayId }}</span>
<span class="pk-gender" :class="item.sex === 1 ? 'male' : 'female'">
{{ item.sex === 1 ? '男' : '女' }}
</span>
<span class="pk-country">{{ item.country }}</span>
</div>
<!-- 时间 -->
<div class="pk-time">PK时间本地时间: {{ formatTime(item.pkTime * 1000) }}</div>
<!-- PK信息 -->
<div class="pk-stats">
<img class="stat-icon" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/gold.png" alt="" />
<span>金币: {{ item.coin }}K</span>
<img class="stat-icon session-icon" src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/session.png" alt="" />
<span>场次: {{ item.pkNumber }}</span>
</div>
<!-- 备注 -->
<div class="pk-remark">{{ item.remark }}</div>
</div>
</div>
<div v-if="pkList.length === 0" class="empty-tip">暂无数据</div>
<div v-if="pkList.length === 0" class="empty-tip">暂无数据</div>
</div>
</div>
<!-- 聊天面板 -->
<div class="chat-panel">
<div v-if="selectedItem" class="chat-container">
<div class="chat-header">{{ chatUserInfo.nickName || '聊天' }}</div>
<div class="chat-messages" ref="chatMessagesRef">
<div
v-for="(msg, index) in messagesList"
:key="index"
class="message-item"
:class="{ mine: msg.senderId == currentUser.id, 'pk-message': msg.type === 'pk' }"
>
<div class="message-triangle" v-if="msg.type === 'text'"></div>
<div class="message-content">
<div v-if="msg.type === 'text'" class="text-message">{{ msg.payload.text }}</div>
<PictureMessage v-else-if="msg.type === 'image'" :item="msg" />
<MiniPKMessage v-else-if="msg.type === 'pk'" :item="msg" :compact="true" />
<VoiceMessage v-else-if="msg.type === 'audio'" :item="msg.payload.url" :size="msg.payload.duration" />
</div>
</div>
</el-splitter-panel>
<!-- 聊天面板 -->
<el-splitter-panel :size="30" :resizable="false">
<div class="chat-panel">
<div v-if="selectedItem" class="chat-container">
<div class="chat-header">{{ chatUserInfo.nickName || '聊天' }}</div>
<div class="chat-messages" ref="chatMessagesRef">
<div
v-for="(msg, index) in messagesList"
:key="index"
class="message-item"
:class="{ mine: msg.senderId == currentUser.id }"
>
<div class="message-avatar">
<img :src="msg.senderId == currentUser.id ? currentUser.headerIcon : chatUserInfo.headerIcon" alt="" />
</div>
<div class="message-triangle" v-if="msg.type === 'text'"></div>
<div class="message-content">
<div v-if="msg.type === 'text'" class="text-message">{{ msg.payload.text }}</div>
<PictureMessage v-else-if="msg.type === 'image'" :item="msg" />
<MiniPKMessage v-else-if="msg.type === 'pk'" :item="msg" />
<VoiceMessage v-else-if="msg.type === 'audio'" :item="msg.payload.url" :size="msg.payload.duration" />
</div>
</div>
</div>
<!-- 聊天输入区 -->
<div class="chat-input-area">
<div class="input-controls">
<div class="control-btns">
<div class="control-btn" @click="handleSendImage">
<img src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Album.png" alt="" />
</div>
<!-- 聊天输入区 -->
<div class="chat-input-area">
<div class="input-controls">
<div class="control-btns">
<div class="control-btn" @click="handleSendImage">
<img src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/Album.png" alt="" />
</div>
<div class="control-btn" @click="handleInvite">
<img src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_invite.png" alt="" />
</div>
</div>
<div class="send-btn" @click="sendMessage">发送</div>
</div>
<div class="input-box">
<textarea
v-model="inputText"
placeholder="输入消息..."
@keydown.enter.prevent="sendMessage"
></textarea>
</div>
<div class="control-btn" @click="handleInvite">
<img src="https://vv-1317974657.cos.ap-shanghai.myqcloud.com/util/chat_invite.png" alt="" />
</div>
</div>
<div v-else class="chat-placeholder">
<span>右方选择主播立即聊天</span>
</div>
<div class="send-btn" @click="sendMessage">发送</div>
</div>
</el-splitter-panel>
</el-splitter>
</el-splitter-panel>
</el-splitter>
<div class="input-box">
<textarea
v-model="inputText"
placeholder="输入消息..."
@keydown.enter.prevent="sendMessage"
></textarea>
</div>
</div>
</div>
<div v-else class="chat-placeholder">
<span>右方选择主播立即聊天</span>
</div>
</div>
</div>
<!-- 隐藏的文件输入 -->
<input
@@ -388,6 +377,7 @@ async function loadPkList() {
}
} catch (e) {
console.error('加载 PK 列表失败', e)
noMore.value = true
} finally {
loading.value = false
}
@@ -403,12 +393,14 @@ async function handleItemClick(item) {
if (isGoEasyEnabled()) {
// GoEasy 已启用,加载聊天消息
const messages = await goEasyGetMessages({ id: item.senderId, timestamp: null })
const messages = await goEasyGetMessages({ id: String(item.senderId), timestamp: null })
messagesList.value = messages || []
await nextTick()
scrollToBottom()
// 异步卡片内容加载完后再滚一次
setTimeout(scrollToBottom, 300)
// 标记消息已读
goEasyMessageRead({ id: item.senderId }).catch(() => {})
goEasyMessageRead({ id: String(item.senderId) }).catch(() => {})
} else {
messagesList.value = []
ElMessage.warning('聊天功能暂时不可用GoEasy 订阅未续费)')
@@ -446,7 +438,7 @@ async function sendMessage() {
try {
const msg = await goEasySendMessage({
text: inputText.value,
id: selectedItem.value.senderId,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
@@ -483,7 +475,7 @@ async function handleFileSelect(event) {
try {
const msg = await goEasySendImageMessage({
imagefile: file,
id: selectedItem.value.senderId,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
@@ -540,7 +532,16 @@ async function confirmInvite() {
const pkRecord = await createPkRecord({
pkIdA: selectedItem.value.id,
pkIdB: selectedAnchor.value.id,
userId: userId
userIdA: selectedItem.value.senderId,
userIdB: userId,
pkTime: selectedItem.value.pkTime,
pkNumber: selectedItem.value.pkNumber,
anchorIdA: selectedItem.value.anchorId,
anchorIdB: selectedAnchor.value.anchorId,
anchorIconA: selectedItem.value.anchorIcon,
anchorIconB: selectedAnchor.value.anchorIcon,
piIdA: selectedItem.value.id,
piIdB: selectedAnchor.value.id,
})
// 发送 PK 邀请消息
@@ -548,7 +549,7 @@ async function confirmInvite() {
msgid: pkRecord.id,
pkIdA: selectedItem.value.id,
pkIdB: selectedAnchor.value.id,
id: selectedItem.value.senderId,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
@@ -573,31 +574,9 @@ onMounted(() => {
console.log('[PkHall] 当前用户数据:', currentUser.value)
console.log('[PkHall] 解析的用户 ID:', userId)
// 同时加载今日PK和PK大厅数据
// 初始加载 PK 大厅数据(通过 loadPkList 统一管理 page/loading/noMore 状态)
if (userId) {
// 加载今日PK
getPkList({
status: 0,
page: 0,
size: 10,
userId: userId,
condition: { type: 1 }
}).then(res => {
todayList.value = res || []
}).catch(() => {})
// 加载PK大厅
getPkList({
status: 0,
page: 0,
size: 10,
userId: userId,
condition: { type: 2 }
}).then(res => {
hallList.value = res || []
pkList.value = hallList.value
page.value = 1
}).catch(() => {})
loadPkList()
} else {
console.warn('[PkHall] 未找到用户 ID无法加载数据')
}
@@ -644,9 +623,10 @@ onUnmounted(() => {
border-bottom: 1px solid #f1f5f9; // slate-100
}
.pk-splitter {
.content-area {
flex: 1;
height: calc(100% - 100px);
display: flex;
min-height: 0;
}
// 切换按钮
@@ -769,7 +749,8 @@ onUnmounted(() => {
// 列表面板
.list-panel {
height: 100%;
flex: 1;
min-width: 0;
overflow: hidden;
}
@@ -894,9 +875,12 @@ onUnmounted(() => {
// 聊天面板
.chat-panel {
height: 100%;
width: 350px;
flex-shrink: 0;
border-left: 1px solid #f1f5f9; // slate-100
background-color: #ffffff;
display: flex;
flex-direction: column;
}
.chat-container {
@@ -929,21 +913,6 @@ onUnmounted(() => {
flex-direction: row-reverse;
}
.message-avatar {
width: 45px;
height: 45px;
border-radius: 10px;
overflow: hidden;
margin: 0 10px;
flex-shrink: 0;
}
.message-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.message-triangle {
width: 0;
height: 0;
@@ -962,6 +931,10 @@ onUnmounted(() => {
max-width: 65%;
}
.message-item.pk-message .message-content {
max-width: 100%;
}
.text-message {
padding: 10px 15px;
background: #f5f5f5;