修正消息中心不显示
This commit is contained in:
@@ -69,8 +69,8 @@ INSERT INTO `tb_sys_permission` (id,permission_id, name, code, description, modu
|
||||
('19','perm_sensitive_manage', '敏感词管理', 'sensitive:manage', '敏感词管理权限', 'module_sensitive', '1', now());
|
||||
|
||||
-- 插入角色-权限关联数据
|
||||
INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, create_time) VALUES
|
||||
-- 超级管理员:拥有所有权限
|
||||
INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, create_time) VALUES
|
||||
('1', 'superadmin', 'perm_default', '1', now()),
|
||||
('2', 'superadmin', 'perm_system_manage', '1', now()),
|
||||
('3', 'superadmin', 'perm_system_dept_manage', '1', now()),
|
||||
@@ -116,8 +116,8 @@ INSERT INTO `tb_sys_role_permission` (id, role_id, permission_id, creator, creat
|
||||
('45', 'freedom', 'perm_message_view', '1', now());
|
||||
|
||||
-- 插入前端菜单数据
|
||||
INSERT INTO `tb_sys_menu` VALUES
|
||||
-- 用户前端菜单 (100-699)
|
||||
INSERT INTO `tb_sys_menu` VALUES
|
||||
('100', 'menu_home', '首页', NULL, '/home', 'user/home/HomeView', NULL, 1, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('101', 'menu_resource_hot', '热门资源', NULL, '/resource-hot', 'user/resource-center/HotResourceView', NULL, 2, 3, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('200', 'menu_resource_center', '资源中心', NULL, '/resource-center', 'user/resource-center/ResourceCenterView', NULL, 2, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
@@ -128,13 +128,13 @@ INSERT INTO `tb_sys_menu` VALUES
|
||||
('304', 'menu_course_detail', '课程详情', 'menu_study_plan', '/study-plan/course-detail', 'user/study-plan/CourseDetailView', NULL, 4, 3, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('305', 'menu_course_study', '课程学习', 'menu_study_plan', '/study-plan/course-study', 'user/study-plan/CourseStudyView', NULL, 5, 3, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('400', 'menu_user_dropdown', '用户下拉菜单', NULL, '', '', NULL, 4, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('401', 'menu_user_center', '个人中心', 'menu_user_dropdown', '/user-center', 'user/user-center/UserCenterView', NULL, 4, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('401', 'menu_user_center', '个人中心', 'menu_user_dropdown', '/user-center', 'user/user-center/UserCenterLayout', NULL, 4, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('402', 'menu_learning_records', '学习记录', 'menu_user_center', '/user-center/learning-records', 'user/user-center/LearningRecordsView', NULL, 1, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('403', 'menu_my_favorites', '我的收藏', 'menu_user_center', '/user-center/favorites', 'user/user-center/MyFavoritesView', NULL, 2, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('404', 'menu_my_achievements', '我的成就', 'menu_user_center', '/user-center/achievements', 'user/user-center/MyAchievementsView', NULL, 3, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('500', 'menu_profile', '账号中心', 'menu_user_dropdown', '/profile', 'user/profile/ProfileView', NULL, 5, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('501', 'menu_personal_info', '个人信息', 'menu_profile', '/profile/personal-info', 'user/profile/PersonalInfoView', NULL, 1, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('502', 'menu_account_settings', '账号设置', 'menu_profile', '/profile/account-settings', 'user/profile/AccountSettingsView', NULL, 2, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('500', 'menu_profile', '账号中心', 'menu_user_dropdown', '/profile', 'user/user-center/UserCenterLayout', NULL, 5, 1, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:49:56', NULL, 0),
|
||||
('501', 'menu_personal_info', '个人信息', 'menu_profile', '/profile/personal-info', 'user/user-center/profile/PersonalInfoView', NULL, 1, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('502', 'menu_account_settings', '账号设置', 'menu_profile', '/profile/account-settings', 'user/user-center/profile/AccountSettingsView', NULL, 2, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
('503', 'menu_search', '搜索', NULL, '/search', 'user/resource-center/SearchView', NULL, 3, 0, 'NavigationLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:48:39', NULL, 0),
|
||||
-- 管理后台菜单 (1000-8999)
|
||||
('1000', 'menu_admin_overview', '系统总览', NULL, '/admin/overview', 'admin/overview/SystemOverviewView', 'admin/overview.svg', 1, 0, 'SidebarLayout', '1', NULL, '2025-10-27 17:26:06', '2025-10-29 11:52:32', NULL, 0),
|
||||
@@ -177,8 +177,8 @@ INSERT INTO `tb_sys_menu` VALUES
|
||||
('651', 'menu_user_message_detail', '消息详情', 'menu_user_message_center', '/user/message/detail/:messageID', 'user/message/MyMessageDetailView', NULL, 1, 3, 'NavigationLayout', '1', NULL, '2025-11-13 10:00:00', '2025-11-13 10:00:00', NULL, 0);
|
||||
|
||||
-- 插入菜单权限关联数据
|
||||
INSERT INTO `tb_sys_menu_permission` (id, permission_id, menu_id, creator, create_time) VALUES
|
||||
-- 前端菜单权限关联
|
||||
INSERT INTO `tb_sys_menu_permission` (id, permission_id, menu_id, creator, create_time) VALUES
|
||||
('100', 'perm_default', 'menu_home', '1', now()),
|
||||
('102', 'perm_default', 'menu_resource_hot', '1', now()),
|
||||
('101', 'perm_default', 'menu_resource_center', '1', now()),
|
||||
@@ -241,11 +241,7 @@ INSERT INTO `tb_sys_menu_permission` (id, permission_id, menu_id, creator, creat
|
||||
|
||||
-- 消息通知管理菜单权限关联
|
||||
('240', 'perm_message_manage', 'menu_admin_message_manage', '1', now()),
|
||||
('241', 'perm_message_manage', 'menu_admin_message_list', '1', now()),
|
||||
('242', 'perm_message_send', 'menu_admin_message_create', '1', now()),
|
||||
('243', 'perm_message_manage', 'menu_admin_message_detail', '1', now()),
|
||||
|
||||
-- 用户端消息中心权限关联
|
||||
('250', 'perm_message_view', 'menu_user_message_center', '1', now()),
|
||||
('251', 'perm_message_view', 'menu_user_message_detail', '1', now());
|
||||
('250', 'perm_default', 'menu_user_message_center', '1', now()),
|
||||
('251', 'perm_default', 'menu_user_message_detail', '1', now());
|
||||
|
||||
|
||||
@@ -97,6 +97,51 @@ execute_init_script() {
|
||||
fi
|
||||
}
|
||||
|
||||
# 执行敏感词导入
|
||||
import_sensitive_words() {
|
||||
print_message $BLUE "开始导入敏感词数据..."
|
||||
|
||||
# 检查conda是否可用
|
||||
if ! command -v conda &> /dev/null; then
|
||||
print_message $YELLOW "conda命令未找到,跳过敏感词导入"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 检查schoolNewsCrawler环境是否存在
|
||||
if ! conda env list | grep -q "schoolNewsCrawler"; then
|
||||
print_message $YELLOW "conda环境 'schoolNewsCrawler' 不存在,跳过敏感词导入"
|
||||
print_message $YELLOW "提示: 可以使用以下命令创建环境: conda create -n schoolNewsCrawler python=3.10"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 切换到敏感词脚本目录
|
||||
local sensitive_dir="$SCRIPT_DIR/sensitiveData"
|
||||
if [ ! -d "$sensitive_dir" ]; then
|
||||
print_message $YELLOW "敏感词脚本目录不存在: $sensitive_dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ ! -f "$sensitive_dir/writeWord.py" ]; then
|
||||
print_message $YELLOW "敏感词脚本不存在: $sensitive_dir/writeWord.py"
|
||||
return 0
|
||||
fi
|
||||
|
||||
print_message $BLUE "激活conda环境: schoolNewsCrawler"
|
||||
cd "$sensitive_dir"
|
||||
|
||||
# 使用conda run来在指定环境中执行命令,添加-y参数自动确认
|
||||
conda run -n schoolNewsCrawler python writeWord.py -y
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
print_message $GREEN "敏感词数据导入成功"
|
||||
else
|
||||
print_message $YELLOW "敏感词数据导入失败,但不影响系统运行"
|
||||
fi
|
||||
|
||||
# 返回脚本目录
|
||||
cd "$SCRIPT_DIR"
|
||||
}
|
||||
|
||||
# 验证初始化结果
|
||||
verify_initialization() {
|
||||
print_message $BLUE "验证初始化结果..."
|
||||
@@ -120,6 +165,14 @@ verify_initialization() {
|
||||
else
|
||||
print_message $YELLOW "默认用户创建失败"
|
||||
fi
|
||||
|
||||
# 检查敏感词数量
|
||||
local sensitive_count=$(mysql -h"$DB_HOST" -P"$DB_PORT" -u"$DB_USER" -p"$DB_PASSWORD" -D"$DB_NAME" -e "SELECT COUNT(*) FROM tb_sensitive_word;" 2>/dev/null | tail -n 1)
|
||||
if [ -n "$sensitive_count" ] && [ "$sensitive_count" -gt 0 ]; then
|
||||
print_message $GREEN "敏感词数据: $sensitive_count 个"
|
||||
else
|
||||
print_message $YELLOW "敏感词数据: 0 个 (可能未导入或表不存在)"
|
||||
fi
|
||||
}
|
||||
|
||||
# 显示初始化信息
|
||||
@@ -146,6 +199,8 @@ show_initialization_info() {
|
||||
print_message $YELLOW " - AI智能体"
|
||||
print_message $YELLOW " - 系统配置"
|
||||
print_message $YELLOW " - 文件管理"
|
||||
print_message $YELLOW " - 敏感词过滤"
|
||||
print_message $YELLOW " - 消息通知"
|
||||
print_message $BLUE "====================================================="
|
||||
}
|
||||
|
||||
@@ -153,7 +208,7 @@ show_initialization_info() {
|
||||
main() {
|
||||
print_message $BLUE "====================================================="
|
||||
print_message $BLUE "校园思政新闻平台数据库重新初始化脚本"
|
||||
print_message $BLUE "版本: 1.0.0"
|
||||
print_message $BLUE "版本: 1.1.0"
|
||||
print_message $BLUE "====================================================="
|
||||
|
||||
# 检查MySQL连接
|
||||
@@ -170,12 +225,15 @@ main() {
|
||||
# 执行初始化脚本
|
||||
execute_init_script
|
||||
|
||||
# 导入敏感词数据
|
||||
|
||||
# 验证初始化结果
|
||||
verify_initialization
|
||||
|
||||
# 显示初始化信息
|
||||
show_initialization_info
|
||||
|
||||
import_sensitive_words
|
||||
|
||||
print_message $GREEN "初始化完成!"
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import pymysql
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from datetime import datetime
|
||||
|
||||
# 数据库配置
|
||||
@@ -110,13 +111,25 @@ def check_duplicates(connection, words):
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
# 解析命令行参数
|
||||
parser = argparse.ArgumentParser(description='敏感词批量导入工具')
|
||||
parser.add_argument('-y', '--yes', action='store_true',
|
||||
help='自动确认导入,跳过交互式确认')
|
||||
parser.add_argument('--file', type=str,
|
||||
help='指定敏感词文件路径(默认: sensitive_word_dict.txt)')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
print("=" * 50)
|
||||
print("敏感词批量导入工具")
|
||||
print("=" * 50)
|
||||
|
||||
# 获取脚本所在目录
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
dict_file = os.path.join(script_dir, 'sensitive_word_dict.txt')
|
||||
# 获取敏感词文件路径
|
||||
if args.file:
|
||||
dict_file = args.file
|
||||
else:
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
dict_file = os.path.join(script_dir, 'sensitive_word_dict.txt')
|
||||
|
||||
# 检查敏感词文件是否存在
|
||||
if not os.path.exists(dict_file):
|
||||
@@ -150,11 +163,20 @@ def main():
|
||||
|
||||
# 确认导入
|
||||
print(f"准备导入 {len(words)} 个敏感词到数据库")
|
||||
confirm = input("是否继续?(y/N): ").strip().lower()
|
||||
|
||||
if confirm != 'y':
|
||||
print("用户取消导入")
|
||||
return
|
||||
if args.yes:
|
||||
print("自动确认模式,开始导入...")
|
||||
else:
|
||||
try:
|
||||
confirm = input("是否继续?(y/N): ").strip().lower()
|
||||
if confirm != 'y':
|
||||
print("用户取消导入")
|
||||
return
|
||||
except EOFError:
|
||||
print("检测到非交互式环境,自动确认导入...")
|
||||
except KeyboardInterrupt:
|
||||
print("\n用户中断导入")
|
||||
return
|
||||
|
||||
# 批量插入
|
||||
print("开始批量导入敏感词...")
|
||||
@@ -1,331 +0,0 @@
|
||||
# 成就模块迁移指南
|
||||
|
||||
## 📝 迁移概述
|
||||
|
||||
成就相关功能已从 `usercenter` 模块迁移到独立的 `achievement` 模块。
|
||||
|
||||
### 迁移日期
|
||||
2025-10-24
|
||||
|
||||
### 迁移原因
|
||||
- ✅ **模块职责分离** - usercenter负责用户中心,achievement专注于成就系统
|
||||
- ✅ **更好的可维护性** - 独立模块易于管理和扩展
|
||||
- ✅ **清晰的依赖关系** - 减少模块间的耦合
|
||||
- ✅ **可扩展性** - 便于添加新的成就类型和功能
|
||||
|
||||
## 🔄 包路径变更
|
||||
|
||||
### API接口变更
|
||||
|
||||
**旧路径(已删除):**
|
||||
```java
|
||||
org.xyzh.api.usercenter.achievement.UserAchievementService
|
||||
```
|
||||
|
||||
**新路径:**
|
||||
```java
|
||||
org.xyzh.api.achievement.AchievementService
|
||||
```
|
||||
|
||||
### 服务实现变更
|
||||
|
||||
**旧路径(已删除):**
|
||||
```java
|
||||
org.xyzh.usercenter.service.UCUserAchievementService
|
||||
org.xyzh.usercenter.service.impl.UCUserAchievementServiceImpl
|
||||
```
|
||||
|
||||
**新路径:**
|
||||
```java
|
||||
org.xyzh.api.achievement.AchievementService
|
||||
org.xyzh.achievement.service.impl.ACHAchievementServiceImpl
|
||||
```
|
||||
|
||||
### Mapper变更
|
||||
|
||||
**旧路径(已删除):**
|
||||
```java
|
||||
org.xyzh.usercenter.mapper.AchievementMapper
|
||||
org.xyzh.usercenter.mapper.UserAchievementMapper
|
||||
```
|
||||
|
||||
**新路径:**
|
||||
```java
|
||||
org.xyzh.achievement.mapper.AchievementMapper
|
||||
org.xyzh.achievement.mapper.UserAchievementMapper
|
||||
org.xyzh.achievement.mapper.UserAchievementProgressMapper // 新增
|
||||
```
|
||||
|
||||
### Controller变更
|
||||
|
||||
**旧路径(已删除):**
|
||||
```java
|
||||
org.xyzh.usercenter.controller.UserAchievementController
|
||||
```
|
||||
|
||||
**新路径:**
|
||||
```java
|
||||
org.xyzh.achievement.controller.AchievementController
|
||||
```
|
||||
|
||||
## 📦 依赖变更
|
||||
|
||||
### 如果你的模块之前依赖了成就功能
|
||||
|
||||
#### 旧的依赖配置(需要删除):
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.xyzh</groupId>
|
||||
<artifactId>api-usercenter</artifactId> <!-- 包含成就接口 -->
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
#### 新的依赖配置(需要添加):
|
||||
```xml
|
||||
<!-- API接口依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.xyzh</groupId>
|
||||
<artifactId>api-achievement</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 如果需要使用实现类(通常不需要,使用Dubbo远程调用) -->
|
||||
<dependency>
|
||||
<groupId>org.xyzh</groupId>
|
||||
<artifactId>achievement</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
## 🔧 代码迁移步骤
|
||||
|
||||
### 1. 更新导入语句
|
||||
|
||||
**旧代码:**
|
||||
```java
|
||||
import org.xyzh.api.usercenter.achievement.UserAchievementService;
|
||||
```
|
||||
|
||||
**新代码:**
|
||||
```java
|
||||
import org.xyzh.api.achievement.AchievementService;
|
||||
```
|
||||
|
||||
### 2. 更新服务注入
|
||||
|
||||
**旧代码:**
|
||||
```java
|
||||
@Autowired
|
||||
private UserAchievementService userAchievementService;
|
||||
```
|
||||
|
||||
**新代码:**
|
||||
```java
|
||||
@Autowired
|
||||
private AchievementService achievementService;
|
||||
```
|
||||
|
||||
### 3. 更新方法调用
|
||||
|
||||
大部分方法签名保持不变,只需更新服务名称:
|
||||
|
||||
**旧代码:**
|
||||
```java
|
||||
ResultDomain<TbUserAchievement> result = userAchievementService.getUserAchievements(userID, type);
|
||||
```
|
||||
|
||||
**新代码:**
|
||||
```java
|
||||
ResultDomain<TbUserAchievement> result = achievementService.getUserAchievements(userID, type);
|
||||
```
|
||||
|
||||
### 4. 新增功能调用
|
||||
|
||||
新的成就系统增加了事件驱动机制:
|
||||
|
||||
```java
|
||||
// 发布成就事件
|
||||
AchievementEvent event = AchievementEvent.builder(userID, AchievementEventType.COURSE_COMPLETED)
|
||||
.value(1)
|
||||
.build();
|
||||
|
||||
// 方式1:使用Spring事件发布(推荐)
|
||||
eventPublisher.publishEvent(event);
|
||||
|
||||
// 方式2:直接调用服务
|
||||
achievementService.processAchievementEvent(event);
|
||||
```
|
||||
|
||||
## 🗄️ 数据库变更
|
||||
|
||||
### 新增表
|
||||
|
||||
```sql
|
||||
-- 用户成就进度表(新增)
|
||||
CREATE TABLE tb_user_achievement_progress (
|
||||
id VARCHAR(32) NOT NULL,
|
||||
user_id VARCHAR(32) NOT NULL,
|
||||
achievement_id VARCHAR(32) NOT NULL,
|
||||
current_value INT DEFAULT 0,
|
||||
target_value INT DEFAULT 0,
|
||||
progress_percentage INT DEFAULT 0,
|
||||
completed TINYINT(1) DEFAULT 0,
|
||||
last_update_time DATETIME,
|
||||
create_time DATETIME,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_user_achievement_progress (user_id, achievement_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 已有表
|
||||
|
||||
`tb_achievement` 和 `tb_user_achievement` 表结构保持不变,无需迁移数据。
|
||||
|
||||
## 🌐 REST API变更
|
||||
|
||||
### 接口路径变更
|
||||
|
||||
**旧路径:**
|
||||
```
|
||||
/usercenter/achievement/*
|
||||
```
|
||||
|
||||
**新路径:**
|
||||
```
|
||||
/achievement/*
|
||||
```
|
||||
|
||||
### 具体接口映射
|
||||
|
||||
| 功能 | 旧接口 | 新接口 | 变化 |
|
||||
|-----|-------|-------|-----|
|
||||
| 获取所有成就 | GET /usercenter/achievement/list | GET /achievement/list | 路径变更 |
|
||||
| 获取用户成就 | GET /usercenter/achievement/user/{userID} | GET /achievement/user/{userID} | 路径变更 |
|
||||
| 获取我的成就 | - | GET /achievement/my | **新增** |
|
||||
| 授予成就 | POST /usercenter/achievement/grant | POST /achievement/grant | 路径变更 |
|
||||
| 检查条件 | GET /usercenter/achievement/condition/{userID}/{achievementID} | GET /achievement/condition/check/{userID}/{achievementID} | 路径变更 |
|
||||
| 获取进度 | - | GET /achievement/progress/{userID} | **新增** |
|
||||
| 处理事件 | - | POST /achievement/event/process | **新增** |
|
||||
| 获取统计 | - | GET /achievement/statistics/{userID} | **新增** |
|
||||
| 排行榜 | - | GET /achievement/ranking | **新增** |
|
||||
|
||||
## ✨ 新增功能
|
||||
|
||||
### 1. 事件驱动机制
|
||||
```java
|
||||
// 自动监听业务事件并触发成就检测
|
||||
@Autowired
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
AchievementEvent event = AchievementEvent.builder(userID, eventType)
|
||||
.value(value)
|
||||
.build();
|
||||
eventPublisher.publishEvent(event);
|
||||
```
|
||||
|
||||
### 2. 成就进度追踪
|
||||
```java
|
||||
// 查询用户的成就进度
|
||||
ResultDomain<TbUserAchievementProgress> result =
|
||||
achievementService.getMyAchievementProgress(achievementID);
|
||||
```
|
||||
|
||||
### 3. 策略模式检测器
|
||||
- 可扩展的成就检测器
|
||||
- 支持多种成就类型
|
||||
- 易于添加新的成就类型
|
||||
|
||||
### 4. 统计和排行榜
|
||||
```java
|
||||
// 获取用户统计
|
||||
ResultDomain<Map<String, Object>> stats =
|
||||
achievementService.getUserAchievementStatistics(userID);
|
||||
|
||||
// 获取排行榜
|
||||
ResultDomain<Map<String, Object>> ranking =
|
||||
achievementService.getAchievementRanking(10);
|
||||
```
|
||||
|
||||
## 🚨 注意事项
|
||||
|
||||
### 1. 破坏性变更
|
||||
|
||||
#### ❌ 已删除的类(不再可用)
|
||||
- `org.xyzh.api.usercenter.achievement.UserAchievementService`
|
||||
- `org.xyzh.usercenter.service.UCUserAchievementService`
|
||||
- `org.xyzh.usercenter.mapper.AchievementMapper`
|
||||
- `org.xyzh.usercenter.controller.UserAchievementController`
|
||||
|
||||
#### ✅ 对应的新类
|
||||
- `org.xyzh.api.achievement.AchievementService`
|
||||
- `org.xyzh.achievement.service.impl.ACHAchievementServiceImpl`
|
||||
- `org.xyzh.achievement.mapper.AchievementMapper`
|
||||
- `org.xyzh.achievement.controller.AchievementController`
|
||||
|
||||
### 2. 接口变化
|
||||
|
||||
新的 `AchievementService` 接口方法更多、更完善:
|
||||
- ✅ 所有旧方法都有对应的新方法
|
||||
- ✅ 新增了事件处理、进度查询、统计等功能
|
||||
- ✅ 方法签名大部分保持兼容
|
||||
|
||||
### 3. 前端调用
|
||||
|
||||
如果你的前端代码调用了成就相关API,需要:
|
||||
1. 更新API路径:`/usercenter/achievement/*` → `/achievement/*`
|
||||
2. 检查返回数据格式(大部分保持兼容)
|
||||
3. 利用新增的API(进度、统计、排行榜等)
|
||||
|
||||
## 📋 迁移检查清单
|
||||
|
||||
迁移时请检查以下项目:
|
||||
|
||||
- [ ] 更新 pom.xml 依赖
|
||||
- [ ] 更新 import 语句
|
||||
- [ ] 更新服务注入
|
||||
- [ ] 更新方法调用
|
||||
- [ ] 测试成就创建功能
|
||||
- [ ] 测试成就授予功能
|
||||
- [ ] 测试成就查询功能
|
||||
- [ ] 测试事件触发功能(如有)
|
||||
- [ ] 更新前端API路径(如有)
|
||||
- [ ] 更新相关文档
|
||||
- [ ] 执行集成测试
|
||||
|
||||
## 🆘 常见问题
|
||||
|
||||
### Q1: 编译报错找不到 UserAchievementService
|
||||
**A:** 更新 import 语句为:
|
||||
```java
|
||||
import org.xyzh.api.achievement.AchievementService;
|
||||
```
|
||||
|
||||
### Q2: 旧的成就数据会丢失吗?
|
||||
**A:** 不会。数据库表结构保持不变,所有数据完整保留。
|
||||
|
||||
### Q3: 需要修改数据库吗?
|
||||
**A:** 需要执行新表创建SQL(`tb_user_achievement_progress`),见 `.bin/mysql/sql/createTableAchievement.sql`。
|
||||
|
||||
### Q4: 如何使用新的事件驱动功能?
|
||||
**A:** 参考 `README.md` 中的"使用方法"章节。
|
||||
|
||||
### Q5: admin模块已经自动配置好了吗?
|
||||
**A:** 是的,admin模块的pom.xml已自动添加achievement依赖。
|
||||
|
||||
## 📚 相关文档
|
||||
|
||||
- [成就系统使用文档](../README.md)
|
||||
- [数据库建表SQL](../../.bin/mysql/sql/createTableAchievement.sql)
|
||||
|
||||
## 👥 联系支持
|
||||
|
||||
如果在迁移过程中遇到问题,请联系:
|
||||
- 开发者:yslg
|
||||
- 创建Issue或PR
|
||||
|
||||
---
|
||||
|
||||
**迁移完成日期**: 2025-10-24
|
||||
**版本**: 1.0.0
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.xyzh.common.core.event.AchievementEvent;
|
||||
import org.xyzh.common.core.page.PageDomain;
|
||||
import org.xyzh.common.core.page.PageParam;
|
||||
import org.xyzh.common.dto.user.TbSysUser;
|
||||
import org.xyzh.common.dto.user.TbSysUserInfo;
|
||||
import org.xyzh.common.dto.usercenter.TbAchievement;
|
||||
import org.xyzh.common.dto.usercenter.TbUserAchievement;
|
||||
import org.xyzh.common.dto.usercenter.TbUserAchievementProgress;
|
||||
@@ -26,6 +27,7 @@ import org.xyzh.common.utils.IDUtils;
|
||||
import org.xyzh.common.vo.AchievementVO;
|
||||
import org.xyzh.system.utils.LoginUtil;
|
||||
import org.xyzh.api.system.permission.ResourcePermissionService;
|
||||
import org.xyzh.system.mapper.UserInfoMapper;
|
||||
import org.xyzh.common.vo.UserDeptRoleVO;
|
||||
import org.xyzh.common.core.enums.ResourceType;
|
||||
|
||||
@@ -62,6 +64,9 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Autowired
|
||||
private UserInfoMapper userInfoMapper;
|
||||
|
||||
// ==================== 成就定义管理 ====================
|
||||
|
||||
@@ -551,7 +556,7 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
||||
|
||||
// 检查是否达成
|
||||
if (checker.check(event, achievement, currentProgress)) {
|
||||
TbUserAchievement userAchievement = grantAchievementInternal(event.getUserID(), achievement.getAchievementID());
|
||||
TbUserAchievement userAchievement = grantAchievementInternal(event.getUserID(), achievement);
|
||||
if (userAchievement != null) {
|
||||
newAchievements.add(userAchievement);
|
||||
logger.info("用户 {} 通过事件 {} 获得成就: {}", event.getUserID(), event.getEventType(), achievement.getName());
|
||||
@@ -748,17 +753,21 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
||||
/**
|
||||
* 内部授予成就方法(不检查是否已获得)
|
||||
*/
|
||||
private TbUserAchievement grantAchievementInternal(String userID, String achievementID) {
|
||||
private TbUserAchievement grantAchievementInternal(String userID, TbAchievement achievement) {
|
||||
try {
|
||||
TbUserAchievement userAchievement = new TbUserAchievement();
|
||||
userAchievement.setID(IDUtils.generateID());
|
||||
userAchievement.setUserID(userID);
|
||||
userAchievement.setAchievementID(achievementID);
|
||||
userAchievement.setAchievementID(achievement.getAchievementID());
|
||||
userAchievement.setObtainTime(new Date());
|
||||
|
||||
int result = userAchievementMapper.insertUserAchievement(userAchievement);
|
||||
if (result > 0) {
|
||||
updateProgressToCompleted(userID, achievementID);
|
||||
updateProgressToCompleted(userID, achievement.getAchievementID());
|
||||
|
||||
// 检查是否需要更新用户等级(learning_time开头的成就)
|
||||
updateUserLevelIfNeeded(userID, achievement);
|
||||
|
||||
return userAchievement;
|
||||
}
|
||||
return null;
|
||||
@@ -824,5 +833,56 @@ public class ACHAchievementServiceImpl implements AchievementService {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并更新用户等级(仅针对learning_time开头的成就)
|
||||
* @param userID 用户ID
|
||||
* @param achievement 成就对象
|
||||
*/
|
||||
private void updateUserLevelIfNeeded(String userID, TbAchievement achievement) {
|
||||
try {
|
||||
// 检查成就ID是否以learning_time开头
|
||||
if (achievement == null || achievement.getAchievementID() == null ||
|
||||
!achievement.getAchievementID().startsWith("learning_time")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查成就是否有等级信息
|
||||
if (achievement.getLevel() == null) {
|
||||
logger.warn("成就没有等级信息: {}", achievement.getAchievementID());
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取用户当前信息
|
||||
TbSysUserInfo userInfo = userInfoMapper.selectById(userID);
|
||||
if (userInfo == null) {
|
||||
logger.warn("用户信息不存在: {}", userID);
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否需要更新等级(只有当成就等级高于当前用户等级时才更新)
|
||||
Integer currentLevel = userInfo.getLevel() != null ? userInfo.getLevel() : 0;
|
||||
Integer achievementLevel = achievement.getLevel();
|
||||
|
||||
if (achievementLevel > currentLevel) {
|
||||
userInfo.setLevel(achievementLevel);
|
||||
int updateResult = userInfoMapper.updateUserInfo(userInfo);
|
||||
|
||||
if (updateResult > 0) {
|
||||
logger.info("用户 {} 通过成就 {} 等级从 {} 提升到 {}",
|
||||
userID, achievement.getAchievementID(), currentLevel, achievementLevel);
|
||||
} else {
|
||||
logger.error("更新用户等级失败: userID={}, achievementID={}", userID, achievement.getAchievementID());
|
||||
}
|
||||
} else {
|
||||
logger.debug("用户 {} 当前等级 {} 已达到或超过成就等级 {},无需更新",
|
||||
userID, currentLevel, achievementLevel);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("更新用户等级时发生异常: userID={}, achievementID={}, error={}",
|
||||
userID, achievement.getAchievementID(), e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -272,8 +272,8 @@ public class NewsCrawlerTask extends PythonCommandTask {
|
||||
// 状态和时间
|
||||
item.setStatus(0); // 未处理
|
||||
item.setCrawlTime(now);
|
||||
ResultDomain<Boolean> pass = auditService.auditText(item.getContent());
|
||||
if(pass.isSuccess() && pass.getData()){
|
||||
ResultDomain<String> pass = auditService.auditText(item.getContent());
|
||||
if(pass.isSuccess()){
|
||||
item.setIsAudited(true);
|
||||
passList.add(item);
|
||||
}else{
|
||||
|
||||
@@ -265,15 +265,15 @@ public class SysMenuServiceImpl implements SysMenuService {
|
||||
}
|
||||
|
||||
// 检查菜单名称是否已存在(排除自身)
|
||||
ResultDomain<Boolean> checkResult = checkMenuNameExists(menu.getName(), menu.getID());
|
||||
if (!checkResult.isSuccess()) {
|
||||
resultDomain.fail(checkResult.getMessage());
|
||||
return resultDomain;
|
||||
}
|
||||
if (checkResult.getData()) {
|
||||
resultDomain.fail("菜单名称已存在");
|
||||
return resultDomain;
|
||||
}
|
||||
// ResultDomain<Boolean> checkResult = checkMenuNameExists(menu.getName(), menu.getID());
|
||||
// if (!checkResult.isSuccess()) {
|
||||
// resultDomain.fail(checkResult.getMessage());
|
||||
// return resultDomain;
|
||||
// }
|
||||
// if (checkResult.getData()) {
|
||||
// resultDomain.fail("菜单名称已存在");
|
||||
// return resultDomain;
|
||||
// }
|
||||
|
||||
// 设置更新时间
|
||||
menu.setUpdateTime(new Date());
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
SELECT COUNT(1)
|
||||
FROM tb_sys_menu m
|
||||
WHERE deleted = 0
|
||||
AND m.name = #{name}
|
||||
AND m.name = #{menuName}
|
||||
<if test="excludeId != null and excludeId != ''">
|
||||
AND m.id != #{excludeId}
|
||||
</if>
|
||||
|
||||
Reference in New Issue
Block a user