diff --git a/.kiro/specs/wishtree-mobile/design.md b/.kiro/specs/wishtree-mobile/design.md new file mode 100644 index 00000000..e69de29b diff --git a/.kiro/specs/wishtree-mobile/tasks.md b/.kiro/specs/wishtree-mobile/tasks.md new file mode 100644 index 00000000..e69de29b diff --git a/Zhibo/admin/src/api/ban.js b/Zhibo/admin/src/api/ban.js new file mode 100644 index 00000000..020c5ae9 --- /dev/null +++ b/Zhibo/admin/src/api/ban.js @@ -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' + }); +} diff --git a/Zhibo/admin/src/views/ban/roomBan.vue b/Zhibo/admin/src/views/ban/roomBan.vue new file mode 100644 index 00000000..66ea2b26 --- /dev/null +++ b/Zhibo/admin/src/views/ban/roomBan.vue @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + + + + + + 封禁房间 + 批量删除 + + + + + + + + + + + + + {{ scope.row.room_name || '未知房间' }} + 主播:{{ scope.row.streamer_name || '-' }} + + + + + + + + {{ scope.row.ban_type === 'permanent' ? '永久封禁' : '临时封禁' }} + + + + + + + {{ scope.row.ban_type === 'permanent' ? '永久' : (scope.row.duration_days + '天') }} + + + + + {{ scope.row.expire_time || '-' }} + + + + + + {{ scope.row.status === 1 ? '生效中' : '已解除' }} + + + + + + + 解除封禁 + 删除 + + + + + + + + + + + + + + + + + + + + 永久封禁 + 临时封禁 + + + + + 天 + + + + + + + 取消 + 确定 + + + + + + + + diff --git a/Zhibo/admin/src/views/ban/userBan.vue b/Zhibo/admin/src/views/ban/userBan.vue new file mode 100644 index 00000000..afc3fd4f --- /dev/null +++ b/Zhibo/admin/src/views/ban/userBan.vue @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 搜索 + 重置 + + + + + + + 封禁用户 + 批量删除 + + + + + + + + + + + + {{ scope.row.nickname || '未知用户' }} + {{ scope.row.phone || '-' }} + + + + + + + + {{ scope.row.ban_type === 'permanent' ? '永久封禁' : '临时封禁' }} + + + + + + + {{ scope.row.ban_type === 'permanent' ? '永久' : (scope.row.duration_days + '天') }} + + + + + {{ scope.row.expire_time || '-' }} + + + + + + {{ scope.row.status === 1 ? '生效中' : '已解除' }} + + + + + + + 解除封禁 + 删除 + + + + + + + + + + + + + + + + + + + + 永久封禁 + 临时封禁 + + + + + 天 + + + + + + + 取消 + 确定 + + + + + + + + diff --git a/Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/BanController.java b/Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/BanController.java new file mode 100644 index 00000000..794d6e15 --- /dev/null +++ b/Zhibo/zhibo-h/crmeb-admin/src/main/java/com/zbkj/admin/controller/BanController.java @@ -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>> 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 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> list = jdbcTemplate.queryForList(sql.toString(), params.toArray()); + + return CommonResult.success(buildPage(list, total, page, limit)); + } + + @ApiOperation(value = "封禁用户") + @PostMapping("/user/add") + public CommonResult banUser(@RequestBody Map 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> 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> 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 unbanUser(@PathVariable Long id) { + // 获取封禁记录 + String querySql = "SELECT user_id FROM eb_user_ban WHERE id = ?"; + List> 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 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 batchDeleteUserBan(@RequestBody List 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>> 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 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> list = jdbcTemplate.queryForList(sql.toString(), params.toArray()); + + return CommonResult.success(buildPage(list, total, page, limit)); + } + + @ApiOperation(value = "封禁房间") + @PostMapping("/room/add") + public CommonResult banRoom(@RequestBody Map 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> 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> 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 unbanRoom(@PathVariable Long id) { + // 获取封禁记录 + String querySql = "SELECT room_id FROM eb_room_ban WHERE id = ?"; + List> 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 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 batchDeleteRoomBan(@RequestBody List 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> 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> records = jdbcTemplate.queryForList(sql, userId); + + Map 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> 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> records = jdbcTemplate.queryForList(sql, roomId); + + Map 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> buildPage(List> list, Integer total, Integer page, Integer limit) { + CommonPage> 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; + } +} diff --git a/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/BanFrontController.java b/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/BanFrontController.java new file mode 100644 index 00000000..dc4da0fd --- /dev/null +++ b/Zhibo/zhibo-h/crmeb-front/src/main/java/com/zbkj/front/controller/BanFrontController.java @@ -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> checkMyBanStatus() { + Integer userId = userService.getUserId(); + if (userId == null || userId == 0) { + return CommonResult.failed("请先登录"); + } + + return checkUserBanStatus(userId); + } + + /** + * 检查指定用户是否被封禁 + */ + @ApiOperation(value = "检查用户封禁状态") + @GetMapping("/check/user/{userId}") + public CommonResult> 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> records = jdbcTemplate.queryForList(sql, userId); + + Map result = new HashMap<>(); + if (records.isEmpty()) { + result.put("isBanned", false); + result.put("message", "用户状态正常"); + } else { + Map 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> 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> records = jdbcTemplate.queryForList(sql, roomId); + + Map result = new HashMap<>(); + if (records.isEmpty()) { + result.put("isBanned", false); + result.put("message", "房间状态正常"); + } else { + Map 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>> 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> list = jdbcTemplate.queryForList(sql, userId, pageSize, offset); + + return CommonResult.success(buildPage(list, total, page, pageSize)); + } + + /** + * 添加用户到黑名单 + */ + @ApiOperation(value = "添加用户到黑名单") + @PostMapping("/blacklist/add") + public CommonResult> addToBlacklist(@RequestBody Map 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> 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> 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> 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 result = new HashMap<>(); + result.put("success", true); + result.put("message", "已将该用户加入黑名单"); + return CommonResult.success(result); + } + + /** + * 从黑名单移除用户 + */ + @ApiOperation(value = "从黑名单移除用户") + @PostMapping("/blacklist/remove") + public CommonResult> removeFromBlacklist(@RequestBody Map 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 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> 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> myBlacklist = jdbcTemplate.queryForList(sql1, userId, targetUserId); + + // 检查对方是否拉黑了我 + String sql2 = "SELECT id FROM eb_user_blacklist WHERE user_id = ? AND blocked_user_id = ?"; + List> theirBlacklist = jdbcTemplate.queryForList(sql2, targetUserId, userId); + + Map 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> buildPage(List> list, Integer total, Integer page, Integer pageSize) { + CommonPage> 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; + } +} diff --git a/add_ban_menus.sql b/add_ban_menus.sql new file mode 100644 index 00000000..1ba5c41a --- /dev/null +++ b/add_ban_menus.sql @@ -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; diff --git a/add_ban_test_data.sql b/add_ban_test_data.sql new file mode 100644 index 00000000..46595922 --- /dev/null +++ b/add_ban_test_data.sql @@ -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 房间封禁生效中; diff --git a/add_blacklist_menu_now.sql b/add_blacklist_menu_now.sql new file mode 100644 index 00000000..c199f21d --- /dev/null +++ b/add_blacklist_menu_now.sql @@ -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; diff --git a/add_blacklist_to_social.sql b/add_blacklist_to_social.sql new file mode 100644 index 00000000..1ec8aade --- /dev/null +++ b/add_blacklist_to_social.sql @@ -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; diff --git a/add_blacklist_to_social_v2.sql b/add_blacklist_to_social_v2.sql new file mode 100644 index 00000000..8b8996f9 --- /dev/null +++ b/add_blacklist_to_social_v2.sql @@ -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; diff --git a/add_test_data_for_user.sql b/add_test_data_for_user.sql new file mode 100644 index 00000000..cfd019f1 --- /dev/null +++ b/add_test_data_for_user.sql @@ -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; diff --git a/add_view_history_121.sql b/add_view_history_121.sql new file mode 100644 index 00000000..aca0bbe1 --- /dev/null +++ b/add_view_history_121.sql @@ -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; diff --git a/add_view_history_121_final.sql b/add_view_history_121_final.sql new file mode 100644 index 00000000..9c971783 --- /dev/null +++ b/add_view_history_121_final.sql @@ -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; diff --git a/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordAdapter.java b/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordAdapter.java new file mode 100644 index 00000000..fa83143f --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordAdapter.java @@ -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 { + + private List> records; + + public BalanceRecordAdapter(List> 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 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); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordFragment.java b/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordFragment.java new file mode 100644 index 00000000..cc2db6ca --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/BalanceRecordFragment.java @@ -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> 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>>> call; + if ("recharge".equals(recordType)) { + call = ApiClient.getService(requireContext()).getRechargeRecords(1, 20); + } else { + call = ApiClient.getService(requireContext()).getConsumeRecords(1, 20); + } + + call.enqueue(new Callback>>>() { + @Override + public void onResponse(Call>>> call, Response>>> response) { + swipeRefresh.setRefreshing(false); + if (response.isSuccessful() && response.body() != null && response.body().isOk()) { + List> data = response.body().getData(); + recordList.clear(); + if (data != null) { + recordList.addAll(data); + } + adapter.notifyDataSetChanged(); + updateEmptyView(); + } + } + + @Override + public void onFailure(Call>>> 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); + } + } +} diff --git a/android-app/app/src/main/java/com/example/livestreaming/BlacklistActivity.java b/android-app/app/src/main/java/com/example/livestreaming/BlacklistActivity.java new file mode 100644 index 00000000..2ef5578b --- /dev/null +++ b/android-app/app/src/main/java/com/example/livestreaming/BlacklistActivity.java @@ -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> 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>>>() { + @Override + public void onResponse(Call>>> call, + Response>>> response) { + isLoading = false; + loadingView.setVisibility(View.GONE); + swipeRefreshLayout.setRefreshing(false); + + if (response.isSuccessful() && response.body() != null && response.body().isOk()) { + PageResponse> 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>>> 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 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 item) { + java.util.Map body = new java.util.HashMap<>(); + body.put("targetUserId", targetUserId); + + ApiClient.getService(this).removeFromBlacklist(body) + .enqueue(new Callback>>() { + @Override + public void onResponse(Call>> call, + Response>> 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>> call, Throwable t) { + Log.e(TAG, "移除黑名单失败", t); + Toast.makeText(BlacklistActivity.this, "网络错误", Toast.LENGTH_SHORT).show(); + } + }); + } + + /** + * 黑名单列表适配器 + */ + private static class BlacklistAdapter extends RecyclerView.Adapter { + + private List> data = new ArrayList<>(); + private final OnItemClickListener listener; + + interface OnItemClickListener { + void onRemoveClick(Map item); + } + + BlacklistAdapter(OnItemClickListener listener) { + this.listener = listener; + } + + void setData(List> 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 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 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); + } + } + } + } +} diff --git a/android-app/app/src/main/res/drawable/bg_btn_followed.xml b/android-app/app/src/main/res/drawable/bg_btn_followed.xml new file mode 100644 index 00000000..fb446cc6 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_btn_followed.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_button_outline_primary.xml b/android-app/app/src/main/res/drawable/bg_button_outline_primary.xml new file mode 100644 index 00000000..ba87912d --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_button_outline_primary.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_cover_rounded_8.xml b/android-app/app/src/main/res/drawable/bg_cover_rounded_8.xml new file mode 100644 index 00000000..ecc26c57 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_cover_rounded_8.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_tag_live.xml b/android-app/app/src/main/res/drawable/bg_tag_live.xml new file mode 100644 index 00000000..b7633a55 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_tag_live.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_tag_profile.xml b/android-app/app/src/main/res/drawable/bg_tag_profile.xml new file mode 100644 index 00000000..2b1b60d2 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_tag_profile.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_tag_room.xml b/android-app/app/src/main/res/drawable/bg_tag_room.xml new file mode 100644 index 00000000..568e95af --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_tag_room.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_tag_wish.xml b/android-app/app/src/main/res/drawable/bg_tag_wish.xml new file mode 100644 index 00000000..2c6ccdf0 --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_tag_wish.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/drawable/bg_tag_work.xml b/android-app/app/src/main/res/drawable/bg_tag_work.xml new file mode 100644 index 00000000..a71757fd --- /dev/null +++ b/android-app/app/src/main/res/drawable/bg_tag_work.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/android-app/app/src/main/res/layout/activity_blacklist.xml b/android-app/app/src/main/res/layout/activity_blacklist.xml new file mode 100644 index 00000000..e6a20739 --- /dev/null +++ b/android-app/app/src/main/res/layout/activity_blacklist.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/layout/fragment_balance_record.xml b/android-app/app/src/main/res/layout/fragment_balance_record.xml new file mode 100644 index 00000000..8d5f343b --- /dev/null +++ b/android-app/app/src/main/res/layout/fragment_balance_record.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/layout/item_balance_record.xml b/android-app/app/src/main/res/layout/item_balance_record.xml new file mode 100644 index 00000000..b5c8cf43 --- /dev/null +++ b/android-app/app/src/main/res/layout/item_balance_record.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/android-app/app/src/main/res/layout/item_blacklist.xml b/android-app/app/src/main/res/layout/item_blacklist.xml new file mode 100644 index 00000000..ef3bfd90 --- /dev/null +++ b/android-app/app/src/main/res/layout/item_blacklist.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/ban_system_tables.sql b/ban_system_tables.sql new file mode 100644 index 00000000..b796dc51 --- /dev/null +++ b/ban_system_tables.sql @@ -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; diff --git a/check_and_fix_records.sql b/check_and_fix_records.sql new file mode 100644 index 00000000..ee35ed23 --- /dev/null +++ b/check_and_fix_records.sql @@ -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 '%道玄%'; diff --git a/check_ban_menu_permission.sql b/check_ban_menu_permission.sql new file mode 100644 index 00000000..e38770fe --- /dev/null +++ b/check_ban_menu_permission.sql @@ -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 '%封禁%'; diff --git a/check_blacklist_menu.sql b/check_blacklist_menu.sql new file mode 100644 index 00000000..fd9c219a --- /dev/null +++ b/check_blacklist_menu.sql @@ -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` = '群组管理'; diff --git a/check_blacklist_menu_v2.sql b/check_blacklist_menu_v2.sql new file mode 100644 index 00000000..a2e8bac5 --- /dev/null +++ b/check_blacklist_menu_v2.sql @@ -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; diff --git a/check_follow_status_type.sql b/check_follow_status_type.sql new file mode 100644 index 00000000..42cbfb6b --- /dev/null +++ b/check_follow_status_type.sql @@ -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; diff --git a/check_table_structure.sql b/check_table_structure.sql new file mode 100644 index 00000000..bbed5fc2 --- /dev/null +++ b/check_table_structure.sql @@ -0,0 +1,6 @@ +-- 检查各表结构 +DESCRIBE eb_live_room_like; +DESCRIBE eb_works_relation; +DESCRIBE eb_follow_record; +DESCRIBE eb_search_history; +DESCRIBE eb_friend; diff --git a/check_tables_for_121.sql b/check_tables_for_121.sql new file mode 100644 index 00000000..49164d17 --- /dev/null +++ b/check_tables_for_121.sql @@ -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; diff --git a/check_user_121_data.sql b/check_user_121_data.sql new file mode 100644 index 00000000..b1bc25d4 --- /dev/null +++ b/check_user_121_data.sql @@ -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; diff --git a/check_user_records.sql b/check_user_records.sql new file mode 100644 index 00000000..9372e5d3 --- /dev/null +++ b/check_user_records.sql @@ -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%'; diff --git a/check_working_menu.sql b/check_working_menu.sql new file mode 100644 index 00000000..7bb6b7c6 --- /dev/null +++ b/check_working_menu.sql @@ -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; diff --git a/complete_test_data_121.sql b/complete_test_data_121.sql new file mode 100644 index 00000000..cff29a1b --- /dev/null +++ b/complete_test_data_121.sql @@ -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; diff --git a/complete_user_activity_data.sql b/complete_user_activity_data.sql new file mode 100644 index 00000000..d2779f3a --- /dev/null +++ b/complete_user_activity_data.sql @@ -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 收藏作品数; diff --git a/create_tables_and_data_121.sql b/create_tables_and_data_121.sql new file mode 100644 index 00000000..ae8a8a9b --- /dev/null +++ b/create_tables_and_data_121.sql @@ -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 结果; diff --git a/create_test_rooms_works.sql b/create_test_rooms_works.sql new file mode 100644 index 00000000..fce3fd48 --- /dev/null +++ b/create_test_rooms_works.sql @@ -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; diff --git a/debug_menu_structure.sql b/debug_menu_structure.sql new file mode 100644 index 00000000..d4d9eef5 --- /dev/null +++ b/debug_menu_structure.sql @@ -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; diff --git a/debug_user_token.sql b/debug_user_token.sql new file mode 100644 index 00000000..1eae044e --- /dev/null +++ b/debug_user_token.sql @@ -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 关注数; diff --git a/deploy_ban_system.bat b/deploy_ban_system.bat new file mode 100644 index 00000000..54693b9b --- /dev/null +++ b/deploy_ban_system.bat @@ -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 diff --git a/deploy_complete.bat b/deploy_complete.bat new file mode 100644 index 00000000..9adef151 --- /dev/null +++ b/deploy_complete.bat @@ -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 diff --git a/deploy_my_records_fix.bat b/deploy_my_records_fix.bat new file mode 100644 index 00000000..6106c249 --- /dev/null +++ b/deploy_my_records_fix.bat @@ -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 diff --git a/deploy_records_debug.bat b/deploy_records_debug.bat new file mode 100644 index 00000000..c1ab6032 --- /dev/null +++ b/deploy_records_debug.bat @@ -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 diff --git a/deploy_user_activity.bat b/deploy_user_activity.bat new file mode 100644 index 00000000..99a38b8e --- /dev/null +++ b/deploy_user_activity.bat @@ -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 diff --git a/deploy_view_history_fix.bat b/deploy_view_history_fix.bat new file mode 100644 index 00000000..f935ab1d --- /dev/null +++ b/deploy_view_history_fix.bat @@ -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 diff --git a/diagnose_my_records.sql b/diagnose_my_records.sql new file mode 100644 index 00000000..a9f3339c --- /dev/null +++ b/diagnose_my_records.sql @@ -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 关注数; diff --git a/fix_ban_menu_component.sql b/fix_ban_menu_component.sql new file mode 100644 index 00000000..400745ba --- /dev/null +++ b/fix_ban_menu_component.sql @@ -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; diff --git a/fix_ban_menu_component_v2.sql b/fix_ban_menu_component_v2.sql new file mode 100644 index 00000000..1aeba50f --- /dev/null +++ b/fix_ban_menu_component_v2.sql @@ -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; diff --git a/fix_blacklist_menu_final.sql b/fix_blacklist_menu_final.sql new file mode 100644 index 00000000..cf9c7210 --- /dev/null +++ b/fix_blacklist_menu_final.sql @@ -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 ('用户拉黑', '房间拉黑'); diff --git a/fix_data_and_tables.sql b/fix_data_and_tables.sql new file mode 100644 index 00000000..2daabd34 --- /dev/null +++ b/fix_data_and_tables.sql @@ -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%'; diff --git a/fix_records_v2.sql b/fix_records_v2.sql new file mode 100644 index 00000000..d086aa7d --- /dev/null +++ b/fix_records_v2.sql @@ -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; diff --git a/fix_view_history_for_user.sql b/fix_view_history_for_user.sql new file mode 100644 index 00000000..a811f896 --- /dev/null +++ b/fix_view_history_for_user.sql @@ -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='查看历史记录表'; diff --git a/insert_data_121_complete.sql b/insert_data_121_complete.sql new file mode 100644 index 00000000..e94fdf1d --- /dev/null +++ b/insert_data_121_complete.sql @@ -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 结果; diff --git a/insert_data_121_final.sql b/insert_data_121_final.sql new file mode 100644 index 00000000..3329f723 --- /dev/null +++ b/insert_data_121_final.sql @@ -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 结果; diff --git a/insert_data_121_fixed.sql b/insert_data_121_fixed.sql new file mode 100644 index 00000000..72fa213e --- /dev/null +++ b/insert_data_121_fixed.sql @@ -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 结果; diff --git a/insert_data_121_v2.sql b/insert_data_121_v2.sql new file mode 100644 index 00000000..aefa22aa --- /dev/null +++ b/insert_data_121_v2.sql @@ -0,0 +1,6 @@ +-- ===================================================== +-- 为用户"道玄"(ID: 121)添加测试数据 - 第二版 +-- 先查看 eb_follow_record 表结构 +-- ===================================================== + +DESCRIBE eb_follow_record; diff --git a/insert_data_121_v3.sql b/insert_data_121_v3.sql new file mode 100644 index 00000000..e64b7eb6 --- /dev/null +++ b/insert_data_121_v3.sql @@ -0,0 +1,3 @@ +-- 查看 eb_search_history 和 eb_friend 表结构 +DESCRIBE eb_search_history; +DESCRIBE eb_friend; diff --git a/insert_test_rooms_works.sql b/insert_test_rooms_works.sql new file mode 100644 index 00000000..6eb9e005 --- /dev/null +++ b/insert_test_rooms_works.sql @@ -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); diff --git a/insert_test_works.sql b/insert_test_works.sql new file mode 100644 index 00000000..0d7f8f7f --- /dev/null +++ b/insert_test_works.sql @@ -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); diff --git a/rebuild_and_restart_backend.bat b/rebuild_and_restart_backend.bat new file mode 100644 index 00000000..c6cb6206 --- /dev/null +++ b/rebuild_and_restart_backend.bat @@ -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 diff --git a/rebuild_backend.bat b/rebuild_backend.bat new file mode 100644 index 00000000..363674f4 --- /dev/null +++ b/rebuild_backend.bat @@ -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 diff --git a/test_activity_api.bat b/test_activity_api.bat new file mode 100644 index 00000000..b47d07d4 --- /dev/null +++ b/test_activity_api.bat @@ -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 diff --git a/test_activity_api.md b/test_activity_api.md new file mode 100644 index 00000000..2ba6ffb3 --- /dev/null +++ b/test_activity_api.md @@ -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,查看后端日志 diff --git a/test_api_curl.sh b/test_api_curl.sh new file mode 100644 index 00000000..6c7be754 --- /dev/null +++ b/test_api_curl.sh @@ -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 "==========================================" diff --git a/test_data_for_user_121.sql b/test_data_for_user_121.sql new file mode 100644 index 00000000..42ae536e --- /dev/null +++ b/test_data_for_user_121.sql @@ -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 结果; diff --git a/test_view_history_api.bat b/test_view_history_api.bat new file mode 100644 index 00000000..60354744 --- /dev/null +++ b/test_view_history_api.bat @@ -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 diff --git a/user_activity_test_data.sql b/user_activity_test_data.sql new file mode 100644 index 00000000..3b7046f9 --- /dev/null +++ b/user_activity_test_data.sql @@ -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; diff --git a/verify_all_data_121.sql b/verify_all_data_121.sql new file mode 100644 index 00000000..1fd1594f --- /dev/null +++ b/verify_all_data_121.sql @@ -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; diff --git a/verify_user_121_data.sql b/verify_user_121_data.sql new file mode 100644 index 00000000..fbc2dc23 --- /dev/null +++ b/verify_user_121_data.sql @@ -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; diff --git a/封禁系统功能说明.md b/封禁系统功能说明.md new file mode 100644 index 00000000..e98fa073 --- /dev/null +++ b/封禁系统功能说明.md @@ -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` - 添加菜单配置 diff --git a/我的记录数据不显示问题排查.md b/我的记录数据不显示问题排查.md new file mode 100644 index 00000000..8c32970e --- /dev/null +++ b/我的记录数据不显示问题排查.md @@ -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` diff --git a/接口配置检查报告.md b/接口配置检查报告.md new file mode 100644 index 00000000..9287aede --- /dev/null +++ b/接口配置检查报告.md @@ -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 diff --git a/直播平台功能清单报告.md b/直播平台功能清单报告.md new file mode 100644 index 00000000..fe2030f0 --- /dev/null +++ b/直播平台功能清单报告.md @@ -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日