commit
This commit is contained in:
@@ -84,8 +84,7 @@ public class MainLauncher {
|
||||
}
|
||||
|
||||
public void init() {
|
||||
Mvcs.X_POWERED_BY = "BudWK-V5 <budwk.com>";
|
||||
|
||||
Mvcs.DISABLE_X_POWERED_BY = true;
|
||||
Globals.AppBase = Mvcs.getServletContext().getContextPath();
|
||||
Globals.AppRoot = Mvcs.getServletContext().getRealPath("/");
|
||||
//注册自定义标签
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.v.nutz.member.controller;
|
||||
|
||||
import cn.wizzer.framework.base.Result;
|
||||
import io.v.nutz.annontation.ViReturn;
|
||||
import io.v.nutz.base.utils.Vi;
|
||||
import io.v.nutz.member.UserMode;
|
||||
import io.v.nutz.member.model.MemberApplyRecord;
|
||||
import io.v.nutz.member.model.MemberChangeRecord;
|
||||
@@ -9,6 +10,7 @@ import io.v.nutz.member.service.MemberService;
|
||||
import io.v.nutz.service.ViService;
|
||||
import io.v.nutz.sys.models.Sys_user;
|
||||
import io.v.nutz.sys.services.SysUserService;
|
||||
import io.v.nutz.web.commons.utils.ShiroUtil;
|
||||
import org.apache.shiro.authz.annotation.RequiresAuthentication;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Sqls;
|
||||
@@ -59,6 +61,9 @@ public class MemberCommonController {
|
||||
@ViReturn
|
||||
@Ok("json:{locked:'password|salt',ignoreNull:false}")
|
||||
public Object userInfo(String userId, String source) {
|
||||
if (!ShiroUtil.hasAnyRoles("sysadmin,A06")){
|
||||
userId= ShiroUtil.getUserId();
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
u.*,unit.`name` unitname,un.unionname,unit.unionid
|
||||
|
||||
@@ -47,7 +47,6 @@ import java.util.List;
|
||||
@At("/platform/member/group/info")
|
||||
@Ok("json:full")
|
||||
@IocBean
|
||||
@RequiresAuthentication
|
||||
public class MemberGroupInfoController {
|
||||
@At("")
|
||||
@Ok("beetl:/platform/member/info/GroupInfo.html")
|
||||
@@ -111,11 +110,13 @@ public class MemberGroupInfoController {
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresPermissions("member.group.person")
|
||||
public Integer getMemberHistoryNum(Integer year) {
|
||||
return memberHistoryService.count(Cnd.where("year", "=", year));
|
||||
}
|
||||
|
||||
@At
|
||||
@RequiresPermissions("member.group.person")
|
||||
public Object archive(Integer year) {
|
||||
try {
|
||||
|
||||
@@ -139,12 +140,14 @@ public class MemberGroupInfoController {
|
||||
|
||||
@At
|
||||
@ViReturn
|
||||
@RequiresPermissions("member.group.person")
|
||||
public Object pageData(PageForm pageForm, String unionId, String unitId, String[] personTypes, String[] userStates, String campus, String sex, Integer memberStatus, String position, String jobTitle) {
|
||||
return memberService.list(pageForm, dataSql(pageForm, unionId, unitId, personTypes, userStates, campus, sex, memberStatus, position, jobTitle));
|
||||
}
|
||||
|
||||
@At
|
||||
@ViReturn
|
||||
@RequiresPermissions("member.group.person")
|
||||
public Object delete(String userId) {
|
||||
UserMode.removeMemberRole(userId);
|
||||
return null;
|
||||
@@ -152,7 +155,7 @@ public class MemberGroupInfoController {
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@RequiresAuthentication
|
||||
@RequiresPermissions("member.group.person")
|
||||
public void export(HttpServletResponse response, String props, PageForm pageForm, String unionId, String unitId, String personTypes, String userStates, String campus, String sex, Integer memberStatus, String position, String jobTitle) throws IOException {
|
||||
ViTool.excelResponse(response, "会员名单.xls");
|
||||
|
||||
|
||||
+3
-2
@@ -45,7 +45,6 @@ import java.util.Map;
|
||||
@At("/platform/member/inquire/integrate")
|
||||
@Ok("json:full")
|
||||
@IocBean
|
||||
@RequiresAuthentication
|
||||
public class MemberInquireIntegrateController {
|
||||
|
||||
@At("")
|
||||
@@ -65,6 +64,7 @@ public class MemberInquireIntegrateController {
|
||||
|
||||
@At
|
||||
@ViReturn
|
||||
@RequiresPermissions("member.inquire.Integrate")
|
||||
public Object pageData(PageForm pageForm, Integer year, String unionId, String unitId, String[] personTypes, String[] userStates, String[] memberStatus, String campus) {
|
||||
int yyyy = Calendar.getInstance().get(Calendar.YEAR);
|
||||
|
||||
@@ -328,6 +328,7 @@ public class MemberInquireIntegrateController {
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@RequiresPermissions("member.inquire.Integrate")
|
||||
public void doExport(HttpServletResponse response, Integer year, String unionId, String unitId, String memberStatus, String personTypes, String userStates) {
|
||||
try {
|
||||
int yyyy = Calendar.getInstance().get(Calendar.YEAR);
|
||||
@@ -385,6 +386,7 @@ public class MemberInquireIntegrateController {
|
||||
|
||||
@At
|
||||
@Ok("void")
|
||||
@RequiresPermissions("member.inquire.Integrate")
|
||||
public void doExportByUnion(HttpServletResponse response, Integer year, String unionId, String unitId, String memberStatus, String personTypes, String userStates, String props) {
|
||||
try {
|
||||
int yyyy = Calendar.getInstance().get(Calendar.YEAR);
|
||||
@@ -465,5 +467,4 @@ public class MemberInquireIntegrateController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.v.nutz.question.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@@ -31,6 +33,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* 问卷H5
|
||||
@@ -286,6 +289,12 @@ public class QuestionH5Controller {
|
||||
//判断是否将题目加进去了
|
||||
|
||||
Sql issueSql = Sqls.create(" SELECT iid FROM `question_issue` $condition");
|
||||
issueSql = Sqls.create("""
|
||||
SELECT iid FROM (
|
||||
SELECT * FROM `question_issue` $condition
|
||||
) AS subquery ORDER BY ipxbh ASC;
|
||||
""");
|
||||
|
||||
Cnd commonIssueCnd = Cnd.NEW();
|
||||
commonIssueCnd.and("iqid", "=", id);
|
||||
|
||||
@@ -305,12 +314,17 @@ public class QuestionH5Controller {
|
||||
QuestionRandomIssue maxQuestionRandomIssue = randomIssues.stream().filter(randomIssue -> randomIssue.getNum() == finalMaxAnswer).findFirst().orElse(null);
|
||||
if (randomIssues.size() < ranDomSum && Lang.isNotEmpty(maxQuestionRandomIssue) && maxQuestionRandomIssue.getIsFinish()) {
|
||||
List<String> allIssueIds = randomIssues.stream().flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
commonIssueCnd.andEX("iid", "not in", allIssueIds);
|
||||
//每次都从20题里面去找
|
||||
// commonIssueCnd.andEX("iid", "not in", allIssueIds);
|
||||
}else{
|
||||
needFor = false;
|
||||
}
|
||||
}
|
||||
|
||||
//固定3题
|
||||
List<String> fixedIssueIds = new java.util.ArrayList<>(List.of("52e2a5c9d54e4a3ab3e60443b1c961aa", "140388aa1a10445bbcd9e6356c28ef2b", "5f04a8e4f43d46378f012a573001bea9","c81599b8bf5e424bba619de39c5860ca","f701af5766244d788513439b9379f3f0"));
|
||||
commonIssueCnd.and("iid","not in",fixedIssueIds);
|
||||
|
||||
if (ObjectUtil.isAllNotEmpty(ranDomSum, ranDomSingleIssueNum)) {
|
||||
commonIssueCnd.and(new Static("1=1 order by rand() limit " + ranDomSingleIssueNum));
|
||||
}
|
||||
@@ -320,48 +334,31 @@ public class QuestionH5Controller {
|
||||
issueSql.setCallback(Sqls.callback.strList());
|
||||
dao.execute(issueSql);
|
||||
List<String> randomIssueIds = (List<String>) issueSql.getResult();
|
||||
Collections.shuffle(randomIssueIds);
|
||||
// Collections.shuffle(randomIssueIds);
|
||||
|
||||
List<String> allIssueIds = Stream.concat(fixedIssueIds.stream(), randomIssueIds.stream()).collect(Collectors.toList());
|
||||
|
||||
QuestionRandomIssue questionRandomIssue = new QuestionRandomIssue();
|
||||
questionRandomIssue.setQuestionId(id);
|
||||
questionRandomIssue.setUserId(ShiroUtil.getUserId());
|
||||
questionRandomIssue.setIssueIds(randomIssueIds);
|
||||
questionRandomIssue.setIssueIds(allIssueIds);
|
||||
questionRandomIssue.setNum(maxAnswer + 1);
|
||||
questionRandomIssue.setIsFinish(false);
|
||||
dao.insert(questionRandomIssue);
|
||||
issueCnd.and("iid", "in", randomIssueIds);
|
||||
if(maxAnswer==0){
|
||||
dao.insert(questionRandomIssue);
|
||||
}
|
||||
issueCnd.and("iid", "in", allIssueIds);
|
||||
}else{
|
||||
// List<String> allIssueIds = randomIssues.stream().flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
int finalMaxAnswer1 = maxAnswer;
|
||||
List<String> allIssueIds = randomIssues.stream().filter(randomIssue -> randomIssue.getNum() == finalMaxAnswer1).flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
issueCnd.and("iid", "in", allIssueIds);
|
||||
}
|
||||
|
||||
// if (Lang.isEmpty(randomIssue)) {
|
||||
//
|
||||
// Sql issueSql = Sqls.create(" SELECT iid FROM `question_issue` where iqid = @qid $randLimit");
|
||||
// issueSql.setParam("qid", id);
|
||||
// if (ranDomSingleIssueNum != null && ranDomSingleIssueNum > 0) {
|
||||
// issueSql.setVar("randLimit", " order by rand() limit " + ranDomSingleIssueNum);
|
||||
// }
|
||||
//
|
||||
// issueSql.setCallback(Sqls.callback.strList());
|
||||
// dao.execute(issueSql);
|
||||
// List<String> randomIssueIds = (List<String>) issueSql.getResult();
|
||||
// Collections.shuffle(randomIssueIds);
|
||||
// QuestionRandomIssue questionRandomIssue = new QuestionRandomIssue();
|
||||
// questionRandomIssue.setQuestionId(id);
|
||||
// questionRandomIssue.setUserId(ShiroUtil.getUserId());
|
||||
// questionRandomIssue.setIssueIds(randomIssueIds);
|
||||
// questionRandomIssue.setNum(null);
|
||||
// questionRandomIssue.setIsFinish(false);
|
||||
// dao.insert(questionRandomIssue);
|
||||
// issueCnd.and("iid", "in", randomIssueIds);
|
||||
// } else {
|
||||
// issueCnd.and("iid", "in", randomIssue.getIssueIds());
|
||||
// }
|
||||
}
|
||||
|
||||
// issueCnd.asc("ipxbh");
|
||||
// issueCnd.and(new Static("1=1 ORDER BY FIELD(iid,'52e2a5c9d54e4a3ab3e60443b1c961aa', '140388aa1a10445bbcd9e6356c28ef2b', '5f04a8e4f43d46378f012a573001bea9', 'c81599b8bf5e424bba619de39c5860ca', 'f701af5766244d788513439b9379f3f0') DESC"));
|
||||
|
||||
issueCnd.desc("ipxbh");
|
||||
questionService.fetchLinks(question, "issues", issueCnd);
|
||||
for (Question_issue issue : question.getIssues()) {
|
||||
questionService.fetchLinks(issue, "wors", Cnd.NEW().asc("wpxbh"));
|
||||
@@ -435,6 +432,80 @@ public class QuestionH5Controller {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
public Result answerAgainCommon(String id){
|
||||
Question question = questionService.fetch(id);
|
||||
Cnd issueCnd = Cnd.NEW();
|
||||
Sql issueSql = Sqls.create(" SELECT iid FROM `question_issue` $condition");
|
||||
issueSql = Sqls.create("""
|
||||
SELECT * FROM (
|
||||
SELECT * FROM `question_issue` $condition
|
||||
) AS subquery ORDER BY ipxbh ASC;
|
||||
""");
|
||||
|
||||
Cnd commonIssueCnd = Cnd.NEW();
|
||||
commonIssueCnd.and("iqid", "=", id);
|
||||
|
||||
//判断是否要随机
|
||||
Integer ranDomSum = question.getRanDomSum();
|
||||
Integer ranDomSingleIssueNum = question.getRanDomSingleIssueNum();
|
||||
|
||||
//已经回答最大次数
|
||||
int maxAnswer = 0;
|
||||
|
||||
boolean needFor = true;
|
||||
|
||||
List<QuestionRandomIssue> randomIssues = dao.query(QuestionRandomIssue.class, Cnd.where("questionId", "=", question.getQid()).and("userId", "=", ShiroUtil.getUserId()));
|
||||
if (Lang.isNotEmpty(randomIssues)) {
|
||||
maxAnswer = randomIssues.stream().mapToInt(QuestionRandomIssue::getNum).max().orElse(0);
|
||||
int finalMaxAnswer = maxAnswer;
|
||||
QuestionRandomIssue maxQuestionRandomIssue = randomIssues.stream().filter(randomIssue -> randomIssue.getNum() == finalMaxAnswer).findFirst().orElse(null);
|
||||
if (randomIssues.size() < ranDomSum && Lang.isNotEmpty(maxQuestionRandomIssue) && maxQuestionRandomIssue.getIsFinish()) {
|
||||
List<String> allIssueIds = randomIssues.stream().flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
//每次都从20题里面去找
|
||||
// commonIssueCnd.andEX("iid", "not in", allIssueIds);
|
||||
}else{
|
||||
needFor = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ObjectUtil.isAllNotEmpty(ranDomSum, ranDomSingleIssueNum)) {
|
||||
commonIssueCnd.and(new Static("1=1 order by rand() limit " + ranDomSingleIssueNum));
|
||||
}
|
||||
|
||||
if(needFor){
|
||||
issueSql.setCondition(commonIssueCnd);
|
||||
issueSql.setCallback(Sqls.callback.strList());
|
||||
dao.execute(issueSql);
|
||||
List<String> randomIssueIds = (List<String>) issueSql.getResult();
|
||||
Collections.shuffle(randomIssueIds);
|
||||
QuestionRandomIssue questionRandomIssue = new QuestionRandomIssue();
|
||||
questionRandomIssue.setQuestionId(id);
|
||||
questionRandomIssue.setUserId(ShiroUtil.getUserId());
|
||||
questionRandomIssue.setIssueIds(randomIssueIds);
|
||||
questionRandomIssue.setNum(maxAnswer + 1);
|
||||
questionRandomIssue.setIsFinish(false);
|
||||
dao.insert(questionRandomIssue);
|
||||
issueCnd.and("iid", "in", randomIssueIds);
|
||||
}else{
|
||||
// List<String> allIssueIds = randomIssues.stream().flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
int finalMaxAnswer1 = maxAnswer;
|
||||
List<String> allIssueIds = randomIssues.stream().filter(randomIssue -> randomIssue.getNum() == finalMaxAnswer1).flatMap(randomIssue -> randomIssue.getIssueIds().stream()).collect(Collectors.toList());
|
||||
issueCnd.and("iid", "in", allIssueIds);
|
||||
}
|
||||
questionService.fetchLinks(question, "issues", issueCnd);
|
||||
for (Question_issue issue : question.getIssues()) {
|
||||
questionService.fetchLinks(issue, "wors", Cnd.NEW().asc("wpxbh"));
|
||||
}
|
||||
|
||||
if (question.getDisruptingOrder()) {
|
||||
Collections.shuffle(question.getIssues());
|
||||
}
|
||||
|
||||
return Result.success(question);
|
||||
}
|
||||
|
||||
|
||||
@At("/winInfo")
|
||||
public Object winInfo(String questionId) {
|
||||
// List<QuestionWinner> winners = dao.query(QuestionWinner.class, Cnd.where("questionId", "=", questionId));
|
||||
@@ -581,12 +652,26 @@ public class QuestionH5Controller {
|
||||
} else if (question.getCtMode() == 3) {
|
||||
QuestionUserScore userScore = dao.fetch(QuestionUserScore.class, Cnd.where("questionId", "=", questionId)
|
||||
.and("userId", "=", ShiroUtil.getUserId())
|
||||
.desc(question.getCalcScoreMode() == 1 ? "score" : "answerNum"));
|
||||
// .desc(question.getCalcScoreMode() == 1 ? "score" : "answerNum"));
|
||||
.desc("answerNum"));
|
||||
return Result.success().addData(Optional.ofNullable(userScore).map(v -> v.getScore()).orElse(0));
|
||||
}
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅限常规模式
|
||||
* @param questionId
|
||||
* @return
|
||||
*/
|
||||
@At
|
||||
@RequiresAuthentication
|
||||
public Result historyScore(String questionId){
|
||||
List<QuestionUserScore> scores = dao.query(QuestionUserScore.class, Cnd.where("questionId", "=", questionId)
|
||||
.and("userId","=",ShiroUtil.getUserId()).asc("answerNum"));
|
||||
return Result.success(scores);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户已回答的轮数 针对单天随机
|
||||
*
|
||||
|
||||
+77
-32
@@ -97,12 +97,44 @@ public class TrainEduStatisticsVideoController {
|
||||
LEFT JOIN `user` u ON u.id = tevwr.userId
|
||||
$condition
|
||||
""");
|
||||
sql = Sqls.create("""
|
||||
SELECT
|
||||
u.username,
|
||||
u.loginname,
|
||||
u.unitname,
|
||||
u.unionname,
|
||||
tev.qualifiedNum,
|
||||
SUM(CASE
|
||||
WHEN sub.cnt > tev.everyDayMaxWatchNum THEN tev.everyDayMaxWatchNum
|
||||
ELSE sub.cnt
|
||||
END) AS watchCount
|
||||
FROM
|
||||
`train_edu_video_watch_record` tevwr
|
||||
LEFT JOIN train_edu_video tev ON tev.id = tevwr.videoId
|
||||
LEFT JOIN train_edu_album tea ON tea.id = tevwr.albumId
|
||||
LEFT JOIN `user` u ON u.id = tevwr.userId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
userId,
|
||||
albumId,
|
||||
watchTime,
|
||||
COUNT(*) AS cnt
|
||||
FROM
|
||||
`train_edu_video_watch_record`
|
||||
WHERE
|
||||
albumId = @albumId
|
||||
GROUP BY
|
||||
userId,
|
||||
watchTime
|
||||
) AS sub ON tevwr.userId = sub.userId AND tevwr.albumId = sub.albumId AND tevwr.watchTime = sub.watchTime
|
||||
$condition
|
||||
""").setParam("albumId", albumId);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("tevwr.albumId", "=", albumId);
|
||||
cnd.and(new Static("IF(tea.createType = 1, u.unionId = tea.unionId , 1=1)"));
|
||||
cnd.and(new Static("tevwr.watchTime >= tev.startDate"));
|
||||
cnd.and(new Static("tevwr.watchTime <= tev.endDate"));
|
||||
cnd.groupBy("tevwr.userId");
|
||||
cnd.groupBy("u.username,u.loginname,u.unitname,u.unionname,tev.qualifiedNum");
|
||||
sql.setCondition(cnd);
|
||||
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
|
||||
return pagination;
|
||||
@@ -152,57 +184,70 @@ public class TrainEduStatisticsVideoController {
|
||||
@At
|
||||
@Ok("void")
|
||||
@RequiresPermissions("trainEdu.statistics.video")
|
||||
public void exportXlsx(String albumId,HttpServletResponse response){
|
||||
public void exportXlsx(String albumId, HttpServletResponse response) {
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
u.username,
|
||||
u.loginname,
|
||||
u.unitname,
|
||||
u.unionname,
|
||||
tev.qualifiedNum,
|
||||
(
|
||||
SELECT
|
||||
SUM(IF( cnt > tev.everyDayMaxWatchNum, tev.everyDayMaxWatchNum, cnt )) AS count
|
||||
FROM
|
||||
( SELECT watchTime, COUNT( 1 ) AS cnt FROM train_edu_video_watch_record where userId = tevwr.userId and albumId = tevwr.albumId GROUP BY watchTime ) AS subquery
|
||||
) as watchCount
|
||||
|
||||
u.username,
|
||||
u.loginname,
|
||||
u.unitname,
|
||||
u.unionname,
|
||||
tev.qualifiedNum,
|
||||
SUM(CASE
|
||||
WHEN sub.cnt > tev.everyDayMaxWatchNum THEN tev.everyDayMaxWatchNum
|
||||
ELSE sub.cnt
|
||||
END) AS watchCount
|
||||
FROM
|
||||
`train_edu_video_watch_record` tevwr
|
||||
LEFT JOIN train_edu_video tev ON tev.id = tevwr.videoId
|
||||
LEFT JOIN train_edu_album tea on tea.id = tevwr.albumId
|
||||
LEFT JOIN `user` u ON u.id = tevwr.userId
|
||||
`train_edu_video_watch_record` tevwr
|
||||
LEFT JOIN train_edu_video tev ON tev.id = tevwr.videoId
|
||||
LEFT JOIN train_edu_album tea ON tea.id = tevwr.albumId
|
||||
LEFT JOIN `user` u ON u.id = tevwr.userId
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
userId,
|
||||
albumId,
|
||||
watchTime,
|
||||
COUNT(*) AS cnt
|
||||
FROM
|
||||
`train_edu_video_watch_record`
|
||||
WHERE
|
||||
albumId = @albumId
|
||||
GROUP BY
|
||||
userId,
|
||||
watchTime
|
||||
) AS sub ON tevwr.userId = sub.userId AND tevwr.albumId = sub.albumId AND tevwr.watchTime = sub.watchTime
|
||||
$condition
|
||||
""");
|
||||
""").setParam("albumId", albumId);
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("tevwr.albumId", "=", albumId);
|
||||
cnd.and(new Static("IF(tea.createType = 1, u.unionId = tea.unionId , 1=1)"));
|
||||
cnd.and(new Static("tevwr.watchTime >= tev.startDate"));
|
||||
cnd.and(new Static("tevwr.watchTime <= tev.endDate"));
|
||||
cnd.groupBy("tevwr.userId");
|
||||
cnd.groupBy("u.username,u.loginname,u.unitname,u.unionname,tev.qualifiedNum");
|
||||
sql.setCondition(cnd);
|
||||
List<NutMap> list = baseService.listMap(sql);
|
||||
|
||||
List<ExcelExportEntity> excelExportEntities = new ArrayList<>();
|
||||
excelExportEntities.add(new ExcelExportEntity("序号","no",10));
|
||||
excelExportEntities.add(new ExcelExportEntity("姓名","username",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("工号","loginname",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("单位","unitname",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("分工会","unionname",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("学习总次数","watchCount",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("是否达标","qualifiedNum",20));
|
||||
excelExportEntities.add(new ExcelExportEntity("序号", "no", 10));
|
||||
excelExportEntities.add(new ExcelExportEntity("姓名", "username", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("工号", "loginname", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("单位", "unitname", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("分工会", "unionname", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("学习总次数", "watchCount", 20));
|
||||
excelExportEntities.add(new ExcelExportEntity("是否达标", "qualified", 20));
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).put("no",i+1);
|
||||
list.get(i).put("qualifiedNum",list.get(i).getInt("qualifiedNum",0)==1?"是":"否");
|
||||
list.get(i).put("no", i + 1);
|
||||
int watchCount = list.get(i).getInt("watchCount", 0);
|
||||
int qualifiedNum = list.get(i).getInt("qualifiedNum", 0);
|
||||
list.get(i).put("qualified", watchCount >= qualifiedNum ? "是" : "否");
|
||||
}
|
||||
|
||||
try{
|
||||
try {
|
||||
ViTool.excelResponse(response, "获奖人员名单.xls");
|
||||
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), excelExportEntities, list);
|
||||
workbook.write(response.getOutputStream());
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,27 +33,29 @@ public class GlobalsSettingProcessor extends AbstractProcessor {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void process(ActionContext ac) throws Throwable {
|
||||
ac.getRequest().setAttribute("AppRoot", Globals.AppRoot);
|
||||
ac.getRequest().setAttribute("AppBase", Globals.AppBase);
|
||||
ac.getRequest().setAttribute("AppName", Globals.AppName);
|
||||
ac.getRequest().setAttribute("AppDomain", Globals.AppDomain);
|
||||
ac.getRequest().setAttribute("AppShrotName", Globals.AppShrotName);
|
||||
ac.getRequest().setAttribute("AppFileDomain", Globals.AppFileDomain);
|
||||
ac.getRequest().setAttribute("config", Globals.MyConfig);
|
||||
ac.getRequest().setAttribute("shiro", ShiroUtil);
|
||||
ac.getRequest().setAttribute("date", dateUtil);
|
||||
ac.getRequest().setAttribute("string", stringUtil);
|
||||
ac.getRequest().setAttribute("BrandActivityName", Globals.BrandActivityName);
|
||||
// 如果url中有语言属性则设置
|
||||
String lang = ac.getRequest().getParameter("lang");
|
||||
if (!Strings.isEmpty(lang)) {
|
||||
Mvcs.setLocalizationKey(lang);
|
||||
} else {
|
||||
// Mvcs.getLocalizationKey() 1.r.56 版本是null,所以要做两次判断, 1.r.57已修复为默认值 Nutz:Fix issue 1072
|
||||
lang = Strings.isBlank(Mvcs.getLocalizationKey()) ? Mvcs.getDefaultLocalizationKey() : Mvcs.getLocalizationKey();
|
||||
}
|
||||
ac.getRequest().setAttribute("lang", lang);
|
||||
doNext(ac);
|
||||
ac.getRequest().setAttribute("AppRoot", Globals.AppRoot);
|
||||
ac.getRequest().setAttribute("AppBase", Globals.AppBase);
|
||||
ac.getRequest().setAttribute("AppName", Globals.AppName);
|
||||
ac.getRequest().setAttribute("AppDomain", Globals.AppDomain);
|
||||
ac.getRequest().setAttribute("AppShrotName", Globals.AppShrotName);
|
||||
ac.getRequest().setAttribute("AppFileDomain", Globals.AppFileDomain);
|
||||
ac.getRequest().setAttribute("config", Globals.MyConfig);
|
||||
ac.getRequest().setAttribute("shiro", ShiroUtil);
|
||||
ac.getRequest().setAttribute("date", dateUtil);
|
||||
ac.getRequest().setAttribute("string", stringUtil);
|
||||
ac.getRequest().setAttribute("BrandActivityName", Globals.BrandActivityName);
|
||||
// 如果url中有语言属性则设置
|
||||
String lang = ac.getRequest().getParameter("lang");
|
||||
if (!Strings.isEmpty(lang)) {
|
||||
Mvcs.setLocalizationKey(lang);
|
||||
} else {
|
||||
// Mvcs.getLocalizationKey() 1.r.56 版本是null,所以要做两次判断, 1.r.57已修复为默认值 Nutz:Fix issue 1072
|
||||
lang = Strings.isBlank(Mvcs.getLocalizationKey()) ? Mvcs.getDefaultLocalizationKey() : Mvcs.getLocalizationKey();
|
||||
}
|
||||
ac.getRequest().setAttribute("lang", lang);
|
||||
doNext(ac);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.v.nutz.web.commons.proc;
|
||||
|
||||
import io.v.nutz.base.result.Result;
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.nutz.integration.shiro.NutShiro;
|
||||
import org.nutz.ioc.IocException;
|
||||
import org.nutz.log.Log;
|
||||
@@ -35,6 +36,12 @@ public class WkFailProcessor extends ViewProcessor {
|
||||
new ForwardView(errorUri).render(ac.getRequest(), ac.getResponse(), Mvcs.getMessage(ac.getRequest(), "system.exception"));
|
||||
}
|
||||
}
|
||||
if(ac.getError() instanceof BadMessageException){
|
||||
NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), Result.error("表单参数错误"));
|
||||
}
|
||||
if(ac.getError() instanceof RuntimeException){
|
||||
NutShiro.rendAjaxResp(ac.getRequest(), ac.getResponse(), Result.error("程序异常"));
|
||||
}
|
||||
super.process(ac);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package io.v.nutz.web.commons.proc;
|
||||
|
||||
import cn.hutool.http.HtmlUtil;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.v.nutz.base.result.Result;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.nutz.integration.shiro.NutShiro;
|
||||
@@ -16,9 +18,11 @@ import org.nutz.mvc.impl.processor.AbstractProcessor;
|
||||
import org.nutz.mvc.view.ForwardView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* SQL XSS拦截
|
||||
@@ -37,6 +41,13 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
|
||||
|
||||
private final static String regxpForImaTagSrcAttrib = "src=\"([^\"]+)\""; // 找出IMG标签的SRC属性
|
||||
|
||||
//合法字段
|
||||
private static final Set<String> ALLOWED_ORDER_FIELDS = new HashSet<>(Arrays.asList(
|
||||
"createdat", "updatedat"
|
||||
));
|
||||
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Override
|
||||
public void init(NutConfig config, ActionInfo ai) throws Throwable {
|
||||
try {
|
||||
@@ -66,64 +77,57 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
|
||||
|
||||
protected boolean checkParams(ActionContext ac) {
|
||||
HttpServletRequest req = ac.getRequest();
|
||||
|
||||
/* String pageOrderName = req.getParameter("pageOrderName");
|
||||
if (pageOrderName != null && ALLOWED_ORDER_FIELDS.contains(pageOrderName.toLowerCase())) {
|
||||
// 如果是预定义的排序字段,直接放行
|
||||
return false;
|
||||
}*/
|
||||
|
||||
|
||||
Iterator<String[]> values = req.getParameterMap().values().iterator();// 获取所有的表单参数
|
||||
Iterator<String[]> values2 = req.getParameterMap().values().iterator();// 因为是游标所以要重新获取
|
||||
boolean isError = false;
|
||||
|
||||
//use remove -|,
|
||||
String regEx_sql = """
|
||||
select|update|and|or|delete|insert|trancate|char|chr|into|substr|ascii|declare|exec|count|master|drop|execute
|
||||
""";
|
||||
String regEx_xss = "script|iframe|img";
|
||||
// XSS过滤
|
||||
String regEx_xss = "script|iframe";
|
||||
//SQL过滤
|
||||
while (values.hasNext()) {
|
||||
String[] valueArray = (String[]) values.next();
|
||||
for (int i = 0; i < valueArray.length; i++) {
|
||||
String value = valueArray[i].toLowerCase();
|
||||
// 不转换为小写,保持原始值进行检查
|
||||
String value = valueArray[i];
|
||||
|
||||
//排除掉base64
|
||||
if (value.startsWith("data:image/png;base64,")) {
|
||||
// URL解码
|
||||
try {
|
||||
value = URLDecoder.decode(value, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error("URL解码失败", e);
|
||||
isError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//分拆关键字
|
||||
String[] inj_stra = StringUtils.split(regEx_sql, "\\|");
|
||||
|
||||
for (int j = 0; j < inj_stra.length; j++) {
|
||||
// 判断如果路径参数值中含有关键字则返回true,并且结束循环
|
||||
// if (value.contains(inj_stra[j] + " ") || value.contains(" " + inj_stra[j] + " ") || value.contains(" " + inj_stra[j])) {
|
||||
// isError = true;
|
||||
// log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL关键字过滤:" + value);
|
||||
// break;
|
||||
// }
|
||||
|
||||
if ("and".equals(inj_stra[j]) || "or".equals(inj_stra[j]) || "into".equals(inj_stra[j])) {
|
||||
if (value.contains(" " + inj_stra[j] + " ")) {
|
||||
isError = true;
|
||||
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL关键字过滤:" + value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (value.contains(" " + inj_stra[j] + " ")
|
||||
|| value.contains(inj_stra[j] + " ")
|
||||
|| value.contains(inj_stra[j] + "/**/")
|
||||
|| value.contains(inj_stra[j] + "/*")
|
||||
|| value.contains("/**/" + inj_stra[j] + "/**/")
|
||||
|| value.contains(inj_stra[j] + "*/")
|
||||
) {
|
||||
isError = true;
|
||||
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL关键字过滤:" + value);
|
||||
break;
|
||||
}
|
||||
// 检查是否是JSON格式
|
||||
if (isValidJson(value)) {
|
||||
// 对JSON内容进行安全检查
|
||||
if (checkJsonContent(value)) {
|
||||
isError = true;
|
||||
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "JSON内容包含危险字符:" + value);
|
||||
break;
|
||||
}
|
||||
// JSON格式验证通过,继续处理下一个参数
|
||||
continue;
|
||||
}
|
||||
if (isError) {
|
||||
|
||||
// 非JSON格式,进行普通的SQL注入检查
|
||||
if (containsSqlInjection(value, false)) {
|
||||
isError = true;
|
||||
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "SQL注入风险:" + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isError) {
|
||||
break;
|
||||
}
|
||||
if (isError) break;
|
||||
}
|
||||
if (!isError) {
|
||||
// XSS漏洞过滤
|
||||
@@ -131,14 +135,6 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
|
||||
String[] valueArray = (String[]) values2.next();
|
||||
for (int i = 0; i < valueArray.length; i++) {
|
||||
String value = valueArray[i].toLowerCase();
|
||||
|
||||
value = HtmlUtil.escape(value);
|
||||
|
||||
if (value.trim().startsWith("<") || value.trim().endsWith(">") ||
|
||||
value.trim().endsWith("/")) {
|
||||
log.debugf("[%-4s]URI=%s %s", req.getMethod(), req.getRequestURI(), "XSS关键字过滤(已被我转义):" + value);
|
||||
}
|
||||
|
||||
// 分拆关键字
|
||||
String[] inj_stra = StringUtils.split(regEx_xss, "|");
|
||||
for (int j = 0; j < inj_stra.length; j++) {
|
||||
@@ -162,4 +158,197 @@ public class XssSqlFilterProcessor extends AbstractProcessor {
|
||||
}
|
||||
return isError;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证是否为有效的JSON
|
||||
*/
|
||||
private boolean isValidJson(String value) {
|
||||
try {
|
||||
objectMapper.readTree(value);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查JSON内容是否包含危险字符
|
||||
*/
|
||||
private boolean checkJsonContent(String jsonStr) {
|
||||
try {
|
||||
JsonNode rootNode = objectMapper.readTree(jsonStr);
|
||||
return checkJsonNode(rootNode, true);
|
||||
} catch (Exception e) {
|
||||
log.error("JSON内容检查失败", e);
|
||||
return true; // 解析失败当作危险处理
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归检查JSON节点
|
||||
*/
|
||||
private boolean checkJsonNode(JsonNode node, boolean isJsonContext) {
|
||||
if (node.isObject()) {
|
||||
Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
|
||||
while (fields.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = fields.next();
|
||||
// JSON对象的键名不需要进行特殊字符检查,因为它们是受控的标识符
|
||||
// 递归检查值
|
||||
if (checkJsonNode(entry.getValue(), true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (node.isArray()) {
|
||||
for (JsonNode element : node) {
|
||||
if (checkJsonNode(element, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (node.isTextual()) {
|
||||
String value = node.asText();
|
||||
// 在JSON上下文中使用更宽松的规则
|
||||
return containsSqlInjection(value, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查是否包含SQL注入风险
|
||||
*
|
||||
* @param value 要检查的值
|
||||
* @param isJsonContext 是否在JSON上下文中
|
||||
*/
|
||||
private boolean containsSqlInjection(String value, boolean isJsonContext) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return false;
|
||||
}
|
||||
// 规范化输入:移除多余的空白字符
|
||||
value = value.replaceAll("\\s+", " ").trim();
|
||||
|
||||
// 检查编码后的特殊字符
|
||||
String decodedValue = value.replaceAll("%20", " ")
|
||||
.replaceAll("%2B", "+")
|
||||
.replaceAll("%2F", "/")
|
||||
.replaceAll("%3D", "=");
|
||||
|
||||
// 检查注释符号和其他危险字符
|
||||
if (decodedValue.contains("--") ||
|
||||
decodedValue.contains("/*") ||
|
||||
decodedValue.contains("*/") ||
|
||||
decodedValue.contains("#") ||
|
||||
Pattern.compile("[;'\"\\\\]").matcher(decodedValue).find()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 如果是UUID格式,直接放行
|
||||
if (value.matches("[a-fA-F0-9]{32}") || value.matches("[a-fA-F0-9-]{36}")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果包含HTML标签,使用更宽松的检查规则
|
||||
if (value.contains("<") && value.contains(">")) {
|
||||
return checkHtmlContent(value);
|
||||
}
|
||||
|
||||
// 添加对常见标识符的检查
|
||||
if (isCommonIdentifier(value) || ALLOWED_ORDER_FIELDS.contains(value.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查注释符号
|
||||
if (value.contains("--") || value.contains("/*") || value.contains("*/")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查危险的特殊字符(针对非JSON数据)
|
||||
if (!isValidJson(value) && containsDangerousChars(value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查SQL关键字,但要避免误判
|
||||
String valueLower = value.toLowerCase();
|
||||
for (String keyword : SQL_KEYWORDS) {
|
||||
// 在JSON上下文中,只有当关键字作为独立单词出现时才判定为危险
|
||||
if (isJsonContext) {
|
||||
if (isStandaloneWord(valueLower, keyword)) {
|
||||
return true;
|
||||
}
|
||||
} else if (valueLower.contains(keyword)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为常见的UUID或标识符格式
|
||||
*/
|
||||
private boolean isCommonIdentifier(String value) {
|
||||
// UUID格式
|
||||
if (value.matches("[a-fA-F0-9]{32}") || value.matches("[a-fA-F0-9-]{36}")) {
|
||||
return true;
|
||||
}
|
||||
// 常见的标识符格式(字母、数字、下划线、中划线)
|
||||
if (value.matches("^[a-zA-Z0-9_-]+$")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检查HTML内容是否包含危险脚本
|
||||
*/
|
||||
private boolean checkHtmlContent(String html) {
|
||||
String lowerHtml = html.toLowerCase();
|
||||
// 只检查真正危险的脚本标签
|
||||
return lowerHtml.contains("<script") ||
|
||||
lowerHtml.contains("javascript:") ||
|
||||
lowerHtml.contains("onerror=") ||
|
||||
lowerHtml.contains("onclick=");
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否包含危险的特殊字符
|
||||
*/
|
||||
private boolean containsDangerousChars(String value) {
|
||||
// 定义真正危险的字符(减少误判)
|
||||
String[] dangerousChars = {
|
||||
"'", // 单引号
|
||||
";", // 分号
|
||||
"\\", // 反斜杠
|
||||
"@@", // 系统变量前缀
|
||||
"0x", // 十六进制前缀
|
||||
"/*", // 注释开始
|
||||
"*/" // 注释结束
|
||||
};
|
||||
|
||||
for (String dangerous : dangerousChars) {
|
||||
if (value.contains(dangerous)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final Set<String> SQL_KEYWORDS = new HashSet<>(Arrays.asList(
|
||||
"select", "update", "delete", "insert", "truncate",
|
||||
"drop", "execute", "exec", "declare", "union",
|
||||
"create", "alter", "database", "table", "varchar",
|
||||
"extractvalue", "concat", "benchmark", "sleep", "delay",
|
||||
"waitfor", "pg_sleep", "information_schema", "sysobjects",
|
||||
"load_file", "outfile", "dumpfile"
|
||||
));
|
||||
|
||||
/**
|
||||
* 检查关键字是否作为独立单词出现
|
||||
*/
|
||||
private boolean isStandaloneWord(String text, String keyword) {
|
||||
String wordBoundary = "\\b" + keyword + "\\b";
|
||||
return Pattern.compile(wordBoundary).matcher(text).find();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
}
|
||||
|
||||
.van-tabs__line {
|
||||
background-color: #1867b0;
|
||||
background-color: #1867b0!important;
|
||||
}
|
||||
|
||||
.font-theme-color {
|
||||
|
||||
@@ -273,6 +273,18 @@ var sublime = function () {
|
||||
},
|
||||
//2022/02/14 zxy pjax跳转自定义页面
|
||||
jumpPagePjax(pageUrl) {
|
||||
// const url = new URL(location.protocol + "//" + location.host + jump_url)
|
||||
// const pathname = url.pathname
|
||||
// headerNavBarVueApp.matchMenu(pathname)
|
||||
// setTimeout(() => {
|
||||
// const a = document.querySelector('a[href="' + pathname + '"][data-pjax]')
|
||||
// if (a) {
|
||||
// a.href = jump_url
|
||||
// a.click()
|
||||
// a.href = pathname
|
||||
// // leftMenuApp.assignmentMenu()
|
||||
// }
|
||||
// }, 0)
|
||||
const index = pageUrl.indexOf("?")
|
||||
const doMainUrl = index > -1 ? pageUrl.substring(0, index) : pageUrl
|
||||
const {protocol, host} = window.location
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
<script src="${base!}/assets/platform/plugins/echarts/macarons.js"></script><!--主题-->
|
||||
<script src="${base!}/assets/platform/plugins/echarts/echarts.js"></script>
|
||||
<script src="${base!}/assets/platform/plugins/echarts/langZH.js"></script>
|
||||
<!-- <script src="https://cdn.staticfile.org/echarts/5.2.2/echarts.js"></script>-->
|
||||
<!-- <script src="https://cdn.staticfile.org/echarts/5.2.2/i18n/langZH.js"></script>-->
|
||||
<!-- <script src="https://cdn.staticfile.org/echarts/5.2.2/echarts.js"></script>-->
|
||||
<!-- <script src="https://cdn.staticfile.org/echarts/5.2.2/i18n/langZH.js"></script>-->
|
||||
|
||||
|
||||
<script src="${base!}/assets/platform/module/mixins/initTableMixins.js?v=1.0.3"></script>
|
||||
@@ -441,7 +441,7 @@
|
||||
secondMenus: {},
|
||||
userDefaultModuleId: null,
|
||||
menuPopover: false,
|
||||
appModuleId:""
|
||||
appModuleId: ""
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -609,13 +609,12 @@
|
||||
const selectEntranceModuleStr = window.sessionStorage.getItem('selectEntranceModule')
|
||||
if (selectEntranceModuleStr) {
|
||||
this.selectEntranceModule = JSON.parse(selectEntranceModuleStr)
|
||||
this.appModuleId = this.selectEntranceModule.id
|
||||
}
|
||||
this.appModuleId=this.selectEntranceModule.id
|
||||
await this.getEntranceModule()
|
||||
await this.getFirstMenus(this.selectEntranceModule.id)
|
||||
await this.getSecondMenus()
|
||||
this.setAttr()
|
||||
|
||||
// let pjax_url = window.sessionStorage.getItem('pjax_url')
|
||||
// pjax_url = pjax_url.replace(window.location.origin, '')
|
||||
// $.pjax({
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
|
||||
<script src="${base!}/assets/platform/js/scannerQrCodeJs.js"></script>
|
||||
|
||||
<script type="text/javascript"
|
||||
src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation"></script>
|
||||
<!-- <script type="text/javascript"-->
|
||||
<!-- src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation"></script>-->
|
||||
|
||||
<script src="https://cdn-go.cn/cdn/vod-js-sdk-v6/latest/vod-js-sdk-v6.js"></script>
|
||||
<link href="https://web.sdk.qcloud.com/player/tcplayer/release/v4.5.2/tcplayer.min.css" rel="stylesheet"/>
|
||||
|
||||
@@ -157,26 +157,30 @@ layout("/mobile/platform.html"){
|
||||
<div class="page-survey" style="touch-action: manipulation;min-height: 100vh;">
|
||||
<div class="survey-container">
|
||||
<!-- v-if="questionData.qlx==2 && (questionData.ctMode==1 || questionData.ctMode==2)"-->
|
||||
<div class="survey-head-top">
|
||||
<template>
|
||||
<div v-if="questionData.qlx==2 && questionData.ctMode==2 && isSameDay && randomCount > 0"
|
||||
class="randomCount"
|
||||
@click="openRandomCount">
|
||||
第<span>{{randomCount}}</span>轮
|
||||
</div>
|
||||
<div v-if="questionData.qlx==2 && (questionData.ctMode==1 || (questionData.ctMode==2 && !isSameDay))"
|
||||
class="randomCount"
|
||||
@click="openRandomCount">
|
||||
<!--定时定题 可切换时间查看以前的题目-->
|
||||
<span>{{currentDate}}</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="survey-head-top" v-if="finishAnswer && ( currentScore || currentScore===0 )">
|
||||
<!-- <template>-->
|
||||
<!-- <div v-if="questionData.qlx==2 && questionData.ctMode==2 && isSameDay && randomCount > 0"-->
|
||||
<!-- class="randomCount"-->
|
||||
<!-- @click="openRandomCount">-->
|
||||
<!-- 第<span>{{randomCount}}</span>轮-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-if="questionData.qlx==2 && (questionData.ctMode==1 || (questionData.ctMode==2 && !isSameDay))"-->
|
||||
<!-- class="randomCount"-->
|
||||
<!-- @click="openRandomCount">-->
|
||||
<!-- <!–定时定题 可切换时间查看以前的题目–>-->
|
||||
<!-- <span>{{currentDate}}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<div class="score" v-if="finishAnswer && ( currentScore || currentScore===0 )">
|
||||
{{questionData.calcScoreMode==1?'今日最高成绩':'得分'}}{{currentScore}}
|
||||
最新得分{{currentScore}}
|
||||
<!-- {{questionData.calcScoreMode==1?'最高成绩':'得分'}}{{currentScore}}-->
|
||||
</div>
|
||||
<div class="timer" v-if="questionData.enableTimer && !finishAnswer">
|
||||
<span>剩余时间:{{remainder}}</span>
|
||||
<div class="" style="margin-left: 5px;color: #1989fa" @click="viewHistoryScore">
|
||||
查看历史得分
|
||||
</div>
|
||||
<!-- <div class="timer" v-if="questionData.enableTimer && !finishAnswer">-->
|
||||
<!-- <span>剩余时间:{{remainder}}</span>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div class="survey-head">
|
||||
<div class="title">
|
||||
@@ -196,8 +200,8 @@ layout("/mobile/platform.html"){
|
||||
{{issue.iisdx?'单选':'多选'}}
|
||||
</van-tag>
|
||||
</template>
|
||||
<!-- <van-tag v-if="issue.fraction" type="primary" size="large">{{issue.fraction}}分-->
|
||||
<!-- </van-tag>-->
|
||||
<van-tag v-if="issue.fraction" type="primary" size="large">{{issue.fraction}}分
|
||||
</van-tag>
|
||||
</div>
|
||||
<h2 class="question-title">
|
||||
<span class="question-seq">
|
||||
@@ -267,6 +271,15 @@ layout("/mobile/platform.html"){
|
||||
close-on-click-action
|
||||
></van-action-sheet>
|
||||
|
||||
<van-action-sheet v-model="historyScorePopup" title="历史得分记录">
|
||||
<van-cell-group style="min-height: 500px">
|
||||
<van-cell v-for="item in historyScores">
|
||||
<div slot="title">第{{item.answerNum}}次</div>
|
||||
<div style="font-weight: bold;color: #000000">{{item.score}}分</div>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
</van-action-sheet>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -310,7 +323,11 @@ layout("/mobile/platform.html"){
|
||||
//答题时间(使用秒)
|
||||
countDownSeconds: 0,
|
||||
//剩余时间
|
||||
remainder: null
|
||||
remainder: null,
|
||||
|
||||
//历史分数
|
||||
historyScores:[],
|
||||
historyScorePopup:false
|
||||
|
||||
}
|
||||
},
|
||||
@@ -362,6 +379,14 @@ layout("/mobile/platform.html"){
|
||||
},
|
||||
|
||||
methods: {
|
||||
viewHistoryScore(){
|
||||
$.get(BASE_URL+"/historyScore",{questionId:this.id}).then(res=>{
|
||||
if(res.code===0){
|
||||
this.historyScores = res.data
|
||||
this.historyScorePopup = true
|
||||
}
|
||||
})
|
||||
},
|
||||
openRandomCount() {
|
||||
this.randomCountSheetShow = true
|
||||
this.randomActions = []
|
||||
@@ -573,7 +598,20 @@ layout("/mobile/platform.html"){
|
||||
|
||||
answerAgain() {
|
||||
if(this.questionData.ctMode===3){
|
||||
location.reload()
|
||||
$.post(BASE_URL+'/answerAgainCommon',{id:this.id}).then(resp=>{
|
||||
if(resp.code===0){
|
||||
this.questionData = resp.data
|
||||
this.finishAnswer = false
|
||||
setTimeout(() => {
|
||||
this.questionData.issues.forEach(issue => {
|
||||
issue.wors.forEach(wor => {
|
||||
this.$refs['checkboxes' + wor.wid][0].toggle(false)
|
||||
})
|
||||
})
|
||||
}, 0)
|
||||
this.checkTimer()
|
||||
}
|
||||
})
|
||||
}else{
|
||||
this.finishAnswer = false
|
||||
setTimeout(() => {
|
||||
@@ -653,7 +691,16 @@ layout("/mobile/platform.html"){
|
||||
} else {
|
||||
this.countDownSeconds = this.countDownSeconds - 1
|
||||
}
|
||||
},
|
||||
|
||||
getHistoryScore(){
|
||||
$.get(BASE_URL+"/historyScore",{questionId:this.id}).then(res=>{
|
||||
if(res.code===0){
|
||||
this.historyScores = res.data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
async created() {
|
||||
if (this.timerInterval) {
|
||||
@@ -666,6 +713,7 @@ layout("/mobile/platform.html"){
|
||||
await this.checkUserFinishAnswer()
|
||||
await this.getScore()
|
||||
await this.checkTimer()
|
||||
this.getHistoryScore()
|
||||
this.mLoading = false
|
||||
}
|
||||
})
|
||||
|
||||
@@ -63,7 +63,7 @@ const onlineAnswer = {
|
||||
<el-col :span="1" v-if="issue.row.fraction">
|
||||
<span>({{issue.row.fraction}}分)</span>
|
||||
</el-col>
|
||||
<el-col :span="23">
|
||||
<el-col :span="23" style="display: flex">
|
||||
<span v-html="issue.row.iname"></span>
|
||||
<span v-if="issue.row.itx===1" size="mini" style="font-weight: bold">
|
||||
({{issue.row.iisdx ? '单选' : '多选'}})
|
||||
@@ -74,7 +74,7 @@ const onlineAnswer = {
|
||||
<div style="color: rgb(160,160,160)" v-html="issue.row.its"
|
||||
v-if="!isNull(issue.row.its)"></div>
|
||||
</el-row>
|
||||
<el-row v-if="issue.row.itx==1">
|
||||
<el-row>
|
||||
<el-row v-for="wor,idx in issue.row.wors">
|
||||
<el-row style="margin-top: 5px" v-if="wor.wimg">
|
||||
<el-image
|
||||
|
||||
@@ -22,8 +22,7 @@ const batchInsert = {
|
||||
<div style="height: 100%;width: 50%;overflow: auto;padding: 20px 10px 10px">
|
||||
<div v-for="(issue,index) in issues" :key="index" style="margin-bottom: 10px">
|
||||
<div style="display: flex">
|
||||
<div>{{index+1}}、</div>
|
||||
<div>{{issue.iname}}</div>
|
||||
<div>{{index+1}}、{{issue.iname}}</div>
|
||||
</div>
|
||||
<div v-if="issue.wors">
|
||||
<el-radio-group v-if="issue.iisdx">
|
||||
|
||||
@@ -539,7 +539,7 @@ layout("/layouts/platform.html"){
|
||||
<div style="color: rgb(160,160,160)" v-html="issue.row.its"
|
||||
v-if="!isNull(issue.row.its)"></div>
|
||||
</el-row>
|
||||
<el-row v-if="issue.row.itx==1">
|
||||
<el-row v-if="issue.row.itx==1 || issue.row.itx==3">
|
||||
<el-row v-for="wor,idx in issue.row.wors">
|
||||
<el-row style="margin-top: 5px" v-if="wor.wimg">
|
||||
<el-image
|
||||
@@ -863,7 +863,7 @@ layout("/layouts/platform.html"){
|
||||
:key="item.x"
|
||||
:label="item.y"
|
||||
:value="item.x"
|
||||
v-for="item in [{x:1,y:'选择题'},{x:2,y:'填空题'}]">
|
||||
v-for="item in [{x:1,y:'选择题'},{x:2,y:'填空题'},{x:3,y:'判断题'}]">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
@@ -928,9 +928,9 @@ layout("/layouts/platform.html"){
|
||||
</el-date-picker>
|
||||
</el-row>
|
||||
|
||||
<template v-if="issueData[currentModifyIssueIndex].itx===1">
|
||||
<template v-if="issueData[currentModifyIssueIndex].itx===1 || issueData[currentModifyIssueIndex].itx===3">
|
||||
<vi-title2 title="选项设置"></vi-title2>
|
||||
<el-row v-if="currentModifyIssue.itx==1">
|
||||
<el-row v-if="currentModifyIssue.itx==1 || currentModifyIssue.itx==3">
|
||||
<el-table :data="issueData[currentModifyIssueIndex].wors" border
|
||||
style="width: 100%;margin-top: 10px;">
|
||||
<el-table-column header-align="center" label="选项文字" property="wtxt">
|
||||
@@ -942,6 +942,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图片" align="center" header-align="center"
|
||||
v-if="currentModifyIssue.itx==1"
|
||||
width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-upload
|
||||
@@ -967,6 +968,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="说明"
|
||||
v-if="currentModifyIssue.itx==1"
|
||||
property="wsm" width="250px">
|
||||
<template slot-scope="scope">
|
||||
<el-input
|
||||
@@ -984,6 +986,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" header-align="center" label="链接"
|
||||
v-if="currentModifyIssue.itx==1"
|
||||
property="wlj" width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-input
|
||||
@@ -1007,6 +1010,7 @@ layout("/layouts/platform.html"){
|
||||
</template>
|
||||
</el-table-column>-->
|
||||
<el-table-column align="center" header-align="center" label="默认选中"
|
||||
v-if="currentModifyIssue.itx==1"
|
||||
property="wismr"
|
||||
width="80px">
|
||||
<template slot-scope="scope">
|
||||
|
||||
@@ -7,7 +7,7 @@ const activity = {
|
||||
<div style="width: 100%">
|
||||
<div style="background-color: #fff; position: relative; margin-bottom: 10px">
|
||||
<div style="display: flex; justify-content: center; align-items: center">
|
||||
<el-image :src="CREATE_PREVIEW_URL(item.cover.id)" alt="" fit="fill"
|
||||
<el-image :src="'/file_server/fileStreamPreview?id='+item.cover.filepath" alt="" fit="fill"
|
||||
style="margin: 3px 14px 0 0; width: 100px; height: 70px; border-radius: 8px">
|
||||
<div slot="error" class="image-slot">
|
||||
<i class="el-icon-picture-outline"></i>
|
||||
|
||||
@@ -39,7 +39,7 @@ const appModule = {
|
||||
created() {
|
||||
this.getEntranceModule()
|
||||
setTimeout(() => {
|
||||
this.id = headerNavBarVueApp.appModuleId
|
||||
}, 100)
|
||||
// this.id = headerNavBarVueApp.appModuleId
|
||||
}, 400)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ const quickEntry = {
|
||||
})*/
|
||||
},
|
||||
menuClick(item) {
|
||||
// location.href=item.url
|
||||
sublime.jumpPagePjax(item.url)
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user