Commit f5256687 by zwb

新增岗位智推岗位三级分类查询

parent d2faaa1c
package com.bkty.system.controller;
import com.bkty.system.init.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author Zhang Wenbiao
* @description 岗位智推Controller
* @datetime 2025/12/3 11:13
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/jobRecommend", method = RequestMethod.POST)
@Tag(description = "jobRecommend", name = "岗位智推")
public class JobRecommendController {
@Autowired
private CategoryCacheManager categoryCacheManager;
@Operation(summary = "岗位三级分类查询")
@GetMapping("/positions")
public R<List<Level1Group>> getAllPositions(@RequestParam(value = "level1", required = false) String level1) {
if (StringUtils.isBlank(level1)){
return new R<>(categoryCacheManager.getPositionCache());
}
// 根据岗位名称过滤,创建新的数据结构而不修改原始缓存
List<Level1Group> positionCache = categoryCacheManager.getPositionCache();
List<Level1Group> result = new ArrayList<>();
for (Level1Group level1Group : positionCache) {
if (level1Group.getName().toLowerCase().contains(level1.toLowerCase())){
result.add(level1Group);
continue;
}
List<Level2Group> level2Groups = new ArrayList<>();
for (Level2Group level2Group : level1Group.getLevel2Groups()) {
List<Level3Group> level3Groups = new ArrayList<>();
for (Level3Group level3Group : level2Group.getLevel3Groups()) {
if (level3Group.getName().toLowerCase().contains(level1.toLowerCase())){
level3Groups.add(level3Group);
}
}
if (CollectionUtils.isNotEmpty(level3Groups)){
Level2Group level2Group1 = new Level2Group(level2Group.getName());
level2Group1.setLevel3Groups(level3Groups);
level2Groups.add(level2Group1);
}
}
if (CollectionUtils.isNotEmpty(level2Groups)){
Level1Group level1Group1 = new Level1Group(level1Group.getName());
level1Group1.setLevel2Groups(level2Groups);
result.add(level1Group1);
}
}
return new R<>(result);
}
}
......@@ -52,8 +52,11 @@ public class NewEditionResumeController {
@RequestMapping(value = "/insertNewEditionResume")
@Operation(description = "新版导入简历")
@RepeatSubmit(interval = 1000)
public R insertNewEditionResume(@RequestParam("file") MultipartFile file, @RequestParam(value = "type", required = false) String type) {
this.newEditionResumeService.insertNewEditionResume(file,type);
public R insertNewEditionResume(@RequestParam("file") MultipartFile file,
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "targetPosition", required = false) String targetPosition,
@RequestParam(value = "jobDescription", required = false) String jobDescription) {
this.newEditionResumeService.insertNewEditionResume(file,type,targetPosition,jobDescription);
return new R<>(Boolean.TRUE);
}
......
package com.bkty.system.init;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@Component
public class CategoryCacheManager {
// 全局缓存结构: 完整的层级结构列表
private static List<Level1Group> positionCache = new CopyOnWriteArrayList<>();
// 一级分类名称到Level1Group对象的映射,便于快速查找
private static Map<String, Level1Group> positionNameMap = new ConcurrentHashMap<>();
/**
* 将岗位数据加载到缓存
*/
public void loadPositionCache(List<Level1Group> data) {
positionCache = new CopyOnWriteArrayList<>(data);
// 更新名称映射
positionNameMap.clear();
for (Level1Group group : data) {
positionNameMap.put(group.getName(), group);
}
}
/**
* 获取缓存数据
*/
public List<Level1Group> getPositionCache() {
return positionCache;
}
/**
* 根据一级分类名称获取数据 (更新后的方法)
*/
public Level1Group getPositionDataByName(String level1Name) {
return positionNameMap.get(level1Name);
}
/**
* 根据一级分类获取数据
*/
/*public List<CategoryData> getCategoryData(String level1) {
return categoryCache.get(level1);
}*/
}
package com.bkty.system.init;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Service
public class ExcelPositionReader {
/**
* 读取xlsx文件并解析为新的分层Map结构
* @param filePath resources下的文件路径
* @return 分层结构 List<Level1Group>
*/
public List<Level1Group> readPositionData(String filePath) throws Exception {
// 用于保持顺序的列表
List<Level1Group> level1Groups = new ArrayList<>();
Map<String, Level1Group> level1Map = new LinkedHashMap<>();
// 获取resources目录下的文件
ClassPathResource resource = new ClassPathResource(filePath);
InputStream inputStream = resource.getInputStream();
try (Workbook workbook = new XSSFWorkbook(inputStream)) {
Sheet sheet = workbook.getSheetAt(0); // 获取第一个sheet
// 跳过第一行(标题行),从第二行开始读取数据
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
// 读取六列数据
String level1Name = getCellValueAsString(row.getCell(0)); // 第一列:一级分类名称
// String level1Icon = getCellValueAsString(row.getCell(1)); // 第二列:一级分类图标url
String level2Name = getCellValueAsString(row.getCell(2)); // 第三列:二级分类名称
String level3Name = getCellValueAsString(row.getCell(3)); // 第四列:三级分类名称
// String level3Desc = getCellValueAsString(row.getCell(4)); // 第五列:三级分类描述
// String level3Icon = getCellValueAsString(row.getCell(5)); // 第六列:三级分类图标url
// 跳过空行或数据不完整的行
if (level1Name == null || level1Name.trim().isEmpty() ||
level2Name == null || level2Name.trim().isEmpty() ||
level3Name == null || level3Name.trim().isEmpty()) {
continue;
}
// 处理一级分类
Level1Group level1Group;
if (level1Map.containsKey(level1Name)) {
level1Group = level1Map.get(level1Name);
} else {
level1Group = new Level1Group(level1Name);
level1Map.put(level1Name, level1Group);
level1Groups.add(level1Group);
}
// 处理二级分类
Level2Group level2Group = null;
for (Level2Group group : level1Group.getLevel2Groups()) {
if (group.getName().equals(level2Name)) {
level2Group = group;
break;
}
}
if (level2Group == null) {
level2Group = new Level2Group(level2Name);
level1Group.getLevel2Groups().add(level2Group);
}
// 添加三级分类
Level3Group level3Group = new Level3Group(
level3Name
);
level2Group.getLevel3Groups().add(level3Group);
}
}
return level1Groups;
}
/**
* 获取单元格值为字符串
*/
private String getCellValueAsString(Cell cell) {
if (cell == null) {
return null;
}
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue().toString();
} else {
return String.valueOf((long) cell.getNumericCellValue());
}
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return cell.getCellFormula();
default:
return null;
}
}
}
package com.bkty.system.init;
import java.util.ArrayList;
import java.util.List;
// 一级分类类
public class Level1Group {
private String name;
// private String iconUrl;
private List<Level2Group> level2Groups;
public Level1Group(String name) {
this.name = name;
// this.iconUrl = iconUrl;
this.level2Groups = new ArrayList<>();
}
// getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// public String getIconUrl() { return iconUrl; }
// public void setIconUrl(String iconUrl) { this.iconUrl = iconUrl; }
public List<Level2Group> getLevel2Groups() { return level2Groups; }
public void setLevel2Groups(List<Level2Group> level2Groups) { this.level2Groups = level2Groups; }
}
// 二级分类类
// 三级分类类
package com.bkty.system.init;
import java.util.ArrayList;
import java.util.List;
public class Level2Group {
private String name;
private List<Level3Group> level3Groups;
public Level2Group(String name) {
this.name = name;
this.level3Groups = new ArrayList<>();
}
// getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Level3Group> getLevel3Groups() { return level3Groups; }
public void setLevel3Groups(List<Level3Group> level3Groups) { this.level3Groups = level3Groups; }
}
\ No newline at end of file
package com.bkty.system.init;
public class Level3Group {
private String name;
// private String description;
// private String iconUrl;
public Level3Group(String name) {
this.name = name;
// this.description = description;
// this.iconUrl = iconUrl;
}
// getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// public String getDescription() { return description; }
// public void setDescription(String description) { this.description = description; }
// public String getIconUrl() { return iconUrl; }
// public void setIconUrl(String iconUrl) { this.iconUrl = iconUrl; }
}
\ No newline at end of file
package com.bkty.system.init;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class PositionCacheInitializer implements CommandLineRunner {
@Autowired
private ExcelPositionReader excelPositionReader;
@Autowired
private CategoryCacheManager categoryCacheManager;
@Override
public void run(String... args) throws Exception {
try {
// 读取resources/template路径下的xlsx文件
// 假设文件名为 positions.xlsx,请根据实际情况调整
var positionDataMap = excelPositionReader.readPositionData("template/positions.xlsx");
// 加载到全局缓存
categoryCacheManager.loadPositionCache(positionDataMap);
} catch (Exception e) {
System.err.println("加载岗位数据缓存失败: " + e.getMessage());
e.printStackTrace();
}
}
}
......@@ -20,10 +20,12 @@ public interface NewEditionResumeService {
/**
* 新版导入简历
*
* @param file 文件
* type 类型(1-文件,2图片)
* @param file 文件
* type 类型(1-文件,2图片)
* @param targetPosition
* @param jobDescription
*/
void insertNewEditionResume(MultipartFile file, String type);
void insertNewEditionResume(MultipartFile file, String type, String targetPosition, String jobDescription);
/**
......
......@@ -106,7 +106,7 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
private final FunctionResumeBaseTagMapper resumeBaseTagMapper;
@Override
public void insertNewEditionResume(MultipartFile file, String type) {
public void insertNewEditionResume(MultipartFile file, String type, String targetPosition, String jobDescription) {
LoginUser user = LoginHelper.getLoginUser();
if (user == null) {
......@@ -150,6 +150,8 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
} else {
parameters.put("imgUrl", resumeUrl);//简历图片导入时的图片链接
}
parameters.put("targetPosition", targetPosition);
parameters.put("jobDescription", jobDescription);
Map<String, Object> body = Map.of("workflow_id", "7571692041894920227", "is_async", false, "parameters", parameters);
String url = Constants.HTTPS + CozeConstsnts.COZE_CN_API_DOMAIN_NAME + "/v1/workflow/run";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment