# MES 接口调用日志页面设计文档 **日期:** 2026-04-13 **作者:** Claude **版本:** v0.3 **状态:** 已批准 --- ## 1. 概述 ### 1.1 目标 在 WMS 系统中添加 MES 接口调用日志查看页面,提供综合性的日志查询、统计和管理功能。 ### 1.2 范围 - 后端:API 接口、服务层扩展 - 前端:日志列表页面、统计卡片、JSON 详情查看器 - 数据库:菜单配置、数据字典 --- ## 2. 后端设计 ### 2.1 Controller 接口 **文件路径:** `WMS/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Mes/MesLogController.cs` **注意:** 此控制器不继承 `ApiBaseController`,因为 MES 日志是只读记录,不需要完整的 CRUD 操作。仅提供查询、统计和导出功能。 | 方法 | 路径 | 说明 | |------|------|------| | POST | `/api/MesLog/page` | 分页查询,支持所有筛选条件 | | GET | `/api/MesLog/{id}` | 获取单条日志完整信息 | | GET | `/api/MesLog/statistics` | 获取统计数据 | | POST | `/api/MesLog/export` | 导出查询结果为 Excel (使用框架内置导出) | ### 2.2 数据传输对象 #### 2.2.1 查询请求 DTO ```csharp namespace WIDESEA_DTO.MES { /// /// MES日志查询请求DTO /// public class MesLogQueryDto { /// /// 接口类型: BindContainer, UnBindContainer, ContainerNgReport, InboundInContainer, OutboundInContainer /// public string ApiType { get; set; } /// /// 成功状态: null-全部, true-成功, false-失败 /// public bool? IsSuccess { get; set; } /// /// 开始时间(前端 dateRange 字段映射:dateRange[0] → StartTime) /// public DateTime? StartTime { get; set; } /// /// 结束时间(前端 dateRange 字段映射:dateRange[1] → EndTime) /// public DateTime? EndTime { get; set; } /// /// 创建人(操作人) /// public string Creator { get; set; } /// /// 最小耗时(毫秒)(前端 elapsedRange 字段映射:elapsedRange[0] → MinElapsedMs) /// public int? MinElapsedMs { get; set; } /// /// 最大耗时(毫秒)(前端 elapsedRange 字段映射:elapsedRange[1] → MaxElapsedMs) /// public int? MaxElapsedMs { get; set; } /// /// 错误信息关键字 /// public string ErrorKeyword { get; set; } /// /// 请求JSON关键字 /// public string JsonRequestKeyword { get; set; } /// /// 响应JSON关键字 /// public string JsonResponseKeyword { get; set; } } } ``` #### 2.2.2 统计数据 DTO ```csharp namespace WIDESEA_DTO.MES { /// /// MES日志统计数据DTO /// public class MesLogStatisticsDto { /// /// 总调用次数 /// public int TotalCount { get; set; } /// /// 成功次数 /// public int SuccessCount { get; set; } /// /// 成功率(百分比) /// public double SuccessRate { get; set; } /// /// 失败次数 /// public int FailedCount { get; set; } /// /// 平均耗时(毫秒) /// public double AvgElapsedMs { get; set; } /// /// 最大耗时(毫秒) /// public int MaxElapsedMs { get; set; } /// /// 今日调用次数 /// public int TodayCount { get; set; } /// /// 各接口类型调用次数统计 /// public Dictionary ApiTypeCounts { get; set; } } } ``` #### 2.2.3 分页响应 DTO ```csharp namespace WIDESEA_DTO.MES { /// /// MES日志列表项DTO /// public class MesLogListItemDto { public long Id { get; set; } public string ApiType { get; set; } public bool IsSuccess { get; set; } public string RequestJsonPreview { get; set; } // 前200字符预览 public string ResponseJsonPreview { get; set; } // 前200字符预览 public string ErrorMessage { get; set; } public int ElapsedMs { get; set; } public DateTime CreateDate { get; set; } public string Creator { get; set; } } /// /// MES日志详情DTO /// public class MesLogDetailDto : MesLogListItemDto { public string RequestJson { get; set; } // 完整JSON public string ResponseJson { get; set; } // 完整JSON public DateTime? ModifyDate { get; set; } public string Modifier { get; set; } } } ``` ### 2.3 Service 接口扩展 **文件路径:** `WMS/WIDESEA_WMSServer/WIDESEA_IMesService/IMesLogService.cs` ```csharp namespace WIDESEA_IMesService { public interface IMesLogService : IDependency { // 现有方法 Task LogAsync(MesApiLogDto log); Task> GetRecentLogsAsync(string apiType, int count = 50); // 新增方法 /// /// 分页查询MES日志 /// Task<(List items, int total)> GetPageAsync(MesLogQueryDto query, int page, int pageSize); /// /// 获取单条日志详情 /// Task GetDetailAsync(long id); /// /// 获取统计数据 /// Task GetStatisticsAsync(MesLogQueryDto query); /// /// 导出日志数据 /// Task ExportAsync(MesLogQueryDto query); } } ``` ### 2.4 Controller 实现框架 ```csharp namespace WIDESEA_WMSServer.Controllers.Mes { [Route("api/MesLog")] [ApiController] public class MesLogController : ControllerBase { private readonly IMesLogService _mesLogService; public MesLogController(IMesLogService mesLogService) { _mesLogService = mesLogService; } /// /// 分页查询MES日志 /// [HttpPost("page")] public async Task GetPage([FromBody] MesLogQueryDto query, [FromQuery] int page = 1, [FromQuery] int pageSize = 20) { // 实现分页查询 } /// /// 获取日志详情 /// [HttpGet("{id}")] public async Task GetDetail(long id) { // 实现详情查询 } /// /// 获取统计数据 /// [HttpGet("statistics")] public async Task GetStatistics([FromQuery] MesLogQueryDto query) { // 实现统计查询 } /// /// 导出日志 - 使用框架内置 ServiceBase.Export() 方法 /// 通过 HttpHelper.Post() 调用框架的通用导出接口 /// [HttpPost("export")] public async Task Export([FromBody] MesLogQueryDto query) { // 调用 _mesLogService.ExportAsync() 生成数据 // 使用框架内置的 ExcelExporter 导出 } } } ``` ### 2.5 服务注册 **注意:** `IMesLogService` 已实现 `IDependency` 接口,无需手动注册。框架会通过 `AutofacModuleRegister` 自动注册所有 `IDependency` 实现。 --- ## 3. 前端设计 ### 3.1 文件结构 ``` src/ ├── views/ │ └── system/ │ └── Mes_Log.vue # 主页面 ├── extension/ │ └── system/ │ └── Mes_Log.jsx # 业务扩展逻辑 ├── components/ │ └── MesJsonViewer.vue # JSON 详情查看器组件 └── router/ └── viewGird.js # 添加路由配置 ``` ### 3.2 Mes_Log.vue 配置 **注意:** `view-grid` 组件不支持 `toolbar` 插槽,统计卡片需要放在 `view-grid` 外部。 ```vue ``` ### 3.3 MesJsonViewer.vue 组件 **注意:** 不使用外部 JSON 查看器库,采用原生 `
` 标签 + `JSON.stringify()` 格式化显示。

```vue





```

### 3.4 统计卡片组件

**文件路径:** `src/components/MesLogStatistics.vue`

**注意:** 当前项目 Element Plus 版本为 2.2.14,不支持 `el-statistic` 组件(需要 2.3+)。采用自定义卡片实现。

```vue





```

### 3.5 自动刷新功能

**UX 说明:**
- 刷新控制位于页面右上角,与查询条件并列
- 当用户打开筛选面板、编辑查询条件或查看详情时,自动刷新暂停
- 用户手动点击查询/刷新按钮后,自动刷新重新计时

```javascript
// 在 Mes_Log.jsx 中实现
const refreshOptions = [
  { label: "关闭", value: 0 },
  { label: "10秒", value: 10 },
  { label: "30秒", value: 30 },
  { label: "1分钟", value: 60 },
  { label: "5分钟", value: 300 }
];

let refreshTimer = null;

const setAutoRefresh = (interval) => {
  if (refreshTimer) {
    clearInterval(refreshTimer);
    refreshTimer = null;
  }
  if (interval > 0) {
    refreshTimer = setInterval(() => {
      // 仅在用户未交互时刷新列表数据
      if (!isUserInteracting) {
        refresh();
      }
    }, interval * 1000);
  }
};

// 用户交互时暂停刷新
const onUserInteractionStart = () => {
  isUserInteracting = true;
};

const onUserInteractionEnd = () => {
  isUserInteracting = false;
};
```

---

## 4. 数据字典配置

### 4.1 接口类型字典 (mesApiType)

| 值 | 显示文本 | 说明 |
|---|---------|------|
| BindContainer | 电芯绑定 | 托盘电芯绑定操作 |
| UnBindContainer | 电芯解绑 | 托盘电芯解绑操作 |
| ContainerNgReport | NG上报 | 托盘NG电芯上报 |
| InboundInContainer | 托盘进站 | 托盘进站操作 |
| OutboundInContainer | 托盘出站 | 托盘出站操作 |

### 4.2 调用状态字典 (mesApiStatus)

| 值 | 显示文本 | 颜色 |
|---|---------|------|
| true | 成功 | 绿色 |
| false | 失败 | 红色 |

---

## 5. 权限与菜单

### 5.1 菜单配置

在 `Dt_Menu` 表中添加:

| 字段 | 值 |
|------|-----|
| ParentId | (系统管理菜单的 ID) |
| MenuName | MES接口日志 |
| Url | /Mes_Log |
| Component | views/system/Mes_Log |
| Permission | Mes_Log:view |
| Sort | (排在 Sys_Log 之后) |
| Icon | el-icon-document |

### 5.2 权限点

- `Mes_Log:view` - 查看日志列表
- `Mes_Log:detail` - 查看日志详情
- `Mes_Log:export` - 导出日志

---

## 6. 实现步骤

### 6.1 后端实现

1. 扩展 `IMesLogService` 接口(添加分页、统计、导出方法)
2. 实现 `MesLogService` 的扩展方法
3. 创建 DTO 文件(`MesLogQueryDto.cs`, `MesLogStatisticsDto.cs`, `MesLogListItemDto.cs`)
4. 创建 `MesLogController.cs`
5. **注意:** 服务注册自动完成(`IMesLogService` 已实现 `IDependency`)

### 6.2 前端实现

1. 创建 `MesJsonViewer.vue` 组件(使用原生 `
` 标签,无外部依赖)
2. 创建 `MesLogStatistics.vue` 组件(使用 `el-card` 自定义实现)
3. 创建 `Mes_Log.jsx` 扩展逻辑
4. 创建 `Mes_Log.vue` 页面
5. 在 `viewGird.js` 添加路由
6. 在 `extension` 目录添加扩展文件

### 6.3 数据库配置

1. 确认 `Dt_MesApiLog` 表已存在(参见 `Database/Scripts/20260412_MesApiLog.sql`)
2. 创建数据库索引(参见 6.4 节)
3. 插入菜单记录到 `Dt_Menu` 表
4. 插入数据字典记录到 `Dt_Dictionary` 表
5. 分配权限给角色

### 6.4 数据库索引

执行以下 SQL 创建索引以优化查询性能:

```sql
-- 接口类型索引(用于按类型筛选)
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_MesApiLog_ApiType' AND object_id = OBJECT_ID('Dt_MesApiLog'))
BEGIN
    CREATE INDEX IX_MesApiLog_ApiType ON Dt_MesApiLog(ApiType);
END

-- 创建时间索引(用于时间范围查询和排序)
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_MesApiLog_CreateDate' AND object_id = OBJECT_ID('Dt_MesApiLog'))
BEGIN
    CREATE INDEX IX_MesApiLog_CreateDate ON Dt_MesApiLog(CreateDate DESC);
END

-- 成功状态索引(用于成功/失败筛选)
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_MesApiLog_IsSuccess' AND object_id = OBJECT_ID('Dt_MesApiLog'))
BEGIN
    CREATE INDEX IX_MesApiLog_IsSuccess ON Dt_MesApiLog(IsSuccess);
END

-- 创建人索引(用于按操作人筛选)
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_MesApiLog_Creator' AND object_id = OBJECT_ID('Dt_MesApiLog'))
BEGIN
    CREATE INDEX IX_MesApiLog_Creator ON Dt_MesApiLog(Creator);
END
```

---

## 7. 技术要点

### 7.1 JSON 内容搜索

由于 SQL Server 对 JSON 字段支持有限,采用 `LIKE` 搜索:
- 适用于关键字搜索
- 注意性能影响,建议配合时间范围筛选
- 搜索字段:`RequestJson`、`ResponseJson`、`ErrorMessage`

### 7.2 分页性能

- 利用索引(参见 6.4 节数据库索引)
- 大数据量时建议增加时间范围限制(默认显示最近 7 天)
- 考虑添加 `TOP 1000` 限制防止全表扫描

### 7.3 导出功能

- 使用框架内置的 `ServiceBase.Export()` 方法
- 通过 `Magicodes.ExporterAndImporter.Excel` 库实现
- 导出文件命名:`MES接口日志_YYYYMMDD_HHMMSS.xlsx`
- 支持与当前查询条件一致的导出

### 7.4 前端字段映射

| 前端字段 | 后端 DTO 字段 | 说明 |
|---------|--------------|------|
| dateRange[0] | StartTime | 开始时间 |
| dateRange[1] | EndTime | 结束时间 |
| elapsedRange[0] | MinElapsedMs | 最小耗时 |
| elapsedRange[1] | MaxElapsedMs | 最大耗时 |
| jsonKeyword | JsonRequestKeyword, JsonResponseKeyword | 同时搜索请求和响应 |

---

## 8. 测试要点

1. **分页查询** - 验证各种筛选条件的组合
2. **统计准确性** - 验证统计数据与实际数据一致
3. **JSON展示** - 验证格式化、折叠、复制功能
4. **自动刷新** - 验证定时刷新功能正常工作
5. **导出功能** - 验证 Excel 文件内容正确
6. **权限控制** - 验证无权限用户无法访问

---

## 9. 后续优化建议

1. **日志归档** - 考虑定期归档旧日志,保持主表性能
2. **实时监控** - 集成 SignalR 实现实时日志推送
3. **异常告警** - 失败率超过阈值时发送告警
4. **性能分析** - 添加耗时趋势图表
5. **接口对比** - 支持同类接口调用的对比分析