forked from baskbuddy/zhangshun
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
7.3 KiB
97 lines
7.3 KiB
package com.mydreamjob.onlineresume;
|
|
|
|
import com.fasterxml.jackson.databind.*;
|
|
import com.mydreamjob.common.api.ApiResponse;
|
|
import com.mydreamjob.common.exception.*;
|
|
import com.mydreamjob.common.logging.RequestIdAccessor;
|
|
import com.mydreamjob.security.CurrentUserAccessor;
|
|
import io.swagger.v3.oas.annotations.*;
|
|
import io.swagger.v3.oas.annotations.media.Schema;
|
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.validation.Valid;
|
|
import jakarta.validation.constraints.*;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.http.*;
|
|
import org.springframework.validation.annotation.Validated;
|
|
import org.springframework.web.bind.annotation.*;
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
@RestController @RequiredArgsConstructor @Validated
|
|
@RequestMapping("/profile/me/online-resume")
|
|
@Tag(name = "在线简历", description = "仅当前 STUDENT 本人;不修改账号登录信息,不读取附件正文")
|
|
public class OnlineResumeController {
|
|
private final OnlineResumeService service;
|
|
private final OnlineResumeDocxWriter docx;
|
|
private final CurrentUserAccessor currentUser;
|
|
private final RequestIdAccessor requestIds;
|
|
private final ObjectMapper mapper;
|
|
|
|
@Schema(name = "OnlineResumeEntryRequest")
|
|
@lombok.Data
|
|
public static class EntryRequest {
|
|
@NotNull @PositiveOrZero private Long revision;
|
|
@NotNull @Schema(implementation = Object.class, oneOf = {OnlineResumeContent.Education.class, OnlineResumeContent.Work.class,
|
|
OnlineResumeContent.Project.class, OnlineResumeContent.Skill.class})
|
|
private JsonNode entry;
|
|
}
|
|
|
|
@GetMapping
|
|
@Operation(operationId = "getMyOnlineResume", summary = "读取本人完整在线简历", description = "无保存记录时 revision=0,从已有资料、求职偏好和账号联系方式组装,不写库。attachment 仅返回文件元数据及鉴权下载地址。phone/email 为本人简历联系方式,不下发到企业候选人接口。")
|
|
public ApiResponse<OnlineResumeView> get(HttpServletRequest request) {
|
|
return ApiResponse.ok(service.get(currentUser.requireUserId()), requestIds.get(request));
|
|
}
|
|
@PutMapping
|
|
@Operation(operationId = "saveMyOnlineResume", summary = "保存完整在线简历", description = "携带最近 GET 的 revision;content 完整替换,空数组删除该类全部条目,null/空字符串可清空可选字段。新条目省略 id,既有条目保留 id。成功 revision+1;过期 revision 返回409/6002。同步既有个人资料和求职偏好,不改登录手机号/邮箱、附件及隐私授权。")
|
|
public ApiResponse<OnlineResumeView> save(@Valid @RequestBody OnlineResumeSaveRequest body, HttpServletRequest request) {
|
|
return ApiResponse.ok(service.save(currentUser.requireUserId(), body), requestIds.get(request));
|
|
}
|
|
@GetMapping("/{section}")
|
|
@Operation(operationId = "listMyOnlineResumeEntries", summary = "读取某类简历条目", description = "section 仅 education-experiences/work-experiences/project-experiences/skills;revision 从整份简历 GET 获取。")
|
|
public ApiResponse<java.util.List<Object>> list(@PathVariable String section, HttpServletRequest request) {
|
|
java.util.List<Object> result = new java.util.ArrayList<>();
|
|
entries(service.get(currentUser.requireUserId()), section).forEach(result::add);
|
|
return ApiResponse.ok(result, requestIds.get(request));
|
|
}
|
|
@GetMapping("/{section}/{id}")
|
|
@Operation(operationId = "getMyOnlineResumeEntry", summary = "读取本人简历条目详情", description = "只在本人指定类别内寻找条目,不存在返回404/6003。")
|
|
public ApiResponse<Object> detail(@PathVariable String section, @PathVariable String id, HttpServletRequest request) {
|
|
for (JsonNode e : entries(service.get(currentUser.requireUserId()), section))
|
|
if (id.equals(e.path("id").asText())) return ApiResponse.ok(e, requestIds.get(request));
|
|
throw new BusinessException(ErrorCode.ONLINE_RESUME_ENTRY_NOT_FOUND);
|
|
}
|
|
@PostMapping("/{section}")
|
|
@Operation(operationId = "createMyOnlineResumeEntry", summary = "新增简历条目", description = "section 仅 education-experiences/work-experiences/project-experiences/skills;entry 为相应类型,新条目不传 id;携带整份简历 revision,返回更新后的完整简历。")
|
|
public ApiResponse<OnlineResumeView> create(@PathVariable String section, @Valid @RequestBody EntryRequest body, HttpServletRequest request) {
|
|
return ApiResponse.ok(service.editEntry(currentUser.requireUserId(), section, null, body.getRevision(), body.getEntry(), false), requestIds.get(request));
|
|
}
|
|
@PutMapping("/{section}/{id}")
|
|
@Operation(operationId = "updateMyOnlineResumeEntry", summary = "替换简历条目", description = "entry 完整替换本人条目;id 可省略或须与 URL 一致;携带整份简历 revision。")
|
|
public ApiResponse<OnlineResumeView> update(@PathVariable String section, @PathVariable String id, @Valid @RequestBody EntryRequest body, HttpServletRequest request) {
|
|
return ApiResponse.ok(service.editEntry(currentUser.requireUserId(), section, id, body.getRevision(), body.getEntry(), false), requestIds.get(request));
|
|
}
|
|
@DeleteMapping("/{section}/{id}")
|
|
@Operation(operationId = "deleteMyOnlineResumeEntry", summary = "删除简历条目", description = "query revision 必填;不存在返回404/6003,过期版本返回409/6002;返回更新后的完整简历。")
|
|
public ApiResponse<OnlineResumeView> delete(@PathVariable String section, @PathVariable String id,
|
|
@RequestParam @Min(0) Long revision, HttpServletRequest request) {
|
|
return ApiResponse.ok(service.editEntry(currentUser.requireUserId(), section, id, revision, null, true), requestIds.get(request));
|
|
}
|
|
@GetMapping(value = "/download", produces = "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
|
|
@Operation(operationId = "downloadMyOnlineResume", summary = "下载在线简历 DOCX", description = "从当前已保存的在线内容生成 Word 文件,不含上传附件,不写文件、不创建附件版本;浏览器应携带鉴权获取 Blob,未保存编辑需先 PUT。")
|
|
public ResponseEntity<byte[]> download() {
|
|
byte[] bytes = docx.write(service.get(currentUser.requireUserId()).content());
|
|
return ResponseEntity.ok().cacheControl(CacheControl.noStore())
|
|
.header(HttpHeaders.CONTENT_DISPOSITION, ContentDisposition.attachment().filename("个人简历.docx", StandardCharsets.UTF_8).build().toString())
|
|
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"))
|
|
.contentLength(bytes.length).body(bytes);
|
|
}
|
|
private JsonNode entries(OnlineResumeView view, String section) {
|
|
return mapper.valueToTree(switch (section) {
|
|
case "education-experiences" -> view.content().getEducationExperiences();
|
|
case "work-experiences" -> view.content().getWorkExperiences();
|
|
case "project-experiences" -> view.content().getProjectExperiences();
|
|
case "skills" -> view.content().getSkills();
|
|
default -> throw new BusinessException(ErrorCode.ONLINE_RESUME_ENTRY_NOT_FOUND);
|
|
});
|
|
}
|
|
}
|
|
|