2
0
Просмотр исходного кода

✨ feat(user): 实现学员过期自动转换功能

- 添加学员过期状态检查中间件,认证后立即验证学员有效期
- 实现学员过期自动转为学生的业务逻辑
- 在用户服务中添加checkAndUpdateTraineeStatus方法处理过期逻辑

💄 style(admin): 优化用户管理页面显示

- 移除用户列表中的"学员状态"列,减少重复信息展示
- 清理相关表格数据渲染代码,提升页面简洁度
yourname 6 месяцев назад
Родитель
Сommit
29d5772501

+ 0 - 9
src/client/admin/pages/Users.tsx

@@ -347,7 +347,6 @@ export const UsersPage = () => {
                   <TableHead>邮箱</TableHead>
                   <TableHead>真实姓名</TableHead>
                   <TableHead>用户类型</TableHead>
-                  <TableHead>学员状态</TableHead>
                   <TableHead>学员有效期</TableHead>
                   <TableHead>状态</TableHead>
                   <TableHead>创建时间</TableHead>
@@ -390,14 +389,6 @@ export const UsersPage = () => {
                          user.userType === UserType.STUDENT ? '学生' : '学员'}
                       </Badge>
                     </TableCell>
-                    <TableCell>
-                      <Badge
-                        variant={user.userType === 'trainee' ? 'default' : 'secondary'}
-                        className={user.userType === 'trainee' ? 'bg-purple-100 text-purple-800' : 'bg-gray-100 text-gray-800'}
-                      >
-                        {user.userType === 'trainee' ? '学员' : '非学员'}
-                      </Badge>
-                    </TableCell>
                     <TableCell>
                       {user.userType === 'trainee' && user.traineeValidFrom && user.traineeValidTo ? (
                         <div className="text-sm">

+ 4 - 1
src/server/middleware/auth.middleware.ts

@@ -4,6 +4,7 @@ import { UserService } from '../modules/users/user.service';
 import { AppDataSource } from '../data-source';
 import { AuthContext } from '../types/context';
 import { DisabledStatus, DeleteStatus } from '@/share/types';
+import { immediateTraineeExpiryMiddleware } from './trainee-expiry.middleware';
 
 export async function authMiddleware(c: Context<AuthContext>, next: Next) {
   try {
@@ -38,7 +39,9 @@ export async function authMiddleware(c: Context<AuthContext>, next: Next) {
 
     c.set('user', user);
     c.set('token', token);
-    await next();
+    
+    // 在认证成功后立即检查学员过期状态
+    await immediateTraineeExpiryMiddleware(c, next);
   } catch (error) {
     console.error('Authentication error:', error);
     return c.json({ message: 'Invalid token' }, 401);

+ 33 - 0
src/server/middleware/trainee-expiry.middleware.ts

@@ -0,0 +1,33 @@
+import { Context, Next } from 'hono';
+import { UserService } from '../modules/users/user.service';
+import { AppDataSource } from '../data-source';
+import { AuthContext } from '../types/context';
+import { UserType } from '../modules/users/user.enum';
+
+/**
+ * 认证后立即检查的中间件版本
+ * 在认证成功后立即检查学员过期状态
+ */
+export async function immediateTraineeExpiryMiddleware(c: Context<AuthContext>, next: Next) {
+  const user = c.get('user');
+  
+  // 在认证成功后立即检查学员过期状态
+  if (user && user.userType === UserType.TRAINEE) {
+    try {
+      const userService = new UserService(AppDataSource);
+      const statusUpdated = await userService.checkAndUpdateTraineeStatus(user.id);
+      
+      // 如果状态已更新,需要更新上下文中的用户信息
+      if (statusUpdated) {
+        const updatedUser = await userService.getUserById(user.id);
+        if (updatedUser) {
+          c.set('user', updatedUser);
+        }
+      }
+    } catch (error) {
+      console.error('立即学员过期检查失败:', error);
+    }
+  }
+  
+  await next();
+}

+ 33 - 0
src/server/modules/users/user.service.ts

@@ -323,4 +323,37 @@ export class UserService {
     
     throw new Error(`无法生成唯一的用户名,请尝试其他用户名`);
   }
+
+  /**
+   * 检查并更新学员过期状态
+   * @param userId 用户ID
+   * @returns 如果状态已更新返回true,否则返回false
+   */
+  async checkAndUpdateTraineeStatus(userId: number): Promise<boolean> {
+    try {
+      const user = await this.getUserById(userId);
+      if (!user || user.userType !== UserType.TRAINEE || !user.traineeValidTo) {
+        return false;
+      }
+
+      const now = new Date();
+      const validTo = new Date(user.traineeValidTo);
+      
+      if (now > validTo) {
+        // 学员已过期,自动变回学生
+        await this.updateUser(userId, {
+          userType: UserType.STUDENT,
+          traineeValidFrom: null,
+          traineeValidTo: null
+        });
+        console.log(`用户 ${user.username} (ID: ${user.id}) 学员身份已过期,自动变回学生`);
+        return true;
+      }
+      
+      return false;
+    } catch (error) {
+      console.error('检查学员过期状态失败:', error);
+      return false;
+    }
+  }
 }