refactor 优化命名和结构,注释

This commit is contained in:
2025-06-30 14:20:26 +08:00
parent 6fd0a2b1ef
commit 221d985850
24 changed files with 368 additions and 205 deletions

View File

@@ -52,18 +52,6 @@ public class HolidaysController : ControllerBase
[HttpGet("remote-ip")] [HttpGet("remote-ip")]
public string GetRemoteIp() public string GetRemoteIp()
{ {
// 检查是否在Kubernetes环境中
var isKubernetes = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST"));
if (isKubernetes)
{
var forwardedFor = HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
if (!string.IsNullOrEmpty(forwardedFor))
{
return forwardedFor.Split(',').First().Trim();
}
}
return HttpContext.Connection.RemoteIpAddress?.ToString(); return HttpContext.Connection.RemoteIpAddress?.ToString();
} }
} }

View File

@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Mvc; using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Services;
using Microsoft.AspNetCore.Mvc;
namespace Dlhis.Basic.Common.Message; namespace Dlhis.Basic.Common.Message.Controller;
[Route("api/[controller]")] [Route("api/[controller]")]
@@ -16,7 +18,7 @@ public class MessagesController : ControllerBase
[HttpPost("dingtalk/workmessage")] [HttpPost("dingtalk/workmessage")]
public async Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request) public async Task SendWorkMessageAsync(DingTalkWorkMessageRequest request)
{ {
await _jinkoApiService.SendWorkMessageAsync(request); await _jinkoApiService.SendWorkMessageAsync(request);
} }

View File

@@ -1,6 +0,0 @@
namespace Dlhis.Basic.Common.Message;
public interface IJinkoApiService : ISingletonDependency
{
Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request);
}

View File

@@ -1,14 +0,0 @@
namespace Dlhis.Basic.Common.Message;
public class JinkoSendWorkMessageRequest
{
/// <summary>
/// 发送内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 工号
/// </summary>
public List<string> WorkCodes { get; set; }
}

View File

@@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace Dlhis.Basic.Common.Message.Requests;
public class DingTalkWorkMessageRequest
{
/// <summary>
/// 工号
/// </summary>
[MinLength(1, ErrorMessage = "{0}不能为空")]
public List<string> WorkCodes { get; set; }
/// <summary>
/// 发送内容
/// </summary>
[Required(ErrorMessage = "{0}不能为空")]
public string Content { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace Dlhis.Basic.Common.Message namespace Dlhis.Basic.Common.Message.Responses
{ {
public class JinkoOaResponse<T> public class JinkoOaResponse<T>
{ {
@@ -12,11 +12,10 @@ namespace Dlhis.Basic.Common.Message
public T Data { get; set; } public T Data { get; set; }
} }
public class JinkoOaInfo public class JinkoOaInfo
{ {
public int Id { get; set; } public int Id { get; set; }
public string Email { get; set; } public string Email { get; set; }
public string Lastname { get; set; } public string Lastname { get; set; }
} }
} }

View File

@@ -0,0 +1,8 @@
using Dlhis.Basic.Common.Message.Requests;
namespace Dlhis.Basic.Common.Message.Services;
public interface IJinkoApiService : ISingletonDependency
{
Task SendWorkMessageAsync(DingTalkWorkMessageRequest request);
}

View File

@@ -1,11 +1,13 @@
using System.Text; using System.Text;
using Dlhis.Basic.Common.ApiLog.Services; using Dlhis.Basic.Common.ApiLog.Services;
using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Responses;
using Dlhis.Entity.Common.Enums; using Dlhis.Entity.Common.Enums;
using Kurisu.AspNetCore.Utils.Extensions; using Kurisu.AspNetCore.Utils.Extensions;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Dlhis.Basic.Common.Message; namespace Dlhis.Basic.Common.Message.Services.Implements;
public class JinkoApiService : IJinkoApiService public class JinkoApiService : IJinkoApiService
{ {
@@ -24,49 +26,51 @@ public class JinkoApiService : IJinkoApiService
private async Task<string> GetTokenAsync() private async Task<string> GetTokenAsync()
{ {
var token = string.Empty; var token = string.Empty;
if (string.IsNullOrEmpty(token)) if (!token.IsEmpty())
{ {
var httpClient = _httpClientFactory.CreateClient("jinko.httpclient"); return token;
var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "appkey", _appKey },
{ "appsecret", _appSecret }
});
//appkey=dingumelppews6rah7x9&appsecret=nsWfJTVjYesHVzrLiP-t1TQqMQvC1L_kZNfXfnIyzcXK4pCTfKprkjZcxAbsDR_l
var response = await httpClient.GetStringAsync($"/gettoken?{await form.ReadAsStringAsync()}");
var jObj = JObject.Parse(response);
(jObj.Value<string>("errcode") == "0").ThrowIfFalse(jObj.Value<string>("errmsg"));
token = jObj.Value<string>("access_token");
} }
var httpClient = _httpClientFactory.CreateClient("jinko.httpclient");
var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "appkey", _appKey },
{ "appsecret", _appSecret }
});
//eg: appkey=dingumelppews6rah7x9&appsecret=nsWfJTVjYesHVzrLiP-t1TQqMQvC1L_kZNfXfnIyzcXK4pCTfKprkjZcxAbsDR_l
var response = await httpClient.GetStringAsync($"/gettoken?{await form.ReadAsStringAsync()}");
var jObj = JObject.Parse(response);
(jObj.Value<string>("errcode") == "0").ThrowIfFalse(jObj.Value<string>("errmsg"));
token = jObj.Value<string>("access_token");
return token; return token;
} }
public async Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request) public async Task SendWorkMessageAsync(DingTalkWorkMessageRequest request)
{ {
request.Content.IsEmpty().ThrowIfTrue("发送内容不能为空"); request.Content.IsEmpty().ThrowIfTrue("发送内容不能为空");
var token = await GetTokenAsync(); var token = await GetTokenAsync();
var users = await GetJinkoOaInfoByWorkCodes(request.WorkCodes); var users = await GetJinkoOaInfoByWorkCodes(request.WorkCodes);
var userStringIds = string.Join(",", users.Select(x => x.Id)); var userIds = users.Select(x => x.Id).Join(",");
(userStringIds.Length > 100).ThrowIfTrue("超出消息接受人数,length > 100"); (userIds.Length > 100).ThrowIfTrue("超出消息接受人数,length > 100");
var body = new var body = new
{ {
agent_id = _agentId, agent_id = _agentId,
userid_list = userStringIds, userid_list = userIds,
msg = new msg = new
{ {
msgtype = "text", msgtype = "text",
text = new text = new
{ {
content = request.Content content = request.Content
}, }
}, }
}.ToJson(); }.ToJson();
var httpClient = _httpClientFactory.CreateClient("jinko.httpclient"); var httpClient = _httpClientFactory.CreateClient("jinko.httpclient");
@@ -76,11 +80,8 @@ public class JinkoApiService : IJinkoApiService
var response = await httpClient.PostAsync(url, content); var response = await httpClient.PostAsync(url, content);
var jsonResponse = await response.Content.ReadAsStringAsync(); var jsonResponse = await response.Content.ReadAsStringAsync();
//_logger.LogInformation("请求参数:{Request} \r\n 钉钉请求参数:{DingTalkRequest} \r\n 钉钉响应:{DingTalkResponse}", JsonConvert.SerializeObject(request), body, jsonResponse); var jObject = JObject.Parse(jsonResponse);
(jObject.Value<string>("errcode") == "0").ThrowIfFalse(jObject.Value<string>("errmsg"));
var jObj = JObject.Parse(jsonResponse);
(jObj.Value<string>("errcode") == "0").ThrowIfFalse(jObj.Value<string>("errmsg"));
using var scope = _serviceProvider.CreateScope(); using var scope = _serviceProvider.CreateScope();
var ol = scope.ServiceProvider.GetService<IOperateLog>(); var ol = scope.ServiceProvider.GetService<IOperateLog>();

View File

@@ -196,7 +196,7 @@ public class DevicePermissionAnalyzeService : IDevicePermissionAnalyzeService
AssignTypeEnumType.Group => analyzePack.UserGainfoGroupCodes.Select(x => x.ToString()), AssignTypeEnumType.Group => analyzePack.UserGainfoGroupCodes.Select(x => x.ToString()),
AssignTypeEnumType.Department => RecursionHelper.HandlerDepartmentPreviousCodes(analyzePack.UserDepartment, departments).Select(x => analyzePack.UserFactory + ":" + x).ToList(), AssignTypeEnumType.Department => RecursionHelper.HandlerDepartmentPreviousCodes(analyzePack.UserDepartment, departments).Select(x => analyzePack.UserFactory + ":" + x).ToList(),
AssignTypeEnumType.Tenant => new List<string> { analyzePack.UserFactory }, AssignTypeEnumType.Tenant => new List<string> { analyzePack.UserFactory },
AssignTypeEnumType.Role => throw new ArgumentOutOfRangeException(), AssignTypeEnumType.Role => throw new NotSupportedException("不支持角色分配"),
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };

View File

@@ -517,6 +517,7 @@ public class DevicePermissionService : IDevicePermissionService
{ {
var now = DateTime.Now; var now = DateTime.Now;
// 获取与指定设备关联的分组编码
var groupCodes = await _dbContext.Queryable<DeviceGroupEntity>() var groupCodes = await _dbContext.Queryable<DeviceGroupEntity>()
.Where(x => SqlFunc.Subqueryable<DeviceGroupRelationshipEntity>() .Where(x => SqlFunc.Subqueryable<DeviceGroupRelationshipEntity>()
.Where(p => p.GroupCode == x.Code) .Where(p => p.GroupCode == x.Code)
@@ -525,25 +526,30 @@ public class DevicePermissionService : IDevicePermissionService
.Select(x => x.Code) .Select(x => x.Code)
.ToListAsync(); .ToListAsync();
// 获取与分组相关联的区域编码及类型
var areaCodes = await _dbContext.Queryable<AppointmentAreaAssignmentEntity>() var areaCodes = await _dbContext.Queryable<AppointmentAreaAssignmentEntity>()
.LeftJoin<AppointmentAreaEntity>((x, y) => x.CustomCode == y.CustomCode) .LeftJoin<AppointmentAreaEntity>((x, y) => x.CustomCode == y.CustomCode)
.Where(x => groupCodes.Contains(x.DeviceGroupCode)) .Where(x => groupCodes.Contains(x.DeviceGroupCode))
.Select((x, y) => new { x.CustomCode, y.Type }) .Select((x, y) => new { x.CustomCode, y.Type })
.ToListAsync(); .ToListAsync();
// 根据区域类型筛选出门区和厂区的区域编码
var doorAreaCodes = areaCodes.Where(p => p.Type == AppointmentAreaEnumType.Door).Select(p => p.CustomCode).ToList(); var doorAreaCodes = areaCodes.Where(p => p.Type == AppointmentAreaEnumType.Door).Select(p => p.CustomCode).ToList();
var workplaceAreaCodes = areaCodes.Where(p => p.Type == AppointmentAreaEnumType.Workplace).Select(p => p.CustomCode).ToList(); var workplaceAreaCodes = areaCodes.Where(p => p.Type == AppointmentAreaEnumType.Workplace).Select(p => p.CustomCode).ToList();
// 查询当前时间段内已到访的访客预约明细
var details = await _dbContext.Queryable<VisitorAppointmentDetailEntity>() var details = await _dbContext.Queryable<VisitorAppointmentDetailEntity>()
.Where(x => (x.IsEnterDoorArea && now >= x.DoorStart && now <= x.DoorEnd && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived) .Where(x => (x.IsEnterDoorArea && now >= x.DoorStart && now <= x.DoorEnd && x.DoorStatus == VisitorAppointmentDetailStatusEnumType.Arrived)
|| x.IsEnterWorkplace && now >= x.WorkplaceStart && now <= x.WorkplaceEnd && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Arrived) || x.IsEnterWorkplace && now >= x.WorkplaceStart && now <= x.WorkplaceEnd && x.WorkplaceStatus == VisitorAppointmentDetailStatusEnumType.Arrived)
.ToListAsync(); .ToListAsync();
//到访门区或厂区的访客编号列表
return details.Where(x => return details.Where(x =>
(x.IsEnterDoorArea && doorAreaCodes.Contains(x.ApplyDoorArea)) (x.IsEnterDoorArea && doorAreaCodes.Contains(x.ApplyDoorArea))
|| (x.IsEnterWorkplace && workplaceAreaCodes.Any(p => x.ApplyWorkplaceAreas.Contains(p))) || (x.IsEnterWorkplace && workplaceAreaCodes.Any(p => x.ApplyWorkplaceAreas.Contains(p)))
) )
.Select(x => x.UserNo) .Select(x => x.UserNo)
.Distinct()
.ToList(); .ToList();
} }
} }

View File

@@ -1,4 +1,5 @@
using Dlhis.Basic.Common.Message; using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Services;
using Dlhis.Basic.Organization.Comparers; using Dlhis.Basic.Organization.Comparers;
using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Basic.Enums;
@@ -186,7 +187,7 @@ public class GainfoUpdateService : IGainfoUpdateService
}); });
} }
private GainfoEntity GainfoSapToGainfo(GainfoSapEntity item) private static GainfoEntity GainfoSapToGainfo(GainfoSapEntity item)
{ {
var info = new GainfoEntity var info = new GainfoEntity
{ {
@@ -319,20 +320,24 @@ public class GainfoUpdateService : IGainfoUpdateService
{ {
var resignationDate = DateOnly.FromDateTime(gainfo.ModifiedTime); var resignationDate = DateOnly.FromDateTime(gainfo.ModifiedTime);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>().Where(x => x.UserCode == gainfo.Code) var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
.Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate) .Where(x => x.Date >= resignationDate)
.ToListAsync(); .ToListAsync();
if (workGridSchedules.Any()) if (workGridSchedules.Any())
{ {
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(","); var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>().Where(x => x.Code == workGridUser.WorkGridCode).Select(x => new var workGrid = await _dbContext.Queryable<WorkGridEntity>()
{ .Where(x => x.Code == workGridUser.WorkGridCode)
x.LeaderUserCode, x.Name .Select(x => new
}).SingleAsync(); {
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!"; x.LeaderUserCode, x.Name
}).SingleAsync();
await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageAsync(new DingTalkWorkMessageRequest
{ {
Content = content, Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode } WorkCodes = new List<string> { workGrid.LeaderUserCode }
@@ -364,30 +369,39 @@ public class GainfoUpdateService : IGainfoUpdateService
await _dbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommandAsync(); await _dbContext.Client.Insertable(gainfo).AS("GainfoLeave").ExecuteCommandAsync();
} }
await _dbContext.Deleteable<GainfoGroupRelationshipEntity>().Where(x => x.UserNo == gainfo.No).ExecuteCommandAsync(); await _dbContext.Deleteable<GainfoGroupRelationshipEntity>()
await _dbContext.Deleteable<DevicePermissionEntity>().Where(x => x.AssignType == AssignTypeEnumType.User && x.AssignValue == gainfo.No).ExecuteCommandAsync(); .Where(x => x.UserNo == gainfo.No)
.ExecuteCommandAsync();
await _dbContext.Deleteable<DevicePermissionEntity>()
.Where(x => x.AssignType == AssignTypeEnumType.User && x.AssignValue == gainfo.No)
.ExecuteCommandAsync();
var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>().Where(x => x.UserCode == gainfo.Code).SingleAsync(); var workGridUser = await _dbContext.Queryable<WorkGridUserEntity>()
.Where(x => x.UserCode == gainfo.Code)
.SingleAsync();
if (workGridUser != null) if (workGridUser != null)
{ {
try try
{ {
var resignationDate = DateOnly.FromDateTime(gainfo.ResignationDate!.Value); var resignationDate = DateOnly.FromDateTime(gainfo.ResignationDate!.Value);
var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>().Where(x => x.UserCode == gainfo.Code) var workGridSchedules = await _dbContext.Queryable<WorkGridScheduleEntity>()
.Where(x => x.UserCode == gainfo.Code)
.Where(x => x.Date >= resignationDate) .Where(x => x.Date >= resignationDate)
.ToListAsync(); .ToListAsync();
if (workGridSchedules.Any()) if (workGridSchedules.Any())
{ {
var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(","); var dates = workGridSchedules.Select(x => $"{x.Date.ToString("yyyy年-MM月-dd日")}的{x.PeriodType.GetDescription()}").Join(",");
var workGrid = await _dbContext.Queryable<WorkGridEntity>().Where(x => x.Code == workGridUser.WorkGridCode).Select(x => new var workGrid = await _dbContext.Queryable<WorkGridEntity>()
{ .Where(x => x.Code == workGridUser.WorkGridCode)
x.LeaderUserCode, x.Name .Select(x => new
}).SingleAsync(); {
x.LeaderUserCode, x.Name
}).SingleAsync();
var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!"; var content = $"{workGrid.Name}的网格长,你好,检测到你网格中 {gainfo.Name}({gainfo.Code}),因发生离职或者异动,现已经删除该员工{dates}的排班信息,请前往系统处理!";
await _dingTalkApi.SendWorkMessageAsync(new JinkoSendWorkMessageRequest await _dingTalkApi.SendWorkMessageAsync(new DingTalkWorkMessageRequest
{ {
Content = content, Content = content,
WorkCodes = new List<string> { workGrid.LeaderUserCode } WorkCodes = new List<string> { workGrid.LeaderUserCode }

View File

@@ -7,9 +7,7 @@ class Program
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
KurisuHost.Builder(args) KurisuHost.Builder(args).RunKurisu<Startup>();
//.EnableAppSettingsReload()
.RunKurisu<Startup>();
} }
} }
@@ -29,7 +27,7 @@ public class Startup : DefaultStartup
options.KnownNetworks.Clear(); options.KnownNetworks.Clear();
options.KnownProxies.Clear(); options.KnownProxies.Clear();
}); });
base.ConfigureServices(services); base.ConfigureServices(services);
services.AddRedis(); services.AddRedis();

View File

@@ -0,0 +1,15 @@
using Dlhis.Basic.WorkGrids.Response;
namespace Dlhis.Basic.WorkGrids.Repositories;
public interface IWorkGridScheduleRepository : IScopeDependency
{
/// <summary>
/// 获取用户在指定天数内最大连续排班信息
/// </summary>
/// <param name="userCodes">用户编码列表</param>
/// <param name="days">天数</param>s
/// <param name="date">日期</param>
/// <returns>最大连续排班信息列表</returns>
Task<List<WorkGridScheduleMaximumConsecutiveDto>> MaximumConsecutiveUserCodesAsync(List<string> userCodes, int days, DateOnly date);
}

View File

@@ -0,0 +1,62 @@
using Dlhis.Basic.WorkGrids.Response;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.Basic.WorkGrids.Repositories.Implements;
public class WorkGridScheduleRepository : IWorkGridScheduleRepository
{
private readonly IDbContext _dbContext;
public WorkGridScheduleRepository(IDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<List<WorkGridScheduleMaximumConsecutiveDto>> MaximumConsecutiveUserCodesAsync(List<string> userCodes, int days, DateOnly date)
{
var userCodesStr = userCodes.Select(x => $"@param{x.Replace("-", "A_")}").Join(",");
var parameters = userCodes.ToDictionary(x => $"param{x.Replace("-", "A_")}", x => x);
parameters.Add("dateBefore", date.AddDays(-1).ToString("yyyy-MM-dd"));
parameters.Add("dateAfter", date.AddDays(1).ToString("yyyy-MM-dd"));
parameters.Add("days", days.ToString());
/* 1.用户按日期排序,标记序号
* 2.将日期减去序号,需要得出结果一致 == 数据连续 == 连续排班
* 3.根据减去序号后的日期分组,统计连续排班的天数
* 4.数据过滤,取当前排班的前后一天
*
* 根据以上结果,获取连续排班天数大于等于指定天数的用户
*/
var sql = $@"
WITH ranked_dates AS (SELECT UserCode,
Date,
ROW_NUMBER() OVER (PARTITION BY UserCode ORDER BY Date) AS rn
FROM WorkGridSchedules
where IsDeleted = 0 and UserCode in ({userCodesStr})
GROUP BY UserCode, Date),
grouped AS (SELECT UserCode,
Date,
DATE_SUB(Date, INTERVAL rn DAY) AS grp
FROM ranked_dates),
streaks AS (SELECT UserCode,
grp,
COUNT(*) AS streak_days,
MIN(Date) AS start_date,
MAX(Date) AS end_date
FROM grouped
GROUP BY UserCode, grp
HAVING streak_days >= @days)
SELECT UserCode, streak_days as Count, start_date as Start, end_date as End
FROM streaks
where (@dateBefore >= start_date
and @dateBefore <= end_date)
or (@dateAfter >= start_date
and @dateAfter <= end_date)
";
return await _dbContext.Client.Ado.SqlQueryAsync<WorkGridScheduleMaximumConsecutiveDto>(sql, parameters);
}
}

View File

@@ -5,7 +5,7 @@ namespace Dlhis.Basic.WorkGrids.Request;
public class WorkGridPageRequest : PageDto public class WorkGridPageRequest : PageDto
{ {
/// <summary> /// <summary>
/// 网格code,不传则取我的网格 /// 网格code,默认为当前用户网格
/// </summary> /// </summary>
public Guid? WorkGridCode { get; set; } public Guid? WorkGridCode { get; set; }

View File

@@ -18,7 +18,7 @@ public class WorkGridScheduleSaveRequest : IValidatableObject
/// <summary> /// <summary>
/// 班次 /// 班次
/// </summary> /// </summary>
[EnumDataType(typeof(WorkGridTimePeriodEnumType))] [EnumDataType(typeof(WorkGridTimePeriodEnumType), ErrorMessage = "班次类型错误")]
public WorkGridTimePeriodEnumType PeriodType { get; set; } public WorkGridTimePeriodEnumType PeriodType { get; set; }
/// <summary> /// <summary>
@@ -27,7 +27,7 @@ public class WorkGridScheduleSaveRequest : IValidatableObject
[MinLength(1, ErrorMessage = "人员不可为空")] [MinLength(1, ErrorMessage = "人员不可为空")]
public List<string> UserCodes { get; set; } public List<string> UserCodes { get; set; }
/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{ {
var now = DateTime.Now; var now = DateTime.Now;

View File

@@ -1,5 +1,11 @@
using Dlhis.Basic.WorkGrids.Repositories;
namespace Dlhis.Basic.WorkGrids.Response; namespace Dlhis.Basic.WorkGrids.Response;
/// <summary>
/// 连续排班信息
/// <see cref="IWorkGridScheduleRepository.MaximumConsecutiveUserCodesAsync"/>的方法返回类型
/// </summary>
public class WorkGridScheduleMaximumConsecutiveDto public class WorkGridScheduleMaximumConsecutiveDto
{ {
public string UserCode { get; set; } public string UserCode { get; set; }

View File

@@ -10,21 +10,60 @@ namespace Dlhis.Basic.WorkGrids.Services;
/// </summary> /// </summary>
public interface IWorkGridScheduleService : IScopeDependency public interface IWorkGridScheduleService : IScopeDependency
{ {
/// <summary>
/// 保存网格排班信息
/// </summary>
/// <param name="request">排班保存请求参数</param>
Task SaveAsync(WorkGridScheduleSaveRequest request); Task SaveAsync(WorkGridScheduleSaveRequest request);
/// <summary>
/// 移除网格排班信息
/// </summary>
/// <param name="request">排班移除请求参数</param>
Task RemoveAsync(WorkGridScheduleSaveRequest request); Task RemoveAsync(WorkGridScheduleSaveRequest request);
/// <summary>
/// 获取指定网格、日期和时段的排班列表
/// </summary>
/// <param name="workGridCode">网格编码</param>
/// <param name="date">日期</param>
/// <param name="periodType">时段类型</param>
/// <returns>排班列表</returns>
Task<List<WorkGridScheduleResponse>> GetListAsync(Guid workGridCode, DateOnly date, WorkGridTimePeriodEnumType? periodType); Task<List<WorkGridScheduleResponse>> GetListAsync(Guid workGridCode, DateOnly date, WorkGridTimePeriodEnumType? periodType);
/// <summary>
/// 获取指定网格和日期范围的排班汇总列表
/// </summary>
/// <param name="workGridCode">网格编码</param>
/// <param name="start">开始日期</param>
/// <param name="end">结束日期</param>
/// <returns>排班汇总列表</returns>
Task<IEnumerable<WorkGridScheduleSummaryResponse>> GetListSummaryAsync(Guid workGridCode, DateOnly start, DateOnly end); Task<IEnumerable<WorkGridScheduleSummaryResponse>> GetListSummaryAsync(Guid workGridCode, DateOnly start, DateOnly end);
/// <summary>
/// 获取排班考勤分页数据
/// </summary>
/// <param name="request">考勤分页请求参数</param>
/// <returns>排班考勤分页数据</returns>
Task<Pagination<WorkGridScheduleAttendancePageResponse>> GetAttendancePageAsync(WorkGridScheduleAttendancePageRequest request); Task<Pagination<WorkGridScheduleAttendancePageResponse>> GetAttendancePageAsync(WorkGridScheduleAttendancePageRequest request);
/// <summary>
/// 获取所有排班考勤分页数据
/// </summary>
/// <param name="request">考勤分页请求参数</param>
/// <returns>排班考勤分页数据</returns>
Task<Pagination<WorkGridScheduleAttendancePageResponse>> GetAllAttendancePageAsync(WorkGridScheduleAttendancePageRequest request); Task<Pagination<WorkGridScheduleAttendancePageResponse>> GetAllAttendancePageAsync(WorkGridScheduleAttendancePageRequest request);
/// <summary>
/// 手动上传考勤日志
/// </summary>
/// <param name="logIds">考勤日志ID列表</param>
Task ManuallyUploadAsync(List<long> logIds); Task ManuallyUploadAsync(List<long> logIds);
Task<List<WorkGridScheduleMaximumConsecutiveDto>> MaximumConsecutiveUserCodesAsync(List<string> userCodes, int days, DateOnly date); /// <summary>
/// 测试接口
/// </summary>
/// <param name="request">排班保存请求参数</param>
/// <returns>测试结果</returns>
Task<object> TestAsync(WorkGridScheduleSaveRequest request); Task<object> TestAsync(WorkGridScheduleSaveRequest request);
} }

View File

@@ -1,5 +1,7 @@
using Dlhis.Basic.Common.ApiLog.Services; using Dlhis.Basic.Common.ApiLog.Services;
using Dlhis.Basic.Common.Message; using Dlhis.Basic.Common.Message.Requests;
using Dlhis.Basic.Common.Message.Services;
using Dlhis.Basic.WorkGrids.Repositories;
using Dlhis.Basic.WorkGrids.Request; using Dlhis.Basic.WorkGrids.Request;
using Dlhis.Basic.WorkGrids.Response; using Dlhis.Basic.WorkGrids.Response;
using Dlhis.Constants; using Dlhis.Constants;
@@ -27,6 +29,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
private readonly IOperateLog _operateLog; private readonly IOperateLog _operateLog;
private readonly ILogger<WorkGridScheduleService> _logger; private readonly ILogger<WorkGridScheduleService> _logger;
private readonly IJinkoApiService _jinkoApiService; private readonly IJinkoApiService _jinkoApiService;
private readonly IWorkGridScheduleRepository _workGridScheduleRepository;
private readonly ICurrentUser _currentUser; private readonly ICurrentUser _currentUser;
public WorkGridScheduleService(IDbContext dbContext, public WorkGridScheduleService(IDbContext dbContext,
@@ -34,6 +37,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
IOperateLog operateLog, IOperateLog operateLog,
ILogger<WorkGridScheduleService> logger, ILogger<WorkGridScheduleService> logger,
IJinkoApiService jinkoApiService, IJinkoApiService jinkoApiService,
IWorkGridScheduleRepository workGridScheduleRepository,
ICurrentUser currentUser) ICurrentUser currentUser)
{ {
_dbContext = dbContext; _dbContext = dbContext;
@@ -41,6 +45,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
_operateLog = operateLog; _operateLog = operateLog;
_logger = logger; _logger = logger;
_jinkoApiService = jinkoApiService; _jinkoApiService = jinkoApiService;
_workGridScheduleRepository = workGridScheduleRepository;
_currentUser = currentUser; _currentUser = currentUser;
} }
@@ -61,7 +66,11 @@ public class WorkGridScheduleService : IWorkGridScheduleService
.SingleAsync(); .SingleAsync();
workGrid.ThrowIfNull("工作网格不存在"); workGrid.ThrowIfNull("工作网格不存在");
var timeSetting = await _dbContext.Queryable<WorkGridTimePeriodEntity>().Where(x => x.Type == request.PeriodType).Select(x => new { x.Start, x.Before }).SingleAsync(); var timeSetting = await _dbContext.Queryable<WorkGridTimePeriodEntity>()
.Where(x => x.Type == request.PeriodType)
.Select(x => new { x.Start, x.Before })
.SingleAsync();
timeSetting.ThrowIfNull("工作网格时间尚未配置,无法操作"); timeSetting.ThrowIfNull("工作网格时间尚未配置,无法操作");
var currentLimit = request.Date.ToDateTime(timeSetting.Start.Add(-TimeSpan.FromHours(1))); var currentLimit = request.Date.ToDateTime(timeSetting.Start.Add(-TimeSpan.FromHours(1)));
@@ -103,8 +112,8 @@ public class WorkGridScheduleService : IWorkGridScheduleService
existsUserCodes.ThrowIfExists(existsUserCodes.Join(",") + $"在{dateAfter.ToString("yyyy-MM-dd")}已存在{WorkGridTimePeriodEnumType.Day.GetDescription()}"); existsUserCodes.ThrowIfExists(existsUserCodes.Join(",") + $"在{dateAfter.ToString("yyyy-MM-dd")}已存在{WorkGridTimePeriodEnumType.Day.GetDescription()}");
} }
var maximumConsecutiveDtos = await MaximumConsecutiveUserCodesAsync(request.UserCodes, workGrid.MaxConsecutiveLimitCount, request.Date); var maximumConsecutiveListDto = await _workGridScheduleRepository.MaximumConsecutiveUserCodesAsync(request.UserCodes, workGrid.MaxConsecutiveLimitCount, request.Date);
maximumConsecutiveDtos.ThrowIfExists(maximumConsecutiveDtos.Select(x => $"{x.UserCode}已经连续排班{workGrid.MaxConsecutiveLimitCount}天({x.Start}-{x.End}),禁止排班").Join("\r\n")); maximumConsecutiveListDto.ThrowIfExists(maximumConsecutiveListDto.Select(x => $"{x.UserCode}已经连续排班{workGrid.MaxConsecutiveLimitCount}天({x.Start}-{x.End}),禁止排班").Join("\r\n"));
var toInserts = request.UserCodes.Select(x => new WorkGridScheduleEntity var toInserts = request.UserCodes.Select(x => new WorkGridScheduleEntity
{ {
@@ -120,12 +129,15 @@ public class WorkGridScheduleService : IWorkGridScheduleService
try try
{ {
var gainfos = await _dbContext.Queryable<GainfoEntity>().Where(x => request.UserCodes.Contains(x.Code)).Select(x => new { x.Code, x.Name }).ToListAsync(); var codeAndNameList = await _dbContext.Queryable<GainfoEntity>().Where(x => request.UserCodes.Contains(x.Code))
foreach (var gainfo in gainfos) .Select(x => new { x.Code, x.Name })
.ToListAsync();
foreach (var gainfo in codeAndNameList)
{ {
try try
{ {
await _jinkoApiService.SendWorkMessageAsync(new JinkoSendWorkMessageRequest await _jinkoApiService.SendWorkMessageAsync(new DingTalkWorkMessageRequest
{ {
Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})安排了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},请按时上班", Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})安排了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},请按时上班",
WorkCodes = new List<string> { gainfo.Code } WorkCodes = new List<string> { gainfo.Code }
@@ -210,7 +222,7 @@ public class WorkGridScheduleService : IWorkGridScheduleService
{ {
try try
{ {
await _jinkoApiService.SendWorkMessageAsync(new JinkoSendWorkMessageRequest await _jinkoApiService.SendWorkMessageAsync(new DingTalkWorkMessageRequest
{ {
Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})删除了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},如有疑问,请联系网格长!", Content = $"{gainfo.Name}({gainfo.Code})你好,系统检测到你被{workGrid.Name}网格的网格长{workGrid.LeaderUserName}({workGrid.LeaderUserCode})删除了{request.Date.ToString("yyyy年MM月dd日")}{request.PeriodType.GetDescription()},如有疑问,请联系网格长!",
WorkCodes = new List<string> { gainfo.Code } WorkCodes = new List<string> { gainfo.Code }
@@ -432,44 +444,4 @@ public class WorkGridScheduleService : IWorkGridScheduleService
} }
} }
} }
public async Task<List<WorkGridScheduleMaximumConsecutiveDto>> MaximumConsecutiveUserCodesAsync(List<string> userCodes, int days, DateOnly date)
{
var p = userCodes.Select(x => $"@param{x.Replace("-", "A_")}").Join(",");
var values = userCodes.ToDictionary(x => $"param{x.Replace("-", "A_")}", x => x);
values.Add("dateBefore", date.AddDays(-1).ToString("yyyy-MM-dd"));
values.Add("dateAfter", date.AddDays(1).ToString("yyyy-MM-dd"));
values.Add("days", days.ToString());
var sql = $@"
WITH ranked_dates AS (SELECT UserCode,
date,
ROW_NUMBER() OVER (PARTITION BY UserCode ORDER BY date) AS rn
FROM WorkGridSchedules where IsDeleted = 0 and UserCode in ({p})
GROUP BY UserCode, date),
grouped AS (SELECT UserCode,
date,
DATE_SUB(date, INTERVAL rn DAY) AS grp
FROM ranked_dates),
streaks AS (SELECT UserCode,
grp,
COUNT(*) AS streak_days,
MIN(date) AS start_date,
MAX(date) AS end_date
FROM grouped
GROUP BY UserCode, grp
HAVING streak_days >= @days)
SELECT UserCode, streak_days as Count, start_date as Start, end_date as End
FROM streaks
where (@dateBefore >= start_date
and @dateBefore <= end_date)
or (@dateAfter >= start_date
and @dateAfter <= end_date);
";
var data = await _dbContext.Client.Ado.SqlQueryAsync<WorkGridScheduleMaximumConsecutiveDto>(sql, values);
return data;
}
} }

View File

@@ -1,6 +1,8 @@
using Dlhis.Basic.Common.ApiLog.Services; using Dlhis.Basic.Common.ApiLog.Services;
using Dlhis.Basic.WorkGrids.Repositories;
using Dlhis.Basic.WorkGrids.Request; using Dlhis.Basic.WorkGrids.Request;
using Dlhis.Basic.WorkGrids.Response; using Dlhis.Basic.WorkGrids.Response;
using Dlhis.Basic.WorkGrids.Validations;
using Dlhis.Constants; using Dlhis.Constants;
using Dlhis.Entity.Basic.Entity; using Dlhis.Entity.Basic.Entity;
using Dlhis.Entity.Basic.Enums; using Dlhis.Entity.Basic.Enums;
@@ -19,17 +21,20 @@ public class WorkGridService : IWorkGridService
{ {
private readonly IDbContext _dbContext; private readonly IDbContext _dbContext;
private readonly ICurrentUser _currentUser; private readonly ICurrentUser _currentUser;
private readonly IWorkGridScheduleService _workGridScheduleService; private readonly IWorkGridValidateService _workGridValidateService;
private readonly IWorkGridScheduleRepository _workGridScheduleRepository;
private readonly IOperateLog _operateLog; private readonly IOperateLog _operateLog;
public WorkGridService(IDbContext dbContext, public WorkGridService(IDbContext dbContext,
ICurrentUser currentUser, ICurrentUser currentUser,
IWorkGridScheduleService workGridScheduleService, IWorkGridValidateService workGridValidateService,
IWorkGridScheduleRepository workGridScheduleRepository,
IOperateLog operateLog) IOperateLog operateLog)
{ {
_dbContext = dbContext; _dbContext = dbContext;
_currentUser = currentUser; _currentUser = currentUser;
_workGridScheduleService = workGridScheduleService; _workGridValidateService = workGridValidateService;
_workGridScheduleRepository = workGridScheduleRepository;
_operateLog = operateLog; _operateLog = operateLog;
} }
@@ -38,7 +43,7 @@ public class WorkGridService : IWorkGridService
{ {
var factory = _currentUser.GetStringTenantId(); var factory = _currentUser.GetStringTenantId();
var r = await _dbContext.Queryable<GainfoEntity>() var pagination = await _dbContext.Queryable<GainfoEntity>()
.LeftJoin<DepartmentEntity>((x, dept) => x.DepartmentNo == dept.No) .LeftJoin<DepartmentEntity>((x, dept) => x.DepartmentNo == dept.No)
.LeftJoin<WorkGridUserEntity>((x, dept, wgu) => x.Code == wgu.UserCode) .LeftJoin<WorkGridUserEntity>((x, dept, wgu) => x.Code == wgu.UserCode)
.LeftJoin<WorkGridEntity>((x, dept, wgu, wg) => wgu.WorkGridCode == wg.Code) .LeftJoin<WorkGridEntity>((x, dept, wgu, wg) => wgu.WorkGridCode == wg.Code)
@@ -59,50 +64,29 @@ public class WorkGridService : IWorkGridService
}) })
.ToPageListAsync(request); .ToPageListAsync(request);
var userCodes = r.Data.Select(x => x.Code).ToList(); var userCodeList = pagination.Data.Select(x => x.Code).ToList();
if (userCodes.Any()) if (userCodeList.Any())
{ {
var maximumConsecutiveUserCodes = await _workGridScheduleService.MaximumConsecutiveUserCodesAsync(userCodes, 1, DateOnly.FromDateTime(request.Date)); var maximumConsecutiveUserCodeList = await _workGridScheduleRepository.MaximumConsecutiveUserCodesAsync(userCodeList, 1, DateOnly.FromDateTime(request.Date));
foreach (var item in r.Data) foreach (var item in pagination.Data)
{ {
item.MaximumConsecutiveSchedules = maximumConsecutiveUserCodes.FirstOrDefault(x => x.UserCode == item.Code); item.MaximumConsecutiveSchedules = maximumConsecutiveUserCodeList.FirstOrDefault(x => x.UserCode == item.Code);
} }
} }
return r; return pagination;
} }
/// <inheritdoc />
public async Task SaveAsync(List<WorkGridSaveRequest> requests) public async Task SaveAsync(List<WorkGridSaveRequest> requests)
{ {
var factory = _currentUser.GetStringTenantId(); await _workGridValidateService.ValidateSaveAsync(requests);
var insertGrids = new List<string>(); var insertGrids = new List<string>();
var updateGrids = new List<string>(); var updateGrids = new List<string>();
var leaderUserCodes = requests.Select(x => x.LeaderUserCode).Distinct().ToList();
var existsUserInfos = await _dbContext.Queryable<GainfoEntity>()
.Where(x => leaderUserCodes.Contains(x.Code))
.Select(x => new { x.Code, x.Factory })
.ToListAsync();
var excludeCodes = existsUserInfos.Where(x => x.Factory != factory).Select(x => x.Code).ToList();
excludeCodes.ThrowIfExists($"工号:{excludeCodes.Join(",")}不属于当前厂区");
var existsUserCodes = existsUserInfos.Select(x => x.Code).ToList();
var notExistsUserCodes = leaderUserCodes.Except(existsUserCodes).ToList();
notExistsUserCodes.ThrowIfExists($"工号:{notExistsUserCodes.Join(",")}不存在");
foreach (var request in requests) foreach (var request in requests)
{ {
if (await _dbContext.Queryable<WorkGridEntity>().Where(x => x.Name == request.Name)
.WhereIF(request.Id.HasValue, x => x.Id != request.Id)
.AnyAsync())
{
true.ThrowIfTrue($"网格区域名称[{request.Name}]重复");
}
if (!request.Id.HasValue) if (!request.Id.HasValue)
{ {
var exists = await _dbContext.Queryable<WorkGridEntity>() var exists = await _dbContext.Queryable<WorkGridEntity>()
@@ -145,7 +129,6 @@ public class WorkGridService : IWorkGridService
await _operateLog.LogAsync(OperateLogType.WorkGrid, "修改网格:" + updateGrids.Join("\r\n")); await _operateLog.LogAsync(OperateLogType.WorkGrid, "修改网格:" + updateGrids.Join("\r\n"));
} }
/// <inheritdoc />
public async Task<Pagination<WorkGridPageResponse>> GetPageAsync(WorkGridPageRequest request) public async Task<Pagination<WorkGridPageResponse>> GetPageAsync(WorkGridPageRequest request)
{ {
var role = _currentUser.GetRole(); var role = _currentUser.GetRole();
@@ -190,7 +173,6 @@ public class WorkGridService : IWorkGridService
.ToPageListAsync(request); .ToPageListAsync(request);
} }
/// <inheritdoc />
public async Task ChangeAsync(string from, string to) public async Task ChangeAsync(string from, string to)
{ {
if (await _dbContext.Queryable<WorkGridEntity>().Where(x => x.LeaderUserCode == to).AnyAsync()) if (await _dbContext.Queryable<WorkGridEntity>().Where(x => x.LeaderUserCode == to).AnyAsync())
@@ -216,7 +198,6 @@ public class WorkGridService : IWorkGridService
await _operateLog.LogAsync(OperateLogType.WorkGrid, $"网格({workGrid.Name})修改负责人{from}->{to}"); await _operateLog.LogAsync(OperateLogType.WorkGrid, $"网格({workGrid.Name})修改负责人{from}->{to}");
} }
/// <inheritdoc />
public async Task<WorkGridUserPageResponse> GetMyWorkGridAsync(WorkGridPageRequest request) public async Task<WorkGridUserPageResponse> GetMyWorkGridAsync(WorkGridPageRequest request)
{ {
var currentUserCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode); var currentUserCode = _currentUser.GetUserClaim(UserClaimConstants.JinkoCode);
@@ -253,11 +234,11 @@ public class WorkGridService : IWorkGridService
var userCodes = myWorkGrid.UserInfos.Select(x => x.Code).ToList(); var userCodes = myWorkGrid.UserInfos.Select(x => x.Code).ToList();
if (userCodes.Any()) if (userCodes.Any())
{ {
var maximumConsecutiveUserCodes = await _workGridScheduleService.MaximumConsecutiveUserCodesAsync(userCodes, 1, DateOnly.FromDateTime(request.Date)); var maximumConsecutiveUserCodeList = await _workGridScheduleRepository.MaximumConsecutiveUserCodesAsync(userCodes, 1, DateOnly.FromDateTime(request.Date));
foreach (var item in myWorkGrid.UserInfos) foreach (var item in myWorkGrid.UserInfos)
{ {
item.MaximumConsecutiveSchedules = maximumConsecutiveUserCodes.FirstOrDefault(x => x.UserCode == item.Code); item.MaximumConsecutiveSchedules = maximumConsecutiveUserCodeList.FirstOrDefault(x => x.UserCode == item.Code);
} }
} }
} }
@@ -265,7 +246,6 @@ public class WorkGridService : IWorkGridService
return myWorkGrid; return myWorkGrid;
} }
/// <inheritdoc />
public async Task AssignAsync(WorkGridUserAssignRequest request) public async Task AssignAsync(WorkGridUserAssignRequest request)
{ {
var currentFactory = _currentUser.GetStringTenantId(); var currentFactory = _currentUser.GetStringTenantId();

View File

@@ -0,0 +1,8 @@
using Dlhis.Basic.WorkGrids.Request;
namespace Dlhis.Basic.WorkGrids.Validations;
public interface IWorkGridValidateService : IScopeDependency
{
Task ValidateSaveAsync(List<WorkGridSaveRequest> requests);
}

View File

@@ -0,0 +1,74 @@
using Dlhis.Basic.WorkGrids.Request;
using Dlhis.Entity.Basic.Entity;
using Kurisu.AspNetCore.Authentication.Abstractions;
using Kurisu.AspNetCore.DataAccess.SqlSugar.Services;
using Kurisu.AspNetCore.Utils.Extensions;
namespace Dlhis.Basic.WorkGrids.Validations.Implements
{
public class WorkGridValidateService : IWorkGridValidateService
{
private readonly ICurrentUser _currentUser;
private readonly IDbContext _dbContext;
public WorkGridValidateService(ICurrentUser currentUser, IDbContext dbContext)
{
_currentUser = currentUser;
_dbContext = dbContext;
}
/// <summary>
/// 验证保存请求
/// </summary>
/// <param name="requests"></param>
public async Task ValidateSaveAsync(List<WorkGridSaveRequest> requests)
{
var duplicateUserCodes = requests.GroupBy(x => x.LeaderUserCode)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
duplicateUserCodes.ThrowIfExists($"请求中存在重复工号:{duplicateUserCodes.Join(",")}");
var duplicateNames = requests.GroupBy(x => x.Name)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
duplicateNames.ThrowIfExists($"请求中存在重复网格名称:{duplicateNames.Join(",")}");
var factory = _currentUser.GetStringTenantId();
var leaderUserCodes = requests.Select(x => x.LeaderUserCode).Distinct().ToList();
var userCodeWithFactories = await _dbContext.Queryable<GainfoEntity>()
.Where(x => leaderUserCodes.Contains(x.Code))
.Select(x => new { x.Code, x.Factory })
.ToListAsync();
//检查工号是否存在
var existsUserCodes = userCodeWithFactories.Select(x => x.Code).ToList();
var notExistsUserCodes = leaderUserCodes.Except(existsUserCodes).ToList();
notExistsUserCodes.ThrowIfExists($"工号:{notExistsUserCodes.Join(",")}不存在");
//检查负责人工号是否存在
var excludeCodes = userCodeWithFactories
.Where(x => x.Factory != factory)
.Select(x => x.Code)
.ToList();
excludeCodes.ThrowIfExists($"工号:{excludeCodes.Join(",")}不属于当前厂区");
//检查网格名称是否重复
var where = LinqExpressionExtensions.False<WorkGridEntity>();
foreach (var req in requests)
{
where = req.Id.HasValue
? where.Or(x => x.Name == req.Name && x.Id != req.Id.Value)
: where.Or(x => x.Name == req.Name);
}
var existsNames = await _dbContext.Queryable<WorkGridEntity>().Where(where).Select(x => x.Name).ToListAsync();
if (existsNames.Any())
{
true.ThrowIfTrue($"网格区域名称[{existsNames.Join(",")}]重复");
}
}
}
}

View File

@@ -27,7 +27,7 @@
}, },
"SwaggerOptions": { "SwaggerOptions": {
"Enable": true, "Enable": true,
"Authority": "http://localhost:5000", "Authority": "https://park.yaens.com/oauth2",
"ClientId": "98958aa485d38412", "ClientId": "98958aa485d38412",
"ClientSecret": "52589e011f02fe19", "ClientSecret": "52589e011f02fe19",
"Scopes": { "Scopes": {
@@ -37,7 +37,7 @@
} }
}, },
"IdentityServerOptions": { "IdentityServerOptions": {
"Authority": "http://localhost:5000", "Authority": "https://park.yaens.com/oauth2",
"RequireHttpsMetadata": false, "RequireHttpsMetadata": false,
"Issuer": "identity.isawesome.cn", "Issuer": "identity.isawesome.cn",
"Audience": "", "Audience": "",

View File

@@ -34,9 +34,9 @@
}, },
"SwaggerOptions": { "SwaggerOptions": {
"Enable": true, "Enable": true,
"Authority": "http://identity.oauth.svc.cluster.local", "Authority": "https://192.168.199.124/oauth2",
"ClientId": "4fb184324eac4180", "ClientId": "98958aa485d38412",
"ClientSecret": "8ac8f235152f1524", "ClientSecret": "52589e011f02fe19",
"Scopes": { "Scopes": {
"openid": "openid", "openid": "openid",
"profile": "profile", "profile": "profile",
@@ -47,10 +47,10 @@
"ConnectionString": "192.168.199.124:6379,defaultDatabase=1,password=dlhis123" "ConnectionString": "192.168.199.124:6379,defaultDatabase=1,password=dlhis123"
}, },
"IdentityServerOptions": { "IdentityServerOptions": {
"Authority": "http://identity.oauth.svc.cluster.local", "Authority": "https://192.168.199.124/oauth2",
"RequireHttpsMetadata": false, "RequireHttpsMetadata": false,
"Issuer": "identity.isawesome.cn", "Issuer": "identity.isawesome.cn",
"Audience": "", "Audience": "yikatong",
"Pat": { "Pat": {
"Enable": false, "Enable": false,
"Scheme": "token", "Scheme": "token",
@@ -60,8 +60,8 @@
}, },
"MinIO": { "MinIO": {
"Endpoint": "http://192.168.199.124:9000", "Endpoint": "http://192.168.199.124:9000",
"AccessKey": "bmQOlK0COe5nL56kzGd3", "AccessKey": "7z9Aeat9givpNbnAt36T",
"SecretKey": "Udc5uBrGcT2yukfGXQtHKpqLQ27L1FmbrLyYunBr", "SecretKey": "tW3WqS1wQZMbIrXKZokyxfF0CDL4vqrthTUNVMdB",
"DefaultBucket": "apk" "DefaultBucket": "apk"
}, },
"Serilog": { "Serilog": {
@@ -75,24 +75,17 @@
}, },
"WriteTo": [ "WriteTo": [
{ {
"Name": "Async", "Name": "Console",
"Args": { "Args": {
"configure": [ "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}"
{ }
"Name": "Console", },
"Args": { {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message:lj}{NewLine}{Exception}" "Name": "MySQL",
} "Args": {
}, "connectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=log;charset=utf8mb4;",
{ "tableName": "Logs",
"Name": "MySQL", "autoCreateSqlTable": true
"Args": {
"connectionString": "server=192.168.199.124;port=3306;userid=root;password=dlhis123;database=log;charset=utf8mb4;",
"tableName": "Logs",
"autoCreateSqlTable": true
}
}
]
} }
} }
] ]