1
0
Quellcode durchsuchen

Squashed commit of the following:

commit d8c7d1ef588b08b739cebd55b49d46c406a298c5
Author: luoshi <luoshi@qmth.com.cn>
Date:   Wed Dec 29 17:41:43 2021 +0800

    补充SubjectiveScore查询结果的排序,保持与ExamQuestion相同逻辑

commit aa2c7bab7973540557848e4361a975bb0fbe9ef7
Author: luoshi <luoshi@qmth.com.cn>
Date:   Wed Dec 29 16:57:05 2021 +0800

    ExamQuestionService内部查询方法统一增加自定义排序;MarkService修改直接访问ExamQuestionDao的模式,切换到ExamQuestionService的统一入口

commit c5df53870ac3f25ceb448554de553ca602695c26
Author: luoshi <luoshi@qmth.com.cn>
Date:   Sun Nov 28 20:29:30 2021 +0800

    还原考生删除的逻辑,去掉已上传禁止删除的限制

commit 289600edcf52ec3892ab4d70a437fd02b735cf5b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Nov 27 17:27:08 2021 +0800

    update

commit cd5e1e293fcb20aea1e14eec5bfd5d8fce82f7ec
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Nov 27 17:08:49 2021 +0800

    开放接口新增试卷接口增加分数小数点2位验证;页面分数精度格式化

commit b3f08fac25f86dff3cf17b18508a0665f5291112
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Nov 27 16:20:14 2021 +0800

    限制导入试题时题目分数必须为小数点后2位以内,大于2位提示

commit 85ebfb068dcc8a9f4a59b4101427f7733021d597
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Nov 27 15:40:20 2021 +0800

    修复因精度问题引起的成绩分析问题;评卷员管理优化没有选中分组就隐藏“绑定评卷员”功能

commit 8638555281f0a687ad49c88e035f88994260c439
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Nov 27 14:16:06 2021 +0800

    精度改为共10位,小数点后3位;已上传考生不允许删除;

commit e949da76570c34da148779f050a95555f8942330
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Nov 26 18:06:44 2021 +0800

    fix bugs

commit 3471962c3953fda34f310388a866b61d5da0f585
Author: luoshi <luoshi@qmth.com.cn>
Date:   Fri Nov 26 17:14:16 2021 +0800

    补充修改遗漏的JPQL精度问题

commit c68e15b013c8f810b459ce1fc2cac4405e21653b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Nov 26 15:26:07 2021 +0800

    修复选做题设置后科目总分合分不正确;
    修复成绩复核多选做在选做题分组下多题目查询失败问题;
    修复精度问题;

commit 654cda73bcedd225b970aaf74500f7f187b2f562
Author: luoshi <luoshi@qmth.com.cn>
Date:   Fri Nov 26 14:24:49 2021 +0800

    修改多个double数值连加的高精度处理方案

commit 7eee8845ea4936a2accbe4b56c2b6ba8a0f1b41a
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Nov 26 11:19:46 2021 +0800

    考生客观题统分精度丢失问题;科目计算题目总分精度丢失问题;

commit 8a32bec0d90d64462a169b998a32eab203b55639
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Nov 25 19:44:39 2021 +0800

    修复问题卷提交未清除给分明细问题;客观题统分精度丢失问题;

commit d79ef895e6968e0e5c6f5d15f475ad7ce52ee279
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Nov 25 17:58:49 2021 +0800

    分组管理,科组长屏蔽新增和修改功能;成绩导出新增科目总分为0和有主观题但未设置评卷分组的验证

commit 505f548165e520c86387956bfa4738488b9ae016
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Nov 25 13:38:40 2021 +0800

    update

commit ecb54dac10400aa110040ea799344dcd61409c92
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Nov 24 17:51:23 2021 +0800

    修复导入评卷分组时试评数量为空时空指针,试评数量为空时默认导入试评数量是0

commit 0d56fbd7a6b4a5e421a3047ad74c36e8669265f9
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 23 15:00:53 2021 +0800

    导入主观题模板必填加*

commit e45dc8333d04ffeb6b79ad403321234c6df86ddc
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Nov 19 09:24:40 2021 +0800

    update

commit 84fa50094e965404387e97ca0685cb2dc87a3582
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Nov 17 16:19:10 2021 +0800

    根据华科检查客观题小工具修改部分接口

commit e9be01da1252dc9aeedca586dcee79f3f17f4093
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 9 14:50:03 2021 +0800

    update

commit b1c5d61e6f0578d8282efd47edf59fb6d4cf542c
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 9 13:48:01 2021 +0800

    新增授权和华师隐藏密号

commit cc25d917b44d41d48d7887d5418ab9d2209b69af
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Nov 5 16:56:05 2021 +0800

    update

commit 6b15fcc8d8748d777d79120d3b8f6302d97ea1a4
Merge: 88d0e12d ec1cb409
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Nov 3 14:22:25 2021 +0800

    Merge branch 'dev_1.3.3' into dev_1.3.4

commit 88d0e12df9df3de91487dc3206b1cbf777d2df55
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Nov 3 11:22:22 2021 +0800

    付xugs

commit ec1cb4092a91dde74d2ab32667b4475e99f91671
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Nov 3 09:24:38 2021 +0800

    update

commit 29968b2d55136de5433aba0db94fe479a87e38c0
Merge: fbc9d0c5 2ab5361b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 17:57:46 2021 +0800

    Merge remote-tracking branch 'origin/release_1.3.3' into dev_1.3.4

commit 2ab5361b433145774cc74cbcc957706cd3f92fd7
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 16:48:47 2021 +0800

    修复试评对未选做的处理

commit 46f2a952f328e544a39f756deaa9314d7173c23a
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 15:24:58 2021 +0800

    fix bugs

commit d6f3aa2f144702711f9a1ed71aff1d5aef81aad6
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 11:42:10 2021 +0800

    update

commit fbc9d0c527a472b1688f1f64a0805343df138e60
Merge: d4f64e10 f7debbad
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 11:09:32 2021 +0800

    Merge branch 'dev_1.3.3' into dev_1.3.4

    Conflicts:
    	stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java

commit f7debbad1c8c58559064d9c72eb4ae3356cac877
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 11:06:24 2021 +0800

    fix bugs

commit d4f64e10b242a6ff46d6ceaf5906d99561a38788
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 11:05:45 2021 +0800

    fix bugs

commit dff6712059ae4d9b568f01b4264ab989e7f32401
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 10:51:13 2021 +0800

    update

commit e87462aae021ec5468bf00e6975014ba01a03e00
Merge: 929fa644 a1099f3b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 10:21:41 2021 +0800

    Merge branch 'dev_1.3.3' into dev_1.3.4

commit a1099f3b61f05c67d8cf7a681f5f38c175a653f2
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 10:20:12 2021 +0800

    update

commit 929fa644dc58b53e98eda67cc84f1f3837572194
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 09:14:50 2021 +0800

    新增api

commit 5ac33d04b1f9d401e7b9a83f3a5ed5e8f658c9fc
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Nov 2 09:12:55 2021 +0800

    修复ip问题,新增多选做条件

commit 5ee2b64b3feafb215edba6140f213bb330d4682f
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Oct 29 10:24:19 2021 +0800

    管理端在禁止其他人查看考生信息,即除管理员外其它人在考生准考证号、姓名、学号时用全显示***号

commit 1b6a33aa30c006c9e1373b6762bbc29bbe309f05
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Oct 28 17:20:33 2021 +0800

    fixbugs

commit d9df49f3f16e10bd4046afbe2dcda823eadab3de
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Oct 28 15:23:39 2021 +0800

    update

commit 961b324b9fa555dcf1d6d71fbd71c2b0fd8d2f2f
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Oct 26 15:41:06 2021 +0800

    恢复考试详情

commit aaf2af2a6ce979d079623744a51bbea0af7d07da
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Oct 25 17:38:34 2021 +0800

    更新回看复核无法打回问题

commit 0c98404f1a77f40e80479253b3c98b044091c521
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Oct 25 16:04:42 2021 +0800

    fix bugs

commit ea8eca28ec86a7dc0a8da7d03142a2938f8f6961
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Oct 25 10:34:08 2021 +0800

    fixbugs

commit 5fc2d5b1b2a8542d373341e2107bae018b18637e
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Oct 22 10:15:35 2021 +0800

    update

commit 3af4ef6c8fe81ac0e624b5240b794e3a254d0b05
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Oct 21 15:32:17 2021 +0800

    update

commit 7d0f32bd1b5d014c4b396816e71440bfd2413e64
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Oct 21 11:06:29 2021 +0800

    研究生补充需求

commit 05511d450c1d2f21944db5de0f9647e264aed531
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Oct 13 17:40:33 2021 +0800

    修复提示消息消失问题

commit 1ce1909efd8bd3ea3e6283cfacc2a27eb5e6920c
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Oct 9 14:05:47 2021 +0800

    修复科目管理导出功能(排序问题)

commit 3d81e0b11f75c16f1fb56ca2fd6916a633bd4610
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Sep 18 15:15:29 2021 +0800

    修复试评回评

commit cf4869004defb5ccf52d52d96ea7a077c000d00b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Sat Sep 18 09:53:39 2021 +0800

    fixbugs

commit c39eda87c96b94484e5ae4527e8c19a224b1f6d7
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Sep 16 14:49:29 2021 +0800

    fixbugs

commit 897b7ad6b7685a837a5c983a876d8137561faa2b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Sep 16 10:04:55 2021 +0800

    修复大题分计算问题

commit 3b0b46cb674177a4e9b77a6652d737eb95d4dee0
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 18:01:27 2021 +0800

    修复试评数量问题

commit 05cf42733d5f2022b514af6d9c27d045703987bb
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 16:40:10 2021 +0800

    fix bugs

commit 3216920c3105a6d3ddfa1cc8669bbe6dae38b676
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 15:24:19 2021 +0800

    fix bugs

commit 68158ccdfb1933a8e09c4132836baf510982d734
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 13:44:51 2021 +0800

    fixbugs

commit 0cd25e7d6778ca57a4942ad1b014480e8244cc81
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 10:22:03 2021 +0800

    update

commit 27ea7c0429e1d4d214378d8b21466e377a4c97f3
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 10:18:18 2021 +0800

    新增绑定班级的评卷员显示的总数量为该班级总数量

commit 0dc2edd316a37ce5c86fccd2a0306f655e6b07e4
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 15 09:36:17 2021 +0800

    fixbugs

commit fbcf9ca7f558e64c5acb86559ac4345539abbdc1
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Sep 14 16:32:38 2021 +0800

    新增试评任务查看,修复切换试评到正评,分组管理取消重置

commit 411d66d61efa7aafe21c64d04ffc6c7806b1a6b1
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Sep 14 11:20:04 2021 +0800

    update

commit 61fdb04cf4d28bb5014aaf3057388df0497cd284
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Sep 13 17:59:40 2021 +0800

    修复成绩分析选做题,新增同一个选做题大题被分开的验证

commit 2e8cf87bb7135473e15fc46fb95799d36fbc827e
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Sep 13 13:52:01 2021 +0800

    update

commit d4745eb2009fdae2d236e3efa71a4c14b6e649ee
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Sep 13 13:45:35 2021 +0800

    修复导入复核问题

commit 781259051ba0b5e4c7a9ed48842235a37054bfb3
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Sep 10 17:30:13 2021 +0800

    fix bugs

commit 2ae51659dcb8af1a49d0e065760387e6516a2223
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Sep 9 11:43:12 2021 +0800

    修复客观题排序问题

commit d2c52b9a6e6d6c1413ed4eed205626d6e107e27b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Sep 9 10:14:31 2021 +0800

    新增删除题目验证,修复前端markerTime名称问题

commit 96e18cad4da521fa5a98683b3b609015d8563c79
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Sep 8 10:08:20 2021 +0800

    fix bugs

commit a14c269f7fd0820fc132bf9715a18e66a63620fd
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Sep 7 18:01:47 2021 +0800

    修复选做题设置时总分计算问题

commit a4e9f5c6880950c1c58f9b25e8f71c3de4f73c12
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Sep 7 14:54:34 2021 +0800

    更新统分问题,新增选做题一大题一组验证,任务查询未选做问题

commit 3f9e39a4b8254f3be4169760d5ca7a7e1daa44cb
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Sep 7 10:42:46 2021 +0800

    fix bugs

commit d77d0028131d5d03e4a560fd500aecacba64c09d
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Sep 2 09:57:00 2021 +0800

    新增清空选做题分组设计,修复打回到待评池

commit f6051affc4619f948caa84664ec45920c5b99c26
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Aug 30 17:22:51 2021 +0800

    fixbugs

commit 9c19ba7c3c50e5f2c8c6508cc49bd7eac72c4d89
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Aug 26 18:19:48 2021 +0800

    新增复核查询扩展功能

commit d9dbf730bd8a25fa8bdbd88fe52194316525e615
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Aug 26 13:58:21 2021 +0800

    fixbugs

commit f6a83804536e7fb758cfb5fc569244a1d7a074e6
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Aug 26 11:39:51 2021 +0800

    fixbugs

commit 9996d1f06e9f5ad8332192da54c58d2e5a0c25ca
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Aug 25 14:35:47 2021 +0800

    update

commit 94edaf54e26d110d56873e767ed3953d736fd597
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Aug 19 20:18:53 2021 +0800

    问题卷新增提出评卷员属性,fixbug

commit 8fbf04914f714b557a8a35d3187990b44a20a7db
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Aug 19 10:26:16 2021 +0800

    新增选做题和试评

commit 6f8b8ababd5fb70c33e12ab7a629529b8f015dab
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Aug 10 09:56:22 2021 +0800

    修复接口取客观题成绩,接口新增考点属性,其他bug修复

commit 5c1485804ebd32ecb3fae2e68a375d44c227951e
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Aug 9 16:08:39 2021 +0800

    新增多图片服务器配置

commit 5d86979de88d7d925085a5e4a3b4d5674a4f9c48
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jul 28 11:39:34 2021 +0800

    fixbugs

commit f6db0cb8bd0283690a9094918c6365c7fae77393
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Jul 27 20:32:30 2021 +0800

    fixbugs

commit 7592d354a6057001a6d362ba6967ee75ff276386
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Jul 27 15:56:27 2021 +0800

    fix bugs

commit 06532e41bd7c8dd602b2588b89e76393a0346ac5
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Jul 26 14:41:21 2021 +0800

    fixbugs

commit d7d4d1a00a873b4abba65b29f279e6c7f2bcf49b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jul 22 16:52:20 2021 +0800

    打回改为不打回到本人,打回到任务池;问题卷改为重置

commit 744602ff6225dd9488e94ecc0bcdeb0ad0c5ae3e
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jul 22 15:20:28 2021 +0800

    新增文件上传,所有文件上传后返回对应url

commit 7f3e307e0efb6c95c3822f4ac46bf627b4f49501
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jul 21 11:19:47 2021 +0800

    fixbugs

commit 536000c4005f399f13ffce0ac042f3c0024a4369
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Jul 19 15:59:11 2021 +0800

    fixbugs

commit f84d4710f4036ad5cbcebf297fe4ebbc51f1544c
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Jul 19 14:43:47 2021 +0800

    机考同步时判断题按true为A,false为B

commit ec4c03724af187753d8957869c139d382cb0360b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Jul 19 11:33:38 2021 +0800

    修改机考上传试卷逻辑,客观题全量更新,主观题无分组更新

commit 53295bbcc943d4f3126be2582b8efb2f952c3308
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Jul 16 18:06:01 2021 +0800

    update

commit 6b445ee8677fb5b183ea1072c3edf59630f92c15
Author: ting.yin <yinting@qmth.com.cn>
Date:   Mon Jul 12 13:59:08 2021 +0800

    fixbugs

commit afbd7b5b057c8dde39c76702ac4dc8c9f5fd4f39
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Jul 6 17:03:22 2021 +0800

    重构查询员增删改查功能

commit b05982327ba3f31014cd8f90d5478acfbc034ec9
Author: ting.yin <yinting@qmth.com.cn>
Date:   Fri Jul 2 14:49:15 2021 +0800

    新增机构同步

commit b9fe16c6f58b072098286c89b0c35548887dcd6b
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jul 1 17:06:34 2021 +0800

    修改一些bug

commit d0711755ce6b078a95cf53084d4231cbc40cf9a2
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jun 16 11:07:55 2021 +0800

    根据多媒体修改setting

commit f28d8526ec1958dae8146cd14f487d36853d59e6
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jun 10 17:48:10 2021 +0800

    fixbugs

commit 3cc9781c786fe7b07d0236cee62beb6c23ddb0e6
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jun 10 16:25:26 2021 +0800

    fix bugs

commit c9147c79734352668559c31223d9d9aa7a7d36d1
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jun 10 16:01:18 2021 +0800

    fixbugs

commit 84fc0a1ee760a8a8dba904ad7f3ef2c5a25beba5
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jun 10 15:56:19 2021 +0800

    修复多媒体小题号排序问题,考生复核时打回部分失败

commit ce09e7a03fa212408a98b3c6e091ee764f39502d
Author: ting.yin <yinting@qmth.com.cn>
Date:   Thu Jun 10 10:20:28 2021 +0800

    fixbugs

commit 7eec2c40d22602effe34f2bff5c6f0cd892eed9e
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jun 9 17:49:03 2021 +0800

    修复打回分数占位符问题,用#代替空字符串

commit 46c2f741a4c89999dbd3def0f193c01b1f28d637
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jun 9 11:07:25 2021 +0800

    打回考生时,若该任务为仲裁,一并打回并删除仲裁记录

commit a062205481e50a39135a01732616982769a200c7
Author: ting.yin <yinting@qmth.com.cn>
Date:   Wed Jun 9 10:07:57 2021 +0800

    fix bugs

commit 9329f70488393b01924136e1de3082006cd3287f
Author: ting.yin <yinting@qmth.com.cn>
Date:   Tue Jun 8 15:55:43 2021 +0800

    fix bugs
luoshi vor 3 Jahren
Ursprung
Commit
e2027346c0
100 geänderte Dateien mit 3055 neuen und 1005 gelöschten Zeilen
  1. 11 0
      pom.xml
  2. 8 0
      stmms-biz/pom.xml
  3. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/dao/SystemAuthDao.java
  4. 14 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/dao/SystemConfigDao.java
  5. 102 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/model/SystemAuth.java
  6. 80 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/model/SystemConfig.java
  7. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/SystemAuthService.java
  8. 18 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/SystemConfigService.java
  9. 32 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemAuthServiceImpl.java
  10. 102 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemCache.java
  11. 58 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemConfigServiceImpl.java
  12. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java
  13. 19 15
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java
  14. 8 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamSubjectDao.java
  15. 10 13
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkGroupDao.java
  16. 26 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/SelectiveGroupDao.java
  17. 12 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java
  18. 11 10
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java
  19. 31 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java
  20. 21 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ImportQuery.java
  21. 18 22
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/MarkGroup.java
  22. 79 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroup.java
  23. 85 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroupPK.java
  24. 20 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SubjectiveScore.java
  25. 7 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamQuestionService.java
  26. 5 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentService.java
  27. 2 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectService.java
  28. 5 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java
  29. 3 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkGroupService.java
  30. 19 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/SelectiveGroupService.java
  31. 80 40
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamQuestionServiceImpl.java
  32. 42 11
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java
  33. 7 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectServiceImpl.java
  34. 83 37
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java
  35. 7 19
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkGroupServiceImpl.java
  36. 48 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/SelectiveGroupServiceImpl.java
  37. 10 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/SubjectiveScoreServiceImpl.java
  38. 3 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FileType.java
  39. 11 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/FileService.java
  40. 84 24
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java
  41. 2 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/store/impl/OssStore.java
  42. 6 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/ArbitrateHistoryDao.java
  43. 12 9
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkLibraryDao.java
  44. 0 49
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialHistoryDao.java
  45. 29 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialLibraryDao.java
  46. 5 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTagDao.java
  47. 1 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTrackDao.java
  48. 6 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/ArbitrationDTO.java
  49. 2 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkLibrary.java
  50. 25 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java
  51. 14 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/ProblemHistory.java
  52. 21 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SpecialTagDTO.java
  53. 5 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/Task.java
  54. 8 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrackDTO.java
  55. 0 188
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistory.java
  56. 0 66
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistoryPK.java
  57. 87 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialLibrary.java
  58. 20 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/ArbitrateHistorySearchQuery.java
  59. 34 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/MarkLibrarySearchQuery.java
  60. 9 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/ArbitrateHistoryServiceImpl.java
  61. 23 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java
  62. 31 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkLibraryServiceImpl.java
  63. 245 152
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java
  64. 70 46
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java
  65. 48 59
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TrialServiceImpl.java
  66. 3 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkLibraryService.java
  67. 17 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java
  68. 1 2
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TaskService.java
  69. 13 15
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TrialService.java
  70. 33 3
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubject.java
  71. 26 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectQuestionServiceImpl.java
  72. 7 6
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/QuestionGroup.java
  73. 7 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectClassRangeModule.java
  74. 4 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectGroupModule.java
  75. 2 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectModule.java
  76. 3 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectQuestionModule.java
  77. 6 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectRangeModule.java
  78. 5 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/dao/SchoolDao.java
  79. 14 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/model/School.java
  80. 8 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/SchoolService.java
  81. 55 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/OrgCornService.java
  82. 82 15
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/SchoolServiceImpl.java
  83. 37 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/thread/OrgSyncThread.java
  84. 3 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/UserService.java
  85. 17 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/impl/UserServiceImpl.java
  86. 76 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/AppLicenseUtil.java
  87. 13 12
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/ScoreInfo.java
  88. 283 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/SolarHttpUtil.java
  89. 31 0
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/ConfigType.java
  90. 2 2
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/HistoryStatus.java
  91. 1 1
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LibraryStatus.java
  92. 4 4
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LockType.java
  93. 47 0
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SelectiveStatus.java
  94. 2 2
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SubjectiveStatus.java
  95. 31 0
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SystemAuthType.java
  96. 36 31
      stmms-common/src/main/java/cn/com/qmth/stmms/common/utils/BigDecimalUtils.java
  97. 151 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/config/SystemAuthController.java
  98. 58 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/config/SystemConfigController.java
  99. 53 21
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ExamStudentDTO.java
  100. 17 5
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/MarkerInfoDTO.java

+ 11 - 0
pom.xml

@@ -29,6 +29,7 @@
         <poi.version>3.9</poi.version>
         <guava.version>14.0.1</guava.version>
         <commons-lang3.version>3.1</commons-lang3.version>
+        <qmth-boot-version>1.0.2</qmth-boot-version>
     </properties>
 
     <dependencyManagement>
@@ -321,6 +322,16 @@
                 <artifactId>javassist</artifactId>
                 <version>3.27.0-GA</version>
             </dependency>
+            <dependency>
+            	<groupId>com.qmth.boot</groupId>
+          		<artifactId>tools-device</artifactId>
+          		<version>${qmth-boot-version}</version>
+        	</dependency>
+        	<dependency>
+       			<groupId>com.qmth.boot</groupId>
+           		<artifactId>tools-common</artifactId>
+           		<version>${qmth-boot-version}</version>
+       		</dependency>
         </dependencies>
     </dependencyManagement>
 

+ 8 - 0
stmms-biz/pom.xml

@@ -68,5 +68,13 @@
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
+		<dependency>
+            <groupId>com.qmth.boot</groupId>
+          	<artifactId>tools-device</artifactId>
+        </dependency>
+        <dependency>
+       		<groupId>com.qmth.boot</groupId>
+           	<artifactId>tools-common</artifactId>
+       	</dependency>
     </dependencies>
 </project>

+ 11 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/dao/SystemAuthDao.java

@@ -0,0 +1,11 @@
+package cn.com.qmth.stmms.biz.config.dao;
+
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+
+public interface SystemAuthDao extends PagingAndSortingRepository<SystemAuth, Integer>,
+        JpaSpecificationExecutor<SystemAuth> {
+
+}

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/dao/SystemConfigDao.java

@@ -0,0 +1,14 @@
+package cn.com.qmth.stmms.biz.config.dao;
+
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import cn.com.qmth.stmms.biz.config.model.SystemConfig;
+import cn.com.qmth.stmms.common.enums.ConfigType;
+
+public interface SystemConfigDao extends PagingAndSortingRepository<SystemConfig, Integer>,
+        JpaSpecificationExecutor<SystemConfig> {
+
+    SystemConfig findByType(ConfigType type);
+
+}

+ 102 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/model/SystemAuth.java

@@ -0,0 +1,102 @@
+package cn.com.qmth.stmms.biz.config.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import cn.com.qmth.stmms.common.enums.SystemAuthType;
+
+@Cacheable
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+@Entity
+@Table(name = "b_sys_auth")
+public class SystemAuth implements Serializable {
+
+    private static final long serialVersionUID = -646381565729623677L;
+
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "type", length = 16, nullable = false)
+    private SystemAuthType type;
+
+    @Column(name = "description")
+    private String description;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "update_time")
+    private Date updateTime;
+
+    @Column(name = "access_key", nullable = true, length = 64)
+    private String accessKey;
+
+    @Column(name = "access_secret", nullable = true, length = 64)
+    private String accessSecret;
+
+    public SystemAuth() {
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public SystemAuthType getType() {
+        return type;
+    }
+
+    public void setType(SystemAuthType type) {
+        this.type = type;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    public String getAccessSecret() {
+        return accessSecret;
+    }
+
+    public void setAccessSecret(String accessSecret) {
+        this.accessSecret = accessSecret;
+    }
+
+}

+ 80 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/model/SystemConfig.java

@@ -0,0 +1,80 @@
+package cn.com.qmth.stmms.biz.config.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Cache;
+import org.hibernate.annotations.CacheConcurrencyStrategy;
+
+import cn.com.qmth.stmms.common.enums.ConfigType;
+
+@Cacheable
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+@Entity
+@Table(name = "b_sys_config")
+public class SystemConfig implements Serializable {
+
+    private static final long serialVersionUID = 6151033013226678852L;
+
+    @Id
+    @GeneratedValue
+    private Integer id;
+
+    @Enumerated(EnumType.STRING)
+    @Column(name = "type", length = 16, nullable = false)
+    private ConfigType type;
+
+    @Column(name = "description")
+    private String description;
+
+    @Temporal(TemporalType.TIMESTAMP)
+    @Column(name = "update_time")
+    private Date updateTime;
+
+    public SystemConfig() {
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public ConfigType getType() {
+        return type;
+    }
+
+    public void setType(ConfigType type) {
+        this.type = type;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+}

+ 11 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/SystemAuthService.java

@@ -0,0 +1,11 @@
+package cn.com.qmth.stmms.biz.config.service;
+
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+
+public interface SystemAuthService {
+
+    SystemAuth findOne();
+
+    SystemAuth save(SystemAuth systemAuth);
+
+}

+ 18 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/SystemConfigService.java

@@ -0,0 +1,18 @@
+package cn.com.qmth.stmms.biz.config.service;
+
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.config.model.SystemConfig;
+import cn.com.qmth.stmms.common.enums.ConfigType;
+
+public interface SystemConfigService {
+
+    SystemConfig update(Integer id, String value);
+
+    List<SystemConfig> findAll();
+
+    SystemConfig findById(Integer id);
+
+    String findByType(ConfigType type);
+
+}

+ 32 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemAuthServiceImpl.java

@@ -0,0 +1,32 @@
+package cn.com.qmth.stmms.biz.config.service.impl;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.config.dao.SystemAuthDao;
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
+
+@Service("systemAuthService")
+public class SystemAuthServiceImpl extends BaseQueryService<SystemAuth> implements SystemAuthService {
+
+    @Autowired
+    private SystemAuthDao authDao;
+
+    @Override
+    public SystemAuth findOne() {
+        List<SystemAuth> list = (List<SystemAuth>) authDao.findAll();
+        return list.isEmpty() ? null : list.get(0);
+    }
+
+    @Override
+    public SystemAuth save(SystemAuth systemAuth) {
+        systemAuth.setUpdateTime(new Date());
+        return authDao.save(systemAuth);
+    }
+
+}

+ 102 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemCache.java

@@ -0,0 +1,102 @@
+package cn.com.qmth.stmms.biz.config.service.impl;
+
+import javax.annotation.PostConstruct;
+
+import net.sf.json.JSONObject;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
+import cn.com.qmth.stmms.biz.config.service.SystemConfigService;
+import cn.com.qmth.stmms.biz.utils.AppLicenseUtil;
+import cn.com.qmth.stmms.biz.utils.SolarHttpUtil;
+import cn.com.qmth.stmms.common.enums.ConfigType;
+import cn.com.qmth.stmms.common.enums.SystemAuthType;
+import cn.com.qmth.stmms.common.utils.AesUtils;
+
+import com.qmth.boot.tools.models.ByteArray;
+
+@Component
+public class SystemCache {
+
+    @Autowired
+    private SystemAuthService authService;
+
+    @Autowired
+    private SystemConfigService configService;
+
+    private boolean Auth;
+
+    private Long expireTime;
+
+    private String fileServer;
+
+    private Long markTime;
+
+    @Value("${qmth.solar.host}")
+    private String host;
+
+    @Value("${qmth.solar.app.uri}")
+    private String uri;
+
+    @PostConstruct
+    public void init() {
+        SystemAuth s = authService.findOne();
+        if (s != null && SystemAuthType.ONLINE.equals(s.getType())) {
+            String accessKey = AesUtils.decrypt(s.getAccessKey());
+            String accessSecret = AesUtils.decrypt(s.getAccessSecret());
+            SolarHttpUtil httpUtil = new SolarHttpUtil(accessKey, accessSecret, host, uri);
+            if (httpUtil.getAPP()) {
+                Auth = true;
+            }
+        } else if (s != null && SystemAuthType.OFFLINE.equals(s.getType())) {
+            JSONObject json = AppLicenseUtil.parseLicense(ByteArray.fromBase64(s.getDescription()).value());
+            if (json != null) {
+                Auth = true;
+                if (json.has("control") && json.getJSONObject("control").has("expireTime")) {
+                    expireTime = json.getJSONObject("control").getLong("expireTime");
+                }
+            }
+        } else {
+            Auth = false;
+        }
+        fileServer = configService.findByType(ConfigType.FILE_SERVER);
+        markTime = Long.parseLong(configService.findByType(ConfigType.MARK_TIME));
+    }
+
+    public boolean isAuth() {
+        return Auth;
+    }
+
+    public void setAuth(boolean auth) {
+        Auth = auth;
+    }
+
+    public String getFileServer() {
+        return fileServer;
+    }
+
+    public void setFileServer(String fileServer) {
+        this.fileServer = fileServer;
+    }
+
+    public Long getMarkTime() {
+        return markTime;
+    }
+
+    public void setMarkTime(Long markTime) {
+        this.markTime = markTime;
+    }
+
+    public Long getExpireTime() {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime) {
+        this.expireTime = expireTime;
+    }
+
+}

+ 58 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemConfigServiceImpl.java

@@ -0,0 +1,58 @@
+package cn.com.qmth.stmms.biz.config.service.impl;
+
+import java.util.Date;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.config.dao.SystemConfigDao;
+import cn.com.qmth.stmms.biz.config.model.SystemConfig;
+import cn.com.qmth.stmms.biz.config.service.SystemConfigService;
+import cn.com.qmth.stmms.common.enums.ConfigType;
+
+@Service("systemConfigService")
+public class SystemConfigServiceImpl extends BaseQueryService<SystemConfig> implements SystemConfigService {
+
+    @Autowired
+    private SystemConfigDao configDao;
+
+    @Autowired
+    private SystemCache systemCache;
+
+    @Override
+    public SystemConfig update(Integer id, String value) {
+        SystemConfig s = configDao.findOne(id);
+        s.setDescription(value);
+        s.setUpdateTime(new Date());
+        configDao.save(s);
+        if (ConfigType.FILE_SERVER.equals(s.getType())) {
+            systemCache.setFileServer(value);
+        }
+        if (ConfigType.MARK_TIME.equals(s.getType())) {
+            systemCache.setMarkTime(Long.parseLong(value));
+        }
+        return s;
+    }
+
+    @Override
+    public List<SystemConfig> findAll() {
+        return (List<SystemConfig>) configDao.findAll();
+    }
+
+    @Override
+    public SystemConfig findById(Integer id) {
+        return configDao.findOne(id);
+    }
+
+    @Override
+    public String findByType(ConfigType type) {
+        SystemConfig s = configDao.findByType(type);
+        if (s != null) {
+            return s.getDescription();
+        }
+        return null;
+    }
+
+}

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamQuestionDao.java

@@ -88,7 +88,7 @@ public interface ExamQuestionDao extends JpaRepository<ExamQuestion, Integer>, J
     public ExamQuestion findByExamIdAndSubjectCodeAndObjectiveAndMainNumberAndSubNumber(Integer examId,
             String subjectCode, boolean objective, Integer mainNumber, String subNumber);
 
-    @Query("select sum(q.totalScore) from ExamQuestion q where q.examId=?1 and q.subjectCode=?2 and q.objective=?3 ")
+    @Query(value = "select sum(cast(q.total_score as decimal(10,3))) from eb_exam_question q where q.exam_id=?1 and q.subject_code=?2 and q.is_objective=?3 ", nativeQuery = true)
     public Double sumTotalScore(int examId, String subjectCode, boolean objective);
 
     @Modifying

+ 19 - 15
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamStudentDao.java

@@ -1,7 +1,8 @@
 package cn.com.qmth.stmms.biz.exam.dao;
 
-import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
-import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
 
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -9,8 +10,8 @@ import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
-import java.util.Date;
-import java.util.List;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 public interface ExamStudentDao extends PagingAndSortingRepository<ExamStudent, Integer>,
         JpaSpecificationExecutor<ExamStudent> {
@@ -152,8 +153,9 @@ public interface ExamStudentDao extends PagingAndSortingRepository<ExamStudent,
             Date minUploadTime, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=true and s.absent=false and s.breach=false "
-            + "and not exists (select l.id from TrialLibrary l where l.studentId=s.id and l.groupNumber=?3)")
-    public List<ExamStudent> findUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber, Pageable page);
+            + "and s.subjectiveStatus=?4 and not exists (select l.id from TrialLibrary l where l.studentId=s.id and l.groupNumber=?3)")
+    public List<ExamStudent> findUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber,
+            SubjectiveStatus status, Pageable page);
 
     @Query("select s from ExamStudent s where s.examId=?1 and s.subjectCode=?2 and s.upload=true and (s.absent=true or s.breach=true) and "
             + "exists (select l.id from MarkLibrary l where l.studentId=s.id)")
@@ -170,18 +172,20 @@ public interface ExamStudentDao extends PagingAndSortingRepository<ExamStudent,
     @Query("select s.className from ExamStudent s where s.examId=?1 and s.subjectCode=?2 group by s.className")
     public List<String> findDistinctClassName(Integer examId, String subjectCode);
 
-    @Query(value = "select s.objective_score+s.subjective_score from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by s.objective_score+s.subjective_score desc limit ?3 ", nativeQuery = true)
-    public List<Double> findHighCountTotalSocreByExamIdAndSubjectCode(Integer examId, String subjectCode, int highCount);
+    @Query(value = "select cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) desc limit ?3 ", nativeQuery = true)
+    public List<BigDecimal> findHighCountTotalSocreByExamIdAndSubjectCode(Integer examId, String subjectCode,
+            int highCount);
 
-    @Query(value = "select s.objective_score+s.subjective_score from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by s.objective_score+s.subjective_score asc limit ?3 ", nativeQuery = true)
-    public List<Double> findLowCountTotalSocreByExamIdAndSubjectCode(Integer examId, String subjectCode, int lowCount);
+    @Query(value = "select cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) asc limit ?3 ", nativeQuery = true)
+    public List<BigDecimal> findLowCountTotalSocreByExamIdAndSubjectCode(Integer examId, String subjectCode,
+            int lowCount);
 
-    @Query(value = "select s.objective_score+s.subjective_score from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.class_name=?3 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by s.objective_score+s.subjective_score desc limit ?4 ", nativeQuery = true)
-    public List<Double> findHighCountTotalSocreByExamIdAndSubjectCodeAndClass(Integer examId, String subjectCode,
+    @Query(value = "select cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.class_name=?3 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) desc limit ?4 ", nativeQuery = true)
+    public List<BigDecimal> findHighCountTotalSocreByExamIdAndSubjectCodeAndClass(Integer examId, String subjectCode,
             String className, int highCount);
 
-    @Query(value = "select s.objective_score+s.subjective_score from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.class_name=?3 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by s.objective_score+s.subjective_score asc limit ?4 ", nativeQuery = true)
-    public List<Double> findLowCountTotalSocreByExamIdAndSubjectCodeAndClass(Integer examId, String subjectCode,
+    @Query(value = "select cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) from eb_exam_student s where s.exam_id=?1 and s.subject_code=?2 and s.class_name=?3 and s.is_upload =true and s.is_absent=false and s.is_breach=false order by cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) asc limit ?4 ", nativeQuery = true)
+    public List<BigDecimal> findLowCountTotalSocreByExamIdAndSubjectCodeAndClass(Integer examId, String subjectCode,
             String className, int lowCount);
 
     @Query("select s.className from ExamStudent s where s.examId=?1 group by s.className")
@@ -192,6 +196,6 @@ public interface ExamStudentDao extends PagingAndSortingRepository<ExamStudent,
     public void updateSubjectiveStatusAndTimeAndInspectorId(Integer studentId, SubjectiveStatus status,
             Date inspectTime, Integer inspectorId);
 
-    public List<ExamStudent> findByExamIdAndStudentCode(int examId, String studentCode);
+    public List<ExamStudent> findByExamIdAndStudentCodeAndSubjectCode(int examId, String studentCode, String subjectCode);
 
 }

+ 8 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/ExamSubjectDao.java

@@ -10,8 +10,8 @@ import org.springframework.data.repository.PagingAndSortingRepository;
 import java.util.List;
 import java.util.Set;
 
-public interface ExamSubjectDao
-        extends PagingAndSortingRepository<ExamSubject, ExamSubjectPK>, JpaSpecificationExecutor<ExamSubject> {
+public interface ExamSubjectDao extends PagingAndSortingRepository<ExamSubject, ExamSubjectPK>,
+        JpaSpecificationExecutor<ExamSubject> {
 
     @Query("select s from ExamSubject s where s.pk.examId=?1")
     public List<ExamSubject> findByExamId(int examId);
@@ -35,11 +35,11 @@ public interface ExamSubjectDao
     public List<ExamSubject> findByExamIdAndUploadCountGt(int examId, int uploadCount);
 
     @Modifying
-    @Query("update ExamSubject s set s.totalScore=s.objectiveScore+s.subjectiveScore where s.pk.examId=?1")
+    @Query(value = "update eb_exam_subject s set s.total_score=cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) where s.exam_id=?1", nativeQuery = true)
     public void updateTotalScoreByExamId(int examId);
 
     @Modifying
-    @Query("update ExamSubject s set s.totalScore=s.objectiveScore+s.subjectiveScore where s.pk.examId=?1 and s.pk.code=?2")
+    @Query(value = "update eb_exam_subject s set s.total_score=cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3)) where s.exam_id=?1 and s.code=?2", nativeQuery = true)
     public void updateTotalScoreByExamIdAndCode(int examId, String code);
 
     @Modifying
@@ -65,4 +65,8 @@ public interface ExamSubjectDao
     @Query("update ExamSubject s set s.sliceConfig=?3 where s.pk.examId=?1 and s.pk.code=?2")
     public void updateSliceConfig(Integer examId, String subjectCode, String configString);
 
+    @Modifying
+    @Query("update ExamSubject s set s.trialCount=?3 where s.pk.examId=?1 and s.pk.code=?2")
+    public void updateTrialCount(int examId, String subjectCode, int trialCount);
+
 }

+ 10 - 13
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/MarkGroupDao.java

@@ -6,6 +6,7 @@ import cn.com.qmth.stmms.common.enums.MarkMode;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
 import cn.com.qmth.stmms.common.enums.ScorePolicy;
 import cn.com.qmth.stmms.common.enums.ThirdPolicy;
+
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
@@ -28,8 +29,8 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("delete from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
     void deleteByExamIdAndSubjectCode(Integer examId, String subjectCode);
 
-    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.status in (?2)")
-    long countByExamIdAndStatus(Integer examId, MarkStatus... status);
+    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.status in (?3)")
+    long countByExamIdAndSubjectCodeAndStatus(Integer examId, String subjectCode, MarkStatus... status);
 
     @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
             + "and q.pk.number=?3 and q.status in (?4)")
@@ -60,13 +61,6 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
     long countByExamIdAndSubjectCode(Integer examId, String subjectCode);
 
-    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.number=?3 "
-            + "and q.status=?4 and q.trialCount>q.libraryCount")
-    long countByStatusAndTrailCount(Integer examId, String subjectCode, Integer number, MarkStatus status);
-
-    @Query("select sum(g.totalScore) from MarkGroup g where g.pk.examId=?1 and g.pk.subjectCode=?2")
-    Double sumTotalScore(Integer examId, String subjectCode);
-
     @Modifying(clearAutomatically = true)
     @Query("update MarkGroup g set g.libraryCount=?4, g.leftCount=(?4-g.markedCount) where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateLibraryCount(Integer examId, String subjectCode, Integer number, Integer totalCount);
@@ -112,10 +106,6 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("update MarkGroup g set g.arbitrateThreshold=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateArbitrateThreshold(Integer examId, String subjectCode, Integer number, Double arbitrateThreshold);
 
-    @Modifying(clearAutomatically = true)
-    @Query("update MarkGroup g set g.trialCount=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
-    void updateTrialCount(Integer examId, String subjectCode, Integer number, Integer trialCount);
-
     @Modifying(clearAutomatically = true)
     @Query("update MarkGroup g set g.sheetView=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateSheetView(Integer examId, String subjectCode, Integer number, boolean sheetView);
@@ -134,4 +124,11 @@ public interface MarkGroupDao extends PagingAndSortingRepository<MarkGroup, Mark
     @Query("update MarkGroup g set g.thirdPolicy=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
     void updateThirdPolicy(Integer examId, String subjectCode, Integer number, ThirdPolicy third);
 
+    @Modifying(clearAutomatically = true)
+    @Query("update MarkGroup g set g.selective=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
+    void updateSelective(Integer examId, String subjectCode, Integer number, boolean selective);
+
+    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.selective=?3 order by q.pk.number")
+    List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective);
+
 }

+ 26 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/dao/SelectiveGroupDao.java

@@ -0,0 +1,26 @@
+package cn.com.qmth.stmms.biz.exam.dao;
+
+import java.util.List;
+
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import cn.com.qmth.stmms.biz.exam.model.MarkGroupPK;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+
+public interface SelectiveGroupDao extends PagingAndSortingRepository<SelectiveGroup, MarkGroupPK>,
+        JpaSpecificationExecutor<SelectiveGroup> {
+
+    @Query("select q from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.mainNumber=?3")
+    SelectiveGroup findOne(Integer examId, String subjectCode, Integer mainNumber);
+
+    @Modifying(clearAutomatically = true)
+    @Query("delete from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
+    void deleteByExamIdAndSubjectCode(Integer examId, String subjectCode);
+
+    @Query("select q from SelectiveGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 order by q.pk.mainNumber")
+    List<SelectiveGroup> findByExamIdAndSubjectCode(Integer examId, String subjectCode);
+
+}

+ 12 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamQuestion.java

@@ -35,7 +35,7 @@ public class ExamQuestion implements Serializable {
     @Column(name = "sub_number", nullable = false)
     private String subNumber;
 
-    @Column(name = "main_title", nullable = false, length = 32)
+    @Column(name = "main_title", nullable = false, length = 128)
     private String mainTitle;
 
     @Column(name = "group_number", nullable = true)
@@ -78,6 +78,9 @@ public class ExamQuestion implements Serializable {
     @Transient
     private Integer trialCount;
 
+    @Transient
+    private boolean selective;
+
     public Integer getId() {
         return id;
     }
@@ -276,4 +279,12 @@ public class ExamQuestion implements Serializable {
         this.objectivePolicy = objectivePolicy;
     }
 
+    public boolean isSelective() {
+        return selective;
+    }
+
+    public void setSelective(boolean selective) {
+        this.selective = selective;
+    }
+
 }

+ 11 - 10
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamStudent.java

@@ -25,6 +25,7 @@ import cn.com.qmth.stmms.biz.user.model.User;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.annotation.ExcelField;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
 
 /**
  * 针对某次考试的考生信息
@@ -71,14 +72,14 @@ public class ExamStudent implements Serializable {
      * 科目代码
      */
     @Column(name = "subject_code", length = 32, nullable = false)
-    @ExcelField(title = "课程代码", align = 2, sort = 20)
+    @ExcelField(title = "课程代码*", align = 2, sort = 20)
     private String subjectCode;
 
     /**
      * 科目名称
      */
     @Column(name = "subject_name", length = 32, nullable = false)
-    @ExcelField(title = "课程名称", align = 2, sort = 30)
+    @ExcelField(title = "课程名称*", align = 2, sort = 30)
     private String subjectName;
 
     /**
@@ -91,14 +92,14 @@ public class ExamStudent implements Serializable {
      * 准考证号
      */
     @Column(name = "exam_number", length = 64, nullable = false)
-    @ExcelField(title = "准考证号", align = 2, sort = 40)
+    @ExcelField(title = "准考证号*", align = 2, sort = 40)
     private String examNumber;
 
     /**
      * 学号
      */
     @Column(name = "student_code", length = 64, nullable = false)
-    @ExcelField(title = "学号", align = 2, sort = 50)
+    @ExcelField(title = "学号*", align = 2, sort = 50)
     private String studentCode;
 
     /**
@@ -111,7 +112,7 @@ public class ExamStudent implements Serializable {
      * 姓名
      */
     @Column(name = "name", length = 64, nullable = false)
-    @ExcelField(title = "姓名", align = 2, sort = 60)
+    @ExcelField(title = "姓名*", align = 2, sort = 60)
     private String name;
 
     /**
@@ -248,21 +249,21 @@ public class ExamStudent implements Serializable {
     /**
      * 学院
      */
-    @ExcelField(title = "学院", align = 2, sort = 130)
+    @ExcelField(title = "学院*", align = 2, sort = 130)
     @Column(name = "college", length = 64, nullable = false)
     private String college;
 
     /**
      * 班级
      */
-    @ExcelField(title = "班级", align = 2, sort = 140)
+    @ExcelField(title = "班级*", align = 2, sort = 140)
     @Column(name = "class_name", length = 64, nullable = false)
     private String className;
 
     /**
      * 任课老师
      */
-    @ExcelField(title = "任课老师", align = 2, sort = 150)
+    @ExcelField(title = "任课老师*", align = 2, sort = 150)
     @Column(name = "teacher", length = 64, nullable = false)
     private String teacher;
 
@@ -528,10 +529,10 @@ public class ExamStudent implements Serializable {
     public double getTotalScore() {
         double score = 0;
         if (objectiveScore != null) {
-            score += objectiveScore;
+            score = BigDecimalUtils.add(score, objectiveScore);
         }
         if (subjectiveScore != null) {
-            score += subjectiveScore;
+            score = BigDecimalUtils.add(score, subjectiveScore);
         }
         return score;
     }

+ 31 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ExamSubject.java

@@ -1,14 +1,23 @@
 package cn.com.qmth.stmms.biz.exam.model;
 
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
-import cn.com.qmth.stmms.biz.file.service.FileService;
-import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
 import net.sf.json.JSONObject;
+
 import org.apache.commons.lang.StringUtils;
 
-import javax.persistence.*;
-import java.io.Serializable;
-import java.util.List;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
 
 @Entity
 @Table(name = "eb_exam_subject")
@@ -84,6 +93,12 @@ public class ExamSubject implements Serializable {
      */
     @Column(name = "sas_config", nullable = true)
     private String sasConfig;
+    
+    /**
+     * 试评数量
+     */
+    @Column(name = "trial_count", nullable = true)
+    private Integer trialCount;
 
     /**
      * 大题数量
@@ -343,4 +358,14 @@ public class ExamSubject implements Serializable {
         this.paperType = paperType;
     }
 
+    
+    public Integer getTrialCount() {
+        return trialCount;
+    }
+
+    
+    public void setTrialCount(Integer trialCount) {
+        this.trialCount = trialCount;
+    }
+
 }

+ 21 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/ImportQuery.java

@@ -31,6 +31,8 @@ public class ImportQuery implements Serializable {
 
     public static final String SUCCESS = "success";
 
+    public static final String TAG = "tag";
+
     public static final String FAILURE = "failure";
 
     @Id
@@ -73,6 +75,7 @@ public class ImportQuery implements Serializable {
         JSONObject json = new JSONObject();
         json.accumulate(SUCCESS, StringUtils.join(successStudent, DB_ITEM_JOINER));
         json.accumulate(FAILURE, StringUtils.join(failureStudent, DB_ITEM_JOINER));
+        json.accumulate(TAG, "");
         this.description = json.toString();
         this.createTime = new Date();
     }
@@ -147,6 +150,17 @@ public class ImportQuery implements Serializable {
         return list;
     }
 
+    public List<Integer> getTagIdList() {
+        List<Integer> list = new ArrayList<Integer>();
+        JSONObject json = JSONObject.fromObject(description);
+        String tag = json.getString(TAG);
+        String[] values = StringUtils.split(tag, DB_ITEM_JOINER);
+        for (String studentId : values) {
+            list.add(Integer.parseInt(studentId));
+        }
+        return list;
+    }
+
     public String getStudentIdString() {
         JSONObject json = JSONObject.fromObject(description);
         String success = json.getString(SUCCESS);
@@ -160,4 +174,11 @@ public class ImportQuery implements Serializable {
         return json.toString();
 
     }
+
+    public void buildTag(List<Integer> ids) {
+        JSONObject json = JSONObject.fromObject(description);
+        json.remove(TAG);
+        json.accumulate(TAG, StringUtils.join(ids, DB_ITEM_JOINER));
+        this.description = json.toString();
+    }
 }

+ 18 - 22
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/MarkGroup.java

@@ -40,12 +40,6 @@ public class MarkGroup implements Serializable {
     @Column(name = "total_score", nullable = false)
     private Double totalScore;
 
-    /**
-     * 试评数量
-     */
-    @Column(name = "trial_count", nullable = true)
-    private Integer trialCount;
-
     /**
      * 双评比例(0~1)
      */
@@ -114,6 +108,9 @@ public class MarkGroup implements Serializable {
     @Column(name = "left_count")
     private Integer leftCount;
 
+    @Column(name = "is_selective", nullable = false)
+    private boolean selective;
+
     @Transient
     private int currentCount;
 
@@ -150,14 +147,13 @@ public class MarkGroup implements Serializable {
 
     public MarkGroup(Integer examId, String subjectCode, Integer number, List<PictureConfigItem> configList,
             Double totalScore, Double doubleRate, Double arbitrateThreshold, Integer scorePolicy, String markMode,
-            Integer trialCount, boolean sheetView, boolean enableAllZero, Integer thirdPolicy) {
+            Integer trialCount, boolean sheetView, boolean enableAllZero, Integer thirdPolicy, boolean selective) {
         this.pk = new MarkGroupPK();
         this.pk.setExamId(examId);
         this.pk.setNumber(number);
         this.pk.setSubjectCode(subjectCode);
-        this.picList = configList != null && configList.size() > 0 ?
-                StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) :
-                "";
+        this.picList = configList != null && configList.size() > 0 ? StringUtils.join(configList,
+                PictureConfigItem.DB_ITEM_JOINER) : "";
         this.totalScore = totalScore;
         this.libraryCount = 0;
         this.markedCount = 0;
@@ -179,7 +175,6 @@ public class MarkGroup implements Serializable {
         }
         if (trialCount != null && trialCount > 0) {
             this.status = MarkStatus.TRIAL;
-            this.trialCount = trialCount;
         } else {
             this.status = MarkStatus.FORMAL;
         }
@@ -191,6 +186,7 @@ public class MarkGroup implements Serializable {
         } else {
             this.thirdPolicy = ThirdPolicy.DISABLE;
         }
+        this.selective = selective;
     }
 
     public Integer getExamId() {
@@ -226,9 +222,8 @@ public class MarkGroup implements Serializable {
     }
 
     public void setPicList(List<PictureConfigItem> configList) {
-        this.picList = configList != null && configList.size() > 0 ?
-                StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) :
-                "";
+        this.picList = configList != null && configList.size() > 0 ? StringUtils.join(configList,
+                PictureConfigItem.DB_ITEM_JOINER) : "";
     }
 
     public List<PictureConfigItem> getPictureConfigList() {
@@ -389,14 +384,6 @@ public class MarkGroup implements Serializable {
         this.status = status;
     }
 
-    public Integer getTrialCount() {
-        return trialCount;
-    }
-
-    public void setTrialCount(Integer trialCount) {
-        this.trialCount = trialCount;
-    }
-
     public boolean isSheetView() {
         return sheetView;
     }
@@ -444,4 +431,13 @@ public class MarkGroup implements Serializable {
     public void setDeleting(boolean deleting) {
         this.deleting = deleting;
     }
+
+    public boolean isSelective() {
+        return selective;
+    }
+
+    public void setSelective(boolean selective) {
+        this.selective = selective;
+    }
+
 }

+ 79 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroup.java

@@ -0,0 +1,79 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "eb_selective_group")
+public class SelectiveGroup implements Serializable {
+
+    private static final long serialVersionUID = 7866856607752769258L;
+
+    @EmbeddedId
+    private SelectiveGroupPK pk;
+
+    @Column(name = "selective_index", nullable = false)
+    private Integer selectiveIndex;
+
+    @Column(name = "selective_count", nullable = false)
+    private Integer selectiveCount;
+
+    public SelectiveGroup() {
+        this.pk = new SelectiveGroupPK();
+    }
+
+    public SelectiveGroup(Integer examId, String subjectCode, Integer mainNumber, Integer selectiveIndex,
+            Integer selectiveCount) {
+        this.pk = new SelectiveGroupPK();
+        this.pk.setExamId(examId);
+        this.pk.setSubjectCode(subjectCode);
+        this.pk.setMainNumber(mainNumber);
+        this.selectiveCount = selectiveCount;
+        this.selectiveIndex = selectiveIndex;
+    }
+
+    public Integer getExamId() {
+        return pk.getExamId();
+    }
+
+    public void setExamId(Integer examId) {
+        pk.setExamId(examId);
+    }
+
+    public String getSubjectCode() {
+        return pk.getSubjectCode();
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        pk.setSubjectCode(subjectCode);
+    }
+
+    public Integer getMainNumber() {
+        return pk.getMainNumber();
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        pk.setMainNumber(mainNumber);
+    }
+
+    public Integer getSelectiveIndex() {
+        return selectiveIndex;
+    }
+
+    public void setSelectiveIndex(Integer selectiveIndex) {
+        this.selectiveIndex = selectiveIndex;
+    }
+
+    public Integer getSelectiveCount() {
+        return selectiveCount;
+    }
+
+    public void setSelectiveCount(Integer selectiveCount) {
+        this.selectiveCount = selectiveCount;
+    }
+
+}

+ 85 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SelectiveGroupPK.java

@@ -0,0 +1,85 @@
+package cn.com.qmth.stmms.biz.exam.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class SelectiveGroupPK implements Serializable {
+
+    private static final long serialVersionUID = -6741844373808204701L;
+
+    @Column(name = "exam_id", nullable = false)
+    private Integer examId;
+
+    @Column(name = "subject_code", nullable = false, length = 32)
+    private String subjectCode;
+
+    @Column(name = "main_number", nullable = false)
+    private Integer mainNumber;
+
+    public Integer getExamId() {
+        return examId;
+    }
+
+    public void setExamId(Integer examId) {
+        this.examId = examId;
+    }
+
+    public String getSubjectCode() {
+        return subjectCode;
+    }
+
+    public void setSubjectCode(String subjectCode) {
+        this.subjectCode = subjectCode;
+    }
+
+    public Integer getMainNumber() {
+        return mainNumber;
+    }
+
+    public void setMainNumber(Integer mainNumber) {
+        this.mainNumber = mainNumber;
+    }
+
+    @Override
+    public int hashCode() {
+        final int PRIME = 31;
+        int result = 1;
+        result = PRIME * result + ((examId == null) ? 0 : examId.hashCode());
+        result = PRIME * result + ((subjectCode == null) ? 0 : subjectCode.hashCode());
+        result = PRIME * result + ((mainNumber == null) ? 0 : mainNumber.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        final SelectiveGroupPK other = (SelectiveGroupPK) obj;
+        if (examId == null) {
+            if (other.examId != null)
+                return false;
+        } else if (!examId.equals(other.examId))
+            return false;
+        if (subjectCode == null) {
+            if (other.subjectCode != null)
+                return false;
+        } else if (!subjectCode.equals(other.subjectCode))
+            return false;
+
+        if (mainNumber == null) {
+            if (other.mainNumber != null)
+                return false;
+        } else if (!mainNumber.equals(other.mainNumber))
+            return false;
+
+        return true;
+    }
+
+}

+ 20 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/model/SubjectiveScore.java

@@ -11,7 +11,7 @@ import java.io.Serializable;
  */
 @Entity
 @Table(name = "eb_subjective_score")
-public class SubjectiveScore implements Serializable {
+public class SubjectiveScore implements Serializable, Comparable<SubjectiveScore> {
 
     private static final long serialVersionUID = 6637010422161820147L;
 
@@ -130,4 +130,23 @@ public class SubjectiveScore implements Serializable {
         this.mainScore = mainScore;
     }
 
+    @Override
+    public int compareTo(SubjectiveScore other) {
+        int i = this.getMainNumber() - other.getMainNumber();
+        if (i == 0) {
+            if (this.getSubNumber().contains("-")) {
+                String[] o1s = this.getSubNumber().split("-");
+                String[] o2s = other.getSubNumber().split("-");
+                int j = Integer.parseUnsignedInt(o1s[0]) - Integer.parseUnsignedInt(o2s[0]);
+                if (j == 0) {
+                    return Integer.parseUnsignedInt(o1s[1]) - Integer.parseUnsignedInt(o2s[1]);
+                } else {
+                    return j;
+                }
+            } else {
+                return Integer.parseUnsignedInt(this.getSubNumber()) - Integer.parseUnsignedInt(other.getSubNumber());
+            }
+        }
+        return i;
+    }
 }

+ 7 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamQuestionService.java

@@ -1,16 +1,18 @@
 package cn.com.qmth.stmms.biz.exam.service;
 
-import java.util.List;
-import java.util.Set;
-
 import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
 import cn.com.qmth.stmms.common.enums.ObjectivePolicy;
 
+import java.util.List;
+import java.util.Set;
+
 public interface ExamQuestionService {
 
     ExamQuestion save(ExamQuestion question);
 
+    ExamQuestion saveAndFlush(ExamQuestion question);
+
     void save(List<ExamQuestion> questionList);
 
     ExamQuestionSearchQuery findByQuery(ExamQuestionSearchQuery query);
@@ -72,4 +74,6 @@ public interface ExamQuestionService {
 
     Set<String> FindSubjectCodeByExamIdAndObjectiveAndGroupNumberIsNull(int examId, boolean objective);
 
+    void resetByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(Integer examId, String subjectCode, boolean objective,
+            Integer number);
 }

+ 5 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamStudentService.java

@@ -143,5 +143,9 @@ public interface ExamStudentService {
     public void updateSubjectiveStatusAndTimeAndInspectorId(Integer studentId, SubjectiveStatus status,
             Date inspectTime, Integer inspectorId);
 
-    public List<ExamStudent> findByExamIdAndStudentCode(int examId, String studentCode);
+    public List<ExamStudent> findByExamIdAndStudentCodeAndSubjectCode(int examId, String studentCode, String subjectCode);
+
+    long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus... status);
+
+    public ExamStudent randomStudent(Integer examId, String code);
 }

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/ExamSubjectService.java

@@ -43,4 +43,6 @@ public interface ExamSubjectService {
 
     void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList);
 
+    void updateTrialCount(int examId, String subjectCode, int trialCount);
+
 }

+ 5 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/InspectedService.java

@@ -1,18 +1,19 @@
 package cn.com.qmth.stmms.biz.exam.service;
 
+import java.util.List;
+
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
+import cn.com.qmth.stmms.common.enums.SelectiveStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
-import java.util.List;
-
 public interface InspectedService {
 
     List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore);
+            Double mainStartScore, Double mainEndScore, Double questionScore, SelectiveStatus selectiveStatus);
 
     Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore);
+            Double mainStartScore, Double mainEndScore, Double questionScore, SelectiveStatus selectiveStatus);
 
     void releaseByUserId(Integer examId, String subjectCode, Integer userId);
 

+ 3 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/MarkGroupService.java

@@ -36,14 +36,10 @@ public interface MarkGroupService {
 
     void updateMarkMode(int examId, String subjectCode, Integer number, MarkMode markMode);
 
-    void updateTrialCount(int examId, String subjectCode, Integer number, Integer trialCount);
-
     void updateSheetView(int examId, String subjectCode, Integer number, boolean sheetView);
 
     void updateEnableAllZero(int examId, String subjectCode, Integer number, boolean enableAllZero);
 
-    double sumTotalScore(Integer examId, String subjectCode);
-
     boolean updateStatus(int examId, String subjectCode, Integer number, MarkStatus newStatus,
             MarkStatus... currentStatus);
 
@@ -51,12 +47,12 @@ public interface MarkGroupService {
 
     List<MarkGroup> findByExamAndSubjectAndStatus(Integer examId, String subjectCode, MarkStatus... status);
 
-    boolean needTrialLibrary(Integer examId, String subjectCode, Integer number);
-
-    long countByExamAndStatus(Integer examId, MarkStatus... status);
+    long countByExamAndSubjectAndStatus(Integer examId, String subjectCode, MarkStatus... status);
 
     boolean validateStatus(Integer examId, String subjectCode, Integer number, MarkStatus... status);
 
     int findMaxNumberByExamIdAndSubjectCode(int examId, String subjectCode);
 
+    List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective);
+
 }

+ 19 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/SelectiveGroupService.java

@@ -0,0 +1,19 @@
+package cn.com.qmth.stmms.biz.exam.service;
+
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+
+public interface SelectiveGroupService {
+
+    SelectiveGroup save(SelectiveGroup s);
+
+    void save(List<SelectiveGroup> list);
+
+    SelectiveGroup findOne(int examId, String subjectCode, int mainNumber);
+
+    List<SelectiveGroup> findByExamIdAndSubjectCode(int examId, String code);
+
+    void deleteByExamIdAndSubjectCode(int examId, String subjectCode);
+
+}

+ 80 - 40
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamQuestionServiceImpl.java

@@ -8,7 +8,6 @@ import cn.com.qmth.stmms.biz.exam.service.ExamService;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamQuestionSearchQuery;
 import cn.com.qmth.stmms.common.enums.ObjectivePolicy;
 import cn.com.qmth.stmms.common.enums.ObjectiveStatus;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Sort;
@@ -21,7 +20,7 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
-
+import java.math.BigDecimal;
 import java.util.*;
 
 @Service
@@ -39,6 +38,12 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
         return questionDao.save(question);
     }
 
+    @Transactional
+    @Override
+    public ExamQuestion saveAndFlush(ExamQuestion question) {
+        return questionDao.saveAndFlush(question);
+    }
+
     @Transactional
     @Override
     public void save(List<ExamQuestion> questionList) {
@@ -67,56 +72,66 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
 
     @Override
     public List<ExamQuestion> findByExamAndSubjectAndObjective(Integer examId, String subjectCode, boolean objective) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
+        return questionSort(questionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective));
+    }
+
+    private List<ExamQuestion> questionSort(List<ExamQuestion> list) {
+        list.sort((o1, o2) -> {
+            int i = o1.getMainNumber() - o2.getMainNumber();
+            if (i == 0) {
+                if (o1.getSubNumber().contains("-")) {
+                    String[] o1s = o1.getSubNumber().split("-");
+                    String[] o2s = o2.getSubNumber().split("-");
+                    int j = Integer.parseUnsignedInt(o1s[0]) - Integer.parseUnsignedInt(o2s[0]);
+                    if (j == 0) {
+                        return Integer.parseUnsignedInt(o1s[1]) - Integer.parseUnsignedInt(o2s[1]);
+                    } else {
+                        return j;
+                    }
+                } else {
+                    return Integer.parseUnsignedInt(o1.getSubNumber()) - Integer.parseUnsignedInt(o2.getSubNumber());
+                }
+            }
+            return i;
+        });
+        return list;
     }
 
     @Override
     public List<ExamQuestion> findByExamAndSubjectAndObjectiveGroupByNumber(Integer examId, String subjectCode,
             boolean objective) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveGroupByNumber(examId, subjectCode, objective);
+        return questionSort(
+                questionDao.findByExamIdAndSubjectCodeAndObjectiveGroupByNumber(examId, subjectCode, objective));
     }
 
     @Override
     public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndPaperType(Integer examId, String subjectCode,
             boolean objective, String paperType) {
-        List<ExamQuestion> list = questionDao.findByExamIdAndSubjectCodeAndObjectiveAndPaperType(examId, subjectCode,
-                objective, paperType, new Sort(Direction.ASC, "mainNumber", "subNumber"));
-        if (objective) {
-            Collections.sort(list, new Comparator<ExamQuestion>() {
-
-                @Override
-                public int compare(ExamQuestion o1, ExamQuestion o2) {
-                    int i = o1.getMainNumber() - o2.getMainNumber();
-                    if (i == 0) {
-                        return Integer.parseUnsignedInt(o1.getSubNumber())
-                                - Integer.parseUnsignedInt(o2.getSubNumber());
-                    }
-                    return i;
-                }
-            });
-        }
-        return list;
+        return questionSort(questionDao
+                .findByExamIdAndSubjectCodeAndObjectiveAndPaperType(examId, subjectCode, objective, paperType,
+                        new Sort(Direction.ASC, "mainNumber", "subNumber")));
     }
 
     @Override
     public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndGroupNumber(Integer examId, String subjectCode,
             boolean objective, Integer groupNumber) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(examId, subjectCode, objective,
-                groupNumber);
+        return questionSort(questionDao
+                .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(examId, subjectCode, objective, groupNumber));
     }
 
     @Override
-    public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndGroupNumberNotEqual(Integer examId,
-            String subjectCode, boolean objective, Integer groupNumber) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveAndGroupNumberNotEqual(examId, subjectCode, objective,
-                groupNumber);
+    public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndGroupNumberNotEqual(Integer examId, String subjectCode,
+            boolean objective, Integer groupNumber) {
+        return questionSort(questionDao
+                .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumberNotEqual(examId, subjectCode, objective,
+                        groupNumber));
     }
 
     @Override
     public List<ExamQuestion> findByExamAndSubjectAndObjectiveAndMainNumber(Integer examId, String subjectCode,
             boolean objective, Integer mainNumber) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
-                mainNumber);
+        return questionSort(questionDao
+                .findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective, mainNumber));
     }
 
     @Override
@@ -124,6 +139,10 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
         checkQuery(query);
         Page<ExamQuestion> result = questionDao.findAll(buildSpecification(query), query);
         fillResult(result, query);
+        if (result != null) {
+            List<ExamQuestion> list = new ArrayList<>(query.getResult());
+            query.setResult(questionSort(list));
+        }
         return query;
     }
 
@@ -135,8 +154,8 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     @Override
     public long countByExamAndSubjectAndObjectiveAndMainNumber(Integer examId, String subjectCode, boolean objective,
             Integer mainNumber) {
-        return questionDao.countByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
-                mainNumber);
+        return questionDao
+                .countByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective, mainNumber);
     }
 
     private Specification<ExamQuestion> buildSpecification(final ExamQuestionSearchQuery query) {
@@ -171,8 +190,9 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
                 if (query.getMainNumber() != null) {
                     predicates.add(cb.equal(root.get("mainNumber"), query.getMainNumber()));
                 }
-                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
-                        .size()]));
+                return predicates.isEmpty() ?
+                        cb.conjunction() :
+                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
             }
         };
     }
@@ -191,15 +211,17 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     @Override
     public long countByExamAndSubjectAndObjectiveAndMainNumberAndPaperType(Integer examId, String subjectCode,
             boolean objective, Integer mainNumber, String paperType) {
-        return questionDao.countByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
-                mainNumber, paperType);
+        return questionDao
+                .countByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective, mainNumber,
+                        paperType);
     }
 
     @Override
     public long countByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(Integer examId, String subjectCode,
             boolean objective, Integer mainNumber, String subNumber) {
-        return questionDao.countByExamIdAndSubjectCodeAndObjectiveAndMainNumberAndSubNumber(examId, subjectCode,
-                objective, mainNumber, subNumber);
+        return questionDao
+                .countByExamIdAndSubjectCodeAndObjectiveAndMainNumberAndSubNumber(examId, subjectCode, objective,
+                        mainNumber, subNumber);
     }
 
     @Transactional
@@ -220,18 +242,28 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     @Override
     public ExamQuestion findByExamAndSubjectAndObjectiveAndMainNumberAndSubNumber(Integer examId, String subjectCode,
             boolean objective, Integer mainNumber, String subNumber) {
-        return questionDao.findByExamIdAndSubjectCodeAndObjectiveAndMainNumberAndSubNumber(examId, subjectCode,
-                objective, mainNumber, subNumber);
+        return questionDao
+                .findByExamIdAndSubjectCodeAndObjectiveAndMainNumberAndSubNumber(examId, subjectCode, objective,
+                        mainNumber, subNumber);
     }
 
     @Override
-    public List<ExamQuestion> findMainByExamAndSubjectAndObjective(Integer examId, String subjectCode, boolean objective) {
+    public List<ExamQuestion> findMainByExamAndSubjectAndObjective(Integer examId, String subjectCode,
+            boolean objective) {
         List<ExamQuestion> list = new ArrayList<ExamQuestion>();
         Set<Integer> mainNumbers = new LinkedHashSet<>();
         List<ExamQuestion> all = questionDao.findByExamIdAndSubjectCodeAndObjective(examId, subjectCode, objective);
         for (ExamQuestion q : all) {
             if (!mainNumbers.contains(q.getMainNumber())) {
                 mainNumbers.add(q.getMainNumber());
+                List<ExamQuestion> questions = questionDao
+                        .findByExamIdAndSubjectCodeAndObjectiveAndMainNumber(examId, subjectCode, objective,
+                                q.getMainNumber());
+                BigDecimal totalScore = BigDecimal.ZERO;
+                for (ExamQuestion examQuestion : questions) {
+                    totalScore = totalScore.add(BigDecimal.valueOf(examQuestion.getTotalScore()));
+                }
+                q.setTotalScore(totalScore.doubleValue());
                 list.add(q);
             }
         }
@@ -259,4 +291,12 @@ public class ExamQuestionServiceImpl extends BaseQueryService<ExamQuestion> impl
     public Set<String> FindSubjectCodeByExamIdAndObjectiveAndGroupNumberIsNull(int examId, boolean objective) {
         return questionDao.FindSubjectCodeByExamIdAndObjectiveAndGroupNumberIsNull(examId, objective);
     }
+
+    @Override
+    @Transactional
+    public void resetByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(Integer examId, String subjectCode,
+            boolean objective, Integer groupNumber) {
+        questionDao.resetByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(examId, subjectCode, objective, groupNumber);
+    }
+
 }

+ 42 - 11
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamStudentServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.exam.service.impl;
 
+import java.math.BigDecimal;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -54,6 +55,7 @@ import cn.com.qmth.stmms.biz.utils.PictureConfigTransform;
 import cn.com.qmth.stmms.biz.utils.PictureTag;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
+import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
 
 @Service
 public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implements ExamStudentService {
@@ -731,13 +733,11 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     public ExamStudent randomUnTrialStudent(Integer examId, String subjectCode, Integer groupNumber) {
         ExamStudentSearchQuery query = new ExamStudentSearchQuery();
         query.setPageNumber(1);
-        query.setPageSize(200);
+        query.setPageSize(1);
         query.setSort(new Sort(Direction.ASC, "uploadTime", "id"));
-        List<ExamStudent> list = studentDao.findUnTrialStudent(examId, subjectCode, groupNumber, query);
-        if (list.isEmpty()) {
-            return null;
-        }
-        return list.get(RandomUtils.nextInt(list.size()));
+        List<ExamStudent> list = studentDao.findUnTrialStudent(examId, subjectCode, groupNumber,
+                SubjectiveStatus.TRIAL, query);
+        return list.isEmpty() ? null : list.get(0);
     }
 
     @Override
@@ -940,14 +940,14 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
         }
         DecimalFormat format = new DecimalFormat("####.###");
         // 从考生主观题得分中拆解出本大题得分
-        double score = 0;
+        BigDecimal score = BigDecimal.ZERO;
         List<Double> details = new ArrayList<>();
         int i = -1;
         for (ExamQuestion question : questions) {
             i++;
             if (group.getNumber().equals(question.getGroupNumber())) {
                 double value = scoreList.size() > i ? scoreList.get(i).getScore() : 0;
-                score += value;
+                score = score.add(BigDecimal.valueOf(value));
                 details.add(value);
             }
         }
@@ -969,7 +969,7 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
         MarkLibrary selected = null;
         List<MarkLibrary> libraries = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
         for (MarkLibrary library : libraries) {
-            if (checkScore(library, score, details)) {
+            if (checkScore(library, score.doubleValue(), details)) {
                 selected = library;
                 break;
             }
@@ -1032,7 +1032,38 @@ public class ExamStudentServiceImpl extends BaseQueryService<ExamStudent> implem
     }
 
     @Override
-    public List<ExamStudent> findByExamIdAndStudentCode(int examId, String studentCode) {
-        return studentDao.findByExamIdAndStudentCode(examId, studentCode);
+    public List<ExamStudent> findByExamIdAndStudentCodeAndSubjectCode(int examId, String studentCode, String subjectCode) {
+        return studentDao.findByExamIdAndStudentCodeAndSubjectCode(examId, studentCode, subjectCode);
+    }
+
+    @Override
+    public long countByExamIdAndSubjectCodeAndStatus(int examId, String subjectCode, SubjectiveStatus... status) {
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(subjectCode);
+        for (SubjectiveStatus subjectiveStatus : status) {
+            query.addStatus(subjectiveStatus);
+        }
+        return countByQuery(query);
+    }
+
+    @Override
+    public ExamStudent randomStudent(Integer examId, String code) {
+        ExamStudentSearchQuery query = new ExamStudentSearchQuery();
+        query.setExamId(examId);
+        query.setSubjectCode(code);
+        query.setAbsent(false);
+        query.setUpload(true);
+        query.setBreach(false);
+        query.addStatus(SubjectiveStatus.UNMARK);
+        query.setPageNumber(1);
+        query.setPageSize(200);
+        query.setSort(new Sort(Direction.ASC, "uploadTime", "id"));
+        List<ExamStudent> list = findByQuery(query).getResult();
+        if (list.isEmpty()) {
+            return null;
+        }
+        return list.get(RandomUtils.nextInt(list.size()));
+
     }
 }

+ 7 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/ExamSubjectServiceImpl.java

@@ -6,6 +6,7 @@ import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
 import cn.com.qmth.stmms.biz.mark.model.PictureConfigItem;
+
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
@@ -17,6 +18,7 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
+
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -196,7 +198,12 @@ public class ExamSubjectServiceImpl extends BaseQueryService<ExamSubject> implem
     public void updateSliceConfig(Integer examId, String subjectCode, List<PictureConfigItem> configList) {
         subjectDao.updateSliceConfig(examId, subjectCode,
                 configList != null ? StringUtils.join(configList, PictureConfigItem.DB_ITEM_JOINER) : "");
+    }
 
+    @Transactional
+    @Override
+    public void updateTrialCount(int examId, String subjectCode, int trialCount) {
+        subjectDao.updateTrialCount(examId, subjectCode, trialCount);
     }
 
 }

+ 83 - 37
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/InspectedServiceImpl.java

@@ -1,23 +1,30 @@
 package cn.com.qmth.stmms.biz.exam.service.impl;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
 import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.InspectedService;
+import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
+import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
 import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
+import cn.com.qmth.stmms.common.enums.SelectiveStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import java.util.ArrayList;
-import java.util.List;
 
 @Service
 public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implements InspectedService {
@@ -31,22 +38,27 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     @Autowired
     private UserService userService;
 
+    @Autowired
+    private MarkGroupService groupService;
+
+    @Autowired
+    private SelectiveGroupService selectiveGroupService;
+
     @SuppressWarnings("unchecked")
     @Override
     public List<ExamStudent> findByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore) {
-        StringBuilder dataSql = new StringBuilder("select distinct s.id , s.inspect_time "
-                + " from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
+            Double mainStartScore, Double mainEndScore, Double questionScore, SelectiveStatus selectiveStatus) {
+        StringBuilder dataSql = new StringBuilder("select s.id from eb_exam_student s ");
         StringBuilder limitSql = new StringBuilder(" limit :offset,:pageSize");
-        Query dataQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, dataSql,
-                limitSql);
+        Query dataQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore,
+                selectiveStatus, dataSql, limitSql);
         dataQuery.setParameter("offset", (query.getPageNumber() - 1) * query.getPageSize());
         dataQuery.setParameter("pageSize", query.getPageSize());
-        List<Object[]> list = dataQuery.getResultList();
+        List<Integer> list = dataQuery.getResultList();
         List<ExamStudent> resultList = new ArrayList<ExamStudent>();
         if (list != null && !list.isEmpty()) {
-            for (Object[] array : list) {
-                ExamStudent e = studentService.findById((Integer) array[0]);
+            for (Integer id : list) {
+                ExamStudent e = studentService.findById(id);
                 if (e.getInspectorId() != null) {
                     e.setInspector(userService.findById(e.getInspectorId()));
                 }
@@ -58,8 +70,8 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     }
 
     private Query getQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore, StringBuilder dataSql,
-            StringBuilder limitSql) {
+            Double mainStartScore, Double mainEndScore, Double questionScore, SelectiveStatus selectiveStatus,
+            StringBuilder dataSql, StringBuilder limitSql) {
         StringBuilder whereSql = new StringBuilder(" WHERE s.is_upload = 1 and s.is_absent = 0 and s.is_breach = 0 ");
         if (query.getExamId() != null) {
             whereSql.append(" and s.exam_id = :examId");
@@ -73,22 +85,43 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
             whereSql.append(" and s.subjective_status IN ('MARKED','INSPECTED')");
         }
         if (query.getStartScore() != null) {
-            whereSql.append(" and (s.objective_score+s.subjective_score) >= :startScore");
+            whereSql.append(" and (cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3))) >= :startScore");
         }
         if (query.getEndScore() != null) {
-            whereSql.append(" and (s.objective_score+s.subjective_score) <= :endScore");
+            whereSql.append(" and (cast(s.objective_score as decimal(10,3))+cast(s.subjective_score as decimal(10,3))) <= :endScore");
         }
-        if (mainNumber != null) {
-            whereSql.append(" and e.main_number = :mainNumber");
-        }
-        if (mainStartScore != null) {
-            whereSql.append(" and e.main_score >= :mainStartScore");
-        }
-        if (mainEndScore != null) {
-            whereSql.append(" and e.main_score <= :mainEndScore");
+        if (StringUtils.isNotBlank(query.getSecretNumber())) {
+            whereSql.append(" and s.secret_number = :secretNumber");
         }
-        if (questionScore != null) {
-            whereSql.append(" and e.score = :questionScore");
+        if (mainNumber != null || mainStartScore != null || mainEndScore != null || questionScore != null) {
+            whereSql.append(" and exists (select e.student_id from eb_subjective_score e where e.student_id = s.id ");
+            if (mainNumber != null) {
+                whereSql.append(" and e.main_number = :mainNumber");
+            }
+            if (mainStartScore != null) {
+                whereSql.append(" and e.main_score >= :mainStartScore");
+            }
+            if (mainEndScore != null) {
+                whereSql.append(" and e.main_score <= :mainEndScore");
+            }
+            if (questionScore != null) {
+                whereSql.append(" and e.score = :questionScore");
+            }
+            whereSql.append(" ) ");
+        }
+        // 全部选做题为未选做
+        List<MarkGroup> groups = groupService.findByExamAndSubjectAndSelective(query.getExamId(),
+                query.getSubjectCode(), true);
+        List<SelectiveGroup> selectiveGroups = selectiveGroupService.findByExamIdAndSubjectCode(query.getExamId(),
+                query.getSubjectCode());
+        if (selectiveStatus != null && SelectiveStatus.UN_SELECTIVE.equals(selectiveStatus) && !groups.isEmpty()
+                && !selectiveGroups.isEmpty()) {
+            whereSql.append(" and not exists (select e.student_id from eb_subjective_score e where e.student_id = s.id and e.group_number in (:groupNumbers) and e.group_score != -1 )");
+        }
+        // 选做题多选做
+        if (selectiveStatus != null && SelectiveStatus.MUTI_SELECTIVE.equals(selectiveStatus) && !groups.isEmpty()
+                && !selectiveGroups.isEmpty()) {
+            whereSql.append(" and (select count(distinct ss.group_number) from eb_subjective_score ss where ss.student_id = s.id and ss.group_number in (:groupNumbers) and ss.group_score = -1 )< :unSelectiveCount ");
         }
         dataSql.append(whereSql);
         StringBuilder orderSql = new StringBuilder(" order by s.inspect_time desc ");
@@ -125,16 +158,29 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
         if (questionScore != null) {
             dataQuery.setParameter("questionScore", questionScore);
         }
+        if (StringUtils.isNotBlank(query.getSecretNumber())) {
+            dataQuery.setParameter("secretNumber", query.getSecretNumber());
+        }
+        if (selectiveStatus != null && !groups.isEmpty() && !selectiveGroups.isEmpty()) {
+            List<Integer> groupNumbers = new ArrayList<Integer>();
+            for (int i = 0; i < groups.size(); i++) {
+                groupNumbers.add(groups.get(i).getNumber());
+            }
+            dataQuery.setParameter("groupNumbers", groupNumbers);
+            if (SelectiveStatus.MUTI_SELECTIVE.equals(selectiveStatus)) {
+                int unSelectiveCount = selectiveGroups.size() - selectiveGroups.get(0).getSelectiveCount();
+                dataQuery.setParameter("unSelectiveCount", unSelectiveCount);
+            }
+        }
         return dataQuery;
     }
 
     @Override
     public Integer countByQuery(ExamStudentSearchQuery query, SubjectiveStatus status, Integer mainNumber,
-            Double mainStartScore, Double mainEndScore, Double questionScore) {
-        StringBuilder countSql = new StringBuilder("select count(distinct s.id) "
-                + "from eb_exam_student s left join eb_subjective_score e on e.student_id = s.id ");
-        Query countQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore, countSql,
-                null);
+            Double mainStartScore, Double mainEndScore, Double questionScore, SelectiveStatus selectiveStatus) {
+        StringBuilder countSql = new StringBuilder("select count(s.id) from eb_exam_student s ");
+        Query countQuery = getQuery(query, status, mainNumber, mainStartScore, mainEndScore, questionScore,
+                selectiveStatus, countSql, null);
         Object singleResult = countQuery.getResultList().get(0);
         Integer count = singleResult == null ? 0 : Integer.valueOf(singleResult.toString());
         return count;
@@ -179,4 +225,4 @@ public class InspectedServiceImpl extends BaseQueryService<ExamStudent> implemen
     private String getKey(ExamStudent student) {
         return student.getExamId() + "_" + student.getSubjectCode();
     }
-}
+}

+ 7 - 19
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/MarkGroupServiceImpl.java

@@ -70,12 +70,6 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         groupDao.updateArbitrateThreshold(examId, subjectCode, number, arbitrateThreshold);
     }
 
-    @Transactional
-    @Override
-    public void updateTrialCount(int examId, String subjectCode, Integer number, Integer trialCount) {
-        groupDao.updateTrialCount(examId, subjectCode, number, trialCount);
-    }
-
     @Transactional
     @Override
     public void updateSheetView(int examId, String subjectCode, Integer number, boolean sheetView) {
@@ -95,11 +89,6 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return groupDao.updateStatus(examId, subjectCode, number, newStatus, currentStatus) > 0;
     }
 
-    @Override
-    public boolean needTrialLibrary(Integer examId, String subjectCode, Integer number) {
-        return groupDao.countByStatusAndTrailCount(examId, subjectCode, number, MarkStatus.TRIAL) > 0;
-    }
-
     @Override
     public MarkGroup findOne(int examId, String subjectCode, int number) {
         MarkGroupPK pk = new MarkGroupPK();
@@ -110,8 +99,8 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
     }
 
     @Override
-    public long countByExamAndStatus(Integer examId, MarkStatus... status) {
-        return groupDao.countByExamIdAndStatus(examId, status);
+    public long countByExamAndSubjectAndStatus(Integer examId, String subjectCode, MarkStatus... status) {
+        return groupDao.countByExamIdAndSubjectCodeAndStatus(examId, subjectCode, status);
     }
 
     @Override
@@ -149,12 +138,6 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return groupDao.countByExamId(examId);
     }
 
-    @Override
-    public double sumTotalScore(Integer examId, String subjectCode) {
-        Double score = groupDao.sumTotalScore(examId, subjectCode);
-        return score != null ? score.doubleValue() : 0d;
-    }
-
     @Override
     public boolean validateStatus(Integer examId, String subjectCode, Integer number, MarkStatus... status) {
         return groupDao.countByExamIdAndSubjectCodeAndNumberAndStatus(examId, subjectCode, number, status) > 0;
@@ -172,4 +155,9 @@ public class MarkGroupServiceImpl extends BaseQueryService<MarkGroup> implements
         return number;
     }
 
+    @Override
+    public List<MarkGroup> findByExamAndSubjectAndSelective(Integer examId, String subjectCode, boolean selective) {
+        return groupDao.findByExamAndSubjectAndSelective(examId, subjectCode, selective);
+    }
+
 }

+ 48 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/SelectiveGroupServiceImpl.java

@@ -0,0 +1,48 @@
+package cn.com.qmth.stmms.biz.exam.service.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.exam.dao.SelectiveGroupDao;
+import cn.com.qmth.stmms.biz.exam.model.SelectiveGroup;
+import cn.com.qmth.stmms.biz.exam.service.SelectiveGroupService;
+
+@Service("selectiveGroupService")
+public class SelectiveGroupServiceImpl extends BaseQueryService<SelectiveGroup> implements SelectiveGroupService {
+
+    @Autowired
+    private SelectiveGroupDao selectiveGroupDao;
+
+    @Transactional
+    @Override
+    public SelectiveGroup save(SelectiveGroup group) {
+        return selectiveGroupDao.save(group);
+    }
+
+    @Transactional
+    @Override
+    public void save(List<SelectiveGroup> list) {
+        selectiveGroupDao.save(list);
+    }
+
+    @Override
+    public SelectiveGroup findOne(int examId, String subjectCode, int mainNumber) {
+        return selectiveGroupDao.findOne(examId, subjectCode, mainNumber);
+    }
+
+    @Override
+    public List<SelectiveGroup> findByExamIdAndSubjectCode(int examId, String code) {
+        return selectiveGroupDao.findByExamIdAndSubjectCode(examId, code);
+    }
+
+    @Transactional
+    @Override
+    public void deleteByExamIdAndSubjectCode(int examId, String subjectCode) {
+        selectiveGroupDao.deleteByExamIdAndSubjectCode(examId, subjectCode);
+    }
+
+}

+ 10 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/exam/service/impl/SubjectiveScoreServiceImpl.java

@@ -81,26 +81,29 @@ public class SubjectiveScoreServiceImpl extends BaseQueryService<SubjectiveScore
                 // predicates.add(predicate);
                 // }
                 if (query.getMainStartScore() != null) {
-                    Predicate predicate = cb.greaterThanOrEqualTo(root.get("mainScore").as(Double.class),
-                            query.getMainStartScore());
+                    Predicate predicate = cb
+                            .greaterThanOrEqualTo(root.get("mainScore").as(Double.class), query.getMainStartScore());
                     predicates.add(predicate);
                 }
                 if (query.getMainEndScore() != null) {
-                    Predicate predicate = cb.lessThanOrEqualTo(root.get("mainScore").as(Double.class),
-                            query.getMainEndScore());
+                    Predicate predicate = cb
+                            .lessThanOrEqualTo(root.get("mainScore").as(Double.class), query.getMainEndScore());
                     predicates.add(predicate);
                 }
                 if (query.getScore() != null) {
                     predicates.add(cb.equal(root.get("score"), query.getScore()));
                 }
-                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
-                        .size()]));
+                return predicates.isEmpty() ?
+                        cb.conjunction() :
+                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
             }
         };
     }
 
     @Override
     public List<SubjectiveScore> findByStudentIdAndGroupNumber(Integer studentId, Integer groupNumber) {
-        return scoreDao.findByStudentIdAndGroupNumber(studentId, groupNumber);
+        List<SubjectiveScore> list = scoreDao.findByStudentIdAndGroupNumber(studentId, groupNumber);
+        list.sort(null);
+        return list;
     }
 }

+ 3 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FileType.java

@@ -5,9 +5,9 @@ package cn.com.qmth.stmms.biz.file.enums;
  */
 public enum FileType {
 
-    SHEET("原图", "sheet/%d/%s/%s-%d.%s"), SLICE("裁切图", "slice/%d/%s/%s-%d.%s"), JSON("作答内容",
-            "json/%d/%s/%s.%s"), PACKAGE("签到表", "package/%d/%s/%d.%s"), PAPER("试卷", "paper/%d/%s.%s"), ANSWER("标答",
-            "answer/%d/%s.%s"), CARD("题卡", "card/%d/%s.%s");
+    SHEET("原图", "sheet/%d/%s/%s-%d.%s"), SLICE("裁切图", "slice/%d/%s/%s-%d.%s"), JSON("作答内容", "json/%d/%s/%s.%s"), PACKAGE(
+            "签到表", "package/%d/%s/%d.%s"), PAPER("试卷", "paper/%d/%s.%s"), ANSWER("标答", "answer/%d/%s.%s"), CARD("题卡",
+            "card/%d/%s.%s"), EXCHANGE("文件", "exchange/%s");
 
     private String name;
 

+ 11 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/FileService.java

@@ -9,6 +9,8 @@ public interface FileService {
 
     String getFileServer();
 
+    String getRandomFileServer();
+
     byte[] downloadSheet(int examId, String examNumber, int index) throws Exception;
 
     byte[] downloadSlice(int examId, String secretNumber, int index) throws Exception;
@@ -31,6 +33,8 @@ public interface FileService {
 
     void uploadCard(InputStream ins, String md5, int examId, String subjectCode, FormatType type) throws Exception;
 
+    void uploadExchange(InputStream ins, String md5, String name) throws Exception;
+
     String getSheetUri(int examId, String examNumber, int index);
 
     List<String> getSheetUris(int examId, String examNumber, int start, int end);
@@ -53,9 +57,14 @@ public interface FileService {
 
     String getCardUri(int examId, String subjectCode, FormatType type);
 
+    String getExchangeUri(String name);
+
     boolean sheetExist(int examId, String examNumber, int index);
 
-    boolean sliceExist(int examId, String secreNumber, int index);
+    boolean sliceExist(int examId, String secretNumber, int index);
+
+    boolean jsonExist(int examId, String secretNumber);
+
+    byte[] downloadJson(int examId, String secretNumber) throws Exception;
 
-    boolean jsonExist(int examId, String secreNumber);
 }

+ 84 - 24
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java

@@ -1,20 +1,25 @@
 package cn.com.qmth.stmms.biz.file.service.impl;
 
-import cn.com.qmth.stmms.biz.file.enums.FileType;
-import cn.com.qmth.stmms.biz.file.enums.FormatType;
-import cn.com.qmth.stmms.biz.file.service.FileService;
-import cn.com.qmth.stmms.biz.file.store.FileStore;
-import cn.com.qmth.stmms.biz.file.store.impl.DiskStore;
-import cn.com.qmth.stmms.biz.file.store.impl.OssStore;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.commons.lang.math.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.io.InputStream;
-import java.util.LinkedList;
-import java.util.List;
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
+import cn.com.qmth.stmms.biz.file.enums.FileType;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.file.store.FileStore;
+import cn.com.qmth.stmms.biz.file.store.impl.DiskStore;
+import cn.com.qmth.stmms.biz.file.store.impl.OssStore;
 
 @Service("fileService")
 public class FileServiceImpl implements FileService, InitializingBean, DisposableBean {
@@ -23,8 +28,12 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     private static final int DEFAULT_SUFFIX_LENGTH = 3;
 
-    @Value("${file.server}")
-    private String fileServer;
+    public static final String SERVER_SPLIT = ",";
+
+    @Autowired
+    private SystemCache systemCache;
+
+    private List<String> fileServers;
 
     @Value("${file.store}")
     private String fileStore;
@@ -46,11 +55,32 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     @Override
     public String getFileServer() {
-        return fileServer;
+        return getFileServers().get(0);
+
+    }
+
+    @Override
+    public String getRandomFileServer() {
+        return getFileServers().get(RandomUtils.nextInt(fileServers.size()));
+    }
+
+    public List<String> getFileServers() {
+        fileServers = new ArrayList<>();
+        String[] servers = StringUtils.split(systemCache.getFileServer(), SERVER_SPLIT);
+        for (String server : servers) {
+            server = StringUtils.trimToNull(server);
+            if (server != null) {
+                if (!server.endsWith("/")) {
+                    server = server.concat("/");
+                }
+                fileServers.add(server);
+            }
+        }
+        return fileServers;
     }
 
-    public void setFileServer(String fileServer) {
-        this.fileServer = fileServer;
+    public void setFileServers(List<String> fileServers) {
+        this.fileServers = fileServers;
     }
 
     public String getFileStore() {
@@ -216,17 +246,30 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     @Override
     public void afterPropertiesSet() {
-        fileServer = StringUtils.trimToNull(fileServer);
+        String fileServerString = systemCache.getFileServer();
         fileStore = StringUtils.trimToNull(fileStore);
-        if (fileServer == null) {
+        if (fileServerString == null) {
             throw new RuntimeException("invald property: ${file.server} should not be empty");
         }
         if (fileStore == null) {
             throw new RuntimeException("invald property: ${file.store} should not be empty");
         }
-        if (!fileServer.endsWith("/")) {
-            fileServer = fileServer.concat("/");
+        // 按逗号拆分多个文件服务器地址
+        fileServers = new ArrayList<>();
+        String[] servers = StringUtils.split(fileServerString, SERVER_SPLIT);
+        for (String server : servers) {
+            server = StringUtils.trimToNull(server);
+            if (server != null) {
+                if (!server.endsWith("/")) {
+                    server = server.concat("/");
+                }
+                fileServers.add(server);
+            }
         }
+        if (fileServers.isEmpty()) {
+            throw new RuntimeException("invald property: ${file.server} should not be empty");
+        }
+        // 按前缀解析文件存储引擎
         if (fileStore.startsWith("oss")) {
             store = new OssStore(fileStore);
         } else {
@@ -239,18 +282,35 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
         store.close();
     }
 
+    @Override
+    public byte[] downloadJson(int examId, String secretNumber) throws Exception {
+        return store.read(getJsonUri(examId, secretNumber));
+    }
+
+    @Override
+    public void uploadExchange(InputStream ins, String md5, String name) throws Exception {
+        store.write(getExchangeUri(name), ins, md5);
+    }
+
+    @Override
+    public String getExchangeUri(String name) {
+        return FileType.EXCHANGE.getPath(name);
+    }
+
     public static void main(String[] args) throws Exception {
         FileServiceImpl service = new FileServiceImpl();
-        service.fileServer = "123";
+        // service.fileServerString = "123";
+
         service.fileStore = "oss://LTAI4FnJ2pgV6aGceYcCkeEi:ktrMEVE7PfoxRPeJUPDFeygOIH4aU7@qmth-test.oss-cn-shenzhen.aliyuncs.com";
         service.afterPropertiesSet();
 
-        //DiskStore ds = new DiskStore("/Users/luoshi/Downloads");
-        //String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(ds.read("123456.jpg")));
-        //        service.uploadSheet(new FileInputStream("/Users/luoshi/Downloads/123456.jpg"),
-        //                "7e9b368ff5da88ff2413c2c9083c481d", 1, "123456", 1);
+        // DiskStore ds = new DiskStore("/Users/luoshi/Downloads");
+        // String md5 =
+        // BinaryUtil.toBase64String(BinaryUtil.calculateMd5(ds.read("123456.jpg")));
+        // service.uploadSheet(new
+        // FileInputStream("/Users/luoshi/Downloads/123456.jpg"),
+        // "7e9b368ff5da88ff2413c2c9083c481d", 1, "123456", 1);
         service.downloadSheet(1, "16110003", 1);
         System.out.println("success");
     }
-
 }

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/store/impl/OssStore.java

@@ -57,6 +57,8 @@ public class OssStore implements FileStore {
     public void write(String path, InputStream ins, String md5) throws Exception {
         ObjectMetadata metadata = new ObjectMetadata();
         metadata.setContentMD5(BinaryUtil.toBase64String(Encodes.decodeHex(md5)));
+        // 设置内容被下载时网页的缓存行为。
+        metadata.setCacheControl("no-cache");
         ossClient.putObject(bucket, path, ins, metadata);
     }
 

+ 6 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/ArbitrateHistoryDao.java

@@ -12,8 +12,8 @@ import org.springframework.data.jpa.repository.Query;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
 import cn.com.qmth.stmms.common.enums.LibraryStatus;
 
-public interface ArbitrateHistoryDao
-        extends JpaRepository<ArbitrateHistory, Integer>, JpaSpecificationExecutor<ArbitrateHistory> {
+public interface ArbitrateHistoryDao extends JpaRepository<ArbitrateHistory, Integer>,
+        JpaSpecificationExecutor<ArbitrateHistory> {
 
     List<ArbitrateHistory> findByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode,
             Integer groupNumber, Pageable page);
@@ -32,4 +32,8 @@ public interface ArbitrateHistoryDao
     @Query("delete ArbitrateHistory m where m.studentId=?1")
     void deleteByStudentId(Integer studentId);
 
+    @Modifying
+    @Query("delete ArbitrateHistory m where m.studentId=?1 and m.groupNumber=?2")
+    void deleteByStudentIdAndGroupNumber(Integer id, Integer groupNumber);
+
 }

+ 12 - 9
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/MarkLibraryDao.java

@@ -31,8 +31,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     @Query("select l1 from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 and l1.status in (?6) and (l1.markerId=?4 or l1.markerId is null ) "
             + "and not exists (select l2 from MarkLibrary l2 where l2.studentId=l1.studentId and l2.id!=l1.id and l2.markerId=?4 and l2.markerScore is not null) "
             + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id and mc.userId=?5 and s.className=mc.className)")
-    List<MarkLibrary> findUnMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            Integer userId, Set<LibraryStatus> statusSet, Pageable page);
+    List<MarkLibrary> findUnMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber,
+            Integer markerId, Integer userId, Set<LibraryStatus> statusSet, Pageable page);
 
     List<MarkLibrary> findByMarkerId(Integer markerId);
 
@@ -54,8 +54,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     long countByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);
 
     @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.taskNumber=?4")
-    long countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode, Integer groupNumber,
-            Integer taskNumber);
+    long countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode,
+            Integer groupNumber, Integer taskNumber);
 
     @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.status in (?4)")
     long countByExamIdAndSubjectCodeAndGroupNumberAndStatus(Integer examId, String subjectCode, Integer groupNumber,
@@ -115,8 +115,8 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     @Modifying(clearAutomatically = true)
     @Query("update MarkLibrary m set m.headerId=?3, m.headerScore=?4, m.headerScoreList=?5, m.headerTime=?6, m.status=?7 "
             + " where m.studentId=?1 and m.groupNumber=?2")
-    void updateHeaderResult(Integer studentId, Integer groupNumber, Integer userId, Double totalScore, String scoreList,
-            Date updateTime, LibraryStatus arbitrated);
+    void updateHeaderResult(Integer studentId, Integer groupNumber, Integer userId, Double totalScore,
+            String scoreList, Date updateTime, LibraryStatus arbitrated);
 
     @Modifying(clearAutomatically = true)
     @Query("update MarkLibrary m set m.status=?3 where m.studentId=?1 and m.groupNumber=?2")
@@ -143,12 +143,15 @@ public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, Jpa
     MarkLibrary findByStudentIdAndGroupNumberAndTaskNumber(Integer studentId, Integer groupNumber, Integer taskNumber);
 
     @Modifying(clearAutomatically = true)
-    @Query("update MarkLibrary l set l.status=?2, l.markerId=?3, l.markerTime=?4,l.markerScore=0, "
-            + "l.markerSpent=?5 where l.id=?1 and l.status in (?6) and (l.markerId=null or l.markerId=?3)")
+    @Query("update MarkLibrary l set l.status=?2, l.markerId=?3, l.markerTime=?4,l.markerScore=?6,l.markerScoreList=?7, "
+            + "l.markerSpent=?5 where l.id=?1 and l.status in (?8) and (l.markerId=null or l.markerId=?3)")
     int updateProblemResult(Integer id, LibraryStatus newStatus, Integer markerId, Date markerTime, Integer spent,
-            LibraryStatus... previousStatus);
+            Double markerScore, String markerScoreList, LibraryStatus... previousStatus);
 
     @Query("select distinct m.subjectCode from MarkLibrary m where m.examId=?1 and m.status not in (?2) ")
     Set<String> findSubjectUnFinishByExamId(int examId, LibraryStatus... status);
 
+    @Query("select count(l1) from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 "
+            + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id and mc.userId=?4 and s.className=mc.className)")
+    long countFilterClass(Integer examId, String subjectCode, Integer groupNumber, Integer userId);
 }

+ 0 - 49
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialHistoryDao.java

@@ -1,49 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.dao;
-
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.data.jpa.repository.Modifying;
-import org.springframework.data.jpa.repository.Query;
-
-import java.util.List;
-
-public interface TrialHistoryDao extends JpaRepository<TrialHistory, Integer>, JpaSpecificationExecutor<TrialHistory> {
-
-    List<TrialHistory> findByPkLibraryId(Integer libraryId);
-
-    TrialHistory findByPkLibraryIdAndPkMarkerId(Integer libraryId, Integer markerId);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerId(Integer examId, String subjectCode,
-            Integer groupNumber, Integer markerId, Pageable page);
-
-    @Query("select count(*) from TrialHistory f where f.pk.libraryId=?1")
-    long countByLibraryId(Integer libraryId);
-
-    @Query("select count(*) from TrialHistory f where f.pk.markerId=?1")
-    long countByMarkerId(Integer markerId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
-    void deleteByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.pk.libraryId=?1")
-    void deleteByLibraryId(Integer libraryId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.studentId=?1")
-    void deleteByStudentId(Integer studentId);
-
-    @Modifying
-    @Query("delete TrialHistory m where m.pk.markerId=?1")
-    void deleteByMarkerId(Integer markerId);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndSecretNumber(Integer examId,
-            String subjectCode, Integer groupNumber, Integer markerId, String secretNumber, Pageable query);
-
-    List<TrialHistory> findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndMarkerScore(Integer examId,
-            String subjectCode, Integer groupNumber, Integer markerId, Double markerScore, Pageable query);
-
-}

+ 29 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialLibraryDao.java

@@ -14,16 +14,15 @@ public interface TrialLibraryDao extends JpaRepository<TrialLibrary, Integer>, J
 
     List<TrialLibrary> findByExamIdAndSubjectCode(Integer examId, String subjectCode, Pageable page);
 
-    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber,
-            Pageable page);
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode,
+            Integer groupNumber, Pageable page);
 
-    @Query("select l1 from TrialLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 "
-            + "and not exists (select l2.pk.libraryId from TrialHistory l2 where l2.pk.libraryId=l1.id and l2.pk.markerId=?4)")
-    List<TrialLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            Pageable page);
+    @Query("select l from TrialLibrary l where l.examId=?1 and l.subjectCode=?2 and l.groupNumber=?3 "
+            + "and l.markerId is null ")
+    List<TrialLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Pageable page);
 
     @Query("select count(l) from TrialLibrary l where l.examId=?1 and l.subjectCode=?2 and l.groupNumber=?3 "
-    		 + "and exists (select l2.pk.libraryId from TrialHistory l2 where l2.pk.libraryId=l.id )")
+            + "and l.markerId is not null ")
     long countMarked(Integer examId, String subjectCode, Integer groupNumber);
 
     @Query("select l from TrialLibrary l where l.studentId=?1 order by l.groupNumber ")
@@ -44,5 +43,27 @@ public interface TrialLibraryDao extends JpaRepository<TrialLibrary, Integer>, J
     @Modifying
     @Query("delete TrialLibrary m where m.studentId=?1")
     void deleteByStudentId(Integer studentId);
-    
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerId(Integer examId, String subjectCode,
+            Integer groupNumber, Integer markerId, Pageable page);
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndSecretNumber(Integer examId,
+            String subjectCode, Integer groupNumber, Integer markerId, String secretNumber, Pageable query);
+
+    List<TrialLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndMarkerScore(Integer examId,
+            String subjectCode, Integer groupNumber, Integer markerId, Double markerScore, Pageable query);
+
+    @Query("select count(*) from TrialLibrary f where f.markerId=?1")
+    long countByMarkerId(Integer markerId);
+
+    @Modifying(clearAutomatically = true)
+    @Query("update TrialLibrary m set m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null "
+            + "where m.markerId=?1 ")
+    void resetByMarkerId(Integer markerId);
+
+    @Modifying(clearAutomatically = true)
+    @Query("update TrialLibrary m set m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null "
+            + "where m.id=?1")
+    void resetById(Integer id);
+
 }

+ 5 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTagDao.java

@@ -24,7 +24,7 @@ public interface TrialTagDao extends PagingAndSortingRepository<TrialTag, Intege
             + "(select l.id from TrialLibrary l where l.studentId=?1 and s.libraryId=l.id)")
     public void deleteByStudentId(Integer studentId);
 
-    public List<TrialTag> findByLibraryIdAndMarkerIdOrderByIdAsc(Integer libraryId, Integer markerId);
+    public List<TrialTag> findByLibraryIdOrderByIdAsc(Integer libraryId);
 
     @Modifying
     @Query("delete from TrialTag s where s.markerId=?1")
@@ -34,4 +34,8 @@ public interface TrialTagDao extends PagingAndSortingRepository<TrialTag, Intege
     @Query("delete from TrialTag s where s.libraryId in (select m.id from TrialLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3)")
     public void deleteByExamAndSubjectAndGroup(Integer examId, String subjectCode, Integer groupNumber);
 
+    @Query("select s from TrialTag s where s.libraryId in "
+            + "(select l.id from TrialLibrary l where l.studentId=?1 and s.libraryId=l.id)")
+    public List<TrialTag> findByStudentIdOrderByIdAsc(Integer studentId);
+
 }

+ 1 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/dao/TrialTrackDao.java

@@ -12,7 +12,7 @@ import cn.com.qmth.stmms.biz.mark.model.TrialTrackPK;
 
 public interface TrialTrackDao extends JpaRepository<TrialTrack, TrialTrackPK>, JpaSpecificationExecutor<TrialTrack> {
 
-    List<TrialTrack> findByPkLibraryIdAndPkMarkerId(Integer libraryId, Integer markerId);
+    List<TrialTrack> findByPkLibraryId(Integer libraryId);
 
     List<TrialTrack> findByStudentId(Integer studentId);
 

+ 6 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/ArbitrationDTO.java

@@ -8,7 +8,7 @@ public class ArbitrationDTO {
 
     private String markerName;
 
-    private Date markTime;
+    private Date markerTime;
 
     private Double totalScore;
 
@@ -16,7 +16,7 @@ public class ArbitrationDTO {
 
     public ArbitrationDTO(MarkLibrary library, Marker marker) {
         markerName = marker.getUser().getName();
-        markTime = library.getMarkerTime();
+        markerTime = library.getMarkerTime();
         totalScore = library.getMarkerScore();
         scoreList = library.getMarkerScoreList();
     }
@@ -29,12 +29,12 @@ public class ArbitrationDTO {
         this.markerName = markerName;
     }
 
-    public Date getMarkTime() {
-        return markTime;
+    public Date getMarkerTime() {
+        return markerTime;
     }
 
-    public void setMarkTime(Date markTime) {
-        this.markTime = markTime;
+    public void setMarkerTime(Date markerTime) {
+        this.markerTime = markerTime;
     }
 
     public Double getTotalScore() {

+ 2 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkLibrary.java

@@ -226,7 +226,7 @@ public class MarkLibrary implements Serializable {
             try {
                 String[] values = scoreList.split(",");
                 for (String value : values) {
-                    if (value.equals("")) {
+                    if (value.equals("#")) {
                         list.add(new ScoreItem(false));
                     } else {
                         ScoreItem item = ScoreItem.parse(value, false);
@@ -307,4 +307,5 @@ public class MarkLibrary implements Serializable {
     public void setMarkerLoginName(String markerLoginName) {
         this.markerLoginName = markerLoginName;
     }
+
 }

+ 25 - 5
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/MarkResult.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.mark.model;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -69,6 +70,8 @@ public class MarkResult {
      */
     private Integer problemTypeId;
 
+    private boolean unselective;
+
     public String getStatusValue() {
         return statusValue;
     }
@@ -94,7 +97,16 @@ public class MarkResult {
     }
 
     public String getScoreList() {
-        return StringUtils.join(scoreList, SPLIT);
+        List<Object> list = new ArrayList<Object>();
+        for (int i = 0; i < scoreList.length; i++) {
+            Double d = scoreList[i];
+            if (d % 1 == 0) {
+                list.add(d.intValue());
+            } else {
+                list.add(d);
+            }
+        }
+        return StringUtils.join(list, SPLIT);
     }
 
     public void setScoreList(Double[] scoreList) {
@@ -175,11 +187,11 @@ public class MarkResult {
         return list;
     }
 
-    public List<TrialTrack> getTrackList(TrialHistory history) {
+    public List<TrialTrack> getTrackList(TrialLibrary library) {
         List<TrialTrack> list = new LinkedList<>();
         if (trackList != null) {
             for (TrackDTO dto : trackList) {
-                list.add(dto.transform(history));
+                list.add(dto.transform(library));
             }
         }
         return list;
@@ -195,11 +207,11 @@ public class MarkResult {
         return list;
     }
 
-    public List<TrialTag> getTagList(TrialHistory history) {
+    public List<TrialTag> getTagList(TrialLibrary library) {
         List<TrialTag> list = new LinkedList<>();
         if (specialTagList != null) {
             for (SpecialTagDTO dto : specialTagList) {
-                list.add(dto.transform(history));
+                list.add(dto.transform(library));
             }
         }
         return list;
@@ -221,4 +233,12 @@ public class MarkResult {
         this.problemTypeId = problemTypeId;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
 }

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/ProblemHistory.java

@@ -68,6 +68,12 @@ public class ProblemHistory implements Serializable {
     @Column(name = "secret_number")
     private String secretNumber;
 
+    /**
+     * 提出问题评卷员ID
+     */
+    @Column(name = "marker_id", nullable = true)
+    private Integer markerId;
+
     /**
      * 处理用户ID
      */
@@ -236,4 +242,12 @@ public class ProblemHistory implements Serializable {
         this.libraryId = libraryId;
     }
 
+    public Integer getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(Integer markerId) {
+        this.markerId = markerId;
+    }
+
 }

+ 21 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/SpecialTagDTO.java

@@ -22,6 +22,24 @@ public class SpecialTagDTO implements Serializable {
 
     }
 
+    public SpecialTagDTO(MarkSpecialTag markSpecialTag) {
+        this.tagName = markSpecialTag.getTagName();
+        this.positionX = markSpecialTag.getPositionX();
+        this.positionY = markSpecialTag.getPositionY();
+        this.offsetIndex = markSpecialTag.getOffsetIndex();
+        this.offsetX = markSpecialTag.getOffsetX();
+        this.offsetY = markSpecialTag.getOffsetY();
+    }
+
+    public SpecialTagDTO(TrialTag tag) {
+        this.tagName = tag.getContent();
+        this.positionX = tag.getPositionX();
+        this.positionY = tag.getPositionY();
+        this.offsetIndex = tag.getOffsetIndex();
+        this.offsetX = tag.getOffsetX();
+        this.offsetY = tag.getOffsetY();
+    }
+
     public MarkSpecialTag transform(MarkLibrary library) {
         MarkSpecialTag markSpecialTag = new MarkSpecialTag();
         markSpecialTag.setLibraryId(library.getId());
@@ -34,10 +52,10 @@ public class SpecialTagDTO implements Serializable {
         return markSpecialTag;
     }
 
-    public TrialTag transform(TrialHistory history) {
+    public TrialTag transform(TrialLibrary library) {
         TrialTag tag = new TrialTag();
-        tag.setLibraryId(history.getLibraryId());
-        tag.setMarkerId(history.getMarkerId());
+        tag.setLibraryId(library.getId());
+        tag.setMarkerId(library.getMarkerId());
         tag.setContent(tagName);
         tag.setPositionX(positionX);
         tag.setPositionY(positionY);

+ 5 - 5
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/Task.java

@@ -88,7 +88,7 @@ public class Task implements Serializable {
     /**
      * 评卷时间
      */
-    private Date markTime;
+    private Date markerTime;
 
     /**
      * 是否自评
@@ -240,12 +240,12 @@ public class Task implements Serializable {
         this.markerScore = markerScore;
     }
 
-    public Date getMarkTime() {
-        return markTime;
+    public Date getMarkerTime() {
+        return markerTime;
     }
 
-    public void setMarkTime(Date markTime) {
-        this.markTime = markTime;
+    public void setMarkerTime(Date markerTime) {
+        this.markerTime = markerTime;
     }
 
     public boolean isSelf() {

+ 8 - 8
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrackDTO.java

@@ -81,17 +81,17 @@ public class TrackDTO implements Serializable {
         return track;
     }
 
-    public TrialTrack transform(TrialHistory history) {
+    public TrialTrack transform(TrialLibrary library) {
         TrialTrack track = new TrialTrack();
-        track.setLibraryId(history.getLibraryId());
-        track.setMarkerId(history.getMarkerId());
+        track.setLibraryId(library.getId());
+        track.setMarkerId(library.getMarkerId());
         track.setQuestionNumber(getMainNumber() + "." + getSubNumber());
         track.setNumber(getNumber());
-        track.setStudentId(history.getStudentId());
-        track.setExamId(history.getExamId());
-        track.setSubjectCode(history.getSubjectCode());
-        track.setGroupNumber(history.getGroupNumber());
-        track.setMarkerId(history.getMarkerId());
+        track.setStudentId(library.getStudentId());
+        track.setExamId(library.getExamId());
+        track.setSubjectCode(library.getSubjectCode());
+        track.setGroupNumber(library.getGroupNumber());
+        track.setMarkerId(library.getMarkerId());
         track.setScore(getScore());
         track.setPositionX(getPositionX());
         track.setPositionY(getPositionY());

+ 0 - 188
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistory.java

@@ -1,188 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.model;
-
-import cn.com.qmth.stmms.biz.exam.model.Marker;
-import cn.com.qmth.stmms.biz.utils.ScoreItem;
-
-import javax.persistence.*;
-
-import org.apache.commons.lang.StringUtils;
-
-import java.io.Serializable;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * 试评任务给分记录表
- *
- * @author luoshi
- */
-@Entity
-@Table(name = "m_trial_history")
-public class TrialHistory implements Serializable {
-
-    private static final long serialVersionUID = 1077169224382148814L;
-
-    @EmbeddedId
-    private TrialHistoryPK pk;
-
-    /**
-     * 考试ID
-     */
-    @Column(name = "exam_id")
-    private Integer examId;
-
-    /**
-     * 科目CODE
-     */
-    @Column(name = "subject_code")
-    private String subjectCode;
-
-    /**
-     * 大题序号
-     */
-    @Column(name = "group_number")
-    private Integer groupNumber;
-
-    /**
-     * 考生编号
-     */
-    @Column(name = "student_id")
-    private Integer studentId;
-
-    /**
-     * 考生密号
-     */
-    @Column(name = "secret_number")
-    private String secretNumber;
-
-    /**
-     * 评卷时间
-     */
-    @Column(name = "marker_time")
-    private Date markerTime;
-
-    /**
-     * 评卷员给分总分
-     */
-    @Column(name = "marker_score")
-    private Double markerScore;
-
-    /**
-     * 评卷员给分明细
-     */
-    @Column(name = "marker_score_list")
-    private String markerScoreList;
-
-    @Transient
-    private Marker marker;
-
-    public TrialHistory() {
-        this.pk = new TrialHistoryPK();
-    }
-
-    public Integer getExamId() {
-        return examId;
-    }
-
-    public void setExamId(Integer examId) {
-        this.examId = examId;
-    }
-
-    public String getSubjectCode() {
-        return subjectCode;
-    }
-
-    public void setSubjectCode(String subjectCode) {
-        this.subjectCode = subjectCode;
-    }
-
-    public Integer getStudentId() {
-        return studentId;
-    }
-
-    public void setStudentId(Integer studentId) {
-        this.studentId = studentId;
-    }
-
-    public Integer getLibraryId() {
-        return pk.getLibraryId();
-    }
-
-    public void setLibraryId(Integer libraryId) {
-        pk.setLibraryId(libraryId);
-    }
-
-    public Integer getMarkerId() {
-        return pk.getMarkerId();
-    }
-
-    public void setMarkerId(Integer markerId) {
-        pk.setMarkerId(markerId);
-    }
-
-    public Date getMarkerTime() {
-        return markerTime;
-    }
-
-    public void setMarkerTime(Date markerTime) {
-        this.markerTime = markerTime;
-    }
-
-    public Double getMarkerScore() {
-        return markerScore;
-    }
-
-    public void setMarkerScore(Double markerScore) {
-        this.markerScore = markerScore;
-    }
-
-    public String getMarkerScoreList() {
-        return markerScoreList;
-    }
-
-    public void setMarkerScoreList(String markerScoreList) {
-        this.markerScoreList = markerScoreList;
-    }
-
-    public Integer getGroupNumber() {
-        return groupNumber;
-    }
-
-    public void setGroupNumber(Integer groupNumber) {
-        this.groupNumber = groupNumber;
-    }
-
-    public Marker getMarker() {
-        return marker;
-    }
-
-    public void setMarker(Marker marker) {
-        this.marker = marker;
-    }
-
-    public String getSecretNumber() {
-        return secretNumber;
-    }
-
-    public void setSecretNumber(String secretNumber) {
-        this.secretNumber = secretNumber;
-    }
-
-    public List<ScoreItem> getScoreList() {
-        List<ScoreItem> list = new LinkedList<ScoreItem>();
-        if (StringUtils.isNotBlank(markerScoreList)) {
-            try {
-                String[] values = markerScoreList.split(",");
-                for (String value : values) {
-                    ScoreItem item = ScoreItem.parse(value, false);
-                    if (item != null) {
-                        list.add(item);
-                    }
-                }
-            } catch (Exception e) {
-            }
-        }
-        return list;
-    }
-}

+ 0 - 66
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialHistoryPK.java

@@ -1,66 +0,0 @@
-package cn.com.qmth.stmms.biz.mark.model;
-
-import java.io.Serializable;
-
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-
-@Embeddable
-public class TrialHistoryPK implements Serializable {
-
-    private static final long serialVersionUID = 7082004881704656373L;
-
-    @Column(name = "library_id", nullable = false)
-    private Integer libraryId;
-
-    @Column(name = "marker_id", nullable = false)
-    private Integer markerId;
-
-    public Integer getLibraryId() {
-        return libraryId;
-    }
-
-    public void setLibraryId(Integer libraryId) {
-        this.libraryId = libraryId;
-    }
-
-    public Integer getMarkerId() {
-        return markerId;
-    }
-
-    public void setMarkerId(Integer markerId) {
-        this.markerId = markerId;
-    }
-
-    @Override
-    public int hashCode() {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * result + ((libraryId == null) ? 0 : libraryId.hashCode());
-        result = PRIME * result + ((markerId == null) ? 0 : markerId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        final TrialHistoryPK other = (TrialHistoryPK) obj;
-        if (libraryId == null) {
-            if (other.libraryId != null)
-                return false;
-        } else if (!libraryId.equals(other.libraryId))
-            if (markerId == null) {
-                if (other.markerId != null)
-                    return false;
-            } else if (!markerId.equals(other.markerId))
-                return false;
-
-        return true;
-    }
-
-}

+ 87 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/model/TrialLibrary.java

@@ -1,7 +1,20 @@
 package cn.com.qmth.stmms.biz.mark.model;
 
-import javax.persistence.*;
 import java.io.Serializable;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+import org.apache.commons.lang.StringUtils;
+
+import cn.com.qmth.stmms.biz.utils.ScoreItem;
 
 /**
  * 试评任务表
@@ -54,11 +67,29 @@ public class TrialLibrary implements Serializable {
     @Column(name = "secret_number")
     private String secretNumber;
 
+    @Column(name = "marker_id", nullable = true)
+    private Integer markerId;
+
     /**
-     * 已评人数
+     * 评卷时间
      */
+    @Column(name = "marker_time")
+    private Date markerTime;
+
+    /**
+     * 评卷员给分总分
+     */
+    @Column(name = "marker_score")
+    private Double markerScore;
+
+    /**
+     * 评卷员给分明细
+     */
+    @Column(name = "marker_score_list")
+    private String markerScoreList;
+
     @Transient
-    private Long markCount;
+    private String markerLoginName;
 
     public Integer getId() {
         return id;
@@ -116,12 +147,61 @@ public class TrialLibrary implements Serializable {
         this.groupNumber = groupNumber;
     }
 
-    public Long getMarkCount() {
-        return markCount;
+    public Integer getMarkerId() {
+        return markerId;
+    }
+
+    public void setMarkerId(Integer markerId) {
+        this.markerId = markerId;
+    }
+
+    public Date getMarkerTime() {
+        return markerTime;
+    }
+
+    public void setMarkerTime(Date markerTime) {
+        this.markerTime = markerTime;
+    }
+
+    public Double getMarkerScore() {
+        return markerScore;
+    }
+
+    public void setMarkerScore(Double markerScore) {
+        this.markerScore = markerScore;
+    }
+
+    public String getMarkerScoreList() {
+        return markerScoreList;
+    }
+
+    public void setMarkerScoreList(String markerScoreList) {
+        this.markerScoreList = markerScoreList;
+    }
+
+    public List<ScoreItem> getScoreList() {
+        List<ScoreItem> list = new LinkedList<ScoreItem>();
+        if (StringUtils.isNotBlank(markerScoreList)) {
+            try {
+                String[] values = markerScoreList.split(",");
+                for (String value : values) {
+                    ScoreItem item = ScoreItem.parse(value, false);
+                    if (item != null) {
+                        list.add(item);
+                    }
+                }
+            } catch (Exception e) {
+            }
+        }
+        return list;
+    }
+
+    public String getMarkerLoginName() {
+        return markerLoginName;
     }
 
-    public void setMarkCount(Long markCount) {
-        this.markCount = markCount;
+    public void setMarkerLoginName(String markerLoginName) {
+        this.markerLoginName = markerLoginName;
     }
 
 }

+ 20 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/ArbitrateHistorySearchQuery.java

@@ -25,6 +25,10 @@ public class ArbitrateHistorySearchQuery extends BaseQuery<ArbitrateHistory> {
 
     private String secretNumber;
 
+    private Double startScroe;
+
+    private boolean unselective;
+
     public void orderByIdDesc() {
         setSort(new Sort(Direction.DESC, "id"));
     }
@@ -97,4 +101,20 @@ public class ArbitrateHistorySearchQuery extends BaseQuery<ArbitrateHistory> {
         this.secretNumber = secretNumber;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
+    public Double getStartScroe() {
+        return startScroe;
+    }
+
+    public void setStartScroe(Double startScroe) {
+        this.startScroe = startScroe;
+    }
+
 }

+ 34 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/query/MarkLibrarySearchQuery.java

@@ -35,6 +35,12 @@ public class MarkLibrarySearchQuery extends BaseQuery<MarkLibrary> {
 
     private Double endScroe;
 
+    private boolean unselective;
+
+    private String questionScore;
+
+    private Integer headerId;
+
     public MarkLibrarySearchQuery() {
         super();
         this.statusSet = new HashSet<>();
@@ -44,6 +50,10 @@ public class MarkLibrarySearchQuery extends BaseQuery<MarkLibrary> {
         setSort(new Sort(Direction.DESC, "markerTime"));
     }
 
+    public void orderByHeaderTimeDesc() {
+        setSort(new Sort(Direction.DESC, "headerTime"));
+    }
+
     public void orderByExamNumber() {
         setSort(new Sort(Direction.ASC, "examNumber"));
     }
@@ -152,4 +162,28 @@ public class MarkLibrarySearchQuery extends BaseQuery<MarkLibrary> {
         this.endScroe = endScroe;
     }
 
+    public boolean isUnselective() {
+        return unselective;
+    }
+
+    public void setUnselective(boolean unselective) {
+        this.unselective = unselective;
+    }
+
+    public String getQuestionScore() {
+        return questionScore;
+    }
+
+    public void setQuestionScore(String questionScore) {
+        this.questionScore = questionScore;
+    }
+
+    public Integer getHeaderId() {
+        return headerId;
+    }
+
+    public void setHeaderId(Integer headerId) {
+        this.headerId = headerId;
+    }
+
 }

+ 9 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/ArbitrateHistoryServiceImpl.java

@@ -26,6 +26,8 @@ import cn.com.qmth.stmms.common.enums.HistoryStatus;
 @Service
 public class ArbitrateHistoryServiceImpl extends BaseQueryService<ArbitrateHistory> implements ArbitrateHistoryService {
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     @Autowired
     private ArbitrateHistoryDao historyDao;
 
@@ -102,6 +104,13 @@ public class ArbitrateHistoryServiceImpl extends BaseQueryService<ArbitrateHisto
                 if (StringUtils.isNotBlank(query.getSecretNumber())) {
                     predicates.add(cb.equal(root.get("secretNumber"), query.getSecretNumber()));
                 }
+                if (query.isUnselective()) {
+                    predicates.add(cb.equal(root.get("totalScore"), UN_SELECTIVE_SCORE));
+                }
+                if (query.getStartScroe() != null) {
+                    Predicate predicate1 = cb.ge(root.get("totalScore"), query.getStartScroe());
+                    predicates.add(predicate1);
+                }
                 return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                         .size()]));
             }

+ 23 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java

@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
 import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
 import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
 import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
@@ -23,6 +24,7 @@ import cn.com.qmth.stmms.biz.mark.service.MarkService;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 /**
  * 与评卷相关的所有定时任务
@@ -52,8 +54,8 @@ public class MarkCronService {
     @Autowired
     private MarkerService markerService;
 
-    @Value("${mark.cleanTimeoutMinute}")
-    private long timeoutMinute;
+    @Autowired
+    private SystemCache systemCache;
 
     @Value("${mark.activeExpireMinute}")
     private long markerActiveExpireMinute;
@@ -76,6 +78,7 @@ public class MarkCronService {
     @Scheduled(cron = "${mark.cleanTaskSchedule}")
     public void cronCleanTask() {
         try {
+            long timeoutMinute = systemCache.getMarkTime();
             TaskLockUtil.clearTimeoutTask(timeoutMinute * 60 * 1000);
         } catch (Exception e) {
             log.error("CronCleanTask error", e);
@@ -164,8 +167,22 @@ public class MarkCronService {
             // 生成试评任务
             List<MarkGroup> groups = groupService.findByExamAndSubjectAndStatus(subject.getExamId(), subject.getCode(),
                     MarkStatus.TRIAL);
+            long trialCount = studentService.countByExamIdAndSubjectCodeAndStatus(examId, subject.getCode(),
+                    SubjectiveStatus.TRIAL, SubjectiveStatus.MARKED, SubjectiveStatus.INSPECTED);
+            if (!groups.isEmpty() && trialCount < subject.getTrialCount()) {
+                while (trialCount < subject.getTrialCount()) {
+                    // 取一个的考生
+                    ExamStudent student = studentService.randomStudent(examId, subject.getCode());
+                    if (student == null) {
+                        break;
+                    }
+                    studentService.updateSubjectiveStatusAndTimeAndInspectorId(student.getId(), SubjectiveStatus.TRIAL,
+                            null, null);
+                    trialCount++;
+                }
+            }
             for (MarkGroup group : groups) {
-                buildTrialLibrary(group);
+                buildTrialLibrary(trialCount, group);
             }
             // 生成正评任务
             // 试评状态的分组也提前生成
@@ -220,9 +237,9 @@ public class MarkCronService {
         }
     }
 
-    private void buildTrialLibrary(MarkGroup group) {
-        while (group.getTrialCount() > group.getLibraryCount()) {
-            // 随机取一个未生成试评任务的考生
+    private void buildTrialLibrary(long trialCount, MarkGroup group) {
+        while (trialCount > group.getLibraryCount()) {
+            // 取一个未生成试评任务的考生
             ExamStudent student = studentService.randomUnTrialStudent(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             if (student == null) {

+ 31 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkLibraryServiceImpl.java

@@ -30,6 +30,8 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
     @Autowired
     private MarkLibraryDao libraryDao;
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     @Override
     public MarkLibrary findById(int id) {
         return libraryDao.findOne(id);
@@ -132,10 +134,33 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
                     predicates.add(cb.equal(root.get("markerScore"), query.getMarkerScore()));
                 }
                 if (query.getStartScroe() != null) {
+                    Predicate predicate1 = cb.ge(root.get("markerScore"), query.getStartScroe());
+                    predicates.add(predicate1);
+                }
+                if (query.getEndScroe() != null) {
+                    Predicate predicate2 = cb.le(root.get("markerScore"), query.getEndScroe());
+                    predicates.add(predicate2);
+                }
+                if (query.getMarkerScore() != null && query.getStartScroe() != null) {
                     Predicate predicate1 = cb.ge(root.get("markerScore"), query.getStartScroe());
                     Predicate predicate2 = cb.le(root.get("markerScore"), query.getEndScroe());
                     predicates.add(cb.and(predicate1, predicate2));
                 }
+                if (query.isUnselective()) {
+                    Predicate predicate1 = cb.equal(root.get("markerScore"), UN_SELECTIVE_SCORE);
+                    Predicate predicate2 = cb.equal(root.get("headerScore"), UN_SELECTIVE_SCORE);
+                    predicates.add(cb.or(predicate1, predicate2));
+                }
+                if (StringUtils.isNotBlank(query.getQuestionScore())) {
+                    Predicate predicate1 = cb.like(root.get("markerScoreList").as(String.class),
+                            query.getQuestionScore() + ",%");
+                    Predicate predicate2 = cb.like(root.get("markerScoreList").as(String.class),
+                            "%," + query.getQuestionScore());
+                    predicates.add(cb.or(predicate1, predicate2));
+                }
+                if (query.getHeaderId() != null) {
+                    predicates.add(cb.equal(root.get("headerId"), query.getHeaderId()));
+                }
                 return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
                         .size()]));
             }
@@ -208,4 +233,10 @@ public class MarkLibraryServiceImpl extends BaseQueryService<MarkLibrary> implem
                 LibraryStatus.INSPECTED);
     }
 
+    @Override
+    public long countByExamAndSubjectAndGroupAndFilterClass(Integer examId, String subjectCode, Integer groupNumber,
+            Integer userId) {
+        return libraryDao.countFilterClass(examId, subjectCode, groupNumber, userId);
+    }
+
 }

+ 245 - 152
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkServiceImpl.java

@@ -1,11 +1,11 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
-import cn.com.qmth.stmms.biz.exam.dao.*;
+import cn.com.qmth.stmms.biz.exam.dao.MarkGroupDao;
+import cn.com.qmth.stmms.biz.exam.dao.MarkGroupStudentDao;
+import cn.com.qmth.stmms.biz.exam.dao.MarkerDao;
+import cn.com.qmth.stmms.biz.exam.dao.SubjectiveScoreDao;
 import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
-import cn.com.qmth.stmms.biz.exam.service.ExamService;
-import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
-import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
+import cn.com.qmth.stmms.biz.exam.service.*;
 import cn.com.qmth.stmms.biz.mark.dao.*;
 import cn.com.qmth.stmms.biz.mark.model.*;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
@@ -15,7 +15,6 @@ import cn.com.qmth.stmms.biz.utils.TaskLock;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
 import cn.com.qmth.stmms.common.enums.*;
 import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
-import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -23,6 +22,7 @@ import org.springframework.data.domain.Sort;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -36,6 +36,8 @@ public class MarkServiceImpl implements MarkService {
 
     protected static final Logger log = LoggerFactory.getLogger(MarkServiceImpl.class);
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     @Autowired
     private ExamStudentService studentService;
 
@@ -52,7 +54,7 @@ public class MarkServiceImpl implements MarkService {
     private SubjectiveScoreDao scoreDao;
 
     @Autowired
-    private ExamQuestionDao questionDao;
+    private ExamQuestionService questionService;
 
     @Autowired
     private MarkerDao markerDao;
@@ -72,9 +74,6 @@ public class MarkServiceImpl implements MarkService {
     @Autowired
     private TrialLibraryDao trialLibraryDao;
 
-    @Autowired
-    private TrialHistoryDao trialHistoryDao;
-
     @Autowired
     private TrialTrackDao trialTrackDao;
 
@@ -88,7 +87,7 @@ public class MarkServiceImpl implements MarkService {
     private ExamService examService;
 
     @Autowired
-    private ExamQuestionService questionService;
+    private SelectiveGroupService selectiveGroupService;
 
     private Map<Integer, Long> markerLastUpdateTime = new ConcurrentHashMap<>();
 
@@ -100,12 +99,9 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public int applyCount(MarkGroup group) {
+        TaskLock taskLock = getTaskLock(group);
         int count = 0;
-        if (group.getStatus() == MarkStatus.TRIAL) {
-            TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(group));
-            count = taskLock.count();
-        } else if (group.getStatus() == MarkStatus.FORMAL) {
-            TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(group));
+        if (taskLock != null) {
             count = taskLock.count();
         }
         return count;
@@ -119,20 +115,26 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public int applyCount(Marker marker) {
+        int count = 0;
         MarkGroup group = marker.getGroup();
         if (group == null) {
             group = groupDao.findOne(marker.getExamId(), marker.getSubjectCode(), marker.getGroupNumber());
         }
-        if (group != null) {
-            if (group.getStatus() == MarkStatus.FORMAL) {
-                TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(marker));
-                return taskLock.count(marker.getId());
-            } else if (group.getStatus() == MarkStatus.TRIAL) {
-                TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(marker));
-                return taskLock.count(marker.getId());
-            }
+        TaskLock taskLock = getTaskLock(group);
+        if (taskLock != null) {
+            count = taskLock.count(marker.getId());
         }
-        return 0;
+        return count;
+    }
+
+    private TaskLock getTaskLock(MarkGroup group) {
+        if (group.getStatus() == MarkStatus.FORMAL) {
+            return TaskLockUtil.getFormalTask(getGroupKey(group));
+
+        } else if (group.getStatus() == MarkStatus.TRIAL) {
+            return TaskLockUtil.getTrialTask(getGroupKey(group));
+        }
+        return null;
     }
 
     /**
@@ -149,7 +151,7 @@ public class MarkServiceImpl implements MarkService {
         }
         if (group != null) {
             if (group.getStatus() == MarkStatus.TRIAL) {
-                return trialHistoryDao.countByMarkerId(marker.getId());
+                return trialLibraryDao.countByMarkerId(marker.getId());
             } else {
                 return libraryDao.countByMarkerAndStatus(marker.getId(), LibraryStatus.MARKED, LibraryStatus.ARBITRATED,
                         LibraryStatus.INSPECTED);
@@ -165,13 +167,8 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     public void releaseByGroup(MarkGroup group) {
-        if (group.getStatus() == MarkStatus.TRIAL) {
-            TaskLock taskLock = TaskLockUtil.getTrialTask(getGroupKey(group));
-            taskLock.clear();
-        } else if (group.getStatus() == MarkStatus.FORMAL) {
-            TaskLock taskLock = TaskLockUtil.getFormalTask(getGroupKey(group));
-            taskLock.clear();
-        }
+        TaskLock taskLock = getTaskLock(group);
+        taskLock.clear();
     }
 
     /**
@@ -197,8 +194,6 @@ public class MarkServiceImpl implements MarkService {
         trialTrackDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                 group.getNumber());
         trialTagDao.deleteByExamAndSubjectAndGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
-        trialHistoryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                group.getNumber());
         trialLibraryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                 group.getNumber());
         // 正评相关数据
@@ -215,7 +210,7 @@ public class MarkServiceImpl implements MarkService {
         markerDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                 group.getNumber());
         // 小题数据
-        questionDao
+        questionService
                 .resetByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(group.getExamId(), group.getSubjectCode(), false,
                         group.getNumber());
         // 考生分组状态与得分明细
@@ -227,7 +222,7 @@ public class MarkServiceImpl implements MarkService {
         releaseByGroup(group);
         groupDao.delete(group);
         // 未分组的题目
-        long unGroupQuestionCount = questionDao
+        long unGroupQuestionCount = questionService
                 .countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(group.getExamId(), group.getSubjectCode(),
                         false);
         // 考生整体状态与总分更新
@@ -235,6 +230,7 @@ public class MarkServiceImpl implements MarkService {
         if (groupCount == 0 || unGroupQuestionCount > 0) {
             studentService.updateSubjectiveStatusAndScoreAndInspectorId(group.getExamId(), group.getSubjectCode(),
                     SubjectiveStatus.UNMARK, 0, null, null, null);
+            subjectService.updateTrialCount(group.getExamId(), group.getSubjectCode(), 0);
         } else {
             List<Integer> studentList = studentService
                     .findIdByExamIdAndSubjectCodeAndSubjectiveStatus(group.getExamId(), group.getSubjectCode(),
@@ -252,25 +248,27 @@ public class MarkServiceImpl implements MarkService {
      */
     @Override
     @Transactional
-    public void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third) {
-        List<ExamQuestion> old = questionDao
-                .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(group.getExamId(), group.getSubjectCode(), false,
+    public void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third,
+            boolean selective) {
+        List<ExamQuestion> old = questionService
+                .findByExamAndSubjectAndObjectiveAndGroupNumber(group.getExamId(), group.getSubjectCode(), false,
                         group.getNumber());
         for (ExamQuestion question : old) {
             question.setGroupNumber(null);
-            questionDao.saveAndFlush(question);
+            questionService.saveAndFlush(question);
         }
-        double totalScore = 0d;
+        BigDecimal totalScore = BigDecimal.ZERO;
         for (ExamQuestion question : questionList) {
-            totalScore += question.getTotalScore();
+            totalScore = totalScore.add(BigDecimal.valueOf(question.getTotalScore()));
             question.setGroupNumber(group.getNumber());
-            questionDao.saveAndFlush(question);
+            questionService.saveAndFlush(question);
         }
-        groupDao.updateTotalScore(group.getExamId(), group.getSubjectCode(), group.getNumber(), totalScore);
+        groupDao.updateTotalScore(group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                totalScore.doubleValue());
         groupDao.updateScorePolicy(group.getExamId(), group.getSubjectCode(), group.getNumber(), policy);
         groupDao.updateThirdPolicy(group.getExamId(), group.getSubjectCode(), group.getNumber(), third);
-        subjectService.updateScore(group.getExamId(), group.getSubjectCode(), false,
-                sumTotalScore(group.getExamId(), group.getSubjectCode()));
+        groupDao.updateSelective(group.getExamId(), group.getSubjectCode(), group.getNumber(), selective);
+
         resetGroup(group);
         if (group.getStatus() == MarkStatus.FORMAL) {
             libraryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
@@ -435,7 +433,7 @@ public class MarkServiceImpl implements MarkService {
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             trialTagDao.deleteByMarkerId(marker.getId());
             trialTrackDao.deleteByMarkerId(marker.getId());
-            trialHistoryDao.deleteByMarkerId(marker.getId());
+            trialLibraryDao.resetByMarkerId(marker.getId());
         }
         updateMarkedCount(group);
         releaseByMarker(marker);
@@ -458,7 +456,6 @@ public class MarkServiceImpl implements MarkService {
         // 试评相关数据
         trialTrackDao.deleteByStudentId(student.getId());
         trialTagDao.deleteByStudentId(student.getId());
-        trialHistoryDao.deleteByStudentId(student.getId());
         trialLibraryDao.deleteByStudentId(student.getId());
         // 主观状态与得分明细
         groupStudentDao.deleteByStudentId(student.getId());
@@ -483,71 +480,73 @@ public class MarkServiceImpl implements MarkService {
             return SubmitResult.faile();
         }
 
+        Date now = new Date();
         // 根据评卷状态选择读取不同的评卷任务
         if (group.getStatus() == MarkStatus.FORMAL) {
             MarkLibrary library = libraryDao.findOne(result.getLibraryId());
-            if (library != null && result.isProblem()) {
-                // 状态更新
-                Date now = new Date();
-                if (libraryDao.updateProblemResult(library.getId(), LibraryStatus.PROBLEM, marker.getId(), now,
-                        result.getSpent(), LibraryStatus.WAITING, LibraryStatus.MARKED, LibraryStatus.INSPECTED,
-                        LibraryStatus.REJECTED) != 0) {
-                    saveProblemHistory(result, library);
-                    updateMarkedCount(group);
-                    // 未评完
-                    resetStudentGroup(library.getStudentId(), library.getExamId(), library.getSubjectCode(),
-                            library.getGroupNumber());
-                    trackDao.deleteByLibraryId(library.getId());
-                    specialTagDao.deleteByLibraryId(library.getId());
-                    return SubmitResult.success(library);
-                }
-            }
             if (library != null && library.getExamId().equals(group.getExamId()) && library.getSubjectCode()
-                    .equals(group.getSubjectCode()) && library.getGroupNumber().equals(group.getNumber())
-                    && result.getMarkerScore() <= group.getTotalScore() && StringUtils
-                    .isNotBlank(result.getScoreList())) {
-                if (submitLibrary(library, marker, group, result)) {
-                    updateMarkedCount(group);
-                    return SubmitResult.success(library);
+                    .equals(group.getSubjectCode()) && library.getGroupNumber().equals(group.getNumber())) {
+                // 问题卷
+                if (result.isProblem()) {
+                    // 状态更新
+                    if (libraryDao.updateProblemResult(library.getId(), LibraryStatus.PROBLEM, marker.getId(), now,
+                            result.getSpent(), 0d, null, LibraryStatus.WAITING, LibraryStatus.MARKED,
+                            LibraryStatus.INSPECTED, LibraryStatus.REJECTED) != 0) {
+                        saveProblemHistory(result, library, marker);
+                        updateMarkedCount(group);
+                        // 未评完
+                        resetStudentGroup(library.getStudentId(), library.getExamId(), library.getSubjectCode(),
+                                library.getGroupNumber());
+                        trackDao.deleteByLibraryId(library.getId());
+                        specialTagDao.deleteByLibraryId(library.getId());
+                        return SubmitResult.success(library);
+                    }
+                }
+                if (result.getMarkerScore() <= group.getTotalScore()) {
+                    if (submitLibrary(library, marker, group, result)) {
+                        updateMarkedCount(group);
+                        return SubmitResult.success(library);
+                    }
                 }
             }
         } else if (group.getStatus() == MarkStatus.TRIAL) {
             TrialLibrary library = trialLibraryDao.findOne(result.getLibraryId());
             if (library != null && library.getExamId().equals(group.getExamId()) && library.getSubjectCode()
                     .equals(group.getSubjectCode()) && library.getGroupNumber().equals(group.getNumber())
-                    && result.getMarkerScore() <= group.getTotalScore() && StringUtils
-                    .isNotBlank(result.getScoreList())) {
-                TrialHistory history = new TrialHistory();
-                history.setExamId(library.getExamId());
-                history.setSubjectCode(library.getSubjectCode());
-                history.setGroupNumber(library.getGroupNumber());
-                history.setLibraryId(library.getId());
-                history.setStudentId(library.getStudentId());
-                history.setMarkerId(marker.getId());
-                history.setMarkerTime(new Date());
-                history.setMarkerScore(result.getMarkerScore());
-                history.setMarkerScoreList(result.getScoreList());
-                history.setSecretNumber(library.getSecretNumber());
-                history = trialHistoryDao.save(history);
-                if (history != null) {
-                    if (result.getTrackList() != null) {
-                        trialTrackDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
-                        trialTrackDao.save(result.getTrackList(history));
-                    }
-                    if (result.getSpecialTagList() != null) {
-                        trialTagDao.deleteByLibraryIdAndMarkerId(history.getLibraryId(), history.getMarkerId());
-                        trialTagDao.save(result.getTagList(history));
-                    }
-                    updateMarkedCount(group);
-                    // releaseLibrary(library, marker);
-                    return SubmitResult.success(library);
+                    && result.getMarkerScore() <= group.getTotalScore()) {
+                if ((library.getMarkerId() == null && !hasApplied(library, marker)) || (library.getMarkerId() != null
+                        && !library.getMarkerId().equals(marker.getId()))) {
+                    return SubmitResult.faile();
+                }
+                library.setMarkerId(marker.getId());
+                library.setMarkerTime(new Date());
+                // 未选做
+                if (result.isUnselective() && group.isSelective()) {
+                    result.setMarkerScore(UN_SELECTIVE_SCORE);
+                    result.setScoreList(new Double[0]);
+                    trialTrackDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
+                    trialTagDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
                 }
+                library.setMarkerScore(result.getMarkerScore());
+                library.setMarkerScoreList(result.getScoreList());
+                library = trialLibraryDao.save(library);
+                if (result.getTrackList() != null && !result.isUnselective()) {
+                    trialTrackDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
+                    trialTrackDao.save(result.getTrackList(library));
+                }
+                if (result.getSpecialTagList() != null && !result.isUnselective()) {
+                    trialTagDao.deleteByLibraryIdAndMarkerId(library.getId(), library.getMarkerId());
+                    trialTagDao.save(result.getTagList(library));
+                }
+                checkStudentTrial(library, group);
+                updateMarkedCount(group);
+                return SubmitResult.success(library);
             }
         }
         return SubmitResult.faile();
     }
 
-    private void saveProblemHistory(MarkResult result, MarkLibrary library) {
+    private void saveProblemHistory(MarkResult result, MarkLibrary library, Marker marker) {
         ProblemHistory history = problemHistoryDao.findByLibraryIdAndStatus(library.getId(), HistoryStatus.WAITING);
         if (history == null) {
             history = new ProblemHistory();
@@ -562,6 +561,7 @@ public class MarkServiceImpl implements MarkService {
         history.setGroupNumber(library.getGroupNumber());
         history.setProblemId(result.getProblemTypeId());
         history.setStatus(HistoryStatus.WAITING);
+        history.setMarkerId(marker.getId());
         problemHistoryDao.save(history);
     }
 
@@ -589,6 +589,13 @@ public class MarkServiceImpl implements MarkService {
                 > 0) {
             return false;
         }
+        // 未选做
+        if (result.isUnselective() && group.isSelective()) {
+            result.setMarkerScore(UN_SELECTIVE_SCORE);
+            result.setScoreList(new Double[0]);
+            trackDao.deleteByLibraryId(library.getId());
+            specialTagDao.deleteByLibraryId(library.getId());
+        }
         // 尝试提交评卷结果
         Date now = new Date();
         if (libraryDao
@@ -599,7 +606,7 @@ public class MarkServiceImpl implements MarkService {
             return false;
         }
         // 保存阅卷轨迹
-        if (result.getTrackList() != null) {
+        if (result.getTrackList() != null && !result.isUnselective()) {
             trackDao.deleteByLibraryId(library.getId());
             List<MarkTrack> tracks = result.getTrackList(library, marker);
             for (MarkTrack markTrack : tracks) {
@@ -607,7 +614,7 @@ public class MarkServiceImpl implements MarkService {
             }
         }
         // 保存特殊标记
-        if (result.getSpecialTagList() != null) {
+        if (result.getSpecialTagList() != null && !result.isUnselective()) {
             specialTagDao.deleteByLibraryId(library.getId());
             specialTagDao.save(result.getSpecialTagList(library, marker));
         }
@@ -619,11 +626,22 @@ public class MarkServiceImpl implements MarkService {
                     .findByStudentIdAndGroupNumberAndStatus(library.getStudentId(), library.getGroupNumber(),
                             LibraryStatus.MARKED, LibraryStatus.INSPECTED);
             for (MarkLibrary other : list) {
+                // 本评卷任务或组长已打分,则跳过该任务
                 if (other.getId().equals(library.getId()) || other.getHeaderScore() != null) {
-                    // 本评卷任务或组长已打分,则跳过该任务
                     continue;
                 }
-                // 分差超过阀值,
+                // 均为未选做,跳过该任务
+                if (other.getMarkerScore() == UN_SELECTIVE_SCORE && result.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                    continue;
+                }
+                // 其中一个有分另一个未选做 直接进入仲裁
+                if ((other.getMarkerScore() != UN_SELECTIVE_SCORE && result.getMarkerScore() == UN_SELECTIVE_SCORE) || (
+                        other.getMarkerScore() == UN_SELECTIVE_SCORE
+                                && result.getMarkerScore() != UN_SELECTIVE_SCORE)) {
+                    history = buildArbitrateHistory(library, now);
+                    break;
+                }
+                // 分差超过阀值
                 if (Math.abs(other.getMarkerScore() - result.getMarkerScore()) > group.getArbitrateThreshold()) {
                     // 开启三评
                     if (group.getThirdPolicy().equals(ThirdPolicy.LOW_DIFF_HIGH_AVG)) {
@@ -712,19 +730,19 @@ public class MarkServiceImpl implements MarkService {
 
     /**
      * 管理员/组长打回某个评卷任务<br>
-     * 暂时不用到BACKED状态,直接等同于重置该评卷任务
+     * isRest为true时重置该评卷任务
      *
      * @param library - 正评任务
      */
     @Override
     @Transactional
-    public boolean backLibrary(MarkLibrary library, Integer userId) {
+    public boolean rejectLibrary(MarkLibrary library, Integer userId, boolean isRest) {
         MarkGroup group = groupDao.findOne(library.getExamId(), library.getSubjectCode(), library.getGroupNumber());
         if (group.getStatus() == MarkStatus.FINISH) {
             return false;
         }
-        if (libraryDao.resetById(library.getId(), library.getMarkerId(), LibraryStatus.REJECTED, LibraryStatus.MARKED,
-                LibraryStatus.PROBLEM, LibraryStatus.INSPECTED) > 0) {
+        if (libraryDao.resetById(library.getId(), null, isRest ? LibraryStatus.WAITING : LibraryStatus.REJECTED,
+                LibraryStatus.MARKED, LibraryStatus.PROBLEM, LibraryStatus.INSPECTED) > 0) {
             trackDao.deleteByLibraryId(library.getId());
             specialTagDao.deleteByLibraryId(library.getId());
             resetStudentGroup(library.getStudentId(), library.getExamId(), library.getSubjectCode(),
@@ -759,7 +777,7 @@ public class MarkServiceImpl implements MarkService {
     @Transactional
     public boolean resetLibrary(TrialLibrary library) {
         if (library != null) {
-            trialHistoryDao.deleteByLibraryId(library.getId());
+            trialLibraryDao.resetById(library.getId());
             trialTrackDao.deleteByLibraryId(library.getId());
             trialTagDao.deleteByLibraryId(library.getId());
             return true;
@@ -823,34 +841,65 @@ public class MarkServiceImpl implements MarkService {
 
     private void scoreCalculate(Integer studentId) {
         List<ScoreItem> scoreList = new ArrayList<>();
-        Map<Integer, List<SubjectiveScore>> map = new HashMap<Integer, List<SubjectiveScore>>();
-        double totalScore = 0.0;
+        Map<Integer, List<SubjectiveScore>> mainScoreMap = new HashMap<Integer, List<SubjectiveScore>>();
+        Map<Integer, Double> scoreMap = new HashMap<Integer, Double>();
+
         // 循环所有主观得分明细
         List<SubjectiveScore> list = scoreDao.findByStudentId(studentId);
+        list.sort(null);
         for (SubjectiveScore ss : list) {
-            totalScore = BigDecimalUtils.add(totalScore, ss.getScore());
-            scoreList.add(new ScoreItem(ss));
-            List<SubjectiveScore> mainScoreList = map.get(ss.getMainNumber());
+            List<SubjectiveScore> mainScoreList = mainScoreMap.get(ss.getMainNumber());
             if (mainScoreList == null) {
                 mainScoreList = new ArrayList<SubjectiveScore>();
             }
             mainScoreList.add(ss);
-            map.put(ss.getMainNumber(), mainScoreList);
+            mainScoreMap.put(ss.getMainNumber(), mainScoreList);
+            scoreList.add(new ScoreItem(ss));
         }
         // 计算大题分
-        for (Integer mainNumber : map.keySet()) {
-            List<SubjectiveScore> mainScoreList = map.get(mainNumber);
-            double mainScore = 0.0;
+        for (Integer mainNumber : mainScoreMap.keySet()) {
+            List<SubjectiveScore> mainScoreList = mainScoreMap.get(mainNumber);
+            BigDecimal mainScore = BigDecimal.ZERO;
             for (SubjectiveScore subjectiveScore : mainScoreList) {
-                mainScore = BigDecimalUtils.add(mainScore, subjectiveScore.getScore());
+                if (subjectiveScore.getScore() != UN_SELECTIVE_SCORE) {
+                    mainScore = mainScore.add(BigDecimal.valueOf(subjectiveScore.getScore()));
+                }
             }
             for (SubjectiveScore subjectiveScore : mainScoreList) {
-                subjectiveScore.setMainScore(mainScore);
+                subjectiveScore.setMainScore(mainScore.doubleValue());
                 scoreDao.saveAndFlush(subjectiveScore);
             }
+            scoreMap.put(mainNumber, mainScore.doubleValue());
+        }
+        // 计算选做题分数
+        ExamStudent student = studentService.findById(studentId);
+        List<SelectiveGroup> selectiveGroups = selectiveGroupService
+                .findByExamIdAndSubjectCode(student.getExamId(), student.getSubjectCode());
+
+        List<Double> selectiveList = new ArrayList<Double>();
+        Integer selectiveCount = 0;
+        for (SelectiveGroup selectiveGroup : selectiveGroups) {
+            double mainScore = scoreMap.get(selectiveGroup.getMainNumber());
+            scoreMap.remove(selectiveGroup.getMainNumber());
+            selectiveList.add(mainScore);
+            if (selectiveCount == 0) {
+                selectiveCount = selectiveGroup.getSelectiveCount();
+            }
+        }
+        Collections.sort(selectiveList);
+        Collections.reverse(selectiveList);
+        // 计算总分
+        BigDecimal totalScore = BigDecimal.ZERO;
+        for (Integer mainNumber : scoreMap.keySet()) {
+            totalScore = totalScore.add(BigDecimal.valueOf(scoreMap.get(mainNumber)));
+        }
+        for (int i = 0; i < selectiveList.size(); i++) {
+            if (i < selectiveCount && selectiveList.get(i) != UN_SELECTIVE_SCORE) {
+                totalScore = totalScore.add(BigDecimal.valueOf(selectiveList.get(i)));
+            }
         }
         // 全部评完,更新考生主观题得分
-        studentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.MARKED, totalScore,
+        studentService.updateSubjectiveStatusAndScore(studentId, SubjectiveStatus.MARKED, totalScore.doubleValue(),
                 ExamStudent.buildScoreList(scoreList));
     }
 
@@ -864,12 +913,23 @@ public class MarkServiceImpl implements MarkService {
         if (list.isEmpty()) {
             return false;
         }
+        boolean selectiveAll = false;
         for (MarkLibrary library : list) {
             if (library.getStatus() != LibraryStatus.MARKED && library.getStatus() != LibraryStatus.ARBITRATED
                     && library.getStatus() != LibraryStatus.INSPECTED) {
                 // 有非完成状态的评卷任务,直接返回
                 return false;
             }
+            double markerScore = library.getStatus() == LibraryStatus.ARBITRATED ?
+                    library.getHeaderScore() :
+                    library.getMarkerScore();
+            if (markerScore == UN_SELECTIVE_SCORE) {
+                selectiveAll = true;
+            }
+        }
+        if (selectiveAll) {
+            group.setMarkScore(UN_SELECTIVE_SCORE);
+            return true;
         }
         // 开启三评
         if (ThirdPolicy.LOW_DIFF_HIGH_AVG.equals(group.getThirdPolicy()) && list.size() == 3) {
@@ -897,7 +957,7 @@ public class MarkServiceImpl implements MarkService {
         }
         for (MarkLibrary library : list) {
             count++;
-            Double current = (library.getHeaderScore() != null ? library.getHeaderScore() : library.getMarkerScore());
+            Double current = library.getHeaderScore() != null ? library.getHeaderScore() : library.getMarkerScore();
             List<ScoreItem> scores = library.getScoreList();
             if (count == 1) {
                 // 首份评卷任务,直接取总分与明细
@@ -907,7 +967,7 @@ public class MarkServiceImpl implements MarkService {
                 switch (policy) {
                 case AVG:
                     // 直接累加
-                    score += current;
+                    score = BigDecimalUtils.add(score, current);
                     for (int i = 0; i < detail.size(); i++) {
                         try {
                             ScoreItem item = detail.get(i);
@@ -1131,8 +1191,6 @@ public class MarkServiceImpl implements MarkService {
             trialTrackDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
                     group.getNumber());
             trialTagDao.deleteByExamAndSubjectAndGroup(group.getExamId(), group.getSubjectCode(), group.getNumber());
-            trialHistoryDao.deleteByExamIdAndSubjectCodeAndGroupNumber(group.getExamId(), group.getSubjectCode(),
-                    group.getNumber());
         }
         updateLibraryCount(group);
         groupDao.resetCount(group.getExamId(), group.getSubjectCode(), group.getNumber());
@@ -1178,11 +1236,6 @@ public class MarkServiceImpl implements MarkService {
         markerLastUpdateTime.put(marker.getId(), System.currentTimeMillis());
     }
 
-    private double sumTotalScore(Integer examId, String subjectCode) {
-        Double score = groupDao.sumTotalScore(examId, subjectCode);
-        return score != null ? score : 0d;
-    }
-
     @Override
     public boolean needUpdateQuality(Marker marker, long expireMinutes) {
         if (marker == null) {
@@ -1220,6 +1273,25 @@ public class MarkServiceImpl implements MarkService {
         }
     }
 
+    /**
+     * 考生分组判断是否评卷完成,以及后续的统一处理动作
+     *
+     * @param library
+     * @param group
+     */
+    private void checkStudentTrial(TrialLibrary library, MarkGroup group) {
+        updateStudentGroupStatus(library.getStudentId(), group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                SubjectiveStatus.MARKED);
+        updateStudentGroupScore(library.getStudentId(), group.getExamId(), group.getSubjectCode(), group.getNumber(),
+                library.getMarkerScore(), library.getScoreList());
+        // 未分组的题目
+        long unGroupQuestionCount = questionService
+                .countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(group.getExamId(), group.getSubjectCode(),
+                        false);
+        long groupCount = groupDao.countByExamIdAndSubjectCode(group.getExamId(), group.getSubjectCode());
+        checkStudentSubjective(library.getStudentId(), groupCount, unGroupQuestionCount);
+    }
+
     /**
      * 考生分组判断是否评卷完成,以及后续的统一处理动作
      *
@@ -1233,7 +1305,7 @@ public class MarkServiceImpl implements MarkService {
             updateStudentGroupScore(studentId, group.getExamId(), group.getSubjectCode(), group.getNumber(),
                     group.getMarkScore(), group.getMarkScoreDetail());
             // 未分组的题目
-            long unGroupQuestionCount = questionDao
+            long unGroupQuestionCount = questionService
                     .countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(group.getExamId(), group.getSubjectCode(),
                             false);
             long groupCount = groupDao.countByExamIdAndSubjectCode(group.getExamId(), group.getSubjectCode());
@@ -1289,10 +1361,9 @@ public class MarkServiceImpl implements MarkService {
     private void updateStudentGroupScore(Integer studentId, Integer examId, String subjectCode, Integer groupNumber,
             double score, List<ScoreItem> scoreList) {
         // scoreDao.deleteByStudentIdAndGroupNumber(studentId, groupNumber);
-        List<ExamQuestion> questions = questionDao
-                .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(examId, subjectCode, false, groupNumber);
-        for (int i = 0; i < scoreList.size(); i++) {
-            ScoreItem item = scoreList.get(i);
+        List<ExamQuestion> questions = questionService
+                .findByExamAndSubjectAndObjectiveAndGroupNumber(examId, subjectCode, false, groupNumber);
+        for (int i = 0; i < questions.size(); i++) {
             ExamQuestion question = questions.get(i);
             SubjectiveScore ss = new SubjectiveScore();
             ss.setStudentId(studentId);
@@ -1300,10 +1371,16 @@ public class MarkServiceImpl implements MarkService {
             ss.setSubjectCode(subjectCode);
             ss.setGroupNumber(groupNumber);
             ss.setGroupScore(score);
-            ss.setMainScore(0.0);
             ss.setMainNumber(question.getMainNumber());
             ss.setSubNumber(question.getSubNumber());
-            ss.setScore(item.getScore());
+            if (score != UN_SELECTIVE_SCORE) {
+                ScoreItem item = scoreList.get(i);
+                ss.setScore(item.getScore());
+                ss.setMainScore(0.0);
+            } else {
+                ss.setScore(score);
+                ss.setMainScore(score);
+            }
             scoreDao.saveAndFlush(ss);
         }
     }
@@ -1358,14 +1435,14 @@ public class MarkServiceImpl implements MarkService {
         }
         for (Integer groupNumber : map.keySet()) {
             MarkGroup group = groupDao.findOne(student.getExamId(), student.getSubjectCode(), groupNumber);
-            if (group.getStatus() == MarkStatus.FINISH) {
+            if (group.getStatus() == MarkStatus.FINISH || group.getStatus() == MarkStatus.TRIAL) {
                 return false;
             }
         }
         for (Integer groupNumber : map.keySet()) {
             List<MarkLibrary> list = libraryDao.findByStudentIdAndGroupNumber(student.getId(), groupNumber);
-            List<ExamQuestion> questions = questionDao
-                    .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(student.getExamId(), student.getSubjectCode(),
+            List<ExamQuestion> questions = questionService
+                    .findByExamAndSubjectAndObjectiveAndGroupNumber(student.getExamId(), student.getSubjectCode(),
                             false, groupNumber);
             List<MarkStepDTO> qList = map.get(groupNumber);
             MarkGroup group = groupDao.findOne(student.getExamId(), student.getSubjectCode(), groupNumber);
@@ -1381,14 +1458,16 @@ public class MarkServiceImpl implements MarkService {
                 }
                 if (library.getStatus().equals(LibraryStatus.ARBITRATED) || qList.size() == questions.size()) {
                     // 仲裁任务直接重置 或者该分组下所有分数被打回也重置
-                    libraryDao.resetById(library.getId(), library.getMarkerId(), LibraryStatus.REJECTED,
-                            LibraryStatus.MARKED, LibraryStatus.PROBLEM, LibraryStatus.INSPECTED);
+                    libraryDao.resetById(library.getId(), null, LibraryStatus.REJECTED, LibraryStatus.MARKED,
+                            LibraryStatus.PROBLEM, LibraryStatus.INSPECTED, LibraryStatus.ARBITRATED);
                     trackDao.deleteByLibraryId(library.getId());
                     specialTagDao.deleteByLibraryId(library.getId());
+                    arbitrateDao.deleteByStudentIdAndGroupNumber(student.getId(), groupNumber);
                     count++;
                     continue;
                 }
-                if (library.getStatus().equals(LibraryStatus.MARKED)) {
+                if (library.getStatus().equals(LibraryStatus.MARKED) || library.getStatus()
+                        .equals(LibraryStatus.INSPECTED)) {
                     List<ScoreItem> sList = library.getScoreList();
                     for (MarkStepDTO markStepDTO : qList) {
                         trackDao.deleteByLibraryIdAndQuestionNumber(library.getId(),
@@ -1407,6 +1486,8 @@ public class MarkServiceImpl implements MarkService {
                         ScoreItem scoreItem = sList.get(i);
                         if (scoreItem.getScore() != null) {
                             markerScoreList.append(scoreItem.getScore());
+                        } else {
+                            markerScoreList.append("#");
                         }
                         if (i < sList.size() - 1) {
                             markerScoreList.append(",");
@@ -1414,7 +1495,8 @@ public class MarkServiceImpl implements MarkService {
                     }
                     if (libraryDao
                             .updateMarkerResult(library.getId(), LibraryStatus.REJECTED, library.getMarkerId(), null,
-                                    markerScoreList.toString(), null, null, LibraryStatus.MARKED) == 1) {
+                                    markerScoreList.toString(), null, null, LibraryStatus.MARKED,
+                                    LibraryStatus.INSPECTED) == 1) {
                         count++;
                     }
                 }
@@ -1433,18 +1515,27 @@ public class MarkServiceImpl implements MarkService {
     @Transactional
     @Override
     public boolean deleteByQuestion(ExamQuestion question) {
+        SelectiveGroup selectiveGroup = selectiveGroupService
+                .findOne(question.getExamId(), question.getSubjectCode(), question.getMainNumber());
+        if (selectiveGroup != null) {
+            return false;
+        }
         if (!question.isObjective() && question.getGroupNumber() != null) {
             return false;
         } else {
             int examId = question.getExamId();
             String subjectCode = question.getSubjectCode();
             boolean objective = question.isObjective();
-            questionDao.delete(question);
+            ExamSubject subject = subjectService.find(examId, subjectCode);
+            double totalScore = objective ?
+                    BigDecimalUtils.sub(subject.getObjectiveScore(), question.getTotalScore()) :
+                    BigDecimalUtils.sub(subject.getSubjectiveScore(), question.getTotalScore());
+            questionService.deleteById(question.getId());
             if (objective) {
                 examService.updateObjectiveStatus(examId, ObjectiveStatus.WAITING);
             } else {
                 // 未分组的题目
-                long unGroupQuestionCount = questionDao
+                long unGroupQuestionCount = questionService
                         .countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(examId, subjectCode, false);
                 // 考生整体状态与总分更新
                 long groupCount = groupDao.countByExamIdAndSubjectCode(examId, subjectCode);
@@ -1461,10 +1552,7 @@ public class MarkServiceImpl implements MarkService {
                     }
                 }
             }
-
-            subjectService.updateScore(examId, subjectCode, objective,
-                    questionService.sumTotalScore(examId, subjectCode, objective));
-
+            subjectService.updateScore(examId, subjectCode, objective, totalScore);
             return true;
         }
     }
@@ -1472,13 +1560,16 @@ public class MarkServiceImpl implements MarkService {
     @Override
     @Transactional
     public boolean rejectLibrary(MarkLibrary library, MarkStepDTO[] questionList, Integer userId) {
+        List<ExamQuestion> questions = questionService
+                .findByExamAndSubjectAndObjectiveAndGroupNumber(library.getExamId(), library.getSubjectCode(), false,
+                        library.getGroupNumber());
+        if (questionList.length == questions.size()) {
+            return rejectLibrary(library, userId, false);
+        }
         MarkGroup group = groupDao.findOne(library.getExamId(), library.getSubjectCode(), library.getGroupNumber());
         if (group.getStatus() == MarkStatus.FINISH) {
             return false;
         }
-        List<ExamQuestion> questions = questionDao
-                .findByExamIdAndSubjectCodeAndObjectiveAndGroupNumber(library.getExamId(), library.getSubjectCode(),
-                        false, library.getGroupNumber());
         List<ScoreItem> sList = library.getScoreList();
         for (MarkStepDTO markStepDTO : questionList) {
             trackDao.deleteByLibraryIdAndQuestionNumber(library.getId(),
@@ -1497,13 +1588,15 @@ public class MarkServiceImpl implements MarkService {
             ScoreItem scoreItem = sList.get(i);
             if (scoreItem.getScore() != null) {
                 markerScoreList.append(scoreItem.getScore());
+            } else {
+                markerScoreList.append("#");
             }
             if (i < sList.size() - 1) {
                 markerScoreList.append(",");
             }
         }
         if (libraryDao.updateMarkerResult(library.getId(), LibraryStatus.REJECTED, library.getMarkerId(), null,
-                markerScoreList.toString(), null, null, LibraryStatus.MARKED) == 1) {
+                markerScoreList.toString(), null, null, LibraryStatus.MARKED, LibraryStatus.INSPECTED) == 1) {
             resetStudentGroup(library.getStudentId(), library.getExamId(), library.getSubjectCode(),
                     library.getGroupNumber());
             problemHistoryDao

+ 70 - 46
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TaskServiceImpl.java

@@ -30,7 +30,6 @@ import cn.com.qmth.stmms.biz.mark.model.MarkTrack;
 import cn.com.qmth.stmms.biz.mark.model.SpecialTagDTO;
 import cn.com.qmth.stmms.biz.mark.model.Task;
 import cn.com.qmth.stmms.biz.mark.model.TrackDTO;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
@@ -44,6 +43,8 @@ import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.ScoreItem;
 import cn.com.qmth.stmms.common.enums.ExamType;
 import cn.com.qmth.stmms.common.enums.LibraryStatus;
+import cn.com.qmth.stmms.common.enums.MarkStatus;
+import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
 
 /**
  * 评卷任务服务实现
@@ -55,6 +56,8 @@ public class TaskServiceImpl implements TaskService {
 
     private static Logger log = LoggerFactory.getLogger(TaskServiceImpl.class);
 
+    public static final double UN_SELECTIVE_SCORE = -1;
+
     @Autowired
     private MarkLibraryService libraryService;
 
@@ -118,7 +121,7 @@ public class TaskServiceImpl implements TaskService {
         if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
             task.setObjectiveScore(student.getObjectiveScore());
         }
-        task.setMarkTime(history.getUpdateTime());
+        task.setMarkerTime(history.getUpdateTime());
         if (history.getTotalScore() != null) {
             task.setMarkerScore(history.getTotalScore());
         }
@@ -141,6 +144,10 @@ public class TaskServiceImpl implements TaskService {
                 if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                     step.setScore(sItems.get(i).getScore());
                 }
+                // 未选做
+                if (history.getTotalScore() != null && history.getTotalScore() == UN_SELECTIVE_SCORE) {
+                    step.setScore(UN_SELECTIVE_SCORE);
+                }
                 // 增加阅卷轨迹列表获取
                 String questionNumber = question.getQuestionNumber();
                 for (MarkTrack track : tracks) {
@@ -183,7 +190,7 @@ public class TaskServiceImpl implements TaskService {
         if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
             task.setObjectiveScore(student.getObjectiveScore());
         }
-        task.setMarkTime(library.getMarkerTime());
+        task.setMarkerTime(library.getMarkerTime());
         if (library.getStatus() == LibraryStatus.REJECTED) {
             task.setRejected(true);
         }
@@ -195,7 +202,7 @@ public class TaskServiceImpl implements TaskService {
     }
 
     @Override
-    public Task build(TrialLibrary library, TrialHistory history) {
+    public Task build(TrialLibrary library) {
         Exam exam = examService.findById(library.getExamId());
         ExamSubject subject = subjectService.find(library.getExamId(), library.getSubjectCode());
         ExamStudent student = studentService.findByExamIdAndExamNumber(library.getExamId(), library.getExamNumber());
@@ -209,7 +216,7 @@ public class TaskServiceImpl implements TaskService {
         task.setStudentName(student.getName());
         task.setExamNumber(library.getExamNumber());
         task.setSubject(subject);
-        task.setQuestionList(buildTrialStep(group, history));
+        task.setQuestionList(buildTrialStep(group, library));
         if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
             task.setObjectiveScore(student.getObjectiveScore());
         }
@@ -222,10 +229,10 @@ public class TaskServiceImpl implements TaskService {
             task.setSheetUrls(fileService.getSheetUris(library.getExamId(), library.getExamNumber(), 1,
                     student.getSheetCount()));
         }
-        if (history != null) {
-            task.setSpecialTagList(getTrialTagList(history));
-            task.setMarkTime(history.getMarkerTime());
-            task.setMarkerScore(history.getMarkerScore());
+        if (library.getMarkerId() != null) {
+            task.setSpecialTagList(getTrialTagList(library));
+            task.setMarkerTime(library.getMarkerTime());
+            task.setMarkerScore(library.getMarkerScore());
             task.setPrevious(true);
         }
         return task;
@@ -248,6 +255,10 @@ public class TaskServiceImpl implements TaskService {
                 if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                     step.setScore(sItems.get(i).getScore());
                 }
+                // 未选做
+                if (library.getMarkerScore() != null && library.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                    step.setScore(UN_SELECTIVE_SCORE);
+                }
                 // 增加阅卷轨迹列表获取
                 String questionNumber = question.getQuestionNumber();
                 for (MarkTrack track : tracks) {
@@ -261,15 +272,15 @@ public class TaskServiceImpl implements TaskService {
         return list;
     }
 
-    private List<MarkStepDTO> buildTrialStep(MarkGroup group, TrialHistory history) {
+    private List<MarkStepDTO> buildTrialStep(MarkGroup group, TrialLibrary library) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
         List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(group.getExamId(),
                 group.getSubjectCode(), false, group.getNumber());
         List<TrialTrack> tracks = new ArrayList<TrialTrack>();
         List<ScoreItem> sItems = new ArrayList<ScoreItem>();
-        if (history != null) {
-            tracks = trialService.findTrack(history.getLibraryId(), history.getMarkerId());
-            sItems = history.getScoreList();
+        if (library.getMarkerId() != null) {
+            tracks = trialService.findTrack(library.getId());
+            sItems = library.getScoreList();
         }
         for (int i = 0; i < sList.size(); i++) {
             ExamQuestion question = sList.get(i);
@@ -277,6 +288,9 @@ public class TaskServiceImpl implements TaskService {
             if (!sItems.isEmpty() && sItems.size() == sList.size()) {
                 step.setScore(sItems.get(i).getScore());
             }
+            if (library.getMarkerScore() != null && library.getMarkerScore() == UN_SELECTIVE_SCORE) {
+                step.setScore(UN_SELECTIVE_SCORE);
+            }
             // 增加阅卷轨迹列表获取
             String questionNumber = question.getQuestionNumber();
             for (TrialTrack track : tracks) {
@@ -308,32 +322,20 @@ public class TaskServiceImpl implements TaskService {
         if (!list.isEmpty()) {
             specialTags = new SpecialTagDTO[list.size()];
             for (int i = 0; i < list.size(); i++) {
-                SpecialTagDTO specialTagDTO = new SpecialTagDTO();
-                specialTagDTO.setTagName(list.get(i).getTagName());
-                specialTagDTO.setPositionX(list.get(i).getPositionX());
-                specialTagDTO.setPositionY(list.get(i).getPositionY());
-                specialTagDTO.setOffsetIndex(list.get(i).getOffsetIndex());
-                specialTagDTO.setOffsetX(list.get(i).getOffsetX());
-                specialTagDTO.setOffsetY(list.get(i).getOffsetY());
+                SpecialTagDTO specialTagDTO = new SpecialTagDTO(list.get(i));
                 specialTags[i] = specialTagDTO;
             }
         }
         return specialTags;
     }
 
-    public SpecialTagDTO[] getTrialTagList(TrialHistory history) {
+    public SpecialTagDTO[] getTrialTagList(TrialLibrary library) {
         SpecialTagDTO[] specialTags = null;
-        List<TrialTag> list = trialService.findTag(history.getLibraryId(), history.getMarkerId());
+        List<TrialTag> list = trialService.findTag(library.getId());
         if (!list.isEmpty()) {
             specialTags = new SpecialTagDTO[list.size()];
             for (int i = 0; i < list.size(); i++) {
-                SpecialTagDTO specialTagDTO = new SpecialTagDTO();
-                specialTagDTO.setTagName(list.get(i).getContent());
-                specialTagDTO.setPositionX(list.get(i).getPositionX());
-                specialTagDTO.setPositionY(list.get(i).getPositionY());
-                specialTagDTO.setOffsetIndex(list.get(i).getOffsetIndex());
-                specialTagDTO.setOffsetX(list.get(i).getOffsetX());
-                specialTagDTO.setOffsetY(list.get(i).getOffsetY());
+                SpecialTagDTO specialTagDTO = new SpecialTagDTO(list.get(i));
                 specialTags[i] = specialTagDTO;
             }
         }
@@ -360,8 +362,12 @@ public class TaskServiceImpl implements TaskService {
             task.setSheetUrls(fileService.getSheetUris(student.getExamId(), student.getExamNumber(), 1,
                     student.getSheetCount()));
         }
-        task.setQuestionList(buildMarkStep(student));
-        task.setSpecialTagList(getMarkSpecialTagList(student));
+        if (!student.getSubjectiveStatus().equals(SubjectiveStatus.UNMARK)) {
+            long trialGroupCount = groupService.countByExamAndSubjectAndStatus(student.getExamId(),
+                    student.getSubjectCode(), MarkStatus.TRIAL);
+            task.setQuestionList(buildMarkStep(student, trialGroupCount));
+            task.setSpecialTagList(getMarkSpecialTagList(student, trialGroupCount));
+        }
         if (StringUtils.isNotBlank(student.getObjectiveScoreList())) {
             task.setObjectiveScore(student.getObjectiveScore());
         }
@@ -370,16 +376,24 @@ public class TaskServiceImpl implements TaskService {
         return task;
     }
 
-    private SpecialTagDTO[] getMarkSpecialTagList(ExamStudent student) {
+    private SpecialTagDTO[] getMarkSpecialTagList(ExamStudent student, long trialGroupCount) {
         List<SpecialTagDTO> list = new ArrayList<SpecialTagDTO>();
-        List<MarkGroup> groups = groupService.findByExamAndSubject(student.getExamId(), student.getSubjectCode());
-        for (MarkGroup group : groups) {
-            List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(), group.getNumber());
-            if (libraryList.size() == 1) {
-                SpecialTagDTO[] tags = getMarkSpecialTagList(libraryList.get(0).getId());
-                if (tags != null) {
-                    for (SpecialTagDTO specialTagDTO : tags) {
-                        list.add(specialTagDTO);
+        if (trialGroupCount > 0) {
+            List<TrialTag> tags = trialService.findTagByStudentId(student.getId());
+            for (TrialTag trialTag : tags) {
+                list.add(new SpecialTagDTO(trialTag));
+            }
+        } else {
+            List<MarkGroup> groups = groupService.findByExamAndSubject(student.getExamId(), student.getSubjectCode());
+            for (MarkGroup group : groups) {
+                List<MarkLibrary> libraryList = libraryService
+                        .findByStudentAndGroup(student.getId(), group.getNumber());
+                if (libraryList.size() == 1) {
+                    SpecialTagDTO[] tags = getMarkSpecialTagList(libraryList.get(0).getId());
+                    if (tags != null) {
+                        for (SpecialTagDTO specialTagDTO : tags) {
+                            list.add(specialTagDTO);
+                        }
                     }
                 }
             }
@@ -391,7 +405,7 @@ public class TaskServiceImpl implements TaskService {
         return specialTags;
     }
 
-    private List<MarkStepDTO> buildMarkStep(ExamStudent student) {
+    private List<MarkStepDTO> buildMarkStep(ExamStudent student, long trialGroupCount) {
         List<MarkStepDTO> list = new LinkedList<MarkStepDTO>();
         List<ExamQuestion> sList = questionService.findByExamAndSubjectAndObjective(student.getExamId(),
                 student.getSubjectCode(), false);
@@ -403,16 +417,26 @@ public class TaskServiceImpl implements TaskService {
                 step.setScore(sItems.get(i).getScore());
             }
             // 增加阅卷轨迹列表获取
-            List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(),
-                    question.getGroupNumber());
-            if (libraryList.size() == 1) {
-                List<MarkTrack> tracks = trackService.findByStudentId(student.getId());
+            if (trialGroupCount > 0) {
+                List<TrialTrack> tracks = trialService.findTrackByStudentId(student.getId());
                 String questionNumber = question.getQuestionNumber();
-                for (MarkTrack track : tracks) {
+                for (TrialTrack track : tracks) {
                     if (track.getQuestionNumber().equals(questionNumber)) {
                         step.addTrack(new TrackDTO(track));
                     }
                 }
+            } else {
+                List<MarkLibrary> libraryList = libraryService.findByStudentAndGroup(student.getId(),
+                        question.getGroupNumber());
+                if (libraryList.size() == 1) {
+                    List<MarkTrack> tracks = trackService.findByStudentId(student.getId());
+                    String questionNumber = question.getQuestionNumber();
+                    for (MarkTrack track : tracks) {
+                        if (track.getQuestionNumber().equals(questionNumber)) {
+                            step.addTrack(new TrackDTO(track));
+                        }
+                    }
+                }
             }
             list.add(step);
         }

+ 48 - 59
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/TrialServiceImpl.java

@@ -1,31 +1,31 @@
 package cn.com.qmth.stmms.biz.mark.service.Impl;
 
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+
 import cn.com.qmth.stmms.biz.common.BaseQuery;
 import cn.com.qmth.stmms.biz.common.BaseQueryService;
-import cn.com.qmth.stmms.biz.mark.dao.TrialHistoryDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialLibraryDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialTagDao;
 import cn.com.qmth.stmms.biz.mark.dao.TrialTrackDao;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
 import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
 import cn.com.qmth.stmms.biz.mark.service.TrialService;
-import org.apache.commons.lang.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.stereotype.Service;
-
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-import java.util.LinkedList;
-import java.util.List;
 
 @Service
 public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements TrialService {
@@ -33,9 +33,6 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
     @Autowired
     private TrialLibraryDao libraryDao;
 
-    @Autowired
-    private TrialHistoryDao historyDao;
-
     @Autowired
     private TrialTrackDao trackDao;
 
@@ -43,7 +40,7 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
     private TrialTagDao tagDao;
 
     @Override
-    public TrialLibrary findLibrary(Integer id) {
+    public TrialLibrary findById(Integer id) {
         return libraryDao.findOne(id);
     }
 
@@ -54,7 +51,7 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
 
-        return libraryDao.findUnMarked(examId, subjectCode, groupNumber, markerId, query);
+        return libraryDao.findUnMarked(examId, subjectCode, groupNumber, query);
     }
 
     @Override
@@ -71,9 +68,9 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    public List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             int pageNumber, int pageSize, Sort sort, Double markerScore) {
-        BaseQuery<TrialHistory> query = new BaseQuery<>();
+        BaseQuery<TrialLibrary> query = new BaseQuery<>();
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
         if (sort != null) {
@@ -82,43 +79,22 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
             query.setSort(new Sort(Direction.DESC, "markerTime"));
         }
         if (markerScore != null) {
-            return historyDao.findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndMarkerScore(examId, subjectCode,
+            return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndMarkerScore(examId, subjectCode,
                     groupNumber, markerId, markerScore, query);
         } else {
-            return historyDao
-                    .findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerId(examId, subjectCode, groupNumber, markerId,
-                            query);
+            return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerId(examId, subjectCode, groupNumber,
+                    markerId, query);
         }
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer libraryId) {
-        return historyDao.findByPkLibraryId(libraryId);
-    }
-
-    @Override
-    public TrialHistory findHistory(Integer libraryId, Integer markerId) {
-        return historyDao.findByPkLibraryIdAndPkMarkerId(libraryId, markerId);
-    }
-
-    @Override
-    public long countHistory(Integer libraryId) {
-        return historyDao.countByLibraryId(libraryId);
-    }
-
-    @Override
-    public long countMarkerHistory(Integer markerId) {
-        return historyDao.countByMarkerId(markerId);
-    }
-
-    @Override
-    public List<TrialTrack> findTrack(Integer libraryId, Integer markerId) {
-        return trackDao.findByPkLibraryIdAndPkMarkerId(libraryId, markerId);
+    public List<TrialTrack> findTrack(Integer libraryId) {
+        return trackDao.findByPkLibraryId(libraryId);
     }
 
     @Override
-    public List<TrialTag> findTag(Integer libraryId, Integer markerId) {
-        return tagDao.findByLibraryIdAndMarkerIdOrderByIdAsc(libraryId, markerId);
+    public List<TrialTag> findTag(Integer libraryId) {
+        return tagDao.findByLibraryIdOrderByIdAsc(libraryId);
     }
 
     private Specification<TrialLibrary> buildSpecification(final TrialLibrarySearchQuery query) {
@@ -145,17 +121,16 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
                 if (query.getStudentId() != null) {
                     predicates.add(cb.equal(root.get("studentId"), query.getStudentId()));
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
         };
     }
 
     @Override
-    public List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    public List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             String secretNumber, int pageNumber, int pageSize, Sort sort) {
-        BaseQuery<TrialHistory> query = new BaseQuery<>();
+        BaseQuery<TrialLibrary> query = new BaseQuery<>();
         query.setPageNumber(pageNumber);
         query.setPageSize(pageSize);
         if (sort != null) {
@@ -163,8 +138,22 @@ public class TrialServiceImpl extends BaseQueryService<TrialLibrary> implements
         } else {
             query.setSort(new Sort(Direction.DESC, "markerTime"));
         }
-        return historyDao
-                .findByExamIdAndSubjectCodeAndGroupNumberAndPkMarkerIdAndSecretNumber(examId, subjectCode, groupNumber,
-                        markerId, secretNumber, query);
+        return libraryDao.findByExamIdAndSubjectCodeAndGroupNumberAndMarkerIdAndSecretNumber(examId, subjectCode,
+                groupNumber, markerId, secretNumber, query);
+    }
+
+    @Override
+    public long countByMarkerId(Integer markerId) {
+        return libraryDao.countByMarkerId(markerId);
+    }
+
+    @Override
+    public List<TrialTrack> findTrackByStudentId(Integer studentId) {
+        return trackDao.findByStudentId(studentId);
+    }
+
+    @Override
+    public List<TrialTag> findTagByStudentId(Integer studentId) {
+        return tagDao.findByStudentIdOrderByIdAsc(studentId);
     }
 }

+ 3 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkLibraryService.java

@@ -46,4 +46,7 @@ public interface MarkLibraryService {
 
     Set<String> findSubjectUnFinishByExamId(int examId);
 
+    long countByExamAndSubjectAndGroupAndFilterClass(Integer examId, String subjectCode, Integer groupNumber,
+            Integer userId);
+
 }

+ 17 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/MarkService.java

@@ -1,12 +1,21 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
-import cn.com.qmth.stmms.biz.exam.model.*;
-import cn.com.qmth.stmms.biz.mark.model.*;
+import java.util.List;
+
+import cn.com.qmth.stmms.biz.exam.model.ExamQuestion;
+import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
+import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
+import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
+import cn.com.qmth.stmms.biz.exam.model.Marker;
+import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
+import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
+import cn.com.qmth.stmms.biz.mark.model.MarkResult;
+import cn.com.qmth.stmms.biz.mark.model.MarkStepDTO;
+import cn.com.qmth.stmms.biz.mark.model.SubmitResult;
+import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.common.enums.ScorePolicy;
 import cn.com.qmth.stmms.common.enums.ThirdPolicy;
 
-import java.util.List;
-
 public interface MarkService {
 
     /**
@@ -44,7 +53,8 @@ public interface MarkService {
      * @param group
      * @param third
      */
-    void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third);
+    void updateGroup(MarkGroup group, List<ExamQuestion> questionList, ScorePolicy policy, ThirdPolicy third,
+            boolean selective);
 
     /**
      * 评卷员申请领取某个正式评卷任务
@@ -118,12 +128,12 @@ public interface MarkService {
     void processArbitrate(ArbitrateHistory history);
 
     /**
-     * 管理员/组长打回某个评卷任务
+     * 管理员/组长重置(打回某个评卷任务
      *
      * @param library
      * @return
      */
-    boolean backLibrary(MarkLibrary library, Integer userId);
+    boolean rejectLibrary(MarkLibrary library, Integer userId, boolean isRest);
 
     /**
      * 更新某个大题已评任务数量

+ 1 - 2
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TaskService.java

@@ -7,7 +7,6 @@ import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
 import cn.com.qmth.stmms.biz.mark.model.ArbitrateHistory;
 import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
 import cn.com.qmth.stmms.biz.mark.model.Task;
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
 
@@ -17,7 +16,7 @@ public interface TaskService {
 
     Task build(ArbitrateHistory history, MarkGroup group);
 
-    Task build(TrialLibrary library, TrialHistory history);
+    Task build(TrialLibrary library);
 
     Task build(MarkLibrary library);
 

+ 13 - 15
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/TrialService.java

@@ -1,17 +1,17 @@
 package cn.com.qmth.stmms.biz.mark.service;
 
-import cn.com.qmth.stmms.biz.mark.model.TrialHistory;
+import java.util.List;
+
+import org.springframework.data.domain.Sort;
+
 import cn.com.qmth.stmms.biz.mark.model.TrialLibrary;
 import cn.com.qmth.stmms.biz.mark.model.TrialTag;
 import cn.com.qmth.stmms.biz.mark.model.TrialTrack;
 import cn.com.qmth.stmms.biz.mark.query.TrialLibrarySearchQuery;
-import org.springframework.data.domain.Sort;
-
-import java.util.List;
 
 public interface TrialService {
 
-    TrialLibrary findLibrary(Integer id);
+    TrialLibrary findById(Integer id);
 
     TrialLibrarySearchQuery findLibrary(TrialLibrarySearchQuery query);
 
@@ -20,22 +20,20 @@ public interface TrialService {
 
     long countLibrary(Integer examId, String subjectCode, Integer groupNumber);
 
-    List<TrialHistory> findHistory(Integer libraryId);
-
-    TrialHistory findHistory(Integer libraryId, Integer markerId);
+    long countByMarkerId(Integer markerId);
 
-    long countHistory(Integer libraryId);
+    List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+            int pageNumber, int pageSize, Sort sort, Double markerScore);
 
-    long countMarkerHistory(Integer markerId);
+    List<TrialTrack> findTrack(Integer libraryId);
 
-    List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
-            int pageNumber, int pageSize, Sort sort, Double markerScore);
+    List<TrialTag> findTag(Integer libraryId);
 
-    List<TrialTrack> findTrack(Integer libraryId, Integer markerId);
+    List<TrialTrack> findTrackByStudentId(Integer studentId);
 
-    List<TrialTag> findTag(Integer libraryId, Integer markerId);
+    List<TrialTag> findTagByStudentId(Integer studentId);
 
-    List<TrialHistory> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
+    List<TrialLibrary> findHistory(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
             String secretNumber, int pageNumber, int pageSize, Sort querySort);
 
 }

+ 33 - 3
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/model/ReportSubject.java

@@ -95,24 +95,38 @@ public class ReportSubject implements Serializable {
     @Column(name = "pass_rate")
     private Double passRate;
 
+    /**
+     * 优秀率
+     */
+    @ExcelField(title = "优秀率(%)", align = 2, sort = 90)
+    @Column(name = "excellent_rate")
+    private Double excellentRate;
+
+    /**
+     * 优秀人数
+     */
+    @ExcelField(title = "优秀人数", align = 2, sort = 100)
+    @Column(name = "excellent_count")
+    private Integer excellentCount;
+
     /**
      * 缺考人数
      */
-    @ExcelField(title = "缺考人数", align = 2, sort = 90)
+    @ExcelField(title = "缺考人数", align = 2, sort = 110)
     @Column(name = "absent_count")
     private Integer absentCount;
 
     /**
      * 违纪人数
      */
-    @ExcelField(title = "违纪人数", align = 2, sort = 100)
+    @ExcelField(title = "违纪人数", align = 2, sort = 120)
     @Column(name = "breach_count")
     private Integer breachCount;
 
     /**
      * 有效人数
      */
-    @ExcelField(title = "有效人数", align = 2, sort = 110)
+    @ExcelField(title = "有效人数", align = 2, sort = 130)
     @Column(name = "reality_count")
     private Integer realityCount;
 
@@ -402,6 +416,22 @@ public class ReportSubject implements Serializable {
         this.questionCount = questionCount;
     }
 
+    public Double getExcellentRate() {
+        return excellentRate;
+    }
+
+    public void setExcellentRate(Double excellentRate) {
+        this.excellentRate = excellentRate;
+    }
+
+    public Integer getExcellentCount() {
+        return excellentCount;
+    }
+
+    public void setExcellentCount(Integer excellentCount) {
+        this.excellentCount = excellentCount;
+    }
+
     // public void addOptions(String option) {
     // options = StringUtils.trimToNull(options);
     // StringBuilder sb = new StringBuilder(options);

+ 26 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/service/impl/ReportSubjectQuestionServiceImpl.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.report.service.impl;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -32,8 +33,8 @@ import cn.com.qmth.stmms.biz.report.service.ReportSubjectQuestionService;
  * @Date 2019-04-17
  */
 @Service
-public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSubjectQuestion>
-        implements ReportSubjectQuestionService {
+public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSubjectQuestion> implements
+        ReportSubjectQuestionService {
 
     @Autowired
     private ReportSubjectQuestionDao reportSubjectQuestionDao;
@@ -58,8 +59,8 @@ public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSub
     @Override
     public List<ReportSubjectQuestion> findByQuery(final ReportSubjectQuery query) {
         query.setSort(new Sort(Direction.ASC, "paperType", "mainNumber", "subNumber"));
-        Page<ReportSubjectQuestion> result = reportSubjectQuestionDao
-                .findAll(new Specification<ReportSubjectQuestion>() {
+        Page<ReportSubjectQuestion> result = reportSubjectQuestionDao.findAll(
+                new Specification<ReportSubjectQuestion>() {
 
                     @Override
                     public Predicate toPredicate(Root<ReportSubjectQuestion> root, CriteriaQuery<?> cQuery,
@@ -91,7 +92,9 @@ public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSub
                                 .toArray(new Predicate[predicates.size()]));
                     }
                 }, query);
-        List<ReportSubjectQuestion> list = result.getContent();
+        List<ReportSubjectQuestion> list = new ArrayList<ReportSubjectQuestion>();
+        list.addAll(result.getContent());
+        questionSort(list);
         return list;
     }
 
@@ -114,13 +117,30 @@ public class ReportSubjectQuestionServiceImpl extends BaseQueryService<ReportSub
             String subjectCode, boolean objective, String paperType) {
         List<ReportSubjectQuestion> list = reportSubjectQuestionDao.findByExamIdAndSubjectCodeAndObjectiveAndPaperType(
                 examId, subjectCode, objective, paperType, new Sort(Direction.ASC, "mainNumber", "subNumber"));
+        questionSort(list);
+        return list;
+    }
+
+    private List<ReportSubjectQuestion> questionSort(List<ReportSubjectQuestion> list) {
         Collections.sort(list, new Comparator<ReportSubjectQuestion>() {
 
             @Override
             public int compare(ReportSubjectQuestion o1, ReportSubjectQuestion o2) {
                 int i = o1.getMainNumber() - o2.getMainNumber();
                 if (i == 0) {
-                    return Integer.parseUnsignedInt(o1.getSubNumber()) - Integer.parseUnsignedInt(o2.getSubNumber());
+                    if (o1.getSubNumber().contains("-")) {
+                        String[] o1s = o1.getSubNumber().split("-");
+                        String[] o2s = o2.getSubNumber().split("-");
+                        int j = Integer.parseUnsignedInt(o1s[0]) - Integer.parseUnsignedInt(o2s[0]);
+                        if (j == 0) {
+                            return Integer.parseUnsignedInt(o1s[1]) - Integer.parseUnsignedInt(o2s[1]);
+                        } else {
+                            return j;
+                        }
+                    } else {
+                        return Integer.parseUnsignedInt(o1.getSubNumber())
+                                - Integer.parseUnsignedInt(o2.getSubNumber());
+                    }
                 }
                 return i;
             }

+ 7 - 6
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/QuestionGroup.java

@@ -1,5 +1,7 @@
 package cn.com.qmth.stmms.biz.report.utils;
 
+import cn.com.qmth.stmms.common.utils.BigDecimalUtils;
+
 public class QuestionGroup {
 
     private boolean objective;
@@ -9,21 +11,21 @@ public class QuestionGroup {
     private double totalScore;
 
     private double fullScore;
-    
+
     private String paperType;
 
-    public QuestionGroup(boolean objective, int mainNumber,String paperType) {
+    public QuestionGroup(boolean objective, int mainNumber, String paperType) {
         this.objective = objective;
         this.mainNumber = mainNumber;
         this.paperType = paperType;
     }
 
     public void incrTotalScore(double score) {
-        totalScore += score;
+        totalScore = BigDecimalUtils.add(totalScore, score);
     }
 
     public void incrFullScore(double score) {
-        fullScore += score;
+        fullScore = BigDecimalUtils.add(fullScore, score);
     }
 
     public int getMainNumber() {
@@ -50,11 +52,10 @@ public class QuestionGroup {
         return objective;
     }
 
-    
     public String getPaperType() {
         return paperType;
     }
-    
+
     public void setPaperType(String paperType) {
         this.paperType = paperType;
     }

+ 7 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectClassRangeModule.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.report.utils.module;
 
+import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -51,12 +52,14 @@ public class SubjectClassRangeModule implements Module {
                 JSONObject rangeLevel = new JSONObject();
                 double highCount = Math.ceil(context.getHighValueConfig() * r.getRealityCount() * 0.01);
                 double lowCount = Math.ceil(context.getLowValueConfig() * r.getRealityCount() * 0.01);
-                List<Double> highScore = studentDao.findHighCountTotalSocreByExamIdAndSubjectCodeAndClass(
+                List<BigDecimal> highScore = studentDao.findHighCountTotalSocreByExamIdAndSubjectCodeAndClass(
                         context.getExamId(), subjectCode, className, (int) highCount);
-                List<Double> lowScore = studentDao.findLowCountTotalSocreByExamIdAndSubjectCodeAndClass(
+                List<BigDecimal> lowScore = studentDao.findLowCountTotalSocreByExamIdAndSubjectCodeAndClass(
                         context.getExamId(), subjectCode, className, (int) lowCount);
-                rangeLevel.accumulate("highScore", highScore.isEmpty() ? 0 : highScore.get(highScore.size() - 1));
-                rangeLevel.accumulate("lowScore", lowScore.isEmpty() ? 0 : lowScore.get(lowScore.size() - 1));
+                rangeLevel.accumulate("highScore", highScore.isEmpty() ? 0 : highScore.get(highScore.size() - 1)
+                        .doubleValue());
+                rangeLevel.accumulate("lowScore", lowScore.isEmpty() ? 0 : lowScore.get(lowScore.size() - 1)
+                        .doubleValue());
                 r.setRangeLevel(rangeLevel.toString());
 
                 JSONObject scoreRange = new JSONObject();

+ 4 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectGroupModule.java

@@ -26,6 +26,8 @@ public class SubjectGroupModule implements Module {
 
     protected ReportContext context;
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     public SubjectGroupModule(ReportContext context) {
         this.calculators = new HashMap<String, BaseCalculatorUnit>();
         this.context = context;
@@ -60,7 +62,8 @@ public class SubjectGroupModule implements Module {
                 group = new QuestionGroup(objective, question.getMainNumber(), question.getPaperType());
                 map.put(groupKey, group);
             }
-            group.incrTotalScore(item != null ? item.getScore() : 0);
+            double score = item != null && item.getScore() != UN_SELECTIVE_SCORE ? item.getScore() : 0;
+            group.incrTotalScore(score);
             group.incrFullScore(question.getTotalScore());
         }
         for (Entry<String, QuestionGroup> entry : map.entrySet()) {

+ 2 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectModule.java

@@ -65,6 +65,8 @@ public class SubjectModule implements Module {
                 subject.setAvgScore(unit.avgScore);
                 subject.setPassCount(unit.passCount);
                 subject.setPassRate(unit.passRate);
+                subject.setExcellentCount(unit.excellentCount);
+                subject.setExcellentRate(unit.excellentRate);
                 subject.setDifficulty(unit.difficulty);
                 subject.setDiscrimination(unit.discrimination);
                 subject.setCoefficient(unit.coefficient);

+ 3 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectQuestionModule.java

@@ -29,6 +29,8 @@ public class SubjectQuestionModule implements Module, QuestionCalculatorProvider
 
     protected ReportContext context;
 
+    public static final int UN_SELECTIVE_SCORE = -1;
+
     public SubjectQuestionModule(ReportContext context) {
         this.calculators = new HashMap<String, BaseCalculatorUnit>();
         this.context = context;
@@ -56,7 +58,7 @@ public class SubjectQuestionModule implements Module, QuestionCalculatorProvider
                 continue;
             }
             ScoreItem item = scoreCount > i ? scoreList.get(i) : null;
-            double score = item != null ? item.getScore() : 0;
+            double score = item != null && item.getScore() != UN_SELECTIVE_SCORE ? item.getScore() : 0;
             process(student, question, score, totalScore);
         }
     }

+ 6 - 4
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/report/utils/module/SubjectRangeModule.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.report.utils.module;
 
+import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -71,12 +72,13 @@ public class SubjectRangeModule implements Module {
             JSONObject rangeLevel = new JSONObject();
             double highCount = Math.ceil(context.getHighValueConfig() * subject.getRealityCount() * 0.01);
             double lowCount = Math.ceil(context.getLowValueConfig() * subject.getRealityCount() * 0.01);
-            List<Double> highScore = studentDao.findHighCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
+            List<BigDecimal> highScore = studentDao.findHighCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
                     subjectCode, (int) highCount);
-            List<Double> lowScore = studentDao.findLowCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
+            List<BigDecimal> lowScore = studentDao.findLowCountTotalSocreByExamIdAndSubjectCode(context.getExamId(),
                     subjectCode, (int) lowCount);
-            rangeLevel.accumulate("highScore", highScore.isEmpty() ? 0 : highScore.get(highScore.size() - 1));
-            rangeLevel.accumulate("lowScore", lowScore.isEmpty() ? 0 : lowScore.get(lowScore.size() - 1));
+            rangeLevel.accumulate("highScore", highScore.isEmpty() ? 0 : highScore.get(highScore.size() - 1)
+                    .doubleValue());
+            rangeLevel.accumulate("lowScore", lowScore.isEmpty() ? 0 : lowScore.get(lowScore.size() - 1).doubleValue());
             subject.setRangeLevel(rangeLevel.toString());
 
             JSONObject scoreRange = new JSONObject();

+ 5 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/dao/SchoolDao.java

@@ -1,11 +1,15 @@
 package cn.com.qmth.stmms.biz.school.dao;
 
+import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.PagingAndSortingRepository;
 
 import cn.com.qmth.stmms.biz.school.model.School;
 
-public interface SchoolDao extends PagingAndSortingRepository<School, Integer>, JpaSpecificationExecutor<School> {
+public interface SchoolDao extends PagingAndSortingRepository<School, Integer>, JpaSpecificationExecutor<School>,
+        JpaRepository<School, Integer> {
 
     School findFirstByAccessKey(String accessKey);
+
+    School findByCode(String code);
 }

+ 14 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/model/School.java

@@ -26,6 +26,11 @@ public class School implements Serializable {
      */
     private String name;
 
+    /**
+     * 代码
+     */
+    private String code;
+
     /**
      * 省份
      */
@@ -182,4 +187,13 @@ public class School implements Serializable {
     public void setUpdateTime(Date updateTime) {
         this.updateTime = updateTime;
     }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
 }

+ 8 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/SchoolService.java

@@ -1,8 +1,9 @@
 package cn.com.qmth.stmms.biz.school.service;
 
+import java.util.List;
+
 import cn.com.qmth.stmms.biz.school.model.School;
 import cn.com.qmth.stmms.biz.school.query.SchoolSearchQuery;
-import org.springframework.transaction.annotation.Transactional;
 
 public interface SchoolService {
 
@@ -20,4 +21,10 @@ public interface SchoolService {
 
     School resetAccessKeyAndSecret(School school);
 
+    void updateOrg();
+
+    void updateOrg(List<School> list);
+
+    List<School> parseJson(String json);
+
 }

+ 55 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/OrgCornService.java

@@ -0,0 +1,55 @@
+package cn.com.qmth.stmms.biz.school.service.impl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
+import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.school.service.SchoolService;
+import cn.com.qmth.stmms.common.enums.LockType;
+import cn.com.qmth.stmms.common.enums.SystemAuthType;
+
+/**
+ * 机构同步定时任务
+ *
+ */
+
+@Component
+public class OrgCornService {
+
+    protected static final Logger log = LoggerFactory.getLogger(OrgCornService.class);
+
+    @Autowired
+    SchoolService schoolService;
+
+    @Autowired
+    private LockService lockService;
+
+    @Autowired
+    private SystemAuthService authService;
+
+    @Autowired
+    private SystemCache authCache;
+
+    /**
+     * 自动同步
+     */
+    @Scheduled(cron = "${school.updateMinute}")
+    public void cronUpdateOrg() {
+        SystemAuth systemAuth = authService.findOne();
+        if (systemAuth != null && SystemAuthType.ONLINE.equals(systemAuth.getType()) && authCache.isAuth()) {
+            lockService.trylock(LockType.SCHOOL, "");
+            try {
+                schoolService.updateOrg();
+            } catch (Exception e) {
+                log.error("OrgCornTask error", e);
+            }
+            lockService.unlock(LockType.SCHOOL, "");
+        }
+    }
+}

+ 82 - 15
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/SchoolServiceImpl.java

@@ -1,24 +1,35 @@
 package cn.com.qmth.stmms.biz.school.service.impl;
 
-import cn.com.qmth.stmms.biz.common.BaseQueryService;
-import cn.com.qmth.stmms.biz.school.dao.SchoolDao;
-import cn.com.qmth.stmms.biz.school.model.School;
-import cn.com.qmth.stmms.biz.school.query.SchoolSearchQuery;
-import cn.com.qmth.stmms.biz.school.service.SchoolService;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
 import org.apache.commons.lang.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Page;
 import org.springframework.data.jpa.domain.Specification;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
+import cn.com.qmth.stmms.biz.common.BaseQueryService;
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
+import cn.com.qmth.stmms.biz.school.dao.SchoolDao;
+import cn.com.qmth.stmms.biz.school.model.School;
+import cn.com.qmth.stmms.biz.school.query.SchoolSearchQuery;
+import cn.com.qmth.stmms.biz.school.service.SchoolService;
+import cn.com.qmth.stmms.biz.utils.SolarHttpUtil;
+import cn.com.qmth.stmms.common.utils.AesUtils;
 
 @Service("schoolService")
 public class SchoolServiceImpl extends BaseQueryService<School> implements SchoolService {
@@ -26,6 +37,15 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
     @Autowired
     public SchoolDao schoolDao;
 
+    @Autowired
+    private SystemAuthService authService;
+
+    @Value("${qmth.solar.host}")
+    private String host;
+
+    @Value("${qmth.solar.org.uri}")
+    private String uri;
+
     @Override
     public School findById(Integer id) {
         return schoolDao.findOne(id);
@@ -52,9 +72,8 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
                 if (StringUtils.isNotBlank(query.getCity())) {
                     predicates.add(cb.equal(root.get("city"), query.getCity()));
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
 
         }, query);
@@ -91,4 +110,52 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
             }
         }
     }
+
+    @Transactional
+    @Override
+    public void updateOrg() {
+        SystemAuth systemAuth = authService.findOne();
+        String accessKey = AesUtils.decrypt(systemAuth.getAccessKey());
+        String accessSecret = AesUtils.decrypt(systemAuth.getAccessSecret());
+        SolarHttpUtil orgUtil = new SolarHttpUtil(accessKey, accessSecret, host, uri);
+        List<School> list = orgUtil.getOrgs();
+        this.updateOrg(list);
+    }
+
+    @Override
+    public void updateOrg(List<School> list) {
+        for (School s : list) {
+            School school = schoolDao.findByCode(s.getCode());
+            if (school == null) {
+                school = s;
+                school.setCreateTime(new Date());
+                school.setProvince("");
+                school.setCity("");
+            }
+            school.setName(s.getName());
+            school.setAccessKey(s.getAccessKey());
+            school.setAccessSecret(s.getAccessSecret());
+            school.setLogoUrl(s.getLogoUrl());
+            school.setUpdateTime(new Date());
+            schoolDao.saveAndFlush(school);
+        }
+    }
+
+    @Override
+    public List<School> parseJson(String json) {
+        List<School> schools = new ArrayList<School>();
+        JSONArray orgArray = JSONArray.fromObject(json);
+        for (int i = 0; i < orgArray.size(); i++) {
+            JSONObject org = orgArray.getJSONObject(i);
+            School school = new School();
+            school.setAccessKey(org.getString("accessKey"));
+            school.setAccessSecret(org.getString("accessSecret"));
+            school.setCode(org.getString("code"));
+            school.setName(org.getString("name"));
+            school.setLogoUrl(org.getString("logo"));
+            school.setEnable(true);
+            schools.add(school);
+        }
+        return schools;
+    }
 }

+ 37 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/thread/OrgSyncThread.java

@@ -0,0 +1,37 @@
+package cn.com.qmth.stmms.biz.school.thread;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
+import cn.com.qmth.stmms.biz.lock.LockService;
+import cn.com.qmth.stmms.biz.school.service.SchoolService;
+import cn.com.qmth.stmms.biz.utils.SpringContextHolder;
+import cn.com.qmth.stmms.common.enums.LockType;
+
+public class OrgSyncThread implements Runnable {
+
+    protected static Logger log = LoggerFactory.getLogger(OrgSyncThread.class);
+
+    private SchoolService schoolService;
+
+    private SystemCache authCache;
+
+    public OrgSyncThread(SchoolService schoolService, SystemCache authCache) {
+        this.schoolService = schoolService;
+        this.authCache = authCache;
+    }
+
+    @Override
+    public void run() {
+        LockService lockService = SpringContextHolder.getBean(LockService.class);
+        try {
+            schoolService.updateOrg();
+        } catch (Exception e) {
+            authCache.setAuth(false);
+            log.error("OrgSyncThread error", e);
+        }
+        lockService.unlock(LockType.SCHOOL, "");
+    }
+
+}

+ 3 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/UserService.java

@@ -8,7 +8,7 @@ public interface UserService {
 
     User login(String loginName, String password, String ip);
 
-    User externalLogin(Integer schoolId, String account, String name, Role role);
+    User externalLogin(Integer schoolId, String account, String name, String password, Role role);
 
     User findByLoginName(String loginName);
 
@@ -24,4 +24,6 @@ public interface UserService {
 
     User findByMarkerId(Integer markerId);
 
+    User externalSaveAndUpdate(Integer schoolId, String account, String name, String password, Role role);
+
 }

+ 17 - 7
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/user/service/impl/UserServiceImpl.java

@@ -7,6 +7,7 @@ import cn.com.qmth.stmms.biz.user.service.query.UserSearchQuery;
 import cn.com.qmth.stmms.common.enums.Role;
 import cn.com.qmth.stmms.common.enums.UserSource;
 import cn.com.qmth.stmms.common.utils.EncryptUtils;
+
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +20,7 @@ import javax.persistence.criteria.CriteriaBuilder;
 import javax.persistence.criteria.CriteriaQuery;
 import javax.persistence.criteria.Predicate;
 import javax.persistence.criteria.Root;
+
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -130,9 +132,8 @@ public class UserServiceImpl implements UserService {
                         predicates.add(cb.equal(root.get("role"), role));
                     }
                 }
-                return predicates.isEmpty() ?
-                        cb.conjunction() :
-                        cb.and(predicates.toArray(new Predicate[predicates.size()]));
+                return predicates.isEmpty() ? cb.conjunction() : cb.and(predicates.toArray(new Predicate[predicates
+                        .size()]));
             }
         }, query);
         if (result != null) {
@@ -163,7 +164,15 @@ public class UserServiceImpl implements UserService {
 
     @Override
     @Transactional
-    public User externalLogin(Integer schoolId, String account, String name, Role role) {
+    public User externalLogin(Integer schoolId, String account, String name, String password, Role role) {
+        User user = externalSaveAndUpdate(schoolId, account, name, password, role);
+        user.setLastLoginTime(new Date());
+        user.refreshAccessToken();
+        return userDao.save(user);
+    }
+
+    @Override
+    public User externalSaveAndUpdate(Integer schoolId, String account, String name, String password, Role role) {
         User user = userDao.findFirstBySchoolIdAndRelatedAccount(schoolId, account);
         if (user == null) {
             user = new User();
@@ -178,11 +187,12 @@ public class UserServiceImpl implements UserService {
             user.setCreatedTime(new Date());
             user.setUpdatedTime(new Date());
         }
-        if (name != null) {
+        if (StringUtils.isNotBlank(name)) {
             user.setName(name);
         }
-        user.setLastLoginTime(new Date());
-        user.refreshAccessToken();
+        if (StringUtils.isNotBlank(password)) {
+            user.setPassword(EncryptUtils.md5(password));
+        }
         return userDao.save(user);
     }
 

+ 76 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/AppLicenseUtil.java

@@ -0,0 +1,76 @@
+package cn.com.qmth.stmms.biz.utils;
+
+import java.util.Arrays;
+
+import net.sf.json.JSONObject;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.qmth.boot.tools.codec.CodecUtils;
+import com.qmth.boot.tools.crypto.AES;
+import com.qmth.boot.tools.crypto.RSA;
+import com.qmth.boot.tools.device.DeviceInfo;
+import com.qmth.boot.tools.models.ByteArray;
+
+/**
+ * 应用许可证解析工具
+ */
+public class AppLicenseUtil {
+
+    private static final Logger log = LoggerFactory.getLogger(AppLicenseUtil.class);
+
+    private static final String PUBLIC_KEY_PATH = "license/public.key";
+
+    /**
+     * 构造当前设备加密信息文件
+     *
+     * @return
+     */
+    public static ByteArray buildDeviceInfo() throws Exception {
+        return RSA.getPublicKey(
+                ByteArray.fromInputStream(AppLicenseUtil.class.getClassLoader().getResourceAsStream(PUBLIC_KEY_PATH))
+                        .value()).encrypt(new ObjectMapper().writeValueAsBytes(DeviceInfo.current()));
+    }
+
+    /**
+     * 直接解析许可证文件内容
+     *
+     * @param data
+     * @return
+     */
+    public static JSONObject parseLicense(byte[] data) {
+        try {
+            byte[] original = ArrayUtils.subarray(data, 1, data.length);
+            // 是否绑定硬件
+            if (data[0] == 0) {
+                // 不绑定硬件
+            } else if (data[0] == 1) {
+                // 获取当前设备标识
+                String deviceId = DeviceInfo.current().uuid();
+                // 使用设备标识进行AES解密
+                original = AES.decrypt(original, deviceId.substring(0, 16), deviceId.substring(16)).value();
+            } else {
+                return null;
+            }
+            // 截取前16位摘要信息
+            byte[] digest = ArrayUtils.subarray(original, 0, 16);
+            // 进行RSA解密
+            byte[] content = RSA
+                    .getPublicKey(
+                            ByteArray.fromInputStream(
+                                    AppLicenseUtil.class.getClassLoader().getResourceAsStream(PUBLIC_KEY_PATH)).value())
+                    .decrypt(ArrayUtils.subarray(original, 16, original.length)).value();
+            // 比对摘要是否一致
+            if (Arrays.equals(digest, CodecUtils.md5(content))) {
+                return new ObjectMapper().readValue(content, JSONObject.class);
+            }
+        } catch (Exception e) {
+            log.error("license parse error", e);
+        }
+        return null;
+    }
+
+}

+ 13 - 12
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/ScoreInfo.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.utils;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -11,20 +12,20 @@ public class ScoreInfo {
 
     private String mainTitle;
 
-    private double objectiveScore;
+    private BigDecimal objectiveScore;
 
-    private double subjectiveScore;
+    private BigDecimal subjectiveScore;
 
-    private double totalScore;
+    private BigDecimal totalScore;
 
     private List<ScoreItem> scoreList;
 
     public ScoreInfo() {
         this.mainNumber = 0;
         this.subNumber = "";
-        this.objectiveScore = 0d;
-        this.subjectiveScore = 0d;
-        this.totalScore = 0d;
+        this.objectiveScore = BigDecimal.ZERO;
+        this.subjectiveScore = BigDecimal.ZERO;
+        this.totalScore = BigDecimal.ZERO;
         this.scoreList = new ArrayList<ScoreItem>();
     }
 
@@ -45,24 +46,24 @@ public class ScoreInfo {
         item.setScore(score);
 
         scoreList.add(item);
-        totalScore += item.getScore();
+        totalScore = totalScore.add(BigDecimal.valueOf(item.getScore()));
         if (item.isObjective()) {
-            objectiveScore += item.getScore();
+            objectiveScore = objectiveScore.add(BigDecimal.valueOf(item.getScore()));
         } else {
-            subjectiveScore += item.getScore();
+            subjectiveScore = subjectiveScore.add(BigDecimal.valueOf(item.getScore()));
         }
     }
 
     public double getObjectiveScore() {
-        return objectiveScore;
+        return objectiveScore.doubleValue();
     }
 
     public double getSubjectiveScore() {
-        return subjectiveScore;
+        return subjectiveScore.doubleValue();
     }
 
     public double getTotalScore() {
-        return totalScore;
+        return totalScore.doubleValue();
     }
 
     public List<ScoreItem> getScoreList() {

+ 283 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/SolarHttpUtil.java

@@ -0,0 +1,283 @@
+package cn.com.qmth.stmms.biz.utils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import cn.com.qmth.stmms.biz.school.model.School;
+import cn.com.qmth.stmms.common.signature.SignatureInfo;
+import cn.com.qmth.stmms.common.signature.SignatureType;
+
+public class SolarHttpUtil {
+
+    private static Logger log = LoggerFactory.getLogger(SolarHttpUtil.class);
+
+    /** 默认的编码格式 */
+    public static final String DEFAULT_CHARSET = "UTF-8";
+
+    public static final String CONTENT_TYPE = "Content-Type";
+
+    public static final String APPLICATION_JSON = "application/x-www-form-urlencoded;charset=utf-8";
+
+    public static final String METHOD_POST = "POST";
+
+    public static final String AUTH = "Authorization";
+
+    protected String host = null;
+
+    protected String uri = null;
+
+    protected String accessKey = null;
+
+    protected String accessSecret = null;
+
+    public SolarHttpUtil(String accessKey, String accessSecret, String host, String uri) {
+        this.accessKey = accessKey;
+        this.accessSecret = accessSecret;
+        this.uri = uri;
+        this.host = host;
+    }
+
+    /**
+     * 
+     * @param params
+     *            headers参数
+     * @param datas
+     *            requestParams参数
+     * @return
+     */
+    public String httpAction(Map<String, String> params, Map<String, Object> datas) {
+        String result = null;
+        HttpsURLConnection conn = null;
+        OutputStream os = null;
+        InputStream is = null;
+
+        try {
+
+            // 获取链接
+            URL url = new URL(host + uri);
+            conn = (HttpsURLConnection) url.openConnection();
+
+            conn.setRequestMethod(METHOD_POST);
+            conn.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON);
+            // 设置鉴权
+            long time = System.currentTimeMillis();
+            String signature = SignatureInfo.build(SignatureType.SECRET, METHOD_POST, uri, time, accessKey,
+                    accessSecret);
+            conn.setRequestProperty(AUTH, signature);
+            conn.setRequestProperty("time", String.valueOf(time));
+            // ssl
+            SSLContext context = SSLContext.getInstance("SSL", "SunJSSE");
+            TrustManager[] tm = new TrustManager[] { new X509TrustManager() {
+
+                @Override
+                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+                }
+
+                @Override
+                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+                }
+
+                @Override
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+            } };
+            // 初始化
+            context.init(null, tm, new java.security.SecureRandom());
+            // 获取SSLSocketFactory对象
+            SSLSocketFactory ssf = context.getSocketFactory();
+            conn.setSSLSocketFactory(ssf);
+
+            conn.setUseCaches(false);
+            conn.setDoOutput(true);
+
+            // 设置额外的参数
+            if (params != null && !params.isEmpty()) {
+
+                for (Map.Entry<String, String> param : params.entrySet()) {
+                    conn.setRequestProperty(param.getKey(), param.getValue());
+                }
+            }
+            // 创建链接
+            conn.connect();
+            // 设置请求参数
+            if (datas != null) {
+                StringBuilder sb = new StringBuilder();
+                for (Map.Entry<String, Object> data : datas.entrySet()) {
+                    sb.append(data.getKey()).append("=").append(data.getValue()).append("&");
+                }
+                os = conn.getOutputStream();
+                os.write(sb.toString().getBytes());
+                os.flush();
+            }
+
+            result = getResult(conn);
+        } catch (Exception e) {
+            // 操作失败
+            log.error("OrgUtil connection error!", e);
+            e.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (os != null) {
+                    os.close();
+                    os = null;
+                }
+                if (is != null) {
+                    is.close();
+                    is = null;
+                }
+            } catch (IOException e) {
+                log.error("OrgUtil connection error!", e);
+            }
+
+            if (conn != null) {
+                conn.disconnect();
+                conn = null;
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 获得连接请求的返回数据
+     * 
+     * @param conn
+     * 
+     * @return 字符串
+     */
+    private String getResult(HttpURLConnection conn) throws IOException {
+
+        StringBuilder text = new StringBuilder();
+
+        InputStream is = null;
+        InputStreamReader sr = null;
+        BufferedReader br = null;
+
+        int code = conn.getResponseCode();
+
+        try {
+            is = code >= 400 ? conn.getErrorStream() : conn.getInputStream();
+
+            sr = new InputStreamReader(is, DEFAULT_CHARSET);
+            br = new BufferedReader(sr);
+
+            char[] chars = new char[4096];
+            int length = 0;
+
+            while ((length = br.read(chars)) != -1) {
+                text.append(chars, 0, length);
+            }
+        } finally {
+            if (br != null) {
+                br.close();
+                br = null;
+            }
+            if (sr != null) {
+                sr.close();
+                sr = null;
+            }
+            if (is != null) {
+                is.close();
+                is = null;
+            }
+        }
+        if (code >= 400) {
+            throw new IOException(text.toString());
+        }
+        return text.toString();
+    }
+
+    public boolean getAPP() {
+        try {
+            String str = this.httpAction(null, null);
+            JSONObject json = JSONObject.fromObject(str);
+            @SuppressWarnings("unused")
+            Integer id = json.getInt("id");
+            return true;
+        } catch (Exception e) {
+            log.error("OrgUtil connection error!", e);
+            return false;
+        }
+    }
+
+    public List<School> getOrgs() {
+        List<School> schools = new ArrayList<School>();
+        int pageNumber = 1;
+        int pageSize = 100;
+        while (pageNumber != 0) {
+            Map<String, Object> datas = new HashMap<String, Object>();
+            datas.put("pageNumber", pageNumber);
+            datas.put("pageSize", pageSize);
+            String str = this.httpAction(null, datas);
+            JSONArray orgArray = JSONArray.fromObject(str);
+            if (orgArray.size() == pageSize) {
+                pageNumber++;
+            } else {
+                pageNumber = 0;
+            }
+            for (int i = 0; i < orgArray.size(); i++) {
+                JSONObject org = orgArray.getJSONObject(i);
+                School school = new School();
+                school.setAccessKey(org.getString("accessKey"));
+                school.setAccessSecret(org.getString("accessSecret"));
+                school.setCode(org.getString("code"));
+                school.setName(org.getString("name"));
+                school.setLogoUrl(org.getString("logo"));
+                school.setEnable(true);
+                schools.add(school);
+            }
+        }
+
+        return schools;
+    }
+
+    public static void main(String[] args) {
+        SolarHttpUtil orgUtil = new SolarHttpUtil("7bbdc11570bc474dbf50e0d4a5dff328",
+                "IOodRvbp2LspJTHOScgB7Yx8MRloMpyl", "https://solar.qmth.com.cn", "/api/open/org/query");
+
+        String str = orgUtil.httpAction(null, null);
+        System.out.println(str);
+        // int pageNumber = 1;
+        // int pageSize = 1;
+        //
+        // while (pageNumber != 0) {
+        // Map<String, Object> datas = new HashMap<String, Object>();
+        // datas.put("pageNumber", pageNumber);
+        // datas.put("pageSize", pageSize);
+        // String str = orgUtil.httpAction(null, datas);
+        // JSONArray orgArray = JSONArray.fromObject(str);
+        // if (orgArray.size() == pageSize) {
+        // pageNumber++;
+        // } else {
+        // pageNumber = 0;
+        // }
+        // System.out.println(str);
+        // }
+
+    }
+}

+ 31 - 0
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/ConfigType.java

@@ -0,0 +1,31 @@
+package cn.com.qmth.stmms.common.enums;
+
+public enum ConfigType {
+    FILE_SERVER("图片服务", 1), MARK_TIME("评卷时长", 2);
+
+    private String name;
+
+    private int value;
+
+    private ConfigType(String name, int value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public static ConfigType findByValue(int value) {
+        for (ConfigType c : ConfigType.values()) {
+            if (c.getValue() == value) {
+                return c;
+            }
+        }
+        return null;
+    }
+}

+ 2 - 2
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/HistoryStatus.java

@@ -10,7 +10,7 @@ public enum HistoryStatus {
     private String name;
 
     private int value;
-    
+
     private static List<HistoryStatus> options;
 
     private HistoryStatus(String name, int value) {
@@ -34,7 +34,7 @@ public enum HistoryStatus {
         }
         return null;
     }
-    
+
     public static List<HistoryStatus> getOptionList() {
         if (options == null) {
             options = new LinkedList<>();

+ 1 - 1
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LibraryStatus.java

@@ -4,7 +4,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 public enum LibraryStatus {
-    WAITING("未处理", 0), MARKED("已给分", 1), REJECTED("已打回", 2), WAIT_ARBITRATE("等待仲裁", 3), ARBITRATED("已仲裁", 4), PROBLEM(
+    WAITING("未处理", 0), MARKED("已", 1), REJECTED("已打回", 2), WAIT_ARBITRATE("等待仲裁", 3), ARBITRATED("已仲裁", 4), PROBLEM(
             "问题卷", 5), INSPECTED("已复核", 6);
 
     private String name;

+ 4 - 4
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/LockType.java

@@ -1,10 +1,10 @@
 package cn.com.qmth.stmms.common.enums;
 
 public enum LockType {
-    EXAM_SUBJECT("exam_subject"), GROUP("group"), GROUP_DELETE("group_delete"), STUDENT("student"), MARKER(
-            "marker"), MARKER_RESET("marker_reset"), USER("user"), FORMAL_LIBRARY("formal_library"), TRIAL_LIBRARY(
-            "trial_library"), ARBITRATE("arbitrate"), BATCH_QUALITY("batch_quality"), SCORE_CALCULATE(
-            "score_calculate"), GROUP_LIBRARY("group_library"), DATA_SYNC("data_sync");
+    EXAM_SUBJECT("exam_subject"), GROUP("group"), GROUP_DELETE("group_delete"), STUDENT("student"), MARKER("marker"), MARKER_RESET(
+            "marker_reset"), USER("user"), FORMAL_LIBRARY("formal_library"), TRIAL_LIBRARY("trial_library"), ARBITRATE(
+            "arbitrate"), BATCH_QUALITY("batch_quality"), SCORE_CALCULATE("score_calculate"), GROUP_LIBRARY(
+            "group_library"), DATA_SYNC("data_sync"), SCHOOL("school");
 
     private String name;
 

+ 47 - 0
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SelectiveStatus.java

@@ -0,0 +1,47 @@
+package cn.com.qmth.stmms.common.enums;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public enum SelectiveStatus {
+    UN_SELECTIVE("未选做", 0), MUTI_SELECTIVE("多选做", 1);
+
+    private String name;
+
+    private int value;
+
+    private static List<SelectiveStatus> options;
+
+    private SelectiveStatus(String name, int value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public static SelectiveStatus findByValue(Integer value) {
+        for (SelectiveStatus c : SelectiveStatus.values()) {
+            if (c.getValue() == value) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    public static List<SelectiveStatus> getOptionList() {
+        if (options == null) {
+            options = new LinkedList<>();
+            for (SelectiveStatus status : SelectiveStatus.values()) {
+                options.add(status);
+            }
+        }
+        return options;
+    }
+
+}

+ 2 - 2
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SubjectiveStatus.java

@@ -5,7 +5,7 @@ import java.util.List;
 
 public enum SubjectiveStatus {
 
-    UNMARK("未评完"), MARKED("已评完"), INSPECTED("已复核");
+    UNMARK("未评完"), TRIAL("试评"), MARKED("已评完"), INSPECTED("已复核");
 
     private String name;
 
@@ -32,7 +32,7 @@ public enum SubjectiveStatus {
         if (options == null) {
             options = new LinkedList<>();
             for (SubjectiveStatus status : SubjectiveStatus.values()) {
-                if (status != UNMARK) {
+                if (status != UNMARK && status != TRIAL) {
                     options.add(status);
                 }
             }

+ 31 - 0
stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SystemAuthType.java

@@ -0,0 +1,31 @@
+package cn.com.qmth.stmms.common.enums;
+
+public enum SystemAuthType {
+    ONLINE("在线激活", 1), OFFLINE("离线激活", 2);
+
+    private String name;
+
+    private int value;
+
+    private SystemAuthType(String name, int value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public static SystemAuthType findByValue(int value) {
+        for (SystemAuthType c : SystemAuthType.values()) {
+            if (c.getValue() == value) {
+                return c;
+            }
+        }
+        return null;
+    }
+}

+ 36 - 31
stmms-common/src/main/java/cn/com/qmth/stmms/common/utils/BigDecimalUtils.java

@@ -12,17 +12,13 @@ public class BigDecimalUtils {
     }
 
     /**
+     * 提供精确加法计算的add方法
      * 
-     * 鎻愪緵绮剧‘鐨勫姞娉曡繍绠椼�
-     * 
-     * @param v1
-     *            琚姞鏁�
-     * 
-     * @param v2
-     *            鍔犳暟
-     * 
-     * @return 涓や釜鍙傛暟鐨勫拰
-     * 
+     * @param value1
+     *            被加数
+     * @param value2
+     *            加数
+     * @return 两个参数的和
      */
 
     public static double add(double v1, double v2) {
@@ -36,13 +32,13 @@ public class BigDecimalUtils {
     }
 
     /**
-     * 鎻愪緵绮剧‘鐨勫噺娉曡繍绠椼�
+     * 提供精确减法运算的sub方法
      * 
-     * @param v1
-     *            琚噺鏁�
-     * @param v2
-     *            鍑忔暟
-     * @return 涓や釜鍙傛暟鐨勫樊
+     * @param value1
+     *            被减数
+     * @param value2
+     *            减数
+     * @return 两个参数的差
      */
     public static double sub(double v1, double v2) {
 
@@ -55,13 +51,13 @@ public class BigDecimalUtils {
     }
 
     /**
-     * 鎻愪緵绮剧‘鐨勪箻娉曡繍绠椼�
+     * 提供精确乘法运算的mul方法
      * 
-     * @param v1
-     *            琚箻鏁�
-     * @param v2
-     *            涔樻暟
-     * @return 涓や釜鍙傛暟鐨勭Н
+     * @param value1
+     *            被乘数
+     * @param value2
+     *            乘数
+     * @return 两个参数的积
      */
     public static double mul(double v1, double v2) {
 
@@ -93,13 +89,16 @@ public class BigDecimalUtils {
     }
 
     /**
-     * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠楋紝褰撳彂鐢熼櫎涓嶅敖鐨勬儏鍐垫椂锛岀簿纭埌 灏忔暟鐐逛互鍚�0浣嶏紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ�
+     * 提供精确的除法运算方法div
      * 
-     * @param v1
-     *            琚櫎鏁�
-     * @param v2
-     *            闄ゆ暟
-     * @return 涓や釜鍙傛暟鐨勫晢
+     * @param value1
+     *            被除数
+     * @param value2
+     *            除数
+     * @param scale
+     *            精确范围
+     * @return 两个参数的商
+     * @throws IllegalAccessException
      */
     public static double div(double v1, double v2) {
 
@@ -108,10 +107,16 @@ public class BigDecimalUtils {
     }
 
     /**
+     * 提供精确的除法运算方法div
      * 
-     * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠椼�褰撳彂鐢熼櫎涓嶅敖鐨勬儏鍐垫椂锛岀敱scale鍙傛暟鎸�
-     * 
-     * 瀹氱簿搴︼紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ�
+     * @param value1
+     *            被除数
+     * @param value2
+     *            除数
+     * @param scale
+     *            精确范围
+     * @return 两个参数的商
+     * @throws IllegalAccessException
      */
 
     public static double div(double v1, double v2, int scale) {

+ 151 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/config/SystemAuthController.java

@@ -0,0 +1,151 @@
+package cn.com.qmth.stmms.admin.config;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.sf.json.JSONObject;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import cn.com.qmth.stmms.biz.config.model.SystemAuth;
+import cn.com.qmth.stmms.biz.config.service.SystemAuthService;
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
+import cn.com.qmth.stmms.biz.school.model.School;
+import cn.com.qmth.stmms.biz.school.service.SchoolService;
+import cn.com.qmth.stmms.biz.utils.AppLicenseUtil;
+import cn.com.qmth.stmms.biz.utils.SolarHttpUtil;
+import cn.com.qmth.stmms.common.annotation.Logging;
+import cn.com.qmth.stmms.common.annotation.RoleRequire;
+import cn.com.qmth.stmms.common.controller.BaseController;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.Role;
+import cn.com.qmth.stmms.common.enums.SystemAuthType;
+import cn.com.qmth.stmms.common.utils.AesUtils;
+import cn.com.qmth.stmms.common.utils.Encodes;
+
+import com.qmth.boot.tools.models.ByteArray;
+
+@Controller
+@RequestMapping("/admin/sys/auth")
+public class SystemAuthController extends BaseController {
+
+    private static Logger log = LoggerFactory.getLogger(SystemAuthController.class);
+
+    @Autowired
+    private SystemAuthService authService;
+
+    @Autowired
+    private SchoolService schoolService;
+
+    @Autowired
+    private SystemCache authCache;
+
+    @Value("${qmth.solar.host}")
+    private String host;
+
+    @Value("${qmth.solar.app.uri}")
+    private String uri;
+
+    @Logging(menu = "查询授权信息", type = LogType.QUERY)
+    @RoleRequire(Role.SYS_ADMIN)
+    @RequestMapping
+    public ModelAndView list(HttpServletRequest request) {
+        ModelAndView view = new ModelAndView("modules/sys/authInfo");
+        SystemAuth systemAuth = authService.findOne();
+        view.addObject("systemAuth", systemAuth == null ? new SystemAuth() : systemAuth);
+        view.addObject("typeList", SystemAuthType.values());
+        view.addObject("auth", authCache.isAuth());
+        view.addObject("expireTime", authCache.getExpireTime() == null ? null : new Date(authCache.getExpireTime()));
+        return view;
+    }
+
+    @RoleRequire(Role.SYS_ADMIN)
+    @RequestMapping(value = "/edit", method = RequestMethod.GET)
+    public ModelAndView edit(HttpServletRequest request) {
+        ModelAndView view = new ModelAndView("modules/sys/authEdit");
+        SystemAuth systemAuth = authService.findOne();
+        view.addObject("systemAuth", systemAuth == null ? new SystemAuth() : systemAuth);
+        view.addObject("typeList", SystemAuthType.values());
+        view.addObject("auth", authCache.isAuth());
+        view.addObject("expireTime", authCache.getExpireTime() == null ? null : new Date(authCache.getExpireTime()));
+        return view;
+    }
+
+    @Logging(menu = "修改授权配置", type = LogType.UPDATE)
+    @RoleRequire(Role.SYS_ADMIN)
+    @RequestMapping(value = "/update", method = RequestMethod.POST)
+    public String update(HttpServletRequest request, SystemAuth systemAuth, MultipartFile file) {
+        if (SystemAuthType.ONLINE.equals(systemAuth.getType())) {
+            SolarHttpUtil httpUtil = new SolarHttpUtil(systemAuth.getAccessKey(), systemAuth.getAccessSecret(), host,
+                    uri);
+            systemAuth.setAccessKey(AesUtils.encrypt(systemAuth.getAccessKey()));
+            systemAuth.setAccessSecret(AesUtils.encrypt(systemAuth.getAccessSecret()));
+            authService.save(systemAuth);
+            if (httpUtil.getAPP()) {
+                authCache.setAuth(true);
+                authCache.setExpireTime(null);
+                schoolService.updateOrg();
+            } else {
+                authCache.setAuth(false);
+                authCache.setExpireTime(null);
+            }
+        } else {
+            try {
+                systemAuth.setDescription(ByteArray.fromInputStream(file.getInputStream()).toBase64());
+                JSONObject json = AppLicenseUtil.parseLicense(ByteArray.fromInputStream(file.getInputStream()).value());
+                if (json != null) {
+                    authCache.setAuth(true);
+                    if (json.has("control") && json.getJSONObject("control").has("expireTime")) {
+                        long expireTime = json.getJSONObject("control").getLong("expireTime");
+                        authCache.setExpireTime(expireTime);
+                        List<School> list = schoolService.parseJson(json.getString("orgs"));
+                        schoolService.updateOrg(list);
+                    }
+                } else {
+                    authCache.setAuth(false);
+                    authCache.setExpireTime(null);
+                }
+                authService.save(systemAuth);
+            } catch (IOException e) {
+                e.printStackTrace();
+                log.error("parseLicense error", e);
+            }
+        }
+        return "redirect:/admin/sys/auth";
+    }
+
+    @Logging(menu = "导出硬件信息", type = LogType.EXPORT)
+    @RoleRequire(Role.SYS_ADMIN)
+    @RequestMapping(value = "/exportInfo")
+    public String exportInfo(HttpServletResponse response, RedirectAttributes redirectAttributes) {
+        try {
+            download(response, AppLicenseUtil.buildDeviceInfo().value());
+            return null;
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("export device.info error", e);
+        }
+        return "redirect:/admin/sys/auth";
+    }
+
+    private void download(HttpServletResponse response, byte[] data) throws Exception {
+        response.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("device.info"));
+        IOUtils.copy(new ByteArrayInputStream(data), response.getOutputStream());
+    }
+
+}

+ 58 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/admin/config/SystemConfigController.java

@@ -0,0 +1,58 @@
+package cn.com.qmth.stmms.admin.config;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+
+import cn.com.qmth.stmms.biz.config.model.SystemConfig;
+import cn.com.qmth.stmms.biz.config.service.SystemConfigService;
+import cn.com.qmth.stmms.common.annotation.Logging;
+import cn.com.qmth.stmms.common.annotation.RoleRequire;
+import cn.com.qmth.stmms.common.controller.BaseController;
+import cn.com.qmth.stmms.common.enums.LogType;
+import cn.com.qmth.stmms.common.enums.Role;
+
+@Controller
+@RequestMapping("/admin/sys/config")
+public class SystemConfigController extends BaseController {
+
+    @Autowired
+    private SystemConfigService configService;
+
+    @Logging(menu = "查询", type = LogType.QUERY)
+    @RoleRequire(Role.SYS_ADMIN)
+    @RequestMapping
+    public ModelAndView list(HttpServletRequest request) {
+        ModelAndView view = new ModelAndView("modules/sys/configList");
+        List<SystemConfig> list = configService.findAll();
+        view.addObject("list", list);
+        return view;
+    }
+
+    @RequestMapping(value = "/edit", method = RequestMethod.GET)
+    public ModelAndView editInit(HttpServletRequest request, @RequestParam Integer id) {
+        SystemConfig config = configService.findById(id);
+        if (config != null) {
+            ModelAndView view = new ModelAndView("modules/sys/configEdit");
+            view.addObject("config", config);
+            return view;
+        } else {
+            return new ModelAndView("redirect:/admin/sys/config");
+        }
+    }
+
+    @Logging(menu = "修改配置", type = LogType.UPDATE)
+    @RequestMapping(value = "/update", method = RequestMethod.POST)
+    public String save(HttpServletRequest request, SystemConfig config) {
+        configService.update(config.getId(), config.getDescription());
+        return "redirect:/admin/sys/config";
+    }
+
+}

+ 53 - 21
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/ExamStudentDTO.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.admin.dto;
 
+import java.util.LinkedList;
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
@@ -32,32 +33,37 @@ public class ExamStudentDTO {
     private String name;
 
     @ExcelField(title = "客观总分", align = 2, sort = 90)
-    private double objectiveScore;
+    private String objectiveScore;
 
     @ExcelField(title = "主观总分", align = 2, sort = 100)
-    private double subjectiveScore;
+    private String subjectiveScore;
 
     @ExcelField(title = "总分", align = 2, sort = 110)
-    private double totalScore;
+    private String totalScore;
 
-    @ExcelField(title = "评分明细", align = 2, sort = 120)
+    @ExcelField(title = "违纪", align = 2, sort = 120)
+    private String breach;
+
+    @ExcelField(title = "评分明细", align = 2, sort = 130)
     private String subjectiveScoreList;
 
-    @ExcelField(title = "备注", align = 2, sort = 130)
+    @ExcelField(title = "备注", align = 2, sort = 140)
     private String remark;
 
-    @ExcelField(title = "班级", align = 2, sort = 140)
+    @ExcelField(title = "班级", align = 2, sort = 150)
     private String className;
 
-    @ExcelField(title = "学院", align = 2, sort = 150)
+    @ExcelField(title = "学院", align = 2, sort = 160)
     private String college;
 
-    @ExcelField(title = "任课老师", align = 2, sort = 160)
+    @ExcelField(title = "任课老师", align = 2, sort = 170)
     private String teacher;
 
     private List<ScoreItem> objectiveList;
 
-    private List<ScoreItem> subjectiveList;
+    private List<String> subjectiveList;
+
+    public static final String SPLIT = ";";
 
     public ExamStudentDTO(ExamStudent student) {
         setSubjectCode(student.getSubjectCode());
@@ -67,16 +73,34 @@ public class ExamStudentDTO {
         setExamNumber(student.getExamNumber());
         setStudentCode(student.getStudentCode());
         setName(student.getName());
-        setObjectiveScore(student.getObjectiveScore());
-        setSubjectiveScore(student.getSubjectiveScore());
         setSubjectiveScoreList(StringUtils.trimToEmpty(student.getSubjectiveScoreList()));
-        setTotalScore(student.getTotalScore());
+        if (!student.isUpload() || student.isAbsent()) {
+            setTotalScore("-");
+            setObjectiveScore("-");
+            setSubjectiveScore("-");
+        } else {
+            setObjectiveScore(String.valueOf(student.getObjectiveScore()));
+            setSubjectiveScore(String.valueOf(student.getSubjectiveScore()));
+            setTotalScore(String.valueOf(student.getTotalScore()));
+        }
+        if (student.isBreach()) {
+            setBreach("是");
+        } else {
+            setBreach("否");
+        }
         setRemark(StringUtils.trimToEmpty(student.getRemark()));
         setClassName(student.getClassName());
         setCollege(student.getCollege());
         setTeacher(student.getTeacher());
         setObjectiveList(student.getScoreList(true));
-        setSubjectiveList(student.getScoreList(false));
+        List<String> subjectiveList = new LinkedList<String>();
+        if (StringUtils.isNotBlank(student.getSubjectiveScoreList())) {
+            String[] values = StringUtils.split(student.getSubjectiveScoreList(), SPLIT);
+            for (String value : values) {
+                subjectiveList.add(value);
+            }
+        }
+        setSubjectiveList(subjectiveList);
     }
 
     public String getSubjectCode() {
@@ -119,27 +143,27 @@ public class ExamStudentDTO {
         this.examNumber = examNumber;
     }
 
-    public double getTotalScore() {
+    public String getTotalScore() {
         return totalScore;
     }
 
-    public void setTotalScore(double totalScore) {
+    public void setTotalScore(String totalScore) {
         this.totalScore = totalScore;
     }
 
-    public double getObjectiveScore() {
+    public String getObjectiveScore() {
         return objectiveScore;
     }
 
-    public void setObjectiveScore(double objectiveScore) {
+    public void setObjectiveScore(String objectiveScore) {
         this.objectiveScore = objectiveScore;
     }
 
-    public double getSubjectiveScore() {
+    public String getSubjectiveScore() {
         return subjectiveScore;
     }
 
-    public void setSubjectiveScore(double subjectiveScore) {
+    public void setSubjectiveScore(String subjectiveScore) {
         this.subjectiveScore = subjectiveScore;
     }
 
@@ -207,12 +231,20 @@ public class ExamStudentDTO {
         this.objectiveList = objectiveList;
     }
 
-    public List<ScoreItem> getSubjectiveList() {
+    public List<String> getSubjectiveList() {
         return subjectiveList;
     }
 
-    public void setSubjectiveList(List<ScoreItem> subjectiveList) {
+    public void setSubjectiveList(List<String> subjectiveList) {
         this.subjectiveList = subjectiveList;
     }
 
+    public String getBreach() {
+        return breach;
+    }
+
+    public void setBreach(String breach) {
+        this.breach = breach;
+    }
+
 }

+ 17 - 5
stmms-web/src/main/java/cn/com/qmth/stmms/admin/dto/MarkerInfoDTO.java

@@ -13,22 +13,26 @@ public class MarkerInfoDTO {
     @ExcelField(title = "课程名称", align = 2, sort = 20)
     private String subjectName;
 
-    @ExcelField(title = "大题名称", align = 2, sort = 30)
+    @ExcelField(title = "分组序号", align = 2, sort = 30)
+    private String groupNumber;
+
+    @ExcelField(title = "大题名称", align = 2, sort = 40)
     private String groupName;
 
-    @ExcelField(title = "登录名", align = 2, sort = 40)
+    @ExcelField(title = "登录名", align = 2, sort = 50)
     private String loginName;
 
-    @ExcelField(title = "姓名", align = 2, sort = 50)
+    @ExcelField(title = "姓名", align = 2, sort = 60)
     private String name;
 
-    @ExcelField(title = "评卷数量", align = 2, sort = 60)
+    @ExcelField(title = "评卷数量", align = 2, sort = 70)
     private long markedCount;
 
     public MarkerInfoDTO(Marker marker, ExamSubject subject, MarkGroup group) {
         setSubjectCode(subject.getCode());
         setSubjectName(subject.getName());
-        setGroupName(group.getNumber() + "_" + group.getTitle());
+        setGroupName(group.getTitle());
+        setGroupNumber(String.valueOf(group.getNumber()));
         setLoginName(marker.getUser().getLoginName());
         setName(marker.getUser().getName());
         setMarkedCount(marker.getMarkedCount());
@@ -82,4 +86,12 @@ public class MarkerInfoDTO {
         this.groupName = groupName;
     }
 
+    public String getGroupNumber() {
+        return groupNumber;
+    }
+
+    public void setGroupNumber(String groupNumber) {
+        this.groupNumber = groupNumber;
+    }
+
 }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.