diff --git a/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs b/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs
index f7d0cf09..4189e6b8 100644
--- a/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs
+++ b/Src/Dlhis.Canteen/Order/Controllers/OrdersController.cs
@@ -40,8 +40,8 @@ public class OrdersController : ControllerBase
///
[AllowAnonymous]
[HttpPost]
- public async Task AddAsync(OrderAddRequest request)
+ public async Task AddAsync(OrderAddRequest request)
{
- await _orderService.AddAsync(request);
+ return await _orderService.AddAsync(request);
}
}
diff --git a/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs
index bae8e194..8fdba839 100644
--- a/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs
+++ b/Src/Dlhis.Canteen/Order/Response/BalanceRecordResponse.cs
@@ -13,7 +13,7 @@ public class BalanceRecordResponse
///
/// 档案号/QRCode
///
- public string UserId { get; set; }
+ public string UserNo { get; set; }
///
/// 姓名
diff --git a/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs b/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs
new file mode 100644
index 00000000..969483d8
--- /dev/null
+++ b/Src/Dlhis.Canteen/Order/Response/OrderConsumeResponse.cs
@@ -0,0 +1,29 @@
+namespace Dlhis.Canteen.Order.Response;
+
+public class OrderConsumeResponse
+{
+ ///
+ /// 用户工号
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 用户名称
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 部门号
+ ///
+ public string DepartmentNo { get; set; }
+
+ ///
+ /// 部门名称
+ ///
+ public string DepartmentName { get; set; }
+
+ ///
+ /// 余额
+ ///
+ public decimal Balance { get; set; }
+}
diff --git a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
index e7e36fca..c7e53edb 100644
--- a/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/IOrderService.cs
@@ -8,5 +8,5 @@ public interface IOrderService : IScopeDependency
{
Task> GetPageAsync(OrderPageRequest request);
- Task AddAsync(OrderAddRequest request);
+ Task AddAsync(OrderAddRequest request);
}
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
index 8bb905f9..912179fe 100644
--- a/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/BalanceService.cs
@@ -1,5 +1,6 @@
using Dlhis.Canteen.Order.Request;
using Dlhis.Canteen.Order.Response;
+using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Canteen.Entities;
using Kurisu.Core.DataAccess.Dto;
using Kurisu.SqlSugar.Extensions;
@@ -19,10 +20,37 @@ public class BalanceService : IBalanceService
public async Task> GetPageAsync(BalanceRecordPageRequest request)
{
var page = await _dbContext.Queryable()
+ .LeftJoin((record, ga) => record.UserNo == ga.No)
+ .LeftJoin((record, ga, department) => ga.DepartmentNo == department.No)
+ .LeftJoin((record, ga, department, bplace) => record.BusinessPlaceCode == bplace.Code)
+ .LeftJoin((record, ga, department, bplace, bshift) => record.BusinessShiftCode == bshift.Code)
.WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true, record => record.CreateTime >= request.SearchDateTimePeriod.Start)
.WhereIF(request.SearchDateTimePeriod?.End.HasValue == true, record => record.CreateTime <= request.SearchDateTimePeriod.End)
.OrderBy(record => record.CreateTime)
- .Select()
+ .Select((record, ga, department, bplace, bshift) => new BalanceRecordResponse
+ {
+ Amount = record.Amount,
+ BusinessPlaceCode = record.BusinessPlaceCode,
+ BusinessShiftCode = record.BusinessShiftCode,
+ CostDate = record.CostDate,
+ CostId = record.CostId,
+ DepartmentNo = record.DepartmentNo,
+ DeviceInfo = record.DeviceInfo,
+ IP = record.IP,
+ UserNo = record.UserNo,
+ UserCode = record.UserCode,
+ Type = record.Type,
+ SubsidiesFromMonth = record.SubsidiesFromMonth,
+ Status = record.Status,
+ Source = record.Source,
+ No = record.No,
+ IsCostCrossTenant = record.IsCostCrossTenant,
+ OriginTenantId = record.OriginTenantId,
+ Name = record.Name,
+ DepartmentName = department.Name,
+ BusinessPlaceName = bplace.Name,
+ BusinessShiftName = bshift.Name,
+ })
.ToPageListAsync(request);
return page;
diff --git a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
index d6084f62..7e3ef6de 100644
--- a/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
+++ b/Src/Dlhis.Canteen/Order/Services/Implements/OrderService.cs
@@ -41,7 +41,7 @@ public class OrderService : IOrderService
}
[IgnoreTenant]
- public async Task AddAsync(OrderAddRequest request)
+ public async Task AddAsync(OrderAddRequest request)
{
var device = await _dbContext.Queryable().Where(x => x.UniqueNo == request.DeviceUniqueNo).Where(x => x.Enable).FirstAsync();
device.ThrowIfNull("设备不存在或者尚未启用");
@@ -107,10 +107,9 @@ public class OrderService : IOrderService
RequestJson = request.ToJson(),
ThirdNo = request.ThirdNo,
Type = request.Type.Value,
- OrderStatus = CanteenOrderStatusEnumType.Wait,
Name = gafinfo.Name,
Source = request.Source,
- UserId = canteenUser.UserNo,
+ UserNo = canteenUser.UserNo,
UserCode = canteenUser.UserCode,
Amount = request.Amount,
BusinessPlaceCode = businessPlace.Code,
@@ -127,14 +126,139 @@ public class OrderService : IOrderService
OriginTenantId = canteenUser.TenantId,//人员可能跨基地消费
- Status = BalanceRecordStatusEnumType.Doubtful,
- TenantId = device.TenantId, //设备才能标识当前消费的基地
+ //餐别异常处理
+ Status = shift == null ? BalanceRecordStatusEnumType.Doubtful : BalanceRecordStatusEnumType.Valid,
+ OrderStatus = CanteenOrderStatusEnumType.Wait,
+ //设备才能标识当前消费的基地
+ TenantId = device.TenantId,
+
+ //默认为admin
+ CreatedBy = 1,
+ CreateTime = DateTime.Now,
+ ModifiedBy = 1,
+ ModifiedTime = DateTime.Now,
};
var id = await _dbContext.InsertReturnIdentityAsync(order);
- await GenerateChargeRecordAsync(id, settings, shifts, request.CostDateTime);
+ var result = await _dbContext.UseTransactionAsync(async () =>
+ {
+ try
+ {
+ var r = await GenerateChargeRecordAsync(id, settings, shifts, request.CostDateTime);
+ return r;
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ finally
+ {
+ //订单消费成功
+ order.OrderStatus = CanteenOrderStatusEnumType.Successful;
+ await _dbContext.UpdateAsync(order);
+ }
+ });
+
+ if (!result.IsSuccess)
+ {
+ throw new UserFriendlyException(result.ErrorMessage);
+ }
+
+ return result.Data;
}
+ public async Task GenerateChargeRecordAsync(long orderId,
+ Dictionary settings,
+ List shifts,
+ DateTime costDateTime)
+ {
+ var order = await _dbContext.Queryable().Where(x => x.Id == orderId).FirstAsync();
+
+ //校验
+ await Verify(settings, shifts, costDateTime, order);
+
+
+ return await ContinueUpdateAsync(async () =>
+ {
+ var canteenUser = await _dbContext.Queryable().Where(x => x.UserNo == order.UserNo).FirstAsync();
+ //金额+-
+ canteenUser.Balance += order.Amount;
+
+ if (order.Type == BalanceRecordTypeEnumType.Out)
+ {
+ if (canteenUser.Balance < 0)
+ {
+ throw new UserFriendlyException("余额不足,无法消费");
+ }
+ }
+
+ var effect = await _dbContext.Updateable()
+ .SetColumns(x => x.Balance == canteenUser.Balance + order.Amount)
+ .SetColumns(x => x.Version == x.Version + 1)
+ .Where(x => x.UserNo == order.UserNo && x.Version == canteenUser.Version)//必须与查询时的version一致
+ .ExecuteCommandAsync();
+
+ if (effect <= 0) throw new VersionExceptions("更新版本冲突");
+
+ //写入消费记录
+ var balanceRecord = order.Adapt();
+ await _dbContext.InsertAsync(balanceRecord);
+
+ return await _dbContext.Queryable()
+ .LeftJoin((ga, department) => ga.DepartmentNo == department.No)
+ .LeftJoin((ga, department, mealUser) => ga.No == mealUser.UserNo)
+ .Select((ga, department, mealUser) => new OrderConsumeResponse
+ {
+ UserCode = ga.Code,
+ UserName = ga.Name,
+ DepartmentNo = ga.DepartmentNo,
+ DepartmentName = department.Name,
+ Balance = mealUser.Balance
+ })
+ .FirstAsync();
+ }, 5);
+ }
+
+ //******************************************************* help methods ************************************************************/
+
+ ///
+ /// 设备并发更新
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private async Task ContinueUpdateAsync(Func> func, int retry)
+ {
+ for (int i = 0; i < retry; i++)
+ {
+ try
+ {
+ return await func();
+ }
+ catch (Exception ex) when (ex is VersionExceptions)
+ {
+ _logger.LogWarning(ex, ex.Message);
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+
+ throw new UserFriendlyException("消费失败,请重试");
+ }
+
+
+ ///
+ /// 获取参数配置
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
private static T GetSetting(Dictionary settings, CanteenSettingItemEnumType item, T defaultValue = default)
{
if (settings.TryGetValue(item, out var v))
@@ -145,59 +269,17 @@ public class OrderService : IOrderService
return defaultValue;
}
- public async Task GenerateChargeRecordAsync(long orderId,
- Dictionary settings,
- List shifts,
- DateTime costDateTime)
- {
- var order = await _dbContext.Queryable().Where(x => x.Id == orderId).FirstAsync();
- await Verify(settings, shifts, costDateTime, order);//校验
-
- for (int i = 0; i < 5; i++)
- {
- try
- {
- var canteenUser = await _dbContext.Queryable().Where(x => x.UserNo == order.UserId).FirstAsync();
- //金额+-
- canteenUser.Balance += order.Amount;
-
- if (order.Type == BalanceRecordTypeEnumType.Out)
- {
- if (canteenUser.Balance < 0)
- {
- throw new UserFriendlyException("余额不足,无法消费");
- }
- }
-
- var effect = await _dbContext.Updateable()
- .SetColumns(x => x.Balance == canteenUser.Balance + order.Amount)
- .SetColumns(x => x.Version == x.Version + 1)
- .Where(x => x.UserNo == order.UserId && x.Version == canteenUser.Version)//必须与查询时的version一致
- .ExecuteCommandAsync();
-
- if (effect <= 0)
- {
- throw new VersionExceptions("更新版本冲突");
- }
-
- var balanceRecord = order.Adapt();
- await _dbContext.InsertAsync(balanceRecord);
- order.Status = BalanceRecordStatusEnumType.Valid; //订单改为有效
-
- break;
- }
- catch (Exception ex) when (ex is VersionExceptions)
- {
- _logger.LogError(ex, ex.Message);
- }
- catch (Exception)
- {
- throw;
- }
- }
- }
+ ///
+ /// 验证参数
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
private async Task Verify(Dictionary settings, List shifts, DateTime costDateTime, CanteenOrderEntity order)
{
//在线
@@ -215,8 +297,8 @@ public class OrderService : IOrderService
var endOfDay = beginOfDay.AddHours(23).AddMinutes(59).AddSeconds(59);
var balanceRecords = await _dbContext.Queryable()
- .Where(x => x.UserId == order.UserId)
- .Where(x => x.CreateTime >= beginOfDay && x.CreateTime <= endOfDay) //今天消费记录
+ .Where(x => x.UserNo == order.UserNo)
+ .Where(x => x.CreateTime <= beginOfDay && x.CreateTime <= endOfDay) //今天消费记录
.ToListAsync();
var dayMarketCostMax = GetSetting(settings, CanteenSettingItemEnumType.DayMarketCostMax);
diff --git a/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs b/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs
index 61daa06e..28c29ef6 100644
--- a/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs
+++ b/Src/Dlhis.Entity/Canteen/Entities/BalanceRecordEntity.cs
@@ -22,7 +22,7 @@ public class BalanceRecordEntity : SugarBaseEntity, ITenantId
/// 档案号/QRCode
///
[SugarColumn(ColumnDescription = "档案号/QRCode")]
- public string UserId { get; set; }
+ public string UserNo { get; set; }
///
/// 姓名
diff --git a/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs b/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs
index 7bb3a02f..1c00c06f 100644
--- a/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs
+++ b/Src/Dlhis.Entity/Canteen/Enums/BalanceRecordStatusEnumType.cs
@@ -15,7 +15,6 @@ public enum BalanceRecordStatusEnumType
[Description("有效数据")]
Valid = 1,
-
///
/// 存疑
///
diff --git a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs
index 94df132e..cb56f36c 100644
--- a/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs
+++ b/Src/Dlhis.Entity/Device/Entities/DeviceTask.cs
@@ -1,4 +1,5 @@
using Dlhis.Entity.Device.Enums;
+using Kurisu.Core.DataAccess.Entity;
using Kurisu.SqlSugar;
using SqlSugar;
using SqlSugar.DbConvert;
@@ -9,7 +10,7 @@ namespace Dlhis.Entity.Device.Entities;
/// 设备任务表
///
[SugarTable(TableName = "DeviceTask")]
-public class DeviceTaskEntity : SugarBaseEntity
+public class DeviceTaskEntity : SugarBaseEntity, ITenantId
{
///
/// 任务类型
@@ -52,4 +53,6 @@ public class DeviceTaskEntity : SugarBaseEntity
/// 处理结果
///
public string ResultMessage { get; set; }
+
+ public string TenantId { get; set; }
}
diff --git a/Src/Dlhis.Entity/Device/Entities/DeviceUploadLogEntity.cs b/Src/Dlhis.Entity/Device/Entities/DeviceUploadLogEntity.cs
new file mode 100644
index 00000000..25d87232
--- /dev/null
+++ b/Src/Dlhis.Entity/Device/Entities/DeviceUploadLogEntity.cs
@@ -0,0 +1,31 @@
+using Kurisu.Core.DataAccess.Entity;
+using Kurisu.SqlSugar;
+using SqlSugar;
+
+namespace Dlhis.Entity.Device.Entities;
+
+[SugarTable(TableName = "DeviceUploadLog", TableDescription = "设备上传记录")]
+public class DeviceUploadLogEntity : SugarBaseEntity, ITenantId
+{
+ ///
+ /// 设备号
+ ///
+ public string DeviceUniqueNo { get; set; }
+
+ ///
+ /// 用户档案号
+ ///
+ public string UserNo { get; set; }
+
+ ///
+ /// 用户学工号
+ ///
+ public string UserCode { get; set; }
+
+ ///
+ /// 上传IP
+ ///
+ public string Ip { get; set; }
+
+ public string TenantId { get; set; }
+}
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs
new file mode 100644
index 00000000..d7809b21
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Controllers/DeviceUploadLogsController.cs
@@ -0,0 +1,35 @@
+using Dlhis.ScheduledTask.DeviceUploadLog.Request;
+using Dlhis.ScheduledTask.DeviceUploadLog.Response;
+using Dlhis.ScheduledTask.DeviceUploadLog.Services;
+using Kurisu.Core.DataAccess.Dto;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Controllers;
+
+///
+/// 设备上传记录
+///
+[Authorize]
+[Route("api/[controller]")]
+[ApiController]
+public class DeviceUploadLogsController : ControllerBase
+{
+ private readonly IDeviceUploadLogService _deviceUploadLogService;
+
+ public DeviceUploadLogsController(IDeviceUploadLogService deviceUploadLogService)
+ {
+ _deviceUploadLogService = deviceUploadLogService;
+ }
+
+ ///
+ /// 获取上传记录分页
+ ///
+ ///
+ ///
+ [HttpGet("page")]
+ public async Task> GetPageAsync([FromQuery] DeviceUploadLogPageRequest request)
+ {
+ return await _deviceUploadLogService.GetPageAsync(request);
+ }
+}
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Request/DeviceUploadLogPageRequest.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Request/DeviceUploadLogPageRequest.cs
new file mode 100644
index 00000000..37aef592
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Request/DeviceUploadLogPageRequest.cs
@@ -0,0 +1,66 @@
+using Dlhis.Entity.Canteen.Enums;
+using Kurisu.Core.CustomClass;
+using System.ComponentModel.DataAnnotations;
+using Kurisu.Core.DataAccess.Dto;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Request;
+
+public class DeviceUploadLogPageRequest : PageDto, IValidatableObject
+{
+ ///
+ /// 查询日期范围类型 DateTimeSearchEnumType
+ ///
+ [EnumDataType(typeof(DateTimeSearchEnumType))]
+ public DateTimeSearchEnumType? SearchDateTimeDimension { get; set; }
+
+ ///
+ /// 日期范围查询
+ ///
+ public DateTimePeriod SearchDateTimePeriod { get; set; }
+
+ public IEnumerable Validate(ValidationContext validationContext)
+ {
+ var now = DateTime.Now;
+ if (SearchDateTimeDimension.HasValue)
+ {
+ //重新赋值
+ SearchDateTimePeriod = new DateTimePeriod();
+
+ if (SearchDateTimeDimension == DateTimeSearchEnumType.Day)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, now.Month, now.Day, 0, 0, 1);
+ SearchDateTimePeriod.End = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Week)
+ {
+ SearchDateTimePeriod.Start = now.AddDays(1 - (int)now.DayOfWeek);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddDays(6);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Month)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, now.Month, 1);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddMonths(1).AddDays(-1);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Season)
+ {
+ SearchDateTimePeriod.Start = now.AddMonths(0 - ((now.Month - 1) % 3));
+ SearchDateTimePeriod.End = now.AddMonths(3 - ((now.Month - 1) % 3)).AddMonths(1).AddDays(-1);
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.HalfOfYear)
+ {
+ SearchDateTimePeriod.Start = now.AddDays(-180);
+ SearchDateTimePeriod.End = now;
+ }
+ else if (SearchDateTimeDimension == DateTimeSearchEnumType.Year)
+ {
+ SearchDateTimePeriod.Start = new DateTime(now.Year, 1, 1);
+ SearchDateTimePeriod.End = SearchDateTimePeriod.Start.Value.AddYears(1).AddDays(-1);
+ }
+
+ SearchDateTimePeriod.Start = SearchDateTimePeriod.Start.Value.Date;
+ SearchDateTimePeriod.End = SearchDateTimePeriod.End.Value.Date;
+ }
+
+ yield break;
+ }
+}
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DeviceUploadLogResponse.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DeviceUploadLogResponse.cs
new file mode 100644
index 00000000..1770a7e6
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Response/DeviceUploadLogResponse.cs
@@ -0,0 +1,37 @@
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Response;
+
+public class DeviceUploadLogResponse
+{
+ public long Id { get; set; }
+
+ ///
+ /// 设备号
+ ///
+ public string DeviceUniqueNo { get; set; }
+
+ ///
+ /// 用户档案号
+ ///
+ public string UserNo { get; set; }
+
+ ///
+ /// 用户学工号
+ ///
+ public string UserCode { get; set; }
+
+
+ ///
+ /// 用户名称
+ ///
+ public string UserName { get; set; }
+
+ ///
+ /// 上传IP
+ ///
+ public string Ip { get; set; }
+
+ ///
+ /// 上传时间
+ ///
+ public DateTime UploadTime { get; set; }
+}
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/IDeviceUploadLogService.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/IDeviceUploadLogService.cs
new file mode 100644
index 00000000..8ff42806
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/IDeviceUploadLogService.cs
@@ -0,0 +1,10 @@
+using Dlhis.ScheduledTask.DeviceUploadLog.Request;
+using Dlhis.ScheduledTask.DeviceUploadLog.Response;
+using Kurisu.Core.DataAccess.Dto;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Services;
+
+public interface IDeviceUploadLogService : IScopeDependency
+{
+ Task> GetPageAsync(DeviceUploadLogPageRequest request);
+}
diff --git a/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
new file mode 100644
index 00000000..795cd81e
--- /dev/null
+++ b/Src/Dlhis.ScheduledTask/DeviceUploadLog/Services/Implements/DeviceUploadLogService.cs
@@ -0,0 +1,40 @@
+using Dlhis.Entity.Basic.Entity;
+using Dlhis.Entity.Device.Entities;
+using Dlhis.ScheduledTask.DeviceUploadLog.Request;
+using Dlhis.ScheduledTask.DeviceUploadLog.Response;
+using Kurisu.Core.DataAccess.Dto;
+using Kurisu.SqlSugar.Extensions;
+using Kurisu.SqlSugar.Services;
+
+namespace Dlhis.ScheduledTask.DeviceUploadLog.Services.Implements;
+
+public class DeviceUploadLogService : IDeviceUploadLogService
+{
+ private readonly IDbContext _dbContext;
+
+ public DeviceUploadLogService(IDbContext dbContext)
+ {
+ _dbContext = dbContext;
+ }
+
+ public async Task> GetPageAsync(DeviceUploadLogPageRequest request)
+ {
+ var page = await _dbContext.Queryable()
+ .LeftJoin((deviceUp, ga) => deviceUp.UserNo == ga.No)
+ .WhereIF(request.SearchDateTimePeriod?.Start.HasValue == true, deviceUp => deviceUp.CreateTime >= request.SearchDateTimePeriod.Start)
+ .WhereIF(request.SearchDateTimePeriod?.End.HasValue == true, deviceUp => deviceUp.CreateTime <= request.SearchDateTimePeriod.End)
+ .Select((deviceUp, ga) => new DeviceUploadLogResponse
+ {
+ DeviceUniqueNo = deviceUp.DeviceUniqueNo,
+ Id = deviceUp.Id,
+ Ip = deviceUp.Ip,
+ UploadTime = deviceUp.CreateTime,
+ UserNo = deviceUp.UserNo,
+ UserCode = deviceUp.UserCode,
+ UserName = ga.Name,
+ })
+ .ToPageListAsync(request);
+
+ return page;
+ }
+}