diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
index ad756d55..8359f712 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
@@ -16,6 +16,8 @@ namespace YLErp.DBModels
public string ConditionJson { get; set; }
/// 规则执行表达式(C# 布尔表达式,引擎用 Roslyn 编译执行)
public string RuleExpr { get; set; }
+ /// 规则说明
+ public string Description { get; set; }
/// 规则状态
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
/// 版本号(乐观锁)
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
index f6cefd70..89da2889 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
@@ -10,6 +10,8 @@ namespace YLErp.DBModels
{
/// 关联规则 ID 列表(JSON 数组)
public string RuleIds { get; set; }
+ /// 应用说明
+ public string Description { get; set; }
/// 应用配置状态
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
/// 风控策略(预警/阻断)
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
index d9642a21..448439e8 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
@@ -6,6 +6,7 @@ CREATE TABLE `glms_risk_rule` (
`RuleText` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则文本',
`ConditionJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '条件JSON(结构化模式, RuleCondition数组)',
`RuleExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '规则表达式(自由文本模式, 类C#表达式)',
+ `Description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
@@ -21,6 +22,7 @@ CREATE TABLE `glms_risk_rule` (
CREATE TABLE `glms_risk_rule_application` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
`RuleIds` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '关联规则Id列表(逗号分隔)',
+ `Description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
`ControlStrategy` tinyint NOT NULL COMMENT '控制策略: 1=Block, 2=Approval, 3=Warning',
`TriggerPoints` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '触发时点(逗号分隔)',
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
index 71914328..b426ea1c 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
@@ -9,6 +9,8 @@ namespace YLErp.Modules.RiskEngine.Dto
{
/// 关联规则 ID 列表(JSON 数组)
public string RuleIds { get; set; }
+ /// 应用说明
+ public string Description { get; set; }
/// 风控策略
public RiskControlStrategy ControlStrategy { get; set; }
/// 触发点列表(JSON 数组)
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskRuleReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskRuleReq.cs
index df27186d..280c3e17 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskRuleReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskRuleReq.cs
@@ -13,5 +13,7 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ConditionJson { get; set; }
/// 规则执行表达式
public string RuleExpr { get; set; }
+ /// 规则说明
+ public string Description { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
index 648a08b8..11d5cf7f 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
@@ -12,6 +12,8 @@ namespace YLErp.Modules.RiskEngine.Dto
public long Id { get; set; }
/// 关联规则 ID 列表(JSON 数组)
public string RuleIds { get; set; }
+ /// 应用说明
+ public string Description { get; set; }
/// 应用配置状态
public RiskRuleStatus Status { get; set; }
/// 风控策略
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
index fec34ea9..f50283ed 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
@@ -12,6 +12,8 @@ namespace YLErp.Modules.RiskEngine.Dto
public long Id { get; set; }
/// 关联规则 ID 列表(JSON 数组)
public string RuleIds { get; set; }
+ /// 应用说明
+ public string Description { get; set; }
/// 应用配置状态
public int Status { get; set; }
/// 风控策略
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleDetail.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleDetail.cs
index 09364933..cdb2e9ec 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleDetail.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleDetail.cs
@@ -19,6 +19,8 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ConditionJson { get; set; }
/// 规则执行表达式
public string RuleExpr { get; set; }
+ /// 规则说明
+ public string Description { get; set; }
/// 规则状态
public RiskRuleStatus Status { get; set; }
/// 版本号
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
index 32a462e2..b35999a2 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
@@ -18,6 +18,8 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ConditionJson { get; set; }
/// 规则执行表达式
public string RuleExpr { get; set; }
+ /// 规则说明
+ public string Description { get; set; }
/// 规则状态
public RiskRuleStatus Status { get; set; }
/// 版本号
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
index f152f276..877639d0 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
@@ -9,6 +9,8 @@ namespace YLErp.Modules.RiskEngine.Dto
{
/// 关联规则 ID 列表(JSON 数组)
public string RuleIds { get; set; }
+ /// 应用说明
+ public string Description { get; set; }
/// 风控策略
public RiskControlStrategy ControlStrategy { get; set; }
/// 触发点列表(JSON 数组)
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
index 9fa13d3c..0d19a313 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
@@ -13,6 +13,8 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ConditionJson { get; set; }
/// 规则执行表达式
public string RuleExpr { get; set; }
+ /// 规则说明
+ public string Description { get; set; }
/// 版本号(乐观锁)
public int Version { get; set; }
}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index b2162888..783a6bbc 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -1,10 +1,8 @@
using BaseOUDAL;
using Newtonsoft.Json;
-using Qdp.Foundation.Utilities;
using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.DBModels;
-using YLErp.Model;
using YLErp.Modules.RiskEngine.Dto;
/*
@@ -694,6 +692,7 @@ namespace YLErp.Modules.RiskEngine
RuleText = r.RuleText,
ConditionJson = r.ConditionJson,
RuleExpr = r.RuleExpr,
+ Description = r.Description,
Status = r.Status,
Version = r.Version,
OptName = r.OptName,
@@ -732,6 +731,7 @@ namespace YLErp.Modules.RiskEngine
RuleText = rule.RuleText,
ConditionJson = rule.ConditionJson,
RuleExpr = rule.RuleExpr,
+ Description = rule.Description,
Status = rule.Status,
Version = rule.Version,
OptName = rule.OptName,
@@ -749,12 +749,17 @@ namespace YLErp.Modules.RiskEngine
{
ValidateRuleParams(req.RuleName, req.ConditionJson, req.RuleExpr);
+ var compileResult = RuleCompiler.ValidateAndCompileFormula(null, req.RuleExpr);
+ if (!compileResult.Success)
+ throw new ServiceException($"规则表达式编译失败:{compileResult.ErrorMessage}");
+
var entity = new glms_risk_rule
{
RuleName = req.RuleName,
RuleText = req.RuleText,
ConditionJson = req.ConditionJson,
RuleExpr = req.RuleExpr,
+ Description = req.Description,
Status = RiskRuleStatus.Active,
Version = 1
};
@@ -784,7 +789,7 @@ namespace YLErp.Modules.RiskEngine
}
}
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshOneRuleCache(entity.id);
return GetRuleDetail(entity.id);
}
@@ -801,10 +806,15 @@ namespace YLErp.Modules.RiskEngine
ValidateRuleParams(req.RuleName, req.ConditionJson, req.RuleExpr);
+ var compileResult = RuleCompiler.ValidateAndCompileFormula(ruleId, req.RuleExpr);
+ if (!compileResult.Success)
+ throw new ServiceException($"规则表达式编译失败:{compileResult.ErrorMessage}");
+
rule.RuleName = req.RuleName;
rule.RuleText = req.RuleText;
rule.ConditionJson = req.ConditionJson;
rule.RuleExpr = req.RuleExpr;
+ rule.Description = req.Description;
rule.Version = rule.Version + 1;
rule.UpdateOptId = UserId;
rule.UpdateOptName = UserName;
@@ -813,7 +823,7 @@ namespace YLErp.Modules.RiskEngine
WriteAuditLog("RULE_UPDATE", "RULE", ruleId, req.RuleName, "修改规则");
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId);
return GetRuleDetail(ruleId);
}
@@ -1074,6 +1084,7 @@ namespace YLErp.Modules.RiskEngine
{
Id = a.id,
RuleIds = a.RuleIds,
+ Description = a.Description,
Status = (int)a.Status,
ControlStrategy = a.ControlStrategy,
TriggerPoints = a.TriggerPoints,
@@ -1107,6 +1118,7 @@ namespace YLErp.Modules.RiskEngine
{
Id = app.id,
RuleIds = app.RuleIds,
+ Description = app.Description,
Status = app.Status,
ControlStrategy = app.ControlStrategy,
TriggerPoints = app.TriggerPoints,
@@ -1135,6 +1147,7 @@ namespace YLErp.Modules.RiskEngine
var entity = new glms_risk_rule_application
{
RuleIds = req.RuleIds,
+ Description = req.Description,
Status = RiskRuleStatus.Active,
ControlStrategy = req.ControlStrategy,
TriggerPoints = req.TriggerPoints,
@@ -1172,7 +1185,7 @@ namespace YLErp.Modules.RiskEngine
}
}
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
return GetApplicationDetail(entity.id);
}
@@ -1203,6 +1216,7 @@ namespace YLErp.Modules.RiskEngine
if (!string.IsNullOrWhiteSpace(req.RuleIds))
app.RuleIds = req.RuleIds;
+ app.Description = req.Description;
app.ControlStrategy = req.ControlStrategy;
app.TriggerPoints = req.TriggerPoints;
app.ScopeAssetBookIds = req.ScopeAssetBookIds;
@@ -1219,7 +1233,7 @@ namespace YLErp.Modules.RiskEngine
$"修改应用配置:策略={GetStrategyName(req.ControlStrategy)}, 触发时点={MapTriggerPointsToChinese(req.TriggerPoints)}");
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
return GetApplicationDetail(applicationId);
}
@@ -1240,7 +1254,7 @@ namespace YLErp.Modules.RiskEngine
WriteAuditLog("APP_DELETE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "删除应用配置");
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
}
///
@@ -1262,7 +1276,7 @@ namespace YLErp.Modules.RiskEngine
WriteAuditLog("APP_ENABLE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "启用应用配置");
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
}
///
@@ -1282,7 +1296,7 @@ namespace YLErp.Modules.RiskEngine
WriteAuditLog("APP_DISABLE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "停用应用配置");
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
}
///
@@ -1313,7 +1327,7 @@ namespace YLErp.Modules.RiskEngine
}
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
return new BatchOperationResult
{
@@ -1346,7 +1360,7 @@ namespace YLErp.Modules.RiskEngine
}
DbContext.SaveChanges();
- TryRefreshCache();
+ RiskEngineService.GetInstance().RefreshApplication();
return new BatchOperationResult
{
@@ -1534,14 +1548,24 @@ namespace YLErp.Modules.RiskEngine
if (variableExprChanged)
{
+ // 编译校验:变量表达式变更后,需验证所有级联更新的规则表达式可编译
+ var affectedRules = DbContext.glms_risk_rule
+ .Where(r => r.RuleExpr != null && r.RuleExpr.Contains(oldVariableExpr))
+ .ToList();
+
+ var compileTasks = affectedRules.Select(r =>
+ Task.Run(() => RuleCompiler.ValidateAndCompileFormula(
+ r.id, r.RuleExpr.Replace(oldVariableExpr, req.VariableExpr)))
+ );
+ var compileResults = Task.WhenAll(compileTasks).GetAwaiter().GetResult();
+ var failed = compileResults.FirstOrDefault(r => !r.Success);
+ if (failed is not null)
+ throw new ServiceException($"变量表达式变更导致规则编译失败:{failed.ErrorMessage}");
+
using (var transaction = DbContext.Database.BeginTransaction())
{
try
{
- var affectedRules = DbContext.glms_risk_rule
- .Where(r => r.RuleExpr != null && r.RuleExpr.Contains(oldVariableExpr))
- .ToList();
-
foreach (var rule in affectedRules)
{
rule.RuleExpr = rule.RuleExpr.Replace(oldVariableExpr, req.VariableExpr);
@@ -1570,16 +1594,20 @@ namespace YLErp.Modules.RiskEngine
throw;
}
}
+
+ InvalidateVariableCache();
+ foreach (var rule in affectedRules)
+ {
+ RiskEngineService.GetInstance().RefreshOneRuleCache(rule.id);
+ }
}
else
{
WriteAuditLog("VAR_UPDATE", "VARIABLE", variableId, req.VariableName, $"修改变量:{variable.VariableName}");
DbContext.SaveChanges();
+ InvalidateVariableCache();
}
- InvalidateVariableCache();
- TryRefreshCache();
-
return GetVariableDetail(variableId);
}
@@ -1735,4 +1763,4 @@ namespace YLErp.Modules.RiskEngine
#endregion
}
-}
+}
\ No newline at end of file