Commit e2c3879a79e1f6ce550f63c21ca3e52826a6ac29

Authored by huanggang
1 parent 1113ff62

logging service supported

assistant-logging/src/main/java/com/diligrp/assistant/logging/LoggingConfiguration.java
1 1 package com.diligrp.assistant.logging;
2 2  
  3 +import com.diligrp.assistant.shared.mybatis.MybatisMapperSupport;
  4 +import org.mybatis.spring.annotation.MapperScan;
3 5 import org.springframework.context.annotation.ComponentScan;
4 6 import org.springframework.context.annotation.Configuration;
5 7  
6 8 @Configuration
7 9 @ComponentScan("com.diligrp.assistant.logging")
  10 +@MapperScan(basePackages = {"com.diligrp.assistant.logging.dao"}, markerInterface = MybatisMapperSupport.class)
8 11 public class LoggingConfiguration {
9 12 }
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/controller/UserEventController.java 0 → 100644
  1 +package com.diligrp.assistant.logging.controller;
  2 +
  3 +import com.diligrp.assistant.logging.domain.EventPageQuery;
  4 +import com.diligrp.assistant.logging.domain.UserEventDTO;
  5 +import com.diligrp.assistant.logging.service.UserEventService;
  6 +import com.diligrp.assistant.shared.domain.Message;
  7 +import com.diligrp.assistant.shared.domain.PageMessage;
  8 +import com.diligrp.assistant.shared.service.ThreadPollService;
  9 +import com.diligrp.assistant.shared.util.AssertUtils;
  10 +import jakarta.annotation.Resource;
  11 +import org.springframework.web.bind.annotation.RequestBody;
  12 +import org.springframework.web.bind.annotation.RequestMapping;
  13 +import org.springframework.web.bind.annotation.RequestParam;
  14 +import org.springframework.web.bind.annotation.RestController;
  15 +
  16 +import java.time.LocalDateTime;
  17 +import java.util.List;
  18 +
  19 +@RestController
  20 +@RequestMapping("/logging/event")
  21 +public class UserEventController {
  22 +
  23 + @Resource
  24 + private UserEventService userEventService;
  25 +
  26 + @RequestMapping(value = "/fire.do")
  27 + public Message<?> fire(@RequestBody UserEventDTO request, @RequestParam(value = "async", defaultValue = "false") boolean async) {
  28 + AssertUtils.notEmpty(request.getModuleId(), "moduleId missed");
  29 + AssertUtils.notEmpty(request.getAction(), "action missed");
  30 + AssertUtils.notEmpty(request.getObjectId(), "objectId missed");
  31 + AssertUtils.notNull(request.getWhen(), "when missed");
  32 + AssertUtils.notEmpty(request.getUserId(), "userId missed");
  33 +
  34 + if (async) {
  35 + ThreadPollService.getInstance().submit(() -> userEventService.insertUserEvent(request));
  36 + } else {
  37 + userEventService.insertUserEvent(request);
  38 + }
  39 + return Message.success();
  40 + }
  41 +
  42 + @RequestMapping(value = "/fires.do")
  43 + public Message<?> fires(@RequestBody List<UserEventDTO> request, @RequestParam(value = "async", defaultValue = "false") boolean async) {
  44 + request.stream().forEach(event -> {
  45 + AssertUtils.notEmpty(event.getModuleId(), "moduleId missed");
  46 + AssertUtils.notEmpty(event.getAction(), "action missed");
  47 + AssertUtils.notEmpty(event.getObjectId(), "objectId missed");
  48 + AssertUtils.notNull(event.getWhen(), "when missed");
  49 + AssertUtils.notEmpty(event.getUserId(), "userId missed");
  50 + });
  51 +
  52 + if (async) {
  53 + ThreadPollService.getInstance().submit(() -> userEventService.insertUserEvents(request));
  54 + } else {
  55 + userEventService.insertUserEvents(request);
  56 + }
  57 + return Message.success();
  58 + }
  59 +
  60 + @RequestMapping(value = "/list.do")
  61 + public PageMessage<UserEventDTO> list(@RequestBody EventPageQuery request) {
  62 + AssertUtils.notNull(request.getStartTime(), "startTime missed");
  63 + AssertUtils.notNull(request.getPageNo(), "pageNo missed");
  64 + AssertUtils.notNull(request.getPageSize(), "pageSize missed");
  65 + AssertUtils.isTrue(request.getPageNo() > 0, "invalid pageNo");
  66 + AssertUtils.isTrue(request.getPageSize() > 0, "invalid pageSize");
  67 +
  68 + // 如果未指定结束时间,则查询一天的日志数据
  69 + LocalDateTime endTime = request.getEndTime() == null ? request.getStartTime().plusDays(1) : request.getEndTime();
  70 + request.setEndTime(endTime);
  71 + request.from(request.getPageNo(), request.getPageSize());
  72 +
  73 + return userEventService.listUserEvents(request);
  74 + }
  75 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/dao/UserEventDao.java 0 → 100644
  1 +package com.diligrp.assistant.logging.dao;
  2 +
  3 +import com.diligrp.assistant.logging.domain.EventPageQuery;
  4 +import com.diligrp.assistant.logging.model.UserEventDo;
  5 +import com.diligrp.assistant.shared.mybatis.MybatisMapperSupport;
  6 +import org.springframework.stereotype.Repository;
  7 +
  8 +import java.util.List;
  9 +
  10 +@Repository("userEventDao")
  11 +public interface UserEventDao extends MybatisMapperSupport {
  12 + void insertUserEvent(UserEventDo event);
  13 +
  14 + void insertUserEvents(List<UserEventDo> events);
  15 +
  16 + long countUserEvents(EventPageQuery query);
  17 +
  18 + List<UserEventDo> listUserEvents(EventPageQuery query);
  19 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/domain/EventPageQuery.java 0 → 100644
  1 +package com.diligrp.assistant.logging.domain;
  2 +
  3 +import com.diligrp.assistant.shared.domain.PageQuery;
  4 +
  5 +import java.time.LocalDateTime;
  6 +
  7 +public class EventPageQuery extends PageQuery {
  8 + // 页号
  9 + private Integer pageNo = 1;
  10 + // 每页记录数
  11 + private Integer pageSize = 20;
  12 + // 事件分组ID
  13 + private String groupId;
  14 + // 系统模块ID
  15 + private String moduleId;
  16 + // 事件动作
  17 + private String action;
  18 + // 操作对象ID
  19 + private String objectId;
  20 + // 操作对象
  21 + private String objectName;
  22 + // 操作人ID
  23 + private String userId;
  24 + // 操作人
  25 + private String userName;
  26 + // 事件来源-IP/MAC
  27 + private String source;
  28 + // 开始时间
  29 + private LocalDateTime startTime;
  30 + // 结束时间
  31 + private LocalDateTime endTime;
  32 +
  33 + public Integer getPageNo() {
  34 + return pageNo;
  35 + }
  36 +
  37 + public void setPageNo(Integer pageNo) {
  38 + this.pageNo = pageNo;
  39 + }
  40 +
  41 + public Integer getPageSize() {
  42 + return pageSize;
  43 + }
  44 +
  45 + public void setPageSize(Integer pageSize) {
  46 + this.pageSize = pageSize;
  47 + }
  48 +
  49 + public String getGroupId() {
  50 + return groupId;
  51 + }
  52 +
  53 + public void setGroupId(String groupId) {
  54 + this.groupId = groupId;
  55 + }
  56 +
  57 + public String getModuleId() {
  58 + return moduleId;
  59 + }
  60 +
  61 + public void setModuleId(String moduleId) {
  62 + this.moduleId = moduleId;
  63 + }
  64 +
  65 + public String getAction() {
  66 + return action;
  67 + }
  68 +
  69 + public void setAction(String action) {
  70 + this.action = action;
  71 + }
  72 +
  73 + public String getObjectId() {
  74 + return objectId;
  75 + }
  76 +
  77 + public void setObjectId(String objectId) {
  78 + this.objectId = objectId;
  79 + }
  80 +
  81 + public String getObjectName() {
  82 + return objectName;
  83 + }
  84 +
  85 + public void setObjectName(String objectName) {
  86 + this.objectName = objectName;
  87 + }
  88 +
  89 + public String getUserId() {
  90 + return userId;
  91 + }
  92 +
  93 + public void setUserId(String userId) {
  94 + this.userId = userId;
  95 + }
  96 +
  97 + public String getUserName() {
  98 + return userName;
  99 + }
  100 +
  101 + public void setUserName(String userName) {
  102 + this.userName = userName;
  103 + }
  104 +
  105 + public String getSource() {
  106 + return source;
  107 + }
  108 +
  109 + public void setSource(String source) {
  110 + this.source = source;
  111 + }
  112 +
  113 + public LocalDateTime getStartTime() {
  114 + return startTime;
  115 + }
  116 +
  117 + public void setStartTime(LocalDateTime startTime) {
  118 + this.startTime = startTime;
  119 + }
  120 +
  121 + public LocalDateTime getEndTime() {
  122 + return endTime;
  123 + }
  124 +
  125 + public void setEndTime(LocalDateTime endTime) {
  126 + this.endTime = endTime;
  127 + }
  128 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/domain/UserEventDTO.java 0 → 100644
  1 +package com.diligrp.assistant.logging.domain;
  2 +
  3 +import com.diligrp.assistant.logging.model.UserEventDo;
  4 +
  5 +public class UserEventDTO extends UserEventDo {
  6 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/model/UserEventDo.java 0 → 100644
  1 +package com.diligrp.assistant.logging.model;
  2 +
  3 +import com.diligrp.assistant.shared.domain.BaseDo;
  4 +
  5 +import java.time.LocalDateTime;
  6 +
  7 +public class UserEventDo extends BaseDo {
  8 + // 事件分组ID
  9 + private String groupId;
  10 + // 系统模块ID
  11 + private String moduleId;
  12 + // 事件动作
  13 + private String action;
  14 + // 操作对象ID
  15 + private String objectId;
  16 + // 操作对象
  17 + private String objectName;
  18 + // 事件描述
  19 + private String event;
  20 + // 发生时间
  21 + private LocalDateTime when;
  22 + // 操作人ID
  23 + private String userId;
  24 + // 操作人
  25 + private String userName;
  26 + // 事件来源-IP/MAC
  27 + private String source;
  28 +
  29 + public String getGroupId() {
  30 + return groupId;
  31 + }
  32 +
  33 + public void setGroupId(String groupId) {
  34 + this.groupId = groupId;
  35 + }
  36 +
  37 + public String getModuleId() {
  38 + return moduleId;
  39 + }
  40 +
  41 + public void setModuleId(String moduleId) {
  42 + this.moduleId = moduleId;
  43 + }
  44 +
  45 + public String getAction() {
  46 + return action;
  47 + }
  48 +
  49 + public void setAction(String action) {
  50 + this.action = action;
  51 + }
  52 +
  53 + public String getObjectId() {
  54 + return objectId;
  55 + }
  56 +
  57 + public void setObjectId(String objectId) {
  58 + this.objectId = objectId;
  59 + }
  60 +
  61 + public String getObjectName() {
  62 + return objectName;
  63 + }
  64 +
  65 + public void setObjectName(String objectName) {
  66 + this.objectName = objectName;
  67 + }
  68 +
  69 + public String getEvent() {
  70 + return event;
  71 + }
  72 +
  73 + public void setEvent(String event) {
  74 + this.event = event;
  75 + }
  76 +
  77 + public LocalDateTime getWhen() {
  78 + return when;
  79 + }
  80 +
  81 + public void setWhen(LocalDateTime when) {
  82 + this.when = when;
  83 + }
  84 +
  85 + public String getUserId() {
  86 + return userId;
  87 + }
  88 +
  89 + public void setUserId(String userId) {
  90 + this.userId = userId;
  91 + }
  92 +
  93 + public String getUserName() {
  94 + return userName;
  95 + }
  96 +
  97 + public void setUserName(String userName) {
  98 + this.userName = userName;
  99 + }
  100 +
  101 + public String getSource() {
  102 + return source;
  103 + }
  104 +
  105 + public void setSource(String source) {
  106 + this.source = source;
  107 + }
  108 +
  109 + public static Builder builder() {
  110 + return new UserEventDo().new Builder();
  111 + }
  112 +
  113 + public class Builder {
  114 + public Builder groupId(String groupId) {
  115 + UserEventDo.this.groupId = groupId;
  116 + return this;
  117 + }
  118 +
  119 + public Builder moduleId(String moduleId) {
  120 + UserEventDo.this.moduleId = moduleId;
  121 + return this;
  122 + }
  123 +
  124 + public Builder action(String action) {
  125 + UserEventDo.this.action = action;
  126 + return this;
  127 + }
  128 +
  129 + public Builder objectId(String objectId) {
  130 + UserEventDo.this.objectId = objectId;
  131 + return this;
  132 + }
  133 +
  134 + public Builder objectName(String objectName) {
  135 + UserEventDo.this.objectName = objectName;
  136 + return this;
  137 + }
  138 +
  139 + public Builder event(String event) {
  140 + UserEventDo.this.event = event;
  141 + return this;
  142 + }
  143 +
  144 + public Builder when(LocalDateTime when) {
  145 + UserEventDo.this.when = when;
  146 + return this;
  147 + }
  148 +
  149 + public Builder userId(String userId) {
  150 + UserEventDo.this.userId = userId;
  151 + return this;
  152 + }
  153 +
  154 + public Builder userName(String userName) {
  155 + UserEventDo.this.userName = userName;
  156 + return this;
  157 + }
  158 +
  159 + public Builder source(String source) {
  160 + UserEventDo.this.source = source;
  161 + return this;
  162 + }
  163 +
  164 + public Builder createdTime(LocalDateTime createdTime) {
  165 + UserEventDo.this.createdTime = createdTime;
  166 + return this;
  167 + }
  168 +
  169 + public UserEventDo build() {
  170 + return UserEventDo.this;
  171 + }
  172 + }
  173 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/service/UserEventService.java 0 → 100644
  1 +package com.diligrp.assistant.logging.service;
  2 +
  3 +import com.diligrp.assistant.logging.domain.EventPageQuery;
  4 +import com.diligrp.assistant.logging.domain.UserEventDTO;
  5 +import com.diligrp.assistant.logging.model.UserEventDo;
  6 +import com.diligrp.assistant.shared.domain.PageMessage;
  7 +
  8 +import java.util.List;
  9 +
  10 +public interface UserEventService {
  11 + void insertUserEvent(UserEventDTO event);
  12 +
  13 + void insertUserEvents(List<UserEventDTO> events);
  14 +
  15 + PageMessage<UserEventDTO> listUserEvents(EventPageQuery query);
  16 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/service/impl/UserEventServiceImpl.java 0 → 100644
  1 +package com.diligrp.assistant.logging.service.impl;
  2 +
  3 +import com.diligrp.assistant.logging.dao.UserEventDao;
  4 +import com.diligrp.assistant.logging.domain.EventPageQuery;
  5 +import com.diligrp.assistant.logging.domain.UserEventDTO;
  6 +import com.diligrp.assistant.logging.model.UserEventDo;
  7 +import com.diligrp.assistant.logging.service.UserEventService;
  8 +import com.diligrp.assistant.logging.util.UserEventConverters;
  9 +import com.diligrp.assistant.shared.domain.PageMessage;
  10 +import jakarta.annotation.Resource;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.transaction.annotation.Transactional;
  13 +
  14 +import java.time.LocalDateTime;
  15 +import java.util.Collections;
  16 +import java.util.List;
  17 +import java.util.stream.Collectors;
  18 +
  19 +@Service("userEventService")
  20 +public class UserEventServiceImpl implements UserEventService {
  21 +
  22 + @Resource
  23 + private UserEventDao userEventDao;
  24 +
  25 + @Override
  26 + @Transactional(rollbackFor = Exception.class)
  27 + public void insertUserEvent(UserEventDTO event) {
  28 + event.setCreatedTime(LocalDateTime.now());
  29 + userEventDao.insertUserEvent(UserEventConverters.DTO2DO.convert(event));
  30 + }
  31 +
  32 + @Override
  33 + @Transactional(rollbackFor = Exception.class)
  34 + public void insertUserEvents(List<UserEventDTO> events) {
  35 + LocalDateTime now = LocalDateTime.now();
  36 + events.forEach(event -> event.setCreatedTime(now));
  37 + userEventDao.insertUserEvents(events.stream().map(UserEventConverters.DTO2DO::convert).collect(Collectors.toList()));
  38 + }
  39 +
  40 + @Override
  41 + public PageMessage<UserEventDTO> listUserEvents(EventPageQuery query) {
  42 + long total = userEventDao.countUserEvents(query);
  43 + List<UserEventDTO> dtos = null;
  44 +
  45 + if (total > 0) {
  46 + dtos = userEventDao.listUserEvents(query).stream().map(UserEventConverters.DO2DTO::convert).collect(Collectors.toList());
  47 + } else {
  48 + dtos = Collections.emptyList();
  49 + }
  50 +
  51 + return PageMessage.success(total, dtos);
  52 + }
  53 +}
... ...
assistant-logging/src/main/java/com/diligrp/assistant/logging/util/UserEventConverters.java 0 → 100644
  1 +package com.diligrp.assistant.logging.util;
  2 +
  3 +import com.diligrp.assistant.logging.domain.UserEventDTO;
  4 +import com.diligrp.assistant.logging.model.UserEventDo;
  5 +import org.springframework.core.convert.converter.Converter;
  6 +
  7 +public final class UserEventConverters {
  8 + public static final Converter<UserEventDTO, UserEventDo> DTO2DO = new DTO2DO();
  9 +
  10 + public static final Converter<UserEventDo, UserEventDTO> DO2DTO = new DO2DTO();
  11 +
  12 + private static class DTO2DO implements Converter<UserEventDTO, UserEventDo> {
  13 + @Override
  14 + public UserEventDo convert(UserEventDTO source) {
  15 + return (UserEventDo) source;
  16 + }
  17 + }
  18 +
  19 + private static class DO2DTO implements Converter<UserEventDo, UserEventDTO> {
  20 + @Override
  21 + public UserEventDTO convert(UserEventDo source) {
  22 + UserEventDTO dto = new UserEventDTO();
  23 + dto.setGroupId(source.getGroupId());
  24 + dto.setModuleId(source.getModuleId());
  25 + dto.setAction(source.getAction());
  26 + dto.setObjectId(source.getObjectId());
  27 + dto.setObjectName(source.getObjectName());
  28 + dto.setEvent(source.getEvent());
  29 + dto.setWhen(source.getWhen());
  30 + dto.setUserId(source.getUserId());
  31 + dto.setUserName(source.getUserName());
  32 + dto.setCreatedTime(source.getCreatedTime());
  33 +
  34 + return dto;
  35 + }
  36 + }
  37 +}
... ...
assistant-logging/src/main/resources/com/diligrp/assistant/dao/mapper/UserEventDao.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3 + "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4 +
  5 +<mapper namespace="com.diligrp.assistant.logging.dao.UserEventDao">
  6 + <resultMap id="UserEventMap" type="com.diligrp.assistant.logging.model.UserEventDo">
  7 + <id column="id" property="id"/>
  8 + <result column="group_id" property="groupId"/>
  9 + <result column="module_id" property="moduleId"/>
  10 + <result column="action" property="action"/>
  11 + <result column="object_id" property="objectId"/>
  12 + <result column="object_name" property="objectName"/>
  13 + <result column="event" property="event"/>
  14 + <result column="when" property="when"/>
  15 + <result column="user_id" property="userId"/>
  16 + <result column="user_name" property="userName"/>
  17 + <result column="source" property="source"/>
  18 + <result column="created_time" property="createdTime"/>
  19 + </resultMap>
  20 +
  21 + <insert id="insertUserEvent" parameterType="com.diligrp.assistant.sms.model.SmsTemplateDo">
  22 + INSERT INTO logging_user_event
  23 + (`group_id`, `module_id`, `action`, `object_id`, `object_name`, `event`, `when`, `user_id`, `user_name`, `source`, `created_time`)
  24 + VALUES
  25 + (#{groupId}, #{moduleId}, #{action}, #{objectId}, #{objectName}, #{event}, #{when}, #{userId}, #{userName}, #{source}, #{createdTime})
  26 + </insert>
  27 +
  28 + <insert id="insertUserEvents">
  29 + INSERT INTO logging_user_event
  30 + (`group_id`, `module_id`, `action`, `object_id`, `object_name`, `event`, `when`, `user_id`, `user_name`, `source`, `created_time`)
  31 + VALUES
  32 + <foreach collection="list" item="item" separator=",">
  33 + (#{item.groupId}, #{item.moduleId}, #{item.action}, #{item.objectId}, #{item.objectName}, #{item.event}, #{item.when}, #{item.userId}, #{item.userName}, #{item.source}, #{item.createdTime})
  34 + </foreach>
  35 + </insert>
  36 +
  37 + <select id="countUserEvents" parameterType="com.diligrp.assistant.logging.domain.EventPageQuery" resultType="long">
  38 + SELECT
  39 + COUNT(*)
  40 + FROM
  41 + logging_user_event
  42 + <where>
  43 + <if test="groupId != null">
  44 + AND `group_id` = #{groupId}
  45 + </if>
  46 + <if test="moduleId != null">
  47 + AND `module_id` = #{moduleId}
  48 + </if>
  49 + <if test="action != null">
  50 + AND `action` = #{action}
  51 + </if>
  52 + <if test="objectId != null">
  53 + AND `object_id` = #{objectId}
  54 + </if>
  55 + <if test="objectName != null">
  56 + AND `object_name` = #{objectName}
  57 + </if>
  58 + <if test="userId != null">
  59 + AND `user_id` = #{userId}
  60 + </if>
  61 + <if test="userName != null">
  62 + AND `user_name` = #{userName}
  63 + </if>
  64 + <if test="source != null">
  65 + AND `source` = #{source}
  66 + </if>
  67 + <if test="startTime != null">
  68 + <![CDATA[AND `when` >= #{startTime}]]>
  69 + </if>
  70 + <if test="endTime != null">
  71 + <![CDATA[AND `when` <= #{endTime}]]>
  72 + </if>
  73 + </where>
  74 + </select>
  75 +
  76 + <select id="listUserEvents" parameterType="com.diligrp.assistant.logging.domain.EventPageQuery" resultMap="UserEventMap">
  77 + SELECT
  78 + *
  79 + FROM
  80 + logging_user_event
  81 + <where>
  82 + <if test="groupId != null">
  83 + AND `group_id` = #{groupId}
  84 + </if>
  85 + <if test="moduleId != null">
  86 + AND `module_id` = #{moduleId}
  87 + </if>
  88 + <if test="action != null">
  89 + AND `action` = #{action}
  90 + </if>
  91 + <if test="objectId != null">
  92 + AND `object_id` = #{objectId}
  93 + </if>
  94 + <if test="objectName != null">
  95 + AND `object_name` = #{objectName}
  96 + </if>
  97 + <if test="userId != null">
  98 + AND `user_id` = #{userId}
  99 + </if>
  100 + <if test="userName != null">
  101 + AND `user_name` = #{userName}
  102 + </if>
  103 + <if test="source != null">
  104 + AND `source` = #{source}
  105 + </if>
  106 + <if test="startTime != null">
  107 + <![CDATA[AND `when` >= #{startTime}]]>
  108 + </if>
  109 + <if test="endTime != null">
  110 + <![CDATA[AND `when` <= #{endTime}]]>
  111 + </if>
  112 + </where>
  113 + ORDER BY id DESC
  114 + LIMIT #{start}, #{limit}
  115 + </select>
  116 +</mapper>
... ...
scripts/dili-assistant.sql
... ... @@ -156,3 +156,27 @@ CREATE TABLE `product_category` (
156 156 KEY `idx_product_category_name` (`name`) USING BTREE,
157 157 KEY `idx_product_category_shortCode` (`short_code`, `py_code`) USING BTREE
158 158 ) ENGINE=InnoDB;
  159 +
  160 +-- --------------------------------------------------------------------
  161 +-- 用户操作日志
  162 +-- --------------------------------------------------------------------
  163 +DROP TABLE IF EXISTS `logging_user_event`;
  164 +CREATE TABLE `logging_user_event` (
  165 + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  166 + `group_id` VARCHAR(20) COMMENT '事件分组ID', -- 按照商户/市场/店铺/卖家/业务系统等进行分组
  167 + `module_id` VARCHAR(40) NOT NULL COMMENT '系统模块ID', -- 如:订单管理/商品销售
  168 + `action` VARCHAR(20) NOT NULL COMMENT '事件动作', -- 如:新增/删除/修改/审核
  169 + `object_id` VARCHAR(20) NOT NULL COMMENT '操作对象ID', -- 事件发生的对象
  170 + `object_name` VARCHAR(40) COMMENT '操作对象',
  171 + `event` VARCHAR(250) COMMENT '事件描述', -- 详细事件描述,按照需要进行拼接
  172 + `when` DATETIME NOT NULL COMMENT '发生时间',
  173 + `user_id` VARCHAR(20) NOT NULL COMMENT '操作人ID',
  174 + `user_name` VARCHAR(40) COMMENT '操作人',
  175 + `source` VARCHAR(40) COMMENT '事件来源-IP/MAC', -- 可记录客户端IP/MAC地址/手机设备标识
  176 + `created_time` DATETIME COMMENT '创建时间',
  177 + PRIMARY KEY (`id`),
  178 + KEY `idx_user_event_objectId` (`object_id`) USING BTREE,
  179 + KEY `idx_user_event_action` (`action`, `module_id`) USING BTREE,
  180 + KEY `idx_user_event_when` (`when`) USING BTREE,
  181 + KEY `idx_user_event_userId` (`user_id`) USING BTREE
  182 +) ENGINE=InnoDB;
... ...