重新修改了组织权限管理功能

This commit is contained in:
root 2025-06-18 10:20:10 +08:00
parent c5d701282f
commit fe40140a69
51 changed files with 2456 additions and 3389 deletions

View File

@ -1,16 +1,6 @@
package com.stdproject.config;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.entity.AppUser;
import com.stdproject.entity.AppRole;
import com.stdproject.entity.AppRoleUser;
import com.stdproject.entity.AppRoleMenu;
import com.stdproject.entity.AppMenu;
import com.stdproject.service.IAppUserService;
import com.stdproject.service.IAppRoleService;
import com.stdproject.service.IAppRoleUserService;
import com.stdproject.service.IAppRoleMenuService;
import com.stdproject.service.IAppMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;

View File

@ -0,0 +1,54 @@
package com.stdproject.config;
import java.util.HashMap;
public class ResponseResult extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public ResponseResult() {
}
public static ResponseResult error() {
return error("操作失败");
}
public static ResponseResult success() {
return success("操作成功");
}
public static ResponseResult error(String msg) {
ResponseResult json = new ResponseResult();
json.put((String)"code", "1");//错误
json.put((String)"msg", msg);
return json;
}
public static ResponseResult message(String code, String msg) {
ResponseResult json = new ResponseResult();
json.put((String)"code", code);
json.put((String)"msg", msg);
return json;
}
public static ResponseResult success(String msg) {
ResponseResult json = new ResponseResult();
json.put((String)"code", "0");//正常
json.put((String)"msg", msg);
return json;
}
public static ResponseResult successData(Object obj) {
ResponseResult json = new ResponseResult();
json.put((String)"code", "0");//正常
json.put((String)"msg", "操作成功");
json.put("data", obj);
return json;
}
public ResponseResult put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@ -1,271 +0,0 @@
package com.stdproject.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppDictionary;
import com.stdproject.service.IAppDictionaryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 应用-数据字典表 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "数据字典管理", description = "数据字典添加、数据字典修改、数据字典删除、数据字典查询等功能")
@RestController
@RequestMapping("/app-dictionary")
public class AppDictionaryController {
@Autowired
private IAppDictionaryService appDictionaryService;
@Operation(summary = "分页查询数据字典列表")
@PostMapping("/page")
@OperationLog(type = "06", module = "数据字典管理", description = "分页查询数据字典列表")
public Result<IPage<AppDictionary>> page(@RequestBody @Valid PageRequest pageRequest) {
Page<AppDictionary> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
// 关键字搜索
if (StringUtils.hasText(pageRequest.getKeyword())) {
queryWrapper.and(wrapper -> wrapper
.like("dictname", pageRequest.getKeyword())
.or().like("dictcode", pageRequest.getKeyword())
.or().like("dictdata", pageRequest.getKeyword())
);
}
// 排序
if (StringUtils.hasText(pageRequest.getOrderBy())) {
if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
queryWrapper.orderByAsc(pageRequest.getOrderBy());
} else {
queryWrapper.orderByDesc(pageRequest.getOrderBy());
}
} else {
queryWrapper.orderByAsc("dictcode", "orderno");
}
IPage<AppDictionary> result = appDictionaryService.page(page, queryWrapper);
return Result.success(result);
}
@Operation(summary = "查询所有数据字典列表")
@GetMapping("/list")
@OperationLog(type = "06", module = "数据字典管理", description = "查询所有数据字典列表")
public Result<List<AppDictionary>> list() {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("dictcode", "orderno");
List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
return Result.success(dictionaries);
}
@Operation(summary = "根据ID查询数据字典详情")
@GetMapping("/{id}")
@OperationLog(type = "06", module = "数据字典管理", description = "查询数据字典详情")
public Result<AppDictionary> getById(@Parameter(description = "字典ID") @PathVariable String id) {
AppDictionary dictionary = appDictionaryService.getById(id);
return Result.success(dictionary);
}
@Operation(summary = "根据字典编码查询字典项列表")
@GetMapping("/code/{dictCode}")
@OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码查询字典项列表")
public Result<List<AppDictionary>> getByDictCode(@Parameter(description = "字典编码") @PathVariable String dictCode) {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictcode", dictCode);
queryWrapper.orderByAsc("orderno");
List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
return Result.success(dictionaries);
}
@Operation(summary = "根据字典编码和字典值查询字典项")
@GetMapping("/code/{dictCode}/data/{dictData}")
@OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码和字典数据查询字典项")
public Result<AppDictionary> getByCodeAndData(
@Parameter(description = "字典编码") @PathVariable String dictCode,
@Parameter(description = "字典数据") @PathVariable String dictData) {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictcode", dictCode);
queryWrapper.eq("dictdata", dictData);
AppDictionary dictionary = appDictionaryService.getOne(queryWrapper);
return Result.success(dictionary);
}
@Operation(summary = "新增数据字典")
@PostMapping
@OperationLog(type = "01", module = "数据字典管理", description = "新增数据字典")
public Result<String> save(@RequestBody @Valid AppDictionary appDictionary) {
// 检查同一字典编码下的字典值是否已存在
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictcode", appDictionary.getDictcode());
queryWrapper.eq("dictdata", appDictionary.getDictdata());
AppDictionary existDictionary = appDictionaryService.getOne(queryWrapper);
if (existDictionary != null) {
return Result.error("该字典编码下的字典值已存在");
}
// 设置默认值
if (appDictionary.getOrderno() == null) {
// 获取同一字典编码下的最大序号
QueryWrapper<AppDictionary> orderQuery = new QueryWrapper<>();
orderQuery.eq("app_id", appDictionary.getAppId());
orderQuery.orderByDesc("orderno");
orderQuery.last("LIMIT 1");
AppDictionary lastDict = appDictionaryService.getOne(orderQuery);
appDictionary.setOrderno(lastDict != null ? lastDict.getOrderno() + 1 : 1);
}
appDictionary.setLastmodifydate(LocalDateTime.now());
boolean success = appDictionaryService.save(appDictionary);
return success ? Result.success("新增成功") : Result.error("新增失败");
}
@Operation(summary = "修改数据字典")
@PutMapping
@OperationLog(type = "02", module = "数据字典管理", description = "修改数据字典")
public Result<String> update(@RequestBody @Valid AppDictionary appDictionary) {
// 检查字典是否存在
AppDictionary existDictionary = appDictionaryService.getById(appDictionary.getId());
if (existDictionary == null) {
return Result.error("数据字典不存在");
}
// 如果修改了字典编码或字典值检查新的组合是否已被其他字典项使用
if (!existDictionary.getDictcode().equals(appDictionary.getDictcode()) ||
!existDictionary.getDictdata().equals(appDictionary.getDictdata())) {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictcode", appDictionary.getDictcode());
queryWrapper.eq("dictdata", appDictionary.getDictdata());
queryWrapper.ne("id", appDictionary.getId());
AppDictionary dictWithSameCodeValue = appDictionaryService.getOne(queryWrapper);
if (dictWithSameCodeValue != null) {
return Result.error("该字典编码下的字典数据已被其他字典项使用");
}
}
appDictionary.setLastmodifydate(LocalDateTime.now());
boolean success = appDictionaryService.updateById(appDictionary);
return success ? Result.success("修改成功") : Result.error("修改失败");
}
@Operation(summary = "删除数据字典")
@DeleteMapping("/{id}")
@OperationLog(type = "03", module = "数据字典管理", description = "删除数据字典")
public Result<String> delete(@Parameter(description = "字典ID") @PathVariable String id) {
boolean success = appDictionaryService.removeById(id);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
@Operation(summary = "批量删除数据字典")
@DeleteMapping("/batch")
@OperationLog(type = "03", module = "数据字典管理", description = "批量删除数据字典")
public Result<String> deleteBatch(@RequestBody List<String> ids) {
boolean success = appDictionaryService.removeByIds(ids);
return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
}
@Operation(summary = "根据字典编码删除所有字典项")
@DeleteMapping("/code/{dictCode}")
@OperationLog(type = "03", module = "数据字典管理", description = "根据字典编码删除所有字典项")
public Result<String> deleteByDictCode(@Parameter(description = "字典编码") @PathVariable String dictCode) {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictcode", dictCode);
boolean success = appDictionaryService.remove(queryWrapper);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
@Operation(summary = "根据字典名称获取字典数据")
@GetMapping("/name/{dictName}")
@OperationLog(type = "06", module = "数据字典管理", description = "根据字典名称获取字典数据")
public Result<String> getDictDataByName(@Parameter(description = "字典名称") @PathVariable String dictName) {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("dictname", dictName);
AppDictionary dictionary = appDictionaryService.getOne(queryWrapper);
if (dictionary != null) {
return Result.success(dictionary.getDictdata());
}
return Result.error("未找到对应的字典数据");
}
@Operation(summary = "获取所有字典编码列表")
@GetMapping("/codes")
@OperationLog(type = "06", module = "数据字典管理", description = "获取所有字典编码列表")
public Result<List<String>> getDictCodes() {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.select("DISTINCT dictcode");
queryWrapper.orderByAsc("dictcode");
List<AppDictionary> dictionaries = appDictionaryService.list(queryWrapper);
List<String> dictCodes = dictionaries.stream()
.map(AppDictionary::getDictcode)
.distinct()
.collect(java.util.stream.Collectors.toList());
return Result.success(dictCodes);
}
@Operation(summary = "调整字典项顺序")
@PutMapping("/reorder")
@OperationLog(type = "02", module = "数据字典管理", description = "调整字典项顺序")
public Result<String> reorder(@RequestBody List<DictOrderRequest> orderRequests) {
for (DictOrderRequest request : orderRequests) {
AppDictionary dictionary = appDictionaryService.getById(request.getId());
if (dictionary != null) {
dictionary.setOrderno(request.getOrderno());
dictionary.setLastmodifydate(LocalDateTime.now());
appDictionaryService.updateById(dictionary);
}
}
return Result.success("顺序调整成功");
}
@Operation(summary = "根据字典编码分组查询字典项")
@GetMapping("/grouped")
@OperationLog(type = "06", module = "数据字典管理", description = "根据字典编码分组查询字典项")
public Result<Map<String, List<AppDictionary>>> getGroupedDictionaries() {
QueryWrapper<AppDictionary> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("dictcode", "orderno");
List<AppDictionary> allDictionaries = appDictionaryService.list(queryWrapper);
java.util.Map<String, List<AppDictionary>> groupedDict = allDictionaries.stream()
.collect(java.util.stream.Collectors.groupingBy(AppDictionary::getDictcode));
return Result.success(groupedDict);
}
/**
* 字典排序请求
*/
public static class DictOrderRequest {
private String id;
private Integer orderno;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public Integer getOrderno() { return orderno; }
public void setOrderno(Integer orderno) { this.orderno = orderno; }
}
}

View File

@ -1,499 +0,0 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppMenu;
import com.stdproject.service.IAppMenuService;
import com.stdproject.service.IAppUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 应用-菜单表 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "菜单管理", description = "菜单添加、菜单修改、菜单删除、菜单查询等功能")
@RestController
@RequestMapping("/app-menu")
public class AppMenuController {
@Autowired
private IAppMenuService appMenuService;
@Autowired
private IAppUserService appUserService;
@Operation(summary = "分页查询菜单列表")
@PostMapping("/page")
@OperationLog(type = "06", module = "菜单管理", description = "分页查询菜单列表")
public Result<IPage<AppMenu>> page(@RequestBody @Valid PageRequest pageRequest) {
Page<AppMenu> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
// 关键字搜索
if (StringUtils.hasText(pageRequest.getKeyword())) {
queryWrapper.and(wrapper -> wrapper
.like("name", pageRequest.getKeyword())
.or().like("code", pageRequest.getKeyword())
.or().like("url", pageRequest.getKeyword())
);
}
// 排序
if (StringUtils.hasText(pageRequest.getOrderBy())) {
if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
queryWrapper.orderByAsc(pageRequest.getOrderBy());
} else {
queryWrapper.orderByDesc(pageRequest.getOrderBy());
}
} else {
queryWrapper.orderByAsc("parentid", "orderno");
}
IPage<AppMenu> result = appMenuService.page(page, queryWrapper);
return Result.success(result);
}
@Operation(summary = "查询所有菜单列表")
@GetMapping("/list")
@OperationLog(type = "06", module = "菜单管理", description = "查询所有菜单列表")
public Result<List<AppMenu>> list() {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("parentid", "orderno");
List<AppMenu> menus = appMenuService.list(queryWrapper);
return Result.success(menus);
}
@Operation(summary = "获取菜单树形结构")
@GetMapping("/tree")
@OperationLog(type = "06", module = "菜单管理", description = "获取菜单树形结构")
public Result<List<MenuTreeNode>> getMenuTree(@RequestParam String appId,@RequestParam String name) {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(appId),"app_id", appId);
queryWrapper.like(StrUtil.isNotBlank(name),"name", name);
queryWrapper.orderByAsc("parentid", "orderno");
List<AppMenu> allMenus = appMenuService.list(queryWrapper);
List<MenuTreeNode> tree = buildMenuTree(allMenus, "0");
return Result.success(tree);
}
@Operation(summary = "根据ID查询菜单详情")
@GetMapping("/{id}")
@OperationLog(type = "06", module = "菜单管理", description = "查询菜单详情")
public Result<AppMenu> getById(@Parameter(description = "菜单ID") @PathVariable String id) {
AppMenu menu = appMenuService.getById(id);
return Result.success(menu);
}
@Operation(summary = "根据父级ID查询子菜单")
@GetMapping("/children/{parentId}")
@OperationLog(type = "06", module = "菜单管理", description = "根据父级ID查询子菜单")
public Result<List<AppMenu>> getChildren(@Parameter(description = "父级菜单ID") @PathVariable String parentId) {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parentid", parentId);
queryWrapper.orderByAsc("orderno");
List<AppMenu> children = appMenuService.list(queryWrapper);
return Result.success(children);
}
@Operation(summary = "新增菜单")
@PostMapping
@OperationLog(type = "01", module = "菜单管理", description = "新增菜单")
public Result<String> save(@RequestBody @Valid AppMenu appMenu) {
// 检查菜单编号是否已存在
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("code", appMenu.getCode());
AppMenu existMenu = appMenuService.getOne(queryWrapper);
if (existMenu != null) {
return Result.error("菜单编号已存在");
}
// 检查父级菜单是否存在如果不是顶级菜单
if (!"0".equals(appMenu.getParentid())) {
AppMenu parentMenu = appMenuService.getById(appMenu.getParentid());
if (parentMenu == null) {
return Result.error("父级菜单不存在");
}
}
// 设置默认值
if (appMenu.getOrderno() == null) {
// 获取同级菜单的最大序号
QueryWrapper<AppMenu> orderQuery = new QueryWrapper<>();
orderQuery.eq("parentid", appMenu.getParentid());
orderQuery.orderByDesc("orderno");
orderQuery.last("LIMIT 1");
AppMenu lastMenu = appMenuService.getOne(orderQuery);
appMenu.setOrderno(lastMenu != null ? lastMenu.getOrderno() + 1 : 1);
}
if (!StringUtils.hasText(appMenu.getIsdisplay())) {
appMenu.setIsdisplay("1");
}
if (!StringUtils.hasText(appMenu.getIslink())) {
appMenu.setIslink("0");
}
if (!StringUtils.hasText(appMenu.getType())) {
appMenu.setType("01");
}
appMenu.setLastmodifydate(LocalDateTime.now());
appMenu.setLastmodifier(appUserService.getCurrentUsername());
boolean success = appMenuService.save(appMenu);
return success ? Result.success("新增成功") : Result.error("新增失败");
}
@Operation(summary = "修改菜单")
@PutMapping
@OperationLog(type = "02", module = "菜单管理", description = "修改菜单")
public Result<String> update(@RequestBody @Valid AppMenu appMenu) {
// 检查菜单是否存在
AppMenu existMenu = appMenuService.getById(appMenu.getId());
if (existMenu == null) {
return Result.error("菜单不存在");
}
// 如果修改了菜单编号检查新编号是否已被其他菜单使用
if (!existMenu.getCode().equals(appMenu.getCode())) {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("code", appMenu.getCode());
queryWrapper.ne("id", appMenu.getId());
AppMenu menuWithSameCode = appMenuService.getOne(queryWrapper);
if (menuWithSameCode != null) {
return Result.error("菜单编号已被其他菜单使用");
}
}
// 如果修改了父级菜单检查是否会形成循环引用
if (!existMenu.getParentid().equals(appMenu.getParentid())) {
if (isCircularReference(appMenu.getId(), appMenu.getParentid())) {
return Result.error("不能将菜单移动到自己的子菜单下");
}
// 检查父级菜单是否存在如果不是顶级菜单
if (!"0".equals(existMenu.getParentid())) {
AppMenu parentMenu = appMenuService.getById(appMenu.getParentid());
if (parentMenu == null) {
return Result.error("父级菜单不存在");
}
}
}
appMenu.setLastmodifydate(LocalDateTime.now());
appMenu.setLastmodifier(appUserService.getCurrentUsername());
boolean success = appMenuService.updateById(appMenu);
return success ? Result.success("修改成功") : Result.error("修改失败");
}
@Operation(summary = "更新菜单及按钮是否有效")
@PutMapping("/display/{id}")
@OperationLog(type = "02", module = "菜单管理", description = "更新菜单及按钮是否有效")
public Result<String> setIsDisplay(
@Parameter(description = "菜单ID") @PathVariable String id,
@RequestParam String isDisplay) {
LambdaUpdateWrapper<AppMenu> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AppMenu::getId, id).set(AppMenu::getIsdisplay, isDisplay).set(AppMenu::getLastmodifydate,
LocalDateTime.now()).set(AppMenu::getLastmodifier, appUserService.getCurrentUsername());
boolean success = appMenuService.update(updateWrapper);
return success ? Result.success("更新成功") : Result.error("更新失败");
}
@Operation(summary = "更新关联模块ID")
@PutMapping("/module/{id}")
@OperationLog(type = "02", module = "菜单管理", description = "更新关联模块ID")
public Result<String> setModuleId(
@Parameter(description = "菜单ID") @PathVariable String id,
@RequestParam String moduleId) {
LambdaUpdateWrapper<AppMenu> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AppMenu::getId, id).set(AppMenu::getModuleId, moduleId).set(AppMenu::getLastmodifydate,
LocalDateTime.now()).set(AppMenu::getLastmodifier, appUserService.getCurrentUsername());
boolean success = appMenuService.update(updateWrapper);
return success ? Result.success("更新成功") : Result.error("更新失败");
}
@Operation(summary = "删除菜单")
@DeleteMapping("/{id}")
@OperationLog(type = "03", module = "菜单管理", description = "删除菜单")
public Result<String> delete(@Parameter(description = "菜单ID") @PathVariable String id) {
// 检查是否有子菜单
QueryWrapper<AppMenu> childQuery = new QueryWrapper<>();
childQuery.eq("parentid", id);
long childCount = appMenuService.count(childQuery);
if (childCount > 0) {
return Result.error("存在子菜单,无法删除");
}
boolean success = appMenuService.removeById(id);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
@Operation(summary = "批量删除菜单")
@DeleteMapping("/batch")
@OperationLog(type = "03", module = "菜单管理", description = "批量删除菜单")
public Result<String> deleteBatch(@RequestBody List<String> ids) {
for (String id : ids) {
// 检查是否有子菜单
QueryWrapper<AppMenu> childQuery = new QueryWrapper<>();
childQuery.eq("parentid", id);
long childCount = appMenuService.count(childQuery);
if (childCount > 0) {
return Result.error("存在子菜单的菜单无法删除");
}
}
boolean success = appMenuService.removeByIds(ids);
return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
}
@Operation(summary = "根据菜单类型查询菜单列表")
@GetMapping("/type/{type}")
@OperationLog(type = "06", module = "菜单管理", description = "根据菜单类型查询菜单列表")
public Result<List<AppMenu>> getByType(@Parameter(description = "菜单类型") @PathVariable String type) {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("type", type);
queryWrapper.orderByAsc("parentid", "orderno");
List<AppMenu> menus = appMenuService.list(queryWrapper);
return Result.success(menus);
}
@Operation(summary = "获取显示的菜单树")
@GetMapping("/display-tree")
@OperationLog(type = "06", module = "菜单管理", description = "获取显示的菜单树")
public Result<List<MenuTreeNode>> getDisplayMenuTree() {
QueryWrapper<AppMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("isdisplay", "1");
queryWrapper.orderByAsc("parentid", "orderno");
List<AppMenu> displayMenus = appMenuService.list(queryWrapper);
List<MenuTreeNode> tree = buildMenuTree(displayMenus, "0");
return Result.success(tree);
}
@Operation(summary = "调整菜单顺序")
@PutMapping("/reorder")
@OperationLog(type = "02", module = "菜单管理", description = "调整菜单顺序")
public Result<String> reorder(@RequestBody List<MenuOrderRequest> orderRequests) {
for (MenuOrderRequest request : orderRequests) {
AppMenu menu = appMenuService.getById(request.getId());
if (menu != null) {
menu.setOrderno(request.getOrderno());
menu.setLastmodifydate(LocalDateTime.now());
appMenuService.updateById(menu);
}
}
return Result.success("顺序调整成功");
}
/**
* 构建菜单树
*/
private List<MenuTreeNode> buildMenuTree(List<AppMenu> allMenus, String parentId) {
return allMenus.stream()
.filter(menu -> parentId.equals(menu.getParentid()))
.map(menu -> {
MenuTreeNode node = new MenuTreeNode();
node.setId(menu.getId());
node.setCode(menu.getCode());
node.setName(menu.getName());
node.setIcon(menu.getIcon());
node.setUrl(menu.getUrl());
node.setType(menu.getType());
node.setIslink(menu.getIslink());
node.setIsdisplay(menu.getIsdisplay());
node.setOrderno(menu.getOrderno());
node.setParentid(menu.getParentid());
node.setModuleId(menu.getModuleId());
node.setChildren(buildMenuTree(allMenus, menu.getId()));
return node;
})
.collect(Collectors.toList());
}
/**
* 检查是否会形成循环引用
*/
private boolean isCircularReference(String menuId, String newParentId) {
if ("0".equals(newParentId)) {
return false;
}
if (menuId.equals(newParentId)) {
return true;
}
AppMenu parentMenu = appMenuService.getById(newParentId);
if (parentMenu == null) {
return false;
}
return isCircularReference(menuId, parentMenu.getParentid());
}
/**
* 菜单树节点
*/
public static class MenuTreeNode {
private String id;
private String code;
private String name;
private String icon;
private String url;
private String type;
private String islink;
private String isdisplay;
private Integer orderno;
private String parentid;
private String moduleId;
private List<MenuTreeNode> children = new ArrayList<>();
// Getters and Setters
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getIslink() {
return islink;
}
public void setIslink(String islink) {
this.islink = islink;
}
public String getIsdisplay() {
return isdisplay;
}
public void setIsdisplay(String isdisplay) {
this.isdisplay = isdisplay;
}
public Integer getOrderno() {
return orderno;
}
public void setOrderno(Integer orderno) {
this.orderno = orderno;
}
public String getParentid() {
return parentid;
}
public void setParentid(String parentid) {
this.parentid = parentid;
}
public String getModuleId() {
return moduleId;
}
public void setModuleId(String moduleId) {
this.moduleId = moduleId;
}
public List<MenuTreeNode> getChildren() {
return children;
}
public void setChildren(List<MenuTreeNode> children) {
this.children = children;
}
}
/**
* 菜单排序请求
*/
public static class MenuOrderRequest {
private String id;
private Integer orderno;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Integer getOrderno() {
return orderno;
}
public void setOrderno(Integer orderno) {
this.orderno = orderno;
}
}
}

View File

@ -1,284 +0,0 @@
package com.stdproject.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppOptLog;
import com.stdproject.service.IAppOptLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
* <p>
* 应用-操作日志表 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "操作日志管理", description = "操作日志查询、操作日志删除等功能")
@RestController
@RequestMapping("/api/optlog")
@Slf4j
public class AppOptLogController {
@Autowired
private IAppOptLogService appOptLogService;
@Operation(summary = "分页查询操作日志列表")
@PostMapping("/page")
@OperationLog(type = "06", module = "操作日志管理", description = "分页查询操作日志列表")
public Result<IPage<AppOptLog>> page(@RequestBody @Valid PageRequest pageRequest) {
Page<AppOptLog> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
// 关键字搜索
if (StringUtils.hasText(pageRequest.getKeyword())) {
queryWrapper.and(wrapper -> wrapper
.like("username", pageRequest.getKeyword())
.or().like("module", pageRequest.getKeyword())
.or().like("description", pageRequest.getKeyword())
);
}
// 排序
if (StringUtils.hasText(pageRequest.getOrderBy())) {
if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
queryWrapper.orderByAsc(pageRequest.getOrderBy());
} else {
queryWrapper.orderByDesc(pageRequest.getOrderBy());
}
} else {
queryWrapper.orderByDesc("logtime");
}
IPage<AppOptLog> result = appOptLogService.page(page, queryWrapper);
return Result.success(result);
}
@Operation(summary = "根据ID查询操作日志详情")
@GetMapping("/{id}")
@OperationLog(type = "06", module = "操作日志管理", description = "查询操作日志详情")
public Result<AppOptLog> getById(@Parameter(description = "日志ID") @PathVariable String id) {
AppOptLog optLog = appOptLogService.getById(id);
return Result.success(optLog);
}
@Operation(summary = "根据用户名查询操作日志")
@GetMapping("/user/{username}")
@OperationLog(type = "06", module = "操作日志管理", description = "根据用户名查询操作日志")
public Result<List<AppOptLog>> getByUsername(
@Parameter(description = "用户名") @PathVariable String username,
@Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", username);
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
@Operation(summary = "根据操作类型查询操作日志")
@GetMapping("/type/{type}")
@OperationLog(type = "06", module = "操作日志管理", description = "根据操作类型查询操作日志")
public Result<List<AppOptLog>> getByType(
@Parameter(description = "操作类型") @PathVariable String type,
@Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("type", type);
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
@Operation(summary = "根据模块查询操作日志")
@GetMapping("/module/{module}")
@OperationLog(type = "06", module = "操作日志管理", description = "根据模块查询操作日志")
public Result<List<AppOptLog>> getByModule(
@Parameter(description = "模块名称") @PathVariable String module,
@Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("module", module);
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
@Operation(summary = "根据时间范围查询操作日志")
@GetMapping("/time-range")
@OperationLog(type = "06", module = "操作日志管理", description = "根据时间范围查询操作日志")
public Result<List<AppOptLog>> getByTimeRange(
@Parameter(description = "开始时间") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
@Parameter(description = "结束时间") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
@Parameter(description = "限制条数") @RequestParam(defaultValue = "1000") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.between("logtime", startTime, endTime);
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
@Operation(summary = "根据IP地址查询操作日志")
@GetMapping("/ip/{ip}")
@OperationLog(type = "06", module = "操作日志管理", description = "根据IP地址查询操作日志")
public Result<List<AppOptLog>> getByIp(
@Parameter(description = "IP地址") @PathVariable String ip,
@Parameter(description = "限制条数") @RequestParam(defaultValue = "100") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("ip", ip);
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
@Operation(summary = "删除操作日志")
@DeleteMapping("/{id}")
@OperationLog(type = "03", module = "操作日志管理", description = "删除操作日志")
public Result<String> delete(@Parameter(description = "日志ID") @PathVariable String id) {
boolean success = appOptLogService.removeById(id);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
@Operation(summary = "批量删除操作日志")
@DeleteMapping("/batch")
@OperationLog(type = "03", module = "操作日志管理", description = "批量删除操作日志")
public Result<String> deleteBatch(@RequestBody List<String> ids) {
boolean success = appOptLogService.removeByIds(ids);
return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
}
@Operation(summary = "清理指定天数前的操作日志")
@DeleteMapping("/clean/{days}")
@OperationLog(type = "03", module = "操作日志管理", description = "清理历史操作日志")
public Result<String> cleanOldLogs(@Parameter(description = "保留天数") @PathVariable Integer days) {
try {
// 参数校验
if (days == null || days < 0 || days > 3650) {
return Result.error("保留天数必须在0到3650之间");
}
LocalDateTime cutoff = LocalDateTime.now().minusDays(days);
LambdaQueryWrapper<AppOptLog> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.lt(AppOptLog::getLogtime, cutoff);
boolean success = appOptLogService.remove(queryWrapper);
return success ? Result.success("清理成功") : Result.error("清理失败");
} catch (Exception e) {
// 记录异常日志以便排查
log.error("清理操作日志失败", e);
return Result.error("系统异常,请稍后再试");
}
}
@Operation(summary = "获取操作日志统计信息")
@GetMapping("/statistics")
@OperationLog(type = "06", module = "操作日志管理", description = "获取操作日志统计信息")
public Result<LogStatistics> getStatistics() {
// 总日志数
long totalCount = appOptLogService.count();
// 今日日志数
LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
QueryWrapper<AppOptLog> todayQuery = new QueryWrapper<>();
todayQuery.ge("logtime", todayStart);
long todayCount = appOptLogService.count(todayQuery);
// 本周日志数
LocalDateTime weekStart = LocalDateTime.now().minusDays(7).withNano(0);
QueryWrapper<AppOptLog> weekQuery = new QueryWrapper<>();
weekQuery.ge("logtime", weekStart);
long weekCount = appOptLogService.count(weekQuery);
// 本月日志数
LocalDateTime monthStart = LocalDateTime.now().minusDays(30).withNano(0);
QueryWrapper<AppOptLog> monthQuery = new QueryWrapper<>();
monthQuery.ge("logtime", monthStart);
long monthCount = appOptLogService.count(monthQuery);
LogStatistics statistics = new LogStatistics();
statistics.setTotalCount(totalCount);
statistics.setTodayCount(todayCount);
statistics.setWeekCount(weekCount);
statistics.setMonthCount(monthCount);
return Result.success(statistics);
}
@Operation(summary = "获取最近的操作日志")
@GetMapping("/recent")
@OperationLog(type = "06", module = "操作日志管理", description = "获取最近的操作日志")
public Result<List<AppOptLog>> getRecentLogs(
@Parameter(description = "限制条数") @RequestParam(defaultValue = "50") Integer limit) {
QueryWrapper<AppOptLog> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("logtime");
queryWrapper.last("LIMIT " + limit);
List<AppOptLog> logs = appOptLogService.list(queryWrapper);
return Result.success(logs);
}
/**
* 日志统计信息
*/
public static class LogStatistics {
private Long totalCount;
private Long todayCount;
private Long weekCount;
private Long monthCount;
public Long getTotalCount() {
return totalCount;
}
public void setTotalCount(Long totalCount) {
this.totalCount = totalCount;
}
public Long getTodayCount() {
return todayCount;
}
public void setTodayCount(Long todayCount) {
this.todayCount = todayCount;
}
public Long getWeekCount() {
return weekCount;
}
public void setWeekCount(Long weekCount) {
this.weekCount = weekCount;
}
public Long getMonthCount() {
return monthCount;
}
public void setMonthCount(Long monthCount) {
this.monthCount = monthCount;
}
}
}

View File

@ -1,333 +0,0 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.stdproject.common.OperationLog;
import com.stdproject.common.Result;
import com.stdproject.entity.AppOrganization;
import com.stdproject.service.IAppOrganizationService;
import com.stdproject.service.IAppUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 应用-组织机构 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "组织管理", description = "组织添加、组织修改、组织删除、组织查询等功能,支持公司和部门两级树形结构")
@RestController
@RequestMapping("/api/org")
public class AppOrganizationController {
@Autowired
private IAppOrganizationService appOrganizationService;
// 需要在类开头注入 IAppUserService
@Autowired
private IAppUserService appUserService;
@Operation(summary = "查询公司结构树")
@GetMapping("/getCompanyTree")
@OperationLog(type = "06", module = "组织管理", description = "查询公司结构树")
public Result<List<OrganizationTreeNode>> getCompanyTree(@RequestParam String appId) {
QueryWrapper<AppOrganization> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(appId),"app_id", appId);
queryWrapper.eq("isvaild", "1");
queryWrapper.orderByAsc("orgcode");
List<AppOrganization> children = appOrganizationService.list(queryWrapper);
List<OrganizationTreeNode> organizationTreeNodes = buildOrganizationTree(children, "0");
return Result.success(organizationTreeNodes);
}
@Operation(summary = "查询公司/部门列表")
@GetMapping("/getDepartmentList")
@OperationLog(type = "06", module = "组织管理", description = "查询公司/部门列表")
public Result<List<AppOrganization>> getDepartmentList(@RequestParam String appId, @RequestParam String orgtype,
@RequestParam String parentid, @RequestParam String keystr) {
QueryWrapper<AppOrganization> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(appId), "app_id", appId);
queryWrapper.eq(StrUtil.isNotBlank(orgtype), "orgtype", orgtype);
queryWrapper.eq("parentid", parentid);
queryWrapper.eq("isvaild", "1");
if (StringUtils.hasText(keystr)) {
queryWrapper.and(wrapper -> wrapper
.like("orgname", keystr)
.or().like("orgcode", keystr)
.or().like("description", keystr)
);
}
queryWrapper.orderByAsc("orgcode");
List<AppOrganization> children = appOrganizationService.list(queryWrapper);
return Result.success(children);
}
@Operation(summary = "根据ID查询组织详情")
@GetMapping("getDetailById/{id}")
@OperationLog(type = "06", module = "组织管理", description = "根据ID查询组织详情")
public Result<AppOrganization> getDetailById(@PathVariable String id) {
AppOrganization organization = appOrganizationService.getById(id);
return Result.success(organization);
}
@Operation(summary = "新增组织")
@PostMapping("add")
@OperationLog(type = "01", module = "组织管理", description = "新增组织")
public Result<String> add(@RequestBody @Valid AppOrganization appOrganization) {
// 设置默认值
//生成新的组织编号 公司编号010101 部门编号0001
appOrganization.setOrgcode(getNewOrgCode(appOrganization.getOrgtype(), appOrganization.getParentid()));
//设置状态为有效
appOrganization.setIsvaild("1");
// 从当前登录用户上下文中获取用户名
appOrganization.setLastmodifier(appUserService.getCurrentUsername());
appOrganization.setLastmodifydate(LocalDateTime.now());
boolean success = appOrganizationService.save(appOrganization);
return success ? Result.success("新增成功") : Result.error("新增失败");
}
@Operation(summary = "修改组织")
@PostMapping("update")
@OperationLog(type = "02", module = "组织管理", description = "修改组织")
public Result<String> update(@RequestBody @Valid AppOrganization appOrganization) {
// 检查组织是否存在
AppOrganization existOrg = appOrganizationService.getById(appOrganization.getId());
if (existOrg == null) {
return Result.error("组织不存在");
}
// 验证父级组织变更的合法性
if (StringUtils.hasText(appOrganization.getParentid()) && !"0".equals(appOrganization.getParentid())) {
// 不能将自己设为父级
if (appOrganization.getId().equals(appOrganization.getParentid())) {
return Result.error("不能将自己设为父级组织");
}
// 验证父级组织是否存在
AppOrganization parent = appOrganizationService.getById(appOrganization.getParentid());
if (parent == null || !"1".equals(parent.getIsvaild())) {
return Result.error("父级组织不存在或已禁用");
}
if ("02".equals(parent.getOrgtype())) {
return Result.error("部门下不能有子组织");
}
}
appOrganization.setLastmodifier(appUserService.getCurrentUsername());
appOrganization.setLastmodifydate(LocalDateTime.now());
boolean success = appOrganizationService.updateById(appOrganization);
return success ? Result.success("修改成功") : Result.error("修改失败");
}
@Operation(summary = "设置组织是否有效")
@PutMapping("/isValid/{id}")
@OperationLog(type = "02", module = "组织管理", description = "设置组织是否有效")
public Result<String> setIsValid(
@Parameter(description = "组织ID") @PathVariable String id,
@RequestParam String isValid) {
LambdaUpdateWrapper<AppOrganization> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(AppOrganization::getId, id).set(AppOrganization::getIsvaild, isValid).set(AppOrganization::getLastmodifydate,
LocalDateTime.now()).set(AppOrganization::getLastmodifier, appUserService.getCurrentUsername());
boolean success = appOrganizationService.update(updateWrapper);
return success ? Result.success("设置成功") : Result.error("设置失败");
}
@Operation(summary = "删除组织")
@PostMapping("delete/{id}")
@OperationLog(type = "03", module = "组织管理", description = "删除组织")
public Result<String> delete(@PathVariable String id) {
boolean success = appOrganizationService.removeById(id);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
/**
* 根据组织类型和父节点生成新的组织编码
*
* @param orgType 组织类型"01"表示公司"02"表示部门
* @param parentId 父节点ID新增部门时使用
* @return 新的组织编码
*/
private String getNewOrgCode(String orgType, String parentId) {
if ("01".equals(orgType)) {
// 公司类型查找当前最大的公司编码并递增最后一级
AppOrganization parentOrg = null;
if (StringUtils.hasText(parentId) && !"0".equals(parentId)) {
parentOrg = appOrganizationService.getById(parentId);
if (parentOrg == null || !"1".equals(parentOrg.getIsvaild())) {
throw new IllegalArgumentException("无效的父级组织");
}
}
// 获取父节点编码顶级为01
String parentCode = parentOrg != null ? parentOrg.getOrgcode() : "01";
// 获取当前父节点下的最大子节点编码
String maxCompanyCode = getMaxCodeByParentId("01", parentId);
int nextLevel = 1;
if (maxCompanyCode != null && !maxCompanyCode.isEmpty()) {
try {
// 提取最后两位
String lastTwo = maxCompanyCode.substring(maxCompanyCode.length() - 2);
nextLevel = Integer.parseInt(lastTwo) + 1;
} catch (Exception e) {
nextLevel = 1; // 出错则重置为1
}
}
if (nextLevel > 99) {
throw new RuntimeException("公司编码已达上限,请联系管理员处理");
}
return parentCode + String.format("%02d", nextLevel);
} else if ("02".equals(orgType) && StringUtils.hasText(parentId)) {
// 部门类型查找该公司下最大部门编码并递增
AppOrganization parentOrg = appOrganizationService.getById(parentId);
if (parentOrg == null || !"1".equals(parentOrg.getIsvaild())) {
throw new IllegalArgumentException("无效的父级组织");
}
// 获取该父节点下最大部门编号
String maxDeptCodeStr = getMaxCodeByParentId("02", parentId);
int nextSeq = 1;
if (maxDeptCodeStr != null && !maxDeptCodeStr.isEmpty()) {
try {
nextSeq = Integer.parseInt(maxDeptCodeStr) + 1;
} catch (NumberFormatException e) {
nextSeq = 1;
}
}
if (nextSeq > 9999) {
throw new RuntimeException("部门编码已达上限,请联系管理员处理");
}
return String.format("%04d", nextSeq);
} else {
throw new IllegalArgumentException("无法生成组织编码:参数不完整");
}
}
private String getMaxCodeByParentId(String orgType, String parentId) {
LambdaQueryWrapper<AppOrganization> queryWrapper = new LambdaQueryWrapper<AppOrganization>()
.eq(AppOrganization::getOrgtype, orgType)
.eq(AppOrganization::getParentid, parentId)
.eq(AppOrganization::getIsvaild, "1")
.orderByDesc(AppOrganization::getOrgcode)
.select(AppOrganization::getOrgcode)
.last("LIMIT 1");
// 使用selectList方法获取符合条件的记录列表
List<AppOrganization> list = appOrganizationService.list(queryWrapper);
// 如果列表不为空返回第一个记录的orgcode
return list.isEmpty() ? null : list.get(0).getOrgcode();
}
/**
* 构建菜单树
*/
private List<OrganizationTreeNode> buildOrganizationTree(List<AppOrganization> allOrganizations, String parentId) {
return allOrganizations.stream()
.filter(organization -> parentId.equals(organization.getParentid()))
.map(organization -> {
OrganizationTreeNode node = new OrganizationTreeNode();
node.setId(organization.getId());
node.setAppId(organization.getAppId());
node.setOrgtype(organization.getOrgtype());
node.setOrgcode(organization.getOrgcode());
node.setOrgname(organization.getOrgname());
node.setParentid(organization.getParentid());
node.setManager(organization.getManager());
node.setDescription(organization.getDescription());
node.setAddress(organization.getAddress());
node.setContactPhone(organization.getContactPhone());
node.setContactPerson(organization.getContactPerson());
node.setIsvaild(organization.getIsvaild());
node.setChildren(buildOrganizationTree(allOrganizations, organization.getId()));
return node;
})
.collect(Collectors.toList());
}
/**
* 组织树节点
*/
@Data
public static class OrganizationTreeNode {
/**
* ID
*/
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 组织类型01-公司 02-部门
*/
private String orgtype;
/**
* 组织编号
*/
private String orgcode;
/**
* 组织名称
*/
private String orgname;
/**
* 上级ID
*/
private String parentid;
/**
* 组织负责人
*/
private String manager;
/**
* 组织详情
*/
private String description;
/**
* 联系地址
*/
private String address;
/**
* 联系电话
*/
private String contactPhone;
/**
* 联系人
*/
private String contactPerson;
/**
* 是否有效 1- 0-
*/
private String isvaild;
private List<OrganizationTreeNode> children = new ArrayList<>();
}
}

View File

@ -1,322 +0,0 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.Result;
import com.stdproject.entity.AppRole;
import com.stdproject.entity.AppRoleMenu;
import com.stdproject.entity.AppRoleUser;
import com.stdproject.service.IAppRoleMenuService;
import com.stdproject.service.IAppRoleService;
import com.stdproject.service.IAppRoleUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 应用-角色表 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "角色管理", description = "角色添加、角色修改、角色删除、角色查询,角色权限分配等功能")
@RestController
@RequestMapping("/api/role")
public class AppRoleController {
@Autowired
private IAppRoleService appRoleService;
@Autowired
private IAppRoleMenuService appRoleMenuService;
@Autowired
private IAppRoleUserService appRoleUserService;
@Operation(summary = "分页查询角色列表")
@PostMapping("/page/{appId}")
@OperationLog(type = "06", module = "角色管理", description = "分页查询角色列表")
public Result<IPage<AppRole>> page(@Parameter(description = "用户ID") @PathVariable String appId,
@RequestBody @Valid PageRequest pageRequest) {
Page<AppRole> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(appId),"app_id",appId);
// 关键字搜索
if (StringUtils.hasText(pageRequest.getKeyword())) {
queryWrapper.and(wrapper -> wrapper
.like("rolename", pageRequest.getKeyword())
.or().like("rolecode", pageRequest.getKeyword())
.or().like("description", pageRequest.getKeyword())
);
}
// 只查询有效的角色
queryWrapper.eq("isvaild", "1");
// 排序
if (StringUtils.hasText(pageRequest.getOrderBy())) {
if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
queryWrapper.orderByAsc(pageRequest.getOrderBy());
} else {
queryWrapper.orderByDesc(pageRequest.getOrderBy());
}
} else {
queryWrapper.orderByAsc("rolecode");
}
IPage<AppRole> result = appRoleService.page(page, queryWrapper);
return Result.success(result);
}
@Operation(summary = "查询所有有效角色列表")
@GetMapping("/list")
@OperationLog(type = "06", module = "角色管理", description = "查询所有有效角色列表")
public Result<List<AppRole>> list() {
QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("isvaild", "1");
queryWrapper.orderByAsc("rolecode");
List<AppRole> roles = appRoleService.list(queryWrapper);
return Result.success(roles);
}
@Operation(summary = "根据ID查询角色详情")
@GetMapping("/{id}")
@OperationLog(type = "06", module = "角色管理", description = "查询角色详情")
public Result<AppRole> getById(@Parameter(description = "角色ID") @PathVariable String id) {
AppRole role = appRoleService.getById(id);
return Result.success(role);
}
@Operation(summary = "新增角色")
@PostMapping
@OperationLog(type = "01", module = "角色管理", description = "新增角色")
public Result<String> save(@RequestBody @Valid AppRole appRole) {
// 检查角色名称是否已存在
QueryWrapper<AppRole> nameQuery = new QueryWrapper<>();
nameQuery.eq("rolename", appRole.getRolename());
nameQuery.eq("isvaild", "1");
AppRole existRoleName = appRoleService.getOne(nameQuery);
if (ObjectUtils.isNotEmpty(existRoleName)) {
return Result.error("角色名称已存在");
}
// 自动生成角色编号
String maxRoleCode = getMaxRoleCode();
String newRoleCode;
if (maxRoleCode == null) {
newRoleCode = "001";
} else {
int nextCode = Integer.parseInt(maxRoleCode) + 1;
newRoleCode = String.format("%03d", nextCode);
}
appRole.setRolecode(newRoleCode);
// 设置默认值
appRole.setIsvaild("1");
appRole.setLastmodifier("admin");
appRole.setLastmodifydate(LocalDateTime.now());
boolean success = appRoleService.save(appRole);
return success ? Result.success("新增成功") : Result.error("新增失败");
}
/**
* 获取最大的角色编号
*
* @return 最大角色编号
*/
private String getMaxRoleCode() {
LambdaQueryWrapper<AppRole> queryWrapper = new LambdaQueryWrapper<AppRole>()
.eq(AppRole::getIsvaild, "1")
.orderByDesc(AppRole::getRolecode)
.select(AppRole::getRolecode)
.last("LIMIT 1");
List<AppRole> list = appRoleService.list(queryWrapper);
return list.isEmpty() ? null : list.get(0).getRolecode();
}
@Operation(summary = "修改角色")
@PutMapping
@OperationLog(type = "02", module = "角色管理", description = "修改角色")
public Result<String> update(@RequestBody @Valid AppRole appRole) {
// 检查角色是否存在
AppRole existRole = appRoleService.getById(appRole.getId());
if (existRole == null) {
return Result.error("角色不存在");
}
// 如果修改了角色名称检查新名称是否已被其他角色使用
if (!existRole.getRolename().equals(appRole.getRolename())) {
QueryWrapper<AppRole> nameQuery = new QueryWrapper<>();
nameQuery.eq("rolename", appRole.getRolename());
nameQuery.eq("isvaild", "1");
nameQuery.ne("id", appRole.getId());
AppRole roleWithSameName = appRoleService.getOne(nameQuery);
if (roleWithSameName != null) {
return Result.error("角色名称已被其他角色使用");
}
}
appRole.setLastmodifier("admin");
appRole.setLastmodifydate(LocalDateTime.now());
boolean success = appRoleService.updateById(appRole);
return success ? Result.success("修改成功") : Result.error("修改失败");
}
@Operation(summary = "删除角色")
@DeleteMapping("/{id}")
@OperationLog(type = "03", module = "角色管理", description = "删除角色")
public Result<String> delete(@Parameter(description = "角色ID") @PathVariable String id) {
// 检查是否有用户关联此角色
QueryWrapper<AppRoleUser> userQuery = new QueryWrapper<>();
userQuery.eq("roleid", id);
long userCount = appRoleUserService.count(userQuery);
if (userCount > 0) {
return Result.error("存在用户关联此角色,无法删除");
}
// 软删除设置为无效
AppRole role = appRoleService.getById(id);
if (role != null) {
role.setIsvaild("0");
role.setLastmodifydate(LocalDateTime.now());
boolean success = appRoleService.updateById(role);
if (success) {
// 同时删除角色菜单关联
QueryWrapper<AppRoleMenu> menuQuery = new QueryWrapper<>();
menuQuery.eq("roleid", id);
appRoleMenuService.remove(menuQuery);
}
return success ? Result.success("删除成功") : Result.error("删除失败");
}
return Result.error("角色不存在");
}
@Operation(summary = "根据角色类型查询角色列表")
@GetMapping("/type/{type}")
@OperationLog(type = "06", module = "角色管理", description = "根据角色类型查询角色列表")
public Result<List<AppRole>> getByType(@Parameter(description = "角色类型1-应用管理员2-应用普通用户") @PathVariable String type) {
QueryWrapper<AppRole> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("type", type);
queryWrapper.eq("isvaild", "1");
queryWrapper.orderByAsc("rolecode");
List<AppRole> roles = appRoleService.list(queryWrapper);
return Result.success(roles);
}
@Operation(summary = "分配角色菜单权限")
@PostMapping("/assign-menus/{roleId}")
@OperationLog(type = "02", module = "角色管理", description = "分配角色菜单权限")
public Result<String> assignMenus(
@Parameter(description = "角色ID") @PathVariable String roleId,
@RequestBody List<String> menuIds) {
// 检查角色是否存在
AppRole role = appRoleService.getById(roleId);
if (role == null || !"1".equals(role.getIsvaild())) {
return Result.error("角色不存在或已禁用");
}
// 先删除原有的菜单权限
QueryWrapper<AppRoleMenu> deleteQuery = new QueryWrapper<>();
deleteQuery.eq("roleid", roleId);
appRoleMenuService.remove(deleteQuery);
// 添加新的菜单权限
if (menuIds != null && !menuIds.isEmpty()) {
List<AppRoleMenu> roleMenus = menuIds.stream().map(menuId -> {
AppRoleMenu roleMenu = new AppRoleMenu();
roleMenu.setRoleid(roleId);
roleMenu.setMenuid(menuId);
roleMenu.setAppId(role.getAppId());
return roleMenu;
}).collect(Collectors.toList());
boolean success = appRoleMenuService.saveBatch(roleMenus);
return success ? Result.success("权限分配成功") : Result.error("权限分配失败");
}
return Result.success("权限分配成功");
}
@Operation(summary = "获取角色的菜单权限")
@GetMapping("/menus/{roleId}")
@OperationLog(type = "06", module = "角色管理", description = "获取角色的菜单权限")
public Result<List<String>> getRoleMenus(@Parameter(description = "角色ID") @PathVariable String roleId) {
QueryWrapper<AppRoleMenu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("roleid", roleId);
List<AppRoleMenu> roleMenus = appRoleMenuService.list(queryWrapper);
List<String> menuIds = roleMenus.stream()
.map(AppRoleMenu::getMenuid)
.collect(Collectors.toList());
return Result.success(menuIds);
}
@Operation(summary = "分配用户角色")
@PostMapping("/assign-users/{roleId}")
@OperationLog(type = "02", module = "角色管理", description = "分配用户角色")
public Result<String> assignUsers(
@Parameter(description = "角色ID") @PathVariable String roleId,
@RequestBody List<String> userIds) {
// 检查角色是否存在
AppRole role = appRoleService.getById(roleId);
if (role == null || !"1".equals(role.getIsvaild())) {
return Result.error("角色不存在或已禁用");
}
// 先删除原有的用户角色关联
QueryWrapper<AppRoleUser> deleteQuery = new QueryWrapper<>();
deleteQuery.eq("roleid", roleId);
appRoleUserService.remove(deleteQuery);
// 添加新的用户角色关联
if (userIds != null && !userIds.isEmpty()) {
List<AppRoleUser> roleUsers = userIds.stream().map(userId -> {
AppRoleUser roleUser = new AppRoleUser();
roleUser.setRoleid(roleId);
roleUser.setUserid(userId);
roleUser.setAppId(role.getAppId());
return roleUser;
}).collect(Collectors.toList());
boolean success = appRoleUserService.saveBatch(roleUsers);
return success ? Result.success("用户分配成功") : Result.error("用户分配失败");
}
return Result.success("用户分配成功");
}
@Operation(summary = "获取角色的用户列表")
@GetMapping("/users/{roleId}")
@OperationLog(type = "06", module = "角色管理", description = "获取角色的用户列表")
public Result<List<String>> getRoleUsers(@Parameter(description = "角色ID") @PathVariable String roleId) {
QueryWrapper<AppRoleUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("roleid", roleId);
List<AppRoleUser> roleUsers = appRoleUserService.list(queryWrapper);
List<String> userIds = roleUsers.stream()
.map(AppRoleUser::getUserid)
.collect(Collectors.toList());
return Result.success(userIds);
}
}

View File

@ -1,300 +0,0 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.OperationLog;
import com.stdproject.common.PageRequest;
import com.stdproject.common.QueryWrapperBuilder;
import com.stdproject.common.Result;
import com.stdproject.entity.AppUser;
import com.stdproject.service.IAppUserService;
import com.stdproject.utils.PasswordUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 应用-用户表 前端控制器
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Tag(name = "用户管理", description = "用户信息维护、用户角色分配、用户登录、用户修改密码、用户修改个人信息等功能")
@RestController
@RequestMapping("/app-user")
public class AppUserController {
@Autowired
private IAppUserService appUserService;
@Operation(summary = "分页查询用户列表")
@PostMapping("/page/{orgId}/{appId}")
@OperationLog(type = "06", module = "用户管理", description = "分页查询用户列表")
public Result<IPage<AppUser>> page(@Parameter(description = "用户ID") @PathVariable String orgId,
@Parameter(description = "用户ID") @PathVariable String appId,
@RequestBody @Valid PageRequest pageRequest) {
Page<AppUser> page = new Page<>(pageRequest.getCurrent(), pageRequest.getSize());
QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq(StrUtil.isNotBlank(orgId),"orgid",orgId);
queryWrapper.eq(StrUtil.isNotBlank(appId),"app_id",appId);
// 关键字搜索
if (StringUtils.hasText(pageRequest.getKeyword())) {
queryWrapper.and(wrapper -> wrapper
.like("username", pageRequest.getKeyword())
.or().like("nickname", pageRequest.getKeyword())
.or().like("email", pageRequest.getKeyword())
.or().like("phone", pageRequest.getKeyword())
);
}
// 排序
if (StringUtils.hasText(pageRequest.getOrderBy())) {
if ("asc".equalsIgnoreCase(pageRequest.getOrderDirection())) {
queryWrapper.orderByAsc(pageRequest.getOrderBy());
} else {
queryWrapper.orderByDesc(pageRequest.getOrderBy());
}
} else {
queryWrapper.orderByDesc("lastmodifydate");
}
IPage<AppUser> result = appUserService.page(page, queryWrapper);
return Result.success(result);
}
@Operation(summary = "根据ID查询用户详情")
@GetMapping("/{id}")
@OperationLog(type = "06", module = "用户管理", description = "查询用户详情")
public Result<AppUser> getById(@Parameter(description = "用户ID") @PathVariable String id) {
AppUser user = appUserService.getById(id);
if (user != null) {
// 不返回密码信息
user.setPassword(null);
}
return Result.success(user);
}
@Operation(summary = "根据用户名查询用户")
@GetMapping("/username/{username}")
@OperationLog(type = "06", module = "用户管理", description = "根据用户名查询用户")
public Result<AppUser> getByUsername(@Parameter(description = "用户名") @PathVariable String username) {
AppUser user = appUserService.findByUsername(username);
if (user != null) {
// 不返回密码信息
user.setPassword(null);
}
return Result.success(user);
}
@Operation(summary = "新增用户")
@PostMapping
@OperationLog(type = "01", module = "用户管理", description = "新增用户")
public Result<String> save(@RequestBody @Valid AppUser appUser) {
// 检查用户名是否已存在
AppUser existUser = appUserService.findByUsername(appUser.getUsername());
if (existUser != null) {
return Result.error("用户名已存在");
}
// 设置默认值
if (!StringUtils.hasText(appUser.getStatus())) {
appUser.setStatus("1"); // 默认有效
}
if (appUser.getPwdvalidperiod() == null) {
appUser.setPwdvalidperiod(90); // 默认90天
}
if (appUser.getFailednum() == null) {
appUser.setFailednum(0);
}
// 密码加密
if (StringUtils.hasText(appUser.getPassword())) {
appUser.setPassword(PasswordUtils.encodePassword(appUser.getPassword()));
}
appUser.setLastmodifydate(LocalDateTime.now());
boolean success = appUserService.save(appUser);
return success ? Result.success("新增成功") : Result.error("新增失败");
}
@Operation(summary = "修改用户")
@PutMapping
@OperationLog(type = "02", module = "用户管理", description = "修改用户")
public Result<String> update(@RequestBody @Valid AppUser appUser) {
// 检查用户是否存在
AppUser existUser = appUserService.getById(appUser.getId());
if (existUser == null) {
return Result.error("用户不存在");
}
// 如果修改了用户名检查新用户名是否已被其他用户使用
if (!existUser.getUsername().equals(appUser.getUsername())) {
AppUser userWithSameName = appUserService.findByUsername(appUser.getUsername());
if (userWithSameName != null && !userWithSameName.getId().equals(appUser.getId())) {
return Result.error("用户名已被其他用户使用");
}
}
// 如果传入了新密码进行加密
if (StringUtils.hasText(appUser.getPassword())) {
appUser.setPassword(PasswordUtils.encodePassword(appUser.getPassword()));
appUser.setPwdresettime(LocalDateTime.now());
} else {
// 如果没有传入密码保持原密码不变
appUser.setPassword(existUser.getPassword());
}
appUser.setLastmodifydate(LocalDateTime.now());
boolean success = appUserService.updateById(appUser);
return success ? Result.success("修改成功") : Result.error("修改失败");
}
@Operation(summary = "删除用户")
@DeleteMapping("/{id}")
@OperationLog(type = "03", module = "用户管理", description = "删除用户")
public Result<String> delete(@Parameter(description = "用户ID") @PathVariable String id) {
boolean success = appUserService.removeById(id);
return success ? Result.success("删除成功") : Result.error("删除失败");
}
@Operation(summary = "批量删除用户")
@DeleteMapping("/batch")
@OperationLog(type = "03", module = "用户管理", description = "批量删除用户")
public Result<String> deleteBatch(@RequestBody List<String> ids) {
boolean success = appUserService.removeByIds(ids);
return success ? Result.success("批量删除成功") : Result.error("批量删除失败");
}
@Operation(summary = "修改用户密码")
@PutMapping("/password/{id}")
@OperationLog(type = "02", module = "用户管理", description = "修改用户密码")
public Result<String> updatePassword(
@Parameter(description = "用户ID") @PathVariable String id,
@RequestBody PasswordUpdateRequest request) {
AppUser user = appUserService.getById(id);
if (user == null) {
return Result.error("用户不存在");
}
// 验证旧密码
if (!PasswordUtils.matches(request.getOldPassword(), user.getPassword())) {
return Result.error("原密码错误");
}
// 更新新密码
user.setPassword(PasswordUtils.encodePassword(request.getNewPassword()));
user.setPwdresettime(LocalDateTime.now());
user.setLastmodifydate(LocalDateTime.now());
boolean success = appUserService.updateById(user);
return success ? Result.success("密码修改成功") : Result.error("密码修改失败");
}
@Operation(summary = "重置用户密码")
@PutMapping("/reset-password/{id}")
@OperationLog(type = "02", module = "用户管理", description = "重置用户密码")
public Result<String> resetPassword(
@Parameter(description = "用户ID") @PathVariable String id,
@RequestBody PasswordResetRequest request) {
AppUser user = appUserService.getById(id);
if (user == null) {
return Result.error("用户不存在");
}
// 重置密码
user.setPassword(PasswordUtils.encodePassword(request.getNewPassword()));
user.setPwdresettime(LocalDateTime.now());
user.setLastmodifydate(LocalDateTime.now());
boolean success = appUserService.updateById(user);
return success ? Result.success("密码重置成功") : Result.error("密码重置失败");
}
@Operation(summary = "启用/禁用用户")
@PutMapping("/status/{id}")
@OperationLog(type = "02", module = "用户管理", description = "启用/禁用用户")
public Result<String> updateStatus(
@Parameter(description = "用户ID") @PathVariable String id,
@RequestParam String status) {
AppUser user = appUserService.getById(id);
if (user == null) {
return Result.error("用户不存在");
}
user.setStatus(status);
user.setLastmodifydate(LocalDateTime.now());
boolean success = appUserService.updateById(user);
String message = "1".equals(status) ? "启用成功" : "禁用成功";
return success ? Result.success(message) : Result.error("操作失败");
}
@Operation(summary = "根据组织ID查询用户列表")
@GetMapping("/org/{orgId}")
@OperationLog(type = "06", module = "用户管理", description = "根据组织ID查询用户列表")
public Result<List<AppUser>> getByOrgId(@Parameter(description = "组织ID") @PathVariable String orgId) {
QueryWrapper<AppUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("orgid", orgId);
queryWrapper.orderByDesc("lastmodifydate");
List<AppUser> users = appUserService.list(queryWrapper);
// 不返回密码信息
users.forEach(user -> user.setPassword(null));
return Result.success(users);
}
/**
* 密码修改请求类
*/
public static class PasswordUpdateRequest {
private String oldPassword;
private String newPassword;
// getters and setters
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
/**
* 密码重置请求类
*/
public static class PasswordResetRequest {
private String newPassword;
// getters and setters
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
}

View File

@ -1,322 +0,0 @@
package com.stdproject.controller;
import com.stdproject.common.Constants;
import com.stdproject.common.OperationLog;
import com.stdproject.common.Result;
import com.stdproject.config.WebConfig;
import com.stdproject.entity.AppUser;
import com.stdproject.service.IAppUserService;
import com.stdproject.utils.CaptchaUtils;
import com.stdproject.utils.JwtUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* 认证控制器
*
* @author StdProject
*/
@Tag(name = "认证管理", description = "用户登录、登出、验证码等认证相关接口")
@RestController
@RequestMapping("/auth")
@Slf4j
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@Autowired
private CaptchaUtils captchaUtils;
@Autowired
private IAppUserService appUserService;
@Autowired
private WebConfig webConfig;
/**
* 登录请求类
*/
public static class LoginRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
@NotBlank(message = "验证码不能为空")
private String captcha;
@NotBlank(message = "验证码Key不能为空")
private String captchaKey;
// Getters and Setters
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCaptcha() {
return captcha;
}
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
public String getCaptchaKey() {
return captchaKey;
}
public void setCaptchaKey(String captchaKey) {
this.captchaKey = captchaKey;
}
}
/**
* 修改密码请求类
*/
public static class ChangePasswordRequest {
@NotBlank(message = "原密码不能为空")
private String oldPassword;
@NotBlank(message = "新密码不能为空")
private String newPassword;
// Getters and Setters
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
public String getNewPassword() {
return newPassword;
}
public void setNewPassword(String newPassword) {
this.newPassword = newPassword;
}
}
/**
* 生成验证码
*/
@Operation(summary = "生成验证码", description = "生成图形验证码")
@GetMapping("/captcha")
public Result<Map<String, String>> generateCaptcha() {
try {
// 生成验证码
CaptchaUtils.CaptchaResult captchaResult = captchaUtils.generateCaptcha();
// 生成验证码Key
String captchaKey = UUID.randomUUID().toString();
// 注意验证码应当存储在会话中或其他存储中此处省略存储步骤
// 在实际应用中可以使用Session或其他方式存储验证码
Map<String, String> result = new HashMap<>();
result.put("captchaKey", captchaKey);
result.put("captchaImage", captchaResult.getImageBase64());
result.put("code", captchaResult.getCode()); // 临时方案直接返回验证码生产环境不建议
return Result.success(result);
} catch (Exception e) {
log.error("生成验证码失败: {}", e.getMessage(), e);
return Result.error("生成验证码失败");
}
}
/**
* 用户登录
*/
@Operation(summary = "用户登录", description = "用户登录认证")
@PostMapping("/login")
@OperationLog(type = Constants.OPT_TYPE_LOGIN, module = "认证管理", description = "用户登录")
public Result<Map<String, Object>> login(@Valid @RequestBody LoginRequest loginRequest,
HttpServletRequest request) {
try {
// 注意在实际应用中应该从会话或其他存储中获取验证码进行验证
// 此处简化处理假设验证码已通过实际应用中需要实现验证逻辑
// 如果使用了临时方案可以从前端传回验证码进行比对
// 进行身份认证
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
AppUser user = appUserService.findByUsername(loginRequest.getUsername());
// 设置认证信息到安全上下文
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成JWT Token
String token = jwtUtils.generateToken(user.getUsername(), user.getId());
Map<String, Object> result = new HashMap<>();
result.put("token", token);
result.put("userInfo", user);
return Result.success(result);
} catch (Exception e) {
log.error("用户登录失败: {}", e.getMessage(), e);
return Result.error("登录失败: " + e.getMessage());
}
}
/**
* 用户登出
*/
@Operation(summary = "用户登出", description = "用户登出")
@PostMapping("/logout")
@OperationLog(type = Constants.OPT_TYPE_OTHER, module = "认证管理", description = "用户登出")
public Result<Void> logout(HttpServletRequest request) {
try {
// 获取Token
String token = request.getHeader(Constants.JWT_HEADER);
if (token != null && token.startsWith(Constants.JWT_PREFIX)) {
token = token.substring(Constants.JWT_PREFIX.length());
// 实现token失效
Date expirationDateFromToken = jwtUtils.getExpirationDateFromToken(token);
// 获取当前时间的时间戳毫秒
long nowMillis = System.currentTimeMillis();
// 获取 Token 过期时间的时间戳毫秒
long expirationMillis = expirationDateFromToken.getTime();
// 计算剩余有效时间毫秒
long remainingMillis = expirationMillis - nowMillis;
if (remainingMillis > 0) {
webConfig.timedCache().put(token, remainingMillis);
}
}
// 清除安全上下文
SecurityContextHolder.clearContext();
return Result.success();
} catch (Exception e) {
log.error("用户登出失败: {}", e.getMessage(), e);
return Result.error("登出失败");
}
}
/**
* 获取当前用户信息
*/
@Operation(summary = "获取当前用户信息", description = "获取当前登录用户的详细信息")
@GetMapping("/userinfo")
public Result<AppUser> getCurrentUserInfo(HttpServletRequest request) {
try {
String token = request.getHeader(Constants.JWT_HEADER);
if (token != null && token.startsWith(Constants.JWT_PREFIX)) {
token = token.substring(Constants.JWT_PREFIX.length());
String username = jwtUtils.getUsernameFromToken(token);
AppUser userInfo = appUserService.findByUsername(username);
return Result.success(userInfo);
}
return Result.unauthorized();
} catch (Exception e) {
log.error("获取用户信息失败: {}", e.getMessage(), e);
return Result.error("获取用户信息失败");
}
}
/**
* 修改密码
*/
@Operation(summary = "修改密码", description = "修改当前用户密码")
@PostMapping("/changePassword")
@OperationLog(type = Constants.OPT_TYPE_UPDATE, module = "认证管理", description = "修改密码")
public Result<Void> changePassword(@Valid @RequestBody ChangePasswordRequest request,
HttpServletRequest httpRequest) {
try {
String token = httpRequest.getHeader(Constants.JWT_HEADER);
if (token != null && token.startsWith(Constants.JWT_PREFIX)) {
token = token.substring(Constants.JWT_PREFIX.length());
String username = jwtUtils.getUsernameFromToken(token);
boolean success = appUserService.changePassword(username, request.getOldPassword(),
request.getNewPassword());
if (success) {
return Result.success();
} else {
return Result.error("原密码错误");
}
}
return Result.unauthorized();
} catch (Exception e) {
log.error("修改密码失败: {}", e.getMessage(), e);
return Result.error("修改密码失败");
}
}
@PostMapping("/refreshToken")
@Operation(summary = "刷新令牌", description = "刷新当前用户的令牌")
public Result<String> refreshToken(@RequestBody Map<String, String> params) {
String refreshToken = params.get("refreshToken");
if (refreshToken == null || refreshToken.trim().isEmpty()) {
return Result.error("刷新令牌不能为空");
}
try {
String username = jwtUtils.getUsernameFromToken(refreshToken);
if (username != null && jwtUtils.validateToken(refreshToken, username)) {
AppUser user = appUserService.findByUsername(username);
String newAccessToken = jwtUtils.generateRefreshToken(user.getUsername(), user.getId());
return Result.success(newAccessToken);
} else {
return Result.error("刷新令牌已失效");
}
} catch (Exception e) {
log.error("刷新 Token 失败: {}", e.getMessage());
return Result.error("刷新 Token 失败");
}
}
@GetMapping("/getExpirationDateFromToken")
public Result<Date> getExpirationDateFromToken(String token) {
Date expirationDateFromToken = jwtUtils.getExpirationDateFromToken(token);
return Result.success(expirationDateFromToken);
}
}

View File

@ -0,0 +1,183 @@
package com.stdproject.controller;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.stdproject.config.ResponseResult;
import com.stdproject.entity.Menu;
import com.stdproject.service.IMenuService;
import io.gisbi.utils.AuthUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* <p>
* 菜单及按钮 前端控制器
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@RestController
@RequestMapping("/menuInterface")
public class MenuController {
@Resource
private IMenuService menuService;
/***********************************
* 用途说明新增菜单及按钮
* 参数说明
* sysMenu 菜单表对象
* 返回值说明: 是否添加成功提示
***********************************/
@PostMapping("/addMenu")
@ResponseBody
public ResponseResult addMenu(@RequestBody Menu menu) {
boolean isOk = menuService.addMenu(menu);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明修改菜单及按钮根据ID
* 参数说明
* sysMenu 菜单或按钮表对象
* 返回值说明: 是否修改成功提示
***********************************/
@PostMapping("/updateMenuById")
@ResponseBody
public ResponseResult updateById(@RequestBody Menu menu) {
if (StringUtils.isEmpty(menu.getId())) {
return ResponseResult.error("没有菜单ID");
}
//填写 当前用户名称
menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 当前日期
menu.setLastmodifydate(LocalDateTime.now());
boolean isOk = menuService.updateById(menu);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明获取菜单结构树含按钮
* 参数说明
* appId 应用ID 关联应用系统
* name 名称
* isdisplay 是否显示
* 返回值说明: 菜单结构树集合
***********************************/
@PostMapping("/getMenuTree")
@ResponseBody
public List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay) {
return menuService.getMenuTree(appId, name, isdisplay);
}
/***********************************
* 用途说明根据id查询菜单
* 参数说明
* id 菜单或按钮表id
* 返回值说明: 菜单表对象
***********************************/
@PostMapping("/getMenuById")
@ResponseBody
public ResponseResult getMenuById(String id) {
Menu menu = menuService.getById(id);
return ResponseResult.successData(menu);
}
/***********************************
* 用途说明根据id删除菜单或按钮
* 参数说明
* id 删除列的id
* 返回值说明: 是否删除成功
***********************************/
@PostMapping("/deleteMenuById")
@ResponseBody
public ResponseResult deleteMenuById(@RequestParam String id) {
boolean ok = menuService.deleteMenuById(id);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明更新菜单及按钮是否有效
* 参数说明
* id 菜单及按钮表id
* isdisplay 是否有效字段
* 返回值说明: 是否更新成功
***********************************/
@PostMapping("/setIsDisplay")
@ResponseBody
public ResponseResult setIsDisplay(String id, String isdisplay) {
UpdateWrapper<Menu> updateWrapper = new UpdateWrapper<>();
//根据id 修改是否显示 最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("isdisplay", isdisplay)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
boolean ok = menuService.update(updateWrapper);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明更新关联模块ID
* 参数说明
* id 菜单及按钮表id
* moduleId 关联模块ID
* 返回值说明: 是否更新成功
***********************************/
@PostMapping("/setModuleId")
@ResponseBody
public ResponseResult setModuleId(String id, String moduleId) {
UpdateWrapper<Menu> updateWrapper = new UpdateWrapper<>();
//根据id 修改关联模块ID 最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("module_id", moduleId)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", new Timestamp(System.currentTimeMillis()));
boolean ok = menuService.update(updateWrapper);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明获取分配权限
* 参数说明
* appId 系统id
* roleId 角色ID
* 返回值说明: 菜单结构树集合
***********************************/
@PostMapping("/permissionAssignment")
@ResponseBody
public List<Map<String, Object>> permissionAssignment(String appId, String roleId) {
return menuService.permissionAssignment(appId,roleId);
}
}

View File

@ -0,0 +1,196 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.stdproject.config.ResponseResult;
import com.stdproject.entity.Organization;
import com.stdproject.service.IOrganizationService;
import io.gisbi.utils.AuthUtils;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 组织机构 前端控制器
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@RestController
@RequestMapping("/organization")
public class OrganizationController {
@Resource
private IOrganizationService organizationService;
/***********************************
* 用途说明新增系统组织框架
* 参数说明
* organization 系统组织框架对象
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/addOrganization")
@ResponseBody
public ResponseResult addOrganization(@RequestBody Organization organization) {
if (organization == null) {
return ResponseResult.error("组织信息不能为空");
}
//新增 系统组织R
boolean isOk = organizationService.addOrganization(organization);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error("新增失败,未知原因");
}
}
/***********************************
* 用途说明修改系统组织框架
* 参数说明
* organization 系统组织框架对象
* 返回值说明: 是否修改成功
***********************************/
@PostMapping("/updateOrganizationById")
@ResponseBody
public ResponseResult updateOrganizationById(@RequestBody Organization organization) {
if (StrUtil.isEmpty(organization.getId())) {
return ResponseResult.error("组织信息id不能为空");
}
if (organization == null) {
return ResponseResult.error("组织信息不能为空");
}
//填写 最近修改者
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 最近修改时间
organization.setLastmodifydate(LocalDateTime.now());
//根据id 修改系统组织
boolean isOk = organizationService.updateById(organization);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明获取企业列表
* 参数说明
* id 企业id
* orgName 部门名称
* orgtype 组织类型01-公司 02-部门
* parentid 上级ID
* 返回值说明: 企业列表集合
***********************************/
@PostMapping("/getOrganizations")
@ResponseBody
public List<Map<String, Object>> getOrganizations(String appId, String orgtype, String parentid, String orgName) {
return organizationService.getOrganizations(appId,orgtype, parentid, orgName);
}
/***********************************
* 用途说明查询全部系统组织框架
* 参数说明
* appId 应用ID
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/listOrganization")
@ResponseBody
public ResponseResult listOrganization(String appId) {
if (appId == null) {
return ResponseResult.error("应用ID不能为空");
}
LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Organization::getAppId,appId);
queryWrapper.eq(Organization::getIsvaild,"1");
List<Organization> list = organizationService.list(queryWrapper);
return ResponseResult.successData(list);
}
/***********************************
* 用途说明根据ID查询信息
* 参数说明
* id 企业id
* orgName 部门名称
* 返回值说明: 系统部门框架对象
***********************************/
@PostMapping("/getOrganizationById")
@ResponseBody
public ResponseResult getOrganizationById(String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("查询失败!");
}
Organization Organization = organizationService.getOrganizationById(id);
return ResponseResult.successData(Organization);
}
/***********************************
* 用途说明设置组织是否有效
* 参数说明
* sysOrganization 系统组织框架对象
* 返回值说明: 是否修改成功
***********************************/
@PostMapping("/setIsValid")
@ResponseBody
public ResponseResult setIsValid(@RequestParam String id, @RequestParam String isvaild) {
// 参数校验
if (id == null || id.isEmpty() || isvaild == null || isvaild.isEmpty()) {
return ResponseResult.error("参数不能为空");
}
// 校验 isvalid 的合法性示例
if (!"0".equals(isvaild) && !"1".equals(isvaild)) {
return ResponseResult.error("isvaild 参数不合法");
}
UpdateWrapper<Organization> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", id)
.set("isvaild", isvaild)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate", LocalDateTime.now());
boolean isOk = organizationService.update(updateWrapper);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明根据id删除系统组织框架
* 参数说明
* id 系统组织框架id
* 返回值说明: 是否删除成功
***********************************/
@DeleteMapping("/deleteById")
@ResponseBody
public ResponseResult deleteById(@RequestParam String id) {
String[] orgIds = id.split(",");
for (String orgId : orgIds) {
LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
List<Organization> list = organizationService.list(queryWrapper.eq(Organization::getParentid, orgId));
List<String> ids = list.stream().map(Organization::getId).collect(Collectors.toList());
//删除当前id及其子节点
boolean isOk = organizationService.removeById(orgId);
if (!isOk) {
continue;
}
//删除节点
for (String oid : ids) {
organizationService.removeById(oid);
}
}
return ResponseResult.success();
}
}

View File

@ -0,0 +1,232 @@
package com.stdproject.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.stdproject.config.ResponseResult;
import com.stdproject.entity.Role;
import com.stdproject.service.IRoleService;
import com.stdproject.service.IUserService;
import io.gisbi.utils.AuthUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 角色 前端控制器
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@RestController
@RequestMapping("/role")
public class RoleController {
@Resource
private IRoleService roleService;
@Resource
private IUserService userService;
/***********************************
* 用途说明新增角色
* 参数说明
* sysRole 新增角色信息
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/addRole")
@ResponseBody
public ResponseResult addRole(@RequestBody Role role) {
boolean isOk = roleService.addRole(role);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明更新角色信息
* 参数说明
* role 角色对象
* 返回值说明: 是否修改成功
***********************************/
@PostMapping("/updateRole")
@ResponseBody
public ResponseResult updateRole(@RequestBody Role role) {
if (StrUtil.isBlank(role.getId())) {
return ResponseResult.error("需要提交角色ID");
}
//更新最近修改人
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//更新最近修改时间
role.setLastmodifydate(LocalDateTime.now());
//根据id更新角色信息
boolean ok = roleService.updateById(role);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明查询所有角色
* 参数说明
* rolename 角色名称
* 返回值说明: 查询都有角色
***********************************/
@PostMapping("/listRole")
@ResponseBody
public List<Role> listRole(String appId, String rolename) {
return roleService.listRole(appId,rolename);
}
/***********************************
* 用途说明根据Id获取单个角色
* 参数说明
* id 角色表id
* 返回值说明: 根据id查询到角色详情
***********************************/
@PostMapping("/getRoleById")
@ResponseBody
public ResponseResult getRoleById(String id) {
Role role = roleService.getById(id);
return ResponseResult.successData(role);
}
/***********************************
* 用途说明根据id删除角色
* 参数说明
* id 角色id
* 返回值说明: 是否删除成功
***********************************/
@PostMapping("/deleteRoleById")
@ResponseBody
public ResponseResult deleteRoleById(@RequestParam String id) {
boolean result = roleService.deleteById(id);
if (!result) {
return ResponseResult.error("删除角色失败,可能角色不存在");
}
return ResponseResult.success();
}
/***********************************
* 用途说明根据ID批量删除角色
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
@PostMapping("/deleteRoleByIds")
@ResponseBody
public ResponseResult deleteRoleByIds(String ids) {
if (StringUtils.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
boolean ok = roleService.deleteRoleByIds(ids);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明设置角色是否有效
* 参数说明
* id 角色id
*isvaild 是否有效1 0
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/setIsvaild")
@ResponseBody
public ResponseResult setIsvaild(String id, String isvaild) {
UpdateWrapper<Role> updateWrapper = new UpdateWrapper<>();
//根据id 更新业务范围最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("isvaild", isvaild)
.set("lastmodifier", AuthUtils.getUser().getUserId().toString())
.set("lastmodifydate",LocalDateTime.now());
boolean ok = roleService.update(updateWrapper);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明角色菜单权限
* 参数说明
* id 角色id
* menuIds 权限id字符串
* 返回值说明: 是否分配成功
***********************************/
@PostMapping("/setMenuByRoleId")
@ResponseBody
public ResponseResult setMenuByRoleId(String id, String menuIds) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
if (StrUtil.isBlank(menuIds)) {
return ResponseResult.success();
}
boolean ok = roleService.setMenuByRoleId(id, menuIds);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明角色添加用户
* 参数说明
* roleid 角色id
* userids 用户id组
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/setRoleUsers")
@ResponseBody
public ResponseResult setRoleUsers(String roleid, String userids) {
boolean isOk = true;
String[] temp = userids.split(",");
for (String userid : temp) {
isOk = isOk && userService.addUserRole(roleid, userid);
}
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明删除角色用户
* 参数说明
* roleid 角色id
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/deleteRoleUser")
@ResponseBody
public ResponseResult deleteRoleUsers(@RequestParam String roleid,
@RequestParam String userids) {
//根据角色id用户id删除
boolean ok = roleService.deleteRoleUsers(roleid, userids);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
}

View File

@ -0,0 +1,180 @@
package com.stdproject.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.config.ResponseResult;
import com.stdproject.entity.User;
import com.stdproject.service.IUserService;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* <p>
* 用户 前端控制器
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private IUserService userService;
/***********************************
* 用途说明新增系统用户
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/addUser")
@ResponseBody
public ResponseResult addUser(@RequestBody User user, String roleids) {
Map reslut = userService.addUser(user, roleids);
return ResponseResult.successData(reslut);
}
/***********************************
* 用途说明修改用户信息
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
@PostMapping("/updateUser")
@ResponseBody
public ResponseResult updateUser(@RequestBody User user, String roleids) {
if (StringUtils.isEmpty(user.getId())) {
return ResponseResult.error("没有用户ID");
}
Map reslut = userService.updateById(user, roleids);
return ResponseResult.successData(reslut);
}
/***********************************
* 用途说明查询用户信息
* 参数说明
* orgid 所属组织ID
* nickname 用户昵称
* page 分页条件
* 返回值说明: 用户信息集合
***********************************/
@GetMapping("/queryUsers")
@ResponseBody
public ResponseResult queryUsers(String orgid,String appId, String nickname, Page<User> page) {
Page<Map<String, Object>> mapPage = userService.queryUsers(orgid, appId, nickname, page);
return ResponseResult.successData(mapPage);
}
/***********************************
* 用途说明根据ID删除用户
* 参数说明
*id 用户id
* 返回值说明: 判断是否删除成功
************************************/
@PostMapping("/deleteUserById")
@ResponseBody
public ResponseResult deleteUserById(String id) {
if (id == null || id.trim().isEmpty()) {
return ResponseResult.error("用户ID不能为空");
}
boolean result = userService.deleteUserById(id);
if (!result) {
return ResponseResult.error("删除用户失败,可能用户不存在");
}
return ResponseResult.success();
}
/***********************************
* 用途说明根据ID批量删除用户
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
@PostMapping("/deleteUserByIds")
@ResponseBody
public ResponseResult deleteUserByIds(String ids) {
if (StringUtils.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
boolean ok = userService.deleteUserByIds(ids);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明
*id 用户id
* status 设置状态
* 返回值说明: 判断是否设置成功
************************************/
@PostMapping("/setStatus")
@ResponseBody
public ResponseResult setStatus(@RequestParam String id,@RequestParam String status) {
if (StringUtils.isEmpty(id)) {
return ResponseResult.error("用户ID为空");
}
if (StringUtils.isEmpty(status)) {
return ResponseResult.error("设置状态为空");
}
boolean ok = userService.setStatus(id, status);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明重置用户密码(管理员)
* 参数说明
*id 重置密码的 用户id
* 返回值说明: 判断是否重置成功
************************************/
@PostMapping("/resetPassword")
@ResponseBody
public ResponseResult resetPassword(String id) throws Exception {
if (StrUtil.isBlank(id)) {
ResponseResult.error("参数为空");
}
boolean ok = userService.resetPassword(id);
if (ok) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
@PostMapping("/login")
@ResponseBody
public ResponseResult login(String appid,String username, String password) {
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
return ResponseResult.error("用户名称或者密码不能为空!");
}
// 根据用户名查询用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
User user = userService.getOne(queryWrapper.eq("app_id",appid).eq("username", username));
if (ObjUtil.isEmpty( user)) {
return ResponseResult.error(String.format("%s您输入的用户账号不存在", username));
}
if(password.equals(user.getPassword())){
return ResponseResult.successData(user);
}else{
return ResponseResult.error("您输入的密码错误!");
}
}
}

View File

@ -1,44 +0,0 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 系统角色-数据权限对照
*
* @author StdProject
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("app_role_menu")
public class AppRoleMenu implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 角色id
*/
private String roleid;
/**
* 菜单id
*/
private String menuid;
}

View File

@ -1,44 +0,0 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
* 系统角色-用户对照
*
* @author StdProject
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("app_role_users")
public class AppRoleUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 角色id
*/
private String roleid;
/**
* 用户id
*/
private String userid;
}

View File

@ -1,97 +1,73 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 应用系统_菜单
*
* @author StdProject
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Getter
@Setter
@TableName("app_menu")
public class AppMenu implements Serializable {
public class Menu {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 菜单类型 01-菜单
* 菜单类型 01-目录 02-菜单
*/
private String type;
/**
* 菜单编号
*/
private String code;
/**
* 同级序号
*/
private Integer orderno;
/**
* 菜单名称
*/
private String name;
/**
* 菜单图标 base64存储
*/
private String icon;
/**
* 是否外链 0-非外部 1-是外链
*/
private String islink;
/**
* 菜单URL 内部资源页面URL访问地址
*/
private String url;
/**
* 模块ID 菜单关联的模块ID
*/
private String moduleId;
/**
* 父级菜单ID 顶级为0
*/
private String parentid;
/**
* 是否显示 0-不显示 1-显示
*/
private String isdisplay;
/**
* 最近修改者
*/
private String lastmodifier;
/**
* 最近修改日期
*/
private LocalDateTime lastmodifydate;
/**
* 备用1
*/
@ -106,5 +82,4 @@ public class AppMenu implements Serializable {
* 备用3
*/
private String custom3;
}

View File

@ -1,97 +1,82 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 组织机构
* </p>
*
* @author lilin
* @since 2025-05-08
*/
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 应用系统_用户组织
*
* @author StdProject
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Getter
@Setter
@TableName("app_organization")
public class AppOrganization implements Serializable {
public class Organization {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 组织类型01-公司 02-部门
*/
private String orgtype;
/**
* 组织编号
*/
private String orgcode;
/**
* 组织名称
*/
private String orgname;
/**
* 上级ID
*/
private String parentid;
/**
* 组织负责人
*/
private String manager;
/**
* 组织详情
*/
private String description;
/**
* 联系地址
*/
private String address;
/**
* 联系电话
*/
private String contactPhone;
/**
* 联系人
*/
private String contactPerson;
/**
* 是否有效 1- 0-
*/
private String isvaild;
/**
* 最近修改者
*/
private String lastmodifier;
/**
* 最近修改日期
*/
private LocalDateTime lastmodifydate;
/**
* 备用1
*/
@ -107,4 +92,5 @@ public class AppOrganization implements Serializable {
*/
private String custom3;
}

View File

@ -1,72 +1,61 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 应用系统_系统角色
* <p>
* 角色
* </p>
*
* @author StdProject
* @author lilin
* @since 2025-05-08
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Getter
@Setter
@TableName("app_role")
public class AppRole implements Serializable {
public class Role {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 角色编号 系统生成三位编号
*/
private String rolecode;
/**
* 角色名称
*/
private String rolename;
/**
* 角色类别 1-应用管理员 2-应用普通用户
*/
private String type;
/**
* 角色描述
*/
private String description;
/**
* 是否有效 1- 0-
*/
private String isvaild;
/**
* 最近修改者
*/
private String lastmodifier;
/**
* 最近修改日期
*/
private LocalDateTime lastmodifydate;
/**
* 备用1
*/

View File

@ -1,117 +1,98 @@
package com.stdproject.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 应用系统_系统用户
* <p>
* 用户
* </p>
*
* @author StdProject
* @author lilin
* @since 2025-05-08
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Getter
@Setter
@TableName("app_user")
public class AppUser implements Serializable {
public class User {
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 应用ID 关联应用系统
*/
private String appId;
/**
* 所属组织
*/
private String orgid;
/**
* 用户类型 0-管理员 1-普通用户
*/
private String usertype;
/**
* 用户名称 用户名称账号
*/
private String username;
/**
* 用户昵称(中文)
*/
private String nickname;
/**
* 登录密码
*/
private String password;
/**
* 邮箱
*/
private String email;
/**
* 手机号
*/
private String phone;
/**
* 用户头像 base64存储用户头像
* 头像预留
*/
private String avatar;
/**
* 状态 1-有效 0-停用
* 账号状态1-正常 0-停用
*/
private String status;
/**
* 密码有限期 密码有限期
*/
private Integer pwdvalidperiod;
/**
* 登录失败次数 允许的登录失败次数
*/
private Integer failednum;
/**
* 用户指定登录IP 如果设置了IP则只允许IP用户登录
*/
private String loginip;
/**
* 登录失败锁定时间
*/
private LocalDateTime failedlocktime;
/**
* 密码修改时间
*/
private LocalDateTime pwdresettime;
/**
* 最近修改者
*/
private String lastmodifier;
/**
* 最近修改日期
*/
private LocalDateTime lastmodifydate;
/**
* 备用1
*/
@ -126,5 +107,4 @@ public class AppUser implements Serializable {
* 备用3
*/
private String custom3;
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppMenu;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 应用系统_菜单 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppMenuMapper extends BaseMapper<AppMenu> {
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppOrganization;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 应用系统_用户组织 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppOrganizationMapper extends BaseMapper<AppOrganization> {
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppRole;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 应用系统_系统角色 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppRoleMapper extends BaseMapper<AppRole> {
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppRoleMenu;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 系统角色-数据权限对照 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppRoleMenuMapper extends BaseMapper<AppRoleMenu> {
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppRoleUser;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 系统角色-用户对照 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppRoleUserMapper extends BaseMapper<AppRoleUser> {
}

View File

@ -1,18 +0,0 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.AppUser;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 应用系统_系统用户 Mapper 接口
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Mapper
public interface AppUserMapper extends BaseMapper<AppUser> {
}

View File

@ -0,0 +1,18 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.Menu;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface MenuMapper extends BaseMapper<Menu> {
@Select("select m.id FROM app_role_menu rm INNER JOIN app_menu m on rm.menuid = m.id where m.isdisplay = 1 AND rm.app_id = #{appid} AND rm.roleid = #{roleid} ORDER BY m.orderno ASC")
List<String> selectMenuByRoleId( @Param("appid")String appId, @Param("roleid") String roleId);
}

View File

@ -0,0 +1,10 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.Organization;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrganizationMapper extends BaseMapper<Organization> {
}

View File

@ -0,0 +1,82 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.stdproject.entity.Role;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface RoleMapper extends BaseMapper<Role> {
/**********************************
* 用途说明: 根据用户id获取角色信息
* 参数说明 id 角色id
* 返回值说明: void
***********************************/
@Select("SELECT r.id,r.rolename,r.rolecode FROM app_role_users ru INNER JOIN app_role r ON ru.roleid = r.id WHERE ru.userid = #{id}")
List<Role> getRoleByUserId( @Param("id") String id);
/**********************************
* 用途说明: 根据用户id获取角色id
* 参数说明 userid 用户id
* 返回值说明: void
***********************************/
@Select("SELECT roleid FROM app_role_users WHERE userid = #{userid} AND app_id = #{appId}")
List<String> getRoleUsers(@Param("userid") String userid, @Param("appId") String appId);
/***********************************
* 用途说明根据角色id删除角色菜单关联
* 参数说明
*id 角色id
* 返回值说明: 是否删除成功
***********************************/
@Delete("DELETE FROM app_role_menu WHERE roleid= #{id}")
void deleteRoleMenus( @Param("id") String id);
/***********************************
* 用途说明根据角色id删除角色用户关联
* 参数说明
*id 角色id
* 返回值说明: 是否删除成功
***********************************/
@Delete(" DELETE FROM app_role_users WHERE roleid= #{id}")
void deleteRoleUser( @Param("id")String id);
/***********************************
* 用途说明根据 角色id和用户id 删除 admin除外
* 参数说明
*roleid 角色id
* urserid 用户id
* 返回值说明: 是否删除成功
***********************************/
@Delete("delete from app_role_users where userid !=(select u.id from app_user u where u.account=\"admin\") and roleid=#{roleid} and userid=#{urserid}\n")
boolean deleteRoleUsers(String roleid, String urserid);
@Insert("<script>" +
"INSERT INTO app_role_menu " +
"<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">" +
" <if test=\"id != null and id != ''\">id,</if>" +
" <if test=\"appid != null and appid != ''\">app_id,</if>" + // 字段名 app_id 对应参数 appid
" <if test=\"roleid != null and roleid != ''\">roleid,</if>" +
" <if test=\"menuid != null and menuid != ''\">menuid</if>" +
"</trim>" +
" VALUES " +
"<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">" +
" <if test=\"id != null and id != ''\">#{id},</if>" +
" <if test=\"appid != null and appid != ''\">#{appid},</if>" +
" <if test=\"roleid != null and roleid != ''\">#{roleid},</if>" +
" <if test=\"menuid != null and menuid != ''\">#{menuid}</if>" +
"</trim>" +
"</script>")
void addRoleMenu(@Param("id") String id, @Param("appid") String appid, @Param("roleid") String roleid, @Param("menuid") String menuid);
/***********************************
* 用途说明根据菜单id删除角色菜单关联
* 参数说明
*id 菜单id
* 返回值说明: 是否删除成功
***********************************/
@Delete("DELETE FROM app_role_menu WHERE menuid= #{id}")
void deleteRoleMenusByMenuId(@Param("id") String id);
}

View File

@ -0,0 +1,100 @@
package com.stdproject.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;
@Mapper
public interface UserMapper extends BaseMapper<User> {
/***********************************
* 用途说明新增系统角色用户对照表 对用户分配角色
* 参数说明
* roleid 角色id
* userid 用户id
* 返回值说明:
************************************/
@Insert("INSERT INTO app_role_users(id, app_id, roleid, userid) VALUES (#{id}, #{appid}, #{roleid}, #{userid})")
boolean addUserRoles(@Param("id") String id, @Param("appid") String appid, @Param("roleid") String roleid, @Param("userid") String userid);
/***********************************
* 用途说明根据用户表id查询角色表所有角色id
* 参数说明
* userid 用户id
* 返回值说明:
************************************/
@Select(" SELECT roleid FROM app_role_users WHERE userid = #{userid} ")
List<String> getRoleid(@Param("userid") String id);
/***********************************
* 用途说明根据用户id删除所分配的角色
* 参数说明
* userid 用户id
* 返回值说明:
************************************/
@Delete("delete from app_role_users where userid=#{userid}")
boolean delRoleUsersByUserid( @Param("userid") String id);
/***********************************
* 用途说明根据条件分页查询用户信息
* 参数说明
* orgid 所属组织ID
* nickname 用户昵称
* page 分页条件
* 返回值说明:
************************************/
@Select("<script>" +
"SELECT DISTINCT\n" +
" u.id, u.usertype, u.username, u.nickname,\n" +
" u.email, u.phone, u.avatar, u.orgid,\n" +
" u.status, u.lastmodifier, u.lastmodifydate\n" +
"FROM app_user u\n" +
"WHERE u.usertype != 0\n" +
"<if test='orgid != null and orgid != \"\"'>\n" +
" AND u.orgid = #{orgid}\n" +
"</if>\n" +
"<if test='appId != null and appId != \"\"'>\n" +
" AND u.app_id = #{appId}\n" +
"</if>\n" +
"<if test='nickname != null and nickname != \"\"'>\n" +
" AND u.nickname LIKE CONCAT('%', #{nickname}, '%')\n" +
"</if>\n" +
"ORDER BY u.lastmodifydate DESC" +
"</script>")
Page<Map<String, Object>> queryUsers(
@Param("orgid") String orgid,
@Param("appId") String appId,
@Param("nickname") String nickname,
Page<?> page
);
/***********************************
* 用途说明根据ID删除用户与角色的关联信息
* 参数说明
* idList 用户id集合
* 返回值说明:
************************************/
@Delete("<script>" +
"DELETE FROM app_role_users WHERE userid IN " +
"<foreach collection='idList' item='id' open='(' separator=',' close=')'>#{id}</foreach>" +
"</script>")
void delRoleUsersByUserIds(List<String> idList);
/***********************************
* 用途说明根据用户id 和角色id 查询 系统角色用户对照表
* 参数说明
* userid 用户id
* roleid 角色id
* 返回值说明:
************************************/
@Select(" select id, app_id, roleid, userid from app_role_users where roleid = #{roleid} and userid = #{userid} ")
List<Map> getRoleUsersByid(@Param("roleid") String roleid,@Param("userid") String userid);
}

View File

@ -1,16 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppMenu;
/**
* <p>
* 应用系统_菜单 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppMenuService extends IService<AppMenu> {
}

View File

@ -1,16 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppOrganization;
/**
* <p>
* 应用系统_用户组织 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppOrganizationService extends IService<AppOrganization> {
}

View File

@ -1,16 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppRoleMenu;
/**
* <p>
* 系统角色-数据权限对照 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppRoleMenuService extends IService<AppRoleMenu> {
}

View File

@ -1,16 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppRole;
/**
* <p>
* 应用系统_系统角色 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppRoleService extends IService<AppRole> {
}

View File

@ -1,16 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppRoleUser;
/**
* <p>
* 系统角色-用户对照 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppRoleUserService extends IService<AppRoleUser> {
}

View File

@ -1,43 +0,0 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.AppUser;
/**
* <p>
* 应用系统_系统用户 服务类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
public interface IAppUserService extends IService<AppUser> {
/**
* 根据用户名查找用户
* @param username 用户名
* @return 用户实体
*/
AppUser findByUsername(String username);
/**
* 获取当前登录用户名
* @return 当前登录用户名未登录则返回null
*/
String getCurrentUsername();
/**
* 获取当前登录用户
* @return 当前登录用户实体未登录则返回null
*/
AppUser getCurrentUser();
/**
* 修改用户密码
* @param username 用户名
* @param oldPassword 原密码
* @param newPassword 新密码
* @return 修改是否成功
*/
boolean changePassword(String username, String oldPassword, String newPassword);
}

View File

@ -0,0 +1,14 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.Map;
/**
* 动态数据服务接口
* 提供对数据源表数据的增删改查操作
*/
public interface IDataVisualizationService {
}

View File

@ -0,0 +1,52 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.Menu;
import java.util.List;
import java.util.Map;
/**
* <p>
* 菜单及按钮 服务类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
public interface IMenuService extends IService<Menu> {
/***********************************
* 用途说明获取菜单结构树含按钮
* 参数说明
* appId 应用ID 关联应用系统
* name 名称
* isdisplay 是否显示
* 返回值说明: 菜单结构树集合
***********************************/
List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay);
/***********************************
* 用途说明新增菜单及按钮
* 参数说明
* sysMenu 菜单或按钮表对象
* 返回值说明: 是否添加成功提示
***********************************/
boolean addMenu(Menu menu);
/***********************************
* 用途说明根据id删除菜单或按钮
* 参数说明
* id 删除列的id
* 返回值说明: 是否删除成功
***********************************/
boolean deleteMenuById(String id);
/***********************************
* 用途说明获取分配权限
* 参数说明
* appId 系统id
* roleId 角色ID
* 返回值说明: 菜单结构树集合
***********************************/
List<Map<String, Object>> permissionAssignment(String appId ,String roleId);
}

View File

@ -0,0 +1,48 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.Organization;
import java.util.List;
import java.util.Map;
/**
* <p>
* 组织机构 服务类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
public interface IOrganizationService extends IService<Organization> {
/***********************************
* 用途说明获取企业列表
* 参数说明
* id 企业id
* orgName 部门名称
* orgtype 组织类型01-公司 02-部门
* parentid 上级ID
* 返回值说明: 企业列表集合
***********************************/
List<Map<String, Object>> getOrganizations(String appId, String orgtype, String parentid, String orgname);
/***********************************
* 用途说明根据ID查询信息
* 参数说明
* id 企业id
* orgName 部门名称
* 返回值说明: 系统部门框架对象
***********************************/
Organization getOrganizationById(String id);
/***********************************
* 用途说明新增系统组织框架
* 参数说明
* Organization 系统组织框架对象
* 返回值说明: 是否新增成功
***********************************/
boolean addOrganization(Organization organization);
}

View File

@ -0,0 +1,74 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.Role;
import java.util.List;
/**
* <p>
* 角色 服务类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
public interface IRoleService extends IService<Role> {
/**********************************
* 用途说明: 根据用户id获取角色id
* 参数说明 userid 用户id
* 返回值说明: void
***********************************/
List<String> getRoleUsers(String userid,String appId);
/***********************************
* 用途说明新增角色
* 参数说明
* sysRole 新增角色信息
* 返回值说明: 是否新增成功
***********************************/
boolean addRole(Role role);
/***********************************
* 用途说明查询所有角色
* 参数说明
* rolename 角色名称
* 返回值说明: 查询都有角色
***********************************/
List<Role> listRole(String appId, String rolename);
/***********************************
* 用途说明根据id删除角色
* 参数说明
* id 角色id
* 返回值说明: 是否删除成功
***********************************/
Boolean deleteById(String id);
/***********************************
* 用途说明删除角色用户
* 参数说明
* roleid 角色id
* 返回值说明: 是否新增成功
***********************************/
boolean deleteRoleUsers(String roleid, String userids);
/***********************************
* 用途说明根据ID批量删除角色
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
boolean deleteRoleByIds(String ids);
/***********************************
* 用途说明角色菜单权限
* 参数说明
* id 角色id
* menuIds 权限id字符串
* 返回值说明: 是否分配成功
***********************************/
boolean setMenuByRoleId(String id, String menuIds);
}

View File

@ -0,0 +1,91 @@
package com.stdproject.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.stdproject.entity.User;
import java.util.Map;
/**
* <p>
* 用户 服务类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
public interface IUserService extends IService<User> {
/***********************************
* 用途说明新增系统用户
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
Map addUser(User user, String roleids);
/***********************************
* 用途说明修改用户信息
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
Map updateById(User user, String roleids);
/***********************************
* 用途说明查询用户信息
* 参数说明
* orgid 所属组织ID
* nickname 用户昵称
* page 分页条件
* 返回值说明: 用户信息集合
***********************************/
Page<Map<String, Object>> queryUsers(String orgid,String appId, String nickname, Page<User> page);
/***********************************
* 用途说明根据id删除用户
* 参数说明
*id 用户id
* 返回值说明: 判断是否删除成功
************************************/
Boolean deleteUserById(String id);
/***********************************
* 用途说明根据ID批量删除用户
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
boolean deleteUserByIds(String ids);
/***********************************
* 用途说明重置用户密码(管理员)
* 参数说明
*id 重置密码的 用户id
* 返回值说明: 判断是否重置成功
************************************/
boolean resetPassword(String id);
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明
*id 用户id
* status 设置状态
* 返回值说明: 判断是否设置成功
************************************/
boolean setStatus(String id, String status);
/***********************************
* 用途说明角色添加用户
* 参数说明
* roleid 角色id
* userids 用户id组
* 返回值说明: 是否新增成功
***********************************/
boolean addUserRole(String roleid, String userid);
}

View File

@ -1,20 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppMenu;
import com.stdproject.mapper.AppMenuMapper;
import com.stdproject.service.IAppMenuService;
import org.springframework.stereotype.Service;
/**
* <p>
* 应用系统_菜单 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppMenuServiceImpl extends ServiceImpl<AppMenuMapper, AppMenu> implements IAppMenuService {
}

View File

@ -1,23 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppOrganization;
import com.stdproject.mapper.AppOrganizationMapper;
import com.stdproject.service.IAppOrganizationService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 应用系统_用户组织 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppOrganizationServiceImpl extends ServiceImpl<AppOrganizationMapper, AppOrganization> implements IAppOrganizationService {
}

View File

@ -1,20 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppRoleMenu;
import com.stdproject.mapper.AppRoleMenuMapper;
import com.stdproject.service.IAppRoleMenuService;
import org.springframework.stereotype.Service;
/**
* <p>
* 系统角色-数据权限对照 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppRoleMenuServiceImpl extends ServiceImpl<AppRoleMenuMapper, AppRoleMenu> implements IAppRoleMenuService {
}

View File

@ -1,20 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppRole;
import com.stdproject.mapper.AppRoleMapper;
import com.stdproject.service.IAppRoleService;
import org.springframework.stereotype.Service;
/**
* <p>
* 应用系统_系统角色 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppRoleServiceImpl extends ServiceImpl<AppRoleMapper, AppRole> implements IAppRoleService {
}

View File

@ -1,20 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppRoleUser;
import com.stdproject.mapper.AppRoleUserMapper;
import com.stdproject.service.IAppRoleUserService;
import org.springframework.stereotype.Service;
/**
* <p>
* 系统角色-用户对照 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppRoleUserServiceImpl extends ServiceImpl<AppRoleUserMapper, AppRoleUser> implements IAppRoleUserService {
}

View File

@ -1,78 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.AppUser;
import com.stdproject.mapper.AppUserMapper;
import com.stdproject.service.IAppUserService;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
/**
* <p>
* 应用系统_系统用户 服务实现类
* </p>
*
* @author StdProject
* @since 2023-12-07
*/
@Service
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements IAppUserService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public AppUser findByUsername(String username) {
return getOne(new QueryWrapper<AppUser>().eq("username", username).select( "id", "username","password","status", "orgid", "usertype","nickname"));
}
@Override
public String getCurrentUsername() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.isAuthenticated()) {
return authentication.getName();
}
return null;
}
@Override
public AppUser getCurrentUser() {
String username = getCurrentUsername();
if (StringUtils.hasText(username)) {
return findByUsername(username);
}
return null;
}
@Override
public boolean changePassword(String username, String oldPassword, String newPassword) {
if (!StringUtils.hasText(username) || !StringUtils.hasText(oldPassword) || !StringUtils.hasText(newPassword)) {
return false;
}
// 获取完整的用户信息包含密码
AppUser user = getOne(new QueryWrapper<AppUser>().eq("username", username));
if (user == null) {
return false;
}
// 验证原密码
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
return false;
}
// 更新新密码
user.setPassword(passwordEncoder.encode(newPassword));
user.setPwdresettime(LocalDateTime.now());
return updateById(user);
}
}

View File

@ -1,430 +0,0 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stdproject.common.BusinessException;
import com.stdproject.entity.CoreDatasource;
import com.stdproject.mapper.CoreDatasourceMapper;
import com.stdproject.service.IDynamicDataService;
import io.gisbi.extensions.datasource.dto.DatasourceRequest;
import io.gisbi.extensions.datasource.dto.DatasourceSchemaDTO;
import io.gisbi.extensions.datasource.dto.TableField;
import io.gisbi.extensions.datasource.factory.ProviderFactory;
import io.gisbi.extensions.datasource.provider.Provider;
import io.gisbi.utils.BeanUtils;
import io.gisbi.utils.IDUtils;
import io.gisbi.utils.JsonUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.stdproject.utils.EncryptUtils;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Service
public class DynamicDataServiceImpl implements IDynamicDataService {
@Resource
private CoreDatasourceMapper coreDatasourceMapper;
@Override
public boolean addTableData(Long datasourceId, String tableData) throws Exception {
// 根据数据源 id 查询数据源信息调用通用数据源执行器
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(datasourceId);
if (coreDatasource == null) {
BusinessException.throwException("数据源不存在");
}
coreDatasource.setConfiguration(String.valueOf(EncryptUtils.aesDecrypt(coreDatasource.getConfiguration())));
// 解析 tableData JSON 字符串 "{ \"tableName\": \"user\", \"data\": [ { \"fieldName\": \"id\", \"fieldType\": \"varchar\", \"IsPrimaryKey\": true, \"fieldValue\": \"0001\" }, { \"fieldName\": \"name\", \"fieldType\": \"varchar\", \"fieldValue\": \"张三\" } ] }";
Map<String, Object> dataMap = JsonUtil.parseObject(tableData, Map.class);
String tableName = (String) dataMap.get("tableName");
List<Map<String, Object>> fieldList = (List<Map<String, Object>>) dataMap.get("data");
if (fieldList == null || fieldList.isEmpty()) {
BusinessException.throwException("没有可插入的数据字段");
}
// 构建插入语句
StringBuilder columns = new StringBuilder();
StringBuilder values = new StringBuilder();
for (int i = 0; i < fieldList.size(); i++) {
Map<String, Object> field = fieldList.get(i);
String fieldName = (String) field.get("fieldName");
Object fieldValue = field.get("fieldValue");
boolean isPrimaryKey = field.get("IsPrimaryKey") != null && (boolean) field.get("IsPrimaryKey");
if (isPrimaryKey) {
if (fieldValue == null) {fieldValue= IDUtils.snowID();}
}
if (i > 0) {
columns.append(", ");
values.append(", ");
}
columns.append(fieldName);
if (fieldValue instanceof String) {
values.append("'").append(fieldValue).append("'");
} else {
values.append(fieldValue);
}
}
String sql = String.format("INSERT INTO %s (%s) VALUES (%s)", tableName, columns.toString(), values.toString());
// 调用执行器向数据表中插入 tableData 数据
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();
BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource);
Provider provider = ProviderFactory.getProvider(coreDatasource.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setQuery(sql);
datasourceRequest.setDsList(Map.of(datasourceSchemaDTO.getId(), datasourceSchemaDTO));
log.debug("执行插入数据的SQL: {}", sql);
// 执行插入操作
int result= provider.executeUpdate(datasourceRequest);
if (result==1) {
return true;
// process result set
} else {
return false;
}
}
@Override
public Map<String, Object> getTableDataByPk(Long datasourceId, String condtion) throws Exception {
// 获取数据源信息
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(datasourceId);
if (coreDatasource == null) {
BusinessException.throwException("数据源不存在");
}
coreDatasource.setConfiguration(String.valueOf(EncryptUtils.aesDecrypt(coreDatasource.getConfiguration())));
// 解析 JSON 数据
//condtion={ \"tableName\": \"user\", key:[{ \"fieldName\": \"id\",\"fieldValue\": \"0001\"]
Map<String, Object> dataMap = JsonUtil.parseObject(condtion, Map.class);
String tableName = (String) dataMap.get("tableName");
// 参数校验
if (StringUtils.isBlank(tableName)) {
BusinessException.throwException("表名不能为空");
}
List<Map<String, Object>> keyFields = (List<Map<String, Object>>) dataMap.get("key");
if (CollectionUtils.isEmpty(keyFields)) {
BusinessException.throwException("主键字段或值不能为空");
}
String whereClause = buildWhereCondition(keyFields);
String sql = String.format("SELECT * FROM %s WHERE %s", tableName, whereClause);
// 执行查询操作
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();
BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource);
Provider provider = ProviderFactory.getProvider(coreDatasource.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setQuery(sql);
datasourceRequest.setDsList(Map.of(datasourceSchemaDTO.getId(), datasourceSchemaDTO));
log.debug("执行查询数据的SQL: {}", sql);
// 获取查询结果
Map<String, Object> data = provider.fetchResultField(datasourceRequest);
// 处理查询结果
List<String[]> dataList = (List<String[]>) data.get("data");
List<TableField> fields = (List<TableField>) data.get("fields");
if (CollectionUtils.isEmpty(dataList) || dataList.size() == 0) {
return null;
}
// 将结果转换为 Map 格式
String[] row = dataList.get(0);
Map<String, Object> resultMap = new LinkedHashMap<>();
for (int i = 0; i < fields.size(); i++) {
TableField field = fields.get(i);
String fieldName = field.getOriginName();
resultMap.put(fieldName, row[i]);
}
return resultMap;
}
/**
* 构建 WHERE 条件字符串用于多字段主键查询/更新/删除操作
*
* @param keyFields 主键字段列表格式如{ "fieldName": "id", "fieldValue": "0001" }
* @return SQL WHERE 子句字符串
*/
private String buildWhereCondition(List<Map<String, Object>> keyFields) {
StringBuilder whereClause = new StringBuilder();
for (int i = 0; i < keyFields.size(); i++) {
Map<String, Object> keyField = keyFields.get(i);
String fieldName = (String) keyField.get("fieldName");
Object fieldValue = keyField.get("fieldValue");
if (i > 0) {
whereClause.append(" AND ");
}
if (fieldValue == null) {
whereClause.append(fieldName).append(" IS NULL");
} else if (fieldValue instanceof String) {
whereClause.append(String.format("%s = '%s'", fieldName, fieldValue));
} else {
whereClause.append(String.format("%s = %s", fieldName, fieldValue));
}
}
return whereClause.toString();
}
@Override
public boolean updateTableData(Long datasourceId, String tableData) throws Exception {
// 获取数据源信息
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(datasourceId);
if (coreDatasource == null) {
BusinessException.throwException("数据源不存在");
}
coreDatasource.setConfiguration(String.valueOf(EncryptUtils.aesDecrypt(coreDatasource.getConfiguration())));
//String tableDataJson = "{ \"tableName\": \"user\", key:[{ \"fieldName\": \"id\",\"fieldValue\": \"0001\"], \"data\": [ { \"fieldName\": \"name\", \"fieldType\": \"varchar\", \"fieldValue\": \"李四\" } ] }";
// 解析 JSON 数据
Map<String, Object> dataMap = JsonUtil.parseObject(tableData, Map.class);
String tableName = (String) dataMap.get("tableName");
if (StringUtils.isBlank(tableName)) {
BusinessException.throwException("表名不能为空");
}
List<Map<String, Object>> keyFields = (List<Map<String, Object>>) dataMap.get("key");
if (CollectionUtils.isEmpty(keyFields)) {
BusinessException.throwException("主键字段或值不能为空");
}
List<Map<String, Object>> fieldList = (List<Map<String, Object>>) dataMap.get("data");
if (fieldList == null || fieldList.isEmpty()) {
BusinessException.throwException("没有可更新的数据字段");
}
// 构建 UPDATE 语句
StringBuilder setClause = new StringBuilder();
for (int i = 0; i < fieldList.size(); i++) {
Map<String, Object> field = fieldList.get(i);
String fieldName = (String) field.get("fieldName");
Object fieldValue = field.get("fieldValue");
if (i > 0) {
setClause.append(", ");
}
if (fieldValue instanceof String) {
setClause.append(String.format("%s = '%s'", fieldName, fieldValue));
} else {
setClause.append(String.format("%s = %s", fieldName, fieldValue));
}
}
String whereClause = buildWhereCondition(keyFields);
String sql = String.format("UPDATE %s SET %s WHERE %s", tableName, setClause, whereClause);
// 调用执行器执行 SQL
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();
BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource);
Provider provider = ProviderFactory.getProvider(coreDatasource.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setQuery(sql);
datasourceRequest.setDsList(Map.of(datasourceSchemaDTO.getId(), datasourceSchemaDTO));
log.debug("执行更新数据的SQL: {}", sql);
// 执行更新操作
int result= provider.executeUpdate(datasourceRequest);
if (result==1) {
return true;
// process result set
} else {
return false;
}
}
@Override
public boolean deleteTableData(Long datasourceId, String condtion) throws Exception {
// 获取数据源信息
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(datasourceId);
if (coreDatasource == null) {
BusinessException.throwException("数据源不存在"); }
coreDatasource.setConfiguration(String.valueOf(EncryptUtils.aesDecrypt(coreDatasource.getConfiguration())));
// 解析 JSON 数据
//String tableDataJson = "{ \"tableName\": \"user\", key:[{ \"fieldName\": \"id\",\"fieldValue\": \"0001\"] }";
Map<String, Object> dataMap = JsonUtil.parseObject(condtion, Map.class);
String tableName = (String) dataMap.get("tableName");
if (StringUtils.isBlank(tableName)) {
BusinessException.throwException("表名不能为空");
}
List<Map<String, Object>> keyFields = (List<Map<String, Object>>) dataMap.get("key");
if (CollectionUtils.isEmpty(keyFields)) {
BusinessException.throwException("主键字段或值不能为空");
}
String whereClause = buildWhereCondition(keyFields);
String sql = String.format("DELETE FROM %s WHERE %s", tableName, whereClause);
// 调用执行器执行 SQL
DatasourceSchemaDTO datasourceSchemaDTO = new DatasourceSchemaDTO();
BeanUtils.copyBean(datasourceSchemaDTO, coreDatasource);
Provider provider = ProviderFactory.getProvider(coreDatasource.getType());
DatasourceRequest datasourceRequest = new DatasourceRequest();
datasourceRequest.setQuery(sql);
datasourceRequest.setDsList(Map.of(datasourceSchemaDTO.getId(), datasourceSchemaDTO));
log.debug("执行删除数据的SQL: {}", sql);
// 执行删除操作
int result= provider.executeUpdate(datasourceRequest);
if (result==1) {
return true;
// process result set
} else {
return false;
}
}
@Override
public Page<Map<String, Object>> queryTableDataPaged(Long datasourceId, String condition) throws Exception {
// 获取数据源信息
CoreDatasource coreDatasource = coreDatasourceMapper.selectById(datasourceId);
if (coreDatasource == null) {
BusinessException.throwException("数据源不存在");
}
coreDatasource.setConfiguration(String.valueOf(EncryptUtils.aesDecrypt(coreDatasource.getConfiguration())));
// 解析 condition JSON 数据
Map<String, Object> dataMap = JsonUtil.parseObject(condition, Map.class);
String tableName = (String) dataMap.get("tableName");
List<Map<String, Object>> conditionList = (List<Map<String, Object>>) dataMap.get("conditions");
Integer pageNum = (Integer) dataMap.getOrDefault("pageNum", 1);
Integer pageSize = (Integer) dataMap.getOrDefault("pageSize", 10);
if (StringUtils.isBlank(tableName)) {
BusinessException.throwException("表名不能为空");
}
// 构建 WHERE 条件子句
StringBuilder whereClause = new StringBuilder();
if (conditionList != null && !conditionList.isEmpty()) {
whereClause.append(" WHERE ");
for (int i = 0; i < conditionList.size(); i++) {
Map<String, Object> cond = conditionList.get(i);
String field = (String) cond.get("field");
String operator = ((String) cond.get("operator")).toLowerCase();
Object value = cond.get("value");
if (i > 0) {
whereClause.append(" AND ");
}
switch (operator) {
case "like":
whereClause.append(String.format("%s LIKE '%%%s%%'", field, value));
break;
case "=":
appendValue(whereClause, field, value, "=");
break;
case "<":
appendValue(whereClause, field, value, "<");
break;
case ">":
appendValue(whereClause, field, value, ">");
break;
case "<=":
appendValue(whereClause, field, value, "<=");
break;
case ">=":
appendValue(whereClause, field, value, ">=");
break;
case "!=":
case "<>":
appendValue(whereClause, field, value, "<>");
break;
case "in":
if (!(value instanceof List<?>)) {
BusinessException.throwException("IN 操作符要求值为列表类型");
}
List<?> values = (List<?>) value;
String inValues = values.stream()
.map(v -> v instanceof String ? "'" + v + "'" : v.toString())
.collect(Collectors.joining(", "));
whereClause.append(String.format("%s IN (%s)", field, inValues));
break;
default:
BusinessException.throwException("不支持的操作符: " + operator);
}
}
}
// 构建基础 SQL
String baseSql = String.format("SELECT * FROM %s%s", tableName, whereClause);
String dbType = coreDatasource.getType().toLowerCase();
String pagedSql = buildPagedSQL(baseSql, dbType, pageNum, pageSize);
String countSql = String.format("SELECT COUNT(*) FROM %s%s", tableName, whereClause);
DatasourceSchemaDTO schemaDTO = new DatasourceSchemaDTO();
BeanUtils.copyBean(schemaDTO, coreDatasource);
Provider provider = ProviderFactory.getProvider(coreDatasource.getType());
DatasourceRequest request = new DatasourceRequest();
request.setDsList(Map.of(schemaDTO.getId(), schemaDTO));
// 查询分页数据
request.setQuery(pagedSql);
Map<String, Object> result = provider.fetchResultField(request);
List<String[]> dataList = (List<String[]>) result.get("data");
List<TableField> fields = (List<TableField>) result.get("fields");
// 查询总记录数
request.setQuery(countSql);
Map<String, Object> countResult = provider.fetchResultField(request);
long total = Long.parseLong(((List<String[]>) countResult.get("data")).get(0)[0]);
// 将数据封装为 Map 形式
List<Map<String, Object>> records = new ArrayList<>();
if (!CollectionUtils.isEmpty(dataList)) {
for (String[] row : dataList) {
Map<String, Object> rowMap = new LinkedHashMap<>();
for (int i = 0; i < fields.size() && i < row.length; i++) {
String fieldName = fields.get(i).getOriginName();
String fieldValue = row[i];
rowMap.put(fieldName, fieldValue);
}
records.add(rowMap);
}
}
// 返回分页结果
Page<Map<String, Object>> page = new Page<>();
page.setCurrent(pageNum);
page.setSize(pageSize);
page.setTotal(total);
page.setRecords(records);
return page;
}
private void appendValue(StringBuilder sb, String field, Object value, String op) {
if (value instanceof String) {
sb.append(String.format("%s %s '%s'", field, op, value));
} else {
sb.append(String.format("%s %s %s", field, op, value));
}
}
private String buildPagedSQL(String baseSql, String dbType, int pageNum, int pageSize) {
int offset = (pageNum - 1) * pageSize;
switch (dbType) {
case "mysql":
case "mariadb":
return String.format("%s LIMIT %d OFFSET %d", baseSql, pageSize, offset);
case "postgresql":
return String.format("%s LIMIT %d OFFSET %d", baseSql, pageSize, offset);
case "oracle":
int start = offset + 1;
int end = offset + pageSize;
return String.format("SELECT * FROM (SELECT ROWNUM rn, t.* FROM (%s) t WHERE ROWNUM <= %d) WHERE rn >= %d", baseSql, end, start);
case "sqlserver":
return String.format("%s OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", baseSql, offset, pageSize);
default:
// 默认使用 MySQL 方式
return String.format("%s LIMIT %d OFFSET %d", baseSql, pageSize, offset);
}
}
}

View File

@ -0,0 +1,330 @@
package com.stdproject.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.entity.Menu;
import com.stdproject.mapper.MenuMapper;
import com.stdproject.mapper.RoleMapper;
import com.stdproject.service.IMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.gisbi.utils.AuthUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* 菜单及按钮 服务实现类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {
@Resource
private MenuMapper menuMapper;
@Resource
private RoleMapper roleMapper;
@Override
public List<Map<String, Object>> getMenuTree(String appId, String name, String isdisplay) {
List<Map<String, Object>> listMap = null;
//不带名称查询返回树结构
if (StringUtils.isEmpty(name)) {
QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parentid", "0").eq("app_id", appId).orderByAsc("orderno");
listMap = this.listMaps(queryWrapper);
for (int i = 0; i < listMap.size(); i++) {
//查询下一子集
List<Map<String, Object>> childList = child(listMap.get(i).get(
"id").toString(), appId, name, null, null);
listMap.get(i).put("children", childList); //添加新列 子集
}
} else { //根据菜单名称查询直接返回类别
QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name", name).eq("app_id", appId).orderByAsc("name");
listMap = this.listMaps(queryWrapper);
}
return listMap;
}
/***********************************
* 用途说明新增菜单及按钮
* 参数说明
* sysMenu 菜单或按钮表对象
* 返回值说明: 是否添加成功提示
***********************************/
@Override
public boolean addMenu(Menu menu) {
String parentId = menu.getParentid();
QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
//根据上级id 查询到总数 并累加
int orderno = (int) (this.count(queryWrapper.eq("parentid", parentId)) + 1);
// 生成排序号
// 生成编号
QueryWrapper<Menu> queryMaxCode = new QueryWrapper<>();
queryMaxCode.eq("parentid", parentId);
// 查询最大的编号
List<Object> maxList = this.listObjs(queryMaxCode.select("max(code) " +
"code").eq("app_id", menu.getAppId()));
Menu parentMenu = menuMapper.selectById(parentId);
// 最大编号转换成int类型
String maxCode = maxList.isEmpty() ? "0" : (maxList.get(0) != null ? maxList.get(0).toString() : "0");
int max = ObjectUtil.isEmpty(maxList) ? 0 : Integer.parseInt(maxCode);
DecimalFormat df;
if ("0".equals(menu.getParentid())) {
df = new DecimalFormat("00");
} else if (parentMenu.getCode().length() == 2) {
df = new DecimalFormat("0000");
} else {
df = new DecimalFormat("000000");
}
//DecimalFormat df = new DecimalFormat("00");
//int parentCode = Integer.parseInt(parentMenu.getCode());
String parentCode = "";
if (parentMenu != null) {
parentCode = parentMenu.getCode();
}
// 生成的新编号 年月日+4位编号
String code;
if (max > 0) {
code = df.format(max + 1);
} else {
max = max + 1;
if (StringUtils.isBlank(parentCode)) {
parentCode = "0" + max;
} else {
int i = Integer.parseInt(parentCode);
parentCode = i + "0" + max;
}
int format = Integer.parseInt(parentCode);
code = df.format(format);
}
// 判断是否显示字段 是否填写 为空
if (StringUtils.isEmpty(menu.getIsdisplay())) {
// 默认设置成 1 显示
menu.setIsdisplay("1");
}
// 判断是否填写父级id 为空 默认设置成 0
if (StringUtils.isEmpty(menu.getParentid())) {
menu.setParentid("0");
}
// 添加编号
menu.setCode(code);
// 添加排序号
menu.setOrderno(orderno);
//填写 当前用户名称
menu.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 当前日期
menu.setLastmodifydate(LocalDateTime.now());
return this.save(menu);
}
/***********************************
* 用途说明根据id删除菜单或按钮
* 参数说明
* id 删除列的id
* 返回值说明: 是否删除成功
***********************************/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteMenuById(String id) {
//根据id查询
Menu menu = this.getById(id);
// 根据id删除主菜单
boolean isOk = this.removeById(id);
if (!isOk) {
return false;
}
// 通过ID 删除角色菜单关联信息
roleMapper.deleteRoleMenusByMenuId(id);
//1 创建list集合用于封装所有删除目录或菜单id值 如果下面有子项 都删除
List<String> idList = new ArrayList<>();
this.selectPermissionChildById(id, idList);
if (!idList.isEmpty()) {
menuMapper.deleteBatchIds(idList);
//通过ID集合 删除角色菜单关联信息
for (String menuId : idList) {
roleMapper.deleteRoleMenusByMenuId(menuId);
}
}
QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
//根据上级id 查询 根据 orderno 正序排序
queryWrapper.eq("parentid", menu.getParentid()).orderByAsc(
"orderno");
List<Menu> list = this.list(queryWrapper);
for (int i = 0; i < list.size(); i++) {
Menu menuData = list.get(i);
//更新序列号
menuData.setOrderno(i + 1);
}
//更新表数据
this.updateBatchById(list);
return isOk;
}
/***********************************
* 用途说明获取分配权限
* 参数说明
* appId 系统id
* roleId 角色ID
* 返回值说明: 菜单结构树集合
***********************************/
@Override
public List<Map<String, Object>> permissionAssignment(String appId ,String roleId) {
LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Menu::getAppId, appId).select(Menu::getId,Menu::getAppId,Menu::getType,Menu::getCode,
Menu::getParentid, Menu::getName).orderByAsc
(Menu::getOrderno);
List<Map<String, Object>> listAll =
menuMapper.selectMaps(queryWrapper);
List<String> listRole =
menuMapper.selectMenuByRoleId(appId,roleId);
for (Map<String, Object> map : listAll) {
String id = (String) map.get("id");
if (listRole.contains(id)) {
map.put("checkinfo", true);
} else {
map.put("checkinfo", false);
}
}
List<Map<String, Object>> listTree = buildTrees(listAll);
return listTree;
}
/**********************************
* 用途说明: 生成权菜单权限树
* 参数说明 sysMenus
* 返回值说明: java.util.List<java.util.Map<java.lang.String,java.lang.Object>>
***********************************/
public List<Map<String, Object>> buildTrees(List<Map<String, Object>> Menus) {
List<Map<String, Object>> resultMenuList = new ArrayList<>();
for (Map<String, Object> sysMenu : Menus) {
if ("0".equals(sysMenu.get("parentid"))) {
resultMenuList.add(sysMenu);
}
}
for (Map<String, Object> sysMenu : resultMenuList) {
List<Map<String, Object>> menus = iterateMenus(Menus,
(String) sysMenu.get("id"));
for (Map<String, Object> menu : menus) {
if (!(boolean) menu.get("checkinfo")) {
sysMenu.put("checkinfo", false);
break;
}
}
sysMenu.put("children", menus);
}
return resultMenuList;
}
/**
* 多级菜单查询方法
*
* @param menuVoList 不包含最高层次菜单的菜单集合
* @param pid 父类id
* @return
*/
public List<Map<String, Object>> iterateMenus(List<Map<String, Object>> menuVoList, String pid) {
List<Map<String, Object>> result = new ArrayList<>();
for (Map<String, Object> menu : menuVoList) {
//获取菜单的id
String menuid = (String) menu.get("id");
//获取菜单的父id
String parentid = (String) menu.get("parentid");
if (StrUtil.isNotBlank(parentid)) {
if (parentid.equals(pid)) {
//递归查询当前子菜单的子菜单
List<Map<String, Object>> iterateMenu =
iterateMenus(menuVoList, menuid);
for (Map<String, Object> map : iterateMenu) {
boolean checkinfo = (boolean) map.get("checkinfo");
if (!checkinfo) {
menu.put("checkinfo", false);
}
}
menu.put("children", iterateMenu);
result.add(menu);
}
}
}
return result;
}
//2 根据当前菜单id查询菜单里面子菜单id封装到list集合
private void selectPermissionChildById(String id, List<String> idList) {
//查询菜单里面子菜单id
QueryWrapper<Menu> wrapper = new QueryWrapper<>();
wrapper.eq("parentid", id);
wrapper.select("id");
List<Menu> childIdList = baseMapper.selectList(wrapper);
//把childIdList里面菜单id值获取出来封装idList里面做递归查询
childIdList.stream().forEach(item -> {
//封装idList里面
idList.add(item.getId());
//递归查询
this.selectPermissionChildById(item.getId(), idList);
});
}
/***********************************
* 用途说明查询菜单
* 参数说明
* parentid 上级id
*systemcode 系统
* isdisplay 是否显示
* type 菜单类型
* 返回值说明: 菜单结构树集合
***********************************/
private List<Map<String, Object>> child(String parentid,
String appId, String name,
String isdisplay, String type) {
List<Map<String, Object>> listMap = new ArrayList<>();
QueryWrapper<Menu> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parentid", parentid).eq("app_id", appId);
//根据上级id 系统 查询
if (StringUtils.isNotEmpty(type)) {
queryWrapper.ne("type", type);
}
//根据菜单名称查询
if (StringUtils.isNotEmpty(name)) {
queryWrapper.like("name", name);
}
listMap = this.listMaps(queryWrapper.orderByAsc("orderno"));
if (listMap.size() > 0) { //判断是否存在子集
for (int i = 0; i < listMap.size(); i++) { //遍历表数据
List<Map<String, Object>> childList =
child(listMap.get(i).get("id").toString(), appId
, name, isdisplay, type); //循环获取下一子集
listMap.get(i).put("children", childList); //添加新列 子集
}
}
return listMap;
}
}

View File

@ -0,0 +1,177 @@
package com.stdproject.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.stdproject.entity.Organization;
import com.stdproject.mapper.OrganizationMapper;
import com.stdproject.service.IOrganizationService;
import com.stdproject.service.IUserService;
import io.gisbi.utils.AuthUtils;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* 组织机构 服务实现类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@Service
public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, Organization> implements IOrganizationService {
@Resource
private IUserService userService;
@Resource
private OrganizationMapper organizationMapper;
public static final String DEFAULT_IS_VALID = "1";
/***********************************
* 用途说明获取企业列表
* 参数说明
* id 企业id
* orgName 部门名称
* orgtype 组织类型01-公司 02-部门
* parentid 上级ID
* 返回值说明: 企业列表集合
***********************************/
@Override
public List<Map<String, Object>> getOrganizations(String appId, String orgtype, String parentid, String orgname) {
LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Organization::getParentid, parentid);
queryWrapper.eq(Organization::getAppId, appId);
queryWrapper.eq(Organization::getOrgtype, orgtype);
//根据部门名称查询
queryWrapper.like(StringUtils.isNotBlank(orgname), Organization::getOrgname, orgname);
List<Map<String, Object>> listMap = this.listMaps(queryWrapper.orderByAsc(Organization::getOrgcode));
if (listMap == null) {
return new ArrayList<>();
}
for (Map<String, Object> item : listMap) {
Object idObj = item.get("id");
// 避免空指针
if (idObj == null) {
continue;
}
List<Map<String, Object>> childList = child(idObj.toString(), appId, orgname);
item.put("childList", childList); // 添加新列 子集
// if (childList != null && !childList.isEmpty()) {
// listMap.add(item); // 仅保留有子节点的数据
// }
}
return listMap;
}
/***********************************
* 用途说明获取部门结构树
* 参数说明
* parentid 上级id
* orgname (根据参数查询部门名称)
* 返回值说明: 部门结构树
***********************************/
private List<Map<String, Object>> child(String parentid, String appId, String orgname) {
List<Map<String, Object>> listMap;
LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
//根据上级id 查询
queryWrapper.eq(Organization::getParentid, parentid);
queryWrapper.eq(Organization::getAppId, appId);
//根据部门名称查询
queryWrapper.like(StringUtils.isNotBlank(orgname), Organization::getOrgname, orgname);
listMap = this.listMaps(queryWrapper.orderByAsc(Organization::getOrgcode));
//判断是否存在子集
if (listMap != null && !listMap.isEmpty()) {
//遍历表数据
for (int i = 0; i < listMap.size(); i++) {
//循环获取下一子集
List<Map<String, Object>> childList = child(listMap.get(i).get("id").toString(), appId, orgname);
//添加新列 子集
listMap.get(i).put("childList", childList);
}
}
return listMap;
}
/***********************************
* 用途说明根据ID查询信息
* 参数说明
* id 企业id
* orgName 部门名称
* 返回值说明: 系统部门框架对象
***********************************/
@Override
public Organization getOrganizationById(String id) {
Organization organization=this.getById(id);
return organization;
}
/***********************************
* 用途说明新增系统组织框架
* 参数说明
* Organization 系统组织框架对象
* 返回值说明: 是否新增成功
***********************************/
@Override
public boolean addOrganization(Organization organization) {
// 构建查询条件
LambdaQueryWrapper<Organization> queryWrapper = new LambdaQueryWrapper<>();
Organization parent = null;
int codeMax = 0;
//查询最大的编号 判断是否存在父级id 有值 根据父级id查询 否则 根据父级id为0 查询
queryWrapper.select(Organization::getOrgcode);
if (StrUtil.isNotBlank(organization.getParentid())) {
parent = this.getById(organization.getParentid());
queryWrapper.eq(Organization::getParentid, organization.getParentid());
} else {
organization.setParentid("0");
queryWrapper.eq(Organization::getParentid, "0");
}
List<Object> maxResult = this.listObjs(queryWrapper);
if (!maxResult.isEmpty()) {
String maxCodeStr = maxResult.get(0).toString();
try {
codeMax = Integer.parseInt(maxCodeStr.substring(maxCodeStr.length() - 2));
} catch (NumberFormatException e) {
// 记录日志并默认从 0 开始
codeMax = 0;
}
}
DecimalFormat df = new DecimalFormat("00");
String code = df.format(codeMax + 1);
if (parent != null) {
code = parent.getOrgcode() + df.format(codeMax + 1);
}
if (StrUtil.isBlank(organization.getIsvaild())) {
organization.setIsvaild(DEFAULT_IS_VALID);
}
//填写 编号
organization.setOrgcode(code);
//填写 当前用户名称
organization.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//填写 当前日期
organization.setLastmodifydate(LocalDateTime.now());
return this.save(organization);
}
}

View File

@ -0,0 +1,216 @@
package com.stdproject.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; // 正确引入 ServiceImpl
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stdproject.entity.Role;
import com.stdproject.mapper.RoleMapper;
import com.stdproject.service.IRoleService;
import io.gisbi.utils.AuthUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 应用系统 服务实现类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
@Resource
private RoleMapper roleMapper;
/**********************************
* 用途说明: 根据用户id获取角色id
* 参数说明 userid 用户id
* 返回值说明: void
***********************************/
@Override
public List<String> getRoleUsers(String userid, String appId) {
List<String> roleIds = roleMapper.getRoleUsers(userid, appId);
return roleIds;
}
/***********************************
* 用途说明新增角色
* 参数说明
* sysRole 新增角色信息
* 返回值说明: 是否新增成功
***********************************/
@Override
public boolean addRole(Role role) {
//生成用户编号
int codeMax = 0;
DecimalFormat df = new DecimalFormat("000");//四位数字编号
QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
// 查询最大的编号
List<Object> max = this.listObjs(queryWrapper.select("MAX(rolecode) " + "rolecode"));
//判断查询是否存在
if (max.size() > 0) {
codeMax = Integer.parseInt(max.get(0).toString());
}
// 存在转换成int类型并给codeMax替换值 // 最大编号累加
String code = df.format(codeMax + 1);
//添加角色编号
role.setRolecode(code);
//判断是否填写有效性 默认为 1
if (StringUtils.isEmpty(role.getIsvaild())) {
role.setIsvaild("1");
}
//添加最近修改者
role.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//添加最近修改时间
role.setLastmodifydate(LocalDateTime.now());
return this.save(role);
}
/***********************************
* 用途说明查询所有角色
* 参数说明
* rolename 角色名称
* 返回值说明: 查询都有角色
***********************************/
@Override
public List<Role> listRole(String appId, String rolename) {
LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Role::getAppId, appId);
//根据角色名称模糊查询
if (StringUtils.isNotEmpty(rolename)) {
queryWrapper.like(Role::getRolename, rolename);
}
//根据角色类别 正序排序
queryWrapper.orderByAsc(Role::getType, Role::getRolecode);
List<Role> roles = roleMapper.selectList(queryWrapper);
return roles;
}
/***********************************
* 用途说明根据id删除角色
* 参数说明
*id 角色id
* 返回值说明: 是否删除成功
***********************************/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteById(String id) {
try {
// 根据id删除角色
boolean isOk = this.removeById(id);
if (!isOk) {
return false;
}
// 删除角色菜单关联
roleMapper.deleteRoleMenus(id);
// 删除角色用户关联
roleMapper.deleteRoleUser(id);
return true;
} catch (Exception e) {
// 可结合日志记录异常信息
LOGGER.error("删除角色失败ID: {}", id, e);
throw e; // 抛出异常以便事务回滚
}
}
/***********************************
* 用途说明根据ID批量删除角色
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteRoleByIds(String ids) {
if (StringUtils.isBlank(ids)) {
// 参数为空直接返回失败
return false;
}
final String SEPARATOR = ",";
List<String> idList = Arrays.asList(ids.split(SEPARATOR));
boolean allSuccess = true;
for (String id : idList) {
if (StringUtils.isBlank(id)) {
// 跳过非法空ID
continue;
}
// 删除角色信息
if (!this.removeById(id)) {
allSuccess = false;
break;
}
// 删除角色菜单关联
roleMapper.deleteRoleMenus(id);
// 删除角色用户关联
roleMapper.deleteRoleUser(id);
}
return allSuccess;
}
/***********************************
* 用途说明角色菜单权限
* 参数说明
* id 角色id
* menuIds 权限id字符串
* 返回值说明: 是否分配成功
***********************************/
@Override
public boolean setMenuByRoleId(String id, String menuIds) {
Role role = roleMapper.selectById(id);
// 删除角色所对应的权限
roleMapper.deleteRoleMenus(id);
// 重新赋予权限
String[] ids = menuIds.split(",");
for (String menuId : ids) {
String uuid = IdUtil.fastSimpleUUID();
roleMapper.addRoleMenu(uuid, role.getAppId(), id, menuId);
}
return true;
}
/***********************************
* 用途说明删除角色用户
* 参数说明
* id 系统角色用户对照表id
* 返回值说明: 是否新增成功
***********************************/
@Override
public boolean deleteRoleUsers(String roleid, String userids) {
boolean ok = true;
//得到单个用户id
String[] temp = userids.split(",");
for (String userid : temp) {
//根据角色id用户id删除 登录账号admin除外
ok = ok && roleMapper.deleteRoleUsers(roleid, userid);
}
return ok;
}
}

View File

@ -0,0 +1,351 @@
package com.stdproject.service.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stdproject.entity.Role;
import com.stdproject.entity.User; // 确保 User 类存在并路径正确
import com.stdproject.mapper.RoleMapper;
import com.stdproject.mapper.UserMapper;
import com.stdproject.service.IUserService; // 确保接口存在
import io.gisbi.utils.AuthUtils;
import io.gisbi.utils.RsaUtils;
import io.micrometer.common.util.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>
* 用户 服务实现类
* </p>
*
* @author lilin
* @since 2025-05-08
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
@Resource
private UserMapper userMapper;
@Resource
private RoleMapper roleMapper;
public static final String DEFAULT_IS_VALID = "1";
//定义密码常量
public static final String PASSWORD_VALID = "123456";
/***********************************
* 用途说明新增系统用户
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务控制
public Map addUser(User user, String roleids) {
//返回信息
Map<String, String> result = new HashMap<>();
//普通用户
//设置缺省密码
String cryptPassword = RsaUtils.encryptStr(PASSWORD_VALID);
user.setPassword(cryptPassword);
//最近修改日期
user.setLastmodifydate(LocalDateTime.now());
//最近修改者
user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
//账号有效 状态 1-有效 0-停用
user.setStatus(DEFAULT_IS_VALID);
//判断注册的登录账号是否存在
if (!isExistAccount(user.getAppId(), StrUtil.trim(user.getUsername()))) {
//新增用户
boolean ok = this.save(user);
//新增用户分配权限
if (StringUtils.isNotEmpty(roleids)) {
String[] roles = roleids.split(",");
for (String roleid : roles) {
//系统生成id
String id = IdUtil.fastSimpleUUID();
//新增app_role_users表数据
ok = ok && userMapper.addUserRoles(id, user.getAppId(), roleid, user.getId());
}
}
//判断新增是否成功 消息提示
if (ok) {
result.put("status", "sucess");
result.put("msg", "新增用户成功!");
} else {
result.put("status", "error");
result.put("msg", "新增用户失败!");
}
} else {
result.put("status", "error");
result.put("msg", "用户账号已存在,不能重复添加!");
}
return result;
}
/***********************************
* 用途说明修改用户信息
* 参数说明
* user 用户对象
* roleids 角色ID
* 返回值说明: 是否新增成功
***********************************/
@Override
@Transactional(rollbackFor = Exception.class)
public Map updateById(User user, String roleids) {
Map<String, String> result = new HashMap<>();
try {
// 设置最近修改人和时间
user.setLastmodifier(AuthUtils.getUser().getUserId().toString());
user.setLastmodifydate(LocalDateTime.now());
//修改用户信息
boolean ok = this.updateById(user);
if (ok) {
//判断角色id是否为空 如果不为空 先删除 后增加 如果为空删除用户下所有角色信息
if (StringUtils.isNotEmpty(roleids)) {
String[] roles = roleids.split(",");
Set<String> roleSet = new HashSet<>(Arrays.asList(roles));
//首先根绝用户ID删除用户角色关联表中的数据
ok = ok && userMapper.delRoleUsersByUserid(user.getId());
// 添加新角色
for (String role : roles) {
//系统生成id
String id = IdUtil.fastSimpleUUID();
ok = ok && userMapper.addUserRoles(id, user.getAppId(), role, user.getId());
}
} else {
// 删除所有关联角色
ok = ok && userMapper.delRoleUsersByUserid(user.getId());
}
result.put("status", "success");
result.put("msg", "用户信息修改成功!");
} else {
result.put("status", "error");
result.put("msg", "用户信息修改失败!");
}
} catch (Exception e) {
// 记录日志
LOGGER.error("用户信息修改过程中发生异常", e);
result.put("status", "error");
result.put("msg", "用户信息修改失败,请稍后再试!");
}
return result;
}
/***********************************
* 用途说明查询用户信息
* 参数说明
* orgid 所属组织ID
* nickname 用户昵称
* page 分页条件
* 返回值说明: 用户信息集合
***********************************/
@Override
public Page<Map<String, Object>> queryUsers(String orgid, String appId, String nickname, Page<User> page) {
//当前用户类型 用户类型 0-管理员 1-普通用户
int usertype = 0;//currentUser.getUsertype();
if (usertype == 0 || usertype == 1) {
//根据条件分页查询用户信息 查询到的用户信息挨个查询角色信息
Page<Map<String, Object>> mapPage = userMapper.queryUsers(orgid, appId, nickname, page);
List<Map<String, Object>> records = mapPage != null ? mapPage.getRecords() : new ArrayList<>();
if (records.isEmpty()) {
return mapPage;
}
List<Map<String, Object>> list = new ArrayList<>(records.size());
//根据用户ID获取对应的角色信息
for (Map<String, Object> record : records) {
Object idObj = record.get("id");
if (idObj == null) {
continue; // 跳过无效记录
}
// 更安全地处理id
String id = idObj.toString();
List<Role> roles = roleMapper.getRoleByUserId(id);
if (roles == null) {
// 防止null值
roles = Collections.emptyList();
}
record.put("roles", roles);
list.add(record);
}
mapPage.setRecords(list);
return mapPage;
} else {
// 明确返回null比返回未初始化的mapPage更好
return null;
}
}
/***********************************
* 用途说明根据id删除用户
* 参数说明
*id 用户id
* 返回值说明: 判断是否删除成功
************************************/
@Override
public Boolean deleteUserById(String id) {
//根据id查询
User user = this.getById(id);
//如果是管理员不能删除
if ("admin".equals(user.getUsername())) {
return false;
} else {
//删除用户及对应的橘色信息
boolean isOk = this.removeById(id);
//判断是否删除成功
if (isOk) {
//根据用户id 删除该用户角色关联
userMapper.delRoleUsersByUserid(id);
return true;
} else {
return false;
}
}
}
/***********************************
* 用途说明根据ID批量删除用户
* 参数说明
*ids 用户id集合
* 返回值说明: 判断是否删除成功
************************************/
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deleteUserByIds(String ids) {
List<String> idList = Arrays.asList(ids.split(","));
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(User::getId, idList);
List<User> sysUsers = userMapper.selectList(queryWrapper);
List<String> names = sysUsers.stream().map(User::getUsername).collect(Collectors.toList());
if (names.contains("admin")) {
return false;
} else {
//批量删除用户
int result = userMapper.deleteBatchIds(idList);
if (result <= 0) {
return false;
}
// 根据ID删除用户与角色的关联信息
userMapper.delRoleUsersByUserIds(idList);
return true;
}
}
/***********************************
* 用途说明重置用户密码(管理员)
* 参数说明
*id 重置密码的 用户id
* 返回值说明: 判断是否重置成功
************************************/
@Override
public boolean resetPassword(String id) {
boolean isOk = false;
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
//根据id 修改密码密码修改时间最近修改者最近修改日期 将密码修改为 123456
String cryptPassword = PASSWORD_VALID;
updateWrapper.eq("id", id).set("password", cryptPassword)
.set("pwdresettime", LocalDateTime.now())
.set("lastmodifydate", LocalDateTime.now())
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
//是否修改成功
isOk = this.update(updateWrapper);
return isOk;
}
/***********************************
* 用途说明设置账号状态(管理员)
* 参数说明
*id 用户id
* status 设置状态
* 返回值说明: 判断是否设置成功
************************************/
@Override
public boolean setStatus(String id, String status) {
boolean isOk = false;
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
//根据id修改用户状态最近修改人最近修改时间
updateWrapper.eq("id", id)
.set("status", status)
.set("lastmodifydate", LocalDateTime.now())
.set("lastmodifier", AuthUtils.getUser().getUserId().toString());
//是否修改成功
isOk = this.update(updateWrapper);
return isOk;
}
/***********************************
* 用途说明角色添加用户
* 参数说明
* roleid 角色id
* userid 用户id
* 返回值说明: 是否新增成功
***********************************/
@Override
public boolean addUserRole(String roleid, String userid) {
boolean isOk = true;
if (StringUtils.isEmpty(roleid) || StringUtils.isEmpty(userid)) {
return false;
}
User user = userMapper.selectById(userid);
//根据角色id与用户id查询
List<Map> list = userMapper.getRoleUsersByid(roleid, userid);
//判断是否用户已分配此权限
if (list.size() == 0) {
//系统生成id
String id = IdUtil.fastSimpleUUID();
//新增app_role_users表数据
isOk = userMapper.addUserRoles(id, user.getAppId(), roleid, userid);
}
return isOk;
}
/***********************************
* 用途说明:比较登录名称是否有重复
* 参数说明
* account 登录名称
* 返回值说明: 重复返回 false 否则返回 true
************************************/
private boolean isExistAccount(String appid, String username) {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
if (this.list(queryWrapper.eq("app_id", appid).eq("username", username)).size() > 0) {
//判断 查询登录账号 结果集是否为null 重复返回 false 否则返回 tree
return true;
} else {
return false;
}
}
}