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

262 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# DeviceCode / DeviceName Header 接收及 label_scan_history 表扩展计划
## 概述
更新后的文档新增了 2 个 Header
- `DeviceCode` — 设备唯一编码GUID32位无横线
- `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<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` 时赋值:
```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`),现有所有调用方无需修改即可编译通过。只有需要记录设备信息的调用方才需显式传入。