mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	新增:新增系统监控/操作日志功能,优化日志表结构
This commit is contained in:
		| @@ -250,6 +250,9 @@ continew-admin | |||||||
|     │  ├─ utils             # 工具库 |     │  ├─ utils             # 工具库 | ||||||
|     │  ├─ views             # 页面模板 |     │  ├─ views             # 页面模板 | ||||||
|     │  │  ├─ login            # 登录模块 |     │  │  ├─ login            # 登录模块 | ||||||
|  |     │  │  ├─ monitor          # 系统监控模块 | ||||||
|  |     │  │  │ └─ log              # 日志管理 | ||||||
|  |     │  │  │   └─ operation        # 操作日志 | ||||||
|     │  │  └─ system           # 系统管理模块 |     │  │  └─ system           # 系统管理模块 | ||||||
|     │  │    └─ user             # 用户模块 |     │  │    └─ user             # 用户模块 | ||||||
|     │  │      └─ center           # 个人中心 |     │  │      └─ center           # 个人中心 | ||||||
|   | |||||||
| @@ -30,12 +30,12 @@ import lombok.Data; | |||||||
| public class LogContext { | public class LogContext { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作人 |      * 创建人 | ||||||
|      */ |      */ | ||||||
|     private Long createUser; |     private Long createUser; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作时间 |      * 创建时间 | ||||||
|      */ |      */ | ||||||
|     private LocalDateTime createTime; |     private LocalDateTime createTime; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -43,16 +43,16 @@ import net.dreamlu.mica.ip2region.core.IpInfo; | |||||||
| public class IpUtils { | public class IpUtils { | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 太平洋网开放 API,查询 IP 归属地 |      * 太平洋网开放 API:查询 IP 归属地 | ||||||
|      */ |      */ | ||||||
|     private static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true"; |     private static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true"; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 根据IP获取详细地址 |      * 根据 IP 获取归属地信息 | ||||||
|      * |      * | ||||||
|      * @param ip |      * @param ip | ||||||
|      *            IP地址 |      *            IP 地址 | ||||||
|      * @return 详细地址 |      * @return 归属地信息 | ||||||
|      */ |      */ | ||||||
|     public static String getCityInfo(String ip) { |     public static String getCityInfo(String ip) { | ||||||
|         if (ContinewAdminProperties.IP_ADDR_LOCAL_PARSE_ENABLED) { |         if (ContinewAdminProperties.IP_ADDR_LOCAL_PARSE_ENABLED) { | ||||||
| @@ -63,11 +63,11 @@ public class IpUtils { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 根据 IP 获取详细地址(网络解析) |      * 根据 IP 获取归属地信息(网络解析) | ||||||
|      * |      * | ||||||
|      * @param ip |      * @param ip | ||||||
|      *            IP地址 |      *            IP 地址 | ||||||
|      * @return 详细地址 |      * @return 归属地信息 | ||||||
|      */ |      */ | ||||||
|     public static String getHttpCityInfo(String ip) { |     public static String getHttpCityInfo(String ip) { | ||||||
|         if (isInnerIP(ip)) { |         if (isInnerIP(ip)) { | ||||||
| @@ -79,11 +79,11 @@ public class IpUtils { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 根据 IP 获取详细地址(本地解析) |      * 根据 IP 获取归属地信息(本地解析) | ||||||
|      * |      * | ||||||
|      * @param ip |      * @param ip | ||||||
|      *            IP 地址 |      *            IP 地址 | ||||||
|      * @return 详细地址 |      * @return 归属地信息 | ||||||
|      */ |      */ | ||||||
|     public static String getLocalCityInfo(String ip) { |     public static String getLocalCityInfo(String ip) { | ||||||
|         if (isInnerIP(ip)) { |         if (isInnerIP(ip)) { | ||||||
| @@ -98,11 +98,11 @@ public class IpUtils { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 是否为内网IPv4 |      * 是否为内网 IPv4 | ||||||
|      * |      * | ||||||
|      * @param ip |      * @param ip | ||||||
|      *            IP 地址 |      *            IP 地址 | ||||||
|      * @return 是否为内网IP |      * @return 是否为内网 IP | ||||||
|      */ |      */ | ||||||
|     public static boolean isInnerIP(String ip) { |     public static boolean isInnerIP(String ip) { | ||||||
|         ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip); |         ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip); | ||||||
|   | |||||||
| @@ -22,14 +22,14 @@ import lombok.RequiredArgsConstructor; | |||||||
| import com.baomidou.mybatisplus.annotation.IEnum; | import com.baomidou.mybatisplus.annotation.IEnum; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * 操作结果枚举 |  * 操作状态枚举 | ||||||
|  * |  * | ||||||
|  * @author Charles7c |  * @author Charles7c | ||||||
|  * @since 2022/12/25 9:09 |  * @since 2022/12/25 9:09 | ||||||
|  */ |  */ | ||||||
| @Getter | @Getter | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
| public enum LogResultEnum implements IEnum<Integer> { | public enum LogStatusEnum implements IEnum<Integer> { | ||||||
| 
 | 
 | ||||||
|     /** 成功 */ |     /** 成功 */ | ||||||
|     SUCCESS(1, "成功"), |     SUCCESS(1, "成功"), | ||||||
| @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletRequest; | |||||||
| import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||||
|  |  | ||||||
| import org.springframework.core.Ordered; | import org.springframework.core.Ordered; | ||||||
|  | import org.springframework.lang.NonNull; | ||||||
| import org.springframework.stereotype.Component; | import org.springframework.stereotype.Component; | ||||||
| import org.springframework.web.filter.OncePerRequestFilter; | import org.springframework.web.filter.OncePerRequestFilter; | ||||||
| import org.springframework.web.util.ContentCachingRequestWrapper; | import org.springframework.web.util.ContentCachingRequestWrapper; | ||||||
| @@ -32,7 +33,7 @@ import org.springframework.web.util.ContentCachingResponseWrapper; | |||||||
| import org.springframework.web.util.WebUtils; | import org.springframework.web.util.WebUtils; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 操作日志过滤器(缓存请求和响应体过滤器) |  * 系统日志过滤器(缓存请求和响应体过滤器) | ||||||
|  * |  * | ||||||
|  * <p> |  * <p> | ||||||
|  * 由于 requestBody 和 responseBody 分别对应的是 InputStream 和 OutputStream,由于流的特性,读取完之后就无法再被使用了。 所以,需要额外缓存一次流信息。 |  * 由于 requestBody 和 responseBody 分别对应的是 InputStream 和 OutputStream,由于流的特性,读取完之后就无法再被使用了。 所以,需要额外缓存一次流信息。 | ||||||
| @@ -50,8 +51,8 @@ public class LogFilter extends OncePerRequestFilter implements Ordered { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) |     protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, | ||||||
|         throws ServletException, IOException { |         @NonNull FilterChain filterChain) throws ServletException, IOException { | ||||||
|         // 包装流,可重复读取 |         // 包装流,可重复读取 | ||||||
|         if (!(request instanceof ContentCachingRequestWrapper)) { |         if (!(request instanceof ContentCachingRequestWrapper)) { | ||||||
|             request = new ContentCachingRequestWrapper(request); |             request = new ContentCachingRequestWrapper(request); | ||||||
|   | |||||||
| @@ -52,7 +52,7 @@ import top.charles7c.cnadmin.common.util.helper.LoginHelper; | |||||||
| import top.charles7c.cnadmin.common.util.holder.LogContextHolder; | import top.charles7c.cnadmin.common.util.holder.LogContextHolder; | ||||||
| import top.charles7c.cnadmin.monitor.annotation.Log; | import top.charles7c.cnadmin.monitor.annotation.Log; | ||||||
| import top.charles7c.cnadmin.monitor.config.properties.LogProperties; | import top.charles7c.cnadmin.monitor.config.properties.LogProperties; | ||||||
| import top.charles7c.cnadmin.monitor.enums.LogResultEnum; | import top.charles7c.cnadmin.monitor.enums.LogStatusEnum; | ||||||
| import top.charles7c.cnadmin.monitor.model.entity.SysLog; | import top.charles7c.cnadmin.monitor.model.entity.SysLog; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -73,7 +73,7 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|     public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, |     public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, | ||||||
|         @NonNull Object handler) { |         @NonNull Object handler) { | ||||||
|         if (checkIsNeedRecord(handler, request)) { |         if (checkIsNeedRecord(handler, request)) { | ||||||
|             // 记录操作时间 |             // 记录时间 | ||||||
|             this.logCreateTime(); |             this.logCreateTime(); | ||||||
|         } |         } | ||||||
|         return true; |         return true; | ||||||
| @@ -100,7 +100,7 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 记录操作时间 |      * 记录时间 | ||||||
|      */ |      */ | ||||||
|     private void logCreateTime() { |     private void logCreateTime() { | ||||||
|         LogContext logContext = new LogContext(); |         LogContext logContext = new LogContext(); | ||||||
| @@ -121,12 +121,12 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|             SysLog sysLog = new SysLog(); |             SysLog sysLog = new SysLog(); | ||||||
|             sysLog.setCreateTime(logContext.getCreateTime()); |             sysLog.setCreateTime(logContext.getCreateTime()); | ||||||
|             sysLog.setElapsedTime(System.currentTimeMillis() - LocalDateTimeUtil.toEpochMilli(sysLog.getCreateTime())); |             sysLog.setElapsedTime(System.currentTimeMillis() - LocalDateTimeUtil.toEpochMilli(sysLog.getCreateTime())); | ||||||
|             sysLog.setResult(LogResultEnum.SUCCESS); |             sysLog.setStatus(LogStatusEnum.SUCCESS); | ||||||
|  |  | ||||||
|             // 记录异常信息 |             // 记录异常信息 | ||||||
|             Exception exception = logContext.getException(); |             Exception exception = logContext.getException(); | ||||||
|             if (exception != null) { |             if (exception != null) { | ||||||
|                 sysLog.setResult(LogResultEnum.FAILURE); |                 sysLog.setStatus(LogStatusEnum.FAILURE); | ||||||
|                 sysLog.setException(ExceptionUtil.stacktraceToString(exception, -1)); |                 sysLog.setException(ExceptionUtil.stacktraceToString(exception, -1)); | ||||||
|             } |             } | ||||||
|             return sysLog; |             return sysLog; | ||||||
| @@ -175,8 +175,8 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|             sysLog.setRequestBody(this.desensitize( |             sysLog.setRequestBody(this.desensitize( | ||||||
|                 JSONUtil.isTypeJSON(requestBody) ? JSONUtil.parseObj(requestBody) : ServletUtil.getParamMap(request))); |                 JSONUtil.isTypeJSON(requestBody) ? JSONUtil.parseObj(requestBody) : ServletUtil.getParamMap(request))); | ||||||
|         } |         } | ||||||
|         sysLog.setRequestIp(ServletUtil.getClientIP(request)); |         sysLog.setClientIp(ServletUtil.getClientIP(request)); | ||||||
|         sysLog.setLocation(IpUtils.getCityInfo(sysLog.getRequestIp())); |         sysLog.setLocation(IpUtils.getCityInfo(sysLog.getClientIp())); | ||||||
|         sysLog.setBrowser(ServletUtils.getBrowser(request)); |         sysLog.setBrowser(ServletUtils.getBrowser(request)); | ||||||
|         sysLog.setCreateUser(sysLog.getCreateUser() == null ? LoginHelper.getUserId() : sysLog.getCreateUser()); |         sysLog.setCreateUser(sysLog.getCreateUser() == null ? LoginHelper.getUserId() : sysLog.getCreateUser()); | ||||||
|     } |     } | ||||||
| @@ -199,7 +199,7 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|             sysLog.setResponseBody(responseBody); |             sysLog.setResponseBody(responseBody); | ||||||
|         } |         } | ||||||
|         // 操作失败:>= 400 |         // 操作失败:>= 400 | ||||||
|         sysLog.setResult(status >= HttpStatus.HTTP_BAD_REQUEST ? LogResultEnum.FAILURE : sysLog.getResult()); |         sysLog.setStatus(status >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : sysLog.getStatus()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -265,9 +265,9 @@ public class LogInterceptor implements HandlerInterceptor { | |||||||
|      * 检查是否要记录系统日志 |      * 检查是否要记录系统日志 | ||||||
|      * |      * | ||||||
|      * @param handler |      * @param handler | ||||||
|      *            / |      *            处理器 | ||||||
|      * @param request |      * @param request | ||||||
|      *            / |      *            请求对象 | ||||||
|      * @return true 需要记录,false 不需要记录 |      * @return true 需要记录,false 不需要记录 | ||||||
|      */ |      */ | ||||||
|     private boolean checkIsNeedRecord(Object handler, HttpServletRequest request) { |     private boolean checkIsNeedRecord(Object handler, HttpServletRequest request) { | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ import lombok.Data; | |||||||
| import com.baomidou.mybatisplus.annotation.TableId; | import com.baomidou.mybatisplus.annotation.TableId; | ||||||
| import com.baomidou.mybatisplus.annotation.TableName; | import com.baomidou.mybatisplus.annotation.TableName; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.monitor.enums.LogResultEnum; | import top.charles7c.cnadmin.monitor.enums.LogStatusEnum; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 系统日志实体 |  * 系统日志实体 | ||||||
| @@ -90,17 +90,17 @@ public class SysLog implements Serializable { | |||||||
|     private Long elapsedTime; |     private Long elapsedTime; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作结果(1成功 2失败) |      * 操作状态(1成功 2失败) | ||||||
|      */ |      */ | ||||||
|     private LogResultEnum result; |     private LogStatusEnum status; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作IP |      * 客户端IP | ||||||
|      */ |      */ | ||||||
|     private String requestIp; |     private String clientIp; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作地点 |      * IP归属地 | ||||||
|      */ |      */ | ||||||
|     private String location; |     private String location; | ||||||
|  |  | ||||||
| @@ -115,12 +115,12 @@ public class SysLog implements Serializable { | |||||||
|     private String exception; |     private String exception; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作人 |      * 创建人 | ||||||
|      */ |      */ | ||||||
|     private Long createUser; |     private Long createUser; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作时间 |      * 创建时间 | ||||||
|      */ |      */ | ||||||
|     private LocalDateTime createTime; |     private LocalDateTime createTime; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,12 +19,15 @@ package top.charles7c.cnadmin.monitor.model.query; | |||||||
| import static top.charles7c.cnadmin.common.annotation.Query.Type; | import static top.charles7c.cnadmin.common.annotation.Query.Type; | ||||||
|  |  | ||||||
| import java.io.Serializable; | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
| import lombok.Data; | import lombok.Data; | ||||||
|  |  | ||||||
| import io.swagger.v3.oas.annotations.media.Schema; | import io.swagger.v3.oas.annotations.media.Schema; | ||||||
|  |  | ||||||
| import org.springdoc.api.annotations.ParameterObject; | import org.springdoc.api.annotations.ParameterObject; | ||||||
|  | import org.springframework.format.annotation.DateTimeFormat; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.common.annotation.Query; | import top.charles7c.cnadmin.common.annotation.Query; | ||||||
|  |  | ||||||
| @@ -47,4 +50,26 @@ public class OperationLogQuery implements Serializable { | |||||||
|     @Schema(description = "操作人") |     @Schema(description = "操作人") | ||||||
|     @Query(property = "createUser", type = Type.EQUAL) |     @Query(property = "createUser", type = Type.EQUAL) | ||||||
|     private Long uid; |     private Long uid; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 操作内容 | ||||||
|  |      */ | ||||||
|  |     @Schema(description = "操作内容") | ||||||
|  |     @Query(type = Type.INNER_LIKE) | ||||||
|  |     private String description; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 操作状态(1成功 2失败) | ||||||
|  |      */ | ||||||
|  |     @Schema(description = "操作状态(1成功 2失败)") | ||||||
|  |     @Query(type = Type.EQUAL) | ||||||
|  |     private Integer status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 操作时间 | ||||||
|  |      */ | ||||||
|  |     @Schema(description = "操作时间") | ||||||
|  |     @Query(type = Type.BETWEEN) | ||||||
|  |     @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||||||
|  |     private List<Date> createTime; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ import io.swagger.v3.oas.annotations.media.Schema; | |||||||
|  |  | ||||||
| import com.fasterxml.jackson.annotation.JsonIgnore; | import com.fasterxml.jackson.annotation.JsonIgnore; | ||||||
|  |  | ||||||
| import top.charles7c.cnadmin.monitor.enums.LogResultEnum; | import top.charles7c.cnadmin.monitor.enums.LogStatusEnum; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 操作日志信息 |  * 操作日志信息 | ||||||
| @@ -52,16 +52,16 @@ public class OperationLogVO implements Serializable { | |||||||
|     private String description; |     private String description; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作结果(1成功 2失败) |      * 操作状态(1成功 2失败) | ||||||
|      */ |      */ | ||||||
|     @Schema(description = "操作结果(1成功 2失败)", type = "Integer", allowableValues = {"1", "2"}) |     @Schema(description = "操作状态(1成功 2失败)", type = "Integer", allowableValues = {"1", "2"}) | ||||||
|     private LogResultEnum result; |     private LogStatusEnum status; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作IP |      * 操作IP | ||||||
|      */ |      */ | ||||||
|     @Schema(description = "操作IP") |     @Schema(description = "操作IP") | ||||||
|     private String requestIp; |     private String clientIp; | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * 操作地点 |      * 操作地点 | ||||||
|   | |||||||
| @@ -69,7 +69,14 @@ public class OperationLogServiceImpl implements OperationLogService { | |||||||
|         // 分页查询 |         // 分页查询 | ||||||
|         IPage<SysLog> page = logMapper.selectPage(pageQuery.toPage(), queryWrapper); |         IPage<SysLog> page = logMapper.selectPage(pageQuery.toPage(), queryWrapper); | ||||||
|         PageInfo<OperationLogVO> pageInfo = PageInfo.build(page, OperationLogVO.class); |         PageInfo<OperationLogVO> pageInfo = PageInfo.build(page, OperationLogVO.class); | ||||||
|         pageInfo.getList().forEach(this::fill); |  | ||||||
|  |         // 填充数据(如果是查询个人操作日志,只查询一次用户信息即可) | ||||||
|  |         if (query.getUid() != null) { | ||||||
|  |             SysUser sysUser = userMapper.selectById(query.getUid()); | ||||||
|  |             pageInfo.getList().forEach(o -> o.setCreateUserString(sysUser.getUsername())); | ||||||
|  |         } else { | ||||||
|  |             pageInfo.getList().forEach(this::fill); | ||||||
|  |         } | ||||||
|         return pageInfo; |         return pageInfo; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -85,6 +92,6 @@ public class OperationLogServiceImpl implements OperationLogService { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         SysUser sysUser = userMapper.selectById(createUser); |         SysUser sysUser = userMapper.selectById(createUser); | ||||||
|         vo.setCreateUserString(sysUser.getNickname()); |         vo.setCreateUserString(sysUser.getUsername()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,8 +4,8 @@ import qs from 'query-string'; | |||||||
| export interface OperationLogRecord { | export interface OperationLogRecord { | ||||||
|   logId: string; |   logId: string; | ||||||
|   description: string; |   description: string; | ||||||
|   result: number, |   status: number, | ||||||
|   requestIp: string, |   clientIp: string, | ||||||
|   location: string, |   location: string, | ||||||
|   browser: string, |   browser: string, | ||||||
|   createUserString: string; |   createUserString: string; | ||||||
| @@ -16,7 +16,7 @@ export interface OperationLogParams extends Partial<OperationLogRecord> { | |||||||
|   page: number; |   page: number; | ||||||
|   size: number; |   size: number; | ||||||
|   sort: Array<string>; |   sort: Array<string>; | ||||||
|   uid: string; |   uid?: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| export interface OperationLogListRes { | export interface OperationLogListRes { | ||||||
|   | |||||||
| @@ -5,6 +5,11 @@ import localeWorkplace from '@/views/dashboard/workplace/locale/en-US'; | |||||||
|  |  | ||||||
| import localeMonitor from '@/views/dashboard/monitor/locale/en-US'; | import localeMonitor from '@/views/dashboard/monitor/locale/en-US'; | ||||||
|  |  | ||||||
|  | import localeDataAnalysis from '@/views/visualization/data-analysis/locale/en-US'; | ||||||
|  | import localeMultiDAnalysis from '@/views/visualization/multi-dimension-data-analysis/locale/en-US'; | ||||||
|  |  | ||||||
|  | import localeLog from '@/views/monitor/log/operation/locale/en-US'; | ||||||
|  |  | ||||||
| import localeSearchTable from '@/views/list/search-table/locale/en-US'; | import localeSearchTable from '@/views/list/search-table/locale/en-US'; | ||||||
| import localeCardList from '@/views/list/card/locale/en-US'; | import localeCardList from '@/views/list/card/locale/en-US'; | ||||||
|  |  | ||||||
| @@ -13,9 +18,6 @@ import localeGroupForm from '@/views/form/group/locale/en-US'; | |||||||
|  |  | ||||||
| import localeBasicProfile from '@/views/profile/basic/locale/en-US'; | import localeBasicProfile from '@/views/profile/basic/locale/en-US'; | ||||||
|  |  | ||||||
| import localeDataAnalysis from '@/views/visualization/data-analysis/locale/en-US'; |  | ||||||
| import localeMultiDAnalysis from '@/views/visualization/multi-dimension-data-analysis/locale/en-US'; |  | ||||||
|  |  | ||||||
| import localeSuccess from '@/views/result/success/locale/en-US'; | import localeSuccess from '@/views/result/success/locale/en-US'; | ||||||
| import localeError from '@/views/result/error/locale/en-US'; | import localeError from '@/views/result/error/locale/en-US'; | ||||||
|  |  | ||||||
| @@ -33,12 +35,13 @@ export default { | |||||||
|   'menu.server.dashboard': 'Dashboard-Server', |   'menu.server.dashboard': 'Dashboard-Server', | ||||||
|   'menu.server.workplace': 'Workplace-Server', |   'menu.server.workplace': 'Workplace-Server', | ||||||
|   'menu.server.monitor': 'Monitor-Server', |   'menu.server.monitor': 'Monitor-Server', | ||||||
|  |   'menu.visualization': 'Data Visualization', | ||||||
|  |   'menu.monitor': 'Monitor', | ||||||
|   'menu.list': 'List', |   'menu.list': 'List', | ||||||
|   'menu.result': 'Result', |  | ||||||
|   'menu.exception': 'Exception', |  | ||||||
|   'menu.form': 'Form', |   'menu.form': 'Form', | ||||||
|   'menu.profile': 'Profile', |   'menu.profile': 'Profile', | ||||||
|   'menu.visualization': 'Data Visualization', |   'menu.result': 'Result', | ||||||
|  |   'menu.exception': 'Exception', | ||||||
|   'menu.user': 'User Center', |   'menu.user': 'User Center', | ||||||
|   'menu.arcoWebsite': 'Arco Design', |   'menu.arcoWebsite': 'Arco Design', | ||||||
|   'menu.faq': 'FAQ', |   'menu.faq': 'FAQ', | ||||||
| @@ -48,15 +51,17 @@ export default { | |||||||
|   ...localeMessageBox, |   ...localeMessageBox, | ||||||
|   ...localeLogin, |   ...localeLogin, | ||||||
|   ...localeWorkplace, |   ...localeWorkplace, | ||||||
|  |  | ||||||
|   ...localeMonitor, |   ...localeMonitor, | ||||||
|  |   ...localeDataAnalysis, | ||||||
|  |   ...localeMultiDAnalysis, | ||||||
|  |  | ||||||
|  |   ...localeLog, | ||||||
|  |  | ||||||
|   ...localeSearchTable, |   ...localeSearchTable, | ||||||
|   ...localeCardList, |   ...localeCardList, | ||||||
|   ...localeStepForm, |   ...localeStepForm, | ||||||
|   ...localeGroupForm, |   ...localeGroupForm, | ||||||
|   ...localeBasicProfile, |   ...localeBasicProfile, | ||||||
|   ...localeDataAnalysis, |  | ||||||
|   ...localeMultiDAnalysis, |  | ||||||
|   ...localeSuccess, |   ...localeSuccess, | ||||||
|   ...localeError, |   ...localeError, | ||||||
|   ...locale403, |   ...locale403, | ||||||
|   | |||||||
| @@ -5,6 +5,11 @@ import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN'; | |||||||
|  |  | ||||||
| import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN'; | import localeMonitor from '@/views/dashboard/monitor/locale/zh-CN'; | ||||||
|  |  | ||||||
|  | import localeDataAnalysis from '@/views/visualization/data-analysis/locale/zh-CN'; | ||||||
|  | import localeMultiDAnalysis from '@/views/visualization/multi-dimension-data-analysis/locale/zh-CN'; | ||||||
|  |  | ||||||
|  | import localeLog from '@/views/monitor/log/operation/locale/zh-CN'; | ||||||
|  |  | ||||||
| import localeSearchTable from '@/views/list/search-table/locale/zh-CN'; | import localeSearchTable from '@/views/list/search-table/locale/zh-CN'; | ||||||
| import localeCardList from '@/views/list/card/locale/zh-CN'; | import localeCardList from '@/views/list/card/locale/zh-CN'; | ||||||
|  |  | ||||||
| @@ -13,9 +18,6 @@ import localeGroupForm from '@/views/form/group/locale/zh-CN'; | |||||||
|  |  | ||||||
| import localeBasicProfile from '@/views/profile/basic/locale/zh-CN'; | import localeBasicProfile from '@/views/profile/basic/locale/zh-CN'; | ||||||
|  |  | ||||||
| import localeDataAnalysis from '@/views/visualization/data-analysis/locale/zh-CN'; |  | ||||||
| import localeMultiDAnalysis from '@/views/visualization/multi-dimension-data-analysis/locale/zh-CN'; |  | ||||||
|  |  | ||||||
| import localeSuccess from '@/views/result/success/locale/zh-CN'; | import localeSuccess from '@/views/result/success/locale/zh-CN'; | ||||||
| import localeError from '@/views/result/error/locale/zh-CN'; | import localeError from '@/views/result/error/locale/zh-CN'; | ||||||
|  |  | ||||||
| @@ -33,12 +35,13 @@ export default { | |||||||
|   'menu.server.dashboard': '仪表盘-服务端', |   'menu.server.dashboard': '仪表盘-服务端', | ||||||
|   'menu.server.workplace': '工作台-服务端', |   'menu.server.workplace': '工作台-服务端', | ||||||
|   'menu.server.monitor': '实时监控-服务端', |   'menu.server.monitor': '实时监控-服务端', | ||||||
|  |   'menu.visualization': '数据可视化', | ||||||
|  |   'menu.monitor': '系统监控', | ||||||
|   'menu.list': '列表页', |   'menu.list': '列表页', | ||||||
|   'menu.result': '结果页', |  | ||||||
|   'menu.exception': '异常页', |  | ||||||
|   'menu.form': '表单页', |   'menu.form': '表单页', | ||||||
|   'menu.profile': '详情页', |   'menu.profile': '详情页', | ||||||
|   'menu.visualization': '数据可视化', |   'menu.result': '结果页', | ||||||
|  |   'menu.exception': '异常页', | ||||||
|   'menu.user': '个人中心', |   'menu.user': '个人中心', | ||||||
|   'menu.arcoWebsite': 'Arco Design', |   'menu.arcoWebsite': 'Arco Design', | ||||||
|   'menu.faq': '常见问题', |   'menu.faq': '常见问题', | ||||||
| @@ -48,15 +51,17 @@ export default { | |||||||
|   ...localeMessageBox, |   ...localeMessageBox, | ||||||
|   ...localeLogin, |   ...localeLogin, | ||||||
|   ...localeWorkplace, |   ...localeWorkplace, | ||||||
|  |  | ||||||
|   ...localeMonitor, |   ...localeMonitor, | ||||||
|  |   ...localeDataAnalysis, | ||||||
|  |   ...localeMultiDAnalysis, | ||||||
|  |  | ||||||
|  |   ...localeLog, | ||||||
|  |  | ||||||
|   ...localeSearchTable, |   ...localeSearchTable, | ||||||
|   ...localeCardList, |   ...localeCardList, | ||||||
|   ...localeStepForm, |   ...localeStepForm, | ||||||
|   ...localeGroupForm, |   ...localeGroupForm, | ||||||
|   ...localeBasicProfile, |   ...localeBasicProfile, | ||||||
|   ...localeDataAnalysis, |  | ||||||
|   ...localeMultiDAnalysis, |  | ||||||
|   ...localeSuccess, |   ...localeSuccess, | ||||||
|   ...localeError, |   ...localeError, | ||||||
|   ...locale403, |   ...locale403, | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const EXCEPTION: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.exception', |     locale: 'menu.exception', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     icon: 'icon-exclamation-circle', |     icon: 'icon-exclamation-circle', | ||||||
|     order: 6, |     order: 7, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const FORM: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.form', |     locale: 'menu.form', | ||||||
|     icon: 'icon-settings', |     icon: 'icon-settings', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     order: 3, |     order: 4, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const LIST: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.list', |     locale: 'menu.list', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     icon: 'icon-list', |     icon: 'icon-list', | ||||||
|     order: 2, |     order: 3, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								continew-admin-ui/src/router/routes/modules/monitor.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								continew-admin-ui/src/router/routes/modules/monitor.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | import { DEFAULT_LAYOUT } from '../base'; | ||||||
|  | import { AppRouteRecordRaw } from '../types'; | ||||||
|  |  | ||||||
|  | const Monitor: AppRouteRecordRaw = { | ||||||
|  |   path: '/monitor', | ||||||
|  |   name: 'monitor', | ||||||
|  |   component: DEFAULT_LAYOUT, | ||||||
|  |   meta: { | ||||||
|  |     locale: 'menu.monitor', | ||||||
|  |     requiresAuth: true, | ||||||
|  |     icon: 'icon-computer', | ||||||
|  |     order: 2, | ||||||
|  |   }, | ||||||
|  |   children: [ | ||||||
|  |     { | ||||||
|  |       path: 'log/operation', | ||||||
|  |       name: 'OperationLog', | ||||||
|  |       component: () => import('@/views/monitor/log/operation/index.vue'), | ||||||
|  |       meta: { | ||||||
|  |         locale: 'menu.log.operation.list', | ||||||
|  |         requiresAuth: true, | ||||||
|  |         roles: ['*'], | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export default Monitor; | ||||||
| @@ -9,7 +9,7 @@ const PROFILE: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.profile', |     locale: 'menu.profile', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     icon: 'icon-file', |     icon: 'icon-file', | ||||||
|     order: 4, |     order: 5, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const RESULT: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.result', |     locale: 'menu.result', | ||||||
|     icon: 'icon-check-circle', |     icon: 'icon-check-circle', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     order: 5, |     order: 6, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const USER: AppRouteRecordRaw = { | |||||||
|     locale: 'menu.user', |     locale: 'menu.user', | ||||||
|     icon: 'icon-user', |     icon: 'icon-user', | ||||||
|     requiresAuth: true, |     requiresAuth: true, | ||||||
|     order: 7, |     order: 8, | ||||||
|   }, |   }, | ||||||
|   children: [ |   children: [ | ||||||
|     { |     { | ||||||
|   | |||||||
							
								
								
									
										222
									
								
								continew-admin-ui/src/views/monitor/log/operation/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								continew-admin-ui/src/views/monitor/log/operation/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,222 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="container"> | ||||||
|  |     <Breadcrumb :items="['menu.monitor', 'menu.log.operation.list']" /> | ||||||
|  |     <a-card class="general-card" :title="$t('menu.log.operation.list')"> | ||||||
|  |       <a-row style="margin-bottom: 15px"> | ||||||
|  |         <a-col :span="24"> | ||||||
|  |           <a-form | ||||||
|  |             ref="queryFormRef" | ||||||
|  |             :model="queryFormData" | ||||||
|  |             layout="inline" | ||||||
|  |           > | ||||||
|  |             <a-form-item | ||||||
|  |               field="description" | ||||||
|  |               hide-label | ||||||
|  |             > | ||||||
|  |               <a-input | ||||||
|  |                 v-model="queryFormData.description" | ||||||
|  |                 placeholder="输入操作内容搜索" | ||||||
|  |                 allow-clear | ||||||
|  |                 style="width: 150px;" | ||||||
|  |                 @press-enter="toQuery" | ||||||
|  |               /> | ||||||
|  |             </a-form-item> | ||||||
|  |             <a-form-item | ||||||
|  |               field="status" | ||||||
|  |               hide-label | ||||||
|  |             > | ||||||
|  |               <a-select | ||||||
|  |                 v-model="queryFormData.status" | ||||||
|  |                 :options="statusOptions" | ||||||
|  |                 placeholder="操作状态搜索" | ||||||
|  |                 allow-clear | ||||||
|  |                 style="width: 150px;" | ||||||
|  |               /> | ||||||
|  |             </a-form-item> | ||||||
|  |             <a-form-item | ||||||
|  |               field="createTime" | ||||||
|  |               hide-label | ||||||
|  |             > | ||||||
|  |               <a-range-picker | ||||||
|  |                 v-model="queryFormData.createTime" | ||||||
|  |                 format="YYYY-MM-DD HH:mm:ss" | ||||||
|  |                 show-time | ||||||
|  |                 style="width: 100%" | ||||||
|  |               /> | ||||||
|  |             </a-form-item> | ||||||
|  |             <a-button type="primary" @click="toQuery"> | ||||||
|  |               <template #icon> | ||||||
|  |                 <icon-search /> | ||||||
|  |               </template> | ||||||
|  |               查询 | ||||||
|  |             </a-button> | ||||||
|  |             <a-button @click="resetQuery"> | ||||||
|  |               <template #icon> | ||||||
|  |                 <icon-refresh /> | ||||||
|  |               </template> | ||||||
|  |               重置 | ||||||
|  |             </a-button> | ||||||
|  |           </a-form> | ||||||
|  |         </a-col> | ||||||
|  |       </a-row> | ||||||
|  |       <a-table | ||||||
|  |         row-key="logId" | ||||||
|  |         :loading="loading" | ||||||
|  |         :pagination="pagination" | ||||||
|  |         :columns="columns" | ||||||
|  |         :data="renderData" | ||||||
|  |         :bordered="false" | ||||||
|  |         :stripe="true" | ||||||
|  |         size="large" | ||||||
|  |         @page-change="onPageChange" | ||||||
|  |       > | ||||||
|  |         <template #index="{ rowIndex }"> | ||||||
|  |           {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} | ||||||
|  |         </template> | ||||||
|  |         <template #status="{ record }"> | ||||||
|  |           <a-space v-if="record.status === 1"> | ||||||
|  |             <a-tag color="green"> | ||||||
|  |               <span class="circle pass"></span> | ||||||
|  |               成功 | ||||||
|  |             </a-tag> | ||||||
|  |           </a-space> | ||||||
|  |           <a-space v-else> | ||||||
|  |             <a-tag color="red"> | ||||||
|  |               <span class="circle fail"></span> | ||||||
|  |               失败 | ||||||
|  |             </a-tag> | ||||||
|  |           </a-space> | ||||||
|  |         </template> | ||||||
|  |       </a-table> | ||||||
|  |     </a-card> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script lang="ts" setup> | ||||||
|  |   import { computed, ref, reactive } from 'vue'; | ||||||
|  |   import useLoading from '@/hooks/loading'; | ||||||
|  |   import { queryOperationLogList, OperationLogRecord, OperationLogParams } from '@/api/monitor/operation-log'; | ||||||
|  |   import { Pagination } from '@/types/global'; | ||||||
|  |   import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface'; | ||||||
|  |   import type { TableColumnData } from '@arco-design/web-vue/es/table/interface'; | ||||||
|  |   import { FormInstance } from '@arco-design/web-vue/es/form'; | ||||||
|  |  | ||||||
|  |   const { loading, setLoading } = useLoading(true); | ||||||
|  |   const queryFormRef = ref<FormInstance>(); | ||||||
|  |   const renderData = ref<OperationLogRecord[]>([]); | ||||||
|  |  | ||||||
|  |   const queryFormData = ref({ | ||||||
|  |     description: '', | ||||||
|  |     status: undefined, | ||||||
|  |     createTime: [], | ||||||
|  |   }); | ||||||
|  |   const statusOptions = computed<SelectOptionData[]>(() => [ | ||||||
|  |     { | ||||||
|  |       label: '成功', | ||||||
|  |       value: 1, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: '失败', | ||||||
|  |       value: 2, | ||||||
|  |     }, | ||||||
|  |   ]); | ||||||
|  |  | ||||||
|  |   const basePagination: Pagination = { | ||||||
|  |     current: 1, | ||||||
|  |     pageSize: 10, | ||||||
|  |   }; | ||||||
|  |   const pagination = reactive({ | ||||||
|  |     ...basePagination, | ||||||
|  |   }); | ||||||
|  |   const columns = computed<TableColumnData[]>(() => [ | ||||||
|  |     { | ||||||
|  |       title: '序号', | ||||||
|  |       dataIndex: 'index', | ||||||
|  |       slotName: 'index', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作时间', | ||||||
|  |       dataIndex: 'createTime', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作人', | ||||||
|  |       dataIndex: 'createUserString', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作内容', | ||||||
|  |       dataIndex: 'description', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作状态', | ||||||
|  |       dataIndex: 'status', | ||||||
|  |       slotName: 'status', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作IP', | ||||||
|  |       dataIndex: 'clientIp', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '操作地点', | ||||||
|  |       dataIndex: 'location', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '浏览器', | ||||||
|  |       dataIndex: 'browser', | ||||||
|  |     }, | ||||||
|  |   ]); | ||||||
|  |   const fetchData = async ( | ||||||
|  |     params: OperationLogParams = { page: 1, size: 10, sort: ['createTime,desc'] } | ||||||
|  |   ) => { | ||||||
|  |     setLoading(true); | ||||||
|  |     try { | ||||||
|  |       const { data } = await queryOperationLogList(params); | ||||||
|  |       renderData.value = data.list; | ||||||
|  |       pagination.current = params.page; | ||||||
|  |       pagination.total = data.total; | ||||||
|  |     } catch (err) { | ||||||
|  |       // you can report use errorHandler or other | ||||||
|  |     } finally { | ||||||
|  |       setLoading(false); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   const onPageChange = (current: number) => { | ||||||
|  |     fetchData({ page: current, size: pagination.pageSize, sort: ['createTime,desc'] }); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 查询 | ||||||
|  |   const toQuery = () => { | ||||||
|  |     fetchData({ | ||||||
|  |       page: pagination.current, | ||||||
|  |       size: pagination.pageSize, | ||||||
|  |       sort: ['createTime,desc'], | ||||||
|  |       ...queryFormData.value, | ||||||
|  |     } as unknown as OperationLogParams); | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   // 重置 | ||||||
|  |   const resetQuery = async () => { | ||||||
|  |     await queryFormRef.value?.resetFields(); | ||||||
|  |     await fetchData(); | ||||||
|  |   }; | ||||||
|  |   fetchData(); | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <script lang="ts"> | ||||||
|  |   export default { | ||||||
|  |     name: 'OperationLog', | ||||||
|  |   }; | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped lang="less"> | ||||||
|  |   .container { | ||||||
|  |     padding: 0 20px 20px 20px; | ||||||
|  |   } | ||||||
|  |   :deep(.arco-table-th) { | ||||||
|  |     &:last-child { | ||||||
|  |       .arco-table-th-item-title { | ||||||
|  |         margin-left: 16px; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | </style> | ||||||
| @@ -0,0 +1,3 @@ | |||||||
|  | export default { | ||||||
|  |   'menu.log.operation.list': 'Operation log', | ||||||
|  | }; | ||||||
| @@ -0,0 +1,3 @@ | |||||||
|  | export default { | ||||||
|  |   'menu.log.operation.list': '操作日志', | ||||||
|  | }; | ||||||
| @@ -1,20 +1,21 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="container"> |   <div class="container"> | ||||||
|     <a-table |     <a-table | ||||||
|       row-key="id" |       row-key="logId" | ||||||
|       :loading="loading" |       :loading="loading" | ||||||
|       :pagination="pagination" |       :pagination="pagination" | ||||||
|       :columns="columns" |       :columns="columns" | ||||||
|       :data="renderData" |       :data="renderData" | ||||||
|       :bordered="false" |       :bordered="false" | ||||||
|  |       :stripe="true" | ||||||
|       size="large" |       size="large" | ||||||
|       @page-change="onPageChange" |       @page-change="onPageChange" | ||||||
|     > |     > | ||||||
|       <template #index="{ rowIndex }"> |       <template #index="{ rowIndex }"> | ||||||
|         {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} |         {{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }} | ||||||
|       </template> |       </template> | ||||||
|       <template #result="{ record }"> |       <template #status="{ record }"> | ||||||
|         <a-space v-if="record.result === 1"> |         <a-space v-if="record.status === 1"> | ||||||
|           <a-tag color="green"> |           <a-tag color="green"> | ||||||
|             <span class="circle pass"></span> |             <span class="circle pass"></span> | ||||||
|             成功 |             成功 | ||||||
| @@ -72,13 +73,13 @@ | |||||||
|       dataIndex: 'description', |       dataIndex: 'description', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       title: '操作结果', |       title: '操作状态', | ||||||
|       dataIndex: 'result', |       dataIndex: 'status', | ||||||
|       slotName: 'result', |       slotName: 'status', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       title: '操作IP', |       title: '操作IP', | ||||||
|       dataIndex: 'requestIp', |       dataIndex: 'clientIp', | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       title: '操作地点', |       title: '操作地点', | ||||||
|   | |||||||
| @@ -2,5 +2,5 @@ | |||||||
|  |  | ||||||
| -- changeset Charles7c:1 | -- changeset Charles7c:1 | ||||||
| -- 初始化默认用户:admin/123456;test/123456 | -- 初始化默认用户:admin/123456;test/123456 | ||||||
| INSERT IGNORE INTO `sys_user` VALUES (1, 'admin', '超级管理员', 'f0df7414507bcb57e07e18555821228a', 1, '18888888888', 'charles7c@126.com', NULL, NULL, 1, NOW(), 1, NOW(), 1, NOW()); | INSERT IGNORE INTO `sys_user` VALUES (1, 'admin', '超级管理员', '9802815bcc5baae7feb1ae0d0566baf2', 1, '18888888888', 'charles7c@126.com', NULL, NULL, 1, NOW(), 1, NOW(), 1, NOW()); | ||||||
| INSERT IGNORE INTO `sys_user` VALUES (2, 'test', '测试员', '8e114197e1b33783a00542ad67e80516', 0, NULL, NULL, NULL, NULL, 2, NOW(), 1, NOW(), 1, NOW()); | INSERT IGNORE INTO `sys_user` VALUES (2, 'test', '测试员', '8e114197e1b33783a00542ad67e80516', 0, NULL, NULL, NULL, NULL, 2, NOW(), 1, NOW(), 1, NOW()); | ||||||
|   | |||||||
| @@ -35,13 +35,13 @@ CREATE TABLE IF NOT EXISTS `sys_log` ( | |||||||
|     `response_header` text DEFAULT NULL COMMENT '响应头', |     `response_header` text DEFAULT NULL COMMENT '响应头', | ||||||
|     `response_body` mediumtext DEFAULT NULL COMMENT '响应体', |     `response_body` mediumtext DEFAULT NULL COMMENT '响应体', | ||||||
|     `elapsed_time` bigint(20) unsigned DEFAULT NULL COMMENT '请求耗时(ms)', |     `elapsed_time` bigint(20) unsigned DEFAULT NULL COMMENT '请求耗时(ms)', | ||||||
|     `result` tinyint(1) unsigned DEFAULT 1 COMMENT '操作结果(1成功 2失败)', |     `status` tinyint(1) unsigned DEFAULT 1 COMMENT '操作状态(1成功 2失败)', | ||||||
|     `request_ip` varchar(255) DEFAULT NULL COMMENT '操作IP', |     `client_ip` varchar(255) DEFAULT NULL COMMENT '客户端IP', | ||||||
|     `location` varchar(512) DEFAULT NULL COMMENT '操作地点', |     `location` varchar(512) DEFAULT NULL COMMENT 'IP归属地', | ||||||
|     `browser` varchar(255) DEFAULT NULL COMMENT '浏览器', |     `browser` varchar(255) DEFAULT NULL COMMENT '浏览器', | ||||||
|     `exception` mediumtext DEFAULT NULL COMMENT '异常', |     `exception` mediumtext DEFAULT NULL COMMENT '异常', | ||||||
|     `create_user` bigint(20) unsigned DEFAULT NULL COMMENT '操作人', |     `create_user` bigint(20) unsigned DEFAULT NULL COMMENT '创建人', | ||||||
|     `create_time` datetime NOT NULL COMMENT '操作时间', |     `create_time` datetime NOT NULL COMMENT '创建时间', | ||||||
|     PRIMARY KEY (`log_id`) USING BTREE, |     PRIMARY KEY (`log_id`) USING BTREE, | ||||||
|     INDEX `idx_createUser`(`create_user`) USING BTREE |     INDEX `idx_createUser`(`create_user`) USING BTREE | ||||||
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统日志表'; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统日志表'; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user