Files
web-fusion/src/views/pk-mini/PkHall.vue
2026-02-26 13:15:19 +08:00

1132 lines
26 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>
<!-- PK 大厅页面 -->
<div class="pk-hall">
<!-- 顶部筛选面板 - 固定高度 -->
<div class="control-panel">
<!-- PK大厅/今日PK 切换 -->
<div class="switch-box">
<div class="switch-text" @click="switchMode">PK大厅</div>
<div class="switch-text" @click="switchMode">今日PK</div>
<div class="switch-slider" :class="{ 'slide-right': !isHallMode }">
{{ isHallMode ? 'PK大厅' : '今日PK' }}
</div>
</div>
<!-- 国家和性别选择 -->
<div class="select-box">
<el-select-v2
v-model="countryValue"
:options="countryOptions"
placeholder="国家"
filterable
clearable
class="filter-select"
/>
<el-select-v2
v-model="genderValue"
:options="genderOptions"
placeholder="性别"
clearable
class="filter-select"
/>
</div>
<!-- 金币数量 -->
<div class="coin-box">
<div class="coin-item">
<div class="coin-label">最小金币数单位为K</div>
<el-input-number v-model="minCoin" :min="0" controls-position="right" />
</div>
<div class="coin-item">
<div class="coin-label">最大金币数单位为K</div>
<el-input-number v-model="maxCoin" :min="0" controls-position="right" />
</div>
</div>
<!-- 时间选择 (仅PK大厅模式) -->
<div class="time-box" :class="{ 'is-hidden': !isHallMode }">
<el-date-picker
v-model="timeRange"
type="datetimerange"
range-separator=""
start-placeholder="最小PK时间"
end-placeholder="最大PK时间"
format="YYYY/MM/DD HH:mm"
value-format="x"
/>
</div>
<!-- 搜索和重置按钮 -->
<div class="btn-box">
<div class="search-btn" @click="handleSearch">
<img class="btn-icon" :src="iconSearch" alt="" />
<span>搜索</span>
</div>
<div class="reset-btn" @click="handleReset">
<img class="btn-icon" :src="iconReset" alt="" />
<span>重置</span>
</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>
</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>
</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>
</div>
<div v-else class="chat-placeholder">
<span>右方选择主播立即聊天</span>
</div>
</div>
</div>
<!-- 隐藏的文件输入 -->
<input
ref="fileInputRef"
type="file"
accept="image/*"
style="display: none"
@change="handleFileSelect"
/>
<!-- PK邀请弹窗 -->
<el-dialog v-model="inviteDialogVisible" title="选择主播发起PK邀请" width="500" align-center>
<div class="invite-dialog-content">
<div v-if="myAnchorList.length === 0" class="no-anchor-tip">
暂无可用主播请先在"我的"页面添加主播
</div>
<div v-else class="anchor-list">
<div
v-for="anchor in myAnchorList"
:key="anchor.id"
class="anchor-item"
:class="{ selected: selectedAnchor?.id === anchor.id }"
@click="selectedAnchor = anchor"
>
<img class="anchor-avatar" :src="anchor.anchorIcon" alt="" />
<div class="anchor-info">
<div class="anchor-name">{{ anchor.anchorId }}</div>
<div class="anchor-detail">
<span class="anchor-gender" :class="anchor.sex === 1 ? 'male' : 'female'">
{{ anchor.sex === 1 ? '男' : '女' }}
</span>
<span class="anchor-coin">{{ anchor.coin }}K</span>
</div>
<div class="anchor-time">PK时间: {{ formatTime(anchor.pkTime * 1000) }}</div>
</div>
</div>
</div>
</div>
<template #footer>
<div class="invite-dialog-footer">
<el-button @click="inviteDialogVisible = false">取消</el-button>
<el-button type="primary" :disabled="!selectedAnchor" @click="confirmInvite">
发送邀请
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { getPkList, getUserInfo, getAnchorListById, createPkRecord } from '@/api/pk-mini'
import { getCountryNamesArray } from '@/utils/pk-mini/countryUtil'
import { TimestamptolocalTime } from '@/utils/pk-mini/timeConversion'
import { getMainUserData } from '@/utils/pk-mini/storage'
import { isGoEasyEnabled } from '@/config/pk-mini'
import {
goEasyGetMessages,
goEasySendMessage,
goEasySendImageMessage,
goEasySendPKMessage,
goEasyMessageRead,
getPkGoEasy,
GoEasy
} from '@/utils/pk-mini/goeasy'
import PictureMessage from '@/components/pk-mini/chat/PictureMessage.vue'
import MiniPKMessage from '@/components/pk-mini/chat/MiniPKMessage.vue'
import VoiceMessage from '@/components/pk-mini/chat/VoiceMessage.vue'
import { ElMessage } from 'element-plus'
// 导入本地图片
import iconSearch from '@/assets/pk-mini/Search.png'
import iconReset from '@/assets/pk-mini/Reset.png'
// 获取用户 ID兼容不同的字段名
function getUserId(user) {
return user?.id || user?.userId || user?.uid || null
}
// 状态
const isHallMode = ref(true) // true: PK大厅, false: 今日PK
const countryValue = ref(null)
const genderValue = ref(null)
const minCoin = ref(null)
const maxCoin = ref(null)
const timeRange = ref(null)
const pkList = ref([])
const hallList = ref([])
const todayList = ref([])
const page = ref(0)
const selectedItem = ref(null)
const chatUserInfo = ref({})
const messagesList = ref([])
const inputText = ref('')
const currentUser = ref({})
const chatMessagesRef = ref(null)
const fileInputRef = ref(null)
// 邀请相关状态
const inviteDialogVisible = ref(false)
const myAnchorList = ref([])
const selectedAnchor = ref(null)
// 加载状态
const loading = ref(false)
const noMore = ref(false)
const countryOptions = ref([])
const genderOptions = [
{ value: 1, label: '男' },
{ value: 2, label: '女' }
]
const formatTime = TimestamptolocalTime
// 切换 PK大厅/今日PK
function switchMode() {
isHallMode.value = !isHallMode.value
selectedItem.value = null
if (isHallMode.value) {
pkList.value = hallList.value
} else {
pkList.value = todayList.value
}
}
// 搜索
function handleSearch() {
page.value = 0
noMore.value = false
if (isHallMode.value) {
hallList.value = []
} else {
todayList.value = []
}
pkList.value = []
loadPkList()
}
// 重置
function handleReset() {
countryValue.value = null
genderValue.value = null
minCoin.value = null
maxCoin.value = null
timeRange.value = null
handleSearch()
}
// 加载更多
function loadMore() {
loadPkList()
}
// 加载PK列表
async function loadPkList() {
const userId = getUserId(currentUser.value)
if (!userId) return
if (loading.value) return
loading.value = true
const body = {
status: 0,
page: page.value,
size: 10,
userId: userId,
condition: {
type: isHallMode.value ? 2 : 1
}
}
if (countryValue.value) body.condition.country = countryValue.value
if (genderValue.value) body.condition.sex = genderValue.value
if (minCoin.value != null && maxCoin.value != null) {
body.condition.coin = { start: minCoin.value, end: maxCoin.value }
} else if (minCoin.value != null && maxCoin.value == null) {
ElMessage.error('请输入最大金币数')
loading.value = false
return
} else if (minCoin.value == null && maxCoin.value != null) {
ElMessage.error('请输入最小金币数')
loading.value = false
return
}
if (timeRange.value && isHallMode.value) {
body.condition.pkTime = {
start: timeRange.value[0] / 1000,
end: timeRange.value[1] / 1000
}
}
try {
const res = await getPkList(body)
if (res && res.length > 0) {
if (isHallMode.value) {
hallList.value.push(...res)
pkList.value = hallList.value
} else {
todayList.value.push(...res)
pkList.value = todayList.value
}
page.value++
} else {
// 没有更多数据了
noMore.value = true
}
} catch (e) {
console.error('加载 PK 列表失败', e)
noMore.value = true
} finally {
loading.value = false
}
}
// 点击主播卡片
async function handleItemClick(item) {
selectedItem.value = item
try {
const res = await getUserInfo({ id: item.senderId })
chatUserInfo.value = res
if (isGoEasyEnabled()) {
// GoEasy 已启用,加载聊天消息
const messages = await goEasyGetMessages({ id: String(item.senderId), timestamp: null })
messagesList.value = messages || []
await nextTick()
scrollToBottom()
// 异步卡片内容加载完后再滚一次
setTimeout(scrollToBottom, 300)
// 标记消息已读
goEasyMessageRead({ id: String(item.senderId) }).catch(() => {})
} else {
messagesList.value = []
ElMessage.warning('聊天功能暂时不可用GoEasy 订阅未续费)')
}
} catch (e) {
console.error('获取聊天信息失败', e)
}
}
function onMessageReceived(message) {
if (!isGoEasyEnabled()) return
// 处理接收到的消息
if (message && selectedItem.value && message.senderId === selectedItem.value.senderId) {
messagesList.value.push(message)
nextTick(() => scrollToBottom())
}
}
function scrollToBottom() {
if (chatMessagesRef.value) {
chatMessagesRef.value.scrollTop = chatMessagesRef.value.scrollHeight
}
}
// 发送消息
async function sendMessage() {
if (!isGoEasyEnabled()) {
ElMessage.warning('聊天功能暂时不可用GoEasy 订阅未续费)')
return
}
if (!inputText.value.trim()) return
if (!selectedItem.value) return
try {
const msg = await goEasySendMessage({
text: inputText.value,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
messagesList.value.push(msg)
inputText.value = ''
await nextTick()
scrollToBottom()
} catch (e) {
console.error('发送消息失败', e)
ElMessage.error('发送失败')
}
}
// 发送图片
function handleSendImage() {
if (!isGoEasyEnabled()) {
ElMessage.warning('聊天功能暂时不可用GoEasy 订阅未续费)')
return
}
if (!selectedItem.value) {
ElMessage.warning('请先选择一个主播')
return
}
fileInputRef.value?.click()
}
async function handleFileSelect(event) {
const file = event.target.files?.[0]
event.target.value = ''
if (!file || !isGoEasyEnabled()) return
if (!selectedItem.value) return
try {
const msg = await goEasySendImageMessage({
imagefile: file,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
messagesList.value.push(msg)
await nextTick()
scrollToBottom()
} catch (e) {
console.error('发送图片失败', e)
ElMessage.error('发送图片失败')
}
}
// PK邀请
async function handleInvite() {
if (!isGoEasyEnabled()) {
ElMessage.warning('邀请功能暂时不可用GoEasy 订阅未续费)')
return
}
if (!selectedItem.value) {
ElMessage.warning('请先选择一个主播')
return
}
const userId = getUserId(currentUser.value)
if (!userId) {
ElMessage.warning('用户信息异常')
return
}
// 获取我的主播列表(未邀请过的)
try {
const res = await getAnchorListById({
pkId: selectedItem.value.id,
userId: userId
})
myAnchorList.value = res || []
selectedAnchor.value = null
inviteDialogVisible.value = true
} catch (e) {
console.error('获取主播列表失败', e)
ElMessage.error('获取主播列表失败')
}
}
// 确认发送邀请
async function confirmInvite() {
if (!selectedAnchor.value || !selectedItem.value) return
const userId = getUserId(currentUser.value)
if (!userId) return
try {
// 创建 PK 记录
const pkRecord = await createPkRecord({
pkIdA: selectedItem.value.id,
pkIdB: selectedAnchor.value.id,
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 邀请消息
const msg = await goEasySendPKMessage({
msgid: pkRecord.id,
pkIdA: selectedItem.value.id,
pkIdB: selectedAnchor.value.id,
id: String(selectedItem.value.senderId),
avatar: currentUser.value.headerIcon,
nickname: currentUser.value.nickName
})
messagesList.value.push(msg)
await nextTick()
scrollToBottom()
inviteDialogVisible.value = false
ElMessage.success('邀请已发送')
} catch (e) {
console.error('发送邀请失败', e)
ElMessage.error('发送邀请失败')
}
}
onMounted(() => {
countryOptions.value = getCountryNamesArray()
currentUser.value = getMainUserData() || {}
const userId = getUserId(currentUser.value)
console.log('[PkHall] 当前用户数据:', currentUser.value)
console.log('[PkHall] 解析的用户 ID:', userId)
// 初始加载 PK 大厅数据(通过 loadPkList 统一管理 page/loading/noMore 状态)
if (userId) {
loadPkList()
} else {
console.warn('[PkHall] 未找到用户 ID无法加载数据')
}
})
onUnmounted(() => {
if (isGoEasyEnabled()) {
const goeasy = getPkGoEasy()
if (goeasy) {
try {
goeasy.im.off(GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, onMessageReceived)
} catch (e) {
console.warn('清理 GoEasy 监听器失败', e)
}
}
}
})
</script>
<style scoped lang="less">
.pk-hall {
width: 100%;
height: 100%;
background-color: #ffffff;
border: 1px solid #f1f5f9; // slate-100
border-radius: 12px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); // shadow-sm
overflow: hidden;
display: flex;
flex-direction: column;
}
// 顶部控制面板 - 固定高度
.control-panel {
width: 100%;
height: 100px;
min-height: 100px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 20px;
background: linear-gradient(180deg, #eff6ff, #ffffff); // from-blue-50 to-white
border-bottom: 1px solid #f1f5f9; // slate-100
}
.content-area {
flex: 1;
display: flex;
min-height: 0;
}
// 切换按钮
.switch-box {
position: relative;
width: 280px;
height: 50px;
background-color: #3b82f6; // blue-500
border-radius: 25px;
box-shadow: -3px 3px 4px rgba(37, 99, 235, 0.3) inset;
display: flex;
align-items: center;
}
.switch-text {
width: 50%;
height: 50px;
text-align: center;
color: #ffffff;
font-size: 18px;
line-height: 50px;
cursor: pointer;
z-index: 1;
position: relative;
}
.switch-slider {
position: absolute;
top: 0;
left: 0;
width: 140px;
height: 50px;
border-radius: 25px;
color: #2563eb; // blue-600
text-align: center;
line-height: 50px;
font-size: 18px;
font-weight: bold;
background: linear-gradient(180deg, #eff6ff, #ffffff); // from-blue-50 to-white
transition: left 0.3s ease;
z-index: 2;
}
.switch-slider.slide-right {
left: 140px;
}
// 选择器
.select-box {
display: flex;
gap: 15px;
}
.filter-select {
width: 140px;
}
// 金币输入
.coin-box {
display: flex;
gap: 15px;
}
.coin-item {
display: flex;
flex-direction: column;
}
.coin-label {
font-size: 11px;
color: #999;
margin-bottom: 4px;
}
// 时间选择
.time-box {
width: 380px;
}
// 按钮
.btn-box {
display: flex;
flex-direction: column;
gap: 8px;
}
.search-btn, .reset-btn {
width: 80px;
height: 30px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
cursor: pointer;
transition: all 0.3s;
font-size: 14px;
}
.search-btn {
background: linear-gradient(0deg, #2563eb, #3b82f6); // from-blue-600 to-blue-500
color: white;
}
.reset-btn {
background: white;
border: 1px solid #2563eb; // blue-600
color: #2563eb; // blue-600
}
.search-btn:hover, .reset-btn:hover {
transform: scale(1.05);
opacity: 0.9;
}
.btn-icon {
width: 18px;
height: 18px;
}
// 列表面板
.list-panel {
flex: 1;
min-width: 0;
overflow: hidden;
}
.pk-list {
height: 100%;
overflow: auto;
padding: 15px;
background-color: #ffffff;
border-radius: 16px 0 0 16px;
}
.pk-card {
display: flex;
padding: 20px;
margin-bottom: 15px;
background-color: #ffffff;
border: 1px solid #f1f5f9; // slate-100
border-radius: 12px;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05); // shadow-sm
cursor: pointer;
transition: all 0.3s;
}
.pk-card:hover {
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); // shadow-md
transform: scale(1.02);
}
.pk-card.selected {
background-color: rgba(239, 246, 255, 0.3); // blue-50/30
border-color: #bfdbfe; // blue-200
}
.pk-avatar {
width: 90px;
height: 90px;
border-radius: 50%;
overflow: hidden;
margin-right: 20px;
flex-shrink: 0;
}
.pk-avatar img {
width: 100%;
height: 100%;
object-fit: cover;
}
.pk-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.pk-personal {
display: flex;
align-items: center;
gap: 15px;
}
.pk-name {
font-size: 18px;
font-weight: bold;
}
.pk-gender {
padding: 2px 12px;
border-radius: 10px;
font-size: 12px;
color: white;
}
.pk-gender.male {
background-color: #60a5fa; // blue-400
}
.pk-gender.female {
background-color: #f472b6; // pink-400
}
.pk-country {
padding: 2px 10px;
background-color: #eff6ff; // blue-50
border-radius: 10px;
font-size: 12px;
color: #2563eb; // blue-600
}
.pk-time {
font-size: 14px;
color: #999;
}
.pk-stats {
display: flex;
align-items: center;
font-size: 14px;
}
.stat-icon {
width: 18px;
height: 18px;
margin-right: 8px;
}
.session-icon {
margin-left: 40px;
}
.pk-remark {
font-size: 13px;
color: #999;
}
.empty-tip {
text-align: center;
padding: 50px;
color: #2563eb; // blue-600
font-size: 16px;
}
// 聊天面板
.chat-panel {
width: 350px;
flex-shrink: 0;
border-left: 1px solid #f1f5f9; // slate-100
background-color: #ffffff;
display: flex;
flex-direction: column;
}
.chat-container {
height: 100%;
display: flex;
flex-direction: column;
}
.chat-header {
height: 50px;
text-align: center;
line-height: 50px;
font-weight: bold;
color: #666;
border-bottom: 1px solid #eee;
}
.chat-messages {
flex: 1;
overflow: auto;
padding: 15px;
}
.message-item {
display: flex;
margin-bottom: 15px;
}
.message-item.mine {
flex-direction: row-reverse;
}
.message-triangle {
width: 0;
height: 0;
border-top: 8px solid transparent;
border-right: 8px solid #f5f5f5;
border-bottom: 8px solid transparent;
margin-top: 14px;
}
.message-item.mine .message-triangle {
border-right: none;
border-left: 8px solid #7bbd0093;
}
.message-content {
max-width: 65%;
}
.message-item.pk-message .message-content {
max-width: 100%;
}
.text-message {
padding: 10px 15px;
background: #f5f5f5;
border-radius: 10px;
font-size: 14px;
line-height: 1.5;
}
.message-item.mine .text-message {
background: #7bbd0093;
}
// 输入区域
.chat-input-area {
border-top: 1px solid #eee;
}
.input-controls {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #eff6ff; // blue-50
}
.control-btns {
display: flex;
gap: 10px;
}
.control-btn {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 8px;
transition: all 0.2s;
}
.control-btn:hover {
background: white;
box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
}
.control-btn img {
width: 22px;
height: 22px;
}
.send-btn {
padding: 8px 20px;
color: #2563eb; // blue-600
cursor: pointer;
border-radius: 8px;
transition: all 0.2s;
}
.send-btn:hover {
background-color: #dbeafe; // blue-100
}
.input-box {
padding: 10px 15px;
}
.input-box textarea {
width: 100%;
height: 50px;
border: none;
outline: none;
resize: none;
font-size: 14px;
}
.chat-placeholder {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #2563eb; // blue-600
font-size: 18px;
font-weight: bold;
}
.time-box {
width: 380px;
transition: opacity 0.2s ease;
}
.time-box.is-hidden {
opacity: 0;
visibility: hidden; // 仍然占位,但看不见
pointer-events: none; // 不能点击
}
// 邀请弹窗样式
.invite-dialog-content {
max-height: 400px;
overflow-y: auto;
}
.no-anchor-tip {
text-align: center;
padding: 40px;
color: #999;
font-size: 14px;
}
.anchor-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.anchor-item {
display: flex;
align-items: center;
padding: 12px;
border: 2px solid #eee;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s;
}
.anchor-item:hover {
border-color: #60a5fa; // blue-400
background-color: rgba(239, 246, 255, 0.5); // blue-50/50
}
.anchor-item.selected {
border-color: #2563eb; // blue-600
background-color: #eff6ff; // blue-50
}
.anchor-avatar {
width: 50px;
height: 50px;
border-radius: 50%;
object-fit: cover;
margin-right: 12px;
}
.anchor-info {
flex: 1;
}
.anchor-name {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 4px;
}
.anchor-detail {
display: flex;
align-items: center;
gap: 10px;
}
.anchor-gender {
padding: 2px 10px;
border-radius: 10px;
font-size: 12px;
color: white;
}
.anchor-gender.male {
background-color: #60a5fa; // blue-400
}
.anchor-gender.female {
background-color: #f472b6; // pink-400
}
.anchor-coin {
font-size: 14px;
color: #666;
}
.anchor-time {
font-size: 12px;
color: #999;
margin-top: 4px;
}
.invite-dialog-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>