Bladeren bron

1、邀请码管理功能
2、web用户权限管理表
3、注册、获取用户信息(课程权限)、激活邀请码

liyanbo 2 maanden geleden
bovenliggende
commit
3978dc3736
19 gewijzigde bestanden met toevoegingen van 772 en 26 verwijderingen
  1. 3 0
      byzs-framework/byzs-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/byzs/framework/tenant/core/security/TenantDataSecurityFilter.java
  2. 102 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/UserWebExpireTimeController.java
  3. 28 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimePageReqVO.java
  4. 31 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimeRespVO.java
  5. 24 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimeSaveReqVO.java
  6. 45 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/dal/dataobject/userwebexpiretime/UserWebExpireTimeDO.java
  7. 26 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/dal/mysql/userwebexpiretime/UserWebExpireTimeMapper.java
  8. 4 1
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/enums/ErrorCodeConstants.java
  9. 8 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/invitecode/InviteCodeService.java
  10. 6 1
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/invitecode/InviteCodeServiceImpl.java
  11. 63 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/userwebexpiretime/UserWebExpireTimeService.java
  12. 88 0
      byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/userwebexpiretime/UserWebExpireTimeServiceImpl.java
  13. 7 0
      byzs-module-system/src/main/resources/mapper/userwebexpiretime/UserWebExpireTimeMapper.xml
  14. 3 2
      byzs-server/src/main/resources/application.yaml
  15. 1 22
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/login/WebLoginController.java
  16. 45 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/user/WebUserInfoController.java
  17. 61 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/user/vo/WebUserVO.java
  18. 95 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/login/WebLoginServiceImpl.java
  19. 132 0
      byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/user/WebUserInfoServiceImpl.java

+ 3 - 0
byzs-framework/byzs-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/byzs/framework/tenant/core/security/TenantDataSecurityFilter.java

@@ -89,6 +89,9 @@ public class TenantDataSecurityFilter extends OncePerRequestFilter {
      */
     private boolean isExcludedPath(HttpServletRequest request) {
         String requestURI = request.getRequestURI();
+        if (requestURI.contains("bjdxWeb/web/getRoleRoute")) {
+            return false;
+        }
         return EXCLUDED_METHOD_PATHS.stream().anyMatch(path -> requestURI.contains(path));
     }
 }

+ 102 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/UserWebExpireTimeController.java

@@ -0,0 +1,102 @@
+package cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime;
+
+import cn.iocoder.byzs.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import cn.iocoder.byzs.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimePageReqVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeRespVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import cn.iocoder.byzs.module.system.service.userwebexpiretime.UserWebExpireTimeService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.List;
+
+import static cn.iocoder.byzs.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "管理后台 - 用户平台权限有效期")
+@RestController
+@RequestMapping("/system/user-web-expire-time")
+@Validated
+public class UserWebExpireTimeController {
+
+    @Resource
+    private UserWebExpireTimeService userWebExpireTimeService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建用户平台权限有效期")
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:create')")
+    public CommonResult<Long> createUserWebExpireTime(@Valid @RequestBody UserWebExpireTimeSaveReqVO createReqVO) {
+        return success(userWebExpireTimeService.createUserWebExpireTime(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新用户平台权限有效期")
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:update')")
+    public CommonResult<Boolean> updateUserWebExpireTime(@Valid @RequestBody UserWebExpireTimeSaveReqVO updateReqVO) {
+        userWebExpireTimeService.updateUserWebExpireTime(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除用户平台权限有效期")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:delete')")
+    public CommonResult<Boolean> deleteUserWebExpireTime(@RequestParam("id") Long id) {
+        userWebExpireTimeService.deleteUserWebExpireTime(id);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete-list")
+    @Parameter(name = "ids", description = "编号", required = true)
+    @Operation(summary = "批量删除用户平台权限有效期")
+                @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:delete')")
+    public CommonResult<Boolean> deleteUserWebExpireTimeList(@RequestParam("ids") List<Long> ids) {
+        userWebExpireTimeService.deleteUserWebExpireTimeListByIds(ids);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得用户平台权限有效期")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:query')")
+    public CommonResult<UserWebExpireTimeRespVO> getUserWebExpireTime(@RequestParam("id") Long id) {
+        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(id);
+        return success(BeanUtils.toBean(userWebExpireTime, UserWebExpireTimeRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得用户平台权限有效期分页")
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:query')")
+    public CommonResult<PageResult<UserWebExpireTimeRespVO>> getUserWebExpireTimePage(@Valid UserWebExpireTimePageReqVO pageReqVO) {
+        PageResult<UserWebExpireTimeDO> pageResult = userWebExpireTimeService.getUserWebExpireTimePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, UserWebExpireTimeRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出用户平台权限有效期 Excel")
+    @PreAuthorize("@ss.hasPermission('system:user-web-expire-time:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportUserWebExpireTimeExcel(@Valid UserWebExpireTimePageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<UserWebExpireTimeDO> list = userWebExpireTimeService.getUserWebExpireTimePage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "用户平台权限有效期.xls", "数据", UserWebExpireTimeRespVO.class,
+                        BeanUtils.toBean(list, UserWebExpireTimeRespVO.class));
+    }
+
+}

+ 28 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimePageReqVO.java

@@ -0,0 +1,28 @@
+package cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo;
+
+import cn.iocoder.byzs.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.byzs.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 用户平台权限有效期分页 Request VO")
+@Data
+public class UserWebExpireTimePageReqVO extends PageParam {
+
+    @Schema(description = "课程权限过期时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] courseExpireTime;
+
+    @Schema(description = "编程课权限过期时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] blocklyExpireTime;
+
+    @Schema(description = "AI实验课权限过期时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] aiCourseExpireTime;
+
+}

+ 31 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimeRespVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 用户平台权限有效期 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class UserWebExpireTimeRespVO {
+
+    @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("用户id")
+    private Long userId;
+
+    @Schema(description = "课程权限过期时间")
+    @ExcelProperty("课程权限过期时间")
+    private LocalDateTime courseExpireTime;
+
+    @Schema(description = "编程课权限过期时间")
+    @ExcelProperty("编程课权限过期时间")
+    private LocalDateTime blocklyExpireTime;
+
+    @Schema(description = "AI实验课权限过期时间")
+    @ExcelProperty("AI实验课权限过期时间")
+    private LocalDateTime aiCourseExpireTime;
+
+}

+ 24 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/controller/admin/userwebexpiretime/vo/UserWebExpireTimeSaveReqVO.java

@@ -0,0 +1,24 @@
+package cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "管理后台 - 用户平台权限有效期新增/修改 Request VO")
+@Data
+public class UserWebExpireTimeSaveReqVO {
+
+    @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long userId;
+
+    @Schema(description = "课程权限过期时间")
+    private LocalDateTime courseExpireTime;
+
+    @Schema(description = "编程课权限过期时间")
+    private LocalDateTime blocklyExpireTime;
+
+    @Schema(description = "AI实验课权限过期时间")
+    private LocalDateTime aiCourseExpireTime;
+
+}

+ 45 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/dal/dataobject/userwebexpiretime/UserWebExpireTimeDO.java

@@ -0,0 +1,45 @@
+package cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime;
+
+import cn.iocoder.byzs.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户平台权限有效期 DO
+ *
+ * @author lyb
+ */
+@TableName("system_user_web_expire_time")
+@KeySequence("system_user_web_expire_time_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UserWebExpireTimeDO extends BaseDO {
+
+    /**
+     * 用户id
+     */
+    @TableId
+    private Long userId;
+    /**
+     * 课程权限过期时间
+     */
+    private LocalDateTime courseExpireTime;
+    /**
+     * 编程课权限过期时间
+     */
+    private LocalDateTime blocklyExpireTime;
+    /**
+     * AI实验课权限过期时间
+     */
+    private LocalDateTime aiCourseExpireTime;
+
+
+}

+ 26 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/dal/mysql/userwebexpiretime/UserWebExpireTimeMapper.java

@@ -0,0 +1,26 @@
+package cn.iocoder.byzs.module.system.dal.mysql.userwebexpiretime;
+
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimePageReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户平台权限有效期 Mapper
+ *
+ * @author lyb
+ */
+@Mapper
+public interface UserWebExpireTimeMapper extends BaseMapperX<UserWebExpireTimeDO> {
+
+    default PageResult<UserWebExpireTimeDO> selectPage(UserWebExpireTimePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<UserWebExpireTimeDO>()
+                .betweenIfPresent(UserWebExpireTimeDO::getCourseExpireTime, reqVO.getCourseExpireTime())
+                .betweenIfPresent(UserWebExpireTimeDO::getBlocklyExpireTime, reqVO.getBlocklyExpireTime())
+                .betweenIfPresent(UserWebExpireTimeDO::getAiCourseExpireTime, reqVO.getAiCourseExpireTime())
+                .orderByDesc(UserWebExpireTimeDO::getUserId));
+    }
+
+}

+ 4 - 1
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/enums/ErrorCodeConstants.java

@@ -37,7 +37,10 @@ public interface ErrorCodeConstants {
     ErrorCode ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_002_002_005, "标识【{}】不能使用");
 
     // ========== 邀请码 1-002-003-000==========
-    ErrorCode INVITE_CODE_NOT_EXISTS = new ErrorCode(1_002_003_004, "邀请码不存在");
+    ErrorCode INVITE_CODE_NOT_EXISTS = new ErrorCode(1_002_030_004, "邀请码不存在");
+
+    // ========== 用户权限有效期 1-002-031-000==========
+    ErrorCode USER_WEB_EXPIRE_TIME_NOT_EXISTS = new ErrorCode(1_002_031_004, "用户平台权限有效期不存在");
 
     // ========== 用户模块 1-002-003-000 ==========
     ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_002_003_000, "用户账号已经存在");

+ 8 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/invitecode/InviteCodeService.java

@@ -61,6 +61,14 @@ public interface InviteCodeService {
      */
     InviteCodeDO getUnusedInviteCode(String inviteCode);
 
+    /**
+     * 获得用户激活的邀请码
+     *
+     * @param useUserId 使用用户id
+     * @return 邀请码
+     */
+    List<InviteCodeDO> getInviteCodeByUserId(Long useUserId);
+
     /**
      * 获得邀请码分页
      *

+ 6 - 1
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/invitecode/InviteCodeServiceImpl.java

@@ -20,7 +20,6 @@ import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
-import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -156,6 +155,12 @@ public class InviteCodeServiceImpl implements InviteCodeService {
                 .eq(InviteCodeDO::getStatus, "0"));
     }
 
+    @Override
+    public List<InviteCodeDO> getInviteCodeByUserId(Long useUserId) {
+        return inviteCodeMapper.selectList(new LambdaQueryWrapper<InviteCodeDO>()
+                .eq(InviteCodeDO::getUseUserId, useUserId));
+    }
+
     @Override
     public PageResult<InviteCodeRespVO> getInviteCodePage(InviteCodePageReqVO pageReqVO) {
         PageResult<InviteCodeDO> inviteCodeDOPageResult = inviteCodeMapper.selectPage(pageReqVO);

+ 63 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/userwebexpiretime/UserWebExpireTimeService.java

@@ -0,0 +1,63 @@
+package cn.iocoder.byzs.module.system.service.userwebexpiretime;
+
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimePageReqVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import jakarta.validation.Valid;
+
+import java.util.List;
+
+/**
+ * 用户平台权限有效期 Service 接口
+ *
+ * @author lyb
+ */
+public interface UserWebExpireTimeService {
+
+    /**
+     * 创建用户平台权限有效期
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createUserWebExpireTime(@Valid UserWebExpireTimeSaveReqVO createReqVO);
+
+    /**
+     * 更新用户平台权限有效期
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateUserWebExpireTime(@Valid UserWebExpireTimeSaveReqVO updateReqVO);
+
+    /**
+     * 删除用户平台权限有效期
+     *
+     * @param id 编号
+     */
+    void deleteUserWebExpireTime(Long id);
+
+    /**
+    * 批量删除用户平台权限有效期
+    *
+    * @param ids 编号
+    */
+    void deleteUserWebExpireTimeListByIds(List<Long> ids);
+
+    /**
+     * 获得用户平台权限有效期
+     *
+     * @param id 编号
+     * @return 用户平台权限有效期
+     */
+    UserWebExpireTimeDO getUserWebExpireTime(Long id);
+
+    /**
+     * 获得用户平台权限有效期分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 用户平台权限有效期分页
+     */
+    PageResult<UserWebExpireTimeDO> getUserWebExpireTimePage(UserWebExpireTimePageReqVO pageReqVO);
+
+}

+ 88 - 0
byzs-module-system/src/main/java/cn/iocoder/byzs/module/system/service/userwebexpiretime/UserWebExpireTimeServiceImpl.java

@@ -0,0 +1,88 @@
+package cn.iocoder.byzs.module.system.service.userwebexpiretime;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimePageReqVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import cn.iocoder.byzs.module.system.dal.mysql.userwebexpiretime.UserWebExpireTimeMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.List;
+
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.byzs.module.system.enums.ErrorCodeConstants.USER_WEB_EXPIRE_TIME_NOT_EXISTS;
+
+/**
+ * 用户平台权限有效期 Service 实现类
+ *
+ * @author lyb
+ */
+@Service
+@Validated
+public class UserWebExpireTimeServiceImpl implements UserWebExpireTimeService {
+
+    @Resource
+    private UserWebExpireTimeMapper userWebExpireTimeMapper;
+
+    @Override
+    public Long createUserWebExpireTime(UserWebExpireTimeSaveReqVO createReqVO) {
+        // 插入
+        UserWebExpireTimeDO userWebExpireTime = BeanUtils.toBean(createReqVO, UserWebExpireTimeDO.class);
+        userWebExpireTimeMapper.insert(userWebExpireTime);
+        // 返回
+        return userWebExpireTime.getUserId();
+    }
+
+    @Override
+    public void updateUserWebExpireTime(UserWebExpireTimeSaveReqVO updateReqVO) {
+        // 校验存在
+        validateUserWebExpireTimeExists(updateReqVO.getUserId());
+        // 更新
+        UserWebExpireTimeDO updateObj = BeanUtils.toBean(updateReqVO, UserWebExpireTimeDO.class);
+        userWebExpireTimeMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteUserWebExpireTime(Long id) {
+        // 校验存在
+        validateUserWebExpireTimeExists(id);
+        // 删除
+        userWebExpireTimeMapper.deleteById(id);
+    }
+
+    @Override
+        public void deleteUserWebExpireTimeListByIds(List<Long> ids) {
+        // 校验存在
+        validateUserWebExpireTimeExists(ids);
+        // 删除
+        userWebExpireTimeMapper.deleteByIds(ids);
+        }
+
+    private void validateUserWebExpireTimeExists(List<Long> ids) {
+        List<UserWebExpireTimeDO> list = userWebExpireTimeMapper.selectByIds(ids);
+        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
+            throw exception(USER_WEB_EXPIRE_TIME_NOT_EXISTS);
+        }
+    }
+
+    private void validateUserWebExpireTimeExists(Long id) {
+        if (userWebExpireTimeMapper.selectById(id) == null) {
+            throw exception(USER_WEB_EXPIRE_TIME_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public UserWebExpireTimeDO getUserWebExpireTime(Long id) {
+        return userWebExpireTimeMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<UserWebExpireTimeDO> getUserWebExpireTimePage(UserWebExpireTimePageReqVO pageReqVO) {
+        return userWebExpireTimeMapper.selectPage(pageReqVO);
+    }
+
+}

+ 7 - 0
byzs-module-system/src/main/resources/mapper/userwebexpiretime/UserWebExpireTimeMapper.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.byzs.module.system.dal.mysql.userwebexpiretime.UserWebExpireTimeMapper">
+
+
+
+</mapper>

+ 3 - 2
byzs-server/src/main/resources/application.yaml

@@ -4,8 +4,8 @@ spring:
 
   profiles:
 #        active: local
-#    active: localProd
-      active: prodDev
+    active: localProd
+#      active: prodDev
 #      active: prod
 
   main:
@@ -282,6 +282,7 @@ byzs:
       - /admin-api/system/user/profile/**
       - /admin-api/system/auth/**
     ignore-tables:
+      - system_invite_code
     ignore-caches:
       - user_role_ids
       - permission_menu_ids

+ 1 - 22
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/login/WebLoginController.java

@@ -12,12 +12,10 @@ import cn.iocoder.byzs.module.system.controller.admin.auth.vo.AuthLoginReqVO;
 import cn.iocoder.byzs.module.system.controller.admin.auth.vo.AuthLoginRespVO;
 import cn.iocoder.byzs.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
 import cn.iocoder.byzs.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
-import cn.iocoder.byzs.module.system.dal.dataobject.dict.DictDataDO;
 import cn.iocoder.byzs.module.system.dal.dataobject.permission.RoleDO;
 import cn.iocoder.byzs.module.system.dal.dataobject.tenant.TenantDO;
 import cn.iocoder.byzs.module.system.enums.logger.LoginLogTypeEnum;
 import cn.iocoder.byzs.module.system.service.auth.AdminAuthService;
-import cn.iocoder.byzs.module.system.service.dict.DictDataService;
 import cn.iocoder.byzs.module.system.service.permission.PermissionService;
 import cn.iocoder.byzs.module.system.service.permission.RoleService;
 import cn.iocoder.byzs.module.system.service.tenant.TenantService;
@@ -36,7 +34,6 @@ import org.springframework.web.bind.annotation.*;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
 
@@ -56,8 +53,6 @@ public class WebLoginController {
     @Resource
     private RoleService roleService;
     @Resource
-    private DictDataService dictDataService;
-    @Resource
     private WebLoginServiceImpl webLoginServiceImpl;
 
 
@@ -116,23 +111,7 @@ public class WebLoginController {
     @GetMapping("/getRoleRoute")
     @Operation(summary = "根据用户ID,取角色路由")
     public CommonResult<Set<String>> getRoleRoute() {
-        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(WebFrameworkUtils.getLoginUserId());
-        List<RoleDO> roles = roleService.getRoleList(roleIds);
-        roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
-
-        // 填充角色路由
-        Set<String> roleRouteSet = new HashSet<>();
-        for (RoleDO role : roles) {
-            if(role.getDataScopeWebRoute() != null && !role.getDataScopeWebRoute().isEmpty()){
-                roleRouteSet.addAll(role.getDataScopeWebRoute());
-            }
-        }
-        // 如果roleRoutes为空,则从字典中获取默认路由
-        if (roleRouteSet.isEmpty()) {
-            List<DictDataDO> webRoleRoute = dictDataService.getDictDataListByDictType("web_role_route");
-            Set<String> roleRoute = webRoleRoute.stream().map(DictDataDO::getValue).collect(Collectors.toSet());
-            roleRouteSet.addAll(roleRoute);
-        }
+        Set<String> roleRouteSet = webLoginServiceImpl.getRoleRoute(WebFrameworkUtils.getLoginUserId());
         return success(roleRouteSet);
     }
 

+ 45 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/user/WebUserInfoController.java

@@ -0,0 +1,45 @@
+package cn.iocoder.byzs.module.web.controller.admin.user;
+
+import cn.iocoder.byzs.framework.common.pojo.CommonResult;
+import cn.iocoder.byzs.framework.web.core.util.WebFrameworkUtils;
+import cn.iocoder.byzs.module.web.controller.admin.user.vo.WebUserVO;
+import cn.iocoder.byzs.module.web.service.user.WebUserInfoServiceImpl;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.error;
+import static cn.iocoder.byzs.framework.common.pojo.CommonResult.success;
+
+@Tag(name = "前端")
+@RestController
+@RequestMapping("/bjdxWeb/web")
+public class WebUserInfoController {
+
+    @Resource
+    private WebUserInfoServiceImpl userInfoServiceImpl;
+
+    @PostMapping("/activateInviteCode")
+    @Operation(summary = "激活邀请码")
+    public CommonResult<Boolean> activateInviteCode(String inviteCode) {
+        return success(userInfoServiceImpl.activateInviteCode(inviteCode));
+    }
+
+    @GetMapping("/getUserInfo")
+    @Operation(summary = "获取用户信息")
+    public CommonResult<WebUserVO> getUserInfo(Long userId) {
+        if(userId == null){
+            return error(null,"用户ID不能为空");
+        }
+        if(!userId.equals(WebFrameworkUtils.getLoginUserId())){
+            return error(null,"您没有权限查询其他用户信息");
+        }
+
+        return success(userInfoServiceImpl.getUserInfo(userId));
+    }
+
+}

+ 61 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/controller/admin/user/vo/WebUserVO.java

@@ -0,0 +1,61 @@
+package cn.iocoder.byzs.module.web.controller.admin.user.vo;
+
+import cn.iocoder.byzs.module.system.enums.common.SexEnum;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户 DO
+ *
+ * @author 博雅智算源码
+ */
+@Data
+public class WebUserVO {
+
+    /**
+     * 用户ID
+     */
+    private Long id;
+    /**
+     * 用户账号
+     */
+    private String username;
+    /**
+     * 加密后的密码
+     *
+     */
+    private String password;
+    /**
+     * 用户昵称
+     */
+    private String nickname;
+    /**
+     * 用户邮箱
+     */
+    private String email;
+    /**
+     * 手机号码
+     */
+    private String mobile;
+    /**
+     * 用户性别
+     *
+     * 枚举类 {@link SexEnum}
+     */
+    private Integer sex;
+    /**
+     * 用户头像
+     */
+    private String avatar;
+
+    @Schema(description = "课程权限过期时间")
+    private LocalDateTime courseExpireTime;
+
+    @Schema(description = "编程课权限过期时间")
+    private LocalDateTime blocklyExpireTime;
+
+    @Schema(description = "AI实验课权限过期时间")
+    private LocalDateTime aiCourseExpireTime;
+}

+ 95 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/login/WebLoginServiceImpl.java

@@ -1,19 +1,30 @@
 package cn.iocoder.byzs.module.web.service.login;
 
+import cn.iocoder.byzs.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
 import cn.iocoder.byzs.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
 import cn.iocoder.byzs.module.system.controller.admin.invitecode.vo.InviteCodeSaveReqVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.dict.DictDataDO;
 import cn.iocoder.byzs.module.system.dal.dataobject.invitecode.InviteCodeDO;
+import cn.iocoder.byzs.module.system.dal.dataobject.permission.RoleDO;
 import cn.iocoder.byzs.module.system.dal.dataobject.user.AdminUserDO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import cn.iocoder.byzs.module.system.service.dict.DictDataService;
 import cn.iocoder.byzs.module.system.service.invitecode.InviteCodeService;
 import cn.iocoder.byzs.module.system.service.permission.PermissionService;
+import cn.iocoder.byzs.module.system.service.permission.RoleService;
 import cn.iocoder.byzs.module.system.service.user.AdminUserServiceImpl;
+import cn.iocoder.byzs.module.system.service.userwebexpiretime.UserWebExpireTimeService;
 import cn.iocoder.byzs.module.web.controller.admin.login.vo.WebRegisterVO;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDateTime;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -24,10 +35,18 @@ public class WebLoginServiceImpl {
     @Resource
     private AdminUserServiceImpl userService;
     @Resource
+    private RoleService roleService;
+    @Resource
+    private DictDataService dictDataService;
+    @Resource
     private PermissionService permissionService;
     @Resource
     private InviteCodeService inviteCodeService;
+    @Resource
+    private UserWebExpireTimeService userWebExpireTimeService;
 
+
+    @Transactional(rollbackFor = Exception.class)
     public Long register(WebRegisterVO registerVO) {
 
         //校验邀请码
@@ -54,7 +73,83 @@ public class WebLoginServiceImpl {
                         .setExpireTime(LocalDateTime.now().plusDays(inviteCode.getValidTime()))
                         .setStatus("2"));
 
+
+        List<RoleDO> roleList = roleService.getRoleList(roleIds);
+        roleList.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
+        Set<String> roleWebMap = new HashSet<>();
+        roleList.forEach(role -> {
+            if(role.getDataScopeWebRoute() != null && !role.getDataScopeWebRoute().isEmpty()){
+                roleWebMap.addAll(role.getDataScopeWebRoute());
+            }
+        });
+
+        //当前用户web过期时间
+        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(userId);
+        if (userWebExpireTime != null) {
+            if(roleWebMap.contains("course")){
+                userWebExpireTime.setCourseExpireTime(userWebExpireTime.getCourseExpireTime().plusDays(inviteCode.getValidTime()));
+            }
+            if(roleWebMap.contains("blockly")){
+                userWebExpireTime.setBlocklyExpireTime(userWebExpireTime.getBlocklyExpireTime().plusDays(inviteCode.getValidTime()));
+            }
+            if (roleWebMap.contains("aiCourse")){
+                userWebExpireTime.setAiCourseExpireTime(userWebExpireTime.getAiCourseExpireTime().plusDays(inviteCode.getValidTime()));
+            }
+
+            // 更新用户web过期时间
+            userWebExpireTimeService.updateUserWebExpireTime(BeanUtils.toBean(userWebExpireTime, UserWebExpireTimeSaveReqVO.class));
+        }else{
+            // 创建用户web过期时间
+            UserWebExpireTimeSaveReqVO userWebExpireTimeDO = new UserWebExpireTimeSaveReqVO().setUserId(userId);
+            if(roleWebMap.contains("course")){
+                userWebExpireTimeDO.setCourseExpireTime(LocalDateTime.now().plusDays(inviteCode.getValidTime()));
+            }
+            if(roleWebMap.contains("blockly")){
+                userWebExpireTimeDO.setBlocklyExpireTime(LocalDateTime.now().plusDays(inviteCode.getValidTime()));
+            }
+            if (roleWebMap.contains("aiCourse")){
+                userWebExpireTimeDO.setAiCourseExpireTime(LocalDateTime.now().plusDays(inviteCode.getValidTime()));
+            }
+            userWebExpireTimeService.createUserWebExpireTime(userWebExpireTimeDO);
+        }
+
         // 用户id
         return userId;
     }
+
+    public Set<String> getRoleRoute(Long userId) {
+        Set<Long> roleIds = permissionService.getUserRoleIdListByUserId(userId);
+        List<RoleDO> roles = roleService.getRoleList(roleIds);
+        roles.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
+
+        // 获得用户激活的邀请码
+        List<InviteCodeDO> inviteCodes = inviteCodeService.getInviteCodeByUserId(userId);
+
+//        Set<Long> roleIds1 = new HashSet<>();
+//        Set<Long> roleIds2 = new HashSet<>();
+//        inviteCodes.forEach(inviteCode -> {
+//            roleIds1.addAll(Arrays.stream(inviteCode.getRoleIds().split(","))
+//                    .map(s -> Long.parseLong(s.trim()))
+//                    .collect(Collectors.toSet()));
+//        } );
+
+//        Set<Long> roleIds = Arrays.stream(inviteCode.getRoleIds().split(","))
+//                .map(s ->Long.parseLong(s.trim())).collect(Collectors.toSet());
+        inviteCodes.removeIf(inviteCode -> !CommonStatusEnum.ENABLE.getStatus().equals(inviteCode.getStatus())); // 移除禁用的邀请码
+
+        // 填充角色路由
+        Set<String> roleRouteSet = new HashSet<>();
+        for (RoleDO role : roles) {
+            if(role.getDataScopeWebRoute() != null && !role.getDataScopeWebRoute().isEmpty()){
+                roleRouteSet.addAll(role.getDataScopeWebRoute());
+            }
+        }
+        // 如果roleRoutes为空,则从字典中获取默认路由
+        if (roleRouteSet.isEmpty()) {
+            List<DictDataDO> webRoleRoute = dictDataService.getDictDataListByDictType("web_role_route");
+            Set<String> roleRoute = webRoleRoute.stream().map(DictDataDO::getValue).collect(Collectors.toSet());
+            roleRouteSet.addAll(roleRoute);
+        }
+        return roleRouteSet;
+    }
 }

+ 132 - 0
byzs-web/src/main/java/cn/iocoder/byzs/module/web/service/user/WebUserInfoServiceImpl.java

@@ -0,0 +1,132 @@
+package cn.iocoder.byzs.module.web.service.user;
+
+import cn.iocoder.byzs.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
+import cn.iocoder.byzs.framework.web.core.util.WebFrameworkUtils;
+import cn.iocoder.byzs.module.system.controller.admin.invitecode.vo.InviteCodeSaveReqVO;
+import cn.iocoder.byzs.module.system.controller.admin.userwebexpiretime.vo.UserWebExpireTimeSaveReqVO;
+import cn.iocoder.byzs.module.system.dal.dataobject.invitecode.InviteCodeDO;
+import cn.iocoder.byzs.module.system.dal.dataobject.permission.RoleDO;
+import cn.iocoder.byzs.module.system.dal.dataobject.user.AdminUserDO;
+import cn.iocoder.byzs.module.system.dal.dataobject.userwebexpiretime.UserWebExpireTimeDO;
+import cn.iocoder.byzs.module.system.service.invitecode.InviteCodeService;
+import cn.iocoder.byzs.module.system.service.permission.PermissionService;
+import cn.iocoder.byzs.module.system.service.permission.RoleService;
+import cn.iocoder.byzs.module.system.service.user.AdminUserServiceImpl;
+import cn.iocoder.byzs.module.system.service.userwebexpiretime.UserWebExpireTimeService;
+import cn.iocoder.byzs.module.web.controller.admin.user.vo.WebUserVO;
+import cn.iocoder.byzs.module.web.service.login.WebLoginServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.byzs.module.system.enums.ErrorCodeConstants.USER_CODE_FAILURE;
+
+@Service
+public class WebUserInfoServiceImpl {
+    @Resource
+    private AdminUserServiceImpl userService;
+    @Resource
+    private PermissionService permissionService;
+    @Resource
+    private InviteCodeService inviteCodeService;
+    @Resource
+    private WebLoginServiceImpl loginService;
+    @Resource
+    private RoleService roleService;
+    @Resource
+    private UserWebExpireTimeService userWebExpireTimeService;
+
+
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean activateInviteCode(String inviteCode) {
+
+        //校验邀请码
+        InviteCodeDO inviteCodeDo = inviteCodeService.getUnusedInviteCode(inviteCode);
+        if (inviteCodeDo == null) {
+            throw exception(USER_CODE_FAILURE);
+        }
+        Set<Long> codeRoleIds = Arrays.stream(inviteCodeDo.getRoleIds().split(","))
+                .map(s ->Long.parseLong(s.trim())).collect(Collectors.toSet());
+
+        //补充用户角色
+        Long userId = WebFrameworkUtils.getLoginUserId();
+        AdminUserDO user = userService.getUser(userId);
+        permissionService.assignUserRole(userId, codeRoleIds);
+
+        // 更新邀请码为已使用
+        inviteCodeService.updateInviteCode(new InviteCodeSaveReqVO()
+                .setId(inviteCodeDo.getId())
+                .setUseUserId(userId)
+                .setUseUserTenantId(user.getTenantId())
+                .setUseTime(LocalDateTime.now())
+                .setExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()))
+                .setStatus("2"));
+
+        // 更新用户web过期时间
+        List<RoleDO> roleList = roleService.getRoleList(codeRoleIds);
+        roleList.removeIf(role -> !CommonStatusEnum.ENABLE.getStatus().equals(role.getStatus())); // 移除禁用的角色
+        Set<String> roleWebMap = new HashSet<>();
+        roleList.forEach(role -> {
+            if(role.getDataScopeWebRoute() != null && !role.getDataScopeWebRoute().isEmpty()){
+                roleWebMap.addAll(role.getDataScopeWebRoute());
+            }
+        });
+
+        //当前用户web过期时间
+        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(userId);
+        if (userWebExpireTime != null) {
+            if(roleWebMap.contains("course")){
+                userWebExpireTime.setCourseExpireTime(userWebExpireTime.getCourseExpireTime().plusDays(inviteCodeDo.getValidTime()));
+            }
+            if(roleWebMap.contains("blockly")){
+                userWebExpireTime.setBlocklyExpireTime(userWebExpireTime.getBlocklyExpireTime().plusDays(inviteCodeDo.getValidTime()));
+            }
+            if (roleWebMap.contains("aiCourse")){
+                userWebExpireTime.setAiCourseExpireTime(userWebExpireTime.getAiCourseExpireTime().plusDays(inviteCodeDo.getValidTime()));
+            }
+
+            // 更新用户web过期时间
+            userWebExpireTimeService.updateUserWebExpireTime(BeanUtils.toBean(userWebExpireTime, UserWebExpireTimeSaveReqVO.class));
+        }else{
+            // 创建用户web过期时间
+            UserWebExpireTimeSaveReqVO userWebExpireTimeDO = new UserWebExpireTimeSaveReqVO().setUserId(userId);
+            if(roleWebMap.contains("course")){
+                userWebExpireTimeDO.setCourseExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
+            }
+            if(roleWebMap.contains("blockly")){
+                userWebExpireTimeDO.setBlocklyExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
+            }
+            if (roleWebMap.contains("aiCourse")){
+                userWebExpireTimeDO.setAiCourseExpireTime(LocalDateTime.now().plusDays(inviteCodeDo.getValidTime()));
+            }
+            userWebExpireTimeService.createUserWebExpireTime(userWebExpireTimeDO);
+        }
+
+        // 用户id
+        return true;
+    }
+
+    public WebUserVO getUserInfo(Long userId) {
+        AdminUserDO user = userService.getUser(userId);
+        WebUserVO webUserVO = BeanUtils.toBean(user, WebUserVO.class);
+
+        UserWebExpireTimeDO userWebExpireTime = userWebExpireTimeService.getUserWebExpireTime(userId);
+        if (userWebExpireTime != null) {
+            webUserVO.setCourseExpireTime(userWebExpireTime.getCourseExpireTime());
+            webUserVO.setBlocklyExpireTime(userWebExpireTime.getBlocklyExpireTime());
+            webUserVO.setAiCourseExpireTime(userWebExpireTime.getAiCourseExpireTime());
+        }
+
+        // 用户id
+        return webUserVO;
+    }
+}