Browse Source

增加产品类别功能

zhangqiankun 3 years ago
parent
commit
fad727b7f2
36 changed files with 828 additions and 161 deletions
  1. 3 0
      saas-account/src/main/java/com/persagy/account/config/ApplicationProperties.java
  2. 1 2
      saas-account/src/main/java/com/persagy/account/controller/SaasFunctionController.java
  3. 22 20
      saas-account/src/main/java/com/persagy/account/controller/SaasMenuController.java
  4. 103 0
      saas-account/src/main/java/com/persagy/account/controller/SaasProductCategeoryController.java
  5. 19 6
      saas-account/src/main/java/com/persagy/account/controller/SaasProductController.java
  6. 22 9
      saas-account/src/main/java/com/persagy/account/controller/SaasProductPageController.java
  7. 4 3
      saas-account/src/main/java/com/persagy/account/manage/SaasProductHandler.java
  8. 21 25
      saas-account/src/main/java/com/persagy/account/manage/SaasRoleMenuHandler.java
  9. 19 0
      saas-account/src/main/java/com/persagy/account/mapper/SaasProductCategeoryMapper.java
  10. 0 14
      saas-account/src/main/java/com/persagy/account/pojo/dto/SaasFunction.java
  11. 207 0
      saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProductCategeory.java
  12. 15 1
      saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProductPage.java
  13. 31 0
      saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProject.java
  14. 0 5
      saas-account/src/main/java/com/persagy/account/pojo/vo/function/SaasFunctionCreateVO.java
  15. 1 1
      saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuCreateVO.java
  16. 2 2
      saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuDeleteVO.java
  17. 3 0
      saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuSort.java
  18. 45 0
      saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductCategeoryQueryVO.java
  19. 5 5
      saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductCreateVO.java
  20. 3 3
      saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductPageCreateVO.java
  21. 4 3
      saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductPageTreeVO.java
  22. 9 0
      saas-account/src/main/java/com/persagy/account/pojo/vo/project/SaasProjectCreateVO.java
  23. 20 1
      saas-account/src/main/java/com/persagy/account/service/ISaasMenuService.java
  24. 17 0
      saas-account/src/main/java/com/persagy/account/service/ISaasProductCategeoryService.java
  25. 22 0
      saas-account/src/main/java/com/persagy/account/service/ISaasProductPageService.java
  26. 47 0
      saas-account/src/main/java/com/persagy/account/service/impl/SaasMenuServiceImpl.java
  27. 21 0
      saas-account/src/main/java/com/persagy/account/service/impl/SaasProductCategeoryServiceImpl.java
  28. 56 1
      saas-account/src/main/java/com/persagy/account/service/impl/SaasProductPageServiceImpl.java
  29. 4 5
      saas-account/src/main/resources/mapper/SaasFunctionMapper.xml
  30. 3 1
      saas-account/src/main/resources/mapper/SaasMenuMapper.xml
  31. 18 0
      saas-account/src/main/resources/mapper/SaasProductCategeoryMapper.xml
  32. 2 2
      saas-account/src/main/resources/mapper/SaasProductPageMapper.xml
  33. 4 1
      saas-account/src/main/resources/mapper/SaasProjectMapper.xml
  34. 4 1
      saas-common/src/main/java/com/persagy/common/constant/SaasCommonConstant.java
  35. 71 50
      saas-doc/doc/saas_platform.md
  36. BIN
      saas-doc/doc/运维管理3.0-数据库表设计.xlsx

+ 3 - 0
saas-account/src/main/java/com/persagy/account/config/ApplicationProperties.java

@@ -21,6 +21,9 @@ public class ApplicationProperties {
 	@Value("${saas.system.default-menu-id}")
 	private String defaultMenuId;
 	
+	@Value("${saas.system.default-product-icon}")
+	private String productIcon;
+	
 	@Value("${saas.rabitmq.enable:false}")
 	private boolean raabitmqEnable;
 	

+ 1 - 2
saas-account/src/main/java/com/persagy/account/controller/SaasFunctionController.java

@@ -47,7 +47,6 @@ import io.swagger.annotations.ApiOperation;
  * @author zhangqiankun
  * @date 2021-03-13 15:29:50
  */
-
 @Api(tags = "功能信息")
 @RestController
 @RequestMapping(value = "/function", method = RequestMethod.POST)
@@ -106,7 +105,7 @@ public class SaasFunctionController {
     	LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper()
     			.menuIdEq(queryVO.getMenuId()).funCodeEq(queryVO.getFunCode()).updateUserEq(queryVO.getUpdateUser())
     			.pageIdEq(queryVO.getPageId()).funNameLike(queryVO.getFunName()).builderQueryWrapper();
-    	queryWrapper.orderByAsc(SaasFunction::getFunSort);
+    	queryWrapper.orderByAsc(SaasFunction::getCreateTime);
     	List<SaasFunction> list = this.saasFunctionService.list(queryWrapper);
     	if (CollectionUtil.isEmpty(list)) {
 			return ResponseResultUtil.successResult(Lists.newArrayList(), 0L);

+ 22 - 20
saas-account/src/main/java/com/persagy/account/controller/SaasMenuController.java

@@ -1,9 +1,6 @@
 package com.persagy.account.controller;
 
-import java.util.ArrayList;
-import java.util.Comparator;
 import java.util.List;
-import java.util.stream.Collectors;
 
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -73,6 +70,7 @@ public class SaasMenuController {
     	LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper()
     			.appIdEq(queryVO.getAppId()).menuTypeEq(queryVO.getMenuType()).builderQueryWrapper();
     	queryWrapper.apply("(PARENT_ID IS NULL OR TRIM(PARENT_ID) = '')");
+    	queryWrapper.orderByAsc(SaasMenu::getMenuSort);		// 默认菜单升序排序
     	List<SaasMenu> menuTree = this.saasMenuService.list(queryWrapper);
     	return ResponseResultUtil.successResult(menuTree);
     }
@@ -89,22 +87,15 @@ public class SaasMenuController {
     	// 这里按照超管的逻辑进行处理,因为不会做权限过滤
 		LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().idEq(queryVO.getMenuId())
 				.menuTypeEq(queryVO.getMenuType()).appIdEq(queryVO.getAppId()).builderQueryWrapper();
-		List<SaasMenu> menuTree = this.saasMenuService.list(queryWrapper);
-		if (CollectionUtil.isEmpty(menuTree)) {
+		queryWrapper.apply("(PARENT_ID IS NULL OR TRIM(PARENT_ID) = '')");
+		queryWrapper.orderByAsc(SaasMenu::getMenuSort);		// 默认菜单升序排序
+		List<SaasMenu> topList = this.saasMenuService.list(queryWrapper);
+		if (CollectionUtil.isEmpty(topList)) {
 			return ResponseResultUtil.successResult(Lists.newArrayList());
 		}
 		// 2.转为菜单树
-		List<SaasMenu> topMenus = new ArrayList<SaasMenu>();
-		for (int i = menuTree.size() - 1; i >= 0; i--) {
-			SaasMenu saasMenu = menuTree.get(i);
-			if (StringUtil.isBlank(saasMenu.getParentId())) {
-				topMenus.add(saasMenu);
-				menuTree.remove(i);
-			}
-		}
-		List<SaasMenu> parents = topMenus.stream().sorted(Comparator.comparing(SaasMenu::getMenuSort)).collect(Collectors.toList());
-		this.saasRoleMenuHandler.setMenuChildrens(null, queryVO.getGroupCode(), queryVO.getProjectId(), menuTree, parents, true, !queryVO.isMenu());
-    	return ResponseResultUtil.successResult(parents);
+		this.saasRoleMenuHandler.setMenuChildrens(null, queryVO.getGroupCode(), queryVO.getProjectId(), null, topList, true, !queryVO.isMenu());
+    	return ResponseResultUtil.successResult(topList);
     }
     
     /**
@@ -117,7 +108,7 @@ public class SaasMenuController {
 			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "当菜单URL存在时,URL类型不可为空");
 		}
 		// 应用下菜单编码唯一
-		ResponseResult validRequestParam = this.validRequestParam(createVO.getAppId(), createVO.getMenuCode(), null);
+		ResponseResult validRequestParam = this.validRequestParam(createVO.getAppId(), createVO.getMenuCode(), createVO.getMenuName(), null);
 		if (validRequestParam != null) {
 			return validRequestParam;
 		}
@@ -141,15 +132,20 @@ public class SaasMenuController {
 		if (StringUtil.isNotBlank(createVO.getMenuUrl()) && StringUtil.isEmpty(createVO.getUrlType())) {
 			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "当菜单URL存在时,URL类型不可为空");
 		}
+		// 验证菜单是否存在
+		SaasMenu menu = this.saasMenuService.getById(createVO.getId());
+		if (menu == null) {
+			return ResponseResultUtil.errorResult(ResponseCode.C0320.getCode(), "不存在此菜单");
+		}
 		// 应用下菜单编码唯一
-		ResponseResult validRequestParam = this.validRequestParam(createVO.getAppId(), createVO.getMenuCode(), createVO.getId());
+		ResponseResult validRequestParam = this.validRequestParam(createVO.getAppId(), createVO.getMenuCode(), createVO.getMenuName(), createVO.getId());
 		if (validRequestParam != null) {
 			return validRequestParam;
 		}
 		SaasMenu saasMenu = new SaasMenu();
 		BeanUtils.copyProperties(createVO, saasMenu);
 		saasMenu.setUpdateUser(createVO.getAccountId());
-        boolean result = saasMenuService.updateById(saasMenu);
+		boolean result = this.saasMenuService.updateSaasMenu(saasMenu, menu.getProductId());
         return result ? ResponseResultUtil.successResult("更新成功") : ResponseResultUtil.errorResult("更新失败");
     }
 
@@ -195,7 +191,7 @@ public class SaasMenuController {
      * 
      * @return
      */
-    private ResponseResult validRequestParam(String appId, String menuCode, String menuId) {
+    private ResponseResult validRequestParam(String appId, String menuCode, String menuName, String menuId) {
     	if (StringUtil.isBlank(appId)) {
 			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "应用ID,不可为空");
 		}
@@ -205,6 +201,12 @@ public class SaasMenuController {
 				return ResponseResultUtil.errorResult(ResponseCode.A0402.getCode(), "此编码已存在");
 			}
 		}
+		if (StringUtil.isNotBlank(menuName)) {
+			boolean validMenuName = this.saasMenuService.validMenuName(appId, menuName, menuId);
+			if (!validMenuName) {
+				return ResponseResultUtil.errorResult(ResponseCode.A0402.getCode(), "此名称已存在");
+			}
+		}
     	return null;
     }
 }

+ 103 - 0
saas-account/src/main/java/com/persagy/account/controller/SaasProductCategeoryController.java

@@ -0,0 +1,103 @@
+package com.persagy.account.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.collect.Lists;
+import com.persagy.account.pojo.dto.SaasProductCategeory;
+import com.persagy.account.pojo.vo.product.SaasProductCategeoryQueryVO;
+import com.persagy.account.service.ISaasProductCategeoryService;
+import com.persagy.common.utils.ResponseResult;
+import com.persagy.common.utils.ResponseResultUtil;
+
+import cn.hutool.core.collection.CollectionUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * 产品信息
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021-05-11 19:23:03
+ */
+
+@Api(tags = "产品类别信息")
+@RestController
+@RequestMapping(value = "/productCategeory", method = RequestMethod.POST)
+public class SaasProductCategeoryController {
+	
+    @Autowired
+    private ISaasProductCategeoryService saasProductCategeoryService;
+    
+    /**
+     * 列表查询
+     */
+    @ApiOperation(value = "产品类别树查询")
+    @RequestMapping(value = "querySaasProductCategeoryTree")
+    public ResponseResult querySaasProductCategeoryTree(@RequestBody @Validated SaasProductCategeoryQueryVO model) {
+    	LambdaQueryWrapper<SaasProductCategeory> queryWrapper = new SaasProductCategeory.BuilderQueryWrapper()
+    			.categoryNameLike(model.getCategoryName()).idEq(model.getId()).menuTypeEq(model.getMenuType())
+    			.productTypeEq(model.getProductType()).terminalEq(model.getTerminal()).builder();
+    	queryWrapper.apply("(PARENT_ID IS NULL OR TRIM(PARENT_ID) = '')");
+    	List<SaasProductCategeory> topList = this.saasProductCategeoryService.list(queryWrapper.orderByAsc(SaasProductCategeory::getCreateTime));
+    	if (CollectionUtil.isEmpty(topList)) {
+			return ResponseResultUtil.successResult(Lists.newArrayList());
+		}
+    	this.querySaasProductCategeoryTree(topList);
+        return ResponseResultUtil.successResult(topList);
+    }
+    
+    /**
+     * 获取产品类别树
+     * @param list
+     */
+    private void querySaasProductCategeoryTree(List<SaasProductCategeory> list) {
+		for (SaasProductCategeory categeory : list) {
+			LambdaQueryWrapper<SaasProductCategeory> queryWrapper = new SaasProductCategeory.BuilderQueryWrapper().parentIdEq(categeory.getId()).builder();
+	    	List<SaasProductCategeory> nextList = this.saasProductCategeoryService.list(queryWrapper.orderByAsc(SaasProductCategeory::getCreateTime));
+	    	nextList = CollectionUtil.isEmpty(nextList) ? Lists.newArrayList() : nextList;
+	    	categeory.setChildrens(nextList);
+			this.querySaasProductCategeoryTree(nextList);
+		}
+	}
+
+    /**
+     * 新增
+     */
+	@ApiOperation(value = "保存")
+	@RequestMapping(value = "createSaasProductCategeory")
+    public ResponseResult createSaasProductCategeory(@RequestBody SaasProductCategeory saasProductCategeory) {
+        boolean result = this.saasProductCategeoryService.save(saasProductCategeory);
+        return result ? ResponseResultUtil.successResult("保存成功", saasProductCategeory.getId()) : ResponseResultUtil.errorResult("保存失败");
+    }
+    
+    /**
+     * 更新
+     */
+	@ApiOperation(value = "更新")
+	@RequestMapping(value = "updateSaasProductCategeory")
+    public ResponseResult updateSaasProductCategeory(@RequestBody SaasProductCategeory saasProductCategeory) {
+        boolean result = this.saasProductCategeoryService.updateById(saasProductCategeory);
+        return result ? ResponseResultUtil.successResult("更新成功") : ResponseResultUtil.errorResult("更新失败");
+    }
+
+    /**
+     * 物理删除
+     */
+    @ApiOperation(value = "删除")
+    @RequestMapping(value = "deleteSaasProductCategeory")
+    public ResponseResult deleteSaasProductCategeory(@RequestBody SaasProductCategeory saasProductCategeory) {
+        boolean result = this.saasProductCategeoryService.removeById(saasProductCategeory.getId());
+        return result ? ResponseResultUtil.successResult("删除成功") : ResponseResultUtil.errorResult("删除失败");
+    }
+    
+}

+ 19 - 6
saas-account/src/main/java/com/persagy/account/controller/SaasProductController.java

@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.google.common.collect.Lists;
+import com.persagy.account.config.ApplicationProperties;
 import com.persagy.account.pojo.dto.SaasProduct;
 import com.persagy.account.pojo.vo.product.SaasProductCreateVO;
 import com.persagy.account.pojo.vo.product.SaasProductPageVO;
@@ -41,6 +42,9 @@ import io.swagger.annotations.ApiOperation;
 @RequestMapping(value = "/product", method = RequestMethod.POST)
 public class SaasProductController {
 	
+	@Autowired
+	private ApplicationProperties properties;
+	
     @Autowired
     private ISaasProductService saasProductService;
     
@@ -91,9 +95,12 @@ public class SaasProductController {
 			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "应用ID,不可为空"); 
 		}
 		// 验证产品名称、产品编码的唯一性
-		boolean result = this.saasProductService.validProductCode(model.getProductCode(), null);
-		if (!result) {
-			return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "产品编码已存在");
+		boolean result = false;
+		if (StringUtil.isNotBlank(model.getProductCode())) {
+			result = this.saasProductService.validProductCode(model.getProductCode(), null);
+			if (!result) {
+				return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "产品编码已存在");
+			}
 		}
 		result = this.saasProductService.validProductName(model.getProductName(), null);
 		if (!result) {
@@ -103,6 +110,9 @@ public class SaasProductController {
 		BeanUtils.copyProperties(model, saasProduct);
 		saasProduct.setUpdateUser(model.getAccountId());
 		saasProduct.setId(null);
+		if (StringUtil.isBlank(saasProduct.getProductIcon())) {
+			saasProduct.setProductIcon(properties.getProductIcon());
+		}
         result = this.saasProductService.save(saasProduct);
         return result ? ResponseResultUtil.successResult("保存成功", saasProduct.getId()) : ResponseResultUtil.errorResult("保存失败");
     }
@@ -120,9 +130,12 @@ public class SaasProductController {
 			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "应用ID,不可为空"); 
 		}
 		// 验证产品名称、产品编码的唯一性
-		boolean result = this.saasProductService.validProductCode(model.getProductCode(), model.getId());
-		if (!result) {
-			return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "产品编码已存在");
+		boolean result = false;
+		if (StringUtil.isNotBlank(model.getProductCode())) {
+			result = this.saasProductService.validProductCode(model.getProductCode(), null);
+			if (!result) {
+				return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "产品编码已存在");
+			}
 		}
 		result = this.saasProductService.validProductName(model.getProductName(), model.getId());
 		if (!result) {

+ 22 - 9
saas-account/src/main/java/com/persagy/account/controller/SaasProductPageController.java

@@ -10,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.google.common.collect.Lists;
 import com.persagy.account.manage.SaasProductHandler;
 import com.persagy.account.pojo.dto.SaasProduct;
 import com.persagy.account.pojo.dto.SaasProductPage;
@@ -24,6 +26,7 @@ import com.persagy.common.utils.ResponseResult;
 import com.persagy.common.utils.ResponseResultUtil;
 import com.persagy.common.utils.StringUtil;
 
+import cn.hutool.core.collection.CollectionUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
@@ -56,14 +59,17 @@ public class SaasProductPageController {
 	@RequestMapping(value = "querySaasProductPageTree")
 	public ResponseResult querySaasProductPageTree(@RequestBody @Validated SaasProductPageTreeVO treeVO) {
 		// 验证产品信息是否存在
-		SaasProduct saasProduct = this.saasProductService.getById(treeVO.getProductId());
-		if (saasProduct == null) {
-			return ResponseResultUtil.errorResult(ResponseCode.A0400.getCode(), "产品信息不存在");
+		LambdaQueryWrapper<SaasProduct> queryWrapper = new SaasProduct.BuilderQueryWrapper().appIdEq(treeVO.getAppId()).idEq(treeVO.getProductId()).productTypeEq(treeVO.getProductType()).builder();
+		List<SaasProduct> saasProducts = this.saasProductService.list(queryWrapper);
+		if (CollectionUtil.isEmpty(saasProducts)) {
+			return ResponseResultUtil.successResult(Lists.newArrayList());
 		}
 		// 获取该产品的下级页面权限信息,按照超管逻辑处理
-		List<SaasProductPage> pageList = this.saasProductHandler.querySaasProductPageTree(treeVO.getAngle(), treeVO.getProductId(), null, null, true, treeVO.isShowPageAuth());
-		saasProduct.setProductPages(pageList);
-		return ResponseResultUtil.successResult(saasProduct);
+		for (SaasProduct saasProduct : saasProducts) {
+			List<SaasProductPage> pageList = this.saasProductHandler.querySaasProductPageTree(treeVO.getAngle(), treeVO.getProductId(), null, null, true, treeVO.isShowPageAuth());
+			saasProduct.setProductPages(pageList);
+		}
+		return ResponseResultUtil.successResult(saasProducts);
 	}
 
 	/**
@@ -77,12 +83,15 @@ public class SaasProductPageController {
 		if (saasProduct == null) {
 			return ResponseResultUtil.errorResult(ResponseCode.C0320.getCode(), "产品信息不存在");
 		}
+		boolean result = this.saasProductPageService.validPageName(model.getPageName(), null);
+		if (!result) {
+			return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "页面名称已存在");
+		}
 		SaasProductPage saasProductPage = new SaasProductPage();
 		BeanUtils.copyProperties(model, saasProductPage);
 		saasProductPage.setId(null);
 		saasProductPage.setUpdateUser(model.getAccountId());
-		
-		boolean result = this.saasProductPageService.save(saasProductPage);
+		result = this.saasProductPageService.createSaasProductPage(saasProductPage);
 		return result ? ResponseResultUtil.successResult("保存成功", saasProductPage.getId()) : ResponseResultUtil.errorResult("保存失败");
 	}
 
@@ -100,11 +109,15 @@ public class SaasProductPageController {
 		if (saasProduct == null) {
 			return ResponseResultUtil.errorResult(ResponseCode.C0320.getCode(), "产品信息不存在");
 		}
+		boolean result = this.saasProductPageService.validPageName(model.getPageName(), model.getId());
+		if (!result) {
+			return ResponseResultUtil.errorResult(ResponseCode.C0341.getCode(), "页面名称已存在");
+		}
 		SaasProductPage saasProductPage = new SaasProductPage();
 		BeanUtils.copyProperties(model, saasProductPage);
 		saasProductPage.setUpdateUser(model.getAccountId());
 		
-		boolean result = this.saasProductPageService.updateById(saasProductPage);
+		result = this.saasProductPageService.updateSaasProductPage(saasProductPage);
 		return result ? ResponseResultUtil.successResult("更新成功") : ResponseResultUtil.errorResult("更新失败");
 	}
 

+ 4 - 3
saas-account/src/main/java/com/persagy/account/manage/SaasProductHandler.java

@@ -70,7 +70,7 @@ public class SaasProductHandler {
 				// 未挂有产品,关联查询出对应的功能点集合,即可返回
 				if (isAdmin) {
 					LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper().menuIdEq(saasMenu.getMenuId()).builderQueryWrapper();
-					functions = this.saasFunctionService.list(queryWrapper.orderByAsc(SaasFunction::getFunSort));
+					functions = this.saasFunctionService.list(queryWrapper.orderByAsc(SaasFunction::getCreateTime));
 				} else {
 					functions = this.saasFunctionService.queryAccountFunctionList(accountId, saasMenu.getGroupCode(), saasMenu.getMenuId());
 				}
@@ -118,7 +118,7 @@ public class SaasProductHandler {
 			List<SaasFunction> functions = null;
 			if (isAdmin) {
 				LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper().menuIdEq(menuId).builderQueryWrapper();
-				functions = this.saasFunctionService.list(queryWrapper.orderByAsc(SaasFunction::getFunSort));
+				functions = this.saasFunctionService.list(queryWrapper.orderByAsc(SaasFunction::getCreateTime));
 			} else {
 				functions = this.saasFunctionService.queryAccountFunctionList(accountId, groupCode, menuId);
 			}
@@ -170,7 +170,8 @@ public class SaasProductHandler {
 	 */
 	public List<SaasProductPage> getTopProductPageList(String angle, String productId) {
 		LambdaQueryWrapper<SaasProductPage> queryWrapper = new SaasProductPage.BuilderQueryWrapper().pageAngleIn(angle).productIdEq(productId).builder();
-		queryWrapper.last("AND (PARENT_ID IS NULL OR TRIM(PARENT_ID) = '')");
+		queryWrapper.apply("(PARENT_ID IS NULL OR TRIM(PARENT_ID) = '')");
+		queryWrapper.orderByAsc(SaasProductPage::getCreateTime);
 		List<SaasProductPage> topList = this.saasProductPageService.list(queryWrapper);
 		return CollectionUtil.isEmpty(topList) ? Lists.newArrayList() : topList;
 	}

+ 21 - 25
saas-account/src/main/java/com/persagy/account/manage/SaasRoleMenuHandler.java

@@ -12,9 +12,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.common.collect.Lists;
-import com.persagy.common.constant.SaasCommonConstant;
-import com.persagy.common.exception.BusinessException;
-import com.persagy.common.utils.StringUtil;
 import com.persagy.account.pojo.dto.SaasAccountRole;
 import com.persagy.account.pojo.dto.SaasFunction;
 import com.persagy.account.pojo.dto.SaasMenu;
@@ -31,6 +28,9 @@ import com.persagy.account.service.ISaasMenuService;
 import com.persagy.account.service.ISaasProductService;
 import com.persagy.account.service.ISaasRoleMenuService;
 import com.persagy.account.service.ISaasRoleService;
+import com.persagy.common.constant.SaasCommonConstant;
+import com.persagy.common.exception.BusinessException;
+import com.persagy.common.utils.StringUtil;
 
 import cn.hutool.core.collection.CollectionUtil;
 
@@ -138,7 +138,7 @@ public class SaasRoleMenuHandler {
 	 * @param accountId 为null时,isAdmin 为true
 	 * @param angle 1-集团视角,2-项目视角
 	 * @param groupCode
-	 * @param menuTree
+	 * @param menuTree 为空时,会去查询,但是不会做权限过滤
 	 * @param parents
 	 * @param isAdmin 是否为超管 true-是
 	 * @param menuAndFun 
@@ -150,30 +150,26 @@ public class SaasRoleMenuHandler {
 			}
 			if (StringUtil.isNotBlank(parent.getMenuUrl())) {
 				this.saasProductHandler.queryMenuProductAuths(parent, accountId, groupCode, projectId, isAdmin, menuAndFun);
-				
-				// 查询出对应功能点集合
-				List<SaasFunction> functions = null;
-				if (isAdmin) {
-					LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper().menuIdEq(parent.getMenuId()).builderQueryWrapper();
-					functions = this.saasFunctionService.list(queryWrapper.orderByAsc(SaasFunction::getFunSort));
-				} else {
-					functions = this.saasFunctionService.queryAccountFunctionList(accountId, parent.getGroupCode(), parent.getMenuId());
-				}
-				parent.setFunctions(CollectionUtil.isEmpty(functions) ? Lists.newArrayList() : functions);
 			}
 			
-			List<SaasMenu> childrens = new ArrayList<SaasMenu>();
-			for (int i = menuTree.size() - 1; i >= 0; i--) {
-				SaasMenu saasMenu = menuTree.get(i);
-				if (parent.getMenuId().equals(saasMenu.getParentId())) {
-					childrens.add(saasMenu);
-					menuTree.remove(i);
+			List<SaasMenu> childrens = null;
+			if (menuTree == null) {
+				LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().parentIdEq(parent.getId())
+						.menuTypeEq(parent.getMenuType()).appIdEq(parent.getAppId()).builderQueryWrapper();
+				childrens = this.saasMenuService.list(queryWrapper.orderByAsc(SaasMenu::getMenuSort));
+				childrens = CollectionUtil.isEmpty(childrens) ? Lists.newArrayList() : childrens;
+			} else {
+				childrens = new ArrayList<SaasMenu>();
+				for (int i = menuTree.size() - 1; i >= 0; i--) {
+					SaasMenu saasMenu = menuTree.get(i);
+					if (parent.getMenuId().equals(saasMenu.getParentId())) {
+						childrens.add(saasMenu);
+						menuTree.remove(i);
+					}
 				}
 			}
-			
-			List<SaasMenu> nextTops = childrens.stream().sorted(Comparator.comparing(SaasMenu::getMenuSort)).collect(Collectors.toList());
-			parent.setChildrens(nextTops);
-			this.setMenuChildrens(accountId, groupCode, projectId, menuTree, nextTops, isAdmin, menuAndFun);
+			parent.setChildrens(childrens);
+			this.setMenuChildrens(accountId, groupCode, projectId, menuTree, childrens, isAdmin, menuAndFun);
 		}
 	}
 	
@@ -236,7 +232,7 @@ public class SaasRoleMenuHandler {
 	@Transactional
 	public boolean deleteSaasFunction(String funId) {
 		LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper().idEq(funId).builderQueryWrapper();
-		boolean result = this.saasFunctionService.removeById(queryWrapper);
+		boolean result = this.saasFunctionService.remove(queryWrapper);
 		if (result) {
 			// 1.删除此功能对应的菜单、角色关系数据
 			LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().functionIdEq(funId).builderQueryWrapper();

+ 19 - 0
saas-account/src/main/java/com/persagy/account/mapper/SaasProductCategeoryMapper.java

@@ -0,0 +1,19 @@
+package com.persagy.account.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.persagy.account.pojo.dto.SaasProductCategeory;
+
+/**
+ * 产品信息
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021-05-11 19:23:03
+ */
+@Mapper
+public interface SaasProductCategeoryMapper extends BaseMapper<SaasProductCategeory> {
+
+}

+ 0 - 14
saas-account/src/main/java/com/persagy/account/pojo/dto/SaasFunction.java

@@ -50,9 +50,6 @@ public class SaasFunction extends BaseEntity<SaasFunction> {
 	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
 	private String funUrl;	//功能URL
 
-	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
-	private Integer funSort; // 功能顺序
-
 	@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NOT_EMPTY)
 	private Date createTime; // 创建时间
 
@@ -161,17 +158,6 @@ public class SaasFunction extends BaseEntity<SaasFunction> {
 			return this;
 		}
 
-		public Builder funSortEq(Integer funSort) {
-			if (null != funSort) {
-				if (updateWrapper != null) {
-					updateWrapper.eq(SaasFunction::getFunSort, funSort);
-				} else {
-					queryWrapper.eq(SaasFunction::getFunSort, funSort);
-				}
-			}
-			return this;
-		}
-
 		public Builder createTimeEq(Date createTime) {
 			if (null != createTime) {
 				if (updateWrapper != null) {

+ 207 - 0
saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProductCategeory.java

@@ -0,0 +1,207 @@
+package com.persagy.account.pojo.dto;
+
+import java.util.Date;
+import java.util.List;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.persagy.common.annotation.IdGeneratorPrefix;
+import com.persagy.common.constant.SaasCommonConstant;
+import com.persagy.common.model.BaseEntity;
+import com.persagy.common.utils.StringUtil;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 产品信息
+ * 
+ * @version 1.0.0
+ * @company persagy
+ * @author zhangqiankun
+ * @date 2021-05-11 19:23:03
+ */
+@Getter
+@Setter
+@ToString
+@EqualsAndHashCode(callSuper = false)
+@TableName("saas_product_categeory")
+@IdGeneratorPrefix(SaasCommonConstant.SAAS_PRODUCT_CATEGEORY_ID_PREFIX)
+public class SaasProductCategeory extends BaseEntity<SaasProductCategeory> {
+	private static final long serialVersionUID = 8965388764057710104L;
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String parentId; // 上级ID
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String categoryName; // 类别名称
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String categoryIcon; // 类别图标
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String terminal; // 类别所属终端
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String terminalName; // 类别所属终端名称
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String productType; // 此类别所对应的产品类型
+
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String menuType; // 此类别所对应的菜单类型
+	
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private Date createTime;	// 创建时间
+	
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String remark;	// 备注
+	
+	@TableField(exist = false)
+	private List<SaasProductCategeory> childrens;	//资料
+
+	public static class BuilderQueryWrapper {
+
+		private LambdaQueryWrapper<SaasProductCategeory> queryWrapper = new LambdaQueryWrapper<SaasProductCategeory>();
+
+		public BuilderQueryWrapper idEq(String id) {
+			if (StringUtil.isNotBlank(id)) {
+				queryWrapper.eq(SaasProductCategeory::getId, id);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper parentIdEq(String parentId) {
+			if (StringUtil.isNotBlank(parentId)) {
+				queryWrapper.eq(SaasProductCategeory::getParentId, parentId);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper categoryNameEq(String categoryName) {
+			if (StringUtil.isNotBlank(categoryName)) {
+				queryWrapper.eq(SaasProductCategeory::getCategoryName, categoryName);
+			}
+			return this;
+		}
+		
+		public BuilderQueryWrapper categoryNameLike(String categoryName) {
+			if (StringUtil.isNotBlank(categoryName)) {
+				queryWrapper.like(SaasProductCategeory::getCategoryName, categoryName);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper categoryIconEq(String categoryIcon) {
+			if (StringUtil.isNotBlank(categoryIcon)) {
+				queryWrapper.eq(SaasProductCategeory::getCategoryIcon, categoryIcon);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper terminalEq(String terminal) {
+			if (StringUtil.isNotBlank(terminal)) {
+				queryWrapper.eq(SaasProductCategeory::getTerminal, terminal);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper terminalNameEq(String terminalName) {
+			if (StringUtil.isNotBlank(terminalName)) {
+				queryWrapper.eq(SaasProductCategeory::getTerminalName, terminalName);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper productTypeEq(String productType) {
+			if (StringUtil.isNotBlank(productType)) {
+				queryWrapper.eq(SaasProductCategeory::getProductType, productType);
+			}
+			return this;
+		}
+
+		public BuilderQueryWrapper menuTypeEq(String menuType) {
+			if (StringUtil.isNotBlank(menuType)) {
+				queryWrapper.eq(SaasProductCategeory::getMenuType, menuType);
+			}
+			return this;
+		}
+
+		public LambdaQueryWrapper<SaasProductCategeory> builder() {
+			return queryWrapper;
+		}
+
+	}
+
+	public static class BuilderUpdateWrapper {
+
+		private LambdaUpdateWrapper<SaasProductCategeory> updateWrapper = new LambdaUpdateWrapper<SaasProductCategeory>();
+
+		public BuilderUpdateWrapper idEq(String id) {
+			if (StringUtil.isNotBlank(id)) {
+				updateWrapper.eq(SaasProductCategeory::getId, id);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper parentIdEq(String parentId) {
+			if (StringUtil.isNotBlank(parentId)) {
+				updateWrapper.eq(SaasProductCategeory::getParentId, parentId);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper categoryNameEq(String categoryName) {
+			if (StringUtil.isNotBlank(categoryName)) {
+				updateWrapper.eq(SaasProductCategeory::getCategoryName, categoryName);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper categoryIconEq(String categoryIcon) {
+			if (StringUtil.isNotBlank(categoryIcon)) {
+				updateWrapper.eq(SaasProductCategeory::getCategoryIcon, categoryIcon);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper terminalEq(String terminal) {
+			if (StringUtil.isNotBlank(terminal)) {
+				updateWrapper.eq(SaasProductCategeory::getTerminal, terminal);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper terminalNameEq(String terminalName) {
+			if (StringUtil.isNotBlank(terminalName)) {
+				updateWrapper.eq(SaasProductCategeory::getTerminalName, terminalName);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper productTypeEq(String productType) {
+			if (StringUtil.isNotBlank(productType)) {
+				updateWrapper.eq(SaasProductCategeory::getProductType, productType);
+			}
+			return this;
+		}
+
+		public BuilderUpdateWrapper menuTypeEq(String menuType) {
+			if (StringUtil.isNotBlank(menuType)) {
+				updateWrapper.eq(SaasProductCategeory::getMenuType, menuType);
+			}
+			return this;
+		}
+
+		public LambdaUpdateWrapper<SaasProductCategeory> builder() {
+			return updateWrapper;
+		}
+
+	}
+	
+}

+ 15 - 1
saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProductPage.java

@@ -59,7 +59,7 @@ public class SaasProductPage extends BaseEntity<SaasProductPage> {
 	private String pageFloor; // 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页
 
 	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
-	private Integer pageSort;	// 页面顺序
+	private Integer pageLevel;	// 页面层级
 	
 	@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NOT_EMPTY)
 	private Date createTime; // 创建时间
@@ -149,6 +149,13 @@ public class SaasProductPage extends BaseEntity<SaasProductPage> {
 			}
 			return this;
 		}
+		
+		public BuilderQueryWrapper pageLevelEq(String pageLevel) {
+			if (StringUtil.isNotBlank(pageLevel)) {
+				queryWrapper.eq(SaasProductPage::getPageLevel, pageLevel);
+			}
+			return this;
+		}
 
 		public BuilderQueryWrapper createTimeEq(Date createTime) {
 			if (null != createTime) {
@@ -255,6 +262,13 @@ public class SaasProductPage extends BaseEntity<SaasProductPage> {
 			return this;
 		}
 
+		public BuilderUpdateWrapper pageLevelEq(String pageLevel) {
+			if (StringUtil.isNotBlank(pageLevel)) {
+				updateWrapper.eq(SaasProductPage::getPageLevel, pageLevel);
+			}
+			return this;
+		}
+		
 		public BuilderUpdateWrapper createTimeEq(Date createTime) {
 			if (null != createTime) {
 				updateWrapper.eq(SaasProductPage::getCreateTime, createTime);

+ 31 - 0
saas-account/src/main/java/com/persagy/account/pojo/dto/SaasProject.java

@@ -67,6 +67,15 @@ public class SaasProject extends BaseEntity<SaasProject> {
 	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
 	private Date openTime;	//项目开业时间
 	
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String projectFun;		//项目功能
+	
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String projectWeather;	//项目天气
+	
+	@TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
+	private String projectImage;	//项目图标,多个之间,用逗号分隔
+	
 	@TableField(fill = FieldFill.INSERT, updateStrategy = FieldStrategy.NOT_EMPTY)
 	private Date createTime; 	// 创建时间
 
@@ -250,6 +259,28 @@ public class SaasProject extends BaseEntity<SaasProject> {
 			return this;
 		}
 		
+		public Builder projectFunEq(String projectFun) {
+			if (StringUtil.isNotBlank(projectFun)) {
+				if (updateWrapper != null) {
+					updateWrapper.eq(SaasProject::getProjectFun, projectFun);
+				} else {
+					queryWrapper.eq(SaasProject::getProjectFun, projectFun);
+				}
+			}
+			return this;
+		}
+		
+		public Builder projectWeatherEq(String projectWeather) {
+			if (StringUtil.isNotBlank(projectWeather)) {
+				if (updateWrapper != null) {
+					updateWrapper.eq(SaasProject::getProjectWeather, projectWeather);
+				} else {
+					queryWrapper.eq(SaasProject::getProjectWeather, projectWeather);
+				}
+			}
+			return this;
+		}
+		
 		public Builder createTimeEq(Date createTime) {
 			if (null != createTime) {
 				if (updateWrapper != null) {

+ 0 - 5
saas-account/src/main/java/com/persagy/account/pojo/vo/function/SaasFunctionCreateVO.java

@@ -1,7 +1,6 @@
 package com.persagy.account.pojo.vo.function;
 
 import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
 
 import com.persagy.common.model.BaseUserModel;
 
@@ -47,10 +46,6 @@ public class SaasFunctionCreateVO extends BaseUserModel {
 	@ApiModelProperty(value = "功能URL", example = "http://127.0.0.1:8080/test.png")
 	private String funUrl;	// 功能URL
 
-	@NotNull(message = "功能顺序,不可为空")
-	@ApiModelProperty(value = "功能顺序", example = "1")
-	private Integer funSort; // 功能顺序
-
 	@ApiModelProperty(value = "备注", example = "测试功能点")
 	private String remark; // 备注
 

+ 1 - 1
saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuCreateVO.java

@@ -39,7 +39,7 @@ public class SaasMenuCreateVO extends BaseUserModel {
 	@ApiModelProperty(value = "菜单编码", example = "ceshi", required = true)
 	private String menuCode; // 菜单编码
 	
-	@NotBlank(message = "菜单名称,不可为空")
+	//@NotBlank(message = "菜单名称,不可为空")
 	@ApiModelProperty(value = "菜单名称", example = "测试菜单", required = true)
 	private String menuName; // 菜单名称
 

+ 2 - 2
saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuDeleteVO.java

@@ -2,7 +2,7 @@ package com.persagy.account.pojo.vo.menu;
 
 import javax.validation.constraints.NotBlank;
 
-import com.persagy.common.model.BaseGroupModel;
+import com.persagy.account.pojo.vo.BaseGroupVO;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -22,7 +22,7 @@ import lombok.ToString;
 @Setter
 @ToString
 @ApiModel
-public class SaasMenuDeleteVO extends BaseGroupModel {
+public class SaasMenuDeleteVO extends BaseGroupVO {
 
 	@NotBlank(message = "菜单ID,不可为空")
 	@ApiModelProperty(value = "菜单ID", example = "123456")

+ 3 - 0
saas-account/src/main/java/com/persagy/account/pojo/vo/menu/SaasMenuSort.java

@@ -25,6 +25,9 @@ public class SaasMenuSort {
 	@ApiModelProperty(value = "菜单ID", example = "123456", required = true)
 	private String menuId;
 	
+	@ApiModelProperty(value = "上级菜单ID", example = "123456")
+	private String parentId;	// 上级菜单ID
+	
 	@NotBlank(message = "菜单顺序,不可为空")
 	@ApiModelProperty(value = "菜单顺序", example = "1", required = true)
 	private Integer menuSort;

+ 45 - 0
saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductCategeoryQueryVO.java

@@ -0,0 +1,45 @@
+package com.persagy.account.pojo.vo.product;
+
+import com.persagy.common.model.BaseUserModel;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021年5月11日 下午7:30:05
+ */
+@Getter
+@Setter
+@ApiModel
+@ToString
+public class SaasProductCategeoryQueryVO extends BaseUserModel {
+	
+	@ApiModelProperty(value = "类别ID", example = "PD1001")
+	private String id; // ID
+	
+	@ApiModelProperty(value = "上级ID", example = "PD1001")
+	private String parentId; // 上级ID
+
+	@ApiModelProperty(value = "类别名称", example = "PD1001")
+	private String categoryName; // 类别名称
+
+	@ApiModelProperty(value = "终端", example = "PD1001")
+	private String terminal; // 类别所属终端
+
+	@ApiModelProperty(value = "终端名称", example = "PD1001")
+	private String terminalName; // 类别所属终端名称
+
+	@ApiModelProperty(value = "产品类型", example = "PD1001")
+	private String productType; // 此类别所对应的产品类型
+
+	@ApiModelProperty(value = "菜单类型", example = "PD1001")
+	private String menuType; // 此类别所对应的菜单类型
+	
+}

+ 5 - 5
saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductCreateVO.java

@@ -26,23 +26,23 @@ public class SaasProductCreateVO extends BaseUserModel {
 	@ApiModelProperty(value = "产品ID,更新时不可为空", example = "1001")
 	private String id; 		// 产品id
 
-	@NotBlank(message = "产品编码,不可为空")
+	//@NotBlank(message = "产品编码,不可为空")
 	@ApiModelProperty(value = "产品编码", required = true, example = "1001")
 	private String productCode; // 产品编码
 
-	@NotBlank(message = "产品编码,不可为空")
+	@NotBlank(message = "产品名称,不可为空")
 	@ApiModelProperty(value = "产品名称", required = true, example = "chanpin")
 	private String productName; // 产品名称
 
-	@NotBlank(message = "产品图标,不可为空")
+	//@NotBlank(message = "产品图标,不可为空")
 	@ApiModelProperty(value = "产品图标", required = true, example = "chanpin")
 	private String productIcon; // 产品图标
 	
-	@NotBlank(message = "产品编码,不可为空")
+	@NotBlank(message = "产品状态,不可为空")
 	@ApiModelProperty(value = "产品状态,0-建设中,1-已完成,2-已关联", required = true, example = "0")
 	private String productState; // 产品状态,0-建设中,1-已完成,2-已关联
 
-	@NotBlank(message = "产品编码,不可为空")
+	@NotBlank(message = "产品是否关联菜单,不可为空")
 	@ApiModelProperty(value = "产品是否关联菜单,0-未关联,1-已关联", required = true, example = "0")
 	private String productMenu; // 产品是否关联菜单,0-未关联,1-已关联
 

+ 3 - 3
saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductPageCreateVO.java

@@ -52,9 +52,9 @@ public class SaasProductPageCreateVO extends BaseUserModel {
 	@ApiModelProperty(value = "是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页,默认0", example = "1001", required = true)
 	private String pageFloor = SaasCommonConstant.STR_STATUS_0; // 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页
 	
-	@NotNull(message = "页面顺序,不可为空")
-	@ApiModelProperty(value = "页面顺序", example = "1", required = true)
-	private Integer pageSort;	// 页面顺序
+	@NotNull(message = "页面层级,不可为空")
+	@ApiModelProperty(value = "页面层级", example = "1", required = true)
+	private Integer pageLevel;	// 页面层级
 	
 	@ApiModelProperty(value = "备注", example = "1001")
 	private String remark; // 备注

+ 4 - 3
saas-account/src/main/java/com/persagy/account/pojo/vo/product/SaasProductPageTreeVO.java

@@ -1,7 +1,5 @@
 package com.persagy.account.pojo.vo.product;
 
-import javax.validation.constraints.NotBlank;
-
 import com.persagy.common.model.BaseUserModel;
 
 import io.swagger.annotations.ApiModel;
@@ -23,10 +21,13 @@ import lombok.ToString;
 @ToString
 public class SaasProductPageTreeVO extends BaseUserModel {
 	
-	@NotBlank(message = "产品ID,不可为空")
+	//@NotBlank(message = "产品ID,不可为空")
 	@ApiModelProperty(value = "产品ID", example = "PD1001")
 	private String productId; // 产品ID
 	
+	@ApiModelProperty(value = "产品类型,0-系统产品,1-标准业务产品,2-IBMS产品", example = "0")
+	private String productType;	//产品类型,0-系统产品,1-标准业务产品,2-IBMS产品
+	
 	@ApiModelProperty(value = "当前角度", example = "123")
 	private String angle; // 当前角度,1-集团视角,2-项目视角
 

+ 9 - 0
saas-account/src/main/java/com/persagy/account/pojo/vo/project/SaasProjectCreateVO.java

@@ -65,6 +65,15 @@ public class SaasProjectCreateVO extends BaseGroupModel {
 	@ApiModelProperty(value = "项目开业时间", example = "123456789")
 	private Date openTime;	//项目开业时间
 
+	@ApiModelProperty(value = "项目功能", example = "123456789")
+	private String projectFun;		//项目功能
+	
+	@ApiModelProperty(value = "项目天气", example = "123456789")
+	private String projectWeather;	//项目天气
+	
+	@ApiModelProperty(value = "项目图标,多个之间,用英文逗号分隔", example = "123456789")
+	private String projectImage;	//项目图标,多个之间,用英文逗号分隔
+	
 	@ApiModelProperty(value = "备注信息", example = "测试项目")
 	private String remark; // 备注
 	

+ 20 - 1
saas-account/src/main/java/com/persagy/account/service/ISaasMenuService.java

@@ -53,11 +53,30 @@ public interface ISaasMenuService extends ISuperService<SaasMenu> {
 	boolean validMenuCode(String appId, String menuCode, String menuId);
 	
 	/**
+	 * 验证菜单名称的唯一性
+	 * 
+	 * @param appId
+	 * @param menuName
+	 * @param menuId
+	 * @return
+	 */
+	boolean validMenuName(String appId, String menuName, String menuId);
+	
+	/**
 	 * 创建菜单,同时设置产品是否已关联菜单
 	 * @param saasMenu
 	 * @return
 	 */
 	boolean createSaasMenu(SaasMenu saasMenu);
-	
+
+	/**
+	 * 更新菜单
+	 * 
+	 * @param saasMenu
+	 * @param orgProductId 原纪录的产品ID 
+	 * @return
+	 */
+	boolean updateSaasMenu(SaasMenu saasMenu, String orgProductId);
+
 }
 

+ 17 - 0
saas-account/src/main/java/com/persagy/account/service/ISaasProductCategeoryService.java

@@ -0,0 +1,17 @@
+package com.persagy.account.service;
+
+import com.persagy.common.service.ISuperService;
+import com.persagy.account.pojo.dto.SaasProductCategeory;
+
+/**
+ * 产品信息
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021-05-11 19:23:03
+ */
+public interface ISaasProductCategeoryService extends ISuperService<SaasProductCategeory> {
+
+}
+

+ 22 - 0
saas-account/src/main/java/com/persagy/account/service/ISaasProductPageService.java

@@ -47,5 +47,27 @@ public interface ISaasProductPageService extends ISuperService<SaasProductPage>
 	 */
 	List<SaasProductPage> queryAccountProductPages(String accountId, String productId, String menuId, String parentId, String angle);
 
+	/**
+	 * 创建产品页面
+	 * @param saasProductPage
+	 * @return
+	 */
+	boolean createSaasProductPage(SaasProductPage saasProductPage);
+
+	/**
+	 * 更新产品页面
+	 * @param saasProductPage
+	 * @return
+	 */
+	boolean updateSaasProductPage(SaasProductPage saasProductPage);
+
+	/**
+	 * 验证页面名称在此页面下的唯一性
+	 * @param pageName
+	 * @param pageId
+	 * @return
+	 */
+	boolean validPageName(String pageName, String pageId);
+
 }
 

+ 47 - 0
saas-account/src/main/java/com/persagy/account/service/impl/SaasMenuServiceImpl.java

@@ -7,6 +7,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 import com.persagy.account.mapper.SaasMenuMapper;
 import com.persagy.account.mapper.SaasProductMapper;
@@ -58,6 +59,16 @@ public class SaasMenuServiceImpl extends SuperServiceImpl<SaasMenuMapper, SaasMe
 		}
 		return true;
 	}
+	
+	@Override
+	public boolean validMenuName(String appId, String menuName, String menuId) {
+		LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().appIdEq(appId).menuNameEq(menuName).builderQueryWrapper();
+		SaasMenu selectOne = this.baseMapper.selectOne(queryWrapper);
+		if (selectOne != null && (StringUtil.isBlank(menuId) || !menuId.equals(selectOne.getId()))) {
+			return false;
+		}
+		return true;
+	}
 
 	@Override
 	@Transactional
@@ -73,4 +84,40 @@ public class SaasMenuServiceImpl extends SuperServiceImpl<SaasMenuMapper, SaasMe
 		return SqlHelper.retBool(result);
 	}
 
+	@Override
+	@Transactional
+	public boolean updateSaasMenu(SaasMenu saasMenu, String orgProductId) {
+		Integer result = null;
+		if (StringUtil.isAllBlank(saasMenu.getProductId(), orgProductId)) {
+			result = this.baseMapper.updateById(saasMenu);
+			return SqlHelper.retBool(result);
+		}
+		if (StringUtil.isNotBlank(orgProductId) && StringUtil.isBlank(saasMenu.getProductId())) {
+			// 判断此产品是否仅被此菜单使用
+    		LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().productId(saasMenu.getProductId()).builderQueryWrapper();
+    		int count = this.baseMapper.selectCount(queryWrapper);
+    		if (count < 2) {
+    			// 更新产品是否已关联菜单字段
+				SaasProduct saasProduct = new SaasProduct();
+				saasProduct.setId(orgProductId);
+				saasProduct.setProductMenu(SaasCommonConstant.STR_STATUS_0);
+				this.saasProductMapper.updateById(saasProduct);
+			}
+    		// 更新此菜单信息
+    		LambdaUpdateWrapper<SaasMenu> updateWrapper = new SaasMenu.Builder().idEq(saasMenu.getId()).builderUpdateWrapper();
+    		updateWrapper.setSql("PRODUCT_ID = NULL");
+			result = this.baseMapper.update(saasMenu, updateWrapper);
+			return SqlHelper.retBool(result);
+		}
+		// 更新产品是否已关联菜单字段
+		result = this.baseMapper.updateById(saasMenu);
+		if (SqlHelper.retBool(result)) {
+			SaasProduct saasProduct = new SaasProduct();
+			saasProduct.setId(saasMenu.getProductId());
+			saasProduct.setProductMenu(SaasCommonConstant.STR_STATUS_1);
+			result = this.saasProductMapper.updateById(saasProduct);
+		}
+		return SqlHelper.retBool(result);
+	}
+
 }

+ 21 - 0
saas-account/src/main/java/com/persagy/account/service/impl/SaasProductCategeoryServiceImpl.java

@@ -0,0 +1,21 @@
+package com.persagy.account.service.impl;
+
+import org.springframework.stereotype.Service;
+
+import com.persagy.common.service.impl.SuperServiceImpl;
+import com.persagy.account.mapper.SaasProductCategeoryMapper;
+import com.persagy.account.pojo.dto.SaasProductCategeory;
+import com.persagy.account.service.ISaasProductCategeoryService;
+
+/**
+ * 产品信息
+ * 
+ * @version 1.0.0
+ * @company persagy 
+ * @author zhangqiankun
+ * @date 2021-05-11 19:23:03
+ */
+@Service
+public class SaasProductCategeoryServiceImpl extends SuperServiceImpl<SaasProductCategeoryMapper, SaasProductCategeory> implements ISaasProductCategeoryService {
+
+}

+ 56 - 1
saas-account/src/main/java/com/persagy/account/service/impl/SaasProductPageServiceImpl.java

@@ -3,11 +3,17 @@ package com.persagy.account.service.impl;
 import java.util.List;
 
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
-import com.persagy.common.service.impl.SuperServiceImpl;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 import com.persagy.account.mapper.SaasProductPageMapper;
 import com.persagy.account.pojo.dto.SaasProductPage;
 import com.persagy.account.service.ISaasProductPageService;
+import com.persagy.common.constant.SaasCommonConstant;
+import com.persagy.common.service.impl.SuperServiceImpl;
+import com.persagy.common.utils.StringUtil;
 
 /**
  * 产品页面配置
@@ -35,4 +41,53 @@ public class SaasProductPageServiceImpl extends SuperServiceImpl<SaasProductPage
 		return this.baseMapper.queryAccountProductPages(accountId, productId, menuId, parentId, angle);
 	}
 
+	@Override
+	@Transactional
+	public boolean createSaasProductPage(SaasProductPage saasProductPage) {
+		// 判断是否是落地页,落地页的时候,取消其余的落地页设置
+		Integer result =  1;
+		if (!SaasCommonConstant.STR_STATUS_0.equals(saasProductPage.getPageFloor())) {
+			LambdaUpdateWrapper<SaasProductPage> updateWrapper = new SaasProductPage.BuilderUpdateWrapper()
+					.productIdEq(saasProductPage.getProductId()).pageFloorEq(saasProductPage.getPageFloor()).builder();
+			SaasProductPage updatePage = new SaasProductPage();
+			updatePage.setPageFloor(SaasCommonConstant.STR_STATUS_0);
+			result = this.baseMapper.update(updatePage, updateWrapper);
+		}
+		if (SqlHelper.retBool(result)) {
+			result = this.baseMapper.insert(saasProductPage);
+		}
+		return SqlHelper.retBool(result);
+	}
+
+	@Override
+	@Transactional
+	public boolean updateSaasProductPage(SaasProductPage saasProductPage) {
+		// 判断是否是落地页,落地页的时候,取消其余的落地页设置
+		Integer result =  1;
+		if (!SaasCommonConstant.STR_STATUS_0.equals(saasProductPage.getPageFloor())) {
+			LambdaUpdateWrapper<SaasProductPage> updateWrapper = new SaasProductPage.BuilderUpdateWrapper()
+					.productIdEq(saasProductPage.getProductId()).pageFloorEq(saasProductPage.getPageFloor()).builder();
+			SaasProductPage updatePage = new SaasProductPage();
+			updatePage.setPageFloor(SaasCommonConstant.STR_STATUS_0);
+			result = this.baseMapper.update(updatePage, updateWrapper);
+		}
+		if (SqlHelper.retBool(result)) {
+			result = this.baseMapper.insert(saasProductPage);
+		}
+		return SqlHelper.retBool(result);
+	}
+
+	@Override
+	public boolean validPageName(String pageName, String pageId) {
+		LambdaQueryWrapper<SaasProductPage> queryWrapper = new SaasProductPage.BuilderQueryWrapper().pageNameEq(pageName).builder();
+		SaasProductPage selectOne = this.baseMapper.selectOne(queryWrapper);
+		if (selectOne == null) {
+			return true;
+		}
+		if (StringUtil.isNotBlank(pageId) && selectOne.getId().equals(pageId)) {
+			return true;
+		}
+		return false;
+	}
+
 }

+ 4 - 5
saas-account/src/main/resources/mapper/SaasFunctionMapper.xml

@@ -10,7 +10,6 @@
 		<result column="FUN_CODE" property="funCode" jdbcType="VARCHAR" />
 		<result column="FUN_NAME" property="funName" jdbcType="VARCHAR" />
 		<result column="FUN_URL" property="funUrl" jdbcType="VARCHAR" />
-		<result column="FUN_SORT" property="funSort" jdbcType="INTEGER" />
 		<result column="CREATE_TIME" property="createTime" jdbcType="DATE" />
 		<result column="UPDATE_TIME" property="updateTime" jdbcType="DATE" />
 		<result column="UPDATE_USER" property="updateUser" jdbcType="VARCHAR" />
@@ -20,7 +19,7 @@
 	</resultMap>
 	
 	<sql id="Base_Sql_Column">
-		ID, MENU_ID, PAGE_ID, FUN_CODE, FUN_NAME, FUN_URL, FUN_SORT, REMARK
+		ID, MENU_ID, PAGE_ID, FUN_CODE, FUN_NAME, FUN_URL, CREATE_TIME, REMARK
 	</sql>
 	
 	<select id="queryAccountFunctionList" resultMap="BaseResultMap">
@@ -36,7 +35,7 @@
 		JOIN (SELECT <include refid="Base_Sql_Column"></include> FROM saas_function 
 		<where>
 			<if test="menuId != null and menuId.trim().length() != 0">AND MENU_ID = #{menuId}</if>
-		</where>) P ON P.ID = N.FUNCTION_ID ORDER BY P.FUN_SORT
+		</where>) P ON P.ID = N.FUNCTION_ID ORDER BY P.CREATE_TIME
 	</select>
 	
 	<select id="queryRoleFunctionList" resultMap="BaseResultMap">
@@ -51,7 +50,7 @@
 		<where>
 			<if test="menuId != null and menuId.trim().length() != 0">AND MENU_ID = #{menuId}</if>
 			<if test="pageId != null and pageId.trim().length() != 0">AND PAGE_ID = #{pageId}</if>
-		</where>) N ON N.ID = M.FUNCTION_ID ORDER BY N.FUN_SORT
+		</where>) N ON N.ID = M.FUNCTION_ID ORDER BY N.CREATE_TIME
 	</select>
 	
 	<select id="queryProductPageFunctions" resultMap="BaseResultMap">
@@ -68,7 +67,7 @@
 		<where>
 			<!-- 此处不能添加菜单ID作为查询条件 -->
 			<if test="pageId != null and pageId.trim().length() != 0">AND PAGE_ID = #{pageId}</if>
-		</where>) P ON P.ID = N.FUNCTION_ID ORDER BY P.FUN_SORT
+		</where>) P ON P.ID = N.FUNCTION_ID ORDER BY P.CREATE_TIME
 	</select>
 	
 </mapper>

+ 3 - 1
saas-account/src/main/resources/mapper/SaasMenuMapper.xml

@@ -65,7 +65,9 @@
 	
 	<update id="sortSaasMenu">
 		<foreach collection="menus" index="index" item="menu" separator=";" >
-			UPDATE saas_menu SET MENU_SORT = #{menu.menuSort} WHERE ID = #{menu.menuId}
+			UPDATE saas_menu SET MENU_SORT = #{menu.menuSort}
+			<if test="menu.parentId != null and menu.parentId.trim().length() != 0">, PARENT_ID = #{menu.parentId}</if>
+			WHERE ID = #{menu.menuId}
 		</foreach>
 	</update>
 	

+ 18 - 0
saas-account/src/main/resources/mapper/SaasProductCategeoryMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.persagy.account.mapper.SaasProductCategeoryMapper">
+    
+	<resultMap id="BaseResultMap" type="com.persagy.account.pojo.dto.SaasProductCategeory">
+		<result column="ID" property="id" jdbcType="VARCHAR" />
+		<result column="PARENT_ID" property="parentId" jdbcType="VARCHAR" />
+		<result column="CATEGORY_NAME" property="categoryName" jdbcType="VARCHAR" />
+		<result column="CATEGORY_ICON" property="categoryIcon" jdbcType="VARCHAR" />
+		<result column="TERMINAL" property="terminal" jdbcType="VARCHAR" />
+		<result column="TERMINAL_NAME" property="terminalName" jdbcType="VARCHAR" />
+		<result column="PRODUCT_TYPE" property="productType" jdbcType="VARCHAR" />
+		<result column="MENU_TYPE" property="menuType" jdbcType="VARCHAR" />
+		<result column="CREATE_TIME" property="createTime" jdbcType="DATE" />
+		<result column="REMARK" property="remark" jdbcType="VARCHAR" />
+	</resultMap>
+</mapper>

+ 2 - 2
saas-account/src/main/resources/mapper/SaasProductPageMapper.xml

@@ -12,7 +12,7 @@
 		<result column="PAGE_URL" property="pageUrl" jdbcType="VARCHAR" />
 		<result column="PAGE_ANGLE" property="pageAngle" jdbcType="VARCHAR" />
 		<result column="PAGE_FLOOR" property="pageFloor" jdbcType="VARCHAR" />
-		<result column="PAGE_SORT" property="pageSort" jdbcType="INTEGER" />
+		<result column="PAGE_LEVEL" property="pageLevel" jdbcType="INTEGER" />
 		<result column="CREATE_TIME" property="createTime" jdbcType="DATE" />
 		<result column="UPDATE_TIME" property="updateTime" jdbcType="DATE" />
 		<result column="UPDATE_USER" property="updateUser" jdbcType="VARCHAR" />
@@ -20,7 +20,7 @@
 	</resultMap>
 	
 	<sql id="Base_Sql_Column">
-		ID, PRODUCT_ID, PARENT_ID, PAGE_NAME, PAGE_ICON, PAGE_URL, PAGE_ANGLE, PAGE_FLOOR, PAGE_SORT, CREATE_TIME, UPDATE_TIME, UPDATE_USER, REMARK
+		ID, PRODUCT_ID, PARENT_ID, PAGE_NAME, PAGE_ICON, PAGE_URL, PAGE_ANGLE, PAGE_FLOOR, PAGE_LEVEL, CREATE_TIME, UPDATE_TIME, UPDATE_USER, REMARK
 	</sql>
 	
 	<select id="queryGroupProductPages" resultMap="BaseResultMap">

+ 4 - 1
saas-account/src/main/resources/mapper/SaasProjectMapper.xml

@@ -15,6 +15,9 @@
 		<result column="ZONE_CODE" property="zoneCode" jdbcType="VARCHAR" />
 		<result column="LOCATION" property="location" jdbcType="VARCHAR" />
 		<result column="OPEN_TIME" property="openTime" jdbcType="DATE" />
+		<result column="PROJECT_FUN" property="projectFun" jdbcType="VARCHAR" />
+		<result column="PROJECT_WEATHER" property="projectWeather" jdbcType="VARCHAR" />
+		<result column="PROJECT_IMAGE" property="projectImage" jdbcType="VARCHAR" />
 		<result column="CREATE_TIME" property="createTime" jdbcType="DATE" />
 		<result column="UPDATE_TIME" property="updateTime" jdbcType="DATE" />
 		<result column="UPDATE_USER" property="updateUser" jdbcType="VARCHAR" />
@@ -26,7 +29,7 @@
 	
 	<sql id="Base_Sql_Column">
 		ID, GROUP_CODE, PROJECT_ID, AREA_ID, PROJECT_LOCAL_ID, PROJECT_NAME, PROVINCE_CODE, CITY_CODE, ZONE_CODE, 
-		LOCATION, OPEN_TIME, CREATE_TIME, UPDATE_TIME, UPDATE_USER, REMARK, VALID
+		LOCATION, OPEN_TIME, PROJECT_FUN, PROJECT_WEATHER, PROJECT_IMAGE, CREATE_TIME, UPDATE_TIME, UPDATE_USER, REMARK, VALID
 	</sql>
 	
 	<!-- 单独项目表查询 -->

+ 4 - 1
saas-common/src/main/java/com/persagy/common/constant/SaasCommonConstant.java

@@ -56,8 +56,11 @@ public interface SaasCommonConstant {
 	//产品ID前缀
 	String SAAS_PRODUCT_ID_PREFIX = "PD";
 	
+	//产品类别ID前缀
+	String SAAS_PRODUCT_CATEGEORY_ID_PREFIX = "PC";
+		
 	//产品页面ID前缀
-	String SAAS_PRODUCT_PAGE_ID_PREFIX = "PA";
+	String SAAS_PRODUCT_PAGE_ID_PREFIX = "PP";
 	
 	//产品签约ID前缀
 	String SAAS_GROUP_PRODUCT_ID_PREFIX = "GP";

+ 71 - 50
saas-doc/doc/saas_platform.md

@@ -921,7 +921,7 @@ body:
 
 ### 查询集团区域项目树(权限过滤)
 
-结构:集团->区域->项目,根据账号ID,做数据权限过滤,且会剔除不存在项目信息的区域
+结构:集团->区域->项目,根据账号ID,做数据权限过滤
 
 ```
 URL:http://develop.persagy.com/saas-platform/saas-account/project/queryAllowAreaProjectTree
@@ -1046,6 +1046,14 @@ Header:Content-Type=application/json
 	            "projectLocalId": "1209010205",
 	            "projectName": "测试项目",
 	            "remark": "项目备注信息",
+	            "provinceCode":"",	
+	            "cityCode":"",	
+	            "zoneCode":"",	
+	            "projectFun":"",	
+	            "projectWeather":"",	
+	            "projectImage":"",	
+	            "location":"",	
+	            "openTime":14654645212,	//开业时间
 	            "updateTime": 1615794390000,
 	            "updateUser": "1371370289309515777",
 	            "valid": 1
@@ -1073,6 +1081,14 @@ Header:Content-Type=application/json
 	    "areaId":"123",     //区域ID,选填
 	    "projectLocalId":"1209010205",         //项目本地编码,必填
 	    "projectName":"测试项目",    //项目名称,必填
+	    "provinceCode":"",	//省份编码,选填
+	    "cityCode":"",	//城市编码,选填
+	    "zoneCode":"",	//区域编码,选填
+	    "projectFun":"",	//项目功能类型,选填
+	    "projectWeather":"",	//项目天气,选填
+	    "projectImage":"",	//项目图片,多个之间,用英文逗号分开,选填
+	    "location":"",	//项目详细地址,选填
+	    "openTime":14654645212,	//项目开业时间,选填
 	    "remark":"项目备注信息"    //备注,选填
 	}
 
@@ -1102,6 +1118,14 @@ Header:Content-Type=application/json
 	    "areaId":"123",     //区域ID,选填
 	    "projectLocalId":"1209010205",         //项目本地编码,必填
 	    "projectName":"测试项目",    //项目名称,必填
+	    "provinceCode":"",	//省份编码,选填
+	    "cityCode":"",	//城市编码,选填
+	    "zoneCode":"",	//区域编码,选填
+	    "projectFun":"",	//项目功能类型,选填
+	    "projectWeather":"",	//项目天气,选填
+	    "projectImage":"",	//项目图片,多个之间,用英文逗号分开,选填
+	    "location":"",	//项目详细地址,选填
+	    "openTime":14654645212,	//项目开业时间,选填
 	    "remark":"项目备注信息"    //备注,选填
 	}
 
@@ -1247,6 +1271,7 @@ Header:Content-Type=application/json
 	{
 	    "groupCode":"WD",    //集团编码,必填
 	    "roleIds":["RO1372505156457959327"],          //角色ID,必填
+	    "casType":"0",          //关联类型,0-主岗,1-副岗,2-业务超管默认角色
 	    "valid":1,         //是否可用,0-不可用,1-可用,选填
 	    "page":1,       //分页页码,不可低于1,必填
 	    "size":10       //分页大小,不可低于1,必填
@@ -1987,10 +2012,10 @@ Header:Content-Type=application/json
 	    "appId":"PC",                   // 应用ID,PC-电脑,APP-手机应用,必填
 	    "productCode":"1001",           // 产品编码,必填,唯一
 	    "productName":"测试",           // 产品名称,必填,唯一
-	    "productIcon":"layui-test-icon",   // 产品图标,必填
+	    "productIcon":"layui-test-icon",   // 产品图标,不填,会采用默认的ICON
 	    "productState":"0",         // 产品状态,0-建设中,1-已完成,2-已关联,必填
 	    "productMenu":"0",          // 产品是否关联菜单,0-未关联,1-已关联,必填
-	    "productType":"0",			//产品类型,0-系统产品,1-标准业务产品,2-IBMS产品,必填
+	    "productType":"0",			//产品类型,0-系统产品,1-标准业务产品,必填
 	    "remark":"测试"             //备注,选填
 	}
 
@@ -2040,43 +2065,46 @@ Header:Content-Type=application/json
 
 	{
 	    "accountId":"AC1372371635352403969",     // 账号ID,必填,不做为sql条件
-	    "appId":"PC",                   // 应用ID,PC-电脑,APP-手机应用,必填
-	    "productId":"PD1390234244466438145",        //产品ID,必填
+	    "appId":"PC",                   // 应用ID,PC-电脑,APP-手机应用,必填,作为sql条件
+	    "productId":"PD1390234244466438145",        //产品ID,选填
+	    "productType":"0",			//产品类型,0-系统产品,1-标准业务产品,2-IBMS产品,选填
 	    "showPageAuth": false   //是否展示出页面对应的权限信息,true-展示,默认false
 	}
 
 返回:
 
 	{
-	    "content": {
-	        "appId": "PC",
-	        "createTime": 1620292648000,
-	        "id": "PD1390234244466438145",
-	        "pages": [		// 该产品下,所有的页面
-	            {
-	                "childrens": [],		//该产品页面下的子页面
-	                "createTime": 1620292920000,
-	                "id": "PA1390235384671203330",
-	                "pageAngle": "0",		// 页面视角,0-集团项目页,1-集团独有页,2-项目独有页
-	                "pageFloor": "0",		// 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页
-	                "pageIcon": "",
-	                "pageName": "测试页面",
-	                "pageUrl": "",
-	                "parentId": "",
-	                "productId": "PD1390234244466438145",
-	                "remark": "测试页面",
-	                "updateTime": 1620293119000
-	            }
-	        ],
-	        "productCode": "1002",		// 产品编码
-	        "productIcon": "layui-test-icon",
-	        "productMenu": "0",		// 产品是否关联菜单,0-未关联,1-已关联
-	        "productName": "测试2",
-	        "productState": "0",		// 产品状态,0-建设中,1-已完成,2-已关联
-	        "remark": "测试",
-	        "updateTime": 1620292648000,
-	        "updateUser": "AC68464684542455"
-	    },
+	    "content": [
+	    	{
+	            "appId": "PC",
+	            "createTime": 1620292648000,
+	            "id": "PD1390234244466438145",
+	            "productPages": [		// 该产品下,所有的页面
+	                {
+	                    "childrens": [],		//该产品页面下的子页面
+	                    "createTime": 1620292920000,
+	                    "id": "PA1390235384671203330",
+	                    "pageAngle": "0",		// 页面视角,0-集团项目页,1-集团独有页,2-项目独有页
+	                    "pageFloor": "0",		// 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页
+	                    "pageIcon": "",
+	                    "pageName": "测试页面",
+	                    "pageUrl": "",
+	                    "parentId": "",
+	                    "productId": "PD1390234244466438145",
+	                    "remark": "测试页面",
+	                    "updateTime": 1620293119000
+	                }
+	            ],
+	            "productCode": "1002",		// 产品编码
+	            "productIcon": "layui-test-icon",
+	            "productMenu": "0",		// 产品是否关联菜单,0-未关联,1-已关联
+	            "productName": "测试2",
+	            "productState": "0",		// 产品状态,0-建设中,1-已完成,2-已关联
+	            "remark": "测试",
+	            "updateTime": 1620292648000,
+	            "updateUser": "AC68464684542455"
+	        }
+	    ],
 	    "respCode": "00000",
 	    "respMsg": "success"
 	}
@@ -2099,7 +2127,7 @@ Header:Content-Type=application/json
 	    "pageUrl":"",         // 页面URL,选填
 	    "pageAngle":"0",         // 页面视角,0-集团项目页,1-集团独有页,2-项目独有页,必填
 	    "pageFloor":"0",         // 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页,默认0,不填-默认0
-	    "pageSort":1,           //页面列表展示上下顺序,必填
+	    "pageLevel":1,           //当前页面层级,必填
 	    "remark":"测试页面"             //备注,选填
 	}
 
@@ -2130,7 +2158,7 @@ Header:Content-Type=application/json
 	    "pageUrl":"",         // 页面URL,选填
 	    "pageAngle":"0",         // 页面视角,0-集团项目页,1-集团独有页,2-项目独有页,必填
 	    "pageFloor":"0",         // 是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页,默认0,不填-默认0
-	    "pageSort":1,           //页面列表展示上下顺序,必填
+	    "pageLevel":1,           //当前页面层级,必填
 	    "remark":"测试页面"             //备注,选填
 	}
 
@@ -2152,22 +2180,16 @@ Header:Content-Type=application/json
 请求:
 
 	{
-	    "accountId":"AC68464684542455",     // 账号ID,必填,不做为sql条件
+	    "accountId":"AC1372371635352403969",     // 账号ID,必填,不做为sql条件
 	    "appId":"PC",                   // 应用ID,PC-电脑,APP-手机应用,必填
-	    "id":"PD1386991620691402753",        //产品ID,必填
-	    "productCode":"1001",           // 产品编码,必填,唯一
-	    "productName":"测试",           // 产品名称,必填,唯一
-	    "productIcon":"layui-test-icon",   // 产品图标,必填
-	    "productState":"0",         // 产品状态,0-建设中,1-已完成,2-已关联,必填
-	    "productMenu":"0",          // 产品是否关联菜单,0-未关联,1-已关联,必填
-	    "remark":"测试但是"             //备注,选填
+	    "id":"PA1390235384671203330"        //页面ID,必填
 	}
 
 返回:
 
 	{
 	    "respCode": "00000",
-	    "respMsg": "更新成功"
+	    "respMsg": "删除成功"
 	}
 
 ## 角色管理
@@ -2438,6 +2460,7 @@ Header:Content-Type=application/json
 	            "menuName": "账号权限管理",
 	            "menuSort": 2,
 	            "menuType": "0",
+	            "menuIcon":"",
 	            "menuUrl": "/oms/accountPermission",
 	            "remark": "账号权限管理",
 	            "updateTime": 1618242292000,
@@ -2707,6 +2730,7 @@ Header:Content-Type=application/json
 	    "menus": [
 	        {
 	            "menuId": "ME1372501618212643050",      //菜单ID,必填
+	            "parentId":"",				// 上级菜单ID,选填,存在会被更新为此值
 	            "menuSort": 2               //菜单顺序,必填
 	        },
 	        {
@@ -2829,7 +2853,7 @@ Header:Content-Type=application/json
 	    "projectId":"",       //项目ID,存在,即为项目视角
 	    "productId":"PD1390234244466438145",    //产品ID,选填
 	    "menuId":"ME1372501618212643050",       //菜单ID,必填
-	    "showPageAuth":false		//当返回产品页面树结果集时,是否展示产品页面的功能点信息,true-展示,默认false
+	    "showPageAuth":false		//当返回产品页面树结果集时,是否展示产品页面的功能点信息,true-展示,默认false
 	}
 
 返回:
@@ -2841,7 +2865,6 @@ Header:Content-Type=application/json
 	            "createTime": 1618855281000,
 	            "funCode": "101004",
 	            "funName": "查询平台管理员",
-	            "funSort": 1,
 	            "funUrl": "/account/queryAccountPageList",
 	            "id": "FU1372501618212832063",
 	            "menuId": "ME1372501618212643050",
@@ -2865,7 +2888,7 @@ Header:Content-Type=application/json
 	            "pageFloor": "0",		//是否为落地页,0-非落地页,1-集团落地页,2-项目落地页,3-集团项目落地页
 	            "pageIcon": "",
 	            "pageName": "测试页面",
-	            "pageSort": 1,
+	            "pageLevel": 1,
 	            "pageUrl": "",
 	            "parentId": "",
 	            "productId": "PD1390234244466438145",
@@ -2904,7 +2927,6 @@ Header:Content-Type=application/json
 	            "createTime": 1620300248000,
 	            "funCode": "1001",
 	            "funName": "查询",
-	            "funSort": 1,
 	            "funUrl": "/789/456",
 	            "id": "FU1390266121168408578",
 	            "menuId": "",
@@ -3007,7 +3029,6 @@ Header:Content-Type=application/json
 	    "funCode":"1001010102",    //功能编码,必填
 	    "funName":"删除",       //功能名称,必填
 	    "funUrl":"/account/deleteSaasAccount",      //功能URL,必填
-	    "funSort":2,    //功能顺序,必填
 	    "remark":"功能点备注信息"   //备注
 	}
 

BIN
saas-doc/doc/运维管理3.0-数据库表设计.xlsx