1
0
Эх сурвалжийг харах

新增授权和华师隐藏密号

ting.yin 3 жил өмнө
parent
commit
b1c5d61e6f
32 өөрчлөгдсөн 1140 нэмэгдсэн , 321 устгасан
  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. 102 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/model/SystemAuth.java
  5. 11 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/SystemAuthService.java
  6. 32 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemAuthServiceImpl.java
  7. 102 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemCache.java
  8. 11 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/config/service/impl/SystemConfigServiceImpl.java
  9. 4 5
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java
  10. 3 4
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/mark/service/Impl/MarkCronService.java
  11. 6 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/SchoolService.java
  12. 10 7
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/OrgCornService.java
  13. 38 8
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/impl/SchoolServiceImpl.java
  14. 6 1
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/thread/OrgSyncThread.java
  15. 76 0
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/AppLicenseUtil.java
  16. 38 22
      stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/SolarHttpUtil.java
  17. 31 0
      stmms-common/src/main/java/cn/com/qmth/stmms/common/enums/SystemAuthType.java
  18. 151 0
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/config/SystemAuthController.java
  19. 15 7
      stmms-web/src/main/java/cn/com/qmth/stmms/admin/school/SchoolController.java
  20. 12 0
      stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java
  21. 22 0
      stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/LoginController.java
  22. 11 0
      stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java
  23. BIN
      stmms-web/src/main/resources/license/public.key
  24. 3 3
      stmms-web/src/main/webapp/WEB-INF/application.properties
  25. 101 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/sys/authEdit.jsp
  26. 37 0
      stmms-web/src/main/webapp/WEB-INF/views/modules/sys/authInfo.jsp
  27. 2 1
      stmms-web/src/main/webapp/WEB-INF/views/modules/sys/sysIndex.jsp
  28. 17 1
      stmms-web/src/main/webapp/sql/stmms_ft.sql
  29. 2 0
      stmms-web/src/main/webapp/static/i18n/messages.properties
  30. 5 3
      stmms-web/src/main/webapp/static/i18n/messages_en.properties
  31. 260 258
      stmms-web/src/main/webapp/static/i18n/messages_ja.properties
  32. 2 0
      stmms-web/src/main/webapp/static/i18n/messages_zh.properties

+ 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> {
+
+}

+ 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;
+    }
+
+}

+ 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);
+
+}

+ 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;
+    }
+
+}

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

@@ -18,12 +18,22 @@ public class SystemConfigServiceImpl extends BaseQueryService<SystemConfig> impl
     @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());
-        return configDao.save(s);
+        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

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

@@ -13,14 +13,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import cn.com.qmth.stmms.biz.config.service.SystemConfigService;
+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;
-import cn.com.qmth.stmms.common.enums.ConfigType;
 
 @Service("fileService")
 public class FileServiceImpl implements FileService, InitializingBean, DisposableBean {
@@ -32,7 +31,7 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
     public static final String SERVER_SPLIT = ",";
 
     @Autowired
-    private SystemConfigService configService;
+    private SystemCache systemCache;
 
     private List<String> fileServers;
 
@@ -67,7 +66,7 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     public List<String> getFileServers() {
         fileServers = new ArrayList<>();
-        String[] servers = StringUtils.split(configService.findByType(ConfigType.FILE_SERVER), SERVER_SPLIT);
+        String[] servers = StringUtils.split(systemCache.getFileServer(), SERVER_SPLIT);
         for (String server : servers) {
             server = StringUtils.trimToNull(server);
             if (server != null) {
@@ -247,7 +246,7 @@ public class FileServiceImpl implements FileService, InitializingBean, Disposabl
 
     @Override
     public void afterPropertiesSet() {
-        String fileServerString = configService.findByType(ConfigType.FILE_SERVER);
+        String fileServerString = systemCache.getFileServer();
         fileStore = StringUtils.trimToNull(fileStore);
         if (fileServerString == null) {
             throw new RuntimeException("invald property: ${file.server} should not be empty");

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

@@ -10,7 +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.SystemConfigService;
+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;
@@ -22,7 +22,6 @@ import cn.com.qmth.stmms.biz.exam.service.MarkerService;
 import cn.com.qmth.stmms.biz.lock.LockService;
 import cn.com.qmth.stmms.biz.mark.service.MarkService;
 import cn.com.qmth.stmms.biz.utils.TaskLockUtil;
-import cn.com.qmth.stmms.common.enums.ConfigType;
 import cn.com.qmth.stmms.common.enums.LockType;
 import cn.com.qmth.stmms.common.enums.MarkStatus;
 import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
@@ -56,7 +55,7 @@ public class MarkCronService {
     private MarkerService markerService;
 
     @Autowired
-    private SystemConfigService configService;
+    private SystemCache systemCache;
 
     @Value("${mark.activeExpireMinute}")
     private long markerActiveExpireMinute;
@@ -79,7 +78,7 @@ public class MarkCronService {
     @Scheduled(cron = "${mark.cleanTaskSchedule}")
     public void cronCleanTask() {
         try {
-            long timeoutMinute = Long.parseLong(configService.findByType(ConfigType.MARK_TIME));
+            long timeoutMinute = systemCache.getMarkTime();
             TaskLockUtil.clearTimeoutTask(timeoutMinute * 60 * 1000);
         } catch (Exception e) {
             log.error("CronCleanTask error", e);

+ 6 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/service/SchoolService.java

@@ -1,5 +1,7 @@
 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;
 
@@ -21,4 +23,8 @@ public interface SchoolService {
 
     void updateOrg();
 
+    void updateOrg(List<School> list);
+
+    List<School> parseJson(String json);
+
 }

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

@@ -1,16 +1,18 @@
 package cn.com.qmth.stmms.biz.school.service.impl;
 
-import org.apache.commons.lang.StringUtils;
 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.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;
 
 /**
  * 机构同步定时任务
@@ -28,18 +30,19 @@ public class OrgCornService {
     @Autowired
     private LockService lockService;
 
-    @Value("${qmth.solar.accessKey}")
-    private String accessKey;
+    @Autowired
+    private SystemAuthService authService;
 
-    @Value("${qmth.solar.accessSecret}")
-    private String accessSecret;
+    @Autowired
+    private SystemCache authCache;
 
     /**
      * 自动同步
      */
     @Scheduled(cron = "${school.updateMinute}")
     public void cronUpdateOrg() {
-        if (StringUtils.isNotBlank(accessKey) && StringUtils.isNotBlank(accessSecret)) {
+        SystemAuth systemAuth = authService.findOne();
+        if (systemAuth != null && SystemAuthType.ONLINE.equals(systemAuth.getType()) && authCache.isAuth()) {
             lockService.trylock(LockType.SCHOOL, "");
             try {
                 schoolService.updateOrg();

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

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.biz.school.service.impl;
 
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -9,6 +10,9 @@ 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;
@@ -18,11 +22,14 @@ 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.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.OrgUtil;
+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 {
@@ -30,16 +37,13 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
     @Autowired
     public SchoolDao schoolDao;
 
-    @Value("${qmth.solar.accessKey}")
-    private String accessKey;
-
-    @Value("${qmth.solar.accessSecret}")
-    private String accessSecret;
+    @Autowired
+    private SystemAuthService authService;
 
     @Value("${qmth.solar.host}")
     private String host;
 
-    @Value("${qmth.solar.uri}")
+    @Value("${qmth.solar.org.uri}")
     private String uri;
 
     @Override
@@ -110,8 +114,16 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
     @Transactional
     @Override
     public void updateOrg() {
-        OrgUtil orgUtil = new OrgUtil(accessKey, accessSecret, host, uri);
+        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) {
@@ -128,4 +140,22 @@ public class SchoolServiceImpl extends BaseQueryService<School> implements Schoo
             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;
+    }
 }

+ 6 - 1
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/school/thread/OrgSyncThread.java

@@ -3,6 +3,7 @@ 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;
@@ -14,8 +15,11 @@ public class OrgSyncThread implements Runnable {
 
     private SchoolService schoolService;
 
-    public OrgSyncThread(SchoolService schoolService) {
+    private SystemCache authCache;
+
+    public OrgSyncThread(SchoolService schoolService, SystemCache authCache) {
         this.schoolService = schoolService;
+        this.authCache = authCache;
     }
 
     @Override
@@ -24,6 +28,7 @@ public class OrgSyncThread implements Runnable {
         try {
             schoolService.updateOrg();
         } catch (Exception e) {
+            authCache.setAuth(false);
             log.error("OrgSyncThread error", e);
         }
         lockService.unlock(LockType.SCHOOL, "");

+ 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;
+    }
+
+}

+ 38 - 22
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/OrgUtil.java → stmms-biz/src/main/java/cn/com/qmth/stmms/biz/utils/SolarHttpUtil.java

@@ -30,9 +30,9 @@ 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 OrgUtil {
+public class SolarHttpUtil {
 
-    private static Logger log = LoggerFactory.getLogger(OrgUtil.class);
+    private static Logger log = LoggerFactory.getLogger(SolarHttpUtil.class);
 
     /** 默认的编码格式 */
     public static final String DEFAULT_CHARSET = "UTF-8";
@@ -53,7 +53,7 @@ public class OrgUtil {
 
     protected String accessSecret = null;
 
-    public OrgUtil(String accessKey, String accessSecret, String host, String uri) {
+    public SolarHttpUtil(String accessKey, String accessSecret, String host, String uri) {
         this.accessKey = accessKey;
         this.accessSecret = accessSecret;
         this.uri = uri;
@@ -212,6 +212,19 @@ public class OrgUtil {
         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;
@@ -243,25 +256,28 @@ public class OrgUtil {
         return schools;
     }
 
-    public static void main(String[] args) throws IOException {
-        OrgUtil orgUtil = new OrgUtil("7bbdc11570bc474dbf50e0d4a5dff328", "IOodRvbp2LspJTHOScgB7Yx8MRloMpyl",
-                "https://solar.qmth.com.cn", "/api/open/org/query");
-        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);
-        }
+    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/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;
+    }
+}

+ 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());
+    }
+
+}

+ 15 - 7
stmms-web/src/main/java/cn/com/qmth/stmms/admin/school/SchoolController.java

@@ -5,7 +5,6 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.core.task.AsyncTaskExecutor;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -13,6 +12,9 @@ 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.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.model.School;
 import cn.com.qmth.stmms.biz.school.query.SchoolSearchQuery;
@@ -25,6 +27,7 @@ import cn.com.qmth.stmms.common.controller.BaseController;
 import cn.com.qmth.stmms.common.enums.LockType;
 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.enums.UserSource;
 import cn.com.qmth.stmms.common.utils.EncryptUtils;
 
@@ -45,11 +48,11 @@ public class SchoolController extends BaseController {
     @Autowired
     private LockService lockService;
 
-    @Value("${qmth.solar.accessKey}")
-    private String accessKey;
+    @Autowired
+    private SystemAuthService authService;
 
-    @Value("${qmth.solar.accessSecret}")
-    private String accessSecret;
+    @Autowired
+    private SystemCache authCache;
 
     @Logging(menu = "学校查询", type = LogType.QUERY)
     @RequestMapping
@@ -57,7 +60,12 @@ public class SchoolController extends BaseController {
         ModelAndView view = new ModelAndView("modules/sys/schoolList");
         query = schoolService.findByQuery(query);
         view.addObject("query", query);
-        view.addObject("enableUpadteOrg", StringUtils.isNotBlank(accessKey) && StringUtils.isNotBlank(accessSecret));
+        boolean enableUpadteOrg = false;
+        SystemAuth systemAuth = authService.findOne();
+        if (systemAuth != null && SystemAuthType.ONLINE.equals(systemAuth.getType()) && authCache.isAuth()) {
+            enableUpadteOrg = true;
+        }
+        view.addObject("enableUpadteOrg", enableUpadteOrg);
         view.addObject("running", lockService.isLocked(LockType.SCHOOL, ""));
         return view;
     }
@@ -178,7 +186,7 @@ public class SchoolController extends BaseController {
     @RequestMapping(value = "/updateOrg", method = RequestMethod.GET)
     public String updateOrg(HttpServletRequest request) {
         if (lockService.trylock(LockType.SCHOOL, "")) {
-            OrgSyncThread thread = new OrgSyncThread(schoolService);
+            OrgSyncThread thread = new OrgSyncThread(schoolService, authCache);
             taskExecutor.submit(thread);
         }
         return "redirect:/admin/sys/school";

+ 12 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java

@@ -283,6 +283,18 @@ public class BaseController {
                 }
             }
         });
+        // SystemAuthType 类型转换
+        binder.registerCustomEditor(SystemAuthType.class, new PropertyEditorSupport() {
+
+            @Override
+            public void setAsText(String text) {
+                try {
+                    setValue(SystemAuthType.findByValue(Integer.valueOf(text)));
+                } catch (Exception e) {
+                    setValue(null);
+                }
+            }
+        });
         binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
     }
 

+ 22 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/LoginController.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.stmms.common.controller;
 
+import cn.com.qmth.stmms.biz.config.service.impl.SystemCache;
 import cn.com.qmth.stmms.biz.user.model.User;
 import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.common.annotation.Logging;
@@ -35,6 +36,9 @@ public class LoginController {
     @Autowired
     private SessionService sessionService;
 
+    @Autowired
+    private SystemCache authCache;
+
     @Value("${index.logo}")
     private String indexLogo;
 
@@ -79,6 +83,15 @@ public class LoginController {
             modelAndView.addObject("message", "user.login.error.disabled");
             return modelAndView;
         }
+        if (!authCache.isAuth() && u.getRole() != Role.SYS_ADMIN) {
+            modelAndView.addObject("message", "user.login.error.auth");
+            return modelAndView;
+        }
+        if (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date())
+                && u.getRole() != Role.SYS_ADMIN) {
+            modelAndView.addObject("message", "user.login.error.expire");
+            return modelAndView;
+        }
         if (ADMIN_LOGIN.equals(loginType)) {
             if (u.getRole() == Role.SYS_ADMIN || u.getRole() == Role.SCHOOL_ADMIN || u.getRole() == Role.SUBJECT_HEADER
                     || u.getRole() == Role.SCHOOL_VIEWER || u.getRole() == Role.INSPECTOR) {
@@ -138,6 +151,15 @@ public class LoginController {
         ModelAndView modelAndView = new ModelAndView("modules/sys/login");
         modelAndView.addObject("indexLogo", indexLogo);
         modelAndView.addObject(LOGIN_TYPE_KEY, MARK_LOGIN_ONLY);
+        if (!authCache.isAuth()
+                || (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date()))) {
+            modelAndView.addObject("message", "user.login.error.auth");
+            return modelAndView;
+        }
+        if (authCache.getExpireTime() != null && new Date(authCache.getExpireTime()).before(new Date())) {
+            modelAndView.addObject("message", "user.login.error.expire");
+            return modelAndView;
+        }
         if (u == null) {
             modelAndView.addObject("message", "user.login.error.account");
             return modelAndView;

+ 11 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/mark/MarkController.java

@@ -140,6 +140,11 @@ public class MarkController extends BaseController {
     @Value("${marker.name.verify}")
     private boolean nameVerify;
 
+    @Value("${marker.secretNumber.hide}")
+    private boolean secretNumberHide;
+
+    private static final String DEFALT_SECRET_NUMBER = "***";
+
     @RequestMapping(value = "/reset", method = RequestMethod.GET)
     public ModelAndView reset(HttpServletRequest request) {
         User user = RequestUtils.getWebUser(request).getUser();
@@ -429,6 +434,9 @@ public class MarkController extends BaseController {
         }
         task.setExamNumber(null);
         task.setStudentCode(null);
+        if (secretNumberHide) {
+            task.setSecretNumber(DEFALT_SECRET_NUMBER);
+        }
         return task;
     }
 
@@ -570,6 +578,9 @@ public class MarkController extends BaseController {
         for (Task task : list) {
             task.setExamNumber(null);
             task.setStudentCode(null);
+            if (secretNumberHide) {
+                task.setSecretNumber(DEFALT_SECRET_NUMBER);
+            }
         }
         return list;
     }

BIN
stmms-web/src/main/resources/license/public.key


+ 3 - 3
stmms-web/src/main/webapp/WEB-INF/application.properties

@@ -25,6 +25,7 @@ marker.showBtnImportAndBtnUpdateImport=false
 marker.forceMode=
 marker.name.verify=true
 marker.prefetch.count=3
+marker.secretNumber.hide=false
 ##\u9996\u9875\u53ef\u9009\u7684logo\u6587\u4ef6
 index.logo=
 ##\u4e91\u5e73\u53f0\u5bf9\u63a5\u914d\u7f6e
@@ -39,7 +40,6 @@ qmth.examcloud.subject.paper.uri=/api/exchange/outer/question/getSubjectivePaper
 qmth.examcloud.student.uri=/api/exchange/outer/question/getSubjectiveQuestion
 
 school.updateMinute=0 0 0 * * ?
-qmth.solar.accessKey=
-qmth.solar.accessSecret=
 qmth.solar.host=https://solar.qmth.com.cn
-qmth.solar.uri=/api/open/org/query
+qmth.solar.org.uri=/api/open/org/query
+qmth.solar.app.uri=/api/open/app/info

+ 101 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/sys/authEdit.jsp

@@ -0,0 +1,101 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+	<title>授权管理</title>
+	<meta name="decorator" content="default"/>
+	<%@include file="/WEB-INF/views/include/head.jsp" %>
+	<script type="text/javascript">
+		$(document).ready(function() {
+			$("#inputForm").validate({
+				submitHandler: function(form){
+					loading('正在提交,请稍等...');
+					form.submit();
+				},
+				errorContainer: "#messageBox",
+				errorPlacement: function(error, element) {
+					$("#messageBox").text("输入有误,请先更正。");
+					if (element.is(":checkbox")||element.is(":radio")||element.parent().is(".input-append")){
+						error.appendTo(element.parent().parent());
+					} else {
+						error.insertAfter(element);
+					}
+				}
+			});
+		});
+	</script>
+</head>
+<body>
+	<ul class="nav nav-tabs">
+		<li><a href="${ctx}/admin/sys/auth">授权信息</a></li>
+		<li class="active"><a href="${ctx}/admin/sys/auth/edit">更新授权</a></li>
+	</ul><br/>
+	<form:form id="inputForm" modelAttribute="systemAuth" action="${ctx}/admin/sys/auth/update" method="post" class="form-horizontal" enctype="multipart/form-data">
+		<tags:message content="${message}"/>
+		<input type="hidden" name="id" value="${systemAuth.id}"/>
+		<div class="control-group">
+	        <label class="control-label">授权模式</label>
+	        <div class="controls">
+	            <select name="type" id="type">
+	                <c:forEach items="${typeList}" var="item">
+	                    <option value="${item.value}" <c:if test="${systemAuth.type.value==item.value }">selected="selected"</c:if>>${item.name}</option>
+	                </c:forEach>
+	            </select>
+	        </div>
+	    </div>
+	    <div id="onlineDiv">
+	    	<div class="control-group">
+				<label class="control-label">导出</label>
+				<div class="controls">
+					<a href="${ctx}/admin/sys/auth/exportInfo" class="btn">硬件信息</a> 
+				</div>
+			</div>
+			<div class="control-group">
+				<label class="control-label">导入授权文件</label>
+				<div class="controls">
+					<input name="file" type="file" style="width:330px"/>  
+				</div>
+			</div>
+	    </div>
+	    <div id="offlineDiv">
+	    	<div class="control-group">
+			<label class="control-label">密匙</label>
+			<div class="controls">
+				<input name="accessKey" value=""/>
+			</div>
+			</div>
+			<div class="control-group">
+				<label class="control-label">密钥</label>
+				<div class="controls">
+					<input name="accessSecret" value=""/>
+				</div>
+			</div>
+	    </div>
+	    <div class="form-actions">
+        	 <input class="btn btn-primary" type="submit" value="保  存"/>
+    	</div>
+	</form:form>
+    <script type="text/javascript">
+	    $(document).ready(function () {
+	    	if ($("#type").val()==1) {
+	            $("#offlineDiv").show();
+	            $("#onlineDiv").hide();
+	        } 
+	        if ($("#type").val()==2) {
+	        	$("#onlineDiv").show();
+	        	$("#offlineDiv").hide();
+	        }
+	    });
+	    $("#type").change(function () {
+	        if ($("#type").val()==1) {
+	            $("#offlineDiv").show();
+	            $("#onlineDiv").hide();
+	        } 
+	        if ($("#type").val()==2) {
+	        	$("#onlineDiv").show();
+	        	$("#offlineDiv").hide();
+	        }
+	    });
+    </script>
+</body>
+</html>

+ 37 - 0
stmms-web/src/main/webapp/WEB-INF/views/modules/sys/authInfo.jsp

@@ -0,0 +1,37 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
+<html>
+<head>
+	<title>授权管理</title>
+	<meta name="decorator" content="default"/>
+	<%@include file="/WEB-INF/views/include/head.jsp" %>
+</head>
+<body>
+	<ul class="nav nav-tabs">
+		<li class="active"><a href="${ctx}/admin/sys/auth">授权信息</a></li>
+		<li><a href="${ctx}/admin/sys/auth/edit">更新授权</a></li>
+	</ul><br/>
+	<form:form id="inputForm" modelAttribute="systemAuth" action="${ctx}/admin/sys/auth/save" method="post" class="form-horizontal" enctype="multipart/form-data">
+		<tags:message content="${message}"/>
+		<input type="hidden" name="id" value="${systemAuth.id}"/>
+		<div class="control-group">
+	        <label class="control-label">当前信息</label>
+	        <div class="controls">
+	            <c:if test="${auth}">已</c:if><c:if test="${!auth}">未</c:if>授权
+	        </div>
+	    </div>
+	    <div class="control-group">
+	        <label class="control-label">过期时间</label>
+	        <div class="controls">
+	            <c:if test="${expireTime!=null}"><fmt:formatDate value="${expireTime}" pattern="yyyy-MM-dd HH:mm:ss" /></c:if><c:if test="${expireTime==null}">无</c:if>
+	        </div>
+	    </div>
+		<div class="control-group">
+	        <label class="control-label">授权模式</label>
+	        <div class="controls">
+	        	${systemAuth.type.name }
+	        </div>
+	    </div>
+	</form:form>
+</body>
+</html>

+ 2 - 1
stmms-web/src/main/webapp/WEB-INF/views/modules/sys/sysIndex.jsp

@@ -88,7 +88,8 @@
 									<div class="accordion-inner">
 										<ul class="nav nav-list">
 											<li><a href="${ctx}/admin/sys/school" target="mainFrame" ><i class="icon-th-list"></i>学校管理</a></li>	
-											<li><a href="${ctx}/admin/sys/config" target="mainFrame" ><i class="icon-th-list"></i>配置管理</a></li>							
+											<li><a href="${ctx}/admin/sys/config" target="mainFrame" ><i class="icon-th-list"></i>配置管理</a></li>
+											<li><a href="${ctx}/admin/sys/auth" target="mainFrame" ><i class="icon-th-list"></i>授权管理</a></li>														
 											<c:set var="firstMenu" value="false"/>
 										</ul>
 									</div>

+ 17 - 1
stmms-web/src/main/webapp/sql/stmms_ft.sql

@@ -18,7 +18,7 @@ CREATE TABLE `b_school`
     `code`          varchar(64)  DEFAULT NULL COMMENT '代码',
     `address`       varchar(128) DEFAULT NULL COMMENT '地址',
     `phone`         varchar(32)  DEFAULT NULL COMMENT '电话',
-    `logo_url`      varchar(64)  DEFAULT NULL COMMENT '图片地址',
+    `logo_url`      text  DEFAULT NULL COMMENT '图片地址',
     `description`   varchar(128) DEFAULT NULL COMMENT '描述',
     `enable`        tinyint(1)  NOT NULL COMMENT '是否禁用',
     `access_key`    varchar(64)  DEFAULT NULL COMMENT 'AccessKey',
@@ -54,6 +54,22 @@ INSERT INTO `b_sys_config` (`id`, `type`, `description`, `update_time`)
 VALUES (2, 'MARK_TIME', '30', '2021-08-09 15:38:58');
 
 UNLOCK TABLES;
+
+
+# Dump of table b_sys_auth
+# ------------------------------------------------------------
+DROP TABLE IF EXISTS `b_sys_auth`;
+CREATE TABLE `b_sys_auth` (
+	`id`            int(11)     NOT NULL AUTO_INCREMENT COMMENT '主键',
+	`access_key` 	varchar(255) DEFAULT NULL COMMENT 'AccessKey',
+	`access_secret` varchar(255) DEFAULT NULL COMMENT 'AccessSecret',
+	`description` 	text		DEFAULT NULL COMMENT '离线授权证书',
+	`type` 			varchar(16) NOT NULL COMMENT '授权类型',
+    `update_time`   datetime    DEFAULT NULL COMMENT '修改时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB 
+	DEFAULT CHARSET = utf8mb4 COMMENT ='授权配置表';
+
   
 # Dump of table b_user
 # ------------------------------------------------------------

+ 2 - 0
stmms-web/src/main/webapp/static/i18n/messages.properties

@@ -5,6 +5,8 @@ user.login.marker=\u8bc4\u5377\u5458\u767b\u5f55
 user.login.name=\u8d26\u53f7
 user.login.password=\u5bc6\u7801
 user.login.submit=\u767b\u5f55
+user.login.error.auth=\u672a\u6388\u6743\u65e0\u6cd5\u767b\u5f55
+user.login.error.expire=\u6388\u6743\u5df2\u7ecf\u8fc7\u671f
 user.login.error.account=\u5e10\u53f7\u4e0d\u5b58\u5728
 user.login.error.finish=\u8bc4\u5377\u5206\u7ec4\u5df2\u7ed3\u675f
 user.login.error.group=\u5927\u9898\u4e0d\u5b58\u5728

+ 5 - 3
stmms-web/src/main/webapp/static/i18n/messages_en.properties

@@ -5,6 +5,8 @@ user.login.marker=Marker
 user.login.name=username
 user.login.password=password
 user.login.submit=Login
+user.login.error.auth=Unable to login without authorization
+user.login.error.expire=The authorization has expired
 user.login.error.account=Account does not exist
 user.login.error.finish=marking is finish
 user.login.error.group=the question group is not exist
@@ -19,7 +21,7 @@ user.reset.name=press your name
 user.reset.password=press new password
 user.reset.password.again=press new password again
 user.reset.name.length=length cannot exceed 10 words
-user.reset.name.chinese=\u8BF7\u8F93\u5165\u4E2D\u6587
+user.reset.name.chinese=\u8bf7\u8f93\u5165\u4e2d\u6587
 user.reset.password.same=please keep the same password twice
 user.reset.password.length=password must be at least 4 word,cannot exceed 8 words
 #mark-control
@@ -99,7 +101,7 @@ mark.history.error=Unable to read the history at this time. Please try again lat
 mark.history.number.error=please press number
 #mark-board
 mark.board.submit=submit
-mark.board.total.score=Score\uFF1A
+mark.board.total.score=Score\uff1a
 mark.board.score.zero=all zero
 mark.board.pass=pass
 mark.board.choose.result=choose result
@@ -291,4 +293,4 @@ student.search.list.subjectName=subject name
 student.search.list.objectiveScore=objective score
 student.search.list.subjectiveScore=subjective score
 student.search.list.totalScore=total score
-student.search.list.remark=\u5907\u6CE8
+student.search.list.remark=\u5907\u6ce8

+ 260 - 258
stmms-web/src/main/webapp/static/i18n/messages_ja.properties

@@ -1,294 +1,296 @@
 #login
-user.login.title=\u30C7\u30B8\u30BF\u30EB\u63A1\u70B9\u30B7\u30B9\u30C6\u30E0\u3078\u30ED\u30B0\u30A4\u30F3
-user.login.admin=\u7BA1\u7406\u8005\u767B\u9332
-user.login.marker=\u63A1\u70B9\u8005\u767B\u9332
-user.login.name=\u30E6\u30FC\u30B6\u30FC\u540D
-user.login.password=\u30D1\u30B9\u30EF\u30FC\u30C9
-user.login.submit=\u30ED\u30B0\u30A4\u30F3
-user.login.error.account=\u8A72\u5F53\u3059\u308B\u30A2\u30AB\u30A6\u30F3\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093
-user.login.error.finish=\u63A1\u70B9\u4F5C\u696D\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F
-user.login.error.group=\u8A72\u5F53\u3059\u308B\u5927\u554F\u304C\u5B58\u5728\u3057\u307E\u305B\u3093
-user.login.error.disabled=\u3053\u306E\u30A2\u30AB\u30A6\u30F3\u30C8\u306F\u73FE\u5728\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093
-user.login.error.password=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u9593\u9055\u3063\u3066\u3044\u307E\u3059
-user.login.error.access=\u30A2\u30AF\u30BB\u30B9\u3059\u308B\u6A29\u5229\u304C\u3042\u308A\u307E\u305B\u3093
+user.login.title=\u30c7\u30b8\u30bf\u30eb\u63a1\u70b9\u30b7\u30b9\u30c6\u30e0\u3078\u30ed\u30b0\u30a4\u30f3
+user.login.admin=\u7ba1\u7406\u8005\u767b\u9332
+user.login.marker=\u63a1\u70b9\u8005\u767b\u9332
+user.login.name=\u30e6\u30fc\u30b6\u30fc\u540d
+user.login.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+user.login.submit=\u30ed\u30b0\u30a4\u30f3
+user.login.error.auth=\u672a\u6388\u6743\u65e0\u6cd5\u767b\u5f55
+user.login.error.expire=\u6388\u6743\u5df2\u7ecf\u8fc7\u671f
+user.login.error.account=\u8a72\u5f53\u3059\u308b\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u5b58\u5728\u3057\u307e\u305b\u3093
+user.login.error.finish=\u63a1\u70b9\u4f5c\u696d\u304c\u7d42\u4e86\u3057\u307e\u3057\u305f
+user.login.error.group=\u8a72\u5f53\u3059\u308b\u5927\u554f\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+user.login.error.disabled=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u73fe\u5728\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093
+user.login.error.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u9593\u9055\u3063\u3066\u3044\u307e\u3059
+user.login.error.access=\u30a2\u30af\u30bb\u30b9\u3059\u308b\u6a29\u5229\u304c\u3042\u308a\u307e\u305b\u3093
 #reset
-user.reset.submit=\u78BA\u5B9A
-user.reset.logout=\u30ED\u30B0\u30A2\u30A6\u30C8
-user.reset.title=\u65B0\u898F\u767B\u9332
-user.reset.name=\u30E6\u30FC\u30B6\u30FC\u540D
-user.reset.password=\u30D1\u30B9\u30EF\u30FC\u30C9
-user.reset.password.again=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u518D\u5165\u529B
-user.reset.name.length=\u30D1\u30B9\u30EF\u30FC\u30C9\u306F10\u6587\u5B57\u4EE5\u5185\u306B\u3057\u3066\u304F\u3060\u3055\u3044
-user.reset.name.chinese=\u8BF7\u8F93\u5165\u4E2D\u6587
-user.reset.password.same=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093
-user.reset.password.length=4\u6587\u5B57\u4EE5\u4E0A\u30018\u6587\u5B57\u4EE5\u5185\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u4F5C\u6210\u3057\u3066\u304F\u3060\u3055\u3044
+user.reset.submit=\u78ba\u5b9a
+user.reset.logout=\u30ed\u30b0\u30a2\u30a6\u30c8
+user.reset.title=\u65b0\u898f\u767b\u9332
+user.reset.name=\u30e6\u30fc\u30b6\u30fc\u540d
+user.reset.password=\u30d1\u30b9\u30ef\u30fc\u30c9
+user.reset.password.again=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u518d\u5165\u529b
+user.reset.name.length=\u30d1\u30b9\u30ef\u30fc\u30c9\u306f10\u6587\u5b57\u4ee5\u5185\u306b\u3057\u3066\u304f\u3060\u3055\u3044
+user.reset.name.chinese=\u8bf7\u8f93\u5165\u4e2d\u6587
+user.reset.password.same=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093
+user.reset.password.length=4\u6587\u5b57\u4ee5\u4e0a\u30018\u6587\u5b57\u4ee5\u5185\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u4f5c\u6210\u3057\u3066\u304f\u3060\u3055\u3044
 #mark-control
-mark.control.assistant=\u305D\u306E\u4ED6\u306E\u6A5F\u80FD
-mark.control.mode.track=\u90E8\u5206\u63A1\u70B9\u30E2\u30FC\u30C9\u306B\u5207\u308A\u66FF\u3048\u308B
-mark.control.mode.common=\u901A\u5E38\u63A1\u70B9\u30E2\u30FC\u30C9\u306B\u5207\u308A\u66FF\u3048\u308B
-mark.control.board=\u63A1\u70B9\u677F
-mark.control.function=\u63A1\u70B9\u6A5F\u80FD
+mark.control.assistant=\u305d\u306e\u4ed6\u306e\u6a5f\u80fd
+mark.control.mode.track=\u90e8\u5206\u63a1\u70b9\u30e2\u30fc\u30c9\u306b\u5207\u308a\u66ff\u3048\u308b
+mark.control.mode.common=\u901a\u5e38\u63a1\u70b9\u30e2\u30fc\u30c9\u306b\u5207\u308a\u66ff\u3048\u308b
+mark.control.board=\u63a1\u70b9\u677f
+mark.control.function=\u63a1\u70b9\u6a5f\u80fd
 mark.control.logout=EXIT
-mark.control.init.error=\u30C7\u30FC\u30BF\u30FC\u66F4\u65B0\u304C\u5931\u6557\u3057\u305F\u306E\u3067\u3001\u518D\u5EA6\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3057\u3066\u304F\u3060\u3055\u3044
-mark.control.task.not.exist=\u8A72\u5F53\u3059\u308B\u5927\u554F\u304C\u5B58\u5728\u3057\u307E\u305B\u3093
-mark.control.task.finish=\u63A1\u70B9\u4F5C\u696D\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F
-mark.control.task.null=\u63A1\u70B9\u5BFE\u8C61\u304C\u3042\u308A\u307E\u305B\u3093
-mark.control.task.error=\u63D0\u51FA\u306B\u5931\u6557\u3057\u305F\u306E\u3067\u3001\u518D\u5EA6\u8A66\u3057\u3066\u304F\u3060\u3055\u3044
-mark.control.group=\u5927\u554F
+mark.control.init.error=\u30c7\u30fc\u30bf\u30fc\u66f4\u65b0\u304c\u5931\u6557\u3057\u305f\u306e\u3067\u3001\u518d\u5ea6\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3057\u3066\u304f\u3060\u3055\u3044
+mark.control.task.not.exist=\u8a72\u5f53\u3059\u308b\u5927\u554f\u304c\u5b58\u5728\u3057\u307e\u305b\u3093
+mark.control.task.finish=\u63a1\u70b9\u4f5c\u696d\u304c\u7d42\u4e86\u3057\u307e\u3057\u305f
+mark.control.task.null=\u63a1\u70b9\u5bfe\u8c61\u304c\u3042\u308a\u307e\u305b\u3093
+mark.control.task.error=\u63d0\u51fa\u306b\u5931\u6557\u3057\u305f\u306e\u3067\u3001\u518d\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044
+mark.control.group=\u5927\u554f
 #status
-mark.status.student.number=\u53D7\u9A13\u8005\u7BA1\u7406\u756A\u53F7
-mark.status.library.number=\u63A1\u70B9\u30BF\u30B9\u30AF\u7BA1\u7406\u756A\u53F7
-mark.status.objective.score=\u30DE\u30FC\u30AF\u63A1\u70B9\u306E\u70B9\u6570
-mark.status.marked.count=\u63A1\u70B9\u30BF\u30B9\u30AF\u7D42\u4E86
-mark.status.unmark.count=\u63A1\u70B9\u30BF\u30B9\u30AF\u672A\u7D42\u4E86
-mark.status.top.count=\u5272\u308A\u5F53\u3066\u3089\u308C\u305F\u7B54\u6848\u7528\u7D19\u6570
-mark.status.progress=\u9032\u6357\u72B6\u6CC1
-mark.status.continue=\u5F15\u304D\u7D9A\u304D\u63A1\u70B9\u3057\u307E\u3059\u304B
-mark.status.top.count.finish=\u5272\u308A\u5F53\u3066\u3089\u308C\u305F\u30BF\u30B9\u30AF\u304C\u5B8C\u6210\u3057\u307E\u3057\u305F\u3002\u5F15\u304D\u7D9A\u304D\u63A1\u70B9\u3057\u307E\u3059\u304B\uFF1F
-mark.status.loading=\u30ED\u30FC\u30C9\u4E2D\u2026
-mark.status.logout=\u30ED\u30B0\u30A2\u30A6\u30C8
+mark.status.student.number=\u53d7\u9a13\u8005\u7ba1\u7406\u756a\u53f7
+mark.status.library.number=\u63a1\u70b9\u30bf\u30b9\u30af\u7ba1\u7406\u756a\u53f7
+mark.status.objective.score=\u30de\u30fc\u30af\u63a1\u70b9\u306e\u70b9\u6570
+mark.status.marked.count=\u63a1\u70b9\u30bf\u30b9\u30af\u7d42\u4e86
+mark.status.unmark.count=\u63a1\u70b9\u30bf\u30b9\u30af\u672a\u7d42\u4e86
+mark.status.top.count=\u5272\u308a\u5f53\u3066\u3089\u308c\u305f\u7b54\u6848\u7528\u7d19\u6570
+mark.status.progress=\u9032\u6357\u72b6\u6cc1
+mark.status.continue=\u5f15\u304d\u7d9a\u304d\u63a1\u70b9\u3057\u307e\u3059\u304b
+mark.status.top.count.finish=\u5272\u308a\u5f53\u3066\u3089\u308c\u305f\u30bf\u30b9\u30af\u304c\u5b8c\u6210\u3057\u307e\u3057\u305f\u3002\u5f15\u304d\u7d9a\u304d\u63a1\u70b9\u3057\u307e\u3059\u304b\uff1f
+mark.status.loading=\u30ed\u30fc\u30c9\u4e2d\u2026
+mark.status.logout=\u30ed\u30b0\u30a2\u30a6\u30c8
 #single-image-view
-mark.single.zoom.in=\u62E1\u5927
-mark.single.zoom.out=\u7E2E\u5C0F
-mark.single.zoom.fit=\u753B\u9762\u30B5\u30A4\u30BA\u306B\u5408\u308F\u305B\u3066\u8868\u793A
-mark.single.student.answer=\u7B54\u6848\u7528\u7D19
+mark.single.zoom.in=\u62e1\u5927
+mark.single.zoom.out=\u7e2e\u5c0f
+mark.single.zoom.fit=\u753b\u9762\u30b5\u30a4\u30ba\u306b\u5408\u308f\u305b\u3066\u8868\u793a
+mark.single.student.answer=\u7b54\u6848\u7528\u7d19
 #chang name
-mark.change.name=\u30E6\u30FC\u30B6\u30FC\u30CB\u30C3\u30AF\u30CD\u30FC\u30E0\u5165\u529B
-mark.change.press.name=\u30E6\u30FC\u30B6\u30FC\u540D\u5165\u529B
-mark.change.press.password=\u30D1\u30B9\u30EF\u30FC\u30C9\u5165\u529B
-mark.change.press.password.again=\u30D1\u30B9\u30EF\u30FC\u30C9\u518D\u5165\u529B
-mark.change.confirm=\u78BA\u5B9A
-mark.change.name.null=\u30E6\u30FC\u30B6\u30FC\u540D\u5165\u529B
-mark.change.name.length=8\u6587\u5B57\u4EE5\u5185\u306B\u3057\u3066\u304F\u3060\u3055\u3044
-mark.change.password.same=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u307E\u305B\u3093
-mark.change.password.length=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6587\u5B57\u6570\u306F\uFF14\u6587\u5B57\u4EE5\u4E0A\u304C\u5FC5\u8981\u3067\u3059
-mark.change.network.error=\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u306E\u4E0D\u5177\u5408\u304C\u751F\u3058\u305F\u305F\u3081\u3001\u3084\u308A\u76F4\u3057\u3066\u4E0B\u3055\u3044
-mark.change.error=\u64CD\u4F5C\u304C\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u518D\u5EA6\u8A66\u3057\u3066\u304F\u3060\u3055\u3044
+mark.change.name=\u30e6\u30fc\u30b6\u30fc\u30cb\u30c3\u30af\u30cd\u30fc\u30e0\u5165\u529b
+mark.change.press.name=\u30e6\u30fc\u30b6\u30fc\u540d\u5165\u529b
+mark.change.press.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u5165\u529b
+mark.change.press.password.again=\u30d1\u30b9\u30ef\u30fc\u30c9\u518d\u5165\u529b
+mark.change.confirm=\u78ba\u5b9a
+mark.change.name.null=\u30e6\u30fc\u30b6\u30fc\u540d\u5165\u529b
+mark.change.name.length=8\u6587\u5b57\u4ee5\u5185\u306b\u3057\u3066\u304f\u3060\u3055\u3044
+mark.change.password.same=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093
+mark.change.password.length=\u30d1\u30b9\u30ef\u30fc\u30c9\u306e\u6587\u5b57\u6570\u306f\uff14\u6587\u5b57\u4ee5\u4e0a\u304c\u5fc5\u8981\u3067\u3059
+mark.change.network.error=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u4e0d\u5177\u5408\u304c\u751f\u3058\u305f\u305f\u3081\u3001\u3084\u308a\u76f4\u3057\u3066\u4e0b\u3055\u3044
+mark.change.error=\u64cd\u4f5c\u304c\u5931\u6557\u3057\u307e\u3057\u305f\u3002\u518d\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044
 #specialTag
-mark.special.tag=\u7279\u6B8A\u8A18\u53F7
-mark.special.back=\u623B\u308B
-mark.special.clear=\u3059\u3079\u3066\u306E\u63A1\u70B9\u3092\u524A\u9664
-mark.special.underline=\u30A2\u30F3\u30C0\u30FC\u30E9\u30A4\u30F3
-mark.special.open=\u958B\u304F
-mark.special.close=\u9589\u3058\u308B
+mark.special.tag=\u7279\u6b8a\u8a18\u53f7
+mark.special.back=\u623b\u308b
+mark.special.clear=\u3059\u3079\u3066\u306e\u63a1\u70b9\u3092\u524a\u9664
+mark.special.underline=\u30a2\u30f3\u30c0\u30fc\u30e9\u30a4\u30f3
+mark.special.open=\u958b\u304f
+mark.special.close=\u9589\u3058\u308b
 #problem-process
-mark.problem=\u7B54\u6848\u7528\u7D19\u554F\u984C\u3042\u308A
-mark.problem.type=\u554F\u984C\u30BF\u30A4\u30D7\u3092\u9078\u629E
-mark.problem.confirm=\u78BA\u5B9A
-mark.problem.cancel=\u30AD\u30E3\u30F3\u30BB\u30EB
-mark.problem.check=\u554F\u984C\u30BF\u30A4\u30D7\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044
+mark.problem=\u7b54\u6848\u7528\u7d19\u554f\u984c\u3042\u308a
+mark.problem.type=\u554f\u984c\u30bf\u30a4\u30d7\u3092\u9078\u629e
+mark.problem.confirm=\u78ba\u5b9a
+mark.problem.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb
+mark.problem.check=\u554f\u984c\u30bf\u30a4\u30d7\u3092\u9078\u629e\u3057\u3066\u4e0b\u3055\u3044
 #thumbnail
-mark.thumbnail=\u30B5\u30E0\u30CD\u30A4\u30EB\u8868\u793A
-mark.thumbnail.open=\u958B\u304F
-mark.thumbnail.close=\u9589\u3058\u308B
+mark.thumbnail=\u30b5\u30e0\u30cd\u30a4\u30eb\u8868\u793a
+mark.thumbnail.open=\u958b\u304f
+mark.thumbnail.close=\u9589\u3058\u308b
 #view-sidebar
-mark.sidebar=\u30B5\u30A4\u30C9\u30D0\u30FC
-mark.sidebar.paper=\u554F\u984C\u7528\u7D19
-mark.sidebar.answer=\u6A19\u6E96\u89E3\u7B54
+mark.sidebar=\u30b5\u30a4\u30c9\u30d0\u30fc
+mark.sidebar.paper=\u554f\u984c\u7528\u7d19
+mark.sidebar.answer=\u6a19\u6e96\u89e3\u7b54
 #mark-history
-mark.history.title=\u518D\u63A1\u70B9
+mark.history.title=\u518d\u63a1\u70b9
 mark.history.time=\u6642\u9593
-mark.history.number=\u756A\u53F7
-mark.history.score=\u5408\u8A08\u70B9
-mark.history.search=\u7B54\u6848\u7528\u7D19\u306E\u691C\u7D22
-mark.history.pre=\u623B\u308B
-mark.history.success=\u518D\u63A1\u70B9\u7D42\u4E86\u3000\u5408\u8A08\u70B9\uFF1A
-mark.history.problem=\u518D\u63A1\u70B9\u7D42\u4E86\u3000\u63D0\u51FA\u6E08\u307F\u3000
-mark.history.loading=\u30ED\u30FC\u30C9\u4E2D\u2026
-mark.history.error=\u63A1\u70B9\u8A18\u9332\u306E\u8AAD\u8FBC\u307F\u304C\u3067\u304D\u307E\u305B\u3093\u3002\u3057\u3070\u3089\u304F\u3057\u3066\u304B\u3089\u3082\u3046\u4E00\u5EA6\u8A66\u3057\u3066\u304F\u3060\u3055\u3044
-mark.history.number.error=\u8A8D\u8B58\u3067\u304D\u306A\u3044\u6587\u5B57
+mark.history.number=\u756a\u53f7
+mark.history.score=\u5408\u8a08\u70b9
+mark.history.search=\u7b54\u6848\u7528\u7d19\u306e\u691c\u7d22
+mark.history.pre=\u623b\u308b
+mark.history.success=\u518d\u63a1\u70b9\u7d42\u4e86\u3000\u5408\u8a08\u70b9\uff1a
+mark.history.problem=\u518d\u63a1\u70b9\u7d42\u4e86\u3000\u63d0\u51fa\u6e08\u307f\u3000
+mark.history.loading=\u30ed\u30fc\u30c9\u4e2d\u2026
+mark.history.error=\u63a1\u70b9\u8a18\u9332\u306e\u8aad\u8fbc\u307f\u304c\u3067\u304d\u307e\u305b\u3093\u3002\u3057\u3070\u3089\u304f\u3057\u3066\u304b\u3089\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u304f\u3060\u3055\u3044
+mark.history.number.error=\u8a8d\u8b58\u3067\u304d\u306a\u3044\u6587\u5b57
 #mark-board
-mark.board.submit=\u63D0\u51FA
-mark.board.total.score=\u5408\u8A08\u70B9
-mark.board.score.zero=\u5408\u8A08\u70B9\uFF1A0
-mark.board.pass=\u30B9\u30AD\u30C3\u30D7 
-mark.board.choose.result=\u63A1\u70B9
-mark.board.keyboard=\u30AD\u30FC\u30DC\u30FC\u30C9\u63A1\u70B9 >>
-mark.board.mouse=<< \u30DE\u30A6\u30B9\u63A1\u70B9
-mark.board.interval=\u9593\u9694\u8A2D\u5B9A
-mark.board.score=\u70B9\u6570
-mark.board.back=\u623B\u308B
-mark.board.clear.question=\u90E8\u5206\u63A1\u70B9\u524A\u9664
-mark.board.clear=\u5168\u63A1\u70B9\u306E\u524A\u9664
-mark.board.question.not.mark=\u672A\u63A1\u70B9\u306E\u554F\u984C\u304C\u3042\u308A\u307E\u3059
-mark.board.confirm=,\u63D0\u51FA\u3057\u307E\u3059\u304B\uFF1F
-mark.board.zero.confirm=\u5408\u8A08\u70B9\u306F0\u3067\u3059\u3002\u63D0\u51FA\u3057\u307E\u3059\u304B\uFF1F
+mark.board.submit=\u63d0\u51fa
+mark.board.total.score=\u5408\u8a08\u70b9
+mark.board.score.zero=\u5408\u8a08\u70b9\uff1a0
+mark.board.pass=\u30b9\u30ad\u30c3\u30d7 
+mark.board.choose.result=\u63a1\u70b9
+mark.board.keyboard=\u30ad\u30fc\u30dc\u30fc\u30c9\u63a1\u70b9 >>
+mark.board.mouse=<< \u30de\u30a6\u30b9\u63a1\u70b9
+mark.board.interval=\u9593\u9694\u8a2d\u5b9a
+mark.board.score=\u70b9\u6570
+mark.board.back=\u623b\u308b
+mark.board.clear.question=\u90e8\u5206\u63a1\u70b9\u524a\u9664
+mark.board.clear=\u5168\u63a1\u70b9\u306e\u524a\u9664
+mark.board.question.not.mark=\u672a\u63a1\u70b9\u306e\u554f\u984c\u304c\u3042\u308a\u307e\u3059
+mark.board.confirm=,\u63d0\u51fa\u3057\u307e\u3059\u304b\uff1f
+mark.board.zero.confirm=\u5408\u8a08\u70b9\u306f0\u3067\u3059\u3002\u63d0\u51fa\u3057\u307e\u3059\u304b\uff1f
 mark.board.null=
-mark.board.interval.error=\u70B9\u6570\u306E\u6700\u5C0F\u9593\u9694\u3068\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093
-mark.board.gt=\u4EE5\u4E0B
-mark.board.lt=\u4EE5\u4E0A
-mark.board.number.error=\u8A8D\u8B58\u3067\u304D\u306A\u3044\u6587\u5B57
+mark.board.interval.error=\u70b9\u6570\u306e\u6700\u5c0f\u9593\u9694\u3068\u4e00\u81f4\u3057\u3066\u3044\u307e\u305b\u3093
+mark.board.gt=\u4ee5\u4e0b
+mark.board.lt=\u4ee5\u4e0a
+mark.board.number.error=\u8a8d\u8b58\u3067\u304d\u306a\u3044\u6587\u5b57
 #sheet-view
-mark.sheet=\u7B54\u6848\u7528\u7D19
-mark.sheet.check=\u7B54\u6848\u7528\u7D19\u306E\u5207\u66FF
-mark.sheet.open=\u958B\u304F
-mark.sheet.close=\u9589\u3058\u308B
+mark.sheet=\u7b54\u6848\u7528\u7d19
+mark.sheet.check=\u7b54\u6848\u7528\u7d19\u306e\u5207\u66ff
+mark.sheet.open=\u958b\u304f
+mark.sheet.close=\u9589\u3058\u308b
 #slice-view
-mark.slice=\u7B54\u6848\u7528\u7D19
-mark.slice.check=\u7B54\u6848\u7528\u7D19\u306E\u5207\u66FF
-mark.slice.open=\u958B\u304F
-mark.slice.close=\u9589\u3058\u308B
+mark.slice=\u7b54\u6848\u7528\u7d19
+mark.slice.check=\u7b54\u6848\u7528\u7d19\u306e\u5207\u66ff
+mark.slice.open=\u958b\u304f
+mark.slice.close=\u9589\u3058\u308b
 #answer-view
-mark.answer=\u6A21\u7BC4\u89E3\u7B54
+mark.answer=\u6a21\u7bc4\u89e3\u7b54
 #warning-info
-mark.warning.try.again=\u3084\u308A\u76F4\u3057\u30DC\u30BF\u30F3\u3092\u30AF\u30EA\u30C3\u30AF\u3057\u3066\u4E0B\u3055\u3044
-mark.warning.force.special.tag=\u7279\u6B8A\u8A18\u53F7\u6A5F\u80FD\u304C\u30AA\u30F3\u306B\u306A\u3063\u3066\u3044\u308B\u306E\u3067\u3001\u7279\u6B8A\u8A18\u53F7\u3092\u6700\u4F4E\u4E00\u3064\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044
-mark.warning.network.error=\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u306E\u4E0D\u5177\u5408\u304C\u751F\u3058\u305F\u305F\u3081\u3001\u63D0\u51FA\u304C\u5931\u6557\u3057\u307E\u3057\u305F
-mark.warning.task.error=\u30C7\u30FC\u30BF\u30FC\u306E\u8AAD\u8FBC\u307F\u304C\u5931\u6557\u3057\u307E\u3057\u305F
-mark.warning.task.finish=\u63A1\u70B9\u304C\u7D42\u4E86\u3057\u307E\u3057\u305F
-mark.warning.task.loading=\u7B54\u6848\u7528\u7D19\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u4E2D\u2026
-mark.warning.close=\u9589\u3058\u308B
-mark.warning.success=\u518D\u63A1\u70B9\u7D42\u4E86\u3001\u5408\u8A08\u70B9\uFF1A
-mark.warning.problem=\u554F\u984C\u3042\u308A\u306E\u7B54\u6848\u7528\u7D19\u306E\u518D\u63A1\u70B9\u7D42\u4E86
+mark.warning.try.again=\u3084\u308a\u76f4\u3057\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u4e0b\u3055\u3044
+mark.warning.force.special.tag=\u7279\u6b8a\u8a18\u53f7\u6a5f\u80fd\u304c\u30aa\u30f3\u306b\u306a\u3063\u3066\u3044\u308b\u306e\u3067\u3001\u7279\u6b8a\u8a18\u53f7\u3092\u6700\u4f4e\u4e00\u3064\u4f7f\u7528\u3057\u3066\u304f\u3060\u3055\u3044
+mark.warning.network.error=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u4e0d\u5177\u5408\u304c\u751f\u3058\u305f\u305f\u3081\u3001\u63d0\u51fa\u304c\u5931\u6557\u3057\u307e\u3057\u305f
+mark.warning.task.error=\u30c7\u30fc\u30bf\u30fc\u306e\u8aad\u8fbc\u307f\u304c\u5931\u6557\u3057\u307e\u3057\u305f
+mark.warning.task.finish=\u63a1\u70b9\u304c\u7d42\u4e86\u3057\u307e\u3057\u305f
+mark.warning.task.loading=\u7b54\u6848\u7528\u7d19\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u4e2d\u2026
+mark.warning.close=\u9589\u3058\u308b
+mark.warning.success=\u518d\u63a1\u70b9\u7d42\u4e86\u3001\u5408\u8a08\u70b9\uff1a
+mark.warning.problem=\u554f\u984c\u3042\u308a\u306e\u7b54\u6848\u7528\u7d19\u306e\u518d\u63a1\u70b9\u7d42\u4e86
 #json-view
-mark.json.loading=\u30ED\u30FC\u30C9\u4E2D\u2026
-mark.json.student.answer=\u53D7\u9A13\u8005\u306E\u56DE\u7B54\uFF1A
-mark.json.answer=\u6A21\u7BC4\u89E3\u7B54\uFF1A
-mark.json.body=\u8A66\u9A13\u554F\u984C\uFF1A
-mark.json.question.number=\u8A66\u9A13\u554F\u984C\u756A\u53F7\uFF1A
+mark.json.loading=\u30ed\u30fc\u30c9\u4e2d\u2026
+mark.json.student.answer=\u53d7\u9a13\u8005\u306e\u56de\u7b54\uff1a
+mark.json.answer=\u6a21\u7bc4\u89e3\u7b54\uff1a
+mark.json.body=\u8a66\u9a13\u554f\u984c\uff1a
+mark.json.question.number=\u8a66\u9a13\u554f\u984c\u756a\u53f7\uff1a
 
 #index
-index.user=\u30E6\u30FC\u30B6\u30FC\u7BA1\u7406
-index.exam=\u8A66\u9A13\u7BA1\u7406
-index.student=\u53D7\u9A13\u751F\u7BA1\u7406
-index.paper=\u79D1\u76EE\u7BA1\u7406
-index.scan=\u30B9\u30AD\u30E3\u30F3\u9032\u5EA6
-index.mark=\u30DE\u30FC\u30AD\u30F3\u30B0\u7BA1\u7406
-index.score=\u6210\u7E3E\u30AF\u30A8\u30EA\u30FC
-index.inspected=\u6210\u7E3E\u590D\u6838
-index.problem=\u554F\u984C\u3042\u308B\u8A66\u9A13\u7528\u7D19
-index.report.total=\u96C6\u8A08\u5206\u6790
-index.report.subject=\u79D1\u76EE\u5225\u5206\u6790
-index.check=\u30C7\u30FC\u30BF\u691C\u67FB
-index.log=\u64CD\u4F5C\u8A18\u9332
+index.user=\u30e6\u30fc\u30b6\u30fc\u7ba1\u7406
+index.exam=\u8a66\u9a13\u7ba1\u7406
+index.student=\u53d7\u9a13\u751f\u7ba1\u7406
+index.paper=\u79d1\u76ee\u7ba1\u7406
+index.scan=\u30b9\u30ad\u30e3\u30f3\u9032\u5ea6
+index.mark=\u30de\u30fc\u30ad\u30f3\u30b0\u7ba1\u7406
+index.score=\u6210\u7e3e\u30af\u30a8\u30ea\u30fc
+index.inspected=\u6210\u7e3e\u590d\u6838
+index.problem=\u554f\u984c\u3042\u308b\u8a66\u9a13\u7528\u7d19
+index.report.total=\u96c6\u8a08\u5206\u6790
+index.report.subject=\u79d1\u76ee\u5225\u5206\u6790
+index.check=\u30c7\u30fc\u30bf\u691c\u67fb
+index.log=\u64cd\u4f5c\u8a18\u9332
 
 #report.subject
-report.subject=\u96C6\u8A08\u5206\u6790
-report.subject.name=\u79D1\u76EE
-report.subject.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.subject.search=\u691C\u7D22
-report.subject.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.subject.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.subject.name=\u79D1\u76EE
-report.subject.totalCount=\u5FDC\u52DF\u8005\u6570
-report.subject.absentCount=\u6B20\u5E2D
-report.subject.breachCount=\u4E0D\u6B63\u884C\u70BA
-report.subject.realityCount=\u6709\u52B9\u8005\u6570
-report.subject.avgScore=\u5E73\u5747\u70B9
-report.subject.maxScore=\u6700\u9AD8\u70B9
-report.subject.minScore=\u6700\u4F4E\u70B9
-report.subject.passCount=\u5408\u683C\u8005\u6570
-report.subject.passRate=\u5408\u683C\u7387
+report.subject=\u96c6\u8a08\u5206\u6790
+report.subject.name=\u79d1\u76ee
+report.subject.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.subject.search=\u691c\u7d22
+report.subject.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.subject.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.subject.name=\u79d1\u76ee
+report.subject.totalCount=\u5fdc\u52df\u8005\u6570
+report.subject.absentCount=\u6b20\u5e2d
+report.subject.breachCount=\u4e0d\u6b63\u884c\u70ba
+report.subject.realityCount=\u6709\u52b9\u8005\u6570
+report.subject.avgScore=\u5e73\u5747\u70b9
+report.subject.maxScore=\u6700\u9ad8\u70b9
+report.subject.minScore=\u6700\u4f4e\u70b9
+report.subject.passCount=\u5408\u683c\u8005\u6570
+report.subject.passRate=\u5408\u683c\u7387
 #report.range
-report.range=\u70B9\u6570\u533A\u5206\u7D71\u8A08
-report.range.subject=\u79D1\u76EE
-report.range.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.range.search=\u691C\u7D22
-report.range.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.range.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.range.level=\u5B66\u6B74
+report.range=\u70b9\u6570\u533a\u5206\u7d71\u8a08
+report.range.subject=\u79d1\u76ee
+report.range.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.range.search=\u691c\u7d22
+report.range.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.range.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.range.level=\u5b66\u6b74
 report.range.proportion=\u5272\u5408
-report.range.total=\u7DCF\u4EBA\u6570
-report.range.operation=\u64CD\u4F5C\u6A5F\u80FD
-report.range.chart=\u7D71\u8A08\u56F3\u8868
+report.range.total=\u7dcf\u4eba\u6570
+report.range.operation=\u64cd\u4f5c\u6a5f\u80fd
+report.range.chart=\u7d71\u8a08\u56f3\u8868
 #report.college
-report.college=\u5B66\u90E8\u5225\u5206\u6790
-report.college.subject=\u79D1\u76EE
-report.college.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.college.search=\u691C\u7D22
-report.college.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.college.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.college.name=\u6240\u5C5E\u5B66\u90E8
-report.college.avgScore=\u5E73\u5747\u70B9
-report.college.maxScore=\u6700\u9AD8\u70B9
-report.college.minScore=\u6700\u4F4E\u70B9
-report.college.passCount=\u5408\u683C\u8005\u6570
-report.college.passRate=\u5408\u683C\u7387
-report.college.excellentRate=\u512A\u79C0\u5224\u5B9A\u7387
+report.college=\u5b66\u90e8\u5225\u5206\u6790
+report.college.subject=\u79d1\u76ee
+report.college.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.college.search=\u691c\u7d22
+report.college.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.college.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.college.name=\u6240\u5c5e\u5b66\u90e8
+report.college.avgScore=\u5e73\u5747\u70b9
+report.college.maxScore=\u6700\u9ad8\u70b9
+report.college.minScore=\u6700\u4f4e\u70b9
+report.college.passCount=\u5408\u683c\u8005\u6570
+report.college.passRate=\u5408\u683c\u7387
+report.college.excellentRate=\u512a\u79c0\u5224\u5b9a\u7387
 #report.teacher
-report.teacher=\u6559\u54E1\u306B\u3064\u3044\u3066\u306E\u8A55\u4FA1
-report.teacher.subject=\u79D1\u76EE
-report.teacher.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.teacher.search=\u691C\u7D22
-report.teacher.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.teacher.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.teacher.name=\u6559\u54E1\u540D
-report.teacher.realityCount=\u6709\u52B9\u8005\u6570
-report.teacher.passCount=\u5408\u683C
-report.teacher.excellentCount=\u512A\u79C0
-report.teacher.maxScore=\u6700\u9AD8\u70B9
-report.teacher.minScore=\u6700\u4F4E\u70B9
-report.teacher.passRate=\u5408\u683C\u7387
-report.teacher.excellentRate=\u512A\u79C0\u5224\u5B9A\u7387
-report.teacher.avgScore=\u5E73\u5747\u70B9
-report.teacher.relativeAvgScore=\u5E73\u5747\u70B9\u5DEE\u5206
-report.teacher.return=\u623B\u308B
+report.teacher=\u6559\u54e1\u306b\u3064\u3044\u3066\u306e\u8a55\u4fa1
+report.teacher.subject=\u79d1\u76ee
+report.teacher.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.teacher.search=\u691c\u7d22
+report.teacher.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.teacher.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.teacher.name=\u6559\u54e1\u540d
+report.teacher.realityCount=\u6709\u52b9\u8005\u6570
+report.teacher.passCount=\u5408\u683c
+report.teacher.excellentCount=\u512a\u79c0
+report.teacher.maxScore=\u6700\u9ad8\u70b9
+report.teacher.minScore=\u6700\u4f4e\u70b9
+report.teacher.passRate=\u5408\u683c\u7387
+report.teacher.excellentRate=\u512a\u79c0\u5224\u5b9a\u7387
+report.teacher.avgScore=\u5e73\u5747\u70b9
+report.teacher.relativeAvgScore=\u5e73\u5747\u70b9\u5dee\u5206
+report.teacher.return=\u623b\u308b
 #report.class
-report.class=\u30AF\u30E9\u30B9\u5225\u5206\u6790
-report.class.subject=\u79D1\u76EE
-report.class.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.class.search=\u691C\u7D22
-report.class.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.class.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.class.name=\u30AF\u30E9\u30B9
-report.class.avgScore=\u5E73\u5747\u70B9
-report.class.maxScore=\u6700\u9AD8\u70B9
-report.class.minScore=\u6700\u4F4E\u70B9
-report.class.passCount=\u5408\u683C\u30AF\u30E9\u30B9\u6570
-report.class.passRate=\u5408\u683C\u7387
-report.class.excellentCount=\u512A\u79C0
-report.class.excellentRate=\u512A\u79C0\u5224\u5B9A\u7387
+report.class=\u30af\u30e9\u30b9\u5225\u5206\u6790
+report.class.subject=\u79d1\u76ee
+report.class.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.class.search=\u691c\u7d22
+report.class.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.class.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.class.name=\u30af\u30e9\u30b9
+report.class.avgScore=\u5e73\u5747\u70b9
+report.class.maxScore=\u6700\u9ad8\u70b9
+report.class.minScore=\u6700\u4f4e\u70b9
+report.class.passCount=\u5408\u683c\u30af\u30e9\u30b9\u6570
+report.class.passRate=\u5408\u683c\u7387
+report.class.excellentCount=\u512a\u79c0
+report.class.excellentRate=\u512a\u79c0\u5224\u5b9a\u7387
 #report.question
-report.question.objective=\u30DE\u30FC\u30AF\u30B7\u30FC\u30C8\u5F0F\u554F\u984C\u306B\u3064\u3044\u3066\u306E\u5206\u6790
-report.question.subjective=\u8A18\u8FF0\u554F\u984C\u306B\u3064\u3044\u3066\u306E\u5206\u6790
-report.question.subject=\u79D1\u76EE
-report.question.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.question.search=\u691C\u7D22
-report.question.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.question.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.question.paperType=\u7B54\u6848\u7528\u7D19\u306E\u5206\u985E
-report.question.name=\u8A2D\u554F\u540D
-report.question.mainNumber=\u5927\u554F\u756A\u53F7
-report.question.subNumber=\u5C0F\u554F\u756A\u53F7
-report.question.score=\u914D\u70B9
-report.question.avgScore=\u5E73\u5747\u70B9
-report.question.stdev=\u6A19\u6E96\u504F\u5DEE
-report.question.scoreRate=\u6B63\u7B54\u7387
-report.question.fullScoreRate=\u6E80\u70B9\u7387
+report.question.objective=\u30de\u30fc\u30af\u30b7\u30fc\u30c8\u5f0f\u554f\u984c\u306b\u3064\u3044\u3066\u306e\u5206\u6790
+report.question.subjective=\u8a18\u8ff0\u554f\u984c\u306b\u3064\u3044\u3066\u306e\u5206\u6790
+report.question.subject=\u79d1\u76ee
+report.question.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.question.search=\u691c\u7d22
+report.question.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.question.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.question.paperType=\u7b54\u6848\u7528\u7d19\u306e\u5206\u985e
+report.question.name=\u8a2d\u554f\u540d
+report.question.mainNumber=\u5927\u554f\u756a\u53f7
+report.question.subNumber=\u5c0f\u554f\u756a\u53f7
+report.question.score=\u914d\u70b9
+report.question.avgScore=\u5e73\u5747\u70b9
+report.question.stdev=\u6a19\u6e96\u504f\u5dee
+report.question.scoreRate=\u6b63\u7b54\u7387
+report.question.fullScoreRate=\u6e80\u70b9\u7387
 #report.group
-report.group=\u5927\u554F\u306B\u3064\u3044\u3066\u306E\u5206\u6790
-report.group.subject=\u79D1\u76EE
-report.group.select=\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044
-report.group.search=\u691C\u7D22
-report.group.export=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8
-report.group.chart=\u7D71\u8A08\u56F3\u3092\u898B\u308B
-report.group.name=\u8A2D\u554F\u540D
-report.group.number=\u554F\u984C\u756A\u53F7
-report.group.totalScore=\u6E80\u70B9
-report.group.maxScore=\u6700\u9AD8\u70B9
-report.group.minScore=\u6700\u4F4E\u70B9
-report.group.avgScore=\u5E73\u5747\u70B9
-report.group.stdev=\u6A19\u6E96\u504F\u5DEE
-report.group.coefficient=\u4E0D\u7B49\u7387
-report.group.scoreRate=\u6B63\u7B54\u7387
-report.group.zeroCount=0\u70B9\u8005\u6570
-report.group.fullCount=\u6E80\u70B9\u8005\u6570
+report.group=\u5927\u554f\u306b\u3064\u3044\u3066\u306e\u5206\u6790
+report.group.subject=\u79d1\u76ee
+report.group.select=\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044
+report.group.search=\u691c\u7d22
+report.group.export=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
+report.group.chart=\u7d71\u8a08\u56f3\u3092\u898b\u308b
+report.group.name=\u8a2d\u554f\u540d
+report.group.number=\u554f\u984c\u756a\u53f7
+report.group.totalScore=\u6e80\u70b9
+report.group.maxScore=\u6700\u9ad8\u70b9
+report.group.minScore=\u6700\u4f4e\u70b9
+report.group.avgScore=\u5e73\u5747\u70b9
+report.group.stdev=\u6a19\u6e96\u504f\u5dee
+report.group.coefficient=\u4e0d\u7b49\u7387
+report.group.scoreRate=\u6b63\u7b54\u7387
+report.group.zeroCount=0\u70b9\u8005\u6570
+report.group.fullCount=\u6e80\u70b9\u8005\u6570
 #report.massage
-report.massage.school.null=\u8A72\u5F53\u5B66\u6821\u898B\u3064\u304B\u3089\u306A\u3044
+report.massage.school.null=\u8a72\u5f53\u5b66\u6821\u898b\u3064\u304b\u3089\u306a\u3044
 #head
-head.title=\u30C7\u30B8\u30BF\u30EB\u63A1\u70B9\u30B7\u30B9\u30C6\u30E0
-head.logout=\u30ED\u30B0\u30A2\u30A6\u30C8
+head.title=\u30c7\u30b8\u30bf\u30eb\u63a1\u70b9\u30b7\u30b9\u30c6\u30e0
+head.logout=\u30ed\u30b0\u30a2\u30a6\u30c8
 
 #student search
-student.search.title=\u5B66\u751F\u67E5\u8BE2\u6210\u7EE9
-student.search.code=\u756A\u53F7
-student.search.name=\u30E6\u30FC\u30B6\u30FC\u540D
-student.search.submit=\u691C\u7D22
-student.search.error=\u5B66\u6821\u4E0D\u5B58\u5728
+student.search.title=\u5b66\u751f\u67e5\u8be2\u6210\u7ee9
+student.search.code=\u756a\u53f7
+student.search.name=\u30e6\u30fc\u30b6\u30fc\u540d
+student.search.submit=\u691c\u7d22
+student.search.error=\u5b66\u6821\u4e0d\u5b58\u5728
 #student search list
-student.search.list.examName=\u8003\u8BD5\u540D\u79F0
-student.search.list.subjectName=\u8BFE\u7A0B\u540D\u79F0
-student.search.list.objectiveScore=\u5BA2\u89C2\u5206
-student.search.list.subjectiveScore=\u4E3B\u89C2\u5206
-student.search.list.totalScore=\u603B\u5206
-student.search.list.remark=\u5907\u6CE8
+student.search.list.examName=\u8003\u8bd5\u540d\u79f0
+student.search.list.subjectName=\u8bfe\u7a0b\u540d\u79f0
+student.search.list.objectiveScore=\u5ba2\u89c2\u5206
+student.search.list.subjectiveScore=\u4e3b\u89c2\u5206
+student.search.list.totalScore=\u603b\u5206
+student.search.list.remark=\u5907\u6ce8

+ 2 - 0
stmms-web/src/main/webapp/static/i18n/messages_zh.properties

@@ -5,6 +5,8 @@ user.login.marker=\u8bc4\u5377\u5458\u767b\u5f55
 user.login.name=\u8d26\u53f7
 user.login.password=\u5bc6\u7801
 user.login.submit=\u767b\u5f55
+user.login.error.auth=\u672a\u6388\u6743\u65e0\u6cd5\u767b\u5f55
+user.login.error.expire=\u6388\u6743\u5df2\u7ecf\u8fc7\u671f
 user.login.error.account=\u5e10\u53f7\u4e0d\u5b58\u5728
 user.login.error.finish=\u8bc4\u5377\u5206\u7ec4\u5df2\u7ed3\u675f
 user.login.error.group=\u5927\u9898\u4e0d\u5b58\u5728