plan.md 29 KB

订单操作日志 Implementation Plan (COMPLETED)

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: 新建 pos_order_log 表,在所有订单状态变更处自动记录日志,并在平台管理端提供查询/导出页面。

Architecture: 跟随 SysOperLog 的模式——Entity + Mapper(XML) + Service + Controller。日志写入封装为一个工具类 OrderLogHelper,供各 Controller 和定时任务调用。前端新增独立的日志查询页面挂到"订单管理"菜单下。

Tech Stack: Java (Spring Boot, MyBatis XML), Vue.js (Element UI), MySQL


File Structure

操作 文件 职责
Create ruoyi-system/.../domain/PosOrderLog.java 实体类
Create ruoyi-system/.../mapper/PosOrderLogMapper.java Mapper 接口
Create ruoyi-system/.../mapper/PosOrderLogMapper.xml (resources/mapper/system/) XML mapper
Create ruoyi-system/.../service/IPosOrderLogService.java Service 接口
Create ruoyi-system/.../service/impl/PosOrderLogServiceImpl.java Service 实现
Create ruoyi-admin/.../controller/system/PosOrderLogController.java 后台管理接口
Create ruoyi-system/.../utils/OrderLogHelper.java 日志写入工具类
Modify ruoyi-admin/.../app/order/PosOrderShOprateController.java 商家操作插入日志
Modify ruoyi-admin/.../app/order/PosOrderQsOprateController.java 骑手操作插入日志
Modify ruoyi-admin/.../app/order/UserOrderController.java 用户操作插入日志
Modify ruoyi-admin/.../app/order/PosOrderController.java 平台操作插入日志
Modify ruoyi-admin/.../app/order/TestTask.java 系统定时任务插入日志
Modify ruoyi-admin/.../app/pay/PayController.java 支付回调插入日志
Create foodie-admin-vue/src/api/system/orderLog.js 前端 API
Create foodie-admin-vue/src/views/system/order/log.vue 前端页面

Task 1: 创建 PosOrderLog 实体类

Files:

  • Create: ruoyi-system/src/main/java/com/ruoyi/system/domain/PosOrderLog.java

  • [ ] Step 1: 创建实体类

    package com.ruoyi.system.domain;
    
    import java.util.Date;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import com.ruoyi.common.annotation.Excel;
    import com.ruoyi.common.annotation.Excel.ColumnType;
    import com.ruoyi.common.core.domain.BaseEntity;
    
    /**
    * 订单操作日志表 pos_order_log
    */
    public class PosOrderLog extends BaseEntity
    {
    private static final long serialVersionUID = 1L;
    
    /** 主键 */
    @Excel(name = "主键ID", cellType = ColumnType.NUMERIC)
    private Long id;
    
    /** 订单号 */
    @Excel(name = "订单号")
    private String ddId;
    
    /** 操作人类型:0系统,1平台管理员,2商家,3骑手,4用户 */
    @Excel(name = "操作人类型", readConverterExp = "0=系统,1=平台管理员,2=商家,3=骑手,4=用户")
    private Integer operatorType;
    
    /** 操作人ID */
    @Excel(name = "操作人ID", cellType = ColumnType.NUMERIC)
    private Long operatorId;
    
    /** 操作人名称 */
    @Excel(name = "操作人名称")
    private String operatorName;
    
    /** 操作内容 */
    @Excel(name = "操作内容")
    private String content;
    
    /** 操作时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date logTime;
    
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getDdId() { return ddId; }
    public void setDdId(String ddId) { this.ddId = ddId; }
    public Integer getOperatorType() { return operatorType; }
    public void setOperatorType(Integer operatorType) { this.operatorType = operatorType; }
    public Long getOperatorId() { return operatorId; }
    public void setOperatorId(Long operatorId) { this.operatorId = operatorId; }
    public String getOperatorName() { return operatorName; }
    public void setOperatorName(String operatorName) { this.operatorName = operatorName; }
    public String getContent() { return content; }
    public void setContent(String content) { this.content = content; }
    public Date getLogTime() { return logTime; }
    public void setLogTime(Date logTime) { this.logTime = logTime; }
    }
    

注意:logTime 使用 logTime 而非 createTime,避免与 BaseEntity 的 createTime 冲突。BaseEntity 提供 params map 用于查询参数传递。

  • [ ] Step 2: Commit

    git add ruoyi-system/src/main/java/com/ruoyi/system/domain/PosOrderLog.java
    git commit -m "feat(order-log): add PosOrderLog entity"
    

Task 2: 创建 MyBatis Mapper 接口和 XML

Files:

  • Create: ruoyi-system/src/main/java/com/ruoyi/system/mapper/PosOrderLogMapper.java
  • Create: ruoyi-system/src/main/resources/mapper/system/PosOrderLogMapper.xml

  • [ ] Step 1: 创建 Mapper 接口

    package com.ruoyi.system.mapper;
    
    import java.util.List;
    import com.ruoyi.system.domain.PosOrderLog;
    
    /**
    * 订单操作日志 数据层
    */
    public interface PosOrderLogMapper
    {
    public void insertOrderLog(PosOrderLog orderLog);
    
    public List<PosOrderLog> selectOrderLogList(PosOrderLog orderLog);
    
    public PosOrderLog selectOrderLogById(Long id);
    }
    
  • [ ] Step 2: 创建 XML Mapper

    <?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="com.ruoyi.system.mapper.PosOrderLogMapper">
    
    <resultMap type="PosOrderLog" id="PosOrderLogResult">
        <id     property="id"            column="id"             />
        <result property="ddId"          column="dd_id"          />
        <result property="operatorType"  column="operator_type"  />
        <result property="operatorId"    column="operator_id"    />
        <result property="operatorName"  column="operator_name"  />
        <result property="content"       column="content"        />
        <result property="logTime"       column="create_time"    />
    </resultMap>
    
    <sql id="selectOrderLogVo">
        select id, dd_id, operator_type, operator_id, operator_name, content, create_time
        from pos_order_log
    </sql>
    
    <insert id="insertOrderLog" parameterType="PosOrderLog">
        insert into pos_order_log(dd_id, operator_type, operator_id, operator_name, content, create_time)
        values (#{ddId}, #{operatorType}, #{operatorId}, #{operatorName}, #{content}, sysdate())
    </insert>
    
    <select id="selectOrderLogList" parameterType="PosOrderLog" resultMap="PosOrderLogResult">
        <include refid="selectOrderLogVo"/>
        <where>
            <if test="ddId != null and ddId != ''">
                AND dd_id like concat('%', #{ddId}, '%')
            </if>
            <if test="operatorId != null">
                AND operator_id = #{operatorId}
            </if>
            <if test="operatorName != null and operatorName != ''">
                AND operator_name like concat('%', #{operatorName}, '%')
            </if>
            <if test="operatorType != null">
                AND operator_type = #{operatorType}
            </if>
            <if test="params.beginTime != null and params.beginTime != ''">
                AND create_time &gt;= #{params.beginTime}
            </if>
            <if test="params.endTime != null and params.endTime != ''">
                AND create_time &lt;= #{params.endTime}
            </if>
        </where>
        order by id desc
    </select>
    
    <select id="selectOrderLogById" parameterType="Long" resultMap="PosOrderLogResult">
        <include refid="selectOrderLogVo"/>
        where id = #{id}
    </select>
    
    </mapper>
    
  • [ ] Step 3: Commit

    git add ruoyi-system/src/main/java/com/ruoyi/system/mapper/PosOrderLogMapper.java ruoyi-system/src/main/resources/mapper/system/PosOrderLogMapper.xml
    git commit -m "feat(order-log): add PosOrderLog mapper interface and XML"
    

Task 3: 创建 Service 层

Files:

  • Create: ruoyi-system/src/main/java/com/ruoyi/system/service/IPosOrderLogService.java
  • Create: ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PosOrderLogServiceImpl.java

  • [ ] Step 1: 创建 Service 接口

    package com.ruoyi.system.service;
    
    import java.util.List;
    import com.ruoyi.system.domain.PosOrderLog;
    
    /**
    * 订单操作日志 服务层
    */
    public interface IPosOrderLogService
    {
    public void insertOrderLog(PosOrderLog orderLog);
    
    public List<PosOrderLog> selectOrderLogList(PosOrderLog orderLog);
    
    public PosOrderLog selectOrderLogById(Long id);
    }
    
  • [ ] Step 2: 创建 Service 实现

    package com.ruoyi.system.service.impl;
    
    import java.util.List;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.ruoyi.system.domain.PosOrderLog;
    import com.ruoyi.system.mapper.PosOrderLogMapper;
    import com.ruoyi.system.service.IPosOrderLogService;
    
    /**
    * 订单操作日志 服务层处理
    */
    @Service
    public class PosOrderLogServiceImpl implements IPosOrderLogService
    {
    @Autowired
    private PosOrderLogMapper orderLogMapper;
    
    @Override
    public void insertOrderLog(PosOrderLog orderLog)
    {
        orderLogMapper.insertOrderLog(orderLog);
    }
    
    @Override
    public List<PosOrderLog> selectOrderLogList(PosOrderLog orderLog)
    {
        return orderLogMapper.selectOrderLogList(orderLog);
    }
    
    @Override
    public PosOrderLog selectOrderLogById(Long id)
    {
        return orderLogMapper.selectOrderLogById(id);
    }
    }
    
  • [ ] Step 3: Commit

    git add ruoyi-system/src/main/java/com/ruoyi/system/service/IPosOrderLogService.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/PosOrderLogServiceImpl.java
    git commit -m "feat(order-log): add service interface and implementation"
    

Task 4: 创建 OrderLogHelper 工具类

Files:

  • Create: ruoyi-system/src/main/java/com/ruoyi/system/utils/OrderLogHelper.java

这个工具类封装日志构建逻辑,各调用方只需传入 ddId、operatorType、operatorId、operatorName、content 即可。

  • [ ] Step 1: 创建工具类

    package com.ruoyi.system.utils;
    
    import com.ruoyi.framework.manager.AsyncManager;
    import com.ruoyi.system.domain.PosOrderLog;
    import com.ruoyi.system.service.IPosOrderLogService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.util.TimerTask;
    
    /**
    * 订单操作日志工具类
    */
    @Component
    public class OrderLogHelper {
    
    @Autowired
    private IPosOrderLogService orderLogService;
    
    /**
     * 异步写入订单日志
     */
    public void log(String ddId, int operatorType, Long operatorId, String operatorName, String content) {
        PosOrderLog log = new PosOrderLog();
        log.setDdId(ddId);
        log.setOperatorType(operatorType);
        log.setOperatorId(operatorId);
        log.setOperatorName(operatorName);
        log.setContent(content);
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                orderLogService.insertOrderLog(log);
            }
        });
    }
    
    /**
     * 同步写入订单日志(用于定时任务等异步上下文)
     */
    public void logSync(String ddId, int operatorType, Long operatorId, String operatorName, String content) {
        PosOrderLog log = new PosOrderLog();
        log.setDdId(ddId);
        log.setOperatorType(operatorType);
        log.setOperatorId(operatorId);
        log.setOperatorName(operatorName);
        log.setContent(content);
        orderLogService.insertOrderLog(log);
    }
    }
    

使用 AsyncManager 异步写入,避免影响主流程性能。logSync 给定时任务使用(定时任务已在异步线程中)。

  • [ ] Step 2: Commit

    git add ruoyi-system/src/main/java/com/ruoyi/system/utils/OrderLogHelper.java
    git commit -m "feat(order-log): add OrderLogHelper utility for async log writing"
    

Task 5: 创建后台管理 Controller

Files:

  • Create: ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/PosOrderLogController.java

  • [ ] Step 1: 创建 Controller

    package com.ruoyi.web.controller.system;
    
    import java.util.List;
    import jakarta.servlet.http.HttpServletResponse;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.web.bind.annotation.*;
    import com.ruoyi.common.annotation.Log;
    import com.ruoyi.common.core.controller.BaseController;
    import com.ruoyi.common.core.domain.AjaxResult;
    import com.ruoyi.common.core.page.TableDataInfo;
    import com.ruoyi.common.enums.BusinessType;
    import com.ruoyi.common.utils.poi.ExcelUtil;
    import com.ruoyi.system.domain.PosOrderLog;
    import com.ruoyi.system.service.IPosOrderLogService;
    
    /**
    * 订单操作日志
    */
    @RestController
    @RequestMapping("/system/orderLog")
    public class PosOrderLogController extends BaseController
    {
    @Autowired
    private IPosOrderLogService orderLogService;
    
    @PreAuthorize("@ss.hasPermi('system:orderLog:list')")
    @GetMapping("/list")
    public TableDataInfo list(PosOrderLog orderLog)
    {
        startPage();
        List<PosOrderLog> list = orderLogService.selectOrderLogList(orderLog);
        return getDataTable(list);
    }
    
    @PreAuthorize("@ss.hasPermi('system:orderLog:query')")
    @GetMapping("/{id}")
    public AjaxResult getInfo(@PathVariable Long id)
    {
        return success(orderLogService.selectOrderLogById(id));
    }
    
    @Log(title = "订单操作日志", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:orderLog:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, PosOrderLog orderLog)
    {
        List<PosOrderLog> list = orderLogService.selectOrderLogList(orderLog);
        ExcelUtil<PosOrderLog> util = new ExcelUtil<PosOrderLog>(PosOrderLog.class);
        util.exportExcel(response, list, "订单操作日志");
    }
    }
    
  • [ ] Step 2: Commit

    git add ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/PosOrderLogController.java
    git commit -m "feat(order-log): add admin controller with list/detail/export"
    

Task 6: 商家端操作插入日志

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderShOprateController.java

  • [ ] Step 1: 注入 OrderLogHelper

PosOrderShOprateController 的成员变量区域添加:

@Autowired
private OrderLogHelper orderLogHelper;

添加 import:

import com.ruoyi.system.utils.OrderLogHelper;
  • Step 2: acceptOrder 方法添加日志

posOrderService.saveOrUpdate(update); 之后添加:

InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String shName = shUser != null ? shUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已接单");
  • Step 3: dispatchOrder 方法添加日志

posOrderService.saveOrUpdate(update); 之后、chuCan(order, update); 之前添加:

InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String shName = shUser != null ? shUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已出餐");
  • Step 4: completeOrder 方法添加日志

posOrderService.saveOrUpdate(update); 之后添加:

InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String shName = shUser != null ? shUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "已完成订单");
  • Step 5: cancelOrder 方法添加日志

posOrderService.saveOrUpdate(update); 之后添加:

InfoUser shUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String shName = shUser != null ? shUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 2, Long.valueOf(new JwtUtil().getusid(token)), shName, "商家" + shName + "取消订单");
  • [ ] Step 6: Commit

    git add ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderShOprateController.java
    git commit -m "feat(order-log): add order log to merchant operations"
    

Task 7: 骑手端操作插入日志

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderQsOprateController.java

  • [ ] Step 1: 注入 OrderLogHelper

在成员变量区域添加:

@Autowired
private OrderLogHelper orderLogHelper;

添加 import:

import com.ruoyi.system.utils.OrderLogHelper;
  • Step 2: acceptOrder 方法添加日志

return setOrderQsState(posOrder, qsId, push); 之前添加:

InfoUser qsUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(qsId)));
String qsName = qsUser != null ? qsUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 3, Long.valueOf(qsId), qsName, "骑手" + qsName + "接单成功");
  • Step 3: pickupOrder 方法添加日志

return setOrderQsState(posOrder, qsId, push); 之前添加:

InfoUser qsUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(qsId)));
String qsName = qsUser != null ? qsUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 3, Long.valueOf(qsId), qsName, "骑手" + qsName + "已取餐");
  • Step 4: deliverOrder 方法添加日志

return setOrderQsState(posOrder, qsId, push); 之前添加:

InfoUser qsUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(qsId)));
String qsName = qsUser != null ? qsUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 3, Long.valueOf(qsId), qsName, "骑手" + qsName + "已送达");
  • [ ] Step 5: Commit

    git add ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderQsOprateController.java
    git commit -m "feat(order-log): add order log to rider operations"
    

Task 8: 用户端和平台端操作插入日志

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java
  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java

  • [ ] Step 1: UserOrderController 注入 OrderLogHelper

添加 import 和成员变量:

import com.ruoyi.system.utils.OrderLogHelper;

@Autowired
private OrderLogHelper orderLogHelper;
  • Step 2: UserOrderController.createOrderChild 添加日志

在订单创建成功后(posOrderService.saveOrUpdate() 之后)添加:

InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(userId)));
String uName = uUser != null ? uUser.getNickName() : "";
orderLogHelper.log(String.valueOf(posOrder.getDdId()), 4, Long.valueOf(userId), uName, "用户" + uName + "创建订单");

注意:userId 在 createOrderChild 方法中从 token 获取,变量名需确认是 userId 还是从 jwtUtil.getusid(token) 获取。根据实际方法中已有的变量名调整。

  • Step 3: UserOrderController.confirmPickup 添加日志

posOrderService.saveOrUpdate(update); 之后添加:

InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String uName = uUser != null ? uUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 4, Long.valueOf(new JwtUtil().getusid(token)), uName, "用户" + uName + "确认取餐");
  • Step 4: UserOrderController.cancelOrder 添加日志

posOrderService.saveOrUpdate(update); 之后添加:

InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(new JwtUtil().getusid(token))));
String uName = uUser != null ? uUser.getNickName() : "";
orderLogHelper.log(String.valueOf(order.getDdId()), 4, Long.valueOf(new JwtUtil().getusid(token)), uName, "用户" + uName + "取消订单");
  • Step 5: PosOrderController.setorderuzt 添加日志

PosOrderController 中注入 OrderLogHelper。

setorderuzt 方法中,通用的 posOrderService.saveOrUpdate(posOrder) 成功分支添加:

// 获取平台管理员信息
SysUser adminUser = SecurityUtils.getLoginUser().getUser();
String adminName = adminUser != null ? adminUser.getNickName() : "";
PosOrder beforeOrder = posOrderService.getById(posOrder.getId());
String ddId = beforeOrder != null ? String.valueOf(beforeOrder.getDdId()) : "";
orderLogHelper.log(ddId, 1, adminUser != null ? adminUser.getUserId() : null, adminName,
    "平台管理员" + adminName + "修改订单状态: " + (posOrder.getState() != null ? posOrder.getState() : ""));

注意:PosOrderController.setorderuzt 是平台管理端调用的接口(使用 Spring Security 认证),通过 SecurityUtils.getLoginUser() 获取当前管理员信息。需添加 import com.ruoyi.common.utils.SecurityUtilscom.ruoyi.common.core.domain.entity.SysUser

  • [ ] Step 6: Commit

    git add ruoyi-admin/src/main/java/com/ruoyi/app/order/UserOrderController.java ruoyi-admin/src/main/java/com/ruoyi/app/order/PosOrderController.java
    git commit -m "feat(order-log): add order log to user and platform operations"
    

Task 9: 定时任务和支付回调插入日志

Files:

  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/order/TestTask.java
  • Modify: ruoyi-admin/src/main/java/com/ruoyi/app/pay/PayController.java

  • [ ] Step 1: TestTask 注入 OrderLogHelper

添加 import 和成员变量:

import com.ruoyi.system.utils.OrderLogHelper;

@Autowired
private OrderLogHelper orderLogHelper;
  • Step 2: TestTask.testTiming 添加日志

posOrderService.saveOrUpdate(posOrder); 之后添加:

orderLogHelper.logSync(String.valueOf(ordlist.get(i).getDdId()), 0, null, "系统", "系统自动取消超时未接单订单");

使用 logSync 而非 log,因为定时任务已在异步上下文中。

  • Step 3: TestTask.zidwancheng 添加日志

posOrderService.saveOrUpdate(pos); 之后添加:

orderLogHelper.logSync(String.valueOf(ordlist.get(i).getDdId()), 0, null, "系统", "系统自动完成超时订单");
  • Step 4: TestTask.refundProcessing 添加日志

在退款成功后(posOrderService.saveOrUpdate(posOrder); 之后)添加:

orderLogHelper.logSync(String.valueOf(list.get(i).getDdId()), 0, null, "系统", "系统处理退款完成");
  • Step 5: PayController 注入 OrderLogHelper

添加 import 和成员变量:

import com.ruoyi.system.utils.OrderLogHelper;

@Autowired
private OrderLogHelper orderLogHelper;
  • Step 6: PayController 支付回调添加日志

在支付成功设置 payStatus=1 之后添加:

orderLogHelper.logSync(String.valueOf(order.getDdId()), 0, null, "系统", "系统收到支付成功回调");
  • [ ] Step 7: Commit

    git add ruoyi-admin/src/main/java/com/ruoyi/app/order/TestTask.java ruoyi-admin/src/main/java/com/ruoyi/app/pay/PayController.java
    git commit -m "feat(order-log): add order log to scheduled tasks and payment callback"
    

Task 10: 前端 - API 文件

Files:

  • Create: E:\QtwCode\foodie\foodie-admin-vue\src\api\system\orderLog.js

  • [ ] Step 1: 创建 API 文件

    import request from '@/utils/request'
    
    // 查询订单操作日志列表
    export function listOrderLog(query) {
    return request({
    url: '/system/orderLog/list',
    method: 'get',
    params: query
    })
    }
    
    // 查询订单操作日志详细
    export function getOrderLog(id) {
    return request({
    url: '/system/orderLog/' + id,
    method: 'get'
    })
    }
    
  • [ ] Step 2: Commit

    git add "E:/QtwCode/foodie/foodie-admin-vue/src/api/system/orderLog.js"
    git commit -m "feat(order-log): add frontend API file"
    

Task 11: 前端 - 日志查询页面

Files:

  • Create: E:\QtwCode\foodie\foodie-admin-vue\src\views\system\order\log.vue

这是核心前端页面,参照截图中的 UI 设计。页面使用 Element UI 组件,包含搜索栏、数据表格、分页。

  • Step 1: 创建日志页面

创建 log.vue,包含以下核心结构:

搜索栏:订单号输入框、操作人ID输入框、操作人名称输入框、搜索按钮、重置按钮、导出按钮

数据表格列:主键ID、订单号、操作人类型(格式化为中文)、操作人ID、操作人名称、操作内容、时间、操作(查看链接)

操作人类型格式化方法

operatorTypeFormat(type) {
  const map = { 0: '系统', 1: '平台', 2: '商家', 3: '骑手', 4: '用户' }
  return map[type] || type
}

核心 data 属性

data() {
  return {
    orderLogList: [],
    total: 0,
    queryParams: {
      pageNum: 1,
      pageSize: 10,
      ddId: undefined,
      operatorId: undefined,
      operatorName: undefined
    }
  }
}

核心方法

methods: {
  getList() {
    listOrderLog(this.queryParams).then(response => {
      this.orderLogList = response.rows
      this.total = response.total
    })
  },
  handleQuery() {
    this.queryParams.pageNum = 1
    this.getList()
  },
  resetQuery() {
    this.queryParams = { pageNum: 1, pageSize: 10, ddId: undefined, operatorId: undefined, operatorName: undefined }
    this.getList()
  },
  handleExport() {
    this.download('system/orderLog/export', { ...this.queryParams }, '订单操作日志.xlsx')
  }
}

查看按钮点击后弹窗显示该条日志详情(使用 el-dialog)。

由于前端文件使用 CRLF 换行,编写时使用 Python 脚本方式创建文件。

  • [ ] Step 2: Commit

    git add "E:/QtwCode/foodie/foodie-admin-vue/src/views/system/order/log.vue"
    git commit -m "feat(order-log): add order log query page for admin"
    

Task 12: 前端 - 路由和菜单配置

Files:

  • Modify: E:\QtwCode\foodie\foodie-admin-vue\src\router\index.js

订单日志页面需要添加到路由配置中。在系统管理或订单管理路由组下添加。

由于本项目使用动态路由(菜单由后台数据库配置),路由代码不需要手动添加。需要在数据库的 sys_menu 表中插入菜单记录。

  • Step 1: 添加 SQL 到 updatesql/sql.md

updatesql/sql.md 末尾追加菜单插入 SQL:

-- 2026-05-19 新增订单操作日志菜单
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time, remark)
SELECT '订单日志', menu_id, 6, 'orderLog', 'system/order/log', 'C', '0', '0', 'system:orderLog:list', 'log', 'admin', NOW(), '订单操作日志菜单'
FROM sys_menu WHERE menu_name = '订单管理' AND parent_id = 0 LIMIT 1;

-- 日志查询按钮权限
SET @logMenuId = (SELECT menu_id FROM sys_menu WHERE perms = 'system:orderLog:list' LIMIT 1);
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time)
VALUES ('订单日志查询', @logMenuId, 1, '#', '', 'F', '0', '0', 'system:orderLog:query', '#', 'admin', NOW());
INSERT INTO sys_menu (menu_name, parent_id, order_num, path, component, menu_type, visible, status, perms, icon, create_by, create_time)
VALUES ('订单日志导出', @logMenuId, 2, '#', '', 'F', '0', '0', 'system:orderLog:export', '#', 'admin', NOW());
  • [ ] Step 2: Commit

    git add updatesql/sql.md
    git commit -m "feat(order-log): add menu SQL for order log page"
    

Task 13: 执行数据库建表 SQL

  • Step 1: 在数据库执行建表语句

updatesql/sql.md 中复制 CREATE TABLE pos_order_log 和菜单插入 SQL,在 MySQL 中执行。

  • [ ] Step 2: 验证

  • 启动后端服务

  • 使用商家端操作一个订单(接单→出餐→完成)

  • 打开平台管理端,进入"订单管理 > 订单日志"页面

  • 确认能看到操作日志记录

  • 测试搜索和导出功能


Self-Review Checklist

1. Spec Coverage

Spec 要求 对应 Task
pos_order_log 表 Task 1-3 (Entity/Mapper/Service), SQL in updatesql/sql.md
5 种操作人类型 Task 1 (Entity), Task 4 (Helper), Task 6-9 (各调用方)
日志写入时机(商家4种) Task 6
日志写入时机(骑手3种) Task 7
日志写入时机(用户3种) Task 8
日志写入时机(平台1种) Task 8
日志写入时机(系统3种) Task 9
平台管理端查询页面 Task 10-12
搜索条件(订单号/操作人ID/名称) Task 2 (XML), Task 11 (前端)
导出功能 Task 5 (Controller), Task 11 (前端)
菜单配置 Task 12

2. Placeholder Scan

  • 无 TBD/TODO/实现稍后
  • 所有代码步骤都有完整代码

3. Type Consistency

  • PosOrderLog 字段在 Entity/Mapper XML/Service/Controller/Helper 中保持一致
  • ddId 类型 String, operatorType 类型 Integer, operatorId 类型 Long
  • logTime 映射到数据库 create_time