Commit 93a5e2440181cf855badbad49668303a3ff134cf

Authored by ljq
2 parents b292d514 37a1d1c0

Merge remote-tracking branch 'origin/school_control' into school_control

# Conflicts:
#	src/main/java/com/bsth/entity/subject/SubjectUser.java
#	src/main/java/com/bsth/repository/subject/SubjectUserRepository.java
src/main/java/com/bsth/controller/ddexam/DdexamController.java
... ... @@ -23,8 +23,8 @@ public class DdexamController {
23 23  
24 24 //创建账号
25 25 @RequestMapping("initialization")
26   - public Map initializationAll(@RequestParam Integer rs ,@RequestParam Long userName){
27   - return ddexamService.initializationAll(rs,userName);
  26 + public Map initializationAll(@RequestParam String name ,@RequestParam Long userName){
  27 + return ddexamService.initializationAll(name,userName);
28 28 }
29 29 //初始化
30 30 @RequestMapping("initialization2")
... ...
src/main/java/com/bsth/controller/subject/SubjectController.java
... ... @@ -3,15 +3,51 @@ package com.bsth.controller.subject;
3 3 import com.bsth.controller.BaseController;
4 4 import com.bsth.entity.subject.Subject;
5 5 import com.bsth.service.subject.SubjectService;
  6 +import com.bsth.service.subject.SubjectUserService;
  7 +import org.slf4j.Logger;
  8 +import org.slf4j.LoggerFactory;
6 9 import org.springframework.beans.factory.annotation.Autowired;
7 10 import org.springframework.web.bind.annotation.RequestMapping;
  11 +import org.springframework.web.bind.annotation.RequestParam;
8 12 import org.springframework.web.bind.annotation.RestController;
9 13  
  14 +import java.util.HashMap;
  15 +import java.util.List;
  16 +import java.util.Map;
  17 +
10 18 @RestController
11 19 @RequestMapping("subject")
12 20 public class SubjectController extends BaseController<Subject, Integer> {
13 21  
  22 + private static final Logger LOGGER = LoggerFactory.getLogger(SubjectController.class);
  23 +
14 24 @Autowired
15 25 SubjectService subjectService;
16 26  
  27 + @Autowired
  28 + SubjectUserService subjectUserService;
  29 +
  30 + @RequestMapping("/subjectList")
  31 + public List<Subject> subjectList(){
  32 + List<Subject> r=subjectService.subjectAll();
  33 + return r;
  34 + }
  35 +
  36 + @RequestMapping("/selectSubject")
  37 + public Map<String,String> selectSubject(@RequestParam() Map<String, Object> map){
  38 + Map<String,String> result=new HashMap<>();
  39 + try {
  40 + String[] arr=map.get("ids").toString().split(",");
  41 + subjectUserService.selectSubject(arr);
  42 + result.put("result","成功");
  43 + return result;
  44 + } catch (Exception e) {
  45 + LOGGER.error("",e);
  46 + // TODO: handle exception
  47 + result.put("result","失败");
  48 + return result;
  49 + }
  50 + }
  51 +
  52 +
17 53 }
... ...
src/main/java/com/bsth/controller/subject/SubjectUserController.java
... ... @@ -29,6 +29,16 @@ public class SubjectUserController extends BaseController&lt;SubjectUser, Integer&gt;
29 29 public String determine(@RequestParam("id") Integer id){
30 30 return subjectUserService.determine(id);
31 31 }
  32 +
  33 + @RequestMapping("/subjectUserList")
  34 + public List<Map<String,Object>> subjectUserList(@RequestParam Map<String, Object> map){
  35 + return subjectUserService.subjectUserList(map);
  36 + }
  37 +
  38 + @RequestMapping("/subjectUserDetail")
  39 + public List<Map<String,Object>> subjectUserDetail(@RequestParam Map<String, Object> map){
  40 + return subjectUserService.subjectUserDetail(map);
  41 + }
32 42  
33 43  
34 44 }
... ...
src/main/java/com/bsth/entity/subject/Subject.java
... ... @@ -24,6 +24,14 @@ public class Subject {
24 24  
25 25 private String schStatus;
26 26  
  27 + public Integer getId() {
  28 + return id;
  29 + }
  30 +
  31 + public void setId(Integer id) {
  32 + this.id = id;
  33 + }
  34 +
27 35 public String getSubjectText() {
28 36 return subjectText;
29 37 }
... ...
src/main/java/com/bsth/entity/subject/SubjectUser.java
1 1 package com.bsth.entity.subject;
2 2  
3   -import com.bsth.entity.schedule.BEntity;
4   -
5 3 import javax.persistence.*;
6 4 import java.io.Serializable;
7 5 import java.util.Date;
... ... @@ -24,7 +22,6 @@ public class SubjectUser {
24 22 //题库id
25 23 @ManyToOne
26 24 private Subject subjectId;
27   -
28 25  
29 26  
30 27 // 创建人
... ...
src/main/java/com/bsth/entity/sys/SysUser.java
1 1 package com.bsth.entity.sys;
2 2  
  3 +import com.bsth.security.util.SecurityUtils;
3 4 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
  5 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
4 6  
5 7 import javax.persistence.*;
6 8 import java.io.Serializable;
... ... @@ -144,4 +146,16 @@ public class SysUser implements Serializable {
144 146 public void setParentID(String parentID) {
145 147 this.parentID = parentID;
146 148 }
  149 +
  150 + public SysUser(){
  151 + }
  152 + public SysUser(String name,String userName,SysUser loginUser){
  153 + this.createDate=new Date();
  154 + this.enabled=true;
  155 + this.name=name;
  156 + this.password=new BCryptPasswordEncoder(4).encode("123456");
  157 + this.userName=userName;
  158 + this.ksstatus="1"; //状态 表示今日账户已用
  159 + this.parentID=String.valueOf(loginUser.getId());
  160 + }
147 161 }
... ...
src/main/java/com/bsth/repository/subject/SubjectRepository.java
... ... @@ -2,7 +2,13 @@ package com.bsth.repository.subject;
2 2  
3 3 import com.bsth.entity.subject.Subject;
4 4 import com.bsth.repository.BaseRepository;
  5 +import org.springframework.data.jpa.repository.Query;
  6 +
  7 +import java.util.List;
5 8  
6 9 public interface SubjectRepository extends BaseRepository<Subject, Integer> {
  10 +
  11 + @Query(value = "SELECT s FROM Subject s ")
  12 + List<Subject> subjectAll();
7 13  
8 14 }
... ...
src/main/java/com/bsth/repository/subject/SubjectUserRepository.java
... ... @@ -19,4 +19,18 @@ public interface SubjectUserRepository extends BaseRepository&lt;SubjectUser, Integ
19 19 @Modifying
20 20 @Query(value = "update SubjectUser su set su.result =?1,su.updateBy = ?2,su.updateDate = ?3 where su.id =?4")
21 21 int updates(String rq, Integer id, Date updateDate, Integer userId);
  22 +
  23 + @Query(value="select su.user_id,su.rq,su.result,u.name,u.user_name "
  24 + + " from bsth_subject_user su,bsth_c_sys_user u where su.user_id =u.id and su.rq =?1 and su.user_id in ( ?2 ) "
  25 + + " order by su.user_id",nativeQuery=true)
  26 + List<Object[]> searchSubjectUserByUserId(String rq, List<String> userIds);
  27 +
  28 + @Query(value="select su.subject_id,su.rq,su.result,s.subject_text,s.operate_test "
  29 + + " from bsth_subject_user su,bsth_subject s where su.subject_id =s.id and su.rq =?1 and su.user_id = ?2 "
  30 + + " order by su.user_id",nativeQuery=true)
  31 + List<Object[]> searchSubjectUserDetail(String rq, String userId);
  32 +
  33 + @Modifying
  34 + @Query(value = "delete from SubjectUser s where s.rq=?1 and s.userId in ( ?2 )")
  35 + void deleteSubjectUserByUserIds(String date, List<Integer> userIds);
22 36 }
... ...
src/main/java/com/bsth/service/ddexam/DdexamService.java
... ... @@ -8,7 +8,7 @@ import java.util.Map;
8 8  
9 9 public interface DdexamService {
10 10  
11   - public Map initializationAll(Integer rs,Long userName);
  11 + public Map initializationAll(String name,Long userName);
12 12  
13 13 public Map initializationAll2(Long userName);
14 14  
... ...
src/main/java/com/bsth/service/ddexam/impl/DdexamServiceImpl.java
... ... @@ -194,12 +194,12 @@ public class DdexamServiceImpl implements DdexamService {
194 194 //考生人初始化 单线程 测试1:执行中途再次执行是否同步 测试2:
195 195 @Override
196 196 @Transactional //事务
197   - public synchronized Map initializationAll(Integer rs,Long userName) {
  197 + public synchronized Map initializationAll(String name,Long userName) {
198 198 Long start = System.currentTimeMillis();
199 199 Map m = new HashMap<>();
200 200 try { //用户当天分配完直接改状态 无二次分配的可能
  201 + SysUser loginUser=SecurityUtils.getCurrentUser();
201 202 List<SysUser> userList = sysUserRepository.findBySusUserAll(); //已有的用户 不考虑用户角色表 正常情况下创建必分配
202   - Map suerMap = new HashMap();
203 203 for (SysUser s :userList){
204 204 if(Long.parseLong(s.getUserName()) == userName ){
205 205 m.put("code","创建失败 账号重复");
... ... @@ -209,7 +209,8 @@ public class DdexamServiceImpl implements DdexamService {
209 209  
210 210 new Thread() {
211 211 public synchronized void run() {
212   - if(usercreateType(rs,userName)){
  212 + SysUser user = new SysUser(name,String.valueOf(userName),loginUser);
  213 + if(createUser(user)){
213 214 log.info("考试初始化创建成功");
214 215 kk();
215 216 }
... ... @@ -358,83 +359,7 @@ public class DdexamServiceImpl implements DdexamService {
358 359 return true;
359 360 }
360 361  
361   - //创建考试人数 并分配线路信息
362   - public synchronized Boolean usercreateType(int st,Long userName){
363   - int usernum = sysUserRepository.findAll_distinct().size();
364   - SysUser user = new SysUser();//总人数
365   - for (int i = 0; i < st; i++) { //创建考试人数
366   - int username = usernum++;
367   - user = new SysUser();
368   - user.setCreateDate(new Date());
369   - user.setEnabled(true);
370   - user.setName(String.valueOf(userName + i));
371   - user.setPassword(new BCryptPasswordEncoder(4).encode("123456"));
372   - user.setUserName(String.valueOf(userName + i));
373   - user.setKsstatus("1"); //状态 表示今日账户已用
374   - sysUserRepository.save(user); //添加 -------**--
375   -
376   - BsthCSysUserRoles userRoles = new BsthCSysUserRoles();
377   - userRoles.setUsers(user.getId());
378   - userRoles.setRoles(73); //统一用73考生
379   - bsthCSysUserRolesRepository.save(userRoles); //添加 -------**--
380   - List<LineConfigSt> lineConfigList = lineConfigStRepository.findAll(); //线调 线路相关配置信息
381   - Integer linebumber = lineRepository.findAll().size(); //线路数量 线路code
382   - String [] mtline = {"A线","B线","C线","D线","E线","F线"}; //对应模板6条线 换成线路name
383   - List<LineInformationSt> litst = (List<LineInformationSt>) LineInformationStRepository.findAll(); //所有模板线路标准和线路
384   - if(litst.size() != 6){
385   - return false;
386   - }
387   - String lineCodeStr = "";
388   - for(int j = 0 ; j < litst.size() ; j++){ //6个 <6
389   - LineSt linest = litst.get(j).getLine(); //旧line
390   - LineInformationSt Limst = litst.get(j);
391   - Line line = new Line();
392   - BeanUtils.copyProperties(linest,line); //copy
393   - Integer linecodeId = linebumber++ ;
394   - line.setId(linecodeId);
395   - line.setLineCode(linecodeId.toString());
396   - line.setName(mtline[j]+"-"+user.getName());
397   - line.setCoLineCode(linest.getLineCode());
398   - lineRepository.save(line); //线路添加
399   - //----------------线路--------------------------//
400   - LineInformation lifat = new LineInformation(); //线路标准
401   - BeanUtils.copyProperties(Limst,lifat);
402   - lifat.setLine(line);
403   - lineInformationRepository.save(lifat); //线路标准信息条件
404   - //-------------------线路标准-----------------------//
405   - for(LineConfigSt cfgt : lineConfigList){
406   - if(cfgt.getLine().getLineCode().equals(linest.getLineCode())){
407   - LineConfig config = new LineConfig();
408   - BeanUtils.copyProperties(cfgt,config); //copy
409   - config.setLine(line);
410   - lineConfigRepository.save(config);
411   - }
412   - }
413   - //-------------------线调 线路相关配置信息-----------------------//
414   -
415   - List<StationRouteSt> srstList = stationRouteStRepository.findByLine(linest.getLineCode());
416   - List<StationRoute> srstListAll = new ArrayList<>();
417   - for(StationRouteSt route : srstList){
418   - StationRoute srt = new StationRoute();
419   - BeanUtils.copyProperties(route,srt); //copy
420   - srt.setLine(line);
421   - srt.setLineCode(linecodeId.toString());
422   - srstListAll.add(srt);
423   - }
424   - stationRouteRepository.saveAll(srstListAll);//添加站点
425   - //-------------------站点-----------------------//
426   - lineCodeStr += linecodeId.toString()+","; //线调线路
427   - inforealType(line);
428   - }
429   - RealControAuthority raty = new RealControAuthority();
430   - raty.setUserId(user.getId());
431   - raty.setLineCodeStr(lineCodeStr);
432   - raty.setPattern(1); //可用
433   - realControAuthorityRepository.save(raty);
434   - //-------------------分配本次线调权限-----------------------//
435   - }
436   - return true;
437   - }
  362 +
438 363  
439 364 //添加排班
440 365 public void inforealType(Line line){
... ... @@ -495,19 +420,10 @@ public class DdexamServiceImpl implements DdexamService {
495 420 continue;
496 421 textList.add(text + ";");
497 422 }
498   - SysUser loginUser = SecurityUtils.getCurrentUser();
499 423 for(int i = 0; i < textList.size(); i++) {
500 424 String text = textList.get(i);
501 425 String[] split = text.split(",");
502   - SysUser user = new SysUser();
503   - user.setCreateDate(new Date());
504   - user.setEnabled(true);
505   - user.setName(split[1].trim());
506   - user.setPassword(new BCryptPasswordEncoder(4).encode("123456"));
507   - user.setUserName(split[0].trim());
508   - user.setKsstatus("1"); //状态 表示今日账户已用
509   - user.setLastLoginDate(new Date());
510   - user.setParentID(String.valueOf(loginUser.getId()));
  426 + SysUser user = new SysUser(split[1].trim(),split[0].trim(),SecurityUtils.getCurrentUser());
511 427 userList.add(user);
512 428 }
513 429 List<SysUser> users = sysUserRepository.findBySusUserAll();
... ...
src/main/java/com/bsth/service/subject/SubjectService.java
... ... @@ -3,5 +3,9 @@ package com.bsth.service.subject;
3 3 import com.bsth.entity.subject.Subject;
4 4 import com.bsth.service.BaseService;
5 5  
  6 +import java.util.List;
  7 +
6 8 public interface SubjectService extends BaseService<Subject, Integer> {
  9 +
  10 + List<Subject> subjectAll();
7 11 }
... ...
src/main/java/com/bsth/service/subject/SubjectUserService.java
... ... @@ -4,6 +4,7 @@ import com.bsth.entity.subject.SubjectUser;
4 4 import com.bsth.service.BaseService;
5 5  
6 6 import java.util.List;
  7 +import java.util.Map;
7 8  
8 9 public interface SubjectUserService extends BaseService<SubjectUser, Integer> {
9 10  
... ... @@ -11,4 +12,10 @@ public interface SubjectUserService extends BaseService&lt;SubjectUser, Integer&gt; {
11 12 List<SubjectUser> userAll();
12 13  
13 14 String determine(Integer id);
  15 +
  16 + List<Map<String,Object>> subjectUserList(Map<String, Object> map);
  17 +
  18 + List<Map<String,Object>> subjectUserDetail(Map<String, Object> map);
  19 +
  20 + void selectSubject(String[] arr) throws Exception;
14 21 }
... ...
src/main/java/com/bsth/service/subject/impl/SubjectServiceImpl.java
1 1 package com.bsth.service.subject.impl;
2 2  
3 3 import com.bsth.entity.subject.Subject;
  4 +import com.bsth.repository.subject.SubjectRepository;
4 5 import com.bsth.service.impl.BaseServiceImpl;
5 6 import com.bsth.service.subject.SubjectService;
  7 +import org.springframework.beans.factory.annotation.Autowired;
6 8 import org.springframework.stereotype.Service;
7 9  
  10 +import java.util.List;
  11 +
8 12 @Service
9 13 public class SubjectServiceImpl extends BaseServiceImpl<Subject, Integer> implements SubjectService {
  14 +
  15 + @Autowired
  16 + SubjectRepository subjectRepository;
  17 +
  18 + @Override
  19 + public List<Subject> subjectAll() {
  20 + return subjectRepository.subjectAll();
  21 + }
  22 +
10 23 }
... ...
src/main/java/com/bsth/service/subject/impl/SubjectUserServiceImpl.java
... ... @@ -3,31 +3,41 @@ package com.bsth.service.subject.impl;
3 3 import com.bsth.data.schedule.DayOfSchedule;
4 4 import com.bsth.entity.Line;
5 5 import com.bsth.entity.realcontrol.ScheduleRealInfo;
  6 +import com.bsth.entity.subject.Subject;
6 7 import com.bsth.entity.subject.SubjectUser;
7 8 import com.bsth.entity.sys.SysUser;
8 9 import com.bsth.repository.LineRepository;
9 10 import com.bsth.repository.subject.SubjectUserRepository;
  11 +import com.bsth.repository.sys.SysUserRepository;
10 12 import com.bsth.security.util.SecurityUtils;
11   -import com.bsth.service.impl.BaseServiceImpl;
  13 +import com.bsth.service.impl.BaseServiceImpl;
12 14 import com.bsth.service.subject.SubjectUserService;
13 15 import com.bsth.util.subject.subEnum;
  16 +import org.slf4j.Logger;
  17 +import org.slf4j.LoggerFactory;
14 18 import org.springframework.beans.factory.annotation.Autowired;
15 19 import org.springframework.stereotype.Service;
  20 +import org.springframework.transaction.annotation.Transactional;
16 21  
17 22 import java.text.SimpleDateFormat;
  23 +import java.time.LocalDate;
  24 +import java.time.format.DateTimeFormatter;
18 25 import java.util.*;
19 26 import java.util.stream.Collectors;
20 27  
21 28 @Service
22 29 public class SubjectUserServiceImpl extends BaseServiceImpl<SubjectUser, Integer> implements SubjectUserService {
23 30 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
24   -
  31 +
  32 + private static final Logger LOGGER = LoggerFactory.getLogger(SubjectUserServiceImpl.class);
25 33 @Autowired
26 34 SubjectUserRepository subjectUserRepository;
27 35 @Autowired
28 36 LineRepository lineRepository;
29 37 @Autowired
30 38 DayOfSchedule dayOfSchedule;
  39 + @Autowired
  40 + SysUserRepository sysUserRepository;
31 41  
32 42 public List<SubjectUser> userAll(){
33 43 SysUser user = SecurityUtils.getCurrentUser();
... ... @@ -86,7 +96,135 @@ public class SubjectUserServiceImpl extends BaseServiceImpl&lt;SubjectUser, Integer
86 96 }
87 97  
88 98  
89   -
90   -
91   -
  99 + @Override
  100 + public List<Map<String, Object>> subjectUserList(Map<String, Object> map) {
  101 + List<Map<String,Object>> results=new ArrayList<>();
  102 + String date=map.get("date").toString();
  103 + String userName=map.get("userName").toString();
  104 + try {
  105 + List<String> users=new ArrayList<>();
  106 + if(userName.equals("")){
  107 + SysUser loginUser = SecurityUtils.getCurrentUser();
  108 + List<SysUser> userList=sysUserRepository.findByParentID(String.valueOf(loginUser.getId()));;//根据教师id查询所属学生id
  109 + for (SysUser user : userList) {
  110 + users.add(String.valueOf(user.getId()));
  111 + }
  112 + }else {
  113 + SysUser user=sysUserRepository.findByUserName(userName);
  114 + users.add(String.valueOf(user.getId()));
  115 + }
  116 + List<Map<String,Object>> subjectUserList=new ArrayList<>();
  117 + List<Object[]> objects = subjectUserRepository.searchSubjectUserByUserId(date,users);
  118 + int len = objects.size();
  119 + if(len>0) {
  120 + for(int i = 0 ; i < len; i++) {
  121 + Map<String, Object> tempM = new HashMap<String,Object>();
  122 + tempM.put("userId", objects.get(i)[0]);
  123 + tempM.put("rq", objects.get(i)[1]);
  124 + tempM.put("result", objects.get(i)[2]);
  125 + tempM.put("name", objects.get(i)[3]);
  126 + tempM.put("userName", objects.get(i)[4]);
  127 + subjectUserList.add(tempM);
  128 + }
  129 + }
  130 + Map<String,List<Map<String,Object>>>m=subjectUserList.stream().collect(Collectors.groupingBy(group->group.get("userId").toString()));
  131 + m.forEach((k,v)->{
  132 + Map<String,Object> result=new HashMap<>();
  133 + int sum=0;
  134 + int t=0;
  135 + int f=0;
  136 + int na=0;
  137 + for (Map<String,Object> su : v) {
  138 + sum++;
  139 + if(su.get("result")==null||"".equals(su.get("result"))){
  140 + na++;
  141 + }
  142 + else if("0".equals(su.get("result").toString())){
  143 + t++;
  144 + }else if("1".equals(su.get("result").toString())){
  145 + f++;
  146 + }
  147 + }
  148 + if(v.size()>0){
  149 + Map<String,Object> su=v.get(0);
  150 + result.put("userId",su.get("userId"));
  151 + result.put("rq",su.get("rq"));
  152 + result.put("name",su.get("name"));
  153 + result.put("userName",su.get("name"));
  154 + result.put("sum",sum);
  155 + result.put("t",t);
  156 + result.put("f",f);
  157 + result.put("na",na);
  158 + results.add(result);
  159 + }
  160 + });
  161 +
  162 + } catch (Exception e) {
  163 + LOGGER.error("",e);
  164 + // TODO: handle exception
  165 + }
  166 + return results;
  167 + }
  168 +
  169 +
  170 + @Override
  171 + public List<Map<String, Object>> subjectUserDetail(Map<String, Object> map) {
  172 + List<Map<String,Object>> results=new ArrayList<>();
  173 + String date=map.get("rq").toString();
  174 + String userId=map.get("userId").toString();
  175 + try {
  176 + List<Object[]> objects = subjectUserRepository.searchSubjectUserDetail(date,userId);
  177 + int len = objects.size();
  178 + if(len>0) {
  179 + for(int i = 0 ; i < len; i++) {
  180 + Map<String, Object> tempM = new HashMap<String,Object>();
  181 + tempM.put("subjectId", objects.get(i)[0]);
  182 + tempM.put("rq", objects.get(i)[1]);
  183 + String result = null;
  184 + if (objects.get(i)[2]==null||"".equals(objects.get(i)[2])){
  185 + result="未答";
  186 + }else if ("0".equals(objects.get(i)[2])){
  187 + result="正确";
  188 + }else if ("1".equals(objects.get(i)[2])){
  189 + result="错误";
  190 + }
  191 + tempM.put("result",result);
  192 + tempM.put("subjectText", objects.get(i)[3]);
  193 + tempM.put("operateTest", objects.get(i)[4]);
  194 + results.add(tempM);
  195 + }
  196 + }
  197 + } catch (Exception e) {
  198 + LOGGER.error("",e);
  199 + // TODO: handle exception
  200 + }
  201 + return results;
  202 + }
  203 +
  204 + @Override
  205 + @Transactional
  206 + public void selectSubject(String[] arr) throws Exception{
  207 + SysUser loginUser = SecurityUtils.getCurrentUser();
  208 + List<SysUser> userList= sysUserRepository.findByParentID(String.valueOf(loginUser.getId()));
  209 + DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
  210 + LocalDate localDate=LocalDate.now();
  211 + String rq=localDate.format(dateTimeFormatter);
  212 + List<Integer> userIds=new ArrayList<>();
  213 + for (SysUser user : userList) {
  214 + userIds.add(user.getId());
  215 + }
  216 + subjectUserRepository.deleteSubjectUserByUserIds(rq,userIds);
  217 + for (SysUser user : userList) {
  218 + for (String s : arr) {
  219 + SubjectUser subjectUser=new SubjectUser();
  220 + subjectUser.setUserId(user.getId());
  221 + subjectUser.setRq(rq);
  222 + subjectUser.setCreateBy(loginUser.getId());
  223 + Subject subject=new Subject();
  224 + subject.setId(Integer.parseInt(s));
  225 + subjectUser.setSubjectId(subject);
  226 + subjectUserRepository.save(subjectUser);
  227 + }
  228 + }
  229 + }
92 230 }
... ...
src/main/resources/static/assets/css/MSFmultiSelect.css 0 → 100644
  1 +.msf_multiselect_container .msf_multiselect {
  2 + border: 1px solid #e4e4e4;
  3 + list-style-type:none;
  4 + margin: 0;
  5 + padding: 0;
  6 + position: absolute;
  7 + z-index: 240;
  8 +}
  9 +.msf_multiselect li:hover, .sb_multiselect li:active, .sb_multiselect li:focus{
  10 + background-color: #e5e5e5;
  11 +}
  12 +.msf_multiselect li.active{
  13 + background-color: #e5e5e5;
  14 +}
  15 +.msf_multiselect li{
  16 + padding-left: 4px;
  17 + background-color: #ffffff;
  18 + cursor: pointer;
  19 +}
  20 +.msf_multiselect_container textarea{
  21 + resize: none;
  22 + padding-left: 2px;
  23 + padding-top: 2px;
  24 + overflow: auto;
  25 +}
  26 +.msf_multiselect_container .msf_multiselect{
  27 + height: 200px;
  28 + overflow: auto;
  29 + background-color: white;
  30 + display: grid;
  31 + text-align: left;
  32 +}
  33 +.msf_multiselect label{
  34 + display: block;
  35 + margin-bottom: 1px;
  36 +}
... ...
src/main/resources/static/assets/js/MSFmultiSelect.js 0 → 100644
  1 +/* MSFmultiSelect v1.00
  2 + * Developed by Jagadeesan S
  3 + * jagadeesanjd11@gamil.coms
  4 + * https://minisuperfiles.blogspot.com
  5 + */
  6 +class MSFmultiSelect{
  7 + constructor(select, settings={}) {
  8 + this.select = select;
  9 + this.settings = settings;
  10 + this.defultSettings={
  11 + width:350,
  12 + height:30,
  13 + appendTo:'body',
  14 + className:''
  15 + }
  16 + this.select.multiple=true;
  17 + this.select.style.display='none';
  18 + this.create();
  19 + }
  20 + create(){
  21 + var div=document.createElement('DIV');
  22 + div.className='msf_multiselect_container';
  23 + this.id='msf_multiselect_'+(document.querySelectorAll('.msf_multiselect_container').length+1);
  24 + div.id=this.id;
  25 + var ul=document.createElement('UL');
  26 + ul.className='msf_multiselect';
  27 + var textarea=document.createElement('textarea'); textarea.readOnly=true;
  28 + textarea.style.height=(this.settings.height) ? this.settings.height+'px' : this.defultSettings.height+'px';
  29 + textarea.style.width=(this.settings.width) ? this.settings.width+'px' : this.defultSettings.width+'px';
  30 + textarea.className=(this.settings.className) ? this.settings.className : this.defultSettings.className;
  31 + var self=this,display="";
  32 + if(this.settings.selectAll){
  33 + var label=document.createElement('label');
  34 + var li=document.createElement('LI');
  35 + var input=document.createElement('input');
  36 + input.type='checkbox';
  37 + input.disabled=(this.settings.readOnly) ? true: false;
  38 + input.addEventListener('click',function(){
  39 + this.parentElement.className=(this.checked) ? 'active' : '';
  40 + self.selectAll(this.checked);
  41 + });
  42 + var caption=document.createTextNode('<Select all>');
  43 + li.appendChild(input);
  44 + li.appendChild(caption);
  45 + label.appendChild(li);
  46 + ul.appendChild(label);
  47 + }
  48 + for(var i=0,len=this.select.children.length; i<len; i++){
  49 + var label=document.createElement('label');
  50 + var li=document.createElement('LI');
  51 + var input=document.createElement('input');
  52 + input.type='checkbox';
  53 + input.disabled=(this.settings.readOnly) ? true: false;
  54 + input.value=this.select.children[i].value;
  55 + var caption=document.createTextNode(this.select.children[i].innerText);
  56 + input.addEventListener('click',function(){
  57 + if(this.checked){
  58 + self.setValue([this.value]);
  59 + }else{
  60 + self.removeValue([this.value]);
  61 + }
  62 + if(typeof self.settings.onChange=='function'){
  63 + self.settings.onChange(this.checked,this.value,self);
  64 + }
  65 + });
  66 + li.appendChild(input);
  67 + li.appendChild(caption);
  68 + if(this.select.children[i].selected){
  69 + li.className='active';
  70 + input.checked=true;
  71 + display+=(display) ? ", "+this.select.children[i].innerText : this.select.children[i].innerText;
  72 + }else{
  73 + li.className='';
  74 + input.checked=false;
  75 + }
  76 + label.appendChild(li);
  77 + ul.appendChild(label);
  78 + }
  79 + textarea.value=display;
  80 + this.logger=textarea;
  81 + div.appendChild(textarea);
  82 + var addTarget;
  83 + if(this.settings.appendTo){
  84 + addTarget=document.querySelector(this.settings.appendTo);
  85 + }else{
  86 + addTarget=document.querySelector(this.defultSettings.appendTo);
  87 + }
  88 + //set width
  89 + ul.style.width=(this.settings.width) ? this.settings.width+2+'px' : this.defultSettings.width+2+'px';
  90 + ul.style.display='none';
  91 + div.appendChild(ul);
  92 + this.list=ul;
  93 + this.container=div;
  94 + addTarget.appendChild(div);
  95 + // add event
  96 + document.addEventListener('click',function(event){
  97 + var isClickInside=self.container.contains(event.target);
  98 + if(!isClickInside){
  99 + self.list.style.display='none';
  100 + }
  101 + });
  102 + this.logger.addEventListener('click',function(){
  103 + if(self.list.style.display=='none'){
  104 + self.list.style.display='';
  105 + }else{
  106 + self.list.style.display='none';
  107 + }
  108 + });
  109 + }
  110 + setValue(selected=[]){
  111 + if(selected.length){
  112 + for(var i=0; i<this.select.children.length; i++){
  113 + for(var j=0; j<selected.length; j++){
  114 + if(this.select.children[i].value==selected[j]){
  115 + this.select.children[i].selected=true;
  116 + var sync=(this.settings.selectAll) ? (i+1) : i;
  117 + this.list.children[sync].children[0].children[0].checked=true;
  118 + this.list.children[sync].children[0].className='active'; //need to change;
  119 + break;
  120 + }
  121 + }
  122 + }
  123 + this.log();
  124 + }
  125 + }
  126 + removeValue(selected=[]){
  127 + if(selected.length){
  128 + for(var i=0; i<this.select.children.length; i++){
  129 + for(var j=0; j<selected.length; j++){
  130 + if(this.select.children[i].value==selected[j]){
  131 + this.select.children[i].selected=false;
  132 + var sync=(this.settings.selectAll) ? (i+1) : i;
  133 + this.list.children[sync].children[0].children[0].checked=false;
  134 + this.list.children[sync].children[0].className=''; //need to change;
  135 + break;
  136 + }
  137 + }
  138 + }
  139 + this.log();
  140 + }
  141 + }
  142 + log(){
  143 + var display="";
  144 + for(var i=0; i<this.select.children.length; i++){
  145 + if(this.select.children[i].selected){
  146 + display+=(display) ? ", "+this.select.children[i].innerText : this.select.children[i].innerText;
  147 + }
  148 + }
  149 + this.logger.value=display;
  150 + }
  151 + getData(){
  152 + var data=[];
  153 + for(var i=0; i<this.select.children.length; i++){
  154 + if(this.select.children[i].selected){
  155 + data.push(this.select.children[i].value);
  156 + }
  157 + }
  158 + return data;
  159 + }
  160 + selectAll(is=false){
  161 + var data=[];
  162 + for(var i=0; i<this.select.children.length; i++){
  163 + data.push(this.select.children[i].value);
  164 + }
  165 + if(is){
  166 + this.setValue(data);
  167 + }else{
  168 + this.removeValue(data);
  169 + }
  170 + }
  171 + loadSource(data=[]){
  172 + if(data.length!=0){
  173 + this.select.innerHTML='';
  174 + for(var i=0; i<data.length; i++){
  175 + var option=document.createElement('OPTION');
  176 + option.value=data[i].value;
  177 + option.innerHTML=data[i].caption;
  178 + option.selected=data[i].selected;
  179 + this.select.appendChild(option);
  180 + }
  181 + this.reload();
  182 + }
  183 + }
  184 + getSource(){
  185 + var data=[];
  186 + for(var i=0; i<this.select.children.length; i++){
  187 + data.push({value:this.select.children[i].value,caption:this.select.children[i].innerText,selected:this.select.children[i].selected});
  188 + }
  189 + return data;
  190 + }
  191 + reload(){
  192 + this.container.remove();
  193 + this.create();
  194 + }
  195 +}
  196 +
... ...
src/main/resources/static/index.html
... ... @@ -85,7 +85,8 @@
85 85 <link
86 86 href="/metronic_v4.5.4/plugins/tipso/css/tipso.css"
87 87 rel="stylesheet" type="text/css" />
88   -
  88 + <link href="/assets/css/MSFmultiSelect.css" rel="stylesheet" type="text/css" />
  89 + <script src="/assets/js/MSFmultiSelect.js"></script>
89 90 <style type="text/css">
90 91 .searchForm {
91 92  
... ...
src/main/resources/static/pages/ddexam/index.html
... ... @@ -55,14 +55,14 @@
55 55 <div class="tes">
56 56 <label class="col-md-12 sizell">请输入学号:</label>
57 57 <div class="col-md-9 scm">
58   - <input id="userName" type="text" class="form-control" name="rnumber" autocomplete="off" oninput="value=value.replace(/[^\d]/g,'')"/>
  58 + <input id="userName" type="text" class="form-control" name="userName" autocomplete="off" oninput="value=value.replace(/[^\d]/g,'')"/>
59 59  
60 60 </div>
61 61  
62   - <label class="col-md-12 sizell">请输入考试人数:</label>
  62 + <label class="col-md-12 sizell">请输入姓名:</label>
63 63 <div class="col-md-9 scm">
64 64  
65   - <input id="rnumber" type="text" class="form-control" name="rnumber" autocomplete="off" oninput="value=value.replace(/[^\d]/g,'')"/>
  65 + <input id="name" type="text" class="form-control" name="name" autocomplete="off" />
66 66 <h6>人数过大时,耗时较久,请耐心等待</h6>
67 67 </div>
68 68  
... ... @@ -140,13 +140,9 @@
140 140  
141 141  
142 142 function onckil(){
143   - if($("#rnumber").val() == undefined || $("#rnumber").val() == null || $("#rnumber").val() == "" || $("#rnumber").val() > 100){
144   - layer.msg('考试人数未输入或人数过大,请正确输入...');
145   - return
146   - }
147 143 var params ={
148 144 userName : $("#userName").val(),
149   - rs : $("#rnumber").val()
  145 + name : $("#name").val()
150 146 }
151 147 var i = layer.load(2);
152 148 $.post('/ddexam/initialization',params,function(data) {
... ...
src/main/resources/static/pages/subjectUser/selectSubject.html 0 → 100644
  1 +<style type="text/css">
  2 + .table-bordered {
  3 + border: 1px solid; }
  4 + .table-bordered > thead > tr > th,
  5 + .table-bordered > thead > tr > td,
  6 + .table-bordered > tbody > tr > th,
  7 + .table-bordered > tbody > tr > td,
  8 + .table-bordered > tfoot > tr > th,
  9 + .table-bordered > tfoot > tr > td {
  10 + border: 1px solid; }
  11 + .table-bordered > thead > tr > th,
  12 + .table-bordered > thead > tr > td {
  13 + border-bottom-width: 2px; }
  14 +
  15 + .table > tbody + tbody {
  16 + border-top: 1px solid; }
  17 +</style>
  18 +<div class="page-head">
  19 + <div class="page-title">
  20 + <h1>考题选择</h1>
  21 + </div>
  22 +</div>
  23 +<body>
  24 +
  25 +</body>
  26 +<div class="row">
  27 + <div class="col-md-12">
  28 + <div class="portlet light porttlet-fit bordered">
  29 + <div class="portlet-title">
  30 + <form class="form-inline" action="">
  31 + <div style="display: inline-block;">
  32 + <span class="item-label" style="width: 80px;margin-left: 6px;">选题: </span>
  33 + <div id="myselect">
  34 + <select id="multiselect" style="width: 350px;" class="form-control" name="countries[]" multiple="multiple">
  35 + </select>
  36 + </div>
  37 + </div>
  38 + <div class="form-group">
  39 + <input class="btn btn-default" type="button" onclick="selectSubject()" value="提交" style="margin-left: 2px;margin-top: -24px;"/>
  40 + </div>
  41 + </form>
  42 + </div>
  43 + <div class="portlet-body">
  44 + <div class="table-container" style="margin-top: 10px;overflow:auto;min-width: 906px">
  45 + <form role="form">
  46 + <div class="form-group">
  47 + <span class="item-label" style="width: 80px;margin-left: 6px;">题目: </span>
  48 + <textarea class="form-control" rows="12" id="subjectText"></textarea>
  49 + </div>
  50 + </form>
  51 + <form role="form">
  52 + <div class="form-group">
  53 + <span class="item-label" style="width: 80px;margin-left: 6px;">操作: </span>
  54 + <textarea class="form-control" rows="12" id="operateTest"></textarea>
  55 + </div>
  56 + </form>
  57 + </div>
  58 + </div>
  59 + </div>
  60 + </div>
  61 +</div>
  62 +<script>
  63 + var select=new MSFmultiSelect(
  64 + document.querySelector('#multiselect'),
  65 + {
  66 + onChange:function(checked,value,instance){
  67 + var subjectTextStr='';
  68 + var operateTestStr='';
  69 + var arr=select.getData();
  70 + for (let i of arr) {
  71 + let index=1;
  72 + for (let s of subjectList) {
  73 + if(s.id==i){
  74 + subjectTextStr+='题'+index+':'+s.subjectText+'\n';
  75 + operateTestStr+='题'+index+':'+s.operateTest+'\n';
  76 + }
  77 + index++;
  78 + }
  79 + }
  80 + $("#subjectText").val(subjectTextStr);
  81 + $("#operateTest").val(operateTestStr);
  82 + },
  83 + appendTo:'#myselect',
  84 + }
  85 + );
  86 + var subjectList;
  87 + $(function(){
  88 + $get('/subject/subjectList',{type:'query'},function(result){
  89 + subjectList=result;
  90 + var datas=[];
  91 + let i=1;
  92 + for (let r of result) {
  93 + var d=new Object();
  94 + d.value=r.id;
  95 + d.caption="题"+i;
  96 + datas[i-1]=d;
  97 + i++;
  98 + }
  99 + select.loadSource(datas);
  100 + });
  101 + });
  102 + function selectSubject(){
  103 + var arr=select.getData();
  104 + if(arr.length!=10){
  105 + layer.alert("请选择10道题");
  106 + return;
  107 + }
  108 + layer.confirm('提交后会覆盖当天选题是否确认', {
  109 + btn: ['确认', '取消'],isOutAnim: false,//可以无限个按钮
  110 + }, function(index, layero){
  111 + layer.close(index)
  112 + var ids='';
  113 + for (let id of arr) {
  114 + ids+=id+',';
  115 + }
  116 + $get('/subject/selectSubject',{ids:ids},function(result){
  117 + layer.alert(result.result);
  118 + });
  119 + });
  120 + }
  121 +</script>
  122 +
  123 +
  124 +
  125 +
  126 +
... ...
src/main/resources/static/pages/subjectUser/subjectUserDetailList.html 0 → 100644
  1 +<style type="text/css">
  2 + .table-bordered {
  3 + border: 1px solid; }
  4 + .table-bordered > thead > tr > th,
  5 + .table-bordered > thead > tr > td,
  6 + .table-bordered > tbody > tr > th,
  7 + .table-bordered > tbody > tr > td,
  8 + .table-bordered > tfoot > tr > th,
  9 + .table-bordered > tfoot > tr > td {
  10 + border: 1px solid; }
  11 + .table-bordered > thead > tr > th,
  12 + .table-bordered > thead > tr > td {
  13 + border-bottom-width: 2px; }
  14 +
  15 + .table > tbody + tbody {
  16 + border-top: 1px solid; }
  17 +</style>
  18 +
  19 +<div class="row" id="subjectUserDetailList">
  20 + <div class="col-md-12">
  21 + <div class="portlet light porttlet-fit bordered">
  22 + <div class="portlet-body">
  23 + <div class="table-container" style="margin-top: 10px;overflow:auto;min-width: 600px">
  24 + <table class="table table-bordered table-hover table-checkable" id="forms_2">
  25 + <thead>
  26 + <tr>
  27 + <td style="min-width: 40px">题号</td>
  28 + <td style="min-width: 100px">日期</td>
  29 + <td style="min-width: 150px">题目</td>
  30 + <td style="min-width: 150px">操作</td>
  31 + <td style="min-width: 150px">结果</td>
  32 + <td style="min-width: 50px">成绩</td>
  33 + </tr>
  34 + </thead>
  35 + <tbody>
  36 + </tbody>
  37 + </table>
  38 + </div>
  39 + </div>
  40 + </div>
  41 + </div>
  42 +</div>
  43 +<script>
  44 + $(function(){
  45 + // 关闭左侧栏
  46 + if (!$('body').hasClass('page-sidebar-closed'))
  47 + $('.menu-toggler.sidebar-toggler').click();
  48 + var userId="";
  49 + var rq="";
  50 + $("#subjectUserDetailList").on('init', function (e, id) {
  51 + console.log(id);
  52 + userId=id.split(",")[0];
  53 + rq = id.split(",")[1];
  54 + $("#remark").html(id.split(",")[2] + "<br/>" + id.split(",")[3]);
  55 + var i = layer.load(2);
  56 + $get('/subjectUser/subjectUserDetail',{userId:userId,rq:rq,status:"detail",type:'query'},function(result){
  57 + layer.close(i);
  58 + var subjectUserDetailList_2 = template('subjectUserDetailList_2',{list:result});
  59 + $('#forms_2 tbody').html(subjectUserDetailList_2);
  60 + });
  61 + })
  62 + });
  63 +</script>
  64 +<script type="text/html" id="subjectUserDetailList_2">
  65 + {{each list as obj i}}
  66 + <tr >
  67 + <td>{{obj.subjectId}}</td>
  68 + <td>{{obj.rq}}</td>
  69 + <td>{{obj.subjectText}}</td>
  70 + <td>{{obj.operateTest}}</td>
  71 + <td>{{obj.operateTest}}</td>
  72 + <td>{{obj.result}}</td>
  73 + </tr>
  74 + {{/each}}
  75 + {{if list.length == 0}}
  76 + <tr>
  77 + <td colspan="10"><h6 class="muted">没有找到相关数据</h6></td>
  78 + </tr>
  79 + {{/if}}
  80 +</script>
0 81 \ No newline at end of file
... ...
src/main/resources/static/pages/subjectUser/subjectUserList.html 0 → 100644
  1 +<style type="text/css">
  2 + .table-bordered {
  3 + border: 1px solid; }
  4 + .table-bordered > thead > tr > th,
  5 + .table-bordered > thead > tr > td,
  6 + .table-bordered > tbody > tr > th,
  7 + .table-bordered > tbody > tr > td,
  8 + .table-bordered > tfoot > tr > th,
  9 + .table-bordered > tfoot > tr > td {
  10 + border: 1px solid; }
  11 + .table-bordered > thead > tr > th,
  12 + .table-bordered > thead > tr > td {
  13 + border-bottom-width: 2px; }
  14 +
  15 + .table > tbody + tbody {
  16 + border-top: 1px solid; }
  17 +</style>
  18 +
  19 +<div class="page-head">
  20 + <div class="page-title">
  21 + <h1>成绩查询</h1>
  22 + </div>
  23 +</div>
  24 +
  25 +<div class="row">
  26 + <div class="col-md-12">
  27 + <div class="portlet light porttlet-fit bordered">
  28 + <div class="portlet-title">
  29 + <form class="form-inline" action="">
  30 + <div style="display: inline-block;">
  31 + <span class="item-label" style="width: 80px;margin-left: 6px;">开始时间: </span>
  32 + <input class="form-control" type="text" id="date" style="width: 160px;"/>
  33 + </div>
  34 + <div style="display: inline-block;margin-left: 15px;">
  35 + <span class="item-label" style="width: 80px;">学号: </span>
  36 + <input class="form-control" name="userName" id="userName" style="width: 180px;">
  37 + </div>
  38 + <div class="form-group">
  39 + <input class="btn btn-default" type="button" id="query" value="查询" style="margin-left: 2px;"/>
  40 + </div>
  41 + </form>
  42 + </div>
  43 +
  44 + <div class="portlet-body">
  45 + <div class="table-container" style="margin-top: 10px;overflow:auto;min-width: 906px">
  46 + <table class="table table-bordered table-hover table-checkable" id="forms">
  47 + <thead>
  48 + <tr>
  49 + <td>序号</td>
  50 + <td>学号</td>
  51 + <td>姓名</td>
  52 + <td>日期</td>
  53 + <td>总题数</td>
  54 + <td>正确</td>
  55 + <td>错误</td>
  56 + <td>未答</td>
  57 + <td>查看</td>
  58 + </tr>
  59 + </thead>
  60 + <tbody>
  61 + </tbody>
  62 + </table>
  63 + </div>
  64 + </div>
  65 + </div>
  66 + </div>
  67 +</div>
  68 +<script src="/pages/mforms/singledatas/jquery.table2excel.min.js"></script>
  69 +<script>
  70 + $(function(){
  71 + // 关闭左侧栏
  72 + if (!$('body').hasClass('page-sidebar-closed'))
  73 + $('.menu-toggler.sidebar-toggler').click();
  74 +
  75 + var d = new Date();
  76 + d.setTime(d.getTime());
  77 + var year = d.getFullYear();
  78 + var month = d.getMonth() + 1;
  79 + var day = d.getDate();
  80 + if(month < 10)
  81 + month = "0"+month;
  82 + if(day < 10)
  83 + day = "0"+day;
  84 + var dateTime = year + "-" + month + "-" + day;
  85 + $("#date").datetimepicker({
  86 + format : 'YYYY-MM-DD',
  87 + locale : 'zh-cn',
  88 + maxDate : dateTime
  89 + });
  90 + $("#date").val(dateTime);
  91 + //查询
  92 + $("#query").on('click',function(){
  93 + var date = $("#date").val();
  94 + var userName = $("#userName").val();
  95 + $get('/subjectUser/subjectUserList',{date:date,userName:userName,type:'query'},function(result){
  96 + var subjectUserList = template('subjectUserList',{list:result});
  97 + $('#forms tbody').html(subjectUserList);
  98 + $('.btn-subjectUserList').on('click', openSubjectUserList);
  99 + });
  100 + });
  101 +
  102 + function openSubjectUserList(){
  103 + var id = $(this).data('id');
  104 + id += ","+$(this).data('rq');
  105 + $.get('/pages/subjectUser/subjectUserDetailList.html', function (content) {
  106 + layer.open({
  107 + type: 1,
  108 + area: ['1300px', '600px'],
  109 + content: content,
  110 + title: '考生答题详细',
  111 + shift: 5,
  112 + scrollbar: false,
  113 + success: function () {
  114 + $('#subjectUserDetailList').trigger('init', id);
  115 + }
  116 + });
  117 + });
  118 + }
  119 + });
  120 +</script>
  121 +<script type="text/html" id="subjectUserList">
  122 + {{each list as obj i}}
  123 + <tr>
  124 + <td>{{i+1}}</td>
  125 + <td>{{obj.userName}}</td>
  126 + <td>{{obj.name}}</td>
  127 + <td>{{obj.rq}}</td>
  128 + <td>{{obj.sum}}</td>``
  129 + <td>{{obj.t}}</td>
  130 + <td>{{obj.f}}</td>
  131 + <td>{{obj.na}}</td>
  132 + <td>
  133 + <button type="button" class="btn btn-sm blue btn-subjectUserList"
  134 + data-id="{{obj.userId}}" data-rq="{{obj.rq}}">查看</button>
  135 + </td>
  136 + </tr>
  137 + {{/each}}
  138 + {{if list.length == 0}}
  139 + <tr>
  140 + <td colspan="13"><h6 class="muted">没有找到相关数据</h6></td>
  141 + </tr>
  142 + {{/if}}
  143 +</script>
  144 +
  145 +
  146 +
... ...