Przeglądaj źródła

merge from release_v3.0

deason 5 lat temu
rodzic
commit
1288620b5c
26 zmienionych plików z 1588 dodań i 1149 usunięć
  1. 1 1
      examcloud-core-basic-api-provider/pom.xml
  2. 133 47
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java
  3. 1 1
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java
  4. 722 461
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/RolePrivilegeController.java
  5. 21 19
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java
  6. 12 0
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/bean/ResourceDomain.java
  7. 1 1
      examcloud-core-basic-base/pom.xml
  8. 1 1
      examcloud-core-basic-dao/pom.xml
  9. 8 1
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/PrivilegeGroupRepo.java
  10. 2 0
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/PrivilegeRepo.java
  11. 2 0
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/RootOrgPrivilegeRelationRepo.java
  12. 37 3
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/PrivilegeGroupEntity.java
  13. 72 60
      examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/ResourceEntity.java
  14. 1 1
      examcloud-core-basic-service/pom.xml
  15. 453 448
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/OrgServiceImpl.java
  16. 81 92
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/ResourceServiceImpl.java
  17. 3 0
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/RolePrivilegeServiceImpl.java
  18. 1 1
      examcloud-core-basic-starter/pom.xml
  19. 2 2
      examcloud-core-basic-starter/shell/start.sh
  20. 2 2
      examcloud-core-basic-starter/shell/stop.sh
  21. 0 1
      examcloud-core-basic-starter/shell/version
  22. 1 1
      examcloud-core-basic-starter/src/main/resources/aliyun.xml
  23. 26 2
      examcloud-core-basic-starter/src/main/resources/org-properties.xml
  24. 2 1
      examcloud-core-basic-starter/src/main/resources/security.properties
  25. 1 1
      examcloud-core-basic-starter/src/main/resources/upyun.xml
  26. 2 2
      pom.xml

+ 1 - 1
examcloud-core-basic-api-provider/pom.xml

@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 		<artifactId>examcloud-core-basic</artifactId>
-		<version>2019-SNAPSHOT</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<artifactId>examcloud-core-basic-api-provider</artifactId>
 	<packaging>jar</packaging>

+ 133 - 47
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java

@@ -1,49 +1,5 @@
 package cn.com.qmth.examcloud.core.basic.api.controller;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import javax.persistence.criteria.Predicate;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.codec.DecoderException;
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.fileupload.disk.DiskFileItem;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.domain.Sort.Direction;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.commons.CommonsMultipartFile;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-
 import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
@@ -82,7 +38,37 @@ import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ApiId;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.web.support.Naked;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.fileupload.disk.DiskFileItem;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.domain.Sort.Direction;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+
+import javax.persistence.criteria.Predicate;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.*;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * {@link StatusException} 状态码范围:001XXX<br>
@@ -702,7 +688,7 @@ public class OrgController extends ControllerSupport {
 //			req.setSiteId("orgPropertiesByOrgDomain");
 //			putFileResp = upyunCloudService.putFile(req);
 //			urlList.add(putFileResp.getUrl());
-			
+
 			//通用存储
 			YunPathInfo pi=null;
 			FileStoragePathEnvInfo env=new FileStoragePathEnvInfo();
@@ -1187,7 +1173,6 @@ public class OrgController extends ControllerSupport {
 	 * 方法注释
 	 *
 	 * @author WANGWEI
-	 * @param id
 	 * @param request
 	 * @param file
 	 * @throws IOException
@@ -1276,7 +1261,7 @@ public class OrgController extends ControllerSupport {
 //		req.setRootOrgId(orgEntity.getRootId());
 //		PutFileResp putFileResp = upyunCloudService.putFile(req);
 //		String url = putFileResp.getUrl();
-		
+
 		//通用存储
 		FileStoragePathEnvInfo env=new FileStoragePathEnvInfo();
 		env.setFileSuffix(fileSuffix);
@@ -1301,6 +1286,7 @@ public class OrgController extends ControllerSupport {
 	@GetMapping("importTemplate")
 	public void getDownloadTemplate(HttpServletResponse response) {
 		String resoucePath = PathUtil.getResoucePath("templates/subOrgImportTemplate.xlsx");
+		log.info("-------getDownloadTemplate-resoucePath="+resoucePath);
 		exportFile("学习中心导入模板.xlsx", new File(resoucePath));
 	}
 
@@ -1318,4 +1304,104 @@ public class OrgController extends ControllerSupport {
 		return map;
 	}
 
+	/**
+	 * 导入自定义菜单logo
+	 *
+	 * @author lideyin
+	 * @param request
+	 * @param file
+	 * @throws IOException
+	 */
+	@ApiOperation(value = "导入自定义菜单logo", notes = "导入自定义菜单logo")
+	@PostMapping("importCusMenuLogo/{orgId}")
+	@Transactional
+	public String importCusMenuLogo(@PathVariable Long orgId, HttpServletRequest request,
+							 @RequestParam CommonsMultipartFile file) throws IOException {
+
+		OrgEntity orgEntity = GlobalHelper.getEntity(orgRepo, orgId, OrgEntity.class);
+		if (null == orgEntity) {
+			throw new StatusException("140002", "orgEntity is null");
+		}
+
+		validateRootOrgIsolation(orgEntity.getRootId());
+
+		DiskFileItem fileItem = (DiskFileItem) file.getFileItem();
+		File storeLocation = fileItem.getStoreLocation();
+		String name = file.getOriginalFilename();
+
+		System.out.println(storeLocation.length());
+		if (999999 < storeLocation.length()) {
+			throw new StatusException("140082", "文件过大");
+		}
+
+		String fileSuffix = null;
+		if (name.endsWith(".jpg")) {
+			fileSuffix = ".jpg";
+		} else if (name.endsWith(".gif")) {
+			fileSuffix = ".gif";
+		} else if (name.endsWith(".png")) {
+			fileSuffix = ".png";
+		} else {
+			throw new StatusException("101001", "文件格式错误");
+		}
+
+		byte[] byteArray = null;
+		InputStream inputStream = null;
+		try {
+			inputStream = new FileInputStream(storeLocation);
+			byteArray = IOUtils.toByteArray(inputStream);
+		} finally {
+			IOUtils.closeQuietly(inputStream);
+		}
+
+		String hexString = Hex.encodeHexString(byteArray);
+
+		DynamicEnumManager manager = OrgProperty.getDynamicEnumManager();
+		DynamicEnum logoFile = manager.getByName("CUS_MENU_LOGO_FILE");
+		DynamicEnum logoFileSuffix = manager.getByName("CUS_MENU_LOGO_FILE_SUFFIX");
+		DynamicEnum logoFileUrl = manager.getByName("CUS_MENU_LOGO_FILE_URL");
+
+		OrgPropertyEntity fileEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId, logoFile.getId());
+		if (null == fileEntity) {
+			fileEntity = new OrgPropertyEntity();
+			fileEntity.setKeyId(logoFile.getId());
+			fileEntity.setOrgId(orgId);
+		}
+		fileEntity.setValue(hexString);
+		orgPropertyRepo.save(fileEntity);
+
+		OrgPropertyEntity fileSuffixEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId,
+				logoFileSuffix.getId());
+		if (null == fileSuffixEntity) {
+			fileSuffixEntity = new OrgPropertyEntity();
+			fileSuffixEntity.setKeyId(logoFileSuffix.getId());
+			fileSuffixEntity.setOrgId(orgId);
+		}
+		fileSuffixEntity.setValue(fileSuffix);
+		orgPropertyRepo.save(fileSuffixEntity);
+
+		String path = systemConfig.getTempDataDir() + "/cusMenuLogo/" + orgId
+				+ fileSuffixEntity.getValue();
+
+		FileUtils.copyFile(storeLocation, new File(path));
+
+		//通用存储
+		FileStoragePathEnvInfo env=new FileStoragePathEnvInfo();
+		env.setFileSuffix(fileSuffix);
+		env.setRootOrgId(orgEntity.getRootId().toString());
+		YunPathInfo pi=FileStorageUtil.saveFile("orgLogo", env, storeLocation,null);
+		String url =pi.getUrl();
+
+		OrgPropertyEntity logoFileUrlEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId,
+				logoFileUrl.getId());
+		if (null == logoFileUrlEntity) {
+			logoFileUrlEntity = new OrgPropertyEntity();
+			logoFileUrlEntity.setKeyId(logoFileUrl.getId());
+			logoFileUrlEntity.setOrgId(orgId);
+		}
+		logoFileUrlEntity.setValue(url);
+		orgPropertyRepo.save(logoFileUrlEntity);
+
+		return url;
+	}
 }

+ 1 - 1
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java

@@ -100,7 +100,7 @@ public class ResourceController extends ControllerSupport {
 			BeanUtils.copyProperties(next, bean);
 //			bean.setFileUrl(upyunFileUrl + bean.getFilePath());
 			//通用存储
-			bean.setFileUrl(FileStorageUtil.realPath(bean.getFilePath()));
+			bean.setFileUrl(FileStorageUtil.realPath(bean.getFileTreatyPath()));
 			resourceDomainList.add(bean);
 		}
 		PageInfo<ResourceDomain> ret = new PageInfo<ResourceDomain>();

+ 722 - 461
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/RolePrivilegeController.java

@@ -7,9 +7,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import cn.com.qmth.examcloud.core.basic.api.controller.bean.*;
 import org.apache.commons.collections.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Sort;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -25,16 +25,12 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
+import cn.com.qmth.examcloud.api.commons.enums.PrivilegeGroupType;
 import cn.com.qmth.examcloud.api.commons.security.bean.User;
 import cn.com.qmth.examcloud.api.commons.security.enums.RoleMeta;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
 import cn.com.qmth.examcloud.core.basic.api.bean.RoleBean;
-import cn.com.qmth.examcloud.core.basic.api.controller.bean.PrivilegeDomain;
-import cn.com.qmth.examcloud.core.basic.api.controller.bean.PrivilegeGroupDomain;
-import cn.com.qmth.examcloud.core.basic.api.controller.bean.RoleDomain;
-import cn.com.qmth.examcloud.core.basic.api.controller.bean.UpdateRolePrivilegeRelationsDomain;
-import cn.com.qmth.examcloud.core.basic.api.controller.bean.UpdateRootOrgPrivilegeRelationsDomain;
 import cn.com.qmth.examcloud.core.basic.base.constants.BasicConsts;
 import cn.com.qmth.examcloud.core.basic.dao.PrivilegeGroupRepo;
 import cn.com.qmth.examcloud.core.basic.dao.PrivilegeRepo;
@@ -52,6 +48,7 @@ import cn.com.qmth.examcloud.core.basic.service.bean.RoleInfo;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.helpers.tree.EleTreeNode;
 import cn.com.qmth.examcloud.web.helpers.tree.TreeUtil;
+import cn.com.qmth.examcloud.web.interceptor.GlobalSequenceLock;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -68,476 +65,740 @@ import io.swagger.annotations.ApiOperation;
 @RequestMapping("${$rmp.ctr.basic}/rolePrivilege")
 public class RolePrivilegeController extends ControllerSupport {
 
-	private static List<String> disabledPrivilegeCodeList = Arrays
-			.asList(new String[]{"index_privilege_group_list", "index_app_list", "index_school",
-					"school_config", "index_school_privilege_settings", "system"});
+    private static List<String> disabledPrivilegeCodeList = Arrays
+            .asList(new String[]{"index_privilege_group_list", "index_app_list", "index_school",
+                    "school_config", "index_school_privilege_settings", "system"});
 
-	@Autowired
-	PrivilegeGroupRepo privilegeGroupRepo;
-
-	@Autowired
-	PrivilegeRepo privilegeRepo;
-
-	@Autowired
-	RoleRepo roleRepo;
-
-	@Autowired
-	RolePrivilegeRelationRepo rolePrivilegeRelationRepo;
-
-	@Autowired
-	RootOrgPrivilegeRelationRepo rootOrgPrivilegeRelationRepo;
-
-	@Autowired
-	RolePrivilegeService rolePrivilegeService;
-
-	@ApiOperation(value = "查询角色", notes = "")
-	@PostMapping("getRoles")
-	public List<RoleBean> getRoles(@RequestParam Boolean includeSuperAdmin,
-			@RequestParam(required = false) Long rootOrgId) {
-		User accessUser = getAccessUser();
-
-		List<RoleEntity> roleList = roleRepo.findByRootOrgIdIsNull();
-
-		if (null != rootOrgId) {
-			validateRootOrgIsolation(rootOrgId);
-			List<RoleEntity> rootOrgRoleList = roleRepo.findByRootOrgId(rootOrgId);
-			roleList.addAll(rootOrgRoleList);
-		} else {
-			List<RoleEntity> rootOrgRoleList = roleRepo.findByRootOrgId(accessUser.getRootOrgId());
-			roleList.addAll(rootOrgRoleList);
-		}
-		List<RoleBean> roleBeanList = Lists.newArrayList();
-
-		for (RoleEntity cur : roleList) {
-
-			if ((!includeSuperAdmin) && cur.getCode().equals(RoleMeta.SUPER_ADMIN.name())) {
-				continue;
-			}
-
-			RoleBean bean = new RoleBean();
-			bean.setRoleId(cur.getId());
-			bean.setRoleName(cur.getName());
-			bean.setRoleCode(cur.getCode());
-			bean.setRootOrgId(cur.getRootOrgId());
-
-			roleBeanList.add(bean);
-		}
-
-		return roleBeanList;
-	}
-
-	@ApiOperation(value = "查询用户的权限树", notes = "")
-	@PostMapping("getUserPrivileges")
-	public List<PrivilegeDomain> getPrivileges(@RequestParam String groupCode,
-			@RequestParam boolean full) {
-
-		User accessUser = getAccessUser();
-		Long rootOrgId = accessUser.getRootOrgId();
-
-		PrivilegeGroupEntity privilegeGroup = privilegeGroupRepo.findByCode(groupCode);
-
-		if (null == privilegeGroup) {
-			throw new StatusException("002001", "groupCode is not existing");
-		}
-
-		List<Long> roleIdList = getAccessUserRoleIdList();
-
-		List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
-				.findAllByRoleIdInAndRootOrgId(roleIdList, rootOrgId);
-
-		Set<String> pIdSet = Sets.newHashSet();
-		for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
-			pIdSet.add(String.valueOf(cur.getPrivilegeId()));
-		}
-
-		List<PrivilegeEntity> privilegeList = privilegeRepo
-				.findAllByGroupIdOrderByWeightDesc(privilegeGroup.getId());
-
-		List<PrivilegeDomain> privilegeInfoList = Lists.newArrayList();
-
-		for (PrivilegeEntity cur : privilegeList) {
-			boolean hasPrivilege = pIdSet.contains(String.valueOf(cur.getId()));
-			// 超级管理员拥有所有权限
-			if (isSuperAdmin()) {
-				hasPrivilege = true;
-			} else if (disabledPrivilegeCodeList.contains(cur.getCode())) {
-				hasPrivilege = false;
-			}
-			if ((!full) && (!hasPrivilege)) {
-				continue;
-			}
-
-			PrivilegeDomain privilegeInfo = new PrivilegeDomain();
-			privilegeInfo.setHasPrivilege(hasPrivilege);
-			privilegeInfo.setCode(cur.getCode());
-			privilegeInfo.setCreationTime(cur.getCreationTime());
-			privilegeInfo.setGroupId(cur.getGroupId());
-			privilegeInfo.setGroupCode(privilegeGroup.getCode());
-			privilegeInfo.setId(cur.getId());
-			privilegeInfo.setName(cur.getName());
-			privilegeInfo.setParentId(cur.getParentId());
-			privilegeInfo.setUpdateTime(cur.getUpdateTime());
-			privilegeInfo.setDescription(cur.getDescription());
-			privilegeInfo.setWeight(cur.getWeight());
-			privilegeInfo.setExt1(cur.getExt1());
-			privilegeInfo.setExt2(cur.getExt2());
-			privilegeInfo.setExt3(cur.getExt3());
-			privilegeInfo.setExt4(cur.getExt4());
-			privilegeInfo.setExt5(cur.getExt5());
-
-			privilegeInfoList.add(privilegeInfo);
-
-		}
-
-		return privilegeInfoList;
-	}
-
-	@ApiOperation(value = "查询权限组")
-	@GetMapping("getPrivilegeGroupList")
-	public List<PrivilegeGroupDomain> getPrivilegeGroupList() {
-		Sort sort = new Sort(Sort.Direction.ASC, "id");
-		List<PrivilegeGroupEntity> list = privilegeGroupRepo.findAll(sort);
-
-		List<PrivilegeGroupDomain> ret = Lists.newArrayList();
-
-		for (PrivilegeGroupEntity cur : list) {
-			PrivilegeGroupDomain bean = new PrivilegeGroupDomain();
-			bean.setId(cur.getId());
-			bean.setCode(cur.getCode());
-			bean.setName(cur.getName());
-			bean.setExt1(cur.getExt1());
-			bean.setExt2(cur.getExt2());
-			bean.setExt3(cur.getExt3());
-			bean.setExt4(cur.getExt4());
-			bean.setExt5(cur.getExt5());
-
-			ret.add(bean);
-		}
-
-		return ret;
-	}
-
-	@ApiOperation(value = "查询权限树")
-	@GetMapping("getPrivilegeTree/{groupId}")
-	public EleTreeNode getPrivilegeTree(@PathVariable Long groupId,
-			@RequestParam(required = false) Boolean includeDisabledCodes) {
-		PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo, groupId,
-				PrivilegeGroupEntity.class);
-		List<PrivilegeEntity> privilegeList = privilegeRepo
-				.findAllByGroupIdOrderByWeightDesc(groupId);
-		EleTreeNode rootNode = new EleTreeNode(BasicConsts.ROOT_PRIVILEGE_ID, group.getName());
-
-		if (null != includeDisabledCodes && includeDisabledCodes) {
-			if (!isSuperAdmin()) {
-				throw new StatusException("012001", "非法请求");
-			}
-			TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, Lists.newArrayList());
-		} else {
-			TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, disabledPrivilegeCodeList);
-		}
-
-		return rootNode;
-	}
-
-	@ApiOperation(value = "查询顶级机构的权限ID集合")
-	@GetMapping("getRootOrgPrivilegeIdList/{rootOrgId}/{privilegeGroupId}")
-	public List<Long> getRootOrgPrivilegeIdList(@PathVariable Long rootOrgId,
-			@PathVariable Long privilegeGroupId) {
-
-		List<RootOrgPrivilegeRelationEntity> list = rootOrgPrivilegeRelationRepo
-				.findAllByRootOrgIdAndGroupId(rootOrgId, privilegeGroupId);
-
-		List<Long> pList = list.stream().map(RootOrgPrivilegeRelationEntity::getPrivilegeId)
-				.collect(Collectors.toList());
-
-		return pList;
-	}
-
-	@ApiOperation(value = "查询角色的权限ID集合")
-	@GetMapping("getPrivilegeIdList/{rootOrgId}/{roleId}")
-	public Set<Long> getPrivilegeIdList(@PathVariable Long rootOrgId, @PathVariable Long roleId) {
-		List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
-				.findAllByRoleIdAndRootOrgId(roleId, rootOrgId);
-
-		Set<Long> pIdSet = Sets.newHashSet();
-		for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
-			pIdSet.add(cur.getPrivilegeId());
-		}
-
-		return pIdSet;
-	}
-
-	@ApiOperation(value = "查询角色的权限ID集合(限制权限组)")
-	@GetMapping("getPrivilegeIdList/{rootOrgId}/{roleId}/{privilegeGroupId}")
-	public Set<Long> getPrivilegeIdList(@PathVariable Long rootOrgId, @PathVariable Long roleId,
-			@PathVariable Long privilegeGroupId) {
-		List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
-				.findAllByRoleIdAndRootOrgId(roleId, rootOrgId);
-
-		Set<Long> pIdSet = Sets.newHashSet();
-		for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
-			PrivilegeEntity privilegeEntity = GlobalHelper.getPresentEntity(privilegeRepo,
-					cur.getPrivilegeId(), PrivilegeEntity.class);
-			if (privilegeEntity.getGroupId().equals(privilegeGroupId)) {
-				pIdSet.add(cur.getPrivilegeId());
-			}
-		}
-
-		return pIdSet;
-	}
-
-	@ApiOperation(value = "更新角色权限关联")
-	@PostMapping("updateRolePrivilegeRelations")
-	@Transactional
-	public void updateRolePrivilegeRelations(@RequestBody UpdateRolePrivilegeRelationsDomain req) {
-		Long rootOrgId = Long.parseLong(req.getRootOrgId());
-		Long roleId = Long.parseLong(req.getRoleId());
-		Long privilegeGroupId = Long.parseLong(req.getPrivilegeGroupId());
-		Set<Long> privilegeIdSet = req.getPrivilegeIdSet();
-
-		User accessUser = getAccessUser();
-		Long userRootOrgId = accessUser.getRootOrgId();
-		if ((!rootOrgId.equals(userRootOrgId)) && (!isSuperAdmin())) {
-			throw new StatusException("012001", "非法请求");
-		}
-
-		rolePrivilegeService.updateRolePrivilegeRelations(rootOrgId, roleId, privilegeGroupId,
-				privilegeIdSet);
-	}
-
-	@ApiOperation(value = "更新顶级机构权限关联")
-	@PostMapping("updateRootOrgPrivilegeRelations")
-	@Transactional
-	public void updateRootOrgPrivilegeRelations(
-			@RequestBody UpdateRootOrgPrivilegeRelationsDomain req) {
-		Long rootOrgId = Long.parseLong(req.getRootOrgId());
-		Long privilegeGroupId = req.getPrivilegeGroupId();
-		Set<Long> privilegeIdSet = req.getPrivilegeIdSet();
-
-		if (!isSuperAdmin()) {
-			throw new StatusException("012601", "非法请求");
-		}
-
-		rolePrivilegeService.updateRootOrgPrivilegeRelations(rootOrgId, privilegeGroupId,
-				privilegeIdSet);
-	}
-
-	@ApiOperation(value = "增加权限")
-	@PostMapping("addPrivilege")
-	@Transactional
-	public PrivilegeEntity addPrivilege(@RequestBody PrivilegeEntity privilege) {
-
-		privilege.setName(privilege.getName().trim());
-		privilege.setCode(privilege.getCode().trim());
-		privilege.setDescription(privilege.getDescription());
-
-		if (!privilege.getCode().matches("[0-9a-zA-Z_]+")) {
-			throw new StatusException("020101", "权限编码必须由字母,数字和下划线组成");
-		}
-
-		PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo,
-				privilege.getGroupId(), PrivilegeGroupEntity.class);
-		if (null == group) {
-			throw new StatusException("020001", "权限组不存在");
-		}
-
-		if (null == privilege.getParentId()
-				|| BasicConsts.ROOT_PRIVILEGE_ID == privilege.getParentId()) {
-			privilege.setParentId(null);
-		} else {
-			PrivilegeEntity parentPrivilege = GlobalHelper.getEntity(privilegeRepo,
-					privilege.getParentId(), PrivilegeEntity.class);
-			if (null == parentPrivilege) {
-				throw new StatusException("020002", "父权限不存在");
-			}
-			if (!parentPrivilege.getGroupId().equals(privilege.getGroupId())) {
-				throw new StatusException("020003", "权限组错误");
-			}
-		}
-
-		PrivilegeEntity ret = privilegeRepo.save(privilege);
-
-		return ret;
-	}
-
-	@ApiOperation(value = "更新权限")
-	@PutMapping("updatePrivilege")
-	@Transactional
-	public PrivilegeEntity updatePrivilege(@RequestBody PrivilegeEntity privilege) {
-
-		privilege.setName(privilege.getName().trim());
-		privilege.setCode(privilege.getCode().trim());
-		privilege.setDescription(privilege.getDescription());
-		PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo,
-				privilege.getGroupId(), PrivilegeGroupEntity.class);
-		if (null == group) {
-			throw new StatusException("020001", "权限组不存在");
-		}
-
-		if (null != privilege.getParentId()) {
-			PrivilegeEntity parentPrivilege = GlobalHelper.getEntity(privilegeRepo,
-					privilege.getParentId(), PrivilegeEntity.class);
-			if (null == parentPrivilege) {
-				throw new StatusException("020002", "父权限不存在");
-			}
-			if (!parentPrivilege.getGroupId().equals(privilege.getGroupId())) {
-				throw new StatusException("020003", "权限组错误");
-			}
-		}
-
-		PrivilegeEntity ret = privilegeRepo.save(privilege);
-
-		return ret;
-	}
-
-	@ApiOperation(value = "删除权限")
-	@DeleteMapping("deletePrivilege/{id}")
-	@Transactional
-	public void deletePrivilege(@PathVariable Long id) {
-		PrivilegeEntity privilege = GlobalHelper.getEntity(privilegeRepo, id,
-				PrivilegeEntity.class);
-		if (null == privilege) {
-			throw new StatusException("020004", "权限不存在");
-		}
-
-		List<PrivilegeEntity> children = privilegeRepo.findAllByParentId(privilege.getId());
-		if (CollectionUtils.isNotEmpty(children)) {
-			throw new StatusException("020005", "存在子权限");
-		}
-
-		privilegeRepo.deleteById(id);
-		rolePrivilegeRelationRepo.deleteByPrivilegeId(id);
-	}
-
-	@ApiOperation(value = "查询权限")
-	@GetMapping("getPrivilege/{id}")
-	public PrivilegeEntity getPrivilege(@PathVariable Long id) {
-		PrivilegeEntity privilege = GlobalHelper.getEntity(privilegeRepo, id,
-				PrivilegeEntity.class);
-		if (null == privilege) {
-			throw new StatusException("020004", "权限不存在");
-		}
-		return privilege;
-	}
-
-	@ApiOperation(value = "校验权限(角色判断)")
-	@PostMapping("checkPrivileges")
-	public Map<String, Boolean> checkPrivileges(@RequestParam String privilegeCodes) {
-
-		List<String> privilegeCodeList = RegExpUtil.findAll(privilegeCodes, "[0-9A-Za-z_]+");
-
-		User accessUser = getAccessUser();
-
-		List<Long> roleIdList = getAccessUserRoleIdList();
-
-		List<PrivilegeEntity> privilegeEntityList = privilegeRepo
-				.findAllByCodeIn(privilegeCodeList);
-
-		Map<String, Boolean> ret = Maps.newHashMap();
-
-		boolean isSuperAdmin = isSuperAdmin();
-
-		for (PrivilegeEntity cur : privilegeEntityList) {
-			if (isSuperAdmin) {
-				ret.put(cur.getCode(), true);
-			} else {
-				List<RolePrivilegeRelationEntity> relationEntityList = rolePrivilegeRelationRepo
-						.findAllByRoleIdInAndRootOrgIdAndPrivilegeId(roleIdList,
-								accessUser.getRootOrgId(), cur.getId());
-				ret.put(cur.getCode(), CollectionUtils.isNotEmpty(relationEntityList));
-			}
-		}
-
-		return ret;
-	}
-
-	@ApiOperation(value = "校验权限(机构判断)")
-	@PostMapping("checkRootOrgPrivileges")
-	public Map<String, Boolean> checkRootOrgPrivileges(@RequestParam String privilegeCodes) {
-
-		List<String> privilegeCodeList = RegExpUtil.findAll(privilegeCodes, "[0-9A-Za-z_]+");
-
-		User accessUser = getAccessUser();
-
-		List<PrivilegeEntity> privilegeEntityList = privilegeRepo
-				.findAllByCodeIn(privilegeCodeList);
-
-		Map<String, Boolean> ret = Maps.newHashMap();
-
-		for (PrivilegeEntity cur : privilegeEntityList) {
-
-			Optional<RootOrgPrivilegeRelationEntity> optional = rootOrgPrivilegeRelationRepo
-					.findById(
-							new RootOrgPrivilegeRelationPK(cur.getId(), accessUser.getRootOrgId()));
-			ret.put(cur.getCode(), optional.isPresent());
-		}
-
-		return ret;
-	}
-
-	@ApiOperation(value = "添加角色")
-	@PostMapping("addRole")
-	@Transactional
-	public RoleEntity addRole(@RequestBody RoleDomain req) {
-		Long rootOrgId = req.getRootOrgId();
-		String code = req.getCode();
-		String name = req.getName();
+    @Autowired
+    PrivilegeGroupRepo privilegeGroupRepo;
+
+    @Autowired
+    PrivilegeRepo privilegeRepo;
+
+    @Autowired
+    RoleRepo roleRepo;
+
+    @Autowired
+    RolePrivilegeRelationRepo rolePrivilegeRelationRepo;
+
+    @Autowired
+    RootOrgPrivilegeRelationRepo rootOrgPrivilegeRelationRepo;
+
+    @Autowired
+    RolePrivilegeService rolePrivilegeService;
+
+    @ApiOperation(value = "查询角色", notes = "")
+    @PostMapping("getRoles")
+    public List<RoleBean> getRoles(@RequestParam Boolean includeSuperAdmin,
+                                   @RequestParam(required = false) Long rootOrgId) {
+        User accessUser = getAccessUser();
+
+        List<RoleEntity> roleList = roleRepo.findByRootOrgIdIsNull();
 
-		validateRootOrgIsolation(rootOrgId);
+        if (null != rootOrgId) {
+            validateRootOrgIsolation(rootOrgId);
+            List<RoleEntity> rootOrgRoleList = roleRepo.findByRootOrgId(rootOrgId);
+            roleList.addAll(rootOrgRoleList);
+        } else {
+            List<RoleEntity> rootOrgRoleList = roleRepo.findByRootOrgId(accessUser.getRootOrgId());
+            roleList.addAll(rootOrgRoleList);
+        }
+        List<RoleBean> roleBeanList = Lists.newArrayList();
+
+        for (RoleEntity cur : roleList) {
+
+            if ((!includeSuperAdmin) && cur.getCode().equals(RoleMeta.SUPER_ADMIN.name())) {
+                continue;
+            }
+
+            RoleBean bean = new RoleBean();
+            bean.setRoleId(cur.getId());
+            bean.setRoleName(cur.getName());
+            bean.setRoleCode(cur.getCode());
+            bean.setRootOrgId(cur.getRootOrgId());
+
+            roleBeanList.add(bean);
+        }
+
+        return roleBeanList;
+    }
+
+    @ApiOperation(value = "查询用户的权限树", notes = "")
+    @PostMapping("getUserPrivileges")
+    public List<PrivilegeDomain> getPrivileges(@RequestParam String groupCode,
+                                               @RequestParam boolean full) {
+
+        User accessUser = getAccessUser();
+        Long rootOrgId = accessUser.getRootOrgId();
+
+        PrivilegeGroupEntity privilegeGroup = privilegeGroupRepo.findByCode(groupCode);
+
+        if (null == privilegeGroup) {
+            throw new StatusException("002001", "groupCode is not existing");
+        }
+
+        List<Long> roleIdList = getAccessUserRoleIdList();
+
+        List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
+                .findAllByRoleIdInAndRootOrgId(roleIdList, rootOrgId);
+
+        Set<String> pIdSet = Sets.newHashSet();
+        for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
+            pIdSet.add(String.valueOf(cur.getPrivilegeId()));
+        }
+
+        List<PrivilegeEntity> privilegeList = privilegeRepo
+                .findAllByGroupIdOrderByWeightDesc(privilegeGroup.getId());
+
+        List<PrivilegeDomain> privilegeInfoList = Lists.newArrayList();
+
+        for (PrivilegeEntity cur : privilegeList) {
+            boolean hasPrivilege = pIdSet.contains(String.valueOf(cur.getId()));
+            // 超级管理员拥有所有权限
+            if (isSuperAdmin()) {
+                hasPrivilege = true;
+            } else if (disabledPrivilegeCodeList.contains(cur.getCode())) {
+                hasPrivilege = false;
+            }
+            if ((!full) && (!hasPrivilege)) {
+                continue;
+            }
+
+            PrivilegeDomain privilegeInfo = new PrivilegeDomain();
+            privilegeInfo.setHasPrivilege(hasPrivilege);
+            privilegeInfo.setCode(cur.getCode());
+            privilegeInfo.setCreationTime(cur.getCreationTime());
+            privilegeInfo.setGroupId(cur.getGroupId());
+            privilegeInfo.setGroupCode(privilegeGroup.getCode());
+            privilegeInfo.setId(cur.getId());
+            privilegeInfo.setName(cur.getName());
+            privilegeInfo.setParentId(cur.getParentId());
+            privilegeInfo.setUpdateTime(cur.getUpdateTime());
+            privilegeInfo.setDescription(cur.getDescription());
+            privilegeInfo.setWeight(cur.getWeight());
+            privilegeInfo.setExt1(cur.getExt1());
+            privilegeInfo.setExt2(cur.getExt2());
+            privilegeInfo.setExt3(cur.getExt3());
+            privilegeInfo.setExt4(cur.getExt4());
+            privilegeInfo.setExt5(cur.getExt5());
+
+            privilegeInfoList.add(privilegeInfo);
+
+        }
+
+        return privilegeInfoList;
+    }
+
+    @ApiOperation(value = "查询权限组")
+    @GetMapping("getPrivilegeGroupList")
+    public List<PrivilegeGroupDomain> getPrivilegeGroupList() {
+
+        List<PrivilegeGroupEntity> list = privilegeGroupRepo.findAllByRootOrgIdIsNullOrderById();
+
+        List<PrivilegeGroupDomain> ret = Lists.newArrayList();
+
+        if (null != list && !list.isEmpty()) {
+            list = list.stream().filter(p -> PrivilegeGroupType.STUDENT_CLIENT_MENU != p.getType())
+                    .collect(Collectors.toList());
+        }
+
+        for (PrivilegeGroupEntity cur : list) {
+            PrivilegeGroupDomain bean = new PrivilegeGroupDomain();
+            bean.setId(cur.getId());
+            bean.setCode(cur.getCode());
+            bean.setName(cur.getName());
+            bean.setExt1(cur.getExt1());
+            bean.setExt2(cur.getExt2());
+            bean.setExt3(cur.getExt3());
+            bean.setExt4(cur.getExt4());
+            bean.setExt5(cur.getExt5());
+
+            ret.add(bean);
+        }
+
+        return ret;
+    }
+
+    @ApiOperation(value = "查询权限树")
+    @GetMapping("getPrivilegeTree/{groupId}")
+    public EleTreeNode getPrivilegeTree(@PathVariable Long groupId,
+                                        @RequestParam(required = false) Boolean includeDisabledCodes) {
+        PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo, groupId,
+                PrivilegeGroupEntity.class);
+        List<PrivilegeEntity> privilegeList = privilegeRepo
+                .findAllByGroupIdOrderByWeightDesc(groupId);
+        EleTreeNode rootNode = new EleTreeNode(BasicConsts.ROOT_PRIVILEGE_ID, group.getName());
+
+        if (null != includeDisabledCodes && includeDisabledCodes) {
+            if (!isSuperAdmin()) {
+                throw new StatusException("012001", "非法请求");
+            }
+            TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, Lists.newArrayList());
+        } else {
+            TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, disabledPrivilegeCodeList);
+        }
+
+        return rootNode;
+    }
+
+    @ApiOperation(value = "查询顶级机构的权限ID集合")
+    @GetMapping("getRootOrgPrivilegeIdList/{rootOrgId}/{privilegeGroupId}")
+    public List<Long> getRootOrgPrivilegeIdList(@PathVariable Long rootOrgId,
+                                                @PathVariable Long privilegeGroupId) {
+
+        List<RootOrgPrivilegeRelationEntity> list = rootOrgPrivilegeRelationRepo
+                .findAllByRootOrgIdAndGroupId(rootOrgId, privilegeGroupId);
+
+        List<Long> pList = list.stream().map(RootOrgPrivilegeRelationEntity::getPrivilegeId)
+                .collect(Collectors.toList());
+
+        return pList;
+    }
+
+    /**
+     * 2020年2月19日
+     *
+     * @param rootOrgId
+     * @param includeDisabledCodes
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "查询菜单树")
+    @GetMapping("getStudentClientMenuTree/{rootOrgId}")
+    @GlobalSequenceLock
+    @Transactional
+    public OrgPrivilegeTreeDomain getStudentClientMenuTree(@PathVariable Long rootOrgId,
+                                                           @RequestParam(required = false) Boolean includeDisabledCodes) {
+
+        PrivilegeGroupEntity group = privilegeGroupRepo.findByRootOrgIdAndType(rootOrgId,
+                PrivilegeGroupType.STUDENT_CLIENT_MENU);
+
+        //如果考生自定义菜单未初始化,默认初始化一份
+        if (null == group) {
+            PrivilegeGroupEntity globalGroup = privilegeGroupRepo
+                    .findByCode(PrivilegeGroupType.STUDENT_CLIENT_MENU.name());
+
+            group = new PrivilegeGroupEntity();
+            group.setCode(PrivilegeGroupType.STUDENT_CLIENT_MENU.name() + "_" + rootOrgId);
+            group.setName(globalGroup.getName());
+            group.setRootOrgId(rootOrgId);
+            group.setType(PrivilegeGroupType.STUDENT_CLIENT_MENU);
+
+            group.setExt1(globalGroup.getExt1());
+            group.setExt2(globalGroup.getExt2());
+            group.setExt3(globalGroup.getExt3());
+            group.setExt4(globalGroup.getExt4());
+            group.setExt5(globalGroup.getExt5());
+
+            group = privilegeGroupRepo.save(group);
+
+            List<PrivilegeEntity> globalPrivilegeList = privilegeRepo
+                    .findAllByGroupIdOrderByWeightDesc(globalGroup.getId());
+            Map<Long, Integer> idIndex = Maps.newHashMap();
+            List<PrivilegeEntity> privilegeList = Lists.newArrayList();
+            Set<Long> privilegeIdSet = Sets.newHashSet();
+            int c = 0;
+            for (PrivilegeEntity cur : globalPrivilegeList) {
+                idIndex.put(cur.getId(), c);
+                c++;
+
+                PrivilegeEntity privilegeEntity = new PrivilegeEntity();
+                privilegeEntity.setCode(cur.getCode() + "_" + rootOrgId);
+                privilegeEntity.setDescription(cur.getDescription());
+                privilegeEntity.setGroupId(group.getId());
+                privilegeEntity.setName(cur.getName());
+                privilegeEntity.setWeight(cur.getWeight());
+
+                privilegeEntity.setExt1(cur.getExt1());
+                privilegeEntity.setExt2(cur.getExt2());
+                privilegeEntity.setExt3(cur.getExt3());
+                privilegeEntity.setExt4(cur.getExt4());
+                privilegeEntity.setExt5(cur.getExt5());
+
+                PrivilegeEntity saved = privilegeRepo.save(privilegeEntity);
+                privilegeList.add(saved);
+
+                privilegeIdSet.add(saved.getId());
+
+            }
+
+            for (int i = 0; i < globalPrivilegeList.size(); i++) {
+                PrivilegeEntity p = privilegeList.get(i);
+                if (null == p.getParentId()) {
+                    continue;
+                }
+
+                Integer j = idIndex.get(globalPrivilegeList.get(i).getId());
+                p.setParentId(privilegeList.get(j).getId());
+                privilegeRepo.save(p);
+            }
+
+            rolePrivilegeService.updateRootOrgPrivilegeRelations(rootOrgId, group.getId(),
+                    privilegeIdSet);
+        }
+
+        List<PrivilegeEntity> privilegeList = privilegeRepo
+                .findAllByGroupIdOrderByWeightDesc(group.getId());
+
+        EleTreeNode rootNode = new EleTreeNode(BasicConsts.ROOT_PRIVILEGE_ID, group.getName());
+
+        if (null != includeDisabledCodes && includeDisabledCodes) {
+            if (!isSuperAdmin()) {
+                throw new StatusException("012001", "非法请求");
+            }
+            TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, Lists.newArrayList());
+        } else {
+            TreeUtil.convert2OneEleTreeNode(rootNode, privilegeList, disabledPrivilegeCodeList);
+        }
+
+        OrgPrivilegeTreeDomain domain = new OrgPrivilegeTreeDomain();
+        domain.setPrivilegeGroupId(group.getId());
+        domain.setPrivilegeGroupType(group.getType().name());
+        domain.setTreeData(rootNode);
+
+        List<RootOrgPrivilegeRelationEntity> roprlist = rootOrgPrivilegeRelationRepo
+                .findAllByRootOrgIdAndGroupId(rootOrgId, group.getId());
+
+        List<Long> pList = roprlist.stream().map(RootOrgPrivilegeRelationEntity::getPrivilegeId)
+                .collect(Collectors.toList());
+
+        domain.setOwnedPrivilegeIds(pList);
+
+        return domain;
+    }
+
+    /**
+     * 2020年2月11日
+     *
+     * @param rootOrgId
+     * @return
+     * @author WANGWEI
+     */
+    @ApiOperation(value = "查询学生端菜单")
+    @GetMapping("getStudentClientMenu")
+    public List<CustomPrivilegeDomain> getStudentClientMenu(
+            @RequestParam(required = false) Long rootOrgId) {
+
+        if (null == rootOrgId) {
+            rootOrgId = getRootOrgId();
+        } else {
+            validateRootOrgIsolation(rootOrgId);
+        }
+
+        String code = PrivilegeGroupType.STUDENT_CLIENT_MENU.name() + "_" + rootOrgId;
+
+        boolean undefined = false;
+
+        PrivilegeGroupEntity privilegeGroup = privilegeGroupRepo.findByCode(code);
+
+        if (null == privilegeGroup) {
+            privilegeGroup = privilegeGroupRepo
+                    .findByCode(PrivilegeGroupType.STUDENT_CLIENT_MENU.name());
+            undefined = true;
+        } else {
+            if (null == privilegeGroup.getRootOrgId()) {
+                throw new StatusException("002101", "data error");
+            }
+            GlobalHelper.uniformRootOrg(rootOrgId, privilegeGroup.getRootOrgId());
+        }
+
+        List<Long> pList = null;
+        if (!undefined) {
+            List<RootOrgPrivilegeRelationEntity> list = rootOrgPrivilegeRelationRepo
+                    .findAllByRootOrgIdAndGroupId(rootOrgId, privilegeGroup.getId());
+
+            pList = list.stream().map(RootOrgPrivilegeRelationEntity::getPrivilegeId)
+                    .collect(Collectors.toList());
+        }
+
+        List<PrivilegeEntity> privilegeList = privilegeRepo
+                .findAllByGroupId(privilegeGroup.getId());
+
+        List<CustomPrivilegeDomain> privilegeInfoList = Lists.newArrayList();
+
+        for (PrivilegeEntity cur : privilegeList) {
+            boolean hasPrivilege = undefined ? true : (pList != null && pList.contains(cur.getId()));
+
+            if (!hasPrivilege) {
+                continue;
+            }
+
+            CustomPrivilegeDomain privilegeInfo = new CustomPrivilegeDomain();
+            privilegeInfo.setHasPrivilege(hasPrivilege);
+            privilegeInfo.setCode(cur.getCode());
+            privilegeInfo.setCreationTime(cur.getCreationTime());
+            privilegeInfo.setGroupId(cur.getGroupId());
+            privilegeInfo.setGroupCode(privilegeGroup.getCode());
+            privilegeInfo.setId(cur.getId());
+            privilegeInfo.setName(cur.getName());
+            privilegeInfo.setParentId(cur.getParentId());
+            privilegeInfo.setUpdateTime(cur.getUpdateTime());
+            privilegeInfo.setDescription(cur.getDescription());
+            privilegeInfo.setWeight(cur.getWeight());
+            privilegeInfo.setExt1(cur.getExt1());
+            privilegeInfo.setExt2(cur.getExt2());
+            privilegeInfo.setExt3(cur.getExt3());
+            privilegeInfo.setExt4(cur.getExt4());
+            privilegeInfo.setExt5(cur.getExt5());
+
+            //如果未自定义过菜单,则routeCode和权限编码一致
+            String routeCode;
+            if (undefined) {
+                routeCode = cur.getCode();
+            }
+            //如果自定义过菜单,则特殊处理
+            else {
+                routeCode = cur.getCode().replace("_" + rootOrgId, "");
+            }
+            privilegeInfo.setRouteCode(routeCode);
+
+            privilegeInfoList.add(privilegeInfo);
+
+        }
+
+        return privilegeInfoList;
+    }
+
+    @ApiOperation(value = "查询角色的权限ID集合")
+    @GetMapping("getPrivilegeIdList/{rootOrgId}/{roleId}")
+    public Set<Long> getPrivilegeIdList(@PathVariable Long rootOrgId, @PathVariable Long roleId) {
+        List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
+                .findAllByRoleIdAndRootOrgId(roleId, rootOrgId);
+
+        Set<Long> pIdSet = Sets.newHashSet();
+        for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
+            pIdSet.add(cur.getPrivilegeId());
+        }
+
+        return pIdSet;
+    }
+
+    @ApiOperation(value = "查询角色的权限ID集合(限制权限组)")
+    @GetMapping("getPrivilegeIdList/{rootOrgId}/{roleId}/{privilegeGroupId}")
+    public Set<Long> getPrivilegeIdList(@PathVariable Long rootOrgId, @PathVariable Long roleId,
+                                        @PathVariable Long privilegeGroupId) {
+        List<RolePrivilegeRelationEntity> rolePrivRelationList = rolePrivilegeRelationRepo
+                .findAllByRoleIdAndRootOrgId(roleId, rootOrgId);
+
+        Set<Long> pIdSet = Sets.newHashSet();
+        for (RolePrivilegeRelationEntity cur : rolePrivRelationList) {
+            PrivilegeEntity privilegeEntity = GlobalHelper.getPresentEntity(privilegeRepo,
+                    cur.getPrivilegeId(), PrivilegeEntity.class);
+            if (privilegeEntity.getGroupId().equals(privilegeGroupId)) {
+                pIdSet.add(cur.getPrivilegeId());
+            }
+        }
+
+        return pIdSet;
+    }
+
+    @ApiOperation(value = "更新角色权限关联")
+    @PostMapping("updateRolePrivilegeRelations")
+    @Transactional
+    public void updateRolePrivilegeRelations(@RequestBody UpdateRolePrivilegeRelationsDomain req) {
+        Long rootOrgId = Long.parseLong(req.getRootOrgId());
+        Long roleId = Long.parseLong(req.getRoleId());
+        Long privilegeGroupId = Long.parseLong(req.getPrivilegeGroupId());
+        Set<Long> privilegeIdSet = req.getPrivilegeIdSet();
+
+        User accessUser = getAccessUser();
+        Long userRootOrgId = accessUser.getRootOrgId();
+        if ((!rootOrgId.equals(userRootOrgId)) && (!isSuperAdmin())) {
+            throw new StatusException("012001", "非法请求");
+        }
+
+        rolePrivilegeService.updateRolePrivilegeRelations(rootOrgId, roleId, privilegeGroupId,
+                privilegeIdSet);
+    }
+
+    @ApiOperation(value = "更新顶级机构权限关联")
+    @PostMapping("updateRootOrgPrivilegeRelations")
+    @Transactional
+    public void updateRootOrgPrivilegeRelations(
+            @RequestBody UpdateRootOrgPrivilegeRelationsDomain req) {
+        Long rootOrgId = Long.parseLong(req.getRootOrgId());
+        Long privilegeGroupId = req.getPrivilegeGroupId();
+        Set<Long> privilegeIdSet = req.getPrivilegeIdSet();
+
+        User accessUser = getAccessUser();
+        Long userRootOrgId = accessUser.getRootOrgId();
+        if ((!rootOrgId.equals(userRootOrgId)) && !isSuperAdmin()) {
+            throw new StatusException("012601", "非法请求");
+        }
+
+        rolePrivilegeService.updateRootOrgPrivilegeRelations(rootOrgId, privilegeGroupId,
+                privilegeIdSet);
+    }
+
+    @ApiOperation(value = "增加权限")
+    @PostMapping("addPrivilege")
+    @Transactional
+    public PrivilegeEntity addPrivilege(@RequestBody PrivilegeEntity privilege) {
+
+        privilege.setName(privilege.getName().trim());
+        privilege.setCode(privilege.getCode().trim());
+        privilege.setDescription(privilege.getDescription());
+
+        if (!privilege.getCode().matches("[0-9a-zA-Z_]+")) {
+            throw new StatusException("020101", "权限编码必须由字母,数字和下划线组成");
+        }
+
+        PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo,
+                privilege.getGroupId(), PrivilegeGroupEntity.class);
+        if (null == group) {
+            throw new StatusException("020001", "权限组不存在");
+        }
+
+        if (null == privilege.getParentId()
+                || BasicConsts.ROOT_PRIVILEGE_ID == privilege.getParentId()) {
+            privilege.setParentId(null);
+        } else {
+            PrivilegeEntity parentPrivilege = GlobalHelper.getEntity(privilegeRepo,
+                    privilege.getParentId(), PrivilegeEntity.class);
+            if (null == parentPrivilege) {
+                throw new StatusException("020002", "父权限不存在");
+            }
+            if (!parentPrivilege.getGroupId().equals(privilege.getGroupId())) {
+                throw new StatusException("020003", "权限组错误");
+            }
+        }
+
+        PrivilegeEntity ret = privilegeRepo.save(privilege);
+
+        return ret;
+    }
+
+    @ApiOperation(value = "更新权限")
+    @PutMapping("updatePrivilege")
+    @Transactional
+    public PrivilegeEntity updatePrivilege(@RequestBody PrivilegeEntity privilege) {
+
+        privilege.setName(privilege.getName().trim());
+        privilege.setCode(privilege.getCode().trim());
+        privilege.setDescription(privilege.getDescription());
+        PrivilegeGroupEntity group = GlobalHelper.getEntity(privilegeGroupRepo,
+                privilege.getGroupId(), PrivilegeGroupEntity.class);
+        if (null == group) {
+            throw new StatusException("020001", "权限组不存在");
+        }
+
+        if (null != privilege.getParentId()) {
+            PrivilegeEntity parentPrivilege = GlobalHelper.getEntity(privilegeRepo,
+                    privilege.getParentId(), PrivilegeEntity.class);
+            if (null == parentPrivilege) {
+                throw new StatusException("020002", "父权限不存在");
+            }
+            if (!parentPrivilege.getGroupId().equals(privilege.getGroupId())) {
+                throw new StatusException("020003", "权限组错误");
+            }
+        }
+
+        privilege = privilegeRepo.save(privilege);
+
+        if (group.getType().equals(PrivilegeGroupType.STUDENT_CLIENT_MENU)
+                && group.getCode().equals(PrivilegeGroupType.STUDENT_CLIENT_MENU.name())) {
+
+            List<PrivilegeGroupEntity> gList = privilegeGroupRepo
+                    .findAllByType(PrivilegeGroupType.STUDENT_CLIENT_MENU);
+
+            for (PrivilegeGroupEntity cur : gList) {
+                if (null == cur.getRootOrgId()) {
+                    continue;
+                }
+                PrivilegeEntity p = privilegeRepo
+                        .findByCode(privilege.getCode() + "_" + cur.getRootOrgId());
+                if (null != p) {
+                    p.setDescription(privilege.getDescription());
+
+                    p.setExt1(privilege.getExt1());
+                    p.setExt2(privilege.getExt2());
+                    p.setExt3(privilege.getExt3());
+                    p.setExt4(privilege.getExt4());
+                    p.setExt5(privilege.getExt5());
+
+                    privilegeRepo.save(p);
+                }
+            }
+
+        }
+
+        return privilege;
+    }
+
+    @ApiOperation(value = "删除权限")
+    @DeleteMapping("deletePrivilege/{id}")
+    @Transactional
+    public void deletePrivilege(@PathVariable Long id) {
+        PrivilegeEntity privilege = GlobalHelper.getEntity(privilegeRepo, id,
+                PrivilegeEntity.class);
+        if (null == privilege) {
+            throw new StatusException("020004", "权限不存在");
+        }
+
+        List<PrivilegeEntity> children = privilegeRepo.findAllByParentId(privilege.getId());
+        if (CollectionUtils.isNotEmpty(children)) {
+            throw new StatusException("020005", "存在子权限");
+        }
+
+        privilegeRepo.deleteById(id);
+        rolePrivilegeRelationRepo.deleteByPrivilegeId(id);
+        rootOrgPrivilegeRelationRepo.deleteByPrivilegeId(id);
+
+        PrivilegeGroupEntity groupEntity = GlobalHelper.getPresentEntity(privilegeGroupRepo,
+                privilege.getGroupId(), PrivilegeGroupEntity.class);
+
+        if (groupEntity.getType().equals(PrivilegeGroupType.STUDENT_CLIENT_MENU)
+                && groupEntity.getCode().equals(PrivilegeGroupType.STUDENT_CLIENT_MENU.name())) {
+
+            List<PrivilegeGroupEntity> gList = privilegeGroupRepo
+                    .findAllByType(PrivilegeGroupType.STUDENT_CLIENT_MENU);
+
+            for (PrivilegeGroupEntity cur : gList) {
+                if (null == cur.getRootOrgId()) {
+                    continue;
+                }
+                PrivilegeEntity p = privilegeRepo
+                        .findByCode(privilege.getCode() + "_" + cur.getRootOrgId());
+                if (null != p) {
+                    privilegeRepo.deleteById(p.getId());
+                    rolePrivilegeRelationRepo.deleteByPrivilegeId(p.getId());
+                    rootOrgPrivilegeRelationRepo.deleteByPrivilegeId(p.getId());
+                }
+            }
+
+        }
+
+    }
+
+    @ApiOperation(value = "查询权限")
+    @GetMapping("getPrivilege/{id}")
+    public PrivilegeEntity getPrivilege(@PathVariable Long id) {
+        PrivilegeEntity privilege = GlobalHelper.getEntity(privilegeRepo, id,
+                PrivilegeEntity.class);
+        if (null == privilege) {
+            throw new StatusException("020004", "权限不存在");
+        }
+        return privilege;
+    }
+
+    @ApiOperation(value = "校验权限(角色判断)")
+    @PostMapping("checkPrivileges")
+    public Map<String, Boolean> checkPrivileges(@RequestParam String privilegeCodes) {
+
+        List<String> privilegeCodeList = RegExpUtil.findAll(privilegeCodes, "[0-9A-Za-z_]+");
+
+        User accessUser = getAccessUser();
+
+        List<Long> roleIdList = getAccessUserRoleIdList();
+
+        List<PrivilegeEntity> privilegeEntityList = privilegeRepo
+                .findAllByCodeIn(privilegeCodeList);
+
+        Map<String, Boolean> ret = Maps.newHashMap();
+
+        boolean isSuperAdmin = isSuperAdmin();
+
+        for (PrivilegeEntity cur : privilegeEntityList) {
+            if (isSuperAdmin) {
+                ret.put(cur.getCode(), true);
+            } else {
+                List<RolePrivilegeRelationEntity> relationEntityList = rolePrivilegeRelationRepo
+                        .findAllByRoleIdInAndRootOrgIdAndPrivilegeId(roleIdList,
+                                accessUser.getRootOrgId(), cur.getId());
+                ret.put(cur.getCode(), CollectionUtils.isNotEmpty(relationEntityList));
+            }
+        }
+
+        return ret;
+    }
+
+    @ApiOperation(value = "校验权限(机构判断)")
+    @PostMapping("checkRootOrgPrivileges")
+    public Map<String, Boolean> checkRootOrgPrivileges(@RequestParam String privilegeCodes) {
 
-		RoleEntity roleByCode = roleRepo.findByCode(code);
-		if (null != roleByCode) {
-			throw new StatusException("620001", "角色编码已被占用");
-		}
+        List<String> privilegeCodeList = RegExpUtil.findAll(privilegeCodes, "[0-9A-Za-z_]+");
 
-		RoleEntity roleByName = roleRepo.findByNameAndRootOrgId(name, rootOrgId);
-		if (null != roleByName) {
-			throw new StatusException("620002", "角色名称已被占用");
-		}
+        User accessUser = getAccessUser();
 
-		RoleInfo info = new RoleInfo();
-		info.setCode(code);
-		info.setName(name);
-		info.setRootOrgId(rootOrgId);
+        List<PrivilegeEntity> privilegeEntityList = privilegeRepo
+                .findAllByCodeIn(privilegeCodeList);
+
+        Map<String, Boolean> ret = Maps.newHashMap();
+
+        for (PrivilegeEntity cur : privilegeEntityList) {
+
+            Optional<RootOrgPrivilegeRelationEntity> optional = rootOrgPrivilegeRelationRepo
+                    .findById(
+                            new RootOrgPrivilegeRelationPK(cur.getId(), accessUser.getRootOrgId()));
+            ret.put(cur.getCode(), optional.isPresent());
+        }
 
-		RoleEntity saved = rolePrivilegeService.saveRole(info);
+        return ret;
+    }
 
-		return saved;
-	}
+    @ApiOperation(value = "添加角色")
+    @PostMapping("addRole")
+    @Transactional
+    public RoleEntity addRole(@RequestBody RoleDomain req) {
+        Long rootOrgId = req.getRootOrgId();
+        String code = req.getCode();
+        String name = req.getName();
 
-	@ApiOperation(value = "更新角色")
-	@PutMapping("updateRole")
-	@Transactional
-	public RoleEntity updateRole(@RequestBody RoleDomain req) {
-		Long rootOrgId = req.getRootOrgId();
-		String code = req.getCode();
-		String name = req.getName();
+        validateRootOrgIsolation(rootOrgId);
 
-		validateRootOrgIsolation(rootOrgId);
+        RoleEntity roleByCode = roleRepo.findByCode(code);
+        if (null != roleByCode) {
+            throw new StatusException("620001", "角色编码已被占用");
+        }
 
-		RoleInfo info = new RoleInfo();
-		info.setCode(code);
-		info.setName(name);
-		info.setRootOrgId(rootOrgId);
+        RoleEntity roleByName = roleRepo.findByNameAndRootOrgId(name, rootOrgId);
+        if (null != roleByName) {
+            throw new StatusException("620002", "角色名称已被占用");
+        }
 
-		RoleEntity saved = rolePrivilegeService.saveRole(info);
+        RoleInfo info = new RoleInfo();
+        info.setCode(code);
+        info.setName(name);
+        info.setRootOrgId(rootOrgId);
 
-		return saved;
-	}
+        RoleEntity saved = rolePrivilegeService.saveRole(info);
 
-	@ApiOperation(value = "删除角色")
-	@DeleteMapping("deleteRole/{roleId}")
-	@Transactional
-	public RoleEntity deleteRole(@PathVariable Long roleId) {
-		User accessUser = getAccessUser();
+        return saved;
+    }
 
-		RoleInfo info = new RoleInfo();
-		info.setId(roleId);
-		info.setRootOrgId(accessUser.getRootOrgId());
+    @ApiOperation(value = "更新角色")
+    @PutMapping("updateRole")
+    @Transactional
+    public RoleEntity updateRole(@RequestBody RoleDomain req) {
+        Long rootOrgId = req.getRootOrgId();
+        String code = req.getCode();
+        String name = req.getName();
 
-		RoleEntity saved = rolePrivilegeService.deleteRole(info, false);
+        validateRootOrgIsolation(rootOrgId);
 
-		return saved;
-	}
+        RoleInfo info = new RoleInfo();
+        info.setCode(code);
+        info.setName(name);
+        info.setRootOrgId(rootOrgId);
+
+        RoleEntity saved = rolePrivilegeService.saveRole(info);
+
+        return saved;
+    }
+
+    @ApiOperation(value = "删除角色")
+    @DeleteMapping("deleteRole/{roleId}")
+    @Transactional
+    public RoleEntity deleteRole(@PathVariable Long roleId) {
+        User accessUser = getAccessUser();
+
+        RoleInfo info = new RoleInfo();
+        info.setId(roleId);
+        info.setRootOrgId(accessUser.getRootOrgId());
+
+        RoleEntity saved = rolePrivilegeService.deleteRole(info, false);
+
+        return saved;
+    }
 
 }

+ 21 - 19
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java

@@ -102,12 +102,13 @@ public class StudentController extends ControllerSupport {
      */
     @ApiOperation(value = "查询学生分页数据", notes = "分页")
     @GetMapping("studentPage/{curPage}/{pageSize}")
-    public PageInfo<StudentDomain> getStudentPage(@PathVariable Integer curPage,
-                                                  @PathVariable Integer pageSize, @RequestParam String name,
-                                                  @RequestParam String studentCode, @RequestParam String identityNumber,
-                                                  @RequestParam(required = false) Long rootOrgId,
-                                                  @RequestParam(required = false) Long orgId,
-                                                  @RequestParam(required = false) BooleanSelect hasPhoto) {
+    public PageInfo<StudentDomain> getStudentPage(
+            @PathVariable Integer curPage,
+            @PathVariable Integer pageSize, @RequestParam String name,
+            @RequestParam String studentCode, @RequestParam String identityNumber,
+            @RequestParam(required = false) Long rootOrgId,
+            @RequestParam(required = false) Long orgId,
+            @RequestParam(required = false) BooleanSelect hasPhoto) {
 
         User accessUser = getAccessUser();
         if (null == rootOrgId) {
@@ -125,10 +126,10 @@ public class StudentController extends ControllerSupport {
             if (StringUtils.isNotEmpty(name)) {
                 predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
             }
-            if (StringUtils.isNotEmpty(identityNumber)) {
-                predicates.add(
-                        cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
+            if (StringUtils.isNotBlank(identityNumber)) {
+                predicates.add(cb.like(root.get("identityNumber"), toSqlRightLike(identityNumber)));
             }
+
             if (null != hasPhoto) {
                 Boolean hasPhotoBoolean = hasPhoto.getBoolean();
                 if (null != hasPhotoBoolean) {
@@ -140,12 +141,12 @@ public class StudentController extends ControllerSupport {
                 }
             }
 
-            if (StringUtils.isNotEmpty(studentCode)) {
+            if (StringUtils.isNotBlank(studentCode)) {
                 Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
                 Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
                 subquery.select(subRoot.get("id"));
                 Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
-                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
+                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlRightLike(studentCode));
                 subquery.where(cb.and(p1, p2));
                 predicates.add(cb.exists(subquery));
             }
@@ -246,13 +247,14 @@ public class StudentController extends ControllerSupport {
         ret.setList(studentDomainList);
         ret.setTotal(studentList.getTotalElements());
         return ret;
-
     }
 
     @ApiOperation(value = "导出学生", notes = "")
     @GetMapping("export")
-    public void exportStudents(@RequestParam String name, @RequestParam String studentCode,
-                               @RequestParam String identityNumber, @RequestParam(required = false) Long rootOrgId,
+    public void exportStudents(@RequestParam String name,
+                               @RequestParam String studentCode,
+                               @RequestParam String identityNumber,
+                               @RequestParam(required = false) Long rootOrgId,
                                @RequestParam(required = false) Long orgId,
                                @RequestParam(required = false) BooleanSelect hasPhoto) {
 
@@ -272,10 +274,10 @@ public class StudentController extends ControllerSupport {
             if (StringUtils.isNotEmpty(name)) {
                 predicates.add(cb.like(root.get("name"), toSqlSearchPattern(name)));
             }
-            if (StringUtils.isNotEmpty(identityNumber)) {
-                predicates.add(
-                        cb.like(root.get("identityNumber"), toSqlSearchPattern(identityNumber)));
+            if (StringUtils.isNotBlank(identityNumber)) {
+                predicates.add(cb.like(root.get("identityNumber"), toSqlRightLike(identityNumber)));
             }
+
             if (null != hasPhoto) {
                 Boolean hasPhotoBoolean = hasPhoto.getBoolean();
                 if (null != hasPhotoBoolean) {
@@ -287,12 +289,12 @@ public class StudentController extends ControllerSupport {
                 }
             }
 
-            if (StringUtils.isNotEmpty(studentCode)) {
+            if (StringUtils.isNotBlank(studentCode)) {
                 Subquery<StudentCodeEntity> subquery = query.subquery(StudentCodeEntity.class);
                 Root<StudentCodeEntity> subRoot = subquery.from(StudentCodeEntity.class);
                 subquery.select(subRoot.get("id"));
                 Predicate p1 = cb.equal(subRoot.get("studentId"), root.get("id"));
-                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlSearchPattern(studentCode));
+                Predicate p2 = cb.like(subRoot.get("studentCode"), toSqlRightLike(studentCode));
                 subquery.where(cb.and(p1, p2));
                 predicates.add(cb.exists(subquery));
             }

+ 12 - 0
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/bean/ResourceDomain.java

@@ -25,6 +25,8 @@ public class ResourceDomain implements JsonSerializable {
 	private Long parentId;
 
 	private Date creationTime;
+	
+	private String fileTreatyPath;
 
 	public Long getId() {
 		return id;
@@ -98,4 +100,14 @@ public class ResourceDomain implements JsonSerializable {
 		this.creationTime = creationTime;
 	}
 
+    
+    public String getFileTreatyPath() {
+        return fileTreatyPath;
+    }
+
+    
+    public void setFileTreatyPath(String fileTreatyPath) {
+        this.fileTreatyPath = fileTreatyPath;
+    }
+
 }

+ 1 - 1
examcloud-core-basic-base/pom.xml

@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 		<artifactId>examcloud-core-basic</artifactId>
-		<version>2019-SNAPSHOT</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<artifactId>examcloud-core-basic-base</artifactId>
 

+ 1 - 1
examcloud-core-basic-dao/pom.xml

@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 		<artifactId>examcloud-core-basic</artifactId>
-		<version>2019-SNAPSHOT</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<artifactId>examcloud-core-basic-dao</artifactId>
 

+ 8 - 1
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/PrivilegeGroupRepo.java

@@ -1,9 +1,12 @@
 package cn.com.qmth.examcloud.core.basic.dao;
 
+import java.util.List;
+
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
 
+import cn.com.qmth.examcloud.api.commons.enums.PrivilegeGroupType;
 import cn.com.qmth.examcloud.core.basic.dao.entity.PrivilegeGroupEntity;
 
 public interface PrivilegeGroupRepo
@@ -14,6 +17,10 @@ public interface PrivilegeGroupRepo
 
 	PrivilegeGroupEntity findByCode(String code);
 
-}
+	List<PrivilegeGroupEntity> findAllByRootOrgIdIsNullOrderById();
 
+	PrivilegeGroupEntity findByRootOrgIdAndType(Long rootOrgId, PrivilegeGroupType type);
 
+	List<PrivilegeGroupEntity> findAllByType(PrivilegeGroupType type);
+
+}

+ 2 - 0
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/PrivilegeRepo.java

@@ -23,6 +23,8 @@ public interface PrivilegeRepo
 
 	List<PrivilegeEntity> findAllByGroupIdOrderByWeightDesc(Long groupId);
 
+	List<PrivilegeEntity> findAllByGroupId(Long groupId);
+
 	List<PrivilegeEntity> findAllByParentId(Long parentId);
 
 	List<PrivilegeEntity> findAllByIdIn(List<Long> idList);

+ 2 - 0
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/RootOrgPrivilegeRelationRepo.java

@@ -17,6 +17,8 @@ public interface RootOrgPrivilegeRelationRepo
 
 	void deleteByRootOrgIdAndGroupId(Long rootOrgId, Long groupId);
 
+	void deleteByPrivilegeId(Long privilegeId);
+
 	List<RootOrgPrivilegeRelationEntity> findAllByRootOrgId(Long rootOrgId);
 
 	List<RootOrgPrivilegeRelationEntity> findAllByRootOrgIdAndGroupId(Long rootOrgId, Long groupId);

+ 37 - 3
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/PrivilegeGroupEntity.java

@@ -2,11 +2,15 @@ package cn.com.qmth.examcloud.core.basic.dao.entity;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.Index;
 import javax.persistence.Table;
 
+import cn.com.qmth.examcloud.api.commons.enums.PrivilegeGroupType;
 import cn.com.qmth.examcloud.web.jpa.JpaEntity;
 
 /**
@@ -17,7 +21,9 @@ import cn.com.qmth.examcloud.web.jpa.JpaEntity;
  * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
  */
 @Entity
-@Table(name = "EC_B_PRIVILEGE_GROUP")
+@Table(name = "EC_B_PRIVILEGE_GROUP", indexes = {
+		@Index(name = "IDX_B_PRI_G_002001", columnList = "code", unique = true),
+		@Index(name = "IDX_B_PRI_G_002002", columnList = "rootOrgId,type", unique = true)})
 public class PrivilegeGroupEntity extends JpaEntity {
 
 	private static final long serialVersionUID = -3654724059677675683L;
@@ -32,15 +38,27 @@ public class PrivilegeGroupEntity extends JpaEntity {
 	/**
 	 * 权限组名称
 	 */
-	@Column(unique = true, nullable = false)
+	@Column(nullable = false)
 	private String name;
 
 	/**
 	 * 权限组编码
 	 */
-	@Column(unique = true, nullable = false)
+	@Column(nullable = false)
 	private String code;
 
+	/**
+	 * 权限组类型
+	 */
+	@Enumerated(EnumType.STRING)
+	private PrivilegeGroupType type;
+
+	/**
+	 * 顶级机构ID
+	 */
+	@Column(nullable = true)
+	private Long rootOrgId;
+
 	/**
 	 * 扩展属性
 	 */
@@ -95,6 +113,22 @@ public class PrivilegeGroupEntity extends JpaEntity {
 		this.code = code;
 	}
 
+	public PrivilegeGroupType getType() {
+		return type;
+	}
+
+	public void setType(PrivilegeGroupType type) {
+		this.type = type;
+	}
+
+	public Long getRootOrgId() {
+		return rootOrgId;
+	}
+
+	public void setRootOrgId(Long rootOrgId) {
+		this.rootOrgId = rootOrgId;
+	}
+
 	public String getExt1() {
 		return ext1;
 	}

+ 72 - 60
examcloud-core-basic-dao/src/main/java/cn/com/qmth/examcloud/core/basic/dao/entity/ResourceEntity.java

@@ -12,87 +12,99 @@ import cn.com.qmth.examcloud.web.jpa.JpaEntity;
 
 @Entity
 @Table(name = "EC_B_RESOURCE", indexes = {
-		@Index(name = "IDX_B_RESOURCE_000001", columnList = "rootOrgId,parentId", unique = false),
-		@Index(name = "IDX_B_RESOURCE_000002", columnList = "rootOrgId,filePath", unique = true)})
+        @Index(name = "IDX_B_RESOURCE_000001", columnList = "rootOrgId,parentId", unique = false),
+        @Index(name = "IDX_B_RESOURCE_000002", columnList = "rootOrgId,filePath", unique = true) })
 public class ResourceEntity extends JpaEntity {
-	private static final long serialVersionUID = 4326176782077577894L;
 
-	@Id
-	@GeneratedValue(strategy = GenerationType.IDENTITY)
-	private Long id;
+    private static final long serialVersionUID = 4326176782077577894L;
 
-	@Column(nullable = false)
-	private Long rootOrgId;
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
 
-	@Column(nullable = false)
-	private String name;
+    @Column(nullable = false)
+    private Long rootOrgId;
 
-	@Column(nullable = false)
-	private Boolean isFile;
+    @Column(nullable = false)
+    private String name;
 
-	@Column(nullable = true)
-	private String suffix;
+    @Column(nullable = false)
+    private Boolean isFile;
 
-	@Column(nullable = false)
-	private String filePath;
+    @Column(nullable = true)
+    private String suffix;
 
-	@Column(nullable = true)
-	private Long parentId;
+    @Column(nullable = false)
+    private String filePath;
 
-	public Long getId() {
-		return id;
-	}
+    @Column(nullable = true)
+    private Long parentId;
 
-	public void setId(Long id) {
-		this.id = id;
-	}
+    @Column(nullable = true)
+    private String fileTreatyPath;
 
-	public Long getRootOrgId() {
-		return rootOrgId;
-	}
+    public Long getId() {
+        return id;
+    }
 
-	public void setRootOrgId(Long rootOrgId) {
-		this.rootOrgId = rootOrgId;
-	}
+    public void setId(Long id) {
+        this.id = id;
+    }
 
-	public String getName() {
-		return name;
-	}
+    public Long getRootOrgId() {
+        return rootOrgId;
+    }
 
-	public void setName(String name) {
-		this.name = name;
-	}
+    public void setRootOrgId(Long rootOrgId) {
+        this.rootOrgId = rootOrgId;
+    }
 
-	public Boolean getIsFile() {
-		return isFile;
-	}
+    public String getName() {
+        return name;
+    }
 
-	public void setIsFile(Boolean isFile) {
-		this.isFile = isFile;
-	}
+    public void setName(String name) {
+        this.name = name;
+    }
 
-	public String getSuffix() {
-		return suffix;
-	}
+    public Boolean getIsFile() {
+        return isFile;
+    }
 
-	public void setSuffix(String suffix) {
-		this.suffix = suffix;
-	}
+    public void setIsFile(Boolean isFile) {
+        this.isFile = isFile;
+    }
 
-	public String getFilePath() {
-		return filePath;
-	}
+    public String getSuffix() {
+        return suffix;
+    }
 
-	public void setFilePath(String filePath) {
-		this.filePath = filePath;
-	}
+    public void setSuffix(String suffix) {
+        this.suffix = suffix;
+    }
 
-	public Long getParentId() {
-		return parentId;
-	}
+    public String getFilePath() {
+        return filePath;
+    }
 
-	public void setParentId(Long parentId) {
-		this.parentId = parentId;
-	}
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+    
+    public String getFileTreatyPath() {
+        return fileTreatyPath;
+    }
+    
+    public void setFileTreatyPath(String fileTreatyPath) {
+        this.fileTreatyPath = fileTreatyPath;
+    }
 
 }

+ 1 - 1
examcloud-core-basic-service/pom.xml

@@ -4,7 +4,7 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 		<artifactId>examcloud-core-basic</artifactId>
-		<version>2019-SNAPSHOT</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<artifactId>examcloud-core-basic-service</artifactId>
 	<packaging>jar</packaging>

+ 453 - 448
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/OrgServiceImpl.java

@@ -46,453 +46,458 @@ import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 @Service
 public class OrgServiceImpl implements OrgService {
 
-	@Autowired
-	RoleRepo roleRepo;
-
-	@Autowired
-	OrgRepo orgRepo;
-
-	@Autowired
-	OrgCache orgCache;
-
-	@Autowired
-	RootOrgCache rootOrgCache;
-
-	@Autowired
-	UserRepo userRepo;
-
-	@Autowired
-	UserRoleRelationRepo userRoleRelationRepo;
-
-	@Autowired
-	OrgPropertyRepo orgPropertyRepo;
-
-	@Autowired
-	StudentRepo studentRepo;
-
-	@Autowired
-	DataSyncCloudService dataSyncCloudService;
-
-	@Autowired
-	OrgPropertyCache orgPropertyCache;
-
-	private static final String[] EXCEL_HEADER = new String[]{"机构名称", "机构代码", "联系人", "联系电话"};
-
-	/*
-	 * 保存顶级机构
-	 *
-	 * @author WANGWEI
-	 * 
-	 * @see
-	 * cn.com.qmth.examcloud.core.basic.service.OrgService#saveRootOrg(cn.com.
-	 * qmth.examcloud.core.basic.service.bean.OrgInfo)
-	 */
-	@Override
-	public OrgEntity saveRootOrg(OrgInfo orgInfo) {
-
-		String code = orgInfo.getCode();
-		String name = orgInfo.getName();
-		Boolean enable = orgInfo.getEnable();
-		String contacts = orgInfo.getContacts();
-		String telephone = orgInfo.getTelephone();
-		String domainName = orgInfo.getDomainName();
-		String remark = orgInfo.getRemark();
-		Map<String, String> properties = orgInfo.getProperties();
-
-		if (StringUtils.isBlank(code)) {
-			throw new StatusException("150001", "code is null");
-		}
-		if (StringUtils.isBlank(name)) {
-			throw new StatusException("150002", "name is null");
-		}
-
-		if (StringUtils.isNotBlank(domainName)) {
-			OrgEntity tempOrg = orgRepo.findByParentIdIsNullAndDomainName(domainName);
-			if (null != tempOrg && !tempOrg.getCode().equals(code)) {
-				throw new StatusException("150004", "域名被占用");
-			}
-		}
-
-		if (null == enable) {
-			enable = true;
-		}
-
-		long updateTime = 0L;
-		OrgEntity orgEntity = orgRepo.findByParentIdIsNullAndCode(code);
-		if (null == orgEntity) {
-			OrgEntity tmp = new OrgEntity();
-			tmp.setRootId(-1L);
-			tmp.setCode(code);
-			tmp.setEnable(enable);
-			tmp.setName(name);
-			orgEntity = orgRepo.save(tmp);
-		} else {
-			if (!orgEntity.getId().equals(orgEntity.getRootId())) {
-				throw new StatusException("150003", "数据错误");
-			}
-
-			if (null != orgEntity.getUpdateTime()) {
-				updateTime = orgEntity.getUpdateTime().getTime();
-			}
-		}
-
-		orgEntity.setRootId(orgEntity.getId());
-		orgEntity.setName(name);
-		orgEntity.setEnable(enable);
-		orgEntity.setContacts(contacts);
-		orgEntity.setTelephone(telephone);
-		orgEntity.setDomainName(domainName);
-		orgEntity.setRemark(remark);
-
-		OrgEntity saved = orgRepo.saveAndFlush(orgEntity);
-
-		// 同步操作
-		if (updateTime != saved.getUpdateTime().getTime()) {
-			SyncOrgReq req = new SyncOrgReq();
-			req.setEnable(saved.getEnable());
-			req.setId(saved.getId());
-			req.setName(saved.getName());
-			req.setParentId(saved.getParentId());
-			req.setRootId(saved.getRootId());
-			req.setSyncType("update");
-			dataSyncCloudService.syncOrg(req);
-		}
-
-		saveOrgProperties(saved.getId(), properties);
-
-		orgCache.remove(saved.getId());
-		if (null != saved.getDomainName()) {
-			rootOrgCache.remove(saved.getDomainName());
-		}
-
-		return saved;
-	}
-
-	/*
-	 * 保存子机构
-	 *
-	 * @author WANGWEI
-	 * 
-	 * @see
-	 * cn.com.qmth.examcloud.core.basic.service.OrgService#saveSubOrg(cn.com.
-	 * qmth.examcloud.core.basic.service.bean.OrgInfo)
-	 */
-	@Override
-	public OrgEntity saveSubOrg(OrgInfo orgInfo) {
-
-		String code = orgInfo.getCode();
-		String name = orgInfo.getName();
-		Boolean enable = orgInfo.getEnable();
-		String contacts = orgInfo.getContacts();
-		String telephone = orgInfo.getTelephone();
-		Long rootId = orgInfo.getRootId();
-		Long parentId = orgInfo.getParentId();
-		String remark = orgInfo.getRemark();
-		Map<String, String> properties = orgInfo.getProperties();
-
-		if (null == enable) {
-			enable = true;
-		}
-
-		if (null == rootId) {
-			throw new StatusException("150000", "rootId is null");
-		}
-		if (StringUtils.isBlank(code)) {
-			throw new StatusException("150001", "code is null");
-		}
-		if (StringUtils.isBlank(name)) {
-			throw new StatusException("150002", "name is null");
-		}
-		if (null == parentId) {
-			throw new StatusException("150003", "parentId is null");
-		}
-
-		OrgEntity rootOrgEntity = GlobalHelper.getEntity(orgRepo, rootId, OrgEntity.class);
-		if (null == rootOrgEntity) {
-			throw new StatusException("150004", "rootId is wrong");
-		}
-		if (null != rootOrgEntity.getParentId()) {
-			throw new StatusException("150005", "rootId is wrong");
-		}
-
-		OrgEntity parentOrgEntity = GlobalHelper.getEntity(orgRepo, parentId, OrgEntity.class);
-		if (null == parentOrgEntity) {
-			throw new StatusException("150006", "parentId is wrong");
-		}
-
-		if (!rootOrgEntity.getRootId().equals(parentOrgEntity.getRootId())) {
-			throw new StatusException("150007", "parentId, rootId is wrong");
-		}
-
-		long updateTime = 0L;
-		OrgEntity orgEntity = orgRepo.findByRootIdAndCode(rootId, code);
-		if (null == orgEntity) {
-			orgEntity = new OrgEntity();
-			orgEntity.setRootId(rootId);
-			orgEntity.setParentId(parentId);
-			orgEntity.setCode(code);
-		} else {
-			if (null != orgEntity.getUpdateTime()) {
-				updateTime = orgEntity.getUpdateTime().getTime();
-			}
-		}
-
-		orgEntity.setName(name);
-		orgEntity.setEnable(enable);
-		orgEntity.setContacts(contacts);
-		orgEntity.setTelephone(telephone);
-		orgEntity.setRemark(remark);
-
-		OrgEntity saved = orgRepo.saveAndFlush(orgEntity);
-
-		// 同步操作
-		if (updateTime != saved.getUpdateTime().getTime()) {
-			SyncOrgReq req = new SyncOrgReq();
-			req.setEnable(saved.getEnable());
-			req.setId(saved.getId());
-			req.setName(saved.getName());
-			req.setParentId(saved.getParentId());
-			req.setRootId(saved.getRootId());
-			req.setSyncType("update");
-			dataSyncCloudService.syncOrg(req);
-		}
-
-		saveOrgProperties(saved.getId(), properties);
-
-		orgCache.remove(saved.getId());
-		if (null != saved.getDomainName()) {
-			rootOrgCache.remove(saved.getDomainName());
-		}
-
-		return saved;
-	}
-
-	@Override
-	public void saveOrgProperties(Long orgId, Map<String, String> properties) {
-
-		GlobalHelper.getPresentEntity(orgRepo, orgId, OrgEntity.class);
-
-		Map<DynamicEnum, String> map = checkAndGetOrgProperties(properties);
-
-		for (Entry<DynamicEnum, String> entry : map.entrySet()) {
-			DynamicEnum de = entry.getKey();
-			String value = entry.getValue();
-			OrgPropertyEntity entity = orgPropertyRepo.findByOrgIdAndKeyId(orgId, de.getId());
-			if (null == entity) {
-				entity = new OrgPropertyEntity();
-				entity.setOrgId(orgId);
-				entity.setKeyId(de.getId());
-			}
-			if (StringUtils.isBlank(value)) {
-				entity.setValue(null);
-			} else {
-				entity.setValue(value);
-			}
-
-			orgPropertyRepo.save(entity);
-		}
-
-		if (null != properties) {
-			for (String key : properties.keySet()) {
-				orgPropertyCache.remove(orgId, key);
-			}
-		}
-
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param properties
-	 * @return
-	 */
-	private Map<DynamicEnum, String> checkAndGetOrgProperties(Map<String, String> properties) {
-		DynamicEnumManager manager = OrgProperty.getDynamicEnumManager();
-
-		Map<DynamicEnum, String> map = Maps.newHashMap();
-		if (null == properties) {
-			return map;
-		}
-		for (Entry<String, String> entry : properties.entrySet()) {
-			String key = entry.getKey();
-			String value = entry.getValue();
-			DynamicEnum de = null;
-			try {
-				de = manager.getByName(key);
-			} catch (Exception e) {
-				throw new StatusException("001004", "机构属性错误. key=" + key);
-			}
-			if (!de.isLegal(value)) {
-				throw new StatusException("001200", "机构属性值非法. key=" + key);
-			}
-			map.put(de, value.trim());
-		}
-
-		return map;
-	}
-
-	@Override
-	public List<Map<String, Object>> importSubOrg(Long rootOrgId, File file) {
-
-		List<String[]> lineList = null;
-		try {
-			lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(file), 1, 4);
-		} catch (Exception e) {
-			throw new StatusException("100110", "Excel 解析失败");
-		}
-
-		if (CollectionUtils.isEmpty(lineList)) {
-			throw new StatusException("100111", "Excel无内容");
-		}
-
-		if (10001 < lineList.size()) {
-			throw new StatusException("100112", "数据行数不能超过10000");
-		}
-
-		List<Map<String, Object>> failRecords = Collections
-				.synchronizedList(new ArrayList<Map<String, Object>>());
-
-		List<OrgEntity> courseList = Lists.newArrayList();
-
-		for (int i = 0; i < lineList.size(); i++) {
-			String[] line = lineList.get(i);
-			if (0 == i) {
-				if (headerError(line)) {
-					throw new StatusException("100111", "Excel表头错误");
-				}
-				continue;
-			}
-
-			boolean hasError = false;
-			StringBuilder msg = new StringBuilder();
-
-			OrgEntity org = new OrgEntity();
-			org.setParentId(rootOrgId);
-			org.setEnable(true);
-
-			String name = trimAndNullIfBlank(line[0]);
-			if (StringUtils.isBlank(name)) {
-				msg.append("  学习中心名称不能为空");
-				hasError = true;
-			} else if (name.length() > 30) {
-				msg.append("  学习中心名称不能超过30个字符");
-				hasError = true;
-			}
-			org.setName(name);
-
-			String code = trimAndNullIfBlank(line[1]);
-			if (StringUtils.isBlank(code)) {
-				msg.append("  学习中心代码不能为空");
-				hasError = true;
-			} else if (code.length() > 30) {
-				msg.append("  学习中心代码不能超过30个字符");
-				hasError = true;
-			}
-			org.setCode(code);
-
-			String contacts = trimAndNullIfBlank(line[2]);
-			if (StringUtils.isBlank(contacts)) {
-				msg.append("  联系人不能为空");
-				hasError = true;
-			} else if (contacts.length() > 30) {
-				msg.append("  联系人不能超过30个字符");
-				hasError = true;
-			}
-			org.setContacts(contacts);
-
-			String telephone = trimAndNullIfBlank(line[3]);
-			if (StringUtils.isBlank(telephone)) {
-				msg.append("  联系电话不能为空");
-				hasError = true;
-			} else if (telephone.length() > 30) {
-				msg.append("  联系电话不能超过30个字符");
-				hasError = true;
-			}
-			org.setTelephone(telephone);
-
-			if (hasError) {
-				failRecords.add(newError(i + 1, msg.toString()));
-			} else {
-				courseList.add(org);
-			}
-
-		}
-
-		if (CollectionUtils.isNotEmpty(failRecords)) {
-			return failRecords;
-		}
-
-		for (OrgEntity cur : courseList) {
-			OrgInfo info = new OrgInfo();
-			info.setCode(cur.getCode());
-			info.setParentId(rootOrgId);
-			info.setRootId(rootOrgId);
-
-			info.setName(cur.getName());
-			info.setContacts(cur.getContacts());
-			info.setTelephone(cur.getTelephone());
-
-			OrgEntity saved = saveSubOrg(info);
-
-			createLearnerCenterUser(saved);
-		}
-
-		return failRecords;
-	}
-
-	public void createLearnerCenterUser(OrgEntity org) {
-		UserEntity user = userRepo.findByRootOrgIdAndLoginName(org.getRootId(), org.getCode());
-		if (null != user) {
-			return;
-		}
-		user = new UserEntity();
-		user.setRootOrgId(org.getRootId());
-		user.setOrgId(org.getId());
-		user.setLoginName(org.getCode());
-		user.setName(org.getContacts());
-		user.setPhoneNumber(org.getTelephone());
-		user.setEnable(true);
-		user.setPassword(BasicConsts.DEFAULT_PASSWORD);
-		UserEntity savedUser = userRepo.save(user);
-		List<UserRoleRelationEntity> userRoles = Lists.newArrayList();
-		RoleEntity role = roleRepo.findByCode(RoleMeta.LC_USER.name());
-		UserRoleRelationEntity relation = new UserRoleRelationEntity(savedUser.getId(),
-				role.getId());
-		userRoles.add(relation);
-		userRoleRelationRepo.saveAll(userRoles);
-	}
-
-	private Map<String, Object> newError(int lineNum, String msg) {
-		Map<String, Object> map = Maps.newHashMap();
-		map.put("lineNum", lineNum);
-		map.put("msg", msg);
-		return map;
-	}
-
-	private String trimAndNullIfBlank(String s) {
-		if (StringUtils.isBlank(s)) {
-			return null;
-		}
-		return s.trim();
-	}
-
-	/**
-	 * 方法注释
-	 *
-	 * @author WANGWEI
-	 * @param header
-	 */
-	private boolean headerError(String[] header) {
-		for (int i = 0; i < EXCEL_HEADER.length; i++) {
-			if (null == header[i]) {
-				return true;
-			}
-			if (!EXCEL_HEADER[i].equals(header[i].trim())) {
-				return true;
-			}
-		}
-		return false;
-	}
+    @Autowired
+    RoleRepo roleRepo;
+
+    @Autowired
+    OrgRepo orgRepo;
+
+    @Autowired
+    OrgCache orgCache;
+
+    @Autowired
+    RootOrgCache rootOrgCache;
+
+    @Autowired
+    UserRepo userRepo;
+
+    @Autowired
+    UserRoleRelationRepo userRoleRelationRepo;
+
+    @Autowired
+    OrgPropertyRepo orgPropertyRepo;
+
+    @Autowired
+    StudentRepo studentRepo;
+
+    @Autowired
+    DataSyncCloudService dataSyncCloudService;
+
+    @Autowired
+    OrgPropertyCache orgPropertyCache;
+
+    private static final String[] EXCEL_HEADER = new String[]{"机构名称", "机构代码", "联系人", "联系电话"};
+
+    /*
+     * 保存顶级机构
+     *
+     * @author WANGWEI
+     *
+     * @see
+     * cn.com.qmth.examcloud.core.basic.service.OrgService#saveRootOrg(cn.com.
+     * qmth.examcloud.core.basic.service.bean.OrgInfo)
+     */
+    @Override
+    public OrgEntity saveRootOrg(OrgInfo orgInfo) {
+
+        String code = orgInfo.getCode();
+        String name = orgInfo.getName();
+        Boolean enable = orgInfo.getEnable();
+        String contacts = orgInfo.getContacts();
+        String telephone = orgInfo.getTelephone();
+        String domainName = orgInfo.getDomainName();
+        String remark = orgInfo.getRemark();
+        Map<String, String> properties = orgInfo.getProperties();
+
+        if (StringUtils.isBlank(code)) {
+            throw new StatusException("150001", "code is null");
+        }
+        if (StringUtils.isBlank(name)) {
+            throw new StatusException("150002", "name is null");
+        }
+
+        if (StringUtils.isNotBlank(domainName)) {
+            OrgEntity tempOrg = orgRepo.findByParentIdIsNullAndDomainName(domainName);
+            if (null != tempOrg && !tempOrg.getCode().equals(code)) {
+                throw new StatusException("150004", "域名被占用");
+            }
+        }
+
+        if (null == enable) {
+            enable = true;
+        }
+
+        long updateTime = 0L;
+        OrgEntity orgEntity = orgRepo.findByParentIdIsNullAndCode(code);
+        if (null == orgEntity) {
+            OrgEntity tmp = new OrgEntity();
+            tmp.setRootId(-1L);
+            tmp.setCode(code);
+            tmp.setEnable(enable);
+            tmp.setName(name);
+            orgEntity = orgRepo.save(tmp);
+        } else {
+            if (!orgEntity.getId().equals(orgEntity.getRootId())) {
+                throw new StatusException("150003", "数据错误");
+            }
+
+            if (null != orgEntity.getUpdateTime()) {
+                updateTime = orgEntity.getUpdateTime().getTime();
+            }
+        }
+
+        orgEntity.setRootId(orgEntity.getId());
+        orgEntity.setName(name);
+        orgEntity.setEnable(enable);
+        orgEntity.setContacts(contacts);
+        orgEntity.setTelephone(telephone);
+        orgEntity.setDomainName(domainName);
+        orgEntity.setRemark(remark);
+
+        OrgEntity saved = orgRepo.saveAndFlush(orgEntity);
+
+        // 同步操作
+        if (updateTime != saved.getUpdateTime().getTime()) {
+            SyncOrgReq req = new SyncOrgReq();
+            req.setEnable(saved.getEnable());
+            req.setId(saved.getId());
+            req.setName(saved.getName());
+            req.setParentId(saved.getParentId());
+            req.setRootId(saved.getRootId());
+            req.setSyncType("update");
+            dataSyncCloudService.syncOrg(req);
+        }
+
+        saveOrgProperties(saved.getId(), properties);
+
+        orgCache.remove(saved.getId());
+        if (null != saved.getDomainName()) {
+            rootOrgCache.remove(saved.getDomainName());
+        }
+
+        return saved;
+    }
+
+    /*
+     * 保存子机构
+     *
+     * @author WANGWEI
+     *
+     * @see
+     * cn.com.qmth.examcloud.core.basic.service.OrgService#saveSubOrg(cn.com.
+     * qmth.examcloud.core.basic.service.bean.OrgInfo)
+     */
+    @Override
+    public OrgEntity saveSubOrg(OrgInfo orgInfo) {
+
+        String code = orgInfo.getCode();
+        String name = orgInfo.getName();
+        Boolean enable = orgInfo.getEnable();
+        String contacts = orgInfo.getContacts();
+        String telephone = orgInfo.getTelephone();
+        Long rootId = orgInfo.getRootId();
+        Long parentId = orgInfo.getParentId();
+        String remark = orgInfo.getRemark();
+        Map<String, String> properties = orgInfo.getProperties();
+
+        if (null == enable) {
+            enable = true;
+        }
+
+        if (null == rootId) {
+            throw new StatusException("150000", "rootId is null");
+        }
+        if (StringUtils.isBlank(code)) {
+            throw new StatusException("150001", "code is null");
+        }
+        if (StringUtils.isBlank(name)) {
+            throw new StatusException("150002", "name is null");
+        }
+        if (null == parentId) {
+            throw new StatusException("150003", "parentId is null");
+        }
+
+        OrgEntity rootOrgEntity = GlobalHelper.getEntity(orgRepo, rootId, OrgEntity.class);
+        if (null == rootOrgEntity) {
+            throw new StatusException("150004", "rootId is wrong");
+        }
+        if (null != rootOrgEntity.getParentId()) {
+            throw new StatusException("150005", "rootId is wrong");
+        }
+
+        OrgEntity parentOrgEntity = GlobalHelper.getEntity(orgRepo, parentId, OrgEntity.class);
+        if (null == parentOrgEntity) {
+            throw new StatusException("150006", "parentId is wrong");
+        }
+
+        if (!rootOrgEntity.getRootId().equals(parentOrgEntity.getRootId())) {
+            throw new StatusException("150007", "parentId, rootId is wrong");
+        }
+
+        long updateTime = 0L;
+        OrgEntity orgEntity = orgRepo.findByRootIdAndCode(rootId, code);
+        if (null == orgEntity) {
+            orgEntity = new OrgEntity();
+            orgEntity.setRootId(rootId);
+            orgEntity.setParentId(parentId);
+            orgEntity.setCode(code);
+        } else {
+            if (null != orgEntity.getUpdateTime()) {
+                updateTime = orgEntity.getUpdateTime().getTime();
+            }
+        }
+
+        orgEntity.setName(name);
+        orgEntity.setEnable(enable);
+        orgEntity.setContacts(contacts);
+        orgEntity.setTelephone(telephone);
+        orgEntity.setRemark(remark);
+
+        OrgEntity saved = orgRepo.saveAndFlush(orgEntity);
+
+        // 同步操作
+        if (updateTime != saved.getUpdateTime().getTime()) {
+            SyncOrgReq req = new SyncOrgReq();
+            req.setEnable(saved.getEnable());
+            req.setId(saved.getId());
+            req.setName(saved.getName());
+            req.setParentId(saved.getParentId());
+            req.setRootId(saved.getRootId());
+            req.setSyncType("update");
+            dataSyncCloudService.syncOrg(req);
+        }
+
+        saveOrgProperties(saved.getId(), properties);
+
+        orgCache.remove(saved.getId());
+        if (null != saved.getDomainName()) {
+            rootOrgCache.remove(saved.getDomainName());
+        }
+
+        return saved;
+    }
+
+    @Override
+    public void saveOrgProperties(Long orgId, Map<String, String> properties) {
+
+        GlobalHelper.getPresentEntity(orgRepo, orgId, OrgEntity.class);
+
+        Map<DynamicEnum, String> map = checkAndGetOrgProperties(properties);
+
+        for (Entry<DynamicEnum, String> entry : map.entrySet()) {
+            DynamicEnum de = entry.getKey();
+            String value = entry.getValue();
+            OrgPropertyEntity entity = orgPropertyRepo.findByOrgIdAndKeyId(orgId, de.getId());
+            if (null == entity) {
+                entity = new OrgPropertyEntity();
+                entity.setOrgId(orgId);
+                entity.setKeyId(de.getId());
+            }
+            if (StringUtils.isBlank(value)) {
+                entity.setValue(null);
+            } else {
+                entity.setValue(value);
+            }
+
+            orgPropertyRepo.save(entity);
+        }
+
+        if (null != properties) {
+            for (String key : properties.keySet()) {
+                orgPropertyCache.remove(orgId, key);
+            }
+        }
+
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param properties
+     * @return
+     * @author WANGWEI
+     */
+    private Map<DynamicEnum, String> checkAndGetOrgProperties(Map<String, String> properties) {
+        DynamicEnumManager manager = OrgProperty.getDynamicEnumManager();
+
+        Map<DynamicEnum, String> map = Maps.newHashMap();
+        if (null == properties) {
+            return map;
+        }
+        for (Entry<String, String> entry : properties.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            DynamicEnum de = null;
+            try {
+                de = manager.getByName(key);
+            } catch (Exception e) {
+                throw new StatusException("001004", "机构属性错误. key=" + key);
+            }
+            if (!de.isLegal(value)) {
+                throw new StatusException("001200", "机构属性值非法. key=" + key);
+            }
+
+            if (null == value) {
+                map.put(de, null);
+            } else {
+                map.put(de, value.trim());
+            }
+        }
+
+        return map;
+    }
+
+    @Override
+    public List<Map<String, Object>> importSubOrg(Long rootOrgId, File file) {
+
+        List<String[]> lineList = null;
+        try {
+            lineList = ExcelReader.readSheetBySax(PathUtil.getCanonicalPath(file), 1, 4);
+        } catch (Exception e) {
+            throw new StatusException("100110", "Excel 解析失败");
+        }
+
+        if (CollectionUtils.isEmpty(lineList)) {
+            throw new StatusException("100111", "Excel无内容");
+        }
+
+        if (10001 < lineList.size()) {
+            throw new StatusException("100112", "数据行数不能超过10000");
+        }
+
+        List<Map<String, Object>> failRecords = Collections
+                .synchronizedList(new ArrayList<Map<String, Object>>());
+
+        List<OrgEntity> courseList = Lists.newArrayList();
+
+        for (int i = 0; i < lineList.size(); i++) {
+            String[] line = lineList.get(i);
+            if (0 == i) {
+                if (headerError(line)) {
+                    throw new StatusException("100111", "Excel表头错误");
+                }
+                continue;
+            }
+
+            boolean hasError = false;
+            StringBuilder msg = new StringBuilder();
+
+            OrgEntity org = new OrgEntity();
+            org.setParentId(rootOrgId);
+            org.setEnable(true);
+
+            String name = trimAndNullIfBlank(line[0]);
+            if (StringUtils.isBlank(name)) {
+                msg.append("  学习中心名称不能为空");
+                hasError = true;
+            } else if (name.length() > 30) {
+                msg.append("  学习中心名称不能超过30个字符");
+                hasError = true;
+            }
+            org.setName(name);
+
+            String code = trimAndNullIfBlank(line[1]);
+            if (StringUtils.isBlank(code)) {
+                msg.append("  学习中心代码不能为空");
+                hasError = true;
+            } else if (code.length() > 30) {
+                msg.append("  学习中心代码不能超过30个字符");
+                hasError = true;
+            }
+            org.setCode(code);
+
+            String contacts = trimAndNullIfBlank(line[2]);
+            if (StringUtils.isBlank(contacts)) {
+                msg.append("  联系人不能为空");
+                hasError = true;
+            } else if (contacts.length() > 30) {
+                msg.append("  联系人不能超过30个字符");
+                hasError = true;
+            }
+            org.setContacts(contacts);
+
+            String telephone = trimAndNullIfBlank(line[3]);
+            if (StringUtils.isBlank(telephone)) {
+                msg.append("  联系电话不能为空");
+                hasError = true;
+            } else if (telephone.length() > 30) {
+                msg.append("  联系电话不能超过30个字符");
+                hasError = true;
+            }
+            org.setTelephone(telephone);
+
+            if (hasError) {
+                failRecords.add(newError(i + 1, msg.toString()));
+            } else {
+                courseList.add(org);
+            }
+
+        }
+
+        if (CollectionUtils.isNotEmpty(failRecords)) {
+            return failRecords;
+        }
+
+        for (OrgEntity cur : courseList) {
+            OrgInfo info = new OrgInfo();
+            info.setCode(cur.getCode());
+            info.setParentId(rootOrgId);
+            info.setRootId(rootOrgId);
+
+            info.setName(cur.getName());
+            info.setContacts(cur.getContacts());
+            info.setTelephone(cur.getTelephone());
+
+            OrgEntity saved = saveSubOrg(info);
+
+            createLearnerCenterUser(saved);
+        }
+
+        return failRecords;
+    }
+
+    public void createLearnerCenterUser(OrgEntity org) {
+        UserEntity user = userRepo.findByRootOrgIdAndLoginName(org.getRootId(), org.getCode());
+        if (null != user) {
+            return;
+        }
+        user = new UserEntity();
+        user.setRootOrgId(org.getRootId());
+        user.setOrgId(org.getId());
+        user.setLoginName(org.getCode());
+        user.setName(org.getContacts());
+        user.setPhoneNumber(org.getTelephone());
+        user.setEnable(true);
+        user.setPassword(BasicConsts.DEFAULT_PASSWORD);
+        UserEntity savedUser = userRepo.save(user);
+        List<UserRoleRelationEntity> userRoles = Lists.newArrayList();
+        RoleEntity role = roleRepo.findByCode(RoleMeta.LC_USER.name());
+        UserRoleRelationEntity relation = new UserRoleRelationEntity(savedUser.getId(),
+                role.getId());
+        userRoles.add(relation);
+        userRoleRelationRepo.saveAll(userRoles);
+    }
+
+    private Map<String, Object> newError(int lineNum, String msg) {
+        Map<String, Object> map = Maps.newHashMap();
+        map.put("lineNum", lineNum);
+        map.put("msg", msg);
+        return map;
+    }
+
+    private String trimAndNullIfBlank(String s) {
+        if (StringUtils.isBlank(s)) {
+            return null;
+        }
+        return s.trim();
+    }
+
+    /**
+     * 方法注释
+     *
+     * @param header
+     * @author WANGWEI
+     */
+    private boolean headerError(String[] header) {
+        for (int i = 0; i < EXCEL_HEADER.length; i++) {
+            if (null == header[i]) {
+                return true;
+            }
+            if (!EXCEL_HEADER[i].equals(header[i].trim())) {
+                return true;
+            }
+        }
+        return false;
+    }
 
 }

+ 81 - 92
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/ResourceServiceImpl.java

@@ -17,100 +17,89 @@ import cn.com.qmth.examcloud.core.basic.service.ResourceService;
 import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
 import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
+import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
 
 @Service
 public class ResourceServiceImpl implements ResourceService {
 
-	private static final String FILE_ROOT_PATH = "/resource";
-
-	private static final String FILE_PATH_SEPARATE = "/";
-
-	@Autowired
-	ResourceRepo resourceRepo;
-
-//	@Autowired
-//	UpyunCloudService upyunCloudService;
-
-	@Override
-	public void addDir(ResourceInfo info) {
-
-		ResourceEntity e = new ResourceEntity();
-		e.setName(info.getName());
-		e.setRootOrgId(info.getRootOrgId());
-		e.setIsFile(false);
-		if (info.getParentId() == null) {
-			e.setParentId(null);
-			e.setFilePath(FILE_ROOT_PATH + FILE_PATH_SEPARATE + info.getRootOrgId()
-					+ FILE_PATH_SEPARATE + info.getName());
-		} else {
-			e.setParentId(info.getParentId());
-			Optional<ResourceEntity> op = resourceRepo.findById(info.getParentId());
-			if (op.isPresent()) {
-				ResourceEntity pe = op.get();
-				e.setFilePath(pe.getFilePath() + FILE_PATH_SEPARATE + info.getName());
-			} else {
-				throw new StatusException("100000", "上级目录不存在");
-			}
-		}
-		resourceRepo.saveAndFlush(e);
-	}
-
-	@Override
-	public void addFile(Long rootOrgId, Long parentId, MultipartFile dataFile) {
-
-		ResourceEntity e = new ResourceEntity();
-		String fileName = dataFile.getOriginalFilename();
-		e.setName(fileName);
-		e.setRootOrgId(rootOrgId);
-		e.setIsFile(true);
-		String suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
-		e.setSuffix(suffix);
-		if (parentId == null) {
-			e.setParentId(null);
-			e.setFilePath(FILE_ROOT_PATH + FILE_PATH_SEPARATE + rootOrgId + FILE_PATH_SEPARATE
-					+ fileName);
-		} else {
-			e.setParentId(parentId);
-			Optional<ResourceEntity> op = resourceRepo.findById(parentId);
-			if (op.isPresent()) {
-				ResourceEntity pe = op.get();
-				e.setFilePath(pe.getFilePath() + FILE_PATH_SEPARATE + fileName);
-			} else {
-				throw new StatusException("100020", "上级目录不存在");
-			}
-		}
-		ResourceEntity olde = resourceRepo.findByRootOrgIdAndFilePath(rootOrgId, e.getFilePath());
-		if (olde != null) {
-			olde.setUpdateTime(new Date());
-			resourceRepo.save(olde);
-		} else {
-			resourceRepo.save(e);
-		}
-		CommonsMultipartFile cf = (CommonsMultipartFile) dataFile;
-		DiskFileItem fi = (DiskFileItem) cf.getFileItem();
-
-		File f = fi.getStoreLocation();
-//		PutFileReq req = new PutFileReq();
-//		List<FormFilePart> formFilePartList = new ArrayList<FormFilePart>();
-
-//		FormFilePart part = new FormFilePart("file", fileName, f);
-//		formFilePartList.add(part);
-//
-//		req.setFormFilePartList(formFilePartList);
-//		req.setSiteId("resource");
-//		req.setRootOrgId(rootOrgId);
-//		String relativePath = e.getFilePath().replaceFirst(FILE_ROOT_PATH, "")
-//				.replaceFirst(FILE_PATH_SEPARATE, "");
-//		req.setRelativePath(relativePath);
-//		upyunCloudService.putFile(req);
-		
-		//通用存储
-		FileStoragePathEnvInfo env=new FileStoragePathEnvInfo();
-		env.setRootOrgId(rootOrgId.toString());
-		String relativePath = e.getFilePath().replaceFirst(FILE_ROOT_PATH, "")
-				.replaceFirst(FILE_PATH_SEPARATE, "");
-		env.setRelativePath(relativePath);
-		FileStorageUtil.saveFile("resource", env, f,null);
-		
-	}
+    private static final String FILE_ROOT_PATH = "/resource";
+
+    private static final String FILE_PATH_SEPARATE = "/";
+
+    @Autowired
+    ResourceRepo resourceRepo;
+
+    // @Autowired
+    // UpyunCloudService upyunCloudService;
+
+    @Override
+    public void addDir(ResourceInfo info) {
+
+        ResourceEntity e = new ResourceEntity();
+        e.setName(info.getName());
+        e.setRootOrgId(info.getRootOrgId());
+        e.setIsFile(false);
+        if (info.getParentId() == null) {
+            e.setParentId(null);
+            e.setFilePath(
+                    FILE_ROOT_PATH + FILE_PATH_SEPARATE + info.getRootOrgId() + FILE_PATH_SEPARATE + info.getName());
+        } else {
+            e.setParentId(info.getParentId());
+            Optional<ResourceEntity> op = resourceRepo.findById(info.getParentId());
+            if (op.isPresent()) {
+                ResourceEntity pe = op.get();
+                e.setFilePath(pe.getFilePath() + FILE_PATH_SEPARATE + info.getName());
+            } else {
+                throw new StatusException("100000", "上级目录不存在");
+            }
+        }
+        resourceRepo.saveAndFlush(e);
+    }
+
+    @Override
+    public void addFile(Long rootOrgId, Long parentId, MultipartFile dataFile) {
+
+        ResourceEntity e = new ResourceEntity();
+        String fileName = dataFile.getOriginalFilename();
+        e.setName(fileName);
+        e.setRootOrgId(rootOrgId);
+        e.setIsFile(true);
+        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
+        e.setSuffix(suffix);
+
+
+        if (parentId == null) {
+            e.setParentId(null);
+            e.setFilePath(FILE_ROOT_PATH + FILE_PATH_SEPARATE + rootOrgId + FILE_PATH_SEPARATE + fileName);
+        } else {
+            e.setParentId(parentId);
+            Optional<ResourceEntity> op = resourceRepo.findById(parentId);
+            if (op.isPresent()) {
+                ResourceEntity pe = op.get();
+                e.setFilePath(pe.getFilePath() + FILE_PATH_SEPARATE + fileName);
+            } else {
+                throw new StatusException("100020", "上级目录不存在");
+            }
+        }
+        
+        CommonsMultipartFile cf = (CommonsMultipartFile) dataFile;
+        DiskFileItem fi = (DiskFileItem) cf.getFileItem();
+
+        File f = fi.getStoreLocation();
+        // 通用存储
+        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
+        env.setRootOrgId(rootOrgId.toString());
+        env.setRelativePath(e.getFilePath());
+        YunPathInfo pi=FileStorageUtil.saveFile("resource", env, f, null);
+        e.setFileTreatyPath(pi.getRelativePath());
+        
+        ResourceEntity olde = resourceRepo.findByRootOrgIdAndFilePath(rootOrgId, e.getFilePath());
+        if (olde != null) {
+            olde.setUpdateTime(new Date());
+            resourceRepo.save(olde);
+        } else {
+            resourceRepo.save(e);
+        }
+
+    }
 }

+ 3 - 0
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/RolePrivilegeServiceImpl.java

@@ -127,6 +127,9 @@ public class RolePrivilegeServiceImpl implements RolePrivilegeService {
 		rootOrgPrivilegeRelationRepo.deleteByRootOrgIdAndGroupId(rootOrgId, privilegeGroupId);
 
 		for (Long cur : privilegeIdSet) {
+			if(cur==-1){
+				continue;
+			}
 			PrivilegeEntity privilegeEntity = GlobalHelper.getPresentEntity(privilegeRepo, cur,
 					PrivilegeEntity.class);
 			if (!privilegeEntity.getGroupId().equals(privilegeGroupId)) {

+ 1 - 1
examcloud-core-basic-starter/pom.xml

@@ -5,7 +5,7 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 		<artifactId>examcloud-core-basic</artifactId>
-		<version>2019-SNAPSHOT</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<artifactId>examcloud-core-basic-starter</artifactId>
 	<packaging>jar</packaging>

+ 2 - 2
examcloud-core-basic-starter/shell/start.sh

@@ -1,8 +1,8 @@
 #!/bin/bash
 
 FILE_PATH=$(cd `dirname $0`; pwd)
-APP_VERSION=`cat $FILE_PATH/version`
-APP_MAIN_JAR="examcloud-core-basic-starter-"$APP_VERSION"-SNAPSHOT.jar"
+
+APP_MAIN_JAR="examcloud-core-basic-starter-v3.0-RELEASE.jar"
 
 JAVA_OPTS=`cat $FILE_PATH/start.vmoptions`
 APP_ARGS=`cat $FILE_PATH/start.args`

+ 2 - 2
examcloud-core-basic-starter/shell/stop.sh

@@ -1,8 +1,8 @@
 #!/bin/bash
 
 FILE_PATH=$(cd `dirname $0`; pwd)
-APP_VERSION=`cat $FILE_PATH/version`
-APP_MAIN_JAR="examcloud-core-basic-starter-"$APP_VERSION"-SNAPSHOT.jar"
+
+APP_MAIN_JAR="examcloud-core-basic-starter-v3.0-RELEASE.jar"
 
 PID_LIST=`ps -ef|grep $APP_MAIN_JAR|grep java|awk '{print $2}'`
 

+ 0 - 1
examcloud-core-basic-starter/shell/version

@@ -1 +0,0 @@
-2019

+ 1 - 1
examcloud-core-basic-starter/src/main/resources/aliyun.xml

@@ -6,7 +6,7 @@
 		<name>资源</name>
 		<aliyunId>1</aliyunId>
 		<maxSize>50M</maxSize>
-		<path>/resource/${relativePath}</path>
+		<path>/${relativePath}</path>
 	</site>
 	<site>
 		<id>orgLogo</id>

+ 26 - 2
examcloud-core-basic-starter/src/main/resources/org-properties.xml

@@ -33,7 +33,7 @@
 	<enum>
 		<id>5</id>
 		<name>LOGIN_TYPE</name>
-		<desc>登录帐号类型</desc>
+		<desc>登录方式</desc>
 		<valueType>STRING</valueType>
 	</enum>
 	<enum>
@@ -132,4 +132,28 @@
 		<desc>学生端登录支持</desc>
 		<valueType>STRING</valueType>
 	</enum>
-</enums>
+	<enum>
+		<id>22</id>
+		<name>CUS_MENU_LOGO_FILE</name>
+		<desc>机构自定义菜单图标文件(文件转字符串存储)</desc>
+		<valueType>STRING</valueType>
+	</enum>
+	<enum>
+		<id>23</id>
+		<name>CUS_MENU_LOGO_FILE_SUFFIX</name>
+		<desc>机构自定义菜单图标文件后缀</desc>
+		<valueType>STRING</valueType>
+	</enum>
+	<enum>
+		<id>24</id>
+		<name>CUS_MENU_LOGO_FILE_URL</name>
+		<desc>机构自定义菜单图标URL</desc>
+		<valueType>STRING</valueType>
+	</enum>
+	<enum>
+		<id>25</id>
+		<name>IS_CUSTOM_MENU_LOGO</name>
+		<desc>机构是否自定义菜单</desc>
+		<valueType>BOOLEAN</valueType>
+	</enum>
+</enums>

+ 2 - 1
examcloud-core-basic-starter/src/main/resources/security.properties

@@ -8,4 +8,5 @@
 [s][${$rmp.ctr.basic}/auth][/sendVerificationCode][POST]=true
 [s][${$rmp.ctr.basic}/org][propertyNoSession/{key}][GET]=true
 [s][${$rmp.ctr.basic}/org][property/{orgId}/{key}][GET]=true
-[s][${$rmp.ctr.basic}/systemProperty][{key}][GET]=true
+[s][${$rmp.ctr.basic}/systemProperty][{key}][GET]=true
+[s][${$rmp.ctr.basic}/rolePrivilege][getStudentClientMenu][GET]=true

+ 1 - 1
examcloud-core-basic-starter/src/main/resources/upyun.xml

@@ -6,7 +6,7 @@
 		<name>资源</name>
 		<upyunId>1</upyunId>
 		<maxSize>50M</maxSize>
-		<path>/resource/${relativePath}</path>
+		<path>/${relativePath}</path>
 	</site>
 	<site>
 		<id>orgLogo</id>

+ 2 - 2
pom.xml

@@ -4,11 +4,11 @@
 	<parent>
 		<groupId>cn.com.qmth.examcloud</groupId>
 		<artifactId>examcloud-parent</artifactId>
-		<version>2019</version>
+		<version>v3.0-RELEASE</version>
 	</parent>
 	<groupId>cn.com.qmth.examcloud.core.basic</groupId>
 	<artifactId>examcloud-core-basic</artifactId>
-	<version>2019-SNAPSHOT</version>
+	<version>v3.0-RELEASE</version>
 	<packaging>pom</packaging>
 
 	<modules>