上传源代码版本

This commit is contained in:
Im-Jenisson
2026-06-01 16:30:29 +08:00
commit b2a9b7d3c2
462 changed files with 104365 additions and 0 deletions

View File

@@ -0,0 +1,746 @@
# 到货交接单和出货交接单模块规格说明
## 1. 需求概述
在系统中增加两个新模块:到货交接单和出货交接单,用于记录和管理货物的交接过程。
### 1.1 到货交接单
- **交接单号**:唯一标识
- **头程物流商送达时间**:物流商送达时间
- **收货时间**:实际收货时间
- **POD**:图片链接,多张用逗号隔开
- **备注**:交接备注信息
- **创建人**:创建该交接单的用户
- **创建时间**:交接单创建时间
- **修改时间**:交接单最后修改时间
### 1.2 出货交接单
- **交接单号**:唯一标识,格式如 BOL-GOFO-202
- **大包数**:大包数量
- **小包数**:小包数量
- **渠道**:物流渠道
- **交货时间**:实际交货时间
- **POD**:图片链接,多张用逗号隔开
- **备注**:交接备注信息
- **创建人**:创建该交接单的用户
- **创建时间**:交接单创建时间
- **修改时间**:交接单最后修改时间
## 2. 技术方案
### 2.1 数据库设计
#### 2.1.1 到货交接单表 (`arrival_handover_forms`)
| 字段名 | 数据类型 | 约束 | 描述 |
|--------|----------|------|------|
| `Id` | `INT` | `PRIMARY KEY, AUTO_INCREMENT` | 主键ID |
| `HandoverNumber` | `VARCHAR(100)` | `NOT NULL, UNIQUE` | 交接单号 |
| `LogisticsProviderArrivalTime` | `DATETIME` | `NULL` | 头程物流商送达时间 |
| `ReceiptTime` | `DATETIME` | `NULL` | 收货时间 |
| `POD` | `TEXT` | `NULL` | 图片链接,多张用逗号隔开 |
| `Remarks` | `TEXT` | `NULL` | 备注 |
| `Creator` | `VARCHAR(50)` | `NOT NULL` | 创建人 |
| `CreatedAt` | `DATETIME` | `NOT NULL` | 创建时间 |
| `UpdatedAt` | `DATETIME` | `NOT NULL` | 修改时间 |
#### 2.1.2 出货交接单表 (`shipping_handover_forms`)
| 字段名 | 数据类型 | 约束 | 描述 |
|--------|----------|------|------|
| `Id` | `INT` | `PRIMARY KEY, AUTO_INCREMENT` | 主键ID |
| `HandoverNumber` | `VARCHAR(100)` | `NOT NULL, UNIQUE` | 交接单号 |
| `BigBagCount` | `INT` | `NOT NULL` | 大包数 |
| `SmallBagCount` | `INT` | `NOT NULL` | 小包数 |
| `Channel` | `VARCHAR(100)` | `NOT NULL` | 渠道 |
| `DeliveryTime` | `DATETIME` | `NULL` | 交货时间 |
| `POD` | `TEXT` | `NULL` | 图片链接,多张用逗号隔开 |
| `Remarks` | `TEXT` | `NULL` | 备注 |
| `Creator` | `VARCHAR(50)` | `NOT NULL` | 创建人 |
| `CreatedAt` | `DATETIME` | `NOT NULL` | 创建时间 |
| `UpdatedAt` | `DATETIME` | `NOT NULL` | 修改时间 |
### 2.2 模型设计
#### 2.2.1 到货交接单模型 (`ArrivalHandoverFormEntity`)
```csharp
using System;
using SqlSugar;
namespace MDL.Models
{
[SugarTable("arrival_handover_forms")]
public class ArrivalHandoverFormEntity
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(Length = 100, IsNullable = false, IsUnique = true)]
public string HandoverNumber { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? LogisticsProviderArrivalTime { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? ReceiptTime { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string POD { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string Remarks { get; set; }
[SugarColumn(Length = 50, IsNullable = false)]
public string Creator { get; set; }
[SugarColumn(IsNullable = false)]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
[SugarColumn(IsNullable = false)]
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
}
```
#### 2.2.2 出货交接单模型 (`ShippingHandoverFormEntity`)
```csharp
using System;
using SqlSugar;
namespace MDL.Models
{
[SugarTable("shipping_handover_forms")]
public class ShippingHandoverFormEntity
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; }
[SugarColumn(Length = 100, IsNullable = false, IsUnique = true)]
public string HandoverNumber { get; set; }
[SugarColumn(IsNullable = false)]
public int BigBagCount { get; set; }
[SugarColumn(IsNullable = false)]
public int SmallBagCount { get; set; }
[SugarColumn(Length = 100, IsNullable = false)]
public string Channel { get; set; }
[SugarColumn(IsNullable = true)]
public DateTime? DeliveryTime { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string POD { get; set; }
[SugarColumn(ColumnDataType = "TEXT", IsNullable = true)]
public string Remarks { get; set; }
[SugarColumn(Length = 50, IsNullable = false)]
public string Creator { get; set; }
[SugarColumn(IsNullable = false)]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
[SugarColumn(IsNullable = false)]
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}
}
```
### 2.3 仓库设计
#### 2.3.1 到货交接单仓库接口 (`IArrivalHandoverFormRepository`)
```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IArrivalHandoverFormRepository
{
Task<int> InsertAsync(ArrivalHandoverFormEntity form);
Task<ArrivalHandoverFormEntity> GetByIdAsync(int id);
Task<ArrivalHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ArrivalHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ArrivalHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator);
}
}
```
#### 2.3.2 出货交接单仓库接口 (`IShippingHandoverFormRepository`)
```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace DAL.Interfaces
{
public interface IShippingHandoverFormRepository
{
Task<int> InsertAsync(ShippingHandoverFormEntity form);
Task<ShippingHandoverFormEntity> GetByIdAsync(int id);
Task<ShippingHandoverFormEntity> GetByHandoverNumberAsync(string handoverNumber);
Task<List<ShippingHandoverFormEntity>> GetAllAsync();
Task<int> UpdateAsync(ShippingHandoverFormEntity form);
Task<int> DeleteAsync(int id);
Task<bool> ExistsByHandoverNumberAsync(string handoverNumber);
Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator);
}
}
```
### 2.4 服务设计
#### 2.4.1 到货交接单服务接口 (`IArrivalHandoverFormService`)
```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace BLL.Interfaces
{
public interface IArrivalHandoverFormService
{
Task<int> CreateArrivalHandoverFormAsync(ArrivalHandoverFormEntity form);
Task<ArrivalHandoverFormEntity> GetArrivalHandoverFormByIdAsync(int id);
Task<ArrivalHandoverFormEntity> GetArrivalHandoverFormByNumberAsync(string handoverNumber);
Task<List<ArrivalHandoverFormEntity>> GetAllArrivalHandoverFormsAsync();
Task<int> UpdateArrivalHandoverFormAsync(ArrivalHandoverFormEntity form);
Task<int> DeleteArrivalHandoverFormAsync(int id);
Task<string> GenerateArrivalHandoverNumberAsync();
Task<(List<ArrivalHandoverFormEntity> Forms, int TotalCount)> GetArrivalHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string creator);
}
}
```
#### 2.4.2 出货交接单服务接口 (`IShippingHandoverFormService`)
```csharp
using System.Collections.Generic;
using System.Threading.Tasks;
using MDL.Models;
namespace BLL.Interfaces
{
public interface IShippingHandoverFormService
{
Task<int> CreateShippingHandoverFormAsync(ShippingHandoverFormEntity form);
Task<ShippingHandoverFormEntity> GetShippingHandoverFormByIdAsync(int id);
Task<ShippingHandoverFormEntity> GetShippingHandoverFormByNumberAsync(string handoverNumber);
Task<List<ShippingHandoverFormEntity>> GetAllShippingHandoverFormsAsync();
Task<int> UpdateShippingHandoverFormAsync(ShippingHandoverFormEntity form);
Task<int> DeleteShippingHandoverFormAsync(int id);
Task<string> GenerateShippingHandoverNumberAsync();
Task<(List<ShippingHandoverFormEntity> Forms, int TotalCount)> GetShippingHandoverFormsBatchAsync(
int page,
int pageSize,
string sortBy,
string sortOrder,
string handoverNumber,
string channel,
string creator);
}
}
```
### 2.5 控制器设计
#### 2.5.1 到货交接单控制器 (`ArrivalHandoverFormController`)
```csharp
using BLL.Interfaces;
using MDL.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
namespace CONTROLLER.Controllers
{
[Route("api/arrival-handover")]
[ApiController]
public class ArrivalHandoverFormController : ControllerBase
{
private readonly IArrivalHandoverFormService _arrivalHandoverFormService;
public ArrivalHandoverFormController(IArrivalHandoverFormService arrivalHandoverFormService)
{
_arrivalHandoverFormService = arrivalHandoverFormService;
}
[HttpPost("create")]
public async Task<IActionResult> CreateArrivalHandoverForm([FromBody] ArrivalHandoverFormEntity form)
{
try
{
if (string.IsNullOrEmpty(form.HandoverNumber))
{
form.HandoverNumber = await _arrivalHandoverFormService.GenerateArrivalHandoverNumberAsync();
}
form.CreatedAt = DateTime.UtcNow;
form.UpdatedAt = DateTime.UtcNow;
var result = await _arrivalHandoverFormService.CreateArrivalHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get/{id}")]
public async Task<IActionResult> GetArrivalHandoverFormById(int id)
{
try
{
var form = await _arrivalHandoverFormService.GetArrivalHandoverFormByIdAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get-by-number/{handoverNumber}")]
public async Task<IActionResult> GetArrivalHandoverFormByNumber(string handoverNumber)
{
try
{
var form = await _arrivalHandoverFormService.GetArrivalHandoverFormByNumberAsync(handoverNumber);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("list")]
public async Task<IActionResult> GetArrivalHandoverForms(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string sortBy = "CreatedAt",
[FromQuery] string sortOrder = "desc",
[FromQuery] string handoverNumber = "",
[FromQuery] string creator = "")
{
try
{
var (forms, totalCount) = await _arrivalHandoverFormService.GetArrivalHandoverFormsBatchAsync(
page, pageSize, sortBy, sortOrder, handoverNumber, creator);
return Ok(new
{
code = 0,
message = "success",
data = new
{
forms,
totalCount
}
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpPut("update")]
public async Task<IActionResult> UpdateArrivalHandoverForm([FromBody] ArrivalHandoverFormEntity form)
{
try
{
form.UpdatedAt = DateTime.UtcNow;
var result = await _arrivalHandoverFormService.UpdateArrivalHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpDelete("delete/{id}")]
public async Task<IActionResult> DeleteArrivalHandoverForm(int id)
{
try
{
var result = await _arrivalHandoverFormService.DeleteArrivalHandoverFormAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("generate-number")]
public async Task<IActionResult> GenerateArrivalHandoverNumber()
{
try
{
var number = await _arrivalHandoverFormService.GenerateArrivalHandoverNumberAsync();
return Ok(new
{
code = 0,
message = "success",
data = number
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
}
}
```
#### 2.5.2 出货交接单控制器 (`ShippingHandoverFormController`)
```csharp
using BLL.Interfaces;
using MDL.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Threading.Tasks;
namespace CONTROLLER.Controllers
{
[Route("api/shipping-handover")]
[ApiController]
public class ShippingHandoverFormController : ControllerBase
{
private readonly IShippingHandoverFormService _shippingHandoverFormService;
public ShippingHandoverFormController(IShippingHandoverFormService shippingHandoverFormService)
{
_shippingHandoverFormService = shippingHandoverFormService;
}
[HttpPost("create")]
public async Task<IActionResult> CreateShippingHandoverForm([FromBody] ShippingHandoverFormEntity form)
{
try
{
if (string.IsNullOrEmpty(form.HandoverNumber))
{
form.HandoverNumber = await _shippingHandoverFormService.GenerateShippingHandoverNumberAsync();
}
form.CreatedAt = DateTime.UtcNow;
form.UpdatedAt = DateTime.UtcNow;
var result = await _shippingHandoverFormService.CreateShippingHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get/{id}")]
public async Task<IActionResult> GetShippingHandoverFormById(int id)
{
try
{
var form = await _shippingHandoverFormService.GetShippingHandoverFormByIdAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("get-by-number/{handoverNumber}")]
public async Task<IActionResult> GetShippingHandoverFormByNumber(string handoverNumber)
{
try
{
var form = await _shippingHandoverFormService.GetShippingHandoverFormByNumberAsync(handoverNumber);
return Ok(new
{
code = 0,
message = "success",
data = form
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("list")]
public async Task<IActionResult> GetShippingHandoverForms(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string sortBy = "CreatedAt",
[FromQuery] string sortOrder = "desc",
[FromQuery] string handoverNumber = "",
[FromQuery] string channel = "",
[FromQuery] string creator = "")
{
try
{
var (forms, totalCount) = await _shippingHandoverFormService.GetShippingHandoverFormsBatchAsync(
page, pageSize, sortBy, sortOrder, handoverNumber, channel, creator);
return Ok(new
{
code = 0,
message = "success",
data = new
{
forms,
totalCount
}
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpPut("update")]
public async Task<IActionResult> UpdateShippingHandoverForm([FromBody] ShippingHandoverFormEntity form)
{
try
{
form.UpdatedAt = DateTime.UtcNow;
var result = await _shippingHandoverFormService.UpdateShippingHandoverFormAsync(form);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpDelete("delete/{id}")]
public async Task<IActionResult> DeleteShippingHandoverForm(int id)
{
try
{
var result = await _shippingHandoverFormService.DeleteShippingHandoverFormAsync(id);
return Ok(new
{
code = 0,
message = "success",
data = result
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
[HttpGet("generate-number")]
public async Task<IActionResult> GenerateShippingHandoverNumber()
{
try
{
var number = await _shippingHandoverFormService.GenerateShippingHandoverNumberAsync();
return Ok(new
{
code = 0,
message = "success",
data = number
});
}
catch (Exception ex)
{
return Ok(new
{
code = 9999,
message = ex.Message
});
}
}
}
}
```
## 3. 数据库SQL脚本
### 3.1 到货交接单表创建脚本
```sql
CREATE TABLE IF NOT EXISTS `arrival_handover_forms` (
`Id` INT NOT NULL AUTO_INCREMENT,
`HandoverNumber` VARCHAR(100) NOT NULL,
`LogisticsProviderArrivalTime` DATETIME NULL,
`ReceiptTime` DATETIME NULL,
`POD` TEXT NULL,
`Remarks` TEXT NULL,
`Creator` VARCHAR(50) NOT NULL,
`CreatedAt` DATETIME NOT NULL,
`UpdatedAt` DATETIME NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE INDEX `UQ_HandoverNumber` (`HandoverNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
### 3.2 出货交接单表创建脚本
```sql
CREATE TABLE IF NOT EXISTS `shipping_handover_forms` (
`Id` INT NOT NULL AUTO_INCREMENT,
`HandoverNumber` VARCHAR(100) NOT NULL,
`BigBagCount` INT NOT NULL,
`SmallBagCount` INT NOT NULL,
`Channel` VARCHAR(100) NOT NULL,
`DeliveryTime` DATETIME NULL,
`POD` TEXT NULL,
`Remarks` TEXT NULL,
`Creator` VARCHAR(50) NOT NULL,
`CreatedAt` DATETIME NOT NULL,
`UpdatedAt` DATETIME NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE INDEX `UQ_HandoverNumber` (`HandoverNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```
## 4. 实现计划
1. **创建模型类**在MDL项目中创建ArrivalHandoverFormEntity和ShippingHandoverFormEntity
2. **创建仓库接口**在DAL项目中创建IArrivalHandoverFormRepository和IShippingHandoverFormRepository
3. **实现仓库类**在DAL项目中实现ArrivalHandoverFormRepository和ShippingHandoverFormRepository
4. **创建服务接口**在BLL项目中创建IArrivalHandoverFormService和IShippingHandoverFormService
5. **实现服务类**在BLL项目中实现ArrivalHandoverFormService和ShippingHandoverFormService
6. **创建控制器**在CONTROLLER项目中创建ArrivalHandoverFormController和ShippingHandoverFormController
7. **更新依赖注入**在Program.cs中注册新的服务和仓库
8. **测试API**验证所有CRUD操作是否正常工作
## 5. 验收标准
1. 数据库表结构正确创建
2. 所有API接口正常工作
3. 交接单号生成规则正确
4. POD字段支持多个图片链接用逗号隔开
5. 分页查询功能正常
6. 所有CRUD操作返回正确的响应格式