# DeviceCode / DeviceName Header 接收及 label_scan_history 表扩展计划 ## 概述 更新后的文档新增了 2 个 Header: - `DeviceCode` — 设备唯一编码(GUID,32位无横线) - `DeviceName` — 设备名称(计算机名) 要求在扫描记录表 `label_scan_history` 中增加设备信息字段,用于跟踪每条记录是哪个设备产生的。 --- ## 涉及修改的文件 | # | 文件 | 操作 | 说明 | |---|------|------|------| | 1 | `src/CONTROLLER/Models/RequestTrackingContext.cs` | 修改 | 加 `DeviceCode`、`DeviceName` | | 2 | `src/CONTROLLER/Middleware/RequestTrackingMiddleware.cs` | 修改 | 读取 `DeviceCode`、`DeviceName` Header | | 3 | `src/CONTROLLER/Extensions/HttpContextExtensions.cs` | 修改 | 加便捷访问方法 | | 4 | `src/MDL/Models/LabelScanEntity.cs` | 修改 | 加 `DeviceCode`、`DeviceName` 属性 | | 5 | `src/BLL/Interfaces/ILabelScanService.cs` | 修改 | `RecordScanAsync` 加 2 个可选参数 | | 6 | `src/BLL/Services/LabelScanService.cs` | 修改 | 实现层写入新字段 | | 7 | `src/MDL/DTOs/LabelScanWithCustomerDto.cs` | 修改 | 加 `DeviceCode`、`DeviceName` | | 8 | `src/DAL/repositories/LabelScanRepository.cs` | 修改 | DTO 映射加设备字段 | | 9 | `src/CONTROLLER/Controllers/LabelController.cs` | 修改 | 3 个 download 端点传设备信息 | | 10 | `database/004_add_device_fields.sql` | **新建** | 数据库 DDL 迁移脚本 | --- ## 实施步骤 ### 步骤 1:扩展 `RequestTrackingContext` 模型 文件:`src/CONTROLLER/Models/RequestTrackingContext.cs` ```csharp namespace CONTROLLER.Models { public class RequestTrackingContext { public string Caller { get; set; } = "system"; public string? DeviceCode { get; set; } public string? DeviceName { get; set; } } } ``` `DeviceCode` 和 `DeviceName` 为可空,未传 Header 时为 `null`。 --- ### 步骤 2:扩展 `RequestTrackingMiddleware` 文件:`src/CONTROLLER/Middleware/RequestTrackingMiddleware.cs` ```csharp var deviceCode = context.Request.Headers["DeviceCode"].FirstOrDefault(); if (!string.IsNullOrWhiteSpace(deviceCode)) trackingContext.DeviceCode = deviceCode; var deviceName = context.Request.Headers["DeviceName"].FirstOrDefault(); if (!string.IsNullOrWhiteSpace(deviceName)) trackingContext.DeviceName = deviceName; ``` 在 `Caller` 读取之后、`context.Items` 赋值之前加入。 --- ### 步骤 3:扩展 `HttpContextExtensions` 文件:`src/CONTROLLER/Extensions/HttpContextExtensions.cs` 新增便捷方法: ```csharp public static string? GetDeviceCode(this HttpContext context) => context.GetRequestTrackingContext().DeviceCode; public static string? GetDeviceName(this HttpContext context) => context.GetRequestTrackingContext().DeviceName; ``` --- ### 步骤 4:扩展 `LabelScanEntity` 模型 文件:`src/MDL/Models/LabelScanEntity.cs` 在 `CreatedBy` 属性之后新增: ```csharp [SugarColumn(Length = 64)] public string? DeviceCode { get; set; } [SugarColumn(Length = 100)] public string? DeviceName { get; set; } ``` - `DeviceCode`: VARCHAR(64),GUID 去除横线后 32 位 - `DeviceName`: VARCHAR(100),计算机名 --- ### 步骤 5:扩展 `ILabelScanService` 接口 文件:`src/BLL/Interfaces/ILabelScanService.cs` `RecordScanAsync` 方法签名追加 2 个可选参数(放在末尾,兼容现有调用): ```csharp Task RecordScanAsync(int customerId, string neutralWaybillNumber, ScanResult result, string createdBy, string? referenceNumber = null, string? finalMileTrackingNumber = null, string? description = null, string? deviceCode = null, string? deviceName = null); ``` --- ### 步骤 6:扩展 `LabelScanService` 实现 文件:`src/BLL/Services/LabelScanService.cs` - 方法签名同步更新 - 创建 `LabelScanEntity` 时赋值: ```csharp var scanRecord = new LabelScanEntity { // ... existing fields ... DeviceCode = deviceCode, DeviceName = deviceName }; ``` --- ### 步骤 7:扩展 `LabelScanWithCustomerDto` 文件:`src/MDL/DTOs/LabelScanWithCustomerDto.cs` 新增: ```csharp public string? DeviceCode { get; set; } public string? DeviceName { get; set; } ``` --- ### 步骤 8:更新 `LabelScanRepository` DTO 映射 文件:`src/DAL/repositories/LabelScanRepository.cs` 在 `GetByPageAsync` 方法的 DTO 构建(第 306-318 行)中增加: ```csharp DeviceCode = l.DeviceCode, DeviceName = l.DeviceName, ``` --- ### 步骤 9:改造 `LabelController` 下载端点传设备信息 文件:`src/CONTROLLER/Controllers/LabelController.cs` 涉及 3 个方法的 `RecordScanAsync` 调用(第 721、1306、1714 行附近),各增加 2 个参数。 **具体改动方案:** 在每个方法的**变量声明区**新增 `deviceCode` 和 `deviceName`: ```csharp string? deviceCode = HttpContext.GetDeviceCode(); string? deviceName = HttpContext.GetDeviceName(); ``` 对于使用 `Task.Run` 异步捕获的方法(download, download/v2),在 finally 块中增加捕获变量: ```csharp var capturedDeviceCode = deviceCode; var capturedDeviceName = deviceName; ``` 然后在 `RecordScanAsync` 调用中添加: ```csharp deviceCode: capturedDeviceCode, deviceName: capturedDeviceName, ``` 对于 NoTrigger 方法(直接 await,无需捕获),直接在调用中添加: ```csharp deviceCode: deviceCode, deviceName: deviceName, ``` **注意**:`deviceCode` 的声明位置需要与 `caller` 一样,放在方法级别的变量初始化区(`try` 块之前),以便 `finally` 块可以访问。 --- ### 步骤 10:创建数据库 DDL 迁移脚本 文件:`database/004_add_device_fields.sql` ```sql -- 为 label_scan_history 表添加设备信息字段 -- 用于跟踪每条扫描记录是哪个设备产生的 ALTER TABLE `label_scan_history` ADD COLUMN `DeviceCode` VARCHAR(64) NULL COMMENT '设备唯一编码(GUID)' AFTER `CreatedBy`, ADD COLUMN `DeviceName` VARCHAR(100) NULL COMMENT '设备名称(计算机名)' AFTER `DeviceCode`; -- 为设备编码添加索引,方便按设备查询/统计 ALTER TABLE `label_scan_history` ADD INDEX `IX_DeviceCode` (`DeviceCode`); ``` 由于 SqlSugar 的 `CodeFirst.InitTables` 在 `LabelScanRepository.CreateAsync` 中会自动建表(首次),新增字段后可能需要手动执行此 SQL(或依赖 CodeFirst 的自动列添加行为,取决于 SqlSugar 配置)。 --- ## 调用链路总结 ``` HTTP Request ├── Header: Caller, DeviceCode, DeviceName │ ▼ RequestTrackingMiddleware └── 提取所有 Header → RequestTrackingContext → HttpContext.Items │ ▼ LabelController.DownloadLabelByWaybillNumber (及另 2 个) ├── var caller = HttpContext.GetCaller(); ├── var deviceCode = HttpContext.GetDeviceCode(); ├── var deviceName = HttpContext.GetDeviceName(); │ ▼ finally RecordScanAsync(..., createdBy: caller, deviceCode: deviceCode, deviceName: deviceName) │ ▼ LabelScanService.RecordScanAsync └── LabelScanEntity { DeviceCode = deviceCode, DeviceName = deviceName } │ ▼ LabelScanRepository.CreateAsync → INSERT INTO label_scan_history ``` --- ## 改造汇总 | 步骤 | 文件 | 操作 | 涉及行数 | |------|------|------|---------| | 1 | `Models/RequestTrackingContext.cs` | 加 2 属性 | ~3 行 | | 2 | `Middleware/RequestTrackingMiddleware.cs` | 加 2 段读取 | ~6 行 | | 3 | `Extensions/HttpContextExtensions.cs` | 加 2 方法 | ~6 行 | | 4 | `MDL/Models/LabelScanEntity.cs` | 加 2 属性 | ~6 行 | | 5 | `BLL/Interfaces/ILabelScanService.cs` | 接口加 2 参数 | ~2 行 | | 6 | `BLL/Services/LabelScanService.cs` | 实现加赋值 | ~3 行 | | 7 | `MDL/DTOs/LabelScanWithCustomerDto.cs` | 加 2 属性 | ~2 行 | | 8 | `DAL/repositories/LabelScanRepository.cs` | DTO 映射加 2 行 | ~2 行 | | 9 | `CONTROLLER/LabelController.cs` | 3 个方法各加声明+传参 | ~15 行 | | 10 | `database/004_add_device_fields.sql` | **新建** | ~8 行 | > **向后兼容**:`RecordScanAsync` 追加的是可选参数(带默认值 `null`),现有所有调用方无需修改即可编译通过。只有需要记录设备信息的调用方才需显式传入。