Преглед изворни кода

Merge branch 'cjp' into test_dev

# Conflicts:
#	gateway/src/main/resources/application.yml
caojp пре 1 месец
родитељ
комит
e0500aa713

+ 13 - 2
gateway/src/main/resources/application.yml

@@ -161,14 +161,25 @@ spring:
           filters:
             - StripPrefix=1
         
-        # 课程服务路由(homePage服务)
+        # 课程服务路由(homePage服务,端口8081)
+        # 注意:课程Controller在homePage服务中,路径为 /api/course/**
         - id: course-route
           uri: http://localhost:8081
           predicates:
             - Path=/api/course/**
           filters:
             - StripPrefix=0
-        
+
+        # 推荐服务路由(Recommend服务,端口8089)
+        # 注意:必须在homepage-route之前,避免被兜底路由覆盖
+        - id: recommend-route
+          uri: http://localhost:8089
+          predicates:
+            - Path=/api/recommend/**
+          filters:
+            - StripPrefix=0
+            - StripPrefix=0
+
         # 课程订单服务路由(Essential服务-微信支付)
         - id: course-order-route
           uri: http://localhost:1005

+ 10 - 0
marriageAdmin-vue/src/config/api.js

@@ -13,6 +13,16 @@ export const API_ENDPOINTS = {
   LOGOUT: '/admin/auth/logout',
   GET_USER_INFO: '/admin/auth/userInfo',
   
+  // 管理员管理
+  ADMIN_USER_LIST: '/admin/admin-user/list',
+  ADMIN_USER_DETAIL: '/admin/admin-user/detail',
+  ADMIN_USER_REGISTER: '/admin/admin-user/register',
+  ADMIN_USER_UPDATE: '/admin/admin-user/update',
+  ADMIN_USER_DELETE: '/admin/admin-user/delete',
+  ADMIN_USER_DISABLE: '/admin/admin-user/disable',
+  ADMIN_USER_ENABLE: '/admin/admin-user/enable',
+  ADMIN_USER_ROLES: '/admin/admin-user/roles',
+  
   // 轮播图管理
   BANNER_LIST: '/admin/banner/list',
   BANNER_DETAIL: '/admin/banner/detail',

+ 12 - 2
marriageAdmin-vue/src/layouts/MainLayout.vue

@@ -19,7 +19,8 @@
         text-color="#cbd5e1"
         active-text-color="#ffffff"
       >
-        <el-menu-item index="/dashboard">
+        <!-- 数据面板 - 仅超级管理员 -->
+        <el-menu-item v-if="isSuperAdmin" index="/dashboard">
           <el-icon><DataBoard /></el-icon>
           <template #title>数据面板</template>
         </el-menu-item>
@@ -34,6 +35,12 @@
           <template #title>小喇叭公告</template>
         </el-menu-item>
         
+        <!-- 管理员管理 - 仅超级管理员 -->
+        <el-menu-item v-if="isSuperAdmin" index="/admin-user">
+          <el-icon><User /></el-icon>
+          <template #title>管理员管理</template>
+        </el-menu-item>
+        
         <el-sub-menu index="/activity">
           <template #title>
             <el-icon><Calendar /></el-icon>
@@ -51,6 +58,7 @@
           <el-menu-item index="/matchmaker/list">红娘列表</el-menu-item>
           <el-menu-item index="/matchmaker/audit">红娘审核</el-menu-item>
           <el-menu-item index="/matchmaker/create">添加红娘</el-menu-item>
+          <el-menu-item index="/matchmaker/points-product">积分商品</el-menu-item>
         </el-sub-menu>
         
         <el-sub-menu index="/course">
@@ -80,7 +88,8 @@
           <el-menu-item index="/user/vip">VIP用户</el-menu-item>
         </el-sub-menu>
         
-        <el-menu-item index="/vip-package">
+        <!-- VIP套餐 - 仅超级管理员 -->
+        <el-menu-item v-if="isSuperAdmin" index="/vip-package">
           <el-icon><Medal /></el-icon>
           <template #title>VIP套餐</template>
         </el-menu-item>
@@ -170,6 +179,7 @@ const isCollapse = ref(false)
 const userInfo = computed(() => userStore.userInfo)
 const currentRoute = computed(() => route)
 const activeMenu = computed(() => route.path)
+const isSuperAdmin = computed(() => userStore.isSuperAdmin)
 
 // 切换侧边栏折叠状态
 const toggleCollapse = () => {

+ 13 - 0
marriageAdmin-vue/src/router/index.js

@@ -39,6 +39,13 @@ const router = createRouter({
           component: () => import('@/views/announcement/AnnouncementList.vue'),
           meta: { title: '小喇叭公告', icon: 'Microphone' }
         },
+        // 管理员管理
+        {
+          path: 'admin-user',
+          name: 'AdminUser',
+          component: () => import('@/views/admin/AdminUserList.vue'),
+          meta: { title: '管理员管理', icon: 'User' }
+        },
         // 活动管理
         {
           path: 'activity',
@@ -102,6 +109,12 @@ const router = createRouter({
               name: 'MatchmakerEdit',
               component: () => import('@/views/matchmaker/MatchmakerForm.vue'),
               meta: { title: '编辑红娘' }
+            },
+            {
+              path: 'points-product',
+              name: 'PointsProduct',
+              component: () => import('@/views/points-product/PointsProductList.vue'),
+              meta: { title: '积分商品' }
             }
           ]
         },

+ 12 - 1
marriageAdmin-vue/src/stores/user.js

@@ -10,7 +10,8 @@ export const useUserStore = defineStore('user', () => {
   // 状态
   const token = ref(localStorage.getItem('admin_token') || '')
   const userInfo = ref(JSON.parse(localStorage.getItem('admin_user') || 'null'))
-  const permissions = ref([])
+  const permissions = ref(JSON.parse(localStorage.getItem('admin_permissions') || '[]'))
+  const isSuperAdmin = ref(localStorage.getItem('admin_isSuperAdmin') === 'true')
   
   // 登录
   const login = async (username, password) => {
@@ -24,10 +25,13 @@ export const useUserStore = defineStore('user', () => {
         token.value = response.data.token
         userInfo.value = response.data.userInfo
         permissions.value = response.data.permissions || []
+        isSuperAdmin.value = response.data.isSuperAdmin || false
         
         // 保存到 localStorage
         localStorage.setItem('admin_token', response.data.token)
         localStorage.setItem('admin_user', JSON.stringify(response.data.userInfo))
+        localStorage.setItem('admin_permissions', JSON.stringify(response.data.permissions || []))
+        localStorage.setItem('admin_isSuperAdmin', response.data.isSuperAdmin ? 'true' : 'false')
         
         return true
       }
@@ -48,8 +52,11 @@ export const useUserStore = defineStore('user', () => {
       token.value = ''
       userInfo.value = null
       permissions.value = []
+      isSuperAdmin.value = false
       localStorage.removeItem('admin_token')
       localStorage.removeItem('admin_user')
+      localStorage.removeItem('admin_permissions')
+      localStorage.removeItem('admin_isSuperAdmin')
     }
   }
   
@@ -60,7 +67,10 @@ export const useUserStore = defineStore('user', () => {
       if (response.code === 200) {
         userInfo.value = response.data.userInfo
         permissions.value = response.data.permissions || []
+        isSuperAdmin.value = response.data.isSuperAdmin || false
         localStorage.setItem('admin_user', JSON.stringify(response.data.userInfo))
+        localStorage.setItem('admin_permissions', JSON.stringify(response.data.permissions || []))
+        localStorage.setItem('admin_isSuperAdmin', response.data.isSuperAdmin ? 'true' : 'false')
         return true
       }
       return false
@@ -79,6 +89,7 @@ export const useUserStore = defineStore('user', () => {
     token,
     userInfo,
     permissions,
+    isSuperAdmin,
     login,
     logout,
     getUserInfo,

+ 6 - 0
service/Essential/pom.xml

@@ -31,6 +31,12 @@
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
+        <!-- Spring Boot Starter Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
         <!-- Spring Boot Redis -->
         <dependency>
             <groupId>org.springframework.boot</groupId>

+ 10 - 0
service/admin/pom.xml

@@ -76,5 +76,15 @@
             <groupId>org.springframework.security</groupId>
             <artifactId>spring-security-crypto</artifactId>
         </dependency>
+        <!-- Spring Security -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>4.4.0</version>
+        </dependency>
     </dependencies>
 </project>

+ 22 - 3
service/admin/src/main/java/com/zhentao/controller/AuthController.java

@@ -3,10 +3,12 @@ package com.zhentao.controller;
 import com.zhentao.common.Result;
 import com.zhentao.entity.AdminUser;
 import com.zhentao.service.AuthService;
+import com.zhentao.service.AdminSecurityService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -20,6 +22,9 @@ public class AuthController {
     @Autowired
     private AuthService authService;
     
+    @Autowired
+    private AdminSecurityService adminSecurityService;
+    
     /**
      * 登录
      */
@@ -39,16 +44,23 @@ public class AuthController {
                 return Result.error("用户名或密码错误");
             }
             
-            // 生成token(这里简化处理,实际项目应使用JWT)
+            // 生成token
             String token = authService.generateToken(user);
             
+            // 获取用户权限
+            List<String> permissions = adminSecurityService.getUserPermissions(user.getId());
+            List<String> roles = adminSecurityService.getUserRoles(user.getId());
+            boolean isSuperAdmin = adminSecurityService.isSuperAdmin(user.getId());
+            
             Map<String, Object> data = new HashMap<>();
             data.put("token", token);
             
             // 返回用户信息(不包含密码)
             user.setPassword(null);
             data.put("userInfo", user);
-            data.put("permissions", new String[]{"*"});
+            data.put("permissions", permissions);
+            data.put("roles", roles);
+            data.put("isSuperAdmin", isSuperAdmin);
             
             return Result.success(data);
         } catch (Exception e) {
@@ -82,10 +94,17 @@ public class AuthController {
                 return Result.error(401, "token无效");
             }
             
+            // 获取用户权限
+            List<String> permissions = adminSecurityService.getUserPermissions(user.getId());
+            List<String> roles = adminSecurityService.getUserRoles(user.getId());
+            boolean isSuperAdmin = adminSecurityService.isSuperAdmin(user.getId());
+            
             Map<String, Object> data = new HashMap<>();
             user.setPassword(null);
             data.put("userInfo", user);
-            data.put("permissions", new String[]{"*"});
+            data.put("permissions", permissions);
+            data.put("roles", roles);
+            data.put("isSuperAdmin", isSuperAdmin);
             
             return Result.success(data);
         } catch (Exception e) {

+ 92 - 33
service/admin/src/main/java/com/zhentao/entity/AdminUser.java

@@ -1,77 +1,136 @@
 package com.zhentao.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.Date;
 import lombok.Data;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
- * 管理员用户实体
+ * 管理员用户表
+ * @TableName admin_user
  */
+@TableName(value ="admin_user")
 @Data
-@TableName("admin_user")
-public class AdminUser implements Serializable {
-    
-    private static final long serialVersionUID = 1L;
-    
-    @TableId(value = "id", type = IdType.AUTO)
+public class AdminUser {
+    /**
+     * 主键ID
+     */
+    @TableId(type = IdType.AUTO)
     private Integer id;
-    
+
     /**
      * 用户名
      */
     private String username;
-    
+
     /**
-     * 密码(加密
+     * 密码(MD5加密)
      */
     private String password;
-    
+
+    /**
+     * 密码盐
+     */
+    private String salt;
+
     /**
      * 真实姓名
      */
     private String realName;
-    
+
     /**
      * 手机号
      */
     private String phone;
-    
+
     /**
      * 邮箱
      */
     private String email;
-    
-    /**
-     * 角色:1-超级管理员 2-普通管理员
-     */
-    private Integer role;
-    
+
     /**
      * 状态:0-禁用 1-启用
      */
     private Integer status;
-    
+
     /**
      * 创建时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-    
+    private Date createTime;
+
     /**
      * 更新时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-    
+    private Date updateTime;
+
     /**
      * 最后登录时间
      */
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime lastLoginTime;
-}
+    private Date lastLoginTime;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        AdminUser other = (AdminUser) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getUsername() == null ? other.getUsername() == null : this.getUsername().equals(other.getUsername()))
+            && (this.getPassword() == null ? other.getPassword() == null : this.getPassword().equals(other.getPassword()))
+            && (this.getSalt() == null ? other.getSalt() == null : this.getSalt().equals(other.getSalt()))
+            && (this.getRealName() == null ? other.getRealName() == null : this.getRealName().equals(other.getRealName()))
+            && (this.getPhone() == null ? other.getPhone() == null : this.getPhone().equals(other.getPhone()))
+            && (this.getEmail() == null ? other.getEmail() == null : this.getEmail().equals(other.getEmail()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
+            && (this.getLastLoginTime() == null ? other.getLastLoginTime() == null : this.getLastLoginTime().equals(other.getLastLoginTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getUsername() == null) ? 0 : getUsername().hashCode());
+        result = prime * result + ((getPassword() == null) ? 0 : getPassword().hashCode());
+        result = prime * result + ((getSalt() == null) ? 0 : getSalt().hashCode());
+        result = prime * result + ((getRealName() == null) ? 0 : getRealName().hashCode());
+        result = prime * result + ((getPhone() == null) ? 0 : getPhone().hashCode());
+        result = prime * result + ((getEmail() == null) ? 0 : getEmail().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        result = prime * result + ((getLastLoginTime() == null) ? 0 : getLastLoginTime().hashCode());
+        return result;
+    }
 
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", username=").append(username);
+        sb.append(", password=").append(password);
+        sb.append(", salt=").append(salt);
+        sb.append(", realName=").append(realName);
+        sb.append(", phone=").append(phone);
+        sb.append(", email=").append(email);
+        sb.append(", status=").append(status);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", lastLoginTime=").append(lastLoginTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 124 - 36
service/admin/src/main/java/com/zhentao/entity/PointsProduct.java

@@ -1,56 +1,144 @@
 package com.zhentao.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.Date;
 import lombok.Data;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
- * 积分商品实体类
+ * 
+ * @TableName points_product
  */
+@TableName(value ="points_product")
 @Data
-@TableName("points_product")
-public class PointsProduct implements Serializable {
-    
-    private static final long serialVersionUID = 1L;
-    
-    @TableId(value = "id", type = IdType.AUTO)
+public class PointsProduct {
+    /**
+     * 
+     */
+    @TableId(type = IdType.AUTO)
     private Long id;
-    
-    /** 商品名称 */
+
+    /**
+     * 商品名称
+     */
     private String name;
-    
-    /** 商品描述 */
+
+    /**
+     * 商品描述
+     */
     private String description;
-    
-    /** 商品图片 */
+
+    /**
+     * 商品图片
+     */
     private String imageUrl;
-    
-    /** 积分价格 */
+
+    /**
+     * 积分价格
+     */
     private Integer pointsPrice;
-    
-    /** 库存数量 */
+
+    /**
+     * 库存
+     */
     private Integer stock;
-    
-    /** 分类: 1-实物商品 2-虚拟商品 */
+
+    /**
+     * 1-实物 2-虚拟
+     */
     private Integer category;
-    
-    /** 是否推荐: 0-否 1-是 */
+
+    /**
+     * 是否推荐
+     */
     private Integer isRecommend;
-    
-    /** 状态: 0-下架 1-上架 */
+
+    /**
+     * 0-下架 1-上架
+     */
     private Integer status;
-    
-    /** 排序 */
+
+    /**
+     * 
+     */
     private Integer sortOrder;
-    
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime createTime;
-    
-    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
-    private LocalDateTime updateTime;
-}
+
+    /**
+     * 
+     */
+    private Date createTime;
+
+    /**
+     * 
+     */
+    private Date updateTime;
+
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        PointsProduct other = (PointsProduct) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
+            && (this.getDescription() == null ? other.getDescription() == null : this.getDescription().equals(other.getDescription()))
+            && (this.getImageUrl() == null ? other.getImageUrl() == null : this.getImageUrl().equals(other.getImageUrl()))
+            && (this.getPointsPrice() == null ? other.getPointsPrice() == null : this.getPointsPrice().equals(other.getPointsPrice()))
+            && (this.getStock() == null ? other.getStock() == null : this.getStock().equals(other.getStock()))
+            && (this.getCategory() == null ? other.getCategory() == null : this.getCategory().equals(other.getCategory()))
+            && (this.getIsRecommend() == null ? other.getIsRecommend() == null : this.getIsRecommend().equals(other.getIsRecommend()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getSortOrder() == null ? other.getSortOrder() == null : this.getSortOrder().equals(other.getSortOrder()))
+            && (this.getCreateTime() == null ? other.getCreateTime() == null : this.getCreateTime().equals(other.getCreateTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()));
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getDescription() == null) ? 0 : getDescription().hashCode());
+        result = prime * result + ((getImageUrl() == null) ? 0 : getImageUrl().hashCode());
+        result = prime * result + ((getPointsPrice() == null) ? 0 : getPointsPrice().hashCode());
+        result = prime * result + ((getStock() == null) ? 0 : getStock().hashCode());
+        result = prime * result + ((getCategory() == null) ? 0 : getCategory().hashCode());
+        result = prime * result + ((getIsRecommend() == null) ? 0 : getIsRecommend().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getSortOrder() == null) ? 0 : getSortOrder().hashCode());
+        result = prime * result + ((getCreateTime() == null) ? 0 : getCreateTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", name=").append(name);
+        sb.append(", description=").append(description);
+        sb.append(", imageUrl=").append(imageUrl);
+        sb.append(", pointsPrice=").append(pointsPrice);
+        sb.append(", stock=").append(stock);
+        sb.append(", category=").append(category);
+        sb.append(", isRecommend=").append(isRecommend);
+        sb.append(", status=").append(status);
+        sb.append(", sortOrder=").append(sortOrder);
+        sb.append(", createTime=").append(createTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append("]");
+        return sb.toString();
+    }
+}

+ 10 - 5
service/admin/src/main/java/com/zhentao/mapper/AdminUserMapper.java

@@ -1,13 +1,18 @@
 package com.zhentao.mapper;
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zhentao.entity.AdminUser;
-import org.apache.ibatis.annotations.Mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
- * 管理员用户Mapper
- */
-@Mapper
+* @author 联想
+* @description 针对表【admin_user(管理员用户表)】的数据库操作Mapper
+* @createDate 2025-12-11 16:08:57
+* @Entity com.zhentao.entity.AdminUser
+*/
 public interface AdminUserMapper extends BaseMapper<AdminUser> {
+
 }
 
+
+
+

+ 11 - 5
service/admin/src/main/java/com/zhentao/mapper/PointsProductMapper.java

@@ -1,12 +1,18 @@
 package com.zhentao.mapper;
 
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zhentao.entity.PointsProduct;
-import org.apache.ibatis.annotations.Mapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
 /**
- * 积分商品Mapper
- */
-@Mapper
+* @author 联想
+* @description 针对表【points_product】的数据库操作Mapper
+* @createDate 2025-12-11 10:49:42
+* @Entity com.zhentao.entity.PointsProduct
+*/
 public interface PointsProductMapper extends BaseMapper<PointsProduct> {
+
 }
+
+
+
+

+ 37 - 12
service/admin/src/main/java/com/zhentao/service/impl/AuthServiceImpl.java

@@ -10,7 +10,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.util.DigestUtils;
 
 import java.nio.charset.StandardCharsets;
-import java.time.LocalDateTime;
+import java.util.Date;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
@@ -40,17 +40,34 @@ public class AuthServiceImpl implements AuthService {
                 return null;
             }
             
-            // 验证密码(简化处理,实际项目应使用BCrypt)
-            String encryptedPassword = encryptPassword(password);
-            if (!user.getPassword().equals(encryptedPassword)) {
-                // 兼容明文密码(测试用)
-                if (!user.getPassword().equals(password)) {
+            // 验证密码:MD5(密码+盐)
+            if (user.getSalt() == null || user.getSalt().isEmpty()) {
+                // 兼容旧数据:如果没有盐,使用MD5(密码)验证
+                String md5Password = encryptPassword(password, "");
+                if (!user.getPassword().equals(md5Password)) {
+                    // 兼容明文密码(测试用)
+                    if (!user.getPassword().equals(password)) {
+                        return null;
+                    } else {
+                        // 如果是明文密码,更新为加密密码
+                        String salt = generateSalt();
+                        String encryptedPassword = encryptPassword(password, salt);
+                        user.setSalt(salt);
+                        user.setPassword(encryptedPassword);
+                        user.setUpdateTime(new Date());
+                        adminUserMapper.updateById(user);
+                    }
+                }
+            } else {
+                // 使用盐验证密码:MD5(密码+盐)
+                String encryptedPassword = encryptPassword(password, user.getSalt());
+                if (!user.getPassword().equals(encryptedPassword)) {
                     return null;
                 }
             }
             
             // 更新最后登录时间
-            user.setLastLoginTime(LocalDateTime.now());
+            user.setLastLoginTime(new Date());
             adminUserMapper.updateById(user);
             
             return user;
@@ -64,11 +81,11 @@ public class AuthServiceImpl implements AuthService {
     public String generateToken(AdminUser user) {
         String token = UUID.randomUUID().toString().replace("-", "");
         
-        // 将token存储到Redis(如果可用)
+        // 将token存储到Redis(如果可用),1小时过期
         if (redisTemplate != null) {
             try {
                 String key = "admin:token:" + token;
-                redisTemplate.opsForValue().set(key, String.valueOf(user.getId()), 24, TimeUnit.HOURS);
+                redisTemplate.opsForValue().set(key, String.valueOf(user.getId()), 1, TimeUnit.HOURS);
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -113,10 +130,18 @@ public class AuthServiceImpl implements AuthService {
     }
     
     /**
-     * 密码加密(简化版,实际项目应使用BCrypt)
+     * 生成随机盐
+     */
+    private String generateSalt() {
+        return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
+    }
+    
+    /**
+     * 密码加密:MD5(密码+盐)
      */
-    private String encryptPassword(String password) {
-        return DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));
+    private String encryptPassword(String password, String salt) {
+        String passwordWithSalt = password + salt;
+        return DigestUtils.md5DigestAsHex(passwordWithSalt.getBytes(StandardCharsets.UTF_8));
     }
 }
 

+ 5 - 0
service/homePage/pom.xml

@@ -53,6 +53,11 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
+        <!-- Spring Boot Starter Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.minio</groupId>
             <artifactId>minio</artifactId>

+ 3 - 1
service/homePage/src/main/java/com/zhentao/controller/ActivityController.java

@@ -14,6 +14,7 @@ import java.util.*;
  */
 @RestController
 @RequestMapping("/api/activity")
+@CrossOrigin(origins = "*")
 public class ActivityController {
     
     @Autowired
@@ -110,7 +111,8 @@ public class ActivityController {
             return Result.success(activityList);
         } catch (Exception e) {
             e.printStackTrace();
-            return Result.error("获取活动列表失败:" + e.getMessage());
+            System.err.println("❌ 获取活动列表异常: " + e.getClass().getName() + " - " + e.getMessage());
+            return Result.error("获取活动列表失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
         }
     }
     

+ 13 - 3
service/homePage/src/main/java/com/zhentao/controller/CourseController.java

@@ -17,6 +17,7 @@ import java.util.Map;
  */
 @RestController
 @RequestMapping("/api/course")
+@CrossOrigin(origins = "*")
 public class CourseController {
     
     @Autowired
@@ -51,10 +52,18 @@ public class CourseController {
      */
     @GetMapping("/list")
     public Result<Map<String, Object>> getCourseList(
-            @RequestParam(defaultValue = "1") Integer page,
-            @RequestParam(defaultValue = "10") Integer pageSize,
+            @RequestParam(required = false, defaultValue = "1") Integer page,
+            @RequestParam(required = false, defaultValue = "10") Integer pageSize,
             @RequestParam(required = false) Integer status) {
         try {
+            // 参数校验和默认值设置
+            if (page == null || page < 1) {
+                page = 1;
+            }
+            if (pageSize == null || pageSize < 1) {
+                pageSize = 10;
+            }
+            
             Page<Course> pageObj = new Page<>(page, pageSize);
             LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
             // 如果指定了 status 参数,则按状态过滤(用于小程序端)
@@ -90,7 +99,8 @@ public class CourseController {
             return Result.success(data);
         } catch (Exception e) {
             e.printStackTrace();
-            return Result.error("获取课程列表失败:" + e.getMessage());
+            System.err.println("❌ 获取课程列表异常: " + e.getClass().getName() + " - " + e.getMessage());
+            return Result.error("获取课程列表失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
         }
     }
     

+ 18 - 2
service/homePage/src/main/java/com/zhentao/controller/MatchmakerController.java

@@ -23,6 +23,7 @@ import java.util.Map;
  */
 @RestController
 @RequestMapping("/api/matchmaker")
+@CrossOrigin(origins = "*")
 public class MatchmakerController {
     
     @Autowired
@@ -40,8 +41,21 @@ public class MatchmakerController {
      * @return 分页数据
      */
     @PostMapping("/list")
-    public Result<Page<MatchmakerVO>> getMatchmakerList(@RequestBody MatchmakerQueryDTO queryDTO) {
+    public Result<Page<MatchmakerVO>> getMatchmakerList(@RequestBody(required = false) MatchmakerQueryDTO queryDTO) {
         try {
+            // 如果queryDTO为null,创建默认对象
+            if (queryDTO == null) {
+                queryDTO = new MatchmakerQueryDTO();
+            }
+            
+            // 设置默认值
+            if (queryDTO.getPageNum() == null || queryDTO.getPageNum() < 1) {
+                queryDTO.setPageNum(1);
+            }
+            if (queryDTO.getPageSize() == null || queryDTO.getPageSize() < 1) {
+                queryDTO.setPageSize(10);
+            }
+            
             // 调试日志:打印接收到的参数
             System.out.println("📥 接收到的查询参数: matchmakerType=" + queryDTO.getMatchmakerType() 
                     + ", level=" + queryDTO.getLevel() 
@@ -53,7 +67,9 @@ public class MatchmakerController {
             return Result.success(page);
         } catch (Exception e) {
             e.printStackTrace();
-            return Result.error("查询红娘列表失败:" + e.getMessage());
+            System.err.println("❌ 查询红娘列表异常: " + e.getClass().getName() + " - " + e.getMessage());
+            e.printStackTrace();
+            return Result.error("查询红娘列表失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
         }
     }
     

+ 13 - 3
service/homePage/src/main/java/com/zhentao/controller/SuccessCaseController.java

@@ -14,6 +14,7 @@ import java.util.Map;
  * 成功案例控制器
  */
 @RestController
+@CrossOrigin(origins = "*")
 public class SuccessCaseController {
     
     @Autowired
@@ -84,14 +85,23 @@ public class SuccessCaseController {
      */
     @GetMapping("/api/case/list")
     public Result<Map<String, Object>> getAdminCaseList(
-            @RequestParam(defaultValue = "1") Integer page,
-            @RequestParam(defaultValue = "10") Integer pageSize) {
+            @RequestParam(required = false, defaultValue = "1") Integer page,
+            @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
         try {
+            // 参数校验和默认值设置
+            if (page == null || page < 1) {
+                page = 1;
+            }
+            if (pageSize == null || pageSize < 1) {
+                pageSize = 10;
+            }
+            
             Map<String, Object> result = successCaseService.getAdminCaseList(page, pageSize);
             return Result.success(result);
         } catch (Exception e) {
             e.printStackTrace();
-            return Result.error("获取案例列表失败:" + e.getMessage());
+            System.err.println("❌ 获取案例列表异常: " + e.getClass().getName() + " - " + e.getMessage());
+            return Result.error("获取案例列表失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
         }
     }
     

+ 6 - 0
service/websocket/pom.xml

@@ -32,6 +32,12 @@
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 
+        <!-- Spring Boot Starter Validation -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+
         <!-- Spring Boot WebSocket -->
         <dependency>
             <groupId>org.springframework.boot</groupId>