Merge branch 'master' of https://gitee.com/youlaiorg/youlai-boot into feature/noticews

# Conflicts:
#	src/main/java/com/youlai/boot/platform/websocket/service/impl/WebsocketServiceImpl.java
#	src/main/java/com/youlai/boot/system/controller/NoticeController.java
#	src/main/java/com/youlai/boot/system/controller/NoticeStatusController.java
#	src/main/java/com/youlai/boot/system/converter/NoticeConverter.java
#	src/main/java/com/youlai/boot/system/converter/NoticeStatusConverter.java
#	src/main/java/com/youlai/boot/system/mapper/NoticeMapper.java
#	src/main/java/com/youlai/boot/system/mapper/NoticeStatusMapper.java
#	src/main/java/com/youlai/boot/system/model/entity/Notice.java
#	src/main/java/com/youlai/boot/system/model/entity/NoticeStatus.java
#	src/main/java/com/youlai/boot/system/model/form/NoticeForm.java
#	src/main/java/com/youlai/boot/system/model/form/NoticeStatusForm.java
#	src/main/java/com/youlai/boot/system/model/query/NoticeQuery.java
#	src/main/java/com/youlai/boot/system/model/query/NoticeStatusQuery.java
#	src/main/java/com/youlai/boot/system/model/vo/NoticeStatusVO.java
#	src/main/java/com/youlai/boot/system/model/vo/NoticeVO.java
#	src/main/java/com/youlai/boot/system/service/NoticeService.java
#	src/main/java/com/youlai/boot/system/service/NoticeStatusService.java
#	src/main/java/com/youlai/boot/system/service/impl/NoticeServiceImpl.java
#	src/main/java/com/youlai/boot/system/service/impl/NoticeStatusServiceImpl.java
This commit is contained in:
Theo committed 2024-08-31 20:10:54 +08:00
commit 55ec7673fd
252 files changed
+1338 -1267

No files matched your search

@@ -0,0 +1,81 @@
package com.youlai.boot.system.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.system.model.form.ConfigForm;
import com.youlai.boot.system.model.query.ConfigPageQuery;
import com.youlai.boot.system.model.vo.ConfigVO;
import com.youlai.boot.system.service.ConfigService;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
/**
* 系统配置前端控制层
*
* @author Theo
* @since 2024-07-30 11:25
*/
@Slf4j
@RestController
@RequiredArgsConstructor
@Tag(name = "10.系统配置")
@RequestMapping("/api/v1/config")
public class ConfigController {
private final ConfigService configService;
@GetMapping("/page")
@Operation(summary = "系统配置分页列表")
@PreAuthorize("@ss.hasPerm('sys:config:query')")
public PageResult<ConfigVO> page(@ParameterObject ConfigPageQuery configPageQuery) {
IPage<ConfigVO> result = configService.page(configPageQuery);
return PageResult.success(result);
}
@Operation(summary = "新增系统配置")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:config:add')")
public Result<?> save(@RequestBody @Valid ConfigForm configForm) {
return Result.judge(configService.save(configForm));
}
@Operation(summary = "获取系统配置表单数据")
@GetMapping("/{id}/form")
public Result<ConfigForm> getConfigForm(
@Parameter(description = "系统配置ID") @PathVariable Long id
) {
ConfigForm formData = configService.getConfigFormData(id);
return Result.success(formData);
}
@Operation(summary = "刷新系统配置缓存")
@PatchMapping
@PreAuthorize("@ss.hasPerm('sys:config:refresh')")
public Result<ConfigForm> refreshCache() {
return Result.judge(configService.refreshCache());
}
@PutMapping(value = "/{id}")
@Operation(summary = "修改系统配置")
@PreAuthorize("@ss.hasPerm('sys:config:update')")
public Result<?> update(@Valid @PathVariable Long id, @RequestBody ConfigForm configForm) {
return Result.judge(configService.edit(id, configForm));
}
@DeleteMapping("/{id}")
@Operation(summary = "删除系统配置")
@PreAuthorize("@ss.hasPerm('sys:config:delete')")
public Result<?> delete(@PathVariable Long id) {
return Result.judge(configService.delete(id));
}
}
@@ -0,0 +1,94 @@
package com.youlai.boot.system.controller;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.system.model.form.DeptForm;
import com.youlai.boot.system.model.query.DeptQuery;
import com.youlai.boot.system.model.vo.DeptVO;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.system.service.DeptService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
* 部门控制器
*
* @author haoxr
* @since 2020/11/6
*/
@Tag(name = "05.部门接口")
@RestController
@RequestMapping("/api/v1/dept")
@RequiredArgsConstructor
public class DeptController {
private final DeptService deptService;
@Operation(summary = "部门列表")
@GetMapping
@Log( value = "部门列表",module = LogModuleEnum.DEPT)
public Result<List<DeptVO>> getDeptList(
DeptQuery queryParams
) {
List<DeptVO> list = deptService.getDeptList(queryParams);
return Result.success(list);
}
@Operation(summary = "部门下拉列表")
@GetMapping("/options")
public Result<List<Option<Long>>> getDeptOptions() {
List<Option<Long>> list = deptService.listDeptOptions();
return Result.success(list);
}
@Operation(summary = "新增部门")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:dept:add')")
@RepeatSubmit
public Result<?> saveDept(
@Valid @RequestBody DeptForm formData
) {
Long id = deptService.saveDept(formData);
return Result.success(id);
}
@Operation(summary = "获取部门表单数据")
@GetMapping("/{deptId}/form")
public Result<DeptForm> getDeptForm(
@Parameter(description ="部门ID") @PathVariable Long deptId
) {
DeptForm deptForm = deptService.getDeptForm(deptId);
return Result.success(deptForm);
}
@Operation(summary = "修改部门")
@PutMapping(value = "/{deptId}")
@PreAuthorize("@ss.hasPerm('sys:dept:edit')")
public Result<?> updateDept(
@PathVariable Long deptId,
@Valid @RequestBody DeptForm formData
) {
deptId = deptService.updateDept(deptId, formData);
return Result.success(deptId);
}
@Operation(summary = "删除部门")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('sys:dept:delete')")
public Result<?> deleteDepartments(
@Parameter(description ="部门ID,多个以英文逗号(,)分割") @PathVariable("ids") String ids
) {
boolean result = deptService.deleteByIds(ids);
return Result.judge(result);
}
}
@@ -0,0 +1,103 @@
package com.youlai.boot.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.system.model.query.DictPageQuery;
import com.youlai.boot.system.model.vo.DictPageVO;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.system.model.form.DictForm;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.system.service.DictService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 字典控制层
*
* @author Ray
* @since 2.9.0
*/
@Tag(name = "06.字典接口")
@RestController
@RequestMapping("/api/v1/dict")
@RequiredArgsConstructor
public class DictController {
private final DictService dictService;
@Operation(summary = "字典分页列表")
@GetMapping("/page")
@Log( value = "字典分页列表",module = LogModuleEnum.DICT)
public PageResult<DictPageVO> getDictPage(
DictPageQuery queryParams
) {
Page<DictPageVO> result = dictService.getDictPage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "字典列表")
@GetMapping("/list")
public Result<List<Option<String>>> getDictList() {
List<Option<String>> list = dictService.getDictList();
return Result.success(list);
}
@Operation(summary = "字典数据项列表")
@GetMapping("/{code}/options")
public Result<List<Option<Long>>> getDictOptions(
@Parameter(description = "字典编码") @PathVariable String code
) {
List<Option<Long>> options = dictService.listDictItemsByCode(code);
return Result.success(options);
}
@Operation(summary = "字典表单")
@GetMapping("/{id}/form")
public Result<DictForm> getDictForm(
@Parameter(description = "字典ID") @PathVariable Long id
) {
DictForm formData = dictService.getDictForm(id);
return Result.success(formData);
}
@Operation(summary = "新增字典")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:dict:add')")
@RepeatSubmit
public Result<?> saveDict(@RequestBody DictForm formData) {
boolean result = dictService.saveDict(formData);
return Result.judge(result);
}
@Operation(summary = "修改字典")
@PutMapping("/{id}")
@PreAuthorize("@ss.hasPerm('sys:dict:edit')")
public Result<?> updateDict(
@PathVariable Long id,
@RequestBody DictForm DictForm
) {
boolean status = dictService.updateDict(id, DictForm);
return Result.judge(status);
}
@Operation(summary = "删除字典")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('sys:dict:delete')")
public Result<?> deleteDictionaries(
@Parameter(description = "字典ID,多个以英文逗号(,)拼接") @PathVariable String ids
) {
dictService.deleteDictByIds(ids);
return Result.success();
}
}
@@ -0,0 +1,63 @@
package com.youlai.boot.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.system.model.query.LogPageQuery;
import com.youlai.boot.system.model.vo.LogPageVO;
import com.youlai.boot.system.model.vo.VisitStatsVO;
import com.youlai.boot.system.model.vo.VisitTrendVO;
import com.youlai.boot.system.service.LogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.List;
/**
* 日志控制层
*
* @author Ray
* @since 2.10.0
*/
@Tag(name = "08.日志接口")
@RestController
@RequestMapping("/api/v1/logs")
@RequiredArgsConstructor
public class LogController {
private final LogService logService;
@Operation(summary = "日志分页列表")
@GetMapping("/page")
public PageResult<LogPageVO> listPagedLogs(
LogPageQuery queryParams
) {
Page<LogPageVO> result = logService.listPagedLogs(queryParams);
return PageResult.success(result);
}
@Operation(summary = "获取访问趋势")
@GetMapping("/visit-trend")
public Result<VisitTrendVO> getVisitTrend(
@Parameter(description = "开始时间", example = "yyyy-MM-dd") @RequestParam String startDate,
@Parameter(description = "结束时间", example = "yyyy-MM-dd") @RequestParam String endDate
) {
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
VisitTrendVO data = logService.getVisitTrend(start, end);
return Result.success(data);
}
@Operation(summary = "获取统计数据")
@GetMapping("/visit-stats")
public Result<List<VisitStatsVO>> getVisitStats() {
List<VisitStatsVO> list = logService.getVisitStats();
return Result.success(list);
}
}
@@ -0,0 +1,116 @@
package com.youlai.boot.system.controller;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.system.model.form.MenuForm;
import com.youlai.boot.system.model.query.MenuQuery;
import com.youlai.boot.system.model.vo.MenuVO;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.system.model.vo.RouteVO;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.system.service.MenuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
/**
* 菜单控制层
*
* @author Ray
* @since 2020/11/06
*/
@Tag(name = "04.菜单接口")
@RestController
@RequestMapping("/api/v1/menus")
@RequiredArgsConstructor
@Slf4j
public class MenuController {
private final MenuService menuService;
@Operation(summary = "菜单列表")
@GetMapping
@Log( value = "菜单列表",module = LogModuleEnum.MENU)
public Result<List<MenuVO>> listMenus(MenuQuery queryParams) {
List<MenuVO> menuList = menuService.listMenus(queryParams);
return Result.success(menuList);
}
@Operation(summary = "菜单下拉列表")
@GetMapping("/options")
public Result<?> listMenuOptions(
@Parameter(description = "是否只查询父级菜单")
@RequestParam(required = false, defaultValue = "false") boolean onlyParent
) {
List<Option> menus = menuService.listMenuOptions(onlyParent);
return Result.success(menus);
}
@Operation(summary = "菜单路由列表")
@GetMapping("/routes")
public Result<List<RouteVO>> listRoutes() {
Set<String> roles = SecurityUtils.getRoles();
List<RouteVO> routeList = menuService.listRoutes(roles);
return Result.success(routeList);
}
@Operation(summary = "菜单表单数据")
@GetMapping("/{id}/form")
public Result<MenuForm> getMenuForm(
@Parameter(description = "菜单ID") @PathVariable Long id
) {
MenuForm menu = menuService.getMenuForm(id);
return Result.success(menu);
}
@Operation(summary = "新增菜单")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:menu:add')")
@RepeatSubmit
public Result<?> addMenu(@RequestBody MenuForm menuForm) {
boolean result = menuService.saveMenu(menuForm);
return Result.judge(result);
}
@Operation(summary = "修改菜单")
@PutMapping(value = "/{id}")
@PreAuthorize("@ss.hasPerm('sys:menu:edit')")
public Result<?> updateMenu(
@RequestBody MenuForm menuForm
) {
boolean result = menuService.saveMenu(menuForm);
return Result.judge(result);
}
@Operation(summary = "删除菜单")
@DeleteMapping("/{id}")
@PreAuthorize("@ss.hasPerm('sys:menu:delete')")
public Result<?> deleteMenu(
@Parameter(description = "菜单ID,多个以英文(,)分割") @PathVariable("id") Long id
) {
boolean result = menuService.deleteMenu(id);
return Result.judge(result);
}
@Operation(summary = "修改菜单显示状态")
@PatchMapping("/{menuId}")
public Result<?> updateMenuVisible(
@Parameter(description = "菜单ID") @PathVariable Long menuId,
@Parameter(description = "显示状态(1:显示;0:隐藏)") Integer visible
) {
boolean result = menuService.updateMenuVisible(menuId, visible);
return Result.judge(result);
}
}
@@ -0,0 +1,81 @@
package com.youlai.system.controller;
import com.youlai.system.service.NoticeService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.youlai.system.model.form.NoticeForm;
import com.youlai.system.model.query.NoticeQuery;
import com.youlai.system.model.vo.NoticeVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
/**
* 通知公告前端控制层
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Tag(name = "通知公告接口")
@RestController
@RequestMapping("/api/v1/notices")
@RequiredArgsConstructor
public class NoticeController {
private final NoticeService noticeService;
@Operation(summary = "通知公告分页列表")
@GetMapping("/page")
@PreAuthorize("@ss.hasPerm('system:notice:query')")
public PageResult<NoticeVO> getNoticePage(NoticeQuery queryParams ) {
IPage<NoticeVO> result = noticeService.getNoticePage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "新增通知公告")
@PostMapping
@PreAuthorize("@ss.hasPerm('system:notice:add')")
public Result saveNotice(@RequestBody @Valid NoticeForm formData ) {
boolean result = noticeService.saveNotice(formData);
return Result.judge(result);
}
@Operation(summary = "获取通知公告表单数据")
@GetMapping("/{id}/form")
@PreAuthorize("@ss.hasPerm('system:notice:edit')")
public Result<NoticeForm> getNoticeForm(
@Parameter(description = "通知公告ID") @PathVariable Long id
) {
NoticeForm formData = noticeService.getNoticeFormData(id);
return Result.success(formData);
}
@Operation(summary = "修改通知公告")
@PutMapping(value = "/{id}")
@PreAuthorize("@ss.hasPerm('system:notice:edit')")
public Result updateNotice(
@Parameter(description = "通知公告ID") @PathVariable Long id,
@RequestBody @Validated NoticeForm formData
) {
boolean result = noticeService.updateNotice(id, formData);
return Result.judge(result);
}
@Operation(summary = "删除通知公告")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('system:notice:delete')")
public Result deleteNotices(
@Parameter(description = "通知公告ID,多个以英文逗号(,)分割") @PathVariable String ids
) {
boolean result = noticeService.deleteNotices(ids);
return Result.judge(result);
}
}
@@ -0,0 +1,81 @@
package com.youlai.system.controller;
import com.youlai.system.service.NoticeStatusService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.youlai.system.model.form.NoticeStatusForm;
import com.youlai.system.model.query.NoticeStatusQuery;
import com.youlai.system.model.vo.NoticeStatusVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.system.common.result.PageResult;
import com.youlai.system.common.result.Result;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
/**
* 用户公告状态前端控制层
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Tag(name = "用户公告状态接口")
@RestController
@RequestMapping("/api/v1/noticeStatuss")
@RequiredArgsConstructor
public class NoticeStatusController {
private final NoticeStatusService noticeStatusService;
@Operation(summary = "用户公告状态分页列表")
@GetMapping("/page")
@PreAuthorize("@ss.hasPerm('system:noticeStatus:query')")
public PageResult<NoticeStatusVO> getNoticeStatusPage(NoticeStatusQuery queryParams ) {
IPage<NoticeStatusVO> result = noticeStatusService.getNoticeStatusPage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "新增用户公告状态")
@PostMapping
@PreAuthorize("@ss.hasPerm('system:noticeStatus:add')")
public Result saveNoticeStatus(@RequestBody @Valid NoticeStatusForm formData ) {
boolean result = noticeStatusService.saveNoticeStatus(formData);
return Result.judge(result);
}
@Operation(summary = "获取用户公告状态表单数据")
@GetMapping("/{id}/form")
@PreAuthorize("@ss.hasPerm('system:noticeStatus:edit')")
public Result<NoticeStatusForm> getNoticeStatusForm(
@Parameter(description = "用户公告状态ID") @PathVariable Long id
) {
NoticeStatusForm formData = noticeStatusService.getNoticeStatusFormData(id);
return Result.success(formData);
}
@Operation(summary = "修改用户公告状态")
@PutMapping(value = "/{id}")
@PreAuthorize("@ss.hasPerm('system:noticeStatus:edit')")
public Result updateNoticeStatus(
@Parameter(description = "用户公告状态ID") @PathVariable Long id,
@RequestBody @Validated NoticeStatusForm formData
) {
boolean result = noticeStatusService.updateNoticeStatus(id, formData);
return Result.judge(result);
}
@Operation(summary = "删除用户公告状态")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('system:noticeStatus:delete')")
public Result deleteNoticeStatuss(
@Parameter(description = "用户公告状态ID,多个以英文逗号(,)分割") @PathVariable String ids
) {
boolean result = noticeStatusService.deleteNoticeStatuss(ids);
return Result.judge(result);
}
}
@@ -0,0 +1,121 @@
package com.youlai.boot.system.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.system.model.form.RoleForm;
import com.youlai.boot.system.model.query.RolePageQuery;
import com.youlai.boot.system.model.vo.RolePageVO;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.system.service.RoleService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;
import java.util.List;
/**
* 角色控制层
*
* @author Ray
* @since 2022/10/16
*/
@Tag(name = "03.角色接口")
@RestController
@RequestMapping("/api/v1/roles")
@RequiredArgsConstructor
public class RoleController {
private final RoleService roleService;
@Operation(summary = "角色分页列表")
@GetMapping("/page")
@Log( value = "角色分页列表",module = LogModuleEnum.ROLE)
public PageResult<RolePageVO> getRolePage(
RolePageQuery queryParams
) {
Page<RolePageVO> result = roleService.getRolePage(queryParams);
return PageResult.success(result);
}
@Operation(summary = "角色下拉列表")
@GetMapping("/options")
public Result<List<Option<Long>>> listRoleOptions() {
List<Option<Long>> list = roleService.listRoleOptions();
return Result.success(list);
}
@Operation(summary = "新增角色")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:role:add')")
@RepeatSubmit
public Result<?> addRole(@Valid @RequestBody RoleForm roleForm) {
boolean result = roleService.saveRole(roleForm);
return Result.judge(result);
}
@Operation(summary = "角色表单数据")
@GetMapping("/{roleId}/form")
public Result<RoleForm> getRoleForm(
@Parameter(description = "角色ID") @PathVariable Long roleId
) {
RoleForm roleForm = roleService.getRoleForm(roleId);
return Result.success(roleForm);
}
@Operation(summary = "修改角色")
@PutMapping(value = "/{id}")
@PreAuthorize("@ss.hasPerm('sys:role:edit')")
public Result<?> updateRole(@Valid @RequestBody RoleForm roleForm) {
boolean result = roleService.saveRole(roleForm);
return Result.judge(result);
}
@Operation(summary = "删除角色")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('sys:role:delete')")
public Result<?> deleteRoles(
@Parameter(description = "删除角色,多个以英文逗号(,)拼接") @PathVariable String ids
) {
boolean result = roleService.deleteRoles(ids);
return Result.judge(result);
}
@Operation(summary = "修改角色状态")
@PutMapping(value = "/{roleId}/status")
public Result<?> updateRoleStatus(
@Parameter(description = "角色ID") @PathVariable Long roleId,
@Parameter(description = "状态(1:启用;0:禁用)") @RequestParam Integer status
) {
boolean result = roleService.updateRoleStatus(roleId, status);
return Result.judge(result);
}
@Operation(summary = "获取角色的菜单ID集合")
@GetMapping("/{roleId}/menuIds")
public Result<List<Long>> getRoleMenuIds(
@Parameter(description = "角色ID") @PathVariable Long roleId
) {
List<Long> menuIds = roleService.getRoleMenuIds(roleId);
return Result.success(menuIds);
}
@Operation(summary = "分配菜单(包括按钮权限)给角色")
@PutMapping("/{roleId}/menus")
public Result<?> assignMenusToRole(
@PathVariable Long roleId,
@RequestBody List<Long> menuIds
) {
boolean result = roleService.assignMenusToRole(roleId, menuIds);
return Result.judge(result);
}
}
@@ -0,0 +1,233 @@
package com.youlai.boot.system.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.form.*;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.common.enums.ContactType;
import com.youlai.boot.system.model.vo.UserProfileVO;
import com.youlai.boot.core.security.util.SecurityUtils;
import com.youlai.boot.common.util.ExcelUtils;
import com.youlai.boot.common.enums.LogModuleEnum;
import com.youlai.boot.system.model.dto.UserImportDTO;
import com.youlai.boot.common.annotation.RepeatSubmit;
import com.youlai.boot.system.listener.UserImportListener;
import com.youlai.boot.system.model.query.UserPageQuery;
import com.youlai.boot.system.model.dto.UserExportDTO;
import com.youlai.boot.system.model.vo.UserInfoVO;
import com.youlai.boot.system.model.vo.UserPageVO;
import com.youlai.boot.common.annotation.Log;
import com.youlai.boot.system.service.UserService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* 用户控制层
*
* @author Ray
* @since 2022/10/16
*/
@Tag(name = "02.用户接口")
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@Operation(summary = "用户分页列表")
@GetMapping("/page")
@Log(value = "用户分页列表", module = LogModuleEnum.USER)
public PageResult<UserPageVO> listPagedUsers(
UserPageQuery queryParams
) {
IPage<UserPageVO> result = userService.listPagedUsers(queryParams);
return PageResult.success(result);
}
@Operation(summary = "新增用户")
@PostMapping
@PreAuthorize("@ss.hasPerm('sys:user:add')")
@RepeatSubmit
public Result<?> saveUser(
@RequestBody @Valid UserForm userForm
) {
boolean result = userService.saveUser(userForm);
return Result.judge(result);
}
@Operation(summary = "用户表单数据")
@GetMapping("/{userId}/form")
public Result<UserForm> getUserForm(
@Parameter(description = "用户ID") @PathVariable Long userId
) {
UserForm formData = userService.getUserFormData(userId);
return Result.success(formData);
}
@Operation(summary = "修改用户")
@PutMapping(value = "/{userId}")
@PreAuthorize("@ss.hasPerm('sys:user:edit')")
public Result<?> updateUser(
@Parameter(description = "用户ID") @PathVariable Long userId,
@RequestBody @Validated UserForm userForm) {
boolean result = userService.updateUser(userId, userForm);
return Result.judge(result);
}
@Operation(summary = "删除用户")
@DeleteMapping("/{ids}")
@PreAuthorize("@ss.hasPerm('sys:user:delete')")
public Result<?> deleteUsers(
@Parameter(description = "用户ID,多个以英文逗号(,)分割") @PathVariable String ids
) {
boolean result = userService.deleteUsers(ids);
return Result.judge(result);
}
@Operation(summary = "修改用户状态")
@PatchMapping(value = "/{userId}/status")
public Result<?> updateUserStatus(
@Parameter(description = "用户ID") @PathVariable Long userId,
@Parameter(description = "用户状态(1:启用;0:禁用)") @RequestParam Integer status
) {
boolean result = userService.update(new LambdaUpdateWrapper<User>()
.eq(User::getId, userId)
.set(User::getStatus, status)
);
return Result.judge(result);
}
@Operation(summary = "获取当前登录用户信息")
@GetMapping("/me")
public Result<UserInfoVO> getCurrentUserInfo() {
UserInfoVO userInfoVO = userService.getCurrentUserInfo();
return Result.success(userInfoVO);
}
@Operation(summary = "用户导入模板下载")
@GetMapping("/template")
public void downloadTemplate(HttpServletResponse response) throws IOException {
String fileName = "用户导入模板.xlsx";
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
String fileClassPath = "templates" + File.separator + "excel" + File.separator + fileName;
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileClassPath);
ServletOutputStream outputStream = response.getOutputStream();
ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();
excelWriter.finish();
}
@Operation(summary = "导入用户")
@PostMapping("/import")
public Result<?> importUsers(MultipartFile file) throws IOException {
UserImportListener listener = new UserImportListener();
String msg = ExcelUtils.importExcel(file.getInputStream(), UserImportDTO.class, listener);
return Result.success(msg);
}
@Operation(summary = "导出用户")
@GetMapping("/export")
public void exportUsers(UserPageQuery queryParams, HttpServletResponse response) throws IOException {
String fileName = "用户列表.xlsx";
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
List<UserExportDTO> exportUserList = userService.listExportUsers(queryParams);
EasyExcel.write(response.getOutputStream(), UserExportDTO.class).sheet("用户列表")
.doWrite(exportUserList);
}
@Operation(summary = "获取个人中心用户信息")
@GetMapping("/profile")
public Result<UserProfileVO> getUserProfile() {
Long userId = SecurityUtils.getUserId();
UserProfileVO userProfile = userService.getUserProfile(userId);
return Result.success(userProfile);
}
@Operation(summary = "修改个人中心用户信息")
@PutMapping("/profile")
public Result<?> updateUserProfile(@RequestBody UserProfileForm formData) {
boolean result = userService.updateUserProfile(formData);
return Result.judge(result);
}
@Operation(summary = "重置用户密码")
@PutMapping(value = "/{userId}/password/reset")
@PreAuthorize("@ss.hasPerm('sys:user:password:reset')")
public Result<?> resetPassword(
@Parameter(description = "用户ID") @PathVariable Long userId,
@RequestParam String password
) {
boolean result = userService.resetPassword(userId, password);
return Result.judge(result);
}
@Operation(summary = "修改密码")
@PutMapping(value = "/password")
public Result<?> changePassword(
@RequestBody PasswordChangeForm data
) {
Long currUserId = SecurityUtils.getUserId();
boolean result = userService.changePassword(currUserId, data);
return Result.judge(result);
}
@Operation(summary = "发送短信/邮箱验证码")
@PostMapping(value = "/send-verification-code")
public Result<?> sendVerificationCode(
@Parameter(description = "联系方式(手机号码或邮箱地址)", required = true) @RequestParam String contact,
@Parameter(description = "联系方式类型(Mobile或Email)", required = true) @RequestParam ContactType contactType
) {
boolean result = userService.sendVerificationCode(contact, contactType);
return Result.judge(result);
}
@Operation(summary = "绑定个人中心用户手机号")
@PutMapping(value = "/mobile")
public Result<?> bindMobile(
@RequestBody @Validated MobileBindingForm data
) {
boolean result = userService.bindMobile(data);
return Result.judge(result);
}
@Operation(summary = "绑定个人中心用户邮箱")
@PutMapping(value = "/email")
public Result<?> bindEmail(
@RequestBody @Validated EmailChangeForm data
) {
boolean result = userService.bindEmail(data);
return Result.judge(result);
}
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.Config;
import com.youlai.boot.system.model.vo.ConfigVO;
import com.youlai.boot.system.model.form.ConfigForm;
import org.mapstruct.Mapper;
/**
* 系统配置对象转换器
*
* @author Theo
* @since 2024-7-29 11:42:49
*/
@Mapper(componentModel = "spring")
public interface ConfigConverter {
Page<ConfigVO> toPageVo(Page<Config> page);
Config toEntity(ConfigForm configForm);
ConfigForm toForm(Config entity);
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.converter;
import com.youlai.boot.system.model.entity.Dept;
import com.youlai.boot.system.model.vo.DeptVO;
import com.youlai.boot.system.model.form.DeptForm;
import org.mapstruct.Mapper;
/**
* 部门对象转换器
*
* @author haoxr
* @since 2022/7/29
*/
@Mapper(componentModel = "spring")
public interface DeptConverter {
DeptForm toForm(Dept entity);
DeptVO toVo(Dept entity);
Dept toEntity(DeptForm deptForm);
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.Dict;
import com.youlai.boot.system.model.vo.DictPageVO;
import com.youlai.boot.system.model.form.DictForm;
import org.mapstruct.Mapper;
/**
* 字典 对象转换器
*
* @author Ray Hao
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface DictConverter {
Page<DictPageVO> toPageVo(Page<Dict> page);
DictForm toForm(Dict entity);
Dict toEntity(DictForm entity);
}
@@ -0,0 +1,39 @@
package com.youlai.boot.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.DictItem;
import com.youlai.boot.system.model.vo.DictPageVO;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.system.model.form.DictForm;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import java.util.List;
/**
* 字典项 对象转换器
*
* @author Ray
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface DictItemConverter {
Page<DictPageVO> toPageVo(Page<DictItem> page);
DictForm toForm(DictItem entity);
DictItem toEntity(DictForm.DictItem dictItems);
List<DictItem> toEntity(List<DictForm.DictItem> dictItems);
DictForm.DictItem toDictItem(DictItem entity);
List<DictForm.DictItem> toDictItem(List<DictItem> entities);
@Mappings({
@Mapping(target = "value", source = "value"),
@Mapping(target = "label", source = "name")
})
Option<Long> toOption(DictItem dictItem);
List<Option<Long>> toOption(List<DictItem> dictItems);
}
@@ -0,0 +1,39 @@
package com.youlai.boot.system.converter;
import com.youlai.boot.platform.generator.model.entity.GenConfig;
import com.youlai.boot.platform.generator.model.entity.GenFieldConfig;
import com.youlai.boot.platform.generator.model.form.GenConfigForm;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.List;
/**
* 代码生成配置转换器
*
* @author Ray
* @since 2.10.0
*/
@Mapper(componentModel = "spring")
public interface GenConfigConverter {
@Mapping(source = "genConfig.tableName", target = "tableName")
@Mapping(source = "genConfig.businessName", target = "businessName")
@Mapping(source = "genConfig.moduleName", target = "moduleName")
@Mapping(source = "genConfig.packageName", target = "packageName")
@Mapping(source = "genConfig.entityName", target = "entityName")
@Mapping(source = "genConfig.author", target = "author")
@Mapping(source = "fieldConfigs", target = "fieldConfigs")
GenConfigForm toGenConfigForm(GenConfig genConfig, List<GenFieldConfig> fieldConfigs);
List<GenConfigForm.FieldConfig> toGenFieldConfigForm(List<GenFieldConfig> fieldConfigs);
GenConfigForm.FieldConfig toGenFieldConfigForm(GenFieldConfig genFieldConfig);
GenConfig toGenConfig(GenConfigForm formData);
List<GenFieldConfig> toGenFieldConfig(List<GenConfigForm.FieldConfig> fieldConfigs);
GenFieldConfig toGenFieldConfig(GenConfigForm.FieldConfig fieldConfig);
}
@@ -0,0 +1,26 @@
package com.youlai.boot.system.converter;
import com.youlai.boot.system.model.entity.Menu;
import com.youlai.boot.system.model.vo.MenuVO;
import com.youlai.boot.system.model.form.MenuForm;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
/**
* 菜单对象转换器
*
* @author Ray Hao
* @since 2024/5/26
*/
@Mapper(componentModel = "spring")
public interface MenuConverter {
MenuVO toVo(Menu entity);
@Mapping(target = "params", ignore = true)
MenuForm toForm(Menu entity);
@Mapping(target = "params", ignore = true)
Menu toEntity(MenuForm menuForm);
}
@@ -0,0 +1,23 @@
package com.youlai.system.converter;
import com.youlai.system.model.vo.NoticeVO;
import org.mapstruct.Mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.Notice;
import com.youlai.system.model.form.NoticeForm;
/**
* 通知公告对象转换器
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Mapper(componentModel = "spring")
public interface NoticeConverter{
NoticeForm toForm(Notice entity);
Notice toEntity(NoticeForm formData);
NoticeVO toVO(Notice notice);
}
@@ -0,0 +1,20 @@
package com.youlai.system.converter;
import org.mapstruct.Mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.entity.NoticeStatus;
import com.youlai.system.model.form.NoticeStatusForm;
/**
* 用户公告状态对象转换器
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Mapper(componentModel = "spring")
public interface NoticeStatusConverter{
NoticeStatusForm toForm(NoticeStatus entity);
NoticeStatus toEntity(NoticeStatusForm formData);
}
@@ -0,0 +1,36 @@
package com.youlai.boot.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.Role;
import com.youlai.boot.system.model.vo.RolePageVO;
import com.youlai.boot.common.model.Option;
import com.youlai.boot.system.model.form.RoleForm;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import java.util.List;
/**
* 角色对象转换器
*
* @author haoxr
* @since 2022/5/29
*/
@Mapper(componentModel = "spring")
public interface RoleConverter {
Page<RolePageVO> toPageVo(Page<Role> page);
@Mappings({
@Mapping(target = "value", source = "id"),
@Mapping(target = "label", source = "name")
})
Option<Long> entity2Option(Role role);
List<Option<Long>> entities2Options(List<Role> roles);
Role toEntity(RoleForm roleForm);
RoleForm toForm(Role entity);
}
@@ -0,0 +1,49 @@
package com.youlai.boot.system.converter;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.vo.UserInfoVO;
import com.youlai.boot.system.model.vo.UserPageVO;
import com.youlai.boot.system.model.vo.UserProfileVO;
import com.youlai.boot.system.model.bo.UserBO;
import com.youlai.boot.system.model.form.UserForm;
import com.youlai.boot.system.model.dto.UserImportDTO;
import com.youlai.boot.system.model.form.UserProfileForm;
import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
/**
* 用户对象转换器
*
* @author haoxr
* @since 2022/6/8
*/
@Mapper(componentModel = "spring")
public interface UserConverter {
@Mappings({
@Mapping(target = "genderLabel", expression = "java(com.youlai.boot.common.base.IBaseEnum.getLabelByValue(bo.getGender(), com.youlai.boot.common.enums.GenderEnum.class))")
})
UserPageVO toPageVo(UserBO bo);
Page<UserPageVO> toPageVo(Page<UserBO> bo);
UserForm toForm(User entity);
@InheritInverseConfiguration(name = "toForm")
User toEntity(UserForm entity);
@Mappings({
@Mapping(target = "userId", source = "id")
})
UserInfoVO toUserInfoVo(User entity);
User toEntity(UserImportDTO vo);
UserProfileVO toProfileVO(UserBO bo);
User toEntity(UserProfileForm formData);
}
@@ -0,0 +1,16 @@
package com.youlai.boot.system.event;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
@Getter
public class UserConnectionEvent extends ApplicationEvent {
private final String username;
private final boolean connected;
public UserConnectionEvent(Object source, String username, boolean connected) {
super(source);
this.username = username;
this.connected = connected;
}
}
@@ -0,0 +1,19 @@
package com.youlai.boot.system.handler;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* xxl-job 测试示例(Bean模式)
*/
@Component
@Slf4j
public class XxlJobSampleHandler {
@XxlJob("demoJobHandler")
public void demoJobHandler() {
log.info("XXL-JOB, Hello World.");
}
}
@@ -0,0 +1,178 @@
package com.youlai.boot.system.listener;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.youlai.boot.common.base.BaseAnalysisEventListener;
import com.youlai.boot.system.model.entity.Dept;
import com.youlai.boot.system.model.entity.Role;
import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.entity.UserRole;
import com.youlai.boot.common.base.IBaseEnum;
import com.youlai.boot.common.constant.SystemConstants;
import com.youlai.boot.common.enums.GenderEnum;
import com.youlai.boot.common.enums.StatusEnum;
import com.youlai.boot.system.converter.UserConverter;
import com.youlai.boot.system.model.dto.UserImportDTO;
import com.youlai.boot.system.service.DeptService;
import com.youlai.boot.system.service.RoleService;
import com.youlai.boot.system.service.UserRoleService;
import com.youlai.boot.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户导入监听器
* <p>
* <a href="https://easyexcel.opensource.alibaba.com/docs/current/quickstart/read#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84%E8%AF%BB%E7%9A%84%E7%9B%91%E5%90%AC%E5%99%A8">最简单的读的监听器</a>
*
* @author Ray
* @since 2022/4/10
*/
@Slf4j
public class UserImportListener extends BaseAnalysisEventListener<UserImportDTO> {
// 有效条数
private int validCount;
// 无效条数
private int invalidCount;
// 导入返回信息
StringBuilder msg = new StringBuilder();
private final UserService userService;
private final PasswordEncoder passwordEncoder;
private final UserConverter userConverter;
private final RoleService roleService;
private final UserRoleService userRoleService;
private final DeptService deptService;
public UserImportListener() {
this.userService = SpringUtil.getBean(UserService.class);
this.passwordEncoder = SpringUtil.getBean(PasswordEncoder.class);
this.roleService = SpringUtil.getBean(RoleService.class);
this.userRoleService = SpringUtil.getBean(UserRoleService.class);
this.deptService = SpringUtil.getBean(DeptService.class);
this.userConverter = SpringUtil.getBean(UserConverter.class);
}
/**
* 每一条数据解析都会来调用
* <p>
* 1. 数据校验;全字段校验
* 2. 数据持久化;
*
* @param userImportDTO 一行数据,类似于 {@link AnalysisContext#readRowHolder()}
*/
@Override
public void invoke(UserImportDTO userImportDTO, AnalysisContext analysisContext) {
log.info("解析到一条用户数据:{}", JSONUtil.toJsonStr(userImportDTO));
// 校验数据
StringBuilder validationMsg = new StringBuilder();
String username = userImportDTO.getUsername();
if (StrUtil.isBlank(username)) {
validationMsg.append("用户名为空;");
} else {
long count = userService.count(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
if (count > 0) {
validationMsg.append("用户名已存在;");
}
}
String nickname = userImportDTO.getNickname();
if (StrUtil.isBlank(nickname)) {
validationMsg.append("用户昵称为空;");
}
String mobile = userImportDTO.getMobile();
if (StrUtil.isBlank(mobile)) {
validationMsg.append("手机号码为空;");
} else {
if (!Validator.isMobile(mobile)) {
validationMsg.append("手机号码不正确;");
}
}
if (validationMsg.isEmpty()) {
// 校验通过,持久化至数据库
User entity = userConverter.toEntity(userImportDTO);
entity.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD)); // 默认密码
// 性别翻译
String genderLabel = userImportDTO.getGenderLabel();
if (StrUtil.isNotBlank(genderLabel)) {
Integer genderValue = (Integer) IBaseEnum.getValueByLabel(genderLabel, GenderEnum.class);
entity.setGender(genderValue);
}
// 角色解析
String roleCodes = userImportDTO.getRoleCodes();
List<Long> roleIds = null;
if (StrUtil.isNotBlank(roleCodes)) {
roleIds = roleService.list(
new LambdaQueryWrapper<Role>()
.in(Role::getCode, (Object) roleCodes.split(","))
.eq(Role::getStatus, StatusEnum.ENABLE.getValue())
.select(Role::getId)
).stream()
.map(Role::getId)
.collect(Collectors.toList());
}
// 部门解析
String deptCode = userImportDTO.getDeptCode();
if (StrUtil.isNotBlank(deptCode)) {
Dept dept = deptService.getOne(new LambdaQueryWrapper<Dept>().eq(Dept::getCode, deptCode)
.select(Dept::getId)
);
if (dept != null) {
entity.setDeptId(dept.getId());
}
}
boolean saveResult = userService.save(entity);
if (saveResult) {
validCount++;
// 保存用户角色关联
if (CollectionUtil.isNotEmpty(roleIds)) {
List<UserRole> userRoles = roleIds.stream()
.map(roleId -> new UserRole(entity.getId(), roleId))
.collect(Collectors.toList());
userRoleService.saveBatch(userRoles);
}
} else {
invalidCount++;
msg.append("第").append(validCount + invalidCount).append("行数据保存失败;<br/>");
}
} else {
invalidCount++;
msg.append("第").append(validCount + invalidCount).append("行数据校验失败:").append(validationMsg + "<br/>");
}
}
/**
* 所有数据解析完成会来调用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
log.info("所有数据解析完成!");
}
@Override
public String getMsg() {
// 总结信息
return StrUtil.format("导入用户结束:成功{}条,失败{}条;<br/>{}", validCount, invalidCount, msg);
}
}
@@ -0,0 +1,16 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.entity.Config;
import org.apache.ibatis.annotations.Mapper;
/**
* 系统配置 访问层
*
* @author Theo
* @since 2024-7-29 11:41:04
*/
@Mapper
public interface ConfigMapper extends BaseMapper<Config> {
}
@@ -0,0 +1,20 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.youlai.boot.common.annotation.DataPermission;
import com.youlai.boot.system.model.entity.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface DeptMapper extends BaseMapper<Dept> {
@DataPermission(deptIdColumnName = "id")
@Override
List<Dept> selectList(@Param(Constants.WRAPPER) Wrapper<Dept> queryWrapper);
}
@@ -0,0 +1,20 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.entity.DictItem;
import org.apache.ibatis.annotations.Mapper;
/**
* 字典项 访问层
*
* @author Ray Hao
* @since 2.9.0
*/
@Mapper
public interface DictItemMapper extends BaseMapper<DictItem> {
}
@@ -0,0 +1,31 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.entity.Dict;
import com.youlai.boot.system.model.query.DictPageQuery;
import com.youlai.boot.system.model.vo.DictPageVO;
import org.apache.ibatis.annotations.Mapper;
/**
* 字典 访问层
*
* @author Ray Hao
* @since 2.9.0
*/
@Mapper
public interface DictMapper extends BaseMapper<Dict> {
/**
* 字典分页列表
*
* @param page 分页参数
* @param queryParams 查询参数
* @return
*/
Page<DictPageVO> getDictPage(Page<DictPageVO> page, DictPageQuery queryParams);
}
@@ -0,0 +1,68 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.bo.VisitCount;
import com.youlai.boot.system.model.entity.Log;
import com.youlai.boot.system.model.query.LogPageQuery;
import com.youlai.boot.system.model.vo.LogPageVO;
import com.youlai.boot.system.model.vo.VisitStatsVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 系统日志 数据库访问层
*
* @author Ray
* @since 2.10.0
*/
@Mapper
public interface LogMapper extends BaseMapper<Log> {
/**
* 获取日志分页列表
*
* @param page
* @param queryParams
* @return
*/
Page<LogPageVO> listPagedLogs(Page<LogPageVO> page, LogPageQuery queryParams);
/**
* 统计浏览数(PV)
*
* @param startDate 开始日期 yyyy-MM-dd
* @param endDate 结束日期 yyyy-MM-dd
* @return
*/
List<VisitCount> getPvCounts(String startDate, String endDate);
/**
* 统计IP数
*
* @param startDate 开始日期 yyyy-MM-dd
* @param endDate 结束日期 yyyy-MM-dd
* @return
*/
List<VisitCount> getIpCounts(String startDate, String endDate);
/**
* 获取浏览量(PV)统计数据
*
* @return
*/
VisitStatsVO getPvStats();
/**
* 获取IP统计数据
*
* @return
*/
VisitStatsVO getIpStats();
}
@@ -0,0 +1,26 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.bo.RouteBO;
import com.youlai.boot.system.model.entity.Menu;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Set;
/**
* 菜单访问层
*
* @author Ray
* @since 2022/1/24
*/
@Mapper
public interface MenuMapper extends BaseMapper<Menu> {
/**
* 获取菜单路由列表
*/
List<RouteBO> listRoutes(Set<String> roles);
}
@@ -0,0 +1,28 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.system.model.entity.Notice;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.query.NoticeQuery;
import com.youlai.system.model.vo.NoticeVO;
import org.apache.ibatis.annotations.Mapper;
/**
* 通知公告Mapper接口
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Mapper
public interface NoticeMapper extends BaseMapper<Notice> {
/**
* 获取通知公告分页数据
*
* @param page 分页对象
* @param queryParams 查询参数
* @return
*/
Page<NoticeVO> getNoticePage(Page<NoticeVO> page, NoticeQuery queryParams);
}
@@ -0,0 +1,28 @@
package com.youlai.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.system.model.entity.NoticeStatus;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.system.model.query.NoticeStatusQuery;
import com.youlai.system.model.vo.NoticeStatusVO;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户公告状态Mapper接口
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Mapper
public interface NoticeStatusMapper extends BaseMapper<NoticeStatus> {
/**
* 获取用户公告状态分页数据
*
* @param page 分页对象
* @param queryParams 查询参数
* @return
*/
Page<NoticeStatusVO> getNoticeStatusPage(Page<NoticeStatusVO> page, NoticeStatusQuery queryParams);
}
@@ -0,0 +1,20 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.entity.Role;
import org.apache.ibatis.annotations.Mapper;
import java.util.Set;
@Mapper
public interface RoleMapper extends BaseMapper<Role> {
/**
* 获取最大范围的数据权限
*
* @param roles
* @return
*/
Integer getMaximumDataScope(Set<String> roles);
}
@@ -0,0 +1,41 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.bo.RolePermsBO;
import com.youlai.boot.system.model.entity.RoleMenu;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Set;
/**
* 角色菜单访问层
*
* @author haoxr
* @since 2022/6/4
*/
@Mapper
public interface RoleMenuMapper extends BaseMapper<RoleMenu> {
/**
* 获取角色拥有的菜单ID集合
*
* @param roleId 角色ID
* @return 菜单ID集合
*/
List<Long> listMenuIdsByRoleId(Long roleId);
/**
* 获取权限和拥有权限的角色列表
*/
List<RolePermsBO> getRolePermsList(String roleCode);
/**
* 获取角色权限集合
*
* @param roles
* @return
*/
Set<String> listRolePerms(Set<String> roles);
}
@@ -0,0 +1,67 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youlai.boot.system.model.bo.UserBO;
import com.youlai.boot.system.model.entity.User;
import com.youlai.boot.system.model.query.UserPageQuery;
import com.youlai.boot.system.model.form.UserForm;
import com.youlai.boot.common.annotation.DataPermission;
import com.youlai.boot.system.model.dto.UserAuthInfo;
import com.youlai.boot.system.model.dto.UserExportDTO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 用户持久层
*
* @author haoxr
* @since 2022/1/14
*/
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 获取用户分页列表
*
* @param page
* @param queryParams 查询参数
* @return
*/
@DataPermission(deptAlias = "u")
Page<UserBO> listPagedUsers(Page<UserBO> page, UserPageQuery queryParams);
/**
* 获取用户表单详情
*
* @param userId 用户ID
* @return
*/
UserForm getUserFormData(Long userId);
/**
* 根据用户名获取认证信息
*
* @param username
* @return
*/
UserAuthInfo getUserAuthInfo(String username);
/**
* 获取导出用户列表
*
* @param queryParams
* @return
*/
@DataPermission(deptAlias = "u")
List<UserExportDTO> listExportUsers(UserPageQuery queryParams);
/**
* 获取用户个人中心信息
*
* @param userId 用户ID
* @return
*/
UserBO getUserProfile(Long userId);
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.system.model.entity.UserRole;
import org.apache.ibatis.annotations.Mapper;
/**
* 用户角色访问层
*
* @author haoxr
* @since 2022/1/15
*/
@Mapper
public interface UserRoleMapper extends BaseMapper<UserRole> {
/**
* 获取角色绑定的用户数
*
* @param roleId 角色ID
*/
int countUsersForRole(Long roleId);
}
@@ -0,0 +1,50 @@
package com.youlai.boot.system.model.bo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "数据表字段VO")
@Data
public class ColumnMetaData {
/**
* 字段名称
*/
private String columnName;
/**
* 字段类型
*/
private String dataType;
/**
* 字段描述
*/
private String columnComment;
/**
* 字段长度
*/
private Integer characterMaximumLength;
/**
* 是否主键(1-是 0-否)
*/
private Integer isPrimaryKey;
/**
* 是否可为空(1-是 0-否)
*/
private String isNullable;
/**
* 字符集
*/
private String characterSetName;
/**
* 排序规则
*/
private String collationName;
}
@@ -0,0 +1,26 @@
package com.youlai.boot.system.model.bo;
import lombok.Data;
import java.util.Set;
/**
* 角色权限业务对象
*
* @author haoxr
* @since 2023/11/29
*/
@Data
public class RolePermsBO {
/**
* 角色编码
*/
private String roleCode;
/**
* 权限标识集合
*/
private Set<String> perms;
}
@@ -0,0 +1,84 @@
package com.youlai.boot.system.model.bo;
import com.youlai.boot.common.enums.MenuTypeEnum;
import lombok.Data;
/**
* 路由
*/
@Data
public class RouteBO {
private Long id;
/**
* 父菜单ID
*/
private Long parentId;
/**
* 菜单名称
*/
private String name;
/**
* 菜单类型(1-菜单 2-目录 3-外链 4-按钮)
*/
private MenuTypeEnum type;
/**
* 路由名称(Vue Router 中定义的路由名称)
*/
private String routeName;
/**
* 路由路径(Vue Router 中定义的 URL 路径)
*/
private String routePath;
/**
* 组件路径(vue页面完整路径,省略.vue后缀)
*/
private String component;
/**
* 权限标识
*/
private String perm;
/**
* 显示状态(1:显示;0:隐藏)
*/
private Integer visible;
/**
* 排序
*/
private Integer sort;
/**
* 菜单图标
*/
private String icon;
/**
* 跳转路径
*/
private String redirect;
/**
* 【目录】只有一个子路由是否始终显示(1:是 0:否)
*/
private Integer alwaysShow;
/**
* 【菜单】是否开启页面缓存(1:是 0:否)
*/
private Integer keepAlive;
/**
* 【菜单】路由参数
*/
private String params;
}
@@ -0,0 +1,45 @@
package com.youlai.boot.system.model.bo;
import lombok.Data;
/**
* 数据表元数据
*
* @author Ray
* @since 2.10.0
*/
@Data
public class TableMetaData {
/**
* 表名称
*/
private String tableName;
/**
* 表描述
*/
private String tableComment;
/**
* 排序规则
*/
private String tableCollation;
/**
* 存储引擎
*/
private String engine;
/**
* 字符集
*/
private String charset;
/**
* 创建时间
*/
private String createTime;
}
@@ -0,0 +1,72 @@
package com.youlai.boot.system.model.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 用户持久化对象
*
* @author haoxr
* @since 2022/6/10
*/
@Data
public class UserBO {
/**
* 用户ID
*/
private Long id;
/**
* 账户名
*/
private String username;
/**
* 昵称
*/
private String nickname;
/**
* 手机号
*/
private String mobile;
/**
* 性别(1->男;2->女)
*/
private Integer gender;
/**
* 头像URL
*/
private String avatar;
/**
* 邮箱
*/
private String email;
/**
* 状态: 1->启用;0->禁用
*/
private Integer status;
/**
* 部门名称
*/
private String deptName;
/**
* 角色名称,多个使用英文逗号(,)分割
*/
private String roleNames;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.model.bo;
import lombok.Data;
/**
* 特定日期访问统计
*
* @author Ray
* @since 2.10.0
*/
@Data
public class VisitCount {
/**
* 日期 yyyy-MM-dd
*/
private String date;
/**
* 访问次数
*/
private Integer count;
}
@@ -0,0 +1,28 @@
package com.youlai.boot.system.model.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 验证码响应对象
*
* @author Ray Hao
* @since 2023/03/24
*/
@Schema(description = "验证码响应对象")
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CaptchaResult {
@Schema(description = "验证码ID")
private String captchaKey;
@Schema(description = "验证码图片Base64字符串")
private String captchaBase64;
}
@@ -0,0 +1,25 @@
package com.youlai.boot.system.model.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* WebSocket 消息体
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatMessage {
/**
* 发送者
*/
private String sender;
/**
* 消息内容
*/
private String content;
}
@@ -0,0 +1,16 @@
package com.youlai.boot.system.model.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "文件对象")
@Data
public class FileInfo {
@Schema(description = "文件名称")
private String name;
@Schema(description = "文件URL")
private String url;
}
@@ -0,0 +1,24 @@
package com.youlai.boot.system.model.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
@Schema(description ="登录响应对象")
@Data
@Builder
public class LoginResult {
@Schema(description = "访问token")
private String accessToken;
@Schema(description = "token 类型",example = "Bearer")
private String tokenType;
@Schema(description = "刷新token")
private String refreshToken;
@Schema(description = "过期时间(单位:毫秒)")
private Long expires;
}
@@ -0,0 +1,35 @@
package com.youlai.boot.system.model.dto;
import lombok.Data;
import java.util.Set;
/**
* 用户认证信息
*
* @author haoxr
* @since 2022/10/22
*
*/
@Data
public class UserAuthInfo {
private Long userId;
private String username;
private String nickname;
private Long deptId;
private String password;
private Integer status;
private Set<String> roles;
private Set<String> perms;
private Integer dataScope;
}
@@ -0,0 +1,44 @@
package com.youlai.boot.system.model.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户导出视图对象
*
* @author haoxr
* @since 2022/4/11 8:46
*/
@Data
@ColumnWidth(20)
public class UserExportDTO {
@ExcelProperty(value = "用户名")
private String username;
@ExcelProperty(value = "用户昵称")
private String nickname;
@ExcelProperty(value = "部门")
private String deptName;
@ExcelProperty(value = "性别")
private String gender;
@ExcelProperty(value = "手机号码")
private String mobile;
@ExcelProperty(value = "邮箱")
private String email;
@ExcelProperty(value = "创建时间")
@DateTimeFormat("yyyy/MM/dd HH:mm:ss")
private LocalDateTime createTime;
}
@@ -0,0 +1,36 @@
package com.youlai.boot.system.model.dto;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* 用户导入对象
*
* @author haoxr
* @since 2022/4/10
*/
@Data
public class UserImportDTO {
@ExcelProperty(value = "用户名")
private String username;
@ExcelProperty(value = "昵称")
private String nickname;
@ExcelProperty(value = "性别")
private String genderLabel;
@ExcelProperty(value = "手机号码")
private String mobile;
@ExcelProperty(value = "邮箱")
private String email;
@ExcelProperty("角色")
private String roleCodes;
@ExcelProperty("部门")
private String deptCode;
}
@@ -0,0 +1,42 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.youlai.boot.common.base.BaseEntity;
import lombok.Data;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 系统配置 实体
*
* @author Theo
* @since 2024-07-29 11:17:26
*/
@Schema(description = "系统配置")
@TableName("sys_config")
@Data
public class Config extends BaseEntity {
@Schema(description = "配置名称")
private String configName;
@Schema(description = "配置键")
private String configKey;
@Schema(description = "配置值")
private String configValue;
@Schema(description = "描述、备注")
private String remark;
@Schema(description = "创建人ID")
@TableField(fill = FieldFill.INSERT)
private Long createBy;
@Schema(description = "更新人ID")
@TableField(fill = FieldFill.UPDATE)
private Long updateBy;
@TableLogic(value = "0", delval = "1")
private Integer isDeleted;
}
@@ -0,0 +1,59 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.boot.common.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;
/**
* 部门实体
*
* @author Ray
* @since 2024/06/23
*/
@TableName("sys_dept")
@Getter
@Setter
public class Dept extends BaseEntity {
/**
* 部门名称
*/
private String name;
/**
* 部门编码
*/
private String code;
/**
* 父节点id
*/
private Long parentId;
/**
* 父节点id路径
*/
private String treePath;
/**
* 显示顺序
*/
private Integer sort;
/**
* 状态(1-正常 0-禁用)
*/
private Integer status;
/**
* 创建人 ID
*/
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}
@@ -0,0 +1,37 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.boot.common.base.BaseEntity;
import lombok.Data;
/**
* 字典实体
*
* @author haoxr
* @since 2022/12/17
*/
@TableName("sys_dict")
@Data
public class Dict extends BaseEntity {
/**
* 类型名称
*/
private String name;
/**
* 类型编码
*/
private String code;
/**
* 状态(0:正常;1:禁用)
*/
private Integer status;
/**
* 备注
*/
private String remark;
}
@@ -0,0 +1,55 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 字典项实体
*
* @author haoxr
* @since 2022/12/17
*/
@TableName("sys_dict_item")
@Data
public class DictItem implements Serializable {
/**
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 字典类ID
*/
private Long dictId;
/**
* 字典项名称
*/
private String name;
/**
* 字典项值
*/
private String value;
/**
* 排序
*/
private Integer sort;
/**
* 状态(1-正常,0-禁用)
*/
private Integer status;
/**
* 备注
*/
private String remark;
}
@@ -0,0 +1,90 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.youlai.boot.common.enums.LogModuleEnum;
import lombok.Data;
/**
* 系统日志 实体类
*
* @author Ray
* @since 2.10.0
*/
@TableName("sys_log")
@Data
public class Log implements Serializable {
/**
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 日志模块
*/
private LogModuleEnum module;
/**
* 日志内容
*/
private String content;
/**
* 请求路径
*/
private String requestUri;
/**
* IP 地址
*/
private String ip;
/**
* 省份
*/
private String province;
/**
* 城市
*/
private String city;
/**
* 浏览器
*/
private String browser;
/**
* 浏览器版本
*/
private String browserVersion;
/**
* 终端系统
*/
private String os;
/**
* 执行时间(毫秒)
*/
private Long executionTime;
/**
* 创建人ID
*/
private Long createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
}
@@ -0,0 +1,113 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.youlai.boot.common.enums.MenuTypeEnum;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 菜单实体
*
* @author Ray
* @since 2023/3/6
*/
@TableName("sys_menu")
@Getter
@Setter
public class Menu {
/**
* 菜单ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 父菜单ID
*/
private Long parentId;
/**
* 菜单名称
*/
private String name;
/**
* 菜单类型(1-菜单;2-目录;3-外链;4-按钮权限)
*/
private MenuTypeEnum type;
/**
* 路由名称(Vue Router 中定义的路由名称)
*/
private String routeName;
/**
* 路由路径(Vue Router 中定义的 URL 路径)
*/
private String routePath;
/**
* 组件路径(vue页面完整路径,省略.vue后缀)
*/
private String component;
/**
* 权限标识
*/
private String perm;
/**
* 显示状态(1:显示;0:隐藏)
*/
private Integer visible;
/**
* 排序
*/
private Integer sort;
/**
* 菜单图标
*/
private String icon;
/**
* 跳转路径
*/
private String redirect;
/**
* 父节点路径,以英文逗号(,)分割
*/
private String treePath;
/**
* 【菜单】是否开启页面缓存(1:开启;0:关闭)
*/
private Integer keepAlive;
/**
* 【目录】只有一个子路由是否始终显示(1:是 0:否)
*/
private Integer alwaysShow;
/**
* 路由参数
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String params;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
@@ -0,0 +1,73 @@
package com.youlai.system.model.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.system.common.base.BaseEntity;
/**
* 通知公告实体对象
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Getter
@Setter
@TableName("sys_notice")
public class Notice extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 通知标题
*/
private String title;
/**
* 通知内容
*/
private String content;
/**
* 通知类型
*/
private Integer noticeType;
/**
* 发布人
*/
private Long releaseBy;
/**
* 优先级(0-低 1-中 2-高)
*/
private Integer priority;
/**
* 目标类型(0-全体 1-指定)
*/
private Integer tarType;
/**
* 发布状态(0-未发布 1已发布 2已撤回)
*/
private Integer sendStatus;
/**
* 发布时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sendTime;
/**
* 撤回时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime recallTime;
/**
* 创建人ID
*/
private Long createBy;
/**
* 更新人ID
*/
private Long updateBy;
/**
* 逻辑删除标识(0-未删除 1-已删除)
*/
private Integer isDelete;
}
@@ -0,0 +1,48 @@
package com.youlai.system.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.system.common.base.BaseEntity;
/**
* 用户公告状态实体对象
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Getter
@Setter
@TableName("sys_notice_status")
public class NoticeStatus implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 公共通知id
*/
private Long noticeId;
/**
* 用户id
*/
private Long userId;
/**
* 读取状态,0未读,1已读取
*/
private Long readStatus;
/**
* 用户阅读时间
*/
private LocalDateTime readTiem;
}
@@ -0,0 +1,53 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.boot.common.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;
/**
* 角色实体
*
* @author Ray
* @since 2024/6/23
*/
@TableName("sys_role")
@Getter
@Setter
public class Role extends BaseEntity {
/**
* 角色名称
*/
private String name;
/**
* 角色编码
*/
private String code;
/**
* 显示顺序
*/
private Integer sort;
/**
* 角色状态(1-正常 0-停用)
*/
private Integer status;
/**
* 数据权限
*/
private Integer dataScope;
/**
* 创建人 ID
*/
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}
@@ -0,0 +1,30 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 角色和菜单关联表
*/
@TableName("sys_role_menu")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RoleMenu {
/**
* 角色ID
*/
private Long roleId;
/**
* 菜单ID
*/
private Long menuId;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,70 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.youlai.boot.common.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;
/**
* 用户实体
*/
@TableName("sys_user")
@Getter
@Setter
public class User extends BaseEntity {
/**
* 用户名
*/
private String username;
/**
* 昵称
*/
private String nickname;
/**
* 性别((1-男 2-女 0-保密)
*/
private Integer gender;
/**
* 密码
*/
private String password;
/**
* 部门ID
*/
private Long deptId;
/**
* 用户头像
*/
private String avatar;
/**
* 联系方式
*/
private String mobile;
/**
* 状态((1-正常 0-禁用)
*/
private Integer status;
/**
* 用户邮箱
*/
private String email;
/**
* 创建人 ID
*/
private Long createBy;
/**
* 更新人 ID
*/
private Long updateBy;
}
@@ -0,0 +1,33 @@
package com.youlai.boot.system.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 用户和角色关联表
*
* @author haoxr
* @since 2022/12/17
*/
@TableName("sys_user_role")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRole {
/**
* 用户ID
*/
private Long userId;
/**
* 角色ID
*/
private Long roleId;
@TableField(exist = false)
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,41 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 系统配置 表单实体
*
* @author Theo
* @since 2024-07-29 11:17:26
*/
@Data
@Schema(description = "系统配置Form实体")
public class ConfigForm implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "主键")
private Long id;
@NotBlank(message = "配置名称不能为空")
@Schema(description = "配置名称")
private String configName;
@NotBlank(message = "配置键不能为空")
@Schema(description = "配置键")
private String configKey;
@NotBlank(message = "配置值不能为空")
@Schema(description = "配置值")
private String configValue;
@Schema(description = "描述、备注")
private String remark;
}
@@ -0,0 +1,34 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Range;
@Schema(description = "部门表单对象")
@Getter
@Setter
public class DeptForm {
@Schema(description="部门ID", example = "1001")
private Long id;
@Schema(description="部门名称", example = "研发部")
private String name;
@Schema(description="部门编号", example = "RD001")
private String code;
@Schema(description="父部门ID", example = "1000")
@NotNull(message = "父部门ID不能为空")
private Long parentId;
@Schema(description="状态(1:启用;0:禁用)", example = "1")
@Range(min = 0, max = 1, message = "状态值不正确")
private Integer status;
@Schema(description="排序(数字越小排名越靠前)", example = "1")
private Integer sort;
}
@@ -0,0 +1,61 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.Range;
import java.util.List;
/**
* 字典表单对象
*
* @author Ray Hao
* @since 2.9.0
*/
@Schema(description = "字典")
@Data
public class DictForm {
@Schema(description = "字典ID",example = "1")
private Long id;
@Schema(description = "字典名称",example = "性别")
private String name;
@Schema(description = "字典编码", example ="gender")
private String code;
@Schema(description = "字典状态(1-启用,0-禁用)", example = "1")
@Range(min = 0, max = 1, message = "字典状态不正确")
private Integer status;
@Schema(description = "字典数据项列表",example = "[{\"id\":1,\"name\":\"男\",\"value\":\"1\",\"sort\":1,\"status\":1},{\"id\":2,\"name\":\"女\",\"value\":\"2\",\"sort\":2,\"status\":1}]")
private List<DictItem> dictItems;
@Schema(description = "字典数据项")
@Getter
@Setter
public static class DictItem {
@Schema(description = "字典ID")
private Long id;
@Schema(description = "字典名称")
private String name;
@Schema(description = "字典值")
private String value;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "状态(1-启用,0-禁用)")
private Integer status;
}
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 修改邮箱表单
*
* @author Ray
* @since 2024/8/19
*/
@Schema(description = "修改邮箱表单")
@Data
public class EmailChangeForm {
@Schema(description = "原密码")
private String email;
@Schema(description = "验证码")
private String code;
}
@@ -0,0 +1,67 @@
package com.youlai.boot.system.model.form;
import com.youlai.boot.common.enums.MenuTypeEnum;
import com.youlai.boot.common.model.KeyValue;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import java.util.List;
/**
* 菜单表单对象
*
* @author Ray
* @since 2024/06/23
*/
@Schema(description = "菜单表单对象")
@Data
public class MenuForm {
@Schema(description = "菜单ID")
private Long id;
@Schema(description = "父菜单ID")
private Long parentId;
@Schema(description = "菜单名称")
private String name;
@Schema(description = "菜单类型(1-菜单 2-目录 3-外链 4-按钮)")
private MenuTypeEnum type;
@Schema(description = "路由名称")
private String routeName;
@Schema(description = "路由路径")
private String routePath;
@Schema(description = "组件路径(vue页面完整路径,省略.vue后缀)")
private String component;
@Schema(description = "权限标识")
private String perm;
@Schema(description = "显示状态(1:显示;0:隐藏)")
@Range(max = 1, min = 0, message = "显示状态不正确")
private Integer visible;
@Schema(description = "排序(数字越小排名越靠前)")
private Integer sort;
@Schema(description = "菜单图标")
private String icon;
@Schema(description = "跳转路径")
private String redirect;
@Schema(description = "【菜单】是否开启页面缓存", example = "1")
private Integer keepAlive;
@Schema(description = "【目录】只有一个子路由是否始终显示", example = "1")
private Integer alwaysShow;
@Schema(description = "路由参数")
private List<KeyValue> params;
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 修改手机表单
*
* @author Ray
* @since 2024/8/19
*/
@Schema(description = "修改手机表单")
@Data
public class MobileBindingForm {
@Schema(description = "原密码")
private String mobile;
@Schema(description = "验证码")
private String code;
}
@@ -0,0 +1,66 @@
package com.youlai.system.model.form;
import java.io.Serial;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import jakarta.validation.constraints.*;
/**
* 通知公告表单对象
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Getter
@Setter
@Schema(description = "通知公告表单对象")
public class NoticeForm implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
@Schema(description = "通知标题")
@NotBlank(message = "通知标题不能为空")
@Size(max=50, message="通知标题长度不能超过50个字符")
private String title;
@Schema(description = "通知内容")
@NotBlank(message = "通知内容不能为空")
@Size(max=65535, message="通知内容长度不能超过65535个字符")
private String content;
@Schema(description = "通知类型")
private Integer noticeType;
@Schema(description = "发布人")
@NotNull(message = "发布人不能为空")
private Long releaseBy;
@Schema(description = "优先级(0-低 1-中 2-高)")
private Integer priority;
@Schema(description = "目标类型(0-全体 1-指定)")
private Integer tarType;
@Schema(description = "发布状态(0-未发布 1已发布 2已撤回)")
private Integer sendStatus;
@Schema(description = "发布时间")
@NotNull(message = "发布时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime sendTime;
@Schema(description = "撤回时间")
@NotNull(message = "撤回时间不能为空")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime recallTime;
}
@@ -0,0 +1,26 @@
package com.youlai.system.model.form;
import java.io.Serial;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import jakarta.validation.constraints.*;
/**
* 用户公告状态表单对象
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Getter
@Setter
@Schema(description = "用户公告状态表单对象")
public class NoticeStatusForm implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 修改密码表单
*
* @author Ray
* @since 2024/8/13
*/
@Schema(description = "修改密码表单")
@Data
public class PasswordChangeForm {
@Schema(description = "原密码")
private String oldPassword;
@Schema(description = "新密码")
private String newPassword;
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 重置密码表单
*
* @author Ray
* @since 2024/8/13
*/
@Schema(description = "重置密码表单")
@Data
public class PasswordResetForm {
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "密码")
private String password;
}
@@ -0,0 +1,35 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
// import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;
@Schema(description = "角色表单对象")
@Data
public class RoleForm {
@Schema(description="角色ID")
private Long id;
@Schema(description="角色名称")
@NotBlank(message = "角色名称不能为空")
private String name;
@Schema(description="角色编码")
@NotBlank(message = "角色编码不能为空")
private String code;
@Schema(description="排序")
private Integer sort;
@Schema(description="角色状态(1-正常;0-停用)")
@Range(max = 1, min = 0, message = "角色状态不正确")
private Integer status;
@Schema(description="数据权限")
private Integer dataScope;
}
@@ -0,0 +1,59 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Range;
import java.util.List;
/**
* 用户表单对象
*
* @author haoxr
* @since 2022/4/12 11:04
*/
@Schema(description = "用户表单对象")
@Data
public class UserForm {
@Schema(description="用户ID")
private Long id;
@Schema(description="用户名")
@NotBlank(message = "用户名不能为空")
private String username;
@Schema(description="昵称")
@NotBlank(message = "昵称不能为空")
private String nickname;
@Schema(description="手机号码")
@Pattern(regexp = "^$|^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "手机号码格式不正确")
private String mobile;
@Schema(description="性别")
private Integer gender;
@Schema(description="用户头像")
private String avatar;
@Schema(description="邮箱")
private String email;
@Schema(description="用户状态(1:正常;0:禁用)")
@Range(min = 0, max = 1, message = "用户状态不正确")
private Integer status;
@Schema(description="部门ID")
private Long deptId;
@Schema(description="角色ID集合")
@NotEmpty(message = "用户角色不能为空")
private List<Long> roleIds;
}
@@ -0,0 +1,38 @@
package com.youlai.boot.system.model.form;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 个人中心用户信息
*
* @author Ray
* @since 2024/8/13
*/
@Schema(description = "个人中心用户信息")
@Data
public class UserProfileForm {
@Schema(description = "用户ID")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "用户昵称")
private String nickname;
@Schema(description = "头像URL")
private String avatar;
@Schema(description = "性别")
private Integer gender;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "邮箱")
private String email;
}
@@ -0,0 +1,21 @@
package com.youlai.boot.system.model.query;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
/**
* 系统配置查询对象
*
* @author Theo
* @since 2024-7-29 11:38:00
*/
@Getter
@Setter
@Schema(description = "系统配置分页查询")
public class ConfigPageQuery extends BasePageQuery {
@Schema(description="关键字(配置项名称/配置项值)")
private String keywords;
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 部门查询对象
*
* @author haoxr
* @since 2022/6/11
*/
@Schema(description ="部门分页查询对象")
@Data
public class DeptQuery {
@Schema(description="关键字(部门名称)")
private String keywords;
@Schema(description="状态(1->正常;0->禁用)")
private Integer status;
}
@@ -0,0 +1,17 @@
package com.youlai.boot.system.model.query;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description ="字典数据项分页查询对象")
@Data
public class DictPageQuery extends BasePageQuery {
@Schema(description="关键字(字典项名称)")
private String keywords;
@Schema(description="字典编码")
private String typeCode;
}
@@ -0,0 +1,26 @@
package com.youlai.boot.system.model.query;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 日志分页查询对象
*
* @author Ray
* @since 2.10.0
*/
@Schema(description = "日志分页查询对象")
@Getter
@Setter
public class LogPageQuery extends BasePageQuery {
@Schema(description="关键字(日志内容/请求路径/请求方法/地区/浏览器/终端系统)")
private String keywords;
@Schema(description="操作时间范围")
List<String> createTime;
}
@@ -0,0 +1,22 @@
package com.youlai.boot.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 菜单查询对象
*
* @author haoxr
* @since 2022/10/28
*/
@Schema(description ="部门分页查询对象")
@Data
public class MenuQuery {
@Schema(description="关键字(菜单名称)")
private String keywords;
@Schema(description="状态(1->显示;0->隐藏)")
private Integer status;
}
@@ -0,0 +1,41 @@
package com.youlai.system.model.query;
import com.youlai.system.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.List;
/**
* 通知公告分页查询对象
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Schema(description ="通知公告查询对象")
@Getter
@Setter
public class NoticeQuery extends BasePageQuery {
private static final long serialVersionUID = 1L;
@Schema(description = "通知标题")
private String title;
@Schema(description = "通知内容")
private String content;
@Schema(description = "通知类型")
private Integer noticeType;
@Schema(description = "发布人")
private Long releaseBy;
@Schema(description = "优先级(0-低 1-中 2-高)")
private Integer priority;
@Schema(description = "目标类型(0-全体 1-指定)")
private Integer tarType;
@Schema(description = "发布状态(0-未发布 1已发布 2已撤回)")
private Integer sendStatus;
@Schema(description = "发布时间")
private List<String> sendTime;
@Schema(description = "撤回时间")
private List<String> recallTime;
}
@@ -0,0 +1,33 @@
package com.youlai.system.model.query;
import com.youlai.system.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
import java.util.List;
/**
* 用户公告状态分页查询对象
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Schema(description ="用户公告状态查询对象")
@Getter
@Setter
public class NoticeStatusQuery extends BasePageQuery {
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private Long id;
@Schema(description = "公共通知id")
private Long noticeId;
@Schema(description = "用户id")
private Integer userId;
@Schema(description = "读取状态,0未读,1已读取")
private Long readStatus;
@Schema(description = "用户阅读时间")
private List<String> readTiem;
}
@@ -0,0 +1,23 @@
package com.youlai.boot.system.model.query;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 权限分页查询对象
*
* @author haoxr
* @since 2022/1/14 22:22
*/
@Data
@Schema
public class PermPageQuery extends BasePageQuery {
@Schema(description="权限名称")
private String name;
@Schema(description="菜单ID")
private Long menuId;
}
@@ -0,0 +1,32 @@
package com.youlai.boot.system.model.query;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 角色分页查询对象
*
* @author Ray
* @since 2022/6/3
*/
@Schema(description = "角色分页查询对象")
@Getter
@Setter
public class RolePageQuery extends BasePageQuery {
@Schema(description="关键字(角色名称/角色编码)")
private String keywords;
@Schema(description="开始日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime startDate;
@Schema(description="结束日期")
@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDateTime endDate;
}
@@ -0,0 +1,31 @@
package com.youlai.boot.system.model.query;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 数据表分页查询对象
*
* @author Ray
* @since 2.10.0
*/
@Schema(description = "数据表分页查询对象")
@Getter
@Setter
public class TablePageQuery extends BasePageQuery {
@Schema(description="关键字(表名)")
private String keywords;
/**
* 排除的表名
*/
@JsonIgnore
private List<String> excludeTables;
}
@@ -0,0 +1,31 @@
package com.youlai.boot.system.model.query;
import com.youlai.boot.common.base.BasePageQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 用户分页查询对象
*
* @author haoxr
* @since 2022/1/14
*/
@Schema(description ="用户分页查询对象")
@Data
public class UserPageQuery extends BasePageQuery {
@Schema(description="关键字(用户名/昵称/手机号)")
private String keywords;
@Schema(description="用户状态")
private Integer status;
@Schema(description="部门ID")
private Long deptId;
@Schema(description="创建时间范围")
private List<String> createTime;
}
@@ -0,0 +1,38 @@
package com.youlai.boot.system.model.vo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* 系统配置视图对象
*
* @author Theo
* @since 2024-07-30 14:49
*/
@Data
@Builder
@EqualsAndHashCode(callSuper = false)
@Schema(description = "系统配置VO")
public class ConfigVO {
@Schema(description = "主键")
private Long id;
@Schema(description = "配置名称")
private String configName;
@Schema(description = "配置键")
private String configKey;
@Schema(description = "配置值")
private String configValue;
@Schema(description = "描述、备注")
private String remark;
}
@@ -0,0 +1,42 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "部门视图对象")
@Data
public class DeptVO {
@Schema(description = "部门ID")
private Long id;
@Schema(description = "父部门ID")
private Long parentId;
@Schema(description = "部门名称")
private String name;
@Schema(description = "部门编号")
private String code;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "状态(1:启用;0:禁用)")
private Integer status;
@Schema(description = "子部门")
private List<DeptVO> children;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime createTime;
@Schema(description = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime updateTime;
}
@@ -0,0 +1,59 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* 字典分页VO
*
* @author Ray
* @since 0.0.1
*/
@Schema(description = "字典分页对象")
@Getter
@Setter
public class DictPageVO {
@Schema(description = "字典ID")
private Long id;
@Schema(description = "字典名称")
private String name;
@Schema(description = "字典编码")
private String code;
@Schema(description = "字典状态(1-启用,0-禁用)")
private Integer status;
@Schema(description = "字典项列表")
private List<DictItem> dictItems;
@Schema(description = "字典")
@Getter
@Setter
public static class DictItem {
@Schema(description = "字典项ID")
private Long id;
@Schema(description = "字典项名称")
private String name;
@Schema(description = "字典项值")
private String value;
@Schema(description = "排序")
private Integer sort;
@Schema(description = "状态(1-启用,0-禁用)")
private Integer status;
}
}
@@ -0,0 +1,19 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "代码生成代码预览VO")
@Data
public class GeneratorPreviewVO {
@Schema(description = "生成文件路径")
private String path;
@Schema(description = "生成文件名称",example = "SysUser.java" )
private String fileName;
@Schema(description = "生成文件内容")
private String content;
}
@@ -0,0 +1,59 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.youlai.boot.common.enums.LogModuleEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* 系统日志分页VO
*
* @author Ray
* @since 2.10.0
*/
@Data
@Schema(description = "系统日志分页VO")
public class LogPageVO implements Serializable {
@Schema(description = "主键")
private Long id;
@Schema(description = "日志模块")
private LogModuleEnum module;
@Schema(description = "日志内容")
private String content;
@Schema(description = "请求路径")
private String requestUri;
@Schema(description = "请求方法")
private String method;
@Schema(description = "IP 地址")
private String ip;
@Schema(description = "地区")
private String region;
@Schema(description = "浏览器")
private String browser;
@Schema(description = "终端系统")
private String os;
@Schema(description = "执行时间(毫秒)")
private Long executionTime;
@Schema(description = "创建人ID")
private Long createBy;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@Schema(description = "操作人")
private String operator;
}
@@ -0,0 +1,54 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.youlai.boot.common.enums.MenuTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description ="菜单视图对象")
@Data
public class MenuVO {
@Schema(description = "菜单ID")
private Long id;
@Schema(description = "父菜单ID")
private Long parentId;
@Schema(description = "菜单名称")
private String name;
@Schema(description="菜单类型")
private MenuTypeEnum type;
@Schema(description = "路由名称")
private String routeName;
@Schema(description = "路由路径")
private String routePath;
@Schema(description = "组件路径")
private String component;
@Schema(description = "菜单排序(数字越小排名越靠前)")
private Integer sort;
@Schema(description = "菜单是否可见(1:显示;0:隐藏)")
private Integer visible;
@Schema(description = "ICON")
private String icon;
@Schema(description = "跳转路径")
private String redirect;
@Schema(description="按钮权限标识")
private String perm;
@Schema(description = "子菜单")
@JsonInclude(value = JsonInclude.Include.NON_NULL)
private List<MenuVO> children;
}
@@ -0,0 +1,35 @@
package com.youlai.system.model.vo;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 用户公告状态视图对象
*
* @author youlaitech
* @since 2024-08-28 16:56
*/
@Getter
@Setter
@Schema( description = "用户公告状态视图对象")
public class NoticeStatusVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "id")
private Long id;
@Schema(description = "公共通知id")
private Long noticeId;
@Schema(description = "用户id")
private Integer userId;
@Schema(description = "读取状态,0未读,1已读取")
private Long readStatus;
@Schema(description = "用户阅读时间")
private LocalDateTime readTiem;
}
@@ -0,0 +1,48 @@
package com.youlai.system.model.vo;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
/**
* 通知公告视图对象
*
* @author youlaitech
* @since 2024-08-27 10:31
*/
@Getter
@Setter
@Schema( description = "通知公告视图对象")
public class NoticeVO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
@Schema(description = "通知标题")
private String title;
@Schema(description = "通知内容")
private String content;
@Schema(description = "通知类型")
private Integer noticeType;
@Schema(description = "发布人")
private Long releaseBy;
@Schema(description = "优先级(0-低 1-中 2-高)")
private Integer priority;
@Schema(description = "目标类型(0-全体 1-指定)")
private Integer tarType;
@Schema(description = "发布状态(0-未发布 1已发布 2已撤回)")
private Integer sendStatus;
@Schema(description = "发布时间")
private LocalDateTime sendTime;
@Schema(description = "撤回时间")
private LocalDateTime recallTime;
@Schema(description = "创建时间")
private LocalDateTime createTime;
@Schema(description = "更新时间")
private LocalDateTime updateTime;
}
@@ -0,0 +1,33 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description ="角色分页对象")
@Data
public class RolePageVO {
@Schema(description="角色ID")
private Long id;
@Schema(description="角色名称")
private String name;
@Schema(description="角色编码")
private String code;
@Schema(description="角色状态")
private Integer status;
@Schema(description="排序")
private Integer sort;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}
@@ -0,0 +1,63 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 菜单路由视图对象
*
* @author haoxr
* @since 2020/11/28
*/
@Schema(description = "路由对象")
@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class RouteVO {
@Schema(description = "路由路径", example = "user")
private String path;
@Schema(description = "组件路径", example = "system/user/index")
private String component;
@Schema(description = "跳转链接", example = "https://www.youlai.tech")
private String redirect;
@Schema(description = "路由名称")
private String name;
@Schema(description = "路由属性")
private Meta meta;
@Schema(description = "路由属性类型")
@Data
public static class Meta {
@Schema(description = "路由title")
private String title;
@Schema(description = "ICON")
private String icon;
@Schema(description = "是否隐藏(true-是 false-否)", example = "true")
private Boolean hidden;
@Schema(description = "【菜单】是否开启页面缓存", example = "true")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean keepAlive;
@Schema(description = "【目录】只有一个子路由是否始终显示", example = "true")
@JsonInclude(JsonInclude.Include.NON_NULL)
private Boolean alwaysShow;
@Schema(description = "路由参数")
private Map<String,String> params;
}
@Schema(description = "子路由列表")
private List<RouteVO> children;
}
@@ -0,0 +1,32 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "表视图对象")
@Data
public class TablePageVO {
@Schema(description = "表名称", example = "sys_user")
private String tableName;
@Schema(description = "表描述",example = "用户表")
private String tableComment;
@Schema(description = "表排序规则",example = "utf8mb4_general_ci")
private String tableCollation;
@Schema(description = "存储引擎",example = "InnoDB")
private String engine;
@Schema(description = "字符集",example = "utf8mb4")
private String charset;
@Schema(description = "创建时间",example = "2023-08-08 08:08:08")
private String createTime;
@Schema(description="是否已配置")
private Integer isConfigured;
}
@@ -0,0 +1,36 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Set;
/**
* 用户登录视图对象
*
* @author haoxr
* @since 2022/1/14
*/
@Schema(description ="当前登录用户视图对象")
@Data
public class UserInfoVO {
@Schema(description="用户ID")
private Long userId;
@Schema(description="用户名")
private String username;
@Schema(description="用户昵称")
private String nickname;
@Schema(description="头像地址")
private String avatar;
@Schema(description="用户角色编码集合")
private Set<String> roles;
@Schema(description="用户权限标识集合")
private Set<String> perms;
}
@@ -0,0 +1,53 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
/**
* 用户分页视图对象
*
* @author haoxr
* @since 2022/1/15 9:41
*/
@Schema(description ="用户分页对象")
@Data
public class UserPageVO {
@Schema(description="用户ID")
private Long id;
@Schema(description="用户名")
private String username;
@Schema(description="用户昵称")
private String nickname;
@Schema(description="手机号")
private String mobile;
@Schema(description="性别")
private String genderLabel;
@Schema(description="用户头像地址")
private String avatar;
@Schema(description="用户邮箱")
private String email;
@Schema(description="用户状态(1:启用;0:禁用)")
private Integer status;
@Schema(description="部门名称")
private String deptName;
@Schema(description="角色名称,多个使用英文逗号(,)分割")
private String roleNames;
@Schema(description="创建时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
}
@@ -0,0 +1,50 @@
package com.youlai.boot.system.model.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
/**
* 个人中心用户信息
*
* @author Ray
* @since 2024/8/13
*/
@Schema(description = "个人中心用户信息")
@Data
public class UserProfileVO {
@Schema(description = "用户ID")
private Long id;
@Schema(description = "用户名")
private String username;
@Schema(description = "用户昵称")
private String nickname;
@Schema(description = "头像URL")
private String avatar;
@Schema(description = "性别")
private Integer gender;
@Schema(description = "手机号")
private String mobile;
@Schema(description = "邮箱")
private String email;
@Schema(description = "部门名称")
private String deptName;
@Schema(description = "角色名称")
private String roleNames;
@Schema(description = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date createTime;
}
@@ -0,0 +1,38 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.math.BigDecimal;
/**
* 访问量统计VO
*
* @author Ray
* @since 2024/7/2
*/
@Schema(description = "访问量统计VO")
@Getter
@Setter
public class VisitStatsVO {
@Schema(description = "统计类型")
private String type;
@Schema(description = "标题")
private String title;
@Schema(description = "今日访问量")
private Integer todayCount;
@Schema(description = "总访问量")
private Integer totalCount;
@Schema(description = "增长率")
private BigDecimal growthRate;
@Schema(description = "统计粒度标签")
private String granularityLabel;
}
@@ -0,0 +1,27 @@
package com.youlai.boot.system.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Schema(description = "访问趋势VO")
@Getter
@Setter
public class VisitTrendVO {
@Schema(description = "日期列表")
private List<String> dates;
@Schema(description = "浏览量(PV)")
private List<Integer> pvList;
@Schema(description = "访客数(UV)")
private List<Integer> uvList;
@Schema(description = "IP数")
private List<Integer> ipList;
}
@@ -0,0 +1,68 @@
package com.youlai.boot.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.boot.system.model.entity.Config;
import com.youlai.boot.system.model.form.ConfigForm;
import com.youlai.boot.system.model.query.ConfigPageQuery;
import com.youlai.boot.system.model.vo.ConfigVO;
/**
* 系统配置Service接口
*
* @author Theo
* @since 2024-07-29 11:17:26
*/
public interface ConfigService extends IService<Config> {
/**
* 分页查询系统配置
* @param sysConfigPageQuery 查询参数
* @return 系统配置分页列表
*/
IPage<ConfigVO> page(ConfigPageQuery sysConfigPageQuery);
/**
* 保存系统配置
* @param sysConfigForm 系统配置表单
* @return 是否保存成功
*/
boolean save(ConfigForm sysConfigForm);
/**
* 获取系统配置表单数据
*
* @param id 系统配置ID
* @return 系统配置表单数据
*/
ConfigForm getConfigFormData(Long id);
/**
* 编辑系统配置
* @param id 系统配置ID
* @param sysConfigForm 系统配置表单
* @return 是否编辑成功
*/
boolean edit(Long id, ConfigForm sysConfigForm);
/**
* 删除系统配置
* @param ids 系统配置ID
* @return 是否删除成功
*/
boolean delete(Long ids);
/**
* 刷新系统配置缓存
* @return 是否刷新成功
*/
boolean refreshCache();
/**
* 获取系统配置
* @param key 配置键
* @return 配置值
*/
Object getSystemConfig(String key);
}
Loaded 100 of 252 files, more files were not shown because too many files have changed in this diff. Show more