SystemMenuServiceImpl.java
7.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package com.diligrp.rider.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.diligrp.rider.common.enums.MenuScopeEnum;
import com.diligrp.rider.common.exception.BizException;
import com.diligrp.rider.dto.AdminMenuSaveDTO;
import com.diligrp.rider.entity.SysMenu;
import com.diligrp.rider.mapper.SysMenuMapper;
import com.diligrp.rider.service.SystemMenuService;
import com.diligrp.rider.vo.AdminRoleMenuTreeVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
public class SystemMenuServiceImpl implements SystemMenuService {
private final SysMenuMapper sysMenuMapper;
@Override
public List<AdminRoleMenuTreeVO> tree() {
List<SysMenu> menus = listAllMenus();
return buildTree(menus, Map.of(), false);
}
@Override
public void add(AdminMenuSaveDTO dto) {
validateSave(dto, null);
SysMenu menu = new SysMenu();
apply(menu, dto);
menu.setCreateTime(System.currentTimeMillis() / 1000);
sysMenuMapper.insert(menu);
}
@Override
public void edit(AdminMenuSaveDTO dto) {
if (dto.getId() == null || dto.getId() < 1) {
throw new BizException("菜单ID不能为空");
}
SysMenu existing = requireMenu(dto.getId());
validateSave(dto, existing);
apply(existing, dto);
sysMenuMapper.updateById(existing);
}
@Override
@Transactional
public void delete(Long id) {
SysMenu menu = requireMenu(id);
Long childCount = sysMenuMapper.selectCount(new LambdaQueryWrapper<SysMenu>()
.eq(SysMenu::getParentId, id));
if (childCount != null && childCount > 0) {
throw new BizException("请先删除子菜单");
}
sysMenuMapper.deleteById(menu.getId());
}
@Override
public void setVisible(Long id, int visible) {
requireMenu(id);
sysMenuMapper.update(null, new LambdaUpdateWrapper<SysMenu>()
.eq(SysMenu::getId, id)
.set(SysMenu::getVisible, visible));
}
@Override
public void setStatus(Long id, int status) {
requireMenu(id);
sysMenuMapper.update(null, new LambdaUpdateWrapper<SysMenu>()
.eq(SysMenu::getId, id)
.set(SysMenu::getStatus, status));
}
public List<SysMenu> listAllMenus() {
return sysMenuMapper.selectList(new LambdaQueryWrapper<SysMenu>()
.orderByAsc(SysMenu::getListOrder)
.orderByAsc(SysMenu::getId));
}
public List<AdminRoleMenuTreeVO> buildTree(List<SysMenu> menus, Map<Long, Boolean> checkedMap, boolean disableByScope) {
Map<Long, AdminRoleMenuTreeVO> voMap = new LinkedHashMap<>();
List<AdminRoleMenuTreeVO> roots = new ArrayList<>();
for (SysMenu menu : menus) {
AdminRoleMenuTreeVO vo = toVO(menu, checkedMap.get(menu.getId()));
if (disableByScope && checkedMap.get(menu.getId()) == null) {
vo.setDisabled(true);
}
voMap.put(menu.getId(), vo);
Long parentId = menu.getParentId() == null ? 0L : menu.getParentId();
if (parentId > 0 && voMap.containsKey(parentId)) {
voMap.get(parentId).getChildren().add(vo);
} else {
roots.add(vo);
}
}
return roots;
}
private void validateSave(AdminMenuSaveDTO dto, SysMenu existing) {
validateTypeAndPath(dto);
validateScope(dto.getMenuScope());
SysMenu duplicate = sysMenuMapper.selectOne(new LambdaQueryWrapper<SysMenu>()
.eq(SysMenu::getCode, dto.getCode())
.ne(existing != null, SysMenu::getId, existing != null ? existing.getId() : null)
.last("LIMIT 1"));
if (duplicate != null) {
throw new BizException("菜单编码已存在");
}
Long parentId = dto.getParentId() == null ? 0L : dto.getParentId();
if (parentId > 0) {
SysMenu parent = requireMenu(parentId);
if (existing != null && existing.getId().equals(parent.getId())) {
throw new BizException("父级菜单不能选择自己");
}
if (existing != null) {
ensureNotDescendant(parent.getId(), existing.getId());
}
}
}
private void validateTypeAndPath(AdminMenuSaveDTO dto) {
if (!"DIR".equals(dto.getType()) && !"MENU".equals(dto.getType())) {
throw new BizException("菜单类型只能是 DIR 或 MENU");
}
if ("MENU".equals(dto.getType()) && !StringUtils.hasText(dto.getPath())) {
throw new BizException("菜单路由不能为空");
}
}
private void validateScope(String scope) {
for (MenuScopeEnum value : MenuScopeEnum.values()) {
if (value.name().equals(scope)) {
return;
}
}
throw new BizException("菜单范围不合法");
}
private void ensureNotDescendant(Long parentId, Long selfId) {
Long currentId = parentId;
while (currentId != null && currentId > 0) {
if (currentId.equals(selfId)) {
throw new BizException("父级菜单不能选择当前菜单的子节点");
}
SysMenu current = sysMenuMapper.selectById(currentId);
currentId = current == null ? null : current.getParentId();
}
}
private SysMenu requireMenu(Long id) {
SysMenu menu = sysMenuMapper.selectById(id);
if (menu == null) {
throw new BizException("菜单不存在");
}
return menu;
}
private void apply(SysMenu menu, AdminMenuSaveDTO dto) {
menu.setCode(dto.getCode());
menu.setName(dto.getName());
menu.setType(dto.getType());
menu.setPath(StringUtils.hasText(dto.getPath()) ? dto.getPath().trim() : "");
menu.setIcon(StringUtils.hasText(dto.getIcon()) ? dto.getIcon().trim() : "");
menu.setParentId(dto.getParentId());
menu.setMenuScope(dto.getMenuScope());
menu.setListOrder(dto.getListOrder() == null ? 0 : dto.getListOrder());
menu.setVisible(dto.getVisible() == null ? 1 : dto.getVisible());
menu.setStatus(dto.getStatus() == null ? 1 : dto.getStatus());
}
private AdminRoleMenuTreeVO toVO(SysMenu menu, Boolean checked) {
AdminRoleMenuTreeVO vo = new AdminRoleMenuTreeVO();
vo.setId(menu.getId());
vo.setCode(menu.getCode());
vo.setName(menu.getName());
vo.setType(menu.getType());
vo.setPath(menu.getPath());
vo.setIcon(menu.getIcon());
vo.setMenuScope(menu.getMenuScope());
vo.setVisible(menu.getVisible());
vo.setStatus(menu.getStatus());
vo.setListOrder(menu.getListOrder());
vo.setChecked(Boolean.TRUE.equals(checked));
return vo;
}
}