历史记录与用户拉黑,用户封禁功能完善。
This commit is contained in:
parent
86c37cd688
commit
25274c523b
0
.kiro/specs/wishtree-mobile/design.md
Normal file
0
.kiro/specs/wishtree-mobile/design.md
Normal file
0
.kiro/specs/wishtree-mobile/tasks.md
Normal file
0
.kiro/specs/wishtree-mobile/tasks.md
Normal file
131
Zhibo/admin/src/api/ban.js
Normal file
131
Zhibo/admin/src/api/ban.js
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
import request from '@/utils/request';
|
||||
|
||||
// ==================== 用户封禁 ====================
|
||||
|
||||
/**
|
||||
* 获取用户封禁列表
|
||||
*/
|
||||
export function userBanListApi(params) {
|
||||
return request({
|
||||
url: '/admin/ban/user/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 封禁用户
|
||||
*/
|
||||
export function userBanAddApi(data) {
|
||||
return request({
|
||||
url: '/admin/ban/user/add',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除用户封禁
|
||||
*/
|
||||
export function userBanUnbanApi(id) {
|
||||
return request({
|
||||
url: `/admin/ban/user/unban/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户封禁记录
|
||||
*/
|
||||
export function userBanDeleteApi(id) {
|
||||
return request({
|
||||
url: `/admin/ban/user/delete/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除用户封禁记录
|
||||
*/
|
||||
export function userBanBatchDeleteApi(ids) {
|
||||
return request({
|
||||
url: '/admin/ban/user/batch-delete',
|
||||
method: 'post',
|
||||
data: ids
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户封禁状态
|
||||
*/
|
||||
export function checkUserBanApi(userId) {
|
||||
return request({
|
||||
url: `/admin/ban/user/check/${userId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 房间封禁 ====================
|
||||
|
||||
/**
|
||||
* 获取房间封禁列表
|
||||
*/
|
||||
export function roomBanListApi(params) {
|
||||
return request({
|
||||
url: '/admin/ban/room/list',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 封禁房间
|
||||
*/
|
||||
export function roomBanAddApi(data) {
|
||||
return request({
|
||||
url: '/admin/ban/room/add',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 解除房间封禁
|
||||
*/
|
||||
export function roomBanUnbanApi(id) {
|
||||
return request({
|
||||
url: `/admin/ban/room/unban/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除房间封禁记录
|
||||
*/
|
||||
export function roomBanDeleteApi(id) {
|
||||
return request({
|
||||
url: `/admin/ban/room/delete/${id}`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除房间封禁记录
|
||||
*/
|
||||
export function roomBanBatchDeleteApi(ids) {
|
||||
return request({
|
||||
url: '/admin/ban/room/batch-delete',
|
||||
method: 'post',
|
||||
data: ids
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查房间封禁状态
|
||||
*/
|
||||
export function checkRoomBanApi(roomId) {
|
||||
return request({
|
||||
url: `/admin/ban/room/check/${roomId}`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
315
Zhibo/admin/src/views/ban/roomBan.vue
Normal file
315
Zhibo/admin/src/views/ban/roomBan.vue
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
<template>
|
||||
<div class="divBox">
|
||||
<el-card shadow="never" class="ivu-mt">
|
||||
<div class="padding-add">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="mb20">
|
||||
<el-form :inline="true" :model="searchForm" size="small">
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.roomName" placeholder="房间名称" clearable style="width: 150px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.streamerName" placeholder="主播名称" clearable style="width: 150px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.banType" placeholder="封禁类型" clearable style="width: 120px;">
|
||||
<el-option label="永久封禁" value="permanent"></el-option>
|
||||
<el-option label="临时封禁" value="temporary"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.status" placeholder="状态" clearable style="width: 100px;">
|
||||
<el-option label="生效中" :value="1"></el-option>
|
||||
<el-option label="已解除" :value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb20">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">封禁房间</el-button>
|
||||
<el-button type="danger" size="small" :disabled="!selectedIds.length" @click="handleBatchDelete">批量删除</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table :data="tableData" v-loading="loading" border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column label="房间信息" min-width="200" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div class="room-info">
|
||||
<el-image
|
||||
v-if="scope.row.cover_image"
|
||||
:src="scope.row.cover_image"
|
||||
style="width: 60px; height: 40px; border-radius: 4px;"
|
||||
fit="cover">
|
||||
</el-image>
|
||||
<div class="room-detail">
|
||||
<div class="room-name">{{ scope.row.room_name || '未知房间' }}</div>
|
||||
<div class="streamer-name">主播:{{ scope.row.streamer_name || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="封禁类型" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.ban_type === 'permanent' ? 'danger' : 'warning'" size="small">
|
||||
{{ scope.row.ban_type === 'permanent' ? '永久封禁' : '临时封禁' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="reason" label="封禁原因" min-width="200" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="封禁时长" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.ban_type === 'permanent' ? '永久' : (scope.row.duration_days + '天') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expire_time" label="到期时间" width="160" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.expire_time || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'danger' : 'info'" size="small">
|
||||
{{ scope.row.status === 1 ? '生效中' : '已解除' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="封禁时间" width="160" align="center" />
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="scope.row.status === 1"
|
||||
type="success"
|
||||
size="mini"
|
||||
@click="handleUnban(scope.row)">解除封禁</el-button>
|
||||
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="acea-row row-right page mt20">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="searchForm.page"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="searchForm.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 封禁房间对话框 -->
|
||||
<el-dialog title="封禁房间" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
|
||||
<el-form-item label="房间ID" prop="roomId">
|
||||
<el-input v-model="formData.roomId" placeholder="请输入要封禁的房间ID"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="封禁类型" prop="banType">
|
||||
<el-radio-group v-model="formData.banType">
|
||||
<el-radio label="permanent">永久封禁</el-radio>
|
||||
<el-radio label="temporary">临时封禁</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.banType === 'temporary'" label="封禁天数" prop="duration">
|
||||
<el-input-number v-model="formData.duration" :min="1" :max="365" placeholder="天数"></el-input-number>
|
||||
<span class="ml10">天</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="封禁原因" prop="reason">
|
||||
<el-input type="textarea" v-model="formData.reason" :rows="3" placeholder="请输入封禁原因"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { roomBanListApi, roomBanAddApi, roomBanUnbanApi, roomBanDeleteApi, roomBanBatchDeleteApi } from '@/api/ban';
|
||||
|
||||
export default {
|
||||
name: 'RoomBan',
|
||||
data() {
|
||||
return {
|
||||
searchForm: {
|
||||
roomName: '',
|
||||
streamerName: '',
|
||||
banType: '',
|
||||
status: '',
|
||||
page: 1,
|
||||
limit: 10
|
||||
},
|
||||
tableData: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
selectedIds: [],
|
||||
dialogVisible: false,
|
||||
submitLoading: false,
|
||||
formData: {
|
||||
roomId: '',
|
||||
banType: 'permanent',
|
||||
duration: 7,
|
||||
reason: ''
|
||||
},
|
||||
formRules: {
|
||||
roomId: [{ required: true, message: '请输入房间ID', trigger: 'blur' }],
|
||||
banType: [{ required: true, message: '请选择封禁类型', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '请输入封禁原因', trigger: 'blur' }]
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
async getList() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const params = {
|
||||
page: this.searchForm.page,
|
||||
limit: this.searchForm.limit,
|
||||
roomName: this.searchForm.roomName || undefined,
|
||||
streamerName: this.searchForm.streamerName || undefined,
|
||||
banType: this.searchForm.banType || undefined,
|
||||
status: this.searchForm.status !== '' ? this.searchForm.status : undefined
|
||||
};
|
||||
const res = await roomBanListApi(params);
|
||||
if (res) {
|
||||
this.tableData = res.list || [];
|
||||
this.total = res.total || 0;
|
||||
} else {
|
||||
this.tableData = [];
|
||||
this.total = 0;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取房间封禁列表失败:', error);
|
||||
this.tableData = [];
|
||||
this.total = 0;
|
||||
if (error && error.message) {
|
||||
this.$message.error(error.message);
|
||||
}
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm = { roomName: '', streamerName: '', banType: '', status: '', page: 1, limit: 10 };
|
||||
this.getList();
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.selectedIds = selection.map(item => item.id);
|
||||
},
|
||||
handleAdd() {
|
||||
this.formData = { roomId: '', banType: 'permanent', duration: 7, reason: '' };
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
async handleSubmit() {
|
||||
this.$refs.formRef.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
|
||||
this.submitLoading = true;
|
||||
try {
|
||||
await roomBanAddApi(this.formData);
|
||||
this.$message.success('封禁成功');
|
||||
this.dialogVisible = false;
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '封禁失败');
|
||||
} finally {
|
||||
this.submitLoading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleUnban(row) {
|
||||
this.$confirm('确定要解除该房间的封禁吗?', '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await roomBanUnbanApi(row.id);
|
||||
this.$message.success('解除封禁成功');
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '解除封禁失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm('确定要删除该封禁记录吗?', '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await roomBanDeleteApi(row.id);
|
||||
this.$message.success('删除成功');
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleBatchDelete() {
|
||||
if (!this.selectedIds.length) {
|
||||
this.$message.warning('请先选择要删除的记录');
|
||||
return;
|
||||
}
|
||||
this.$confirm(`确定要删除选中的 ${this.selectedIds.length} 条记录吗?`, '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await roomBanBatchDeleteApi(this.selectedIds);
|
||||
this.$message.success('批量删除成功');
|
||||
this.selectedIds = [];
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '批量删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.searchForm.limit = val;
|
||||
this.getList();
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.searchForm.page = val;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mb20 { margin-bottom: 20px; }
|
||||
.mt20 { margin-top: 20px; }
|
||||
.ml10 { margin-left: 10px; }
|
||||
|
||||
.room-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
|
||||
.room-detail {
|
||||
text-align: left;
|
||||
|
||||
.room-name {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.streamer-name {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
310
Zhibo/admin/src/views/ban/userBan.vue
Normal file
310
Zhibo/admin/src/views/ban/userBan.vue
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
<template>
|
||||
<div class="divBox">
|
||||
<el-card shadow="never" class="ivu-mt">
|
||||
<div class="padding-add">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="mb20">
|
||||
<el-form :inline="true" :model="searchForm" size="small">
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.nickname" placeholder="用户昵称" clearable style="width: 150px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="searchForm.phone" placeholder="手机号" clearable style="width: 150px;"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.banType" placeholder="封禁类型" clearable style="width: 120px;">
|
||||
<el-option label="永久封禁" value="permanent"></el-option>
|
||||
<el-option label="临时封禁" value="temporary"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-select v-model="searchForm.status" placeholder="状态" clearable style="width: 100px;">
|
||||
<el-option label="生效中" :value="1"></el-option>
|
||||
<el-option label="已解除" :value="0"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mb20">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">封禁用户</el-button>
|
||||
<el-button type="danger" size="small" :disabled="!selectedIds.length" @click="handleBatchDelete">批量删除</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<el-table :data="tableData" v-loading="loading" border @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||||
<el-table-column label="用户信息" min-width="180" align="center">
|
||||
<template slot-scope="scope">
|
||||
<div class="user-info">
|
||||
<el-avatar :src="scope.row.avatar" :size="40" icon="el-icon-user"></el-avatar>
|
||||
<div class="user-detail">
|
||||
<div class="nickname">{{ scope.row.nickname || '未知用户' }}</div>
|
||||
<div class="phone">{{ scope.row.phone || '-' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="封禁类型" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.ban_type === 'permanent' ? 'danger' : 'warning'" size="small">
|
||||
{{ scope.row.ban_type === 'permanent' ? '永久封禁' : '临时封禁' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="reason" label="封禁原因" min-width="200" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="封禁时长" width="100" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.ban_type === 'permanent' ? '永久' : (scope.row.duration_days + '天') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expire_time" label="到期时间" width="160" align="center">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.expire_time || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.status === 1 ? 'danger' : 'info'" size="small">
|
||||
{{ scope.row.status === 1 ? '生效中' : '已解除' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="封禁时间" width="160" align="center" />
|
||||
<el-table-column label="操作" width="180" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="scope.row.status === 1"
|
||||
type="success"
|
||||
size="mini"
|
||||
@click="handleUnban(scope.row)">解除封禁</el-button>
|
||||
<el-button type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="acea-row row-right page mt20">
|
||||
<el-pagination
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
:current-page="searchForm.page"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
:page-size="searchForm.limit"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 封禁用户对话框 -->
|
||||
<el-dialog title="封禁用户" :visible.sync="dialogVisible" width="500px">
|
||||
<el-form :model="formData" :rules="formRules" ref="formRef" label-width="100px">
|
||||
<el-form-item label="用户ID" prop="userId">
|
||||
<el-input v-model="formData.userId" placeholder="请输入要封禁的用户ID"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="封禁类型" prop="banType">
|
||||
<el-radio-group v-model="formData.banType">
|
||||
<el-radio label="permanent">永久封禁</el-radio>
|
||||
<el-radio label="temporary">临时封禁</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.banType === 'temporary'" label="封禁天数" prop="duration">
|
||||
<el-input-number v-model="formData.duration" :min="1" :max="365" placeholder="天数"></el-input-number>
|
||||
<span class="ml10">天</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="封禁原因" prop="reason">
|
||||
<el-input type="textarea" v-model="formData.reason" :rows="3" placeholder="请输入封禁原因"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { userBanListApi, userBanAddApi, userBanUnbanApi, userBanDeleteApi, userBanBatchDeleteApi } from '@/api/ban';
|
||||
|
||||
export default {
|
||||
name: 'UserBan',
|
||||
data() {
|
||||
return {
|
||||
searchForm: {
|
||||
nickname: '',
|
||||
phone: '',
|
||||
banType: '',
|
||||
status: '',
|
||||
page: 1,
|
||||
limit: 10
|
||||
},
|
||||
tableData: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
selectedIds: [],
|
||||
dialogVisible: false,
|
||||
submitLoading: false,
|
||||
formData: {
|
||||
userId: '',
|
||||
banType: 'permanent',
|
||||
duration: 7,
|
||||
reason: ''
|
||||
},
|
||||
formRules: {
|
||||
userId: [{ required: true, message: '请输入用户ID', trigger: 'blur' }],
|
||||
banType: [{ required: true, message: '请选择封禁类型', trigger: 'change' }],
|
||||
reason: [{ required: true, message: '请输入封禁原因', trigger: 'blur' }]
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
async getList() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const params = {
|
||||
page: this.searchForm.page,
|
||||
limit: this.searchForm.limit,
|
||||
nickname: this.searchForm.nickname || undefined,
|
||||
phone: this.searchForm.phone || undefined,
|
||||
banType: this.searchForm.banType || undefined,
|
||||
status: this.searchForm.status !== '' ? this.searchForm.status : undefined
|
||||
};
|
||||
const res = await userBanListApi(params);
|
||||
if (res) {
|
||||
this.tableData = res.list || [];
|
||||
this.total = res.total || 0;
|
||||
} else {
|
||||
this.tableData = [];
|
||||
this.total = 0;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取用户封禁列表失败:', error);
|
||||
this.tableData = [];
|
||||
this.total = 0;
|
||||
if (error && error.message) {
|
||||
this.$message.error(error.message);
|
||||
}
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.page = 1;
|
||||
this.getList();
|
||||
},
|
||||
handleReset() {
|
||||
this.searchForm = { nickname: '', phone: '', banType: '', status: '', page: 1, limit: 10 };
|
||||
this.getList();
|
||||
},
|
||||
handleSelectionChange(selection) {
|
||||
this.selectedIds = selection.map(item => item.id);
|
||||
},
|
||||
handleAdd() {
|
||||
this.formData = { userId: '', banType: 'permanent', duration: 7, reason: '' };
|
||||
this.dialogVisible = true;
|
||||
},
|
||||
async handleSubmit() {
|
||||
this.$refs.formRef.validate(async (valid) => {
|
||||
if (!valid) return;
|
||||
|
||||
this.submitLoading = true;
|
||||
try {
|
||||
await userBanAddApi(this.formData);
|
||||
this.$message.success('封禁成功');
|
||||
this.dialogVisible = false;
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '封禁失败');
|
||||
} finally {
|
||||
this.submitLoading = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleUnban(row) {
|
||||
this.$confirm('确定要解除该用户的封禁吗?', '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await userBanUnbanApi(row.id);
|
||||
this.$message.success('解除封禁成功');
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '解除封禁失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleDelete(row) {
|
||||
this.$confirm('确定要删除该封禁记录吗?', '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await userBanDeleteApi(row.id);
|
||||
this.$message.success('删除成功');
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleBatchDelete() {
|
||||
if (!this.selectedIds.length) {
|
||||
this.$message.warning('请先选择要删除的记录');
|
||||
return;
|
||||
}
|
||||
this.$confirm(`确定要删除选中的 ${this.selectedIds.length} 条记录吗?`, '提示', { type: 'warning' }).then(async () => {
|
||||
try {
|
||||
await userBanBatchDeleteApi(this.selectedIds);
|
||||
this.$message.success('批量删除成功');
|
||||
this.selectedIds = [];
|
||||
this.getList();
|
||||
} catch (error) {
|
||||
this.$message.error(error.message || '批量删除失败');
|
||||
}
|
||||
}).catch(() => {});
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.searchForm.limit = val;
|
||||
this.getList();
|
||||
},
|
||||
handleCurrentChange(val) {
|
||||
this.searchForm.page = val;
|
||||
this.getList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mb20 { margin-bottom: 20px; }
|
||||
.mt20 { margin-top: 20px; }
|
||||
.ml10 { margin-left: 10px; }
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
|
||||
.user-detail {
|
||||
text-align: left;
|
||||
|
||||
.nickname {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.phone {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
package com.zbkj.admin.controller;
|
||||
|
||||
import com.zbkj.common.page.CommonPage;
|
||||
import com.zbkj.common.result.CommonResult;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 封禁管理控制器(管理后台)
|
||||
* 提供用户封禁、房间封禁功能
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("api/admin/ban")
|
||||
@Api(tags = "封禁管理")
|
||||
@Validated
|
||||
public class BanController {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
// ==================== 用户封禁 ====================
|
||||
|
||||
@ApiOperation(value = "获取用户封禁列表")
|
||||
@GetMapping("/user/list")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getUserBanList(
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "limit", defaultValue = "10") Integer limit,
|
||||
@RequestParam(value = "nickname", required = false) String nickname,
|
||||
@RequestParam(value = "phone", required = false) String phone,
|
||||
@RequestParam(value = "banType", required = false) String banType,
|
||||
@RequestParam(value = "status", required = false) Integer status) {
|
||||
|
||||
StringBuilder sql = new StringBuilder(
|
||||
"SELECT ub.*, u.nickname, u.avatar, u.phone " +
|
||||
"FROM eb_user_ban ub " +
|
||||
"LEFT JOIN eb_user u ON ub.user_id = u.uid " +
|
||||
"WHERE 1=1");
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
if (nickname != null && !nickname.trim().isEmpty()) {
|
||||
sql.append(" AND u.nickname LIKE ?");
|
||||
params.add("%" + nickname.trim() + "%");
|
||||
}
|
||||
if (phone != null && !phone.trim().isEmpty()) {
|
||||
sql.append(" AND u.phone LIKE ?");
|
||||
params.add("%" + phone.trim() + "%");
|
||||
}
|
||||
if (banType != null && !banType.trim().isEmpty()) {
|
||||
sql.append(" AND ub.ban_type = ?");
|
||||
params.add(banType);
|
||||
}
|
||||
if (status != null) {
|
||||
sql.append(" AND ub.status = ?");
|
||||
params.add(status);
|
||||
}
|
||||
|
||||
// 计算总数
|
||||
String countSql = sql.toString().replace("SELECT ub.*, u.nickname, u.avatar, u.phone", "SELECT COUNT(*)");
|
||||
Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, params.toArray());
|
||||
|
||||
// 分页查询
|
||||
sql.append(" ORDER BY ub.create_time DESC LIMIT ?, ?");
|
||||
params.add((page - 1) * limit);
|
||||
params.add(limit);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
|
||||
|
||||
return CommonResult.success(buildPage(list, total, page, limit));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "封禁用户")
|
||||
@PostMapping("/user/add")
|
||||
public CommonResult<String> banUser(@RequestBody Map<String, Object> body) {
|
||||
Integer userId = body.get("userId") != null ? Integer.valueOf(body.get("userId").toString()) : null;
|
||||
String banType = body.get("banType") != null ? body.get("banType").toString() : "permanent";
|
||||
String reason = body.get("reason") != null ? body.get("reason").toString() : "";
|
||||
Integer duration = body.get("duration") != null ? Integer.valueOf(body.get("duration").toString()) : null;
|
||||
Integer operatorId = body.get("operatorId") != null ? Integer.valueOf(body.get("operatorId").toString()) : 0;
|
||||
|
||||
if (userId == null) {
|
||||
return CommonResult.failed("用户ID不能为空");
|
||||
}
|
||||
|
||||
// 检查用户是否存在
|
||||
String checkSql = "SELECT uid, nickname FROM eb_user WHERE uid = ?";
|
||||
List<Map<String, Object>> users = jdbcTemplate.queryForList(checkSql, userId);
|
||||
if (users.isEmpty()) {
|
||||
return CommonResult.failed("用户不存在");
|
||||
}
|
||||
|
||||
// 检查是否已被封禁
|
||||
String existSql = "SELECT id FROM eb_user_ban WHERE user_id = ? AND status = 1";
|
||||
List<Map<String, Object>> existing = jdbcTemplate.queryForList(existSql, userId);
|
||||
if (!existing.isEmpty()) {
|
||||
return CommonResult.failed("该用户已被封禁");
|
||||
}
|
||||
|
||||
// 计算封禁结束时间
|
||||
String expireTime = null;
|
||||
if ("temporary".equals(banType) && duration != null && duration > 0) {
|
||||
expireTime = String.format("DATE_ADD(NOW(), INTERVAL %d DAY)", duration);
|
||||
}
|
||||
|
||||
// 插入封禁记录
|
||||
String insertSql;
|
||||
if (expireTime != null) {
|
||||
insertSql = "INSERT INTO eb_user_ban (user_id, ban_type, reason, duration_days, expire_time, operator_id, status, create_time, update_time) " +
|
||||
"VALUES (?, ?, ?, ?, " + expireTime + ", ?, 1, NOW(), NOW())";
|
||||
jdbcTemplate.update(insertSql, userId, banType, reason, duration, operatorId);
|
||||
} else {
|
||||
insertSql = "INSERT INTO eb_user_ban (user_id, ban_type, reason, duration_days, operator_id, status, create_time, update_time) " +
|
||||
"VALUES (?, ?, ?, ?, ?, 1, NOW(), NOW())";
|
||||
jdbcTemplate.update(insertSql, userId, banType, reason, duration, operatorId);
|
||||
}
|
||||
|
||||
// 更新用户状态
|
||||
jdbcTemplate.update("UPDATE eb_user SET status = 0 WHERE uid = ?", userId);
|
||||
|
||||
log.info("【用户封禁】userId={}, banType={}, reason={}, operatorId={}", userId, banType, reason, operatorId);
|
||||
return CommonResult.success("封禁成功");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "解除用户封禁")
|
||||
@PostMapping("/user/unban/{id}")
|
||||
public CommonResult<String> unbanUser(@PathVariable Long id) {
|
||||
// 获取封禁记录
|
||||
String querySql = "SELECT user_id FROM eb_user_ban WHERE id = ?";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(querySql, id);
|
||||
if (records.isEmpty()) {
|
||||
return CommonResult.failed("封禁记录不存在");
|
||||
}
|
||||
|
||||
Integer userId = ((Number) records.get(0).get("user_id")).intValue();
|
||||
|
||||
// 更新封禁状态
|
||||
String updateSql = "UPDATE eb_user_ban SET status = 0, update_time = NOW() WHERE id = ?";
|
||||
jdbcTemplate.update(updateSql, id);
|
||||
|
||||
// 恢复用户状态
|
||||
jdbcTemplate.update("UPDATE eb_user SET status = 1 WHERE uid = ?", userId);
|
||||
|
||||
log.info("【解除用户封禁】id={}, userId={}", id, userId);
|
||||
return CommonResult.success("解除封禁成功");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除用户封禁记录")
|
||||
@PostMapping("/user/delete/{id}")
|
||||
public CommonResult<String> deleteUserBan(@PathVariable Long id) {
|
||||
String sql = "DELETE FROM eb_user_ban WHERE id = ?";
|
||||
int rows = jdbcTemplate.update(sql, id);
|
||||
return rows > 0 ? CommonResult.success("删除成功") : CommonResult.failed("删除失败");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量删除用户封禁记录")
|
||||
@PostMapping("/user/batch-delete")
|
||||
public CommonResult<String> batchDeleteUserBan(@RequestBody List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return CommonResult.failed("请选择要删除的记录");
|
||||
}
|
||||
|
||||
String placeholders = String.join(",", Collections.nCopies(ids.size(), "?"));
|
||||
String sql = "DELETE FROM eb_user_ban WHERE id IN (" + placeholders + ")";
|
||||
int rows = jdbcTemplate.update(sql, ids.toArray());
|
||||
|
||||
return rows > 0 ? CommonResult.success("批量删除成功,删除" + rows + "条记录") : CommonResult.failed("删除失败");
|
||||
}
|
||||
|
||||
// ==================== 房间封禁 ====================
|
||||
|
||||
@ApiOperation(value = "获取房间封禁列表")
|
||||
@GetMapping("/room/list")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getRoomBanList(
|
||||
@RequestParam(value = "page", defaultValue = "1") Integer page,
|
||||
@RequestParam(value = "limit", defaultValue = "10") Integer limit,
|
||||
@RequestParam(value = "roomName", required = false) String roomName,
|
||||
@RequestParam(value = "streamerName", required = false) String streamerName,
|
||||
@RequestParam(value = "banType", required = false) String banType,
|
||||
@RequestParam(value = "status", required = false) Integer status) {
|
||||
|
||||
StringBuilder sql = new StringBuilder(
|
||||
"SELECT rb.*, lr.title as room_name, lr.streamer_name, lr.cover_image " +
|
||||
"FROM eb_room_ban rb " +
|
||||
"LEFT JOIN eb_live_room lr ON rb.room_id = lr.id " +
|
||||
"WHERE 1=1");
|
||||
List<Object> params = new ArrayList<>();
|
||||
|
||||
if (roomName != null && !roomName.trim().isEmpty()) {
|
||||
sql.append(" AND lr.title LIKE ?");
|
||||
params.add("%" + roomName.trim() + "%");
|
||||
}
|
||||
if (streamerName != null && !streamerName.trim().isEmpty()) {
|
||||
sql.append(" AND lr.streamer_name LIKE ?");
|
||||
params.add("%" + streamerName.trim() + "%");
|
||||
}
|
||||
if (banType != null && !banType.trim().isEmpty()) {
|
||||
sql.append(" AND rb.ban_type = ?");
|
||||
params.add(banType);
|
||||
}
|
||||
if (status != null) {
|
||||
sql.append(" AND rb.status = ?");
|
||||
params.add(status);
|
||||
}
|
||||
|
||||
// 计算总数
|
||||
String countSql = sql.toString().replace("SELECT rb.*, lr.title as room_name, lr.streamer_name, lr.cover_image", "SELECT COUNT(*)");
|
||||
Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, params.toArray());
|
||||
|
||||
// 分页查询
|
||||
sql.append(" ORDER BY rb.create_time DESC LIMIT ?, ?");
|
||||
params.add((page - 1) * limit);
|
||||
params.add(limit);
|
||||
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql.toString(), params.toArray());
|
||||
|
||||
return CommonResult.success(buildPage(list, total, page, limit));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "封禁房间")
|
||||
@PostMapping("/room/add")
|
||||
public CommonResult<String> banRoom(@RequestBody Map<String, Object> body) {
|
||||
Integer roomId = body.get("roomId") != null ? Integer.valueOf(body.get("roomId").toString()) : null;
|
||||
String banType = body.get("banType") != null ? body.get("banType").toString() : "permanent";
|
||||
String reason = body.get("reason") != null ? body.get("reason").toString() : "";
|
||||
Integer duration = body.get("duration") != null ? Integer.valueOf(body.get("duration").toString()) : null;
|
||||
Integer operatorId = body.get("operatorId") != null ? Integer.valueOf(body.get("operatorId").toString()) : 0;
|
||||
|
||||
if (roomId == null) {
|
||||
return CommonResult.failed("房间ID不能为空");
|
||||
}
|
||||
|
||||
// 检查房间是否存在
|
||||
String checkSql = "SELECT id, title FROM eb_live_room WHERE id = ?";
|
||||
List<Map<String, Object>> rooms = jdbcTemplate.queryForList(checkSql, roomId);
|
||||
if (rooms.isEmpty()) {
|
||||
return CommonResult.failed("房间不存在");
|
||||
}
|
||||
|
||||
// 检查是否已被封禁
|
||||
String existSql = "SELECT id FROM eb_room_ban WHERE room_id = ? AND status = 1";
|
||||
List<Map<String, Object>> existing = jdbcTemplate.queryForList(existSql, roomId);
|
||||
if (!existing.isEmpty()) {
|
||||
return CommonResult.failed("该房间已被封禁");
|
||||
}
|
||||
|
||||
// 计算封禁结束时间
|
||||
String expireTime = null;
|
||||
if ("temporary".equals(banType) && duration != null && duration > 0) {
|
||||
expireTime = String.format("DATE_ADD(NOW(), INTERVAL %d DAY)", duration);
|
||||
}
|
||||
|
||||
// 插入封禁记录
|
||||
String insertSql;
|
||||
if (expireTime != null) {
|
||||
insertSql = "INSERT INTO eb_room_ban (room_id, ban_type, reason, duration_days, expire_time, operator_id, status, create_time, update_time) " +
|
||||
"VALUES (?, ?, ?, ?, " + expireTime + ", ?, 1, NOW(), NOW())";
|
||||
jdbcTemplate.update(insertSql, roomId, banType, reason, duration, operatorId);
|
||||
} else {
|
||||
insertSql = "INSERT INTO eb_room_ban (room_id, ban_type, reason, duration_days, operator_id, status, create_time, update_time) " +
|
||||
"VALUES (?, ?, ?, ?, ?, 1, NOW(), NOW())";
|
||||
jdbcTemplate.update(insertSql, roomId, banType, reason, duration, operatorId);
|
||||
}
|
||||
|
||||
// 更新房间状态(关闭直播)
|
||||
jdbcTemplate.update("UPDATE eb_live_room SET is_live = 0, status = 0 WHERE id = ?", roomId);
|
||||
|
||||
log.info("【房间封禁】roomId={}, banType={}, reason={}, operatorId={}", roomId, banType, reason, operatorId);
|
||||
return CommonResult.success("封禁成功");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "解除房间封禁")
|
||||
@PostMapping("/room/unban/{id}")
|
||||
public CommonResult<String> unbanRoom(@PathVariable Long id) {
|
||||
// 获取封禁记录
|
||||
String querySql = "SELECT room_id FROM eb_room_ban WHERE id = ?";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(querySql, id);
|
||||
if (records.isEmpty()) {
|
||||
return CommonResult.failed("封禁记录不存在");
|
||||
}
|
||||
|
||||
Integer roomId = ((Number) records.get(0).get("room_id")).intValue();
|
||||
|
||||
// 更新封禁状态
|
||||
String updateSql = "UPDATE eb_room_ban SET status = 0, update_time = NOW() WHERE id = ?";
|
||||
jdbcTemplate.update(updateSql, id);
|
||||
|
||||
// 恢复房间状态
|
||||
jdbcTemplate.update("UPDATE eb_live_room SET status = 1 WHERE id = ?", roomId);
|
||||
|
||||
log.info("【解除房间封禁】id={}, roomId={}", id, roomId);
|
||||
return CommonResult.success("解除封禁成功");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "删除房间封禁记录")
|
||||
@PostMapping("/room/delete/{id}")
|
||||
public CommonResult<String> deleteRoomBan(@PathVariable Long id) {
|
||||
String sql = "DELETE FROM eb_room_ban WHERE id = ?";
|
||||
int rows = jdbcTemplate.update(sql, id);
|
||||
return rows > 0 ? CommonResult.success("删除成功") : CommonResult.failed("删除失败");
|
||||
}
|
||||
|
||||
@ApiOperation(value = "批量删除房间封禁记录")
|
||||
@PostMapping("/room/batch-delete")
|
||||
public CommonResult<String> batchDeleteRoomBan(@RequestBody List<Long> ids) {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
return CommonResult.failed("请选择要删除的记录");
|
||||
}
|
||||
|
||||
String placeholders = String.join(",", Collections.nCopies(ids.size(), "?"));
|
||||
String sql = "DELETE FROM eb_room_ban WHERE id IN (" + placeholders + ")";
|
||||
int rows = jdbcTemplate.update(sql, ids.toArray());
|
||||
|
||||
return rows > 0 ? CommonResult.success("批量删除成功,删除" + rows + "条记录") : CommonResult.failed("删除失败");
|
||||
}
|
||||
|
||||
// ==================== 检查封禁状态(供前端API调用) ====================
|
||||
|
||||
@ApiOperation(value = "检查用户封禁状态")
|
||||
@GetMapping("/user/check/{userId}")
|
||||
public CommonResult<Map<String, Object>> checkUserBanStatus(@PathVariable Integer userId) {
|
||||
String sql = "SELECT * FROM eb_user_ban WHERE user_id = ? AND status = 1 " +
|
||||
"AND (expire_time IS NULL OR expire_time > NOW()) ORDER BY create_time DESC LIMIT 1";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(sql, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (records.isEmpty()) {
|
||||
result.put("isBanned", false);
|
||||
} else {
|
||||
result.put("isBanned", true);
|
||||
result.put("banInfo", records.get(0));
|
||||
}
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "检查房间封禁状态")
|
||||
@GetMapping("/room/check/{roomId}")
|
||||
public CommonResult<Map<String, Object>> checkRoomBanStatus(@PathVariable Integer roomId) {
|
||||
String sql = "SELECT * FROM eb_room_ban WHERE room_id = ? AND status = 1 " +
|
||||
"AND (expire_time IS NULL OR expire_time > NOW()) ORDER BY create_time DESC LIMIT 1";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(sql, roomId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (records.isEmpty()) {
|
||||
result.put("isBanned", false);
|
||||
} else {
|
||||
result.put("isBanned", true);
|
||||
result.put("banInfo", records.get(0));
|
||||
}
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
// ==================== 工具方法 ====================
|
||||
|
||||
private CommonPage<Map<String, Object>> buildPage(List<Map<String, Object>> list, Integer total, Integer page, Integer limit) {
|
||||
CommonPage<Map<String, Object>> result = new CommonPage<>();
|
||||
result.setList(list);
|
||||
result.setTotal(total != null ? total.longValue() : 0L);
|
||||
result.setPage(page);
|
||||
result.setLimit(limit);
|
||||
result.setTotalPage((int) Math.ceil((double) (total != null ? total : 0) / limit));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
package com.zbkj.front.controller;
|
||||
|
||||
import com.zbkj.common.page.CommonPage;
|
||||
import com.zbkj.common.result.CommonResult;
|
||||
import com.zbkj.service.service.UserService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 封禁功能控制器(移动端API)
|
||||
* 提供用户封禁检查、黑名单管理等功能
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("api/front/ban")
|
||||
@Api(tags = "封禁管理-移动端")
|
||||
@Validated
|
||||
public class BanFrontController {
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
// ==================== 封禁状态检查 ====================
|
||||
|
||||
/**
|
||||
* 检查当前用户是否被封禁
|
||||
*/
|
||||
@ApiOperation(value = "检查当前用户封禁状态")
|
||||
@GetMapping("/check/me")
|
||||
public CommonResult<Map<String, Object>> checkMyBanStatus() {
|
||||
Integer userId = userService.getUserId();
|
||||
if (userId == null || userId == 0) {
|
||||
return CommonResult.failed("请先登录");
|
||||
}
|
||||
|
||||
return checkUserBanStatus(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定用户是否被封禁
|
||||
*/
|
||||
@ApiOperation(value = "检查用户封禁状态")
|
||||
@GetMapping("/check/user/{userId}")
|
||||
public CommonResult<Map<String, Object>> checkUserBanStatus(@PathVariable Integer userId) {
|
||||
String sql = "SELECT id, ban_type, reason, expire_time, create_time " +
|
||||
"FROM eb_user_ban WHERE user_id = ? AND status = 1 " +
|
||||
"AND (expire_time IS NULL OR expire_time > NOW()) " +
|
||||
"ORDER BY create_time DESC LIMIT 1";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(sql, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (records.isEmpty()) {
|
||||
result.put("isBanned", false);
|
||||
result.put("message", "用户状态正常");
|
||||
} else {
|
||||
Map<String, Object> banInfo = records.get(0);
|
||||
result.put("isBanned", true);
|
||||
result.put("banType", banInfo.get("ban_type"));
|
||||
result.put("reason", banInfo.get("reason"));
|
||||
result.put("expireTime", banInfo.get("expire_time"));
|
||||
result.put("createTime", banInfo.get("create_time"));
|
||||
|
||||
String banType = (String) banInfo.get("ban_type");
|
||||
if ("permanent".equals(banType)) {
|
||||
result.put("message", "您的账号已被永久封禁");
|
||||
} else {
|
||||
result.put("message", "您的账号已被临时封禁,解封时间:" + banInfo.get("expire_time"));
|
||||
}
|
||||
}
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查房间是否被封禁
|
||||
*/
|
||||
@ApiOperation(value = "检查房间封禁状态")
|
||||
@GetMapping("/check/room/{roomId}")
|
||||
public CommonResult<Map<String, Object>> checkRoomBanStatus(@PathVariable Integer roomId) {
|
||||
String sql = "SELECT id, ban_type, reason, expire_time, create_time " +
|
||||
"FROM eb_room_ban WHERE room_id = ? AND status = 1 " +
|
||||
"AND (expire_time IS NULL OR expire_time > NOW()) " +
|
||||
"ORDER BY create_time DESC LIMIT 1";
|
||||
List<Map<String, Object>> records = jdbcTemplate.queryForList(sql, roomId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (records.isEmpty()) {
|
||||
result.put("isBanned", false);
|
||||
result.put("message", "房间状态正常");
|
||||
} else {
|
||||
Map<String, Object> banInfo = records.get(0);
|
||||
result.put("isBanned", true);
|
||||
result.put("banType", banInfo.get("ban_type"));
|
||||
result.put("reason", banInfo.get("reason"));
|
||||
result.put("expireTime", banInfo.get("expire_time"));
|
||||
result.put("createTime", banInfo.get("create_time"));
|
||||
|
||||
String banType = (String) banInfo.get("ban_type");
|
||||
if ("permanent".equals(banType)) {
|
||||
result.put("message", "该直播间已被永久封禁");
|
||||
} else {
|
||||
result.put("message", "该直播间已被临时封禁,解封时间:" + banInfo.get("expire_time"));
|
||||
}
|
||||
}
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
// ==================== 用户黑名单管理(用户间拉黑) ====================
|
||||
|
||||
/**
|
||||
* 获取我的黑名单列表
|
||||
*/
|
||||
@ApiOperation(value = "获取我的黑名单列表")
|
||||
@GetMapping("/blacklist/list")
|
||||
public CommonResult<CommonPage<Map<String, Object>>> getMyBlacklist(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "20") Integer pageSize) {
|
||||
|
||||
Integer userId = userService.getUserId();
|
||||
if (userId == null || userId == 0) {
|
||||
return CommonResult.failed("请先登录");
|
||||
}
|
||||
|
||||
int offset = (page - 1) * pageSize;
|
||||
|
||||
// 查询总数
|
||||
String countSql = "SELECT COUNT(*) FROM eb_user_blacklist WHERE user_id = ?";
|
||||
Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, userId);
|
||||
|
||||
// 查询列表
|
||||
String sql = "SELECT ub.id, ub.blocked_user_id as blockedUserId, " +
|
||||
"u.nickname as blockedNickname, u.avatar as blockedAvatar, " +
|
||||
"ub.create_time as createTime " +
|
||||
"FROM eb_user_blacklist ub " +
|
||||
"LEFT JOIN eb_user u ON ub.blocked_user_id = u.uid " +
|
||||
"WHERE ub.user_id = ? " +
|
||||
"ORDER BY ub.create_time DESC LIMIT ? OFFSET ?";
|
||||
List<Map<String, Object>> list = jdbcTemplate.queryForList(sql, userId, pageSize, offset);
|
||||
|
||||
return CommonResult.success(buildPage(list, total, page, pageSize));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户到黑名单
|
||||
*/
|
||||
@ApiOperation(value = "添加用户到黑名单")
|
||||
@PostMapping("/blacklist/add")
|
||||
public CommonResult<Map<String, Object>> addToBlacklist(@RequestBody Map<String, Object> body) {
|
||||
Integer userId = userService.getUserId();
|
||||
if (userId == null || userId == 0) {
|
||||
return CommonResult.failed("请先登录");
|
||||
}
|
||||
|
||||
Integer targetUserId = body.get("targetUserId") != null ?
|
||||
Integer.valueOf(body.get("targetUserId").toString()) : null;
|
||||
|
||||
if (targetUserId == null) {
|
||||
return CommonResult.failed("目标用户ID不能为空");
|
||||
}
|
||||
|
||||
if (userId.equals(targetUserId)) {
|
||||
return CommonResult.failed("不能拉黑自己");
|
||||
}
|
||||
|
||||
// 检查目标用户是否存在
|
||||
String checkUserSql = "SELECT uid, nickname FROM eb_user WHERE uid = ?";
|
||||
List<Map<String, Object>> users = jdbcTemplate.queryForList(checkUserSql, targetUserId);
|
||||
if (users.isEmpty()) {
|
||||
return CommonResult.failed("目标用户不存在");
|
||||
}
|
||||
|
||||
// 检查是否已在黑名单
|
||||
String checkSql = "SELECT id FROM eb_user_blacklist WHERE user_id = ? AND blocked_user_id = ?";
|
||||
List<Map<String, Object>> existing = jdbcTemplate.queryForList(checkSql, userId, targetUserId);
|
||||
if (!existing.isEmpty()) {
|
||||
return CommonResult.failed("该用户已在黑名单中");
|
||||
}
|
||||
|
||||
// 获取用户昵称
|
||||
String blockerNickname = "";
|
||||
String blockedNickname = users.get(0).get("nickname") != null ?
|
||||
users.get(0).get("nickname").toString() : "";
|
||||
|
||||
String getUserSql = "SELECT nickname FROM eb_user WHERE uid = ?";
|
||||
List<Map<String, Object>> blockerUsers = jdbcTemplate.queryForList(getUserSql, userId);
|
||||
if (!blockerUsers.isEmpty() && blockerUsers.get(0).get("nickname") != null) {
|
||||
blockerNickname = blockerUsers.get(0).get("nickname").toString();
|
||||
}
|
||||
|
||||
// 添加到黑名单
|
||||
String insertSql = "INSERT INTO eb_user_blacklist (user_id, blocked_user_id, blocker_nickname, blocked_nickname, create_time) " +
|
||||
"VALUES (?, ?, ?, ?, NOW())";
|
||||
jdbcTemplate.update(insertSql, userId, targetUserId, blockerNickname, blockedNickname);
|
||||
|
||||
// 删除好友关系(如果存在)
|
||||
String deleteFriendSql = "DELETE FROM eb_friend WHERE (user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)";
|
||||
jdbcTemplate.update(deleteFriendSql, userId, targetUserId, targetUserId, userId);
|
||||
|
||||
log.info("【添加黑名单】userId={}, targetUserId={}", userId, targetUserId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("success", true);
|
||||
result.put("message", "已将该用户加入黑名单");
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从黑名单移除用户
|
||||
*/
|
||||
@ApiOperation(value = "从黑名单移除用户")
|
||||
@PostMapping("/blacklist/remove")
|
||||
public CommonResult<Map<String, Object>> removeFromBlacklist(@RequestBody Map<String, Object> body) {
|
||||
Integer userId = userService.getUserId();
|
||||
if (userId == null || userId == 0) {
|
||||
return CommonResult.failed("请先登录");
|
||||
}
|
||||
|
||||
Integer targetUserId = body.get("targetUserId") != null ?
|
||||
Integer.valueOf(body.get("targetUserId").toString()) : null;
|
||||
|
||||
if (targetUserId == null) {
|
||||
return CommonResult.failed("目标用户ID不能为空");
|
||||
}
|
||||
|
||||
String deleteSql = "DELETE FROM eb_user_blacklist WHERE user_id = ? AND blocked_user_id = ?";
|
||||
int rows = jdbcTemplate.update(deleteSql, userId, targetUserId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (rows > 0) {
|
||||
result.put("success", true);
|
||||
result.put("message", "已将该用户从黑名单移除");
|
||||
log.info("【移除黑名单】userId={}, targetUserId={}", userId, targetUserId);
|
||||
} else {
|
||||
result.put("success", false);
|
||||
result.put("message", "该用户不在黑名单中");
|
||||
}
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查用户是否在我的黑名单中
|
||||
*/
|
||||
@ApiOperation(value = "检查用户是否在黑名单中")
|
||||
@GetMapping("/blacklist/check/{targetUserId}")
|
||||
public CommonResult<Map<String, Object>> checkBlacklist(@PathVariable Integer targetUserId) {
|
||||
Integer userId = userService.getUserId();
|
||||
if (userId == null || userId == 0) {
|
||||
return CommonResult.failed("请先登录");
|
||||
}
|
||||
|
||||
// 检查我是否拉黑了对方
|
||||
String sql1 = "SELECT id FROM eb_user_blacklist WHERE user_id = ? AND blocked_user_id = ?";
|
||||
List<Map<String, Object>> myBlacklist = jdbcTemplate.queryForList(sql1, userId, targetUserId);
|
||||
|
||||
// 检查对方是否拉黑了我
|
||||
String sql2 = "SELECT id FROM eb_user_blacklist WHERE user_id = ? AND blocked_user_id = ?";
|
||||
List<Map<String, Object>> theirBlacklist = jdbcTemplate.queryForList(sql2, targetUserId, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("isBlocked", !myBlacklist.isEmpty()); // 我是否拉黑了对方
|
||||
result.put("isBlockedByTarget", !theirBlacklist.isEmpty()); // 对方是否拉黑了我
|
||||
result.put("canInteract", myBlacklist.isEmpty() && theirBlacklist.isEmpty()); // 是否可以互动
|
||||
|
||||
return CommonResult.success(result);
|
||||
}
|
||||
|
||||
// ==================== 工具方法 ====================
|
||||
|
||||
private CommonPage<Map<String, Object>> buildPage(List<Map<String, Object>> list, Integer total, Integer page, Integer pageSize) {
|
||||
CommonPage<Map<String, Object>> result = new CommonPage<>();
|
||||
result.setList(list);
|
||||
result.setTotal(total != null ? total.longValue() : 0L);
|
||||
result.setPage(page);
|
||||
result.setLimit(pageSize);
|
||||
result.setTotalPage((int) Math.ceil((double) (total != null ? total : 0) / pageSize));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
43
add_ban_menus.sql
Normal file
43
add_ban_menus.sql
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
-- =====================================================
|
||||
-- 添加封禁管理菜单(替换原有的拉黑菜单)
|
||||
-- eb_system_menu 表结构:id, pid, name, icon, perms, component, menu_type, sort, is_show, is_delte
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 查找用户管理的父菜单ID
|
||||
SET @userManagePid = (SELECT id FROM eb_system_menu WHERE `name` = '用户管理' AND pid = 0 LIMIT 1);
|
||||
|
||||
-- 如果没有找到用户管理,尝试查找"用户"菜单
|
||||
SET @userManagePid = IFNULL(@userManagePid, (SELECT id FROM eb_system_menu WHERE `name` = '用户' AND pid = 0 LIMIT 1));
|
||||
|
||||
-- 如果还是没有找到,使用默认值4(通常是用户菜单的ID)
|
||||
SET @userManagePid = IFNULL(@userManagePid, 4);
|
||||
|
||||
SELECT CONCAT('用户管理菜单ID: ', @userManagePid) as info;
|
||||
|
||||
-- 2. 删除旧的拉黑菜单(如果存在)
|
||||
DELETE FROM eb_system_menu WHERE `name` IN ('房间拉黑', '用户拉黑') AND pid = @userManagePid;
|
||||
|
||||
-- 3. 添加新的封禁菜单
|
||||
-- 用户封禁
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`, `is_delte`, `create_time`, `update_time`)
|
||||
SELECT @userManagePid, '用户封禁', '', 'admin:ban:user', '/user/ban/userBan', 'C', 92, 1, 0, NOW(), NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM eb_system_menu WHERE `name` = '用户封禁' AND pid = @userManagePid);
|
||||
|
||||
-- 房间封禁
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`, `is_delte`, `create_time`, `update_time`)
|
||||
SELECT @userManagePid, '房间封禁', '', 'admin:ban:room', '/user/ban/roomBan', 'C', 91, 1, 0, NOW(), NOW()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM eb_system_menu WHERE `name` = '房间封禁' AND pid = @userManagePid);
|
||||
|
||||
-- 4. 验证菜单
|
||||
SELECT '=== 封禁管理菜单 ===' as info;
|
||||
SELECT id, pid, `name`, perms, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @userManagePid AND (`name` LIKE '%封禁%' OR `name` LIKE '%黑名单%' OR `name` LIKE '%拉黑%')
|
||||
ORDER BY sort DESC;
|
||||
|
||||
-- 5. 显示所有用户管理子菜单
|
||||
SELECT '=== 用户管理所有子菜单 ===' as info;
|
||||
SELECT id, pid, `name`, perms, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @userManagePid
|
||||
ORDER BY sort DESC;
|
||||
70
add_ban_test_data.sql
Normal file
70
add_ban_test_data.sql
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
-- =====================================================
|
||||
-- 添加封禁系统测试数据
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 确保封禁表存在
|
||||
CREATE TABLE IF NOT EXISTS eb_user_ban (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL COMMENT '被封禁用户ID',
|
||||
ban_type VARCHAR(20) DEFAULT 'permanent' COMMENT '封禁类型: permanent-永久, temporary-临时',
|
||||
reason VARCHAR(500) COMMENT '封禁原因',
|
||||
duration_days INT DEFAULT NULL COMMENT '封禁天数(临时封禁)',
|
||||
expire_time DATETIME DEFAULT NULL COMMENT '封禁到期时间',
|
||||
operator_id INT DEFAULT 0 COMMENT '操作人ID',
|
||||
status TINYINT DEFAULT 1 COMMENT '状态: 1-生效中, 0-已解除',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户封禁表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS eb_room_ban (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
room_id INT NOT NULL COMMENT '被封禁房间ID',
|
||||
ban_type VARCHAR(20) DEFAULT 'permanent' COMMENT '封禁类型: permanent-永久, temporary-临时',
|
||||
reason VARCHAR(500) COMMENT '封禁原因',
|
||||
duration_days INT DEFAULT NULL COMMENT '封禁天数(临时封禁)',
|
||||
expire_time DATETIME DEFAULT NULL COMMENT '封禁到期时间',
|
||||
operator_id INT DEFAULT 0 COMMENT '操作人ID',
|
||||
status TINYINT DEFAULT 1 COMMENT '状态: 1-生效中, 0-已解除',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_room_id (room_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房间封禁表';
|
||||
|
||||
-- 2. 添加用户封禁测试数据
|
||||
INSERT INTO eb_user_ban (user_id, ban_type, reason, duration_days, expire_time, operator_id, status, create_time) VALUES
|
||||
(43, 'permanent', '发布违规内容', NULL, NULL, 1, 1, NOW() - INTERVAL 2 DAY),
|
||||
(100, 'temporary', '恶意刷屏', 7, NOW() + INTERVAL 5 DAY, 1, 1, NOW() - INTERVAL 2 DAY),
|
||||
(101, 'temporary', '骚扰其他用户', 30, NOW() + INTERVAL 28 DAY, 1, 1, NOW() - INTERVAL 2 DAY),
|
||||
(102, 'permanent', '传播不良信息', NULL, NULL, 1, 0, NOW() - INTERVAL 10 DAY)
|
||||
ON DUPLICATE KEY UPDATE reason = VALUES(reason);
|
||||
|
||||
-- 3. 添加房间封禁测试数据
|
||||
INSERT INTO eb_room_ban (room_id, ban_type, reason, duration_days, expire_time, operator_id, status, create_time) VALUES
|
||||
(1, 'temporary', '直播内容违规', 3, NOW() + INTERVAL 1 DAY, 1, 1, NOW() - INTERVAL 2 DAY),
|
||||
(2, 'permanent', '严重违规行为', NULL, NULL, 1, 1, NOW() - INTERVAL 5 DAY),
|
||||
(3, 'temporary', '未经授权的商业推广', 7, NOW() + INTERVAL 5 DAY, 1, 1, NOW() - INTERVAL 2 DAY),
|
||||
(4, 'permanent', '涉及敏感内容', NULL, NULL, 1, 0, NOW() - INTERVAL 15 DAY)
|
||||
ON DUPLICATE KEY UPDATE reason = VALUES(reason);
|
||||
|
||||
-- 4. 验证数据
|
||||
SELECT '=== 用户封禁数据 ===' as info;
|
||||
SELECT ub.*, u.nickname, u.phone
|
||||
FROM eb_user_ban ub
|
||||
LEFT JOIN eb_user u ON ub.user_id = u.uid
|
||||
ORDER BY ub.create_time DESC;
|
||||
|
||||
SELECT '=== 房间封禁数据 ===' as info;
|
||||
SELECT rb.*, lr.title as room_name, lr.streamer_name
|
||||
FROM eb_room_ban rb
|
||||
LEFT JOIN eb_live_room lr ON rb.room_id = lr.id
|
||||
ORDER BY rb.create_time DESC;
|
||||
|
||||
SELECT '=== 统计 ===' as info;
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM eb_user_ban) as 用户封禁总数,
|
||||
(SELECT COUNT(*) FROM eb_user_ban WHERE status = 1) as 用户封禁生效中,
|
||||
(SELECT COUNT(*) FROM eb_room_ban) as 房间封禁总数,
|
||||
(SELECT COUNT(*) FROM eb_room_ban WHERE status = 1) as 房间封禁生效中;
|
||||
50
add_blacklist_menu_now.sql
Normal file
50
add_blacklist_menu_now.sql
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
-- =====================================================
|
||||
-- 立即添加拉黑管理菜单到社交互动模块
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 先查看社交互动菜单的ID
|
||||
SELECT id, pid, `name`, component, menu_type FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 2. 查看现有的社交互动子菜单
|
||||
SELECT id, pid, `name`, component, sort FROM eb_system_menu WHERE pid = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' LIMIT 1) ORDER BY sort;
|
||||
|
||||
-- 3. 检查是否已存在拉黑菜单
|
||||
SELECT id, `name`, component FROM eb_system_menu WHERE `name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 4. 删除可能存在的旧记录(避免重复)
|
||||
DELETE FROM eb_system_menu WHERE `name` = '用户拉黑' AND component LIKE '%blacklist%';
|
||||
DELETE FROM eb_system_menu WHERE `name` = '房间拉黑' AND component LIKE '%blacklist%';
|
||||
|
||||
-- 5. 插入用户拉黑菜单(假设社交互动ID为某个值,需要先查询)
|
||||
-- 先获取社交互动的ID
|
||||
SET @social_id = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' AND menu_type = 'M' LIMIT 1);
|
||||
SELECT @social_id as '社交互动菜单ID';
|
||||
|
||||
-- 6. 插入用户拉黑
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_id, '用户拉黑', 'el-icon-user', 'admin:blacklist:user', '/socialManage/blacklist/user', 'C', 100, 1);
|
||||
|
||||
-- 7. 插入房间拉黑
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_id, '房间拉黑', 'el-icon-house', 'admin:blacklist:room', '/socialManage/blacklist/room', 'C', 101, 1);
|
||||
|
||||
-- 8. 为管理员角色(rid=1)添加权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE `name` = '用户拉黑' AND component = '/socialManage/blacklist/user';
|
||||
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE `name` = '房间拉黑' AND component = '/socialManage/blacklist/room';
|
||||
|
||||
-- 9. 验证插入结果
|
||||
SELECT '=== 新增的拉黑菜单 ===' as info;
|
||||
SELECT id, pid, `name`, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE `name` IN ('用户拉黑', '房间拉黑')
|
||||
ORDER BY id DESC;
|
||||
|
||||
-- 10. 验证社交互动下所有子菜单
|
||||
SELECT '=== 社交互动下所有子菜单 ===' as info;
|
||||
SELECT id, `name`, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @social_id
|
||||
ORDER BY sort;
|
||||
35
add_blacklist_to_social.sql
Normal file
35
add_blacklist_to_social.sql
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
-- =====================================================
|
||||
-- 在"社交互动"模块下添加"拉黑管理"菜单
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 查找"社交互动"菜单的ID
|
||||
SELECT id, pid, `name`, component FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 2. 查找现有的拉黑管理菜单(如果有的话)
|
||||
SELECT id, pid, `name`, component FROM eb_system_menu WHERE `name` LIKE '%拉黑%';
|
||||
|
||||
-- 3. 添加"用户拉黑"菜单到社交互动下
|
||||
-- 假设社交互动的ID需要查询,这里用变量方式
|
||||
SET @social_pid = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' AND menu_type = 'M' LIMIT 1);
|
||||
|
||||
-- 如果社交互动菜单存在,添加拉黑子菜单
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`, `is_delete`)
|
||||
SELECT @social_pid, '用户拉黑', '', 'admin:blacklist:user', '/socialManage/blacklist/user', 'C', 100, 1, 0
|
||||
FROM DUAL WHERE @social_pid IS NOT NULL
|
||||
ON DUPLICATE KEY UPDATE `name` = '用户拉黑';
|
||||
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`, `is_delete`)
|
||||
SELECT @social_pid, '房间拉黑', '', 'admin:blacklist:room', '/socialManage/blacklist/room', 'C', 101, 1, 0
|
||||
FROM DUAL WHERE @social_pid IS NOT NULL
|
||||
ON DUPLICATE KEY UPDATE `name` = '房间拉黑';
|
||||
|
||||
-- 4. 为管理员角色添加权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE `name` IN ('用户拉黑', '房间拉黑') AND pid = @social_pid;
|
||||
|
||||
-- 5. 验证结果
|
||||
SELECT '=== 社交互动下的菜单 ===' as info;
|
||||
SELECT id, pid, `name`, component, sort
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @social_pid
|
||||
ORDER BY sort;
|
||||
34
add_blacklist_to_social_v2.sql
Normal file
34
add_blacklist_to_social_v2.sql
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
-- =====================================================
|
||||
-- 在"社交互动"模块下添加"拉黑管理"菜单 (修正版)
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 查看菜单表结构
|
||||
DESC eb_system_menu;
|
||||
|
||||
-- 2. 查找"社交互动"菜单的ID
|
||||
SELECT id, pid, `name`, component FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 3. 获取社交互动的ID
|
||||
SET @social_pid = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' AND menu_type = 'M' LIMIT 1);
|
||||
SELECT @social_pid as social_menu_id;
|
||||
|
||||
-- 4. 添加"用户拉黑"菜单
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_pid, '用户拉黑', '', 'admin:blacklist:user', '/socialManage/blacklist/user', 'C', 100, 1)
|
||||
ON DUPLICATE KEY UPDATE `component` = '/socialManage/blacklist/user';
|
||||
|
||||
-- 5. 添加"房间拉黑"菜单
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_pid, '房间拉黑', '', 'admin:blacklist:room', '/socialManage/blacklist/room', 'C', 101, 1)
|
||||
ON DUPLICATE KEY UPDATE `component` = '/socialManage/blacklist/room';
|
||||
|
||||
-- 6. 为管理员角色添加权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE `name` IN ('用户拉黑', '房间拉黑') AND pid = @social_pid;
|
||||
|
||||
-- 7. 验证结果
|
||||
SELECT '=== 社交互动下的菜单 ===' as info;
|
||||
SELECT id, pid, `name`, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @social_pid
|
||||
ORDER BY sort;
|
||||
125
add_test_data_for_user.sql
Normal file
125
add_test_data_for_user.sql
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
-- 为指定用户添加测试数据
|
||||
-- 使用方法: 将 @USER_ID 替换为实际的用户ID
|
||||
|
||||
-- 设置用户ID变量 (修改这里的值为移动端登录的用户ID)
|
||||
SET @USER_ID = 121;
|
||||
|
||||
-- 查看当前用户信息
|
||||
SELECT uid, nickname, phone FROM eb_user WHERE uid = @USER_ID;
|
||||
|
||||
-- ========================================
|
||||
-- 0. 检查必要的表是否存在
|
||||
-- ========================================
|
||||
-- 如果 eb_view_history 表不存在,先创建它
|
||||
CREATE TABLE IF NOT EXISTS eb_view_history (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL COMMENT '用户ID',
|
||||
target_type VARCHAR(20) NOT NULL COMMENT '目标类型: room-直播间, work-作品, profile-用户主页',
|
||||
target_id VARCHAR(50) NOT NULL COMMENT '目标ID',
|
||||
target_title VARCHAR(200) DEFAULT NULL COMMENT '目标标题',
|
||||
view_duration INT DEFAULT 0 COMMENT '观看时长(秒)',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_target (target_type, target_id),
|
||||
UNIQUE KEY uk_user_target (user_id, target_type, target_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户观看历史';
|
||||
|
||||
-- ========================================
|
||||
-- 1. 添加观看历史
|
||||
-- ========================================
|
||||
-- 先检查是否有直播间数据
|
||||
SELECT COUNT(*) as room_count FROM eb_live_room;
|
||||
|
||||
-- 添加直播间观看历史
|
||||
INSERT IGNORE INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time)
|
||||
SELECT @USER_ID, 'room', id, title, FLOOR(RAND() * 3600), NOW() - INTERVAL FLOOR(RAND() * 7) DAY, NOW()
|
||||
FROM eb_live_room LIMIT 5;
|
||||
|
||||
-- 检查是否有作品数据
|
||||
SELECT COUNT(*) as works_count FROM eb_works;
|
||||
|
||||
-- 添加作品观看历史
|
||||
INSERT IGNORE INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time)
|
||||
SELECT @USER_ID, 'work', id, title, FLOOR(RAND() * 600), NOW() - INTERVAL FLOOR(RAND() * 7) DAY, NOW()
|
||||
FROM eb_works LIMIT 5;
|
||||
|
||||
-- ========================================
|
||||
-- 2. 添加直播间点赞
|
||||
-- ========================================
|
||||
-- 检查 eb_live_room_like 表是否存在
|
||||
CREATE TABLE IF NOT EXISTS eb_live_room_like (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL COMMENT '用户ID',
|
||||
room_id INT NOT NULL COMMENT '直播间ID',
|
||||
like_count INT DEFAULT 1 COMMENT '点赞次数',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_room_id (room_id),
|
||||
UNIQUE KEY uk_user_room (user_id, room_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='直播间点赞记录';
|
||||
|
||||
INSERT IGNORE INTO eb_live_room_like (user_id, room_id, like_count, create_time)
|
||||
SELECT @USER_ID, id, FLOOR(RAND() * 10) + 1, NOW() - INTERVAL FLOOR(RAND() * 7) DAY
|
||||
FROM eb_live_room LIMIT 5;
|
||||
|
||||
-- ========================================
|
||||
-- 3. 添加作品点赞 (type=1)
|
||||
-- ========================================
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time)
|
||||
SELECT @USER_ID, id, 1, NOW() - INTERVAL FLOOR(RAND() * 7) DAY
|
||||
FROM eb_works LIMIT 5;
|
||||
|
||||
-- ========================================
|
||||
-- 4. 添加作品收藏 (type=2)
|
||||
-- ========================================
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time)
|
||||
SELECT @USER_ID, id, 2, NOW() - INTERVAL FLOOR(RAND() * 7) DAY
|
||||
FROM eb_works WHERE id NOT IN (SELECT works_id FROM eb_works_relation WHERE uid = @USER_ID AND type = 2) LIMIT 4;
|
||||
|
||||
-- ========================================
|
||||
-- 5. 添加关注记录
|
||||
-- ========================================
|
||||
-- 检查 eb_follow_record 表是否存在
|
||||
CREATE TABLE IF NOT EXISTS eb_follow_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
follower_id INT NOT NULL COMMENT '关注者ID',
|
||||
follower_nickname VARCHAR(100) DEFAULT NULL COMMENT '关注者昵称',
|
||||
followed_id INT NOT NULL COMMENT '被关注者ID',
|
||||
followed_nickname VARCHAR(100) DEFAULT NULL COMMENT '被关注者昵称',
|
||||
follow_status VARCHAR(20) DEFAULT '1' COMMENT '关注状态: 1或关注=已关注',
|
||||
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
INDEX idx_follower (follower_id),
|
||||
INDEX idx_followed (followed_id),
|
||||
UNIQUE KEY uk_follow (follower_id, followed_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='关注记录';
|
||||
|
||||
INSERT IGNORE INTO eb_follow_record (follower_id, follower_nickname, followed_id, followed_nickname, follow_status, create_time)
|
||||
SELECT @USER_ID,
|
||||
(SELECT nickname FROM eb_user WHERE uid = @USER_ID),
|
||||
uid,
|
||||
nickname,
|
||||
1,
|
||||
NOW() - INTERVAL FLOOR(RAND() * 30) DAY
|
||||
FROM eb_user
|
||||
WHERE uid != @USER_ID
|
||||
AND uid NOT IN (SELECT followed_id FROM eb_follow_record WHERE follower_id = @USER_ID)
|
||||
LIMIT 6;
|
||||
|
||||
-- ========================================
|
||||
-- 验证数据
|
||||
-- ========================================
|
||||
SELECT '观看历史' as type, COUNT(*) as count FROM eb_view_history WHERE user_id = @USER_ID
|
||||
UNION ALL
|
||||
SELECT '直播间点赞', COUNT(*) FROM eb_live_room_like WHERE user_id = @USER_ID
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = @USER_ID AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = @USER_ID AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注记录', COUNT(*) FROM eb_follow_record WHERE follower_id = @USER_ID AND (follow_status = 1 OR follow_status = '关注');
|
||||
|
||||
-- ========================================
|
||||
-- 查看所有用户列表(用于确定移动端登录的用户ID)
|
||||
-- ========================================
|
||||
SELECT uid, nickname, phone, create_time FROM eb_user ORDER BY uid DESC LIMIT 20;
|
||||
18
add_view_history_121.sql
Normal file
18
add_view_history_121.sql
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加观看历史到 eb_view_history 表
|
||||
-- =====================================================
|
||||
|
||||
-- 插入观看历史数据
|
||||
INSERT INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time) VALUES
|
||||
(121, 'room', '1', '欢乐游戏直播', 1800, '2026-01-03 20:30:00', '2026-01-03 20:30:00'),
|
||||
(121, 'room', '2', '音乐分享会', 2400, '2026-01-03 21:00:00', '2026-01-03 21:00:00'),
|
||||
(121, 'room', '3', '户外探险直播', 900, '2026-01-02 19:00:00', '2026-01-02 19:00:00'),
|
||||
(121, 'room', '4', '美食制作教程', 3600, '2026-01-02 12:00:00', '2026-01-02 12:00:00'),
|
||||
(121, 'room', '5', '编程技术分享', 5400, '2026-01-01 14:00:00', '2026-01-01 14:00:00'),
|
||||
(121, 'work', '1', '搞笑短视频合集', 180, '2026-01-03 22:00:00', '2026-01-03 22:00:00'),
|
||||
(121, 'work', '2', '旅行Vlog-云南之旅', 600, '2026-01-03 18:00:00', '2026-01-03 18:00:00'),
|
||||
(121, 'work', '3', '美妆教程分享', 420, '2026-01-02 16:00:00', '2026-01-02 16:00:00');
|
||||
|
||||
-- 验证数据
|
||||
SELECT COUNT(*) as 观看历史数量 FROM eb_view_history WHERE user_id = 121;
|
||||
SELECT * FROM eb_view_history WHERE user_id = 121 ORDER BY update_time DESC;
|
||||
27
add_view_history_121_final.sql
Normal file
27
add_view_history_121_final.sql
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(uid=121)添加观看历史数据
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 确保表存在
|
||||
CREATE TABLE IF NOT EXISTS `eb_view_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`target_type` varchar(20) NOT NULL,
|
||||
`target_id` varchar(50) NOT NULL,
|
||||
`target_title` varchar(255) DEFAULT NULL,
|
||||
`view_duration` int(11) DEFAULT 0,
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- 2. 插入观看历史数据
|
||||
INSERT INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time)
|
||||
VALUES
|
||||
(121, 'room', '1', '欢乐游戏直播', 1800, NOW() - INTERVAL 1 HOUR, NOW() - INTERVAL 1 HOUR),
|
||||
(121, 'room', '2', '音乐分享会', 2400, NOW() - INTERVAL 2 HOUR, NOW() - INTERVAL 2 HOUR),
|
||||
(121, 'room', '8', '火影忍者', 3600, NOW() - INTERVAL 30 MINUTE, NOW() - INTERVAL 30 MINUTE);
|
||||
|
||||
-- 3. 验证结果
|
||||
SELECT * FROM eb_view_history WHERE user_id = 121 ORDER BY update_time DESC;
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.example.livestreaming;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 余额记录列表适配器
|
||||
*/
|
||||
public class BalanceRecordAdapter extends RecyclerView.Adapter<BalanceRecordAdapter.ViewHolder> {
|
||||
|
||||
private List<Map<String, Object>> records;
|
||||
|
||||
public BalanceRecordAdapter(List<Map<String, Object>> records) {
|
||||
this.records = records;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_balance_record, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Map<String, Object> record = records.get(position);
|
||||
|
||||
// 标题
|
||||
String title = (String) record.get("title");
|
||||
if (title == null) title = (String) record.get("remark");
|
||||
if (title == null) title = "交易记录";
|
||||
holder.tvTitle.setText(title);
|
||||
|
||||
// 金额
|
||||
Object amountObj = record.get("amount");
|
||||
if (amountObj == null) amountObj = record.get("price");
|
||||
double amount = amountObj != null ? ((Number) amountObj).doubleValue() : 0;
|
||||
String amountStr = amount >= 0 ? String.format("+%.2f", amount) : String.format("%.2f", amount);
|
||||
holder.tvAmount.setText(amountStr);
|
||||
holder.tvAmount.setTextColor(amount >= 0 ? 0xFF4CAF50 : 0xFFE53935);
|
||||
|
||||
// 时间
|
||||
String time = (String) record.get("createTime");
|
||||
if (time == null) time = (String) record.get("create_time");
|
||||
if (time == null) time = "";
|
||||
holder.tvTime.setText(time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return records != null ? records.size() : 0;
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView tvTitle;
|
||||
TextView tvAmount;
|
||||
TextView tvTime;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
tvTitle = itemView.findViewById(R.id.tv_title);
|
||||
tvAmount = itemView.findViewById(R.id.tv_amount);
|
||||
tvTime = itemView.findViewById(R.id.tv_time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
package com.example.livestreaming;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
import com.example.livestreaming.net.ApiClient;
|
||||
import com.example.livestreaming.net.ApiResponse;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 余额记录Fragment(充值记录/消费记录)
|
||||
*/
|
||||
public class BalanceRecordFragment extends Fragment {
|
||||
|
||||
private static final String ARG_TYPE = "type";
|
||||
private String recordType; // "recharge" or "consume"
|
||||
|
||||
private SwipeRefreshLayout swipeRefresh;
|
||||
private RecyclerView recyclerView;
|
||||
private TextView tvEmpty;
|
||||
private BalanceRecordAdapter adapter;
|
||||
private List<Map<String, Object>> recordList = new ArrayList<>();
|
||||
|
||||
public static BalanceRecordFragment newInstance(String type) {
|
||||
BalanceRecordFragment fragment = new BalanceRecordFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_TYPE, type);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
recordType = getArguments().getString(ARG_TYPE, "recharge");
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_balance_record, container, false);
|
||||
initViews(view);
|
||||
loadRecords();
|
||||
return view;
|
||||
}
|
||||
|
||||
private void initViews(View view) {
|
||||
swipeRefresh = view.findViewById(R.id.swipe_refresh);
|
||||
recyclerView = view.findViewById(R.id.recycler_view);
|
||||
tvEmpty = view.findViewById(R.id.tv_empty);
|
||||
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
adapter = new BalanceRecordAdapter(recordList);
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
swipeRefresh.setOnRefreshListener(this::loadRecords);
|
||||
}
|
||||
|
||||
private void loadRecords() {
|
||||
swipeRefresh.setRefreshing(true);
|
||||
|
||||
Call<ApiResponse<List<Map<String, Object>>>> call;
|
||||
if ("recharge".equals(recordType)) {
|
||||
call = ApiClient.getService(requireContext()).getRechargeRecords(1, 20);
|
||||
} else {
|
||||
call = ApiClient.getService(requireContext()).getConsumeRecords(1, 20);
|
||||
}
|
||||
|
||||
call.enqueue(new Callback<ApiResponse<List<Map<String, Object>>>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<List<Map<String, Object>>>> call, Response<ApiResponse<List<Map<String, Object>>>> response) {
|
||||
swipeRefresh.setRefreshing(false);
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
List<Map<String, Object>> data = response.body().getData();
|
||||
recordList.clear();
|
||||
if (data != null) {
|
||||
recordList.addAll(data);
|
||||
}
|
||||
adapter.notifyDataSetChanged();
|
||||
updateEmptyView();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<List<Map<String, Object>>>> call, Throwable t) {
|
||||
swipeRefresh.setRefreshing(false);
|
||||
updateEmptyView();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateEmptyView() {
|
||||
if (recordList.isEmpty()) {
|
||||
tvEmpty.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
tvEmpty.setText("recharge".equals(recordType) ? "暂无充值记录" : "暂无消费记录");
|
||||
} else {
|
||||
tvEmpty.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,305 @@
|
|||
package com.example.livestreaming;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
|
||||
import com.example.livestreaming.net.ApiClient;
|
||||
import com.example.livestreaming.net.ApiResponse;
|
||||
import com.example.livestreaming.net.PageResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
/**
|
||||
* 黑名单管理页面
|
||||
*/
|
||||
public class BlacklistActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "BlacklistActivity";
|
||||
|
||||
private ImageView backButton;
|
||||
private SwipeRefreshLayout swipeRefreshLayout;
|
||||
private RecyclerView recyclerView;
|
||||
private View loadingView;
|
||||
private View emptyView;
|
||||
|
||||
private BlacklistAdapter adapter;
|
||||
private final List<Map<String, Object>> blacklist = new ArrayList<>();
|
||||
private int currentPage = 1;
|
||||
private boolean isLoading = false;
|
||||
private boolean hasMore = true;
|
||||
|
||||
public static void start(Context context) {
|
||||
Intent intent = new Intent(context, BlacklistActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_blacklist);
|
||||
|
||||
initViews();
|
||||
setupRecyclerView();
|
||||
setupSwipeRefresh();
|
||||
loadBlacklist();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
backButton = findViewById(R.id.backButton);
|
||||
swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
|
||||
recyclerView = findViewById(R.id.recyclerView);
|
||||
loadingView = findViewById(R.id.loadingView);
|
||||
emptyView = findViewById(R.id.emptyView);
|
||||
|
||||
backButton.setOnClickListener(v -> finish());
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new BlacklistAdapter(this::handleRemoveFromBlacklist);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||
if (dy > 0 && !isLoading && hasMore) {
|
||||
LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (lm != null) {
|
||||
int visible = lm.getChildCount();
|
||||
int total = lm.getItemCount();
|
||||
int first = lm.findFirstVisibleItemPosition();
|
||||
if ((visible + first) >= total - 2) {
|
||||
loadMore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupSwipeRefresh() {
|
||||
swipeRefreshLayout.setColorSchemeResources(R.color.colorPrimary);
|
||||
swipeRefreshLayout.setOnRefreshListener(() -> {
|
||||
currentPage = 1;
|
||||
hasMore = true;
|
||||
loadBlacklist();
|
||||
});
|
||||
}
|
||||
|
||||
private void loadBlacklist() {
|
||||
if (isLoading) return;
|
||||
isLoading = true;
|
||||
|
||||
if (currentPage == 1) {
|
||||
loadingView.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
emptyView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
ApiClient.getService(this).getMyBlacklist(currentPage, 20)
|
||||
.enqueue(new Callback<ApiResponse<PageResponse<Map<String, Object>>>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<PageResponse<Map<String, Object>>>> call,
|
||||
Response<ApiResponse<PageResponse<Map<String, Object>>>> response) {
|
||||
isLoading = false;
|
||||
loadingView.setVisibility(View.GONE);
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
PageResponse<Map<String, Object>> data = response.body().getData();
|
||||
if (data != null && data.getList() != null) {
|
||||
if (currentPage == 1) {
|
||||
blacklist.clear();
|
||||
}
|
||||
blacklist.addAll(data.getList());
|
||||
adapter.setData(new ArrayList<>(blacklist));
|
||||
hasMore = data.getList().size() >= 20;
|
||||
}
|
||||
} else {
|
||||
String msg = response.body() != null ? response.body().getMessage() : "获取黑名单失败";
|
||||
Toast.makeText(BlacklistActivity.this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
updateEmptyState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<PageResponse<Map<String, Object>>>> call, Throwable t) {
|
||||
isLoading = false;
|
||||
loadingView.setVisibility(View.GONE);
|
||||
swipeRefreshLayout.setRefreshing(false);
|
||||
updateEmptyState();
|
||||
Log.e(TAG, "加载黑名单失败", t);
|
||||
Toast.makeText(BlacklistActivity.this, "网络错误", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMore() {
|
||||
currentPage++;
|
||||
loadBlacklist();
|
||||
}
|
||||
|
||||
private void updateEmptyState() {
|
||||
if (blacklist.isEmpty()) {
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
recyclerView.setVisibility(View.GONE);
|
||||
} else {
|
||||
emptyView.setVisibility(View.GONE);
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleRemoveFromBlacklist(Map<String, Object> item) {
|
||||
Object blockedUserId = item.get("blockedUserId");
|
||||
String nickname = item.get("blockedNickname") != null ? item.get("blockedNickname").toString() : "该用户";
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("移除黑名单")
|
||||
.setMessage("确定要将 " + nickname + " 从黑名单中移除吗?")
|
||||
.setPositiveButton("确定", (dialog, which) -> {
|
||||
if (blockedUserId != null) {
|
||||
removeFromBlacklist(((Number) blockedUserId).intValue(), item);
|
||||
}
|
||||
})
|
||||
.setNegativeButton("取消", null)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void removeFromBlacklist(int targetUserId, Map<String, Object> item) {
|
||||
java.util.Map<String, Object> body = new java.util.HashMap<>();
|
||||
body.put("targetUserId", targetUserId);
|
||||
|
||||
ApiClient.getService(this).removeFromBlacklist(body)
|
||||
.enqueue(new Callback<ApiResponse<Map<String, Object>>>() {
|
||||
@Override
|
||||
public void onResponse(Call<ApiResponse<Map<String, Object>>> call,
|
||||
Response<ApiResponse<Map<String, Object>>> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().isOk()) {
|
||||
blacklist.remove(item);
|
||||
adapter.setData(new ArrayList<>(blacklist));
|
||||
updateEmptyState();
|
||||
Toast.makeText(BlacklistActivity.this, "已移除", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
String msg = response.body() != null ? response.body().getMessage() : "移除失败";
|
||||
Toast.makeText(BlacklistActivity.this, msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ApiResponse<Map<String, Object>>> call, Throwable t) {
|
||||
Log.e(TAG, "移除黑名单失败", t);
|
||||
Toast.makeText(BlacklistActivity.this, "网络错误", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 黑名单列表适配器
|
||||
*/
|
||||
private static class BlacklistAdapter extends RecyclerView.Adapter<BlacklistAdapter.ViewHolder> {
|
||||
|
||||
private List<Map<String, Object>> data = new ArrayList<>();
|
||||
private final OnItemClickListener listener;
|
||||
|
||||
interface OnItemClickListener {
|
||||
void onRemoveClick(Map<String, Object> item);
|
||||
}
|
||||
|
||||
BlacklistAdapter(OnItemClickListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
void setData(List<Map<String, Object>> data) {
|
||||
this.data = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_blacklist, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Map<String, Object> item = data.get(position);
|
||||
holder.bind(item);
|
||||
holder.btnRemove.setOnClickListener(v -> {
|
||||
if (listener != null) listener.onRemoveClick(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView ivAvatar;
|
||||
TextView tvNickname;
|
||||
TextView tvTime;
|
||||
TextView btnRemove;
|
||||
|
||||
ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ivAvatar = itemView.findViewById(R.id.ivAvatar);
|
||||
tvNickname = itemView.findViewById(R.id.tvNickname);
|
||||
tvTime = itemView.findViewById(R.id.tvTime);
|
||||
btnRemove = itemView.findViewById(R.id.btnRemove);
|
||||
}
|
||||
|
||||
void bind(Map<String, Object> item) {
|
||||
String nickname = item.get("blockedNickname") != null ?
|
||||
item.get("blockedNickname").toString() : "未知用户";
|
||||
String avatar = item.get("blockedAvatar") != null ?
|
||||
item.get("blockedAvatar").toString() : "";
|
||||
String createTime = item.get("createTime") != null ?
|
||||
item.get("createTime").toString() : "";
|
||||
|
||||
tvNickname.setText(nickname);
|
||||
|
||||
if (createTime.length() > 10) {
|
||||
tvTime.setText("拉黑于 " + createTime.substring(0, 10));
|
||||
} else {
|
||||
tvTime.setText("拉黑于 " + createTime);
|
||||
}
|
||||
|
||||
if (!avatar.isEmpty()) {
|
||||
Glide.with(itemView.getContext())
|
||||
.load(avatar)
|
||||
.placeholder(R.drawable.ic_default_avatar)
|
||||
.error(R.drawable.ic_default_avatar)
|
||||
.transform(new CircleCrop())
|
||||
.into(ivAvatar);
|
||||
} else {
|
||||
ivAvatar.setImageResource(R.drawable.ic_default_avatar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
android-app/app/src/main/res/drawable/bg_btn_followed.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_btn_followed.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/colorPrimary" />
|
||||
<corners android:radius="14dp" />
|
||||
<padding
|
||||
android:left="12dp"
|
||||
android:top="4dp"
|
||||
android:right="12dp"
|
||||
android:bottom="4dp" />
|
||||
</shape>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="@color/colorPrimary" />
|
||||
<corners android:radius="16dp" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#F5F5F5" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
||||
11
android-app/app/src/main/res/drawable/bg_tag_live.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_tag_live.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tag_live" />
|
||||
<corners android:radius="10dp" />
|
||||
<padding
|
||||
android:left="6dp"
|
||||
android:top="2dp"
|
||||
android:right="6dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
11
android-app/app/src/main/res/drawable/bg_tag_profile.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_tag_profile.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tag_profile" />
|
||||
<corners android:radius="10dp" />
|
||||
<padding
|
||||
android:left="6dp"
|
||||
android:top="2dp"
|
||||
android:right="6dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
11
android-app/app/src/main/res/drawable/bg_tag_room.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_tag_room.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tag_room" />
|
||||
<corners android:radius="10dp" />
|
||||
<padding
|
||||
android:left="6dp"
|
||||
android:top="2dp"
|
||||
android:right="6dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
11
android-app/app/src/main/res/drawable/bg_tag_wish.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_tag_wish.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tag_wish" />
|
||||
<corners android:radius="10dp" />
|
||||
<padding
|
||||
android:left="6dp"
|
||||
android:top="2dp"
|
||||
android:right="6dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
11
android-app/app/src/main/res/drawable/bg_tag_work.xml
Normal file
11
android-app/app/src/main/res/drawable/bg_tag_work.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tag_work" />
|
||||
<corners android:radius="10dp" />
|
||||
<padding
|
||||
android:left="6dp"
|
||||
android:top="2dp"
|
||||
android:right="6dp"
|
||||
android:bottom="2dp" />
|
||||
</shape>
|
||||
108
android-app/app/src/main/res/layout/activity_blacklist.xml
Normal file
108
android-app/app/src/main/res/layout/activity_blacklist.xml
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/background_light">
|
||||
|
||||
<!-- 顶部标题栏 -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:background="@color/white"
|
||||
android:elevation="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/backButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:padding="12dp"
|
||||
android:src="@drawable/ic_arrow_back_24"
|
||||
android:contentDescription="返回"
|
||||
app:tint="@color/text_primary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="黑名单"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<!-- 下拉刷新 -->
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:padding="8dp" />
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<!-- 加载中 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/loadingView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="加载中..."
|
||||
android:textColor="@color/text_secondary" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<LinearLayout
|
||||
android:id="@+id/emptyView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:src="@drawable/ic_people_24"
|
||||
android:alpha="0.3"
|
||||
app:tint="@color/text_hint" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="暂无黑名单用户"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="被加入黑名单的用户将无法与您互动"
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5">
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="8dp"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="暂无记录"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#999999"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
54
android-app/app/src/main/res/layout/item_balance_record.xml
Normal file
54
android-app/app/src/main/res/layout/item_balance_record.xml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginVertical="4dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="15sp"
|
||||
android:textColor="#333333"
|
||||
android:text="交易记录" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#999999"
|
||||
android:text="2024-01-01 12:00" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="#4CAF50"
|
||||
android:text="+100.00" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
72
android-app/app/src/main/res/layout/item_blacklist.xml
Normal file
72
android-app/app/src/main/res/layout/item_blacklist.xml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:layout_marginVertical="4dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="@color/white">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- 用户头像 -->
|
||||
<ImageView
|
||||
android:id="@+id/ivAvatar"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/ic_default_avatar"
|
||||
android:contentDescription="用户头像" />
|
||||
|
||||
<!-- 用户信息 -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_toStartOf="@+id/btnRemove"
|
||||
android:layout_toEndOf="@id/ivAvatar"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvNickname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:text="用户昵称"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="拉黑于 2024-01-01"
|
||||
android:textColor="@color/text_hint"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 移除按钮 -->
|
||||
<TextView
|
||||
android:id="@+id/btnRemove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/bg_button_outline_primary"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:text="移除"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="14sp" />
|
||||
</RelativeLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
102
ban_system_tables.sql
Normal file
102
ban_system_tables.sql
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
-- =====================================================
|
||||
-- 封禁系统数据库表结构
|
||||
-- 包含用户封禁、房间封禁功能
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 用户封禁表(管理员对用户的封禁)
|
||||
CREATE TABLE IF NOT EXISTS `eb_user_ban` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` int(11) NOT NULL COMMENT '被封禁的用户ID',
|
||||
`ban_type` varchar(20) NOT NULL DEFAULT 'permanent' COMMENT '封禁类型:permanent-永久, temporary-临时',
|
||||
`reason` varchar(500) DEFAULT '' COMMENT '封禁原因',
|
||||
`duration_days` int(11) DEFAULT NULL COMMENT '封禁天数(临时封禁时使用)',
|
||||
`expire_time` datetime DEFAULT NULL COMMENT '封禁到期时间(临时封禁时使用)',
|
||||
`operator_id` int(11) DEFAULT 0 COMMENT '操作人ID(管理员)',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:1-生效中, 0-已解除',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_expire_time` (`expire_time`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户封禁记录表';
|
||||
|
||||
-- 2. 房间封禁表(管理员对直播间的封禁)
|
||||
CREATE TABLE IF NOT EXISTS `eb_room_ban` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`room_id` int(11) NOT NULL COMMENT '被封禁的房间ID',
|
||||
`ban_type` varchar(20) NOT NULL DEFAULT 'permanent' COMMENT '封禁类型:permanent-永久, temporary-临时',
|
||||
`reason` varchar(500) DEFAULT '' COMMENT '封禁原因',
|
||||
`duration_days` int(11) DEFAULT NULL COMMENT '封禁天数(临时封禁时使用)',
|
||||
`expire_time` datetime DEFAULT NULL COMMENT '封禁到期时间(临时封禁时使用)',
|
||||
`operator_id` int(11) DEFAULT 0 COMMENT '操作人ID(管理员)',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:1-生效中, 0-已解除',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_room_id` (`room_id`),
|
||||
KEY `idx_status` (`status`),
|
||||
KEY `idx_expire_time` (`expire_time`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房间封禁记录表';
|
||||
|
||||
-- 3. 确保用户黑名单表存在(用户间的拉黑)
|
||||
CREATE TABLE IF NOT EXISTS `eb_user_blacklist` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID(发起拉黑的用户)',
|
||||
`blocked_user_id` int(11) NOT NULL COMMENT '被拉黑的用户ID',
|
||||
`blocker_nickname` varchar(100) DEFAULT '' COMMENT '拉黑者昵称',
|
||||
`blocker_avatar` varchar(500) DEFAULT '' COMMENT '拉黑者头像',
|
||||
`blocked_nickname` varchar(100) DEFAULT '' COMMENT '被拉黑者昵称',
|
||||
`blocked_avatar` varchar(500) DEFAULT '' COMMENT '被拉黑者头像',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_blocked` (`user_id`, `blocked_user_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_blocked_user_id` (`blocked_user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户黑名单表';
|
||||
|
||||
-- 4. 确保房间黑名单表存在(直播间对用户的拉黑)
|
||||
CREATE TABLE IF NOT EXISTS `eb_room_blacklist` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`room_id` int(11) NOT NULL COMMENT '房间ID',
|
||||
`room_name` varchar(200) DEFAULT '' COMMENT '房间名称',
|
||||
`blocked_user_id` int(11) NOT NULL COMMENT '被拉黑的用户ID',
|
||||
`blocked_user_nickname` varchar(100) DEFAULT '' COMMENT '被拉黑用户昵称',
|
||||
`blocked_user_avatar` varchar(500) DEFAULT '' COMMENT '被拉黑用户头像',
|
||||
`reason` varchar(500) DEFAULT '' COMMENT '拉黑原因',
|
||||
`operator_id` int(11) DEFAULT 0 COMMENT '操作人ID(主播或管理员)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_room_user` (`room_id`, `blocked_user_id`),
|
||||
KEY `idx_room_id` (`room_id`),
|
||||
KEY `idx_blocked_user_id` (`blocked_user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房间黑名单表';
|
||||
|
||||
-- 5. 添加测试数据
|
||||
-- 用户封禁测试数据
|
||||
INSERT IGNORE INTO eb_user_ban (user_id, ban_type, reason, duration_days, operator_id, status) VALUES
|
||||
(999, 'permanent', '违规发布不良内容', NULL, 1, 1),
|
||||
(998, 'temporary', '多次发送垃圾信息', 7, 1, 1);
|
||||
|
||||
-- 更新临时封禁的到期时间
|
||||
UPDATE eb_user_ban SET expire_time = DATE_ADD(create_time, INTERVAL duration_days DAY)
|
||||
WHERE ban_type = 'temporary' AND duration_days IS NOT NULL AND expire_time IS NULL;
|
||||
|
||||
-- 6. 验证表结构
|
||||
SELECT '=== 封禁系统表结构 ===' as info;
|
||||
SHOW TABLES LIKE 'eb_%ban%';
|
||||
SHOW TABLES LIKE 'eb_%blacklist%';
|
||||
|
||||
SELECT '=== 用户封禁记录 ===' as info;
|
||||
SELECT * FROM eb_user_ban ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
SELECT '=== 房间封禁记录 ===' as info;
|
||||
SELECT * FROM eb_room_ban ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
SELECT '=== 用户黑名单 ===' as info;
|
||||
SELECT * FROM eb_user_blacklist ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
SELECT '=== 房间黑名单 ===' as info;
|
||||
SELECT * FROM eb_room_blacklist ORDER BY create_time DESC LIMIT 5;
|
||||
43
check_and_fix_records.sql
Normal file
43
check_and_fix_records.sql
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
-- =====================================================
|
||||
-- 检查并修复"我的记录"数据问题
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 首先找到当前登录用户的真实ID
|
||||
-- 从截图看用户ID是 24187196,但这可能是显示ID,需要找到数据库中的真实uid
|
||||
SELECT uid, id, nickname, phone, avatar
|
||||
FROM eb_user
|
||||
WHERE nickname LIKE '%道玄%'
|
||||
OR uid = 24187196
|
||||
OR id = 121
|
||||
OR id = 43
|
||||
ORDER BY id DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 2. 检查观看历史表
|
||||
SELECT '=== eb_view_history 表数据 ===' as info;
|
||||
SELECT * FROM eb_view_history ORDER BY update_time DESC LIMIT 20;
|
||||
|
||||
-- 3. 检查点赞记录表
|
||||
SELECT '=== eb_live_room_like 表数据 ===' as info;
|
||||
SELECT * FROM eb_live_room_like ORDER BY create_time DESC LIMIT 20;
|
||||
|
||||
-- 4. 检查关注记录表
|
||||
SELECT '=== eb_follow_record 表数据 ===' as info;
|
||||
SELECT * FROM eb_follow_record ORDER BY create_time DESC LIMIT 20;
|
||||
|
||||
-- 5. 检查收藏表(如果存在)
|
||||
SELECT '=== 检查收藏相关表 ===' as info;
|
||||
SHOW TABLES LIKE '%collect%';
|
||||
SHOW TABLES LIKE '%favorite%';
|
||||
|
||||
-- 6. 查看所有用户的活动数据统计
|
||||
SELECT '=== 各用户活动数据统计 ===' as info;
|
||||
SELECT
|
||||
u.uid,
|
||||
u.nickname,
|
||||
(SELECT COUNT(*) FROM eb_view_history vh WHERE vh.user_id = u.uid) as 观看历史,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like lrl WHERE lrl.user_id = u.uid) as 点赞数,
|
||||
(SELECT COUNT(*) FROM eb_follow_record fr WHERE fr.follower_id = u.uid) as 关注数
|
||||
FROM eb_user u
|
||||
WHERE u.uid IN (121, 43, 24187196)
|
||||
OR u.nickname LIKE '%道玄%';
|
||||
24
check_ban_menu_permission.sql
Normal file
24
check_ban_menu_permission.sql
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
-- 检查封禁菜单的完整配置
|
||||
SELECT '=== 封禁菜单配置 ===' as info;
|
||||
SELECT id, pid, `name`, perms, component, menu_type, sort, is_show, is_delte
|
||||
FROM eb_system_menu
|
||||
WHERE `name` LIKE '%封禁%';
|
||||
|
||||
-- 检查管理员角色权限
|
||||
SELECT '=== 管理员角色 ===' as info;
|
||||
SELECT * FROM eb_system_role WHERE id = 1;
|
||||
|
||||
-- 检查角色菜单关联
|
||||
SELECT '=== 角色菜单关联 ===' as info;
|
||||
SELECT * FROM eb_system_role_menu WHERE rid = 1 ORDER BY menu_id DESC LIMIT 20;
|
||||
|
||||
-- 为管理员角色添加封禁菜单权限
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id)
|
||||
SELECT 1, id FROM eb_system_menu WHERE `name` IN ('用户封禁', '房间封禁');
|
||||
|
||||
-- 验证添加结果
|
||||
SELECT '=== 添加权限后 ===' as info;
|
||||
SELECT rm.rid, rm.menu_id, m.name, m.component
|
||||
FROM eb_system_role_menu rm
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.name LIKE '%封禁%';
|
||||
26
check_blacklist_menu.sql
Normal file
26
check_blacklist_menu.sql
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
-- 检查拉黑菜单状态
|
||||
|
||||
-- 1. 查看社交互动菜单ID
|
||||
SELECT id, pid, `name`, component, menu_type, is_show FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 2. 查看社交互动下所有子菜单(包括隐藏的)
|
||||
SELECT id, pid, `name`, component, sort, is_show, is_delete
|
||||
FROM eb_system_menu
|
||||
WHERE pid = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' LIMIT 1)
|
||||
ORDER BY sort;
|
||||
|
||||
-- 3. 查看拉黑菜单是否存在
|
||||
SELECT id, pid, `name`, component, is_show, is_delete
|
||||
FROM eb_system_menu
|
||||
WHERE `name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 4. 查看角色权限
|
||||
SELECT rm.rid, rm.menu_id, m.`name`
|
||||
FROM eb_system_role_menu rm
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.`name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 5. 查看群组管理的配置作为参考
|
||||
SELECT id, pid, `name`, component, sort, is_show, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE `name` = '群组管理';
|
||||
29
check_blacklist_menu_v2.sql
Normal file
29
check_blacklist_menu_v2.sql
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
-- 检查拉黑菜单状态 (修正版)
|
||||
|
||||
-- 1. 查看社交互动菜单ID
|
||||
SELECT id, pid, `name`, component, menu_type, is_show FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 2. 查看社交互动下所有子菜单
|
||||
SELECT id, pid, `name`, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE pid = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' LIMIT 1)
|
||||
ORDER BY sort;
|
||||
|
||||
-- 3. 查看拉黑菜单是否存在
|
||||
SELECT id, pid, `name`, component, is_show, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE `name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 4. 查看角色权限
|
||||
SELECT rm.rid, rm.menu_id, m.`name`
|
||||
FROM eb_system_role_menu rm
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.`name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 5. 查看群组管理的配置作为参考
|
||||
SELECT id, pid, `name`, component, sort, is_show, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE `name` = '群组管理';
|
||||
|
||||
-- 6. 查看表结构
|
||||
DESC eb_system_menu;
|
||||
19
check_follow_status_type.sql
Normal file
19
check_follow_status_type.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
-- 检查 eb_follow_record 表结构
|
||||
DESCRIBE eb_follow_record;
|
||||
|
||||
-- 检查 follow_status 字段的实际值
|
||||
SELECT DISTINCT follow_status, COUNT(*) as cnt
|
||||
FROM eb_follow_record
|
||||
GROUP BY follow_status;
|
||||
|
||||
-- 检查用户121的关注记录
|
||||
SELECT * FROM eb_follow_record WHERE follower_id = 121;
|
||||
|
||||
-- 测试SQL查询
|
||||
SELECT fr.id, fr.followed_id as followedId, fr.followed_nickname as followedNickname,
|
||||
u.avatar as followedAvatar, u.phone, fr.follow_status as followStatus,
|
||||
fr.create_time as createTime
|
||||
FROM eb_follow_record fr
|
||||
LEFT JOIN eb_user u ON fr.followed_id = u.uid
|
||||
WHERE fr.follower_id = 121 AND (fr.follow_status = 1 OR fr.follow_status = '关注')
|
||||
ORDER BY fr.create_time DESC LIMIT 10 OFFSET 0;
|
||||
6
check_table_structure.sql
Normal file
6
check_table_structure.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-- 检查各表结构
|
||||
DESCRIBE eb_live_room_like;
|
||||
DESCRIBE eb_works_relation;
|
||||
DESCRIBE eb_follow_record;
|
||||
DESCRIBE eb_search_history;
|
||||
DESCRIBE eb_friend;
|
||||
21
check_tables_for_121.sql
Normal file
21
check_tables_for_121.sql
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-- 检查关键表的数据情况
|
||||
|
||||
-- 1. 检查直播间点赞表
|
||||
SELECT '=== eb_live_room_like ===' as 表名;
|
||||
SELECT * FROM eb_live_room_like WHERE user_id = 121;
|
||||
|
||||
-- 2. 检查作品关系表
|
||||
SELECT '=== eb_works_relation ===' as 表名;
|
||||
SELECT * FROM eb_works_relation WHERE uid = 121;
|
||||
|
||||
-- 3. 检查关注记录表
|
||||
SELECT '=== eb_follow_record ===' as 表名;
|
||||
SELECT * FROM eb_follow_record WHERE follower_id = 121;
|
||||
|
||||
-- 4. 检查直播间表是否存在
|
||||
SELECT '=== eb_room / eb_live_room ===' as 表名;
|
||||
SHOW TABLES LIKE '%room%';
|
||||
|
||||
-- 5. 检查作品表
|
||||
SELECT '=== eb_works ===' as 表名;
|
||||
SELECT id, title, user_id FROM eb_works LIMIT 5;
|
||||
33
check_user_121_data.sql
Normal file
33
check_user_121_data.sql
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
-- =====================================================
|
||||
-- 检查用户"道玄"(ID: 121)的测试数据
|
||||
-- =====================================================
|
||||
|
||||
-- 检查用户基本信息
|
||||
SELECT uid, nickname, phone, now_money, integral, experience
|
||||
FROM eb_user WHERE uid = 121;
|
||||
|
||||
-- 检查各表数据统计
|
||||
SELECT '观看历史' as 类型, COUNT(*) as 数量 FROM eb_watch_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '直播间点赞', COUNT(*) FROM eb_live_room_like WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE follow_uid = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
-- 检查礼物记录表是否存在
|
||||
SELECT COUNT(*) as 礼物打赏记录 FROM eb_gift_record WHERE uid = 121;
|
||||
|
||||
-- 检查私聊会话
|
||||
SELECT COUNT(*) as 私聊会话数 FROM eb_conversation WHERE user1_id = 121 OR user2_id = 121;
|
||||
|
||||
-- 检查充值记录
|
||||
SELECT COUNT(*) as 充值记录数 FROM eb_recharge_order WHERE uid = 121;
|
||||
16
check_user_records.sql
Normal file
16
check_user_records.sql
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
-- 检查用户"道玄"(ID: 24187196 或 uid) 的活动记录数据
|
||||
-- 先查找用户ID
|
||||
SELECT uid, nickname, phone FROM eb_user WHERE nickname LIKE '%道玄%' OR uid = 24187196 LIMIT 5;
|
||||
|
||||
-- 查看观看历史表结构
|
||||
SHOW TABLES LIKE '%view%';
|
||||
SHOW TABLES LIKE '%history%';
|
||||
|
||||
-- 查看点赞表
|
||||
SHOW TABLES LIKE '%like%';
|
||||
|
||||
-- 查看收藏表
|
||||
SHOW TABLES LIKE '%collect%';
|
||||
|
||||
-- 查看关注表
|
||||
SHOW TABLES LIKE '%follow%';
|
||||
5
check_working_menu.sql
Normal file
5
check_working_menu.sql
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
-- 查看正常工作的菜单配置(如黑名单)
|
||||
SELECT id, pid, `name`, perms, component, menu_type, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE `name` IN ('房间拉黑', '用户拉黑', '用户封禁', '房间封禁', '用户列表', '私聊管理')
|
||||
ORDER BY id;
|
||||
22
complete_test_data_121.sql
Normal file
22
complete_test_data_121.sql
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)创建完整测试数据
|
||||
-- 确保与后端查询逻辑一致
|
||||
-- =====================================================
|
||||
|
||||
-- 先检查现有数据
|
||||
SELECT '=== 检查现有数据 ===' as 信息;
|
||||
|
||||
-- 1. 检查直播间表名和结构
|
||||
SHOW TABLES LIKE '%room%';
|
||||
|
||||
-- 2. 检查作品表
|
||||
SELECT COUNT(*) as 作品数量 FROM eb_works;
|
||||
|
||||
-- 3. 检查用户表中的测试用户
|
||||
SELECT uid, nickname FROM eb_user WHERE uid IN (100, 101, 102, 103, 104, 105, 121) LIMIT 10;
|
||||
|
||||
-- =====================================================
|
||||
-- 创建测试直播间数据(如果不存在)
|
||||
-- =====================================================
|
||||
-- 先检查直播间表结构
|
||||
DESCRIBE eb_room;
|
||||
119
complete_user_activity_data.sql
Normal file
119
complete_user_activity_data.sql
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
-- =====================================================
|
||||
-- 完整的用户活动数据初始化脚本
|
||||
-- 确保移动端"我的记录"功能正常显示
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 确保所有必要的表存在
|
||||
-- =====================================================
|
||||
|
||||
-- 观看历史表
|
||||
CREATE TABLE IF NOT EXISTS `eb_view_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`target_type` varchar(20) NOT NULL COMMENT '目标类型:room-直播间, work-作品, profile-用户主页',
|
||||
`target_id` varchar(50) NOT NULL COMMENT '目标ID',
|
||||
`target_title` varchar(255) DEFAULT NULL COMMENT '目标标题',
|
||||
`view_duration` int(11) DEFAULT 0 COMMENT '观看时长(秒)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_target` (`target_type`, `target_id`),
|
||||
KEY `idx_update_time` (`update_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='观看历史记录表';
|
||||
|
||||
-- 直播间点赞表
|
||||
CREATE TABLE IF NOT EXISTS `eb_live_room_like` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`room_id` varchar(50) NOT NULL COMMENT '直播间ID',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_room` (`user_id`, `room_id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_room_id` (`room_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='直播间点赞记录表';
|
||||
|
||||
-- 心愿点赞表
|
||||
CREATE TABLE IF NOT EXISTS `eb_wish_like` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`wish_id` bigint(20) NOT NULL COMMENT '心愿ID',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_user_wish` (`user_id`, `wish_id`),
|
||||
KEY `idx_user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='心愿点赞记录表';
|
||||
|
||||
-- 搜索历史表
|
||||
CREATE TABLE IF NOT EXISTS `eb_search_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`keyword` varchar(100) NOT NULL COMMENT '搜索关键词',
|
||||
`search_type` varchar(20) DEFAULT 'all' COMMENT '搜索类型',
|
||||
`is_deleted` tinyint(1) DEFAULT 0 COMMENT '是否删除',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_keyword` (`keyword`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='搜索历史记录表';
|
||||
|
||||
-- 2. 为用户121(道玄)添加完整测试数据
|
||||
-- =====================================================
|
||||
|
||||
SET @USER_ID = 121;
|
||||
|
||||
-- 清除旧数据(可选)
|
||||
-- DELETE FROM eb_view_history WHERE user_id = @USER_ID;
|
||||
-- DELETE FROM eb_live_room_like WHERE user_id = @USER_ID;
|
||||
|
||||
-- 添加观看历史
|
||||
INSERT IGNORE INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time) VALUES
|
||||
(@USER_ID, 'room', '1', '欢乐游戏直播', 1800, NOW() - INTERVAL 1 HOUR, NOW() - INTERVAL 1 HOUR),
|
||||
(@USER_ID, 'room', '2', '音乐分享会', 2400, NOW() - INTERVAL 2 HOUR, NOW() - INTERVAL 2 HOUR),
|
||||
(@USER_ID, 'room', '3', '户外探险', 1200, NOW() - INTERVAL 3 HOUR, NOW() - INTERVAL 3 HOUR),
|
||||
(@USER_ID, 'room', '4', '美食制作教程', 3600, NOW() - INTERVAL 4 HOUR, NOW() - INTERVAL 4 HOUR),
|
||||
(@USER_ID, 'room', '5', '编程技术分享', 5400, NOW() - INTERVAL 5 HOUR, NOW() - INTERVAL 5 HOUR);
|
||||
|
||||
-- 添加直播间点赞
|
||||
INSERT IGNORE INTO eb_live_room_like (user_id, room_id, create_time) VALUES
|
||||
(@USER_ID, '1', NOW() - INTERVAL 1 HOUR),
|
||||
(@USER_ID, '2', NOW() - INTERVAL 2 HOUR),
|
||||
(@USER_ID, '3', NOW() - INTERVAL 3 HOUR);
|
||||
|
||||
-- 3. 验证数据
|
||||
-- =====================================================
|
||||
|
||||
SELECT '=== 用户121的观看历史 ===' as info;
|
||||
SELECT id, user_id, target_type, target_id, target_title, view_duration,
|
||||
DATE_FORMAT(update_time, '%Y-%m-%d %H:%i:%s') as update_time
|
||||
FROM eb_view_history
|
||||
WHERE user_id = @USER_ID
|
||||
ORDER BY update_time DESC;
|
||||
|
||||
SELECT '=== 用户121的直播间点赞 ===' as info;
|
||||
SELECT rl.id, rl.user_id, rl.room_id, lr.title as room_title,
|
||||
DATE_FORMAT(rl.create_time, '%Y-%m-%d %H:%i:%s') as create_time
|
||||
FROM eb_live_room_like rl
|
||||
LEFT JOIN eb_live_room lr ON rl.room_id = lr.id
|
||||
WHERE rl.user_id = @USER_ID;
|
||||
|
||||
SELECT '=== 用户121的关注记录 ===' as info;
|
||||
SELECT fr.id, fr.follower_id, fr.followed_id, fr.followed_nickname, fr.follow_status,
|
||||
DATE_FORMAT(fr.create_time, '%Y-%m-%d %H:%i:%s') as create_time
|
||||
FROM eb_follow_record fr
|
||||
WHERE fr.follower_id = @USER_ID AND (fr.follow_status = 1 OR fr.follow_status = '关注');
|
||||
|
||||
SELECT '=== 用户121的收藏作品 ===' as info;
|
||||
SELECT wr.id, wr.uid, wr.works_id, w.title,
|
||||
DATE_FORMAT(wr.create_time, '%Y-%m-%d %H:%i:%s') as create_time
|
||||
FROM eb_works_relation wr
|
||||
LEFT JOIN eb_works w ON wr.works_id = w.id
|
||||
WHERE wr.uid = @USER_ID AND wr.type = 2;
|
||||
|
||||
SELECT '=== 数据汇总 ===' as info;
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM eb_view_history WHERE user_id = @USER_ID) as 观看历史数,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like WHERE user_id = @USER_ID) as 直播间点赞数,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE follower_id = @USER_ID AND (follow_status = 1 OR follow_status = '关注')) as 关注数,
|
||||
(SELECT COUNT(*) FROM eb_works_relation WHERE uid = @USER_ID AND type = 2) as 收藏作品数;
|
||||
159
create_tables_and_data_121.sql
Normal file
159
create_tables_and_data_121.sql
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)创建缺失的表并添加测试数据
|
||||
-- =====================================================
|
||||
|
||||
-- =====================================================
|
||||
-- 1. 创建观看历史表 (eb_watch_history)
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS `eb_watch_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`uid` int(11) NOT NULL COMMENT '用户ID',
|
||||
`target_type` varchar(20) NOT NULL COMMENT '目标类型:room-直播间, work-作品',
|
||||
`target_id` varchar(50) NOT NULL COMMENT '目标ID',
|
||||
`target_title` varchar(200) DEFAULT NULL COMMENT '目标标题',
|
||||
`target_cover` varchar(500) DEFAULT NULL COMMENT '目标封面',
|
||||
`duration` int(11) DEFAULT 0 COMMENT '观看时长(秒)',
|
||||
`watch_time` datetime DEFAULT NULL COMMENT '观看时间',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_uid` (`uid`),
|
||||
KEY `idx_target` (`target_type`, `target_id`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='观看历史表';
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 插入观看历史数据
|
||||
-- =====================================================
|
||||
INSERT INTO eb_watch_history (uid, target_type, target_id, target_title, target_cover, duration, watch_time, create_time) VALUES
|
||||
(121, 'room', '1', '欢乐游戏直播', 'https://example.com/cover1.jpg', 1800, '2026-01-03 20:30:00', '2026-01-03 20:30:00'),
|
||||
(121, 'room', '2', '音乐分享会', 'https://example.com/cover2.jpg', 2400, '2026-01-03 21:00:00', '2026-01-03 21:00:00'),
|
||||
(121, 'room', '3', '户外探险直播', 'https://example.com/cover3.jpg', 900, '2026-01-02 19:00:00', '2026-01-02 19:00:00'),
|
||||
(121, 'room', '4', '美食制作教程', 'https://example.com/cover4.jpg', 3600, '2026-01-02 12:00:00', '2026-01-02 12:00:00'),
|
||||
(121, 'room', '5', '编程技术分享', 'https://example.com/cover5.jpg', 5400, '2026-01-01 14:00:00', '2026-01-01 14:00:00'),
|
||||
(121, 'work', '1', '搞笑短视频合集', 'https://example.com/work1.jpg', 180, '2026-01-03 22:00:00', '2026-01-03 22:00:00'),
|
||||
(121, 'work', '2', '旅行Vlog-云南之旅', 'https://example.com/work2.jpg', 600, '2026-01-03 18:00:00', '2026-01-03 18:00:00'),
|
||||
(121, 'work', '3', '美妆教程分享', 'https://example.com/work3.jpg', 420, '2026-01-02 16:00:00', '2026-01-02 16:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 检查并创建直播间点赞表
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS `eb_live_room_like` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`uid` int(11) NOT NULL COMMENT '用户ID',
|
||||
`room_id` int(11) NOT NULL COMMENT '直播间ID',
|
||||
`like_count` int(11) DEFAULT 1 COMMENT '点赞次数',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_uid_room` (`uid`, `room_id`),
|
||||
KEY `idx_room_id` (`room_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='直播间点赞表';
|
||||
|
||||
-- 插入直播间点赞数据
|
||||
INSERT IGNORE INTO eb_live_room_like (uid, room_id, like_count, create_time) VALUES
|
||||
(121, 1, 15, '2026-01-03 20:35:00'),
|
||||
(121, 2, 28, '2026-01-03 21:15:00'),
|
||||
(121, 3, 8, '2026-01-02 19:10:00'),
|
||||
(121, 4, 42, '2026-01-02 12:30:00'),
|
||||
(121, 5, 20, '2026-01-01 14:30:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 4. 插入作品关系数据(点赞和收藏)
|
||||
-- =====================================================
|
||||
-- 点赞作品 (type=1 或 type='like')
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 1, '2026-01-03 22:05:00'),
|
||||
(121, 2, 1, '2026-01-03 18:10:00'),
|
||||
(121, 3, 1, '2026-01-02 16:15:00'),
|
||||
(121, 4, 1, '2026-01-01 20:00:00'),
|
||||
(121, 5, 1, '2026-01-01 15:00:00');
|
||||
|
||||
-- 收藏作品 (type=2 或 type='collect')
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 2, '2026-01-03 22:06:00'),
|
||||
(121, 2, 2, '2026-01-03 18:12:00'),
|
||||
(121, 6, 2, '2026-01-02 10:00:00'),
|
||||
(121, 7, 2, '2026-01-01 11:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 5. 插入关注记录
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(121, 100, '2026-01-03 20:00:00'),
|
||||
(121, 101, '2026-01-03 15:00:00'),
|
||||
(121, 102, '2026-01-02 18:00:00'),
|
||||
(121, 103, '2026-01-02 12:00:00'),
|
||||
(121, 104, '2026-01-01 20:00:00'),
|
||||
(121, 105, '2026-01-01 10:00:00');
|
||||
|
||||
-- 被关注记录
|
||||
INSERT IGNORE INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(100, 121, '2026-01-03 21:00:00'),
|
||||
(101, 121, '2026-01-03 16:00:00'),
|
||||
(106, 121, '2026-01-02 20:00:00'),
|
||||
(107, 121, '2026-01-02 14:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 6. 插入搜索历史
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_search_history (uid, keyword, search_type, search_count, create_time) VALUES
|
||||
(121, '游戏直播', 1, 3, '2026-01-03 20:00:00'),
|
||||
(121, '音乐', 1, 2, '2026-01-03 19:00:00'),
|
||||
(121, '美食教程', 2, 1, '2026-01-02 11:00:00'),
|
||||
(121, '旅行Vlog', 2, 2, '2026-01-02 10:00:00'),
|
||||
(121, '编程学习', 1, 4, '2026-01-01 13:00:00'),
|
||||
(121, '户外运动', 1, 1, '2026-01-01 09:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 7. 创建并插入好友关系
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS `eb_friend` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`uid` int(11) NOT NULL COMMENT '用户ID',
|
||||
`friend_uid` int(11) NOT NULL COMMENT '好友用户ID',
|
||||
`remark` varchar(50) DEFAULT NULL COMMENT '备注名',
|
||||
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_uid_friend` (`uid`, `friend_uid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='好友关系表';
|
||||
|
||||
INSERT IGNORE INTO eb_friend (uid, friend_uid, remark, create_time) VALUES
|
||||
(121, 100, '游戏主播', '2026-01-03 21:35:00'),
|
||||
(121, 101, '音乐达人', '2026-01-03 16:10:00'),
|
||||
(100, 121, '道玄', '2026-01-03 21:35:00'),
|
||||
(101, 121, '道玄', '2026-01-03 16:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 8. 更新用户余额和积分
|
||||
-- =====================================================
|
||||
UPDATE eb_user SET
|
||||
now_money = 500.00,
|
||||
integral = 1200,
|
||||
experience = 350
|
||||
WHERE uid = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 9. 验证数据
|
||||
-- =====================================================
|
||||
SELECT '=== 用户道玄(ID:121)数据统计 ===' as 信息;
|
||||
|
||||
SELECT '观看历史' as 类型, COUNT(*) as 数量 FROM eb_watch_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '直播间点赞', COUNT(*) FROM eb_live_room_like WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE follow_uid = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
-- 检查用户余额
|
||||
SELECT uid, nickname, now_money as 余额, integral as 积分, experience as 经验
|
||||
FROM eb_user WHERE uid = 121;
|
||||
|
||||
SELECT '数据插入完成!' as 结果;
|
||||
12
create_test_rooms_works.sql
Normal file
12
create_test_rooms_works.sql
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-- =====================================================
|
||||
-- 创建测试直播间和作品数据
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 检查 eb_live_room 表结构
|
||||
DESCRIBE eb_live_room;
|
||||
|
||||
-- 2. 检查现有直播间
|
||||
SELECT id, room_title, owner_nickname, status FROM eb_live_room LIMIT 10;
|
||||
|
||||
-- 3. 检查 eb_works 表结构
|
||||
DESCRIBE eb_works;
|
||||
23
debug_menu_structure.sql
Normal file
23
debug_menu_structure.sql
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-- 查看黑名单菜单的完整层级结构
|
||||
-- 黑名单管理 (id=569) 的父菜单是什么?
|
||||
|
||||
SELECT id, pid, `name`, component, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE id = 569;
|
||||
|
||||
-- 查看 pid=0 的顶级菜单
|
||||
SELECT id, pid, `name`, component, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE pid = 0 AND is_show = 1
|
||||
ORDER BY sort;
|
||||
|
||||
-- 查看用户管理 (id=674) 的子菜单
|
||||
SELECT id, pid, `name`, component, menu_type, sort
|
||||
FROM eb_system_menu
|
||||
WHERE pid = 674
|
||||
ORDER BY sort;
|
||||
|
||||
-- 查看封禁菜单的父菜单
|
||||
SELECT id, pid, `name`, component, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE id = 674;
|
||||
38
debug_user_token.sql
Normal file
38
debug_user_token.sql
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
-- 调试用户Token和数据问题
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 确认用户"道玄"的真实uid
|
||||
SELECT uid, nickname, phone, avatar, status
|
||||
FROM eb_user
|
||||
WHERE nickname LIKE '%道玄%';
|
||||
|
||||
-- 2. 检查该用户的观看历史数据
|
||||
SELECT vh.*, lr.title as room_title
|
||||
FROM eb_view_history vh
|
||||
LEFT JOIN eb_live_room lr ON vh.target_id = lr.id AND vh.target_type = 'room'
|
||||
WHERE vh.user_id = 121
|
||||
ORDER BY vh.update_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 3. 检查该用户的点赞数据
|
||||
SELECT lrl.*, lr.title as room_title
|
||||
FROM eb_live_room_like lrl
|
||||
LEFT JOIN eb_live_room lr ON lrl.room_id = lr.id
|
||||
WHERE lrl.user_id = 121
|
||||
ORDER BY lrl.create_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 4. 检查该用户的关注数据
|
||||
SELECT fr.*, u.nickname as followed_nickname
|
||||
FROM eb_follow_record fr
|
||||
LEFT JOIN eb_user u ON fr.followed_id = u.uid
|
||||
WHERE fr.follower_id = 121
|
||||
ORDER BY fr.create_time DESC
|
||||
LIMIT 10;
|
||||
|
||||
-- 5. 汇总
|
||||
SELECT
|
||||
'道玄(uid=121)' as 用户,
|
||||
(SELECT COUNT(*) FROM eb_view_history WHERE user_id = 121) as 观看历史数,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like WHERE user_id = 121) as 点赞数,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE follower_id = 121) as 关注数;
|
||||
50
deploy_ban_system.bat
Normal file
50
deploy_ban_system.bat
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 部署封禁系统功能
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo 步骤1: 编译后端项目...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -pl crmeb-front,crmeb-admin -am
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [错误] 编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [成功] 编译完成!
|
||||
|
||||
echo.
|
||||
echo 步骤2: 上传JAR包到服务器...
|
||||
scp crmeb-front\target\crmeb-front.jar root@1.15.149.240:/www/wwwroot/zhibo/
|
||||
scp crmeb-admin\target\crmeb-admin.jar root@1.15.149.240:/www/wwwroot/zhibo/
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [错误] 上传失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [成功] 上传完成!
|
||||
|
||||
echo.
|
||||
echo 步骤3: 重启后端服务...
|
||||
ssh root@1.15.149.240 "cd /www/wwwroot/zhibo && ./restart.sh"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 后端部署完成!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 请执行以下操作:
|
||||
echo 1. 在MySQL中执行 ban_system_tables.sql 创建数据库表
|
||||
echo 2. 在MySQL中执行 add_ban_menus.sql 添加菜单
|
||||
echo 3. 重新编译并部署管理后台前端
|
||||
echo 4. 重新编译Android App
|
||||
echo.
|
||||
pause
|
||||
64
deploy_complete.bat
Normal file
64
deploy_complete.bat
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
@echo off
|
||||
chcp 65001
|
||||
echo ========================================
|
||||
echo 完整部署 - 用户活动记录功能
|
||||
echo ========================================
|
||||
|
||||
cd /d %~dp0
|
||||
|
||||
echo.
|
||||
echo [1/4] 编译后端项目...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -q
|
||||
if %errorlevel% neq 0 (
|
||||
echo 后端编译失败!请检查代码错误。
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo 后端编译成功!
|
||||
|
||||
echo.
|
||||
echo [2/4] 编译前端管理端...
|
||||
cd ..\admin
|
||||
call npm install --silent 2>nul
|
||||
call npm run build
|
||||
if %errorlevel% neq 0 (
|
||||
echo 前端编译警告,可能需要手动检查。
|
||||
)
|
||||
echo 前端编译完成!
|
||||
|
||||
cd ..\..
|
||||
|
||||
echo.
|
||||
echo [3/4] 文件位置
|
||||
echo ========================================
|
||||
echo 后端JAR: Zhibo\zhibo-h\crmeb-admin\target\crmeb-admin-*.jar
|
||||
echo 前端dist: Zhibo\admin\dist\
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [4/4] 部署说明
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 管理端API端点:
|
||||
echo - 关注记录: GET /api/admin/user/activity/follow?userId=xxx
|
||||
echo - 点赞记录: GET /api/admin/user/activity/like?userId=xxx
|
||||
echo - 查看历史: GET /api/admin/user/activity/view?userId=xxx
|
||||
echo - 收藏记录: GET /api/admin/user/activity/collect?userId=xxx
|
||||
echo.
|
||||
echo 移动端API端点:
|
||||
echo - 记录观看: POST /api/front/activity/view/record
|
||||
echo - 观看历史: GET /api/front/activity/view/history
|
||||
echo - 点赞记录: GET /api/front/activity/like/records
|
||||
echo - 关注记录: GET /api/front/activity/follow/records
|
||||
echo - 收藏记录: GET /api/front/activity/collect/works
|
||||
echo.
|
||||
echo 部署步骤:
|
||||
echo 1. 停止后端服务
|
||||
echo 2. 上传新的JAR文件到服务器
|
||||
echo 3. 重启后端服务
|
||||
echo 4. 上传前端dist目录到服务器
|
||||
echo 5. 刷新浏览器缓存 (Ctrl+F5)
|
||||
echo ========================================
|
||||
|
||||
pause
|
||||
49
deploy_my_records_fix.bat
Normal file
49
deploy_my_records_fix.bat
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 部署"我的记录"功能修复
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo 步骤1: 编译后端项目...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -pl crmeb-front -am
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [错误] 编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [成功] 编译完成!
|
||||
|
||||
echo.
|
||||
echo 步骤2: 上传JAR包到服务器...
|
||||
scp crmeb-front\target\crmeb-front.jar root@1.15.149.240:/www/wwwroot/zhibo/
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo [错误] 上传失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [成功] 上传完成!
|
||||
|
||||
echo.
|
||||
echo 步骤3: 重启后端服务...
|
||||
ssh root@1.15.149.240 "cd /www/wwwroot/zhibo && ./restart.sh"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 请执行以下操作验证:
|
||||
echo 1. 在MySQL中执行 complete_user_activity_data.sql 添加测试数据
|
||||
echo 2. 在App上退出登录,重新登录
|
||||
echo 3. 进入"我的记录"页面查看数据
|
||||
echo 4. 查看服务器日志: tail -f /www/wwwroot/zhibo/logs/crmeb-front.log ^| grep "API"
|
||||
echo.
|
||||
pause
|
||||
52
deploy_records_debug.bat
Normal file
52
deploy_records_debug.bat
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 部署"我的记录"调试版本
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [1/3] 编译后端项目...
|
||||
cd /d "%~dp0Zhibo\zhibo-h"
|
||||
call mvn clean package -DskipTests -pl crmeb-front -am
|
||||
if errorlevel 1 (
|
||||
echo 后端编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [2/3] 重启后端服务...
|
||||
echo 请手动重启后端服务,或使用以下命令:
|
||||
echo java -jar crmeb-front/target/crmeb-front.jar
|
||||
echo.
|
||||
|
||||
echo [3/3] 编译Android应用...
|
||||
cd /d "%~dp0android-app"
|
||||
call gradlew assembleDebug
|
||||
if errorlevel 1 (
|
||||
echo Android编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 调试步骤:
|
||||
echo 1. 重启后端服务
|
||||
echo 2. 安装新的APK到设备/模拟器
|
||||
echo 3. 登录应用
|
||||
echo 4. 进入"我的记录"页面
|
||||
echo 5. 查看Logcat日志(过滤TAG: MyRecords, ApiClient, FrontTokenInterceptor)
|
||||
echo 6. 查看后端日志(搜索关键字: [FrontTokenInterceptor], [FrontTokenComponent], 【观看历史】)
|
||||
echo.
|
||||
echo 预期日志输出:
|
||||
echo - Android端: "Token状态: 存在, 长度=32, 前20字符=xxx..."
|
||||
echo - Android端: "添加Token到请求头: xxx..."
|
||||
echo - 后端: "[FrontTokenInterceptor] URI=api/front/activity/view/history, rawToken=xxx..."
|
||||
echo - 后端: "[FrontTokenComponent] getUserId: rawToken=xxx..., userId=121"
|
||||
echo - 后端: "【观看历史】返回结果: userId=121, total=18, listSize=18"
|
||||
echo.
|
||||
pause
|
||||
54
deploy_user_activity.bat
Normal file
54
deploy_user_activity.bat
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
@echo off
|
||||
chcp 65001
|
||||
echo ========================================
|
||||
echo 部署用户活动记录功能
|
||||
echo ========================================
|
||||
|
||||
cd /d %~dp0
|
||||
|
||||
echo.
|
||||
echo [1/4] 编译后端项目...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -q
|
||||
if %errorlevel% neq 0 (
|
||||
echo 编译失败!请检查代码错误。
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo 后端编译成功!
|
||||
|
||||
echo.
|
||||
echo [2/4] 编译前端项目...
|
||||
cd ..\admin
|
||||
call npm run build
|
||||
if %errorlevel% neq 0 (
|
||||
echo 前端编译失败!
|
||||
echo 如果不需要重新编译前端,可以忽略此错误。
|
||||
)
|
||||
echo 前端编译完成!
|
||||
|
||||
cd ..\..
|
||||
|
||||
echo.
|
||||
echo [3/4] 部署文件位置
|
||||
echo ========================================
|
||||
echo 后端JAR: Zhibo\zhibo-h\crmeb-admin\target\crmeb-admin-*.jar
|
||||
echo 前端dist: Zhibo\admin\dist\
|
||||
echo ========================================
|
||||
|
||||
echo.
|
||||
echo [4/4] 部署说明
|
||||
echo ========================================
|
||||
echo 1. 停止当前运行的后端服务
|
||||
echo 2. 将新的JAR文件上传到服务器
|
||||
echo 3. 重启后端服务
|
||||
echo 4. 如果前端有更新,将dist目录内容上传到服务器
|
||||
echo.
|
||||
echo API端点:
|
||||
echo - 关注记录: GET /api/admin/user/activity/follow
|
||||
echo - 点赞记录: GET /api/admin/user/activity/like
|
||||
echo - 查看历史: GET /api/admin/user/activity/view
|
||||
echo - 收藏记录: GET /api/admin/user/activity/collect
|
||||
echo ========================================
|
||||
|
||||
pause
|
||||
30
deploy_view_history_fix.bat
Normal file
30
deploy_view_history_fix.bat
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 部署观看历史修复
|
||||
echo ========================================
|
||||
|
||||
cd Zhibo\zhibo-h
|
||||
|
||||
echo.
|
||||
echo 1. 编译项目...
|
||||
call mvn clean package -DskipTests -pl crmeb-front -am
|
||||
|
||||
if %ERRORLEVEL% NEQ 0 (
|
||||
echo 编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo 2. 上传到服务器...
|
||||
scp crmeb-front\target\crmeb-front.jar root@1.15.149.240:/www/wwwroot/zhibo/
|
||||
|
||||
echo.
|
||||
echo 3. 重启服务...
|
||||
ssh root@1.15.149.240 "cd /www/wwwroot/zhibo && ./restart.sh"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!请查看服务器日志确认
|
||||
echo ========================================
|
||||
pause
|
||||
86
diagnose_my_records.sql
Normal file
86
diagnose_my_records.sql
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
-- =====================================================
|
||||
-- 诊断"我的记录"不显示数据问题
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 查看所有用户,找到"道玄"用户的真实ID
|
||||
SELECT id, uid, nickname, phone, avatar, create_time
|
||||
FROM eb_user
|
||||
WHERE nickname LIKE '%道玄%'
|
||||
OR uid = 24187196
|
||||
OR id = 121
|
||||
ORDER BY id DESC;
|
||||
|
||||
-- 2. 检查 eb_view_history 表是否存在
|
||||
SHOW TABLES LIKE 'eb_view_history';
|
||||
|
||||
-- 3. 查看表结构
|
||||
DESC eb_view_history;
|
||||
|
||||
-- 4. 查看所有观看历史数据
|
||||
SELECT * FROM eb_view_history ORDER BY update_time DESC LIMIT 30;
|
||||
|
||||
-- 5. 按用户分组统计观看历史
|
||||
SELECT user_id, COUNT(*) as count
|
||||
FROM eb_view_history
|
||||
GROUP BY user_id
|
||||
ORDER BY count DESC;
|
||||
|
||||
-- 6. 查看直播间列表
|
||||
SELECT id, title, streamer_id, is_live, cover_image
|
||||
FROM eb_live_room
|
||||
ORDER BY id
|
||||
LIMIT 10;
|
||||
|
||||
-- =====================================================
|
||||
-- 为用户121(道玄)添加测试数据
|
||||
-- =====================================================
|
||||
|
||||
-- 先检查用户121是否存在
|
||||
SELECT id, nickname FROM eb_user WHERE id = 121;
|
||||
|
||||
-- 删除旧的测试数据(可选)
|
||||
-- DELETE FROM eb_view_history WHERE user_id = 121;
|
||||
|
||||
-- 插入观看历史测试数据
|
||||
INSERT INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time)
|
||||
SELECT 121, 'room', id, title, FLOOR(RAND() * 3600) + 300,
|
||||
NOW() - INTERVAL FLOOR(RAND() * 24) HOUR,
|
||||
NOW() - INTERVAL FLOOR(RAND() * 24) HOUR
|
||||
FROM eb_live_room
|
||||
WHERE id <= 10
|
||||
ON DUPLICATE KEY UPDATE
|
||||
view_duration = view_duration + VALUES(view_duration),
|
||||
update_time = NOW();
|
||||
|
||||
-- 验证插入结果
|
||||
SELECT '=== 用户121的观看历史 ===' as info;
|
||||
SELECT * FROM eb_view_history WHERE user_id = 121 ORDER BY update_time DESC;
|
||||
|
||||
-- =====================================================
|
||||
-- 检查点赞记录
|
||||
-- =====================================================
|
||||
SELECT '=== 用户121的直播间点赞 ===' as info;
|
||||
SELECT * FROM eb_live_room_like WHERE user_id = 121;
|
||||
|
||||
-- 如果没有点赞记录,添加一些
|
||||
INSERT IGNORE INTO eb_live_room_like (user_id, room_id, create_time)
|
||||
SELECT 121, id, NOW() - INTERVAL FLOOR(RAND() * 48) HOUR
|
||||
FROM eb_live_room
|
||||
WHERE id <= 5;
|
||||
|
||||
SELECT * FROM eb_live_room_like WHERE user_id = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 检查关注记录
|
||||
-- =====================================================
|
||||
SELECT '=== 用户121的关注记录 ===' as info;
|
||||
SELECT * FROM eb_follow_record WHERE follower_id = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 汇总统计
|
||||
-- =====================================================
|
||||
SELECT '=== 用户121数据汇总 ===' as info;
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM eb_view_history WHERE user_id = 121) as 观看历史数,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like WHERE user_id = 121) as 直播间点赞数,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE follower_id = 121) as 关注数;
|
||||
19
fix_ban_menu_component.sql
Normal file
19
fix_ban_menu_component.sql
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
-- =====================================================
|
||||
-- 修复封禁菜单的component路径
|
||||
-- =====================================================
|
||||
|
||||
-- 更新用户封禁菜单的component路径
|
||||
UPDATE eb_system_menu
|
||||
SET component = 'ban/userBan'
|
||||
WHERE `name` = '用户封禁';
|
||||
|
||||
-- 更新房间封禁菜单的component路径
|
||||
UPDATE eb_system_menu
|
||||
SET component = 'ban/roomBan'
|
||||
WHERE `name` = '房间封禁';
|
||||
|
||||
-- 验证更新结果
|
||||
SELECT id, pid, `name`, perms, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE `name` LIKE '%封禁%'
|
||||
ORDER BY sort DESC;
|
||||
28
fix_ban_menu_component_v2.sql
Normal file
28
fix_ban_menu_component_v2.sql
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
-- =====================================================
|
||||
-- 修复封禁菜单的component路径 (v2)
|
||||
-- 参考blacklist的配置格式
|
||||
-- =====================================================
|
||||
|
||||
-- 更新用户封禁菜单的component路径
|
||||
UPDATE eb_system_menu
|
||||
SET component = '/userManage/ban/userBan'
|
||||
WHERE `name` = '用户封禁';
|
||||
|
||||
-- 更新房间封禁菜单的component路径
|
||||
UPDATE eb_system_menu
|
||||
SET component = '/userManage/ban/roomBan'
|
||||
WHERE `name` = '房间封禁';
|
||||
|
||||
-- 验证更新结果
|
||||
SELECT '=== 封禁菜单配置 ===' as info;
|
||||
SELECT id, pid, `name`, perms, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE `name` LIKE '%封禁%'
|
||||
ORDER BY sort DESC;
|
||||
|
||||
-- 对比blacklist菜单配置
|
||||
SELECT '=== 黑名单菜单配置(参考) ===' as info;
|
||||
SELECT id, pid, `name`, perms, component, sort, is_show
|
||||
FROM eb_system_menu
|
||||
WHERE `name` LIKE '%拉黑%'
|
||||
ORDER BY sort DESC;
|
||||
59
fix_blacklist_menu_final.sql
Normal file
59
fix_blacklist_menu_final.sql
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
-- =====================================================
|
||||
-- 修复拉黑菜单 - 最终版
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 查看表结构
|
||||
DESC eb_system_menu;
|
||||
|
||||
-- 2. 查看社交互动菜单
|
||||
SELECT id, pid, `name`, component, menu_type, sort, is_show FROM eb_system_menu WHERE `name` = '社交互动';
|
||||
|
||||
-- 3. 查看群组管理作为参考(它能正常显示)
|
||||
SELECT * FROM eb_system_menu WHERE `name` = '群组管理';
|
||||
|
||||
-- 4. 查看现有的拉黑菜单
|
||||
SELECT * FROM eb_system_menu WHERE `name` IN ('用户拉黑', '房间拉黑');
|
||||
|
||||
-- 5. 删除旧的拉黑菜单记录
|
||||
DELETE FROM eb_system_menu WHERE `name` = '用户拉黑';
|
||||
DELETE FROM eb_system_menu WHERE `name` = '房间拉黑';
|
||||
|
||||
-- 6. 获取社交互动的ID
|
||||
SET @social_id = (SELECT id FROM eb_system_menu WHERE `name` = '社交互动' AND menu_type = 'M' LIMIT 1);
|
||||
SELECT @social_id as '社交互动ID';
|
||||
|
||||
-- 7. 获取群组管理的sort值,在其后面添加
|
||||
SET @group_sort = (SELECT sort FROM eb_system_menu WHERE `name` = '群组管理' LIMIT 1);
|
||||
SELECT @group_sort as '群组管理排序';
|
||||
|
||||
-- 8. 插入用户拉黑菜单(参考群组管理的格式)
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_id, '用户拉黑', '', 'admin:blacklist:user:list', '/socialManage/blacklist/user', 'C', IFNULL(@group_sort, 0) + 1, 1);
|
||||
|
||||
SET @user_blacklist_id = LAST_INSERT_ID();
|
||||
SELECT @user_blacklist_id as '用户拉黑菜单ID';
|
||||
|
||||
-- 9. 插入房间拉黑菜单
|
||||
INSERT INTO eb_system_menu (`pid`, `name`, `icon`, `perms`, `component`, `menu_type`, `sort`, `is_show`)
|
||||
VALUES (@social_id, '房间拉黑', '', 'admin:blacklist:room:list', '/socialManage/blacklist/room', 'C', IFNULL(@group_sort, 0) + 2, 1);
|
||||
|
||||
SET @room_blacklist_id = LAST_INSERT_ID();
|
||||
SELECT @room_blacklist_id as '房间拉黑菜单ID';
|
||||
|
||||
-- 10. 为管理员角色添加权限(rid=1是超级管理员)
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id) VALUES (1, @user_blacklist_id);
|
||||
INSERT IGNORE INTO eb_system_role_menu (rid, menu_id) VALUES (1, @room_blacklist_id);
|
||||
|
||||
-- 11. 验证结果
|
||||
SELECT '=== 社交互动下所有子菜单 ===' as info;
|
||||
SELECT id, pid, `name`, component, sort, is_show, menu_type
|
||||
FROM eb_system_menu
|
||||
WHERE pid = @social_id
|
||||
ORDER BY sort;
|
||||
|
||||
-- 12. 验证权限
|
||||
SELECT '=== 拉黑菜单权限 ===' as info;
|
||||
SELECT rm.rid, rm.menu_id, m.`name`, m.component
|
||||
FROM eb_system_role_menu rm
|
||||
JOIN eb_system_menu m ON rm.menu_id = m.id
|
||||
WHERE m.`name` IN ('用户拉黑', '房间拉黑');
|
||||
17
fix_data_and_tables.sql
Normal file
17
fix_data_and_tables.sql
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-- =====================================================
|
||||
-- 修复数据和表结构,确保与后端服务一致
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 检查观看历史表名
|
||||
SHOW TABLES LIKE '%history%';
|
||||
SHOW TABLES LIKE '%view%';
|
||||
|
||||
-- 2. 检查 eb_works_relation 的 type 字段类型
|
||||
DESCRIBE eb_works_relation;
|
||||
|
||||
-- 3. 检查 eb_follow_record 的 follow_status 字段
|
||||
SELECT DISTINCT follow_status FROM eb_follow_record LIMIT 10;
|
||||
|
||||
-- 4. 检查直播间表名
|
||||
SHOW TABLES LIKE '%room%';
|
||||
SHOW TABLES LIKE '%live%';
|
||||
49
fix_records_v2.sql
Normal file
49
fix_records_v2.sql
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
-- =====================================================
|
||||
-- 修复"我的记录"不显示数据问题 - V2
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 先查看 eb_user 表结构,确认列名
|
||||
DESC eb_user;
|
||||
|
||||
-- 2. 查询用户(使用 uid 作为主键)
|
||||
SELECT uid, nickname, phone, avatar FROM eb_user WHERE nickname LIKE '%道玄%';
|
||||
|
||||
-- 3. 检查观看历史表是否存在
|
||||
SHOW TABLES LIKE 'eb_view_history';
|
||||
|
||||
-- 4. 如果表不存在,创建它
|
||||
CREATE TABLE IF NOT EXISTS `eb_view_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`target_type` varchar(20) NOT NULL COMMENT '目标类型:room-直播间, work-作品, profile-用户主页',
|
||||
`target_id` varchar(50) NOT NULL COMMENT '目标ID',
|
||||
`target_title` varchar(255) DEFAULT NULL COMMENT '目标标题',
|
||||
`view_duration` int(11) DEFAULT 0 COMMENT '观看时长(秒)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '查看时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_target` (`target_type`, `target_id`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='查看历史记录表';
|
||||
|
||||
-- 5. 查看现有观看历史数据
|
||||
SELECT * FROM eb_view_history ORDER BY update_time DESC LIMIT 20;
|
||||
|
||||
-- 6. 查看直播间列表
|
||||
SELECT id, title, streamer_id FROM eb_live_room LIMIT 10;
|
||||
|
||||
-- =====================================================
|
||||
-- 为用户121添加测试数据(假设道玄的uid是121)
|
||||
-- 如果不是121,请替换为实际的uid值
|
||||
-- =====================================================
|
||||
|
||||
-- 插入观看历史
|
||||
INSERT INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time)
|
||||
VALUES
|
||||
(121, 'room', '1', '欢乐游戏直播', 1800, NOW(), NOW()),
|
||||
(121, 'room', '2', '音乐分享会', 2400, NOW(), NOW()),
|
||||
(121, 'room', '8', '火影忍者', 3600, NOW(), NOW());
|
||||
|
||||
-- 验证插入结果
|
||||
SELECT * FROM eb_view_history WHERE user_id = 121;
|
||||
82
fix_view_history_for_user.sql
Normal file
82
fix_view_history_for_user.sql
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
-- =====================================================
|
||||
-- 修复"我的记录"不显示数据问题
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 首先检查当前用户的数据
|
||||
-- 从截图看用户ID显示为 24187196,但这可能是显示ID,实际数据库ID可能不同
|
||||
-- 先查询用户表确认
|
||||
|
||||
-- 查看所有用户
|
||||
SELECT id, uid, nickname, phone FROM eb_user ORDER BY id DESC LIMIT 20;
|
||||
|
||||
-- 2. 检查 eb_view_history 表是否存在
|
||||
SHOW TABLES LIKE 'eb_view_history';
|
||||
|
||||
-- 3. 检查表结构
|
||||
DESC eb_view_history;
|
||||
|
||||
-- 4. 查看现有的观看历史数据
|
||||
SELECT * FROM eb_view_history ORDER BY id DESC LIMIT 20;
|
||||
|
||||
-- 5. 查看直播间列表(用于添加测试数据)
|
||||
SELECT id, title, streamer_id, is_live FROM eb_live_room LIMIT 10;
|
||||
|
||||
-- =====================================================
|
||||
-- 为用户添加测试观看历史数据
|
||||
-- 请根据实际用户ID修改 @USER_ID 的值
|
||||
-- =====================================================
|
||||
|
||||
-- 设置用户ID(请根据实际情况修改)
|
||||
-- 如果用户昵称是"道玄",先查询其真实ID
|
||||
SELECT id, uid, nickname FROM eb_user WHERE nickname LIKE '%道玄%' OR uid = 24187196;
|
||||
|
||||
-- 假设用户ID是121(道玄),添加观看历史
|
||||
SET @USER_ID = 121;
|
||||
|
||||
-- 先删除旧数据(可选)
|
||||
-- DELETE FROM eb_view_history WHERE user_id = @USER_ID;
|
||||
|
||||
-- 插入观看历史测试数据
|
||||
INSERT INTO eb_view_history (user_id, target_type, target_id, target_title, view_duration, create_time, update_time) VALUES
|
||||
(@USER_ID, 'room', '1', '欢乐游戏直播', 1800, NOW() - INTERVAL 1 HOUR, NOW() - INTERVAL 1 HOUR),
|
||||
(@USER_ID, 'room', '2', '音乐分享会', 2400, NOW() - INTERVAL 2 HOUR, NOW() - INTERVAL 2 HOUR),
|
||||
(@USER_ID, 'room', '3', '户外探险', 1200, NOW() - INTERVAL 3 HOUR, NOW() - INTERVAL 3 HOUR),
|
||||
(@USER_ID, 'room', '8', '火影忍者', 3600, NOW() - INTERVAL 30 MINUTE, NOW() - INTERVAL 30 MINUTE)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
target_title = VALUES(target_title),
|
||||
view_duration = view_duration + VALUES(view_duration),
|
||||
update_time = NOW();
|
||||
|
||||
-- 验证插入结果
|
||||
SELECT * FROM eb_view_history WHERE user_id = @USER_ID ORDER BY update_time DESC;
|
||||
|
||||
-- =====================================================
|
||||
-- 同时检查点赞记录表
|
||||
-- =====================================================
|
||||
|
||||
-- 检查直播间点赞表
|
||||
SELECT * FROM eb_live_room_like WHERE user_id = @USER_ID;
|
||||
|
||||
-- 检查作品点赞表(如果存在)
|
||||
SELECT * FROM eb_work_like WHERE user_id = @USER_ID;
|
||||
|
||||
-- 检查关注记录
|
||||
SELECT * FROM eb_follow_record WHERE follower_id = @USER_ID;
|
||||
|
||||
-- =====================================================
|
||||
-- 如果表不存在,创建它
|
||||
-- =====================================================
|
||||
CREATE TABLE IF NOT EXISTS `eb_view_history` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
`user_id` int(11) NOT NULL COMMENT '用户ID',
|
||||
`target_type` varchar(20) NOT NULL COMMENT '目标类型:room-直播间, work-作品, profile-用户主页',
|
||||
`target_id` varchar(50) NOT NULL COMMENT '目标ID',
|
||||
`target_title` varchar(255) DEFAULT NULL COMMENT '目标标题',
|
||||
`view_duration` int(11) DEFAULT 0 COMMENT '观看时长(秒)',
|
||||
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '查看时间',
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_target` (`target_type`, `target_id`),
|
||||
KEY `idx_create_time` (`create_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='查看历史记录表';
|
||||
54
insert_data_121_complete.sql
Normal file
54
insert_data_121_complete.sql
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加测试数据 - 完整修正版
|
||||
-- =====================================================
|
||||
|
||||
-- =====================================================
|
||||
-- 1. 搜索历史 (eb_search_history) - 使用 user_id
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_search_history (user_id, keyword, search_type, search_count, create_time) VALUES
|
||||
(121, '游戏直播', 1, 3, '2026-01-03 20:00:00'),
|
||||
(121, '音乐', 1, 2, '2026-01-03 19:00:00'),
|
||||
(121, '美食教程', 2, 1, '2026-01-02 11:00:00'),
|
||||
(121, '旅行Vlog', 2, 2, '2026-01-02 10:00:00'),
|
||||
(121, '编程学习', 1, 4, '2026-01-01 13:00:00'),
|
||||
(121, '户外运动', 1, 1, '2026-01-01 09:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 好友关系 (eb_friend) - 使用 uid 和 friend_uid
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_friend (uid, friend_uid, remark, user_id, create_time) VALUES
|
||||
(121, 100, '游戏主播', 121, '2026-01-03 21:35:00'),
|
||||
(121, 101, '音乐达人', 121, '2026-01-03 16:10:00'),
|
||||
(100, 121, '道玄', 100, '2026-01-03 21:35:00'),
|
||||
(101, 121, '道玄', 101, '2026-01-03 16:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 更新用户余额和积分
|
||||
-- =====================================================
|
||||
UPDATE eb_user SET
|
||||
now_money = 500.00,
|
||||
integral = 1200,
|
||||
experience = 350
|
||||
WHERE uid = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 4. 验证所有数据
|
||||
-- =====================================================
|
||||
SELECT '直播间点赞' as 类型, COUNT(*) as 数量 FROM eb_live_room_like WHERE user_id = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE follower_id = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE followed_id = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE user_id = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
SELECT uid, nickname, now_money as 余额, integral as 积分, experience as 经验
|
||||
FROM eb_user WHERE uid = 121;
|
||||
|
||||
SELECT '=== 数据插入完成!===' as 结果;
|
||||
73
insert_data_121_final.sql
Normal file
73
insert_data_121_final.sql
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加测试数据 - 最终版
|
||||
-- =====================================================
|
||||
|
||||
-- =====================================================
|
||||
-- 1. 关注记录 (eb_follow_record) - 使用 follower_id 和 followed_id
|
||||
-- =====================================================
|
||||
-- 道玄关注其他用户 (follower_id=121)
|
||||
INSERT IGNORE INTO eb_follow_record (follower_id, follower_nickname, followed_id, followed_nickname, follow_status, create_time) VALUES
|
||||
(121, '道玄', 100, '测试用户100', '关注', '2026-01-03 20:00:00'),
|
||||
(121, '道玄', 101, '测试用户101', '关注', '2026-01-03 15:00:00'),
|
||||
(121, '道玄', 102, '测试用户102', '关注', '2026-01-02 18:00:00'),
|
||||
(121, '道玄', 103, '测试用户103', '关注', '2026-01-02 12:00:00'),
|
||||
(121, '道玄', 104, '测试用户104', '关注', '2026-01-01 20:00:00'),
|
||||
(121, '道玄', 105, '测试用户105', '关注', '2026-01-01 10:00:00');
|
||||
|
||||
-- 其他用户关注道玄 (followed_id=121)
|
||||
INSERT IGNORE INTO eb_follow_record (follower_id, follower_nickname, followed_id, followed_nickname, follow_status, create_time) VALUES
|
||||
(100, '测试用户100', 121, '道玄', '关注', '2026-01-03 21:00:00'),
|
||||
(101, '测试用户101', 121, '道玄', '关注', '2026-01-03 16:00:00'),
|
||||
(106, '测试用户106', 121, '道玄', '关注', '2026-01-02 20:00:00'),
|
||||
(107, '测试用户107', 121, '道玄', '关注', '2026-01-02 14:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 搜索历史 (eb_search_history)
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_search_history (uid, keyword, search_type, search_count, create_time) VALUES
|
||||
(121, '游戏直播', 1, 3, '2026-01-03 20:00:00'),
|
||||
(121, '音乐', 1, 2, '2026-01-03 19:00:00'),
|
||||
(121, '美食教程', 2, 1, '2026-01-02 11:00:00'),
|
||||
(121, '旅行Vlog', 2, 2, '2026-01-02 10:00:00'),
|
||||
(121, '编程学习', 1, 4, '2026-01-01 13:00:00'),
|
||||
(121, '户外运动', 1, 1, '2026-01-01 09:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 好友关系 (eb_friend)
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_friend (uid, friend_uid, remark, create_time) VALUES
|
||||
(121, 100, '游戏主播', '2026-01-03 21:35:00'),
|
||||
(121, 101, '音乐达人', '2026-01-03 16:10:00'),
|
||||
(100, 121, '道玄', '2026-01-03 21:35:00'),
|
||||
(101, 121, '道玄', '2026-01-03 16:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 4. 更新用户余额和积分
|
||||
-- =====================================================
|
||||
UPDATE eb_user SET
|
||||
now_money = 500.00,
|
||||
integral = 1200,
|
||||
experience = 350
|
||||
WHERE uid = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 5. 验证数据
|
||||
-- =====================================================
|
||||
SELECT '直播间点赞' as 类型, COUNT(*) as 数量 FROM eb_live_room_like WHERE user_id = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE follower_id = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE followed_id = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
SELECT uid, nickname, now_money as 余额, integral as 积分, experience as 经验
|
||||
FROM eb_user WHERE uid = 121;
|
||||
|
||||
SELECT '数据插入完成!' as 结果;
|
||||
100
insert_data_121_fixed.sql
Normal file
100
insert_data_121_fixed.sql
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加测试数据 - 修正版
|
||||
-- =====================================================
|
||||
|
||||
-- =====================================================
|
||||
-- 1. 直播间点赞 (eb_live_room_like) - 使用 user_id 字段
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_live_room_like (user_id, room_id, user_nickname, like_count, create_time) VALUES
|
||||
(121, 1, '道玄', 15, '2026-01-03 20:35:00'),
|
||||
(121, 2, '道玄', 28, '2026-01-03 21:15:00'),
|
||||
(121, 3, '道玄', 8, '2026-01-02 19:10:00'),
|
||||
(121, 4, '道玄', 42, '2026-01-02 12:30:00'),
|
||||
(121, 5, '道玄', 20, '2026-01-01 14:30:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 作品关系 (eb_works_relation) - 点赞和收藏
|
||||
-- =====================================================
|
||||
-- 点赞作品 (type=1)
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 1, '2026-01-03 22:05:00'),
|
||||
(121, 2, 1, '2026-01-03 18:10:00'),
|
||||
(121, 3, 1, '2026-01-02 16:15:00'),
|
||||
(121, 4, 1, '2026-01-01 20:00:00'),
|
||||
(121, 5, 1, '2026-01-01 15:00:00');
|
||||
|
||||
-- 收藏作品 (type=2)
|
||||
INSERT IGNORE INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 2, '2026-01-03 22:06:00'),
|
||||
(121, 2, 2, '2026-01-03 18:12:00'),
|
||||
(121, 6, 2, '2026-01-02 10:00:00'),
|
||||
(121, 7, 2, '2026-01-01 11:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 关注记录 (eb_follow_record)
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(121, 100, '2026-01-03 20:00:00'),
|
||||
(121, 101, '2026-01-03 15:00:00'),
|
||||
(121, 102, '2026-01-02 18:00:00'),
|
||||
(121, 103, '2026-01-02 12:00:00'),
|
||||
(121, 104, '2026-01-01 20:00:00'),
|
||||
(121, 105, '2026-01-01 10:00:00');
|
||||
|
||||
-- 被关注记录
|
||||
INSERT IGNORE INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(100, 121, '2026-01-03 21:00:00'),
|
||||
(101, 121, '2026-01-03 16:00:00'),
|
||||
(106, 121, '2026-01-02 20:00:00'),
|
||||
(107, 121, '2026-01-02 14:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 4. 搜索历史 (eb_search_history)
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_search_history (uid, keyword, search_type, search_count, create_time) VALUES
|
||||
(121, '游戏直播', 1, 3, '2026-01-03 20:00:00'),
|
||||
(121, '音乐', 1, 2, '2026-01-03 19:00:00'),
|
||||
(121, '美食教程', 2, 1, '2026-01-02 11:00:00'),
|
||||
(121, '旅行Vlog', 2, 2, '2026-01-02 10:00:00'),
|
||||
(121, '编程学习', 1, 4, '2026-01-01 13:00:00'),
|
||||
(121, '户外运动', 1, 1, '2026-01-01 09:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 5. 好友关系 (eb_friend)
|
||||
-- =====================================================
|
||||
INSERT IGNORE INTO eb_friend (uid, friend_uid, remark, create_time) VALUES
|
||||
(121, 100, '游戏主播', '2026-01-03 21:35:00'),
|
||||
(121, 101, '音乐达人', '2026-01-03 16:10:00'),
|
||||
(100, 121, '道玄', '2026-01-03 21:35:00'),
|
||||
(101, 121, '道玄', '2026-01-03 16:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 6. 更新用户余额和积分
|
||||
-- =====================================================
|
||||
UPDATE eb_user SET
|
||||
now_money = 500.00,
|
||||
integral = 1200,
|
||||
experience = 350
|
||||
WHERE uid = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 7. 验证数据
|
||||
-- =====================================================
|
||||
SELECT '直播间点赞' as 类型, COUNT(*) as 数量 FROM eb_live_room_like WHERE user_id = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE follow_uid = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
SELECT uid, nickname, now_money as 余额, integral as 积分, experience as 经验
|
||||
FROM eb_user WHERE uid = 121;
|
||||
|
||||
SELECT '数据插入完成!' as 结果;
|
||||
6
insert_data_121_v2.sql
Normal file
6
insert_data_121_v2.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加测试数据 - 第二版
|
||||
-- 先查看 eb_follow_record 表结构
|
||||
-- =====================================================
|
||||
|
||||
DESCRIBE eb_follow_record;
|
||||
3
insert_data_121_v3.sql
Normal file
3
insert_data_121_v3.sql
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
-- 查看 eb_search_history 和 eb_friend 表结构
|
||||
DESCRIBE eb_search_history;
|
||||
DESCRIBE eb_friend;
|
||||
17
insert_test_rooms_works.sql
Normal file
17
insert_test_rooms_works.sql
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
-- =====================================================
|
||||
-- 创建测试直播间和作品数据
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 插入测试直播间 (eb_live_room)
|
||||
INSERT IGNORE INTO eb_live_room (id, uid, title, streamer_name, stream_key, is_live, cover_image, description, create_time) VALUES
|
||||
(1, 100, '欢乐游戏直播', '游戏达人', 'stream_key_1', 1, 'https://example.com/room1.jpg', '欢迎来到游戏直播间', '2026-01-01 10:00:00'),
|
||||
(2, 101, '音乐分享会', '音乐主播', 'stream_key_2', 1, 'https://example.com/room2.jpg', '分享好听的音乐', '2026-01-01 11:00:00'),
|
||||
(3, 102, '户外探险直播', '探险家', 'stream_key_3', 0, 'https://example.com/room3.jpg', '带你看世界', '2026-01-01 12:00:00'),
|
||||
(4, 103, '美食制作教程', '美食达人', 'stream_key_4', 1, 'https://example.com/room4.jpg', '教你做美食', '2026-01-01 13:00:00'),
|
||||
(5, 104, '编程技术分享', '程序员', 'stream_key_5', 0, 'https://example.com/room5.jpg', '分享编程技术', '2026-01-01 14:00:00');
|
||||
|
||||
-- 2. 查看 eb_works 表结构
|
||||
DESCRIBE eb_works;
|
||||
|
||||
-- 3. 检查插入的直播间
|
||||
SELECT id, title, streamer_name, is_live FROM eb_live_room WHERE id IN (1,2,3,4,5);
|
||||
22
insert_test_works.sql
Normal file
22
insert_test_works.sql
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-- =====================================================
|
||||
-- 创建测试作品数据
|
||||
-- =====================================================
|
||||
|
||||
-- 先查看 eb_works 表完整结构(需要知道 user_id 字段)
|
||||
SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'zhibo' AND TABLE_NAME = 'eb_works'
|
||||
ORDER BY ORDINAL_POSITION;
|
||||
|
||||
-- 插入测试作品
|
||||
INSERT IGNORE INTO eb_works (id, user_id, title, description, cover_image, like_count, collect_count, view_count, comment_count, is_deleted, create_time) VALUES
|
||||
(1, 100, '搞笑短视频合集', '超级搞笑的视频合集', 'https://example.com/work1.jpg', 100, 50, 1000, 20, 0, '2026-01-01 10:00:00'),
|
||||
(2, 101, '旅行Vlog-云南之旅', '云南旅行记录', 'https://example.com/work2.jpg', 200, 80, 2000, 30, 0, '2026-01-01 11:00:00'),
|
||||
(3, 102, '美妆教程分享', '日常妆容教程', 'https://example.com/work3.jpg', 150, 60, 1500, 25, 0, '2026-01-01 12:00:00'),
|
||||
(4, 103, '健身打卡日记', '每日健身记录', 'https://example.com/work4.jpg', 80, 30, 800, 15, 0, '2026-01-01 13:00:00'),
|
||||
(5, 104, '美食探店', '探索城市美食', 'https://example.com/work5.jpg', 120, 45, 1200, 18, 0, '2026-01-01 14:00:00'),
|
||||
(6, 105, '宠物日常', '可爱宠物的日常', 'https://example.com/work6.jpg', 300, 100, 3000, 50, 0, '2026-01-01 15:00:00'),
|
||||
(7, 100, '游戏精彩时刻', '游戏高光集锦', 'https://example.com/work7.jpg', 180, 70, 1800, 28, 0, '2026-01-01 16:00:00');
|
||||
|
||||
-- 验证插入的作品
|
||||
SELECT id, title, user_id, like_count, collect_count FROM eb_works WHERE id IN (1,2,3,4,5,6,7);
|
||||
46
rebuild_and_restart_backend.bat
Normal file
46
rebuild_and_restart_backend.bat
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
@echo off
|
||||
chcp 65001
|
||||
echo ========================================
|
||||
echo 重新编译并重启后端服务
|
||||
echo ========================================
|
||||
|
||||
cd /d E:\zhibo_1.0\6.0\zhibo\Zhibo\zhibo-h
|
||||
|
||||
echo.
|
||||
echo [1/3] 停止现有后端进程...
|
||||
for /f "tokens=5" %%a in ('netstat -ano ^| findstr ":30001" ^| findstr "LISTENING"') do (
|
||||
echo 正在停止进程 %%a
|
||||
taskkill /F /PID %%a 2>nul
|
||||
)
|
||||
timeout /t 2 /nobreak >nul
|
||||
|
||||
echo.
|
||||
echo [2/3] 重新编译项目...
|
||||
call mvn clean package -DskipTests -q
|
||||
if %errorlevel% neq 0 (
|
||||
echo 编译失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo 编译成功!
|
||||
|
||||
echo.
|
||||
echo [3/3] 启动后端服务...
|
||||
cd crmeb-admin
|
||||
start "CRMEB Admin Backend" java -jar target/crmeb-admin.jar
|
||||
echo 后端服务已启动,请等待约30秒...
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 部署完成!
|
||||
echo 后端地址: http://localhost:30001
|
||||
echo 前端地址: http://localhost:9527
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 请在管理后台测试用户活动记录功能:
|
||||
echo 1. 登录管理后台
|
||||
echo 2. 进入 用户管理 -^> 用户列表
|
||||
echo 3. 点击用户121(道玄)的详情
|
||||
echo 4. 切换到"关注记录"、"点赞记录"等标签页
|
||||
echo.
|
||||
pause
|
||||
28
rebuild_backend.bat
Normal file
28
rebuild_backend.bat
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
@echo off
|
||||
chcp 65001
|
||||
echo ========================================
|
||||
echo 重新编译后端项目
|
||||
echo ========================================
|
||||
|
||||
cd /d %~dp0
|
||||
|
||||
echo.
|
||||
echo [1/2] 编译后端项目...
|
||||
cd Zhibo\zhibo-h
|
||||
call mvn clean package -DskipTests -q
|
||||
if %errorlevel% neq 0 (
|
||||
echo 编译失败!请检查代码错误。
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo 后端编译成功!
|
||||
|
||||
echo.
|
||||
echo [2/2] JAR文件位置
|
||||
echo ========================================
|
||||
dir /b crmeb-admin\target\*.jar 2>nul
|
||||
echo.
|
||||
echo 请将JAR文件部署到服务器并重启后端服务
|
||||
echo ========================================
|
||||
|
||||
pause
|
||||
27
test_activity_api.bat
Normal file
27
test_activity_api.bat
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 测试用户活动记录API
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
echo 1. 检查后端服务是否运行...
|
||||
netstat -an | findstr "30001"
|
||||
echo.
|
||||
|
||||
echo 2. 测试API(需要登录token)
|
||||
echo 请在浏览器中登录管理后台,然后在开发者工具中查看Network请求
|
||||
echo 找到任意请求的 Authori-zation 头,复制token值
|
||||
echo.
|
||||
|
||||
echo 3. 手动测试命令(替换YOUR_TOKEN为实际token):
|
||||
echo curl -X GET "http://localhost:30001/api/admin/user/activity/follow?userId=121&page=1&limit=10" -H "Authori-zation: YOUR_TOKEN"
|
||||
echo.
|
||||
|
||||
echo 4. 或者直接在管理后台测试:
|
||||
echo - 打开 http://localhost:9527
|
||||
echo - 登录后进入 用户管理 -^> 用户列表
|
||||
echo - 点击用户121(道玄)的详情
|
||||
echo - 切换到"关注记录"、"点赞记录"等标签页
|
||||
echo.
|
||||
|
||||
pause
|
||||
71
test_activity_api.md
Normal file
71
test_activity_api.md
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
# 用户活动记录API测试
|
||||
|
||||
## API路径
|
||||
|
||||
后端Controller路径: `api/admin/user/activity`
|
||||
|
||||
完整API端点:
|
||||
- 关注记录: `GET /api/admin/user/activity/follow?userId=121&page=1&limit=10`
|
||||
- 点赞记录: `GET /api/admin/user/activity/like?userId=121&page=1&limit=10`
|
||||
- 查看历史: `GET /api/admin/user/activity/view?userId=121&page=1&limit=10`
|
||||
- 收藏记录: `GET /api/admin/user/activity/collect?userId=121&page=1&limit=10`
|
||||
|
||||
## 测试步骤
|
||||
|
||||
### 1. 重新编译后端
|
||||
```bash
|
||||
cd zhibo/Zhibo/zhibo-h
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
|
||||
### 2. 重启后端服务
|
||||
|
||||
### 3. 使用浏览器开发者工具测试
|
||||
|
||||
打开管理后台,按F12打开开发者工具,切换到Network标签。
|
||||
|
||||
然后:
|
||||
1. 进入用户管理页面
|
||||
2. 点击用户121(道玄)的"详情"按钮
|
||||
3. 切换到"关注记录"标签
|
||||
4. 查看Network中的请求和响应
|
||||
|
||||
### 4. 使用curl测试(需要先获取token)
|
||||
|
||||
```bash
|
||||
# 替换YOUR_TOKEN为实际的登录token
|
||||
curl -X GET "http://localhost:30001/api/admin/user/activity/follow?userId=121&page=1&limit=10" \
|
||||
-H "Authori-zation: YOUR_TOKEN"
|
||||
```
|
||||
|
||||
## 预期响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"list": [
|
||||
{
|
||||
"id": 1,
|
||||
"followedId": 43,
|
||||
"followedNickname": "测试用户",
|
||||
"followedAvatar": "...",
|
||||
"followStatus": "1",
|
||||
"createTime": "2026-01-03 10:00:00"
|
||||
}
|
||||
],
|
||||
"total": 6,
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"totalPage": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
1. **404错误**: 后端没有重新编译部署
|
||||
2. **空数据**: 检查数据库中是否有数据
|
||||
3. **401错误**: token无效或过期
|
||||
4. **500错误**: 后端代码有bug,查看后端日志
|
||||
49
test_api_curl.sh
Normal file
49
test_api_curl.sh
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
# 测试观看历史API
|
||||
|
||||
SERVER="http://1.15.149.240:8080"
|
||||
|
||||
echo "=========================================="
|
||||
echo "测试观看历史API"
|
||||
echo "=========================================="
|
||||
|
||||
# 首先登录获取Token
|
||||
echo ""
|
||||
echo "1. 登录获取Token..."
|
||||
LOGIN_RESPONSE=$(curl -s -X POST "$SERVER/api/front/login/mobile" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"phone":"17629942950","code":"123456"}')
|
||||
|
||||
echo "登录响应: $LOGIN_RESPONSE"
|
||||
|
||||
# 提取Token (需要根据实际响应格式调整)
|
||||
TOKEN=$(echo $LOGIN_RESPONSE | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||||
echo "Token: $TOKEN"
|
||||
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "登录失败,无法获取Token"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "2. 测试Token调试接口..."
|
||||
curl -s -X GET "$SERVER/api/front/activity/debug/token" \
|
||||
-H "Authori-zation: $TOKEN" \
|
||||
-H "Content-Type: application/json" | python3 -m json.tool
|
||||
|
||||
echo ""
|
||||
echo "3. 测试获取观看历史..."
|
||||
curl -s -X GET "$SERVER/api/front/activity/view/history?page=1&pageSize=20" \
|
||||
-H "Authori-zation: $TOKEN" \
|
||||
-H "Content-Type: application/json" | python3 -m json.tool
|
||||
|
||||
echo ""
|
||||
echo "4. 测试获取点赞记录..."
|
||||
curl -s -X GET "$SERVER/api/front/activity/like/records?page=1&pageSize=20" \
|
||||
-H "Authori-zation: $TOKEN" \
|
||||
-H "Content-Type: application/json" | python3 -m json.tool
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "测试完成"
|
||||
echo "=========================================="
|
||||
173
test_data_for_user_121.sql
Normal file
173
test_data_for_user_121.sql
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
-- =====================================================
|
||||
-- 为用户"道玄"(ID: 121)添加测试数据
|
||||
-- 执行时间: 2026-01-04
|
||||
-- =====================================================
|
||||
|
||||
-- 先检查用户是否存在
|
||||
SELECT uid, nickname, phone FROM eb_user WHERE uid = 121;
|
||||
|
||||
-- 检查现有的直播间
|
||||
SELECT id, room_title, owner_nickname, status FROM eb_room LIMIT 10;
|
||||
|
||||
-- 检查现有的作品
|
||||
SELECT id, title, user_id FROM eb_works LIMIT 10;
|
||||
|
||||
-- 检查现有的主播
|
||||
SELECT id, uid, nickname FROM eb_streamer LIMIT 10;
|
||||
|
||||
-- =====================================================
|
||||
-- 1. 观看历史记录 (eb_watch_history)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_watch_history (uid, target_type, target_id, target_title, target_cover, duration, watch_time, create_time) VALUES
|
||||
-- 观看直播间
|
||||
(121, 'room', 1, '欢乐游戏直播', 'https://example.com/cover1.jpg', 1800, '2026-01-03 20:30:00', '2026-01-03 20:30:00'),
|
||||
(121, 'room', 2, '音乐分享会', 'https://example.com/cover2.jpg', 2400, '2026-01-03 21:00:00', '2026-01-03 21:00:00'),
|
||||
(121, 'room', 3, '户外探险直播', 'https://example.com/cover3.jpg', 900, '2026-01-02 19:00:00', '2026-01-02 19:00:00'),
|
||||
(121, 'room', 4, '美食制作教程', 'https://example.com/cover4.jpg', 3600, '2026-01-02 12:00:00', '2026-01-02 12:00:00'),
|
||||
(121, 'room', 5, '编程技术分享', 'https://example.com/cover5.jpg', 5400, '2026-01-01 14:00:00', '2026-01-01 14:00:00'),
|
||||
-- 观看作品
|
||||
(121, 'work', 1, '搞笑短视频合集', 'https://example.com/work1.jpg', 180, '2026-01-03 22:00:00', '2026-01-03 22:00:00'),
|
||||
(121, 'work', 2, '旅行Vlog-云南之旅', 'https://example.com/work2.jpg', 600, '2026-01-03 18:00:00', '2026-01-03 18:00:00'),
|
||||
(121, 'work', 3, '美妆教程分享', 'https://example.com/work3.jpg', 420, '2026-01-02 16:00:00', '2026-01-02 16:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 2. 直播间点赞记录 (eb_live_room_like)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_live_room_like (uid, room_id, like_count, create_time) VALUES
|
||||
(121, 1, 15, '2026-01-03 20:35:00'),
|
||||
(121, 2, 28, '2026-01-03 21:15:00'),
|
||||
(121, 3, 8, '2026-01-02 19:10:00'),
|
||||
(121, 4, 42, '2026-01-02 12:30:00'),
|
||||
(121, 5, 20, '2026-01-01 14:30:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 3. 作品关系记录 (eb_works_relation) - 点赞和收藏
|
||||
-- =====================================================
|
||||
-- 点赞作品 (type=1)
|
||||
INSERT INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 1, '2026-01-03 22:05:00'),
|
||||
(121, 2, 1, '2026-01-03 18:10:00'),
|
||||
(121, 3, 1, '2026-01-02 16:15:00'),
|
||||
(121, 4, 1, '2026-01-01 20:00:00'),
|
||||
(121, 5, 1, '2026-01-01 15:00:00');
|
||||
|
||||
-- 收藏作品 (type=2)
|
||||
INSERT INTO eb_works_relation (uid, works_id, type, create_time) VALUES
|
||||
(121, 1, 2, '2026-01-03 22:06:00'),
|
||||
(121, 2, 2, '2026-01-03 18:12:00'),
|
||||
(121, 6, 2, '2026-01-02 10:00:00'),
|
||||
(121, 7, 2, '2026-01-01 11:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 4. 关注记录 (eb_follow_record)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(121, 100, '2026-01-03 20:00:00'),
|
||||
(121, 101, '2026-01-03 15:00:00'),
|
||||
(121, 102, '2026-01-02 18:00:00'),
|
||||
(121, 103, '2026-01-02 12:00:00'),
|
||||
(121, 104, '2026-01-01 20:00:00'),
|
||||
(121, 105, '2026-01-01 10:00:00');
|
||||
|
||||
-- 被关注记录(其他用户关注道玄)
|
||||
INSERT INTO eb_follow_record (uid, follow_uid, create_time) VALUES
|
||||
(100, 121, '2026-01-03 21:00:00'),
|
||||
(101, 121, '2026-01-03 16:00:00'),
|
||||
(106, 121, '2026-01-02 20:00:00'),
|
||||
(107, 121, '2026-01-02 14:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 5. 搜索历史 (eb_search_history)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_search_history (uid, keyword, search_type, search_count, create_time) VALUES
|
||||
(121, '游戏直播', 1, 3, '2026-01-03 20:00:00'),
|
||||
(121, '音乐', 1, 2, '2026-01-03 19:00:00'),
|
||||
(121, '美食教程', 2, 1, '2026-01-02 11:00:00'),
|
||||
(121, '旅行Vlog', 2, 2, '2026-01-02 10:00:00'),
|
||||
(121, '编程学习', 1, 4, '2026-01-01 13:00:00'),
|
||||
(121, '户外运动', 1, 1, '2026-01-01 09:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 6. 礼物打赏记录 (eb_gift_record)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_gift_record (uid, streamer_id, room_id, gift_id, gift_name, gift_price, quantity, total_price, create_time) VALUES
|
||||
(121, 1, 1, 1, '小红心', 1, 10, 10, '2026-01-03 20:40:00'),
|
||||
(121, 1, 1, 2, '鲜花', 5, 5, 25, '2026-01-03 20:45:00'),
|
||||
(121, 2, 2, 3, '棒棒糖', 10, 3, 30, '2026-01-03 21:20:00'),
|
||||
(121, 3, 3, 4, '火箭', 100, 1, 100, '2026-01-02 19:15:00'),
|
||||
(121, 4, 4, 1, '小红心', 1, 20, 20, '2026-01-02 12:35:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 7. 私聊会话记录 (eb_conversation)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_conversation (user1_id, user2_id, last_message, last_message_time, user1_unread, user2_unread, create_time) VALUES
|
||||
(121, 100, '你好,直播很精彩!', '2026-01-03 21:30:00', 0, 1, '2026-01-03 20:30:00'),
|
||||
(121, 101, '什么时候再开播?', '2026-01-03 16:00:00', 1, 0, '2026-01-03 15:30:00'),
|
||||
(102, 121, '感谢关注!', '2026-01-02 18:30:00', 0, 0, '2026-01-02 18:00:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 8. 私聊消息记录 (eb_private_message)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_private_message (conversation_id, sender_id, receiver_id, content, msg_type, is_read, create_time) VALUES
|
||||
-- 与用户100的对话
|
||||
(1, 121, 100, '你好,直播很精彩!', 'text', 1, '2026-01-03 21:30:00'),
|
||||
(1, 100, 121, '谢谢支持!', 'text', 1, '2026-01-03 21:31:00'),
|
||||
-- 与用户101的对话
|
||||
(2, 101, 121, '什么时候再开播?', 'text', 0, '2026-01-03 16:00:00'),
|
||||
(2, 121, 101, '明天晚上8点', 'text', 1, '2026-01-03 16:05:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 9. 好友关系 (eb_friend)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_friend (uid, friend_uid, remark, create_time) VALUES
|
||||
(121, 100, '游戏主播', '2026-01-03 21:35:00'),
|
||||
(121, 101, '音乐达人', '2026-01-03 16:10:00'),
|
||||
(100, 121, '道玄', '2026-01-03 21:35:00'),
|
||||
(101, 121, '道玄', '2026-01-03 16:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 10. 心愿记录 (eb_wish) - 许愿树功能
|
||||
-- =====================================================
|
||||
INSERT INTO eb_wish (uid, festival_id, content, background_id, like_count, comment_count, status, create_time) VALUES
|
||||
(121, 1, '希望新的一年事业顺利,身体健康!', 1, 15, 3, 1, '2026-01-01 00:05:00'),
|
||||
(121, 1, '愿家人平安幸福', 2, 8, 1, 1, '2026-01-01 00:10:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 11. 虚拟货币余额更新 (eb_user表)
|
||||
-- =====================================================
|
||||
UPDATE eb_user SET
|
||||
now_money = 500.00,
|
||||
integral = 1200,
|
||||
experience = 350
|
||||
WHERE uid = 121;
|
||||
|
||||
-- =====================================================
|
||||
-- 12. 充值记录 (eb_recharge_order)
|
||||
-- =====================================================
|
||||
INSERT INTO eb_recharge_order (uid, order_no, price, give_price, pay_type, paid, pay_time, create_time) VALUES
|
||||
(121, 'RC202601030001', 100.00, 10.00, 'alipay', 1, '2026-01-03 10:00:00', '2026-01-03 09:58:00'),
|
||||
(121, 'RC202601020001', 50.00, 5.00, 'wechat', 1, '2026-01-02 15:00:00', '2026-01-02 14:55:00'),
|
||||
(121, 'RC202601010001', 200.00, 30.00, 'alipay', 1, '2026-01-01 12:00:00', '2026-01-01 11:50:00');
|
||||
|
||||
-- =====================================================
|
||||
-- 验证插入的数据
|
||||
-- =====================================================
|
||||
SELECT '观看历史' as 类型, COUNT(*) as 数量 FROM eb_watch_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '直播间点赞', COUNT(*) FROM eb_live_room_like WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '作品点赞', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1
|
||||
UNION ALL
|
||||
SELECT '作品收藏', COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2
|
||||
UNION ALL
|
||||
SELECT '关注数', COUNT(*) FROM eb_follow_record WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '粉丝数', COUNT(*) FROM eb_follow_record WHERE follow_uid = 121
|
||||
UNION ALL
|
||||
SELECT '搜索历史', COUNT(*) FROM eb_search_history WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '礼物打赏', COUNT(*) FROM eb_gift_record WHERE uid = 121
|
||||
UNION ALL
|
||||
SELECT '好友数', COUNT(*) FROM eb_friend WHERE uid = 121;
|
||||
|
||||
SELECT '数据插入完成!用户道玄(ID:121)的测试数据已添加。' as 结果;
|
||||
33
test_view_history_api.bat
Normal file
33
test_view_history_api.bat
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
@echo off
|
||||
echo ========================================
|
||||
echo 测试观看历史API
|
||||
echo ========================================
|
||||
|
||||
REM 请替换为实际的Token和服务器地址
|
||||
set SERVER=http://1.15.149.240:8080
|
||||
set TOKEN=你的Token
|
||||
|
||||
echo.
|
||||
echo 1. 测试Token调试接口
|
||||
curl -X GET "%SERVER%/api/front/activity/debug/token" -H "Authori-zation: %TOKEN%" -H "Content-Type: application/json"
|
||||
|
||||
echo.
|
||||
echo.
|
||||
echo 2. 测试获取观看历史
|
||||
curl -X GET "%SERVER%/api/front/activity/view/history?page=1&pageSize=20" -H "Authori-zation: %TOKEN%" -H "Content-Type: application/json"
|
||||
|
||||
echo.
|
||||
echo.
|
||||
echo 3. 测试获取点赞记录
|
||||
curl -X GET "%SERVER%/api/front/activity/like/records?page=1&pageSize=20" -H "Authori-zation: %TOKEN%" -H "Content-Type: application/json"
|
||||
|
||||
echo.
|
||||
echo.
|
||||
echo 4. 测试获取关注记录
|
||||
curl -X GET "%SERVER%/api/front/activity/follow/records?page=1&pageSize=20" -H "Authori-zation: %TOKEN%" -H "Content-Type: application/json"
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo 测试完成
|
||||
echo ========================================
|
||||
pause
|
||||
248
user_activity_test_data.sql
Normal file
248
user_activity_test_data.sql
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
-- ============================================
|
||||
-- 用户活动记录测试数据
|
||||
-- 基于已有用户 (uid: 100-109) 生成
|
||||
-- ============================================
|
||||
|
||||
-- 先查看已有用户
|
||||
SELECT uid, nickname, phone FROM eb_user WHERE uid BETWEEN 100 AND 120 LIMIT 20;
|
||||
|
||||
-- 先查看已有直播间
|
||||
SELECT id, title, uid, streamer_name FROM eb_live_room LIMIT 10;
|
||||
|
||||
-- 先查看已有作品
|
||||
SELECT id, title, user_id FROM eb_works LIMIT 10;
|
||||
|
||||
-- ============================================
|
||||
-- 1. 观看历史测试数据 (eb_view_history)
|
||||
-- ============================================
|
||||
INSERT INTO `eb_view_history` (`user_id`, `target_type`, `target_id`, `target_title`, `view_duration`, `create_time`, `update_time`) VALUES
|
||||
-- 用户100的观看历史
|
||||
(100, 'room', '1', '欢乐直播间', 1800, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, 'room', '2', '音乐之夜', 3600, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(100, 'room', '3', '游戏竞技场', 2400, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(100, 'work', '1', '我的第一个作品', 120, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, 'work', '2', '精彩瞬间', 90, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(100, 'profile', '101', '林国瑞', 60, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
|
||||
-- 用户101的观看历史
|
||||
(101, 'room', '1', '欢乐直播间', 2700, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(101, 'room', '4', '美食探店', 1500, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(101, 'work', '3', '旅行日记', 180, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(101, 'profile', '100', '张吉惟', 45, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户102的观看历史
|
||||
(102, 'room', '2', '音乐之夜', 4200, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(102, 'room', '5', '户外探险', 1800, DATE_SUB(NOW(), INTERVAL 4 DAY), DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
(102, 'work', '1', '我的第一个作品', 150, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户103的观看历史
|
||||
(103, 'room', '1', '欢乐直播间', 900, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(103, 'room', '3', '游戏竞技场', 5400, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(103, 'work', '2', '精彩瞬间', 200, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(103, 'profile', '102', '王小明', 30, DATE_SUB(NOW(), INTERVAL 5 DAY), DATE_SUB(NOW(), INTERVAL 5 DAY)),
|
||||
|
||||
-- 用户104的观看历史
|
||||
(104, 'room', '2', '音乐之夜', 2100, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(104, 'work', '4', '日常生活', 80, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
|
||||
-- 用户105的观看历史
|
||||
(105, 'room', '1', '欢乐直播间', 3300, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(105, 'room', '4', '美食探店', 2400, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(105, 'profile', '103', '李小红', 55, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY))
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
view_duration = view_duration + VALUES(view_duration),
|
||||
update_time = NOW();
|
||||
|
||||
-- ============================================
|
||||
-- 2. 直播间点赞记录测试数据 (eb_live_room_like)
|
||||
-- ============================================
|
||||
INSERT INTO `eb_live_room_like` (`user_id`, `room_id`, `like_count`, `create_time`, `update_time`) VALUES
|
||||
-- 用户100点赞的直播间
|
||||
(100, 1, 15, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, 2, 8, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(100, 3, 22, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户101点赞的直播间
|
||||
(101, 1, 30, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(101, 4, 12, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户102点赞的直播间
|
||||
(102, 2, 45, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(102, 5, 18, DATE_SUB(NOW(), INTERVAL 4 DAY), DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
|
||||
-- 用户103点赞的直播间
|
||||
(103, 1, 5, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(103, 3, 88, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
|
||||
-- 用户104点赞的直播间
|
||||
(104, 2, 25, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(104, 1, 10, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户105点赞的直播间
|
||||
(105, 1, 50, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(105, 4, 33, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY))
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
like_count = like_count + VALUES(like_count),
|
||||
update_time = NOW();
|
||||
|
||||
-- ============================================
|
||||
-- 3. 作品关系测试数据 (eb_works_relation) - 点赞和收藏
|
||||
-- ============================================
|
||||
INSERT INTO `eb_works_relation` (`uid`, `works_id`, `type`, `create_time`) VALUES
|
||||
-- 用户100的点赞和收藏
|
||||
(100, 1, 'like', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, 2, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(100, 3, 'like', DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(100, 1, 'collect', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, 2, 'collect', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户101的点赞和收藏
|
||||
(101, 1, 'like', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(101, 3, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(101, 4, 'like', DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(101, 3, 'collect', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
|
||||
-- 用户102的点赞和收藏
|
||||
(102, 1, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(102, 2, 'like', DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(102, 1, 'collect', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(102, 4, 'collect', DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
|
||||
-- 用户103的点赞和收藏
|
||||
(103, 2, 'like', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(103, 5, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(103, 2, 'collect', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
|
||||
-- 用户104的点赞和收藏
|
||||
(104, 1, 'like', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(104, 4, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(104, 5, 'like', DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(104, 4, 'collect', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户105的点赞和收藏
|
||||
(105, 2, 'like', DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(105, 3, 'like', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(105, 3, 'collect', DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(105, 5, 'collect', DATE_SUB(NOW(), INTERVAL 3 DAY))
|
||||
|
||||
ON DUPLICATE KEY UPDATE create_time = VALUES(create_time);
|
||||
|
||||
-- ============================================
|
||||
-- 4. 搜索历史测试数据 (eb_search_history)
|
||||
-- ============================================
|
||||
INSERT INTO `eb_search_history` (`user_id`, `keyword`, `search_type`, `search_count`, `is_deleted`, `create_time`, `update_time`) VALUES
|
||||
-- 用户100的搜索历史
|
||||
(100, '游戏直播', 2, 5, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(100, '音乐', 0, 3, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(100, '美食', 3, 2, 0, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(100, '林国瑞', 1, 1, 0, DATE_SUB(NOW(), INTERVAL 4 DAY), DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
|
||||
-- 用户101的搜索历史
|
||||
(101, '户外', 2, 4, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(101, '旅行', 3, 6, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(101, '张吉惟', 1, 2, 0, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户102的搜索历史
|
||||
(102, '音乐直播', 2, 8, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(102, '唱歌', 0, 3, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户103的搜索历史
|
||||
(103, '电竞', 2, 10, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(103, 'LOL', 0, 5, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(103, '王者荣耀', 0, 7, 0, DATE_SUB(NOW(), INTERVAL 3 DAY), DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户104的搜索历史
|
||||
(104, '美食探店', 2, 4, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(104, '火锅', 3, 2, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户105的搜索历史
|
||||
(105, '舞蹈', 3, 6, 0, DATE_SUB(NOW(), INTERVAL 1 DAY), DATE_SUB(NOW(), INTERVAL 1 DAY)),
|
||||
(105, '健身', 0, 3, 0, DATE_SUB(NOW(), INTERVAL 2 DAY), DATE_SUB(NOW(), INTERVAL 2 DAY))
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
search_count = search_count + 1,
|
||||
update_time = NOW();
|
||||
|
||||
-- ============================================
|
||||
-- 5. 热门搜索测试数据 (eb_hot_search)
|
||||
-- ============================================
|
||||
INSERT INTO `eb_hot_search` (`keyword`, `search_type`, `hot_score`, `search_count`, `sort_order`, `status`, `create_time`, `update_time`) VALUES
|
||||
('游戏直播', 2, 1000, 500, 1, 1, NOW(), NOW()),
|
||||
('音乐', 0, 850, 420, 2, 1, NOW(), NOW()),
|
||||
('美食探店', 2, 780, 380, 3, 1, NOW(), NOW()),
|
||||
('户外探险', 2, 650, 320, 4, 1, NOW(), NOW()),
|
||||
('电竞比赛', 2, 600, 300, 5, 1, NOW(), NOW()),
|
||||
('舞蹈', 3, 550, 280, 6, 1, NOW(), NOW()),
|
||||
('旅行日记', 3, 500, 250, 7, 1, NOW(), NOW()),
|
||||
('健身教程', 3, 450, 220, 8, 1, NOW(), NOW()),
|
||||
('唱歌', 0, 400, 200, 9, 1, NOW(), NOW()),
|
||||
('搞笑视频', 3, 380, 190, 10, 1, NOW(), NOW())
|
||||
|
||||
ON DUPLICATE KEY UPDATE
|
||||
hot_score = VALUES(hot_score),
|
||||
search_count = VALUES(search_count),
|
||||
update_time = NOW();
|
||||
|
||||
-- ============================================
|
||||
-- 6. 关注记录补充数据 (eb_follow_record)
|
||||
-- 确保有足够的关注数据用于测试
|
||||
-- ============================================
|
||||
INSERT IGNORE INTO `eb_follow_record` (`follower_id`, `follower_nickname`, `followed_id`, `followed_nickname`, `follow_status`, `is_deleted`, `create_time`) VALUES
|
||||
-- 用户100关注的人
|
||||
(100, '吉惟同学', 101, '林国瑞', 1, 0, DATE_SUB(NOW(), INTERVAL 10 DAY)),
|
||||
(100, '吉惟同学', 102, '王小明', 1, 0, DATE_SUB(NOW(), INTERVAL 8 DAY)),
|
||||
(100, '吉惟同学', 103, '李小红', 1, 0, DATE_SUB(NOW(), INTERVAL 5 DAY)),
|
||||
|
||||
-- 用户101关注的人
|
||||
(101, '林国瑞', 100, '吉惟同学', 1, 0, DATE_SUB(NOW(), INTERVAL 9 DAY)),
|
||||
(101, '林国瑞', 104, '赵小刚', 1, 0, DATE_SUB(NOW(), INTERVAL 7 DAY)),
|
||||
|
||||
-- 用户102关注的人
|
||||
(102, '王小明', 100, '吉惟同学', 1, 0, DATE_SUB(NOW(), INTERVAL 6 DAY)),
|
||||
(102, '王小明', 101, '林国瑞', 1, 0, DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
(102, '王小明', 105, '孙小美', 1, 0, DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户103关注的人
|
||||
(103, '李小红', 100, '吉惟同学', 1, 0, DATE_SUB(NOW(), INTERVAL 5 DAY)),
|
||||
(103, '李小红', 102, '王小明', 1, 0, DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
|
||||
-- 用户104关注的人
|
||||
(104, '赵小刚', 101, '林国瑞', 1, 0, DATE_SUB(NOW(), INTERVAL 4 DAY)),
|
||||
(104, '赵小刚', 103, '李小红', 1, 0, DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
|
||||
-- 用户105关注的人
|
||||
(105, '孙小美', 100, '吉惟同学', 1, 0, DATE_SUB(NOW(), INTERVAL 3 DAY)),
|
||||
(105, '孙小美', 101, '林国瑞', 1, 0, DATE_SUB(NOW(), INTERVAL 2 DAY)),
|
||||
(105, '孙小美', 104, '赵小刚', 1, 0, DATE_SUB(NOW(), INTERVAL 1 DAY));
|
||||
|
||||
-- ============================================
|
||||
-- 7. 验证数据插入结果
|
||||
-- ============================================
|
||||
SELECT '观看历史' as table_name, COUNT(*) as count FROM eb_view_history
|
||||
UNION ALL
|
||||
SELECT '直播间点赞' as table_name, COUNT(*) as count FROM eb_live_room_like
|
||||
UNION ALL
|
||||
SELECT '作品关系(点赞/收藏)' as table_name, COUNT(*) as count FROM eb_works_relation
|
||||
UNION ALL
|
||||
SELECT '搜索历史' as table_name, COUNT(*) as count FROM eb_search_history
|
||||
UNION ALL
|
||||
SELECT '热门搜索' as table_name, COUNT(*) as count FROM eb_hot_search
|
||||
UNION ALL
|
||||
SELECT '关注记录' as table_name, COUNT(*) as count FROM eb_follow_record;
|
||||
|
||||
-- ============================================
|
||||
-- 8. 查看用户100的活动统计
|
||||
-- ============================================
|
||||
SELECT
|
||||
'用户100活动统计' as title,
|
||||
(SELECT COUNT(*) FROM eb_view_history WHERE user_id = 100) as view_count,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like WHERE user_id = 100) as liked_room_count,
|
||||
(SELECT COUNT(*) FROM eb_works_relation WHERE uid = 100 AND type = 'like') as liked_work_count,
|
||||
(SELECT COUNT(*) FROM eb_works_relation WHERE uid = 100 AND type = 'collect') as collected_work_count,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE follower_id = 100 AND follow_status = 1) as following_count,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE followed_id = 100 AND follow_status = 1) as follower_count,
|
||||
(SELECT COUNT(*) FROM eb_search_history WHERE user_id = 100 AND is_deleted = 0) as search_history_count;
|
||||
|
||||
SELECT '测试数据插入完成!' as message;
|
||||
47
verify_all_data_121.sql
Normal file
47
verify_all_data_121.sql
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
-- =====================================================
|
||||
-- 验证用户121的所有数据
|
||||
-- =====================================================
|
||||
|
||||
-- 1. 关注记录
|
||||
SELECT '=== 关注记录 ===' as 信息;
|
||||
SELECT fr.id, fr.followed_id as followedId, fr.followed_nickname as followedNickname,
|
||||
fr.follow_status as followStatus, fr.create_time as createTime
|
||||
FROM eb_follow_record fr
|
||||
WHERE fr.follower_id = 121
|
||||
AND (fr.follow_status = 1 OR fr.follow_status = '关注')
|
||||
ORDER BY fr.create_time DESC;
|
||||
|
||||
-- 2. 点赞记录 - 直播间
|
||||
SELECT '=== 直播间点赞 ===' as 信息;
|
||||
SELECT 'room' as targetType, CAST(rl.room_id AS CHAR) as targetId,
|
||||
lr.title as targetTitle, rl.create_time as createTime
|
||||
FROM eb_live_room_like rl
|
||||
LEFT JOIN eb_live_room lr ON rl.room_id = lr.id
|
||||
WHERE rl.user_id = 121;
|
||||
|
||||
-- 3. 点赞记录 - 作品
|
||||
SELECT '=== 作品点赞 ===' as 信息;
|
||||
SELECT 'work' as targetType, CAST(wr.works_id AS CHAR) as targetId,
|
||||
w.title as targetTitle, wr.create_time as createTime
|
||||
FROM eb_works_relation wr
|
||||
LEFT JOIN eb_works w ON wr.works_id = w.id
|
||||
WHERE wr.uid = 121 AND wr.type = 1;
|
||||
|
||||
-- 4. 收藏记录
|
||||
SELECT '=== 收藏记录 ===' as 信息;
|
||||
SELECT wr.works_id as workId, w.title, w.user_id as authorId,
|
||||
u.nickname as authorName, w.like_count as likeCount,
|
||||
w.collect_count as collectCount, wr.create_time as collectTime
|
||||
FROM eb_works_relation wr
|
||||
LEFT JOIN eb_works w ON wr.works_id = w.id
|
||||
LEFT JOIN eb_user u ON w.user_id = u.uid
|
||||
WHERE wr.uid = 121 AND wr.type = 2;
|
||||
|
||||
-- 5. 观看历史
|
||||
SELECT '=== 观看历史 ===' as 信息;
|
||||
SELECT target_type as targetType, target_id as targetId,
|
||||
target_title as targetTitle, view_duration as viewDuration,
|
||||
create_time as createTime
|
||||
FROM eb_view_history
|
||||
WHERE user_id = 121
|
||||
ORDER BY update_time DESC;
|
||||
70
verify_user_121_data.sql
Normal file
70
verify_user_121_data.sql
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
-- 验证用户121的所有测试数据
|
||||
-- ========================================
|
||||
|
||||
-- 1. 验证用户信息
|
||||
SELECT '=== 用户信息 ===' as info;
|
||||
SELECT uid, nickname, phone, avatar FROM eb_user WHERE uid = 121;
|
||||
|
||||
-- 2. 验证观看历史
|
||||
SELECT '=== 观看历史 (eb_view_history) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_view_history WHERE user_id = 121;
|
||||
SELECT id, user_id, target_type, target_id, target_title, view_duration, create_time
|
||||
FROM eb_view_history WHERE user_id = 121 ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
-- 3. 验证直播间点赞
|
||||
SELECT '=== 直播间点赞 (eb_live_room_like) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_live_room_like WHERE user_id = 121;
|
||||
SELECT rl.id, rl.user_id, rl.room_id, lr.title as room_title, rl.create_time
|
||||
FROM eb_live_room_like rl
|
||||
LEFT JOIN eb_live_room lr ON rl.room_id = lr.id
|
||||
WHERE rl.user_id = 121 ORDER BY rl.create_time DESC LIMIT 5;
|
||||
|
||||
-- 4. 验证作品点赞 (type=1)
|
||||
SELECT '=== 作品点赞 (eb_works_relation type=1) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_works_relation WHERE uid = 121 AND type = 1;
|
||||
SELECT wr.id, wr.uid, wr.works_id, w.title as work_title, wr.type, wr.create_time
|
||||
FROM eb_works_relation wr
|
||||
LEFT JOIN eb_works w ON wr.works_id = w.id
|
||||
WHERE wr.uid = 121 AND wr.type = 1 ORDER BY wr.create_time DESC LIMIT 5;
|
||||
|
||||
-- 5. 验证作品收藏 (type=2)
|
||||
SELECT '=== 作品收藏 (eb_works_relation type=2) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_works_relation WHERE uid = 121 AND type = 2;
|
||||
SELECT wr.id, wr.uid, wr.works_id, w.title as work_title, wr.type, wr.create_time
|
||||
FROM eb_works_relation wr
|
||||
LEFT JOIN eb_works w ON wr.works_id = w.id
|
||||
WHERE wr.uid = 121 AND wr.type = 2 ORDER BY wr.create_time DESC LIMIT 5;
|
||||
|
||||
-- 6. 验证关注记录
|
||||
SELECT '=== 关注记录 (eb_follow_record) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_follow_record WHERE follower_id = 121 AND (follow_status = 1 OR follow_status = '关注');
|
||||
SELECT fr.id, fr.follower_id, fr.followed_id, fr.followed_nickname, fr.follow_status, fr.create_time
|
||||
FROM eb_follow_record fr
|
||||
WHERE fr.follower_id = 121 AND (fr.follow_status = 1 OR fr.follow_status = '关注')
|
||||
ORDER BY fr.create_time DESC LIMIT 5;
|
||||
|
||||
-- 7. 验证搜索历史
|
||||
SELECT '=== 搜索历史 (eb_search_history) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_search_history WHERE user_id = 121 AND is_deleted = 0;
|
||||
SELECT id, user_id, keyword, search_type, create_time
|
||||
FROM eb_search_history WHERE user_id = 121 AND is_deleted = 0 ORDER BY create_time DESC LIMIT 5;
|
||||
|
||||
-- 8. 验证直播间数据
|
||||
SELECT '=== 直播间 (eb_live_room) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_live_room;
|
||||
SELECT id, title, streamer_name, is_live, like_count, view_count FROM eb_live_room LIMIT 5;
|
||||
|
||||
-- 9. 验证作品数据
|
||||
SELECT '=== 作品 (eb_works) ===' as info;
|
||||
SELECT COUNT(*) as total FROM eb_works;
|
||||
SELECT id, title, user_id, like_count, collect_count, view_count FROM eb_works LIMIT 5;
|
||||
|
||||
-- 10. 汇总统计
|
||||
SELECT '=== 数据汇总 ===' as info;
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM eb_view_history WHERE user_id = 121) as view_history_count,
|
||||
(SELECT COUNT(*) FROM eb_live_room_like WHERE user_id = 121) as room_like_count,
|
||||
(SELECT COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 1) as work_like_count,
|
||||
(SELECT COUNT(*) FROM eb_works_relation WHERE uid = 121 AND type = 2) as work_collect_count,
|
||||
(SELECT COUNT(*) FROM eb_follow_record WHERE follower_id = 121 AND (follow_status = 1 OR follow_status = '关注')) as follow_count,
|
||||
(SELECT COUNT(*) FROM eb_search_history WHERE user_id = 121 AND is_deleted = 0) as search_count;
|
||||
146
封禁系统功能说明.md
Normal file
146
封禁系统功能说明.md
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
# 封禁系统功能说明
|
||||
|
||||
## 功能概述
|
||||
|
||||
封禁系统提供用户封禁、房间封禁和黑名单管理功能,支持管理后台和移动端双端实时同步。
|
||||
|
||||
## 功能模块
|
||||
|
||||
### 1. 用户封禁(管理员功能)
|
||||
|
||||
管理员可以对违规用户进行封禁处理:
|
||||
|
||||
- **永久封禁**:用户账号永久禁用
|
||||
- **临时封禁**:设置封禁天数,到期自动解除
|
||||
- **解除封禁**:手动解除用户封禁状态
|
||||
- **封禁原因**:记录封禁原因,便于追溯
|
||||
|
||||
**API接口**:
|
||||
- `GET /api/admin/ban/user/list` - 获取用户封禁列表
|
||||
- `POST /api/admin/ban/user/add` - 封禁用户
|
||||
- `POST /api/admin/ban/user/unban/{id}` - 解除封禁
|
||||
- `POST /api/admin/ban/user/delete/{id}` - 删除记录
|
||||
- `GET /api/admin/ban/user/check/{userId}` - 检查封禁状态
|
||||
|
||||
### 2. 房间封禁(管理员功能)
|
||||
|
||||
管理员可以对违规直播间进行封禁处理:
|
||||
|
||||
- **永久封禁**:直播间永久关闭
|
||||
- **临时封禁**:设置封禁天数,到期自动解除
|
||||
- **解除封禁**:手动解除房间封禁状态
|
||||
- **封禁原因**:记录封禁原因
|
||||
|
||||
**API接口**:
|
||||
- `GET /api/admin/ban/room/list` - 获取房间封禁列表
|
||||
- `POST /api/admin/ban/room/add` - 封禁房间
|
||||
- `POST /api/admin/ban/room/unban/{id}` - 解除封禁
|
||||
- `POST /api/admin/ban/room/delete/{id}` - 删除记录
|
||||
- `GET /api/admin/ban/room/check/{roomId}` - 检查封禁状态
|
||||
|
||||
### 3. 用户黑名单(用户功能)
|
||||
|
||||
用户可以将其他用户加入黑名单:
|
||||
|
||||
- **添加黑名单**:屏蔽指定用户
|
||||
- **移除黑名单**:解除屏蔽
|
||||
- **黑名单列表**:查看已屏蔽的用户
|
||||
- **互动限制**:被拉黑用户无法发送消息、评论等
|
||||
|
||||
**移动端API接口**:
|
||||
- `GET /api/front/ban/check/me` - 检查当前用户封禁状态
|
||||
- `GET /api/front/ban/check/user/{userId}` - 检查指定用户封禁状态
|
||||
- `GET /api/front/ban/check/room/{roomId}` - 检查房间封禁状态
|
||||
- `GET /api/front/ban/blacklist/list` - 获取我的黑名单
|
||||
- `POST /api/front/ban/blacklist/add` - 添加到黑名单
|
||||
- `POST /api/front/ban/blacklist/remove` - 从黑名单移除
|
||||
- `GET /api/front/ban/blacklist/check/{targetUserId}` - 检查黑名单状态
|
||||
|
||||
## 数据库表结构
|
||||
|
||||
### eb_user_ban(用户封禁表)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | bigint | 主键 |
|
||||
| user_id | int | 被封禁用户ID |
|
||||
| ban_type | varchar(20) | 封禁类型:permanent/temporary |
|
||||
| reason | varchar(500) | 封禁原因 |
|
||||
| duration_days | int | 封禁天数 |
|
||||
| expire_time | datetime | 到期时间 |
|
||||
| operator_id | int | 操作人ID |
|
||||
| status | tinyint | 状态:1-生效,0-已解除 |
|
||||
|
||||
### eb_room_ban(房间封禁表)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | bigint | 主键 |
|
||||
| room_id | int | 被封禁房间ID |
|
||||
| ban_type | varchar(20) | 封禁类型 |
|
||||
| reason | varchar(500) | 封禁原因 |
|
||||
| duration_days | int | 封禁天数 |
|
||||
| expire_time | datetime | 到期时间 |
|
||||
| operator_id | int | 操作人ID |
|
||||
| status | tinyint | 状态 |
|
||||
|
||||
### eb_user_blacklist(用户黑名单表)
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | bigint | 主键 |
|
||||
| user_id | int | 用户ID(发起拉黑) |
|
||||
| blocked_user_id | int | 被拉黑用户ID |
|
||||
| blocker_nickname | varchar(100) | 拉黑者昵称 |
|
||||
| blocked_nickname | varchar(100) | 被拉黑者昵称 |
|
||||
| create_time | datetime | 创建时间 |
|
||||
|
||||
## 部署步骤
|
||||
|
||||
1. **执行数据库脚本**
|
||||
```bash
|
||||
mysql -u root -p zhibo < ban_system_tables.sql
|
||||
mysql -u root -p zhibo < add_ban_menus.sql
|
||||
```
|
||||
|
||||
2. **部署后端**
|
||||
```bash
|
||||
deploy_ban_system.bat
|
||||
```
|
||||
|
||||
3. **部署管理后台前端**
|
||||
- 确保 `Zhibo/admin/src/views/ban/userBan.vue` 和 `roomBan.vue` 已添加
|
||||
- 确保 `Zhibo/admin/src/api/ban.js` 已添加
|
||||
- 重新编译部署前端
|
||||
|
||||
4. **编译Android App**
|
||||
- 确保 `BlacklistActivity.java` 已添加
|
||||
- 确保布局文件已添加
|
||||
- 重新编译APK
|
||||
|
||||
## 双端同步机制
|
||||
|
||||
1. **管理后台封禁用户** → 用户状态更新 → 移动端检测到封禁状态 → 显示封禁提示
|
||||
2. **移动端添加黑名单** → 数据库更新 → 管理后台可查看黑名单记录
|
||||
3. **管理后台解除封禁** → 用户状态恢复 → 移动端可正常使用
|
||||
|
||||
## 文件清单
|
||||
|
||||
### 后端文件
|
||||
- `Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/BanController.java`
|
||||
- `Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/BanFrontController.java`
|
||||
- `Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/BlacklistController.java`(已更新)
|
||||
|
||||
### 管理后台前端文件
|
||||
- `Zhibo/admin/src/views/ban/userBan.vue`
|
||||
- `Zhibo/admin/src/views/ban/roomBan.vue`
|
||||
- `Zhibo/admin/src/api/ban.js`
|
||||
- `Zhibo/admin/src/api/blacklist.js`
|
||||
|
||||
### Android文件
|
||||
- `android-app/app/src/main/java/com/example/livestreaming/BlacklistActivity.java`
|
||||
- `android-app/app/src/main/java/com/example/livestreaming/net/ApiService.java`(已更新)
|
||||
- `android-app/app/src/main/res/layout/activity_blacklist.xml`
|
||||
- `android-app/app/src/main/res/layout/item_blacklist.xml`
|
||||
- `android-app/app/src/main/res/drawable/bg_button_outline_primary.xml`
|
||||
|
||||
### SQL脚本
|
||||
- `ban_system_tables.sql` - 创建数据库表
|
||||
- `add_ban_menus.sql` - 添加菜单配置
|
||||
130
我的记录数据不显示问题排查.md
Normal file
130
我的记录数据不显示问题排查.md
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# 我的记录数据不显示问题排查
|
||||
|
||||
## 问题描述
|
||||
- 管理端显示用户"道玄"(ID: 121)有完整的活动记录数据
|
||||
- 移动端"我的记录"页面显示"暂无记录"
|
||||
|
||||
## 问题分析
|
||||
|
||||
### 数据流程
|
||||
```
|
||||
Android App → HTTP请求(带Token) → 后端拦截器验证Token → Controller获取userId → Service查询数据 → 返回结果
|
||||
```
|
||||
|
||||
### 关键代码路径
|
||||
1. **Android端Token发送**: `ApiClient.java` 中的 `auth` 拦截器
|
||||
2. **后端Token验证**: `FrontTokenInterceptor.java` → `FrontTokenComponent.check()`
|
||||
3. **获取用户ID**: `UserService.getUserId()` → `FrontTokenComponent.getUserId()`
|
||||
4. **数据查询**: `UserActivityRecordService.getViewHistory()` 等方法
|
||||
|
||||
### 可能的问题原因
|
||||
|
||||
1. **Token未正确发送**
|
||||
- `ApiClient.appContext` 为 null
|
||||
- `AuthStore.getToken()` 返回 null
|
||||
|
||||
2. **Token在Redis中不存在或已过期**
|
||||
- Token过期时间: 24小时 (`TOKEN_EXPRESS_MINUTES = 60 * 24`)
|
||||
- Redis key格式: `TOKEN_USER:` + token
|
||||
|
||||
3. **Token格式不匹配**
|
||||
- 后端期望的Header: `Authori-zation`(注意中间有连字符)
|
||||
|
||||
## 已添加的调试日志
|
||||
|
||||
### Android端 (Logcat TAG: MyRecords, ApiClient)
|
||||
```
|
||||
加载记录: type=view, page=1, userId=xxx
|
||||
Token状态: 存在, 长度=32, 前20字符=xxx...
|
||||
请求URL: http://xxx/api/front/activity/view/history
|
||||
请求头Authori-zation: xxx
|
||||
添加Token到请求头: xxx...
|
||||
```
|
||||
|
||||
### 后端 (搜索关键字)
|
||||
```
|
||||
[FrontTokenInterceptor] URI=xxx, rawToken=xxx, processedToken=xxx
|
||||
[FrontTokenInterceptor] Token验证结果: true/false
|
||||
[FrontTokenComponent] getUserId: rawToken=xxx, processedToken=xxx, redisKey=xxx, exists=true/false, userId=xxx
|
||||
【观看历史】请求头Token: xxx
|
||||
【观看历史】请求参数: userId=xxx, targetType=xxx, page=1, pageSize=20
|
||||
【观看历史】返回结果: userId=xxx, total=xxx, listSize=xxx
|
||||
```
|
||||
|
||||
## 调试步骤
|
||||
|
||||
### 1. 检查Android端Token
|
||||
```bash
|
||||
# 在Logcat中过滤
|
||||
adb logcat -s MyRecords ApiClient AuthStore
|
||||
```
|
||||
|
||||
预期输出:
|
||||
- Token状态: 存在
|
||||
- 添加Token到请求头: xxx...
|
||||
|
||||
### 2. 检查后端Token验证
|
||||
查看后端日志,搜索 `[FrontTokenInterceptor]`
|
||||
|
||||
预期输出:
|
||||
- rawToken 不为 null
|
||||
- Token验证结果: true
|
||||
|
||||
### 3. 检查Redis中的Token
|
||||
```bash
|
||||
# 连接Redis
|
||||
redis-cli
|
||||
|
||||
# 查看Token是否存在
|
||||
EXISTS TOKEN_USER:your_token_here
|
||||
|
||||
# 查看Token对应的userId
|
||||
GET TOKEN_USER:your_token_here
|
||||
```
|
||||
|
||||
### 4. 使用调试接口
|
||||
Android端会自动调用 `api/front/activity/debug/token` 接口,查看返回结果:
|
||||
```json
|
||||
{
|
||||
"header_Authori-zation": "xxx",
|
||||
"header_Authorization": "xxx",
|
||||
"userId": 121,
|
||||
"isLoggedIn": true
|
||||
}
|
||||
```
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 如果Token未发送
|
||||
1. 确保登录成功后Token已保存到SharedPreferences
|
||||
2. 检查 `AuthStore.setToken()` 是否被正确调用
|
||||
|
||||
### 如果Token已过期
|
||||
1. 重新登录获取新Token
|
||||
2. 或者在Redis中手动延长Token过期时间
|
||||
|
||||
### 如果Token格式不匹配
|
||||
1. 确保Android端发送的Header名称是 `Authori-zation`
|
||||
2. 确保Token值不包含前缀 `TOKEN_USER:`
|
||||
|
||||
## 修改的文件列表
|
||||
|
||||
1. `zhibo/android-app/app/src/main/java/com/example/livestreaming/net/ApiClient.java`
|
||||
- 增强Token拦截器日志
|
||||
|
||||
2. `zhibo/android-app/app/src/main/java/com/example/livestreaming/MyRecordsActivity.java`
|
||||
- 增加Token调试方法
|
||||
- 增强请求日志
|
||||
|
||||
3. `zhibo/android-app/app/src/main/java/com/example/livestreaming/net/ApiService.java`
|
||||
- 添加调试接口 `debugToken()`
|
||||
|
||||
4. `zhibo/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/interceptor/FrontTokenInterceptor.java`
|
||||
- 增强Token验证日志
|
||||
|
||||
5. `zhibo/Zhibo/zhibo-h/crmeb-common/src/main/java/com/zbkj/common/token/FrontTokenComponent.java`
|
||||
- 增强 `getUserId()` 方法日志
|
||||
|
||||
6. `zhibo/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/UserActivityRecordController.java`
|
||||
- 增强各接口的请求日志
|
||||
- 添加调试接口 `/debug/token`
|
||||
79
接口配置检查报告.md
Normal file
79
接口配置检查报告.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# 接口配置检查报告
|
||||
|
||||
## 一、后端接口配置
|
||||
|
||||
### 1. 前端 API (UserActivityRecordController)
|
||||
路径前缀: `api/front/activity`
|
||||
|
||||
| 接口 | 方法 | 路径 | 状态 |
|
||||
|------|------|------|------|
|
||||
| 记录观看历史 | POST | /view/record | ✅ |
|
||||
| 获取观看历史 | GET | /view/history | ✅ |
|
||||
| 删除单条观看历史 | DELETE | /view/history/{historyId} | ✅ |
|
||||
| 清空观看历史 | DELETE | /view/history | ✅ |
|
||||
| 获取点赞记录 | GET | /like/records | ✅ |
|
||||
| 获取点赞的直播间 | GET | /like/rooms | ✅ |
|
||||
| 获取点赞的作品 | GET | /like/works | ✅ |
|
||||
| 获取点赞的心愿 | GET | /like/wishes | ✅ |
|
||||
| 获取关注记录 | GET | /follow/records | ✅ |
|
||||
| 获取收藏的作品 | GET | /collect/works | ✅ |
|
||||
| 获取用户活动统计 | GET | /stats | ✅ |
|
||||
|
||||
### 2. 管理端 API (UserActivityController)
|
||||
路径前缀: `api/admin/user`
|
||||
|
||||
| 接口 | 方法 | 路径 | 状态 |
|
||||
|------|------|------|------|
|
||||
| 获取用户关注记录 | GET | /follow/records | ✅ |
|
||||
| 获取用户点赞记录 | GET | /like/records | ✅ |
|
||||
| 获取用户查看历史 | GET | /view/history | ✅ |
|
||||
| 获取用户收藏的作品 | GET | /collect/works | ✅ |
|
||||
| 获取用户活动统计 | GET | /activity/stats | ✅ |
|
||||
|
||||
## 二、Android 端接口配置 (ApiService.java)
|
||||
|
||||
| 接口 | 方法 | 路径 | 与后端匹配 |
|
||||
|------|------|------|------|
|
||||
| recordViewHistoryNew | POST | api/front/activity/view/record | ✅ |
|
||||
| getViewHistory | GET | api/front/activity/view/history | ✅ |
|
||||
| deleteViewHistory | DELETE | api/front/activity/view/history/{historyId} | ✅ |
|
||||
| clearViewHistory | DELETE | api/front/activity/view/history | ✅ |
|
||||
| getLikeRecords | GET | api/front/activity/like/records | ✅ |
|
||||
| getLikedRoomsNew | GET | api/front/activity/like/rooms | ✅ |
|
||||
| getLikedWorks | GET | api/front/activity/like/works | ✅ |
|
||||
| getLikedWishes | GET | api/front/activity/like/wishes | ✅ |
|
||||
| getFollowRecords | GET | api/front/activity/follow/records | ✅ |
|
||||
| getCollectedWorks | GET | api/front/activity/collect/works | ✅ |
|
||||
| getUserActivityStats | GET | api/front/activity/stats | ✅ |
|
||||
|
||||
## 三、管理端前端接口配置 (userActivity.js)
|
||||
|
||||
| 接口 | 方法 | 路径 | 与后端匹配 |
|
||||
|------|------|------|------|
|
||||
| getFollowRecords | GET | /admin/user/follow/records | ✅ |
|
||||
| getLikeRecords | GET | /admin/user/like/records | ✅ |
|
||||
| getViewHistory | GET | /admin/user/view/history | ✅ |
|
||||
| getCollectedWorks | GET | /admin/user/collect/works | ✅ |
|
||||
| getUserActivityStats | GET | /admin/user/activity/stats | ✅ |
|
||||
|
||||
> 注:管理端前端 baseURL 为 `/api`,所以实际请求路径为 `/api/admin/user/...`
|
||||
|
||||
## 四、数据库表配置
|
||||
|
||||
| 表名 | 用途 | 状态 |
|
||||
|------|------|------|
|
||||
| eb_view_history | 查看历史记录 | ✅ 已创建 |
|
||||
| eb_live_room_like | 直播间点赞记录 | ✅ 已创建 |
|
||||
| eb_wish_like | 心愿点赞记录 | ✅ 已创建 |
|
||||
| eb_search_history | 搜索历史 | ✅ 已创建 |
|
||||
| eb_hot_search | 热门搜索 | ✅ 已创建 |
|
||||
| eb_works_relation | 作品关系(点赞、收藏) | ✅ 已创建 |
|
||||
|
||||
## 五、检查结论
|
||||
|
||||
✅ **所有接口配置正确,前后端路径匹配**
|
||||
|
||||
### 部署注意事项:
|
||||
1. 后端需要重新编译部署
|
||||
2. 管理端前端需要重新构建部署
|
||||
3. Android 端需要重新编译 APK
|
||||
554
直播平台功能清单报告.md
Normal file
554
直播平台功能清单报告.md
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
# 直播平台功能清单报告
|
||||
|
||||
> 生成日期:2026年1月4日
|
||||
> 项目状态:开发中
|
||||
> 整体完成度:82%
|
||||
|
||||
---
|
||||
|
||||
## 项目概览
|
||||
|
||||
本项目是一个完整的直播社交平台,包含:
|
||||
- **Android移动端**:40+ Activity,95+ 布局文件,60+ API接口
|
||||
- **Java后端**:完整的直播间、礼物、用户、社交等模块
|
||||
- **Node.js直播服务**:SRS服务器 + WebSocket实时通信
|
||||
- **数据库**:50+ 表,覆盖用户、直播、社交、交易等业务
|
||||
|
||||
---
|
||||
|
||||
# 一、Android App 功能
|
||||
|
||||
## 1. 用户系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 手机号验证码登录 | ✅ | 已实现 |
|
||||
| 账号密码登录 | ✅ | 已实现 |
|
||||
| 用户注册 | ✅ | 手机号+验证码 |
|
||||
| 个人中心 | ✅ | 头像、昵称、签名、性别、生日、地区 |
|
||||
| 编辑个人资料 | ✅ | 已实现 |
|
||||
| 查看他人主页 | ✅ | 显示关注/粉丝/获赞数 |
|
||||
| 设置页面 | ✅ | 账号、隐私、通知、关于 |
|
||||
| 第三方登录(微信/QQ) | ⏳ | 待实现 |
|
||||
| 忘记密码 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
## 2. 直播功能
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 首页直播间列表 | ✅ | 瀑布流2列展示 |
|
||||
| 分类标签筛选 | ✅ | 推荐/游戏/才艺/户外/音乐 |
|
||||
| 顶部Tab切换 | ✅ | 关注/推荐/附近 |
|
||||
| 直播间详情页 | ✅ | 双引擎播放(ExoPlayer+IjkPlayer) |
|
||||
| 实时弹幕 | ✅ | WebSocket,心跳检测、断线重连 |
|
||||
| 礼物打赏 | ✅ | 礼物列表、发送、动画效果 |
|
||||
| 搜索主播/直播间 | ✅ | 文字+语音搜索 |
|
||||
| 手机开播(RTMP推流) | ⚠️ | 前端已实现,后端接口待完善 |
|
||||
| 直播间点赞 | ✅ | 无限次点赞,带动画 |
|
||||
| 在线人数显示 | ✅ | 实时更新 |
|
||||
| 下拉刷新/上拉加载 | ✅ | 已实现 |
|
||||
| 全屏切换 | ✅ | 已实现 |
|
||||
| 观众列表 | ⏳ | 待实现 |
|
||||
| 直播间公告 | ⏳ | 待实现 |
|
||||
| 直播间分享 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
## 3. 主播系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 主播认证申请 | ✅ | 已实现 |
|
||||
| 主播中心 | ✅ | 粉丝数、获赞数、收益统计 |
|
||||
| 主播等级显示 | ✅ | 已实现 |
|
||||
| 魅力值统计 | ✅ | 已实现 |
|
||||
| 创建粉丝团 | ⏳ | 待实现 |
|
||||
| 粉丝团成员管理 | ⏳ | 待实现 |
|
||||
| 粉丝团等级 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:75%**
|
||||
|
||||
---
|
||||
|
||||
## 4. 社交功能
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 关注/取消关注 | ✅ | 已实现 |
|
||||
| 关注列表 | ✅ | 已实现 |
|
||||
| 粉丝列表 | ✅ | 已实现 |
|
||||
| 好友列表 | ✅ | 显示在线状态 |
|
||||
| 添加好友 | ✅ | 好友请求处理(同意/拒绝) |
|
||||
| 删除好友 | ✅ | 已实现 |
|
||||
| 拉黑好友 | ✅ | 已实现 |
|
||||
| 黑名单管理 | ✅ | 已实现 |
|
||||
| 点赞的直播间列表 | ⏳ | 待实现 |
|
||||
| 好友分组 | ⏳ | 待实现 |
|
||||
| 好友备注 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
## 5. 消息系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 消息/会话列表 | ✅ | 头像、昵称、最后消息、未读数 |
|
||||
| 会话搜索 | ✅ | 已实现 |
|
||||
| 私信聊天 | ✅ | 文本/图片/语音消息 |
|
||||
| 消息已读状态 | ✅ | 已实现 |
|
||||
| 会话删除 | ✅ | 已实现 |
|
||||
| 系统通知 | ✅ | 已实现 |
|
||||
| 通知设置 | ✅ | 已实现 |
|
||||
| WebSocket实时推送 | ✅ | 已实现 |
|
||||
| 删除单条消息 | ⏳ | 待实现 |
|
||||
| 消息表情回应 | ⏳ | 待实现 |
|
||||
| 视频消息 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:80%**
|
||||
|
||||
---
|
||||
|
||||
## 6. 通话功能
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 语音通话 | ✅ | 已实现 |
|
||||
| 视频通话 | ✅ | 已实现 |
|
||||
| 来电界面 | ✅ | 已实现 |
|
||||
| 通话记录 | ✅ | 已实现 |
|
||||
| 通话管理 | ✅ | CallManager |
|
||||
| WebRTC优化 | ⏳ | 待优化 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
## 7. 群组功能
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 群组列表 | ✅ | 已实现 |
|
||||
| 创建群组 | ✅ | 已实现 |
|
||||
| 群组详情 | ✅ | 成员列表、群信息 |
|
||||
| 群聊天 | ✅ | 已实现 |
|
||||
| 添加/移除成员 | ✅ | 已实现 |
|
||||
| 转让群主 | ✅ | 已实现 |
|
||||
| 解散/退出群组 | ✅ | 已实现 |
|
||||
| 群组信息编辑 | ✅ | 已实现 |
|
||||
| 群组公告 | ⏳ | 待实现 |
|
||||
| 群组权限管理 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
## 8. 钱包系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 钱包余额显示 | ✅ | 金币余额 |
|
||||
| 充值功能 | ✅ | 支付宝/微信支付 |
|
||||
| 充值套餐 | ✅ | 已实现 |
|
||||
| 创建充值订单 | ✅ | 已实现 |
|
||||
| 交易/充值记录 | ✅ | 已实现 |
|
||||
| 提现功能 | ⏳ | 待实现 |
|
||||
| 收益明细 | ⏳ | 待完善 |
|
||||
|
||||
**模块完成度:80%**
|
||||
|
||||
---
|
||||
|
||||
## 9. 娱乐功能
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 缘池(鱼塘匹配) | ✅ | 轨道式用户展示,6头像环绕动画 |
|
||||
| 许愿树主页 | ✅ | 节日横幅、倒计时、祈愿值 |
|
||||
| 发布心愿 | ✅ | 50字限制,最多7个 |
|
||||
| 查看/删除心愿 | ✅ | 已实现 |
|
||||
| 愿望达成 | ✅ | 带庆祝动画 |
|
||||
| 许愿树心愿列表 | ⏳ | 待实现 |
|
||||
| 心愿点赞/评论 | ⏳ | 待实现 |
|
||||
| 语音匹配 | ⚠️ | 页面已有,功能待完善 |
|
||||
| 心动信号 | ⚠️ | 页面已有,功能待完善 |
|
||||
| 在线交友 | ⚠️ | 页面已有,功能待完善 |
|
||||
| 游戏大厅 | ⚠️ | KTV、你画我猜、桌游入口已有 |
|
||||
| 动态社区 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:60%**
|
||||
|
||||
---
|
||||
|
||||
## 10. 作品系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 发布作品 | ✅ | 图片/视频,标题、描述、分类、标签、位置 |
|
||||
| 作品详情 | ✅ | 已实现 |
|
||||
| 作品编辑 | ✅ | 已实现 |
|
||||
| 作品删除 | ✅ | 已实现 |
|
||||
| 作品点赞 | ✅ | 已实现 |
|
||||
| 作品收藏 | ✅ | 已实现 |
|
||||
| 观看历史 | ✅ | 已实现 |
|
||||
| 用户作品列表 | ✅ | 已实现 |
|
||||
| 收藏列表 | ✅ | 已实现 |
|
||||
| 赞过列表 | ✅ | 已实现 |
|
||||
| 作品评论 | ⏳ | 待实现 |
|
||||
| 作品分享 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
## 11. 搜索模块
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 文字搜索 | ✅ | 已实现 |
|
||||
| 语音搜索 | ✅ | 已实现 |
|
||||
| 搜索建议 | ✅ | 已实现 |
|
||||
| 搜索历史 | ✅ | 已实现 |
|
||||
| 热搜词显示 | ✅ | 已实现 |
|
||||
| 搜索结果分类 | ✅ | 用户/房间/作品 |
|
||||
| 综合搜索 | ⏳ | 待优化 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
# 二、管理后台功能
|
||||
|
||||
## 1. 用户管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 用户列表 | ✅ | 查看、编辑、禁用 |
|
||||
| 用户详情 | ✅ | 已实现 |
|
||||
| 用户等级管理 | ✅ | 已实现 |
|
||||
| 用户分组管理 | ✅ | 已实现 |
|
||||
| 用户签到管理 | ✅ | 已实现 |
|
||||
| 用户聊天记录 | ✅ | 已实现 |
|
||||
| 用户认证审核 | ✅ | 已实现 |
|
||||
| 用户黑名单 | ✅ | 已实现 |
|
||||
|
||||
**模块完成度:95%**
|
||||
|
||||
---
|
||||
|
||||
## 2. 直播管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 直播间列表 | ✅ | 查看、关闭、封禁 |
|
||||
| 直播间详情 | ✅ | 已实现 |
|
||||
| 直播间分类管理 | ✅ | 已实现 |
|
||||
| 直播间背景管理 | ✅ | 已实现 |
|
||||
| 直播状态管理 | ✅ | 已实现 |
|
||||
| 直播间搜索 | ✅ | 已实现 |
|
||||
| 开始/结束直播接口 | ⏳ | 后端待实现 |
|
||||
| 实时监控 | ⏳ | 待完善 |
|
||||
|
||||
**模块完成度:80%**
|
||||
|
||||
---
|
||||
|
||||
## 3. 主播管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 主播列表 | ✅ | 审核、管理 |
|
||||
| 主播详情 | ✅ | 已实现 |
|
||||
| 主播认证审核 | ✅ | 已实现 |
|
||||
| 主播等级管理 | ✅ | 已实现 |
|
||||
| 主播家族管理 | ✅ | 已实现 |
|
||||
| 主播统计数据 | ✅ | 粉丝数、魅力值 |
|
||||
| 魅力等级配置 | ✅ | 已实现 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
## 4. 礼物系统
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 礼物列表管理 | ✅ | 添加、编辑、上下架 |
|
||||
| 礼物配置 | ✅ | 图标、价格、动画 |
|
||||
| 礼物打赏记录 | ✅ | 已实现 |
|
||||
| 充值套餐配置 | ✅ | 已实现 |
|
||||
| 虚拟货币管理 | ✅ | 已实现 |
|
||||
| 礼物排行榜 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
## 5. 财务管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 充值订单管理 | ✅ | 已实现 |
|
||||
| 交易记录 | ✅ | 已实现 |
|
||||
| 收益明细 | ✅ | 礼物、钻石、金币 |
|
||||
| 提现审核 | ⏳ | 待审核、已审核 |
|
||||
| 佣金管理 | ⏳ | 待实现 |
|
||||
| 财务统计报表 | ⏳ | 待完善 |
|
||||
|
||||
**模块完成度:70%**
|
||||
|
||||
---
|
||||
|
||||
## 6. 社交管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 好友关系管理 | ✅ | 已实现 |
|
||||
| 关注记录管理 | ✅ | 已实现 |
|
||||
| 群组管理 | ✅ | 已实现 |
|
||||
| 群组成员管理 | ✅ | 已实现 |
|
||||
| 粉丝团管理 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
## 7. 娱乐功能管理
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 许愿树节日管理 | ✅ | 已实现 |
|
||||
| 心愿管理 | ✅ | 发布、审核 |
|
||||
| 心愿点赞管理 | ✅ | 已实现 |
|
||||
| 心愿评论管理 | ✅ | 已实现 |
|
||||
| 背景素材管理 | ✅ | 已实现 |
|
||||
| 缘池话题管理 | ⏳ | 待实现 |
|
||||
| 匹配配置 | ⏳ | 待实现 |
|
||||
| CP配对管理 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:70%**
|
||||
|
||||
---
|
||||
|
||||
## 8. 系统设置
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 管理员权限管理 | ✅ | 已实现 |
|
||||
| 菜单管理 | ✅ | 已实现 |
|
||||
| 系统消息管理 | ✅ | 已实现 |
|
||||
| 短信配置 | ✅ | 已实现 |
|
||||
| 版本管理 | ✅ | 已实现 |
|
||||
| 黑名单管理 | ✅ | 已实现 |
|
||||
| 验证码管理 | ✅ | 已实现 |
|
||||
| 推送通知配置 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:90%**
|
||||
|
||||
---
|
||||
|
||||
## 9. 数据统计
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|:----:|------|
|
||||
| 仪表盘概览 | ✅ | 已实现 |
|
||||
| 用户统计 | ✅ | 活跃度、新增、留存 |
|
||||
| 收益统计 | ✅ | 礼物收入、充值统计 |
|
||||
| 直播间热度统计 | ✅ | 已实现 |
|
||||
| 主播数据统计 | ✅ | 已实现 |
|
||||
| 通话统计 | ⏳ | 待实现 |
|
||||
|
||||
**模块完成度:85%**
|
||||
|
||||
---
|
||||
|
||||
# 三、技术架构
|
||||
|
||||
## 已实现的核心技术
|
||||
|
||||
### 1. 实时通信
|
||||
- ✅ WebSocket弹幕系统(心跳检测、断线重连)
|
||||
- ✅ WebSocket私聊消息推送
|
||||
- ✅ WebSocket在线状态推送
|
||||
- ✅ WebSocket在线人数推送
|
||||
|
||||
### 2. 多媒体支持
|
||||
- ✅ 双引擎视频播放(ExoPlayer + IjkPlayer)
|
||||
- ✅ HLS流支持
|
||||
- ✅ FLV流支持
|
||||
- ✅ RTMP推流
|
||||
- ✅ 图片上传和加载
|
||||
- ✅ 视频上传和处理
|
||||
|
||||
### 3. 支付系统
|
||||
- ✅ 支付宝集成
|
||||
- ✅ 微信支付集成
|
||||
- ✅ 虚拟货币充值
|
||||
- ✅ 交易记录管理
|
||||
|
||||
### 4. 动画效果
|
||||
- ✅ 轨道式用户展示动画
|
||||
- ✅ 呼吸脉冲动画
|
||||
- ✅ 点赞缩放动画
|
||||
- ✅ 庆祝动画
|
||||
- ✅ 列表加载动画
|
||||
- ✅ 礼物动画效果
|
||||
|
||||
---
|
||||
|
||||
# 四、API接口统计
|
||||
|
||||
| 分类 | 已实现 | 待实现 |
|
||||
|------|:------:|:------:|
|
||||
| 用户认证 | 5 | 2 |
|
||||
| 直播间 | 10 | 3 |
|
||||
| 礼物打赏 | 6 | 1 |
|
||||
| 私聊会话 | 7 | 4 |
|
||||
| 好友管理 | 9 | 2 |
|
||||
| 关注功能 | 7 | 1 |
|
||||
| 作品管理 | 12 | 2 |
|
||||
| 文件上传 | 2 | 0 |
|
||||
| 在线状态 | 4 | 1 |
|
||||
| 离线消息 | 3 | 0 |
|
||||
| 搜索功能 | 5 | 1 |
|
||||
| 观看历史 | 1 | 0 |
|
||||
| 分类管理 | 2 | 0 |
|
||||
| **合计** | **73** | **17** |
|
||||
|
||||
**接口完成率:81%**
|
||||
|
||||
---
|
||||
|
||||
# 五、数据库表结构
|
||||
|
||||
## 表分类统计
|
||||
|
||||
| 分类 | 表数量 | 说明 |
|
||||
|------|:------:|------|
|
||||
| 用户相关 | 10+ | eb_user, eb_user_level, eb_user_address 等 |
|
||||
| 直播相关 | 8+ | eb_live_room, eb_live_category, eb_live_danmu 等 |
|
||||
| 社交相关 | 8+ | eb_friend, eb_follow_record, eb_group 等 |
|
||||
| 消息相关 | 5+ | eb_private_message, eb_conversation 等 |
|
||||
| 礼物相关 | 5+ | eb_gift, eb_gift_record, eb_recharge_package 等 |
|
||||
| 许愿树相关 | 5+ | eb_wishtree_festival, eb_wishtree_wish 等 |
|
||||
| 作品相关 | 4+ | eb_works, eb_works_like, eb_works_collect 等 |
|
||||
| 系统配置 | 10+ | eb_system_version, eb_lottery_config 等 |
|
||||
| **合计** | **55+** | - |
|
||||
|
||||
---
|
||||
|
||||
# 六、完成度汇总
|
||||
|
||||
## Android App 模块
|
||||
|
||||
| 模块 | 完成度 |
|
||||
|------|:------:|
|
||||
| 用户系统 | 90% |
|
||||
| 直播功能 | 85% |
|
||||
| 主播系统 | 75% |
|
||||
| 社交功能 | 85% |
|
||||
| 消息系统 | 80% |
|
||||
| 通话功能 | 90% |
|
||||
| 群组功能 | 85% |
|
||||
| 钱包系统 | 80% |
|
||||
| 娱乐功能 | 60% |
|
||||
| 作品系统 | 85% |
|
||||
| 搜索模块 | 90% |
|
||||
| **App整体** | **82%** |
|
||||
|
||||
## 管理后台模块
|
||||
|
||||
| 模块 | 完成度 |
|
||||
|------|:------:|
|
||||
| 用户管理 | 95% |
|
||||
| 直播管理 | 80% |
|
||||
| 主播管理 | 90% |
|
||||
| 礼物系统 | 90% |
|
||||
| 财务管理 | 70% |
|
||||
| 社交管理 | 85% |
|
||||
| 娱乐功能管理 | 70% |
|
||||
| 系统设置 | 90% |
|
||||
| 数据统计 | 85% |
|
||||
| **后台整体** | **84%** |
|
||||
|
||||
## 项目总体完成度:82%
|
||||
|
||||
---
|
||||
|
||||
# 七、待完成功能清单
|
||||
|
||||
## P0 - 紧急(影响核心功能)
|
||||
|
||||
| 序号 | 功能 | 模块 | 说明 |
|
||||
|:----:|------|------|------|
|
||||
| 1 | 开始/结束直播接口 | 直播管理 | 后端接口未实现 |
|
||||
| 2 | 许愿树心愿列表页面 | 娱乐功能 | 查看所有用户心愿 |
|
||||
| 3 | 点赞的直播间列表 | 社交功能 | 我的点赞页面 |
|
||||
|
||||
## P1 - 重要(影响用户体验)
|
||||
|
||||
| 序号 | 功能 | 模块 | 说明 |
|
||||
|:----:|------|------|------|
|
||||
| 1 | 粉丝团功能 | 主播系统 | 创建、管理、等级 |
|
||||
| 2 | 提现功能 | 钱包系统 | 主播收益提现 |
|
||||
| 3 | 推送通知 | 系统设置 | 消息推送集成 |
|
||||
| 4 | 删除单条消息 | 消息系统 | 私聊消息删除 |
|
||||
| 5 | 消息表情回应 | 消息系统 | 点赞、爱心等 |
|
||||
| 6 | 观众列表 | 直播功能 | 直播间观众显示 |
|
||||
| 7 | 直播间公告 | 直播功能 | 主播公告功能 |
|
||||
| 8 | 群组公告 | 群组功能 | 群公告发布 |
|
||||
|
||||
## P2 - 一般(功能完善)
|
||||
|
||||
| 序号 | 功能 | 模块 | 说明 |
|
||||
|:----:|------|------|------|
|
||||
| 1 | 第三方登录 | 用户系统 | 微信/QQ登录 |
|
||||
| 2 | 忘记密码 | 用户系统 | 密码找回 |
|
||||
| 3 | 作品评论 | 作品系统 | 评论功能 |
|
||||
| 4 | 作品分享 | 作品系统 | 分享到社交平台 |
|
||||
| 5 | 好友分组 | 社交功能 | 好友分类管理 |
|
||||
| 6 | 财务报表 | 财务管理 | 统计报表完善 |
|
||||
| 7 | 通话统计 | 数据统计 | 通话数据分析 |
|
||||
|
||||
## P3 - 可选(优化提升)
|
||||
|
||||
| 序号 | 功能 | 模块 | 说明 |
|
||||
|:----:|------|------|------|
|
||||
| 1 | 语音匹配完善 | 娱乐功能 | 匹配算法优化 |
|
||||
| 2 | 心动信号完善 | 娱乐功能 | 功能逻辑完善 |
|
||||
| 3 | 游戏大厅完善 | 娱乐功能 | 各游戏功能实现 |
|
||||
| 4 | 礼物排行榜 | 礼物系统 | 排行榜展示 |
|
||||
| 5 | 推荐算法优化 | 直播功能 | 个性化推荐 |
|
||||
| 6 | WebRTC优化 | 通话功能 | 通话质量提升 |
|
||||
|
||||
---
|
||||
|
||||
# 八、项目优势
|
||||
|
||||
1. **完整的直播生态**:从推流、播放、互动到社交,功能齐全
|
||||
2. **丰富的社交功能**:好友、群组、关注、许愿树等多维度社交
|
||||
3. **实时通信能力**:WebSocket实现真正的实时互动
|
||||
4. **完善的支付系统**:支持多种支付方式和虚拟货币
|
||||
5. **优秀的用户体验**:动画效果、防抖处理、缓存优先
|
||||
6. **可扩展的架构**:模块化设计,易于扩展新功能
|
||||
|
||||
---
|
||||
|
||||
# 九、建议优先级
|
||||
|
||||
1. **立即完成**:后端开始/结束直播接口(影响开播功能)
|
||||
2. **本周完成**:许愿树心愿列表、点赞列表页面
|
||||
3. **下周完成**:粉丝团功能、提现功能
|
||||
4. **持续优化**:推送通知、娱乐功能完善
|
||||
|
||||
---
|
||||
|
||||
> 报告生成工具:Kiro AI
|
||||
> 最后更新:2026年1月4日
|
||||
Loading…
Reference in New Issue
Block a user