mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-04-23 14:42:51 +08:00
fix: 🐛 version lock
[skip ci]
This commit is contained in:
parent
01058ba728
commit
4eecc0b4ce
1
.drone/workflows/README.md
Normal file
1
.drone/workflows/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
drone workflows
|
10
NetAdmin.sln
10
NetAdmin.sln
@ -3,6 +3,14 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
VisualStudioVersion = 17.0.31903.59
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".drone", ".drone", "{3E408077-E73E-45CE-A53A-EF5F9DAE4B46}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
README.md = .drone/workflows/README.md
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1129FE25-466B-4F4F-85FC-3752664245E1}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{1129FE25-466B-4F4F-85FC-3752664245E1}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{3C6F049E-3EE8-4D66-9AFF-E8A369032487}"
|
||||||
@ -55,6 +63,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{BB0B
|
|||||||
2.git.release.ps1 = scripts/2.git.release.ps1
|
2.git.release.ps1 = scripts/2.git.release.ps1
|
||||||
3.git.recreate.branch.ps1 = scripts/3.git.recreate.branch.ps1
|
3.git.recreate.branch.ps1 = scripts/3.git.recreate.branch.ps1
|
||||||
4.git.del.obsolete.tags.ps1 = scripts/4.git.del.obsolete.tags.ps1
|
4.git.del.obsolete.tags.ps1 = scripts/4.git.del.obsolete.tags.ps1
|
||||||
|
5.git.update.submodule.ps1 = scripts/5.git.update.submodule.ps1
|
||||||
clean.ln.csx = scripts/clean.ln.csx
|
clean.ln.csx = scripts/clean.ln.csx
|
||||||
code.clean.csx = scripts/code.clean.csx
|
code.clean.csx = scripts/code.clean.csx
|
||||||
code.clean.ps1 = scripts/code.clean.ps1
|
code.clean.ps1 = scripts/code.clean.ps1
|
||||||
@ -235,5 +244,6 @@ Global
|
|||||||
{932520DF-D312-415A-A128-1117F8221D68} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
|
{932520DF-D312-415A-A128-1117F8221D68} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
|
||||||
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
|
{C3DE6F6A-D1FC-4B8E-9033-980FBEBBD2BA} = {12AE5B4B-CB1A-498E-83B8-04E201E31D86}
|
||||||
{3C6F049E-3EE8-4D66-9AFF-E8A369032487} = {1129FE25-466B-4F4F-85FC-3752664245E1}
|
{3C6F049E-3EE8-4D66-9AFF-E8A369032487} = {1129FE25-466B-4F4F-85FC-3752664245E1}
|
||||||
|
{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1} = {3E408077-E73E-45CE-A53A-EF5F9DAE4B46}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
@ -45,6 +45,20 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
|
|||||||
"""
|
"""
|
||||||
);
|
);
|
||||||
|
|
||||||
|
content = Regex.Replace(
|
||||||
|
content,
|
||||||
|
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"workflows\", \"workflows\", \"{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}\"(?:.|\n)*?EndProject",
|
||||||
|
$$"""
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{BB5BB244-E7D2-4368-8C18-C1C0ED1E12D1}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
{{string.Join('\n',
|
||||||
|
Directory.GetFiles(@"../.drone/workflows", "*")
|
||||||
|
.Select(x=>$" {Path.GetFileName(x)} = .drone/workflows/{Path.GetFileName(x)}")
|
||||||
|
)}}
|
||||||
|
EndProject
|
||||||
|
"""
|
||||||
|
);
|
||||||
|
|
||||||
content = Regex.Replace(
|
content = Regex.Replace(
|
||||||
content,
|
content,
|
||||||
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"scripts\", \"scripts\", \"{BB0B25C9-0901-4923-913F-00F9A6B352A5}\"(?:.|\n)*?EndProject",
|
"Project\\(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\"\\) = \"scripts\", \"scripts\", \"{BB0B25C9-0901-4923-913F-00F9A6B352A5}\"(?:.|\n)*?EndProject",
|
||||||
|
@ -3,6 +3,7 @@ using Microsoft.Net.Http.Headers;
|
|||||||
using NetAdmin.Application.Repositories;
|
using NetAdmin.Application.Repositories;
|
||||||
using NetAdmin.Domain;
|
using NetAdmin.Domain;
|
||||||
using NetAdmin.Domain.DbMaps.Dependency;
|
using NetAdmin.Domain.DbMaps.Dependency;
|
||||||
|
using NetAdmin.Domain.DbMaps.Dependency.Fields;
|
||||||
using NetAdmin.Domain.Dto.Dependency;
|
using NetAdmin.Domain.Dto.Dependency;
|
||||||
|
|
||||||
namespace NetAdmin.Application.Services;
|
namespace NetAdmin.Application.Services;
|
||||||
@ -64,17 +65,19 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
/// <param name="excludeFields">排除的属性</param>
|
/// <param name="excludeFields">排除的属性</param>
|
||||||
/// <param name="whereExp">查询表达式</param>
|
/// <param name="whereExp">查询表达式</param>
|
||||||
/// <param name="whereSql">查询sql</param>
|
/// <param name="whereSql">查询sql</param>
|
||||||
|
/// <param name="ignoreVersion">是否忽略版本锁</param>
|
||||||
/// <returns>更新行数</returns>
|
/// <returns>更新行数</returns>
|
||||||
protected Task<int> UpdateAsync( //
|
protected Task<int> UpdateAsync( //
|
||||||
TEntity newValue //
|
TEntity newValue //
|
||||||
, IEnumerable<string> includeFields //
|
, List<string> includeFields = null //
|
||||||
, string[] excludeFields = null //
|
, List<string> excludeFields = null //
|
||||||
, Expression<Func<TEntity, bool>> whereExp = null //
|
, Expression<Func<TEntity, bool>> whereExp = null //
|
||||||
, string whereSql = null)
|
, string whereSql = null //
|
||||||
|
, bool ignoreVersion = false)
|
||||||
{
|
{
|
||||||
// 默认匹配主键
|
// 默认匹配主键
|
||||||
whereExp ??= a => a.Id.Equals(newValue.Id);
|
whereExp ??= a => a.Id.Equals(newValue.Id);
|
||||||
var update = BuildUpdate(newValue, includeFields, excludeFields).Where(whereExp).Where(whereSql);
|
var update = BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql);
|
||||||
return update.ExecuteAffrowsAsync();
|
return update.ExecuteAffrowsAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,17 +90,19 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
/// <param name="excludeFields">排除的属性</param>
|
/// <param name="excludeFields">排除的属性</param>
|
||||||
/// <param name="whereExp">查询表达式</param>
|
/// <param name="whereExp">查询表达式</param>
|
||||||
/// <param name="whereSql">查询sql</param>
|
/// <param name="whereSql">查询sql</param>
|
||||||
|
/// <param name="ignoreVersion">是否忽略版本锁</param>
|
||||||
/// <returns>更新后的实体列表</returns>
|
/// <returns>更新后的实体列表</returns>
|
||||||
protected Task<List<TEntity>> UpdateReturnListAsync( //
|
protected Task<List<TEntity>> UpdateReturnListAsync( //
|
||||||
TEntity newValue //
|
TEntity newValue //
|
||||||
, IEnumerable<string> includeFields //
|
, List<string> includeFields = null //
|
||||||
, string[] excludeFields = null //
|
, List<string> excludeFields = null //
|
||||||
, Expression<Func<TEntity, bool>> whereExp = null //
|
, Expression<Func<TEntity, bool>> whereExp = null //
|
||||||
, string whereSql = null)
|
, string whereSql = null //
|
||||||
|
, bool ignoreVersion = false)
|
||||||
{
|
{
|
||||||
// 默认匹配主键
|
// 默认匹配主键
|
||||||
whereExp ??= a => a.Id.Equals(newValue.Id);
|
whereExp ??= a => a.Id.Equals(newValue.Id);
|
||||||
return BuildUpdate(newValue, includeFields, excludeFields).Where(whereExp).Where(whereSql).ExecuteUpdatedAsync();
|
return BuildUpdate(newValue, includeFields, excludeFields, ignoreVersion).Where(whereExp).Where(whereSql).ExecuteUpdatedAsync();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -127,17 +132,22 @@ public abstract class RepositoryService<TEntity, TPrimary, TLogger>(BasicReposit
|
|||||||
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
|
return new FileStreamResult(stream, Chars.FLG_HTTP_HEADER_VALUE_APPLICATION_OCTET_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IUpdate<TEntity> BuildUpdate( //
|
private IUpdate<TEntity> BuildUpdate(TEntity entity, List<string> includeFields, List<string> excludeFields, bool ignoreVersion)
|
||||||
TEntity entity //
|
|
||||||
, IEnumerable<string> includeFields //
|
|
||||||
, string[] excludeFields = null)
|
|
||||||
{
|
{
|
||||||
var updateExp = includeFields == null
|
IUpdate<TEntity> updateExp;
|
||||||
? Rpo.UpdateDiy.SetSource(entity)
|
if (includeFields.NullOrEmpty()) {
|
||||||
: Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary(
|
updateExp = Rpo.UpdateDiy.SetSource(entity);
|
||||||
x => x, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!.GetValue(entity)));
|
if (!excludeFields.NullOrEmpty()) {
|
||||||
if (excludeFields != null) {
|
updateExp = updateExp.IgnoreColumns(excludeFields.ToArray());
|
||||||
updateExp = updateExp.IgnoreColumns(excludeFields);
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
updateExp = Rpo.UpdateDiy.SetDto(includeFields!.ToDictionary(
|
||||||
|
x => x
|
||||||
|
, x => typeof(TEntity).GetProperty(x, BindingFlags.Public | BindingFlags.Instance)!.GetValue(entity)));
|
||||||
|
if (!ignoreVersion && entity is IFieldVersion ver) {
|
||||||
|
updateExp = updateExp.Where($"{nameof(IFieldVersion.Version)} = {ver.Version}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updateExp;
|
return updateExp;
|
||||||
|
@ -277,13 +277,13 @@ public sealed class JobService(BasicRepository<Sys_Job, long> rpo, IJobRecordSer
|
|||||||
{
|
{
|
||||||
var ret1 = await UpdateAsync( // 运行中,运行时间超过超时设定;置为空闲状态
|
var ret1 = await UpdateAsync( // 运行中,运行时间超过超时设定;置为空闲状态
|
||||||
new Sys_Job { Status = JobStatues.Idle }, [nameof(Sys_Job.Status)], null
|
new Sys_Job { Status = JobStatues.Idle }, [nameof(Sys_Job.Status)], null
|
||||||
, a => a.Status == JobStatues.Running && a.LastExecTime < DateTime.Now.AddSeconds(-Numbers.SECS_TIMEOUT_JOB))
|
, a => a.Status == JobStatues.Running && a.LastExecTime < DateTime.Now.AddSeconds(-Numbers.SECS_TIMEOUT_JOB), null, true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var ret2 = await UpdateAsync( // 空闲中,下次执行时间在当前时间减去超时时间以前;将下次执行时间调整到现在
|
var ret2 = await UpdateAsync( // 空闲中,下次执行时间在当前时间减去超时时间以前;将下次执行时间调整到现在
|
||||||
new Sys_Job { NextExecTime = DateTime.Now, NextTimeId = DateTime.Now.TimeUnixUtc() }
|
new Sys_Job { NextExecTime = DateTime.Now, NextTimeId = DateTime.Now.TimeUnixUtc() }
|
||||||
, [nameof(Sys_Job.NextExecTime), nameof(Sys_Job.NextTimeId)], null
|
, [nameof(Sys_Job.NextExecTime), nameof(Sys_Job.NextTimeId)], null
|
||||||
, a => a.Status == JobStatues.Idle && a.NextExecTime < DateTime.Now.AddSeconds(-Numbers.SECS_TIMEOUT_JOB))
|
, a => a.Status == JobStatues.Idle && a.NextExecTime < DateTime.Now.AddSeconds(-Numbers.SECS_TIMEOUT_JOB), null, true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
return ret1 + ret2;
|
return ret1 + ret2;
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ public sealed class UserProfileService(BasicRepository<Sys_UserProfile, long> rp
|
|||||||
req.AppConfig = BuildAppConfig(App.GetService<ContextUserInfo>().Roles.ToDictionary(x => x.Id, x => x.DashboardLayout));
|
req.AppConfig = BuildAppConfig(App.GetService<ContextUserInfo>().Roles.ToDictionary(x => x.Id, x => x.DashboardLayout));
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateAsync(req, [nameof(req.AppConfig)], null, a => a.Id == UserToken.Id);
|
return UpdateAsync(req, [nameof(req.AppConfig)], null, a => a.Id == UserToken.Id, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternal(QueryReq<QueryUserProfileReq> req)
|
private ISelect<Sys_UserProfile, Sys_DicContent, Sys_DicContent, Sys_DicContent, Sys_DicContent> QueryInternal(QueryReq<QueryUserProfileReq> req)
|
||||||
|
@ -132,7 +132,7 @@ public sealed class UserService(
|
|||||||
ignoreCols.Add(nameof(Sys_User.Password));
|
ignoreCols.Add(nameof(Sys_User.Password));
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = await UpdateAsync(entity, null, ignoreCols.ToArray()).ConfigureAwait(false);
|
_ = await UpdateAsync(entity, null, ignoreCols).ConfigureAwait(false);
|
||||||
|
|
||||||
// 档案表
|
// 档案表
|
||||||
if (req.Profile != null) {
|
if (req.Profile != null) {
|
||||||
@ -453,7 +453,8 @@ public sealed class UserService(
|
|||||||
throw new NetAdminInvalidOperationException(Ln.请联系管理员激活账号);
|
throw new NetAdminInvalidOperationException(Ln.请联系管理员激活账号);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = await UpdateAsync(dbUser with { LastLoginTime = DateTime.Now }, [nameof(Sys_User.LastLoginTime)]).ConfigureAwait(false);
|
_ = await UpdateAsync(dbUser with { LastLoginTime = DateTime.Now }, [nameof(Sys_User.LastLoginTime)], ignoreVersion: true)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
var tokenPayload = new Dictionary<string, object> { { nameof(ContextUserToken), dbUser.Adapt<ContextUserToken>() } };
|
var tokenPayload = new Dictionary<string, object> { { nameof(ContextUserToken), dbUser.Adapt<ContextUserToken>() } };
|
||||||
|
|
||||||
|
@ -62,9 +62,9 @@ public static class ServiceCollectionExtensions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加定时任务
|
/// 添加定时任务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static IServiceCollection AddSchedules(this IServiceCollection me)
|
public static IServiceCollection AddSchedules(this IServiceCollection me, bool force = false)
|
||||||
{
|
{
|
||||||
return App.WebHostEnvironment.IsProduction()
|
return App.WebHostEnvironment.IsProduction() || force
|
||||||
? me.AddSchedule( //
|
? me.AddSchedule( //
|
||||||
builder => builder //
|
builder => builder //
|
||||||
.AddJob<ScheduledJob>(true, Triggers.PeriodSeconds(1).SetRunOnStart(true))
|
.AddJob<ScheduledJob>(true, Triggers.PeriodSeconds(1).SetRunOnStart(true))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user