恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
189 lines
8.3 KiB
Java
189 lines
8.3 KiB
Java
package com.kaidi.oa.web;
|
|
|
|
import com.kaidi.oa.common.ApiResp;
|
|
import com.kaidi.oa.common.ApiException;
|
|
import com.kaidi.oa.common.NotFoundException;
|
|
import com.kaidi.oa.domain.HrEmpSatisfactionSurvey;
|
|
import com.kaidi.oa.repository.HrEmpSatisfactionSurveyRepository;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.PatchMapping;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.web.bind.annotation.RestController;
|
|
|
|
import java.time.Instant;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* 人力资源部员工满意度调查 CRUD。
|
|
*
|
|
* 该模块是「品牌推广部·项目文化评估与反馈」跨模块数据打通的数据源:
|
|
* 人力资源部每季度发放覆盖全员的敬业度/满意度问卷,系统通过 projectCode 字段
|
|
* 把 HR 调查结果关联到具体项目部,再由 CultureAssessmentService 融合读取,
|
|
* 消除了"只读 CultureSurvey 自有问卷"的缺口(两套维度互补——Culture 侧重文化氛围,
|
|
* HR 侧重工作满意度/敬业度/管理质量),同时 /kpi-writeback 接口把文化考核得分
|
|
* 回写到考核数据供 HR 年度绩效评估引用。
|
|
*
|
|
* 状态机:草稿 → 收集中 → 已完成(关闭冻结评分)。
|
|
*/
|
|
@RestController
|
|
@RequestMapping("/api/oa/hr-emp-satisfaction")
|
|
public class HrEmpSatisfactionSurveyController {
|
|
|
|
private final HrEmpSatisfactionSurveyRepository repo;
|
|
|
|
public HrEmpSatisfactionSurveyController(HrEmpSatisfactionSurveyRepository repo) {
|
|
this.repo = repo;
|
|
}
|
|
|
|
// ---- 请求体 ----
|
|
|
|
record CreateReq(
|
|
String code, String title, String projectCode, String projectName,
|
|
String period, Integer totalCount,
|
|
Double scoreJobSatisfaction, Double scoreEngagement,
|
|
Double scoreManagement, Double scoreTeamwork, Double scoreWellbeing,
|
|
String issuesSummary, String openDate, String closeDate
|
|
) {}
|
|
|
|
record UpdateReq(
|
|
String title, String projectCode, String projectName,
|
|
String period, Integer totalCount, Integer respondedCount,
|
|
Double scoreJobSatisfaction, Double scoreEngagement,
|
|
Double scoreManagement, Double scoreTeamwork, Double scoreWellbeing,
|
|
Double hrOverallScore, String issuesSummary, String openDate, String closeDate
|
|
) {}
|
|
|
|
// ---- 列表 ----
|
|
|
|
@GetMapping
|
|
public ApiResp<List<HrEmpSatisfactionSurvey>> list(
|
|
@RequestParam(required = false) String projectCode,
|
|
@RequestParam(required = false) String status) {
|
|
if (projectCode != null && status != null) {
|
|
return ApiResp.ok(repo.findByProjectCodeAndStatus(projectCode, status));
|
|
}
|
|
if (projectCode != null) {
|
|
return ApiResp.ok(repo.findByProjectCode(projectCode));
|
|
}
|
|
if (status != null) {
|
|
return ApiResp.ok(repo.findByStatus(status));
|
|
}
|
|
return ApiResp.ok(repo.findAll());
|
|
}
|
|
|
|
// ---- 详情 ----
|
|
|
|
@GetMapping("/{id}")
|
|
public ApiResp<HrEmpSatisfactionSurvey> get(@PathVariable Long id) {
|
|
return ApiResp.ok(repo.findById(id).orElseThrow(() -> new NotFoundException("HR满意度调查不存在: " + id)));
|
|
}
|
|
|
|
// ---- 新建 ----
|
|
|
|
@PostMapping
|
|
@Transactional
|
|
public ApiResp<HrEmpSatisfactionSurvey> create(@RequestBody CreateReq req) {
|
|
HrEmpSatisfactionSurvey s = new HrEmpSatisfactionSurvey();
|
|
s.setCode(req.code());
|
|
s.setTitle(req.title());
|
|
s.setInitiatorDept("人力资源部");
|
|
s.setProjectCode(req.projectCode());
|
|
s.setProjectName(req.projectName());
|
|
s.setPeriod(req.period());
|
|
s.setStatus("草稿");
|
|
s.setTotalCount(req.totalCount() == null ? 0 : req.totalCount());
|
|
s.setRespondedCount(0);
|
|
s.setScoreJobSatisfaction(req.scoreJobSatisfaction() == null ? 0.0 : req.scoreJobSatisfaction());
|
|
s.setScoreEngagement(req.scoreEngagement() == null ? 0.0 : req.scoreEngagement());
|
|
s.setScoreManagement(req.scoreManagement() == null ? 0.0 : req.scoreManagement());
|
|
s.setScoreTeamwork(req.scoreTeamwork() == null ? 0.0 : req.scoreTeamwork());
|
|
s.setScoreWellbeing(req.scoreWellbeing() == null ? 0.0 : req.scoreWellbeing());
|
|
s.setHrOverallScore(0.0);
|
|
s.setIssuesSummary(req.issuesSummary());
|
|
s.setOpenDate(req.openDate());
|
|
s.setCloseDate(req.closeDate());
|
|
s.setCreatedAt(Instant.now());
|
|
return ApiResp.ok(repo.save(s));
|
|
}
|
|
|
|
// ---- 更新 ----
|
|
|
|
@PatchMapping("/{id}")
|
|
@Transactional
|
|
public ApiResp<HrEmpSatisfactionSurvey> update(@PathVariable Long id, @RequestBody UpdateReq req) {
|
|
HrEmpSatisfactionSurvey s = repo.findById(id)
|
|
.orElseThrow(() -> new NotFoundException("HR满意度调查不存在: " + id));
|
|
if (req.title() != null) s.setTitle(req.title());
|
|
if (req.projectCode() != null) s.setProjectCode(req.projectCode());
|
|
if (req.projectName() != null) s.setProjectName(req.projectName());
|
|
if (req.period() != null) s.setPeriod(req.period());
|
|
if (req.totalCount() != null) s.setTotalCount(req.totalCount());
|
|
if (req.respondedCount() != null) s.setRespondedCount(req.respondedCount());
|
|
if (req.scoreJobSatisfaction() != null) s.setScoreJobSatisfaction(req.scoreJobSatisfaction());
|
|
if (req.scoreEngagement() != null) s.setScoreEngagement(req.scoreEngagement());
|
|
if (req.scoreManagement() != null) s.setScoreManagement(req.scoreManagement());
|
|
if (req.scoreTeamwork() != null) s.setScoreTeamwork(req.scoreTeamwork());
|
|
if (req.scoreWellbeing() != null) s.setScoreWellbeing(req.scoreWellbeing());
|
|
if (req.issuesSummary() != null) s.setIssuesSummary(req.issuesSummary());
|
|
if (req.openDate() != null) s.setOpenDate(req.openDate());
|
|
if (req.closeDate() != null) s.setCloseDate(req.closeDate());
|
|
// 自动重算综合分(五维均值)
|
|
if (req.hrOverallScore() != null) {
|
|
s.setHrOverallScore(req.hrOverallScore());
|
|
} else {
|
|
double overall = (s.getScoreJobSatisfaction() + s.getScoreEngagement()
|
|
+ s.getScoreManagement() + s.getScoreTeamwork() + s.getScoreWellbeing()) / 5.0;
|
|
s.setHrOverallScore(Math.round(overall * 100.0) / 100.0);
|
|
}
|
|
return ApiResp.ok(repo.save(s));
|
|
}
|
|
|
|
// ---- 状态迁移 ----
|
|
|
|
@PostMapping("/{id}/start")
|
|
@Transactional
|
|
public ApiResp<HrEmpSatisfactionSurvey> start(@PathVariable Long id) {
|
|
HrEmpSatisfactionSurvey s = repo.findById(id)
|
|
.orElseThrow(() -> new NotFoundException("HR满意度调查不存在: " + id));
|
|
if (!"草稿".equals(s.getStatus())) {
|
|
throw new ApiException(400, "只有草稿状态可以开启收集");
|
|
}
|
|
s.setStatus("收集中");
|
|
return ApiResp.ok(repo.save(s));
|
|
}
|
|
|
|
@PostMapping("/{id}/close")
|
|
@Transactional
|
|
public ApiResp<HrEmpSatisfactionSurvey> close(@PathVariable Long id) {
|
|
HrEmpSatisfactionSurvey s = repo.findById(id)
|
|
.orElseThrow(() -> new NotFoundException("HR满意度调查不存在: " + id));
|
|
if (!"收集中".equals(s.getStatus())) {
|
|
throw new ApiException(400, "只有收集中状态可以关闭");
|
|
}
|
|
// 关闭时自动计算综合分(五维均值)
|
|
double overall = (s.getScoreJobSatisfaction() + s.getScoreEngagement()
|
|
+ s.getScoreManagement() + s.getScoreTeamwork() + s.getScoreWellbeing()) / 5.0;
|
|
s.setHrOverallScore(Math.round(overall * 100.0) / 100.0);
|
|
s.setStatus("已完成");
|
|
return ApiResp.ok(repo.save(s));
|
|
}
|
|
|
|
// ---- 删除 ----
|
|
|
|
@DeleteMapping("/{id}")
|
|
@Transactional
|
|
public ApiResp<Void> delete(@PathVariable Long id) {
|
|
if (!repo.existsById(id)) {
|
|
throw new NotFoundException("HR满意度调查不存在: " + id);
|
|
}
|
|
repo.deleteById(id);
|
|
return ApiResp.ok(null);
|
|
}
|
|
}
|