From ad3bd10d65abeb0af09bb80b10947b47295448c6 Mon Sep 17 00:00:00 2001 From: ruisu Date: Mon, 24 Aug 2026 17:59:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B9=B3=E4=BB=93=E9=A3=8E?= =?UTF-8?q?=E6=8E=A7=E4=BA=8C=E6=AC=A1=E7=A1=AE=E8=AE=A4=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/RiskEngine/RiskTrialService.cs | 33 +++++++++++++------ YLErpWeb/Controllers/SwapTrade2Controller.cs | 29 ++++++++++++---- .../Scripts/app/swaptrade/unwindSwapTrade.js | 9 +++-- 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/YLErpDAL/Modules/RiskEngine/RiskTrialService.cs b/YLErpDAL/Modules/RiskEngine/RiskTrialService.cs index ccabf681..fc421953 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskTrialService.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskTrialService.cs @@ -45,11 +45,11 @@ namespace YLErp.Modules.RiskEngine throw new ArgumentException("风控触发时点不能为空", nameof(context)); } - var confirmedRuleIds = new HashSet(); + var ignoreRiskRuleIds = new HashSet(); var confirmationExpired = false; if (confirmation != null) { - confirmationExpired = !TryGetConfirmedRuleIds(context, trialSource, confirmation, confirmedRuleIds); + confirmationExpired = !TryLoadIgnoreRiskRuleIds(context, trialSource, confirmation, ignoreRiskRuleIds); } var riskResult = new RiskEngineService(this).EvaluateRisk(context, context.TriggerPoint); @@ -63,10 +63,10 @@ namespace YLErp.Modules.RiskEngine // 二次提交时,若首次试算记录有效,则剔除已确认过的审批和提示规则;记录过期或上下文不匹配时重新展示全部当前命中的审批和提示规则。 var pendingApprovalRules = confirmationExpired ? currentApprovalRules - : currentApprovalRules.Where(rule => !confirmedRuleIds.Contains(rule.RuleId)).ToList(); + : currentApprovalRules.Where(rule => !ignoreRiskRuleIds.Contains(rule.RuleId)).ToList(); var pendingTipRules = confirmationExpired ? currentTipRules - : currentTipRules.Where(rule => !confirmedRuleIds.Contains(rule.RuleId)).ToList(); + : currentTipRules.Where(rule => !ignoreRiskRuleIds.Contains(rule.RuleId)).ToList(); var trial = CreateQuotaTrial(context, trialSource, riskResult, pendingApprovalRules, pendingTipRules); // 目前复用 quotaTrial 承载风控试算结果,兼容交易确认、平仓等现有详情页和二次确认流程;后续若表语义收敛,再考虑统一重命名为风控试算。 new Modules.RiskModule.QuotaMonitorService(this).SaveQuotaTrial(trial); @@ -94,7 +94,7 @@ namespace YLErp.Modules.RiskEngine /// /// 校验二次确认记录,并恢复首次试算中已确认的审批和提示规则ID。 /// - private bool TryGetConfirmedRuleIds(RiskContext context, int trialSource, RiskTrialConfirmation confirmation, ISet confirmedRuleIds) + private bool TryLoadIgnoreRiskRuleIds(RiskContext context, int trialSource, RiskTrialConfirmation confirmation, ISet ignoreRiskRuleIds) { if (confirmation.TrialDataId <= 0 || confirmation.ExpireSeconds <= 0) { @@ -115,11 +115,11 @@ namespace YLErp.Modules.RiskEngine return false; } - foreach (var ruleId in ParseConfirmedRuleIds(trial.RiskWarningDetails)) + foreach (var ruleId in GetIgnoreRiskRuleIds(confirmation, trial.RiskWarningDetails)) { - confirmedRuleIds.Add(ruleId); + ignoreRiskRuleIds.Add(ruleId); } - return confirmedRuleIds.Count > 0; + return true; } /// @@ -133,10 +133,18 @@ namespace YLErp.Modules.RiskEngine .Any(line => string.Equals(line, expectedContext, StringComparison.Ordinal)); } + private static IEnumerable GetIgnoreRiskRuleIds(RiskTrialConfirmation confirmation, string details) + { + var ignoreRiskRuleIds = confirmation.IgnoreRiskRuleIds ?? new List(); + return ignoreRiskRuleIds.Any() + ? ignoreRiskRuleIds.Where(ruleId => !string.IsNullOrWhiteSpace(ruleId)).Select(ruleId => ruleId.Trim()).Distinct() + : ParseIgnoreRiskRuleIds(details); + } + /// - /// 从系统生成的审批和提示规则明细中恢复规则ID,避免直接信任前端提交的放行规则列表。 + /// 从系统生成的审批和提示规则明细中恢复规则ID,兼容未回传忽略规则ID的旧入口。 /// - private static IEnumerable ParseConfirmedRuleIds(string details) + private static IEnumerable ParseIgnoreRiskRuleIds(string details) { const string ruleIdPrefix = "规则ID:"; var inConfirmableSection = false; @@ -270,6 +278,11 @@ namespace YLErp.Modules.RiskEngine /// 首次试算允许确认放行的有效时长,单位为秒。 /// public int ExpireSeconds { get; set; } + + /// + /// 首次试算返回并经前端回传的需忽略规则ID。 + /// + public List IgnoreRiskRuleIds { get; set; } = new List(); } /// diff --git a/YLErpWeb/Controllers/SwapTrade2Controller.cs b/YLErpWeb/Controllers/SwapTrade2Controller.cs index 0307fff2..0816fb50 100644 --- a/YLErpWeb/Controllers/SwapTrade2Controller.cs +++ b/YLErpWeb/Controllers/SwapTrade2Controller.cs @@ -304,10 +304,11 @@ namespace YLErp.Web.Controllers /// /// 本次单标的平仓数据。 /// 首次新风控试算记录ID;二次确认时传入。 + /// 首次试算返回的需忽略规则ID;二次确认时传入。 /// 平仓结果或新风控确认信息。 - public JsonResult SwapUnwindJson(UnwindData unwindData, int? trialDataId = null) + public JsonResult SwapUnwindJson(UnwindData unwindData, int? trialDataId = null, string ignoreRiskRuleIds = null) { - var result = new SwapDealService(CurUser).SwapUnwind(unwindData, CreateRiskTrialConfirmation(trialDataId)); + var result = new SwapDealService(CurUser).SwapUnwind(unwindData, CreateRiskTrialConfirmation(trialDataId, ignoreRiskRuleIds)); return BuildCloseRiskResult(result, "平仓成功"); } /// @@ -346,10 +347,11 @@ namespace YLErp.Web.Controllers /// 本次互换或平仓数据。 /// 事件类型。 /// 首次新风控试算记录ID;平仓二次确认时传入。 + /// 首次试算返回的需忽略规则ID;二次确认时传入。 /// 提交结果或新风控确认信息。 - public JsonResult ApplyUnwind(UnwindData unwindData, int eventType, int? trialDataId = null) + public JsonResult ApplyUnwind(UnwindData unwindData, int eventType, int? trialDataId = null, string ignoreRiskRuleIds = null) { - var result = new SwapDealService(CurUser).ApplySwapTrade(unwindData, eventType, CreateRiskTrialConfirmation(trialDataId)); + var result = new SwapDealService(CurUser).ApplySwapTrade(unwindData, eventType, CreateRiskTrialConfirmation(trialDataId, ignoreRiskRuleIds)); return BuildCloseRiskResult(result, "提交成功"); } @@ -379,8 +381,9 @@ namespace YLErp.Web.Controllers /// 根据首次试算记录ID创建平仓新风控二次确认参数。 /// /// 首次新风控试算记录ID。 - /// 首次提交返回空,二次确认返回包含有效期的确认参数。 - private static RiskTrialConfirmation CreateRiskTrialConfirmation(int? trialDataId) + /// 首次试算返回的需忽略规则ID,多个ID使用逗号分隔。 + /// 首次提交返回空,二次确认返回包含有效期和需忽略规则ID的确认参数。 + private static RiskTrialConfirmation CreateRiskTrialConfirmation(int? trialDataId, string ignoreRiskRuleIds) { if (!trialDataId.HasValue) { @@ -398,10 +401,21 @@ namespace YLErp.Web.Controllers return new RiskTrialConfirmation { TrialDataId = trialDataId.Value, - ExpireSeconds = expireSeconds + ExpireSeconds = expireSeconds, + IgnoreRiskRuleIds = ParseIgnoreRiskRuleIds(ignoreRiskRuleIds) }; } + private static List ParseIgnoreRiskRuleIds(string ignoreRiskRuleIds) + { + return (ignoreRiskRuleIds ?? string.Empty) + .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(ruleId => ruleId.Trim()) + .Where(ruleId => !string.IsNullOrWhiteSpace(ruleId)) + .Distinct() + .ToList(); + } + /// /// 将平仓新风控结果转换为控制器统一JSON响应。 /// @@ -432,6 +446,7 @@ namespace YLErp.Web.Controllers source = "RiskWarning", type = "RiskWarningConfirm", result.TrialDataId, + ignoreRiskRuleIds = result.ApprovalRuleIds, message = result.ConfirmationExpired ? $"原风控确认已超时,请重新确认。{result.Message}" : result.Message }); } diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js index 20884c3a..bd93614e 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js @@ -371,11 +371,14 @@ const vue = new Vue({ postData.eventType = 2;//互换3,平仓2 } // 提交平仓并处理新风控阻断、二次确认和成功提示。 - var submitClose = function (trialDataId) { + var submitClose = function (trialDataId, ignoreRiskRuleIds) { var requestData = _.cloneDeep(postData); if (trialDataId) { requestData.trialDataId = trialDataId; } + if (ignoreRiskRuleIds && ignoreRiskRuleIds.length > 0) { + requestData.ignoreRiskRuleIds = ignoreRiskRuleIds.join(','); + } main.post(postUrl, requestData).done(function (res) { var riskData = res.obj; if (riskData && riskData.proccessType === "QuotaTrialError") { @@ -397,7 +400,7 @@ const vue = new Vue({ return; } if (res.success && riskData && riskData.proccessType === "AdditionalProcessing" && riskData.TrialDataId) { - // 审批类规则由用户填写说明并确认,二次提交仅回传后端生成的试算记录ID。 + // 审批类规则由用户填写说明并确认,二次提交回传试算记录ID和需忽略规则ID。 var riskTrialLayerIndex = layer.open({ type: 2, title: "风控试算详情", @@ -418,7 +421,7 @@ const vue = new Vue({ remark: trialPage.Data.Remark }).done(function () { layer.close(riskTrialLayerIndex); - submitClose(riskData.TrialDataId); + submitClose(riskData.TrialDataId, riskData.ignoreRiskRuleIds || []); }); } });