diff --git a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java b/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java index c02e4038a..d16ecf804 100644 --- a/src/main/java/cn/iocoder/dashboard/framework/logger/operatelog/core/service/OperateLogFrameworkService.java +++ b/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 createOperateLogAsync(SysOperateLogCreateReqVO reqVO); } diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java index ab68f25b7..a27bf0246 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/logger/impl/SysOperateLogServiceImpl.java +++ b/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 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 diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysLoginLogServiceImplTest.java new file mode 100644 index 000000000..95f2d1985 --- /dev/null +++ b/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 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 loginLogList = sysLoginLogService.getLoginLogList(reqVO); + + // 断言 + assertEquals(1, loginLogList.size()); + assertPojoEquals(loginLogDO, loginLogList.get(0)); + } +} diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/logger/SysOperateLogServiceImplTest.java new file mode 100644 index 000000000..0f071ea7b --- /dev/null +++ b/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 map = MapUtil.builder("orderId", (Object) 1).build(); + vo.setExts(map); + }); + + // 执行service方法 + Future 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 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 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 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 list = sysOperateLogServiceImpl.listOperateLogs(reqVO); + + // 断言,只查到了一条符合条件的 + assertEquals(1, list.size()); + assertPojoEquals(sysOperateLogDO, list.get(0)); + } +} diff --git a/src/test/resources/sql/clean.sql b/src/test/resources/sql/clean.sql index af50ad635..7c847f5a1 100644 --- a/src/test/resources/sql/clean.sql +++ b/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"; diff --git a/src/test/resources/sql/create_tables.sql b/src/test/resources/sql/create_tables.sql index b0558e25b..96ac8088a 100644 --- a/src/test/resources/sql/create_tables.sql +++ b/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 '用户信息表';