第一次提交:Vue3后台前端最新版本
This commit is contained in:
813
src/views/user/PlayerDetail.vue
Normal file
813
src/views/user/PlayerDetail.vue
Normal file
@@ -0,0 +1,813 @@
|
||||
<template>
|
||||
<div class="player-detail">
|
||||
<!-- 加载状态 -->
|
||||
<div v-if="loading" class="loading-container">
|
||||
<el-skeleton :rows="8" animated />
|
||||
</div>
|
||||
|
||||
<div v-else class="detail-content">
|
||||
<!-- 顶部导航栏 -->
|
||||
<div class="detail-header">
|
||||
<div class="header-left">
|
||||
<el-button type="primary" :icon="ArrowLeft" @click="goBack">返回</el-button>
|
||||
<span class="page-title">打手详情</span>
|
||||
</div>
|
||||
<div class="header-right">
|
||||
<el-button
|
||||
v-if="!isEditMode"
|
||||
type="warning"
|
||||
:icon="Edit"
|
||||
@click="toggleEditMode"
|
||||
:disabled="!playerInfo.yonghuid"
|
||||
>编辑</el-button>
|
||||
<template v-else>
|
||||
<el-button type="success" :icon="Check" @click="saveChanges" :loading="saving">保存</el-button>
|
||||
<el-button :icon="Close" @click="cancelEdit">取消</el-button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<el-row :gutter="24">
|
||||
<!-- 左侧:基础信息卡片 + 统计卡片 -->
|
||||
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
||||
<!-- 基础信息卡片 -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>👤 基础信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="base-info">
|
||||
<div class="avatar-wrapper">
|
||||
<el-avatar :size="100" :src="getFullImageUrl(playerInfo.avatar)" fit="cover">
|
||||
<el-icon><Avatar /></el-icon>
|
||||
</el-avatar>
|
||||
<div class="status-badges">
|
||||
<el-tag
|
||||
:type="playerInfo.zaixianzhuangtai === 1 ? 'success' : 'info'"
|
||||
size="small"
|
||||
effect="dark"
|
||||
>
|
||||
{{ playerInfo.zaixianzhuangtai === 1 ? '在线' : '离线' }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
:type="playerInfo.zhanghaozhuangtai === 1 ? 'success' : 'danger'"
|
||||
size="small"
|
||||
effect="dark"
|
||||
>
|
||||
{{ playerInfo.zhanghaozhuangtai === 1 ? '正常' : '封禁' }}
|
||||
</el-tag>
|
||||
<el-tag
|
||||
:type="playerInfo.zhuangtai === 1 ? 'success' : 'warning'"
|
||||
size="small"
|
||||
effect="dark"
|
||||
>
|
||||
{{ playerInfo.zhuangtai === 1 ? '空闲' : '接单中' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="UID">
|
||||
<span class="copyable" @click="copyText(playerInfo.yonghuid)">
|
||||
{{ playerInfo.yonghuid || '--' }} <el-icon><CopyDocument /></el-icon>
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="昵称">{{ playerInfo.nicheng || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="称号">
|
||||
<div class="chenghao-wrapper">
|
||||
<span>{{ playerInfo.chenghao || '无' }}</span>
|
||||
<!-- 金牌打手按钮:非编辑模式下显示 -->
|
||||
<el-button
|
||||
v-if="!isEditMode"
|
||||
size="small"
|
||||
:type="isGoldTitle ? 'danger' : 'primary'"
|
||||
@click="handleChenghaoChange"
|
||||
:disabled="!hasChenghaoPermission"
|
||||
>
|
||||
{{ isGoldTitle ? '降级为普通打手' : '升级为金牌选手' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="电话">{{ playerInfo.dianhua || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="微信号">{{ playerInfo.wechat || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="手机号">{{ playerInfo.phone || '--' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="注册时间">{{ formatTime(playerInfo.create_time) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="IP地址">
|
||||
<span class="copyable" @click="copyText(playerInfo.ip)">
|
||||
{{ playerInfo.ip || '--' }} <el-icon><CopyDocument /></el-icon>
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 统计卡片(保持不变) -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>📊 数据统计</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">接单总量</div>
|
||||
<div class="stat-value">{{ playerInfo.jiedanzongliang || 0 }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">成交总量</div>
|
||||
<div class="stat-value success">{{ playerInfo.chengjiaozongliang || 0 }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">退款总量</div>
|
||||
<div class="stat-value danger">{{ playerInfo.tuikuanliang || 0 }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">今日接单</div>
|
||||
<div class="stat-value">{{ playerInfo.jinrijiedan || 0 }}</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider />
|
||||
<el-row :gutter="16" align="middle">
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">成交率</div>
|
||||
<el-progress
|
||||
type="circle"
|
||||
:percentage="completionRate"
|
||||
:width="80"
|
||||
:stroke-width="6"
|
||||
status="success"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="stat-percent">{{ completionRate }}%</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16" align="middle">
|
||||
<el-col :span="12">
|
||||
<div class="stat-item">
|
||||
<div class="stat-label">退款率</div>
|
||||
<el-progress
|
||||
type="circle"
|
||||
:percentage="refundRate"
|
||||
:width="80"
|
||||
:stroke-width="6"
|
||||
status="warning"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<div class="stat-percent">{{ refundRate }}%</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</el-col>
|
||||
|
||||
<!-- 右侧:详细信息和可编辑字段 -->
|
||||
<el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16">
|
||||
<!-- 财务信息卡片 -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>💰 财务信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="editData" label-width="120px" :disabled="!isEditMode">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="可提现余额">
|
||||
<el-input-number
|
||||
v-if="isEditMode"
|
||||
v-model="editData.yue"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:step="10"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<span v-else>¥{{ formatPrice(playerInfo.yue) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="赚取总额">
|
||||
<span>¥{{ formatPrice(playerInfo.zonge) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="积分">
|
||||
<el-input-number
|
||||
v-if="isEditMode"
|
||||
v-model="editData.jifen"
|
||||
:min="0"
|
||||
:step="10"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<span v-else>{{ playerInfo.jifen || 0 }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="押金">
|
||||
<el-input-number
|
||||
v-if="isEditMode"
|
||||
v-model="editData.yajin"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
:step="10"
|
||||
style="width: 100%"
|
||||
/>
|
||||
<span v-else>¥{{ formatPrice(playerInfo.yajin) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="今日收益">
|
||||
<span>¥{{ formatPrice(playerInfo.jinrishouyi) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="今月收益">
|
||||
<span>¥{{ formatPrice(playerInfo.jinyueshouyi) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 状态信息卡片 -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>⚙️ 状态管理</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-form :model="isEditMode ? editData : playerInfo" label-width="120px">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="在线状态">
|
||||
<el-select
|
||||
v-if="isEditMode"
|
||||
v-model="editData.zaixianzhuangtai"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option :value="1" label="在线" />
|
||||
<el-option :value="0" label="离线" />
|
||||
</el-select>
|
||||
<span v-else>{{ playerInfo.zaixianzhuangtai === 1 ? '在线' : '离线' }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="账号状态">
|
||||
<el-select
|
||||
v-if="isEditMode"
|
||||
v-model="editData.zhanghaozhuangtai"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option :value="1" label="正常" />
|
||||
<el-option :value="0" label="封禁" />
|
||||
</el-select>
|
||||
<span v-else>{{ playerInfo.zhanghaozhuangtai === 1 ? '正常' : '封禁' }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="工作状态">
|
||||
<el-select
|
||||
v-if="isEditMode"
|
||||
v-model="editData.zhuangtai"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option :value="1" label="空闲" />
|
||||
<el-option :value="0" label="接单中" />
|
||||
</el-select>
|
||||
<span v-else>{{ playerInfo.zhuangtai === 1 ? '空闲' : '接单中' }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 会员信息卡片(只读+操作按钮) -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>🎫 会员信息</span>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="openMemberDialog"
|
||||
:disabled="!hasMemberPermission"
|
||||
>添加会员</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div class="member-list">
|
||||
<div v-for="member in memberList" :key="member.id" class="member-item">
|
||||
<el-tag :type="member.is_active ? 'success' : 'info'" effect="plain">
|
||||
{{ member.huiyuan_name }} 到期: {{ formatTime(member.daoqi_time) }}
|
||||
</el-tag>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="removeMember(member)"
|
||||
:disabled="!hasMemberPermission"
|
||||
>移除</el-button>
|
||||
</div>
|
||||
<div v-if="memberList.length === 0" class="empty-message">暂无会员,点击上方按钮添加</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 其他信息卡片 -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>📝 其他信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="邀请人ID">
|
||||
<span class="copyable" @click="copyText(playerInfo.yaoqingren)">
|
||||
{{ playerInfo.yaoqingren || '--' }} <el-icon><CopyDocument /></el-icon>
|
||||
</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="介绍">
|
||||
<el-tooltip v-if="playerInfo.jieshao" :content="playerInfo.jieshao" placement="top">
|
||||
<span class="truncate">{{ playerInfo.jieshao }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>--</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 添加会员弹窗 -->
|
||||
<el-dialog v-model="memberDialogVisible" title="添加会员" width="400px">
|
||||
<el-form :model="memberForm" label-width="80px">
|
||||
<el-form-item label="会员类型" required>
|
||||
<el-select v-model="memberForm.huiyuan_id" placeholder="请选择会员" style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in allMembers"
|
||||
:key="item.huiyuan_id"
|
||||
:label="item.jieshao"
|
||||
:value="item.huiyuan_id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="天数" required>
|
||||
<el-input-number v-model="memberForm.days" :min="1" :step="1" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="memberDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="addMember" :loading="memberAdding">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { ArrowLeft, Edit, Check, Close, CopyDocument, Avatar } from '@element-plus/icons-vue'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
// 基础数据
|
||||
const loading = ref(false)
|
||||
const saving = ref(false)
|
||||
const playerId = ref('')
|
||||
const username = ref(localStorage.getItem('username') || '')
|
||||
const playerInfo = ref({})
|
||||
const originalInfo = ref({})
|
||||
const memberList = ref([])
|
||||
const allMembers = ref([])
|
||||
const isEditMode = ref(false)
|
||||
const editData = ref({})
|
||||
|
||||
// 会员弹窗
|
||||
const memberDialogVisible = ref(false)
|
||||
const memberForm = reactive({ huiyuan_id: '', days: 30 })
|
||||
const memberAdding = ref(false)
|
||||
|
||||
// 权限控制
|
||||
const userPermissions = ref([])
|
||||
|
||||
const isGoldTitle = computed(() => playerInfo.value.chenghao === '金牌选手')
|
||||
const hasMemberPermission = computed(() => userPermissions.value.includes('001ff') || userPermissions.value.includes('001gg'))
|
||||
const hasChenghaoPermission = computed(() => userPermissions.value.includes('001hh'))
|
||||
|
||||
// 辅助函数
|
||||
const getFullImageUrl = (url) => {
|
||||
if (!url) return ''
|
||||
const ossUrl = window.$ossURL || ''
|
||||
return url.startsWith('http') ? url : ossUrl + url
|
||||
}
|
||||
const formatPrice = (val) => parseFloat(val || 0).toFixed(2)
|
||||
const formatTime = (time) => {
|
||||
if (!time) return '--'
|
||||
const date = new Date(time)
|
||||
return `${date.getFullYear()}-${(date.getMonth()+1).toString().padStart(2,'0')}-${date.getDate().toString().padStart(2,'0')} ${date.getHours().toString().padStart(2,'0')}:${date.getMinutes().toString().padStart(2,'0')}`
|
||||
}
|
||||
const copyText = (text) => {
|
||||
if (!text || text === '--') return
|
||||
navigator.clipboard.writeText(text).then(() => ElMessage.success('复制成功')).catch(() => ElMessage.error('复制失败'))
|
||||
}
|
||||
const goBack = () => router.back()
|
||||
|
||||
// 统计
|
||||
const completionRate = computed(() => {
|
||||
const total = playerInfo.value.jiedanzongliang || 0
|
||||
const completed = playerInfo.value.chengjiaozongliang || 0
|
||||
return total === 0 ? 0 : Math.round((completed / total) * 100)
|
||||
})
|
||||
const refundRate = computed(() => {
|
||||
const completed = playerInfo.value.chengjiaozongliang || 0
|
||||
const refund = playerInfo.value.tuikuanliang || 0
|
||||
return completed === 0 ? 0 : Math.round((refund / completed) * 100)
|
||||
})
|
||||
|
||||
// 获取详情
|
||||
const fetchDetail = async () => {
|
||||
if (!playerId.value) return
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/kefuhqdsxq', {
|
||||
phone: username.value,
|
||||
uid: playerId.value
|
||||
})
|
||||
if (res.code === 0) {
|
||||
const data = res.data
|
||||
playerInfo.value = data.user_info || {}
|
||||
originalInfo.value = JSON.parse(JSON.stringify(playerInfo.value))
|
||||
memberList.value = data.member_list || []
|
||||
allMembers.value = data.all_members || []
|
||||
userPermissions.value = data.permissions || []
|
||||
} else if (res.code === 403) {
|
||||
ElMessage.error('无权限访问')
|
||||
router.back()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '获取打手详情失败')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取打手详情失败', error)
|
||||
ElMessage.error('获取打手详情失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑模式
|
||||
const toggleEditMode = () => {
|
||||
editData.value = JSON.parse(JSON.stringify(playerInfo.value))
|
||||
isEditMode.value = true
|
||||
}
|
||||
const cancelEdit = () => {
|
||||
isEditMode.value = false
|
||||
editData.value = {}
|
||||
}
|
||||
const saveChanges = async () => {
|
||||
const changes = {}
|
||||
for (const key in editData.value) {
|
||||
if (editData.value[key] !== playerInfo.value[key]) {
|
||||
changes[key] = editData.value[key]
|
||||
}
|
||||
}
|
||||
if (Object.keys(changes).length === 0) {
|
||||
ElMessage.warning('未做任何修改')
|
||||
cancelEdit()
|
||||
return
|
||||
}
|
||||
saving.value = true
|
||||
try {
|
||||
let success = true
|
||||
for (const [key, val] of Object.entries(changes)) {
|
||||
let caozuo = ''
|
||||
let value = val
|
||||
switch (key) {
|
||||
case 'yue':
|
||||
caozuo = val > playerInfo.value.yue ? 'jia_yue' : 'jian_yue'
|
||||
value = Math.abs(val - playerInfo.value.yue)
|
||||
break
|
||||
case 'jifen':
|
||||
caozuo = val > playerInfo.value.jifen ? 'jia_jifen' : 'jian_jifen'
|
||||
value = Math.abs(val - playerInfo.value.jifen)
|
||||
break
|
||||
case 'yajin':
|
||||
caozuo = val > playerInfo.value.yajin ? 'jia_yajin' : 'jian_yajin'
|
||||
value = Math.abs(val - playerInfo.value.yajin)
|
||||
break
|
||||
case 'zhanghaozhuangtai':
|
||||
caozuo = 'gai_zhanghaozhuangtai'
|
||||
value = val
|
||||
break
|
||||
case 'zaixianzhuangtai':
|
||||
caozuo = 'gai_zaixianzhuangtai'
|
||||
value = val
|
||||
break
|
||||
case 'zhuangtai':
|
||||
caozuo = 'gai_zhuangtai'
|
||||
value = val
|
||||
break
|
||||
default:
|
||||
continue
|
||||
}
|
||||
const res = await request.post('/houtai/kefuxgds', {
|
||||
username: username.value,
|
||||
dashou_id: playerId.value,
|
||||
caozuo: caozuo,
|
||||
value: value
|
||||
})
|
||||
if (res.code !== 0) {
|
||||
success = false
|
||||
ElMessage.error(`修改 ${key} 失败:${res.msg}`)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
ElMessage.success('修改成功')
|
||||
await fetchDetail()
|
||||
cancelEdit()
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('修改失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 称号修改
|
||||
const handleChenghaoChange = async () => {
|
||||
const newTitle = isGoldTitle.value ? '普通打手' : '金牌选手'
|
||||
try {
|
||||
const res = await request.post('/houtai/kefuxgds', {
|
||||
username: username.value,
|
||||
dashou_id: playerId.value,
|
||||
caozuo: 'gai_chenghao',
|
||||
value: newTitle
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(`称号已修改为“${newTitle}”`)
|
||||
await fetchDetail()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '修改称号失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('修改称号失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 添加会员
|
||||
const openMemberDialog = () => {
|
||||
memberForm.huiyuan_id = ''
|
||||
memberForm.days = 30
|
||||
memberDialogVisible.value = true
|
||||
}
|
||||
const addMember = async () => {
|
||||
if (!memberForm.huiyuan_id) {
|
||||
ElMessage.warning('请选择会员类型')
|
||||
return
|
||||
}
|
||||
memberAdding.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/kefuxgds', {
|
||||
username: username.value,
|
||||
dashou_id: playerId.value,
|
||||
caozuo: 'jia_huiyuan',
|
||||
huiyuan_id: memberForm.huiyuan_id,
|
||||
value: memberForm.days
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('添加会员成功')
|
||||
memberDialogVisible.value = false
|
||||
await fetchDetail()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '添加失败')
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('添加失败')
|
||||
} finally {
|
||||
memberAdding.value = false
|
||||
}
|
||||
}
|
||||
const removeMember = async (member) => {
|
||||
ElMessageBox.confirm(`确定移除会员“${member.huiyuan_name}”吗?`, '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(async () => {
|
||||
const res = await request.post('/houtai/kefuxgds', {
|
||||
username: username.value,
|
||||
dashou_id: playerId.value,
|
||||
caozuo: 'jian_huiyuan',
|
||||
huiyuan_id: member.huiyuan_id
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('移除成功')
|
||||
await fetchDetail()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '移除失败')
|
||||
}
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 关键:从路由参数中获取 playerId(参数名必须为 playerId)
|
||||
onMounted(() => {
|
||||
playerId.value = route.params.playerId
|
||||
if (!playerId.value) {
|
||||
ElMessage.error('打手ID不存在')
|
||||
router.back()
|
||||
return
|
||||
}
|
||||
fetchDetail()
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
/* 保持原有样式,新增以下 */
|
||||
.chenghao-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.member-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.member-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.empty-message {
|
||||
color: #999;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
/* 其余样式保持不变(从原代码复制) */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.player-detail {
|
||||
padding: 20px;
|
||||
background-color: #f5f9fc;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24px;
|
||||
background: white;
|
||||
padding: 16px 24px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #1a2634;
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.info-card {
|
||||
margin-bottom: 24px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
font-weight: 600;
|
||||
color: #1a2634;
|
||||
}
|
||||
|
||||
.base-info {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.status-badges {
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.copyable {
|
||||
cursor: pointer;
|
||||
color: #409eff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.copyable:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
padding: 12px 0;
|
||||
}
|
||||
.stat-label {
|
||||
font-size: 13px;
|
||||
color: #6b7a88;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1a2634;
|
||||
}
|
||||
.stat-value.success {
|
||||
color: #67c23a;
|
||||
}
|
||||
.stat-value.danger {
|
||||
color: #f56c6c;
|
||||
}
|
||||
.stat-percent {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #1a2634;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-divider {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.member-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
.member-tag {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
max-width: 200px;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* 手机适配 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.player-detail {
|
||||
padding: 12px;
|
||||
}
|
||||
.detail-header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
.header-right {
|
||||
width: 100%;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.stat-value {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user