浏览代码

!3 system logger junit
Merge pull request !3 from kevinwang0224/unit_logger_system

芋道源码 4 年之前
父节点
当前提交
4e5430b5c0

+ 5 - 2
src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java

@@ -2,13 +2,16 @@ package cn.iocoder.dashboard.framework.logger.operatelog.core.service;
 
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO;
 
+import java.util.concurrent.Future;
+
 public interface OperateLogFrameworkService {
 
     /**
-     * 要不记录操作日志
+     * 异步记录操作日志
      *
      * @param reqVO 操作日志请求
+     * @return true: 记录成功,false: 记录失败
      */
-    void createOperateLogAsync(SysOperateLogCreateReqVO reqVO);
+    Future<Boolean> createOperateLogAsync(SysOperateLogCreateReqVO reqVO);
 
 }

+ 7 - 3
src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java

@@ -7,20 +7,22 @@ import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOp
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO;
 import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO;
 import cn.iocoder.dashboard.modules.system.convert.logger.SysOperateLogConvert;
-import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysOperateLogMapper;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysOperateLogMapper;
 import cn.iocoder.dashboard.modules.system.service.logger.SysOperateLogService;
 import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
 import cn.iocoder.dashboard.util.string.StrUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Future;
 
 import static cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO.JAVA_METHOD_ARGS_MAX_LENGTH;
 import static cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO.RESULT_MAX_LENGTH;
@@ -38,16 +40,18 @@ public class SysOperateLogServiceImpl implements SysOperateLogService {
 
     @Override
     @Async
-    public void createOperateLogAsync(SysOperateLogCreateReqVO reqVO) {
+    public Future<Boolean> createOperateLogAsync(SysOperateLogCreateReqVO reqVO) {
+        boolean success = false;
         try {
             SysOperateLogDO logDO = SysOperateLogConvert.INSTANCE.convert(reqVO);
             logDO.setJavaMethodArgs(StrUtils.maxLength(logDO.getJavaMethodArgs(), JAVA_METHOD_ARGS_MAX_LENGTH));
             logDO.setResultData(StrUtils.maxLength(logDO.getResultData(), RESULT_MAX_LENGTH));
-            operateLogMapper.insert(logDO);
+            success = operateLogMapper.insert(logDO) == 1;
         } catch (Throwable throwable) {
             // 仅仅打印日志,不对外抛出。原因是,还是要保留现场数据。
             log.error("[createOperateLogAsync][记录操作日志异常,日志为 ({})]", reqVO, throwable);
         }
+        return new AsyncResult<>(success);
     }
 
     @Override

+ 151 - 0
src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java

@@ -0,0 +1,151 @@
+package cn.iocoder.dashboard.modules.system.service.logger;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogExportReqVO;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.loginlog.SysLoginLogPageReqVO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysLoginLogDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysLoginLogMapper;
+import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginLogTypeEnum;
+import cn.iocoder.dashboard.modules.system.enums.logger.SysLoginResultEnum;
+import cn.iocoder.dashboard.modules.system.service.logger.impl.SysLoginLogServiceImpl;
+import cn.iocoder.dashboard.util.RandomUtils;
+import cn.iocoder.dashboard.util.object.ObjectUtils;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.dashboard.util.date.DateUtils.buildTime;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@Import(SysLoginLogServiceImpl.class)
+public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private SysLoginLogServiceImpl sysLoginLogService;
+
+    @Resource
+    private SysLoginLogMapper loginLogMapper;
+
+    @Test
+    public void testCreateLoginLog() {
+        String traceId = TracerUtils.getTraceId();
+        SysLoginLogCreateReqVO reqVO = RandomUtils.randomPojo(SysLoginLogCreateReqVO.class, vo -> {
+            // 指定随机的范围,避免超出范围入库失败
+            vo.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
+            vo.setResult(RandomUtil.randomEle(SysLoginResultEnum.values()).getResult());
+            // 使用TracerUtils生成的TraceId
+            vo.setTraceId(traceId);
+        });
+
+        // 执行service方法
+        sysLoginLogService.createLoginLog(reqVO);
+
+        // 断言,忽略基本字段
+        SysLoginLogDO sysLoginLogDO = loginLogMapper.selectOne(null);
+        assertPojoEquals(reqVO, sysLoginLogDO);
+    }
+
+
+    @Test
+    public void testGetLoginLogPage() {
+
+        // 构造测试数据
+
+        // 登录成功的
+        SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> {
+            logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
+            logDO.setTraceId(TracerUtils.getTraceId());
+
+            logDO.setUserIp("192.168.199.16");
+            logDO.setUsername("wangkai");
+            logDO.setCreateTime(buildTime(2021, 3, 6));
+            logDO.setResult(SysLoginResultEnum.SUCCESS.getResult());
+        });
+        loginLogMapper.insert(loginLogDO);
+
+        // 下面几个都是不匹配的数据
+        // 登录失败的
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
+        // 不同ip段的
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
+        // 不同username
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
+        // 构造一个早期时间 2021-02-06 00:00:00
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
+
+
+        // 构造调用参数
+        SysLoginLogPageReqVO reqVO = new SysLoginLogPageReqVO();
+        reqVO.setUsername("wangkai");
+        reqVO.setUserIp("192.168.199");
+        reqVO.setStatus(true);
+        reqVO.setBeginTime(buildTime(2021, 3, 5));
+        reqVO.setEndTime(buildTime(2021, 3, 7));
+
+        // 调用service方法
+        PageResult<SysLoginLogDO> pageResult = sysLoginLogService.getLoginLogPage(reqVO);
+
+        // 断言,只查到了一条符合条件的
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(loginLogDO, pageResult.getList().get(0));
+    }
+
+    @Test
+    public void testGetLoginLogList() {
+
+        // 构造测试数据
+
+        // 登录成功的
+        SysLoginLogDO loginLogDO = RandomUtils.randomPojo(SysLoginLogDO.class, logDO -> {
+            logDO.setLogType(RandomUtil.randomEle(SysLoginLogTypeEnum.values()).getType());
+            logDO.setTraceId(TracerUtils.getTraceId());
+
+            logDO.setUserIp("192.168.111.16");
+            logDO.setUsername("wangxiaokai");
+            logDO.setCreateTime(buildTime(2021, 3, 6));
+            logDO.setResult(SysLoginResultEnum.SUCCESS.getResult());
+        });
+        loginLogMapper.insert(loginLogDO);
+
+        // 下面几个都是不匹配的数据
+        // 登录失败的
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
+        // 不同ip段的
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
+        // 不同username
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
+        // 构造一个早期时间 2021-02-06 00:00:00
+        loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
+
+
+        // 构造调用参数
+        SysLoginLogExportReqVO reqVO = new SysLoginLogExportReqVO();
+        reqVO.setUsername("wangxiaokai");
+        reqVO.setUserIp("192.168.111");
+        reqVO.setStatus(true);
+        reqVO.setBeginTime(buildTime(2021, 3, 5));
+        reqVO.setEndTime(buildTime(2021, 3, 7));
+
+
+        // 调用service方法
+        List<SysLoginLogDO> loginLogList = sysLoginLogService.getLoginLogList(reqVO);
+
+        // 断言
+        assertEquals(1, loginLogList.size());
+        assertPojoEquals(loginLogDO, loginLogList.get(0));
+    }
+}

+ 208 - 0
src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java

@@ -0,0 +1,208 @@
+package cn.iocoder.dashboard.modules.system.service.logger;
+
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.dashboard.BaseDbUnitTest;
+import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
+import cn.iocoder.dashboard.common.exception.enums.GlobalErrorCodeConstants;
+import cn.iocoder.dashboard.common.pojo.PageResult;
+import cn.iocoder.dashboard.framework.logger.operatelog.core.enums.OperateTypeEnum;
+import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.dashboard.framework.tracer.core.util.TracerUtils;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogCreateReqVO;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogExportReqVO;
+import cn.iocoder.dashboard.modules.system.controller.logger.vo.operatelog.SysOperateLogPageReqVO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.logger.SysOperateLogDO;
+import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
+import cn.iocoder.dashboard.modules.system.dal.mysql.logger.SysOperateLogMapper;
+import cn.iocoder.dashboard.modules.system.dal.mysql.user.SysUserMapper;
+import cn.iocoder.dashboard.modules.system.enums.common.SysSexEnum;
+import cn.iocoder.dashboard.modules.system.service.logger.impl.SysOperateLogServiceImpl;
+import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
+import cn.iocoder.dashboard.util.RandomUtils;
+import cn.iocoder.dashboard.util.object.ObjectUtils;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+
+import javax.annotation.Resource;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
+import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
+import static cn.iocoder.dashboard.util.date.DateUtils.buildTime;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+@Import({SysOperateLogServiceImpl.class})
+public class SysOperateLogServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private SysOperateLogService sysOperateLogServiceImpl;
+
+    @Resource
+    private SysOperateLogMapper sysOperateLogMapper;
+
+    @Resource
+    private SysUserMapper sysUserMapper;
+
+    @MockBean
+    private SysUserService sysUserService;
+
+    @Test
+    public void testCreateOperateLogAsync() throws InterruptedException, ExecutionException {
+
+        String traceId = TracerUtils.getTraceId();
+        SysOperateLogCreateReqVO reqVO = RandomUtils.randomPojo(SysOperateLogCreateReqVO.class, vo -> {
+            vo.setTraceId(traceId);
+            vo.setUserId(RandomUtil.randomLong(1, Long.MAX_VALUE));
+
+            Map<String, Object> map = MapUtil.builder("orderId", (Object) 1).build();
+            vo.setExts(map);
+        });
+
+        // 执行service方法
+        Future<Boolean> future = sysOperateLogServiceImpl.createOperateLogAsync(reqVO);
+
+        // 等异步执行完
+        future.get();
+
+        // 查询插入的数据
+        SysOperateLogDO sysOperateLogDO = sysOperateLogMapper.selectOne("trace_id", traceId);
+
+        // 断言
+        assertNotNull(sysOperateLogDO);
+        // 断言,忽略基本字段
+        assertPojoEquals(reqVO, sysOperateLogDO);
+    }
+
+
+    @Test
+    public void testPageOperateLog() {
+
+        // 构造测试数据
+
+        // 先构造用户
+        SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, sysUserDO -> {
+            sysUserDO.setNickname("wangkai");
+            sysUserDO.setSex(SysSexEnum.MALE.getSEX());
+            sysUserDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        });
+        sysUserMapper.insert(user);
+        Long userId = user.getId();
+
+
+        // 构造操作日志
+        SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, entity -> {
+            entity.setTraceId(TracerUtils.getTraceId());
+            entity.setUserId(userId);
+            entity.setModule("order");
+            entity.setType(OperateTypeEnum.CREATE.getType());
+            entity.setStartTime(buildTime(2021, 3, 6));
+            entity.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode());
+
+            Map<String, Object> map = new HashMap<>();
+            map.put("orderId", 1);
+            entity.setExts(map);
+        });
+
+        sysOperateLogMapper.insert(sysOperateLogDO);
+
+        // 下面几个是不匹配的数据
+        // 随机userId
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
+        // module不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
+        // type不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
+        // createTime不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
+        // resultCode不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
+
+        // 构造调用参数
+        SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO();
+        reqVO.setUserNickname("wangkai");
+        reqVO.setModule("order");
+        reqVO.setType(OperateTypeEnum.CREATE.getType());
+        reqVO.setBeginTime(buildTime(2021, 3, 5));
+        reqVO.setEndTime(buildTime(2021, 3, 7));
+        reqVO.setSuccess(true);
+
+        // 调用service方法
+        PageResult<SysOperateLogDO> pageResult = sysOperateLogServiceImpl.pageOperateLog(reqVO);
+
+        // 断言,只查到了一条符合条件的
+        assertEquals(1, pageResult.getTotal());
+        assertEquals(1, pageResult.getList().size());
+        assertPojoEquals(sysOperateLogDO, pageResult.getList().get(0));
+    }
+
+    @Test
+    public void testListOperateLogs() {
+
+        // 构造测试数据
+
+        // 先构造用户
+        SysUserDO user = RandomUtils.randomPojo(SysUserDO.class, sysUserDO -> {
+            sysUserDO.setNickname("wangkai");
+            sysUserDO.setSex(SysSexEnum.MALE.getSEX());
+            sysUserDO.setStatus(CommonStatusEnum.ENABLE.getStatus());
+        });
+        sysUserMapper.insert(user);
+        Long userId = user.getId();
+
+
+        // 构造操作日志
+        SysOperateLogDO sysOperateLogDO = RandomUtils.randomPojo(SysOperateLogDO.class, entity -> {
+            entity.setTraceId(TracerUtils.getTraceId());
+            entity.setUserId(userId);
+            entity.setModule("order");
+            entity.setType(OperateTypeEnum.CREATE.getType());
+            entity.setStartTime(buildTime(2021, 3, 6));
+            entity.setResultCode(GlobalErrorCodeConstants.SUCCESS.getCode());
+
+
+            Map<String, Object> map = MapUtil.builder("orderId", (Object) 1).build();
+            entity.setExts(map);
+        });
+
+        sysOperateLogMapper.insert(sysOperateLogDO);
+
+        // 下面几个是不匹配的数据
+        // 随机userId
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
+        // module不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
+        // type不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
+        // createTime不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
+        // resultCode不同
+        sysOperateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
+
+        // 构造调用参数
+        SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO();
+        reqVO.setUserNickname("wangkai");
+        reqVO.setModule("order");
+        reqVO.setType(OperateTypeEnum.CREATE.getType());
+        reqVO.setBeginTime(buildTime(2021, 3, 5));
+        reqVO.setEndTime(buildTime(2021, 3, 7));
+        reqVO.setSuccess(true);
+
+        // 调用service方法
+        List<SysOperateLogDO> list = sysOperateLogServiceImpl.listOperateLogs(reqVO);
+
+        // 断言,只查到了一条符合条件的
+        assertEquals(1, list.size());
+        assertPojoEquals(sysOperateLogDO, list.get(0));
+    }
+}

+ 3 - 0
src/test/resources/sql/clean.sql

@@ -10,3 +10,6 @@ DELETE FROM "sys_menu";
 DELETE FROM "sys_dict_type";
 DELETE FROM "sys_user_session";
 DELETE FROM "sys_post";
+DELETE FROM "sys_login_log";
+DELETE FROM "sys_operate_log";
+DELETE FROM "sys_user";

+ 68 - 0
src/test/resources/sql/create_tables.sql

@@ -161,3 +161,71 @@ CREATE TABLE IF NOT EXISTS "sys_notice" (
 	PRIMARY KEY("id")
 ) COMMENT '通知公告表';
 
+
+CREATE TABLE IF NOT EXISTS `sys_login_log` (
+    `id`          bigint(20)   NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    `log_type`    bigint(4)    NOT NULL,
+    `trace_id`    varchar(64)  NOT NULL DEFAULT '',
+    `username`    varchar(50)  NOT NULL DEFAULT '',
+    `result`      tinyint(4)   NOT NULL,
+    `user_ip`     varchar(50)  NOT NULL,
+    `user_agent`  varchar(512) NOT NULL,
+    `creator`   varchar(64)           DEFAULT '',
+    `create_time` datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    `updater`   varchar(64)           DEFAULT '',
+    `update_time` datetime     NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `deleted`     bit(1)       NOT NULL DEFAULT '0',
+    PRIMARY KEY (`id`)
+) COMMENT ='系统访问记录';
+
+
+CREATE TABLE `sys_operate_log` (
+    `id`               bigint(20)    NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    `trace_id`         varchar(64)   NOT NULL DEFAULT '',
+    `user_id`          bigint(20)    NOT NULL,
+    `module`           varchar(50)   NOT NULL,
+    `name`             varchar(50)   NOT NULL,
+    `operate_type`     bigint(4)     NOT NULL DEFAULT '0',
+    `content`          varchar(2000) NOT NULL DEFAULT '',
+    `exts`             varchar(512)  NOT NULL DEFAULT '',
+    `request_method`   varchar(16)            DEFAULT '',
+    `request_url`      varchar(255)           DEFAULT '',
+    `user_ip`          varchar(50)            DEFAULT NULL,
+    `user_agent`       varchar(200)           DEFAULT NULL,
+    `java_method`      varchar(512)  NOT NULL DEFAULT '',
+    `java_method_args` varchar(8000)          DEFAULT '',
+    `start_time`       datetime      NOT NULL,
+    `duration`         int(11)       NOT NULL,
+    `result_code`      int(11)       NOT NULL DEFAULT '0',
+    `result_msg`       varchar(512)           DEFAULT '',
+    `result_data`      varchar(4000)          DEFAULT '',
+    `creator`        varchar(64)            DEFAULT '',
+    `create_time`      datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    `updater`        varchar(64)            DEFAULT '',
+    `update_time`      datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `deleted`          bit(1)        NOT NULL DEFAULT '0',
+    PRIMARY KEY (`id`)
+) COMMENT ='操作日志记录';
+
+create table "sys_user" (
+    "id" bigint not null GENERATED BY DEFAULT AS IDENTITY,
+    "username" varchar(30) not null,
+    "password" varchar(100) not null default '',
+    "nickname" varchar(30) not null,
+    "remark" varchar(500) default null,
+    "dept_id" bigint default null,
+    "post_ids" varchar(255) default null,
+    "email" varchar(50) default '',
+    "mobile" varchar(11) default '',
+    "sex" tinyint default '0',
+    "avatar" varchar(100) default '',
+    "status" tinyint not null default '0',
+    "login_ip" varchar(50) default '',
+    "login_date" timestamp default null,
+    "creator" varchar(64) default '',
+    "create_time" timestamp not null default current_timestamp,
+    "updater" varchar(64) default '',
+    "update_time" timestamp not null default current_timestamp,
+    "deleted" bit not null default false,
+    primary key ("id")
+) comment '用户信息表';