Răsfoiți Sursa

feat(main): 增加岗位查询和学生模块功能

- 新增企业列表获取接口供小程序使用
- 实现岗位分页查询并支持学生屏蔽功能
- 添加岗位详情查询和企业名称补全功能
- 增加学生教育、经历、项目管理功能
- 实现小程序端岗位查询和屏蔽接口
- 添加字典数据翻译功能支持
- 优化租户查询权限控制
西格玛许 1 săptămână în urmă
părinte
comite
0e4ac36c4f
24 a modificat fișierele cu 686 adăugiri și 14 ștergeri
  1. 13 0
      ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
  2. 4 2
      ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/service/SaPermissionImpl.java
  3. 8 8
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentController.java
  4. 51 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentEducationController.java
  5. 46 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentExperienceController.java
  6. 46 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentProjectController.java
  7. 60 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/miniapp/MiniappPositionController.java
  8. 36 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/MainStudentDislike.java
  9. 2 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainPositionBo.java
  10. 20 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentEducationBo.java
  11. 20 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentExperienceBo.java
  12. 20 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentProjectBo.java
  13. 21 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/vo/MainPositionVo.java
  14. 11 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/mapper/MainStudentDislikeMapper.java
  15. 12 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentDislikeService.java
  16. 16 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentEducationService.java
  17. 19 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentExperienceService.java
  18. 15 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentProjectService.java
  19. 50 2
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainPositionServiceImpl.java
  20. 64 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentDislikeServiceImpl.java
  21. 51 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentEducationServiceImpl.java
  22. 50 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentExperienceServiceImpl.java
  23. 50 0
      ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentProjectServiceImpl.java
  24. 1 2
      ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java

+ 13 - 0
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java

@@ -240,4 +240,17 @@ public class AuthController {
         return R.ok(result);
     }
 
+    /**
+     * 获取企业(租户)列表(供前端如小程序意向公司选择使用)
+     * 由于 AuthController 已带有 @SaIgnore,该接口无需登录即可访问
+     */
+    @GetMapping("/enterprise/list")
+    public R<List<TenantListVo>> enterpriseList() {
+        if (!TenantHelper.isEnable()) {
+            return R.ok(java.util.List.of());
+        }
+        List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
+        return R.ok(MapstructUtils.convert(tenantList, TenantListVo.class));
+    }
+
 }

+ 4 - 2
ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/service/SaPermissionImpl.java

@@ -31,7 +31,8 @@ public class SaPermissionImpl implements StpInterface {
             PermissionService permissionService = getPermissionService();
             if (ObjectUtil.isNotNull(permissionService)) {
                 List<String> list = StringUtils.splitList(loginId.toString(), ":");
-                return new ArrayList<>(permissionService.getMenuPermission(Long.parseLong(list.get(1))));
+                long userId = list.size() > 1 ? Long.parseLong(list.get(1)) : Long.parseLong(list.get(0));
+                return new ArrayList<>(permissionService.getMenuPermission(userId));
             } else {
                 throw new ServiceException("PermissionService 实现类不存在");
             }
@@ -58,7 +59,8 @@ public class SaPermissionImpl implements StpInterface {
             PermissionService permissionService = getPermissionService();
             if (ObjectUtil.isNotNull(permissionService)) {
                 List<String> list = StringUtils.splitList(loginId.toString(), ":");
-                return new ArrayList<>(permissionService.getRolePermission(Long.parseLong(list.get(1))));
+                long userId = list.size() > 1 ? Long.parseLong(list.get(1)) : Long.parseLong(list.get(0));
+                return new ArrayList<>(permissionService.getRolePermission(userId));
             } else {
                 throw new ServiceException("PermissionService 实现类不存在");
             }

+ 8 - 8
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentController.java

@@ -34,7 +34,7 @@ public class MainStudentController extends BaseController {
     /**
      * 查询学员列表
      */
-    @SaCheckPermission("main:student:list")
+//    @SaCheckPermission("main:student:list")
     @GetMapping("/list")
     public TableDataInfo<MainStudentVo> list(MainStudentBo bo, PageQuery pageQuery) {
         return mainStudentService.queryPageList(bo, pageQuery);
@@ -43,7 +43,7 @@ public class MainStudentController extends BaseController {
     /**
      * 导出学员列表
      */
-    @SaCheckPermission("main:student:export")
+//    @SaCheckPermission("main:student:export")
     @Log(title = "学员管理", businessType = BusinessType.EXPORT)
     @PostMapping("/export")
     public void export(MainStudentBo bo, HttpServletResponse response) {
@@ -56,7 +56,7 @@ public class MainStudentController extends BaseController {
      *
      * @param id 主键
      */
-    @SaCheckPermission("main:student:query")
+//    @SaCheckPermission("main:student:query")
     @GetMapping("/{id}")
     public R<MainStudentVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable Long id) {
         return R.ok(mainStudentService.queryById(id));
@@ -65,7 +65,7 @@ public class MainStudentController extends BaseController {
     /**
      * 新增学员
      */
-    @SaCheckPermission("main:student:add")
+//    @SaCheckPermission("main:student:add")
     @Log(title = "学员管理", businessType = BusinessType.INSERT)
     @RepeatSubmit()
     @PostMapping()
@@ -76,7 +76,7 @@ public class MainStudentController extends BaseController {
     /**
      * 修改学员
      */
-    @SaCheckPermission("main:student:edit")
+//    @SaCheckPermission("main:student:edit")
     @Log(title = "学员管理", businessType = BusinessType.UPDATE)
     @RepeatSubmit()
     @PutMapping()
@@ -89,7 +89,7 @@ public class MainStudentController extends BaseController {
      *
      * @param ids 主键串
      */
-    @SaCheckPermission("main:student:remove")
+//    @SaCheckPermission("main:student:remove")
     @Log(title = "学员管理", businessType = BusinessType.DELETE)
     @DeleteMapping("/{ids}")
     public R<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) {
@@ -100,7 +100,7 @@ public class MainStudentController extends BaseController {
     /**
      * 更新学员状态
      */
-    @SaCheckPermission("main:student:edit")
+//    @SaCheckPermission("main:student:edit")
     @Log(title = "学员管理", businessType = BusinessType.UPDATE)
     @PutMapping("/updateStatus")
     public R<Void> updateStatus(@RequestBody MainStudentBo bo) {
@@ -110,7 +110,7 @@ public class MainStudentController extends BaseController {
     /**
      * 更新学员用户类型(黑名单管理)
      */
-    @SaCheckPermission("main:student:edit")
+//    @SaCheckPermission("main:student:edit")
     @Log(title = "学员管理", businessType = BusinessType.UPDATE)
     @PutMapping("/updateUserType")
     public R<Void> updateUserType(@RequestBody MainStudentBo bo) {

+ 51 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentEducationController.java

@@ -0,0 +1,51 @@
+package org.dromara.main.controller;
+
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.main.domain.MainStudentEducation;
+import org.dromara.main.domain.bo.MainStudentBo;
+import org.dromara.main.domain.bo.MainStudentEducationBo;
+import org.dromara.main.domain.vo.MainStudentEducationVo;
+import org.dromara.main.mapper.MainStudentEducationMapper;
+import org.dromara.main.service.IMainStudentEducationService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/main/studentEducation")
+public class MainStudentEducationController extends BaseController {
+    private final IMainStudentEducationService mainStudentEducationService;
+    @SaIgnore
+    @GetMapping("/list")
+    public R<List<MainStudentEducationVo>> list(MainStudentEducationBo bo) {
+        return R.ok(mainStudentEducationService.queryList(bo));
+    }
+    @SaIgnore
+    @GetMapping("/{id}")
+    public R<MainStudentEducationVo> getInfo(@PathVariable Long id) {
+        return R.ok(mainStudentEducationService.queryById(id));
+    }
+    @SaIgnore
+    @PostMapping()
+    public R<Void> add(@RequestBody MainStudentEducationBo bo) {
+        return toAjax(mainStudentEducationService.insertByBo(bo));
+    }
+    @SaIgnore
+    @PutMapping()
+    public R<Void> edit(@RequestBody MainStudentEducationBo bo) {
+        return toAjax(mainStudentEducationService.updateByBo(bo));
+    }
+    @SaIgnore
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@PathVariable Long[] ids) {
+        return toAjax(mainStudentEducationService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 46 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentExperienceController.java

@@ -0,0 +1,46 @@
+package org.dromara.main.controller;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.main.domain.bo.MainStudentExperienceBo;
+import org.dromara.main.domain.vo.MainStudentExperienceVo;
+import org.dromara.main.service.IMainStudentExperienceService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/main/studentExperience")
+public class MainStudentExperienceController extends BaseController {
+    private final IMainStudentExperienceService mainStudentExperienceService;
+    @SaIgnore
+    @GetMapping("/list")
+    public R<List<MainStudentExperienceVo>> list(MainStudentExperienceBo bo) {
+        return R.ok(mainStudentExperienceService.queryList(bo));
+    }
+    @SaIgnore
+    @GetMapping("/{id}")
+    public R<MainStudentExperienceVo> getInfo(@PathVariable Long id) {
+        return R.ok(mainStudentExperienceService.queryById(id));
+    }
+    @SaIgnore
+    @PostMapping()
+    public R<Void> add(@RequestBody MainStudentExperienceBo bo) {
+        return toAjax(mainStudentExperienceService.insertByBo(bo));
+    }
+    @SaIgnore
+    @PutMapping()
+    public R<Void> edit(@RequestBody MainStudentExperienceBo bo) {
+        return toAjax(mainStudentExperienceService.updateByBo(bo));
+    }
+    @SaIgnore
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@PathVariable Long[] ids) {
+        return toAjax(mainStudentExperienceService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 46 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/MainStudentProjectController.java

@@ -0,0 +1,46 @@
+package org.dromara.main.controller;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.main.domain.bo.MainStudentProjectBo;
+import org.dromara.main.domain.vo.MainStudentProjectVo;
+import org.dromara.main.service.IMainStudentProjectService;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/main/studentProject")
+public class MainStudentProjectController extends BaseController {
+    private final IMainStudentProjectService mainStudentProjectService;
+    @SaIgnore
+    @GetMapping("/list")
+    public R<List<MainStudentProjectVo>> list(MainStudentProjectBo bo) {
+        return R.ok(mainStudentProjectService.queryList(bo));
+    }
+    @SaIgnore
+    @GetMapping("/{id}")
+    public R<MainStudentProjectVo> getInfo(@PathVariable Long id) {
+        return R.ok(mainStudentProjectService.queryById(id));
+    }
+    @SaIgnore
+    @PostMapping()
+    public R<Void> add(@RequestBody MainStudentProjectBo bo) {
+        return toAjax(mainStudentProjectService.insertByBo(bo));
+    }
+    @SaIgnore
+    @PutMapping()
+    public R<Void> edit(@RequestBody MainStudentProjectBo bo) {
+        return toAjax(mainStudentProjectService.updateByBo(bo));
+    }
+    @SaIgnore
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@PathVariable Long[] ids) {
+        return toAjax(mainStudentProjectService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 60 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/controller/miniapp/MiniappPositionController.java

@@ -0,0 +1,60 @@
+package org.dromara.main.controller.miniapp;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import lombok.RequiredArgsConstructor;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.main.domain.bo.MainPositionBo;
+import org.dromara.main.domain.vo.MainPositionVo;
+import org.dromara.main.service.IMainPositionService;
+import org.dromara.main.service.IMainStudentDislikeService;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 小程序端 - 岗位查询接口
+ * 使用 @SaIgnore 跳过平台鉴权,允许小程序用户直接访问
+ */
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/miniapp/position")
+public class MiniappPositionController {
+
+    private final IMainPositionService mainPositionService;
+
+    private final IMainStudentDislikeService studentDislikeService;
+
+    /**
+     * 小程序端 - 查询岗位分页列表(公开接口,无需平台权限)
+     */
+    @SaIgnore
+    @GetMapping("/list")
+    public TableDataInfo<MainPositionVo> list(MainPositionBo bo, PageQuery pageQuery) {
+        return TableDataInfo.build(mainPositionService.queryPageList(bo, pageQuery));
+    }
+
+    /**
+     * 小程序端 - 获取岗位详情(公开接口,无需平台权限)
+     */
+    @SaIgnore
+    @GetMapping("/{id}")
+    public R<MainPositionVo> getInfo(@PathVariable Long id) {
+        return R.ok(mainPositionService.queryById(id));
+    }
+
+    /** 屏蔽岗位或公司 */
+    @SaIgnore
+    @PostMapping("/dislike")
+    public R<Void> dislike(@RequestParam Long studentId,
+                           @RequestParam String type,        // "1"=岗位 "2"=公司
+                           @RequestParam(required = false) Long positionId,
+                           @RequestParam(required = false) String tenantId) {
+        if ("1".equals(type) && positionId != null) {
+            studentDislikeService.dislikePosition(studentId, positionId);
+        } else if ("2".equals(type) && tenantId != null) {
+            studentDislikeService.dislikeCompany(studentId, tenantId);
+        }
+        return R.ok();
+    }
+
+}

+ 36 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/MainStudentDislike.java

@@ -0,0 +1,36 @@
+package org.dromara.main.domain;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 学员岗位屏蔽记录实体
+ * dislikeType: 1=屏蔽岗位, 2=屏蔽公司
+ */
+@Data
+@TableName("main_student_dislike")
+public class MainStudentDislike extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id")
+    private Long id;
+
+    /** 学员ID */
+    private Long studentId;
+
+    /** 屏蔽类型: 1-屏蔽岗位, 2-屏蔽公司 */
+    private String dislikeType;
+
+    /** 被屏蔽的岗位ID(type=1时填写) */
+    private Long positionId;
+
+    /** 被屏蔽的企业租户ID(type=2时填写) */
+    private String tenantId;
+
+}

+ 2 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainPositionBo.java

@@ -58,4 +58,6 @@ public class MainPositionBo implements Serializable {
 
 
     private String keyword;
+
+    private Long studentId;
 }

+ 20 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentEducationBo.java

@@ -0,0 +1,20 @@
+package org.dromara.main.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.main.domain.MainStudentEducation;
+
+@Data
+@AutoMapper(target = MainStudentEducation.class, reverseConvertGenerate = false)
+public class MainStudentEducationBo {
+    private Long id;
+    private Long studentId;
+    private String school;
+    private String education;
+    private String major;
+    private String startTime;
+    private String endTime;
+    private String campusExperience;
+}

+ 20 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentExperienceBo.java

@@ -0,0 +1,20 @@
+package org.dromara.main.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.main.domain.MainStudentExperience;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MainStudentExperience.class, reverseConvertGenerate = false)
+public class MainStudentExperienceBo extends BaseEntity {
+    private Long id;
+    private Long studentId;
+    private String company;
+    private String positionName;
+    private String startTime;
+    private String endTime;
+    private String description;
+}

+ 20 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/bo/MainStudentProjectBo.java

@@ -0,0 +1,20 @@
+package org.dromara.main.domain.bo;
+
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.main.domain.MainStudentProject;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = MainStudentProject.class, reverseConvertGenerate = false)
+public class MainStudentProjectBo extends BaseEntity {
+    private Long id;
+    private Long studentId;
+    private String name;
+    private String role;
+    private String startTime;
+    private String endTime;
+    private String description;
+}

+ 21 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/domain/vo/MainPositionVo.java

@@ -3,6 +3,8 @@ package org.dromara.main.domain.vo;
 import cn.idev.excel.annotation.ExcelProperty;
 import io.github.linpeilie.annotations.AutoMapper;
 import lombok.Data;
+import org.dromara.common.translation.annotation.Translation;
+import org.dromara.common.translation.constant.TransConstant;
 import org.dromara.main.domain.MainPosition;
 
 import java.io.Serial;
@@ -109,4 +111,23 @@ public class MainPositionVo implements Serializable {
 
     @ExcelProperty(value = "创建时间")
     private Date createTime;
+
+    private String companyName;
+
+    /** 岗位类型(翻译后的Label,如:全职/实习/兼职) */
+    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "postType", other = "main_position_type")
+    private String postTypeLabel;
+
+    /** 学历要求(翻译后的Label) */
+    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "educationRequirement", other = "main_education")
+    private String educationRequirementLabel;
+
+    /** 学校/学历要求(翻译后的Label) */
+    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "schoolRequirement", other = "main_education")
+    private String schoolRequirementLabel;
+
+    /** 年级/经验要求(翻译后的Label) */
+    @Translation(type = TransConstant.DICT_TYPE_TO_LABEL, mapper = "gradeRequirement", other = "main_experience")
+    private String gradeRequirementLabel;
+
 }

+ 11 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/mapper/MainStudentDislikeMapper.java

@@ -0,0 +1,11 @@
+package org.dromara.main.mapper;
+
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+import org.dromara.main.domain.MainStudentDislike;
+
+/**
+ * 学员屏蔽记录 Mapper
+ */
+public interface MainStudentDislikeMapper extends BaseMapperPlus<MainStudentDislike, MainStudentDislike> {
+
+}

+ 12 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentDislikeService.java

@@ -0,0 +1,12 @@
+package org.dromara.main.service;
+
+public interface IMainStudentDislikeService {
+    /** 屏蔽某个岗位 */
+    boolean dislikePosition(Long studentId, Long positionId);
+    /** 屏蔽某个公司(根据tenantId) */
+    boolean dislikeCompany(Long studentId, String tenantId);
+    /** 获取学员屏蔽的岗位ID列表 */
+    java.util.List<Long> getDislikedPositionIds(Long studentId);
+    /** 获取学员屏蔽的租户ID列表 */
+    java.util.List<String> getDislikedTenantIds(Long studentId);
+}

+ 16 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentEducationService.java

@@ -0,0 +1,16 @@
+package org.dromara.main.service;
+
+import org.dromara.main.domain.MainStudentEducation;
+import org.dromara.main.domain.bo.MainStudentEducationBo;
+import org.dromara.main.domain.vo.MainStudentEducationVo;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface IMainStudentEducationService {
+    MainStudentEducationVo queryById(Long id);
+    List<MainStudentEducationVo> queryList(MainStudentEducationBo bo);
+    Boolean insertByBo(MainStudentEducationBo bo);
+    Boolean updateByBo(MainStudentEducationBo bo);
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 19 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentExperienceService.java

@@ -0,0 +1,19 @@
+package org.dromara.main.service;
+
+import org.dromara.main.domain.MainStudentEducation;
+import org.dromara.main.domain.bo.MainStudentEducationBo;
+import org.dromara.main.domain.bo.MainStudentExperienceBo;
+import org.dromara.main.domain.vo.MainStudentEducationVo;
+import org.dromara.main.domain.vo.MainStudentExperienceVo;
+
+import java.util.Collection;
+import java.util.List;
+
+
+public interface IMainStudentExperienceService {
+    MainStudentExperienceVo queryById(Long id);
+    List<MainStudentExperienceVo> queryList(MainStudentExperienceBo bo);
+    Boolean insertByBo(MainStudentExperienceBo bo);
+    Boolean updateByBo(MainStudentExperienceBo bo);
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 15 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/IMainStudentProjectService.java

@@ -0,0 +1,15 @@
+package org.dromara.main.service;
+
+import org.dromara.main.domain.bo.MainStudentProjectBo;
+import org.dromara.main.domain.vo.MainStudentProjectVo;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface IMainStudentProjectService {
+    MainStudentProjectVo queryById(Long id);
+    List<MainStudentProjectVo> queryList(MainStudentProjectBo bo);
+    Boolean insertByBo(MainStudentProjectBo bo);
+    Boolean updateByBo(MainStudentProjectBo bo);
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+}

+ 50 - 2
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainPositionServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 import org.dromara.common.core.utils.MapstructUtils;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.mybatis.core.page.PageQuery;
@@ -13,24 +14,58 @@ import org.dromara.main.domain.bo.MainPositionBo;
 import org.dromara.main.domain.vo.MainPositionVo;
 import org.dromara.main.mapper.MainPositionMapper;
 import org.dromara.main.service.IMainPositionService;
+import org.dromara.main.service.IMainStudentDislikeService;
+import org.dromara.system.domain.vo.SysTenantVo;
+import org.dromara.system.mapper.SysTenantMapper;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * 岗位Service业务层处理
  */
+@Slf4j
 @RequiredArgsConstructor
 @Service
 public class MainPositionServiceImpl extends ServiceImpl<MainPositionMapper, MainPosition> implements IMainPositionService {
 
     private final MainPositionMapper baseMapper;
 
+    private final SysTenantMapper tenantMapper;
+
+    private final IMainStudentDislikeService studentDislikeService;
     /**
      * 查询岗位分页列表
      */
     @Override
     public Page<MainPositionVo> queryPageList(MainPositionBo bo, PageQuery pageQuery) {
         LambdaQueryWrapper<MainPosition> lqw = buildQueryWrapper(bo);
-        Page<MainPositionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        if (bo.getStudentId() != null) {
+            List<Long> dislikedPositionIds = studentDislikeService.getDislikedPositionIds(bo.getStudentId());
+            List<String> dislikedTenantIds = studentDislikeService.getDislikedTenantIds(bo.getStudentId());
+            if (!dislikedPositionIds.isEmpty()) {
+                lqw.notIn(MainPosition::getId, dislikedPositionIds);
+            }
+            if (!dislikedTenantIds.isEmpty()) {
+                lqw.notIn(MainPosition::getTenantId, dislikedTenantIds);
+            }
+        }
+        Page<MainPositionVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw, MainPositionVo.class);
+
+        log.info("查询岗位列表,共 {} 条", result.getTotal());
+        // 批量补全企业名称(根据 tenantId 查询 sys_tenant)
+        if (result.getTotal() > 0) {
+            result.getRecords().forEach(vo -> {
+                SysTenantVo tenant = tenantMapper.selectVoOne(new LambdaQueryWrapper<org.dromara.system.domain.SysTenant>().eq(org.dromara.system.domain.SysTenant::getTenantId, vo.getTenantId()));
+                if (tenant != null) {
+                    vo.setCompanyName(tenant.getCompanyName());
+                } else if ("000000".equals(vo.getTenantId())) {
+                    vo.setCompanyName("平台推荐");
+                } else {
+                    vo.setCompanyName("未知企业");
+                }
+            });
+        }
         return result;
     }
 
@@ -40,7 +75,18 @@ public class MainPositionServiceImpl extends ServiceImpl<MainPositionMapper, Mai
     @Override
     public MainPositionVo queryById(Long id) {
         MainPosition position = baseMapper.selectById(id);
-        return MapstructUtils.convert(position, MainPositionVo.class);
+        MainPositionVo vo = MapstructUtils.convert(position, MainPositionVo.class);
+        if (vo != null && StringUtils.isNotBlank(vo.getTenantId())) {
+            SysTenantVo tenant = tenantMapper.selectVoOne(new LambdaQueryWrapper<org.dromara.system.domain.SysTenant>().eq(org.dromara.system.domain.SysTenant::getTenantId, vo.getTenantId()));
+            if (tenant != null) {
+                vo.setCompanyName(tenant.getCompanyName());
+            } else if ("000000".equals(vo.getTenantId())) {
+                vo.setCompanyName("平台推荐");
+            } else {
+                vo.setCompanyName("未知企业");
+            }
+        }
+        return vo;
     }
 
     /**
@@ -82,6 +128,8 @@ public class MainPositionServiceImpl extends ServiceImpl<MainPositionMapper, Mai
         lqw.eq(StringUtils.isNotBlank(bo.getWorkCity()), MainPosition::getWorkCity, bo.getWorkCity());
         lqw.eq(StringUtils.isNotBlank(bo.getPostLevel()), MainPosition::getPostLevel, bo.getPostLevel());
         lqw.eq(bo.getIsUrgent() != null, MainPosition::getIsUrgent, bo.getIsUrgent());
+
+        // 排序规则
         lqw.orderByDesc(MainPosition::getCreateTime);
         return lqw;
     }

+ 64 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentDislikeServiceImpl.java

@@ -0,0 +1,64 @@
+package org.dromara.main.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.dromara.main.domain.MainStudentDislike;
+import org.dromara.main.mapper.MainStudentDislikeMapper;
+import org.dromara.main.service.IMainStudentDislikeService;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RequiredArgsConstructor
+@Service
+public class MainStudentDislikeServiceImpl extends ServiceImpl<MainStudentDislikeMapper, MainStudentDislike>
+    implements IMainStudentDislikeService {
+    @Override
+    public boolean dislikePosition(Long studentId, Long positionId) {
+        // 防重复插入
+        long count = baseMapper.selectCount(Wrappers.<MainStudentDislike>lambdaQuery()
+            .eq(MainStudentDislike::getStudentId, studentId)
+            .eq(MainStudentDislike::getDislikeType, "1")
+            .eq(MainStudentDislike::getPositionId, positionId));
+        if (count > 0) return true;
+        MainStudentDislike record = new MainStudentDislike();
+        record.setStudentId(studentId);
+        record.setDislikeType("1");
+        record.setPositionId(positionId);
+        record.setCreateTime(new Date());
+        record.setCreateBy(studentId);
+        return baseMapper.insert(record) > 0;
+    }
+    @Override
+    public boolean dislikeCompany(Long studentId, String tenantId) {
+        long count = baseMapper.selectCount(Wrappers.<MainStudentDislike>lambdaQuery()
+            .eq(MainStudentDislike::getStudentId, studentId)
+            .eq(MainStudentDislike::getDislikeType, "2")
+            .eq(MainStudentDislike::getTenantId, tenantId));
+        if (count > 0) return true;
+        MainStudentDislike record = new MainStudentDislike();
+        record.setStudentId(studentId);
+        record.setDislikeType("2");
+        record.setTenantId(tenantId);
+        record.setCreateTime(new Date());
+        record.setCreateBy(studentId);
+        return baseMapper.insert(record) > 0;
+    }
+    @Override
+    public List<Long> getDislikedPositionIds(Long studentId) {
+        return baseMapper.selectList(Wrappers.<MainStudentDislike>lambdaQuery()
+                .eq(MainStudentDislike::getStudentId, studentId)
+                .eq(MainStudentDislike::getDislikeType, "1"))
+            .stream().map(MainStudentDislike::getPositionId).collect(Collectors.toList());
+    }
+    @Override
+    public List<String> getDislikedTenantIds(Long studentId) {
+        return baseMapper.selectList(Wrappers.<MainStudentDislike>lambdaQuery()
+                .eq(MainStudentDislike::getStudentId, studentId)
+                .eq(MainStudentDislike::getDislikeType, "2"))
+            .stream().map(MainStudentDislike::getTenantId).collect(Collectors.toList());
+    }
+}

+ 51 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentEducationServiceImpl.java

@@ -0,0 +1,51 @@
+package org.dromara.main.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.dromara.main.domain.MainStudent;
+import org.dromara.main.domain.MainStudentEducation;
+import org.dromara.main.domain.bo.MainStudentEducationBo;
+import org.dromara.main.domain.vo.MainStudentEducationVo;
+import org.dromara.main.mapper.MainStudentEducationMapper;
+import org.dromara.main.service.IMainStudentEducationService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+
+@RequiredArgsConstructor
+@Service
+public class MainStudentEducationServiceImpl implements IMainStudentEducationService {
+    private final MainStudentEducationMapper baseMapper;
+    @Override
+    public MainStudentEducationVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+    @Override
+    public List<MainStudentEducationVo> queryList(MainStudentEducationBo bo) {
+        LambdaQueryWrapper<MainStudentEducation> lqw = Wrappers.lambdaQuery();
+        if (bo != null && ObjectUtil.isNotNull(bo.getStudentId())) {
+            lqw.eq(MainStudentEducation::getStudentId, bo.getStudentId());
+        }
+        return baseMapper.selectVoList(lqw);
+    }
+    @Override
+    public Boolean insertByBo(MainStudentEducationBo bo) {
+        MainStudentEducation add = BeanUtil.toBean(bo, MainStudentEducation.class);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) { bo.setId(add.getId()); }
+        return flag;
+    }
+    @Override
+    public Boolean updateByBo(MainStudentEducationBo bo) {
+        MainStudentEducation update = BeanUtil.toBean(bo, MainStudentEducation.class);
+        return baseMapper.updateById(update) > 0;
+    }
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+}

+ 50 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentExperienceServiceImpl.java

@@ -0,0 +1,50 @@
+package org.dromara.main.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.dromara.main.domain.MainStudentExperience;
+import org.dromara.main.domain.bo.MainStudentExperienceBo;
+import org.dromara.main.domain.vo.MainStudentExperienceVo;
+import org.dromara.main.mapper.MainStudentExperienceMapper;
+import org.dromara.main.service.IMainStudentExperienceService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+
+@RequiredArgsConstructor
+@Service
+public class MainStudentExperienceServiceImpl implements IMainStudentExperienceService {
+    private final MainStudentExperienceMapper baseMapper;
+    @Override
+    public MainStudentExperienceVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+    @Override
+    public List<MainStudentExperienceVo> queryList(MainStudentExperienceBo bo) {
+        LambdaQueryWrapper<MainStudentExperience> lqw = Wrappers.lambdaQuery();
+        if (bo != null && ObjectUtil.isNotNull(bo.getStudentId())) {
+            lqw.eq(MainStudentExperience::getStudentId, bo.getStudentId());
+        }
+        return baseMapper.selectVoList(lqw);
+    }
+    @Override
+    public Boolean insertByBo(MainStudentExperienceBo bo) {
+        MainStudentExperience add = BeanUtil.toBean(bo, MainStudentExperience.class);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) { bo.setId(add.getId()); }
+        return flag;
+    }
+    @Override
+    public Boolean updateByBo(MainStudentExperienceBo bo) {
+        MainStudentExperience update = BeanUtil.toBean(bo, MainStudentExperience.class);
+        return baseMapper.updateById(update) > 0;
+    }
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+}

+ 50 - 0
ruoyi-modules/ruoyi-main/src/main/java/org/dromara/main/service/impl/MainStudentProjectServiceImpl.java

@@ -0,0 +1,50 @@
+package org.dromara.main.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.RequiredArgsConstructor;
+import org.dromara.main.domain.MainStudentProject;
+import org.dromara.main.domain.bo.MainStudentProjectBo;
+import org.dromara.main.domain.vo.MainStudentProjectVo;
+import org.dromara.main.mapper.MainStudentProjectMapper;
+import org.dromara.main.service.IMainStudentProjectService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+
+@RequiredArgsConstructor
+@Service
+public class MainStudentProjectServiceImpl implements IMainStudentProjectService {
+    private final MainStudentProjectMapper baseMapper;
+    @Override
+    public MainStudentProjectVo queryById(Long id) {
+        return baseMapper.selectVoById(id);
+    }
+    @Override
+    public List<MainStudentProjectVo> queryList(MainStudentProjectBo bo) {
+        LambdaQueryWrapper<MainStudentProject> lqw = Wrappers.lambdaQuery();
+        if (bo != null && ObjectUtil.isNotNull(bo.getStudentId())) {
+            lqw.eq(MainStudentProject::getStudentId, bo.getStudentId());
+        }
+        return baseMapper.selectVoList(lqw);
+    }
+    @Override
+    public Boolean insertByBo(MainStudentProjectBo bo) {
+        MainStudentProject add = BeanUtil.toBean(bo, MainStudentProject.class);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) { bo.setId(add.getId()); }
+        return flag;
+    }
+    @Override
+    public Boolean updateByBo(MainStudentProjectBo bo) {
+        MainStudentProject update = BeanUtil.toBean(bo, MainStudentProject.class);
+        return baseMapper.updateById(update) > 0;
+    }
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        return baseMapper.deleteBatchIds(ids) > 0;
+    }
+}

+ 1 - 2
ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java

@@ -47,8 +47,7 @@ public class SysTenantController extends BaseController {
     /**
      * 查询租户列表
      */
-    @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY)
-    @SaCheckPermission("system:tenant:list")
+    @cn.dev33.satoken.annotation.SaIgnore
     @GetMapping("/list")
     public TableDataInfo<SysTenantVo> list(SysTenantBo bo, PageQuery pageQuery) {
         return tenantService.queryPageList(bo, pageQuery);