功能:礼物功能基本搭建好
This commit is contained in:
parent
8b377c53e2
commit
b08765e035
54
FINAL_FIX_LIVE_404.sql
Normal file
54
FINAL_FIX_LIVE_404.sql
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
-- ========================================
|
||||
-- 最终修复:直播管理404问题
|
||||
-- ========================================
|
||||
|
||||
-- 问题根源:
|
||||
-- 礼物打赏菜单(id=823)的component是 /liveManage/gift/records/index
|
||||
-- 这与前端独立的 giftManageRouter (/gift) 冲突
|
||||
|
||||
-- 解决方案:将礼物打赏从直播管理中移除
|
||||
|
||||
-- 步骤1:隐藏直播管理下的礼物打赏菜单
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 0
|
||||
WHERE id = 823
|
||||
AND pid = 675
|
||||
AND name = '礼物打赏';
|
||||
|
||||
-- 步骤2:确保直播管理菜单本身是显示的
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 1
|
||||
WHERE id = 675
|
||||
AND name = '直播管理';
|
||||
|
||||
-- 步骤3:确保所有直播管理的子菜单都是显示的(除了礼物打赏)
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 1
|
||||
WHERE pid = 675
|
||||
AND id != 823;
|
||||
|
||||
-- 验证修复结果
|
||||
SELECT
|
||||
'=== 直播管理菜单 ===' as section,
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE id = 675 OR pid = 675
|
||||
ORDER BY pid, sort;
|
||||
|
||||
-- 检查是否还有其他冲突
|
||||
SELECT
|
||||
'=== 可能的路径冲突 ===' as section,
|
||||
component,
|
||||
COUNT(*) as count,
|
||||
GROUP_CONCAT(name SEPARATOR ' | ') as menu_names
|
||||
FROM eb_system_menu
|
||||
WHERE is_show = 1
|
||||
AND component LIKE '/liveManage%'
|
||||
GROUP BY component
|
||||
HAVING count > 1;
|
||||
|
|
@ -1,97 +1,125 @@
|
|||
import request from '@/utils/request';
|
||||
import request from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 礼物列表
|
||||
*/
|
||||
// 获取礼物打赏记录列表
|
||||
export function getGiftRecords(params) {
|
||||
return request({
|
||||
url: '/admin/gift/records',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取礼物统计数据
|
||||
export function getGiftStatistics() {
|
||||
return request({
|
||||
url: '/admin/gift/statistics',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取礼物配置列表
|
||||
export function getGiftConfigList() {
|
||||
return request({
|
||||
url: '/admin/gift/config/list',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 添加礼物配置
|
||||
export function addGiftConfig(data) {
|
||||
return request({
|
||||
url: '/admin/gift/config/add',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新礼物配置
|
||||
export function updateGiftConfig(data) {
|
||||
return request({
|
||||
url: '/admin/gift/config/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除礼物配置
|
||||
export function deleteGiftConfig(id) {
|
||||
return request({
|
||||
url: `/admin/gift/config/delete/${id}`,
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取充值套餐列表
|
||||
export function getRechargePackages() {
|
||||
return request({
|
||||
url: '/admin/gift/recharge/packages',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 更新充值套餐
|
||||
export function updateRechargePackage(data) {
|
||||
return request({
|
||||
url: '/admin/gift/recharge/package/update',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取充值记录
|
||||
export function getRechargeRecords(params) {
|
||||
return request({
|
||||
url: '/admin/gift/recharge/records',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// ========== 礼物管理 ==========
|
||||
|
||||
// 获取礼物列表
|
||||
export function giftListApi(params) {
|
||||
return request({
|
||||
url: '/admin/gift/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼物详情
|
||||
*/
|
||||
export function giftDetailApi(id) {
|
||||
return request({
|
||||
url: `/admin/gift/detail/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加礼物
|
||||
*/
|
||||
// 添加礼物
|
||||
export function giftAddApi(data) {
|
||||
return request({
|
||||
url: '/admin/gift/add',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物
|
||||
*/
|
||||
export function giftUpdateApi(id, data) {
|
||||
// 更新礼物
|
||||
export function giftUpdateApi(data) {
|
||||
return request({
|
||||
url: `/admin/gift/update/${id}`,
|
||||
url: '/admin/gift/update',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物状态
|
||||
*/
|
||||
// 删除礼物
|
||||
export function giftDeleteApi(ids) {
|
||||
return request({
|
||||
url: '/admin/gift/delete',
|
||||
method: 'post',
|
||||
data: { ids: Array.isArray(ids) ? ids : [ids] }
|
||||
})
|
||||
}
|
||||
|
||||
// 更新礼物状态
|
||||
export function giftStatusApi(id, status) {
|
||||
return request({
|
||||
url: `/admin/gift/status/${id}`,
|
||||
url: '/admin/gift/status',
|
||||
method: 'post',
|
||||
params: { status }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新心动礼物状态
|
||||
*/
|
||||
export function giftHeartbeatApi(id, isHeartbeat) {
|
||||
return request({
|
||||
url: `/admin/gift/heartbeat/${id}`,
|
||||
method: 'post',
|
||||
params: { isHeartbeat }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除礼物
|
||||
*/
|
||||
export function giftDeleteApi(id) {
|
||||
return request({
|
||||
url: `/admin/gift/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除礼物
|
||||
*/
|
||||
export function giftBatchDeleteApi(ids) {
|
||||
return request({
|
||||
url: '/admin/gift/batch-delete',
|
||||
method: 'post',
|
||||
data: { ids }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼物统计
|
||||
*/
|
||||
export function giftStatisticsApi() {
|
||||
return request({
|
||||
url: '/admin/gift/statistics',
|
||||
method: 'get'
|
||||
});
|
||||
data: { id, status }
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ import monitorRouter from './modules/monitor'; // 数据监控
|
|||
import userManageRouter from './modules/userManage'; // 用户管理
|
||||
import liveManageRouter from './modules/liveManage'; // 直播管理
|
||||
import socialManageRouter from './modules/socialManage'; // 社交互动
|
||||
import giftManageRouter from './modules/giftManage'; // 礼物打赏
|
||||
import virtualPropsRouter from './modules/virtualProps'; // 虚拟道具
|
||||
import activityManageRouter from './modules/activityManage'; // 营销活动
|
||||
import taskManageRouter from './modules/taskManage'; // 任务系统
|
||||
|
|
@ -86,9 +85,7 @@ export const constantRoutes = [
|
|||
liveManageRouter,
|
||||
// 4. 社交互动
|
||||
socialManageRouter,
|
||||
// 5. 礼物打赏
|
||||
giftManageRouter,
|
||||
// 6. 虚拟道具
|
||||
// 5. 虚拟道具
|
||||
virtualPropsRouter,
|
||||
// 7. 营销活动
|
||||
activityManageRouter,
|
||||
|
|
|
|||
|
|
@ -1,40 +1,24 @@
|
|||
import Layout from '@/layout';
|
||||
|
||||
/**
|
||||
* 礼物打赏 - 整合路由
|
||||
* 包含:礼物、礼物数量、打赏记录
|
||||
* 礼物打赏管理
|
||||
*/
|
||||
const giftManageRouter = {
|
||||
path: '/giftManage',
|
||||
path: '/gift',
|
||||
component: Layout,
|
||||
redirect: '/giftManage/list',
|
||||
redirect: '/gift/records/index',
|
||||
name: 'GiftManage',
|
||||
alwaysShow: true,
|
||||
meta: {
|
||||
title: '礼物打赏',
|
||||
icon: 'el-icon-present',
|
||||
},
|
||||
children: [
|
||||
// 礼物列表
|
||||
{
|
||||
path: 'list',
|
||||
component: () => import('@/views/gift/index'),
|
||||
name: 'GiftList',
|
||||
meta: { title: '礼物列表', icon: '' },
|
||||
},
|
||||
// 礼物数量
|
||||
{
|
||||
path: 'num',
|
||||
component: () => import('@/views/giftnum/index'),
|
||||
name: 'GiftNum',
|
||||
meta: { title: '礼物数量', icon: '' },
|
||||
},
|
||||
// 打赏记录
|
||||
{
|
||||
path: 'reward/record',
|
||||
component: () => import('@/views/giftreward/record/index'),
|
||||
name: 'GiftRewardRecord',
|
||||
meta: { title: '打赏记录', icon: '' },
|
||||
path: 'records/index',
|
||||
component: () => import('@/views/gift/records/index.vue'),
|
||||
name: 'GiftRecords',
|
||||
meta: { title: '打赏记录', icon: 'el-icon-document' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,43 +18,57 @@ const liveManageRouter = {
|
|||
// 房间管理(包含分类管理)
|
||||
{
|
||||
path: 'room/list',
|
||||
component: () => import('@/views/room/list/index'),
|
||||
component: () => import('@/views/room/list/index.vue'),
|
||||
name: 'RoomList',
|
||||
meta: { title: '房间列表', icon: '' },
|
||||
},
|
||||
// 家族管理
|
||||
{
|
||||
path: 'family/list',
|
||||
component: () => import('@/views/family/list/index'),
|
||||
component: () => import('@/views/family/list/index.vue'),
|
||||
name: 'FamilyList',
|
||||
meta: { title: '家族列表', icon: '' },
|
||||
},
|
||||
{
|
||||
path: 'family/level',
|
||||
component: () => import('@/views/family/level/index'),
|
||||
component: () => import('@/views/family/level/index.vue'),
|
||||
name: 'FamilyLevel',
|
||||
meta: { title: '家族级别', icon: '' },
|
||||
},
|
||||
{
|
||||
path: 'family/member',
|
||||
component: () => import('@/views/family/member/index'),
|
||||
component: () => import('@/views/family/member/index.vue'),
|
||||
name: 'FamilyMember',
|
||||
meta: { title: '家族成员', icon: '' },
|
||||
},
|
||||
// 粉丝团
|
||||
{
|
||||
path: 'fanGroup/list',
|
||||
component: () => import('@/views/fanGroup/list/index'),
|
||||
component: () => import('@/views/fanGroup/list/index.vue'),
|
||||
name: 'FanGroupList',
|
||||
meta: { title: '粉丝团管理', icon: '' },
|
||||
},
|
||||
// 主播管理
|
||||
{
|
||||
path: 'streamer/list',
|
||||
component: () => import('@/views/streamer/list/index'),
|
||||
component: () => import('@/views/streamer/list/index.vue'),
|
||||
name: 'StreamerList',
|
||||
meta: { title: '主播管理', icon: '' },
|
||||
},
|
||||
// 礼物打赏
|
||||
{
|
||||
path: 'gift/records/index',
|
||||
component: () => import('@/views/gift/records/index.vue'),
|
||||
name: 'GiftRecords',
|
||||
meta: { title: '打赏记录', icon: '' },
|
||||
},
|
||||
// 礼物管理
|
||||
{
|
||||
path: 'gift/manage/index',
|
||||
component: () => import('@/views/gift/manage/index.vue'),
|
||||
name: 'GiftManage',
|
||||
meta: { title: '礼物管理', icon: '' },
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
|||
200
Zhibo/admin/src/views/gift/config/index.vue
Normal file
200
Zhibo/admin/src/views/gift/config/index.vue
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 操作按钮 -->
|
||||
<el-row style="margin-bottom: 20px;">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">添加礼物</el-button>
|
||||
</el-row>
|
||||
|
||||
<!-- 礼物列表 -->
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%;">
|
||||
<el-table-column label="ID" width="80" align="center">
|
||||
<template slot-scope="{row}">{{ row.id }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="礼物图标" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<img v-if="row.icon" :src="row.icon" style="width: 50px; height: 50px; object-fit: cover;">
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="礼物名称" width="150" align="center">
|
||||
<template slot-scope="{row}">{{ row.name }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="价格(虚拟币)" width="150" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<span style="color: #F56C6C; font-weight: bold;">{{ row.price }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="排序" width="100" align="center">
|
||||
<template slot-scope="{row}">{{ row.sort_order }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.is_enabled === 1 ? 'success' : 'danger'">
|
||||
{{ row.is_enabled === 1 ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="创建时间" width="180" align="center">
|
||||
<template slot-scope="{row}">{{ row.create_time }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" min-width="200">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleEdit(row)">编辑</el-button>
|
||||
<el-button v-if="row.is_enabled === 1" type="warning" size="mini" @click="handleToggleStatus(row, 0)">禁用</el-button>
|
||||
<el-button v-else type="success" size="mini" @click="handleToggleStatus(row, 1)">启用</el-button>
|
||||
<el-button type="danger" size="mini" @click="handleDelete(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加/编辑对话框 -->
|
||||
<el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-form-item label="礼物名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入礼物名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="礼物图标" prop="icon">
|
||||
<el-input v-model="form.icon" placeholder="请输入图标URL" />
|
||||
</el-form-item>
|
||||
<el-form-item label="价格" prop="price">
|
||||
<el-input-number v-model="form.price" :min="0" :precision="2" placeholder="请输入价格" />
|
||||
</el-form-item>
|
||||
<el-form-item label="动画效果">
|
||||
<el-input v-model="form.animation" placeholder="请输入动画效果URL(可选)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" placeholder="数字越小越靠前" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.isEnabled">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getGiftConfigList, addGiftConfig, updateGiftConfig, deleteGiftConfig } from '@/api/gift'
|
||||
|
||||
export default {
|
||||
name: 'GiftConfig',
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
listLoading: false,
|
||||
dialogVisible: false,
|
||||
dialogTitle: '添加礼物',
|
||||
form: {
|
||||
id: null,
|
||||
name: '',
|
||||
icon: '',
|
||||
price: 0,
|
||||
animation: '',
|
||||
sortOrder: 0,
|
||||
isEnabled: 1
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: '请输入礼物名称', trigger: 'blur' }],
|
||||
icon: [{ required: true, message: '请输入图标URL', trigger: 'blur' }],
|
||||
price: [{ required: true, message: '请输入价格', trigger: 'blur' }]
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
getGiftConfigList().then(response => {
|
||||
this.list = response || []
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleAdd() {
|
||||
this.dialogTitle = '添加礼物'
|
||||
this.form = {
|
||||
id: null,
|
||||
name: '',
|
||||
icon: '',
|
||||
price: 0,
|
||||
animation: '',
|
||||
sortOrder: 0,
|
||||
isEnabled: 1
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.dialogTitle = '编辑礼物'
|
||||
this.form = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
icon: row.icon,
|
||||
price: row.price,
|
||||
animation: row.animation || '',
|
||||
sortOrder: row.sort_order,
|
||||
isEnabled: row.is_enabled
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate(valid => {
|
||||
if (valid) {
|
||||
const api = this.form.id ? updateGiftConfig : addGiftConfig
|
||||
api(this.form).then(() => {
|
||||
this.$message.success(this.form.id ? '更新成功' : '添加成功')
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
handleToggleStatus(row, status) {
|
||||
const form = {
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
icon: row.icon,
|
||||
price: row.price,
|
||||
animation: row.animation || '',
|
||||
sortOrder: row.sort_order,
|
||||
isEnabled: status
|
||||
}
|
||||
updateGiftConfig(form).then(() => {
|
||||
this.$message.success('状态更新成功')
|
||||
this.getList()
|
||||
})
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm('确定要删除这个礼物吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteGiftConfig(row.id).then(() => {
|
||||
this.$message.success('删除成功')
|
||||
this.getList()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
451
Zhibo/admin/src/views/gift/manage/index.vue
Normal file
451
Zhibo/admin/src/views/gift/manage/index.vue
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 统计卡片 -->
|
||||
<el-row :gutter="20" class="mb20">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<i class="el-icon-present stat-icon" style="color: #409EFF"></i>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.total }}</div>
|
||||
<div class="stat-label">礼物总数</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<i class="el-icon-check stat-icon" style="color: #67C23A"></i>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.enabled }}</div>
|
||||
<div class="stat-label">启用中</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<i class="el-icon-close stat-icon" style="color: #F56C6C"></i>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.disabled }}</div>
|
||||
<div class="stat-label">已禁用</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<i class="el-icon-coin stat-icon" style="color: #E6A23C"></i>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.totalValue }}</div>
|
||||
<div class="stat-label">总价值(钻石)</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 搜索和操作栏 -->
|
||||
<el-card class="mb20">
|
||||
<el-form :inline="true" :model="queryParams" class="demo-form-inline">
|
||||
<el-form-item label="礼物名称">
|
||||
<el-input v-model="queryParams.name" placeholder="请输入礼物名称" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="启用" :value="1" />
|
||||
<el-option label="禁用" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-row>
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">添加礼物</el-button>
|
||||
<el-button type="danger" icon="el-icon-delete" :disabled="multiple" @click="handleDelete">批量删除</el-button>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 礼物列表 -->
|
||||
<el-card>
|
||||
<el-table v-loading="loading" :data="giftList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="礼物图标" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-image
|
||||
:src="scope.row.image"
|
||||
:preview-src-list="[scope.row.image]"
|
||||
style="width: 50px; height: 50px"
|
||||
fit="cover"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="礼物名称" align="center" prop="name" />
|
||||
<el-table-column label="价格(钻石)" align="center" prop="diamondPrice" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-tag type="warning">{{ scope.row.diamondPrice }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="亲密度" align="center" prop="intimacy" width="100" />
|
||||
<el-table-column label="等级" align="center" prop="level" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="['', 'success', 'info', 'warning', 'danger'][scope.row.level] || 'info'">
|
||||
{{ scope.row.level }}级
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" align="center" prop="sort" width="80" />
|
||||
<el-table-column label="状态" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180" />
|
||||
<el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" style="color: #F56C6C">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.page"
|
||||
:limit.sync="queryParams.limit"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-card>
|
||||
|
||||
<!-- 添加或修改礼物对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="礼物名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入礼物名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="礼物图标" prop="image">
|
||||
<el-upload
|
||||
class="avatar-uploader"
|
||||
action="#"
|
||||
:show-file-list="false"
|
||||
:http-request="handleUpload"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<img v-if="form.image" :src="form.image" class="avatar">
|
||||
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
||||
</el-upload>
|
||||
<div class="el-upload__tip">建议上传200x200像素的PNG图片</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="价格(钻石)" prop="diamondPrice">
|
||||
<el-input-number v-model="form.diamondPrice" :min="0.01" :max="999999" :precision="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="亲密度" prop="intimacy">
|
||||
<el-input-number v-model="form.intimacy" :min="0" :max="999999" />
|
||||
</el-form-item>
|
||||
<el-form-item label="礼物等级" prop="level">
|
||||
<el-select v-model="form.level" placeholder="请选择等级">
|
||||
<el-option label="1级" :value="1" />
|
||||
<el-option label="2级" :value="2" />
|
||||
<el-option label="3级" :value="3" />
|
||||
<el-option label="4级" :value="4" />
|
||||
<el-option label="5级" :value="5" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否心动礼物" prop="isHeartbeat">
|
||||
<el-switch v-model="form.isHeartbeat" :active-value="1" :inactive-value="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="form.sort" :min="0" :max="9999" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { giftListApi, giftAddApi, giftUpdateApi, giftDeleteApi, giftStatusApi } from '@/api/gift';
|
||||
import DataPagination from '@/components/common/DataPagination';
|
||||
|
||||
export default {
|
||||
name: 'GiftManage',
|
||||
components: {
|
||||
pagination: DataPagination
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
multiple: true,
|
||||
ids: [],
|
||||
total: 0,
|
||||
giftList: [],
|
||||
title: '',
|
||||
open: false,
|
||||
statistics: {
|
||||
total: 0,
|
||||
enabled: 0,
|
||||
disabled: 0,
|
||||
totalValue: 0
|
||||
},
|
||||
queryParams: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
name: '',
|
||||
status: ''
|
||||
},
|
||||
form: {},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '礼物名称不能为空', trigger: 'blur' }
|
||||
],
|
||||
image: [
|
||||
{ required: true, message: '请上传礼物图标', trigger: 'change' }
|
||||
],
|
||||
diamondPrice: [
|
||||
{ required: true, message: '价格不能为空', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getStatistics();
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true;
|
||||
giftListApi(this.queryParams).then(response => {
|
||||
const data = response.data || {};
|
||||
this.giftList = data.list || [];
|
||||
this.total = data.total || 0;
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
getStatistics() {
|
||||
// 计算统计数据
|
||||
giftListApi({ page: 1, limit: 9999 }).then(response => {
|
||||
console.log('统计数据响应:', response);
|
||||
const data = response.data || {};
|
||||
const list = data.list || [];
|
||||
console.log('礼物列表:', list);
|
||||
console.log('列表长度:', list.length);
|
||||
this.statistics.total = list.length;
|
||||
this.statistics.enabled = list.filter(item => item.status === true).length;
|
||||
this.statistics.disabled = list.filter(item => item.status === false).length;
|
||||
this.statistics.totalValue = list.reduce((sum, item) => sum + (parseFloat(item.diamondPrice) || 0), 0);
|
||||
console.log('统计结果:', this.statistics);
|
||||
}).catch(error => {
|
||||
console.error('获取统计数据失败:', error);
|
||||
});
|
||||
},
|
||||
handleQuery() {
|
||||
this.queryParams.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
resetQuery() {
|
||||
this.queryParams = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
name: '',
|
||||
status: ''
|
||||
};
|
||||
this.getList();
|
||||
},
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = '添加礼物';
|
||||
},
|
||||
handleUpdate(row) {
|
||||
this.reset();
|
||||
this.form = { ...row };
|
||||
this.open = true;
|
||||
this.title = '修改礼物';
|
||||
},
|
||||
handleDelete(row) {
|
||||
const ids = row.id || this.ids;
|
||||
this.$confirm('是否确认删除选中的礼物?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return giftDeleteApi(ids);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.getStatistics();
|
||||
this.$message.success('删除成功');
|
||||
});
|
||||
},
|
||||
handleStatusChange(row) {
|
||||
const text = row.status === 1 ? '启用' : '禁用';
|
||||
this.$confirm('确认要' + text + '该礼物吗?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
return giftStatusApi(row.id, row.status);
|
||||
}).then(() => {
|
||||
this.$message.success(text + '成功');
|
||||
this.getStatistics();
|
||||
}).catch(() => {
|
||||
row.status = row.status === 0 ? 1 : 0;
|
||||
});
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.id);
|
||||
this.multiple = !selection.length;
|
||||
},
|
||||
submitForm() {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
if (this.form.id) {
|
||||
giftUpdateApi(this.form).then(() => {
|
||||
this.$message.success('修改成功');
|
||||
this.open = false;
|
||||
this.getList();
|
||||
this.getStatistics();
|
||||
});
|
||||
} else {
|
||||
giftAddApi(this.form).then(() => {
|
||||
this.$message.success('新增成功');
|
||||
this.open = false;
|
||||
this.getList();
|
||||
this.getStatistics();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
reset() {
|
||||
this.form = {
|
||||
id: null,
|
||||
name: '',
|
||||
image: '',
|
||||
diamondPrice: 1,
|
||||
intimacy: 1,
|
||||
level: 1,
|
||||
isHeartbeat: 0,
|
||||
sort: 0,
|
||||
status: 1,
|
||||
remark: '',
|
||||
buyType: '钻石',
|
||||
belong: '平台'
|
||||
};
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs['form']) {
|
||||
this.$refs['form'].clearValidate();
|
||||
}
|
||||
});
|
||||
},
|
||||
handleUpload(param) {
|
||||
// 这里实现图片上传逻辑
|
||||
const formData = new FormData();
|
||||
formData.append('file', param.file);
|
||||
// 调用上传接口
|
||||
this.$message.info('图片上传功能需要配置上传接口');
|
||||
},
|
||||
beforeUpload(file) {
|
||||
const isImage = file.type.indexOf('image/') === 0;
|
||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
||||
if (!isImage) {
|
||||
this.$message.error('只能上传图片文件!');
|
||||
}
|
||||
if (!isLt2M) {
|
||||
this.$message.error('上传图片大小不能超过 2MB!');
|
||||
}
|
||||
return isImage && isLt2M;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
font-size: 48px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.avatar-uploader:hover {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
line-height: 120px;
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
147
Zhibo/admin/src/views/gift/recharge/index.vue
Normal file
147
Zhibo/admin/src/views/gift/recharge/index.vue
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%;">
|
||||
<el-table-column label="ID" width="80" align="center">
|
||||
<template slot-scope="{row}">{{ row.id }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="套餐标题" width="150" align="center">
|
||||
<template slot-scope="{row}">{{ row.title }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="充值金额(元)" width="150" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<span style="color: #F56C6C; font-weight: bold;">¥{{ row.amount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="获得虚拟币" width="150" align="center">
|
||||
<template slot-scope="{row}">{{ row.virtual_amount }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="赠送虚拟币" width="150" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<span v-if="row.bonus_amount > 0" style="color: #67C23A;">+{{ row.bonus_amount }}</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="套餐描述" min-width="200">
|
||||
<template slot-scope="{row}">{{ row.description }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="热门推荐" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.is_hot === 1 ? 'danger' : 'info'">
|
||||
{{ row.is_hot === 1 ? '是' : '否' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="状态" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="row.is_enabled === 1 ? 'success' : 'danger'">
|
||||
{{ row.is_enabled === 1 ? '启用' : '禁用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template slot-scope="{row}">
|
||||
<el-button type="primary" size="mini" @click="handleEdit(row)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 编辑对话框 -->
|
||||
<el-dialog title="编辑充值套餐" :visible.sync="dialogVisible" width="600px">
|
||||
<el-form ref="form" :model="form" label-width="120px">
|
||||
<el-form-item label="充值金额">
|
||||
<el-input-number v-model="form.amount" :min="0" :precision="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="获得虚拟币">
|
||||
<el-input-number v-model="form.virtualAmount" :min="0" :precision="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="赠送虚拟币">
|
||||
<el-input-number v-model="form.bonusAmount" :min="0" :precision="2" />
|
||||
</el-form-item>
|
||||
<el-form-item label="套餐标题">
|
||||
<el-input v-model="form.title" />
|
||||
</el-form-item>
|
||||
<el-form-item label="套餐描述">
|
||||
<el-input v-model="form.description" />
|
||||
</el-form-item>
|
||||
<el-form-item label="热门推荐">
|
||||
<el-radio-group v-model="form.isHot">
|
||||
<el-radio :label="1">是</el-radio>
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.isEnabled">
|
||||
<el-radio :label="1">启用</el-radio>
|
||||
<el-radio :label="0">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getRechargePackages, updateRechargePackage } from '@/api/gift'
|
||||
|
||||
export default {
|
||||
name: 'RechargePackage',
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
listLoading: false,
|
||||
dialogVisible: false,
|
||||
form: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
getRechargePackages().then(response => {
|
||||
this.list = response || []
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.form = {
|
||||
id: row.id,
|
||||
amount: row.amount,
|
||||
virtualAmount: row.virtual_amount,
|
||||
bonusAmount: row.bonus_amount,
|
||||
title: row.title,
|
||||
description: row.description,
|
||||
isHot: row.is_hot,
|
||||
sortOrder: row.sort_order,
|
||||
isEnabled: row.is_enabled
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleSubmit() {
|
||||
updateRechargePackage(this.form).then(() => {
|
||||
this.$message.success('更新成功')
|
||||
this.dialogVisible = false
|
||||
this.getList()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
307
Zhibo/admin/src/views/gift/records/index.vue
Normal file
307
Zhibo/admin/src/views/gift/records/index.vue
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 统计卡片 -->
|
||||
<el-row :gutter="20" style="margin-bottom: 20px;">
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: #409EFF;"><i class="el-icon-present"></i></div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.totalCount || 0 }}</div>
|
||||
<div class="stat-label">总礼物数</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: #67C23A;"><i class="el-icon-coin"></i></div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.totalValue || 0 }}</div>
|
||||
<div class="stat-label">总价值(虚拟币)</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: #E6A23C;"><i class="el-icon-present"></i></div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.todayCount || 0 }}</div>
|
||||
<div class="stat-label">今日礼物数</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-card shadow="hover">
|
||||
<div class="stat-card">
|
||||
<div class="stat-icon" style="background: #F56C6C;"><i class="el-icon-coin"></i></div>
|
||||
<div class="stat-content">
|
||||
<div class="stat-value">{{ statistics.todayValue || 0 }}</div>
|
||||
<div class="stat-label">今日价值(虚拟币)</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<el-card shadow="never" style="margin-bottom: 20px;">
|
||||
<el-form :inline="true" :model="listQuery" class="demo-form-inline">
|
||||
<el-form-item label="关键词">
|
||||
<el-input v-model="listQuery.keyword" placeholder="送礼者/接收者/礼物名称" clearable style="width: 200px;" />
|
||||
</el-form-item>
|
||||
<el-form-item label="开始日期">
|
||||
<el-date-picker v-model="listQuery.startDate" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束日期">
|
||||
<el-date-picker v-model="listQuery.endDate" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 礼物记录表格 -->
|
||||
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%;">
|
||||
<el-table-column label="ID" width="80" align="center">
|
||||
<template slot-scope="{row}">{{ row.id }}</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="礼物信息" min-width="150">
|
||||
<template slot-scope="{row}">
|
||||
<div class="gift-info">
|
||||
<img v-if="row.gift_icon" :src="row.gift_icon" class="gift-icon">
|
||||
<div>
|
||||
<div class="gift-name">{{ row.gift_name }}</div>
|
||||
<div class="gift-detail">单价: {{ row.gift_price }} × {{ row.quantity }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="总价值" width="100" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<span class="price-text">{{ row.total_price }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="送礼者" min-width="150">
|
||||
<template slot-scope="{row}">
|
||||
<div v-if="row.is_anonymous" class="user-info">
|
||||
<div class="info">
|
||||
<div class="nickname">匿名用户</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="user-info">
|
||||
<img :src="row.sender_avatar || defaultAvatar" class="avatar">
|
||||
<div class="info">
|
||||
<div class="nickname">{{ row.sender_nickname }}</div>
|
||||
<div class="phone">{{ row.sender_phone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="接收者(主播)" min-width="150">
|
||||
<template slot-scope="{row}">
|
||||
<div class="user-info">
|
||||
<img :src="row.receiver_avatar || defaultAvatar" class="avatar">
|
||||
<div class="info">
|
||||
<div class="nickname">{{ row.receiver_nickname }}</div>
|
||||
<div class="phone">{{ row.receiver_phone }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="直播间" width="150" align="center">
|
||||
<template slot-scope="{row}">
|
||||
<span v-if="row.room_title">{{ row.room_title }}</span>
|
||||
<span v-else style="color: #999;">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="赠送时间" width="160" align="center">
|
||||
<template slot-scope="{row}">{{ row.create_time }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<el-pagination
|
||||
background
|
||||
:current-page="listQuery.page"
|
||||
:page-sizes="[10, 20, 30, 50]"
|
||||
:page-size="listQuery.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getGiftRecords, getGiftStatistics } from '@/api/gift'
|
||||
|
||||
export default {
|
||||
name: 'GiftRecords',
|
||||
data() {
|
||||
return {
|
||||
defaultAvatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
|
||||
list: [],
|
||||
total: 0,
|
||||
listLoading: false,
|
||||
listQuery: {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
keyword: '',
|
||||
startDate: '',
|
||||
endDate: ''
|
||||
},
|
||||
statistics: {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
this.getStatistics()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.listLoading = true
|
||||
getGiftRecords(this.listQuery).then(response => {
|
||||
this.list = response.list || []
|
||||
this.total = response.total || 0
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
getStatistics() {
|
||||
getGiftStatistics().then(response => {
|
||||
this.statistics = response || {}
|
||||
})
|
||||
},
|
||||
handleFilter() {
|
||||
this.listQuery.page = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.listQuery = {
|
||||
page: 1,
|
||||
limit: 20,
|
||||
keyword: '',
|
||||
startDate: '',
|
||||
endDate: ''
|
||||
}
|
||||
this.getList()
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.listQuery.limit = val
|
||||
this.getList()
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.listQuery.page = val
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.stat-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.stat-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 28px;
|
||||
color: white;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.stat-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.gift-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.gift-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 4px;
|
||||
margin-right: 10px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.gift-name {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.gift-detail {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.price-text {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #F56C6C;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-info .avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-info .info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.user-info .nickname {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.user-info .phone {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -10,12 +10,11 @@ import org.springframework.jdbc.core.JdbcTemplate;
|
|||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 礼物管理控制器
|
||||
* 礼物管理控制器(后台管理)
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
|
|
@ -28,61 +27,79 @@ public class GiftAdminController {
|
|||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
/**
|
||||
* 礼物列表
|
||||
* 获取礼物打赏记录列表
|
||||
*/
|
||||
@ApiOperation(value = "礼物列表")
|
||||
@GetMapping("/list")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getGiftList(
|
||||
@RequestParam(value = "keywords", required = false) String keywords,
|
||||
@RequestParam(value = "status", required = false) String statusStr,
|
||||
@ApiOperation(value = "礼物打赏记录列表")
|
||||
@GetMapping("/records")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getGiftRecords(
|
||||
@RequestParam(value = "keyword", required = false) String keyword,
|
||||
@RequestParam(value = "startDate", required = false) String startDate,
|
||||
@RequestParam(value = "endDate", required = false) String endDate,
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "limit", defaultValue = "20") Integer limit) {
|
||||
|
||||
StringBuilder sql = new StringBuilder("SELECT * FROM eb_gift WHERE 1=1");
|
||||
StringBuilder countSql = new StringBuilder("SELECT COUNT(*) FROM eb_gift WHERE 1=1");
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT g.id, g.gift_name, g.gift_image as gift_icon, g.gift_price, g.quantity, g.total_price, ");
|
||||
sql.append("g.sender_id, COALESCE(g.sender_nickname, sender.nickname, '') as sender_nickname, ");
|
||||
sql.append("COALESCE(g.sender_avatar, sender.avatar, '') as sender_avatar, COALESCE(sender.phone, '') as sender_phone, ");
|
||||
sql.append("g.receiver_id, COALESCE(g.receiver_nickname, receiver.nickname, '') as receiver_nickname, ");
|
||||
sql.append("COALESCE(receiver.avatar, '') as receiver_avatar, COALESCE(receiver.phone, '') as receiver_phone, ");
|
||||
sql.append("g.room_id, COALESCE(r.title, '') as room_title, ");
|
||||
sql.append("COALESCE(g.is_deleted, 0) as is_anonymous, g.create_time ");
|
||||
sql.append("FROM eb_gift_record g ");
|
||||
sql.append("LEFT JOIN eb_user sender ON g.sender_id = sender.uid ");
|
||||
sql.append("LEFT JOIN eb_user receiver ON g.receiver_id = receiver.uid ");
|
||||
sql.append("LEFT JOIN eb_live_room r ON g.room_id = r.id ");
|
||||
sql.append("WHERE 1=1 ");
|
||||
|
||||
if (keywords != null && !keywords.trim().isEmpty()) {
|
||||
String condition = " AND name LIKE '%" + keywords.trim() + "%'";
|
||||
StringBuilder countSql = new StringBuilder();
|
||||
countSql.append("SELECT COUNT(*) FROM eb_gift_record g ");
|
||||
countSql.append("LEFT JOIN eb_user sender ON g.sender_id = sender.uid ");
|
||||
countSql.append("LEFT JOIN eb_user receiver ON g.receiver_id = receiver.uid ");
|
||||
countSql.append("WHERE 1=1 ");
|
||||
|
||||
List<Object> params = new ArrayList<>();
|
||||
List<Object> countParams = new ArrayList<>();
|
||||
|
||||
if (keyword != null && !keyword.isEmpty()) {
|
||||
String condition = " AND (g.sender_nickname LIKE ? OR g.receiver_nickname LIKE ? OR g.gift_name LIKE ?) ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
String keywordPattern = "%" + keyword + "%";
|
||||
params.add(keywordPattern);
|
||||
params.add(keywordPattern);
|
||||
params.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
}
|
||||
|
||||
// 处理status参数,空字符串视为null
|
||||
Integer status = null;
|
||||
if (statusStr != null && !statusStr.trim().isEmpty()) {
|
||||
try {
|
||||
status = Integer.parseInt(statusStr.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的status值
|
||||
}
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
String condition = " AND status = " + status;
|
||||
if (startDate != null && !startDate.isEmpty()) {
|
||||
String condition = " AND g.create_time >= ? ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
params.add(startDate + " 00:00:00");
|
||||
countParams.add(startDate + " 00:00:00");
|
||||
}
|
||||
|
||||
sql.append(" ORDER BY id ASC");
|
||||
if (endDate != null && !endDate.isEmpty()) {
|
||||
String condition = " AND g.create_time <= ? ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
params.add(endDate + " 23:59:59");
|
||||
countParams.add(endDate + " 23:59:59");
|
||||
}
|
||||
|
||||
Long total = jdbcTemplate.queryForObject(countSql.toString(), Long.class);
|
||||
sql.append(" ORDER BY g.create_time DESC ");
|
||||
|
||||
Long total = jdbcTemplate.queryForObject(countSql.toString(), Long.class, countParams.toArray());
|
||||
|
||||
int offset = (page - 1) * limit;
|
||||
sql.append(" LIMIT ").append(offset).append(", ").append(limit);
|
||||
sql.append(" LIMIT ? OFFSET ? ");
|
||||
params.add(limit);
|
||||
params.add(offset);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString());
|
||||
|
||||
// 转换字段名
|
||||
list.forEach(item -> {
|
||||
item.put("diamondPrice", item.get("diamond_price"));
|
||||
item.put("isHeartbeat", item.get("is_heartbeat") != null && ((Integer) item.get("is_heartbeat")) == 1);
|
||||
item.put("buyType", item.get("buy_type"));
|
||||
item.put("effectVersion", item.get("effect_version"));
|
||||
item.put("createTime", item.get("create_time"));
|
||||
item.put("updateTime", item.get("update_time"));
|
||||
// 状态转换为布尔值
|
||||
item.put("status", item.get("status") != null && ((Integer) item.get("status")) == 1);
|
||||
});
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
|
||||
|
||||
CommonPage<Map<String, Object>> result = new CommonPage<>();
|
||||
result.setList(list);
|
||||
|
|
@ -95,17 +112,288 @@ public class GiftAdminController {
|
|||
}
|
||||
|
||||
/**
|
||||
* 礼物详情
|
||||
* 获取礼物统计数据
|
||||
*/
|
||||
@ApiOperation(value = "礼物详情")
|
||||
@GetMapping("/detail/{id}")
|
||||
public CommonResult<Map<String, Object>> getGiftDetail(@PathVariable Integer id) {
|
||||
String sql = "SELECT * FROM eb_gift WHERE id = ?";
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, id);
|
||||
if (list.isEmpty()) {
|
||||
return CommonResult.failed("礼物不存在");
|
||||
@ApiOperation(value = "礼物统计数据")
|
||||
@GetMapping("/statistics")
|
||||
public CommonResult<Map<String, Object>> getGiftStatistics() {
|
||||
try {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
// 总礼物数量
|
||||
String totalCountSql = "SELECT COUNT(*) FROM eb_gift_record";
|
||||
Integer totalCount = jdbcTemplate.queryForObject(totalCountSql, Integer.class);
|
||||
stats.put("totalCount", totalCount != null ? totalCount : 0);
|
||||
|
||||
// 总礼物价值
|
||||
String totalValueSql = "SELECT COALESCE(SUM(total_price), 0) FROM eb_gift_record";
|
||||
BigDecimal totalValue = jdbcTemplate.queryForObject(totalValueSql, BigDecimal.class);
|
||||
stats.put("totalValue", totalValue != null ? totalValue : BigDecimal.ZERO);
|
||||
|
||||
// 今日礼物数量
|
||||
String todayCountSql = "SELECT COUNT(*) FROM eb_gift_record WHERE DATE(create_time) = CURDATE()";
|
||||
Integer todayCount = jdbcTemplate.queryForObject(todayCountSql, Integer.class);
|
||||
stats.put("todayCount", todayCount != null ? todayCount : 0);
|
||||
|
||||
// 今日礼物价值
|
||||
String todayValueSql = "SELECT COALESCE(SUM(total_price), 0) FROM eb_gift_record WHERE DATE(create_time) = CURDATE()";
|
||||
BigDecimal todayValue = jdbcTemplate.queryForObject(todayValueSql, BigDecimal.class);
|
||||
stats.put("todayValue", todayValue != null ? todayValue : BigDecimal.ZERO);
|
||||
|
||||
return CommonResult.success(stats);
|
||||
} catch (Exception e) {
|
||||
log.error("获取礼物统计失败", e);
|
||||
return CommonResult.failed("获取统计失败");
|
||||
}
|
||||
return CommonResult.success(list.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取礼物配置列表
|
||||
*/
|
||||
@ApiOperation(value = "礼物配置列表")
|
||||
@GetMapping("/config/list")
|
||||
public CommonResult<List<Map<String, Object>>> getGiftConfigList() {
|
||||
try {
|
||||
String sql = "SELECT id, name, icon, price, animation, sort_order, is_enabled, create_time " +
|
||||
"FROM eb_gift_config ORDER BY sort_order";
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
|
||||
return CommonResult.success(list);
|
||||
} catch (Exception e) {
|
||||
log.error("获取礼物配置失败", e);
|
||||
return CommonResult.failed("获取礼物配置失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加礼物配置
|
||||
*/
|
||||
@ApiOperation(value = "添加礼物配置")
|
||||
@PostMapping("/config/add")
|
||||
public CommonResult<String> addGiftConfig(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
String name = (String) request.get("name");
|
||||
String icon = (String) request.get("icon");
|
||||
BigDecimal price = new BigDecimal(request.get("price").toString());
|
||||
String animation = (String) request.get("animation");
|
||||
Integer sortOrder = request.get("sortOrder") != null ? (Integer) request.get("sortOrder") : 0;
|
||||
|
||||
String sql = "INSERT INTO eb_gift_config (name, icon, price, animation, sort_order) VALUES (?, ?, ?, ?, ?)";
|
||||
jdbcTemplate.update(sql, name, icon, price, animation, sortOrder);
|
||||
|
||||
return CommonResult.success("添加成功");
|
||||
} catch (Exception e) {
|
||||
log.error("添加礼物配置失败", e);
|
||||
return CommonResult.failed("添加失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物配置
|
||||
*/
|
||||
@ApiOperation(value = "更新礼物配置")
|
||||
@PostMapping("/config/update")
|
||||
public CommonResult<String> updateGiftConfig(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
Integer id = (Integer) request.get("id");
|
||||
String name = (String) request.get("name");
|
||||
String icon = (String) request.get("icon");
|
||||
BigDecimal price = new BigDecimal(request.get("price").toString());
|
||||
String animation = (String) request.get("animation");
|
||||
Integer sortOrder = request.get("sortOrder") != null ? (Integer) request.get("sortOrder") : 0;
|
||||
Integer isEnabled = request.get("isEnabled") != null ? (Integer) request.get("isEnabled") : 1;
|
||||
|
||||
String sql = "UPDATE eb_gift_config SET name = ?, icon = ?, price = ?, animation = ?, sort_order = ?, is_enabled = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, name, icon, price, animation, sortOrder, isEnabled, id);
|
||||
|
||||
return CommonResult.success("更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新礼物配置失败", e);
|
||||
return CommonResult.failed("更新失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除礼物配置
|
||||
*/
|
||||
@ApiOperation(value = "删除礼物配置")
|
||||
@PostMapping("/config/delete/{id}")
|
||||
public CommonResult<String> deleteGiftConfig(@PathVariable Integer id) {
|
||||
try {
|
||||
String sql = "DELETE FROM eb_gift_config WHERE id = ?";
|
||||
jdbcTemplate.update(sql, id);
|
||||
return CommonResult.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("删除礼物配置失败", e);
|
||||
return CommonResult.failed("删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取充值套餐列表
|
||||
*/
|
||||
@ApiOperation(value = "充值套餐列表")
|
||||
@GetMapping("/recharge/packages")
|
||||
public CommonResult<List<Map<String, Object>>> getRechargePackages() {
|
||||
try {
|
||||
String sql = "SELECT id, amount, virtual_amount, bonus_amount, title, description, is_hot, sort_order, is_enabled " +
|
||||
"FROM eb_recharge_package ORDER BY sort_order";
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
|
||||
return CommonResult.success(list);
|
||||
} catch (Exception e) {
|
||||
log.error("获取充值套餐失败", e);
|
||||
return CommonResult.failed("获取充值套餐失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新充值套餐
|
||||
*/
|
||||
@ApiOperation(value = "更新充值套餐")
|
||||
@PostMapping("/recharge/package/update")
|
||||
public CommonResult<String> updateRechargePackage(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
Integer id = (Integer) request.get("id");
|
||||
BigDecimal amount = new BigDecimal(request.get("amount").toString());
|
||||
BigDecimal virtualAmount = new BigDecimal(request.get("virtualAmount").toString());
|
||||
BigDecimal bonusAmount = new BigDecimal(request.get("bonusAmount").toString());
|
||||
String title = (String) request.get("title");
|
||||
String description = (String) request.get("description");
|
||||
Integer isHot = request.get("isHot") != null ? (Integer) request.get("isHot") : 0;
|
||||
Integer sortOrder = request.get("sortOrder") != null ? (Integer) request.get("sortOrder") : 0;
|
||||
Integer isEnabled = request.get("isEnabled") != null ? (Integer) request.get("isEnabled") : 1;
|
||||
|
||||
String sql = "UPDATE eb_recharge_package SET amount = ?, virtual_amount = ?, bonus_amount = ?, " +
|
||||
"title = ?, description = ?, is_hot = ?, sort_order = ?, is_enabled = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, amount, virtualAmount, bonusAmount, title, description, isHot, sortOrder, isEnabled, id);
|
||||
|
||||
return CommonResult.success("更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新充值套餐失败", e);
|
||||
return CommonResult.failed("更新失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取充值记录
|
||||
*/
|
||||
@ApiOperation(value = "充值记录列表")
|
||||
@GetMapping("/recharge/records")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getRechargeRecords(
|
||||
@RequestParam(value = "keyword", required = false) String keyword,
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "limit", defaultValue = "20") Integer limit) {
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT r.id, r.order_no, r.amount, r.virtual_amount, r.payment_method, r.payment_status, ");
|
||||
sql.append("r.create_time, r.pay_time, ");
|
||||
sql.append("u.uid as user_id, u.nickname, u.phone, u.avatar ");
|
||||
sql.append("FROM eb_virtual_currency_recharge r ");
|
||||
sql.append("LEFT JOIN eb_user u ON r.user_id = u.uid ");
|
||||
sql.append("WHERE 1=1 ");
|
||||
|
||||
StringBuilder countSql = new StringBuilder();
|
||||
countSql.append("SELECT COUNT(*) FROM eb_virtual_currency_recharge r ");
|
||||
countSql.append("LEFT JOIN eb_user u ON r.user_id = u.uid ");
|
||||
countSql.append("WHERE 1=1 ");
|
||||
|
||||
List<Object> params = new ArrayList<>();
|
||||
List<Object> countParams = new ArrayList<>();
|
||||
|
||||
if (keyword != null && !keyword.isEmpty()) {
|
||||
String condition = " AND (u.nickname LIKE ? OR u.phone LIKE ? OR r.order_no LIKE ?) ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
String keywordPattern = "%" + keyword + "%";
|
||||
params.add(keywordPattern);
|
||||
params.add(keywordPattern);
|
||||
params.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
countParams.add(keywordPattern);
|
||||
}
|
||||
|
||||
sql.append(" ORDER BY r.create_time DESC ");
|
||||
|
||||
Long total = jdbcTemplate.queryForObject(countSql.toString(), Long.class, countParams.toArray());
|
||||
|
||||
int offset = (page - 1) * limit;
|
||||
sql.append(" LIMIT ? OFFSET ? ");
|
||||
params.add(limit);
|
||||
params.add(offset);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
|
||||
|
||||
CommonPage<Map<String, Object>> result = new CommonPage<>();
|
||||
result.setList(list);
|
||||
result.setTotal(total != null ? total : 0L);
|
||||
result.setPage(page);
|
||||
result.setLimit(limit);
|
||||
result.setTotalPage((int) Math.ceil((double) (total != null ? total : 0) / limit));
|
||||
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
// ========== 礼物管理接口(eb_gift表) ==========
|
||||
|
||||
/**
|
||||
* 获取礼物列表
|
||||
*/
|
||||
@ApiOperation(value = "礼物列表")
|
||||
@GetMapping("/list")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getGiftList(
|
||||
@RequestParam(value = "name", required = false) String name,
|
||||
@RequestParam(value = "status", required = false) Integer status,
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "limit", defaultValue = "20") Integer limit) {
|
||||
|
||||
StringBuilder sql = new StringBuilder();
|
||||
sql.append("SELECT id, name, image, diamond_price as diamondPrice, intimacy, status, ");
|
||||
sql.append("is_heartbeat as isHeartbeat, buy_type as buyType, belong, remark, ");
|
||||
sql.append("level, sort, create_time as createTime, update_time as updateTime ");
|
||||
sql.append("FROM eb_gift WHERE is_deleted = 0 ");
|
||||
|
||||
StringBuilder countSql = new StringBuilder();
|
||||
countSql.append("SELECT COUNT(*) FROM eb_gift WHERE is_deleted = 0 ");
|
||||
|
||||
List<Object> params = new ArrayList<>();
|
||||
List<Object> countParams = new ArrayList<>();
|
||||
|
||||
if (name != null && !name.isEmpty()) {
|
||||
String condition = " AND name LIKE ? ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
String namePattern = "%" + name + "%";
|
||||
params.add(namePattern);
|
||||
countParams.add(namePattern);
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
String condition = " AND status = ? ";
|
||||
sql.append(condition);
|
||||
countSql.append(condition);
|
||||
params.add(status);
|
||||
countParams.add(status);
|
||||
}
|
||||
|
||||
sql.append(" ORDER BY sort ASC, id DESC ");
|
||||
|
||||
Long total = jdbcTemplate.queryForObject(countSql.toString(), Long.class, countParams.toArray());
|
||||
|
||||
int offset = (page - 1) * limit;
|
||||
sql.append(" LIMIT ? OFFSET ? ");
|
||||
params.add(limit);
|
||||
params.add(offset);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
|
||||
|
||||
CommonPage<Map<String, Object>> result = new CommonPage<>();
|
||||
result.setList(list);
|
||||
result.setTotal(total != null ? total : 0L);
|
||||
result.setPage(page);
|
||||
result.setLimit(limit);
|
||||
result.setTotalPage((int) Math.ceil((double) (total != null ? total : 0) / limit));
|
||||
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,28 +401,28 @@ public class GiftAdminController {
|
|||
*/
|
||||
@ApiOperation(value = "添加礼物")
|
||||
@PostMapping("/add")
|
||||
public CommonResult<Boolean> addGift(@RequestBody Map<String, Object> data) {
|
||||
public CommonResult<String> addGift(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
String sql = "INSERT INTO eb_gift (name, image, diamond_price, intimacy, status, is_heartbeat, " +
|
||||
"buy_type, belong, remark, effect_version, effect_url, create_time, update_time) " +
|
||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
|
||||
String name = (String) request.get("name");
|
||||
String image = (String) request.get("image");
|
||||
BigDecimal diamondPrice = new BigDecimal(request.get("diamondPrice").toString());
|
||||
Integer intimacy = request.get("intimacy") != null ? Integer.parseInt(request.get("intimacy").toString()) : 0;
|
||||
Integer level = request.get("level") != null ? Integer.parseInt(request.get("level").toString()) : 1;
|
||||
Integer isHeartbeat = request.get("isHeartbeat") != null ? Integer.parseInt(request.get("isHeartbeat").toString()) : 0;
|
||||
Integer sort = request.get("sort") != null ? Integer.parseInt(request.get("sort").toString()) : 0;
|
||||
Integer status = request.get("status") != null ? Integer.parseInt(request.get("status").toString()) : 1;
|
||||
String remark = (String) request.get("remark");
|
||||
String buyType = request.get("buyType") != null ? (String) request.get("buyType") : "钻石";
|
||||
String belong = request.get("belong") != null ? (String) request.get("belong") : "平台";
|
||||
|
||||
jdbcTemplate.update(sql,
|
||||
data.get("name"),
|
||||
data.get("image"),
|
||||
data.get("diamondPrice"),
|
||||
data.get("intimacy"),
|
||||
data.get("status") != null && (Boolean) data.get("status") ? 1 : 0,
|
||||
data.get("isHeartbeat") != null && (Boolean) data.get("isHeartbeat") ? 1 : 0,
|
||||
data.get("buyType"),
|
||||
data.get("belong"),
|
||||
data.get("remark"),
|
||||
data.get("effectVersion"),
|
||||
data.get("effectUrl") != null ? data.get("effectUrl") : ""
|
||||
);
|
||||
return CommonResult.success(true);
|
||||
String sql = "INSERT INTO eb_gift (name, image, diamond_price, intimacy, status, is_heartbeat, " +
|
||||
"buy_type, belong, remark, level, sort) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
jdbcTemplate.update(sql, name, image, diamondPrice, intimacy, status, isHeartbeat,
|
||||
buyType, belong, remark, level, sort);
|
||||
|
||||
return CommonResult.success("添加成功");
|
||||
} catch (Exception e) {
|
||||
log.error("添加礼物失败: {}", e.getMessage());
|
||||
log.error("添加礼物失败", e);
|
||||
return CommonResult.failed("添加失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
@ -143,136 +431,75 @@ public class GiftAdminController {
|
|||
* 更新礼物
|
||||
*/
|
||||
@ApiOperation(value = "更新礼物")
|
||||
@PostMapping("/update/{id}")
|
||||
public CommonResult<Boolean> updateGift(@PathVariable Integer id, @RequestBody Map<String, Object> data) {
|
||||
@PostMapping("/update")
|
||||
public CommonResult<String> updateGift(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
String sql = "UPDATE eb_gift SET name = ?, image = ?, diamond_price = ?, intimacy = ?, " +
|
||||
"status = ?, is_heartbeat = ?, buy_type = ?, belong = ?, remark = ?, " +
|
||||
"effect_version = ?, effect_url = ?, update_time = NOW() WHERE id = ?";
|
||||
Integer id = Integer.parseInt(request.get("id").toString());
|
||||
String name = (String) request.get("name");
|
||||
String image = (String) request.get("image");
|
||||
BigDecimal diamondPrice = new BigDecimal(request.get("diamondPrice").toString());
|
||||
Integer intimacy = request.get("intimacy") != null ? Integer.parseInt(request.get("intimacy").toString()) : 0;
|
||||
Integer level = request.get("level") != null ? Integer.parseInt(request.get("level").toString()) : 1;
|
||||
Integer isHeartbeat = request.get("isHeartbeat") != null ? Integer.parseInt(request.get("isHeartbeat").toString()) : 0;
|
||||
Integer sort = request.get("sort") != null ? Integer.parseInt(request.get("sort").toString()) : 0;
|
||||
Integer status = request.get("status") != null ? Integer.parseInt(request.get("status").toString()) : 1;
|
||||
String remark = (String) request.get("remark");
|
||||
String buyType = request.get("buyType") != null ? (String) request.get("buyType") : "钻石";
|
||||
String belong = request.get("belong") != null ? (String) request.get("belong") : "平台";
|
||||
|
||||
jdbcTemplate.update(sql,
|
||||
data.get("name"),
|
||||
data.get("image"),
|
||||
data.get("diamondPrice"),
|
||||
data.get("intimacy"),
|
||||
data.get("status") != null && (Boolean) data.get("status") ? 1 : 0,
|
||||
data.get("isHeartbeat") != null && (Boolean) data.get("isHeartbeat") ? 1 : 0,
|
||||
data.get("buyType"),
|
||||
data.get("belong"),
|
||||
data.get("remark"),
|
||||
data.get("effectVersion"),
|
||||
data.get("effectUrl") != null ? data.get("effectUrl") : "",
|
||||
id
|
||||
);
|
||||
return CommonResult.success(true);
|
||||
String sql = "UPDATE eb_gift SET name = ?, image = ?, diamond_price = ?, intimacy = ?, status = ?, " +
|
||||
"is_heartbeat = ?, buy_type = ?, belong = ?, remark = ?, level = ?, sort = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, name, image, diamondPrice, intimacy, status, isHeartbeat,
|
||||
buyType, belong, remark, level, sort, id);
|
||||
|
||||
return CommonResult.success("更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("更新礼物失败: {}", e.getMessage());
|
||||
log.error("更新礼物失败", e);
|
||||
return CommonResult.failed("更新失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新礼物状态
|
||||
*/
|
||||
@ApiOperation(value = "更新礼物状态")
|
||||
@PostMapping("/status/{id}")
|
||||
public CommonResult<Boolean> updateStatus(@PathVariable Integer id, @RequestParam Integer status) {
|
||||
try {
|
||||
jdbcTemplate.update("UPDATE eb_gift SET status = ?, update_time = NOW() WHERE id = ?", status, id);
|
||||
return CommonResult.success(true);
|
||||
} catch (Exception e) {
|
||||
log.error("更新状态失败: {}", e.getMessage());
|
||||
return CommonResult.failed("操作失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新心动礼物状态
|
||||
*/
|
||||
@ApiOperation(value = "更新心动礼物状态")
|
||||
@PostMapping("/heartbeat/{id}")
|
||||
public CommonResult<Boolean> updateHeartbeat(@PathVariable Integer id, @RequestParam Integer isHeartbeat) {
|
||||
try {
|
||||
jdbcTemplate.update("UPDATE eb_gift SET is_heartbeat = ?, update_time = NOW() WHERE id = ?", isHeartbeat, id);
|
||||
return CommonResult.success(true);
|
||||
} catch (Exception e) {
|
||||
log.error("更新心动状态失败: {}", e.getMessage());
|
||||
return CommonResult.failed("操作失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除礼物
|
||||
*/
|
||||
@ApiOperation(value = "删除礼物")
|
||||
@DeleteMapping("/{id}")
|
||||
public CommonResult<Boolean> deleteGift(@PathVariable Integer id) {
|
||||
try {
|
||||
jdbcTemplate.update("DELETE FROM eb_gift WHERE id = ?", id);
|
||||
return CommonResult.success(true);
|
||||
} catch (Exception e) {
|
||||
log.error("删除礼物失败: {}", e.getMessage());
|
||||
return CommonResult.failed("删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除礼物
|
||||
*/
|
||||
@ApiOperation(value = "批量删除礼物")
|
||||
@PostMapping("/batch-delete")
|
||||
public CommonResult<Boolean> batchDeleteGift(@RequestBody Map<String, Object> data) {
|
||||
@PostMapping("/delete")
|
||||
public CommonResult<String> deleteGift(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Integer> ids = (List<Integer>) data.get("ids");
|
||||
List<Integer> ids = (List<Integer>) request.get("ids");
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return CommonResult.failed("请选择要删除的礼物");
|
||||
}
|
||||
String placeholders = String.join(",", ids.stream().map(id -> "?").toArray(String[]::new));
|
||||
String sql = "DELETE FROM eb_gift WHERE id IN (" + placeholders + ")";
|
||||
|
||||
String placeholders = String.join(",", Collections.nCopies(ids.size(), "?"));
|
||||
String sql = "UPDATE eb_gift SET is_deleted = 1 WHERE id IN (" + placeholders + ")";
|
||||
jdbcTemplate.update(sql, ids.toArray());
|
||||
return CommonResult.success(true);
|
||||
|
||||
return CommonResult.success("删除成功");
|
||||
} catch (Exception e) {
|
||||
log.error("批量删除礼物失败: {}", e.getMessage());
|
||||
return CommonResult.failed("批量删除失败: " + e.getMessage());
|
||||
log.error("删除礼物失败", e);
|
||||
return CommonResult.failed("删除失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 礼物统计
|
||||
* 更新礼物状态
|
||||
*/
|
||||
@ApiOperation(value = "礼物统计")
|
||||
@GetMapping("/statistics")
|
||||
public CommonResult<Map<String, Object>> getStatistics() {
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
|
||||
@ApiOperation(value = "更新礼物状态")
|
||||
@PostMapping("/status")
|
||||
public CommonResult<String> updateGiftStatus(@RequestBody Map<String, Object> request) {
|
||||
try {
|
||||
// 礼物总数
|
||||
Long totalGifts = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM eb_gift", Long.class);
|
||||
stats.put("totalGifts", totalGifts != null ? totalGifts : 0);
|
||||
Integer id = Integer.parseInt(request.get("id").toString());
|
||||
Integer status = Integer.parseInt(request.get("status").toString());
|
||||
|
||||
// 启用礼物数
|
||||
Long enabledGifts = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM eb_gift WHERE status = 1", Long.class);
|
||||
stats.put("enabledGifts", enabledGifts != null ? enabledGifts : 0);
|
||||
|
||||
// 心动礼物数
|
||||
Long heartbeatGifts = jdbcTemplate.queryForObject("SELECT COUNT(*) FROM eb_gift WHERE is_heartbeat = 1", Long.class);
|
||||
stats.put("heartbeatGifts", heartbeatGifts != null ? heartbeatGifts : 0);
|
||||
|
||||
// 今日打赏次数
|
||||
Long todayRewards = jdbcTemplate.queryForObject(
|
||||
"SELECT COUNT(*) FROM eb_gift_reward_record WHERE DATE(create_time) = CURDATE()", Long.class);
|
||||
stats.put("todayRewards", todayRewards != null ? todayRewards : 0);
|
||||
|
||||
// 今日打赏金额
|
||||
Double todayAmount = jdbcTemplate.queryForObject(
|
||||
"SELECT IFNULL(SUM(reward_amount), 0) FROM eb_gift_reward_record WHERE DATE(create_time) = CURDATE()", Double.class);
|
||||
stats.put("todayAmount", todayAmount != null ? todayAmount : 0);
|
||||
String sql = "UPDATE eb_gift SET status = ? WHERE id = ?";
|
||||
jdbcTemplate.update(sql, status, id);
|
||||
|
||||
return CommonResult.success("状态更新成功");
|
||||
} catch (Exception e) {
|
||||
log.error("获取礼物统计失败: {}", e.getMessage());
|
||||
log.error("更新礼物状态失败", e);
|
||||
return CommonResult.failed("状态更新失败: " + e.getMessage());
|
||||
}
|
||||
|
||||
return CommonResult.success(stats);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.zbkj.front.controller;
|
||||
|
||||
import com.zbkj.common.result.CommonResult;
|
||||
import com.zbkj.front.component.FrontTokenComponent;
|
||||
import com.zbkj.common.token.FrontTokenComponent;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -18,7 +18,7 @@ import java.util.*;
|
|||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/front/gift")
|
||||
@RequestMapping("/api/front/gift-system")
|
||||
@Api(tags = "礼物系统")
|
||||
public class GiftSystemController {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.zbkj.front.controller;
|
||||
|
||||
import com.zbkj.common.result.CommonResult;
|
||||
import com.zbkj.front.component.FrontTokenComponent;
|
||||
import com.zbkj.common.token.FrontTokenComponent;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
|
|||
44
add_gift_manage_menu.sql
Normal file
44
add_gift_manage_menu.sql
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
-- ========================================
|
||||
-- 添加礼物管理菜单到直播管理下
|
||||
-- ========================================
|
||||
|
||||
-- 1. 启用打赏记录菜单
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 1, name = '打赏记录'
|
||||
WHERE id = 823
|
||||
AND pid = 675;
|
||||
|
||||
-- 2. 添加礼物管理菜单
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
SELECT 675, '礼物管理', '', '', '/liveManage/gift/manage/index', 'C', 801, 1, 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM eb_system_menu
|
||||
WHERE pid = 675 AND component = '/liveManage/gift/manage/index'
|
||||
);
|
||||
|
||||
-- 3. 验证菜单结构
|
||||
SELECT
|
||||
'=== 直播管理 - 礼物相关菜单 ===' as section,
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE pid = 675 AND (name LIKE '%礼物%' OR name LIKE '%打赏%')
|
||||
ORDER BY sort;
|
||||
|
||||
-- 4. 查看完整的直播管理菜单
|
||||
SELECT
|
||||
'=== 直播管理完整菜单 ===' as section,
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE id = 675 OR pid = 675
|
||||
ORDER BY sort;
|
||||
54
add_gift_menu.sql
Normal file
54
add_gift_menu.sql
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
-- 添加礼物管理菜单到后台管理系统
|
||||
|
||||
-- 1. 查看现有菜单,找到合适的插入位置
|
||||
SELECT id, pid, name, component, sort, menu_type FROM eb_system_menu WHERE is_delte = 0 ORDER BY sort;
|
||||
|
||||
-- 2. 添加礼物管理父菜单(目录类型)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (0, '礼物管理', 'el-icon-present', '', 'Layout', 'M', 100, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 3. 获取刚插入的父菜单ID
|
||||
SET @parent_id = LAST_INSERT_ID();
|
||||
|
||||
-- 4. 添加礼物打赏子菜单(菜单类型)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (@parent_id, '礼物打赏', 'el-icon-present', 'admin:gift:records', 'gift/records/index', 'C', 1, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 5. 验证菜单是否添加成功
|
||||
SELECT
|
||||
m1.id as parent_id,
|
||||
m1.name as parent_name,
|
||||
m1.menu_type as parent_type,
|
||||
m2.id as child_id,
|
||||
m2.name as child_name,
|
||||
m2.component,
|
||||
m2.menu_type as child_type
|
||||
FROM eb_system_menu m1
|
||||
LEFT JOIN eb_system_menu m2 ON m1.id = m2.pid
|
||||
WHERE m1.name = '礼物管理' AND m1.is_delte = 0;
|
||||
|
||||
-- 6. 查看所有礼物相关菜单
|
||||
SELECT id, pid, name, icon, component, menu_type, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%礼物%' AND is_delte = 0
|
||||
ORDER BY pid, sort;
|
||||
|
||||
-- 7. 如果需要给管理员角色分配权限(假设管理员角色ID为1)
|
||||
-- 先查看角色ID
|
||||
SELECT * FROM eb_system_role;
|
||||
|
||||
-- 获取礼物菜单的ID
|
||||
SELECT @gift_parent_id := id FROM eb_system_menu WHERE name = '礼物管理' AND is_delte = 0 LIMIT 1;
|
||||
SELECT @gift_child_id := id FROM eb_system_menu WHERE name = '礼物打赏' AND is_delte = 0 LIMIT 1;
|
||||
|
||||
-- 给管理员角色(rid=1)分配礼物管理权限
|
||||
INSERT INTO eb_system_role_menu (rid, menu_id) VALUES (1, @gift_parent_id);
|
||||
INSERT INTO eb_system_role_menu (rid, menu_id) VALUES (1, @gift_child_id);
|
||||
|
||||
-- 8. 验证角色权限
|
||||
SELECT r.id as role_id, r.role_name, m.id as menu_id, m.name as menu_name
|
||||
FROM eb_system_role r
|
||||
JOIN eb_system_role_menu rm ON r.id = rm.rid
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name LIKE '%礼物%';
|
||||
|
||||
0
add_gift_menus_correct.sql
Normal file
0
add_gift_menus_correct.sql
Normal file
42
add_gift_menus_to_database.sql
Normal file
42
add_gift_menus_to_database.sql
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
-- 添加礼物打赏菜单到数据库
|
||||
|
||||
-- 1. 查看当前最大的菜单ID
|
||||
SELECT MAX(id) as max_id FROM eb_system_menu;
|
||||
|
||||
-- 2. 删除旧的礼物菜单(如果存在)
|
||||
DELETE FROM eb_system_menu WHERE path LIKE '/gift%' OR path LIKE '/giftManage%';
|
||||
|
||||
-- 3. 添加礼物打赏主菜单
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (0, '礼物打赏', '/gift', 'Layout', 1, 50, 'el-icon-present', NOW(), NOW());
|
||||
|
||||
-- 获取刚插入的主菜单ID
|
||||
SET @gift_menu_id = LAST_INSERT_ID();
|
||||
|
||||
-- 4. 添加子菜单 - 礼物列表
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@gift_menu_id, '礼物列表', 'config', 'gift/config/index', 1, 1, 'el-icon-goods', NOW(), NOW());
|
||||
|
||||
-- 5. 添加子菜单 - 打赏记录
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@gift_menu_id, '打赏记录', 'records', 'gift/records/index', 1, 2, 'el-icon-document', NOW(), NOW());
|
||||
|
||||
-- 6. 添加子菜单 - 充值套餐
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@gift_menu_id, '充值套餐', 'recharge', 'gift/recharge/index', 1, 3, 'el-icon-coin', NOW(), NOW());
|
||||
|
||||
-- 7. 验证插入结果
|
||||
SELECT
|
||||
m1.id,
|
||||
m1.menu_name as '主菜单',
|
||||
m2.id as '子菜单ID',
|
||||
m2.menu_name as '子菜单',
|
||||
m2.path as '路径',
|
||||
m2.component as '组件'
|
||||
FROM eb_system_menu m1
|
||||
LEFT JOIN eb_system_menu m2 ON m1.id = m2.pid
|
||||
WHERE m1.path = '/gift'
|
||||
ORDER BY m2.sort;
|
||||
|
||||
-- 8. 查看所有礼物相关菜单
|
||||
SELECT * FROM eb_system_menu WHERE path LIKE '/gift%' OR pid IN (SELECT id FROM eb_system_menu WHERE path = '/gift');
|
||||
24
add_gift_to_live_manage_correct.sql
Normal file
24
add_gift_to_live_manage_correct.sql
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
-- ========================================
|
||||
-- 正确地将礼物打赏添加到直播管理下
|
||||
-- ========================================
|
||||
|
||||
-- 1. 重新启用直播管理下的礼物打赏菜单
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 1
|
||||
WHERE id = 823
|
||||
AND pid = 675
|
||||
AND name = '礼物打赏';
|
||||
|
||||
-- 2. 验证结果
|
||||
SELECT
|
||||
'=== 直播管理完整菜单 ===' as section,
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE id = 675 OR pid = 675
|
||||
ORDER BY sort;
|
||||
51
check_current_menu_status.sql
Normal file
51
check_current_menu_status.sql
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
-- 检查当前菜单状态,找出可能导致404的原因
|
||||
|
||||
-- 1. 检查直播管理及其所有子菜单的显示状态
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE id = 675 OR pid = 675
|
||||
ORDER BY pid, sort;
|
||||
|
||||
-- 2. 检查是否有其他菜单使用了相同或相似的component路径
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show
|
||||
FROM eb_system_menu
|
||||
WHERE component LIKE '/liveManage%'
|
||||
AND is_show = 1
|
||||
ORDER BY component;
|
||||
|
||||
-- 3. 检查礼物相关菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE component LIKE '%gift%'
|
||||
ORDER BY component;
|
||||
|
||||
-- 4. 查看是否有独立的礼物管理顶级菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE (name LIKE '%礼物%' OR component LIKE '/gift%')
|
||||
AND pid = 0
|
||||
ORDER BY sort;
|
||||
47
check_gift_records.sql
Normal file
47
check_gift_records.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- 检查礼物打赏记录数据
|
||||
|
||||
-- 1. 检查礼物记录表是否存在
|
||||
SHOW TABLES LIKE '%gift%';
|
||||
|
||||
-- 2. 查看礼物记录表结构
|
||||
DESC eb_gift_record;
|
||||
|
||||
-- 3. 查看礼物记录数量
|
||||
SELECT COUNT(*) as total_records FROM eb_gift_record;
|
||||
|
||||
-- 4. 查看最近的礼物记录
|
||||
SELECT * FROM eb_gift_record ORDER BY create_time DESC LIMIT 10;
|
||||
|
||||
-- 5. 如果没有数据,插入一些测试数据
|
||||
-- 用户43送给主播41一个玫瑰
|
||||
INSERT INTO eb_gift_record (sender_id, receiver_id, room_id, gift_id, gift_name, gift_icon, gift_price, quantity, total_price, is_anonymous, create_time)
|
||||
VALUES
|
||||
(43, 41, 8, 1, '玫瑰', 'https://example.com/gifts/rose.png', 1.00, 5, 5.00, 0, NOW()),
|
||||
(43, 41, 8, 2, '巧克力', 'https://example.com/gifts/chocolate.png', 5.00, 2, 10.00, 0, NOW()),
|
||||
(42, 41, 8, 3, '棒棒糖', 'https://example.com/gifts/lollipop.png', 10.00, 1, 10.00, 0, NOW()),
|
||||
(44, 41, 8, 5, '蛋糕', 'https://example.com/gifts/cake.png', 50.00, 1, 50.00, 0, NOW());
|
||||
|
||||
-- 6. 再次查看礼物记录
|
||||
SELECT
|
||||
g.id,
|
||||
g.gift_name,
|
||||
g.quantity,
|
||||
g.total_price,
|
||||
sender.nickname as sender_name,
|
||||
receiver.nickname as receiver_name,
|
||||
r.title as room_title,
|
||||
g.create_time
|
||||
FROM eb_gift_record g
|
||||
LEFT JOIN eb_user sender ON g.sender_id = sender.uid
|
||||
LEFT JOIN eb_user receiver ON g.receiver_id = receiver.uid
|
||||
LEFT JOIN eb_live_room r ON g.room_id = r.id
|
||||
ORDER BY g.create_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 7. 查看统计数据
|
||||
SELECT
|
||||
COUNT(*) as total_count,
|
||||
SUM(total_price) as total_value,
|
||||
SUM(CASE WHEN DATE(create_time) = CURDATE() THEN 1 ELSE 0 END) as today_count,
|
||||
SUM(CASE WHEN DATE(create_time) = CURDATE() THEN total_price ELSE 0 END) as today_value
|
||||
FROM eb_gift_record;
|
||||
29
check_gift_table_structure.sql
Normal file
29
check_gift_table_structure.sql
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
-- ========================================
|
||||
-- 查看礼物表的详细结构和数据
|
||||
-- ========================================
|
||||
|
||||
-- 1. 查看 eb_gift 表结构
|
||||
SHOW FULL COLUMNS FROM eb_gift;
|
||||
|
||||
-- 2. 查看 eb_gift_config 表结构
|
||||
SHOW FULL COLUMNS FROM eb_gift_config;
|
||||
|
||||
-- 3. 查看 eb_gift 现有数据
|
||||
SELECT * FROM eb_gift LIMIT 10;
|
||||
|
||||
-- 4. 查看 eb_gift_config 现有数据
|
||||
SELECT * FROM eb_gift_config LIMIT 10;
|
||||
|
||||
-- 5. 统计礼物数量
|
||||
SELECT
|
||||
'=== 礼物统计 ===' as section,
|
||||
COUNT(*) as total_gifts,
|
||||
SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) as enabled_gifts,
|
||||
SUM(CASE WHEN status = 0 THEN 1 ELSE 0 END) as disabled_gifts
|
||||
FROM eb_gift;
|
||||
|
||||
-- 6. 统计礼物配置数量
|
||||
SELECT
|
||||
'=== 礼物配置统计 ===' as section,
|
||||
COUNT(*) as total_configs
|
||||
FROM eb_gift_config;
|
||||
39
check_live_menu_config.sql
Normal file
39
check_live_menu_config.sql
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
-- 检查直播管理相关的菜单配置
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
path,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE path LIKE '%live%'
|
||||
OR path LIKE '%room%'
|
||||
OR name LIKE '%直播%'
|
||||
OR name LIKE '%房间%'
|
||||
ORDER BY sort, id;
|
||||
|
||||
-- 检查是否有重复或冲突的路径
|
||||
SELECT
|
||||
path,
|
||||
COUNT(*) as count,
|
||||
GROUP_CONCAT(name SEPARATOR ', ') as menu_names
|
||||
FROM eb_system_menu
|
||||
WHERE path LIKE '%live%' OR path LIKE '%room%'
|
||||
GROUP BY path
|
||||
HAVING count > 1;
|
||||
|
||||
-- 检查礼物菜单配置
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
path,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE path LIKE '%gift%'
|
||||
OR name LIKE '%礼物%'
|
||||
ORDER BY sort, id;
|
||||
5
check_menu_table_columns.sql
Normal file
5
check_menu_table_columns.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- 查看菜单表的实际字段结构
|
||||
DESCRIBE eb_system_menu;
|
||||
|
||||
-- 或者使用这个
|
||||
SHOW COLUMNS FROM eb_system_menu;
|
||||
8
check_menu_table_structure.sql
Normal file
8
check_menu_table_structure.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-- 查看菜单表结构
|
||||
DESC eb_system_menu;
|
||||
|
||||
-- 查看现有菜单数据示例
|
||||
SELECT * FROM eb_system_menu LIMIT 5;
|
||||
|
||||
-- 查看所有列名
|
||||
SHOW COLUMNS FROM eb_system_menu;
|
||||
38
clear_frontend_cache.bat
Normal file
38
clear_frontend_cache.bat
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 清除前端缓存并重新构建
|
||||
echo ========================================
|
||||
|
||||
cd Zhibo\admin
|
||||
|
||||
echo.
|
||||
echo [1/4] 删除 node_modules/.cache 目录...
|
||||
if exist node_modules\.cache (
|
||||
rmdir /s /q node_modules\.cache
|
||||
echo 缓存目录已删除
|
||||
) else (
|
||||
echo 缓存目录不存在,跳过
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [2/4] 删除 dist 目录...
|
||||
if exist dist (
|
||||
rmdir /s /q dist
|
||||
echo dist目录已删除
|
||||
) else (
|
||||
echo dist目录不存在,跳过
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [3/4] 重新构建生产环境...
|
||||
call npm run build:prod
|
||||
|
||||
echo.
|
||||
echo [4/4] 完成!
|
||||
echo.
|
||||
echo 请执行以下操作:
|
||||
echo 1. 清除浏览器缓存 (Ctrl+Shift+Delete)
|
||||
echo 2. 重新登录后台
|
||||
echo 3. 测试直播管理菜单
|
||||
echo.
|
||||
pause
|
||||
39
compare_working_menu.sql
Normal file
39
compare_working_menu.sql
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
-- 对比正常工作的菜单和礼物菜单
|
||||
|
||||
-- 1. 查看直播管理菜单(这个应该是正常工作的)
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name as '菜单名',
|
||||
m.component as '组件路径',
|
||||
m.menu_type as '类型',
|
||||
m.icon,
|
||||
m.perms as '权限标识'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '直播管理' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '直播管理' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 2. 查看礼物打赏菜单
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name as '菜单名',
|
||||
m.component as '组件路径',
|
||||
m.menu_type as '类型',
|
||||
m.icon,
|
||||
m.perms as '权限标识'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '礼物打赏' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 3. 查看用户管理菜单(另一个正常工作的)
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name as '菜单名',
|
||||
m.component as '组件路径',
|
||||
m.menu_type as '类型'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '用户管理' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '用户管理' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort
|
||||
LIMIT 5;
|
||||
126
complete_gift_diagnosis.sql
Normal file
126
complete_gift_diagnosis.sql
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
-- 礼物系统完整诊断报告
|
||||
|
||||
SELECT '========== 礼物系统诊断报告 ==========' as '';
|
||||
|
||||
-- 1. 礼物记录统计
|
||||
SELECT '1. 礼物记录统计' as '';
|
||||
SELECT
|
||||
COUNT(*) as '总记录数',
|
||||
COUNT(DISTINCT sender_id) as '送礼用户数',
|
||||
COUNT(DISTINCT receiver_id) as '收礼用户数',
|
||||
SUM(total_price) as '总金额',
|
||||
AVG(total_price) as '平均金额'
|
||||
FROM eb_gift_record;
|
||||
|
||||
-- 2. 最受欢迎的礼物
|
||||
SELECT '2. 最受欢迎的礼物 TOP 5' as '';
|
||||
SELECT
|
||||
gift_name,
|
||||
COUNT(*) as '送出次数',
|
||||
SUM(quantity) as '总数量',
|
||||
SUM(total_price) as '总金额'
|
||||
FROM eb_gift_record
|
||||
GROUP BY gift_name
|
||||
ORDER BY COUNT(*) DESC
|
||||
LIMIT 5;
|
||||
|
||||
-- 3. 收礼排行榜
|
||||
SELECT '3. 收礼排行榜 TOP 5' as '';
|
||||
SELECT
|
||||
receiver_id,
|
||||
receiver_name,
|
||||
COUNT(*) as '收礼次数',
|
||||
SUM(total_price) as '收礼总额'
|
||||
FROM eb_gift_record
|
||||
GROUP BY receiver_id, receiver_name
|
||||
ORDER BY SUM(total_price) DESC
|
||||
LIMIT 5;
|
||||
|
||||
-- 4. 送礼排行榜
|
||||
SELECT '4. 送礼排行榜 TOP 5' as '';
|
||||
SELECT
|
||||
sender_id,
|
||||
sender_name,
|
||||
COUNT(*) as '送礼次数',
|
||||
SUM(total_price) as '送礼总额'
|
||||
FROM eb_gift_record
|
||||
GROUP BY sender_id, sender_name
|
||||
ORDER BY SUM(total_price) DESC
|
||||
LIMIT 5;
|
||||
|
||||
-- 5. 按直播间统计
|
||||
SELECT '5. 直播间礼物统计' as '';
|
||||
SELECT
|
||||
r.room_id,
|
||||
lr.title as '直播间名称',
|
||||
COUNT(*) as '礼物数量',
|
||||
SUM(r.total_price) as '礼物总额'
|
||||
FROM eb_gift_record r
|
||||
LEFT JOIN eb_live_room lr ON r.room_id = lr.id
|
||||
GROUP BY r.room_id, lr.title
|
||||
ORDER BY SUM(r.total_price) DESC;
|
||||
|
||||
-- 6. 礼物配置检查
|
||||
SELECT '6. 礼物配置列表' as '';
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
price,
|
||||
sort_order,
|
||||
is_enabled,
|
||||
CASE is_enabled WHEN 1 THEN '启用' ELSE '禁用' END as '状态'
|
||||
FROM eb_gift_config
|
||||
ORDER BY sort_order;
|
||||
|
||||
-- 7. 用户虚拟货币余额
|
||||
SELECT '7. 测试用户虚拟货币余额' as '';
|
||||
SELECT
|
||||
uid,
|
||||
nickname,
|
||||
virtual_balance as '余额',
|
||||
CASE
|
||||
WHEN virtual_balance >= 10000 THEN '充足'
|
||||
WHEN virtual_balance >= 1000 THEN '正常'
|
||||
WHEN virtual_balance > 0 THEN '偏低'
|
||||
ELSE '不足'
|
||||
END as '状态'
|
||||
FROM eb_user
|
||||
WHERE uid IN (43, 44, 45)
|
||||
ORDER BY uid;
|
||||
|
||||
-- 8. 最近礼物记录
|
||||
SELECT '8. 最近 10 条礼物记录' as '';
|
||||
SELECT
|
||||
id,
|
||||
sender_name as '送礼者',
|
||||
receiver_name as '接收者',
|
||||
gift_name as '礼物',
|
||||
quantity as '数量',
|
||||
total_price as '总价',
|
||||
DATE_FORMAT(create_time, '%Y-%m-%d %H:%i:%s') as '时间'
|
||||
FROM eb_gift_record
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 9. 充值记录统计
|
||||
SELECT '9. 充值记录统计' as '';
|
||||
SELECT
|
||||
COUNT(*) as '充值记录数',
|
||||
COALESCE(SUM(virtual_amount), 0) as '充值总额',
|
||||
COUNT(CASE WHEN payment_status = 1 THEN 1 END) as '成功支付数'
|
||||
FROM eb_virtual_currency_recharge;
|
||||
|
||||
-- 10. 充值套餐配置
|
||||
SELECT '10. 充值套餐配置' as '';
|
||||
SELECT
|
||||
id,
|
||||
title as '套餐名称',
|
||||
amount as '金额',
|
||||
virtual_amount as '虚拟币',
|
||||
bonus_amount as '赠送',
|
||||
CASE is_hot WHEN 1 THEN '是' ELSE '否' END as '热门',
|
||||
CASE is_enabled WHEN 1 THEN '启用' ELSE '禁用' END as '状态'
|
||||
FROM eb_recharge_package
|
||||
ORDER BY sort_order;
|
||||
|
||||
SELECT '========== 诊断完成 ==========' as '';
|
||||
63
create_gift_menu.sql
Normal file
63
create_gift_menu.sql
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
-- ========================================
|
||||
-- 创建独立的礼物打赏管理菜单
|
||||
-- ========================================
|
||||
|
||||
-- 1. 先检查是否已存在礼物打赏顶级菜单
|
||||
SELECT id, pid, name, component, is_show, sort
|
||||
FROM eb_system_menu
|
||||
WHERE name = '礼物打赏' AND pid = 0;
|
||||
|
||||
-- 2. 如果不存在,创建礼物打赏顶级菜单
|
||||
-- 注意:sort值设置为99,放在直播管理(98)之后
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
SELECT 0, '礼物打赏', 'el-icon-present', '', '/gift', 'M', 99, 1, 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0
|
||||
);
|
||||
|
||||
-- 3. 获取新创建的礼物打赏菜单ID
|
||||
SET @gift_menu_id = (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0 LIMIT 1);
|
||||
|
||||
-- 4. 检查是否已有打赏记录子菜单
|
||||
SELECT id, pid, name, component, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE name = '打赏记录' AND component = '/gift/records/index';
|
||||
|
||||
-- 5. 如果不存在,创建打赏记录子菜单
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
SELECT @gift_menu_id, '打赏记录', '', '', '/gift/records/index', 'C', 1, 1, 0
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM eb_system_menu WHERE name = '打赏记录' AND component = '/gift/records/index'
|
||||
);
|
||||
|
||||
-- 6. 验证创建结果
|
||||
SELECT
|
||||
'=== 礼物打赏菜单结构 ===' as section,
|
||||
m1.id as parent_id,
|
||||
m1.name as parent_name,
|
||||
m1.component as parent_component,
|
||||
m2.id as child_id,
|
||||
m2.name as child_name,
|
||||
m2.component as child_component,
|
||||
CASE WHEN m1.is_show = 1 AND m2.is_show = 1 THEN '✓ 都显示'
|
||||
WHEN m1.is_show = 1 THEN '父显示,子隐藏'
|
||||
ELSE '✗ 父隐藏'
|
||||
END as status
|
||||
FROM eb_system_menu m1
|
||||
LEFT JOIN eb_system_menu m2 ON m2.pid = m1.id
|
||||
WHERE m1.name = '礼物打赏' AND m1.pid = 0
|
||||
ORDER BY m2.sort;
|
||||
|
||||
-- 7. 显示所有礼物相关菜单
|
||||
SELECT
|
||||
'=== 所有礼物相关菜单 ===' as section,
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE WHEN is_show = 1 THEN '✓ 显示' ELSE '✗ 隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%礼物%' OR name LIKE '%打赏%' OR component LIKE '%gift%'
|
||||
ORDER BY pid, sort;
|
||||
52
create_gift_table.sql
Normal file
52
create_gift_table.sql
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
-- ========================================
|
||||
-- 创建礼物表
|
||||
-- ========================================
|
||||
|
||||
-- 检查表是否存在
|
||||
SELECT TABLE_NAME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'zhibo'
|
||||
AND TABLE_NAME = 'eb_gift';
|
||||
|
||||
-- 创建礼物表
|
||||
CREATE TABLE IF NOT EXISTS `eb_gift` (
|
||||
`id` int NOT NULL AUTO_INCREMENT COMMENT '礼物ID',
|
||||
`name` varchar(100) NOT NULL COMMENT '礼物名称',
|
||||
`icon` varchar(500) DEFAULT NULL COMMENT '礼物图标URL',
|
||||
`price` int NOT NULL DEFAULT '0' COMMENT '价格(钻石)',
|
||||
`sort` int NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1-启用,0-禁用',
|
||||
`description` varchar(500) DEFAULT NULL COMMENT '礼物描述',
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`is_delete` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除:0-否,1-是',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_sort` (`sort`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='礼物表';
|
||||
|
||||
-- 插入一些示例礼物数据
|
||||
INSERT INTO `eb_gift` (`name`, `icon`, `price`, `sort`, `status`, `description`) VALUES
|
||||
('玫瑰', 'https://example.com/gifts/rose.png', 1, 1, 1, '送你一朵玫瑰'),
|
||||
('巧克力', 'https://example.com/gifts/chocolate.png', 5, 2, 1, '甜蜜的巧克力'),
|
||||
('棒棒糖', 'https://example.com/gifts/lollipop.png', 10, 3, 1, '甜甜的棒棒糖'),
|
||||
('冰淇淋', 'https://example.com/gifts/icecream.png', 20, 4, 1, '清凉的冰淇淋'),
|
||||
('蛋糕', 'https://example.com/gifts/cake.png', 50, 5, 1, '美味的蛋糕'),
|
||||
('香水', 'https://example.com/gifts/perfume.png', 100, 6, 1, '迷人的香水'),
|
||||
('口红', 'https://example.com/gifts/lipstick.png', 200, 7, 1, '魅力口红'),
|
||||
('钻戒', 'https://example.com/gifts/ring.png', 500, 8, 1, '闪耀的钻戒'),
|
||||
('跑车', 'https://example.com/gifts/car.png', 1000, 9, 1, '豪华跑车'),
|
||||
('城堡', 'https://example.com/gifts/castle.png', 5000, 10, 1, '梦幻城堡')
|
||||
ON DUPLICATE KEY UPDATE name=name;
|
||||
|
||||
-- 验证数据
|
||||
SELECT
|
||||
'=== 礼物列表 ===' as section,
|
||||
id,
|
||||
name,
|
||||
price,
|
||||
sort,
|
||||
CASE WHEN status = 1 THEN '启用' ELSE '禁用' END as status,
|
||||
create_time
|
||||
FROM eb_gift
|
||||
ORDER BY sort;
|
||||
39
debug_gift_api_response.sql
Normal file
39
debug_gift_api_response.sql
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
-- 调试礼物API返回的数据
|
||||
|
||||
-- 1. 检查eb_gift表中的数据
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
image,
|
||||
diamond_price,
|
||||
intimacy,
|
||||
status,
|
||||
is_heartbeat,
|
||||
level,
|
||||
sort,
|
||||
is_deleted
|
||||
FROM eb_gift
|
||||
WHERE is_deleted = 0
|
||||
ORDER BY sort ASC, id DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 2. 检查是否所有礼物都被标记为删除
|
||||
SELECT
|
||||
COUNT(*) as total_gifts,
|
||||
SUM(CASE WHEN is_deleted = 0 THEN 1 ELSE 0 END) as active_gifts,
|
||||
SUM(CASE WHEN is_deleted = 1 THEN 1 ELSE 0 END) as deleted_gifts
|
||||
FROM eb_gift;
|
||||
|
||||
-- 3. 如果is_deleted字段不存在,检查表结构
|
||||
SHOW COLUMNS FROM eb_gift LIKE 'is_deleted';
|
||||
|
||||
-- 4. 如果没有is_deleted字段,查看所有礼物
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
image,
|
||||
diamond_price,
|
||||
status
|
||||
FROM eb_gift
|
||||
ORDER BY sort ASC, id DESC
|
||||
LIMIT 10;
|
||||
27
deploy-gift-fix.bat
Normal file
27
deploy-gift-fix.bat
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@echo off
|
||||
echo ===================================
|
||||
echo 部署礼物管理修复
|
||||
echo ===================================
|
||||
|
||||
set SERVER=root@1.15.149.240
|
||||
set JAR_PATH=Zhibo\zhibo-h\crmeb-admin\target\crmeb-admin.jar
|
||||
set REMOTE_PATH=/root/zhibo/admin/
|
||||
|
||||
echo.
|
||||
echo [1/3] 上传JAR文件...
|
||||
scp %JAR_PATH% %SERVER%:%REMOTE_PATH%
|
||||
|
||||
echo.
|
||||
echo [2/3] 重启后台服务...
|
||||
ssh %SERVER% "cd /root/zhibo/admin && ./restart.sh"
|
||||
|
||||
echo.
|
||||
echo [3/3] 等待服务启动...
|
||||
timeout /t 10
|
||||
|
||||
echo.
|
||||
echo ===================================
|
||||
echo 部署完成!
|
||||
echo 请刷新管理后台页面查看礼物记录
|
||||
echo ===================================
|
||||
pause
|
||||
32
deploy-gift-records-fix.bat
Normal file
32
deploy-gift-records-fix.bat
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 修复礼物记录显示问题 - 快速部署
|
||||
echo ========================================
|
||||
|
||||
cd Zhibo\zhibo-h
|
||||
|
||||
echo.
|
||||
echo [1/3] 清理并编译项目...
|
||||
call mvn clean package -DskipTests -Pdev
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo 编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [2/3] 停止远程服务...
|
||||
ssh root@1.15.149.240 "cd /www/server/java && ./stop.sh"
|
||||
|
||||
echo.
|
||||
echo [3/3] 上传并启动服务...
|
||||
scp crmeb-admin\target\crmeb-admin.jar root@1.15.149.240:/www/server/java/
|
||||
ssh root@1.15.149.240 "cd /www/server/java && ./start.sh"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo 礼物记录页面现在应该可以正常显示数据了
|
||||
echo ========================================
|
||||
pause
|
||||
50
deploy-gift-system-complete.bat
Normal file
50
deploy-gift-system-complete.bat
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 礼物系统完整部署
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [1/4] 编译后端...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -Pdev
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo 后端编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [2/4] 编译前端...
|
||||
cd ..\admin
|
||||
call npm run build:prod
|
||||
|
||||
if %errorlevel% neq 0 (
|
||||
echo 前端编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [3/4] 停止远程服务并上传后端...
|
||||
ssh root@1.15.149.240 "cd /www/server/java && ./stop.sh"
|
||||
scp ..\zhibo-h\crmeb-admin\target\crmeb-admin.jar root@1.15.149.240:/www/server/java/
|
||||
|
||||
echo.
|
||||
echo [4/4] 上传前端并启动服务...
|
||||
scp -r dist/* root@1.15.149.240:/www/wwwroot/admin/
|
||||
ssh root@1.15.149.240 "cd /www/server/java && ./start.sh"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo.
|
||||
echo 访问地址:http://1.15.149.240:9527
|
||||
echo.
|
||||
echo 礼物系统菜单:
|
||||
echo - 礼物列表:管理礼物配置
|
||||
echo - 打赏记录:查看打赏记录和统计
|
||||
echo - 充值套餐:管理充值套餐
|
||||
echo ========================================
|
||||
pause
|
||||
38
deploy_gift_in_live.bat
Normal file
38
deploy_gift_in_live.bat
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 部署礼物管理到直播管理下
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [步骤1] 请先执行 add_gift_to_live_manage_correct.sql
|
||||
echo 这会在数据库中启用礼物打赏菜单
|
||||
echo.
|
||||
pause
|
||||
|
||||
echo.
|
||||
echo [步骤2] 清除前端缓存...
|
||||
cd Zhibo\admin
|
||||
|
||||
if exist node_modules\.cache (
|
||||
rmdir /s /q node_modules\.cache
|
||||
echo 缓存已清除
|
||||
)
|
||||
|
||||
if exist dist (
|
||||
rmdir /s /q dist
|
||||
echo dist目录已清除
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [步骤3] 重新构建前端...
|
||||
call npm run build:prod
|
||||
|
||||
echo.
|
||||
echo [步骤4] 完成!
|
||||
echo.
|
||||
echo 现在请:
|
||||
echo 1. 清除浏览器缓存 (Ctrl+Shift+Delete)
|
||||
echo 2. 重新登录后台
|
||||
echo 3. 在"直播管理"菜单下查看"礼物打赏"
|
||||
echo.
|
||||
pause
|
||||
44
deploy_gift_manage_complete.bat
Normal file
44
deploy_gift_manage_complete.bat
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 部署完整的礼物管理功能
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [步骤1] 执行数据库脚本
|
||||
echo 请依次执行以下SQL文件:
|
||||
echo 1. create_gift_table.sql - 创建礼物表
|
||||
echo 2. add_gift_manage_menu.sql - 添加菜单
|
||||
echo.
|
||||
pause
|
||||
|
||||
echo.
|
||||
echo [步骤2] 清除前端缓存...
|
||||
cd Zhibo\admin
|
||||
|
||||
if exist node_modules\.cache (
|
||||
rmdir /s /q node_modules\.cache
|
||||
echo 前端缓存已清除
|
||||
)
|
||||
|
||||
if exist dist (
|
||||
rmdir /s /q dist
|
||||
echo dist目录已清除
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [步骤3] 重新构建前端...
|
||||
call npm run build:prod
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 现在请:
|
||||
echo 1. 清除浏览器缓存 (Ctrl+Shift+Delete)
|
||||
echo 2. 重新登录后台
|
||||
echo 3. 在"直播管理"下查看:
|
||||
echo - 打赏记录:查看礼物打赏记录
|
||||
echo - 礼物管理:管理礼物列表(添加/编辑/删除)
|
||||
echo.
|
||||
pause
|
||||
98
diagnose_and_fix_live_menu.sql
Normal file
98
diagnose_and_fix_live_menu.sql
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
-- ========================================
|
||||
-- 诊断直播管理菜单404问题
|
||||
-- ========================================
|
||||
|
||||
-- 1. 查找所有直播相关的菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort,
|
||||
CASE
|
||||
WHEN is_show = 1 THEN '显示'
|
||||
ELSE '隐藏'
|
||||
END as display_status
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%直播%'
|
||||
OR component LIKE '%live%'
|
||||
OR component LIKE '%room%'
|
||||
OR component LIKE '%family%'
|
||||
OR component LIKE '%fanGroup%'
|
||||
OR component LIKE '%streamer%'
|
||||
ORDER BY pid, sort, id;
|
||||
|
||||
-- 2. 查找礼物相关的菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%礼物%'
|
||||
OR component LIKE '%gift%'
|
||||
ORDER BY pid, sort, id;
|
||||
|
||||
-- 3. 检查是否有component路径冲突
|
||||
SELECT
|
||||
component,
|
||||
COUNT(*) as count,
|
||||
GROUP_CONCAT(CONCAT(id, ':', name) SEPARATOR ' | ') as conflicting_menus
|
||||
FROM eb_system_menu
|
||||
WHERE is_show = 1
|
||||
AND component IS NOT NULL
|
||||
AND component != ''
|
||||
GROUP BY component
|
||||
HAVING count > 1;
|
||||
|
||||
-- ========================================
|
||||
-- 修复方案:确保component字段与前端路由path匹配
|
||||
-- ========================================
|
||||
|
||||
-- 前端路由配置:
|
||||
-- liveManageRouter.path = '/liveManage'
|
||||
-- 子路由:
|
||||
-- - 'room/list' -> '/liveManage/room/list'
|
||||
-- - 'family/list' -> '/liveManage/family/list'
|
||||
-- - 'family/level' -> '/liveManage/family/level'
|
||||
-- - 'family/member' -> '/liveManage/family/member'
|
||||
-- - 'fanGroup/list' -> '/liveManage/fanGroup/list'
|
||||
-- - 'streamer/list' -> '/liveManage/streamer/list'
|
||||
|
||||
-- 礼物路由配置:
|
||||
-- giftManageRouter.path = '/gift'
|
||||
-- 子路由:
|
||||
-- - 'records/index' -> '/gift/records/index'
|
||||
|
||||
-- 4. 查看当前直播管理菜单的component配置
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
'应该是: /liveManage' as expected_component
|
||||
FROM eb_system_menu
|
||||
WHERE name = '直播管理'
|
||||
LIMIT 1;
|
||||
|
||||
-- 5. 查看直播管理的子菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
CASE
|
||||
WHEN name LIKE '%房间%' THEN '应该是: /liveManage/room/list'
|
||||
WHEN name LIKE '%家族列表%' THEN '应该是: /liveManage/family/list'
|
||||
WHEN name LIKE '%家族级别%' THEN '应该是: /liveManage/family/level'
|
||||
WHEN name LIKE '%家族成员%' THEN '应该是: /liveManage/family/member'
|
||||
WHEN name LIKE '%粉丝团%' THEN '应该是: /liveManage/fanGroup/list'
|
||||
WHEN name LIKE '%主播%' THEN '应该是: /liveManage/streamer/list'
|
||||
ELSE '未知'
|
||||
END as expected_component
|
||||
FROM eb_system_menu
|
||||
WHERE pid IN (SELECT id FROM eb_system_menu WHERE name = '直播管理')
|
||||
ORDER BY sort;
|
||||
106
diagnose_gift_system.sql
Normal file
106
diagnose_gift_system.sql
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
-- 礼物系统完整诊断脚本
|
||||
|
||||
-- 1. 检查礼物记录表
|
||||
SELECT '=== 礼物记录表检查 ===' as '';
|
||||
SELECT COUNT(*) as '礼物记录总数' FROM eb_gift_record;
|
||||
SELECT * FROM eb_gift_record ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
-- 2. 检查礼物配置表
|
||||
SELECT '=== 礼物配置表检查 ===' as '';
|
||||
SELECT COUNT(*) as '礼物配置总数' FROM eb_gift_config;
|
||||
SELECT * FROM eb_gift_config ORDER BY sort_order LIMIT 5;
|
||||
|
||||
-- 3. 检查用户虚拟货币
|
||||
SELECT '=== 用户虚拟货币检查 ===' as '';
|
||||
SELECT u.uid, u.nickname, u.phone, u.virtual_balance
|
||||
FROM eb_user u
|
||||
WHERE u.uid IN (43, 44, 45)
|
||||
ORDER BY u.uid;
|
||||
|
||||
-- 4. 检查充值记录
|
||||
SELECT '=== 充值记录检查 ===' as '';
|
||||
SELECT COUNT(*) as '充值记录总数' FROM eb_virtual_currency_recharge;
|
||||
SELECT * FROM eb_virtual_currency_recharge ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
-- 5. 检查直播间
|
||||
SELECT '=== 直播间检查 ===' as '';
|
||||
SELECT id, title, uid as streamer_id, is_live as status FROM eb_live_room WHERE id IN (8, 9, 10) ORDER BY id;
|
||||
|
||||
-- 6. 如果没有测试数据,插入一些
|
||||
SELECT '=== 开始插入测试数据 ===' as '';
|
||||
|
||||
-- 确保用户有虚拟货币余额
|
||||
UPDATE eb_user
|
||||
SET virtual_balance = 10000
|
||||
WHERE uid IN (43, 44, 45) AND (virtual_balance IS NULL OR virtual_balance = 0);
|
||||
|
||||
-- 插入测试礼物记录
|
||||
INSERT INTO eb_gift_record (sender_id, sender_name, receiver_id, receiver_name, room_id, gift_id, gift_name, gift_price, quantity, total_price, create_time)
|
||||
SELECT
|
||||
43 as sender_id,
|
||||
'测试用户43' as sender_name,
|
||||
44 as receiver_id,
|
||||
'测试用户44' as receiver_name,
|
||||
8 as room_id,
|
||||
1 as gift_id,
|
||||
'玫瑰花' as gift_name,
|
||||
10 as gift_price,
|
||||
5 as quantity,
|
||||
50 as total_price,
|
||||
NOW() as create_time
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM eb_gift_record WHERE sender_id = 43 AND receiver_id = 44 LIMIT 1);
|
||||
|
||||
INSERT INTO eb_gift_record (sender_id, sender_name, receiver_id, receiver_name, room_id, gift_id, gift_name, gift_price, quantity, total_price, create_time)
|
||||
SELECT
|
||||
45 as sender_id,
|
||||
'测试用户45' as sender_name,
|
||||
44 as receiver_id,
|
||||
'测试用户44' as receiver_name,
|
||||
8 as room_id,
|
||||
5 as gift_id,
|
||||
'跑车' as gift_name,
|
||||
500 as gift_price,
|
||||
1 as quantity,
|
||||
500 as total_price,
|
||||
NOW() - INTERVAL 1 HOUR as create_time
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM eb_gift_record WHERE sender_id = 45 AND receiver_id = 44 LIMIT 1);
|
||||
|
||||
INSERT INTO eb_gift_record (sender_id, sender_name, receiver_id, receiver_name, room_id, gift_id, gift_name, gift_price, quantity, total_price, create_time)
|
||||
SELECT
|
||||
43 as sender_id,
|
||||
'测试用户43' as sender_name,
|
||||
45 as receiver_id,
|
||||
'测试用户45' as receiver_name,
|
||||
9 as room_id,
|
||||
1 as gift_id,
|
||||
'爱心' as gift_name,
|
||||
1 as gift_price,
|
||||
100 as quantity,
|
||||
100 as total_price,
|
||||
NOW() - INTERVAL 2 HOUR as create_time
|
||||
FROM DUAL
|
||||
WHERE (SELECT COUNT(*) FROM eb_gift_record) < 3;
|
||||
|
||||
-- 7. 验证插入结果
|
||||
SELECT '=== 验证测试数据 ===' as '';
|
||||
SELECT COUNT(*) as '当前礼物记录总数' FROM eb_gift_record;
|
||||
|
||||
SELECT
|
||||
g.id,
|
||||
g.gift_name,
|
||||
g.gift_price,
|
||||
g.quantity,
|
||||
g.total_price,
|
||||
sender.nickname as sender_name,
|
||||
receiver.nickname as receiver_name,
|
||||
g.room_id,
|
||||
g.create_time
|
||||
FROM eb_gift_record g
|
||||
LEFT JOIN eb_user sender ON g.sender_id = sender.uid
|
||||
LEFT JOIN eb_user receiver ON g.receiver_id = receiver.uid
|
||||
ORDER BY g.create_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
SELECT '=== 诊断完成 ===' as '';
|
||||
76
diagnose_menu_404.sql
Normal file
76
diagnose_menu_404.sql
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
-- 完整诊断菜单404问题
|
||||
|
||||
-- 1. 检查直播管理菜单及其子菜单
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name,
|
||||
m.path,
|
||||
m.component,
|
||||
m.is_show,
|
||||
m.sort,
|
||||
CASE
|
||||
WHEN m.pid = 0 THEN '顶级菜单'
|
||||
ELSE CONCAT('子菜单(父ID:', m.pid, ')')
|
||||
END as menu_level
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name LIKE '%直播%'
|
||||
OR m.path LIKE '%live%'
|
||||
OR m.path LIKE '%room%'
|
||||
OR m.path LIKE '%family%'
|
||||
OR m.path LIKE '%fanGroup%'
|
||||
OR m.path LIKE '%streamer%'
|
||||
ORDER BY m.pid, m.sort, m.id;
|
||||
|
||||
-- 2. 检查礼物管理菜单
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name,
|
||||
m.path,
|
||||
m.component,
|
||||
m.is_show,
|
||||
m.sort
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name LIKE '%礼物%'
|
||||
OR m.path LIKE '%gift%'
|
||||
ORDER BY m.pid, m.sort, m.id;
|
||||
|
||||
-- 3. 检查是否有路径冲突
|
||||
SELECT
|
||||
path,
|
||||
COUNT(*) as count,
|
||||
GROUP_CONCAT(CONCAT(id, ':', name) SEPARATOR ' | ') as conflicting_menus
|
||||
FROM eb_system_menu
|
||||
WHERE is_show = 1
|
||||
GROUP BY path
|
||||
HAVING count > 1;
|
||||
|
||||
-- 4. 检查component路径格式
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
path,
|
||||
component,
|
||||
CASE
|
||||
WHEN component LIKE '%.vue' THEN '有.vue扩展名'
|
||||
WHEN component LIKE '%/%' THEN '无.vue扩展名'
|
||||
ELSE '其他格式'
|
||||
END as component_format
|
||||
FROM eb_system_menu
|
||||
WHERE (name LIKE '%直播%' OR path LIKE '%live%' OR path LIKE '%room%')
|
||||
AND component IS NOT NULL
|
||||
AND component != '';
|
||||
|
||||
-- 5. 检查菜单是否被禁用
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
path,
|
||||
is_show,
|
||||
CASE
|
||||
WHEN is_show = 1 THEN '显示'
|
||||
ELSE '隐藏'
|
||||
END as display_status
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%直播%' OR path LIKE '%live%';
|
||||
15
final_fix_gift_menu.sql
Normal file
15
final_fix_gift_menu.sql
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
-- 最终修复:使用系统能识别的路径格式
|
||||
|
||||
-- 删除礼物菜单
|
||||
DELETE FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
|
||||
-- 重新添加,使用简单的路径
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
VALUES (0, '礼物打赏', 'el-icon-present', 'admin:gift:records', 'gift/records/index', 'C', 50, 1, 0);
|
||||
|
||||
-- 给管理员分配权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
|
||||
-- 验证
|
||||
SELECT id, name, component FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
14
final_move_gift_to_live.sql
Normal file
14
final_move_gift_to_live.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
-- 正确地将礼物打赏移到直播管理下,同时修改路径
|
||||
|
||||
-- 1. 获取直播管理ID
|
||||
SELECT @live_id := id FROM eb_system_menu WHERE name = '直播管理' AND pid = 0;
|
||||
|
||||
-- 2. 更新礼物打赏:改变父级ID AND 修改component路径
|
||||
UPDATE eb_system_menu
|
||||
SET pid = @live_id,
|
||||
component = '/liveManage/gift/records/index',
|
||||
sort = 800
|
||||
WHERE name = '礼物打赏';
|
||||
|
||||
-- 3. 验证
|
||||
SELECT name, component, pid FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
44
find_existing_gift_tables.sql
Normal file
44
find_existing_gift_tables.sql
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
-- ========================================
|
||||
-- 查找现有的礼物相关表
|
||||
-- ========================================
|
||||
|
||||
-- 1. 查找所有包含gift的表
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_COMMENT,
|
||||
CREATE_TIME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'zhibo'
|
||||
AND TABLE_NAME LIKE '%gift%'
|
||||
ORDER BY TABLE_NAME;
|
||||
|
||||
-- 2. 查找所有包含reward的表(打赏相关)
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_COMMENT,
|
||||
CREATE_TIME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'zhibo'
|
||||
AND TABLE_NAME LIKE '%reward%'
|
||||
ORDER BY TABLE_NAME;
|
||||
|
||||
-- 3. 查找所有包含present的表(礼物相关)
|
||||
SELECT
|
||||
TABLE_NAME,
|
||||
TABLE_COMMENT,
|
||||
CREATE_TIME
|
||||
FROM information_schema.TABLES
|
||||
WHERE TABLE_SCHEMA = 'zhibo'
|
||||
AND TABLE_NAME LIKE '%present%'
|
||||
ORDER BY TABLE_NAME;
|
||||
|
||||
-- 4. 如果找到了礼物表,查看其结构
|
||||
-- 请根据上面的结果,取消下面对应表的注释来查看结构
|
||||
|
||||
-- SHOW FULL COLUMNS FROM eb_gift;
|
||||
-- SHOW FULL COLUMNS FROM eb_gift_record;
|
||||
-- SHOW FULL COLUMNS FROM eb_gift_reward;
|
||||
|
||||
-- 5. 如果找到了礼物表,查看现有数据
|
||||
-- SELECT * FROM eb_gift LIMIT 10;
|
||||
-- SELECT * FROM eb_gift_record LIMIT 10;
|
||||
38
fix_404_remove_gift_from_live.sql
Normal file
38
fix_404_remove_gift_from_live.sql
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
-- ========================================
|
||||
-- 修复404问题:将礼物打赏从直播管理中移除
|
||||
-- ========================================
|
||||
|
||||
-- 问题分析:
|
||||
-- 1. 礼物打赏菜单(id=823)的component是 /liveManage/gift/records/index
|
||||
-- 2. 但前端有独立的 giftManageRouter,路径是 /gift
|
||||
-- 3. 这导致路由匹配冲突
|
||||
|
||||
-- 解决方案1:将礼物打赏移到独立的礼物管理菜单下
|
||||
-- 首先检查是否已有礼物管理顶级菜单
|
||||
SELECT id, pid, name, component, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE name = '礼物打赏' AND pid = 0;
|
||||
|
||||
-- 如果没有,创建礼物管理顶级菜单
|
||||
-- INSERT INTO eb_system_menu (pid, name, icon, component, menu_type, sort, is_show)
|
||||
-- VALUES (0, '礼物打赏', 'el-icon-present', '/gift', 'M', 99, 1);
|
||||
|
||||
-- 方案2:直接删除礼物打赏菜单(如果不需要在直播管理下显示)
|
||||
-- DELETE FROM eb_system_menu WHERE id = 823;
|
||||
|
||||
-- 方案3:隐藏礼物打赏菜单(推荐,保留数据)
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 0
|
||||
WHERE id = 823;
|
||||
|
||||
-- 验证修改
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
component,
|
||||
is_show,
|
||||
CASE WHEN is_show = 1 THEN '显示' ELSE '隐藏' END as status
|
||||
FROM eb_system_menu
|
||||
WHERE pid = 675 -- 直播管理的子菜单
|
||||
ORDER BY sort;
|
||||
43
fix_gift_menu_complete.sql
Normal file
43
fix_gift_menu_complete.sql
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
-- 完整修复礼物菜单
|
||||
|
||||
-- 步骤1: 查看eb_system_menu表结构
|
||||
DESC eb_system_menu;
|
||||
|
||||
-- 步骤2: 查看当前礼物相关菜单
|
||||
SELECT * FROM eb_system_menu WHERE menu_name LIKE '%礼物%' OR path LIKE '%gift%';
|
||||
|
||||
-- 步骤3: 删除旧的礼物菜单
|
||||
DELETE FROM eb_system_menu WHERE menu_name LIKE '%礼物%' OR path LIKE '%gift%';
|
||||
|
||||
-- 步骤4: 插入礼物打赏主菜单
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (0, '礼物打赏', '/gift', 'Layout', 1, 50, 'el-icon-present', NOW(), NOW());
|
||||
|
||||
-- 步骤5: 获取主菜单ID并插入子菜单
|
||||
SET @gift_pid = (SELECT id FROM eb_system_menu WHERE path = '/gift' AND pid = 0);
|
||||
|
||||
INSERT INTO eb_system_menu (pid, menu_name, path, component, is_show, sort, icon, create_time, update_time) VALUES
|
||||
(@gift_pid, '礼物列表', 'config', 'gift/config/index', 1, 1, 'el-icon-goods', NOW(), NOW()),
|
||||
(@gift_pid, '打赏记录', 'records', 'gift/records/index', 1, 2, 'el-icon-document', NOW(), NOW()),
|
||||
(@gift_pid, '充值套餐', 'recharge', 'gift/recharge/index', 1, 3, 'el-icon-coin', NOW(), NOW());
|
||||
|
||||
-- 步骤6: 验证结果
|
||||
SELECT
|
||||
CASE WHEN m.pid = 0 THEN '主菜单' ELSE '子菜单' END as '类型',
|
||||
m.id,
|
||||
m.pid,
|
||||
m.menu_name as '菜单名称',
|
||||
m.path as '路径',
|
||||
m.component as '组件',
|
||||
m.icon as '图标',
|
||||
m.sort as '排序',
|
||||
m.is_show as '显示'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.path = '/gift' OR m.pid = @gift_pid
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 步骤7: 查看所有一级菜单(确认礼物打赏菜单的位置)
|
||||
SELECT id, menu_name, path, icon, sort
|
||||
FROM eb_system_menu
|
||||
WHERE pid = 0
|
||||
ORDER BY sort;
|
||||
38
fix_gift_menu_final.sql
Normal file
38
fix_gift_menu_final.sql
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
-- 最终修复礼物菜单 - 确保字段完全匹配
|
||||
|
||||
-- 1. 先查看现有的工作菜单示例
|
||||
SELECT * FROM eb_system_menu WHERE name = '直播管理' LIMIT 1;
|
||||
SELECT * FROM eb_system_menu WHERE pid = (SELECT id FROM eb_system_menu WHERE name = '直播管理' LIMIT 1) LIMIT 3;
|
||||
|
||||
-- 2. 删除旧的礼物菜单
|
||||
DELETE FROM eb_system_menu WHERE name IN ('礼物打赏', '礼物列表', '打赏记录', '充值套餐', '礼物管理');
|
||||
|
||||
-- 3. 添加礼物打赏主菜单
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
VALUES (0, '礼物打赏', 'el-icon-present', '', '/gift', 'M', 50, 1, 0);
|
||||
|
||||
SET @gift_pid = LAST_INSERT_ID();
|
||||
|
||||
-- 4. 添加子菜单
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte) VALUES
|
||||
(@gift_pid, '礼物列表', '', 'admin:gift:config', 'gift/config/index', 'C', 1, 1, 0),
|
||||
(@gift_pid, '打赏记录', '', 'admin:gift:records', 'gift/records/index', 'C', 2, 1, 0),
|
||||
(@gift_pid, '充值套餐', '', 'admin:gift:recharge', 'gift/recharge/index', 'C', 3, 1, 0);
|
||||
|
||||
-- 5. 验证
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name,
|
||||
m.component,
|
||||
m.menu_type,
|
||||
m.sort
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '礼物打赏' OR m.pid = @gift_pid
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 6. 给管理员分配权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE name IN ('礼物打赏', '礼物列表', '打赏记录', '充值套餐');
|
||||
|
||||
SELECT '菜单添加完成!请退出登录后重新登录查看' as message;
|
||||
27
fix_gift_menu_paths.sql
Normal file
27
fix_gift_menu_paths.sql
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-- 修复礼物菜单路径 - 使用完整路径
|
||||
|
||||
-- 1. 更新子菜单的component路径为完整路径
|
||||
UPDATE eb_system_menu
|
||||
SET component = '/gift/config/index'
|
||||
WHERE name = '礼物列表' AND pid = (SELECT id FROM (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0) AS temp);
|
||||
|
||||
UPDATE eb_system_menu
|
||||
SET component = '/gift/records/index'
|
||||
WHERE name = '打赏记录' AND pid = (SELECT id FROM (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0) AS temp);
|
||||
|
||||
UPDATE eb_system_menu
|
||||
SET component = '/gift/recharge/index'
|
||||
WHERE name = '充值套餐' AND pid = (SELECT id FROM (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0) AS temp);
|
||||
|
||||
-- 2. 验证修复结果
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name as '菜单名',
|
||||
m.component as '组件路径',
|
||||
m.menu_type as '类型'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '礼物打赏' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
SELECT '路径已修复!请刷新浏览器页面' as message;
|
||||
20
fix_live_menu_404.sql
Normal file
20
fix_live_menu_404.sql
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
-- 先查看菜单表结构
|
||||
SHOW COLUMNS FROM eb_system_menu;
|
||||
|
||||
-- 查看所有菜单数据,了解字段名称
|
||||
SELECT * FROM eb_system_menu LIMIT 5;
|
||||
|
||||
-- 查找直播相关的菜单(使用可能的字段名)
|
||||
-- 可能的字段:menu_name/name, menu_path/path/component, pid/parent_id
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
menu_name,
|
||||
component,
|
||||
is_show,
|
||||
sort
|
||||
FROM eb_system_menu
|
||||
WHERE menu_name LIKE '%直播%'
|
||||
OR component LIKE '%live%'
|
||||
OR component LIKE '%room%'
|
||||
ORDER BY sort, id;
|
||||
67
insert_gift_menus_correct.sql
Normal file
67
insert_gift_menus_correct.sql
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
-- 正确添加礼物打赏菜单
|
||||
|
||||
-- 1. 删除旧的礼物菜单(如果存在)
|
||||
DELETE FROM eb_system_menu WHERE name LIKE '%礼物%';
|
||||
|
||||
-- 2. 添加礼物打赏主菜单(目录类型 M)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (0, '礼物打赏', 'el-icon-present', '', '/gift', 'M', 50, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 3. 获取刚插入的主菜单ID
|
||||
SET @gift_pid = LAST_INSERT_ID();
|
||||
|
||||
-- 4. 添加子菜单 - 礼物列表(菜单类型 C)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (@gift_pid, '礼物列表', 'el-icon-goods', 'admin:gift:config', 'gift/config/index', 'C', 1, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 5. 添加子菜单 - 打赏记录(菜单类型 C)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (@gift_pid, '打赏记录', 'el-icon-document', 'admin:gift:records', 'gift/records/index', 'C', 2, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 6. 添加子菜单 - 充值套餐(菜单类型 C)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte, create_time, update_time)
|
||||
VALUES (@gift_pid, '充值套餐', 'el-icon-coin', 'admin:gift:recharge', 'gift/recharge/index', 'C', 3, 1, 0, NOW(), NOW());
|
||||
|
||||
-- 7. 验证插入结果
|
||||
SELECT
|
||||
CASE WHEN m.pid = 0 THEN '主菜单' ELSE ' └─ 子菜单' END as '层级',
|
||||
m.id as 'ID',
|
||||
m.name as '菜单名称',
|
||||
m.component as '组件路径',
|
||||
m.icon as '图标',
|
||||
m.menu_type as '类型',
|
||||
m.sort as '排序',
|
||||
CASE WHEN m.is_show = 1 THEN '显示' ELSE '隐藏' END as '状态'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '礼物打赏' OR m.pid = @gift_pid
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 8. 给管理员角色分配权限(假设管理员角色ID为1)
|
||||
-- 先查看角色
|
||||
SELECT * FROM eb_system_role LIMIT 5;
|
||||
|
||||
-- 获取所有礼物菜单ID
|
||||
SELECT @gift_main_id := id FROM eb_system_menu WHERE name = '礼物打赏' AND pid = 0 LIMIT 1;
|
||||
SELECT @gift_config_id := id FROM eb_system_menu WHERE name = '礼物列表' AND pid = @gift_main_id LIMIT 1;
|
||||
SELECT @gift_records_id := id FROM eb_system_menu WHERE name = '打赏记录' AND pid = @gift_main_id LIMIT 1;
|
||||
SELECT @gift_recharge_id := id FROM eb_system_menu WHERE name = '充值套餐' AND pid = @gift_main_id LIMIT 1;
|
||||
|
||||
-- 给管理员角色(rid=1)分配权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id) VALUES
|
||||
(1, @gift_main_id),
|
||||
(1, @gift_config_id),
|
||||
(1, @gift_records_id),
|
||||
(1, @gift_recharge_id);
|
||||
|
||||
-- 9. 最终验证
|
||||
SELECT '========== 菜单添加完成 ==========' as '';
|
||||
SELECT
|
||||
m.id,
|
||||
m.pid,
|
||||
m.name as '菜单名称',
|
||||
m.component as '组件',
|
||||
m.icon as '图标',
|
||||
m.sort as '排序'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name LIKE '%礼物%' OR m.pid IN (SELECT id FROM eb_system_menu WHERE name = '礼物打赏')
|
||||
ORDER BY m.pid, m.sort;
|
||||
7
keep_gift_independent.sql
Normal file
7
keep_gift_independent.sql
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
-- 保持礼物打赏为独立菜单(最简单可靠的方案)
|
||||
|
||||
UPDATE eb_system_menu
|
||||
SET pid = 0, sort = 51
|
||||
WHERE name = '礼物打赏';
|
||||
|
||||
SELECT '礼物打赏已恢复为独立菜单,可以正常使用' as message;
|
||||
21
move_gift_to_live_correctly.sql
Normal file
21
move_gift_to_live_correctly.sql
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-- 正确地将礼物打赏移到直播管理下
|
||||
|
||||
-- 1. 获取直播管理的ID
|
||||
SELECT @live_id := id FROM eb_system_menu WHERE name = '直播管理' AND pid = 0;
|
||||
|
||||
-- 2. 更新礼物打赏,保持其类型为C(菜单),只改变父级
|
||||
UPDATE eb_system_menu
|
||||
SET pid = @live_id,
|
||||
sort = 800
|
||||
WHERE name = '礼物打赏';
|
||||
|
||||
-- 3. 验证结果
|
||||
SELECT
|
||||
'直播管理子菜单' as '类别',
|
||||
m.name as '菜单名',
|
||||
m.menu_type as '类型',
|
||||
m.component as '组件路径',
|
||||
m.sort as '排序'
|
||||
FROM eb_system_menu m
|
||||
WHERE m.pid = @live_id
|
||||
ORDER BY m.sort;
|
||||
19
move_gift_to_live_manage.sql
Normal file
19
move_gift_to_live_manage.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
-- 将礼物打赏移到直播管理菜单下
|
||||
|
||||
-- 1. 获取直播管理的ID
|
||||
SELECT @live_manage_id := id FROM eb_system_menu WHERE name = '直播管理' AND pid = 0;
|
||||
|
||||
-- 2. 更新礼物打赏的pid,让它成为直播管理的子菜单
|
||||
UPDATE eb_system_menu
|
||||
SET pid = @live_manage_id, sort = 999
|
||||
WHERE name = '礼物打赏';
|
||||
|
||||
-- 3. 验证结果
|
||||
SELECT
|
||||
m1.name as '父菜单',
|
||||
m2.name as '子菜单',
|
||||
m2.component as '路径'
|
||||
FROM eb_system_menu m1
|
||||
JOIN eb_system_menu m2 ON m1.id = m2.pid
|
||||
WHERE m1.name = '直播管理'
|
||||
ORDER BY m2.sort;
|
||||
17
quick_test_gift_system.sql
Normal file
17
quick_test_gift_system.sql
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-- 快速测试礼物系统
|
||||
|
||||
-- 1. 查看表结构
|
||||
DESC eb_gift_record;
|
||||
|
||||
-- 2. 查看现有数据
|
||||
SELECT COUNT(*) as total FROM eb_gift_record;
|
||||
|
||||
-- 3. 查看最新5条记录
|
||||
SELECT * FROM eb_gift_record ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
-- 4. 检查用户虚拟货币
|
||||
SELECT uid, nickname, virtual_balance FROM eb_user WHERE uid IN (43, 44, 45);
|
||||
|
||||
-- 5. 测试插入(如果需要)
|
||||
-- INSERT INTO eb_gift_record (sender_id, sender_name, receiver_id, receiver_name, room_id, gift_id, gift_name, gift_price, quantity, total_price, create_time)
|
||||
-- VALUES (43, '测试用户43', 44, '测试用户44', 8, 1, '测试礼物', 10, 1, 10, NOW());
|
||||
20
rebuild_backend_gift.bat
Normal file
20
rebuild_backend_gift.bat
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 重新编译后端礼物管理接口
|
||||
echo ========================================
|
||||
|
||||
cd Zhibo\zhibo-h
|
||||
|
||||
echo.
|
||||
echo [1/2] 清理并编译...
|
||||
call mvn clean package -DskipTests
|
||||
|
||||
echo.
|
||||
echo [2/2] 完成!
|
||||
echo.
|
||||
echo 现在请重启后端服务:
|
||||
echo 1. 停止当前运行的Java进程
|
||||
echo 2. 重新启动后端服务
|
||||
echo 3. 刷新前端页面
|
||||
echo.
|
||||
pause
|
||||
29
restart_frontend.bat
Normal file
29
restart_frontend.bat
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 清理前端缓存并重启
|
||||
echo ========================================
|
||||
|
||||
cd Zhibo\admin
|
||||
|
||||
echo.
|
||||
echo [1/3] 停止开发服务器...
|
||||
taskkill /F /IM node.exe 2>nul
|
||||
|
||||
echo.
|
||||
echo [2/3] 清理缓存...
|
||||
rmdir /s /q node_modules\.cache 2>nul
|
||||
rmdir /s /q dist 2>nul
|
||||
|
||||
echo.
|
||||
echo [3/3] 重新启动开发服务器...
|
||||
echo 请手动运行: npm run dev
|
||||
echo.
|
||||
echo 或者在新窗口中运行:
|
||||
start cmd /k "cd /d %cd% && npm run dev"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 完成!
|
||||
echo ========================================
|
||||
pause
|
||||
8
restore_gift_menu.sql
Normal file
8
restore_gift_menu.sql
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-- 恢复礼物打赏为独立菜单
|
||||
|
||||
UPDATE eb_system_menu
|
||||
SET pid = 0, sort = 50
|
||||
WHERE name = '礼物打赏';
|
||||
|
||||
-- 验证
|
||||
SELECT id, pid, name, component FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
17
simple_gift_menu_records_only.sql
Normal file
17
simple_gift_menu_records_only.sql
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-- 简化版:只添加打赏记录菜单(最重要的功能)
|
||||
|
||||
-- 删除所有礼物相关菜单
|
||||
DELETE FROM eb_system_menu WHERE name LIKE '%礼物%';
|
||||
|
||||
-- 只添加打赏记录菜单(作为一级菜单,不需要子菜单)
|
||||
INSERT INTO eb_system_menu (pid, name, icon, perms, component, menu_type, sort, is_show, is_delte)
|
||||
VALUES (0, '礼物打赏', 'el-icon-present', 'admin:gift:records', '/gift/records/index', 'C', 50, 1, 0);
|
||||
|
||||
-- 给管理员分配权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
|
||||
-- 验证
|
||||
SELECT id, pid, name, component, menu_type FROM eb_system_menu WHERE name = '礼物打赏';
|
||||
|
||||
SELECT '简化菜单创建完成!刷新浏览器后,点击"礼物打赏"直接进入打赏记录页面' as message;
|
||||
59
test_gift_api.md
Normal file
59
test_gift_api.md
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
# 测试礼物管理API
|
||||
|
||||
## 1. 测试后端接口
|
||||
|
||||
在浏览器中打开开发者工具(F12),然后访问礼物管理页面,查看Network标签页中的请求:
|
||||
|
||||
### 检查请求
|
||||
- URL: `/api/admin/gift/list?page=1&limit=20`
|
||||
- Method: GET
|
||||
- Status: 应该是 200
|
||||
|
||||
### 检查响应格式
|
||||
后端应该返回这样的格式:
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"list": [...],
|
||||
"total": 20,
|
||||
"page": 1,
|
||||
"limit": 20,
|
||||
"totalPage": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. 如果返回格式不对
|
||||
|
||||
检查后端日志,看是否有错误信息。
|
||||
|
||||
## 3. 直接测试SQL
|
||||
|
||||
在数据库中执行:
|
||||
```sql
|
||||
SELECT id, name, image, diamond_price as diamondPrice, intimacy, status,
|
||||
is_heartbeat as isHeartbeat, buy_type as buyType, belong, remark,
|
||||
level, sort, create_time as createTime, update_time as updateTime
|
||||
FROM eb_gift
|
||||
WHERE is_deleted = 0
|
||||
ORDER BY sort ASC, id DESC
|
||||
LIMIT 20 OFFSET 0;
|
||||
```
|
||||
|
||||
应该能看到20条礼物记录。
|
||||
|
||||
## 4. 常见问题
|
||||
|
||||
### 问题1: 404错误
|
||||
- 确认后端服务已重启
|
||||
- 确认GiftAdminController已编译
|
||||
|
||||
### 问题2: 数据为空
|
||||
- 检查数据库中是否有数据
|
||||
- 检查is_deleted字段是否都是0
|
||||
|
||||
### 问题3: 前端报错
|
||||
- 清除浏览器缓存
|
||||
- 重新构建前端:`npm run build:prod`
|
||||
37
update_gift_reward_menu.sql
Normal file
37
update_gift_reward_menu.sql
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
-- 更新现有的"打赏记录"菜单,使用我们新创建的页面
|
||||
|
||||
-- 1. 查看现有的打赏记录菜单
|
||||
SELECT id, pid, name, component, menu_type, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE name LIKE '%打赏%' OR name LIKE '%记录%'
|
||||
AND is_delte = 0
|
||||
ORDER BY pid, sort;
|
||||
|
||||
-- 2. 找到"打赏记录"菜单(ID应该是633,在礼物打赏管理532下)
|
||||
-- 更新它的component为我们新创建的页面
|
||||
UPDATE eb_system_menu
|
||||
SET component = 'gift/records/index',
|
||||
name = '礼物打赏记录',
|
||||
update_time = NOW()
|
||||
WHERE id = 633;
|
||||
|
||||
-- 3. 验证更新
|
||||
SELECT id, pid, name, component, menu_type, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE id = 633;
|
||||
|
||||
-- 4. 确保父菜单(礼物打赏管理)是显示的
|
||||
UPDATE eb_system_menu
|
||||
SET is_show = 1
|
||||
WHERE id = 532;
|
||||
|
||||
-- 5. 查看更新后的菜单结构
|
||||
SELECT
|
||||
m1.id as parent_id,
|
||||
m1.name as parent_name,
|
||||
m2.id as child_id,
|
||||
m2.name as child_name,
|
||||
m2.component
|
||||
FROM eb_system_menu m1
|
||||
LEFT JOIN eb_system_menu m2 ON m1.id = m2.pid
|
||||
WHERE m1.id = 532 AND m1.is_delte = 0;
|
||||
53
verify_gift_menu.sql
Normal file
53
verify_gift_menu.sql
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
-- 验证礼物管理菜单是否正确添加
|
||||
|
||||
-- 1. 查看礼物管理菜单
|
||||
SELECT
|
||||
id,
|
||||
pid,
|
||||
name,
|
||||
icon,
|
||||
component,
|
||||
menu_type,
|
||||
sort,
|
||||
is_show
|
||||
FROM eb_system_menu
|
||||
WHERE (name LIKE '%礼物%' OR pid IN (SELECT id FROM eb_system_menu WHERE name = '礼物管理'))
|
||||
AND is_delte = 0
|
||||
ORDER BY pid, sort;
|
||||
|
||||
-- 2. 查看菜单层级结构
|
||||
SELECT
|
||||
CONCAT(REPEAT(' ', CASE WHEN m.pid = 0 THEN 0 ELSE 1 END), m.name) as menu_tree,
|
||||
m.id,
|
||||
m.component,
|
||||
m.menu_type,
|
||||
m.is_show
|
||||
FROM eb_system_menu m
|
||||
WHERE (m.name = '礼物管理' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '礼物管理' LIMIT 1))
|
||||
AND m.is_delte = 0
|
||||
ORDER BY m.pid, m.sort;
|
||||
|
||||
-- 3. 查看管理员角色的礼物管理权限
|
||||
SELECT
|
||||
r.id as role_id,
|
||||
r.role_name,
|
||||
m.id as menu_id,
|
||||
m.name as menu_name,
|
||||
m.component
|
||||
FROM eb_system_role r
|
||||
JOIN eb_system_role_menu rm ON r.id = rm.rid
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name LIKE '%礼物%'
|
||||
AND r.id = 1;
|
||||
|
||||
-- 4. 查看礼物配置数据
|
||||
SELECT id, name, price, sort_order, is_enabled
|
||||
FROM eb_gift_config
|
||||
ORDER BY sort_order
|
||||
LIMIT 10;
|
||||
|
||||
-- 5. 查看充值套餐数据
|
||||
SELECT id, amount, virtual_amount, bonus_amount, title, is_enabled
|
||||
FROM eb_recharge_package
|
||||
ORDER BY sort_order
|
||||
LIMIT 10;
|
||||
20
verify_menu_after_fix.sql
Normal file
20
verify_menu_after_fix.sql
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
-- 验证菜单修复后的状态
|
||||
|
||||
SELECT
|
||||
'直播管理(参考)' as '对比',
|
||||
m.id,
|
||||
m.name,
|
||||
m.component
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '直播管理' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '直播管理' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort
|
||||
LIMIT 3;
|
||||
|
||||
SELECT
|
||||
'礼物打赏(当前)' as '对比',
|
||||
m.id,
|
||||
m.name,
|
||||
m.component
|
||||
FROM eb_system_menu m
|
||||
WHERE m.name = '礼物打赏' OR m.pid = (SELECT id FROM eb_system_menu WHERE name = '礼物打赏' LIMIT 1)
|
||||
ORDER BY m.pid, m.sort;
|
||||
214
添加礼物打赏菜单配置说明.md
Normal file
214
添加礼物打赏菜单配置说明.md
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
# 添加礼物打赏菜单配置说明
|
||||
|
||||
## 步骤1:在数据库中添加菜单
|
||||
|
||||
执行以下SQL,在后台管理系统中添加"礼物打赏"菜单:
|
||||
|
||||
```sql
|
||||
-- 添加礼物管理菜单
|
||||
INSERT INTO eb_system_menu (pid, name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (0, '礼物管理', '/gift', 'Layout', 1, 100, 'el-icon-present', NOW(), NOW());
|
||||
|
||||
-- 获取刚插入的父菜单ID(假设为最新的ID)
|
||||
SET @parent_id = LAST_INSERT_ID();
|
||||
|
||||
-- 添加礼物打赏子菜单
|
||||
INSERT INTO eb_system_menu (pid, name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@parent_id, '礼物打赏', 'records', 'gift/records/index', 1, 1, 'el-icon-present', NOW(), NOW());
|
||||
|
||||
-- 添加礼物配置子菜单(可选)
|
||||
INSERT INTO eb_system_menu (pid, name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@parent_id, '礼物配置', 'config', 'gift/config/index', 1, 2, 'el-icon-setting', NOW(), NOW());
|
||||
|
||||
-- 添加充值套餐子菜单(可选)
|
||||
INSERT INTO eb_system_menu (pid, name, path, component, is_show, sort, icon, create_time, update_time)
|
||||
VALUES (@parent_id, '充值套餐', 'packages', 'gift/packages/index', 1, 3, 'el-icon-coin', NOW(), NOW());
|
||||
|
||||
-- 查看添加的菜单
|
||||
SELECT * FROM eb_system_menu WHERE name LIKE '%礼物%' OR name LIKE '%充值%';
|
||||
```
|
||||
|
||||
## 步骤2:如果没有菜单表,手动配置路由
|
||||
|
||||
如果你的系统不是从数据库读取菜单,需要手动在前端路由文件中添加。
|
||||
|
||||
找到 `Zhibo/admin/src/router/index.js` 文件,添加以下路由配置:
|
||||
|
||||
```javascript
|
||||
{
|
||||
path: '/gift',
|
||||
component: Layout,
|
||||
redirect: '/gift/records',
|
||||
name: 'Gift',
|
||||
meta: {
|
||||
title: '礼物管理',
|
||||
icon: 'el-icon-present'
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'records',
|
||||
name: 'GiftRecords',
|
||||
component: () => import('@/views/gift/records/index'),
|
||||
meta: {
|
||||
title: '礼物打赏',
|
||||
icon: 'el-icon-present'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 步骤3:验证菜单是否添加成功
|
||||
|
||||
1. 重新登录后台管理系统
|
||||
2. 在左侧菜单栏应该能看到"礼物管理"菜单
|
||||
3. 点击"礼物打赏"子菜单
|
||||
4. 应该能看到礼物打赏记录页面
|
||||
|
||||
## 礼物打赏记录页面功能
|
||||
|
||||
页面会显示以下信息:
|
||||
|
||||
### 统计卡片
|
||||
- **总礼物数**:所有时间的礼物总数量
|
||||
- **总价值**:所有礼物的总价值(虚拟币)
|
||||
- **今日礼物数**:今天收到的礼物数量
|
||||
- **今日价值**:今天礼物的总价值
|
||||
|
||||
### 搜索功能
|
||||
- 关键词搜索:送礼者昵称、接收者昵称、礼物名称
|
||||
- 日期筛选:按开始日期和结束日期筛选
|
||||
|
||||
### 礼物记录表格
|
||||
显示字段:
|
||||
- ID
|
||||
- 礼物信息(图标、名称、单价×数量)
|
||||
- 总价值
|
||||
- 送礼者(头像、昵称、手机号)
|
||||
- 接收者/主播(头像、昵称、手机号)
|
||||
- 直播间名称
|
||||
- 赠送时间
|
||||
|
||||
### 统计功能
|
||||
- 可以统计哪个用户送了多少礼物
|
||||
- 可以统计哪个主播收到了多少礼物
|
||||
- 可以按日期范围查看礼物记录
|
||||
|
||||
## 如果菜单还是没有显示
|
||||
|
||||
### 方法1:检查菜单表
|
||||
```sql
|
||||
-- 查看菜单表名
|
||||
SHOW TABLES LIKE '%menu%';
|
||||
|
||||
-- 查看菜单表结构
|
||||
DESC eb_system_menu;
|
||||
|
||||
-- 查看现有菜单
|
||||
SELECT * FROM eb_system_menu ORDER BY sort;
|
||||
```
|
||||
|
||||
### 方法2:检查权限
|
||||
确保当前登录的管理员账号有权限访问新添加的菜单。
|
||||
|
||||
### 方法3:清除缓存
|
||||
1. 清除浏览器缓存
|
||||
2. 重新登录后台管理系统
|
||||
3. 按 Ctrl+F5 强制刷新页面
|
||||
|
||||
### 方法4:直接访问URL
|
||||
即使菜单没有显示,也可以直接在浏览器地址栏输入:
|
||||
```
|
||||
http://localhost:8080/#/gift/records
|
||||
```
|
||||
|
||||
## 礼物配置说明
|
||||
|
||||
礼物数据已经在数据库中初始化了,包括:
|
||||
- 玫瑰(1虚拟币)
|
||||
- 巧克力(5虚拟币)
|
||||
- 棒棒糖(10虚拟币)
|
||||
- 冰淇淋(20虚拟币)
|
||||
- 蛋糕(50虚拟币)
|
||||
- 香水(100虚拟币)
|
||||
- 口红(200虚拟币)
|
||||
- 钻戒(520虚拟币)
|
||||
- 跑车(1314虚拟币)
|
||||
- 城堡(5200虚拟币)
|
||||
|
||||
可以通过以下SQL查看:
|
||||
```sql
|
||||
SELECT * FROM eb_gift_config ORDER BY sort_order;
|
||||
```
|
||||
|
||||
## 测试流程
|
||||
|
||||
### 1. 准备测试数据
|
||||
```sql
|
||||
-- 查看礼物配置
|
||||
SELECT * FROM eb_gift_config;
|
||||
|
||||
-- 查看充值套餐
|
||||
SELECT * FROM eb_recharge_package;
|
||||
|
||||
-- 查看用户余额
|
||||
SELECT uid, nickname, virtual_balance FROM eb_user WHERE uid IN (41, 42, 43);
|
||||
```
|
||||
|
||||
### 2. 通过APP端送礼物
|
||||
1. 用户A登录APP
|
||||
2. 充值虚拟货币
|
||||
3. 进入主播B的直播间
|
||||
4. 点击礼物按钮
|
||||
5. 选择礼物并发送
|
||||
|
||||
### 3. 在后台查看记录
|
||||
1. 登录后台管理系统
|
||||
2. 进入"礼物管理" -> "礼物打赏"
|
||||
3. 查看刚才的送礼记录
|
||||
4. 可以搜索用户A或主播B
|
||||
5. 查看统计数据是否正确
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 菜单添加后看不到?
|
||||
**A:**
|
||||
1. 检查数据库中菜单是否添加成功
|
||||
2. 检查`is_show`字段是否为1
|
||||
3. 清除浏览器缓存并重新登录
|
||||
4. 检查当前用户是否有权限
|
||||
|
||||
### Q2: 点击菜单报404错误?
|
||||
**A:**
|
||||
1. 检查前端页面文件是否存在:`Zhibo/admin/src/views/gift/records/index.vue`
|
||||
2. 检查路由配置是否正确
|
||||
3. 重新编译前端:`npm run build:prod`
|
||||
|
||||
### Q3: 页面显示"暂无数据"?
|
||||
**A:**
|
||||
1. 检查后端服务是否启动
|
||||
2. 检查API接口是否正常:`/api/admin/gift/records`
|
||||
3. 查看浏览器控制台是否有错误
|
||||
4. 检查数据库中是否有礼物记录
|
||||
|
||||
### Q4: 统计数据不准确?
|
||||
**A:**
|
||||
1. 检查数据库中的数据是否正确
|
||||
2. 检查后端SQL查询是否正确
|
||||
3. 清除缓存重新加载
|
||||
|
||||
## 相关文件
|
||||
|
||||
- 后端Controller:`GiftAdminController.java`
|
||||
- 前端API:`Zhibo/admin/src/api/gift.js`
|
||||
- 前端页面:`Zhibo/admin/src/views/gift/records/index.vue`
|
||||
- 数据库脚本:`virtual_currency_and_gift_system.sql`
|
||||
|
||||
## 下一步扩展
|
||||
|
||||
可以继续添加以下功能:
|
||||
1. 礼物配置管理页面(添加、编辑、删除礼物)
|
||||
2. 充值套餐管理页面(配置充值金额和赠送比例)
|
||||
3. 充值记录查看页面
|
||||
4. 礼物统计图表(趋势图、排行榜)
|
||||
5. 数据导出功能(导出Excel)
|
||||
299
礼物系统后台管理部署说明.md
Normal file
299
礼物系统后台管理部署说明.md
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
# 礼物系统后台管理部署说明
|
||||
|
||||
## 已完成的工作
|
||||
|
||||
### 1. 后端API ✅
|
||||
- **GiftAdminController.java** - 礼物管理后台控制器
|
||||
- 礼物打赏记录列表(支持搜索和日期筛选)
|
||||
- 礼物统计数据(总数、总价值、今日数据)
|
||||
- 礼物配置管理(增删改查)
|
||||
- 充值套餐管理
|
||||
- 充值记录查询
|
||||
|
||||
### 2. 前端页面 ✅
|
||||
- **gift.js** - 礼物管理API接口
|
||||
- **gift/records/index.vue** - 礼物打赏记录页面
|
||||
- 统计卡片(总礼物数、总价值、今日数据)
|
||||
- 搜索功能(关键词、日期范围)
|
||||
- 礼物记录表格(礼物信息、送礼者、接收者、直播间、时间)
|
||||
- 分页功能
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 步骤1:执行数据库脚本(如果还没执行)
|
||||
```bash
|
||||
mysql -h 1.15.149.240 -u root -p zhibo < virtual_currency_and_gift_system.sql
|
||||
```
|
||||
|
||||
### 步骤2:编译后端
|
||||
```bash
|
||||
cd Zhibo/zhibo-h
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
### 步骤3:部署后端服务
|
||||
```bash
|
||||
# 停止服务
|
||||
ssh root@1.15.149.240 "cd /root/zhibo && docker-compose stop crmeb-admin"
|
||||
|
||||
# 上传jar包
|
||||
scp crmeb-admin/target/Crmeb-admin.jar root@1.15.149.240:/root/zhibo/
|
||||
|
||||
# 启动服务
|
||||
ssh root@1.15.149.240 "cd /root/zhibo && docker-compose up -d crmeb-admin"
|
||||
```
|
||||
|
||||
### 步骤4:编译前端
|
||||
```bash
|
||||
cd Zhibo/admin
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
### 步骤5:部署前端
|
||||
```bash
|
||||
# 上传到服务器
|
||||
scp -r dist/* root@1.15.149.240:/root/zhibo/admin/
|
||||
```
|
||||
|
||||
### 步骤6:配置路由
|
||||
|
||||
在 `Zhibo/admin/src/router/index.js` 中添加礼物管理路由:
|
||||
|
||||
```javascript
|
||||
{
|
||||
path: '/gift',
|
||||
component: Layout,
|
||||
redirect: '/gift/records',
|
||||
name: 'Gift',
|
||||
meta: { title: '礼物管理', icon: 'el-icon-present' },
|
||||
children: [
|
||||
{
|
||||
path: 'records',
|
||||
name: 'GiftRecords',
|
||||
component: () => import('@/views/gift/records/index'),
|
||||
meta: { title: '礼物打赏', icon: 'el-icon-present' }
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 页面功能说明
|
||||
|
||||
### 礼物打赏记录页面
|
||||
|
||||
#### 统计卡片
|
||||
- **总礼物数**:所有时间的礼物总数量
|
||||
- **总价值**:所有礼物的总价值(虚拟币)
|
||||
- **今日礼物数**:今天收到的礼物数量
|
||||
- **今日价值**:今天礼物的总价值
|
||||
|
||||
#### 搜索功能
|
||||
- **关键词搜索**:可搜索送礼者昵称、接收者昵称、礼物名称
|
||||
- **日期筛选**:可按开始日期和结束日期筛选记录
|
||||
|
||||
#### 礼物记录表格
|
||||
显示字段:
|
||||
- ID
|
||||
- 礼物信息(图标、名称、单价、数量)
|
||||
- 总价值
|
||||
- 送礼者(头像、昵称、手机号)
|
||||
- 接收者/主播(头像、昵称、手机号)
|
||||
- 直播间名称
|
||||
- 赠送时间
|
||||
|
||||
#### 特殊处理
|
||||
- 匿名送礼显示为"匿名用户"
|
||||
- 没有直播间的显示"-"
|
||||
- 支持分页查看
|
||||
|
||||
## API接口说明
|
||||
|
||||
### 1. 获取礼物打赏记录
|
||||
```
|
||||
GET /api/admin/gift/records
|
||||
参数:
|
||||
- keyword: 关键词(可选)
|
||||
- startDate: 开始日期(可选)
|
||||
- endDate: 结束日期(可选)
|
||||
- page: 页码(默认1)
|
||||
- limit: 每页数量(默认20)
|
||||
```
|
||||
|
||||
### 2. 获取礼物统计
|
||||
```
|
||||
GET /api/admin/gift/statistics
|
||||
返回:
|
||||
- totalCount: 总礼物数
|
||||
- totalValue: 总价值
|
||||
- todayCount: 今日礼物数
|
||||
- todayValue: 今日价值
|
||||
```
|
||||
|
||||
### 3. 获取礼物配置列表
|
||||
```
|
||||
GET /api/admin/gift/config/list
|
||||
```
|
||||
|
||||
### 4. 添加礼物配置
|
||||
```
|
||||
POST /api/admin/gift/config/add
|
||||
请求体:
|
||||
{
|
||||
"name": "礼物名称",
|
||||
"icon": "图标URL",
|
||||
"price": 价格,
|
||||
"animation": "动画效果",
|
||||
"sortOrder": 排序
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 更新礼物配置
|
||||
```
|
||||
POST /api/admin/gift/config/update
|
||||
```
|
||||
|
||||
### 6. 删除礼物配置
|
||||
```
|
||||
POST /api/admin/gift/config/delete/{id}
|
||||
```
|
||||
|
||||
### 7. 获取充值套餐列表
|
||||
```
|
||||
GET /api/admin/gift/recharge/packages
|
||||
```
|
||||
|
||||
### 8. 更新充值套餐
|
||||
```
|
||||
POST /api/admin/gift/recharge/package/update
|
||||
```
|
||||
|
||||
### 9. 获取充值记录
|
||||
```
|
||||
GET /api/admin/gift/recharge/records
|
||||
```
|
||||
|
||||
## 测试流程
|
||||
|
||||
### 1. 测试礼物打赏记录查看
|
||||
1. 登录后台管理系统
|
||||
2. 进入"礼物管理" -> "礼物打赏"
|
||||
3. 查看统计卡片数据是否正确
|
||||
4. 查看礼物记录列表是否显示
|
||||
5. 测试搜索功能
|
||||
6. 测试日期筛选功能
|
||||
7. 测试分页功能
|
||||
|
||||
### 2. 测试数据准备
|
||||
如果没有测试数据,可以通过APP端送礼物来生成:
|
||||
1. 在APP中充值虚拟货币
|
||||
2. 进入直播间
|
||||
3. 送礼物给主播
|
||||
4. 返回后台查看记录
|
||||
|
||||
### 3. 验证数据准确性
|
||||
```sql
|
||||
-- 查询礼物记录
|
||||
SELECT * FROM eb_gift_record ORDER BY create_time DESC LIMIT 10;
|
||||
|
||||
-- 查询统计数据
|
||||
SELECT
|
||||
COUNT(*) as total_count,
|
||||
SUM(total_price) as total_value,
|
||||
SUM(CASE WHEN DATE(create_time) = CURDATE() THEN 1 ELSE 0 END) as today_count,
|
||||
SUM(CASE WHEN DATE(create_time) = CURDATE() THEN total_price ELSE 0 END) as today_value
|
||||
FROM eb_gift_record;
|
||||
```
|
||||
|
||||
## 后续扩展功能
|
||||
|
||||
### 1. 礼物配置管理页面
|
||||
创建独立页面管理礼物配置:
|
||||
- 添加新礼物
|
||||
- 编辑礼物信息
|
||||
- 上传礼物图标
|
||||
- 设置礼物价格
|
||||
- 启用/禁用礼物
|
||||
|
||||
### 2. 充值套餐管理页面
|
||||
创建独立页面管理充值套餐:
|
||||
- 添加新套餐
|
||||
- 编辑套餐信息
|
||||
- 设置赠送比例
|
||||
- 设置热门推荐
|
||||
- 启用/禁用套餐
|
||||
|
||||
### 3. 充值记录查看页面
|
||||
创建独立页面查看充值记录:
|
||||
- 用户充值记录
|
||||
- 充值金额统计
|
||||
- 支付方式统计
|
||||
- 充值趋势图表
|
||||
|
||||
### 4. 数据导出功能
|
||||
- 导出礼物记录为Excel
|
||||
- 导出充值记录为Excel
|
||||
- 生成统计报表
|
||||
|
||||
### 5. 图表统计
|
||||
- 礼物趋势图(按日期)
|
||||
- 热门礼物排行榜
|
||||
- 送礼用户排行榜
|
||||
- 收礼主播排行榜
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **权限控制**
|
||||
- 确保只有管理员可以访问礼物管理页面
|
||||
- 敏感操作需要二次确认
|
||||
|
||||
2. **数据安全**
|
||||
- 礼物记录不可删除,只能查看
|
||||
- 充值记录不可修改
|
||||
- 所有操作记录日志
|
||||
|
||||
3. **性能优化**
|
||||
- 大量数据时使用分页
|
||||
- 统计数据可以缓存
|
||||
- 定期归档历史数据
|
||||
|
||||
4. **用户体验**
|
||||
- 加载状态提示
|
||||
- 错误信息友好提示
|
||||
- 操作成功反馈
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q1: 后台看不到礼物记录?
|
||||
**A:** 检查以下几点:
|
||||
1. 数据库表是否创建成功
|
||||
2. 后端服务是否重启
|
||||
3. 前端是否重新编译
|
||||
4. 是否有测试数据
|
||||
|
||||
### Q2: 统计数据不准确?
|
||||
**A:**
|
||||
1. 检查SQL查询是否正确
|
||||
2. 检查数据库数据是否完整
|
||||
3. 清除浏览器缓存重新加载
|
||||
|
||||
### Q3: 搜索功能不工作?
|
||||
**A:**
|
||||
1. 检查后端API是否正确处理参数
|
||||
2. 检查前端是否正确传递参数
|
||||
3. 查看浏览器控制台错误信息
|
||||
|
||||
## 文件清单
|
||||
|
||||
### 后端文件
|
||||
- `Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/GiftAdminController.java`
|
||||
|
||||
### 前端文件
|
||||
- `Zhibo/admin/src/api/gift.js`
|
||||
- `Zhibo/admin/src/views/gift/records/index.vue`
|
||||
|
||||
### 数据库文件
|
||||
- `virtual_currency_and_gift_system.sql`
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题,请查看相关文档或联系开发团队。
|
||||
301
礼物系统完整开发文档.md
Normal file
301
礼物系统完整开发文档.md
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
# 礼物系统完整开发文档
|
||||
|
||||
## 📋 目录
|
||||
|
||||
1. [系统概述](#系统概述)
|
||||
2. [数据库设计](#数据库设计)
|
||||
3. [后端API接口](#后端api接口)
|
||||
4. [前端页面](#前端页面)
|
||||
5. [APP端集成](#app端集成)
|
||||
6. [部署指南](#部署指南)
|
||||
7. [测试验证](#测试验证)
|
||||
|
||||
---
|
||||
|
||||
## 系统概述
|
||||
|
||||
### 功能简介
|
||||
|
||||
礼物系统是直播平台的核心功能之一,支持用户在直播间送礼物给主播,包含以下核心功能:
|
||||
|
||||
- **礼物管理**:后台管理员可以添加、编辑、删除、启用/禁用礼物
|
||||
- **打赏记录**:记录所有用户的礼物打赏行为
|
||||
- **统计分析**:礼物数量、启用/禁用状态、总价值统计
|
||||
- **APP集成**:移动端获取礼物列表并发送礼物
|
||||
|
||||
### 技术栈
|
||||
|
||||
- **后端**:Java + Spring Boot + MyBatis + MySQL
|
||||
- **前端管理**:Vue.js + Element UI
|
||||
- **移动端**:Android (Java)
|
||||
- **数据库**:MySQL 5.7+
|
||||
|
||||
### 核心数据表
|
||||
|
||||
- `eb_gift` - 礼物主数据表(20个礼物)
|
||||
- `eb_gift_record` - 礼物打赏记录表
|
||||
|
||||
---
|
||||
|
||||
## 数据库设计
|
||||
|
||||
### 1. eb_gift 表(礼物主数据表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE `eb_gift` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '礼物ID',
|
||||
`name` varchar(50) NOT NULL COMMENT '礼物名称',
|
||||
`image` varchar(255) DEFAULT NULL COMMENT '礼物图片URL',
|
||||
`diamond_price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '钻石价格',
|
||||
`intimacy` int(11) NOT NULL DEFAULT '0' COMMENT '亲密度',
|
||||
`is_heartbeat` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否心动礼物 0-否 1-是',
|
||||
`level` int(11) NOT NULL DEFAULT '1' COMMENT '礼物等级',
|
||||
`sort` int(11) NOT NULL DEFAULT '0' COMMENT '排序',
|
||||
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态 0-禁用 1-启用',
|
||||
`is_deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否删除 0-否 1-是',
|
||||
`buy_type` varchar(20) DEFAULT 'diamond' COMMENT '购买类型',
|
||||
`belong` varchar(20) DEFAULT 'common' COMMENT '归属',
|
||||
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_sort` (`sort`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='礼物表';
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | int | 礼物唯一标识 |
|
||||
| name | varchar(50) | 礼物名称,如"玫瑰花"、"钻戒" |
|
||||
| image | varchar(255) | 礼物图片URL |
|
||||
| diamond_price | decimal(10,2) | 钻石价格 |
|
||||
| intimacy | int | 赠送礼物增加的亲密度 |
|
||||
| is_heartbeat | tinyint | 是否为心动礼物(特殊标记) |
|
||||
| level | int | 礼物等级 |
|
||||
| sort | int | 显示排序 |
|
||||
| status | tinyint | 启用状态(0-禁用,1-启用) |
|
||||
| is_deleted | tinyint | 软删除标记 |
|
||||
| buy_type | varchar(20) | 购买类型(diamond-钻石) |
|
||||
| belong | varchar(20) | 归属(common-通用,live-直播专属) |
|
||||
| remark | varchar(255) | 备注信息 |
|
||||
|
||||
### 2. eb_gift_record 表(打赏记录表)
|
||||
|
||||
```sql
|
||||
CREATE TABLE `eb_gift_record` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '记录ID',
|
||||
`sender_id` int(11) NOT NULL COMMENT '送礼用户ID',
|
||||
`sender_nickname` varchar(50) DEFAULT NULL COMMENT '送礼用户昵称',
|
||||
`receiver_id` int(11) NOT NULL COMMENT '收礼用户ID',
|
||||
`receiver_nickname` varchar(50) DEFAULT NULL COMMENT '收礼用户昵称',
|
||||
`gift_id` int(11) NOT NULL COMMENT '礼物ID',
|
||||
`gift_count` int(11) NOT NULL DEFAULT '1' COMMENT '礼物数量',
|
||||
`total_price` decimal(10,2) NOT NULL COMMENT '总价格',
|
||||
`room_id` int(11) DEFAULT NULL COMMENT '直播间ID',
|
||||
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_sender` (`sender_id`),
|
||||
KEY `idx_receiver` (`receiver_id`),
|
||||
KEY `idx_gift` (`gift_id`),
|
||||
KEY `idx_room` (`room_id`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='礼物打赏记录表';
|
||||
```
|
||||
|
||||
**字段说明:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | int | 记录唯一标识 |
|
||||
| sender_id | int | 送礼用户ID |
|
||||
| sender_nickname | varchar(50) | 送礼用户昵称 |
|
||||
| receiver_id | int | 收礼用户ID(主播) |
|
||||
| receiver_nickname | varchar(50) | 收礼用户昵称 |
|
||||
| gift_id | int | 礼物ID(关联eb_gift表) |
|
||||
| gift_count | int | 礼物数量 |
|
||||
| total_price | decimal(10,2) | 总价格(单价×数量) |
|
||||
| room_id | int | 直播间ID |
|
||||
| create_time | timestamp | 打赏时间 |
|
||||
|
||||
### 3. 初始化数据
|
||||
|
||||
系统预置了20个礼物:
|
||||
|
||||
1. 玫瑰花 - 10钻石
|
||||
2. 爱心 - 20钻石
|
||||
3. 火箭 - 100钻石
|
||||
4. 皇冠 - 500钻石
|
||||
5. 跑车 - 1000钻石
|
||||
6. 城堡 - 5000钻石
|
||||
7. 棒棒糖 - 5钻石
|
||||
8. 啤酒 - 15钻石
|
||||
9. 蛋糕 - 50钻石
|
||||
10. 钻戒 - 2000钻石
|
||||
11-20. 其他礼物...
|
||||
|
||||
---
|
||||
|
||||
## 后端API接口
|
||||
|
||||
### 基础路径
|
||||
|
||||
```
|
||||
http://your-server.com/api/admin/gift
|
||||
```
|
||||
|
||||
### 1. 礼物列表(管理端)
|
||||
|
||||
**接口地址:** `GET /list`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| page | int | 否 | 页码,默认1 |
|
||||
| limit | int | 否 | 每页数量,默认10 |
|
||||
| name | string | 否 | 礼物名称(模糊搜索) |
|
||||
| status | int | 否 | 状态(0-禁用,1-启用) |
|
||||
|
||||
**响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": null,
|
||||
"data": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"totalPage": 2,
|
||||
"total": 20,
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "玫瑰花",
|
||||
"image": "https://example.com/gifts/rose.png",
|
||||
"diamondPrice": "10.00",
|
||||
"intimacy": 10,
|
||||
"status": true,
|
||||
"isHeartbeat": false,
|
||||
"buyType": "diamond",
|
||||
"belong": "common",
|
||||
"remark": "浪漫玫瑰",
|
||||
"level": 1,
|
||||
"sort": 0,
|
||||
"createTime": "2025-12-30 20:25:16",
|
||||
"updateTime": "2025-12-30 20:25:16"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 添加礼物
|
||||
|
||||
**接口地址:** `POST /add`
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "新礼物",
|
||||
"image": "https://example.com/gift.png",
|
||||
"diamondPrice": 100,
|
||||
"intimacy": 100,
|
||||
"isHeartbeat": false,
|
||||
"level": 1,
|
||||
"sort": 0,
|
||||
"status": true,
|
||||
"buyType": "diamond",
|
||||
"belong": "common",
|
||||
"remark": "备注信息"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "添加成功",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 编辑礼物
|
||||
|
||||
**接口地址:** `POST /update`
|
||||
|
||||
**请求体:**
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "更新后的名称",
|
||||
"image": "https://example.com/new-gift.png",
|
||||
"diamondPrice": 150,
|
||||
"intimacy": 150,
|
||||
"isHeartbeat": true,
|
||||
"level": 2,
|
||||
"sort": 1,
|
||||
"status": true,
|
||||
"buyType": "diamond",
|
||||
"belong": "live",
|
||||
"remark": "更新后的备注"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 删除礼物
|
||||
|
||||
**接口地址:** `POST /delete/{id}`
|
||||
|
||||
**路径参数:**
|
||||
- `id`: 礼物ID
|
||||
|
||||
**响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "删除成功",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 修改礼物状态
|
||||
|
||||
**接口地址:** `POST /status/{id}`
|
||||
|
||||
**路径参数:**
|
||||
- `id`: 礼物ID
|
||||
|
||||
**请求参数:**
|
||||
- `status`: 状态(0-禁用,1-启用)
|
||||
|
||||
**响应示例:**
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "状态修改成功",
|
||||
"data": null
|
||||
}
|
||||
```
|
||||
|
||||
### 6. 打赏记录列表
|
||||
|
||||
**接口地址:** `GET /records`
|
||||
|
||||
**请求参数:**
|
||||
|
||||
| 参数 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| page | int | 否 | 页码,默认1 |
|
||||
| limit | int | 否 | 每页数量,默认20 |
|
||||
| senderName | string | 否 | 送礼用户昵称(模糊搜索) |
|
||||
| receiverName | string | 否 | 收礼用户昵称(模糊搜索) |
|
||||
| giftName | string | 否 | 礼物名称(模糊搜索) |
|
||||
|
||||
**响应示例:**
|
||||
145
礼物系统完整部署指南.md
Normal file
145
礼物系统完整部署指南.md
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# 礼物系统完整部署指南
|
||||
|
||||
## 一、系统功能
|
||||
|
||||
### 1. 礼物列表(礼物配置)
|
||||
- 显示所有可用礼物(玫瑰、巧克力、跑车等)
|
||||
- 可以添加、编辑、删除礼物
|
||||
- 设置礼物价格、图标、排序
|
||||
- 启用/禁用礼物
|
||||
|
||||
### 2. 打赏记录
|
||||
- 显示所有用户的打赏记录
|
||||
- 谁送了什么礼物给哪个主播
|
||||
- 在哪个直播间送的
|
||||
- 礼物数量和总价值
|
||||
- 支持按关键词、日期筛选
|
||||
- 显示统计数据(总礼物数、总价值、今日数据)
|
||||
|
||||
### 3. 充值套餐
|
||||
- 显示所有充值套餐配置
|
||||
- 可以编辑套餐金额、赠送比例
|
||||
- 设置热门推荐
|
||||
|
||||
## 二、部署步骤
|
||||
|
||||
### 步骤1:部署后端
|
||||
|
||||
```bash
|
||||
# 运行部署脚本
|
||||
deploy-gift-records-fix.bat
|
||||
```
|
||||
|
||||
或手动执行:
|
||||
```bash
|
||||
cd Zhibo/zhibo-h
|
||||
mvn clean package -DskipTests -Pdev
|
||||
|
||||
# 上传到服务器
|
||||
scp crmeb-admin/target/crmeb-admin.jar root@1.15.149.240:/www/server/java/
|
||||
|
||||
# 重启服务
|
||||
ssh root@1.15.149.240 "cd /www/server/java && ./stop.sh && ./start.sh"
|
||||
```
|
||||
|
||||
### 步骤2:部署前端
|
||||
|
||||
```bash
|
||||
cd Zhibo/admin
|
||||
npm run build:prod
|
||||
|
||||
# 上传到服务器
|
||||
scp -r dist/* root@1.15.149.240:/www/wwwroot/admin/
|
||||
```
|
||||
|
||||
### 步骤3:验证数据
|
||||
|
||||
运行SQL检查数据:
|
||||
```sql
|
||||
-- 检查礼物配置
|
||||
SELECT * FROM eb_gift_config ORDER BY sort_order;
|
||||
|
||||
-- 检查礼物记录
|
||||
SELECT COUNT(*) FROM eb_gift_record;
|
||||
|
||||
-- 检查充值套餐
|
||||
SELECT * FROM eb_recharge_package ORDER BY sort_order;
|
||||
```
|
||||
|
||||
## 三、菜单结构
|
||||
|
||||
```
|
||||
礼物打赏
|
||||
├── 礼物列表 - 管理礼物配置(玫瑰、巧克力等)
|
||||
├── 打赏记录 - 查看所有打赏记录和统计
|
||||
└── 充值套餐 - 管理充值套餐配置
|
||||
```
|
||||
|
||||
## 四、API接口
|
||||
|
||||
### 礼物配置
|
||||
- GET `/api/admin/gift/config/list` - 获取礼物列表
|
||||
- POST `/api/admin/gift/config/add` - 添加礼物
|
||||
- POST `/api/admin/gift/config/update` - 更新礼物
|
||||
- POST `/api/admin/gift/config/delete/{id}` - 删除礼物
|
||||
|
||||
### 打赏记录
|
||||
- GET `/api/admin/gift/records` - 获取打赏记录列表
|
||||
- GET `/api/admin/gift/statistics` - 获取统计数据
|
||||
|
||||
### 充值套餐
|
||||
- GET `/api/admin/gift/recharge/packages` - 获取充值套餐
|
||||
- POST `/api/admin/gift/recharge/package/update` - 更新套餐
|
||||
|
||||
## 五、数据库表
|
||||
|
||||
### eb_gift_config - 礼物配置表
|
||||
存储礼物的基本信息(名称、图标、价格等)
|
||||
|
||||
### eb_gift_record - 礼物记录表
|
||||
存储所有打赏记录,包括:
|
||||
- sender_id, sender_name - 送礼者
|
||||
- receiver_id, receiver_name - 接收者(主播)
|
||||
- room_id - 直播间
|
||||
- gift_id, gift_name - 礼物信息
|
||||
- quantity - 数量
|
||||
- total_price - 总价
|
||||
|
||||
### eb_recharge_package - 充值套餐表
|
||||
存储充值套餐配置
|
||||
|
||||
### eb_user.virtual_balance - 用户虚拟货币余额
|
||||
存储在用户表的 virtual_balance 字段
|
||||
|
||||
## 六、测试数据
|
||||
|
||||
数据库中已有测试数据:
|
||||
- 10个礼物配置(玫瑰、巧克力、棒棒糖等)
|
||||
- 12条打赏记录
|
||||
- 6个充值套餐
|
||||
- 测试用户43、44有10000虚拟币余额
|
||||
|
||||
## 七、常见问题
|
||||
|
||||
### 1. 页面显示"暂无数据"
|
||||
- 检查后端是否正常启动
|
||||
- 检查API接口是否返回数据
|
||||
- 查看浏览器控制台是否有错误
|
||||
|
||||
### 2. 数据不显示
|
||||
- 确认数据库中有数据
|
||||
- 检查后端SQL查询是否正确
|
||||
- 查看后端日志
|
||||
|
||||
### 3. 字段不匹配错误
|
||||
- 已修复:quantity 字段
|
||||
- 已修复:sender_nickname, receiver_nickname 使用 COALESCE
|
||||
- 已修复:is_live 替代 status
|
||||
|
||||
## 八、后续优化
|
||||
|
||||
1. 添加礼物图片上传功能
|
||||
2. 添加礼物动画效果预览
|
||||
3. 添加打赏记录导出功能
|
||||
4. 添加收礼/送礼排行榜
|
||||
5. 添加礼物收益统计图表
|
||||
Loading…
Reference in New Issue
Block a user