zhf
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
package io.v.nutz.zhgh.qsv.controller;
|
||||
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.base.query.PageForm;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvOption;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvActivityService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/qsv/activity")
|
||||
@Ok("json:full")
|
||||
public class QsvActivityController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvActivityService qsvActivityService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/qsv/activity/index.html")
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 分页查询
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public Result pageData(@Valid PageForm pageForm, Integer year, String title) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("YEAR(startTime)", "=", year);
|
||||
cnd.and(Cnd.likeEX("title",title));
|
||||
Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
|
||||
// 保存问卷基础信息
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public Result save(QsvActivity qsvActivity) {
|
||||
if (qsvActivity.getCategory().equals("QUIZ")) {
|
||||
if (qsvActivity.getMode().equals("SCHEDULED")) {
|
||||
qsvActivity.setRepeatMode("DAILY");
|
||||
} else if (qsvActivity.getMode().equals("REGULAR")) {
|
||||
qsvActivity.setRepeatMode("TOTAL");
|
||||
}
|
||||
}
|
||||
dao.insertOrUpdate(qsvActivity);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public Result findOne(@Valid String id) {
|
||||
QsvActivity activity = dao.fetch(QsvActivity.class, id);
|
||||
return Result.success(activity);
|
||||
}
|
||||
|
||||
// 删除问卷
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public Result delete(@Valid String id) {
|
||||
dao.delete(QsvActivity.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
// 保存问卷题目
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public Result saveSubjects(@Param("activityId") @Valid String activityId, @Param("subjects") QsvSubject[] qsvSubjects) {
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
List<String> subjectIds = subjects.stream().map(QsvSubject::getId).toList();
|
||||
|
||||
//新题目
|
||||
List<String> newSubjectIds = Arrays.stream(qsvSubjects).map(QsvSubject::getId).toList();
|
||||
|
||||
//过滤出需要删除的题目
|
||||
List<String> deleteSubjectIds = subjectIds.stream().filter(id -> !newSubjectIds.contains(id)).toList();
|
||||
dao.clear(QsvSubject.class, Cnd.where("id", "in", deleteSubjectIds));
|
||||
|
||||
for (int i = 0; i < qsvSubjects.length; i++) {
|
||||
QsvSubject qsvSubject = qsvSubjects[i];
|
||||
qsvSubject.setSortNum(i + 1);
|
||||
qsvSubject.setActivityId(activityId);
|
||||
//更新或添加题目
|
||||
dao.insertOrUpdate(qsvSubject);
|
||||
|
||||
|
||||
//更新或添加选项
|
||||
List<QsvOption> newOptions = qsvSubject.getOptions();
|
||||
List<String> optionIds = newOptions.stream().map(QsvOption::getId).toList();
|
||||
|
||||
List<QsvOption> oldOptions = dao.query(QsvOption.class, Cnd.where("subjectId", "=", qsvSubject.getId()));
|
||||
List<String> oldOptionIds = oldOptions.stream().map(QsvOption::getId).toList();
|
||||
|
||||
|
||||
List<String> deleteOptionIds = oldOptionIds.stream().filter(id -> !optionIds.contains(id)).toList();
|
||||
dao.clear(QsvOption.class, Cnd.where("id", "in", deleteOptionIds));
|
||||
|
||||
if (qsvSubject.getType().equals("radio") || qsvSubject.getType().equals("checkbox")) {
|
||||
for (int i1 = 0; i1 < newOptions.size(); i1++) {
|
||||
newOptions.get(i1).setSortNum(i1 + 1);
|
||||
newOptions.get(i1).setSubjectId(qsvSubject.getId());
|
||||
}
|
||||
dao.insertOrUpdate(newOptions);
|
||||
List<String> correctOptionIds = newOptions.stream().filter(QsvOption::getIsCorrect).map(QsvOption::getId).toList();
|
||||
qsvSubject.setCorrectAnswer(correctOptionIds);
|
||||
} else {
|
||||
dao.clear(QsvOption.class, Cnd.where("subjectId", "=", qsvSubject.getId()));
|
||||
}
|
||||
dao.update(qsvSubject);
|
||||
}
|
||||
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
// 查询问卷题目
|
||||
@At
|
||||
@RequiresPermissions("qsv.activity")
|
||||
public Result listSubjects(@Valid String activityId) {
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId).asc("sortNum"));
|
||||
dao.fetchLinks(subjects, "options",Cnd.NEW().asc("sortNum"));
|
||||
return Result.success(subjects);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package io.v.nutz.zhgh.qsv.controller;
|
||||
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvQuizRankPageForm;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvQuizRankService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/qsv/quizRank")
|
||||
@Ok("json:full")
|
||||
public class QsvQuizRankController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvQuizRankService qsvQuizRankService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/qsv/quiz/rank.html")
|
||||
@RequiresPermissions("qsv.quiz.rank")
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
// 根据年度查询问卷
|
||||
@At
|
||||
@RequiresPermissions("qsv.quiz.rank")
|
||||
public Result listQuiz(Integer year) {
|
||||
Cnd cnd = Cnd.where("category", "=", "QUIZ");
|
||||
cnd.andEX("YEAR(startTime)", "=", year);
|
||||
cnd.desc("category");
|
||||
List<QsvActivity> list = dao.query(QsvActivity.class, cnd);
|
||||
return Result.success(list);
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresPermissions("qsv.quiz.rank")
|
||||
public Result pageData(@Valid QsvQuizRankPageForm pageForm) {
|
||||
Pagination pagination = qsvQuizRankService.pageData(pageForm);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@RequiresPermissions("qsv.quiz.rank")
|
||||
public void exportXlsx(@Valid QsvQuizRankPageForm pageForm, HttpServletResponse response) {
|
||||
qsvQuizRankService.exportXlsx(pageForm, response);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package io.v.nutz.zhgh.qsv.controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.base.query.PageForm;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvActivityService;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvSurveyService;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/qsv/survey")
|
||||
@Ok("json:full")
|
||||
public class QsvSurveyController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvActivityService qsvActivityService;
|
||||
@Inject
|
||||
private QsvSurveyService qsvSurveyService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/qsv/survey/index.html")
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public Result pageData(@Valid PageForm pageForm, Integer year) {
|
||||
Cnd cnd = Cnd.where("category", "=", "SURVEY");
|
||||
cnd.andEX("YEAR(startTime)", "=", year);
|
||||
cnd.desc("category");
|
||||
Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
// 报告
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public Result report(@Valid String activityId) {
|
||||
List<NutMap> report = qsvSurveyService.report(activityId);
|
||||
return Result.success(report);
|
||||
}
|
||||
|
||||
// 选项选择详情
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public Result selectOptionUsers(@Valid String activityId, @Valid String subjectId, @Valid String optionId) {
|
||||
List<QsvUserAnswerRecord> answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId));
|
||||
List<QsvUserAnswerRecord> selectOptionUsers = answerRecords.stream().filter(ext -> ObjectUtil.isNotNull(ext.getExtJson().get(subjectId, JSONObject.class)) && ext.getExtJson().get(subjectId, JSONObject.class).getJSONArray("optionIds").contains(optionId)).toList();
|
||||
return Result.success(selectOptionUsers);
|
||||
}
|
||||
|
||||
|
||||
// 用户答题
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public Result userAnswer(@Valid String activityId) {
|
||||
NutMap map = qsvSurveyService.userAnswer(activityId);
|
||||
return Result.success(map);
|
||||
}
|
||||
|
||||
|
||||
// 删除用户答题记录
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public Result deleteUserAnswer(@Valid String id) {
|
||||
dao.delete(QsvUserAnswerRecord.class, id);
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
|
||||
// 导出用户答题记录xlsx
|
||||
@At
|
||||
@RequiresPermissions("qsv.survey")
|
||||
public void exportUserAnswerXlsx(@Valid String activityId, HttpServletResponse response) {
|
||||
qsvSurveyService.exportUserAnswerXlsx(activityId, response);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.v.nutz.zhgh.qsv.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
//答题得分计算结果
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Builder
|
||||
public class QsvCheckAnswerResult {
|
||||
|
||||
private boolean isCorrect;
|
||||
|
||||
private float score;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package io.v.nutz.zhgh.qsv.h5controller;
|
||||
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.base.query.PageForm;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvActivityService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/h5/qsv")
|
||||
@Ok("json:full")
|
||||
@Slf4j
|
||||
public class H5QsvController {
|
||||
|
||||
@Inject
|
||||
private QsvActivityService qsvActivityService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/mobile/qsv/index.html")
|
||||
@RequiresPermissions("h5.qsv")
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
@At
|
||||
@RequiresPermissions("h5.qsv")
|
||||
public Result pageData(@Valid PageForm pageForm, @Valid String category) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.andEX("category", "=", category);
|
||||
cnd.desc("startTime");
|
||||
Pagination pagination = qsvActivityService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd);
|
||||
return Result.success(pagination);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
package io.v.nutz.zhgh.qsv.h5controller;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import io.v.nutz.zhgh.qsv.dto.QsvCheckAnswerResult;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvAnswerParam;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvQuizService;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvUserAnswerRecordService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.shiro.authz.annotation.RequiresAuthentication;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.util.cri.Static;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/h5/qsv/quiz")
|
||||
@Ok("json:full")
|
||||
@Slf4j
|
||||
public class H5QsvQuizController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
@Inject
|
||||
private QsvQuizService qsvQuizService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/mobile/qsv/quiz/index.html")
|
||||
@RequiresAuthentication
|
||||
public void index() {
|
||||
|
||||
}
|
||||
|
||||
@At
|
||||
@Ok("beetl:/mobile/qsv/quiz/result.html")
|
||||
@RequiresAuthentication
|
||||
public void result() {
|
||||
|
||||
}
|
||||
|
||||
// 题目列表
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result subjects(@Valid String activityId) {
|
||||
QsvActivity activity = dao.fetch(QsvActivity.class, activityId);
|
||||
String mode = activity.getMode();
|
||||
//能否重复答题
|
||||
Boolean repeatable = activity.getRepeatable();
|
||||
//重复答题模式
|
||||
String repeatMode = activity.getRepeatMode();
|
||||
//答题最大次数
|
||||
Integer maxAttempts = activity.getMaxAttempts();
|
||||
//题目显示模式
|
||||
String displayMode = activity.getDisplayMode();
|
||||
|
||||
//最终返回的题目数据
|
||||
List<QsvSubject> resultSubjects = new ArrayList<>();
|
||||
String answerRecordId = null;
|
||||
|
||||
//查询用户的答题记录
|
||||
List<QsvUserAnswerRecord> answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId()));
|
||||
|
||||
if (activity.getEndTime().after(new Date())) {
|
||||
//已结束 查询最新一次的答题记录
|
||||
Optional<QsvUserAnswerRecord> lastRecordOptional = answerRecords.stream().max(Comparator.comparing(QsvUserAnswerRecord::getAnswerTime));
|
||||
if (lastRecordOptional.isPresent()) {
|
||||
List<String> subjectIds = lastRecordOptional.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
answerRecordId = lastRecordOptional.get().getId();
|
||||
}else{
|
||||
//没生成过 那就看全部的题目
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList()));
|
||||
answerRecordId = answerRecord.getId();
|
||||
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (mode.equals("REGULAR")) {
|
||||
if (ObjectUtil.isEmpty(answerRecords)) {
|
||||
//首次进来生成答题记录
|
||||
if (displayMode.equals("ALL")) {
|
||||
resultSubjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, resultSubjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId();
|
||||
} else if (displayMode.equals("RANDOM")) {
|
||||
//单次随机抽取题目数量
|
||||
Integer randomCount = activity.getRandomCount();
|
||||
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
if (subjects.size() < randomCount) {
|
||||
throw new RuntimeException("题目数不够,无法生成题目");
|
||||
}
|
||||
|
||||
//从subjects里随机抽取randomCount个题目
|
||||
Collections.shuffle(subjects);
|
||||
List<QsvSubject> randomSubjects = subjects.subList(0, randomCount);
|
||||
QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, randomSubjects.stream().map(QsvSubject::getId).collect(Collectors.toList()));
|
||||
answerRecordId = answerRecord.getId();
|
||||
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
}
|
||||
} else {
|
||||
if (displayMode.equals("ALL")) {
|
||||
//判断能否重复答题 如果可重复要根据次数判断是否再次生成记录 不能重复直接返回最新的一次记录
|
||||
if (repeatable) {
|
||||
//已回答次数
|
||||
if (answerRecords.size() < maxAttempts) {
|
||||
//生成答题记录
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId();
|
||||
QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, answerRecordId);
|
||||
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
} else {
|
||||
//已达到最大次数 返回最新一次记录
|
||||
Optional<QsvUserAnswerRecord> maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber));
|
||||
if (maxAnswerRecordOptional.isPresent()) {
|
||||
List<String> subjectIds = maxAnswerRecordOptional.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
answerRecordId = maxAnswerRecordOptional.get().getId();
|
||||
} else {
|
||||
throw new RuntimeException("业务异常");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Optional<QsvUserAnswerRecord> maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber));
|
||||
if (maxAnswerRecordOptional.isPresent()) {
|
||||
List<String> subjectIds = maxAnswerRecordOptional.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
answerRecordId = maxAnswerRecordOptional.get().getId();
|
||||
} else {
|
||||
throw new RuntimeException("业务异常");
|
||||
}
|
||||
}
|
||||
} else if (displayMode.equals("RANDOM")) {
|
||||
//判断是否有未答完的记录
|
||||
Optional<QsvUserAnswerRecord> notFinishRecordOptional = answerRecords.stream().filter(r -> !r.getIsFinish()).findFirst();
|
||||
if (notFinishRecordOptional.isPresent()) {
|
||||
List<String> subjectIds = notFinishRecordOptional.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
answerRecordId = notFinishRecordOptional.get().getId();
|
||||
} else {
|
||||
//随机抽取模式
|
||||
//单次随机抽取题目数量
|
||||
Integer randomCount = activity.getRandomCount();
|
||||
//总随机抽取次数
|
||||
Integer totalRandom = activity.getTotalRandom();
|
||||
|
||||
Date startTime = activity.getStartTime();
|
||||
Date endTime = activity.getEndTime();
|
||||
|
||||
//是否同一天
|
||||
boolean isSameDay = DateUtil.isSameDay(startTime, endTime);
|
||||
|
||||
// if(!isSameDay){
|
||||
if (answerRecords.size() < totalRandom) {
|
||||
//进行下一次抽取
|
||||
List<String> subjectIds = answerRecords.stream().map(QsvUserAnswerRecord::getSubjectIds).flatMap(Collection::stream).toList();
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("id", "not in", subjectIds));
|
||||
|
||||
if (subjects.size() < randomCount) {
|
||||
throw new RuntimeException("题目数不够,无法生成题目");
|
||||
}
|
||||
|
||||
//从subjects里随机抽取randomCount个题目
|
||||
Collections.shuffle(subjects);
|
||||
resultSubjects = subjects.subList(0, randomCount);
|
||||
answerRecordId = qsvUserAnswerRecordService.insertRecord(activityId, resultSubjects.stream().map(QsvSubject::getId).collect(Collectors.toList())).getId();
|
||||
} else {
|
||||
//返回最后一次抽取的记录
|
||||
Optional<QsvUserAnswerRecord> maxAnswerRecordOptional = answerRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber));
|
||||
if (maxAnswerRecordOptional.isPresent()) {
|
||||
List<String> subjectIds = maxAnswerRecordOptional.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
answerRecordId = maxAnswerRecordOptional.get().getId();
|
||||
} else {
|
||||
throw new RuntimeException("业务异常");
|
||||
}
|
||||
}
|
||||
// }else{
|
||||
//
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode.equals("SCHEDULED")) {
|
||||
//定时定题
|
||||
//查询今天的题目
|
||||
|
||||
List<QsvUserAnswerRecord> todayRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId())
|
||||
.and("attemptDate", "=", DateUtil.today())
|
||||
);
|
||||
|
||||
if (ObjectUtil.isNotEmpty(todayRecords)) {
|
||||
//判断下每天可以答几次(题目实际上都是一样的)
|
||||
boolean todayAllFinish = todayRecords.stream().allMatch(QsvUserAnswerRecord::getIsFinish);
|
||||
//如果今天已生成的题目已答完并且还可以重复答
|
||||
if (todayAllFinish && todayRecords.size() < maxAttempts) {
|
||||
//生成今天的记录
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("displayDate", "=", DateUtil.today()));
|
||||
QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList()));
|
||||
answerRecordId = answerRecord.getId();
|
||||
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
} else {
|
||||
//今天最大那次的记录
|
||||
Optional<QsvUserAnswerRecord> maxTodayRecord = todayRecords.stream().max(Comparator.comparingLong(QsvUserAnswerRecord::getRandomNumber));
|
||||
if (maxTodayRecord.isPresent()) {
|
||||
answerRecordId = maxTodayRecord.get().getId();
|
||||
|
||||
List<String> subjectIds = maxTodayRecord.get().getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
} else {
|
||||
throw new RuntimeException("业务异常");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//生成今天的记录
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("displayDate", "=", DateUtil.today()));
|
||||
QsvUserAnswerRecord answerRecord = qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).collect(Collectors.toList()));
|
||||
answerRecordId = answerRecord.getId();
|
||||
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
resultSubjects = dao.query(QsvSubject.class, cnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dao.fetchLinks(resultSubjects, "options", Cnd.NEW().asc("sortNum"));
|
||||
|
||||
resultSubjects.forEach(v -> v.setUserSelectOptionIds(new ArrayList<>()));
|
||||
|
||||
NutMap result = NutMap.NEW().addv("subjects", resultSubjects).addv("answerRecordId", answerRecordId).addv("activity", activity);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
// 答题记录
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result answerRecord(@Valid String answerRecordId) {
|
||||
QsvUserAnswerRecord record = dao.fetch(QsvUserAnswerRecord.class, answerRecordId);
|
||||
return Result.success(record);
|
||||
}
|
||||
|
||||
// 提交答题
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result submitAnswer(@Valid @Param("answer") QsvAnswerParam qsvAnswerParam) {
|
||||
QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, qsvAnswerParam.getAnswerRecordId());
|
||||
JSONObject extJson = answerRecord.getExtJson();
|
||||
|
||||
float totalScore = 0;
|
||||
|
||||
for (QsvAnswerParam.Subject subject : qsvAnswerParam.getSubjects()) {
|
||||
JSONObject entries = extJson.get(subject.getId(), JSONObject.class);
|
||||
if (ObjectUtil.isNotEmpty(entries)) {
|
||||
entries.set("optionIds", subject.getUserSelectOptionIds());
|
||||
entries.set("text", subject.getUserFillContent());
|
||||
|
||||
QsvCheckAnswerResult answerResult = qsvQuizService.calcScore(subject.getId(), subject.getUserSelectOptionIds());
|
||||
entries.set("score", answerResult.getScore());
|
||||
entries.set("isCorrect", answerResult.isCorrect());
|
||||
|
||||
if (answerResult.isCorrect()) {
|
||||
totalScore += answerResult.getScore();
|
||||
}
|
||||
}
|
||||
extJson.set(subject.getId(), entries);
|
||||
}
|
||||
|
||||
answerRecord.setTotalScore(totalScore);
|
||||
answerRecord.setAttemptDate(new Date());
|
||||
answerRecord.setSubmitTime(new Date());
|
||||
answerRecord.setAnswerTime(qsvAnswerParam.getAnswerTime());
|
||||
answerRecord.setIsFinish(true);
|
||||
dao.update(answerRecord);
|
||||
|
||||
//重新计算最高分 最新得分
|
||||
qsvUserAnswerRecordService.calcByScoreMode(qsvAnswerParam.getActivityId(), ShiroUtil.getUserId());
|
||||
|
||||
return Result.success("提交成功");
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result historyScore(@Valid String activityId) {
|
||||
List<QsvUserAnswerRecord> answerRecords = dao.query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId).and("userId", "=", ShiroUtil.getUserId()).desc("createdAt"));
|
||||
return Result.success(answerRecords);
|
||||
}
|
||||
|
||||
// 答题记录(结果页展示)
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result answerResult(@Valid String answerRecordId) {
|
||||
QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, answerRecordId);
|
||||
List<String> subjectIds = answerRecord.getSubjectIds();
|
||||
|
||||
Cnd cnd = Cnd.where("id", "in", subjectIds);
|
||||
String dynamic = subjectIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
|
||||
cnd.and(new Static("1=1 ORDER BY FIELD (id," + dynamic + ")"));
|
||||
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, cnd);
|
||||
dao.fetchLinks(subjects, "options", Cnd.NEW().asc("sortNum"));
|
||||
|
||||
subjects.forEach(v -> v.setUserSelectOptionIds(new ArrayList<>()));
|
||||
|
||||
QsvActivity activity = dao.fetch(QsvActivity.class, answerRecord.getActivityId());
|
||||
NutMap result = NutMap.NEW().addv("subjects", subjects).addv("answerRecordId", answerRecord.getId()).addv("activity", activity);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package io.v.nutz.zhgh.qsv.h5controller;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvAnswerParam;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvUserAnswerRecordService;
|
||||
import org.apache.shiro.authz.annotation.RequiresAuthentication;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.Inject;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
import org.nutz.mvc.annotation.At;
|
||||
import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean
|
||||
@At("/platform/h5/qsv/survey")
|
||||
@Ok("json:full")
|
||||
public class H5QsvSurveyController {
|
||||
|
||||
@Inject
|
||||
private Dao dao;
|
||||
@Inject
|
||||
private QsvUserAnswerRecordService qsvUserAnswerRecordService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/mobile/qsv/survey/index.html")
|
||||
@RequiresAuthentication
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result subjects(@Valid String activityId) {
|
||||
QsvActivity activity = dao.fetch(QsvActivity.class, activityId);
|
||||
String answerRecordId = null;
|
||||
|
||||
QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId()));
|
||||
if (answerRecord == null) {
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
qsvUserAnswerRecordService.insertRecord(activityId, subjects.stream().map(QsvSubject::getId).toList());
|
||||
}
|
||||
|
||||
QsvUserAnswerRecord answerRecord2 = dao.fetch(QsvUserAnswerRecord.class,
|
||||
Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId()));
|
||||
|
||||
answerRecordId = answerRecord2.getId();
|
||||
|
||||
List<QsvSubject> subjects = dao.query(QsvSubject.class, Cnd.where("id", "in", answerRecord2.getSubjectIds()));
|
||||
dao.fetchLinks(subjects, "options");
|
||||
|
||||
for (QsvSubject subject : subjects) {
|
||||
if (subject.getUserSelectOptionIds() == null) {
|
||||
subject.setUserSelectOptionIds(new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
NutMap result = NutMap.NEW().addv("subjects", subjects).addv("answerRecordId", answerRecordId).addv("activity", activity);
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result answerRecord(@Valid String answerRecordId) {
|
||||
QsvUserAnswerRecord record = dao.fetch(QsvUserAnswerRecord.class, answerRecordId);
|
||||
return Result.success(record);
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result submitAnswer(@Valid @Param("answer") QsvAnswerParam qsvAnswerParam) {
|
||||
QsvUserAnswerRecord answerRecord = dao.fetch(QsvUserAnswerRecord.class, qsvAnswerParam.getAnswerRecordId());
|
||||
JSONObject extJson = answerRecord.getExtJson();
|
||||
|
||||
for (QsvAnswerParam.Subject subject : qsvAnswerParam.getSubjects()) {
|
||||
JSONObject entries = extJson.get(subject.getId(), JSONObject.class);
|
||||
if (ObjectUtil.isNotEmpty(entries)) {
|
||||
entries.set("optionIds", subject.getUserSelectOptionIds());
|
||||
entries.set("text", subject.getUserFillContent());
|
||||
}
|
||||
extJson.set(subject.getId(), entries);
|
||||
}
|
||||
|
||||
answerRecord.setAttemptDate(new Date());
|
||||
answerRecord.setSubmitTime(new Date());
|
||||
answerRecord.setIsFinish(true);
|
||||
dao.update(answerRecord);
|
||||
|
||||
return Result.success("提交成功");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package io.v.nutz.zhgh.qsv.models;
|
||||
|
||||
import io.v.nutz.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Table("qsv_activity")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("问卷调查投票活动表")
|
||||
public class QsvActivity extends BaseModel {
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("活动标题")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String title;
|
||||
|
||||
@Column
|
||||
@Comment("活动描述")
|
||||
@ColDefine(type = ColType.TEXT)
|
||||
private String description;
|
||||
|
||||
@Column
|
||||
@Comment("所属模块(quiz, survey, vote)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String category;
|
||||
|
||||
@Column
|
||||
@Comment("活动开始时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date startTime;
|
||||
|
||||
@Column
|
||||
@Comment("活动结束时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date endTime;
|
||||
|
||||
@Column
|
||||
@Comment("活动分组ID")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer groupId;
|
||||
|
||||
@Column
|
||||
@Comment("模式:定时定题模式(scheduled)或常规模式(regular)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String mode;
|
||||
|
||||
@Column
|
||||
@Comment("是否可重复答题")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean repeatable;
|
||||
|
||||
@Column
|
||||
@Comment("重复模式:按天(daily)或按活动总次数(total)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String repeatMode;
|
||||
|
||||
@Column
|
||||
@Comment("最大答题次数(0表示不限制)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer maxAttempts;
|
||||
|
||||
@Column
|
||||
@Comment("显示模式:全部显示、随机抽取显示(ALL、RANDOM)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String displayMode;
|
||||
|
||||
@Column
|
||||
@Comment("单次随机抽取题目数量")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer randomCount;
|
||||
|
||||
@Column
|
||||
@Comment("总随机抽取次数")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer totalRandom;
|
||||
|
||||
@Column
|
||||
@Comment("随机打乱题目顺序")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean shuffleSubject;
|
||||
|
||||
@Column
|
||||
@Comment("答题时间限制(以分钟为单位,0表示无限制)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer timeLimit;
|
||||
|
||||
@Column
|
||||
@Comment("答题得分统计(最高、最新)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String scoreMode;
|
||||
|
||||
@Column
|
||||
@Comment("封面图片")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String cover;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.v.nutz.zhgh.qsv.models;
|
||||
|
||||
import io.v.nutz.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Table("qsv_option")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("问卷调查投票选项表")
|
||||
public class QsvOption extends BaseModel {
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("题目表")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String subjectId;
|
||||
|
||||
@Column
|
||||
@Comment("选项内容")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String text;
|
||||
|
||||
@Column
|
||||
@Comment("是否为正确答案(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
private Boolean isCorrect;
|
||||
|
||||
@Column
|
||||
@Comment("图片地址")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String imgUrl;
|
||||
|
||||
@Column
|
||||
@Comment("排序")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer sortNum;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package io.v.nutz.zhgh.qsv.models;
|
||||
|
||||
import io.v.nutz.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("qsv_subject")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("问卷调查投票题目表")
|
||||
public class QsvSubject extends BaseModel {
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("活动ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String activityId;
|
||||
|
||||
@Column
|
||||
@Comment("题目标题")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 255)
|
||||
private String title;
|
||||
|
||||
@Column
|
||||
@Comment("题目类型(single, multi, judge, fill)")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String type;
|
||||
|
||||
@Column
|
||||
@Comment("正确答案")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<String> correctAnswer; // 正确答案
|
||||
|
||||
@Column
|
||||
@Comment("题目分数(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer score; //
|
||||
|
||||
@Column
|
||||
@Comment("显示时间")
|
||||
@ColDefine(type = ColType.DATE)
|
||||
private Date displayDate;
|
||||
|
||||
@Column
|
||||
@Comment("排序")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer sortNum;
|
||||
|
||||
/**
|
||||
* 选项
|
||||
*/
|
||||
@Many(target = QsvOption.class, field = "subjectId")
|
||||
private List<QsvOption> options;
|
||||
|
||||
/**
|
||||
* 用户选择的选项(选择题)
|
||||
*/
|
||||
private List<String> userSelectOptionIds;
|
||||
|
||||
/**
|
||||
* 用户填写的内容(填空题)
|
||||
*/
|
||||
private String userFillContent;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package io.v.nutz.zhgh.qsv.models;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import io.v.nutz.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.*;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("qsv_user_answer_record")
|
||||
@TableMeta("{'mysql-charset':'utf8mb4'}")
|
||||
@Comment("问卷调查投票记录表")
|
||||
public class QsvUserAnswerRecord extends BaseModel {
|
||||
|
||||
@Name
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("用户ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String userId;
|
||||
|
||||
@Column
|
||||
@Comment("工号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String loginName;
|
||||
|
||||
@Column
|
||||
@Comment("姓名")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String userName;
|
||||
|
||||
@Column
|
||||
@Comment("分工会")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String unionName;
|
||||
|
||||
@Column
|
||||
@Comment("分工会ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unionId;
|
||||
|
||||
@Column
|
||||
@Comment("单位")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 200)
|
||||
private String unitName;
|
||||
|
||||
@Column
|
||||
@Comment("单位ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String unitId;
|
||||
|
||||
@Column
|
||||
@Comment("活动ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String activityId;
|
||||
|
||||
@Column
|
||||
@Comment("扩展字段")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private JSONObject extJson;
|
||||
|
||||
@Column
|
||||
@Comment("题目ID")
|
||||
@ColDefine(type = ColType.MYSQL_JSON)
|
||||
private List<String> subjectIds;
|
||||
|
||||
@Column
|
||||
@Comment("答题得分(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.FLOAT)
|
||||
private Float totalScore;
|
||||
|
||||
@Column
|
||||
@Comment("随机次数(仅答题模块使用随机抽取模式)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer randomNumber;
|
||||
|
||||
@Column
|
||||
@Comment("答题次数(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.INT, width = 1)
|
||||
private Integer attemptNumber;
|
||||
|
||||
@Column
|
||||
@Comment("答题日期(用于统计某一天的答题次数)")
|
||||
@ColDefine(type = ColType.DATE)
|
||||
private Date attemptDate;
|
||||
|
||||
@Column
|
||||
@Comment("是否为最新得分(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean isLatestScore;
|
||||
|
||||
@Column
|
||||
@Comment("是否为最高得分(仅答题模块使用)")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean isHighestScore;
|
||||
|
||||
@Column
|
||||
@Comment("是否完成")
|
||||
@ColDefine(type = ColType.BOOLEAN)
|
||||
@Default("0")
|
||||
private Boolean isFinish;
|
||||
|
||||
@Column
|
||||
@Comment("提交时间")
|
||||
@ColDefine(type = ColType.DATETIME)
|
||||
private Date submitTime;
|
||||
|
||||
@Column
|
||||
@Comment("答题用时")
|
||||
@ColDefine(type = ColType.INT)
|
||||
private Integer answerTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.v.nutz.zhgh.qsv.param;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
//答题参数
|
||||
public class QsvAnswerParam {
|
||||
|
||||
private String activityId;
|
||||
|
||||
private String answerRecordId;
|
||||
|
||||
private List<Subject> subjects;
|
||||
|
||||
private Integer answerTime;
|
||||
|
||||
@Data
|
||||
public static class Subject{
|
||||
private String id;
|
||||
private List<String> userSelectOptionIds;
|
||||
private String userFillContent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.v.nutz.zhgh.qsv.param;
|
||||
|
||||
import io.v.nutz.base.query.PageForm;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
//问卷排名得分分页查询参数
|
||||
public class QsvQuizRankPageForm extends PageForm {
|
||||
|
||||
private String activityId;
|
||||
|
||||
private String unionId;
|
||||
|
||||
private String unitId;
|
||||
|
||||
private Date attemptDate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.v.nutz.zhgh.qsv.service;
|
||||
|
||||
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
|
||||
public interface QsvActivityService extends BaseService<QsvActivity> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.v.nutz.zhgh.qsv.service;
|
||||
|
||||
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvQuizRankPageForm;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public interface QsvQuizRankService extends BaseService<QsvUserAnswerRecord> {
|
||||
|
||||
Pagination pageData(QsvQuizRankPageForm pageForm);
|
||||
|
||||
void exportXlsx(QsvQuizRankPageForm pageForm, HttpServletResponse response);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.v.nutz.zhgh.qsv.service;
|
||||
|
||||
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.zhgh.qsv.dto.QsvCheckAnswerResult;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QsvQuizService extends BaseService<QsvUserAnswerRecord> {
|
||||
|
||||
/**
|
||||
* 计算答题分数
|
||||
* @param subjectId 题目ID
|
||||
* @param userSelectOptions 用户选项
|
||||
* @return 分数
|
||||
*/
|
||||
QsvCheckAnswerResult calcScore(String subjectId, List<String> userSelectOptions);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.v.nutz.zhgh.qsv.service;
|
||||
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
public interface QsvSurveyService extends BaseService<QsvUserAnswerRecord> {
|
||||
|
||||
List<NutMap> report(String activityId);
|
||||
|
||||
void exportUserAnswerXlsx(String activityId, HttpServletResponse response);
|
||||
|
||||
NutMap userAnswer(String activityId);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.v.nutz.zhgh.qsv.service;
|
||||
|
||||
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvAnswerParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QsvUserAnswerRecordService extends BaseService<QsvUserAnswerRecord> {
|
||||
|
||||
QsvUserAnswerRecord insertRecord(String activityId, List<String> subjectIds);
|
||||
|
||||
/**
|
||||
* 计算得分
|
||||
*/
|
||||
float calcScore(QsvAnswerParam qsvAnswerParam);
|
||||
|
||||
void calcByScoreMode(String activityId, String userId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.v.nutz.zhgh.qsv.service.impl;
|
||||
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvActivityService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class QsvActivityServiceImpl extends BaseServiceImpl<QsvActivity> implements QsvActivityService {
|
||||
|
||||
public QsvActivityServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package io.v.nutz.zhgh.qsv.service.impl;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import io.v.nutz.base.page.Pagination;
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvQuizRankPageForm;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvQuizRankService;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.dao.util.cri.SqlExpressionGroup;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class QsvQuizRankServiceImpl extends BaseServiceImpl<QsvUserAnswerRecord> implements QsvQuizRankService {
|
||||
|
||||
public QsvQuizRankServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination pageData(QsvQuizRankPageForm pageForm) {
|
||||
String activityId = pageForm.getActivityId();
|
||||
if(StrUtil.isBlank(activityId)){
|
||||
return new Pagination();
|
||||
}
|
||||
|
||||
QsvActivity activity = dao().fetch(QsvActivity.class, activityId);
|
||||
if (activity == null) {
|
||||
return new Pagination();
|
||||
}
|
||||
|
||||
String mode = activity.getMode();
|
||||
String scoreStatisticsMode = activity.getScoreMode();
|
||||
|
||||
Sql sql = buildQuerySql(activityId, mode, scoreStatisticsMode, pageForm);
|
||||
|
||||
return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportXlsx(QsvQuizRankPageForm pageForm, HttpServletResponse response) {
|
||||
String activityId = pageForm.getActivityId();
|
||||
QsvActivity activity = dao().fetch(QsvActivity.class, activityId);
|
||||
|
||||
if (activity == null) {
|
||||
throw new RuntimeException("活动不存在: " + activityId);
|
||||
}
|
||||
|
||||
String mode = activity.getMode();
|
||||
String scoreStatisticsMode = activity.getScoreMode();
|
||||
|
||||
Sql sql = buildQuerySql(activityId, mode, scoreStatisticsMode, pageForm);
|
||||
List<NutMap> list = listMap(sql);
|
||||
|
||||
List<ExcelExportEntity> exportEntities = new ArrayList<>();
|
||||
exportEntities.add(new ExcelExportEntity("姓名", "userName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("工号", "loginName", 20));
|
||||
exportEntities.add(new ExcelExportEntity("性别", "sex", 20));
|
||||
exportEntities.add(new ExcelExportEntity("单位", "unitName", 30));
|
||||
exportEntities.add(new ExcelExportEntity("分工会", "unionName", 30));
|
||||
exportEntities.add(new ExcelExportEntity("联系方式", "mobile", 30));
|
||||
if ("SCHEDULED".equals(mode) && pageForm.getAttemptDate() != null) {
|
||||
exportEntities.add(new ExcelExportEntity("答题日期", "attemptDate", 20));
|
||||
exportEntities.add(new ExcelExportEntity("当天得分", "totalScore", 20));
|
||||
} else {
|
||||
exportEntities.add(new ExcelExportEntity("得分", "sumScore", 20));
|
||||
}
|
||||
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list);
|
||||
// CommonDownloadUtil.download(activity.getTitle() + "得分名单" + ".xlsx", workbook, response);
|
||||
}
|
||||
|
||||
private Sql buildQuerySql(String activityId, String mode, String scoreStatisticsMode, QsvQuizRankPageForm pageForm) {
|
||||
StringBuilder sqlBuilder = new StringBuilder("""
|
||||
SELECT
|
||||
t1.userId,
|
||||
t1.userName,
|
||||
t1.loginName,
|
||||
t1.unitName,
|
||||
t1.unionName,
|
||||
u.mobile,
|
||||
t1.totalScore,
|
||||
t1.attemptDate,
|
||||
sum(t1.totalScore) as sumScore
|
||||
FROM
|
||||
`qsv_user_answer_record` t1
|
||||
LEFT JOIN sys_user u ON u.id = t1.userId
|
||||
$condition
|
||||
""");
|
||||
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("t1.activityId","=",activityId);
|
||||
|
||||
if(StrUtil.isNotBlank(pageForm.getSearchKeyword())){
|
||||
SqlExpressionGroup seg = new SqlExpressionGroup();
|
||||
seg.orLike("t1.loginName", pageForm.getSearchKeyword());
|
||||
seg.orLike("t1.userName", pageForm.getSearchKeyword());
|
||||
cnd.and(seg);
|
||||
}
|
||||
|
||||
cnd.andEX("t1.unionId","=",pageForm.getUnionId());
|
||||
cnd.andEX("t1.unitId","=",pageForm.getUnitId());
|
||||
|
||||
if ("SCHEDULED".equals(mode)) {
|
||||
if ("HIGH".equals(scoreStatisticsMode)) {
|
||||
cnd.and("t1.isHighestScore","=",1);
|
||||
} else if ("LAST".equals(scoreStatisticsMode)) {
|
||||
cnd.and("t1.isLatestScore","=",1);
|
||||
}
|
||||
} else if ("REGULAR".equals(mode)) {
|
||||
if ("HIGH".equals(scoreStatisticsMode)) {
|
||||
cnd.and("t1.isHighestScore","=",1);
|
||||
} else if ("LAST".equals(scoreStatisticsMode)) {
|
||||
cnd.and("t1.isLatestScore","=",1);
|
||||
}
|
||||
}
|
||||
|
||||
if (pageForm.getAttemptDate() != null) {
|
||||
cnd.and("t1.attemptDate","=",pageForm.getAttemptDate());
|
||||
}
|
||||
|
||||
cnd.groupBy("t1.userId");
|
||||
cnd.desc("t1.totalScore");
|
||||
|
||||
Sql sql = Sqls.create(sqlBuilder.toString());
|
||||
sql.setCondition(cnd);
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.v.nutz.zhgh.qsv.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.zhgh.qsv.dto.QsvCheckAnswerResult;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvQuizService;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class QsvQuizServiceImpl extends BaseServiceImpl<QsvUserAnswerRecord> implements QsvQuizService {
|
||||
|
||||
public QsvQuizServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QsvCheckAnswerResult calcScore(String subjectId, List<String> userSelectOptions) {
|
||||
QsvSubject subject = dao().fetch(QsvSubject.class, subjectId);
|
||||
List<String> correctOptionIds = subject.getCorrectAnswer();
|
||||
|
||||
if(ObjectUtil.isEmpty(userSelectOptions)){
|
||||
userSelectOptions = new ArrayList<>();
|
||||
}
|
||||
|
||||
//比较选项是否正确 不考虑顺序
|
||||
boolean equals = new HashSet<>(userSelectOptions).equals(new HashSet<>(correctOptionIds));
|
||||
return QsvCheckAnswerResult.builder().isCorrect(equals).score(equals ? subject.getScore() : 0).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package io.v.nutz.zhgh.qsv.service.impl;
|
||||
|
||||
import cn.afterturn.easypoi.excel.ExcelExportUtil;
|
||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
|
||||
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvOption;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvSurveyService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
import org.nutz.dao.sql.Sql;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
import org.nutz.lang.Lang;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class QsvSurveyServiceImpl extends BaseServiceImpl<QsvUserAnswerRecord> implements QsvSurveyService {
|
||||
public QsvSurveyServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NutMap> report(String activityId) {
|
||||
// 检查活动ID是否为空
|
||||
if (activityId == null || activityId.isEmpty()) {
|
||||
throw new IllegalArgumentException("活动ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询用户答题记录
|
||||
List<QsvUserAnswerRecord> answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId));
|
||||
// 将答题记录的扩展JSON转换为JSONObject列表
|
||||
List<JSONObject> answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList();
|
||||
|
||||
// 查询活动题目列表
|
||||
List<NutMap> subjects = querySubjects(activityId);
|
||||
// 获取题目ID列表
|
||||
List<String> subjectIds = subjects.stream().map(v -> v.getString("id")).toList();
|
||||
|
||||
// 查询题目选项列表
|
||||
List<QsvOption> options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum"));
|
||||
// 按题目ID分组选项
|
||||
Map<String, List<QsvOption>> optionsGroup = options.stream().collect(Collectors.groupingBy(QsvOption::getSubjectId));
|
||||
|
||||
// 处理每个题目
|
||||
for (NutMap subject : subjects) {
|
||||
// 获取当前题目的选项列表
|
||||
List<NutMap> subjectOptions = Lang.collection2list(optionsGroup.get(subject.getString("id")), NutMap.class);
|
||||
|
||||
// 获取题目类型
|
||||
String subjectType = subject.getString("type");
|
||||
|
||||
// 处理文本类型题目
|
||||
if ("text".equals(subjectType)) {
|
||||
List<String> texts = answerExtList.stream()
|
||||
.filter(ext -> ObjectUtil.isNull(ext.get(subject.getString("id"), JSONObject.class)))
|
||||
.map(ext -> ext.get(subject.getString("id"), JSONObject.class).getStr("text"))
|
||||
.toList();
|
||||
subject.put("texts", texts);
|
||||
}
|
||||
// 处理单选类型题目 处理多选类型题目
|
||||
else if ("radio".equals(subjectType) || "checkbox".equals(subjectType)) {
|
||||
subjectOptions.forEach(subjectOption -> {
|
||||
long selectCount = answerExtList.stream()
|
||||
.filter(ext ->
|
||||
{
|
||||
JSONObject jsonObject = ext.get(subject.getString("id"), JSONObject.class);
|
||||
return jsonObject != null
|
||||
&& jsonObject.getJSONArray("optionIds") != null
|
||||
&& jsonObject.getJSONArray("optionIds").contains(subjectOption.getString("id"));
|
||||
})
|
||||
.count();
|
||||
subjectOption.put("selectCount", selectCount);
|
||||
});
|
||||
|
||||
long selectTotal = answerExtList.stream()
|
||||
.filter(ext -> ext.containsKey(subject.getString("id")))
|
||||
.count();
|
||||
subject.put("selectTotal", selectTotal);
|
||||
}
|
||||
|
||||
// 添加选项到题目中
|
||||
subject.addv("options", subjectOptions);
|
||||
}
|
||||
|
||||
return subjects;
|
||||
} catch (Exception e) {
|
||||
log.error("报告生成失败", e);
|
||||
throw new RuntimeException("报告生成失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportUserAnswerXlsx(String activityId, HttpServletResponse response) {
|
||||
// 检查活动ID是否为空
|
||||
if (activityId == null || activityId.isEmpty()) {
|
||||
throw new IllegalArgumentException("活动ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询活动信息
|
||||
QsvActivity activity = dao().fetch(QsvActivity.class, activityId);
|
||||
if (activity == null) {
|
||||
throw new IllegalArgumentException("活动不存在");
|
||||
}
|
||||
|
||||
// 查询用户答题记录
|
||||
List<QsvUserAnswerRecord> answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId));
|
||||
// 将答题记录的扩展JSON转换为JSONObject列表
|
||||
List<JSONObject> answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList();
|
||||
|
||||
// 查询活动题目列表
|
||||
List<QsvSubject> subjects = dao().query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
// 将题目列表转换为Map
|
||||
Map<String, QsvSubject> subjectMap = subjects.stream().collect(Collectors.toMap(QsvSubject::getId, v -> v));
|
||||
// 获取题目ID列表
|
||||
List<String> subjectIds = subjects.stream().map(QsvSubject::getId).toList();
|
||||
|
||||
// 查询题目选项列表
|
||||
List<QsvOption> options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum"));
|
||||
// 将选项列表转换为Map
|
||||
Map<String, QsvOption> optionMap = options.stream().collect(Collectors.toMap(QsvOption::getId, v -> v));
|
||||
|
||||
// 构建Excel导出实体
|
||||
List<ExcelExportEntity> excelExportEntities = buildExcelExportEntities(subjects);
|
||||
// 构建答题记录列表
|
||||
List<NutMap> list = buildAnswerRecords(answerRecords, subjectMap, options);
|
||||
|
||||
// 设置导出参数
|
||||
ExportParams exportParams = new ExportParams();
|
||||
exportParams.setType(ExcelType.XSSF);
|
||||
// 导出Excel并下载
|
||||
try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, excelExportEntities, list)) {
|
||||
// CommonDownloadUtil.download(activity.getTitle() + "答题记录" + ".xlsx", workbook, response);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("导出Excel失败", e);
|
||||
throw new RuntimeException("导出Excel失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public NutMap userAnswer(String activityId) {
|
||||
// 检查活动ID是否为空
|
||||
if (activityId == null || activityId.isEmpty()) {
|
||||
throw new IllegalArgumentException("活动ID不能为空");
|
||||
}
|
||||
|
||||
try {
|
||||
// 查询用户答题记录
|
||||
List<QsvUserAnswerRecord> answerRecords = dao().query(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId));
|
||||
// 将答题记录的扩展JSON转换为JSONObject列表
|
||||
List<JSONObject> answerExtList = answerRecords.stream().map(QsvUserAnswerRecord::getExtJson).toList();
|
||||
|
||||
// 查询活动题目列表
|
||||
List<QsvSubject> subjects = dao().query(QsvSubject.class, Cnd.where("activityId", "=", activityId));
|
||||
// 将题目列表转换为Map
|
||||
Map<String, QsvSubject> subjectMap = subjects.stream().collect(Collectors.toMap(QsvSubject::getId, v -> v));
|
||||
// 获取题目ID列表
|
||||
List<String> subjectIds = subjects.stream().map(QsvSubject::getId).toList();
|
||||
|
||||
// 查询题目选项列表
|
||||
List<QsvOption> options = dao().query(QsvOption.class, Cnd.where("subjectId", "in", subjectIds).asc("sortNum"));
|
||||
// 将选项列表转换为Map
|
||||
Map<String, QsvOption> optionMap = options.stream().collect(Collectors.toMap(QsvOption::getId, v -> v));
|
||||
|
||||
// 构建Excel导出实体
|
||||
List<ExcelExportEntity> excelExportEntities = buildExcelExportEntities(subjects);
|
||||
// 构建答题记录列表
|
||||
List<NutMap> list = buildAnswerRecords(answerRecords, subjectMap, options);
|
||||
|
||||
// 构建表格列信息
|
||||
List<NutMap> tableColumns = excelExportEntities.stream()
|
||||
.map(v -> NutMap.NEW().addv("prop", v.getKey()).addv("label", v.getName()))
|
||||
.toList();
|
||||
|
||||
return NutMap.NEW()
|
||||
.addv("tableColumns", tableColumns)
|
||||
.addv("tableData", list);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("获取用户答题记录失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<NutMap> querySubjects(String activityId) {
|
||||
Sql subjectSql = Sqls.create("""
|
||||
SELECT
|
||||
id,
|
||||
title,
|
||||
type,
|
||||
sortNum
|
||||
FROM
|
||||
qsv_subject
|
||||
WHERE
|
||||
activityId = @activityId
|
||||
ORDER BY
|
||||
sortNum ASC
|
||||
""");
|
||||
subjectSql.setParam("activityId", activityId);
|
||||
return listMap(subjectSql);
|
||||
}
|
||||
|
||||
private List<ExcelExportEntity> buildExcelExportEntities(List<QsvSubject> subjects) {
|
||||
List<ExcelExportEntity> excelExportEntities = new ArrayList<>();
|
||||
excelExportEntities.add(new ExcelExportEntity("工号", "loginName", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("姓名", "userName", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("单位", "unitName", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("分工会", "unionName", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("联系方式", "mobile", 20));
|
||||
for (QsvSubject subject : subjects) {
|
||||
excelExportEntities.add(new ExcelExportEntity(subject.getTitle(), subject.getId(), 20));
|
||||
}
|
||||
return excelExportEntities;
|
||||
}
|
||||
|
||||
private List<NutMap> buildAnswerRecords(List<QsvUserAnswerRecord> answerRecords, Map<String, QsvSubject> subjectMap, List<QsvOption> options) {
|
||||
return answerRecords.stream().map(record -> {
|
||||
NutMap map = NutMap.NEW()
|
||||
.addv("id", record.getId())
|
||||
.addv("loginName", record.getLoginName())
|
||||
.addv("userName", record.getUserName())
|
||||
.addv("unitName", record.getUnitName())
|
||||
.addv("unionName", record.getUnionName());
|
||||
JSONObject extJson = record.getExtJson();
|
||||
extJson.forEach((k, v) -> {
|
||||
JSONObject jsonVal = (JSONObject) v;
|
||||
|
||||
String type = subjectMap.get(k).getType();
|
||||
if (type.equals("text")) {
|
||||
map.addv(k, jsonVal.getStr("text"));
|
||||
} else if (type.equals("radio") || type.equals("checkbox")) {
|
||||
JSONArray optionIds = jsonVal.getJSONArray("optionIds");
|
||||
String selectOptionTexts = options.stream().filter(option -> optionIds.contains(option.getId()))
|
||||
.map(QsvOption::getText).collect(Collectors.joining(";"));
|
||||
map.addv(k, selectOptionTexts);
|
||||
}
|
||||
});
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package io.v.nutz.zhgh.qsv.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import io.v.nutz.base.service.impl.BaseServiceImpl;
|
||||
import io.v.nutz.base.utils.Vi;
|
||||
import io.v.nutz.sys.models.User;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvActivity;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvSubject;
|
||||
import io.v.nutz.zhgh.qsv.models.QsvUserAnswerRecord;
|
||||
import io.v.nutz.zhgh.qsv.param.QsvAnswerParam;
|
||||
import io.v.nutz.zhgh.qsv.service.QsvUserAnswerRecordService;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.aop.Aop;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class QsvUserAnswerRecordServiceImpl extends BaseServiceImpl<QsvUserAnswerRecord> implements QsvUserAnswerRecordService {
|
||||
public QsvUserAnswerRecordServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QsvUserAnswerRecord insertRecord(String activityId, List<String> subjectIds) {
|
||||
QsvActivity activity = dao().fetch(QsvActivity.class, activityId);
|
||||
String category = activity.getCategory();
|
||||
String mode = activity.getMode();
|
||||
String displayMode = activity.getDisplayMode();
|
||||
Boolean shuffleSubject = activity.getShuffleSubject();
|
||||
|
||||
//打乱题目顺序
|
||||
if (category.equals("QUIZ") && shuffleSubject) {
|
||||
Collections.shuffle(subjectIds);
|
||||
}
|
||||
|
||||
QsvUserAnswerRecord record = new QsvUserAnswerRecord();
|
||||
record.setActivityId(activityId);
|
||||
record.setUserId(ShiroUtil.getUserId());
|
||||
record.setSubjectIds(subjectIds);
|
||||
|
||||
JSONObject extJson = new JSONObject();
|
||||
for (String subjectId : subjectIds) {
|
||||
extJson.set(subjectId, Dict.create()
|
||||
.set("optionIds", new ArrayList<>())
|
||||
.set("text", null)
|
||||
.set("isCorrect", null)
|
||||
);
|
||||
}
|
||||
record.setExtJson(extJson);
|
||||
|
||||
User user = dao().fetch(User.class, Cnd.where("id", "=", ShiroUtil.getUserId()));
|
||||
record.setLoginName(user.getLoginname());
|
||||
record.setUserName(user.getUsername());
|
||||
record.setUnitId(user.getUnitid());
|
||||
record.setUnitName(user.getUnitname());
|
||||
record.setUnionId(user.getUnionid());
|
||||
record.setUnionName(user.getUnionname());
|
||||
|
||||
//问卷模式
|
||||
if (category.equals("QUIZ")) {
|
||||
if (mode.equals("REGULAR")) {
|
||||
//常规模式 抽取随机题目
|
||||
int count = dao().count(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId()));
|
||||
record.setRandomNumber(count + 1);
|
||||
} else if (mode.equals("SCHEDULED")) {
|
||||
//定时定题模式
|
||||
int count = dao().count(QsvUserAnswerRecord.class, Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", ShiroUtil.getUserId())
|
||||
.and("attemptDate", "=", DateUtil.today()));
|
||||
record.setRandomNumber(count + 1);
|
||||
record.setAttemptDate(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
dao().insert(record);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public float calcScore(QsvAnswerParam qsvAnswerParam) {
|
||||
List<String> subjectIds = qsvAnswerParam.getSubjects().stream().map(QsvAnswerParam.Subject::getId).toList();
|
||||
List<QsvSubject> subjects = dao().query(QsvSubject.class, Cnd.where("id", "in", subjectIds));
|
||||
|
||||
float score = 0;
|
||||
|
||||
for (QsvAnswerParam.Subject subject : qsvAnswerParam.getSubjects()) {
|
||||
List<String> userSelectOptionIds = subject.getUserSelectOptionIds();
|
||||
List<String> correctAnswer = subjects.stream().filter(s -> s.getId().equals(subject.getId())).findFirst().get().getCorrectAnswer();
|
||||
|
||||
String[] array1 = userSelectOptionIds.toArray(new String[0]);
|
||||
String[] array2 = correctAnswer.toArray(new String[0]);
|
||||
Arrays.sort(array1);
|
||||
Arrays.sort(array2);
|
||||
boolean isCorrect = Arrays.equals(array1, array2);
|
||||
|
||||
if (isCorrect) {
|
||||
score += subjects.stream().filter(s -> s.getId().equals(subject.getId())).findFirst().get().getScore();
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public void calcByScoreMode(String activityId, String userId) {
|
||||
// 获取活动信息
|
||||
QsvActivity activity = dao().fetch(QsvActivity.class, activityId);
|
||||
if (activity == null) {
|
||||
throw new RuntimeException("活动找不到" + activityId);
|
||||
}
|
||||
|
||||
String mode = activity.getMode();
|
||||
String scoreMode = activity.getScoreMode();
|
||||
|
||||
if (mode.equals("SCHEDULED")) {
|
||||
processScoreRecords(activityId, ShiroUtil.getUserId(), true, scoreMode.equals("HIGH"));
|
||||
} else if (mode.equals("REGULAR")) {
|
||||
processScoreRecords(activityId, ShiroUtil.getUserId(), false, scoreMode.equals("HIGH"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (mode.equals("SCHEDULED")) {
|
||||
// //定时定题模式
|
||||
// if (scoreStatisticsMode.equals("HIGHEST")) {
|
||||
// //也只能取当天最高的分数
|
||||
// dao().update(QsvUserAnswerRecord.class, Chain.make("isHighestScore", 0), Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).and(QsvUserAnswerRecord::getAttemptDate, "=", DateUtil.today()));
|
||||
// //找出最大的那条
|
||||
// QsvUserAnswerRecord maxScoreRecord = dao().fetch(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).and(QsvUserAnswerRecord::getAttemptDate, "=", DateUtil.today()).desc(QsvUserAnswerRecord::getTotalScore));
|
||||
// if (maxScoreRecord != null) {
|
||||
// maxScoreRecord.setIsHighestScore(true);
|
||||
// dao().update(maxScoreRecord);
|
||||
// }
|
||||
// } else if (scoreStatisticsMode.equals("LAST")) {
|
||||
// //也只能取当天最新的记录
|
||||
// dao().update(QsvUserAnswerRecord.class, Chain.make("isLatestScore", 0), Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).and(QsvUserAnswerRecord::getAttemptDate, "=", DateUtil.today()));
|
||||
// //找出最大的那条
|
||||
// QsvUserAnswerRecord latestScoreRecord = dao().fetch(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).and(QsvUserAnswerRecord::getAttemptDate, "=", DateUtil.today()).desc(QsvUserAnswerRecord::getUpdatedAt));
|
||||
// if (latestScoreRecord != null) {
|
||||
// latestScoreRecord.setIsLatestScore(true);
|
||||
// dao().update(latestScoreRecord);
|
||||
// }
|
||||
// }
|
||||
// } else if (mode.equals("REGULAR")) {
|
||||
// if (scoreStatisticsMode.equals("HIGHEST")) {
|
||||
// dao().update(QsvUserAnswerRecord.class, Chain.make("isHighestScore", 0), Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId));
|
||||
// QsvUserAnswerRecord maxScoreRecord = dao().fetch(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).desc(QsvUserAnswerRecord::getTotalScore));
|
||||
// if (maxScoreRecord != null) {
|
||||
// maxScoreRecord.setIsHighestScore(true);
|
||||
// dao().update(maxScoreRecord);
|
||||
// }
|
||||
// } else if (scoreStatisticsMode.equals("LAST")) {
|
||||
// dao().update(QsvUserAnswerRecord.class, Chain.make("isLatestScore", 0), Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId));
|
||||
// QsvUserAnswerRecord latestScoreRecord = dao().fetch(QsvUserAnswerRecord.class, Cnd.where(QsvUserAnswerRecord::getActivityId, "=", activityId).and(QsvUserAnswerRecord::getUserId, "=", userId).desc(QsvUserAnswerRecord::getUpdatedAt));
|
||||
// if (latestScoreRecord != null) {
|
||||
// latestScoreRecord.setIsLatestScore(true);
|
||||
// dao().update(latestScoreRecord);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param activityId 活动id
|
||||
* @param userId 用户id
|
||||
* @param isScheduled 是否是定时定题模式
|
||||
* @param isHighest 是否是最高分模式
|
||||
*/
|
||||
private void processScoreRecords(String activityId, String userId, boolean isScheduled, boolean isHighest) {
|
||||
String flagField = isHighest ? "isHighestScore" : "isLatestScore";
|
||||
String orderByField = isHighest ? "totalScore" : "updatedAt";
|
||||
|
||||
// 更新所有记录的标志位为0
|
||||
Cnd cnd = Cnd.where("activityId", "=", activityId)
|
||||
.and("userId", "=", userId);
|
||||
if (isScheduled) {
|
||||
cnd.and("attemptDate", "=", DateUtil.today());
|
||||
}
|
||||
|
||||
dao().update(QsvUserAnswerRecord.class, Chain.make(flagField, 0), cnd);
|
||||
|
||||
// 找出符合条件的最大记录
|
||||
Cnd cnd2 = Cnd.where("activityId", "=", activityId).and("userId", "=", userId);
|
||||
if (isScheduled) {
|
||||
cnd2.and("attemptDate", "=", DateUtil.today());
|
||||
}
|
||||
cnd2.desc(orderByField);
|
||||
QsvUserAnswerRecord record = dao().fetch(QsvUserAnswerRecord.class, cnd2);
|
||||
|
||||
if (record != null) {
|
||||
record.setIsHighestScore(isHighest);
|
||||
record.setIsLatestScore(!isHighest);
|
||||
dao().update(record);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
package io.v.nutz.zhgh.question.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import cn.wizzer.framework.page.Pagination;
|
||||
import io.v.nutz.zhgh.activity.models.ActivityUserScope;
|
||||
import io.v.nutz.base.query.PageForm;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import io.v.nutz.zhgh.activity.models.ActivityUserScope;
|
||||
import io.v.nutz.zhgh.question.model.*;
|
||||
import io.v.nutz.zhgh.question.service.QuestionService;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.apache.shiro.authz.annotation.RequiresAuthentication;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -26,9 +24,10 @@ import org.nutz.mvc.annotation.Ok;
|
||||
import org.nutz.mvc.annotation.Param;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -50,6 +49,7 @@ public class QuestionH5Controller {
|
||||
|
||||
@At("/list")
|
||||
@Ok("beetl:/mobile/question/list.html")
|
||||
@RequiresAuthentication
|
||||
public void list() {
|
||||
|
||||
}
|
||||
@@ -74,6 +74,7 @@ public class QuestionH5Controller {
|
||||
|
||||
@At("/answer/index")
|
||||
@Ok("beetl:/mobile/question/answer.html")
|
||||
@RequiresAuthentication
|
||||
public void answerIndex() {
|
||||
|
||||
}
|
||||
@@ -335,8 +336,25 @@ public class QuestionH5Controller {
|
||||
* @return {@link Object}
|
||||
*/
|
||||
@At("/answerInfo/?")
|
||||
public Object answerInfo(String id) {
|
||||
List<Question_reply> replies = questionService.dao().query(Question_reply.class, Cnd.where("qid", "=", id).and("userId", "=", ShiroUtil.getPrincipalProperty("id")));
|
||||
public Object answerInfo(String id,
|
||||
@Param(required = false, value = "currentDate") String currentDate,
|
||||
@Param(required = false, value = "randomCount") Integer randomCount) {
|
||||
Cnd cnd = Cnd.where("qid", "=", id).and("userId", "=", ShiroUtil.getPrincipalProperty("id"));
|
||||
|
||||
Question question = dao.fetch(Question.class, id);
|
||||
if (question.getCtMode() == 1) {
|
||||
cnd.and("DATE(rtime)", "=", currentDate);
|
||||
} else if (question.getCtMode() == 2) {
|
||||
if (questionService.isSameDay(question.getStartTime(), question.getEndTime())) {
|
||||
|
||||
} else {
|
||||
cnd.and("DATE(rtime)", "=", currentDate);
|
||||
}
|
||||
} else if (question.getCtMode() == 3) {
|
||||
|
||||
}
|
||||
|
||||
List<Question_reply> replies = questionService.dao().query(Question_reply.class, cnd);
|
||||
return Result.success(replies);
|
||||
}
|
||||
|
||||
@@ -428,6 +446,11 @@ public class QuestionH5Controller {
|
||||
@Param(required = false, value = "randomCount") Integer randomCount) {
|
||||
Question question = dao.fetch(Question.class, questionId);
|
||||
if (question.getCanRepeatedAnswer()) {
|
||||
//0次则不限制
|
||||
if (question.getCanRepeatedAnswerNum() == 0) {
|
||||
return Result.success(true);
|
||||
}
|
||||
|
||||
if (question.getCtMode() == 3) {
|
||||
int count = dao.count(QuestionUserScore.class, Cnd.where("questionId", "=", questionId).and("userId", "=", ShiroUtil.getUserId()));
|
||||
return Result.success(count < question.getCanRepeatedAnswerNum());
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package io.v.nutz.zhgh.question.service;
|
||||
|
||||
import io.v.nutz.zhgh.question.model.Question;
|
||||
import io.v.nutz.base.service.BaseService;
|
||||
import io.v.nutz.base.service.ViService;
|
||||
import io.v.nutz.zhgh.question.model.Question;
|
||||
import io.v.nutz.zhgh.question.model.Question_reply;
|
||||
import org.nutz.lang.util.NutMap;
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@ package io.v.nutz.zhgh.question.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import io.v.nutz.base.service.impl.ViServiceImpl;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import io.v.nutz.zhgh.question.model.*;
|
||||
import io.v.nutz.zhgh.question.service.QuestionIssueService;
|
||||
import io.v.nutz.zhgh.question.service.QuestionReplyService;
|
||||
import io.v.nutz.zhgh.question.service.QuestionService;
|
||||
import io.v.nutz.zhgh.question.service.QuestionWorService;
|
||||
import io.v.nutz.base.service.impl.ViServiceImpl;
|
||||
import org.nutz.aop.interceptor.ioc.TransAop;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
|
||||
Reference in New Issue
Block a user