Files
LabelChange-server/.trae/documents/device-header-implementation-plan.md
2026-06-01 16:30:29 +08:00

8.1 KiB
Raw Permalink Blame History

DeviceCode / DeviceName Header 接收及 label_scan_history 表扩展计划

概述

更新后的文档新增了 2 个 Header

  • DeviceCode — 设备唯一编码GUID32位无横线
  • DeviceName — 设备名称(计算机名)

要求在扫描记录表 label_scan_history 中增加设备信息字段,用于跟踪每条记录是哪个设备产生的。


涉及修改的文件

# 文件 操作 说明
1 src/CONTROLLER/Models/RequestTrackingContext.cs 修改 DeviceCodeDeviceName
2 src/CONTROLLER/Middleware/RequestTrackingMiddleware.cs 修改 读取 DeviceCodeDeviceName Header
3 src/CONTROLLER/Extensions/HttpContextExtensions.cs 修改 加便捷访问方法
4 src/MDL/Models/LabelScanEntity.cs 修改 DeviceCodeDeviceName 属性
5 src/BLL/Interfaces/ILabelScanService.cs 修改 RecordScanAsync 加 2 个可选参数
6 src/BLL/Services/LabelScanService.cs 修改 实现层写入新字段
7 src/MDL/DTOs/LabelScanWithCustomerDto.cs 修改 DeviceCodeDeviceName
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

namespace CONTROLLER.Models
{
    public class RequestTrackingContext
    {
        public string Caller { get; set; } = "system";
        public string? DeviceCode { get; set; }
        public string? DeviceName { get; set; }
    }
}

DeviceCodeDeviceName 为可空,未传 Header 时为 null


步骤 2扩展 RequestTrackingMiddleware

文件:src/CONTROLLER/Middleware/RequestTrackingMiddleware.cs

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

新增便捷方法:

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 属性之后新增:

[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 个可选参数(放在末尾,兼容现有调用):

Task<LabelScanEntity> 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 时赋值:
var scanRecord = new LabelScanEntity
{
    // ... existing fields ...
    DeviceCode = deviceCode,
    DeviceName = deviceName
};

步骤 7扩展 LabelScanWithCustomerDto

文件:src/MDL/DTOs/LabelScanWithCustomerDto.cs

新增:

public string? DeviceCode { get; set; }
public string? DeviceName { get; set; }

步骤 8更新 LabelScanRepository DTO 映射

文件:src/DAL/repositories/LabelScanRepository.cs

GetByPageAsync 方法的 DTO 构建(第 306-318 行)中增加:

DeviceCode = l.DeviceCode,
DeviceName = l.DeviceName,

步骤 9改造 LabelController 下载端点传设备信息

文件:src/CONTROLLER/Controllers/LabelController.cs

涉及 3 个方法的 RecordScanAsync 调用(第 721、1306、1714 行附近),各增加 2 个参数。

具体改动方案:

在每个方法的变量声明区新增 deviceCodedeviceName

string? deviceCode = HttpContext.GetDeviceCode();
string? deviceName = HttpContext.GetDeviceName();

对于使用 Task.Run 异步捕获的方法download, download/v2在 finally 块中增加捕获变量:

var capturedDeviceCode = deviceCode;
var capturedDeviceName = deviceName;

然后在 RecordScanAsync 调用中添加:

deviceCode: capturedDeviceCode,
deviceName: capturedDeviceName,

对于 NoTrigger 方法(直接 await无需捕获直接在调用中添加

deviceCode: deviceCode,
deviceName: deviceName,

注意deviceCode 的声明位置需要与 caller 一样,放在方法级别的变量初始化区(try 块之前),以便 finally 块可以访问。


步骤 10创建数据库 DDL 迁移脚本

文件:database/004_add_device_fields.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.InitTablesLabelScanRepository.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),现有所有调用方无需修改即可编译通过。只有需要记录设备信息的调用方才需显式传入。