xp-api/src/main/java/com/xiaopeng/api/factory/operation/RemoteMenuFallbackFactory.java
File was renamed from xp-api/src/main/java/com/xiaopeng/api/factory/RemoteMenuFallbackFactory.java @@ -1,6 +1,6 @@ package com.xiaopeng.api.factory; package com.xiaopeng.api.factory.operation; import com.xiaopeng.api.feign.operation.RemoteMenuService; import com.xiaopeng.api.feignClient.operation.SysMenuClient; import com.xiaopeng.api.model.operation.SysMenu; import com.xiaopeng.common.core.domain.R; import org.slf4j.Logger; @@ -12,17 +12,17 @@ import java.util.List; @Component public class RemoteMenuFallbackFactory implements FallbackFactory<RemoteMenuService> { public class RemoteMenuFallbackFactory implements FallbackFactory<SysMenuClient> { private static final Logger log = LoggerFactory.getLogger(RemoteMenuFallbackFactory.class); @Override public RemoteMenuService create(Throwable cause) { public SysMenuClient create(Throwable cause) { log.error("菜单服务调用失败: {}", cause.getMessage()); return new RemoteMenuService(){ return new SysMenuClient(){ @Override public R<List<SysMenu>> getMenusByMenuIds(List<Long> menuIds, String source) { public R<List<SysMenu>> getMenusByMenuIds(List<Long> menuIds) { log.error("获取菜单列表失败,menuIds: {}, 原因: {}", menuIds, cause.getMessage()); // 降级返回空列表,避免登录失败 return R.ok(new ArrayList<>()); xp-api/src/main/java/com/xiaopeng/api/feign/operation/RemoteMenuService.java
File was deleted xp-api/src/main/java/com/xiaopeng/api/feignClient/account/XpAppUserClient.java
New file @@ -0,0 +1,30 @@ package com.xiaopeng.api.feignClient.account; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.statistics.UserStatisticsDTO; import com.xiaopeng.api.factory.account.XpAppUserClientFallbackFactory; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; /** * 小程序用户Feign客户端 * * @author mitao */ @FeignClient(contextId = "XpAppUserClient", value = ServiceNameConstantsEnum.XP_ACCOUNT_SERVICE, fallbackFactory = XpAppUserClientFallbackFactory.class) public interface XpAppUserClient { /** * 获取用户统计数据 * * @param query 查询参数 * @return 用户统计数据 */ @PostMapping("/inner/appUser/statistics") R<UserStatisticsDTO> getUserStatistics(@RequestBody StatisticsQueryDTO query); } xp-api/src/main/java/com/xiaopeng/api/feignClient/operation/SysMenuClient.java
New file @@ -0,0 +1,31 @@ package com.xiaopeng.api.feignClient.operation; import com.xiaopeng.api.factory.operation.RemoteMenuFallbackFactory; import com.xiaopeng.api.model.operation.SysMenu; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import java.util.List; /** * 菜单服务 * * @author ruoyi */ @FeignClient(contextId = "SysMenuClient", value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, fallbackFactory = RemoteMenuFallbackFactory.class) public interface SysMenuClient { /** * 根据菜单ID列表获取菜单列表 * * @param menuIds 菜单ID列表 * @return 菜单列表 */ @PostMapping("/menu/getMenusByMenuIds") R<List<SysMenu>> getMenusByMenuIds(@RequestBody List<Long> menuIds); } xp-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
New file @@ -0,0 +1,30 @@ package com.xiaopeng.api.feignClient.order; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.factory.order.XpOrderClientFallbackFactory; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; /** * 订单Feign客户端 * * @author mitao */ @FeignClient(contextId = "XpOrderClient", value = ServiceNameConstantsEnum.XP_ORDER_SERVICE, fallbackFactory = XpOrderClientFallbackFactory.class) public interface XpOrderClient { /** * 获取订单统计数据 * * @param query 查询参数 * @return 订单统计数据 */ @PostMapping("/inner/order/statistics") R<OrderStatisticsDTO> getOrderStatistics(@RequestBody StatisticsQueryDTO query); } xp-api/src/main/java/com/xiaopeng/api/model/account/SysRole.java
@@ -1,11 +1,8 @@ package com.xiaopeng.api.model.account; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import java.time.LocalDateTime; import java.io.Serializable; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -43,4 +40,14 @@ @ApiModelProperty(value = "备注") private String remarks; public boolean isAdmin() { return isAdmin(this.id); } public static boolean isAdmin(Long roleId) { return roleId != null && 1L == roleId; } } xp-api/src/main/java/com/xiaopeng/api/model/account/SysRoleBak.java
@@ -25,7 +25,7 @@ /** 角色ID */ @Excel(name = "角色序号", cellType = ColumnType.NUMERIC) @TableField("id") private Long id; private Long roleId; /** 角色名称 */ @Excel(name = "角色名称") @@ -81,22 +81,20 @@ public SysRoleBak(Long id) { this.id = id; this.roleId = id; } public Long getId() { return id; public Long getRoleId() { return roleId; } public void setId(Long id) { this.id = id; public void setRoleId(Long roleId) { this.roleId = roleId; } public boolean isAdmin() { return isAdmin(this.id); return isAdmin(this.roleId); } public static boolean isAdmin(Long roleId) @@ -217,7 +215,7 @@ @Override public String toString() { return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("roleId", getId()) .append("roleId", getRoleId()) .append("roleName", getRoleName()) .append("roleKey", getRoleKey()) .append("dataScope", getDataScope()) xp-api/src/main/java/com/xiaopeng/api/model/account/SysUser.java
@@ -35,18 +35,20 @@ private String userAccount; /** 用户昵称 */ @Excel(name = "用户名称") @Excel(name = "用户昵称") @NotBlank(message = "姓名不能为空") @TableField("nick_name") @ApiModelProperty(value = "用户昵称") private String nickName; /** 手机号码 */ @Excel(name = "手机号码") @NotBlank(message = "请输入账号") @NotBlank(message = "请输入手机号码") @ApiModelProperty(value = "手机号码") private String phoneNumber; /** 用户头像 */ @TableField(exist = false) @ApiModelProperty(value = "用户头像") private String avatar; /** 密码 */ @@ -54,6 +56,7 @@ /** 帐号状态(0正常 1停用) */ @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") @ApiModelProperty(value = "帐号状态 0=正常,1=停用") private String status; @ApiModelProperty(value = "备注") @@ -61,7 +64,7 @@ /** 角色对象 */ @TableField(exist = false) private List<SysRole> roles; private List<SysRoleBak> roles; /** 角色组 */ @TableField(exist = false) @@ -71,8 +74,26 @@ @TableField(exist = false) private Long[] postIds; /** 角色ID */ @TableField(exist = false) @ApiModelProperty(value = "角色ID") private Long roleId; @ApiModelProperty(value = "角色") @TableField(exist = false) private List<String> roleNames; @TableField(exist = false) private Long deptId; public boolean isAdmin() { return isAdmin(this.id); } public static boolean isAdmin(Long userId) { return userId != null && 1L == userId; } } xp-api/src/main/java/com/xiaopeng/api/model/operation/TreeSelect.java
@@ -1,9 +1,10 @@ package com.xiaopeng.api.model.operation; import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; import java.util.List; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonInclude; /** * Treeselect树结构实体类 @@ -38,7 +39,7 @@ public TreeSelect(SysMenuBak menu) { this.id = menu.getId(); this.id = menu.getMenuId(); this.label = menu.getMenuName(); this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList()); } xp-api/src/main/java/com/xiaopeng/api/vo/account/LoginUser.java
@@ -2,10 +2,9 @@ import com.xiaopeng.api.model.account.SysUser; import lombok.Data; import java.awt.*; import java.io.Serializable; import java.util.List; import java.util.Set; /** @@ -13,6 +12,7 @@ * * @author ruoyi */ @Data public class LoginUser implements Serializable { private static final long serialVersionUID = 1L; @@ -50,7 +50,7 @@ /** * 权限列表 */ private List<Menu> permissions; private Set<String> permissions; /** * 角色列表 @@ -66,99 +66,4 @@ */ private String userType; public String getToken() { return token; } public void setToken(String token) { this.token = token; } public Long getUserid() { return userid; } public void setUserid(Long userid) { this.userid = userid; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Long getLoginTime() { return loginTime; } public void setLoginTime(Long loginTime) { this.loginTime = loginTime; } public Long getExpireTime() { return expireTime; } public void setExpireTime(Long expireTime) { this.expireTime = expireTime; } public String getIpaddr() { return ipaddr; } public void setIpaddr(String ipaddr) { this.ipaddr = ipaddr; } public List<Menu> getPermissions() { return permissions; } public void setPermissions(List<Menu> permissions) { this.permissions = permissions; } public Set<String> getRoles() { return roles; } public void setRoles(Set<String> roles) { this.roles = roles; } public SysUser getSysUser() { return sysUser; } public void setSysUser(SysUser sysUser) { this.sysUser = sysUser; } public String getUserType() { return userType; } public void setUserType(String userType) { this.userType = userType; } } xp-common/xp-common-core/src/main/java/com/xiaopeng/common/core/web/page/BasePage.java
@@ -2,6 +2,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * <p></p> @@ -9,43 +10,17 @@ * @author mouseyCat * @date 2020/8/24 16:39 */ @Data @ApiModel(value = "基础查询列表dto") public class BasePage { /** * 分页参数,当前页码 */ @ApiModelProperty(value = "分页参数,当前页码") private Integer pageCurr = 1; private Integer pageNum = 1; /** * 分页参数,每页数量 */ @ApiModelProperty(value = "分页参数,每页数量,默认为10") private Integer pageSize = 50; public Integer getPageCurr() { // if(null != pageCurr){ // pageCurr = (pageCurr - 1) * pageSize; // } return pageCurr; } public void setPageCurr(Integer pageCurr) { this.pageCurr = pageCurr; } public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } @Override public String toString() { return "BasePage{" + "pageCurr=" + pageCurr + ", pageSize=" + pageSize + '}'; } } xp-common/xp-common-datascope/src/main/java/com/xiaopeng/common/datascope/aspect/DataScopeAspect.java
@@ -1,21 +1,20 @@ package com.xiaopeng.common.datascope.aspect; import java.util.ArrayList; import java.util.List; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.api.model.account.SysRoleBak; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.vo.account.LoginUser; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; import com.xiaopeng.common.core.context.SecurityContextHolder; import com.xiaopeng.common.core.text.Convert; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.domain.BaseEntity; import com.xiaopeng.common.datascope.annotation.DataScope; import com.xiaopeng.common.security.utils.SecurityUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import java.util.ArrayList; import java.util.List; /** * 数据过滤处理 @@ -23,7 +22,7 @@ * @author ruoyi */ @Aspect @Component // @Component public class DataScopeAspect { /** @@ -94,7 +93,7 @@ StringBuilder sqlString = new StringBuilder(); List<String> conditions = new ArrayList<String>(); for (SysRole role : user.getRoles()) for (SysRoleBak role : user.getRoles()) { String dataScope = role.getDataScope(); if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope)) @@ -132,7 +131,7 @@ { if (StringUtils.isNotBlank(userAlias)) { sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getId())); } else { xp-service/pom.xml
@@ -40,7 +40,7 @@ <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.0.3</version> <version>5.8.38</version> </dependency> <dependency> <groupId>com.xiaopeng</groupId> xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/SysRoleBakController.java
New file @@ -0,0 +1,256 @@ package com.xiaopeng.account.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.xiaopeng.account.mapper.SysRoleMenuMapper; import com.xiaopeng.account.service.ISysDeptService; import com.xiaopeng.account.service.ISysRoleBakService; import com.xiaopeng.account.service.ISysUserRoleService; import com.xiaopeng.account.service.ISysUserService; import com.xiaopeng.account.vo.RoleAddDto; import com.xiaopeng.account.vo.RoleInfoVo; import com.xiaopeng.account.vo.RoleUpdateDto; import com.xiaopeng.api.model.account.SysRoleBak; import com.xiaopeng.api.model.account.SysRoleMenu; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.model.account.SysUserRole; import com.xiaopeng.api.model.operation.SysDept; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.core.web.page.BasePage; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.core.web.page.TableDataInfo; import com.xiaopeng.common.log.annotation.Log; import com.xiaopeng.common.log.enums.BusinessType; import com.xiaopeng.common.security.annotation.Logical; import com.xiaopeng.common.security.annotation.RequiresPermissions; import com.xiaopeng.common.security.utils.SecurityUtils; import io.seata.spring.annotation.GlobalTransactional; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * 角色信息 * * @author ruoyi */ @RestController @RequestMapping("/role") @Api(tags = "角色模块") public class SysRoleBakController extends BaseController { @Resource private ISysRoleBakService roleService; @Resource private ISysUserService userService; @Resource private ISysDeptService deptService; @Resource private SysRoleMenuMapper sysRoleMenuMapper; @Resource private ISysUserRoleService sysUserRoleService; @RequiresPermissions(value = {"/systemUserManagement", "/systemUserManagement/add", "/systemUserManagement/update", "/roleManagement", "/partners", "/partners/add", "/partners/seleete", "/partners/update"}, logical = Logical.OR) @ApiOperation(value = "获取角色列表", tags = {"管理后台-系统用户管理"}) @GetMapping("/list") public AjaxResult list() { List<SysRoleBak> list = roleService.list(new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getDelFlag, 0).eq(SysRoleBak::getStatus, 0)); return AjaxResult.success(list); } @RequiresPermissions(value = {"/roleManagement"}, logical = Logical.OR) @ResponseBody @GetMapping("/listPage") @ApiOperation(value = "获取角色列表", tags = {"管理后台-角色管理"}) public AjaxResult listPage(String name, BasePage basePage) { PageInfo<SysRoleBak> pageInfo = new PageInfo<>(basePage.getPageNum(), basePage.getPageSize()); LambdaQueryWrapper<SysRoleBak> wrapper = new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getStatus, 0).eq(SysRoleBak::getDelFlag, 0); if (StringUtils.isNotEmpty(name)) { wrapper.like(SysRoleBak::getRoleName, name); } PageInfo<SysRoleBak> page = roleService.page(pageInfo, wrapper.orderByDesc(SysRoleBak::getCreateTime)); for (SysRoleBak record : page.getRecords()) { long count = sysUserRoleService.count(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, record.getId())); record.setNumber(count); } return AjaxResult.success(page); } @RequiresPermissions(value = {"/roleManagement/add"}, logical = Logical.OR) @ResponseBody @PostMapping("/roleAdd") @ApiOperation(value = "添加角色", tags = {"管理后台-角色管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult roleAdd(@Validated @RequestBody RoleAddDto dto) { SysRoleBak role = new SysRoleBak(); role.setRoleName(dto.getRoleName()); long count = roleService.count(Wrappers.lambdaQuery(SysRoleBak.class) .eq(SysRoleBak::getRoleName, dto.getRoleName())); if (count > 0) { return AjaxResult.error("角色已存在,请重新输入"); } List<Long> menuIds1 = dto.getMenuIds(); if (CollectionUtils.isEmpty(menuIds1)) { return AjaxResult.error("菜单id不能为空"); } role.setMenuIds(dto.getMenuIds().toArray((new Long[dto.getMenuIds().size()]))); // 添加角色 role.setRemark(dto.getRemark()); role.setCreateBy(SecurityUtils.getUsername()); role.setCreateTime(new Date()); roleService.insertRole(role); return AjaxResult.success(); } @RequiresPermissions(value = {"/roleManagement/info", "/roleManagement/update"}, logical = Logical.OR) @GetMapping("/roleInfo") @ApiOperation(value = "角色详情", tags = {"管理后台-角色管理"}) public AjaxResult roleInfo(@RequestParam Long id) { SysRoleBak role = roleService.selectRoleById(id); RoleInfoVo roleInfoVo = new RoleInfoVo(); roleInfoVo.setRoleId(role.getId()); roleInfoVo.setRoleName(role.getRoleName()); // 获取当前角色的菜单id List<Long> menusId = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, id)).stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); if (menusId.size() == 0) { return AjaxResult.success(new ArrayList<>()); } //获取当前的权限菜单 // List<SysMenus> all = menuMapper.getAllInIds(menusId); // 第三级 // List<SysMenus> s3 = all.stream().filter(e -> e.getMenuType().equals("F")).collect(Collectors.toList()); // // 第二级 // List<SysMenus> s2 = all.stream().filter(e -> e.getMenuType().equals("C")).collect(Collectors.toList()); // // 第一级 // List<SysMenus> s1 = all.stream().filter(e -> e.getMenuType().equals("M")).collect(Collectors.toList()); // for (SysMenus menus : s2) { // List<SysMenus> collect = s3.stream().filter(e -> e.getParentId().equals(menus.getMenuId())).collect(Collectors.toList()); // menus.setChildren(collect); // } // // for (SysMenus menus : s1) { // List<SysMenus> collect = s2.stream().filter(e -> e.getParentId().equals(menus.getMenuId())).collect(Collectors.toList()); // menus.setChildren(collect); // } roleInfoVo.setMenus(menusId); roleInfoVo.setRemark(role.getRemark()); return AjaxResult.success(roleInfoVo); } @RequiresPermissions(value = {"/roleManagement/update"}, logical = Logical.OR) @PostMapping("/roleUpdate") @ApiOperation(value = "编辑角色", tags = {"管理后台-角色管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult roleUpdate(@Validated @RequestBody RoleUpdateDto dto) { SysRoleBak role = new SysRoleBak(); role.setRoleName(dto.getRoleName()); SysRoleBak one = roleService.getOne(new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getRoleName, dto.getRoleName())); if (null != one && !one.getId().equals(dto.getRoleId())) { return AjaxResult.error("角色已存在,请重新输入"); } role.setRemark(dto.getRemark()); role.setUpdateBy(SecurityUtils.getUsername()); role.setUpdateTime(new Date()); role.setId(dto.getRoleId()); roleService.updateRole(role); ArrayList<SysRoleMenu> sysRoleMenus = new ArrayList<>(); List<Long> menuIds = dto.getMenuIds(); // 移除原来的权限菜单 if (menuIds.contains(1061L)) { sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>() .eq(SysRoleMenu::getRoleId, dto.getRoleId())); } else { sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>() .eq(SysRoleMenu::getRoleId, dto.getRoleId()) .ne(SysRoleMenu::getMenuId, 1061L) .ne(SysRoleMenu::getMenuId, 1062L) .ne(SysRoleMenu::getMenuId, 1065L) .ne(SysRoleMenu::getMenuId, 1073L) .ne(SysRoleMenu::getMenuId, 1161L) .ne(SysRoleMenu::getMenuId, 1203L) ); } for (Long menuId : menuIds) { SysRoleMenu sysRoleMenu = new SysRoleMenu(); sysRoleMenu.setMenuId(menuId); sysRoleMenu.setRoleId(role.getId()); sysRoleMenus.add(sysRoleMenu); } sysRoleMenuMapper.batchRoleMenu(sysRoleMenus); return AjaxResult.success(); } /** * 删除角色 */ @RequiresPermissions(value = {"/roleManagement/del"}, logical = Logical.OR) @Log(title = "角色管理", businessType = BusinessType.DELETE) @DeleteMapping("/{roleIds}") @ApiOperation(value = "删除角色", tags = {"管理后台-角色管理"}) public AjaxResult remove(@PathVariable Long[] roleIds) { return toAjax(roleService.deleteRoleByIds(roleIds)); } /** * 查询已分配用户角色列表 */ @RequiresPermissions("/roleManagement") @GetMapping("/authUser/allocatedList") public TableDataInfo allocatedList(SysUser user) { startPage(); List<SysUser> list = userService.selectAllocatedList(user); return getDataTable(list); } /** * 查询未分配用户角色列表 */ @RequiresPermissions("/roleManagement") @GetMapping("/authUser/unallocatedList") public TableDataInfo unallocatedList(SysUser user) { startPage(); List<SysUser> list = userService.selectUnallocatedList(user); return getDataTable(list); } /** * 获取对应角色部门树列表 */ @RequiresPermissions("") @GetMapping(value = "/deptTree/{roleId}") public AjaxResult deptTree(@PathVariable("roleId") Long roleId) { AjaxResult ajax = AjaxResult.success(); ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); return ajax; } } xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/SysRoleController.java
@@ -1,252 +1,68 @@ package com.xiaopeng.account.controller; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.stream.Collectors; import javax.annotation.Resource; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.page.BasePage; import com.xiaopeng.account.model.dto.SysRoleAddDTO; import com.xiaopeng.account.model.dto.SysRoleEditDTO; import com.xiaopeng.account.model.query.SysRolePageQuery; import com.xiaopeng.account.model.vo.SysRoleDetailVO; import com.xiaopeng.account.model.vo.SysRolePageVO; import com.xiaopeng.account.service.ISysRoleService; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.annotation.Logical; import com.xiaopeng.account.mapper.SysRoleMenuMapper; import com.xiaopeng.account.service.ISysDeptService; import com.xiaopeng.account.service.ISysRoleBakService; import com.xiaopeng.account.service.ISysUserRoleService; import com.xiaopeng.account.service.ISysUserService; import com.xiaopeng.account.vo.RoleAddDto; import com.xiaopeng.account.vo.RoleInfoVo; import com.xiaopeng.account.vo.RoleUpdateDto;import com.xiaopeng.api.model.account.*; import com.xiaopeng.api.model.operation.SysDept; import com.xiaopeng.api.model.operation.SysMenus;import io.seata.spring.annotation.GlobalTransactional; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.util.CollectionUtils; import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.core.web.page.TableDataInfo; import com.xiaopeng.common.log.annotation.Log; import com.xiaopeng.common.log.enums.BusinessType; import com.xiaopeng.common.security.annotation.RequiresPermissions; import com.xiaopeng.common.security.utils.SecurityUtils; /** * 角色信息 * <p> * 角色管理 前端控制器 * </p> * * @author ruoyi * @author mitao * @since 2026-02-03 */ @Api(tags = "角色管理") @RequiredArgsConstructor(onConstructor_ = @Lazy) @RestController @RequestMapping("/role") @Api(tags = "角色模块") public class SysRoleController extends BaseController { @Resource private ISysRoleBakService roleService; @Resource private ISysUserService userService; @Resource private ISysDeptService deptService; @Resource private SysRoleMenuMapper sysRoleMenuMapper; @Resource private ISysUserRoleService sysUserRoleService; public class SysRoleController { private final ISysRoleService sysRoleService; @ApiOperation("新增角色") @PostMapping("/api/v1/role/add") public R<?> add(@Validated @RequestBody SysRoleAddDTO dto) { sysRoleService.addRole(dto); return R.ok(); } @RequiresPermissions(value = {"/systemUserManagement", "/systemUserManagement/add", "/systemUserManagement/update", "/roleManagement", "/partners", "/partners/add", "/partners/seleete", "/partners/update"}, logical = Logical.OR) @ApiOperation(value = "获取角色列表", tags = {"管理后台-系统用户管理"}) @GetMapping("/list") public AjaxResult list() { List<SysRoleBak> list = roleService.list(new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getDelFlag, 0).eq(SysRoleBak::getStatus, 0)); return AjaxResult.success(list); } @RequiresPermissions(value = {"/roleManagement"}, logical = Logical.OR) @ResponseBody @GetMapping("/listPage") @ApiOperation(value = "获取角色列表", tags = {"管理后台-角色管理"}) public AjaxResult listPage(String name, BasePage basePage) { PageInfo<SysRoleBak> pageInfo = new PageInfo<>(basePage.getPageCurr(), basePage.getPageSize()); LambdaQueryWrapper<SysRoleBak> wrapper = new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getStatus, 0).eq(SysRoleBak::getDelFlag, 0); if (StringUtils.isNotEmpty(name)) { wrapper.like(SysRoleBak::getRoleName, name); } PageInfo<SysRoleBak> page = roleService.page(pageInfo, wrapper.orderByDesc(SysRoleBak::getCreateTime)); for (SysRoleBak record : page.getRecords()) { long count = sysUserRoleService.count(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, record.getId())); record.setNumber(count); } return AjaxResult.success(page); } @RequiresPermissions(value = {"/roleManagement/add"}, logical = Logical.OR) @ResponseBody @PostMapping("/roleAdd") @ApiOperation(value = "添加角色", tags = {"管理后台-角色管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult roleAdd(@Validated @RequestBody RoleAddDto dto) { SysRoleBak role = new SysRoleBak(); role.setRoleName(dto.getRoleName()); long count = roleService.count(Wrappers.lambdaQuery(SysRoleBak.class) .eq(SysRoleBak::getRoleName, dto.getRoleName())); if (count > 0) { return AjaxResult.error("角色已存在,请重新输入"); } List<Long> menuIds1 = dto.getMenuIds(); if (CollectionUtils.isEmpty(menuIds1)) { return AjaxResult.error("菜单id不能为空"); } role.setMenuIds(dto.getMenuIds().toArray((new Long[dto.getMenuIds().size()]))); // 添加角色 role.setRemark(dto.getRemark()); role.setCreateBy(SecurityUtils.getUsername()); role.setCreateTime(new Date()); roleService.insertRole(role); return AjaxResult.success(); } @RequiresPermissions(value = {"/roleManagement/info", "/roleManagement/update"}, logical = Logical.OR) @GetMapping("/roleInfo") @ApiOperation(value = "角色详情", tags = {"管理后台-角色管理"}) public AjaxResult roleInfo(@RequestParam Long id) { SysRoleBak role = roleService.selectRoleById(id); RoleInfoVo roleInfoVo = new RoleInfoVo(); roleInfoVo.setRoleId(role.getId()); roleInfoVo.setRoleName(role.getRoleName()); // 获取当前角色的菜单id List<Long> menusId = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, id)).stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList()); if (menusId.size() == 0) { return AjaxResult.success(new ArrayList<>()); } //获取当前的权限菜单 List<SysMenus> all = menuMapper.getAllInIds(menusId); // 第三级 List<SysMenus> s3 = all.stream().filter(e -> e.getMenuType().equals("F")).collect(Collectors.toList()); // 第二级 List<SysMenus> s2 = all.stream().filter(e -> e.getMenuType().equals("C")).collect(Collectors.toList()); // 第一级 List<SysMenus> s1 = all.stream().filter(e -> e.getMenuType().equals("M")).collect(Collectors.toList()); for (SysMenus menus : s2) { List<SysMenus> collect = s3.stream().filter(e -> e.getParentId().equals(menus.getMenuId())).collect(Collectors.toList()); menus.setChildren(collect); } for (SysMenus menus : s1) { List<SysMenus> collect = s2.stream().filter(e -> e.getParentId().equals(menus.getMenuId())).collect(Collectors.toList()); menus.setChildren(collect); } roleInfoVo.setMenus(menusId); roleInfoVo.setRemark(role.getRemark()); return AjaxResult.success(roleInfoVo); } @RequiresPermissions(value = {"/roleManagement/update"}, logical = Logical.OR) @PostMapping("/roleUpdate") @ApiOperation(value = "编辑角色", tags = {"管理后台-角色管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult roleUpdate(@Validated @RequestBody RoleUpdateDto dto) { SysRoleBak role = new SysRoleBak(); role.setRoleName(dto.getRoleName()); SysRoleBak one = roleService.getOne(new LambdaQueryWrapper<SysRoleBak>().eq(SysRoleBak::getRoleName, dto.getRoleName())); if (null != one && !one.getId().equals(dto.getRoleId())) { return AjaxResult.error("角色已存在,请重新输入"); } role.setRemark(dto.getRemark()); role.setUpdateBy(SecurityUtils.getUsername()); role.setUpdateTime(new Date()); role.setId(dto.getRoleId()); roleService.updateRole(role); ArrayList<SysRoleMenu> sysRoleMenus = new ArrayList<>(); List<Long> menuIds = dto.getMenuIds(); // 移除原来的权限菜单 if (menuIds.contains(1061L)) { sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>() .eq(SysRoleMenu::getRoleId, dto.getRoleId())); } else { sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>() .eq(SysRoleMenu::getRoleId, dto.getRoleId()) .ne(SysRoleMenu::getMenuId, 1061L) .ne(SysRoleMenu::getMenuId, 1062L) .ne(SysRoleMenu::getMenuId, 1065L) .ne(SysRoleMenu::getMenuId, 1073L) .ne(SysRoleMenu::getMenuId, 1161L) .ne(SysRoleMenu::getMenuId, 1203L) ); } for (Long menuId : menuIds) { SysRoleMenu sysRoleMenu = new SysRoleMenu(); sysRoleMenu.setMenuId(menuId); sysRoleMenu.setRoleId(role.getId()); sysRoleMenus.add(sysRoleMenu); } sysRoleMenuMapper.batchRoleMenu(sysRoleMenus); return AjaxResult.success(); } /** * 删除角色 */ @RequiresPermissions(value = {"/roleManagement/del"}, logical = Logical.OR) @Log(title = "角色管理", businessType = BusinessType.DELETE) @DeleteMapping("/{roleIds}") @ApiOperation(value = "删除角色", tags = {"管理后台-角色管理"}) public AjaxResult remove(@PathVariable Long[] roleIds) { return toAjax(roleService.deleteRoleByIds(roleIds)); } /** * 查询已分配用户角色列表 */ @RequiresPermissions("/roleManagement") @GetMapping("/authUser/allocatedList") public TableDataInfo allocatedList(SysUser user) { startPage(); List<SysUser> list = userService.selectAllocatedList(user); return getDataTable(list); } /** * 查询未分配用户角色列表 */ @RequiresPermissions("/roleManagement") @GetMapping("/authUser/unallocatedList") public TableDataInfo unallocatedList(SysUser user) { startPage(); List<SysUser> list = userService.selectUnallocatedList(user); return getDataTable(list); } /** * 获取对应角色部门树列表 */ @RequiresPermissions("") @GetMapping(value = "/deptTree/{roleId}") public AjaxResult deptTree(@PathVariable("roleId") Long roleId) { AjaxResult ajax = AjaxResult.success(); ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); return ajax; } @ApiOperation("编辑角色") @PostMapping("/api/v1/role/edit") public R<?> edit(@Validated @RequestBody SysRoleEditDTO dto) { sysRoleService.editRole(dto); return R.ok(); } @ApiOperation("角色详情") @GetMapping("/api/v1/role/queryById") public R<SysRoleDetailVO> queryById(@ApiParam(value = "角色id", required = true) @RequestParam Long id) { SysRoleDetailVO detail = sysRoleService.getRoleDetail(id); return R.ok(detail); } @ApiOperation("角色分页列表") @PostMapping("/api/v1/role/pageList") public R<PageInfo<SysRolePageVO>> pageList(@Validated @RequestBody SysRolePageQuery query) { PageInfo<SysRolePageVO> pageInfo = sysRoleService.pageList(query); return R.ok(pageInfo); } @ApiOperation("删除角色") @DeleteMapping("/api/v1/role/delete/{id}") public R<?> delete(@ApiParam(value = "角色id", required = true) @PathVariable Long id) { sysRoleService.deleteRole(id); return R.ok(); } } xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/SysUserController.java
@@ -1,36 +1,39 @@ package com.xiaopeng.account.controller; import java.util.*; import java.util.stream.Collectors; import javax.annotation.Resource; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.service.TokenService; import com.xiaopeng.common.security.annotation.Logical; import com.xiaopeng.account.model.dto.UserPwdResetDTO; import com.xiaopeng.account.model.query.SysUserListQuery; import com.xiaopeng.account.service.*; import com.xiaopeng.account.vo.GetSysUserList; import com.xiaopeng.account.vo.ShopUserStart; import com.xiaopeng.api.model.account.SysUserRole; import com.xiaopeng.api.model.operation.SysDept; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.api.model.account.SysRoleBak; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.model.account.SysUserRole; import com.xiaopeng.api.model.operation.SysDept; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.log.annotation.Log; import com.xiaopeng.common.log.enums.BusinessType; import com.xiaopeng.common.security.annotation.Logical; import com.xiaopeng.common.security.annotation.RequiresPermissions; import com.xiaopeng.common.security.service.TokenService; import com.xiaopeng.common.security.utils.SecurityUtils; import io.seata.spring.annotation.GlobalTransactional; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import org.apache.commons.lang3.ArrayUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.core.web.domain.AjaxResult; import com.xiaopeng.common.log.annotation.Log; import com.xiaopeng.common.log.enums.BusinessType; import com.xiaopeng.common.security.annotation.RequiresPermissions; import com.xiaopeng.common.security.utils.SecurityUtils; import javax.annotation.Resource; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; /** * 用户信息 @@ -38,15 +41,15 @@ * @author ruoyi */ @RestController @RequestMapping("/user") @Api(tags = "用户信息") public class SysUserController extends BaseController { @Resource private ISysUserService userService; @Resource private ISysRoleBakService roleService; private ISysRoleBakService roleBakService; @Resource private ISysRoleService sysRoleService; @Resource private ISysDeptService deptService; @@ -64,11 +67,11 @@ * 获取用户列表 */ @RequiresPermissions(value = {"/systemUserManagement", "/roleManagement/info"}, logical = Logical.OR) @GetMapping("/list") @ApiOperation(value = "获取系统用户列表", tags = {"管理后台-系统用户管理", "管理后台-角色管理"}) public AjaxResult list(GetSysUserList getSysUserList) { PageInfo<SysUser> pageInfo = new PageInfo<>(getSysUserList.getPageCurr(), getSysUserList.getPageSize()); PageInfo<SysUser> page = userService.getList(pageInfo, getSysUserList); @GetMapping("/api/v1/sys-user/pageList") @ApiOperation(value = "账号管理分页列表", tags = {"管理后台-账号管理"}) public AjaxResult<PageInfo<SysUser>> list(SysUserListQuery sysUserListQuery) { PageInfo<SysUser> pageInfo = new PageInfo<>(sysUserListQuery.getPageNum(), sysUserListQuery.getPageSize()); PageInfo<SysUser> page = userService.getList(pageInfo, sysUserListQuery); return AjaxResult.success(page); } @@ -78,25 +81,25 @@ * 新增用户 */ @RequiresPermissions(value = {"/systemUserManagement/add"}, logical = Logical.OR) @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping("/add") @ApiOperation(value = "添加系统用户", tags = {"管理后台-系统用户管理"}) @Log(title = "帐号管理", businessType = BusinessType.INSERT) @PostMapping("/api/v1/sys-user/add") @ApiOperation(value = "添加帐号", tags = {"管理后台-帐号管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult add(@RequestBody SysUser user) { user.setUserName(user.getPhonenumber()); if(!org.springframework.util.StringUtils.hasLength(user.getNickName())){ user.setNickName(user.getPhonenumber()); } if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { if (StringUtils.isNotEmpty(user.getPhoneNumber()) && !userService.checkPhoneUnique(user)) { return error("手机号已开通账号"); } if (StringUtils.isNotEmpty(user.getUserName()) && !userService.checkUserNameUnique(user)) { if (StringUtils.isNotEmpty(user.getUserAccount()) && !userService.checkUserNameUnique(user)) { return error("登录账号重复"); } //校验编号是否唯一 Long count = userService.lambdaQuery().eq(SysUser::getUniqueNumber, user.getUniqueNumber()).count(); if (count > 0) { return error("用户编号已存在"); } user.setCreateBy(SecurityUtils.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); user.setRoleType(1); user.setPassWordUpdate(new Date()); //TODO 手机号脱敏存储 userService.insertUser(user); SysUserRole sysUserRole = new SysUserRole(); sysUserRole.setRoleId(user.getRoleId()); @@ -111,7 +114,7 @@ @ApiOperation(value = "校验账号是否重复", tags = {"管理后台-系统用户管理"}) public AjaxResult verifyUserNameRepeat(@PathVariable String username){ SysUser user = new SysUser(); user.setUserName(username); user.setUserAccount(username); if (StringUtils.isNotEmpty(username) && !userService.checkUserNameUnique(user)) { return error("账号不可重复"); } @@ -127,18 +130,18 @@ * 根据用户编号获取详细信息 */ @ApiOperation(value = "获取用户详情", tags = {"管理后台-系统用户管理"}) @GetMapping("/getInfo/{userId}") @GetMapping("/api/v1/getInfo/{userId}") public AjaxResult getInfo(@PathVariable Long userId) { userService.checkUserDataScope(userId); AjaxResult ajax = AjaxResult.success(); List<SysRoleBak> roles = roleService.selectRoleAll(); List<SysRole> roles = sysRoleService.list(); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); ajax.put("posts", postService.selectPostAll()); if (StringUtils.isNotNull(userId)) { SysUser sysUser = userService.selectUserById(userId); ajax.put(AjaxResult.DATA_TAG, sysUser); ajax.put("postIds", postService.selectPostListByUserId(userId)); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRoleBak::getId).collect(Collectors.toList())); ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getId).collect(Collectors.toList())); } return AjaxResult.success(ajax); } @@ -148,15 +151,11 @@ * 修改用户 */ @RequiresPermissions(value = {"/systemUserManagement/update"}, logical = Logical.OR) @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/update") @ApiOperation(value = "编辑系统用户", tags = {"管理后台-系统用户管理"}) @Log(title = "帐号管理", businessType = BusinessType.UPDATE) @PutMapping("/api/v1/sys-user/edit") @ApiOperation(value = "编辑帐号", tags = {"管理后台-帐号管理"}) @GlobalTransactional(rollbackFor = Exception.class)//分布式事务 public AjaxResult edit(@Validated @RequestBody SysUser user) { user.setUserName(user.getPhonenumber()); if(!org.springframework.util.StringUtils.hasLength(user.getNickName())){ user.setNickName(user.getPhonenumber()); } R<Integer> admin = this.isAdmin(user.getId()); Integer data = admin.getData(); if(data == null || data != 1){ @@ -167,30 +166,23 @@ userService.checkUserAllowed(user); userService.checkUserDataScope(user.getId()); SysUser sysUser = userService.getOne(Wrappers.lambdaQuery(SysUser.class) .eq(SysUser::getPhonenumber, user.getPhonenumber()) .eq(SysUser::getDelFlag,0) .eq(SysUser::getPhoneNumber, user.getPhoneNumber()) .last("LIMIT 1")); if (StringUtils.isNotEmpty(user.getPhonenumber()) && (Objects.nonNull(sysUser) && !user.getId().equals(sysUser.getId()) )) { if (StringUtils.isNotEmpty(user.getPhoneNumber()) && (Objects.nonNull(sysUser) && !user.getId().equals(sysUser.getId()) )) { return error("手机号已开通账号"); } sysUser = userService.getOne(Wrappers.lambdaQuery(SysUser.class) .eq(SysUser::getUserName, user.getUserName()) .eq(SysUser::getDelFlag,0) .eq(SysUser::getUserAccount, user.getUserAccount()) .last("LIMIT 1")); if (StringUtils.isNotEmpty(user.getUserName()) && (Objects.nonNull(sysUser) && !user.getId().equals(sysUser.getId()) )) { if (StringUtils.isNotEmpty(user.getUserAccount()) && (Objects.nonNull(sysUser) && !user.getId().equals(sysUser.getId()) )) { return error("登录账号重复"); } user.setUpdateBy(SecurityUtils.getUsername()); if (user.getPassword() != null && !"".equals(user.getPassword())) { if (user.getPassword() != null && !user.getPassword().isEmpty()) { user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); user.setPassWordUpdate(new Date()); } if (user.getPhonenumber() != null) { user.setUserName(user.getPhonenumber()); } user.setUpdateBy(SecurityUtils.getUsername()); user.setUpdateTime(new Date()); userService.updateUser(user); //删除旧的角色数据,添加新的角色 @@ -209,9 +201,9 @@ * 删除用户 */ @RequiresPermissions(value = {"/systemUserManagement/del"}, logical = Logical.OR) @Log(title = "用户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{userIds}") @ApiOperation(value = "删除系统用户", tags = {"管理后台-系统用户管理"}) @Log(title = "帐号管理", businessType = BusinessType.DELETE) @DeleteMapping("/api/v1/sys-user/{userIds}") @ApiOperation(value = "删除账号", tags = {"管理后台-帐号管理"}) public AjaxResult remove(@PathVariable Long[] userIds) { if (ArrayUtils.contains(userIds, tokenService.getLoginUser())) { return error("当前用户不能删除"); @@ -223,21 +215,16 @@ @RequiresPermissions(value = {"/systemUserManagement/forbidden"}, logical = Logical.OR) @PostMapping("/shopUserStart") @ApiOperation(value = "账号管理--禁用/启用", tags = {"管理后台-系统用户管理"}) public AjaxResult shopUserStart(@RequestBody ShopUserStart shopUserStart) { if (shopUserStart.getUserId() == null) { return AjaxResult.error("userId不能为空"); } SysUser sysUser = userService.selectUserById(shopUserStart.getUserId()); @PostMapping("/api/v1/sys-user/switchStatus/{id}") @ApiOperation(value = "账号管理--禁用/启用", tags = {"管理后台-帐号管理"}) public AjaxResult shopUserStart(@ApiParam(name = "id", value = "帐号ID") @PathVariable("id") Long id) { SysUser sysUser = userService.selectUserById(id); if (sysUser.getStatus().equals("0")) { sysUser.setStatus("1"); sysUser.setForbiddenRemark(shopUserStart.getRemark()); } else { sysUser.setStatus("0"); sysUser.setForbiddenRemark(""); } return toAjax(userService.updateUser(sysUser)); return toAjax(userService.updateById(sysUser)); } @@ -271,7 +258,6 @@ public R<Boolean> updateSysUser(@RequestBody SysUser sysUser) { try { sysUser.setUpdateBy(SecurityUtils.getUsername()); sysUser.setUpdateTime(new Date()); userService.updateUser(sysUser); if(null != sysUser.getRoleId()){ sysUserRoleService.deleteSysUserRoleByUserId(sysUser.getId()); @@ -298,10 +284,14 @@ * 重置密码 */ @RequiresPermissions(value = {"/systemUserManagement/reset_passwords"}, logical = Logical.OR) @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/resetPwd") @ApiOperation(value = "重置密码", tags = {"管理后台-系统用户管理"}) public AjaxResult resetPwd(@RequestBody SysUser user) { @Log(title = "帐号管理", businessType = BusinessType.UPDATE) @PutMapping("/api/v1/sys-user/rePassword") @ApiOperation(value = "重置密码", tags = {"管理后台-帐号管理"}) public AjaxResult resetPwd(@RequestBody UserPwdResetDTO dto) { SysUser user = userService.getById(dto.getUserId()); if (Objects.isNull(user)) { throw new ServiceException("用户不存在"); } userService.checkUserAllowed(user); userService.checkUserDataScope(user.getId()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); @@ -328,7 +318,7 @@ public AjaxResult authRole(@PathVariable("userId") Long userId) { AjaxResult ajax = AjaxResult.success(); SysUser user = userService.selectUserById(userId); List<SysRoleBak> roles = roleService.selectRolesByUserId(userId); List<SysRoleBak> roles = roleBakService.selectRolesByUserId(userId); ajax.put("user", user); ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); return ajax; @@ -364,14 +354,14 @@ * @return */ @PostMapping("/queryRoleByUserId/{userId}") public R<SysRoleBak> queryRoleByUserId(@PathVariable("userId") Long userId){ public R<SysRole> queryRoleByUserId(@PathVariable("userId") Long userId){ SysUserRole one = sysUserRoleService.getOne(Wrappers.lambdaQuery(SysUserRole.class) .eq(SysUserRole::getUserId, userId) .last("LIMIT 1")); System.out.println("通过用户id查询角色对象"+one); if(Objects.nonNull(one)){ SysRoleBak byId = roleService.getOne(Wrappers.lambdaQuery(SysRoleBak.class) .eq(SysRoleBak::getId,one.getRoleId()) SysRole byId = sysRoleService.getOne(Wrappers.lambdaQuery(SysRole.class) .eq(SysRole::getId,one.getRoleId()) .last("LIMIT 1")); return R.ok(byId); } @@ -380,9 +370,9 @@ @PostMapping("/queryRoleByRoleId/{roleId}") public R<SysRoleBak> queryRoleByRoleId(@PathVariable("roleId") Long roleId){ return R.ok( roleService.getOne(Wrappers.lambdaQuery(SysRoleBak.class) .eq(SysRoleBak::getId, roleId) public R<SysRole> queryRoleByRoleId(@PathVariable("roleId") Long roleId){ return R.ok( sysRoleService.getOne(Wrappers.lambdaQuery(SysRole.class) .eq(SysRole::getId, roleId) .last("LIMIT 1"))); } @@ -394,8 +384,7 @@ @PostMapping("/queryUserByPhoneList") public R<List<SysUser>> queryUserByPhoneList(@RequestBody List<String> phoneList){ List<SysUser> list = userService.list(Wrappers.lambdaQuery(SysUser.class) .in(SysUser::getPhonenumber, phoneList) .ne(SysUser::getDelFlag,2)); .in(SysUser::getPhoneNumber, phoneList)); return R.ok(list); } @@ -408,7 +397,7 @@ @PostMapping("/queryUserByPhone") public R<SysUser> queryUserByPhone(@RequestBody String phone){ SysUser user = userService.getOne(Wrappers.lambdaQuery(SysUser.class) .eq(SysUser::getPhonenumber, phone) .eq(SysUser::getPhoneNumber, phone) .last("LIMIT 1")); return R.ok(user); } @@ -423,7 +412,7 @@ @PostMapping("/queryUserByUserName") public R<SysUser> queryUserByUserName(@RequestBody String userName){ SysUser user = userService.getOne(Wrappers.lambdaQuery(SysUser.class) .eq(SysUser::getUserName, userName) .eq(SysUser::getUserAccount, userName) .last("LIMIT 1")); return R.ok(user); } @@ -437,24 +426,14 @@ @PostMapping("/addSysUser") @Transactional(rollbackFor = Exception.class) public R<Long> addSysUser(@RequestBody SysUser user) { if(StringUtils.isEmpty(user.getUserName())){ user.setUserName(user.getPhonenumber()); } if(!org.springframework.util.StringUtils.hasLength(user.getNickName())){ user.setNickName(user.getPhonenumber()); } // if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { // throw new RuntimeException("手机号已开通账号"); // } if (StringUtils.isNotEmpty(user.getUserName()) && !userService.checkUserNameUnique(user)) { if (StringUtils.isNotEmpty(user.getUserAccount()) && !userService.checkUserNameUnique(user)) { throw new RuntimeException("登录账号已存在"); } user.setCreateBy(SecurityUtils.getUsername()); user.setPassword(SecurityUtils.encryptPassword(user.getPassword())); if(null == user.getRoleType()){ user.setRoleType(1); } user.setPassWordUpdate(new Date()); userService.insertUser(user); SysUserRole sysUserRole = new SysUserRole(); sysUserRole.setRoleId(user.getRoleId()); xp-service/xp-account/src/main/java/com/xiaopeng/account/controller/XpAppUserController.java
@@ -1,9 +1,16 @@ package com.xiaopeng.account.controller; import com.xiaopeng.account.service.IXpAppUserService; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.statistics.UserStatisticsDTO; import com.xiaopeng.common.core.domain.R; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import javax.annotation.Resource; /** * <p> @@ -13,8 +20,22 @@ * @author mitao * @since 2026-02-03 */ @Controller @RequestMapping("/xp-app-user") @RestController @Api(tags = "小程序用户") public class XpAppUserController { @Resource private IXpAppUserService xpAppUserService; /** * 获取用户统计数据(内部接口) * * @param query 查询参数 * @return 用户统计数据 */ @ApiOperation(value = "获取用户统计数据", tags = {"内部接口"}) @PostMapping("/inner/appUser/statistics") public R<UserStatisticsDTO> getUserStatistics(@RequestBody StatisticsQueryDTO query) { return R.ok(xpAppUserService.getUserStatistics(query)); } } xp-service/xp-account/src/main/java/com/xiaopeng/account/mapper/SysRoleMapper.java
@@ -2,6 +2,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.model.account.SysRole; import org.apache.ibatis.annotations.Param; /** * <p> @@ -13,4 +14,11 @@ */ public interface SysRoleMapper extends BaseMapper<SysRole> { /** * 统计绑定该角色的用户数 * * @param roleId 角色ID * @return 绑定用户数 */ Long countBindUsers(@Param("roleId") Long roleId); } xp-service/xp-account/src/main/java/com/xiaopeng/account/mapper/SysUserMapper.java
@@ -1,14 +1,14 @@ package com.xiaopeng.account.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.account.model.query.SysUserListQuery; import com.xiaopeng.account.vo.ChangeUserQuery; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.common.core.web.page.PageInfo; import org.apache.ibatis.annotations.Param; import java.util.ArrayList; import java.util.List; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.account.vo.ChangeUserQuery; import com.xiaopeng.account.vo.GetSysUserList; import com.xiaopeng.api.model.account.SysUser; import org.apache.ibatis.annotations.Param; /** * 用户表 数据层 @@ -133,7 +133,7 @@ */ public SysUser checkEmailUnique(String email); List<SysUser> getList(@Param("pageInfo") PageInfo<SysUser> pageInfo, @Param("req") GetSysUserList getSysUserList); PageInfo<SysUser> getList(@Param("pageInfo") PageInfo<SysUser> pageInfo, @Param("req") SysUserListQuery sysUserListQuery); PageInfo<SysUser> getAllList(@Param("pageInfo") PageInfo<SysUser> pageInfo, @Param("ids") List<Integer> collect); xp-service/xp-account/src/main/java/com/xiaopeng/account/mapper/XpAppUserMapper.java
@@ -1,7 +1,12 @@ package com.xiaopeng.account.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.model.account.XpAppUser; import org.apache.ibatis.annotations.Param; import java.time.LocalDate; import java.util.List; /** * <p> @@ -13,4 +18,21 @@ */ public interface XpAppUserMapper extends BaseMapper<XpAppUser> { /** * 统计时间范围内新增用户数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 新增用户数 */ Long countNewUsers(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); /** * 获取每日新增用户数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 每日统计列表 */ List<DailyCountDTO> getDailyUserCount(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); } xp-service/xp-account/src/main/java/com/xiaopeng/account/model/dto/SysRoleAddDTO.java
New file @@ -0,0 +1,29 @@ package com.xiaopeng.account.model.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * 角色新增请求 * * @author mitao */ @Data @ApiModel(value = "角色新增请求", description = "新增角色请求参数") public class SysRoleAddDTO { @ApiModelProperty(value = "权限组id", required = true) @NotNull(message = "权限组id不能为空") private Long groupId; @ApiModelProperty(value = "角色名称", required = true) @NotBlank(message = "角色名称不能为空") private String roleName; @ApiModelProperty(value = "备注") private String remarks; } xp-service/xp-account/src/main/java/com/xiaopeng/account/model/dto/SysRoleEditDTO.java
New file @@ -0,0 +1,23 @@ package com.xiaopeng.account.model.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.NotNull; /** * 角色编辑请求 * * @author mitao */ @Data @EqualsAndHashCode(callSuper = true) @ApiModel(value = "角色编辑请求", description = "编辑角色请求参数") public class SysRoleEditDTO extends SysRoleAddDTO { @ApiModelProperty(value = "角色ID", required = true) @NotNull(message = "角色ID不能为空") private Long id; } xp-service/xp-account/src/main/java/com/xiaopeng/account/model/dto/UserPwdResetDTO.java
New file @@ -0,0 +1,26 @@ package com.xiaopeng.account.model.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author MiTao * @date 2026-02-04 17:14 * */ @Data @ApiModel("用户密码重置DTO") public class UserPwdResetDTO { @NotNull(message = "用户ID不能为空") @ApiModelProperty("用户ID") private Long userId; @NotBlank(message = "新密码不能为空") @ApiModelProperty(value = "新密码") private String newPassword; } xp-service/xp-account/src/main/java/com/xiaopeng/account/model/query/SysRolePageQuery.java
New file @@ -0,0 +1,21 @@ package com.xiaopeng.account.model.query; import com.xiaopeng.common.core.web.page.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; /** * 角色分页查询请求 * * @author mitao */ @Data @EqualsAndHashCode(callSuper = true) @ApiModel(value = "角色分页查询请求", description = "角色分页查询参数") public class SysRolePageQuery extends BasePage { @ApiModelProperty(value = "角色名称") private String roleName; } xp-service/xp-account/src/main/java/com/xiaopeng/account/model/query/SysUserListQuery.java
New file @@ -0,0 +1,27 @@ package com.xiaopeng.account.model.query; import com.xiaopeng.common.core.web.page.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** * @author zhibing.pu * @Date 2024/8/10 14:10 */ @Data @ApiModel public class SysUserListQuery extends BasePage { @ApiModelProperty(value = "用户名称") private String nickName; @ApiModelProperty(value = "电话号码") private String phoneNumber; @ApiModelProperty(value = "角色id") private Long roleId; @ApiModelProperty(value = "账户状态(0=正常,1=禁用)") private Integer status; } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/ISysRoleService.java
@@ -1,7 +1,13 @@ package com.xiaopeng.account.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.account.model.dto.SysRoleAddDTO; import com.xiaopeng.account.model.dto.SysRoleEditDTO; import com.xiaopeng.account.model.query.SysRolePageQuery; import com.xiaopeng.account.model.vo.SysRoleDetailVO; import com.xiaopeng.account.model.vo.SysRolePageVO; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.common.core.web.page.PageInfo; import java.util.Set; @@ -30,4 +36,50 @@ * @return 角色权限集合 */ Set<String> selectRolePermissionByUserId(Long userId); /** * 新增角色 * * @param dto 新增角色请求 */ void addRole(SysRoleAddDTO dto); /** * 编辑角色 * * @param dto 编辑角色请求 */ void editRole(SysRoleEditDTO dto); /** * 获取角色详情(含菜单树) * * @param id 角色ID * @return 角色详情 */ SysRoleDetailVO getRoleDetail(Long id); /** * 角色分页列表 * * @param query 分页查询参数 * @return 分页结果 */ PageInfo<SysRolePageVO> pageList(SysRolePageQuery query); /** * 删除角色(逻辑删除) * * @param id 角色ID */ void deleteRole(Long id); /** * 校验角色名称唯一性 * * @param roleName 角色名称 * @param excludeId 排除的角色ID(编辑时使用) * @return true=唯一,false=不唯一 */ boolean checkRoleNameUnique(String roleName, Long excludeId); } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/ISysUserService.java
@@ -1,11 +1,11 @@ package com.xiaopeng.account.service; import java.util.List; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.account.vo.GetSysUserList; import com.xiaopeng.account.model.query.SysUserListQuery; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.common.core.web.page.PageInfo; import java.util.List; /** * 用户 业务层 @@ -124,5 +124,5 @@ */ int deleteUserByIds(Long[] userIds); PageInfo<SysUser> getList(PageInfo<SysUser> pageInfo, GetSysUserList getSysUserList); PageInfo<SysUser> getList(PageInfo<SysUser> pageInfo, SysUserListQuery sysUserListQuery); } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/IXpAppUserService.java
@@ -1,6 +1,8 @@ package com.xiaopeng.account.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.statistics.UserStatisticsDTO; import com.xiaopeng.api.model.account.XpAppUser; /** @@ -13,4 +15,11 @@ */ public interface IXpAppUserService extends IService<XpAppUser> { /** * 获取用户统计数据 * * @param query 查询参数 * @return 用户统计数据 */ UserStatisticsDTO getUserStatistics(StatisticsQueryDTO query); } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysLoginService.java
@@ -1,20 +1,18 @@ package com.xiaopeng.account.service.impl; import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ; import com.xiaopeng.api.dto.operation.UpdatePasswordDTO; import com.xiaopeng.account.service.ISysPermissionService; import com.xiaopeng.account.service.ISysUserService; import com.xiaopeng.account.service.XpOperationsUserService; import com.xiaopeng.api.dto.operation.UpdatePasswordDTO; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.api.model.operation.SysMenu; import com.xiaopeng.api.vo.account.LoginOperationUser; import com.xiaopeng.api.vo.account.LoginUser; import com.xiaopeng.common.core.constant.VerificationCodeConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.constant.Constants; import com.xiaopeng.common.core.constant.UserConstants; import com.xiaopeng.common.core.constant.VerificationCodeConstants; import com.xiaopeng.common.core.enums.UserStatus; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.text.Convert; @@ -22,11 +20,14 @@ import com.xiaopeng.common.core.utils.ip.IpUtils; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.common.security.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.Set; import java.util.stream.Collectors; /** * 登录校验方法 @@ -71,7 +72,7 @@ LoginUser userInfo = new LoginUser(); userInfo.setSysUser(user); userInfo.setRoles(roles); userInfo.setPermissions(menuPermission); userInfo.setPermissions(menuPermission.stream().map(SysMenu::getPath).collect(Collectors.toSet())); if (StringUtils.isNull(user)) { recordLogService.recordLogininfor(request, null, username, Constants.LOGIN_FAIL_STATUS, "登录用户不存在"); xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysPermissionServiceImpl.java
@@ -4,19 +4,16 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import com.xiaopeng.account.service.ISysGroupMenuService; import com.xiaopeng.account.service.ISysPermissionService; import com.xiaopeng.account.service.ISysRoleService; import com.xiaopeng.account.service.ISysUserRoleService; import com.xiaopeng.api.feign.operation.RemoteMenuService; import com.xiaopeng.api.feignClient.operation.SysMenuClient; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.model.account.SysUserRole; import com.xiaopeng.api.model.operation.SysMenu; import com.xiaopeng.common.core.constant.SecurityConstants; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.utils.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -42,7 +39,7 @@ private ISysGroupMenuService groupMenuService; @Autowired private RemoteMenuService remoteMenuService; private SysMenuClient sysMenuClient; /** * 获取角色数据权限 @@ -104,7 +101,7 @@ } // 4. 通过 Feign 调用 operation 服务,根据 menuId 列表获取菜单列表 R<List<SysMenu>> result = remoteMenuService.getMenusByMenuIds(menuIds); R<List<SysMenu>> result = sysMenuClient.getMenusByMenuIds(menuIds); if (R.isSuccess(result) && result.getData() != null) { menus = result.getData(); } else { xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysRoleServiceImpl.java
@@ -1,18 +1,35 @@ package com.xiaopeng.account.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.account.mapper.SysRoleMapper; import com.xiaopeng.account.model.dto.SysRoleAddDTO; import com.xiaopeng.account.model.dto.SysRoleEditDTO; import com.xiaopeng.account.model.query.SysRolePageQuery; import com.xiaopeng.account.model.vo.SysMenuVO; import com.xiaopeng.account.model.vo.SysRoleDetailVO; import com.xiaopeng.account.model.vo.SysRolePageVO; import com.xiaopeng.account.service.ISysGroupMenuService; import com.xiaopeng.account.service.ISysRoleService; import com.xiaopeng.account.service.ISysUserRoleService; import com.xiaopeng.api.feignClient.operation.SysMenuClient; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.api.model.account.SysUserRole; import com.xiaopeng.api.model.operation.SysMenu; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import com.xiaopeng.common.core.web.page.PageInfo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.HashSet; import java.util.Set; import java.util.*; import java.util.stream.Collectors; /** * <p> @@ -22,11 +39,16 @@ * @author mitao * @since 2026-02-03 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService { @Autowired private ISysUserRoleService userRoleService; private final ISysUserRoleService userRoleService; private final ISysGroupMenuService groupMenuService; private final SysMenuClient sysMenuClient; /** * 根据角色ID查询权限组ID @@ -70,4 +92,244 @@ return roles; } /** * 新增角色 * * @param dto 新增角色请求 */ @Override public void addRole(SysRoleAddDTO dto) { // 校验角色名称唯一性 if (!checkRoleNameUnique(dto.getRoleName(), null)) { throw new ServiceException("角色名称已存在"); } // 创建角色实体 SysRole role = new SysRole(); role.setGroupId(dto.getGroupId()); role.setRoleName(dto.getRoleName()); role.setRemarks(dto.getRemarks()); // 保存角色 this.save(role); } /** * 编辑角色 * * @param dto 编辑角色请求 */ @Override public void editRole(SysRoleEditDTO dto) { // 校验角色是否存在 SysRole existRole = this.getById(dto.getId()); if (existRole == null) { throw new ServiceException("角色不存在"); } // 校验角色名称唯一性(排除自身) if (!checkRoleNameUnique(dto.getRoleName(), dto.getId())) { throw new ServiceException("角色名称已存在"); } // 更新角色信息 existRole.setGroupId(dto.getGroupId()); existRole.setRoleName(dto.getRoleName()); existRole.setRemarks(dto.getRemarks()); this.updateById(existRole); } /** * 获取角色详情(含菜单树) * * @param id 角色ID * @return 角色详情 */ @Override public SysRoleDetailVO getRoleDetail(Long id) { // 查询角色基础信息 SysRole role = this.getById(id); if (role == null) { throw new ServiceException("角色不存在"); } SysRoleDetailVO vo = BeanUtil.toBean(role, SysRoleDetailVO.class); // 根据权限组ID获取菜单ID列表 List<Long> menuIds = groupMenuService.selectMenuIdsByGroupId(role.getGroupId()); if (CollectionUtils.isEmpty(menuIds)) { vo.setMenus(new ArrayList<>()); return vo; } // 通过Feign调用获取菜单详情 try { R<List<SysMenu>> result = sysMenuClient.getMenusByMenuIds(menuIds); if (result != null && result.getData() != null) { List<SysMenu> menus = result.getData(); // 构建菜单树 vo.setMenus(buildMenuTree(menus)); } else { vo.setMenus(new ArrayList<>()); } } catch (Exception e) { log.error("获取菜单列表失败: {}", e.getMessage()); vo.setMenus(new ArrayList<>()); } return vo; } /** * 角色分页列表 * * @param query 分页查询参数 * @return 分页结果 */ @Override public PageInfo<SysRolePageVO> pageList(SysRolePageQuery query) { // 构建查询条件 LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>(); if (StringUtils.isNotBlank(query.getRoleName())) { wrapper.like(SysRole::getRoleName, query.getRoleName()); } wrapper.orderByDesc(SysRole::getCreateTime); // 分页查询 PageInfo<SysRole> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); PageInfo<SysRole> rolePage = this.page(pageInfo, wrapper); // 转换为VO PageInfo<SysRolePageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize()); resultPage.setTotal(rolePage.getTotal()); List<SysRolePageVO> voList = rolePage.getRecords().stream().map(role -> { SysRolePageVO vo = new SysRolePageVO(); vo.setId(role.getId()); vo.setGroupId(role.getGroupId()); vo.setRoleName(role.getRoleName()); vo.setRemarks(role.getRemarks()); vo.setCreateTime(role.getCreateTime()); // 统计绑定用户数 Long bindCount = baseMapper.countBindUsers(role.getId()); vo.setBindCount(bindCount); return vo; }).collect(Collectors.toList()); resultPage.setRecords(voList); return resultPage; } /** * 删除角色(逻辑删除) * * @param id 角色ID */ @Override public void deleteRole(Long id) { // 校验角色是否存在 SysRole role = this.getById(id); if (role == null) { throw new ServiceException("角色不存在"); } // 检查是否有用户绑定该角色 Long bindCount = baseMapper.countBindUsers(id); if (bindCount != null && bindCount > 0) { throw new ServiceException("该角色已绑定用户,无法删除"); } // 逻辑删除 this.removeById(id); } /** * 校验角色名称唯一性 * * @param roleName 角色名称 * @param excludeId 排除的角色ID(编辑时使用) * @return true=唯一,false=不唯一 */ @Override public boolean checkRoleNameUnique(String roleName, Long excludeId) { LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SysRole::getRoleName, roleName); if (excludeId != null) { wrapper.ne(SysRole::getId, excludeId); } return this.count(wrapper) == 0; } /** * 构建菜单树 * * @param menus 菜单列表 * @return 菜单树 */ private List<SysMenuVO> buildMenuTree(List<SysMenu> menus) { if (CollectionUtils.isEmpty(menus)) { return new ArrayList<>(); } Map<Long, SysMenuVO> menuMap = new HashMap<>(); List<SysMenuVO> rootMenus = new ArrayList<>(); // 转换为VO并建立映射 for (SysMenu menu : menus) { SysMenuVO vo = convertToMenuVO(menu); vo.setChildren(new ArrayList<>()); menuMap.put(vo.getId(), vo); } // 构建树结构 for (SysMenuVO vo : menuMap.values()) { if (vo.getParentId() == null || vo.getParentId() == 0) { rootMenus.add(vo); } else { SysMenuVO parent = menuMap.get(vo.getParentId()); if (parent != null) { parent.getChildren().add(vo); } else { // 父节点不在列表中,作为根节点处理 rootMenus.add(vo); } } } // 按orderNum排序 sortMenuTree(rootMenus); return rootMenus; } /** * 转换为菜单VO * * @param menu 菜单实体 * @return 菜单VO */ private SysMenuVO convertToMenuVO(SysMenu menu) { SysMenuVO vo = new SysMenuVO(); BeanUtils.copyProperties(menu, vo); return vo; } /** * 递归排序菜单树 * * @param menus 菜单列表 */ private void sortMenuTree(List<SysMenuVO> menus) { if (CollectionUtils.isEmpty(menus)) { return; } menus.sort(Comparator.comparing(SysMenuVO::getOrderNum, Comparator.nullsLast(Comparator.naturalOrder()))); for (SysMenuVO menu : menus) { if (!CollectionUtils.isEmpty(menu.getChildren())) { sortMenuTree(menu.getChildren()); } } } } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/SysUserServiceImpl.java
@@ -9,7 +9,7 @@ import com.xiaopeng.account.mapper.SysUserMapper; import com.xiaopeng.account.mapper.SysUserRoleMapper; import com.xiaopeng.account.service.ISysUserService; import com.xiaopeng.account.vo.GetSysUserList; import com.xiaopeng.account.model.query.SysUserListQuery; import com.xiaopeng.api.model.account.SysUser; import com.xiaopeng.api.model.account.SysUserRole; import org.slf4j.Logger; @@ -19,8 +19,8 @@ import javax.annotation.Resource; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; /** * 用户 业务层处理 @@ -164,9 +164,7 @@ // insertUserPost(user); // // 新增用户与角色管理 // insertUserRole(user); user.setCreateTime(new Date()); user.setCreateBy(tokenService.getLoginUser().getUsername()); user.setUpdateTime(new Date()); user.setUpdateBy(tokenService.getLoginUser().getUsername()); return userMapper.insert(user); } @@ -248,15 +246,17 @@ @Transactional(rollbackFor = Exception.class) public int deleteUserByIds(Long[] userIds) { for (Long userId : userIds) { checkUserAllowed(new SysUser(userId)); SysUser sysUser = new SysUser(); sysUser.setId(userId); checkUserAllowed(sysUser); } return userMapper.deleteUserByIds(userIds); } @Override public PageInfo<SysUser> getList(PageInfo<SysUser> pageInfo, GetSysUserList getSysUserList) { return null; public PageInfo<SysUser> getList(PageInfo<SysUser> pageInfo, SysUserListQuery sysUserListQuery) { return userMapper.getList(pageInfo, sysUserListQuery); } } xp-service/xp-account/src/main/java/com/xiaopeng/account/service/impl/XpAppUserServiceImpl.java
@@ -3,8 +3,15 @@ import com.xiaopeng.account.mapper.XpAppUserMapper; import com.xiaopeng.account.service.IXpAppUserService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.statistics.UserStatisticsDTO; import com.xiaopeng.api.model.account.XpAppUser; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; /** * <p> @@ -17,4 +24,27 @@ @Service public class XpAppUserServiceImpl extends ServiceImpl<XpAppUserMapper, XpAppUser> implements IXpAppUserService { @Override public UserStatisticsDTO getUserStatistics(StatisticsQueryDTO query) { UserStatisticsDTO dto = new UserStatisticsDTO(); // 1. 查询用户总数 dto.setTotalCount(baseMapper.selectCount(null)); // 2. 查询时间范围内新增用户数 if (query.getStartDate() != null && query.getEndDate() != null) { dto.setNewCount(baseMapper.countNewUsers(query.getStartDate(), query.getEndDate())); } else { dto.setNewCount(0L); } // 3. 查询近N天每日新增用户数(默认30天) Integer trendDays = query.getTrendDays() != null ? query.getTrendDays() : 30; LocalDate endDate = LocalDate.now(); LocalDate startDate = endDate.minusDays(trendDays - 1); List<DailyCountDTO> dailyCountList = baseMapper.getDailyUserCount(startDate, endDate); dto.setDailyCountList(dailyCountList != null ? dailyCountList : new ArrayList<>()); return dto; } } xp-service/xp-account/src/main/java/com/xiaopeng/account/vo/GetSysUserList.java
File was deleted xp-service/xp-account/src/main/resources/mapper/account/SysRoleMapper.xml
@@ -2,4 +2,13 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.account.mapper.SysRoleMapper"> <!-- 统计绑定该角色的用户数 --> <select id="countBindUsers" resultType="java.lang.Long"> SELECT COUNT(*) FROM sys_user_role sur left join sys_user su on su.id = sur.user_id WHERE role_id = #{roleId} and su.is_deleted = 0 </select> </mapper> xp-service/xp-account/src/main/resources/mapper/account/SysUserMapper.xml
@@ -124,27 +124,21 @@ <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult"> select user_id, email from sys_user where email = #{email} and del_flag = '0' limit 1 </select> <select id="getList" resultMap="SysUserResult"> select * from sys_user where 1=1 <if test="req.search !=null and req.search !=''"> and (phonenumber like concat("%", #{req.search},"%") or nick_name like concat("%", #{req.search},"%")) <select id="getList" resultMap="SysUserResult"> select su.*,sr.role_name from sys_user su left join sys_user_role sur on su.id= sur.user_id left join sys_role sr on sr.id = sur.role_id where 1=1 <if test="req.nickname !=null and req.nickname !=''"> and nick_name like concat("%", #{req.nickname},"%") </if> <if test="null != req.siteId"> and user_id in (select user_id from t_user_site where site_id = #{req.siteId}) and user_id in (select user_id from sys_user_role where role_id in (select role_id from t_role_site where site_id = #{req.siteId})) <if test="null != req.roleId"> and sur.role_id = #{req.roleId} </if> <if test="null != req.roleIds and req.roleIds.size() > 0"> and user_id in (select user_id from sys_user_role where role_id in <foreach collection="req.roleIds" item="item" index="index" open="(" separator="," close=")"> #{item} </foreach> ) </if> <if test="null != req.status"> and status = #{req.status} and su.status = #{req.status} </if> and del_flag = '0' and roleType =1 order by create_time desc and su.is_deleted = 0 order by su.create_time desc </select> <select id="getAllList" resultType="com.ruoyi.system.api.domain.SysUser"> select *,user_id userId,nick_name userName ,create_time createTime ,login_date loginDate from sys_user where roleType=3 and user_id in xp-service/xp-account/src/main/resources/mapper/account/XpAppUserMapper.xml
@@ -7,4 +7,24 @@ id, nick_name, avatar, phone_number, gender, open_id, is_deleted, create_time, update_time, create_by, update_by </sql> <!-- 统计时间范围内新增用户数 --> <select id="countNewUsers" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_app_user WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} </select> <!-- 获取每日新增用户数 --> <select id="getDailyUserCount" resultType="com.xiaopeng.api.dto.statistics.DailyCountDTO"> SELECT DATE_FORMAT(create_time, '%Y-%m-%d') as date, COUNT(*) as count FROM xp_app_user WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} GROUP BY DATE(create_time) ORDER BY date ASC </select> </mapper> xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/controller/IndexController.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.maintenance.controller; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.maintenance.dto.IndexDataQuery; import com.xiaopeng.maintenance.service.IndexDataService; import com.xiaopeng.maintenance.vo.IndexDataVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; /** * 首页 Controller * * @author mitao */ @Slf4j @RestController @Api(tags = "管理后台-首页") public class IndexController { @Resource private IndexDataService indexDataService; @ApiOperation(value = "首页数据统计", tags = {"管理后台-首页"}) @PostMapping("/base/v1/indexData") public R<IndexDataVO> indexData(@RequestBody(required = false) IndexDataQuery query) { if (query == null) { query = new IndexDataQuery(); } return R.ok(indexDataService.getIndexData(query)); } } xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpFleetMapper.java
@@ -1,7 +1,12 @@ package com.xiaopeng.maintenance.mapper; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.model.maintenance.XpFleet; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDate; import java.util.List; /** * <p> @@ -13,4 +18,21 @@ */ public interface XpFleetMapper extends BaseMapper<XpFleet> { /** * 统计时间范围内新增车队数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 新增车队数 */ Long countNewFleets(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); /** * 获取每日新增车队数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 每日统计列表 */ List<DailyCountDTO> getDailyFleetCount(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); } xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/mapper/XpVehicleMapper.java
@@ -1,7 +1,12 @@ package com.xiaopeng.maintenance.mapper; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.model.maintenance.XpVehicle; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; import java.time.LocalDate; import java.util.List; /** * <p> @@ -13,4 +18,35 @@ */ public interface XpVehicleMapper extends BaseMapper<XpVehicle> { /** * 统计在线车辆数(operatingStatus=1 运营中) * * @return 在线车辆数 */ Long countOnlineVehicles(); /** * 统计运行车辆数(operatingStatus=1 运营中) * * @return 运行车辆数 */ Long countRunningVehicles(); /** * 统计时间范围内新增车辆数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 新增车辆数 */ Long countNewVehicles(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); /** * 获取每日新增车辆数 * * @param startDate 开始日期 * @param endDate 结束日期 * @return 每日统计列表 */ List<DailyCountDTO> getDailyVehicleCount(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); } xp-service/xp-maintenance/src/main/java/com/xiaopeng/maintenance/vo/IndexDataVO.java
New file @@ -0,0 +1,67 @@ package com.xiaopeng.maintenance.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; /** * 首页数据统计VO * * @author mitao */ @Data @ApiModel(value = "首页数据统计VO") public class IndexDataVO { // ==================== 今日运行情况 ==================== @ApiModelProperty(value = "今日运行情况-新增用户数") private Long newUserCount; @ApiModelProperty(value = "今日运行情况-新增车辆数量") private Long vehicleCount; @ApiModelProperty(value = "今日运行情况-新增订单数量") private Long orderCount; // ==================== 运营总数据 ==================== @ApiModelProperty(value = "运营总数据-用户总数") private Long totalUserCount; @ApiModelProperty(value = "运营总数据-车队数量") private Long fleetCount; @ApiModelProperty(value = "运营总数据-车辆数量") private Long totalVehicleCount; @ApiModelProperty(value = "运营总数据-订单数量") private Long totalOrderCount; @ApiModelProperty(value = "运营总数据-总交易金额") private Long totalMoney; @ApiModelProperty(value = "运营总数据-总收入") private Long totalIncome; // ==================== 运营数据增长 ==================== @ApiModelProperty(value = "运营数据增长-用户增长数") private Long userGrowthCount; @ApiModelProperty(value = "运营数据增长-车辆增长数") private Long vehicleGrowthCount; @ApiModelProperty(value = "运营数据增长-订单增长数") private Long orderGrowthCount; // ==================== 运营总趋势(近30天) ==================== @ApiModelProperty(value = "运营总趋势-订单趋势图(近30天每日订单数)") private List<Long> orderCountList; @ApiModelProperty(value = "运营总趋势-用户注册趋势图(近30天每日用户注册数)") private List<Long> userCountList; } xp-service/xp-maintenance/src/main/resources/mapper/maintenance/SysMenuClient.xml
xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpFleetMapper.xml
@@ -2,4 +2,24 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.maintenance.mapper.XpFleetMapper"> <!-- 统计时间范围内新增车队数 --> <select id="countNewFleets" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_fleet WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} </select> <!-- 获取每日新增车队数 --> <select id="getDailyFleetCount" resultType="com.xiaopeng.api.dto.statistics.DailyCountDTO"> SELECT DATE_FORMAT(create_time, '%Y-%m-%d') as date, COUNT(*) as count FROM xp_fleet WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} GROUP BY DATE(create_time) ORDER BY date ASC </select> </mapper> xp-service/xp-maintenance/src/main/resources/mapper/maintenance/XpVehicleMapper.xml
@@ -2,4 +2,40 @@ <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.maintenance.mapper.XpVehicleMapper"> <!-- 统计在线车辆数(operatingStatus=1 运营中) --> <select id="countOnlineVehicles" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_vehicle WHERE is_deleted = 0 AND operating_status = 1 </select> <!-- 统计运行车辆数(operatingStatus=1 运营中) --> <select id="countRunningVehicles" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_vehicle WHERE is_deleted = 0 AND operating_status = 1 </select> <!-- 统计时间范围内新增车辆数 --> <select id="countNewVehicles" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_vehicle WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} </select> <!-- 获取每日新增车辆数 --> <select id="getDailyVehicleCount" resultType="com.xiaopeng.api.dto.statistics.DailyCountDTO"> SELECT DATE_FORMAT(create_time, '%Y-%m-%d') as date, COUNT(*) as count FROM xp_vehicle WHERE is_deleted = 0 AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} GROUP BY DATE(create_time) ORDER BY date ASC </select> </mapper> xp-service/xp-operation/src/main/java/com/xiaopeng/operation/controller/IndexController.java
File was deleted xp-service/xp-operation/src/main/java/com/xiaopeng/operation/vo/IndexDataVO.java
File was deleted xp-service/xp-order/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -1,9 +1,16 @@ package com.xiaopeng.order.controller; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.order.service.IXpOrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import javax.annotation.Resource; /** * <p> @@ -13,8 +20,22 @@ * @author mitao * @since 2026-02-03 */ @Controller @RequestMapping("/xp-order") @RestController @Api(tags = "订单") public class XpOrderController { @Resource private IXpOrderService xpOrderService; /** * 获取订单统计数据(内部接口) * * @param query 查询参数 * @return 订单统计数据 */ @ApiOperation(value = "获取订单统计数据", tags = {"内部接口"}) @PostMapping("/inner/order/statistics") public R<OrderStatisticsDTO> getOrderStatistics(@RequestBody StatisticsQueryDTO query) { return R.ok(xpOrderService.getOrderStatistics(query)); } } xp-service/xp-order/src/main/java/com/xiaopeng/order/mapper/XpOrderMapper.java
@@ -1,7 +1,13 @@ package com.xiaopeng.order.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.model.order.XpOrder; import org.apache.ibatis.annotations.Param; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; /** * <p> @@ -13,4 +19,35 @@ */ public interface XpOrderMapper extends BaseMapper<XpOrder> { /** * 统计已完成订单总数(状态9=待评价或10=已完成) * * @return 订单总数 */ Long countCompletedOrders(); /** * 统计时间范围内新增订单数(状态9或10) * * @param startDate 开始日期 * @param endDate 结束日期 * @return 新增订单数 */ Long countNewOrders(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); /** * 统计总交易金额(pay_money累加,状态9或10) * * @return 总交易金额 */ BigDecimal sumTotalMoney(); /** * 获取每日新增订单数(状态9或10) * * @param startDate 开始日期 * @param endDate 结束日期 * @return 每日统计列表 */ List<DailyCountDTO> getDailyOrderCount(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate); } xp-service/xp-order/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -1,6 +1,8 @@ package com.xiaopeng.order.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.model.order.XpOrder; /** @@ -13,4 +15,11 @@ */ public interface IXpOrderService extends IService<XpOrder> { /** * 获取订单统计数据 * * @param query 查询参数 * @return 订单统计数据 */ OrderStatisticsDTO getOrderStatistics(StatisticsQueryDTO query); } xp-service/xp-order/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -1,10 +1,18 @@ package com.xiaopeng.order.service.impl; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.order.mapper.XpOrderMapper; import com.xiaopeng.order.service.IXpOrderService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; /** * <p> @@ -17,4 +25,32 @@ @Service public class XpOrderServiceImpl extends ServiceImpl<XpOrderMapper, XpOrder> implements IXpOrderService { @Override public OrderStatisticsDTO getOrderStatistics(StatisticsQueryDTO query) { OrderStatisticsDTO dto = new OrderStatisticsDTO(); // 1. 查询订单总数(状态为9=待评价或10=已完成) dto.setTotalCount(baseMapper.countCompletedOrders()); // 2. 查询时间范围内新增订单数 if (query.getStartDate() != null && query.getEndDate() != null) { dto.setNewCount(baseMapper.countNewOrders(query.getStartDate(), query.getEndDate())); } else { dto.setNewCount(0L); } // 3. 查询总交易金额和总收入(pay_money累加) BigDecimal totalMoney = baseMapper.sumTotalMoney(); dto.setTotalMoney(totalMoney != null ? totalMoney : BigDecimal.ZERO); dto.setTotalIncome(totalMoney != null ? totalMoney : BigDecimal.ZERO); // 4. 查询近N天每日新增订单数(默认30天) Integer trendDays = query.getTrendDays() != null ? query.getTrendDays() : 30; LocalDate endDate = LocalDate.now(); LocalDate startDate = endDate.minusDays(trendDays - 1); List<DailyCountDTO> dailyCountList = baseMapper.getDailyOrderCount(startDate, endDate); dto.setDailyCountList(dailyCountList != null ? dailyCountList : new ArrayList<>()); return dto; } } xp-service/xp-order/src/main/resources/mapper/order/XpOrderMapper.xml
@@ -7,4 +7,42 @@ id, app_user_id, vehicle_id, fleet_id, order_number, transaction_id, order_source, ride_time, placement_lon, placement_lat, placement_address, start_lon, start_lat, end_lon, end_lat, start_address, end_address, boarding_lon, boarding_lat, boarding_address, boarding_time, getoff_lon, getoff_lat, getoff_address, getoff_time, pay_type, order_money, pay_money, prepay_money, start_mileage, start_money, mileage_kilometers, mileage_money, duration, duration_money, wait, wait_money, long_distance, long_distanceMoney, red_packet_money, coupon_money, red_packet_id, coupon_id, status, is_deleted, create_time, update_time, create_by, update_by </sql> <!-- 统计已完成订单总数(状态9=待评价或10=已完成) --> <select id="countCompletedOrders" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_order WHERE is_deleted = 0 AND status IN (9, 10) </select> <!-- 统计时间范围内新增订单数 --> <select id="countNewOrders" resultType="java.lang.Long"> SELECT COUNT(*) FROM xp_order WHERE is_deleted = 0 AND status IN (9, 10) AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} </select> <!-- 统计总交易金额(pay_money累加,状态9或10) --> <select id="sumTotalMoney" resultType="java.math.BigDecimal"> SELECT COALESCE(SUM(pay_money), 0) FROM xp_order WHERE is_deleted = 0 AND status IN (9, 10) </select> <!-- 获取每日新增订单数 --> <select id="getDailyOrderCount" resultType="com.xiaopeng.api.dto.statistics.DailyCountDTO"> SELECT DATE_FORMAT(create_time, '%Y-%m-%d') as date, COUNT(*) as count FROM xp_order WHERE is_deleted = 0 AND status IN (9, 10) AND DATE(create_time) BETWEEN #{startDate} AND #{endDate} GROUP BY DATE(create_time) ORDER BY date ASC </select> </mapper>