package com.yunhai.question.controller.api; import com.yunhai.platform.utils.model.BoaUser; import com.yunhai.question.common.BizException; import com.yunhai.question.entity.Questionnaire; import com.yunhai.question.service.QuestionnaireService; import com.yunhai.question.service.SchoolAdminGuard; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; 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.RestController; import javax.validation.Valid; import javax.validation.constraints.NotBlank; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * 问卷管理端(仅校管理员∪超管可建——FC 侧 create 守卫天然把关第一步,本侧登记步同样过守卫)。 */ @RestController @RequestMapping("/api/question/questionnaire") @RequiredArgsConstructor public class QuestionnaireController { private final QuestionnaireService questionnaireService; private final SchoolAdminGuard adminGuard; public static class RegisterRequest { @NotBlank(message = "formUuid 不能为空") public String formUuid; public String formCode; @NotBlank(message = "问卷标题不能为空") public String title; public Boolean anonymous; /** JSON 字符串:{description,cover,thanks} */ public String description; } public static class DescriptionRequest { public String description; } /** 列表(本校全部未删问卷) */ @GetMapping("/list") public List list(BoaUser user) { Long schId = adminGuard.requireSchool(user); return questionnaireService.list(schId); } /** * 第三步绑定登记(幂等三步的收口;重复提交返回既有行)。 */ @PostMapping public Questionnaire register(BoaUser user, @Valid @RequestBody RegisterRequest body) { Long schId = adminGuard.requireSchool(user); boolean anonymous = Boolean.TRUE.equals(body.anonymous); return questionnaireService.register(schId, body.formUuid.trim(), body.formCode, body.title, anonymous, body.description); } @GetMapping("/{id}") public Questionnaire detail(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); return questionnaireService.requireOwned(schId, id); } /** 问卷说明/封面/致谢(JSON 文本,仅问卷侧元数据) */ @PostMapping("/{id}/description") public Questionnaire updateDescription(BoaUser user, @PathVariable Long id, @RequestBody DescriptionRequest body) { Long schId = adminGuard.requireSchool(user); Questionnaire q = questionnaireService.requireOwned(schId, id); q.setDescription(body == null ? null : body.description); return questionnaireService.save(q); } /** 发布投放:fetchSchema 核验 FC 已发布→钉版+status=1 */ @PostMapping("/{id}/publish") public Questionnaire publish(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); return questionnaireService.publish(schId, id); } /** 结束投放:status=2(FC 侧是否 disable 由前端另行确认调用 FC 端点) */ @PostMapping("/{id}/finish") public Questionnaire finish(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); return questionnaireService.finish(schId, id); } /** 恢复收集 */ @PostMapping("/{id}/reopen") public Questionnaire reopen(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); return questionnaireService.reopen(schId, id); } /** 软删问卷行(FC 表单不动) */ @PostMapping("/{id}/delete") public Map softDelete(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); questionnaireService.softDelete(schId, id); Map out = new LinkedHashMap<>(); out.put("deleted", true); return out; } /** 编辑容器打开时刷新 FC name/code 快照并返回详情 */ @GetMapping("/{id}/refresh") public Questionnaire refresh(BoaUser user, @PathVariable Long id) { Long schId = adminGuard.requireSchool(user); Questionnaire q = questionnaireService.requireOwned(schId, id); return questionnaireService.save(questionnaireService.refreshFromFc(q)); } /** * 我的问卷交集:前端把 FC fillable(appCode=question) 的 code 列表 POST 过来, * 服务端取 ∩ 本校收集中问卷。未登录教师/学生同样可达(无校管理员守卫)。 */ @PostMapping("/my") public List myFillable(BoaUser user, @RequestBody MyCodesRequest body) { if (user == null || user.getId() == null) { throw new BizException("未登录"); } Integer schIdInt = user.getCurrentRole() != null ? user.getCurrentRole().getSchId() : null; if (schIdInt == null) { throw new BizException("当前会话无学校上下文"); } return questionnaireService.myFillable(schIdInt.longValue(), body == null ? null : body.codes); } public static class MyCodesRequest { public List codes; } }