diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/controller/SurveyController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/controller/SurveyController.java new file mode 100644 index 0000000..36085c2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/controller/SurveyController.java @@ -0,0 +1,67 @@ +package net.lab1024.sa.admin.module.business.jwpy.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyQueryForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyAddForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyUpdateForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyAnswerAddForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.vo.SurveyVO; +import net.lab1024.sa.admin.module.business.jwpy.service.SurveyService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.springframework.web.bind.annotation.*; + +/** + * 民意调查与问卷配置 控制器 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@RestController +@Tag(name = "业务功能-民意调查与测评问卷") +public class SurveyController { + + @Resource + private SurveyService surveyService; + + @Operation(summary = "分页查询问卷模板列表") + @PostMapping("/mydc/survey/queryPage") + @SaCheckPermission("mydc:questionnaire:query") + public ResponseDTO> queryPage(@RequestBody @Valid SurveyQueryForm queryForm) { + return surveyService.queryPage(queryForm); + } + + @Operation(summary = "添加新问卷模板") + @PostMapping("/mydc/survey/add") + @SaCheckPermission("mydc:questionnaire:query") // 继承问卷管理基本权限 + public ResponseDTO add(@RequestBody @Valid SurveyAddForm addForm) { + Long userId = SmartRequestUtil.getRequestUserId(); + return surveyService.add(addForm, userId); + } + + @Operation(summary = "修改/保存问卷设计及状态") + @PostMapping("/mydc/survey/update") + @SaCheckPermission("mydc:questionnaire:query") + public ResponseDTO update(@RequestBody @Valid SurveyUpdateForm updateForm) { + Long userId = SmartRequestUtil.getRequestUserId(); + return surveyService.update(updateForm, userId); + } + + @Operation(summary = "逻辑删除问卷模板") + @GetMapping("/mydc/survey/delete/{id}") + @SaCheckPermission("mydc:questionnaire:query") + public ResponseDTO delete(@PathVariable Long id) { + return surveyService.delete(id); + } + + @Operation(summary = "提交群众问卷答卷") + @PostMapping("/mydc/survey/answer/submit") + public ResponseDTO submitAnswer(@RequestBody @Valid SurveyAnswerAddForm answerForm) { + return surveyService.submitAnswer(answerForm); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyAnswerDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyAnswerDao.java new file mode 100644 index 0000000..3c8242d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyAnswerDao.java @@ -0,0 +1,15 @@ +package net.lab1024.sa.admin.module.business.jwpy.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.admin.module.business.jwpy.domain.entity.SurveyAnswerEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 问卷答卷结果 Dao 接口 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Mapper +public interface SurveyAnswerDao extends BaseMapper { +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyDao.java new file mode 100644 index 0000000..8a0a0cf --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/dao/SurveyDao.java @@ -0,0 +1,15 @@ +package net.lab1024.sa.admin.module.business.jwpy.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.admin.module.business.jwpy.domain.entity.SurveyEntity; +import org.apache.ibatis.annotations.Mapper; + +/** + * 问卷模板 Dao 接口 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Mapper +public interface SurveyDao extends BaseMapper { +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyAnswerEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyAnswerEntity.java new file mode 100644 index 0000000..1cda23a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyAnswerEntity.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 问卷答卷结果 实体类 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@TableName("t_jwpy_survey_answer") +@Schema(description = "答卷结果实体") +public class SurveyAnswerEntity { + + @TableId(type = IdType.AUTO) + @Schema(description = "答卷ID") + private Long answerId; + + @Schema(description = "关联问卷模板ID") + private Long surveyId; + + @Schema(description = "关联问题处置工单ID") + private Long wtczId; + + @Schema(description = "答题群众联系电话") + private String respondentPhone; + + @Schema(description = "答题答案详情JSON数据") + private String answers; + + @Schema(description = "答题累计总得分") + private Integer totalScore; + + @Schema(description = "评估满意度层级 (满意/基本满意/不满意)") + private String satisfactionLevel; + + @Schema(description = "提交时间") + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyEntity.java new file mode 100644 index 0000000..524210d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/entity/SurveyEntity.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 民意调查问卷模板 实体类 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@TableName("t_jwpy_survey") +@Schema(description = "问卷模板实体") +public class SurveyEntity { + + @TableId(type = IdType.AUTO) + @Schema(description = "问卷ID") + private Long surveyId; + + @Schema(description = "问卷标题") + private String title; + + @Schema(description = "业务大类编号") + private String sjlyNo; + + @Schema(description = "状态: 0草稿, 1启用, 2禁用") + private Integer status; + + @Schema(description = "问卷结构JSON数据") + private String content; + + @Schema(description = "备注说明") + private String remark; + + @Schema(description = "创建人用户ID") + private Long createUserId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "修改人用户ID") + private Long updateUserId; + + @Schema(description = "修改时间") + private LocalDateTime updateTime; + + @Schema(description = "删除标记: 0未删除, 1已删除") + private Integer deletedFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAddForm.java new file mode 100644 index 0000000..906999b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAddForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 新建问卷表单 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "新建问卷表单") +public class SurveyAddForm { + + @Schema(description = "问卷标题", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "问卷标题不能为空") + private String title; + + @Schema(description = "业务大类编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "业务分类不能为空") + private String sjlyNo; + + @Schema(description = "备注说明") + private String remark; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAnswerAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAnswerAddForm.java new file mode 100644 index 0000000..fe8db49 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyAnswerAddForm.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 提交问卷答卷表单 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "提交答卷表单") +public class SurveyAnswerAddForm { + + @Schema(description = "关联问卷模板ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "问卷ID不能为空") + private Long surveyId; + + @Schema(description = "关联问题处置工单ID") + private Long wtczId; + + @Schema(description = "答题群众联系电话") + private String respondentPhone; + + @Schema(description = "答题答案详情JSON数据", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "答卷内容不能为空") + private String answers; + + @Schema(description = "答题累计总得分") + private Integer totalScore; + + @Schema(description = "评估满意度层级 (满意/基本满意/不满意)") + private String satisfactionLevel; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyQueryForm.java new file mode 100644 index 0000000..e599a8f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyQueryForm.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 问卷分页查询表单 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "问卷模板分页查询表单") +public class SurveyQueryForm extends PageParam { + + @Schema(description = "问卷标题/模糊查询") + private String title; + + @Schema(description = "业务大类编号") + private String sjlyNo; + + @Schema(description = "状态: 0草稿, 1启用, 2禁用") + private Integer status; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyUpdateForm.java new file mode 100644 index 0000000..e83e48f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/form/SurveyUpdateForm.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 修改问卷设计表单 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "修改问卷设计表单") +public class SurveyUpdateForm { + + @Schema(description = "问卷ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "问卷ID不能为空") + private Long surveyId; + + @Schema(description = "问卷标题") + private String title; + + @Schema(description = "业务大类编号") + private String sjlyNo; + + @Schema(description = "问卷结构JSON数据") + private String content; + + @Schema(description = "备注说明") + private String remark; + + @Schema(description = "状态: 0草稿, 1启用, 2禁用") + private Integer status; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyAnswerVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyAnswerVO.java new file mode 100644 index 0000000..2b23a46 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyAnswerVO.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 问卷答卷 VO + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "答卷结果视图对象") +public class SurveyAnswerVO { + + @Schema(description = "答卷ID") + private Long answerId; + + @Schema(description = "关联问卷模板ID") + private Long surveyId; + + @Schema(description = "关联问题处置工单ID") + private Long wtczId; + + @Schema(description = "答题群众联系电话") + private String respondentPhone; + + @Schema(description = "答题答案详情JSON数据") + private String answers; + + @Schema(description = "答题累计总得分") + private Integer totalScore; + + @Schema(description = "评估满意度层级 (满意/基本满意/不满意)") + private String satisfactionLevel; + + @Schema(description = "提交时间") + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyVO.java new file mode 100644 index 0000000..f4ffa0a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/domain/vo/SurveyVO.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.admin.module.business.jwpy.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 问卷模板 VO + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Data +@Schema(description = "问卷模板视图对象") +public class SurveyVO { + + @Schema(description = "问卷ID") + private Long surveyId; + + @Schema(description = "问卷标题") + private String title; + + @Schema(description = "业务大类编号") + private String sjlyNo; + + @Schema(description = "状态: 0草稿, 1启用, 2禁用") + private Integer status; + + @Schema(description = "问卷结构JSON数据") + private String content; + + @Schema(description = "备注说明") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/service/SurveyService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/service/SurveyService.java new file mode 100644 index 0000000..86feaf5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/jwpy/service/SurveyService.java @@ -0,0 +1,145 @@ +package net.lab1024.sa.admin.module.business.jwpy.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.jwpy.dao.SurveyDao; +import net.lab1024.sa.admin.module.business.jwpy.dao.SurveyAnswerDao; +import net.lab1024.sa.admin.module.business.jwpy.domain.entity.SurveyEntity; +import net.lab1024.sa.admin.module.business.jwpy.domain.entity.SurveyAnswerEntity; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyQueryForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyAddForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyUpdateForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.form.SurveyAnswerAddForm; +import net.lab1024.sa.admin.module.business.jwpy.domain.vo.SurveyVO; +import net.lab1024.sa.admin.module.business.jwpy.domain.vo.SurveyAnswerVO; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDateTime; + +/** + * 问卷管理与答卷分析 业务服务类 + * + * @Author Antigravity + * @Date 2026-06-11 + */ +@Service +@Slf4j +public class SurveyService { + + @Resource + private SurveyDao surveyDao; + + @Resource + private SurveyAnswerDao surveyAnswerDao; + + /** + * 分页查询问卷模板列表 + */ + @SuppressWarnings("unchecked") + public ResponseDTO> queryPage(SurveyQueryForm queryForm) { + Page page = (Page) SmartPageUtil.convert2PageQuery(queryForm); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(SurveyEntity::getDeletedFlag, 0); + + if (StringUtils.isNotBlank(queryForm.getTitle())) { + wrapper.like(SurveyEntity::getTitle, queryForm.getTitle()); + } + + if (StringUtils.isNotBlank(queryForm.getSjlyNo())) { + wrapper.eq(SurveyEntity::getSjlyNo, queryForm.getSjlyNo()); + } + + if (queryForm.getStatus() != null) { + wrapper.eq(SurveyEntity::getStatus, queryForm.getStatus()); + } + + wrapper.orderByDesc(SurveyEntity::getCreateTime); + + surveyDao.selectPage(page, wrapper); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, SurveyVO.class); + return ResponseDTO.ok(pageResult); + } + + /** + * 创建问卷基本信息 + */ + public ResponseDTO add(SurveyAddForm addForm, Long userId) { + SurveyEntity entity = SmartBeanUtil.copy(addForm, SurveyEntity.class); + entity.setStatus(0); // 默认草稿 + entity.setCreateUserId(userId); + entity.setCreateTime(LocalDateTime.now()); + entity.setDeletedFlag(0); + surveyDao.insert(entity); + return ResponseDTO.ok("创建问卷成功"); + } + + /** + * 编辑更新问卷及设计结构 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO update(SurveyUpdateForm updateForm, Long userId) { + SurveyEntity entity = surveyDao.selectById(updateForm.getSurveyId()); + if (entity == null || entity.getDeletedFlag() == 1) { + return ResponseDTO.userErrorParam("问卷不存在或已被删除"); + } + + SurveyEntity updateEntity = SmartBeanUtil.copy(updateForm, SurveyEntity.class); + updateEntity.setUpdateUserId(userId); + updateEntity.setUpdateTime(LocalDateTime.now()); + surveyDao.updateById(updateEntity); + return ResponseDTO.ok("更新成功"); + } + + /** + * 删除问卷 + */ + public ResponseDTO delete(Long surveyId) { + SurveyEntity entity = surveyDao.selectById(surveyId); + if (entity == null) { + return ResponseDTO.userErrorParam("问卷不存在"); + } + entity.setDeletedFlag(1); + surveyDao.updateById(entity); + return ResponseDTO.ok("删除成功"); + } + + /** + * 答卷提交录入并判定满意度 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO submitAnswer(SurveyAnswerAddForm answerForm) { + SurveyAnswerEntity entity = SmartBeanUtil.copy(answerForm, SurveyAnswerEntity.class); + entity.setCreateTime(LocalDateTime.now()); + + // 如果满意度未指定且存在总分,做常规简易满意度划分:得分 >= 85 满意,70-84 基本满意,低于 70 不满意 + if (StringUtils.isBlank(entity.getSatisfactionLevel()) && entity.getTotalScore() != null) { + int score = entity.getTotalScore(); + if (score >= 85) { + entity.setSatisfactionLevel("满意"); + } else if (score >= 70) { + entity.setSatisfactionLevel("基本满意"); + } else { + entity.setSatisfactionLevel("不满意"); + } + } + + surveyAnswerDao.insert(entity); + + // 闭环警示:如果不满意,可以打印特殊业务日志或联动处置逻辑 + if ("不满意".equals(entity.getSatisfactionLevel())) { + log.warn("民意调查警报:收到一份 [不满意] 的测评结果,答卷ID: {}, 工单关联ID: {}, 得分: {}", + entity.getAnswerId(), entity.getWtczId(), entity.getTotalScore()); + } + + return ResponseDTO.ok("答卷提报成功"); + } +}