update 同步 ruoyi
* update element-ui 2.15.10 => 2.15.12
* update 优化 tagsView右选框,首页不应该存在关闭左侧选项
* update copyright 2023
* update 优化 监控页面图标显示
* update 优化 日志注解支持排除指定的请求参数
* update 优化 业务校验优化代码
* fix 修复 优化文件下载出现的异常
* fix 修复 修改密码日志存储明文问题
* add 新增 操作日志消耗时间属性
* update 优化 日志管理使用索引提升查询性能
* update 优化 框架时间检索使用时间默认值 00:00:00 - 23:59:59
| | |
| | | import cn.dev33.satoken.secure.BCrypt; |
| | | import com.ruoyi.common.core.constant.Constants; |
| | | import com.ruoyi.common.core.constant.GlobalConstants; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.model.RegisterBody; |
| | | import com.ruoyi.common.core.enums.UserType; |
| | | import com.ruoyi.common.core.exception.user.CaptchaException; |
| | |
| | | sysUser.setPassword(BCrypt.hashpw(password)); |
| | | sysUser.setUserType(userType); |
| | | |
| | | if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) { |
| | | if (!userService.checkUserNameUnique(sysUser)) { |
| | | throw new UserException("user.register.save.error", username); |
| | | } |
| | | boolean regFlag = userService.registerUser(sysUser, tenantId); |
| | |
| | | String DISABLE = "1"; |
| | | |
| | | /** |
| | | * 校验返回结果码 |
| | | */ |
| | | String PASS = "0"; |
| | | String NOT_PASS = "1"; |
| | | |
| | | /** |
| | | * 超级管理员ID |
| | | */ |
| | | Long SUPER_ADMIN_ID = 1L; |
| | |
| | | String INNER_LINK = "InnerLink"; |
| | | |
| | | /** |
| | | * 校验返回结果码 |
| | | */ |
| | | String UNIQUE = "0"; |
| | | String NOT_UNIQUE = "1"; |
| | | |
| | | /** |
| | | * 用户名长度限制 |
| | | */ |
| | | int USERNAME_MIN_LENGTH = 2; |
| | |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>transmittable-thread-local</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| | |
| | | * 是否保存响应的参数 |
| | | */ |
| | | boolean isSaveResponseData() default true; |
| | | |
| | | |
| | | /** |
| | | * 排除指定的请求参数 |
| | | */ |
| | | String[] excludeParamNames() default {}; |
| | | |
| | | } |
| | |
| | | import cn.hutool.core.lang.Dict; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.alibaba.ttl.TransmittableThreadLocal; |
| | | import com.ruoyi.common.core.utils.ServletUtils; |
| | | import com.ruoyi.common.core.utils.SpringUtils; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.time.StopWatch; |
| | | import org.aspectj.lang.JoinPoint; |
| | | import org.aspectj.lang.annotation.AfterReturning; |
| | | import org.aspectj.lang.annotation.AfterThrowing; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.annotation.Before; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.validation.BindingResult; |
| | |
| | | * 排除敏感属性字段 |
| | | */ |
| | | public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; |
| | | |
| | | |
| | | /** |
| | | * 计算操作消耗时间 |
| | | */ |
| | | private static final ThreadLocal<StopWatch> TIME_THREADLOCAL = new TransmittableThreadLocal<>(); |
| | | |
| | | /** |
| | | * 处理请求前执行 |
| | | */ |
| | | @Before(value = "@annotation(controllerLog)") |
| | | public void boBefore(JoinPoint joinPoint, Log controllerLog) { |
| | | StopWatch stopWatch = new StopWatch(); |
| | | TIME_THREADLOCAL.set(stopWatch); |
| | | stopWatch.start(); |
| | | } |
| | | |
| | | /** |
| | | * 处理完请求后执行 |
| | |
| | | operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); |
| | | // 处理设置注解上的参数 |
| | | getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); |
| | | // 设置消耗时间 |
| | | StopWatch stopWatch = TIME_THREADLOCAL.get(); |
| | | stopWatch.stop(); |
| | | operLog.setCostTime(stopWatch.getTime()); |
| | | // 发布事件保存数据库 |
| | | SpringUtils.context().publishEvent(operLog); |
| | | } catch (Exception exp) { |
| | | // 记录本地异常日志 |
| | | log.error("异常信息:{}", exp.getMessage()); |
| | | exp.printStackTrace(); |
| | | } finally { |
| | | TIME_THREADLOCAL.remove(); |
| | | } |
| | | } |
| | | |
| | |
| | | // 是否需要保存request,参数和值 |
| | | if (log.isSaveRequestData()) { |
| | | // 获取参数的信息,传入到数据库中。 |
| | | setRequestValue(joinPoint, operLog); |
| | | setRequestValue(joinPoint, operLog, log.excludeParamNames()); |
| | | } |
| | | // 是否需要保存response,参数和值 |
| | | if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { |
| | |
| | | * @param operLog 操作日志 |
| | | * @throws Exception 异常 |
| | | */ |
| | | private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog) throws Exception { |
| | | private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog, String[] excludeParamNames) throws Exception { |
| | | Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); |
| | | String requestMethod = operLog.getRequestMethod(); |
| | | if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { |
| | | String params = argsArrayToString(joinPoint.getArgs()); |
| | | if (MapUtil.isEmpty(paramsMap) |
| | | && HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { |
| | | String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); |
| | | operLog.setOperParam(StringUtils.substring(params, 0, 2000)); |
| | | } else { |
| | | Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); |
| | | MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES); |
| | | MapUtil.removeAny(paramsMap, excludeParamNames); |
| | | operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000)); |
| | | } |
| | | } |
| | |
| | | /** |
| | | * 参数拼装 |
| | | */ |
| | | private String argsArrayToString(Object[] paramsArray) { |
| | | private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) { |
| | | StringBuilder params = new StringBuilder(); |
| | | if (paramsArray != null && paramsArray.length > 0) { |
| | | for (Object o : paramsArray) { |
| | |
| | | Dict dict = JsonUtils.parseMap(str); |
| | | if (MapUtil.isNotEmpty(dict)) { |
| | | MapUtil.removeAny(dict, EXCLUDE_PROPERTIES); |
| | | MapUtil.removeAny(dict, excludeParamNames); |
| | | str = JsonUtils.toJsonString(dict); |
| | | } |
| | | params.append(str).append(" "); |
| | |
| | | */ |
| | | private Date operTime; |
| | | |
| | | /** |
| | | * 消耗时间 |
| | | */ |
| | | private Long costTime; |
| | | } |
| | |
| | | <el-date-picker |
| | | v-model="daterange${AttrName}" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | #end |
| | |
| | | <el-date-picker |
| | | v-model="daterange${AttrName}" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | #end |
| | |
| | | <el-form-item label="${comment}" style="width: 308px"> |
| | | <el-date-picker |
| | | v-model="daterange${AttrName}" |
| | | value-format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | #end |
| | |
| | | <el-form-item label="${comment}" style="width: 308px"> |
| | | <el-date-picker |
| | | v-model="daterange${AttrName}" |
| | | value-format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | #end |
| | |
| | | package com.ruoyi.system.controller.system; |
| | | |
| | | import cn.dev33.satoken.annotation.SaCheckPermission; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.web.core.BaseController; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.excel.utils.ExcelUtil; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.web.core.BaseController; |
| | | import com.ruoyi.system.domain.bo.SysConfigBo; |
| | | import com.ruoyi.system.domain.vo.SysConfigVo; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "参数管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysConfigBo config) { |
| | | if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { |
| | | if (!configService.checkConfigKeyUnique(config)) { |
| | | return R.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); |
| | | } |
| | | configService.insertConfig(config); |
| | |
| | | @Log(title = "参数管理", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | public R<Void> edit(@Validated @RequestBody SysConfigBo config) { |
| | | if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { |
| | | if (!configService.checkConfigKeyUnique(config)) { |
| | | return R.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); |
| | | } |
| | | configService.updateConfig(config); |
| | |
| | | @Log(title = "部门管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysDeptBo dept) { |
| | | if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { |
| | | if (!deptService.checkDeptNameUnique(dept)) { |
| | | return R.fail("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在"); |
| | | } |
| | | return toAjax(deptService.insertDept(dept)); |
| | |
| | | public R<Void> edit(@Validated @RequestBody SysDeptBo dept) { |
| | | Long deptId = dept.getDeptId(); |
| | | deptService.checkDeptDataScope(deptId); |
| | | if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) { |
| | | if (!deptService.checkDeptNameUnique(dept)) { |
| | | return R.fail("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在"); |
| | | } else if (dept.getParentId().equals(deptId)) { |
| | | return R.fail("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己"); |
| | |
| | | package com.ruoyi.system.controller.system; |
| | | |
| | | import cn.dev33.satoken.annotation.SaCheckPermission; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.excel.utils.ExcelUtil; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | |
| | | @Log(title = "字典类型", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysDictTypeBo dict) { |
| | | if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { |
| | | if (!dictTypeService.checkDictTypeUnique(dict)) { |
| | | return R.fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); |
| | | } |
| | | dictTypeService.insertDictType(dict); |
| | |
| | | @Log(title = "字典类型", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | public R<Void> edit(@Validated @RequestBody SysDictTypeBo dict) { |
| | | if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { |
| | | if (!dictTypeService.checkDictTypeUnique(dict)) { |
| | | return R.fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); |
| | | } |
| | | dictTypeService.updateDictType(dict); |
| | |
| | | @Log(title = "菜单管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysMenuBo menu) { |
| | | if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { |
| | | if (!menuService.checkMenuNameUnique(menu)) { |
| | | return R.fail("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); |
| | | } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { |
| | | return R.fail("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); |
| | |
| | | @Log(title = "菜单管理", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | public R<Void> edit(@Validated @RequestBody SysMenuBo menu) { |
| | | if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu))) { |
| | | if (!menuService.checkMenuNameUnique(menu)) { |
| | | return R.fail("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在"); |
| | | } else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath())) { |
| | | return R.fail("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头"); |
| | |
| | | package com.ruoyi.system.controller.system; |
| | | |
| | | import cn.dev33.satoken.annotation.SaCheckPermission; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.web.core.BaseController; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.excel.utils.ExcelUtil; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.web.core.BaseController; |
| | | import com.ruoyi.system.domain.bo.SysPostBo; |
| | | import com.ruoyi.system.domain.vo.SysPostVo; |
| | | import com.ruoyi.system.service.ISysPostService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | /** |
| | |
| | | @Log(title = "岗位管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysPostBo post) { |
| | | if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) { |
| | | if (!postService.checkPostNameUnique(post)) { |
| | | return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在"); |
| | | } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { |
| | | } else if (!postService.checkPostCodeUnique(post)) { |
| | | return R.fail("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在"); |
| | | } |
| | | return toAjax(postService.insertPost(post)); |
| | |
| | | @Log(title = "岗位管理", businessType = BusinessType.UPDATE) |
| | | @PutMapping |
| | | public R<Void> edit(@Validated @RequestBody SysPostBo post) { |
| | | if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post))) { |
| | | if (!postService.checkPostNameUnique(post)) { |
| | | return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在"); |
| | | } else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post))) { |
| | | } else if (!postService.checkPostCodeUnique(post)) { |
| | | return R.fail("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在"); |
| | | } |
| | | return toAjax(postService.updatePost(post)); |
| | |
| | | import cn.dev33.satoken.secure.BCrypt; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.io.FileUtil; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.core.utils.file.MimeTypeUtils; |
| | |
| | | @PutMapping |
| | | public R<Void> updateProfile(@RequestBody SysUserProfileBo profile) { |
| | | SysUserBo user = BeanUtil.toBean(profile, SysUserBo.class); |
| | | if (StringUtils.isNotEmpty(user.getPhonenumber()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { |
| | | if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { |
| | | return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); |
| | | } |
| | | if (StringUtils.isNotEmpty(user.getEmail()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { |
| | | if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { |
| | | return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); |
| | | } |
| | | user.setUserId(LoginHelper.getUserId()); |
| | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import com.ruoyi.common.core.constant.GlobalConstants; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.domain.model.LoginUser; |
| | | import com.ruoyi.common.excel.utils.ExcelUtil; |
| | |
| | | @Log(title = "角色管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysRoleBo role) { |
| | | if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { |
| | | if (!roleService.checkRoleNameUnique(role)) { |
| | | return R.fail("新增角色'" + role.getRoleName() + "'失败,角色名称已存在"); |
| | | } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { |
| | | } else if (!roleService.checkRoleKeyUnique(role)) { |
| | | return R.fail("新增角色'" + role.getRoleName() + "'失败,角色权限已存在"); |
| | | } |
| | | return toAjax(roleService.insertRole(role)); |
| | |
| | | public R<Void> edit(@Validated @RequestBody SysRoleBo role) { |
| | | roleService.checkRoleAllowed(role); |
| | | roleService.checkRoleDataScope(role.getRoleId()); |
| | | if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) { |
| | | if (!roleService.checkRoleNameUnique(role)) { |
| | | return R.fail("修改角色'" + role.getRoleName() + "'失败,角色名称已存在"); |
| | | } else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) { |
| | | } else if (!roleService.checkRoleKeyUnique(role)) { |
| | | return R.fail("修改角色'" + role.getRoleName() + "'失败,角色权限已存在"); |
| | | } |
| | | |
| | |
| | | import cn.dev33.satoken.annotation.SaCheckRole; |
| | | import com.baomidou.lock.annotation.Lock4j; |
| | | import com.ruoyi.common.core.constant.TenantConstants; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.validate.AddGroup; |
| | |
| | | @RepeatSubmit() |
| | | @PostMapping() |
| | | public R<Void> add(@Validated(AddGroup.class) @RequestBody SysTenantBo bo) { |
| | | if (TenantConstants.NOT_PASS.equals(sysTenantService.checkCompanyNameUnique(bo))) { |
| | | if (!sysTenantService.checkCompanyNameUnique(bo)) { |
| | | throw new ServiceException("新增租户'" + bo.getCompanyName() + "'失败,企业名称已存在"); |
| | | } |
| | | SysUserBo userBo = new SysUserBo(); |
| | | userBo.setUserName(bo.getUsername()); |
| | | // 判断用户名是否重复 |
| | | if (UserConstants.NOT_UNIQUE.equals(sysUserService.checkUserNameUnique(userBo))) { |
| | | if (!sysUserService.checkUserNameUnique(userBo)) { |
| | | throw new ServiceException("新增用户'" + bo.getUsername() + "'失败,登录账号已存在"); |
| | | } |
| | | return toAjax(sysTenantService.insertByBo(bo)); |
| | |
| | | @RepeatSubmit() |
| | | @PutMapping() |
| | | public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysTenantBo bo) { |
| | | if (UserConstants.NOT_UNIQUE.equals(sysTenantService.checkCompanyNameUnique(bo))) { |
| | | if (!sysTenantService.checkCompanyNameUnique(bo)) { |
| | | throw new ServiceException("修改租户'" + bo.getCompanyName() + "'失败,公司名称已存在"); |
| | | } |
| | | return toAjax(sysTenantService.updateByBo(bo)); |
| | |
| | | import cn.hutool.core.lang.tree.Tree; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.ruoyi.common.core.constant.TenantConstants; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.utils.MapstructUtils; |
| | | import com.ruoyi.common.core.utils.StreamUtils; |
| | |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.tenant.helper.TenantHelper; |
| | | import com.ruoyi.common.satoken.utils.LoginHelper; |
| | | import com.ruoyi.common.tenant.helper.TenantHelper; |
| | | import com.ruoyi.common.web.core.BaseController; |
| | | import com.ruoyi.system.domain.bo.SysDeptBo; |
| | | import com.ruoyi.system.domain.bo.SysUserBo; |
| | |
| | | @Log(title = "用户管理", businessType = BusinessType.INSERT) |
| | | @PostMapping |
| | | public R<Void> add(@Validated @RequestBody SysUserBo user) { |
| | | if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { |
| | | if (!userService.checkUserNameUnique(user)) { |
| | | return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); |
| | | } else if (StringUtils.isNotEmpty(user.getPhonenumber()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { |
| | | } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { |
| | | return R.fail("新增用户'" + user.getUserName() + "'失败,手机号码已存在"); |
| | | } else if (StringUtils.isNotEmpty(user.getEmail()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { |
| | | } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { |
| | | return R.fail("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在"); |
| | | } |
| | | if (TenantHelper.isEnable()) { |
| | | String status = tenantService.checkAccountBalance(LoginHelper.getTenantId()); |
| | | if (TenantConstants.NOT_PASS.equals(status)) { |
| | | if (!tenantService.checkAccountBalance(LoginHelper.getTenantId())) { |
| | | return R.fail("当前租户下用户名额不足,请联系管理员"); |
| | | } |
| | | } |
| | |
| | | public R<Void> edit(@Validated @RequestBody SysUserBo user) { |
| | | userService.checkUserAllowed(user); |
| | | userService.checkUserDataScope(user.getUserId()); |
| | | if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { |
| | | if (!userService.checkUserNameUnique(user)) { |
| | | return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); |
| | | } else if (StringUtils.isNotEmpty(user.getPhonenumber()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { |
| | | } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user)) { |
| | | return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); |
| | | } else if (StringUtils.isNotEmpty(user.getEmail()) |
| | | && UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user))) { |
| | | } else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user)) { |
| | | return R.fail("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在"); |
| | | } |
| | | return toAjax(userService.updateUser(user)); |
| | |
| | | */ |
| | | private Date operTime; |
| | | |
| | | /** |
| | | * 消耗时间 |
| | | */ |
| | | private Long costTime; |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.domain.bo; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.ruoyi.common.log.event.OperLogEvent; |
| | | import com.ruoyi.system.domain.SysOperLog; |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | |
| | | private Date operTime; |
| | | |
| | | /** |
| | | * 消耗时间 |
| | | */ |
| | | private Long costTime; |
| | | |
| | | /** |
| | | * 请求参数 |
| | | */ |
| | | @TableField(exist = false) |
| | | private Map<String, Object> params = new HashMap<>(); |
| | | |
| | | } |
| | |
| | | package com.ruoyi.system.domain.vo; |
| | | |
| | | import java.util.Date; |
| | | |
| | | import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; |
| | | import com.alibaba.excel.annotation.ExcelProperty; |
| | | import com.ruoyi.common.excel.annotation.ExcelDictFormat; |
| | |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | |
| | | /** |
| | |
| | | @ExcelProperty(value = "操作时间") |
| | | private Date operTime; |
| | | |
| | | |
| | | /** |
| | | * 消耗时间 |
| | | */ |
| | | @ExcelProperty(value = "消耗时间") |
| | | private Long costTime; |
| | | } |
| | |
| | | * @param config 参数信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkConfigKeyUnique(SysConfigBo config); |
| | | boolean checkConfigKeyUnique(SysConfigBo config); |
| | | |
| | | } |
| | |
| | | * @param dept 部门信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkDeptNameUnique(SysDeptBo dept); |
| | | boolean checkDeptNameUnique(SysDeptBo dept); |
| | | |
| | | /** |
| | | * 校验部门是否有数据权限 |
| | |
| | | * @param dictType 字典类型 |
| | | * @return 结果 |
| | | */ |
| | | String checkDictTypeUnique(SysDictTypeBo dictType); |
| | | boolean checkDictTypeUnique(SysDictTypeBo dictType); |
| | | } |
| | |
| | | * @param menu 菜单信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkMenuNameUnique(SysMenuBo menu); |
| | | boolean checkMenuNameUnique(SysMenuBo menu); |
| | | } |
| | |
| | | * @param post 岗位信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkPostNameUnique(SysPostBo post); |
| | | boolean checkPostNameUnique(SysPostBo post); |
| | | |
| | | /** |
| | | * 校验岗位编码 |
| | |
| | | * @param post 岗位信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkPostCodeUnique(SysPostBo post); |
| | | boolean checkPostCodeUnique(SysPostBo post); |
| | | |
| | | /** |
| | | * 通过岗位ID查询岗位使用数量 |
| | |
| | | * @param role 角色信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkRoleNameUnique(SysRoleBo role); |
| | | boolean checkRoleNameUnique(SysRoleBo role); |
| | | |
| | | /** |
| | | * 校验角色权限是否唯一 |
| | |
| | | * @param role 角色信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkRoleKeyUnique(SysRoleBo role); |
| | | boolean checkRoleKeyUnique(SysRoleBo role); |
| | | |
| | | /** |
| | | * 校验角色是否允许操作 |
| | |
| | | /** |
| | | * 校验企业名称是否唯一 |
| | | */ |
| | | String checkCompanyNameUnique(SysTenantBo bo); |
| | | boolean checkCompanyNameUnique(SysTenantBo bo); |
| | | |
| | | /** |
| | | * 校验账号余额 |
| | | */ |
| | | String checkAccountBalance(String tenantId); |
| | | boolean checkAccountBalance(String tenantId); |
| | | |
| | | /** |
| | | * 校验有效期 |
| | | */ |
| | | String checkExpireTime(String tenantId); |
| | | boolean checkExpireTime(String tenantId); |
| | | |
| | | /** |
| | | * 同步租户套餐 |
| | |
| | | * @param user 用户信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkUserNameUnique(SysUserBo user); |
| | | boolean checkUserNameUnique(SysUserBo user); |
| | | |
| | | /** |
| | | * 校验手机号码是否唯一 |
| | |
| | | * @param user 用户信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkPhoneUnique(SysUserBo user); |
| | | boolean checkPhoneUnique(SysUserBo user); |
| | | |
| | | /** |
| | | * 校验email是否唯一 |
| | |
| | | * @param user 用户信息 |
| | | * @return 结果 |
| | | */ |
| | | String checkEmailUnique(SysUserBo user); |
| | | boolean checkEmailUnique(SysUserBo user); |
| | | |
| | | /** |
| | | * 校验用户是否允许操作 |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkConfigKeyUnique(SysConfigBo config) { |
| | | public boolean checkConfigKeyUnique(SysConfigBo config) { |
| | | long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId(); |
| | | SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey())); |
| | | if (ObjectUtil.isNotNull(info) && info.getConfigId() != configId) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | return false; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkDeptNameUnique(SysDeptBo dept) { |
| | | public boolean checkDeptNameUnique(SysDeptBo dept) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDept>() |
| | | .eq(SysDept::getDeptName, dept.getDeptName()) |
| | | .eq(SysDept::getParentId, dept.getParentId()) |
| | | .ne(ObjectUtil.isNotNull(dept.getDeptId()), SysDept::getDeptId, dept.getDeptId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.common.core.constant.CacheConstants; |
| | | import com.ruoyi.common.core.constant.CacheNames; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.service.DictService; |
| | | import com.ruoyi.common.core.utils.MapstructUtils; |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkDictTypeUnique(SysDictTypeBo dictType) { |
| | | public boolean checkDictTypeUnique(SysDictTypeBo dictType) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysDictType>() |
| | | .eq(SysDictType::getDictType, dictType.getDictType()) |
| | | .ne(ObjectUtil.isNotNull(dictType.getDictId()), SysDictType::getDictId, dictType.getDictId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | router.setQuery(menu.getQueryParam()); |
| | | router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath())); |
| | | List<SysMenu> cMenus = menu.getChildren(); |
| | | if (!cMenus.isEmpty() && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { |
| | | if (CollUtil.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType())) { |
| | | router.setAlwaysShow(true); |
| | | router.setRedirect("noRedirect"); |
| | | router.setChildren(buildMenus(cMenus)); |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkMenuNameUnique(SysMenuBo menu) { |
| | | public boolean checkMenuNameUnique(SysMenuBo menu) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysMenu>() |
| | | .eq(SysMenu::getMenuName, menu.getMenuName()) |
| | | .eq(SysMenu::getParentId, menu.getParentId()) |
| | | .ne(ObjectUtil.isNotNull(menu.getMenuId()), SysMenu::getMenuId, menu.getMenuId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.common.core.constant.CacheNames; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.MapstructUtils; |
| | | import com.ruoyi.common.core.utils.StreamUtils; |
| | |
| | | */ |
| | | private void validEntityBeforeSave(SysOssConfig entity) { |
| | | if (StringUtils.isNotEmpty(entity.getConfigKey()) |
| | | && UserConstants.NOT_UNIQUE.equals(checkConfigKeyUnique(entity))) { |
| | | && !checkConfigKeyUnique(entity)) { |
| | | throw new ServiceException("操作配置'" + entity.getConfigKey() + "'失败, 配置key已存在!"); |
| | | } |
| | | } |
| | |
| | | /** |
| | | * 判断configKey是否唯一 |
| | | */ |
| | | private String checkConfigKeyUnique(SysOssConfig sysOssConfig) { |
| | | private boolean checkConfigKeyUnique(SysOssConfig sysOssConfig) { |
| | | long ossConfigId = ObjectUtil.isNull(sysOssConfig.getOssConfigId()) ? -1L : sysOssConfig.getOssConfigId(); |
| | | SysOssConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysOssConfig>() |
| | | .select(SysOssConfig::getOssConfigId, SysOssConfig::getConfigKey) |
| | | .eq(SysOssConfig::getConfigKey, sysOssConfig.getConfigKey())); |
| | | if (ObjectUtil.isNotNull(info) && info.getOssConfigId() != ossConfigId) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | return false; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | |
| | | oss.setOriginalName(originalfileName); |
| | | oss.setService(storage.getConfigKey()); |
| | | baseMapper.insert(oss); |
| | | SysOssVo sysOssVo = new SysOssVo(); |
| | | MapstructUtils.convert(oss, sysOssVo); |
| | | SysOssVo sysOssVo = MapstructUtils.convert(oss, SysOssVo.class); |
| | | return this.matchingUrl(sysOssVo); |
| | | } |
| | | |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.common.core.constant.UserConstants; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.MapstructUtils; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.common.mybatis.core.page.PageQuery; |
| | | import com.ruoyi.common.mybatis.core.page.TableDataInfo; |
| | | import com.ruoyi.common.core.exception.ServiceException; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.system.domain.SysPost; |
| | | import com.ruoyi.system.domain.SysUserPost; |
| | | import com.ruoyi.system.domain.bo.SysPostBo; |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkPostNameUnique(SysPostBo post) { |
| | | public boolean checkPostNameUnique(SysPostBo post) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>() |
| | | .eq(SysPost::getPostName, post.getPostName()) |
| | | .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkPostCodeUnique(SysPostBo post) { |
| | | public boolean checkPostCodeUnique(SysPostBo post) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysPost>() |
| | | .eq(SysPost::getPostCode, post.getPostCode()) |
| | | .ne(ObjectUtil.isNotNull(post.getPostId()), SysPost::getPostId, post.getPostId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkRoleNameUnique(SysRoleBo role) { |
| | | public boolean checkRoleNameUnique(SysRoleBo role) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>() |
| | | .eq(SysRole::getRoleName, role.getRoleName()) |
| | | .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkRoleKeyUnique(SysRoleBo role) { |
| | | public boolean checkRoleKeyUnique(SysRoleBo role) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysRole>() |
| | | .eq(SysRole::getRoleKey, role.getRoleKey()) |
| | | .ne(ObjectUtil.isNotNull(role.getRoleId()), SysRole::getRoleId, role.getRoleId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * 校验企业名称是否唯一 |
| | | */ |
| | | @Override |
| | | public String checkCompanyNameUnique(SysTenantBo bo) { |
| | | public boolean checkCompanyNameUnique(SysTenantBo bo) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysTenant>() |
| | | .eq(SysTenant::getCompanyName, bo.getCompanyName()) |
| | | .ne(ObjectUtil.isNotNull(bo.getTenantId()), SysTenant::getTenantId, bo.getTenantId())); |
| | | if (exist) { |
| | | return TenantConstants.NOT_PASS; |
| | | } |
| | | return TenantConstants.PASS; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | | * 校验账号余额 |
| | | */ |
| | | @Override |
| | | public String checkAccountBalance(String tenantId) { |
| | | public boolean checkAccountBalance(String tenantId) { |
| | | SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId); |
| | | // 如果余额为-1代表不限制 |
| | | if (tenant.getAccountCount() == -1) { |
| | | return TenantConstants.PASS; |
| | | return true; |
| | | } |
| | | Long userNumber = sysUserMapper.selectCount(new LambdaQueryWrapper<>()); |
| | | // 如果余额大于0代表还有可用名额 |
| | | if (tenant.getAccountCount() - userNumber > 0) { |
| | | return TenantConstants.PASS; |
| | | } |
| | | return TenantConstants.NOT_PASS; |
| | | return tenant.getAccountCount() - userNumber > 0; |
| | | } |
| | | |
| | | /** |
| | | * 校验有效期 |
| | | */ |
| | | @Override |
| | | public String checkExpireTime(String tenantId) { |
| | | public boolean checkExpireTime(String tenantId) { |
| | | SysTenantVo tenant = SpringUtils.getAopProxy(this).queryByTenantId(tenantId); |
| | | // 如果未设置过期时间代表不限制 |
| | | if (ObjectUtil.isNull(tenant.getExpireTime())) { |
| | | return TenantConstants.PASS; |
| | | return true; |
| | | } |
| | | // 如果当前时间在过期时间之前则通过 |
| | | if (new Date().before(tenant.getExpireTime())) { |
| | | return TenantConstants.PASS; |
| | | } |
| | | return TenantConstants.NOT_PASS; |
| | | return new Date().before(tenant.getExpireTime()); |
| | | } |
| | | |
| | | /** |
| | |
| | | * @return 结果 |
| | | */ |
| | | @Override |
| | | public String checkUserNameUnique(SysUserBo user) { |
| | | public boolean checkUserNameUnique(SysUserBo user) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>() |
| | | .eq(SysUser::getUserName, user.getUserName()) |
| | | .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param user 用户信息 |
| | | */ |
| | | @Override |
| | | public String checkPhoneUnique(SysUserBo user) { |
| | | public boolean checkPhoneUnique(SysUserBo user) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>() |
| | | .eq(SysUser::getPhonenumber, user.getPhonenumber()) |
| | | .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | * @param user 用户信息 |
| | | */ |
| | | @Override |
| | | public String checkEmailUnique(SysUserBo user) { |
| | | public boolean checkEmailUnique(SysUserBo user) { |
| | | boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>() |
| | | .eq(SysUser::getEmail, user.getEmail()) |
| | | .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); |
| | | if (exist) { |
| | | return UserConstants.NOT_UNIQUE; |
| | | } |
| | | return UserConstants.UNIQUE; |
| | | return !exist; |
| | | } |
| | | |
| | | /** |
| | |
| | | "clipboard": "2.0.8", |
| | | "core-js": "3.25.3", |
| | | "echarts": "5.4.0", |
| | | "element-ui": "2.15.10", |
| | | "element-ui": "2.15.12", |
| | | "file-saver": "2.0.5", |
| | | "fuse.js": "6.4.3", |
| | | "highlight.js": "9.18.5", |
| | |
| | | }, |
| | | isFirstView() { |
| | | try { |
| | | return this.selectedTag.fullPath === this.visitedViews[1].fullPath || this.selectedTag.fullPath === '/index' |
| | | return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath |
| | | } catch (err) { |
| | | return false |
| | | } |
| | |
| | | |
| | | NProgress.configure({ showSpinner: false }) |
| | | |
| | | const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] |
| | | const whiteList = ['/login', '/register'] |
| | | |
| | | router.beforeEach((to, from, next) => { |
| | | NProgress.start() |
| | |
| | | next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 |
| | | }) |
| | | }).catch(err => { |
| | | store.dispatch('LogOut').then(() => { |
| | | Message.error(err) |
| | | next({ path: '/' }) |
| | | }) |
| | | store.dispatch('LogOut').then(() => { |
| | | Message.error(err) |
| | | next({ path: '/' }) |
| | | }) |
| | | }) |
| | | } else { |
| | | next() |
| | | } |
| | |
| | | url: url, |
| | | responseType: 'blob', |
| | | headers: { 'Authorization': 'Bearer ' + getToken() } |
| | | }).then(async (res) => { |
| | | const isLogin = await blobValidate(res.data); |
| | | if (isLogin) { |
| | | }).then((res) => { |
| | | const isBlob = blobValidate(res.data); |
| | | if (isBlob) { |
| | | const blob = new Blob([res.data], { type: 'application/octet-stream' }) |
| | | this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) |
| | | } else { |
| | |
| | | 'Authorization': 'Bearer ' + getToken(), |
| | | 'datasource': localStorage.getItem("dataName") |
| | | } |
| | | }).then(async (res) => { |
| | | const isLogin = await blobValidate(res.data); |
| | | if (isLogin) { |
| | | }).then((res) => { |
| | | const isBlob = blobValidate(res.data); |
| | | if (isBlob) { |
| | | const blob = new Blob([res.data], { type: 'application/zip' }) |
| | | this.saveAs(blob, name) |
| | | } else { |
| | |
| | | } |
| | | return config |
| | | }, error => { |
| | | console.log(error) |
| | | Promise.reject(error) |
| | | console.log(error) |
| | | Promise.reject(error) |
| | | }) |
| | | |
| | | // 响应拦截器 |
| | | service.interceptors.response.use(res => { |
| | | // 未设置状态码则默认成功状态 |
| | | const code = res.data.code || 200; |
| | | // 获取错误信息 |
| | | const msg = errorCode[code] || res.data.msg || errorCode['default'] |
| | | // 二进制数据则直接返回 |
| | | if(res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer'){ |
| | | return res.data |
| | | // 未设置状态码则默认成功状态 |
| | | const code = res.data.code || 200; |
| | | // 获取错误信息 |
| | | const msg = errorCode[code] || res.data.msg || errorCode['default'] |
| | | // 二进制数据则直接返回 |
| | | if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { |
| | | return res.data |
| | | } |
| | | if (code === 401) { |
| | | if (!isRelogin.show) { |
| | | isRelogin.show = true; |
| | | MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { |
| | | isRelogin.show = false; |
| | | store.dispatch('LogOut').then(() => { |
| | | location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; |
| | | }) |
| | | }).catch(() => { |
| | | isRelogin.show = false; |
| | | }); |
| | | } |
| | | return Promise.reject('无效的会话,或者会话已过期,请重新登录。') |
| | | } else if (code === 500) { |
| | | Message({ message: msg, type: 'error' }) |
| | | return Promise.reject(new Error(msg)) |
| | | } else if (code === 601) { |
| | | Message({ message: msg, type: 'warning' }) |
| | | return Promise.reject('error') |
| | | } else if (code !== 200) { |
| | | Notification.error({ title: msg }) |
| | | return Promise.reject('error') |
| | | } else { |
| | | return res.data |
| | | } |
| | | }, |
| | | error => { |
| | | console.log('err' + error) |
| | | let { message } = error; |
| | | if (message == "Network Error") { |
| | | message = "后端接口连接异常"; |
| | | } else if (message.includes("timeout")) { |
| | | message = "系统接口请求超时"; |
| | | } else if (message.includes("Request failed with status code")) { |
| | | message = "系统接口" + message.substr(message.length - 3) + "异常"; |
| | | } |
| | | Message({ message: message, type: 'error', duration: 5 * 1000 }) |
| | | return Promise.reject(error) |
| | | } |
| | | if (code === 401) { |
| | | if (!isRelogin.show) { |
| | | isRelogin.show = true; |
| | | MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { |
| | | isRelogin.show = false; |
| | | store.dispatch('LogOut').then(() => { |
| | | location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; |
| | | }) |
| | | }).catch(() => { |
| | | isRelogin.show = false; |
| | | }); |
| | | } |
| | | return Promise.reject('无效的会话,或者会话已过期,请重新登录。') |
| | | } else if (code === 500) { |
| | | Message({ message: msg, type: 'error' }) |
| | | return Promise.reject(new Error(msg)) |
| | | } else if (code === 601) { |
| | | Message({ message: msg, type: 'warning' }) |
| | | return Promise.reject('error') |
| | | } else if (code !== 200) { |
| | | Notification.error({ title: msg }) |
| | | return Promise.reject('error') |
| | | } else { |
| | | return res.data |
| | | } |
| | | }, |
| | | error => { |
| | | console.log('err' + error) |
| | | let { message } = error; |
| | | if (message == "Network Error") { |
| | | message = "后端接口连接异常"; |
| | | } else if (message.includes("timeout")) { |
| | | message = "系统接口请求超时"; |
| | | } else if (message.includes("Request failed with status code")) { |
| | | message = "系统接口" + message.substr(message.length - 3) + "异常"; |
| | | } |
| | | Message({ message: message, type: 'error', duration: 5 * 1000 }) |
| | | return Promise.reject(error) |
| | | } |
| | | ) |
| | | |
| | | // 通用下载方法 |
| | |
| | | responseType: 'blob', |
| | | ...config |
| | | }).then(async (data) => { |
| | | const isLogin = await blobValidate(data); |
| | | if (isLogin) { |
| | | const isBlob = blobValidate(data); |
| | | if (isBlob) { |
| | | const blob = new Blob([data]) |
| | | saveAs(blob, filename) |
| | | } else { |
| | |
| | | } |
| | | |
| | | // 验证是否为blob格式 |
| | | export async function blobValidate(data) { |
| | | try { |
| | | const text = await data.text(); |
| | | JSON.parse(text); |
| | | return false; |
| | | } catch (error) { |
| | | return true; |
| | | } |
| | | export function blobValidate(data) { |
| | | return data.type !== 'application/json' |
| | | } |
| | |
| | | v-model="daterangeCreateTime" |
| | | size="small" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | v-model="daterangeCreateTime" |
| | | size="small" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | </el-form> |
| | | <!-- 底部 --> |
| | | <div class="el-login-footer"> |
| | | <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span> |
| | | <span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <el-row> |
| | | <el-col :span="24" class="card-box"> |
| | | <el-card> |
| | | <div slot="header"><span>基本信息</span></div> |
| | | <div slot="header"><span><i class="el-icon-monitor"></i> 基本信息</span></div> |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | | <table cellspacing="0" style="width: 100%"> |
| | | <tbody> |
| | |
| | | |
| | | <el-col :span="12" class="card-box"> |
| | | <el-card> |
| | | <div slot="header"><span>命令统计</span></div> |
| | | <div slot="header"><span><i class="el-icon-pie-chart"></i> 命令统计</span></div> |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | | <div ref="commandstats" style="height: 420px" /> |
| | | </div> |
| | |
| | | |
| | | <el-col :span="12" class="card-box"> |
| | | <el-card> |
| | | <div slot="header"> |
| | | <span>内存信息</span> |
| | | </div> |
| | | <div slot="header"><span><i class="el-icon-odometer"></i> 内存信息</span></div> |
| | | <div class="el-table el-table--enable-row-hover el-table--medium"> |
| | | <div ref="usedmemory" style="height: 420px" /> |
| | | </div> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | </el-row> |
| | | |
| | | <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange"> |
| | | <el-table-column type="selection" width="55" align="center" /> |
| | | <el-table-column type="selection" width="50" align="center" /> |
| | | <el-table-column label="日志编号" align="center" prop="operId" /> |
| | | <el-table-column label="系统模块" align="center" prop="title" /> |
| | | <el-table-column label="系统模块" align="center" prop="title" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作类型" align="center" prop="businessType"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="请求方式" align="center" prop="requestMethod" /> |
| | | <el-table-column label="操作人员" align="center" prop="operName" width="100" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" /> |
| | | <el-table-column label="操作人员" align="center" prop="operName" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" /> |
| | | <el-table-column label="操作地址" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作地点" align="center" prop="operLocation" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="操作状态" align="center" prop="status"> |
| | |
| | | <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> |
| | | <el-table-column label="操作日期" align="center" prop="operTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ parseTime(scope.row.operTime) }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="消耗时间" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']"> |
| | | <template slot-scope="scope"> |
| | | <span>{{ scope.row.costTime }}毫秒</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> |
| | |
| | | <el-col :span="24"> |
| | | <el-form-item label="返回参数:">{{ form.jsonResult }}</el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-col :span="6"> |
| | | <el-form-item label="操作状态:"> |
| | | <div v-if="form.status === 0">正常</div> |
| | | <div v-else-if="form.status === 1">失败</div> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-col :span="8"> |
| | | <el-form-item label="消耗时间:">{{ form.costTime }}毫秒</el-form-item> |
| | | </el-col> |
| | | <el-col :span="10"> |
| | | <el-form-item label="操作时间:">{{ parseTime(form.operTime) }}</el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | |
| | | </el-form> |
| | | <!-- 底部 --> |
| | | <div class="el-register-footer"> |
| | | <span>Copyright © 2018-2022 ruoyi.vip All Rights Reserved.</span> |
| | | <span>Copyright © 2018-2023 ruoyi.vip All Rights Reserved.</span> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <el-table-column label="参数主键" align="center" prop="configId" v-if="false" /> |
| | | <el-table-column label="参数名称" align="center" prop="configName" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键名" align="center" prop="configKey" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="参数键值" align="center" prop="configValue" /> |
| | | <el-table-column label="参数键值" align="center" prop="configValue" :show-overflow-tooltip="true" /> |
| | | <el-table-column label="系统内置" align="center" prop="configType"> |
| | | <template slot-scope="scope"> |
| | | <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | v-model="daterangeCreateTime" |
| | | size="small" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item label="服务商" prop="service"> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | <el-date-picker |
| | | v-model="dateRange" |
| | | style="width: 240px" |
| | | value-format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="daterange" |
| | | range-separator="-" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | ></el-date-picker> |
| | | </el-form-item> |
| | | <el-form-item> |
| | |
| | | json_result varchar2(2100) default '', |
| | | status number(1) default 0, |
| | | error_msg varchar2(2100) default '', |
| | | oper_time date |
| | | oper_time date, |
| | | cost_time number(20) default 0 |
| | | ); |
| | | |
| | | alter table sys_oper_log add constraint pk_sys_oper_log primary key (oper_id); |
| | | create unique index idx_sys_oper_log_bt on sys_oper_log (business_type); |
| | | create unique index idx_sys_oper_log_s on sys_oper_log (status); |
| | | create unique index idx_sys_oper_log_ot on sys_oper_log (oper_time); |
| | | |
| | | comment on table sys_oper_log is '操作日志记录'; |
| | | comment on column sys_oper_log.oper_id is '日志主键'; |
| | |
| | | comment on column sys_oper_log.status is '操作状态(0正常 1异常)'; |
| | | comment on column sys_oper_log.error_msg is '错误消息'; |
| | | comment on column sys_oper_log.oper_time is '操作时间'; |
| | | comment on column sys_oper_log.cost_time is '消耗时间'; |
| | | |
| | | |
| | | -- ---------------------------- |
| | |
| | | ); |
| | | |
| | | alter table sys_logininfor add constraint pk_sys_logininfor primary key (info_id); |
| | | create unique index idx_sys_logininfor_s on sys_logininfor (status); |
| | | create unique index idx_sys_logininfor_lt on sys_logininfor (login_time); |
| | | |
| | | comment on table sys_logininfor is '系统访问记录'; |
| | | comment on column sys_logininfor.info_id is '访问ID'; |
| | |
| | | status int4 default 0, |
| | | error_msg varchar(2000) default ''::varchar, |
| | | oper_time timestamp, |
| | | cost_time int8 default 0, |
| | | constraint sys_oper_log_pk primary key (oper_id) |
| | | ); |
| | | |
| | | create unique index idx_sys_oper_log_bt ON sys_oper_log (business_type); |
| | | create unique index idx_sys_oper_log_s ON sys_oper_log (status); |
| | | create unique index idx_sys_oper_log_ot ON sys_oper_log (oper_time); |
| | | |
| | | comment on table sys_oper_log is '操作日志记录'; |
| | | comment on column sys_oper_log.oper_id is '日志主键'; |
| | |
| | | comment on column sys_oper_log.status is '操作状态(0正常 1异常)'; |
| | | comment on column sys_oper_log.error_msg is '错误消息'; |
| | | comment on column sys_oper_log.oper_time is '操作时间'; |
| | | comment on column sys_oper_log.cost_time is '消耗时间'; |
| | | |
| | | -- ---------------------------- |
| | | -- 11、字典类型表 |
| | |
| | | constraint sys_dict_type_pk primary key (dict_id) |
| | | ); |
| | | |
| | | CREATE UNIQUE INDEX sys_dict_type_index1 ON sys_dict_type (tenant_id, dict_type); |
| | | create unique index sys_dict_type_index1 ON sys_dict_type (tenant_id, dict_type); |
| | | |
| | | comment on table sys_dict_type is '字典类型表'; |
| | | comment on column sys_dict_type.dict_id is '字典主键'; |
| | |
| | | constraint sys_logininfor_pk primary key (info_id) |
| | | ); |
| | | |
| | | create unique index idx_sys_logininfor_s ON sys_logininfor (status); |
| | | create unique index idx_sys_logininfor_lt ON sys_logininfor (login_time); |
| | | |
| | | comment on table sys_logininfor is '系统访问记录'; |
| | | comment on column sys_logininfor.info_id is '访问ID'; |
| | | comment on column sys_logininfor.tenant_id is '租户编号'; |
| | |
| | | gen_type char default '0'::bpchar not null, |
| | | gen_path varchar(200) default '/'::varchar, |
| | | options varchar(1000) default null::varchar, |
| | | create_dept int8, |
| | | create_by int8, |
| | | create_time timestamp, |
| | | update_by int8, |
| | |
| | | status int(1) default 0 comment '操作状态(0正常 1异常)', |
| | | error_msg varchar(2000) default '' comment '错误消息', |
| | | oper_time datetime comment '操作时间', |
| | | primary key (oper_id) |
| | | cost_time bigint(20) default 0 comment '消耗时间', |
| | | primary key (oper_id), |
| | | key idx_sys_oper_log_bt (business_type), |
| | | key idx_sys_oper_log_s (status), |
| | | key idx_sys_oper_log_ot (oper_time) |
| | | ) engine=innodb comment = '操作日志记录'; |
| | | |
| | | |
| | |
| | | status char(1) default '0' comment '登录状态(0成功 1失败)', |
| | | msg varchar(255) default '' comment '提示消息', |
| | | login_time datetime comment '访问时间', |
| | | primary key (info_id) |
| | | primary key (info_id), |
| | | key idx_sys_logininfor_s (status), |
| | | key idx_sys_logininfor_lt (login_time) |
| | | ) engine=innodb comment = '系统访问记录'; |
| | | |
| | | |
| | |
| | | ON [PRIMARY] |
| | | GO |
| | | |
| | | CREATE NONCLUSTERED INDEX idx_sys_logininfor_s ON sys_logininfor (status) |
| | | GO |
| | | CREATE NONCLUSTERED INDEX idx_sys_logininfor_lt ON sys_logininfor (login_time) |
| | | GO |
| | | |
| | | EXEC sys.sp_addextendedproperty |
| | | 'MS_Description', N'访问ID' , |
| | | 'SCHEMA', N'dbo', |
| | |
| | | status int DEFAULT ((0)) NULL, |
| | | error_msg nvarchar(2000) DEFAULT '' NULL, |
| | | oper_time datetime2(7) NULL, |
| | | cost_time bigint DEFAULT ((0)) NULL, |
| | | CONSTRAINT PK__sys_oper__34723BF9BD954573 PRIMARY KEY CLUSTERED (oper_id) |
| | | WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) |
| | | ON [PRIMARY] |
| | | ) |
| | | ON [PRIMARY] |
| | | GO |
| | | |
| | | CREATE NONCLUSTERED INDEX idx_sys_oper_log_bt ON sys_oper_log (business_type) |
| | | GO |
| | | CREATE NONCLUSTERED INDEX idx_sys_oper_log_s ON sys_oper_log (status) |
| | | GO |
| | | CREATE NONCLUSTERED INDEX idx_sys_oper_log_ot ON sys_oper_log (oper_time) |
| | | GO |
| | | |
| | | EXEC sys.sp_addextendedproperty |
| | |
| | | 'COLUMN', N'oper_time' |
| | | GO |
| | | EXEC sys.sp_addextendedproperty |
| | | 'MS_Description', N'消耗时间' , |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sys_oper_log', |
| | | 'COLUMN', N'cost_time' |
| | | GO |
| | | EXEC sys.sp_addextendedproperty |
| | | 'MS_Description', N'操作日志记录' , |
| | | 'SCHEMA', N'dbo', |
| | | 'TABLE', N'sys_oper_log' |
| | |
| | | post_name nvarchar(50) NOT NULL, |
| | | post_sort int NOT NULL, |
| | | status nchar(1) NOT NULL, |
| | | create_dept bigint NOT NULL, |
| | | create_by bigint NOT NULL, |
| | | create_dept bigint NULL, |
| | | create_by bigint NULL, |
| | | create_time datetime2(7) NULL, |
| | | update_by bigint NOT NULL, |
| | | update_by bigint NULL, |
| | | update_time datetime2(7) NULL, |
| | | remark nvarchar(500) NULL, |
| | | CONSTRAINT PK__sys_post__3ED7876668E2D081 PRIMARY KEY CLUSTERED (post_id) |
| | |
| | | ON [PRIMARY] |
| | | GO |
| | | |
| | | CREATE NONCLUSTERED INDEX sys_dict_type_index1 ON sys_dict_type (tenant_id, dict_type) |
| | | GO |
| | | |
| | | EXEC sys.sp_addextendedproperty |
| | | 'MS_Description', N'岗位ID' , |
| | | 'SCHEMA', N'dbo', |