Browse Source

feat[litemall-admin, litemall-admin-api]: 支持操作日志管理

Junling Bu 6 years ago
parent
commit
d27fd3892c
18 changed files with 3654 additions and 17 deletions
  1. 52 4
      doc/platform.md
  2. 4 0
      litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminOrderService.java
  3. 114 0
      litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/LogHelper.java
  4. 6 0
      litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminAdminController.java
  5. 12 0
      litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminAuthController.java
  6. 47 0
      litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminLogController.java
  7. 9 0
      litemall-admin/src/api/log.js
  8. 10 0
      litemall-admin/src/router/index.js
  9. 98 0
      litemall-admin/src/views/sys/log.vue
  10. 1 8
      litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/util/IpUtil.java
  11. 3 0
      litemall-db/mybatis-generator/generatorConfig.xml
  12. 159 0
      litemall-db/src/main/java/org/linlinjava/litemall/db/dao/LitemallLogMapper.java
  13. 666 0
      litemall-db/src/main/java/org/linlinjava/litemall/db/domain/LitemallLog.java
  14. 1918 0
      litemall-db/src/main/java/org/linlinjava/litemall/db/domain/LitemallLogExample.java
  15. 46 0
      litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallLogService.java
  16. 504 0
      litemall-db/src/main/resources/org/linlinjava/litemall/db/dao/LitemallLogMapper.xml
  17. 1 1
      litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/service/WxOrderService.java
  18. 4 4
      litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxAuthController.java

+ 52 - 4
doc/platform.md

@@ -463,25 +463,73 @@ litemall_coupon_user表的status字段,包含以后三种状态:
 当用户或者管理员上传图像时,图像文件会保存到本地或者第三方云存储服务器中,
 同时在存储对象表中记录一下。
 
-### 2.1.10 通用设计
+### 2.1.10 操作日志设计
+
+业务日志表litemall_log记录管理员的关键性操作。
+
+需要讨论的是,很多项目的业务日志模块采用注解方式,即加上方法注解,因此可以自动捕获
+用户的操作行为。虽然这样做很方便且不会影响业务代码,但是实际上最终是粗颗粒地记录,反而记录意义不大。
+
+因此本项目采用在方法内手写业务日志代码方式记录业务操作行为及结果。
+虽然比较繁琐,但是可以保证记录是细颗粒的。而且,如果管理员最终关心的操作较少,那么
+实际上需要写的代码不是很多。
+
+考虑到语义,操作业务应该是“谁做了什么操作,结果成功还是失败,失败原因是什么,补充信息是什么”,
+因此这里设计的业务日志表关键字段如下:
+* 管理员
+* IP地址
+* 操作分类
+* 操作动作
+* 操作状态
+* 操作结果
+* 补充信息
+
+#### 2.1.10.1 操作类别
+
+这里的日志类型设计成四种(当然开发者需要可以扩展)
+* 一般日志:用户觉得需要查看的一般操作日志,建议是默认的日志级别
+* 安全日志:用户安全相关的操作日志,例如登录、删除管理员
+* 订单日志:用户交易相关的操作日志,例如订单发货、退款
+* 其他日志:如果以上三种不合适,可以选择其他日志,建议是优先级最低的日志级别
+
+当然建议开发者应该和最终用户讨论交流,记录真正关键性的业务操作,例如登录相关或订单相关等。
+
+#### 2.1.10.2 操作结果
+
+如果操作成功,可以使用操作结果字段记录被操作的对象。
+当然,有些操作没有具体对象,那么可以省略。
+
+如果操作失败,也可以使用操作结果字段记录失败的原因。
+
+#### 2.1.10.3 操作失败
+
+虽然这里有操作状态字段和操作结果字段,可以记录操作失败的状态。
+但是通常失败操作不会对系统或者数据库带来影响,因此实际上开发者其实不需要
+记录太多操作失败的日志,而是记录操作成功的日志,告诉系统管理员当前状态的变化。
+
+当然,是否记录操作失败取决于开发者或者最终用户是否需要。
+例如,登录这里应该记录用户登录失败的日志,因为保存的IP地址可以帮助管理员了解
+系统被访问的情况。
+
+### 2.1.11 通用设计
 
 除了以上表,数据库还存在其他一些业务表,例如专题表litemall_topic,
 但是都很直观,不需要多讨论。
 
 以下是一些表设计中无具体业务意义可通用的字段。
 
-#### 2.1.10.1 deleted
+#### 2.1.11.1 deleted
 
 除极少数表,其他所有表都存在`deleted`字段,支持逻辑删除。
 因此目前删除数据时,不会直接删除数据,而是修改`deleted`字段。
 当然,数据库管理员可以连接到数据库直接删除数据,或者开发者
 可以修改这里的逻辑采用物理删除。
 
-#### 2.1.10.2 add_time
+#### 2.1.11.2 add_time
 
 除极少数表,其他所有表都存在`add_time`字段,记录数据创建时间。
 
-#### 2.1.10.3 update_time
+#### 2.1.11.3 update_time
 
 除极少数表,其他所有表都存在`update_time`字段,记录数据修改时间。
 

+ 4 - 0
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/AdminOrderService.java

@@ -49,6 +49,8 @@ public class AdminOrderService {
     private WxPayService wxPayService;
     @Autowired
     private NotifyService notifyService;
+    @Autowired
+    private LogHelper logHelper;
 
     public Object list(Integer userId, String orderSn, List<Short> orderStatusArray,
                        Integer page, Integer limit, String sort, String order) {
@@ -161,6 +163,7 @@ public class AdminOrderService {
         // 注意订单号只发后6位
         notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND, new String[]{order.getOrderSn().substring(8, 14)});
 
+        logHelper.logOrderSucceed("退款", "订单编号 " + orderId);
         return ResponseUtil.ok();
     }
 
@@ -205,6 +208,7 @@ public class AdminOrderService {
         // "您的订单已经发货,快递公司 {1},快递单 {2} ,请注意查收"
         notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[]{shipChannel, shipSn});
 
+        logHelper.logOrderSucceed("发货", "订单编号 " + orderId);
         return ResponseUtil.ok();
     }
 

+ 114 - 0
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/service/LogHelper.java

@@ -0,0 +1,114 @@
+package org.linlinjava.litemall.admin.service;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.subject.Subject;
+import org.linlinjava.litemall.core.util.IpUtil;
+import org.linlinjava.litemall.db.domain.LitemallAdmin;
+import org.linlinjava.litemall.db.domain.LitemallLog;
+import org.linlinjava.litemall.db.service.LitemallLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 这里的日志类型设计成四种(当然开发者需要可以自己扩展)
+ * 一般日志:用户觉得需要查看的一般操作日志,建议是默认的日志级别
+ * 安全日志:用户安全相关的操作日志,例如登录、删除管理员
+ * 订单日志:用户交易相关的操作日志,例如订单发货、退款
+ * 其他日志:如果以上三种不合适,可以选择其他日志,建议是优先级最低的日志级别
+ *
+ * 当然可能很多操作是不需要记录到数据库的,例如编辑商品、编辑广告品之类。
+ */
+@Component
+public class LogHelper {
+    public final static Integer LOG_TYPE_GENERAL = 0;
+    public final static Integer LOG_TYPE_AUTH = 1;
+    public final static Integer LOG_TYPE_ORDER = 2;
+    public final static Integer LOG_TYPE_OTHER = 3;
+
+    @Autowired
+    private LitemallLogService logService;
+
+    public void logGeneralSucceed(String action){
+        logAdmin(LOG_TYPE_GENERAL, action, true, "", "");
+    }
+
+    public void logGeneralSucceed(String action, String result){
+        logAdmin(LOG_TYPE_GENERAL, action, true, result, "");
+    }
+
+    public void logGeneralFail(String action, String error){
+        logAdmin(LOG_TYPE_GENERAL, action, false, error, "");
+    }
+
+    public void logAuthSucceed(String action){
+        logAdmin(LOG_TYPE_AUTH, action, true, "", "");
+    }
+
+    public void logAuthSucceed(String action, String result){
+        logAdmin(LOG_TYPE_AUTH, action, true, result, "");
+    }
+
+    public void logAuthFail(String action, String error){
+        logAdmin(LOG_TYPE_AUTH, action, false, error, "");
+    }
+
+    public void logOrderSucceed(String action){
+        logAdmin(LOG_TYPE_ORDER, action, true, "", "");
+    }
+
+    public void logOrderSucceed(String action, String result){
+        logAdmin(LOG_TYPE_ORDER, action, true, result, "");
+    }
+
+    public void logOrderFail(String action, String error){
+        logAdmin(LOG_TYPE_ORDER, action, false, error, "");
+    }
+
+    public void logOtherSucceed(String action){
+        logAdmin(LOG_TYPE_OTHER, action, true, "", "");
+    }
+
+    public void logOtherSucceed(String action, String result){
+        logAdmin(LOG_TYPE_OTHER, action, true, result, "");
+    }
+
+
+    public void logOtherFail(String action, String error){
+        logAdmin(LOG_TYPE_OTHER, action, false, error, "");
+    }
+
+    public void logAdmin (Integer type, String action, Boolean succeed, String result, String comment){
+        LitemallLog log = new LitemallLog();
+
+        Subject currentUser = SecurityUtils.getSubject();
+        if(currentUser != null) {
+            LitemallAdmin admin = (LitemallAdmin) currentUser.getPrincipal();
+            if(admin != null) {
+                log.setAdmin(admin.getUsername());
+            }
+            else{
+                log.setAdmin("匿名用户");
+            }
+        }
+        else{
+            log.setAdmin("匿名用户");
+        }
+
+        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+        if(request != null) {
+            log.setIp(IpUtil.getIpAddr(request));
+        }
+
+        log.setType(type);
+        log.setAction(action);
+        log.setStatus(succeed);
+        log.setResult(result);
+        log.setComment(comment);
+        logService.add(log);
+    }
+
+}

+ 6 - 0
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminAdminController.java

@@ -5,6 +5,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
+import org.linlinjava.litemall.admin.service.LogHelper;
 import org.linlinjava.litemall.core.util.RegexUtil;
 import org.linlinjava.litemall.core.util.ResponseUtil;
 import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
@@ -32,6 +33,8 @@ public class AdminAdminController {
 
     @Autowired
     private LitemallAdminService adminService;
+    @Autowired
+    private LogHelper logHelper;
 
     @RequiresPermissions("admin:admin:list")
     @RequiresPermissionsDesc(menu={"系统管理" , "管理员管理"}, button="查询")
@@ -85,6 +88,7 @@ public class AdminAdminController {
         String encodedPassword = encoder.encode(rawPassword);
         admin.setPassword(encodedPassword);
         adminService.add(admin);
+        logHelper.logAuthSucceed("添加管理员", username);
         return ResponseUtil.ok(admin);
     }
 
@@ -119,6 +123,7 @@ public class AdminAdminController {
             return ResponseUtil.updatedDataFailed();
         }
 
+        logHelper.logAuthSucceed("编辑管理员", admin.getUsername());
         return ResponseUtil.ok(admin);
     }
 
@@ -132,6 +137,7 @@ public class AdminAdminController {
         }
 
         adminService.deleteById(anotherAdminId);
+        logHelper.logAuthSucceed("删除管理员", admin.getUsername());
         return ResponseUtil.ok();
     }
 }

+ 12 - 0
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminAuthController.java

@@ -9,12 +9,15 @@ import org.apache.shiro.authc.UnknownAccountException;
 import org.apache.shiro.authc.UsernamePasswordToken;
 import org.apache.shiro.authz.annotation.RequiresAuthentication;
 import org.apache.shiro.subject.Subject;
+import org.linlinjava.litemall.admin.service.LogHelper;
 import org.linlinjava.litemall.admin.util.Permission;
 import org.linlinjava.litemall.admin.util.PermissionUtil;
 import org.linlinjava.litemall.core.util.JacksonUtil;
 import org.linlinjava.litemall.core.util.ResponseUtil;
 import org.linlinjava.litemall.db.domain.LitemallAdmin;
+import org.linlinjava.litemall.db.domain.LitemallLog;
 import org.linlinjava.litemall.db.service.LitemallAdminService;
+import org.linlinjava.litemall.db.service.LitemallLogService;
 import org.linlinjava.litemall.db.service.LitemallPermissionService;
 import org.linlinjava.litemall.db.service.LitemallRoleService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +42,8 @@ public class AdminAuthController {
     private LitemallRoleService roleService;
     @Autowired
     private LitemallPermissionService permissionService;
+    @Autowired
+    private LogHelper logHelper;
 
     /*
      *  { username : value, password : value }
@@ -56,13 +61,18 @@ public class AdminAuthController {
         try {
             currentUser.login(new UsernamePasswordToken(username, password));
         } catch (UnknownAccountException uae) {
+            logHelper.logAuthFail("登录", "用户帐号或密码不正确");
             return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "用户帐号或密码不正确");
         } catch (LockedAccountException lae) {
+            logHelper.logAuthFail("登录", "用户帐号已锁定不可用");
             return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "用户帐号已锁定不可用");
 
         } catch (AuthenticationException ae) {
+            logHelper.logAuthFail("登录", "认证失败");
             return ResponseUtil.fail(ADMIN_INVALID_ACCOUNT, "认证失败");
         }
+
+        logHelper.logAuthSucceed("登录");
         return ResponseUtil.ok(currentUser.getSession().getId());
     }
 
@@ -73,6 +83,8 @@ public class AdminAuthController {
     @PostMapping("/logout")
     public Object login() {
         Subject currentUser = SecurityUtils.getSubject();
+
+        logHelper.logAuthSucceed("退出");
         currentUser.logout();
         return ResponseUtil.ok();
     }

+ 47 - 0
litemall-admin-api/src/main/java/org/linlinjava/litemall/admin/web/AdminLogController.java

@@ -0,0 +1,47 @@
+package org.linlinjava.litemall.admin.web;
+
+import com.github.pagehelper.PageInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.linlinjava.litemall.admin.annotation.RequiresPermissionsDesc;
+import org.linlinjava.litemall.core.util.ResponseUtil;
+import org.linlinjava.litemall.core.validator.Order;
+import org.linlinjava.litemall.core.validator.Sort;
+import org.linlinjava.litemall.db.domain.LitemallLog;
+import org.linlinjava.litemall.db.service.LitemallLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.constraints.NotNull;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/admin/log")
+@Validated
+public class AdminLogController {
+    private final Log logger = LogFactory.getLog(AdminLogController.class);
+
+    @Autowired
+    private LitemallLogService logService;
+
+    @RequiresPermissions("admin:log:list")
+    @RequiresPermissionsDesc(menu={"系统管理" , "操作日志"}, button="查询")
+    @GetMapping("/list")
+    public Object list(String name,
+                       @RequestParam(defaultValue = "1") Integer page,
+                       @RequestParam(defaultValue = "10") Integer limit,
+                       @Sort @RequestParam(defaultValue = "add_time") String sort,
+                       @Order @RequestParam(defaultValue = "desc") String order) {
+        List<LitemallLog> logList = logService.querySelective(name, page, limit, sort, order);
+        long total = PageInfo.of(logList).getTotal();
+        Map<String, Object> data = new HashMap<>();
+        data.put("total", total);
+        data.put("items", logList);
+
+        return ResponseUtil.ok(data);
+    }
+}

+ 9 - 0
litemall-admin/src/api/log.js

@@ -0,0 +1,9 @@
+import request from '@/utils/request'
+
+export function listLog(query) {
+  return request({
+    url: '/log/list',
+    method: 'get',
+    params: query
+  })
+}

+ 10 - 0
litemall-admin/src/router/index.js

@@ -376,6 +376,16 @@ export const asyncRouterMap = [
         }
       },
       {
+        path: 'log',
+        component: () => import('@/views/sys/log'),
+        name: 'log',
+        meta: {
+          perms: ['GET /admin/admin/log'],
+          title: '操作日志',
+          noCache: true
+        }
+      },
+      {
         path: 'role',
         component: () => import('@/views/sys/role'),
         name: 'role',

+ 98 - 0
litemall-admin/src/views/sys/log.vue

@@ -0,0 +1,98 @@
+<template>
+  <div class="app-container">
+
+    <!-- 查询和其他操作 -->
+    <div class="filter-container">
+      <el-input v-model="listQuery.name" clearable class="filter-item" style="width: 200px;" placeholder="请输入操作管理员"/>
+      <el-button v-permission="['GET /admin/log/list']" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">查找</el-button>
+    </div>
+
+    <!-- 查询结果 -->
+    <el-table v-loading="listLoading" :data="list" element-loading-text="正在查询中。。。" border fit highlight-current-row>
+      <el-table-column align="center" label="操作管理员" prop="admin"/>
+      <el-table-column align="center" label="IP地址" prop="ip"/>
+      <el-table-column align="center" label="操作时间" prop="addTime"/>
+      <el-table-column align="center" label="操作类别" prop="type">
+        <template slot-scope="scope">
+          <el-tag>{{ scope.row.type | typeFilter }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="操作动作" prop="action"/>
+      <el-table-column align="center" label="操作状态" prop="status">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status ? 'success' : 'error' ">{{ scope.row.status ? '成功' : '失败' }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" label="操作结果" prop="result"/>
+      <el-table-column align="center" label="备注信息" prop="comment"/>
+
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
+
+  </div>
+</template>
+
+<script>
+import { listLog } from '@/api/log'
+import Pagination from '@/components/Pagination'
+
+const typeMap = {
+  0: '一般操作',
+  1: '安全操作',
+  2: '订单操作',
+  3: '其他操作'
+}
+
+export default {
+  name: 'Log',
+  components: { Pagination },
+  filters: {
+    typeFilter(type) {
+      return typeMap[type]
+    }
+  },
+  data() {
+    return {
+      list: null,
+      total: 0,
+      listLoading: true,
+      listQuery: {
+        page: 1,
+        limit: 20,
+        name: undefined,
+        sort: 'add_time',
+        order: 'desc'
+      },
+      rules: {
+        name: [
+          { required: true, message: '角色名称不能为空', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.listLoading = true
+      listLog(this.listQuery)
+        .then(response => {
+          this.list = response.data.data.items
+          this.total = response.data.data.total
+          this.listLoading = false
+        })
+        .catch(() => {
+          this.list = []
+          this.total = 0
+          this.listLoading = false
+        })
+    },
+    handleFilter() {
+      this.listQuery.page = 1
+      this.getList()
+    }
+  }
+}
+</script>

+ 1 - 8
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/util/IpUtil.java

@@ -1,4 +1,4 @@
-package org.linlinjava.litemall.wx.util;
+package org.linlinjava.litemall.core.util;
 
 import javax.servlet.http.HttpServletRequest;
 import java.net.InetAddress;
@@ -8,13 +8,6 @@ import java.net.UnknownHostException;
  * IP地址相关工具类
  */
 public class IpUtil {
-    public static String client(HttpServletRequest request) {
-        String xff = request.getHeader("x-forwarded-for");
-        if (xff == null) {
-            xff = request.getRemoteAddr();
-        }
-        return xff;
-    }
 
     public static String getIpAddr(HttpServletRequest request) {
         String ipAddress = null;

+ 3 - 0
litemall-db/mybatis-generator/generatorConfig.xml

@@ -174,5 +174,8 @@
         <table tableName="litemall_permission">
             <generatedKey column="id" sqlStatement="MySql" identity="true"/>
         </table>
+        <table tableName="litemall_log">
+            <generatedKey column="id" sqlStatement="MySql" identity="true"/>
+        </table>
     </context>
 </generatorConfiguration>

+ 159 - 0
litemall-db/src/main/java/org/linlinjava/litemall/db/dao/LitemallLogMapper.java

@@ -0,0 +1,159 @@
+package org.linlinjava.litemall.db.dao;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import org.linlinjava.litemall.db.domain.LitemallLog;
+import org.linlinjava.litemall.db.domain.LitemallLogExample;
+
+public interface LitemallLogMapper {
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    long countByExample(LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int deleteByExample(LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int deleteByPrimaryKey(Integer id);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int insert(LitemallLog record);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int insertSelective(LitemallLog record);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    LitemallLog selectOneByExample(LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    LitemallLog selectOneByExampleSelective(@Param("example") LitemallLogExample example, @Param("selective") LitemallLog.Column ... selective);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    List<LitemallLog> selectByExampleSelective(@Param("example") LitemallLogExample example, @Param("selective") LitemallLog.Column ... selective);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    List<LitemallLog> selectByExample(LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    LitemallLog selectByPrimaryKeySelective(@Param("id") Integer id, @Param("selective") LitemallLog.Column ... selective);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    LitemallLog selectByPrimaryKey(Integer id);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    LitemallLog selectByPrimaryKeyWithLogicalDelete(@Param("id") Integer id, @Param("andLogicalDeleted") boolean andLogicalDeleted);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int updateByExampleSelective(@Param("record") LitemallLog record, @Param("example") LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int updateByExample(@Param("record") LitemallLog record, @Param("example") LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int updateByPrimaryKeySelective(LitemallLog record);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    int updateByPrimaryKey(LitemallLog record);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    int logicalDeleteByExample(@Param("example") LitemallLogExample example);
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    int logicalDeleteByPrimaryKey(Integer id);
+}

+ 666 - 0
litemall-db/src/main/java/org/linlinjava/litemall/db/domain/LitemallLog.java

@@ -0,0 +1,666 @@
+package org.linlinjava.litemall.db.domain;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class LitemallLog {
+    /**
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    public static final Boolean NOT_DELETED = false;
+
+    /**
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    public static final Boolean IS_DELETED = true;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.id
+     *
+     * @mbg.generated
+     */
+    private Integer id;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.admin
+     *
+     * @mbg.generated
+     */
+    private String admin;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.ip
+     *
+     * @mbg.generated
+     */
+    private String ip;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.type
+     *
+     * @mbg.generated
+     */
+    private Integer type;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.action
+     *
+     * @mbg.generated
+     */
+    private String action;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.status
+     *
+     * @mbg.generated
+     */
+    private Boolean status;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.result
+     *
+     * @mbg.generated
+     */
+    private String result;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.comment
+     *
+     * @mbg.generated
+     */
+    private String comment;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.add_time
+     *
+     * @mbg.generated
+     */
+    private LocalDateTime addTime;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.update_time
+     *
+     * @mbg.generated
+     */
+    private LocalDateTime updateTime;
+
+    /**
+     *
+     * This field was generated by MyBatis Generator.
+     * This field corresponds to the database column litemall_log.deleted
+     *
+     * @mbg.generated
+     */
+    private Boolean deleted;
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.id
+     *
+     * @return the value of litemall_log.id
+     *
+     * @mbg.generated
+     */
+    public Integer getId() {
+        return id;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.id
+     *
+     * @param id the value for litemall_log.id
+     *
+     * @mbg.generated
+     */
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.admin
+     *
+     * @return the value of litemall_log.admin
+     *
+     * @mbg.generated
+     */
+    public String getAdmin() {
+        return admin;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.admin
+     *
+     * @param admin the value for litemall_log.admin
+     *
+     * @mbg.generated
+     */
+    public void setAdmin(String admin) {
+        this.admin = admin;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.ip
+     *
+     * @return the value of litemall_log.ip
+     *
+     * @mbg.generated
+     */
+    public String getIp() {
+        return ip;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.ip
+     *
+     * @param ip the value for litemall_log.ip
+     *
+     * @mbg.generated
+     */
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.type
+     *
+     * @return the value of litemall_log.type
+     *
+     * @mbg.generated
+     */
+    public Integer getType() {
+        return type;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.type
+     *
+     * @param type the value for litemall_log.type
+     *
+     * @mbg.generated
+     */
+    public void setType(Integer type) {
+        this.type = type;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.action
+     *
+     * @return the value of litemall_log.action
+     *
+     * @mbg.generated
+     */
+    public String getAction() {
+        return action;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.action
+     *
+     * @param action the value for litemall_log.action
+     *
+     * @mbg.generated
+     */
+    public void setAction(String action) {
+        this.action = action;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.status
+     *
+     * @return the value of litemall_log.status
+     *
+     * @mbg.generated
+     */
+    public Boolean getStatus() {
+        return status;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.status
+     *
+     * @param status the value for litemall_log.status
+     *
+     * @mbg.generated
+     */
+    public void setStatus(Boolean status) {
+        this.status = status;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.result
+     *
+     * @return the value of litemall_log.result
+     *
+     * @mbg.generated
+     */
+    public String getResult() {
+        return result;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.result
+     *
+     * @param result the value for litemall_log.result
+     *
+     * @mbg.generated
+     */
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.comment
+     *
+     * @return the value of litemall_log.comment
+     *
+     * @mbg.generated
+     */
+    public String getComment() {
+        return comment;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.comment
+     *
+     * @param comment the value for litemall_log.comment
+     *
+     * @mbg.generated
+     */
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.add_time
+     *
+     * @return the value of litemall_log.add_time
+     *
+     * @mbg.generated
+     */
+    public LocalDateTime getAddTime() {
+        return addTime;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.add_time
+     *
+     * @param addTime the value for litemall_log.add_time
+     *
+     * @mbg.generated
+     */
+    public void setAddTime(LocalDateTime addTime) {
+        this.addTime = addTime;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.update_time
+     *
+     * @return the value of litemall_log.update_time
+     *
+     * @mbg.generated
+     */
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.update_time
+     *
+     * @param updateTime the value for litemall_log.update_time
+     *
+     * @mbg.generated
+     */
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method returns the value of the database column litemall_log.deleted
+     *
+     * @return the value of litemall_log.deleted
+     *
+     * @mbg.generated
+     */
+    public Boolean getDeleted() {
+        return deleted;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method sets the value of the database column litemall_log.deleted
+     *
+     * @param deleted the value for litemall_log.deleted
+     *
+     * @mbg.generated
+     */
+    public void setDeleted(Boolean deleted) {
+        this.deleted = deleted;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(getClass().getSimpleName());
+        sb.append(" [");
+        sb.append("Hash = ").append(hashCode());
+        sb.append(", id=").append(id);
+        sb.append(", admin=").append(admin);
+        sb.append(", ip=").append(ip);
+        sb.append(", type=").append(type);
+        sb.append(", action=").append(action);
+        sb.append(", status=").append(status);
+        sb.append(", result=").append(result);
+        sb.append(", comment=").append(comment);
+        sb.append(", addTime=").append(addTime);
+        sb.append(", updateTime=").append(updateTime);
+        sb.append(", deleted=").append(deleted);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    @Override
+    public boolean equals(Object that) {
+        if (this == that) {
+            return true;
+        }
+        if (that == null) {
+            return false;
+        }
+        if (getClass() != that.getClass()) {
+            return false;
+        }
+        LitemallLog other = (LitemallLog) that;
+        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
+            && (this.getAdmin() == null ? other.getAdmin() == null : this.getAdmin().equals(other.getAdmin()))
+            && (this.getIp() == null ? other.getIp() == null : this.getIp().equals(other.getIp()))
+            && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType()))
+            && (this.getAction() == null ? other.getAction() == null : this.getAction().equals(other.getAction()))
+            && (this.getStatus() == null ? other.getStatus() == null : this.getStatus().equals(other.getStatus()))
+            && (this.getResult() == null ? other.getResult() == null : this.getResult().equals(other.getResult()))
+            && (this.getComment() == null ? other.getComment() == null : this.getComment().equals(other.getComment()))
+            && (this.getAddTime() == null ? other.getAddTime() == null : this.getAddTime().equals(other.getAddTime()))
+            && (this.getUpdateTime() == null ? other.getUpdateTime() == null : this.getUpdateTime().equals(other.getUpdateTime()))
+            && (this.getDeleted() == null ? other.getDeleted() == null : this.getDeleted().equals(other.getDeleted()));
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
+        result = prime * result + ((getAdmin() == null) ? 0 : getAdmin().hashCode());
+        result = prime * result + ((getIp() == null) ? 0 : getIp().hashCode());
+        result = prime * result + ((getType() == null) ? 0 : getType().hashCode());
+        result = prime * result + ((getAction() == null) ? 0 : getAction().hashCode());
+        result = prime * result + ((getStatus() == null) ? 0 : getStatus().hashCode());
+        result = prime * result + ((getResult() == null) ? 0 : getResult().hashCode());
+        result = prime * result + ((getComment() == null) ? 0 : getComment().hashCode());
+        result = prime * result + ((getAddTime() == null) ? 0 : getAddTime().hashCode());
+        result = prime * result + ((getUpdateTime() == null) ? 0 : getUpdateTime().hashCode());
+        result = prime * result + ((getDeleted() == null) ? 0 : getDeleted().hashCode());
+        return result;
+    }
+
+    /**
+     * This method was generated by MyBatis Generator.
+     * This method corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    public void andLogicalDeleted(boolean deleted) {
+        setDeleted(deleted ? IS_DELETED : NOT_DELETED);
+    }
+
+    /**
+     * This enum was generated by MyBatis Generator.
+     * This enum corresponds to the database table litemall_log
+     *
+     * @mbg.generated
+     * @project https://github.com/itfsw/mybatis-generator-plugin
+     */
+    public enum Column {
+        id("id", "id", "INTEGER", false),
+        admin("admin", "admin", "VARCHAR", true),
+        ip("ip", "ip", "VARCHAR", false),
+        type("type", "type", "INTEGER", true),
+        action("action", "action", "VARCHAR", true),
+        status("status", "status", "BIT", true),
+        result("result", "result", "VARCHAR", true),
+        comment("comment", "comment", "VARCHAR", true),
+        addTime("add_time", "addTime", "TIMESTAMP", false),
+        updateTime("update_time", "updateTime", "TIMESTAMP", false),
+        deleted("deleted", "deleted", "BIT", false);
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private static final String BEGINNING_DELIMITER = "`";
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private static final String ENDING_DELIMITER = "`";
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private final String column;
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private final boolean isColumnNameDelimited;
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private final String javaProperty;
+
+        /**
+         * This field was generated by MyBatis Generator.
+         * This field corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        private final String jdbcType;
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String value() {
+            return this.column;
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String getValue() {
+            return this.column;
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String getJavaProperty() {
+            return this.javaProperty;
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String getJdbcType() {
+            return this.jdbcType;
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) {
+            this.column = column;
+            this.javaProperty = javaProperty;
+            this.jdbcType = jdbcType;
+            this.isColumnNameDelimited = isColumnNameDelimited;
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String desc() {
+            return this.getEscapedColumnName() + " DESC";
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String asc() {
+            return this.getEscapedColumnName() + " ASC";
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public static Column[] excludes(Column ... excludes) {
+            ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
+            if (excludes != null && excludes.length > 0) {
+                columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));
+            }
+            return columns.toArray(new Column[]{});
+        }
+
+        /**
+         * This method was generated by MyBatis Generator.
+         * This method corresponds to the database table litemall_log
+         *
+         * @mbg.generated
+         * @project https://github.com/itfsw/mybatis-generator-plugin
+         */
+        public String getEscapedColumnName() {
+            if (this.isColumnNameDelimited) {
+                return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString();
+            } else {
+                return this.column;
+            }
+        }
+    }
+}

File diff suppressed because it is too large
+ 1918 - 0
litemall-db/src/main/java/org/linlinjava/litemall/db/domain/LitemallLogExample.java


+ 46 - 0
litemall-db/src/main/java/org/linlinjava/litemall/db/service/LitemallLogService.java

@@ -0,0 +1,46 @@
+package org.linlinjava.litemall.db.service;
+
+import com.github.pagehelper.PageHelper;
+import org.linlinjava.litemall.db.dao.LitemallLogMapper;
+import org.linlinjava.litemall.db.domain.LitemallAd;
+import org.linlinjava.litemall.db.domain.LitemallLog;
+import org.linlinjava.litemall.db.domain.LitemallLogExample;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Service
+public class LitemallLogService {
+    @Resource
+    private LitemallLogMapper logMapper;
+
+    public void deleteById(Integer id) {
+        logMapper.logicalDeleteByPrimaryKey(id);
+    }
+
+    public void add(LitemallLog log) {
+        log.setAddTime(LocalDateTime.now());
+        log.setUpdateTime(LocalDateTime.now());
+        logMapper.insertSelective(log);
+    }
+
+    public List<LitemallLog> querySelective(String name, Integer page, Integer size, String sort, String order) {
+        LitemallLogExample example = new LitemallLogExample();
+        LitemallLogExample.Criteria criteria = example.createCriteria();
+
+        if (!StringUtils.isEmpty(name)) {
+            criteria.andAdminLike("%" + name + "%");
+        }
+        criteria.andDeletedEqualTo(false);
+
+        if (!StringUtils.isEmpty(sort) && !StringUtils.isEmpty(order)) {
+            example.setOrderByClause(sort + " " + order);
+        }
+
+        PageHelper.startPage(page, size);
+        return logMapper.selectByExample(example);
+    }
+}

+ 504 - 0
litemall-db/src/main/resources/org/linlinjava/litemall/db/dao/LitemallLogMapper.xml

@@ -0,0 +1,504 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.linlinjava.litemall.db.dao.LitemallLogMapper">
+  <resultMap id="BaseResultMap" type="org.linlinjava.litemall.db.domain.LitemallLog">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    <id column="id" jdbcType="INTEGER" property="id" />
+    <result column="admin" jdbcType="VARCHAR" property="admin" />
+    <result column="ip" jdbcType="VARCHAR" property="ip" />
+    <result column="type" jdbcType="INTEGER" property="type" />
+    <result column="action" jdbcType="VARCHAR" property="action" />
+    <result column="status" jdbcType="BIT" property="status" />
+    <result column="result" jdbcType="VARCHAR" property="result" />
+    <result column="comment" jdbcType="VARCHAR" property="comment" />
+    <result column="add_time" jdbcType="TIMESTAMP" property="addTime" />
+    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
+    <result column="deleted" jdbcType="BIT" property="deleted" />
+  </resultMap>
+  <sql id="Example_Where_Clause">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    <where>
+      <foreach collection="oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Update_By_Example_Where_Clause">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    <where>
+      <foreach collection="example.oredCriteria" item="criteria" separator="or">
+        <if test="criteria.valid">
+          <trim prefix="(" prefixOverrides="and" suffix=")">
+            <foreach collection="criteria.criteria" item="criterion">
+              <choose>
+                <when test="criterion.noValue">
+                  and ${criterion.condition}
+                </when>
+                <when test="criterion.singleValue">
+                  and ${criterion.condition} #{criterion.value}
+                </when>
+                <when test="criterion.betweenValue">
+                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
+                </when>
+                <when test="criterion.listValue">
+                  and ${criterion.condition}
+                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
+                    #{listItem}
+                  </foreach>
+                </when>
+              </choose>
+            </foreach>
+          </trim>
+        </if>
+      </foreach>
+    </where>
+  </sql>
+  <sql id="Base_Column_List">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    id, `admin`, ip, `type`, `action`, `status`, `result`, `comment`, add_time, update_time, 
+    deleted
+  </sql>
+  <select id="selectByExample" parameterType="org.linlinjava.litemall.db.domain.LitemallLogExample" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    select
+    <if test="distinct">
+      distinct
+    </if>
+    <include refid="Base_Column_List" />
+    from litemall_log
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+  </select>
+  <select id="selectByExampleSelective" parameterType="map" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    select
+    <if test="example.distinct">
+      distinct
+    </if>
+    <choose>
+      <when test="selective != null and selective.length &gt; 0">
+        <foreach collection="selective" item="column" separator=",">
+          ${column.escapedColumnName}
+        </foreach>
+      </when>
+      <otherwise>
+        id, `admin`, ip, `type`, `action`, `status`, `result`, `comment`, add_time, update_time, 
+          deleted
+      </otherwise>
+    </choose>
+    from litemall_log
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+    <if test="example.orderByClause != null">
+      order by ${example.orderByClause}
+    </if>
+  </select>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    select 
+    <include refid="Base_Column_List" />
+    from litemall_log
+    where id = #{id,jdbcType=INTEGER}
+  </select>
+  <select id="selectByPrimaryKeyWithLogicalDelete" parameterType="map" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    select 
+    <include refid="Base_Column_List" />
+    from litemall_log
+    where id = #{id,jdbcType=INTEGER}
+      and deleted = 
+    <choose>
+      <when test="andLogicalDeleted">
+        1
+      </when>
+      <otherwise>
+        0
+      </otherwise>
+    </choose>
+  </select>
+  <select id="selectByPrimaryKeySelective" parameterType="map" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    select
+    <choose>
+      <when test="selective != null and selective.length &gt; 0">
+        <foreach collection="selective" item="column" separator=",">
+          ${column.escapedColumnName}
+        </foreach>
+      </when>
+      <otherwise>
+        id, `admin`, ip, `type`, `action`, `status`, `result`, `comment`, add_time, update_time, 
+          deleted
+      </otherwise>
+    </choose>
+    from litemall_log
+    where id = #{id,jdbcType=INTEGER}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    delete from litemall_log
+    where id = #{id,jdbcType=INTEGER}
+  </delete>
+  <delete id="deleteByExample" parameterType="org.linlinjava.litemall.db.domain.LitemallLogExample">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    delete from litemall_log
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </delete>
+  <insert id="insert" parameterType="org.linlinjava.litemall.db.domain.LitemallLog">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into litemall_log (`admin`, ip, `type`, 
+      `action`, `status`, `result`, 
+      `comment`, add_time, update_time, 
+      deleted)
+    values (#{admin,jdbcType=VARCHAR}, #{ip,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, 
+      #{action,jdbcType=VARCHAR}, #{status,jdbcType=BIT}, #{result,jdbcType=VARCHAR}, 
+      #{comment,jdbcType=VARCHAR}, #{addTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP}, 
+      #{deleted,jdbcType=BIT})
+  </insert>
+  <insert id="insertSelective" parameterType="org.linlinjava.litemall.db.domain.LitemallLog">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
+      SELECT LAST_INSERT_ID()
+    </selectKey>
+    insert into litemall_log
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="admin != null">
+        `admin`,
+      </if>
+      <if test="ip != null">
+        ip,
+      </if>
+      <if test="type != null">
+        `type`,
+      </if>
+      <if test="action != null">
+        `action`,
+      </if>
+      <if test="status != null">
+        `status`,
+      </if>
+      <if test="result != null">
+        `result`,
+      </if>
+      <if test="comment != null">
+        `comment`,
+      </if>
+      <if test="addTime != null">
+        add_time,
+      </if>
+      <if test="updateTime != null">
+        update_time,
+      </if>
+      <if test="deleted != null">
+        deleted,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="admin != null">
+        #{admin,jdbcType=VARCHAR},
+      </if>
+      <if test="ip != null">
+        #{ip,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        #{type,jdbcType=INTEGER},
+      </if>
+      <if test="action != null">
+        #{action,jdbcType=VARCHAR},
+      </if>
+      <if test="status != null">
+        #{status,jdbcType=BIT},
+      </if>
+      <if test="result != null">
+        #{result,jdbcType=VARCHAR},
+      </if>
+      <if test="comment != null">
+        #{comment,jdbcType=VARCHAR},
+      </if>
+      <if test="addTime != null">
+        #{addTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="updateTime != null">
+        #{updateTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="deleted != null">
+        #{deleted,jdbcType=BIT},
+      </if>
+    </trim>
+  </insert>
+  <select id="countByExample" parameterType="org.linlinjava.litemall.db.domain.LitemallLogExample" resultType="java.lang.Long">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    select count(*) from litemall_log
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+  </select>
+  <update id="updateByExampleSelective" parameterType="map">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    update litemall_log
+    <set>
+      <if test="record.id != null">
+        id = #{record.id,jdbcType=INTEGER},
+      </if>
+      <if test="record.admin != null">
+        `admin` = #{record.admin,jdbcType=VARCHAR},
+      </if>
+      <if test="record.ip != null">
+        ip = #{record.ip,jdbcType=VARCHAR},
+      </if>
+      <if test="record.type != null">
+        `type` = #{record.type,jdbcType=INTEGER},
+      </if>
+      <if test="record.action != null">
+        `action` = #{record.action,jdbcType=VARCHAR},
+      </if>
+      <if test="record.status != null">
+        `status` = #{record.status,jdbcType=BIT},
+      </if>
+      <if test="record.result != null">
+        `result` = #{record.result,jdbcType=VARCHAR},
+      </if>
+      <if test="record.comment != null">
+        `comment` = #{record.comment,jdbcType=VARCHAR},
+      </if>
+      <if test="record.addTime != null">
+        add_time = #{record.addTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="record.updateTime != null">
+        update_time = #{record.updateTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="record.deleted != null">
+        deleted = #{record.deleted,jdbcType=BIT},
+      </if>
+    </set>
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByExample" parameterType="map">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    update litemall_log
+    set id = #{record.id,jdbcType=INTEGER},
+      `admin` = #{record.admin,jdbcType=VARCHAR},
+      ip = #{record.ip,jdbcType=VARCHAR},
+      `type` = #{record.type,jdbcType=INTEGER},
+      `action` = #{record.action,jdbcType=VARCHAR},
+      `status` = #{record.status,jdbcType=BIT},
+      `result` = #{record.result,jdbcType=VARCHAR},
+      `comment` = #{record.comment,jdbcType=VARCHAR},
+      add_time = #{record.addTime,jdbcType=TIMESTAMP},
+      update_time = #{record.updateTime,jdbcType=TIMESTAMP},
+      deleted = #{record.deleted,jdbcType=BIT}
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="updateByPrimaryKeySelective" parameterType="org.linlinjava.litemall.db.domain.LitemallLog">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    update litemall_log
+    <set>
+      <if test="admin != null">
+        `admin` = #{admin,jdbcType=VARCHAR},
+      </if>
+      <if test="ip != null">
+        ip = #{ip,jdbcType=VARCHAR},
+      </if>
+      <if test="type != null">
+        `type` = #{type,jdbcType=INTEGER},
+      </if>
+      <if test="action != null">
+        `action` = #{action,jdbcType=VARCHAR},
+      </if>
+      <if test="status != null">
+        `status` = #{status,jdbcType=BIT},
+      </if>
+      <if test="result != null">
+        `result` = #{result,jdbcType=VARCHAR},
+      </if>
+      <if test="comment != null">
+        `comment` = #{comment,jdbcType=VARCHAR},
+      </if>
+      <if test="addTime != null">
+        add_time = #{addTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="updateTime != null">
+        update_time = #{updateTime,jdbcType=TIMESTAMP},
+      </if>
+      <if test="deleted != null">
+        deleted = #{deleted,jdbcType=BIT},
+      </if>
+    </set>
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="org.linlinjava.litemall.db.domain.LitemallLog">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+    -->
+    update litemall_log
+    set `admin` = #{admin,jdbcType=VARCHAR},
+      ip = #{ip,jdbcType=VARCHAR},
+      `type` = #{type,jdbcType=INTEGER},
+      `action` = #{action,jdbcType=VARCHAR},
+      `status` = #{status,jdbcType=BIT},
+      `result` = #{result,jdbcType=VARCHAR},
+      `comment` = #{comment,jdbcType=VARCHAR},
+      add_time = #{addTime,jdbcType=TIMESTAMP},
+      update_time = #{updateTime,jdbcType=TIMESTAMP},
+      deleted = #{deleted,jdbcType=BIT}
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+  <select id="selectOneByExample" parameterType="org.linlinjava.litemall.db.domain.LitemallLogExample" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    select
+    <include refid="Base_Column_List" />
+    from litemall_log
+    <if test="_parameter != null">
+      <include refid="Example_Where_Clause" />
+    </if>
+    <if test="orderByClause != null">
+      order by ${orderByClause}
+    </if>
+    limit 1
+  </select>
+  <select id="selectOneByExampleSelective" parameterType="map" resultMap="BaseResultMap">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    select
+    <choose>
+      <when test="selective != null and selective.length &gt; 0">
+        <foreach collection="selective" item="column" separator=",">
+          ${column.escapedColumnName}
+        </foreach>
+      </when>
+      <otherwise>
+        id, `admin`, ip, `type`, `action`, `status`, `result`, `comment`, add_time, update_time, 
+          deleted
+      </otherwise>
+    </choose>
+    from litemall_log
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+    <if test="example.orderByClause != null">
+      order by ${example.orderByClause}
+    </if>
+    limit 1
+  </select>
+  <update id="logicalDeleteByExample" parameterType="map">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    update litemall_log set deleted = 1
+    <if test="_parameter != null">
+      <include refid="Update_By_Example_Where_Clause" />
+    </if>
+  </update>
+  <update id="logicalDeleteByPrimaryKey" parameterType="java.lang.Integer">
+    <!--
+      WARNING - @mbg.generated
+      This element is automatically generated by MyBatis Generator, do not modify.
+      @project https://github.com/itfsw/mybatis-generator-plugin
+    -->
+    update litemall_log set deleted = 1
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+</mapper>

+ 1 - 1
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/service/WxOrderService.java

@@ -25,7 +25,7 @@ import org.linlinjava.litemall.db.service.*;
 import org.linlinjava.litemall.db.util.CouponUserConstant;
 import org.linlinjava.litemall.db.util.OrderHandleOption;
 import org.linlinjava.litemall.db.util.OrderUtil;
-import org.linlinjava.litemall.wx.util.IpUtil;
+import org.linlinjava.litemall.core.util.IpUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;

+ 4 - 4
litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/web/WxAuthController.java

@@ -21,7 +21,7 @@ import org.linlinjava.litemall.wx.dao.UserToken;
 import org.linlinjava.litemall.wx.dao.WxLoginInfo;
 import org.linlinjava.litemall.wx.service.CaptchaCodeManager;
 import org.linlinjava.litemall.wx.service.UserTokenManager;
-import org.linlinjava.litemall.wx.util.IpUtil;
+import org.linlinjava.litemall.core.util.IpUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.util.StringUtils;
 import org.springframework.validation.annotation.Validated;
@@ -145,7 +145,7 @@ public class WxAuthController {
             user.setUserLevel((byte) 0);
             user.setStatus((byte) 0);
             user.setLastLoginTime(LocalDateTime.now());
-            user.setLastLoginIp(IpUtil.client(request));
+            user.setLastLoginIp(IpUtil.getIpAddr(request));
 
             userService.add(user);
 
@@ -153,7 +153,7 @@ public class WxAuthController {
             couponAssignService.assignForRegister(user.getId());
         } else {
             user.setLastLoginTime(LocalDateTime.now());
-            user.setLastLoginIp(IpUtil.client(request));
+            user.setLastLoginIp(IpUtil.getIpAddr(request));
             if (userService.updateById(user) == 0) {
                 return ResponseUtil.updatedDataFailed();
             }
@@ -293,7 +293,7 @@ public class WxAuthController {
         user.setUserLevel((byte) 0);
         user.setStatus((byte) 0);
         user.setLastLoginTime(LocalDateTime.now());
-        user.setLastLoginIp(IpUtil.client(request));
+        user.setLastLoginIp(IpUtil.getIpAddr(request));
         userService.add(user);
 
         // 给新用户发送注册优惠券