MenuController.java 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. package com.xjrsoft.module.system.controller;
  2. import cn.dev33.satoken.stp.StpUtil;
  3. import cn.hutool.core.bean.BeanUtil;
  4. import cn.hutool.core.util.ObjectUtil;
  5. import cn.hutool.core.util.StrUtil;
  6. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  8. import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
  9. import com.baomidou.mybatisplus.core.toolkit.StringPool;
  10. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  11. import com.github.yulichang.toolkit.MPJWrappers;
  12. import com.jdcloud.sdk.utils.StringUtils;
  13. import com.xjrsoft.common.constant.GlobalConstant;
  14. import com.xjrsoft.common.enums.AuthorizeType;
  15. import com.xjrsoft.common.enums.EnabledMark;
  16. import com.xjrsoft.common.enums.MenuType;
  17. import com.xjrsoft.common.enums.SystemTypeEnum;
  18. import com.xjrsoft.common.enums.YesOrNoEnum;
  19. import com.xjrsoft.common.model.result.R;
  20. import com.xjrsoft.common.model.result.RT;
  21. import com.xjrsoft.common.utils.TreeUtil;
  22. import com.xjrsoft.common.utils.VoToColumnUtil;
  23. import com.xjrsoft.module.organization.service.IUserRoleRelationService;
  24. import com.xjrsoft.module.system.dto.AddMenuDto;
  25. import com.xjrsoft.module.system.dto.AddMenuFormDto;
  26. import com.xjrsoft.module.system.dto.MenuTreeDto;
  27. import com.xjrsoft.module.system.dto.RoleMenuServeListDto;
  28. import com.xjrsoft.module.system.dto.UpdateMenuDto;
  29. import com.xjrsoft.module.system.dto.UpdateMenuFormDto;
  30. import com.xjrsoft.module.system.entity.Authorize;
  31. import com.xjrsoft.module.system.entity.Menu;
  32. import com.xjrsoft.module.system.entity.MenuButton;
  33. import com.xjrsoft.module.system.entity.MenuColumn;
  34. import com.xjrsoft.module.system.entity.MenuForm;
  35. import com.xjrsoft.module.system.entity.Subsystem;
  36. import com.xjrsoft.module.system.service.IAuthorizeService;
  37. import com.xjrsoft.module.system.service.IMenuButtonService;
  38. import com.xjrsoft.module.system.service.IMenuColumnService;
  39. import com.xjrsoft.module.system.service.IMenuFormService;
  40. import com.xjrsoft.module.system.service.IMenuService;
  41. import com.xjrsoft.module.system.vo.AuthMenuVo;
  42. import com.xjrsoft.module.system.vo.MenuButtonVo;
  43. import com.xjrsoft.module.system.vo.MenuChildTreeVo;
  44. import com.xjrsoft.module.system.vo.MenuColumnVo;
  45. import com.xjrsoft.module.system.vo.MenuFormVo;
  46. import com.xjrsoft.module.system.vo.MenuListVo;
  47. import com.xjrsoft.module.system.vo.MenuServeVo;
  48. import com.xjrsoft.module.system.vo.MenuSimpleTreeVo;
  49. import com.xjrsoft.module.system.vo.MenuTreeVo;
  50. import com.xjrsoft.module.system.vo.MenuVo;
  51. import io.swagger.annotations.Api;
  52. import io.swagger.annotations.ApiOperation;
  53. import lombok.AllArgsConstructor;
  54. import org.springframework.transaction.annotation.Transactional;
  55. import org.springframework.web.bind.annotation.DeleteMapping;
  56. import org.springframework.web.bind.annotation.GetMapping;
  57. import org.springframework.web.bind.annotation.PostMapping;
  58. import org.springframework.web.bind.annotation.PutMapping;
  59. import org.springframework.web.bind.annotation.RequestBody;
  60. import org.springframework.web.bind.annotation.RequestMapping;
  61. import org.springframework.web.bind.annotation.RequestParam;
  62. import org.springframework.web.bind.annotation.RestController;
  63. import javax.validation.Valid;
  64. import javax.validation.constraints.NotNull;
  65. import java.util.ArrayList;
  66. import java.util.List;
  67. /**
  68. * <p>
  69. * 用户 前端控制器
  70. * </p>
  71. *
  72. * @author tzx
  73. * @since 2022-03-16
  74. */
  75. @RestController
  76. @RequestMapping(GlobalConstant.SYSTEM_MODULE_PREFIX + "/menu")
  77. @Api(value = GlobalConstant.SYSTEM_MODULE_PREFIX + "/menu", tags = "菜单模块")
  78. @AllArgsConstructor
  79. public class MenuController {
  80. private final IMenuService menuService;
  81. private final IMenuButtonService menuButtonService;
  82. private final IMenuColumnService menuColumnService;
  83. private final IMenuFormService menuFormService;
  84. private final IAuthorizeService authorizeService;
  85. private final IUserRoleRelationService userRoleRelationService;
  86. @GetMapping("/list")
  87. @ApiOperation(value = "获取所有菜单(不分页)")
  88. public R list() {
  89. List<Menu> list = menuService.list(Wrappers.lambdaQuery(Menu.class)
  90. .select(Menu.class, x -> VoToColumnUtil.fieldsToColumns(MenuListVo.class).contains(x.getProperty())));
  91. List<MenuListVo> menuListVos = BeanUtil.copyToList(list, MenuListVo.class);
  92. return R.ok(TreeUtil.build(menuListVos));
  93. }
  94. @GetMapping("/tree")
  95. @ApiOperation(value = "获取所有菜单(树结构)")
  96. public R menuTree(@Valid MenuTreeDto dto) {
  97. List<MenuVo> list = menuService.getAuthMenuList(dto);
  98. List<MenuTreeVo> voList = BeanUtil.copyToList(list, MenuTreeVo.class);
  99. List<MenuTreeVo> treeVoList = TreeUtil.build(voList);
  100. return R.ok(treeVoList);
  101. }
  102. @GetMapping("/quick")
  103. @ApiOperation(value = "用户快捷菜单")
  104. public RT<List<MenuVo>> quick(@Valid MenuTreeDto dto) {
  105. List<Menu> menus = menuService.getUserQuick(dto);
  106. List<MenuVo> menuListVos = BeanUtil.copyToList(menus, MenuVo.class);
  107. return RT.ok(menuListVos);
  108. }
  109. @GetMapping("/role-serve")
  110. @ApiOperation(value = "查询角色菜单服务")
  111. public RT<List<MenuServeVo>> roleMenuServe(RoleMenuServeListDto dto) {
  112. List<MenuServeVo> list = menuService.getRoleMenuServe(dto);
  113. return RT.ok(list);
  114. }
  115. @GetMapping("/serve")
  116. @ApiOperation(value = "获取菜单服务")
  117. public RT<List<MenuServeVo>> menuServe(@Valid MenuTreeDto dto) {
  118. List<MenuServeVo> list = menuService.getAuthMenuServe(dto);
  119. return RT.ok(list);
  120. }
  121. @GetMapping("/all-tree")
  122. @ApiOperation(value = "获取所有菜单(树结构)")
  123. public R allMenuTree(@Valid MenuTreeDto dto) {
  124. if (StrUtil.isEmpty(dto.getSystemType())) {
  125. dto.setSystemType(SystemTypeEnum.SYSTEMPC.getCode());
  126. }
  127. List<MenuTreeVo> list = menuService.selectJoinList(MenuTreeVo.class,
  128. MPJWrappers.<Menu>lambdaJoin()
  129. .like(StrUtil.isNotEmpty(dto.getTitle()), Menu::getTitle, dto.getTitle())
  130. .like(StrUtil.isNotEmpty(dto.getName()), Menu::getName, dto.getName())
  131. .like(ObjectUtil.isNotNull(dto.getSystemId()) && dto.getSystemId() > 0, Menu::getSystemId, dto.getSystemId())
  132. .eq(Menu::getSystemType, dto.getSystemType())
  133. .select(Menu::getId)
  134. .select(Menu.class, x -> VoToColumnUtil.fieldsToColumns(MenuTreeVo.class).contains(x.getProperty()))
  135. .selectAs(Subsystem::getName, MenuTreeVo::getSystemName)
  136. .eq(ObjectUtils.isNotEmpty(dto.getEnabledMark()), Menu::getEnabledMark, dto.getEnabledMark())
  137. .leftJoin(Subsystem.class, Subsystem::getId, Menu::getSystemId)
  138. .orderByAsc(Menu::getSortCode));
  139. List<MenuTreeVo> treeVoList = TreeUtil.build(list);
  140. return R.ok(treeVoList);
  141. }
  142. @GetMapping("/child-tree")
  143. @ApiOperation(value = "获取所有菜单(树结构,禁用父级)")
  144. public R menuChildTree(@Valid MenuTreeDto dto) {
  145. List<MenuVo> list = menuService.getAuthMenuList(dto);
  146. List<MenuChildTreeVo> voList = BeanUtil.copyToList(list, MenuChildTreeVo.class);
  147. List<MenuChildTreeVo> treeVoList = TreeUtil.build(voList);
  148. voList.forEach(treeVo -> treeVo.setFullPath(true));
  149. return R.ok(treeVoList);
  150. }
  151. @GetMapping("/simple-tree")
  152. @ApiOperation(value = "获取所有菜单(树结构)")
  153. public R menuAuthTree(@Valid MenuTreeDto dto) {
  154. dto.setDisplay(null);
  155. List<MenuVo> list = menuService.getAuthMenuList(dto);
  156. List<MenuSimpleTreeVo> voList = BeanUtil.copyToList(list, MenuSimpleTreeVo.class);
  157. List<MenuSimpleTreeVo> treeVoList = TreeUtil.build(voList);
  158. return R.ok(treeVoList);
  159. }
  160. @GetMapping(value = "/info")
  161. @ApiOperation(value = "根据id查询菜单信息")
  162. public R info(Long id) {
  163. Menu menu = menuService.getById(id);
  164. if (menu == null) {
  165. R.error("找不到此菜单!");
  166. }
  167. return R.ok(BeanUtil.toBean(menu, MenuVo.class));
  168. }
  169. @PostMapping
  170. @ApiOperation(value = "新增菜单")
  171. @Transactional(rollbackFor = Exception.class)
  172. public R add(@Valid @RequestBody AddMenuDto dto) {
  173. long count = menuService.count(Wrappers.<Menu>query().lambda().eq(Menu::getCode, dto.getCode()));
  174. if (count > 0) {
  175. return R.error("菜单编码已经存在!");
  176. }
  177. Menu menu = BeanUtil.toBean(dto, Menu.class);
  178. if (ObjectUtil.isEmpty(menu.getSystemId())) {
  179. menu.setSystemId(1L);
  180. }
  181. //判断是否为菜单
  182. if (menu.getMenuType() == YesOrNoEnum.NO.getCode()) {
  183. //如果是菜单 需要判断 path 第一个字符 是否为 / 菜单必须要 / 开头
  184. if (!menu.getPath().startsWith(StringPool.SLASH)) {
  185. menu.setPath(StringPool.SLASH + menu.getPath());
  186. }
  187. }
  188. //判断是否为外链
  189. if (menu.getOutLink() == YesOrNoEnum.YES.getCode()) {
  190. //如果是外链 所有组件地址 改为 IFrame
  191. menu.setComponent("IFrame");
  192. }
  193. menu.setAllowDelete(YesOrNoEnum.YES.getCode());
  194. menu.setAllowModify(YesOrNoEnum.YES.getCode());
  195. boolean isSuccess = menuService.save(menu);
  196. //按钮保存
  197. List<MenuButton> menuButtons = BeanUtil.copyToList(dto.getButtonList(), MenuButton.class);
  198. menuButtons.forEach(menuButton -> menuButton.setMenuId(menu.getId()));
  199. //删除原按钮
  200. menuButtonService.remove(Wrappers.<MenuButton>query().lambda().eq(MenuButton::getMenuId, menu.getId()));
  201. menuButtonService.saveBatch(menuButtons);
  202. // 列表字段保存
  203. List<MenuColumn> columnList = BeanUtil.copyToList(dto.getColumnList(), MenuColumn.class);
  204. columnList.forEach(menuColumn -> menuColumn.setMenuId(menu.getId()));
  205. menuColumnService.remove(Wrappers.<MenuColumn>query().lambda().eq(MenuColumn::getMenuId, menu.getId()));
  206. menuColumnService.saveBatch(columnList);
  207. // 表单字段保存
  208. List<MenuForm> formList = new ArrayList<>();
  209. for (AddMenuFormDto addMenuFormDto : dto.getFormList()) {
  210. formList.add(BeanUtil.toBean(addMenuFormDto, MenuForm.class));
  211. List<AddMenuFormDto> children = addMenuFormDto.getChildren();
  212. if (org.apache.commons.collections.CollectionUtils.isNotEmpty(children)) {
  213. formList.addAll(BeanUtil.copyToList(children, MenuForm.class));
  214. }
  215. }
  216. formList.forEach(menuForm -> menuForm.setMenuId(menu.getId()));
  217. menuFormService.remove(Wrappers.<MenuForm>query().lambda().eq(MenuForm::getMenuId, menu.getId()));
  218. menuFormService.saveBatch(formList);
  219. return R.ok(isSuccess);
  220. }
  221. @PutMapping
  222. @ApiOperation(value = "修改菜单")
  223. @Transactional(rollbackFor = Exception.class)
  224. public R edit(@Valid @RequestBody UpdateMenuDto dto) {
  225. long count = menuService.count(Wrappers.<Menu>query().lambda()
  226. .ne(Menu::getId, dto.getId()).and(wrapper ->
  227. wrapper.eq(Menu::getCode, dto.getCode())
  228. )
  229. );
  230. if (count > 0) {
  231. return R.error("菜单编码已经存在!");
  232. }
  233. Menu menu = BeanUtil.toBean(dto, Menu.class);
  234. //判断是否为菜单
  235. if (menu.getMenuType() == YesOrNoEnum.NO.getCode()) {
  236. //如果是菜单 需要判断 path 第一个字符 是否为 / 菜单必须要 / 开头
  237. if (!menu.getPath().startsWith(StringPool.SLASH)) {
  238. menu.setPath(StringPool.SLASH + menu.getPath());
  239. }
  240. }
  241. //判断是否为外链
  242. if (menu.getOutLink() == YesOrNoEnum.YES.getCode()) {
  243. //如果是外链 所有组件地址 改为 IFrame
  244. menu.setComponent("IFrame");
  245. }
  246. menuService.updateById(menu);
  247. List<MenuButton> menuButtons = BeanUtil.copyToList(dto.getButtonList(), MenuButton.class);
  248. menuButtons.forEach(menuButton -> menuButton.setMenuId(menu.getId()));
  249. //删除原按钮
  250. menuButtonService.remove(Wrappers.<MenuButton>query().lambda().eq(MenuButton::getMenuId, menu.getId()));
  251. // 列表字段保存
  252. List<MenuColumn> columnList = BeanUtil.copyToList(dto.getColumnList(), MenuColumn.class);
  253. columnList.forEach(menuColumn -> menuColumn.setMenuId(menu.getId()));
  254. menuColumnService.remove(Wrappers.<MenuColumn>query().lambda().eq(MenuColumn::getMenuId, menu.getId()));
  255. // 表单字段保存
  256. List<MenuForm> formList = new ArrayList<>();
  257. for (UpdateMenuFormDto updateMenuFormDto : dto.getFormList()) {
  258. formList.add(BeanUtil.toBean(updateMenuFormDto, MenuForm.class));
  259. List<UpdateMenuFormDto> children = updateMenuFormDto.getChildren();
  260. if (org.apache.commons.collections.CollectionUtils.isNotEmpty(children)) {
  261. formList.addAll(BeanUtil.copyToList(children, MenuForm.class));
  262. }
  263. }
  264. formList.forEach(menuForm -> menuForm.setMenuId(menu.getId()));
  265. menuFormService.remove(Wrappers.<MenuForm>query().lambda().eq(MenuForm::getMenuId, menu.getId()));
  266. if (CollectionUtils.isNotEmpty(menuButtons)) {
  267. menuButtonService.saveBatch(menuButtons);
  268. }
  269. if (CollectionUtils.isNotEmpty(columnList)) {
  270. menuColumnService.saveBatch(columnList);
  271. }
  272. if (CollectionUtils.isNotEmpty(formList)) {
  273. menuFormService.saveBatch(formList);
  274. }
  275. return R.ok();
  276. }
  277. @GetMapping(value = "/button")
  278. @ApiOperation(value = "根据id查询按钮")
  279. public R button(@NotNull @Valid Long id) {
  280. List<MenuButton> list = menuButtonService.list(Wrappers.<MenuButton>query().lambda().eq(MenuButton::getMenuId, id));
  281. return R.ok(list);
  282. }
  283. @DeleteMapping
  284. @ApiOperation(value = "批量删除菜单")
  285. public R delete(@Valid @RequestBody List<Long> ids) {
  286. return R.ok(menuService.removeByIds(ids));
  287. }
  288. @GetMapping("/auth-tree")
  289. @ApiOperation(value = "获取功能授权页面的菜单树结构")
  290. public R fullAuthTree() {
  291. List<Long> roleIdList = StpUtil.getTokenSession().get(GlobalConstant.LOGIN_USER_ROLE_ID_KEY, new ArrayList<>());
  292. LambdaQueryWrapper<Menu> queryMenuWrapper = Wrappers.<Menu>query().lambda().eq(Menu::getEnabledMark, EnabledMark.ENABLED.getCode());
  293. LambdaQueryWrapper<MenuButton> queryBtnWrapper = Wrappers.<MenuButton>query().lambda();
  294. LambdaQueryWrapper<MenuColumn> queryColWrapper = Wrappers.<MenuColumn>query().lambda();
  295. LambdaQueryWrapper<MenuForm> queryFormWrapper = Wrappers.<MenuForm>query().lambda();
  296. boolean isAdmin = roleIdList.contains(GlobalConstant.SUPER_ADMIN_ROLE_ID);
  297. // 不是管理员
  298. if (!isAdmin) {
  299. List<Authorize> authorizeList = authorizeService.list(Wrappers.<Authorize>query().lambda()
  300. .select(Authorize::getObjectId, Authorize::getAuthorizeType)
  301. .in(Authorize::getAuthorizeType, AuthorizeType.MENU.getCode(), AuthorizeType.BUTTON.getCode(), AuthorizeType.COLUMN.getCode(), AuthorizeType.FORM.getCode())
  302. .in(Authorize::getRoleId, roleIdList));
  303. if (CollectionUtils.isEmpty(authorizeList)) {
  304. return R.ok();
  305. }
  306. List<Long> authMenuIdList = new ArrayList<>();
  307. List<Long> authMenuBtnIdList = new ArrayList<>();
  308. List<Long> authMenuIdColList = new ArrayList<>();
  309. List<Long> authMenuIdFormList = new ArrayList<>();
  310. for (Authorize authorize : authorizeList) {
  311. Long id = authorize.getId();
  312. switch (authorize.getAuthorizeType()) {
  313. case 1:
  314. authMenuIdList.add(id);
  315. break;
  316. case 2:
  317. authMenuBtnIdList.add(id);
  318. break;
  319. case 3:
  320. authMenuIdColList.add(id);
  321. break;
  322. case 4:
  323. authMenuIdFormList.add(id);
  324. break;
  325. default:
  326. break;
  327. }
  328. }
  329. queryMenuWrapper.in(Menu::getId, authMenuIdList);
  330. queryBtnWrapper.in(MenuButton::getId, authMenuBtnIdList);
  331. queryColWrapper.in(MenuColumn::getId, authMenuIdColList);
  332. queryFormWrapper.in(MenuForm::getId, authMenuIdFormList);
  333. }
  334. List<Menu> menuList = menuService.list(queryMenuWrapper);
  335. List<MenuButton> menuBtnList = menuButtonService.list(queryBtnWrapper);
  336. List<MenuColumn> menuColList = menuColumnService.list(queryColWrapper);
  337. List<MenuForm> menuFormList = menuFormService.list(queryFormWrapper);
  338. List<MenuListVo> menuVoList = BeanUtil.copyToList(menuList, MenuListVo.class);
  339. AuthMenuVo resultVo = new AuthMenuVo();
  340. //菜单
  341. resultVo.setMenuList(TreeUtil.build(menuVoList));
  342. //按钮
  343. for (MenuButton menuBtn : menuBtnList) {
  344. resultVo.addButton(menuBtn.getMenuId(), BeanUtil.toBean(menuBtn, MenuButtonVo.class));
  345. }
  346. //列表
  347. for (MenuColumn menuColumn : menuColList) {
  348. resultVo.addColumn(menuColumn.getMenuId(), BeanUtil.toBean(menuColumn, MenuColumnVo.class));
  349. }
  350. //表单
  351. for (MenuForm menuForm : menuFormList) {
  352. resultVo.addForm(menuForm.getMenuId(), BeanUtil.toBean(menuForm, MenuFormVo.class));
  353. }
  354. return R.ok(resultVo);
  355. }
  356. @GetMapping("/parent-tree")
  357. @ApiOperation(value = "获取菜单树结构, 不包含页面类型的菜单")
  358. public R menuTree() {
  359. List<Menu> menuList = menuService.list(Wrappers.<Menu>query().lambda()
  360. .eq(Menu::getMenuType, MenuType.MENU.getCode())
  361. .eq(Menu::getEnabledMark, EnabledMark.ENABLED.getCode())
  362. .select(Menu.class, x -> VoToColumnUtil.fieldsToColumns(MenuListVo.class).contains(x.getProperty()))
  363. .orderByAsc(Menu::getSortCode));
  364. List<MenuListVo> voList = BeanUtil.copyToList(menuList, MenuListVo.class);
  365. List<MenuListVo> treeVoList = TreeUtil.build(voList);
  366. return R.ok(treeVoList);
  367. }
  368. @GetMapping("/validate-url")
  369. @ApiOperation(value = "验证菜单路由是否存在")
  370. public R validateUrl(@RequestParam String outputArea, String className) {
  371. String component = StringPool.SLASH + StringUtils.lowerCase(outputArea) + StringPool.SLASH + StringUtils.lowerCase(className) + StringPool.SLASH + "index";
  372. long count = menuService.count(Wrappers.lambdaQuery(Menu.class).eq(Menu::getComponent, component));
  373. return R.ok(count > 0);
  374. }
  375. @GetMapping("/validate-code")
  376. @ApiOperation(value = "验证菜单编码是否存在")
  377. public R validateCode(@RequestParam(required = false) Long id, @RequestParam String code) {
  378. long count = menuService.count(Wrappers.lambdaQuery(Menu.class).eq(Menu::getCode, code).ne(id != null, Menu::getId, id));
  379. return R.ok(count > 0);
  380. }
  381. }