更新版本

This commit is contained in:
GuoBaoGeng
2025-11-10 14:31:27 +08:00
parent 0a551b17a7
commit 724454f653
21 changed files with 1195 additions and 3519 deletions

View File

@@ -0,0 +1,65 @@
using BP.DA;
using BP.Difference;
using BP.En;
using BP.Sys;
using BP.Web;
using BP.WF;
using BP.WF.HttpHandler;
using BP.WF.Template;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using System;
using System.Collections;
using System.Data;
using System.Net.Http;
using System.Text;
using BP.WF.DTS;
using System.Security.Cryptography;
using BP.Tools;
using DocumentFormat.OpenXml.ExtendedProperties;
using NPOI.SS.Formula.Functions;
using BP.Port;
using System.Collections.Generic;
using BP.WF.CCFast.Third.GoView;
using NPOI.Util;
using NPOI.SS.Util;
using NPOI.HPSF;
using NetTaste;
using Microsoft.AspNetCore.Http;
using System.IO;
using System.Text.Json.Nodes;
using DocumentFormat.OpenXml.Drawing.Charts;
using static CCFlow.NetCore.DataUser.API.Controllers.APIController;
using DataTable = System.Data.DataTable;
using DocumentFormat.OpenXml.Office2016.Drawing.ChartDrawing;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
using BP.App.NetCore.GZSZ;
/**
* 广州审图
*/
namespace CCFlow.NetCore.DataUser.API.Controllers
{
[Route("WF/[controller]/[Action]")]
[ApiController]
public class GZSZController : ControllerBase
{
/**
* 修改历史数据
* @return
* @throws Exception
*/
[HttpGet, HttpPost]
public object UpdateHisData(int num)
{
GZ_CommTS gz = new GZ_CommTS();
gz.UpdateHisData(num);
return "修改成功";
}
}
}

View File

@@ -6,6 +6,7 @@ using System.Collections;
using System.Data;
using System;
using Microsoft.AspNetCore.Mvc;
using BP.WF;
namespace CCFlow.NetCore.DataUser.API.Controllers
{

View File

@@ -1,496 +0,0 @@
using BP.CCFast.Portal.WindowExt;
using BP.DA;
using BP.Difference;
using BP.En;
using BP.Port;
using BP.Star;
using BP.Web;
using BP.WF;
using BP.WF.Admin;
using BP.WF.Template;
using DocumentFormat.OpenXml.Spreadsheet;
using Microsoft.AspNetCore.Mvc;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using Log = BP.DA.Log;
namespace CCFlow.NetCore.DataUser.API.Controllers
{
/// <summary>
/// Star股票系统API接口
/// 对外发布的接口需要用户名密码登录获取token后才能访问数据
/// </summary>
[Route("Star/[controller]/[Action]")]
[ApiController]
public class StarMockController : BPController
{
#region
/// <summary>
/// 执行统计
/// </summary>
/// <param name="token"></param>
/// <param name="stockNo"></param>
/// <returns></returns>
[HttpGet, HttpPost]
public object MockStand_TongJi(string token, string stockNo)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
string safeStockNo = stockNo.Replace("'", "''");
string sql = $"SELECT MockStandSta, COUNT(*) AS N FROM Star_MockStand WHERE StockNo='{safeStockNo}' GROUP BY MockStandSta";
DataTable dt = DBAccess.RunSQLReturnTable(sql);
// 初始化各状态数量
int count0 = 0; // 未执行
int count1 = 0; // 已完成
int count2 = 0; // 执行中
int count3 = 0; // 执行失败
// 遍历查询结果,统计各状态数量
if (dt != null && dt.Rows.Count > 0)
{
foreach (DataRow row in dt.Rows)
{
int mockStandSta = Convert.ToInt32(row["MockStandSta"] ?? 0);
int count = Convert.ToInt32(row["N"] ?? 0);
switch (mockStandSta)
{
case 0:
count0 = count;
break;
case 1:
count1 = count;
break;
case 2:
count2 = count;
break;
case 3:
count3 = count;
break;
}
}
}
// 返回JSON格式的统计数据
var result = new
{
code = 200,
message = "统计成功",
data = new
{
= count0,
= count1,
= count2,
= count3
}
};
string str = BP.Tools.Json.ToJson(result);
return Return_Info(200, "执行成功", str);
}
catch (Exception ex)
{
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 执行Mock 单个股票,单个策略
/// </summary>
/// <param name="token"></param>
/// <param name="stockNo">股票编号</param>
/// <param name="standMyPK">策略编号</param>
/// <returns></returns>
[HttpGet, HttpPost]
public object MockStand(string token, string stockNo, string standMyPK)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Stock stock = new Stock(stockNo);
// standNo 可能是 MyPK 或 StrategyNo先尝试作为 MyPK如果失败则作为 StrategyNo 查询
Stand stand = new Stand(standMyPK);
Handler_Star handler = new Handler_Star();
handler.AddPara("stockNo", stockNo);
handler.AddPara("StandMyPK", stand.MyPK);
string result = handler.Stock_ExecuteMockSingle();
//返回执行结果.
MockStand ms = new MockStand(stockNo + "_" + stand.MyPK);
return Return_Info(200, "执行成功", ms.ToJson());
}
catch (Exception ex)
{
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 执行同步
/// </summary>
/// <param name="token"></param>
/// <param name="stockNo"></param>
/// <returns></returns>
[HttpGet, HttpPost]
public object Stock_DTS(string token, string stockNo)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Stock stock = new Stock(stockNo);
Handler_Star handler = new Handler_Star();
string str = handler.Stock_DTSOneExt(stock);
return Return_Info(200, "执行成功", str);
}
catch (Exception ex)
{
BP.DA.Log.DebugWriteError($"执行失败: {ex.Message}");
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 获得模拟的数据
/// </summary>
/// <param name="token"></param>
/// <param name="stockNo"></param>
/// <returns></returns>
[HttpGet, HttpPost]
public object MockStand_Init(string token, string stockNo)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Stock stock = new Stock(stockNo);
//1. 删除不存在的策略数据.
string sql = "DELETE FROM Star_MockStand WHERE StockNo='" + stockNo + "'";
sql += " AND StandMyPK NOT IN (SELECT MyPK FROM Star_Stand) ";
DBAccess.RunSQL(sql);
//2. 查询出来,没有的
Stands stands = new Stands();
sql = "SELECT MyPK FROM Star_Stand WHERE MyPK NOT IN( SELECT StandMyPK FROM Star_MockStand WHERE StockNo ='" + stockNo + "') ";
stands.RetrieveInSQL(sql);
//3. 生成数据.
MockStand ms = new MockStand();
foreach (Stand stand in stands)
{
ms.StockNo = stock.No;
ms.StockName = stock.Name;
ms.StandName = stand.Name;
ms.StockLocal = stock.StockLocal;
ms.StandMyPK = stand.MyPK;
ms.StandName = stand.Name;
ms.StrategyNo = stand.StrategyNo;
ms.StrategyName = stand.StrategyName;
ms.StrategyKLineType = stand.StrategyKLineType;
ms.MyPK = stock.No + "_" + stand.MyPK;
ms.Insert();
}
return Return_Info(200, "成功", null);
}
catch (Exception ex)
{
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 执行单个策略规格的模拟
/// </summary>
/// <param name="token">访问令牌</param>
/// <param name="stockNo">股票编号</param>
/// <param name="standMyPK">策略规格主键</param>
/// <returns>执行结果</returns>
[HttpGet, HttpPost]
public object Stock_ExecuteMockSingle(string token, string stockNo, string standMyPK)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Handler_Star handler = new Handler_Star();
handler.AddPara("token", token);
handler.AddPara("stockNo", stockNo);
handler.AddPara("standMyPK", standMyPK);
string result = handler.Stock_ExecuteMockSingle();
// 判断结果是否包含错误
bool isError = result.Contains("失败") || result.Contains("错误") ||
result.Contains("不能为空") || result.Contains("不存在");
if (isError)
{
return Return_Info(500, result, null);
}
return Return_Info(200, result, null);
}
catch (Exception ex)
{
BP.DA.Log.DebugWriteError($"执行失败: {ex.Message}");
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 股票数据同步(后台线程执行)
/// </summary>
/// <param name="token">访问令牌</param>
/// <param name="stockNo">股票编号</param>
/// <returns>执行结果</returns>
[HttpGet, HttpPost]
public object Stock_SyncData(string token, string stockNo)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
//执行数据同步的方法这里需要用AddPara方法 ,传入参数。
Handler_Star handler = new Handler_Star();
handler.AddPara("token", token);
handler.AddPara("stockNo", stockNo);
string result = handler.Stock_SyncData();
// 判断结果是否包含错误
bool isError = result.Contains("失败") || result.Contains("错误") ||
result.Contains("不能为空");
if (isError)
{
return Return_Info(500, result, null);
}
return Return_Info(200, result, null);
}
catch (Exception ex)
{
Log.DebugWriteError($"执行失败: {ex.Message}");
return Return_Info(500, "执行失败: " + ex.Message, null);
}
}
/// <summary>
/// 计算并更新股票的最优解策略
/// </summary>
/// <param name="token">访问令牌</param>
/// <param name="No">股票编号</param>
/// <returns>执行结果</returns>
[HttpGet, HttpPost]
public object Stock_CalculateOptimalStrategy(string token, string No)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Handler_Star handler = new Handler_Star();
handler.AddPara("No", No);
string result = handler.Stock_CalculateOptimalStrategy();
// 判断结果是否包含错误
bool isError = result.Contains("失败") || result.Contains("错误") ||
result.Contains("不能为空") || result.Contains("不存在");
if (isError)
{
return Return_Info(500, result, null);
}
return Return_Info(200, result, null);
}
catch (Exception ex)
{
Log.DebugWriteError($"计算最优解失败: {ex.Message}");
return Return_Info(500, $"计算最优解失败: {ex.Message}", null);
}
}
/// <summary>
/// 更新股票状态
/// </summary>
/// <param name="token">访问令牌</param>
/// <param name="stockNo">股票编号</param>
/// <param name="stockSta">股票状态0=不启用, 1=投产, 2=模拟验证中</param>
/// <returns>执行结果</returns>
[HttpGet, HttpPost]
public object Stock_UpdateStatus(string token, string stockNo, int stockSta)
{
try
{
// Token验证
if (DataType.IsNullOrEmpty(token))
return Return_Info(500, "未提供访问令牌,请先登录", null);
// 通过token登录
try
{
Dev2Interface.Port_LoginByToken(token);
}
catch (Exception ex)
{
return Return_Info(401, "Token验证失败请重新登录: " + ex.Message, null);
}
Handler_Star handler = new Handler_Star();
handler.AddPara("token", token);
handler.AddPara("stockNo", stockNo);
handler.AddPara("stockSta", stockSta.ToString());
string result = handler.Stock_UpdateStatus();
// 判断结果是否包含错误
bool isError = result.Contains("失败") || result.Contains("错误") ||
result.Contains("不能为空");
if (isError)
{
return Return_Info(500, result, null);
}
return Return_Info(200, result, null);
}
catch (Exception ex)
{
Log.DebugWriteError($"更新股票状态失败: {ex.Message}");
return Return_Info(500, $"更新股票状态失败: {ex.Message}", null);
}
}
#endregion
#region
/// <summary>
/// 测试接口是否可用无需Token
/// </summary>
/// <returns>服务状态</returns>
[HttpGet, HttpPost]
public object Ping()
{
return Return_Info(200, "Star API服务正常", new
{
version = "1.0.0",
serverTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
service = "Star Stock API"
});
}
/// <summary>
/// 获取当前版本信息无需Token
/// 用于客户端检查更新
/// </summary>
/// <returns>版本信息</returns>
[HttpGet, HttpPost]
public object GetVersion()
{
return Return_Info(200, "获取版本成功", new
{
version = "1.0.0",
clientVersion = "1.0.0",
updateUrl = "http://localhost:56146/DataUser/StarMock.zip",
updateTime = "2025-10-26",
updateDesc = "StarPilot v1.0.0 - 初始版本",
forceUpdate = true, // 是否强制更新
minVersion = "1.0.0" // 最低支持版本
});
}
#endregion
}
}

View File

@@ -322,6 +322,7 @@ namespace CCFlow.NetCore.DataUser.API.Controllers
lock (WF_Comm.frmVSTOTemplateLock)
BP.WF.Dev2Interface.Port_LoginByToken(token);
DataSet ds = new DataSet();
MapData mapData = new MapData(frmID);
DataTable mapDataTable = mapData.ToDataTableField("Sys_MapData");
@@ -408,6 +409,7 @@ namespace CCFlow.NetCore.DataUser.API.Controllers
return "err@参数不能为空";
}
BP.WF.Dev2Interface.Port_LoginByToken(token);
IFormFile file = HttpContextHelper.RequestFiles(0);
byte[] buffer = new byte[file.Length];
@@ -480,6 +482,7 @@ namespace CCFlow.NetCore.DataUser.API.Controllers
{
IFormFile file = HttpContextHelper.RequestFiles(0);
BP.WF.Dev2Interface.Port_LoginByToken(token);
if (file == null || file.Length == 0)
throw new Exception("err@文件数据bytes没有传递过来.");
@@ -545,6 +548,7 @@ namespace CCFlow.NetCore.DataUser.API.Controllers
//执行登录.
BP.WF.Dev2Interface.Port_LoginByToken(token);
GenerWorkFlow gwf = new GenerWorkFlow(workID);
//获得消息.
@@ -1225,7 +1229,7 @@ namespace CCFlow.NetCore.DataUser.API.Controllers
{
try
{
//Dev2Interface.Port_LoginByToken(token);
//BP.WF.Dev2Interface.Port_LoginByToken(token);
//此处为字段中文转拼音设置为最大20个字符edited by liuxc,2017-9-25
string str = BP.Sys.CCFormAPI.ParseStringToPinyinField(name, flag, true, 20);
return Return_Info(200, "成功", str);

View File

@@ -63,8 +63,7 @@ namespace CCFlow
builder.WithOrigins("http://10.38.0.79:30156",
"http://localhost:3000",
"http://localhost:3393",
"http://localhost:6080",
"http://127.0.0.1:3393",
"http://127.0.0.1:3393",
"http://192.168.1.7:8087") // 指定前端地址
.AllowAnyHeader() // 用于支持http头中带token的认证
.AllowAnyMethod() // 跨域时浏览器会发一个OPTIONS请求。这儿也可以用.WithHeaders来指定具体的Http方法

View File

@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<History>True|2025-11-05T07:02:18.7047734Z||;True|2025-11-05T14:45:40.7216826+08:00||;True|2025-10-24T15:21:51.5147185+08:00||;True|2024-11-04T10:49:22.3439780+08:00||;True|2024-11-02T15:30:32.4493531+08:00||;True|2024-10-31T11:59:28.6642920+08:00||;True|2024-10-08T09:36:17.8010764+08:00||;False|2024-10-08T09:35:41.2564843+08:00||;True|2024-09-23T10:25:32.3661449+08:00||;True|2024-09-20T10:18:18.3623728+08:00||;True|2024-09-18T09:23:54.2366096+08:00||;True|2024-09-18T09:20:13.6313145+08:00||;True|2024-09-10T08:59:03.3615113+08:00||;True|2024-09-06T17:12:20.6511430+08:00||;True|2024-09-06T17:11:47.0125481+08:00||;True|2024-09-03T16:16:15.9895220+08:00||;True|2024-09-03T16:15:13.1769002+08:00||;True|2024-08-26T09:50:17.8879731+08:00||;True|2024-08-19T18:17:19.2685669+08:00||;True|2024-08-17T14:41:01.7202982+08:00||;True|2024-08-17T14:20:02.7322151+08:00||;True|2024-08-17T10:37:11.6370780+08:00||;True|2024-08-16T16:32:28.4506212+08:00||;True|2024-08-16T14:27:03.8626125+08:00||;True|2024-08-16T10:25:16.4322486+08:00||;True|2024-08-16T09:58:58.5530777+08:00||;True|2024-08-15T23:33:56.1737136+08:00||;True|2024-08-15T23:26:54.7595429+08:00||;True|2024-08-15T16:31:01.8402297+08:00||;True|2024-08-15T16:25:06.8337675+08:00||;True|2024-08-15T16:20:30.1035707+08:00||;True|2024-08-15T16:15:23.0017935+08:00||;True|2024-08-15T16:14:06.6106725+08:00||;True|2024-08-15T16:12:43.3544482+08:00||;True|2024-08-15T16:11:17.9301252+08:00||;True|2024-08-15T16:09:53.3238193+08:00||;True|2024-08-15T16:07:46.1388207+08:00||;True|2024-08-15T16:02:13.7608193+08:00||;True|2024-08-15T15:47:05.9594330+08:00||;True|2024-08-15T15:33:00.6545868+08:00||;True|2024-08-15T15:23:26.1171247+08:00||;True|2024-08-15T15:21:56.0150016+08:00||;True|2024-08-15T15:21:36.9296801+08:00||;True|2024-08-15T15:20:06.6029405+08:00||;True|2024-08-15T15:17:43.4263365+08:00||;True|2024-08-15T15:13:50.3381323+08:00||;True|2024-08-15T15:10:43.9408787+08:00||;True|2024-08-15T14:45:00.3779697+08:00||;True|2024-08-15T14:41:18.2346769+08:00||;True|2024-08-15T14:40:50.9397723+08:00||;True|2024-08-15T14:19:15.3844761+08:00||;True|2024-08-15T14:11:17.9180694+08:00||;True|2024-08-15T11:58:58.9103250+08:00||;True|2024-08-15T11:52:45.1310040+08:00||;True|2024-08-15T11:40:55.0247636+08:00||;True|2024-08-14T17:57:12.1001520+08:00||;True|2023-07-10T10:46:32.3936546+08:00||;True|2023-02-10T11:04:06.9187348+08:00||;True|2023-02-08T17:07:57.1599828+08:00||;True|2023-01-16T18:00:58.8027043+08:00||;True|2023-01-16T16:57:42.0128462+08:00||;True|2023-01-13T16:19:54.2694025+08:00||;True|2023-01-12T18:45:34.3556424+08:00||;True|2023-01-12T16:26:06.1117663+08:00||;True|2023-01-12T16:19:24.4642741+08:00||;True|2023-01-12T16:06:01.7639094+08:00||;True|2023-01-12T15:14:48.7525821+08:00||;False|2023-01-12T15:12:54.8911185+08:00||;False|2023-01-12T15:11:43.2429571+08:00||;False|2023-01-12T14:40:05.8520549+08:00||;False|2023-01-12T14:39:40.0972234+08:00||;True|2023-01-12T12:08:08.1313782+08:00||;False|2023-01-12T12:07:16.5121334+08:00||;True|2023-01-11T10:41:39.2725002+08:00||;True|2022-08-18T09:29:32.0440022+08:00||;False|2022-08-18T09:26:44.9335531+08:00||;False|2022-08-18T09:26:19.6424677+08:00||;</History>
<History>True|2025-11-10T03:49:14.4433633Z||;True|2025-11-10T09:15:58.6766552+08:00||;True|2025-11-10T09:15:28.5199845+08:00||;True|2025-11-10T09:15:23.6119709+08:00||;False|2025-11-10T09:14:23.2673454+08:00||;True|2025-11-10T09:07:43.0128822+08:00||;True|2025-11-10T09:07:12.9193876+08:00||;True|2025-11-05T15:02:18.7047734+08:00||;True|2025-11-05T14:45:40.7216826+08:00||;True|2025-10-24T15:21:51.5147185+08:00||;True|2024-11-04T10:49:22.3439780+08:00||;True|2024-11-02T15:30:32.4493531+08:00||;True|2024-10-31T11:59:28.6642920+08:00||;True|2024-10-08T09:36:17.8010764+08:00||;False|2024-10-08T09:35:41.2564843+08:00||;True|2024-09-23T10:25:32.3661449+08:00||;True|2024-09-20T10:18:18.3623728+08:00||;True|2024-09-18T09:23:54.2366096+08:00||;True|2024-09-18T09:20:13.6313145+08:00||;True|2024-09-10T08:59:03.3615113+08:00||;True|2024-09-06T17:12:20.6511430+08:00||;True|2024-09-06T17:11:47.0125481+08:00||;True|2024-09-03T16:16:15.9895220+08:00||;True|2024-09-03T16:15:13.1769002+08:00||;True|2024-08-26T09:50:17.8879731+08:00||;True|2024-08-19T18:17:19.2685669+08:00||;True|2024-08-17T14:41:01.7202982+08:00||;True|2024-08-17T14:20:02.7322151+08:00||;True|2024-08-17T10:37:11.6370780+08:00||;True|2024-08-16T16:32:28.4506212+08:00||;True|2024-08-16T14:27:03.8626125+08:00||;True|2024-08-16T10:25:16.4322486+08:00||;True|2024-08-16T09:58:58.5530777+08:00||;True|2024-08-15T23:33:56.1737136+08:00||;True|2024-08-15T23:26:54.7595429+08:00||;True|2024-08-15T16:31:01.8402297+08:00||;True|2024-08-15T16:25:06.8337675+08:00||;True|2024-08-15T16:20:30.1035707+08:00||;True|2024-08-15T16:15:23.0017935+08:00||;True|2024-08-15T16:14:06.6106725+08:00||;True|2024-08-15T16:12:43.3544482+08:00||;True|2024-08-15T16:11:17.9301252+08:00||;True|2024-08-15T16:09:53.3238193+08:00||;True|2024-08-15T16:07:46.1388207+08:00||;True|2024-08-15T16:02:13.7608193+08:00||;True|2024-08-15T15:47:05.9594330+08:00||;True|2024-08-15T15:33:00.6545868+08:00||;True|2024-08-15T15:23:26.1171247+08:00||;True|2024-08-15T15:21:56.0150016+08:00||;True|2024-08-15T15:21:36.9296801+08:00||;True|2024-08-15T15:20:06.6029405+08:00||;True|2024-08-15T15:17:43.4263365+08:00||;True|2024-08-15T15:13:50.3381323+08:00||;True|2024-08-15T15:10:43.9408787+08:00||;True|2024-08-15T14:45:00.3779697+08:00||;True|2024-08-15T14:41:18.2346769+08:00||;True|2024-08-15T14:40:50.9397723+08:00||;True|2024-08-15T14:19:15.3844761+08:00||;True|2024-08-15T14:11:17.9180694+08:00||;True|2024-08-15T11:58:58.9103250+08:00||;True|2024-08-15T11:52:45.1310040+08:00||;True|2024-08-15T11:40:55.0247636+08:00||;True|2024-08-14T17:57:12.1001520+08:00||;True|2023-07-10T10:46:32.3936546+08:00||;True|2023-02-10T11:04:06.9187348+08:00||;True|2023-02-08T17:07:57.1599828+08:00||;True|2023-01-16T18:00:58.8027043+08:00||;True|2023-01-16T16:57:42.0128462+08:00||;True|2023-01-13T16:19:54.2694025+08:00||;True|2023-01-12T18:45:34.3556424+08:00||;True|2023-01-12T16:26:06.1117663+08:00||;True|2023-01-12T16:19:24.4642741+08:00||;True|2023-01-12T16:06:01.7639094+08:00||;True|2023-01-12T15:14:48.7525821+08:00||;False|2023-01-12T15:12:54.8911185+08:00||;False|2023-01-12T15:11:43.2429571+08:00||;False|2023-01-12T14:40:05.8520549+08:00||;False|2023-01-12T14:39:40.0972234+08:00||;True|2023-01-12T12:08:08.1313782+08:00||;False|2023-01-12T12:07:16.5121334+08:00||;True|2023-01-11T10:41:39.2725002+08:00||;True|2022-08-18T09:29:32.0440022+08:00||;False|2022-08-18T09:26:44.9335531+08:00||;False|2022-08-18T09:26:19.6424677+08:00||;</History>
<_PublishTargetUrl>D:\workspace\svn\.netcore发布</_PublishTargetUrl>
<LastFailureDetails />
</PropertyGroup>

View File

@@ -4,11 +4,10 @@
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
</configSections>
<appSettings>
<!--本地演示环境数据库链接-->
<add key="AppCenterDSN" value="SslMode=none;Data Source=localhost;Port=3306;Persist Security info=True;Initial Catalog=数据库名称;User ID=数据库账号;Password=数据库密码;Charset=utf8"/>
<add key="AppCenterDBType" value="MySQL"/>
<add key="CCBPMRunModel" value="0"/>
<add key="appcenterdsn" value="sslmode=none;data source=localhost;port=4316;persist security info=true;initial catalog=XXX;user id=XXX;password=XXXX;charset=utf8;allow user variables=true;"/>
<add key="appcenterdbtype" value="MySQL"/>
<add key="ccbpmrunmodel" value="0"/>
<!--0 -->
<add key="TokenModel" value="0"/>
@@ -83,16 +82,23 @@
<!-- 前端输入的加密AES的Key 默认为:lCCqkL1BfSwt2M@5 -->
<add key="IsEncryptionKey" value="lCCqkL1BfSwt2M@5"/>
<!-- 用户登录密码组合类型 0:无 1: 8-20位字符,必须包含大小写字母、数字。在密码中不得包含户名 -->
<add key="PassWordComposeType" value="1"/>
<!-- 用户第一次登录时是否强制要求修改密码 0:否 1:是 -->
<add key="IsPassWordChangeBYFirstLogin" value="1"/>
<!-- 用户登录密码修改时的校验类型 0:无 1: 至少包含8个字符;必须大小写字母、数字和符号的组合;不得包含户名、实际姓名全拼或缩写;不能出现连续数字3位及以上 -->
<add key="PassWordComposeType" value="0"/>
<!-- 用户登录密码中不能包含的敏感词PassWordComposeType=1时检测多个逗号分隔(忽略大小写) -->
<add key="PassWordComposeTypeSensitiveWords" value="pass,password,root"/>
<!-- 用户第一次登录或使用初始密码时是否强制要求修改密码 0:否 1:是 -->
<add key="IsPassWordChangeBYFirstLogin" value="0"/>
<!-- 用户的操作日志是否记录数据库(登录,访问,删除,权限修改以及其他操作) 0:否 1:是-->
<add key="IsEnableLog" value="0"/>
<!-- 用户信息显示格式 @0=UserID,UserName@1=UserNo,@2=UserName 0=zhangsa,张三. 1=zhangsan, 2=张三. -->
<add key="UserInfoShowModel" value="0" />
<!-- 是否:debug状态. 0 表示不是, 1 是如果系统发布后请将此修改成0以提高执行效率。 -->
<add key="IsDebug" value="0" />
<add key="IsDebug" value="1" />
<!-- 是否:自动测试模式. 0-不是, 1 -是注意系统发布后勿必将此修改成0否则可能影响部分功能使用(2017-09-08暂时仅影响VSTO插件功能)。 -->
<add key="IsAutoTesting" value="0" />

View File

@@ -4,6 +4,11 @@
<name>CCFlow</name>
</assembly>
<members>
<member name="M:CCFlow.NetCore.DataUser.API.Controllers.GZSZController.UpdateHisData(System.Int32)">
修改历史数据
@return
@throws Exception
</member>
<member name="M:CCFlow.NetCore.DataUser.API.Controllers.APIController.Return_Info(System.Int32,System.String,System.String)">
<summary>
返回信息格式

View File

@@ -1,5 +1,4 @@

/*
/*
简介:负责存取数据的类
创建时间2002-10
最后修改时间2004-2-1 ccb
@@ -27,6 +26,9 @@ using Kdbndp;
using BP.Difference;
using KdbndpTypes;
using NPOI.SS.Formula.Functions;
using System.Linq;
using System.Collections.Generic;
using System.Data.Common;
namespace BP.DA
{
@@ -36,6 +38,33 @@ namespace BP.DA
/// </summary>
public class DBAccess
{
// 用于控制对同一表的并发访问,避免死锁
// Key: 表名小写Value: SemaphoreSlim 信号量允许最多1个并发即串行化
private static System.Collections.Generic.Dictionary<string, System.Threading.SemaphoreSlim> _tableSemaphores =
new System.Collections.Generic.Dictionary<string, System.Threading.SemaphoreSlim>();
private static readonly object _semaphoreLock = new object();
/// <summary>
/// 获取或创建表对应的信号量,用于控制并发访问
/// </summary>
private static System.Threading.SemaphoreSlim GetTableSemaphore(string tableName)
{
if (string.IsNullOrEmpty(tableName))
return null;
string key = tableName.ToLower();
lock (_semaphoreLock)
{
if (!_tableSemaphores.ContainsKey(key))
{
// 每个表最多允许3个并发在避免死锁和提高吞吐量之间取得平衡
// 对于DELETE操作由于通常针对不同的行不同的StandMyPK允许有限并发是安全的
_tableSemaphores[key] = new System.Threading.SemaphoreSlim(3, 3);
}
return _tableSemaphores[key];
}
}
public static string GenerMD5(string str, bool islower = false)
{
if (islower == true)
@@ -100,7 +129,7 @@ namespace BP.DA
BP.DA.DBAccess.RunSQL(sql);
}
public static void UpdateTableColumnType(string tableName, string colName,string dataType,SFDBSrc sfdbsrc)
public static void UpdateTableColumnType(string tableName, string colName, string dataType, SFDBSrc sfdbsrc)
{
//判断数据库中表单是否存在
if (sfdbsrc.IsExitsTableCol(tableName, colName) == false || sfdbsrc.IsView(tableName, sfdbsrc.HisDBType) == true)
@@ -111,7 +140,7 @@ namespace BP.DA
switch (sfdbsrc.HisDBType)
{
case DBType.MSSQL:
sql = "SELECT data_type as FTYPE FROM information_schema.columns where table_name='" + tableName + "' AND column_name='"+colName+"'";
sql = "SELECT data_type as FTYPE FROM information_schema.columns where table_name='" + tableName + "' AND column_name='" + colName + "'";
break;
case DBType.Oracle:
case DBType.DM:
@@ -119,10 +148,10 @@ namespace BP.DA
case DBType.KingBaseR6:
case DBType.KingBaseR8:
case DBType.GBASE8CByOracle:
sql = "SELECT DATA_TYPE as FTYPE FROM all_tab_columns WHERE table_name = upper('" + tableName + "') AND UPPER(COLUMN_NAME)='" + colName.ToUpper() ;
sql = "SELECT DATA_TYPE as FTYPE FROM all_tab_columns WHERE table_name = upper('" + tableName + "') AND UPPER(COLUMN_NAME)='" + colName.ToUpper();
break;
case DBType.MySQL:
sql = "SELECT DATA_TYPE FTYPE FROM information_schema.columns WHERE table_name='" + tableName + "' AND column_name='"+colName+"' and TABLE_SCHEMA='" + sfdbsrc.GetTableSchema() + "'";
sql = "SELECT DATA_TYPE FTYPE FROM information_schema.columns WHERE table_name='" + tableName + "' AND column_name='" + colName + "' and TABLE_SCHEMA='" + sfdbsrc.GetTableSchema() + "'";
break;
default:
break;
@@ -151,7 +180,7 @@ namespace BP.DA
}
}
toType = dataType.Equals("String") ? " VARCHAR(20)" : " INT";
toType = dataType.Equals("String") ? " VARCHAR(20)" : " INT";
if (dataType.Equals("String") || dataType.Equals("Int"))
sfdbsrc.RunSQL("alter table " + tableName + " ALTER column " + colName + toType);
@@ -194,7 +223,7 @@ namespace BP.DA
/// <summary>
/// 获得数据表字段描述的SQL
/// </summary>
public static string SQLOfTableFieldDesc(string table,DBType dbType)
public static string SQLOfTableFieldDesc(string table, DBType dbType)
{
if (dbType == DBType.MSSQL)
return "SELECT column_name as FName,data_type as FType,CHARACTER_MAXIMUM_LENGTH as FLen from information_schema.columns where table_name='" + table + "'";
@@ -234,7 +263,7 @@ namespace BP.DA
/// </summary>
/// <param name="table"></param>
/// <returns></returns>
public static string SQLOfTableFieldYueShu(string table,DBType dbType)
public static string SQLOfTableFieldYueShu(string table, DBType dbType)
{
if (dbType == DBType.MSSQL)
return "SELECT b.name, a.name FName from sysobjects b join syscolumns a on b.id = a.cdefault where a.id = object_id('" + table + "') ";
@@ -549,14 +578,14 @@ namespace BP.DA
MySqlCommand cm = new MySqlCommand();
cm.Connection = cn;
cm.CommandType = CommandType.Text;
//if (tableName == "Sys_FrmPrintTemplate")
//{
// cm.CommandText = "UPDATE " + tableName + " SET NodeID=1 WHERE " + tablePK + " =@PKVal";
// }
// else {
cm.CommandText = "UPDATE " + tableName + " SET " + saveToFileField + "=@FlowJsonFile WHERE " + tablePK + " =@PKVal";
// }
// cm.CommandText = "UPDATE " + tableName + " SET NodeID=1 WHERE " + tablePK + " =@PKVal";
// }
// else {
cm.CommandText = "UPDATE " + tableName + " SET " + saveToFileField + "=@FlowJsonFile WHERE " + tablePK + " =@PKVal";
// }
MySqlParameter spFile = new MySqlParameter("FlowJsonFile", MySqlDbType.Blob);
@@ -661,7 +690,8 @@ namespace BP.DA
public static void SaveFileToDB(string fullFileName, string tableName, string tablePK, string pkVal, string saveToFileField)
{
FileInfo fi = new FileInfo(fullFileName);
if (fi.Exists) {
if (fi.Exists)
{
FileStream fs = fi.OpenRead();
byte[] bytes = new byte[fs.Length];
fs.Read(bytes, 0, Convert.ToInt32(fs.Length));
@@ -852,10 +882,10 @@ namespace BP.DA
{
string sql = "";
/*如果没有此列,就自动创建此列.*/
sql = "ALTER TABLE " + tableName + " ADD " + fileSaveField + " blob ";
sql = "ALTER TABLE " + tableName + " ADD " + fileSaveField + " blob ";
DBAccess.RunSQL(sql);
return null;
@@ -878,7 +908,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
cn.Dispose();
}
@@ -940,7 +971,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
cn.Dispose();
}
@@ -994,7 +1026,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
conn.Dispose();
}
@@ -1046,7 +1079,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
cn.Dispose();
}
@@ -1097,7 +1131,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
cn.Dispose();
}
@@ -1147,7 +1182,8 @@ namespace BP.DA
}
finally
{
if (dr != null) { dr.Close(); };
if (dr != null) { dr.Close(); }
;
cm.Dispose();
cn.Dispose();
}
@@ -1725,7 +1761,7 @@ namespace BP.DA
}
else
{
DBAccess.RunSQL("ALTER TABLE " + tableName + " ADD " + columnName + " NVARCHAR(20) DEFAULT '" + defaultVal + "' NULL ");
DBAccess.RunSQL("ALTER TABLE " + tableName + " ADD " + columnName + " NVARCHAR(20) DEFAULT '" + defaultVal + "' NULL ");
}
break;
case DataType.AppInt:
@@ -1757,7 +1793,7 @@ namespace BP.DA
/// </summary>
/// <param name="tableName"></param>
/// <returns>FIELD-字段名称;TYPE-字段类型</returns>
public static DataTable getTableFieldType(string tableName,SFDBSrc sfdbSrc)
public static DataTable getTableFieldType(string tableName, SFDBSrc sfdbSrc)
{
try
{
@@ -1824,7 +1860,7 @@ namespace BP.DA
" JOIN user_ind_columns ic ON i.index_name = ic.index_name" +
" WHERE i.table_name = '" + table.ToUpper() + "' AND ic.column_name = '" + fieldName.ToUpper() + "'" +
" ORDER BY i.index_name";
dt = DBAccess.RunSQLReturnTable(sql);
dt = DBAccess.RunSQLReturnTable(sql);
if (dt.Rows.Count != 0)
{
string indexName = dt.Rows[0][0].ToString();
@@ -1837,7 +1873,7 @@ namespace BP.DA
sql = "SELECT i.name ,i.type_desc,i.is_unique,i.is_primary_key,ic.is_included_column FROM sys.indexes i" +
" INNER JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id" +
" INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id" +
" INNER JOIN sys.tables t ON i.object_id = t.object_id WHERE t.name = '"+ table + "' AND c.name = '"+ fieldName + "' ";
" INNER JOIN sys.tables t ON i.object_id = t.object_id WHERE t.name = '" + table + "' AND c.name = '" + fieldName + "' ";
dt = DBAccess.RunSQLReturnTable(sql);
if (dt.Rows.Count != 0)
{
@@ -2068,26 +2104,29 @@ namespace BP.DA
#region
public static void DropIndex(string table, string idxName)
public static void DropIndex(string table, string idxName)
{
string sql = "";
switch (AppCenterDBType)
{
case DBType.HGDB:
sql = "DROP INDEX IF EXISTS " + idxName;
break;
default:
break;
}
try{
if(!sql.Equals("")){
DBAccess.RunSQL(sql);
}
}catch (Exception ex)
{
switch (AppCenterDBType)
{
case DBType.HGDB:
sql = "DROP INDEX IF EXISTS " + idxName;
break;
default:
break;
}
try
{
if (!sql.Equals(""))
{
DBAccess.RunSQL(sql);
}
}
catch (Exception ex)
{
}
}
}
}
public static void CreatIndex(string table, string fields)
{
string myFields = fields.Replace(",", "_");
@@ -2243,33 +2282,20 @@ namespace BP.DA
switch (AppCenterDBType)
{
case DBType.MSSQL:
result = RunSQL_200705_SQL(sql, paras);
break;
case DBType.Oracle:
case DBType.GBASE8CByOracle:
result = RunSQL_200705_Ora(sql.Replace("]", "").Replace("[", ""), paras);
break;
case DBType.MySQL:
result = RunSQL_200705_MySQL(sql, paras);
break;
case DBType.PostgreSQL:
case DBType.HGDB:
result = RunSQL_201902_PSQL(sql, paras);
break;
case DBType.UX:
result = RunSQL_201902_UXQL(sql, paras);
break;
case DBType.DM:
result = RunSQL_20191230_DM(sql, paras);
break;
case DBType.KingBaseR3:
case DBType.KingBaseR6:
case DBType.KingBaseR8:
result = RunSQL_201902_KingBase(sql.Replace("]", "").Replace("[", ""), paras);
result = RunSQL_2025(sql, paras);
break;
case DBType.Oracle:
case DBType.GBASE8CByOracle:
result = RunSQL_2025(sql.Replace("]", "").Replace("[", ""), paras);
break;
//case DBType.Informix:
// result = RunSQL_201205_Informix(sql, paras);
// break;
default:
throw new Exception("err@RunSQL发现未知的数据库连接类型");
}
@@ -2418,15 +2444,8 @@ namespace BP.DA
}
catch (System.Exception ex)
{
paras.SQL = sql;
string msg = "";
if (paras.Count == 0)
msg = "SQL=" + sql + ",异常信息:" + ex.Message;
else
msg = "SQL=" + paras.SQLNoPara + ",异常信息:" + ex.Message;
BP.DA.Log.DebugWriteError(msg);
throw new Exception(msg);
DealExeSQLException(ex, sql, paras);
return -1;
}
finally
{
@@ -2436,6 +2455,20 @@ namespace BP.DA
conn.Dispose();
}
}
/// <summary>
/// 处理执行SQL异常
/// </summary>
/// <param name="ex"></param>
/// <param name="sql"></param>
/// <param name="paras"></param>
/// <exception cref="Exception"></exception>
private static void DealExeSQLException(Exception ex, string sql, Paras paras)
{
string msg = "执行SQL:" + sql + ",参数:" + paras.ToString() + ",异常:" + ex.Message;
BP.DA.Log.DebugWriteError(msg);
throw new Exception(msg);
}
private static int RunSQL_201902_UXQL(string sql, Paras paras)
{
if (1 == 1)
@@ -2630,82 +2663,376 @@ namespace BP.DA
conn.Close();
}
}
#region mysql conn的缓存.
private static Hashtable _ConnHTOfMySQL = null;
public static Hashtable ConnHTOfMySQL
{
get
{
if (_ConnHTOfMySQL == null || _ConnHTOfMySQL.Count <= 0)
{
_ConnHTOfMySQL = new Hashtable();
int numConn = 10;
for (int i = 0; i < numConn; i++)
{
MySqlConnection conn = new MySqlConnection(BP.Difference.SystemConfig.AppCenterDSN);
conn.Open(); //打开连接.
_ConnHTOfMySQL.Add("Conn" + i, conn);
}
}
return _ConnHTOfMySQL;
}
}
#endregion mysql conn的缓存.
/// <summary>
/// RunSQL_200705_MySQL
/// 从SQL语句中提取表名用于表锁
/// </summary>
/// <param name="sql"></param>
/// <param name="paras"></param>
/// <returns></returns>
private static int RunSQL_200705_MySQL(string sql, Paras paras)
/// <param name="sql">SQL语句</param>
/// <returns>表名如果未找到则返回null</returns>
private static string ExtractTableNameFromSQL(string sql)
{
MySqlConnection connOfMySQL = new MySqlConnection(BP.Difference.SystemConfig.AppCenterDSN);
if (connOfMySQL.State != System.Data.ConnectionState.Open)
if (string.IsNullOrEmpty(sql))
return null;
// 移除注释和多余空格
string cleanSql = sql.Trim();
// 移除SQL注释
cleanSql = System.Text.RegularExpressions.Regex.Replace(cleanSql, @"--.*", "");
cleanSql = System.Text.RegularExpressions.Regex.Replace(cleanSql, @"/\*.*?\*/", "", System.Text.RegularExpressions.RegexOptions.Singleline);
// 匹配 DELETE FROM table_name
var deleteMatch = System.Text.RegularExpressions.Regex.Match(cleanSql, @"DELETE\s+FROM\s+([^\s\(]+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
if (deleteMatch.Success)
{
connOfMySQL.ConnectionString = BP.Difference.SystemConfig.AppCenterDSN;
connOfMySQL.Open();
string tableName = deleteMatch.Groups[1].Value.Trim();
// 移除可能的反引号、方括号等
tableName = tableName.Trim('`', '[', ']');
if (!string.IsNullOrEmpty(tableName))
return tableName;
}
// 匹配 UPDATE table_name
var updateMatch = System.Text.RegularExpressions.Regex.Match(cleanSql, @"UPDATE\s+([^\s\(]+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
if (updateMatch.Success)
{
string tableName = updateMatch.Groups[1].Value.Trim();
tableName = tableName.Trim('`', '[', ']');
if (!string.IsNullOrEmpty(tableName))
return tableName;
}
// 匹配 INSERT INTO table_name
var insertMatch = System.Text.RegularExpressions.Regex.Match(cleanSql, @"INSERT\s+(?:INTO\s+)?([^\s\(]+)", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
if (insertMatch.Success)
{
string tableName = insertMatch.Groups[1].Value.Trim();
tableName = tableName.Trim('`', '[', ']');
if (!string.IsNullOrEmpty(tableName))
return tableName;
}
return null;
}
private static int RunSQL_2025(string sql, Paras paras)
{
if (string.IsNullOrWhiteSpace(sql))
return 0;
DBType dbType = AppCenterDBType;
string originalSql = sql;
string primaryTableName = ExtractTableNameFromSQL(originalSql);
System.Threading.SemaphoreSlim tableSemaphore = GetTableSemaphore(primaryTableName);
int maxRetries = 5;
int baseRetryDelay = 50;
Random random = new Random();
Exception lastException = null;
IEnumerable<Para> effectiveParasEnumerable;
string normalizedSql = NormalizeSqlForProvider(originalSql, paras, dbType, out effectiveParasEnumerable);
List<Para> effectiveParas = effectiveParasEnumerable?.ToList() ?? new List<Para>();
if (tableSemaphore != null && !tableSemaphore.Wait(60000))
throw new Exception($"获取表锁超时60秒: {primaryTableName}, SQL: {originalSql}");
try
{
MySqlCommand cmd = new MySqlCommand(sql, connOfMySQL);
cmd.CommandType = CommandType.Text;
if (paras != null)
for (int attempt = 0; attempt < maxRetries; attempt++)
{
foreach (Para para in paras)
using (DbConnection connection = CreateDbConnection(dbType))
using (DbCommand command = connection.CreateCommand())
{
MySqlParameter oraP = new MySqlParameter(para.ParaName, para.val);
cmd.Parameters.Add(oraP);
command.CommandText = normalizedSql;
command.CommandType = CommandType.Text;
foreach (Para para in effectiveParas)
{
command.Parameters.Add(CreateDbParameter(para, dbType));
}
try
{
if (connection.State != ConnectionState.Open)
connection.Open();
int result = command.ExecuteNonQuery();
return result;
}
catch (Exception ex)
{
lastException = ex;
if (!IsTransientError(ex, dbType) || attempt == maxRetries - 1)
throw new Exception($"err@RunSQL_200705_MySQL({dbType}): {ex.Message} SQL={originalSql}", ex);
System.Threading.Thread.Sleep(CalculateRetryDelay(attempt, baseRetryDelay, random));
}
finally
{
command.Parameters.Clear();
}
}
}
return cmd.ExecuteNonQuery();
}
catch (System.Exception ex)
{
throw new Exception("err@RunSQL_200705_MySQL:" + ex.Message + "@SQL:" + sql);
if (lastException != null)
throw new Exception($"err@RunSQL_200705_MySQL({dbType}): 经过{maxRetries}次重试后仍失败: {lastException.Message} SQL={originalSql}", lastException);
throw new Exception($"err@RunSQL_200705_MySQL({dbType}): 执行失败,未知错误 SQL={originalSql}");
}
finally
{
if (connOfMySQL != null)
if (tableSemaphore != null)
{
try
{
if (connOfMySQL.State == System.Data.ConnectionState.Open)
{
connOfMySQL.Close();
}
tableSemaphore.Release();
}
catch { }
finally
catch
{
connOfMySQL.Dispose();
}
}
}
}
private static string NormalizeSqlForProvider(string sql, Paras paras, DBType dbType, out IEnumerable<Para> effectiveParas)
{
string normalized = sql ?? string.Empty;
List<Para> parameters = new List<Para>();
if (paras != null)
{
foreach (Para para in paras)
{
parameters.Add(para);
}
}
if (dbType != DBType.MSSQL)
{
normalized = normalized.Replace("[", string.Empty).Replace("]", string.Empty);
}
if (dbType == DBType.Oracle || dbType == DBType.GBASE8CByOracle)
{
string trimmed = normalized.Trim();
if (trimmed.EndsWith(";"))
{
normalized = $"begin {trimmed} end;";
}
if (paras != null && paras.Count > 0)
{
List<Para> filtered = new List<Para>();
string dbVarStr = SystemConfig.AppCenterDBVarStr;
foreach (Para para in paras)
{
object val = para.val;
bool isNullOrEmpty = val == null || val == DBNull.Value || string.IsNullOrEmpty(val.ToString());
if (isNullOrEmpty)
{
normalized = normalized.Replace("=" + dbVarStr + para.ParaName, " IS NULL ");
normalized = normalized.Replace("<>" + dbVarStr + para.ParaName, " IS NOT NULL ");
}
else
{
filtered.Add(para);
}
}
parameters = filtered;
}
}
effectiveParas = parameters;
return normalized;
}
private static DbConnection CreateDbConnection(DBType dbType)
{
string dsn = SystemConfig.AppCenterDSN;
switch (dbType)
{
case DBType.MySQL:
return new MySqlConnection(dsn);
case DBType.MSSQL:
return new SqlConnection(dsn);
case DBType.Oracle:
case DBType.GBASE8CByOracle:
return new OracleConnection(dsn);
case DBType.PostgreSQL:
case DBType.HGDB:
return new NpgsqlConnection(dsn);
case DBType.DM:
return new DmConnection(dsn);
case DBType.KingBaseR3:
case DBType.KingBaseR6:
case DBType.KingBaseR8:
return new KdbndpConnection(dsn);
case DBType.UX:
return new NuxsqlConnection(dsn);
default:
throw new NotSupportedException($"err@RunSQL_200705_MySQL: 尚未实现 {dbType} 的执行逻辑");
}
}
private static DbParameter CreateDbParameter(Para para, DBType dbType)
{
if (para == null)
throw new ArgumentNullException(nameof(para));
object value = para.val ?? DBNull.Value;
switch (dbType)
{
case DBType.MSSQL:
{
SqlParameter parameter = new SqlParameter(para.ParaName, value)
{
DbType = para.DAType
};
if (para.Size > 0)
parameter.Size = para.Size;
return parameter;
}
case DBType.MySQL:
{
MySqlParameter parameter = new MySqlParameter(para.ParaName, value)
{
DbType = para.DAType
};
if (para.Size > 0)
parameter.Size = para.Size;
return parameter;
}
case DBType.PostgreSQL:
case DBType.HGDB:
{
NpgsqlParameter parameter = new NpgsqlParameter(para.ParaName, value)
{
DbType = para.DAType
};
if (para.Size > 0)
parameter.Size = para.Size;
return parameter;
}
case DBType.UX:
{
Nuxsql.NuxsqlParameter parameter = new Nuxsql.NuxsqlParameter(para.ParaName, value)
{
DbType = para.DAType
};
if (para.Size > 0)
parameter.Size = para.Size;
return parameter;
}
case DBType.DM:
{
DmParameter parameter = new DmParameter(para.ParaName, value == DBNull.Value ? DBNull.Value : value.ToString())
{
DbType = para.DAType
};
return parameter;
}
case DBType.KingBaseR3:
case DBType.KingBaseR6:
case DBType.KingBaseR8:
{
KdbndpParameter parameter = new KdbndpParameter(para.ParaName, value)
{
DbType = para.DAType
};
if (para.Size > 0)
parameter.Size = para.Size;
return parameter;
}
case DBType.Oracle:
case DBType.GBASE8CByOracle:
{
OracleParameter parameter = new OracleParameter(para.ParaName, para.DATypeOfOra);
parameter.Size = para.Size;
if (para.DATypeOfOra == OracleDbType.Varchar2 && Convert.IsDBNull(para.val))
{
parameter.Value = DBNull.Value;
return parameter;
}
if (para.DATypeOfOra == OracleDbType.Clob && DataType.IsNullOrEmpty(para.val as string) == true)
parameter.Value = DBNull.Value;
else
parameter.Value = para.val;
parameter.DbType = para.DAType;
return parameter;
}
default:
throw new NotSupportedException($"err@RunSQL_200705_MySQL: 尚未实现 {dbType} 的参数绑定");
}
}
private static bool IsTransientError(Exception ex, DBType dbType)
{
if (ex == null)
return false;
string message = ex.Message?.ToLowerInvariant() ?? string.Empty;
if (message.Contains("deadlock") || message.Contains("lock wait timeout") || message.Contains("timeout") ||
message.Contains("try restarting transaction") || message.Contains("could not serialize access") ||
message.Contains("connection reset") || message.Contains("connection refused") ||
message.Contains("broken pipe"))
{
return true;
}
switch (dbType)
{
case DBType.MSSQL:
if (message.Contains("deadlock victim") || message.Contains("could not obtain lock"))
return true;
break;
case DBType.MySQL:
if (message.Contains("lock wait timeout") || message.Contains("deadlock found"))
return true;
break;
case DBType.PostgreSQL:
case DBType.HGDB:
case DBType.UX:
if (message.Contains("could not serialize access due to concurrent update") || message.Contains("deadlock detected"))
return true;
break;
case DBType.Oracle:
case DBType.GBASE8CByOracle:
if (message.Contains("ora-00060") || message.Contains("ora-00054"))
return true;
break;
case DBType.DM:
if (message.Contains("dm-4007") || message.Contains("dm-00642") || message.Contains("lock timeout"))
return true;
break;
case DBType.KingBaseR3:
case DBType.KingBaseR6:
case DBType.KingBaseR8:
if (message.Contains("could not serialize access"))
return true;
break;
}
if (ex.InnerException != null)
return IsTransientError(ex.InnerException, dbType);
return false;
}
private static int CalculateRetryDelay(int attempt, int baseRetryDelay, Random random)
{
int exponentialDelay = baseRetryDelay * (1 << attempt);
int jitter = random.Next(0, exponentialDelay + 1);
return exponentialDelay + jitter;
}
private static int RunSQL_200705_Ora(string sql, Paras paras)
{
if (sql.EndsWith(";") == true)
@@ -2745,11 +3072,11 @@ namespace BP.DA
cmd.Parameters.Add(oraP);
continue;
}
else
oraP.Value = para.val;
}
oraP.DbType = para.DAType;
cmd.Parameters.Add(oraP);
@@ -2972,7 +3299,8 @@ namespace BP.DA
if (para.val == null || para.val.ToString().Equals(""))
{
selectSQL = selectSQL.Replace("=:" + para.ParaName, " Is Null ");
}else
}
else
{
paras.Add(para);
}
@@ -3023,7 +3351,7 @@ namespace BP.DA
{
SqlConnection conn = new SqlConnection(BP.Difference.SystemConfig.AppCenterDSN);
if (conn.State != ConnectionState.Open)
if (conn.State != System.Data.ConnectionState.Open)
conn.Open();
SqlDataAdapter ada = new SqlDataAdapter(sql, conn);
ada.SelectCommand.CommandType = CommandType.Text;
@@ -4051,7 +4379,7 @@ namespace BP.DA
public static bool IsExits(string sql)
{
if (sql.ToUpper().Contains("SELECT") == false)
return DBAccess.IsExitsObject(sql);
return DBAccess.IsExitsObject(sql);
// throw new Exception("@非法的查询语句:" + sql);

View File

@@ -1322,7 +1322,7 @@ namespace BP.Difference
/// </summary>
public static string IsEnableUserLog()
{
return SystemConfig.GetValByKey("IsEnableUserLog", "0");
return SystemConfig.GetValByKey("IsEnableLog", "0");
}

View File

@@ -1086,6 +1086,12 @@ namespace BP.En
string val = this.GetValStrByKey(key);
return DataType.ParseSysDate2DateTime(val);
}
public DateTime GetValDateTimeByKey(string key)
{
string val = this.GetValStrByKey(key);
return DataType.ParseSysDate2DateTime(val);
}
public bool GetValBooleanByKey(string key, bool defval)
{

View File

@@ -808,7 +808,7 @@ namespace BP.Port
pass2 = AESHelper.AESDecrypt(pass2, key);
if (!isCharacterAndNumber(pass2))
{
return "err@新密码必须含大小写字母数字;不得含用户名;长度限制8-20个字符";
return "err@新密码必须含大小写字母数字及特殊符号;不得含用户名、登录账号;长度限制8-20个字符及不能有敏感字符;不能出现连续数字3位及以上";
}
//BCrypt加密类型
@@ -826,19 +826,78 @@ namespace BP.Port
return "执行成功.";
}
/**
* 密码强度:0 无 18-20字符,必须包含大小写字母、数字。在密码中不得包含户名
*/
* 密码强度:0:无 1:8-20字符必须大小写字母、数字和符号的组合,不得包含户名、实际姓名全拼或缩写
* 不能出现连续数字3位及以上
*/
//public bool isCharacterAndNumber(string password)
//{
// String type = SystemConfig.GetPassWordComposeType();
// //8-20位字符,必须包含大小写字母、数字。在密码中不得包含用户名
// if (type.Equals("1"))
// {
// string pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,20}$";
// if (password.Contains(this.No) || !Regex.IsMatch( password,pattern))
// {
// return false;
// }
// }
// return true;
//}
public bool isCharacterAndNumber(string password)
{
String type = SystemConfig.GetPassWordComposeType();
//8-20位字符,必须包含大小写字母、数字。在密码中不得包含用户名
string type = SystemConfig.GetPassWordComposeType();
if (type.Equals("1"))
{
string pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,20}$";
if (password.Contains(this.No) || !Regex.IsMatch( password,pattern))
string userName = this.Name;
// 全拼
string userNamePinYin = NPinyin.Pinyin.GetPinyin(userName);
// 全拼首字母
string userNamePinYinHead = NPinyin.Pinyin.GetInitials(userName);
// 必须是8-20位包含大小写字母和数字
string pattern = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,20}$";
// 8-20个字符必须为大小写字母、数字不得包含帐户名、实际姓名全拼或缩写的判断
if (password.Contains(userNamePinYin) ||
password.Contains(userNamePinYinHead) ||
password.Contains(this.No) ||
!Regex.IsMatch(password, pattern))
{
return false;
}
// 必须包含特殊符号
bool hasSpecialChar = false;
string specialChars = "!@#$%^&*()_+-=[]{};':\"|,.<>/?";
foreach (char c in password)
{
if (specialChars.Contains(c.ToString()))
{
hasSpecialChar = true;
break;
}
}
if (!hasSpecialChar)
{
return false;
}
// 敏感词判断
string sensitiveWords = SystemConfig.GetValByKey("PassWordComposeTypeSensitiveWords", "");
if (!string.IsNullOrEmpty(sensitiveWords))
{
foreach (string str in sensitiveWords.Split(','))
{
if (password.Contains(str))
{
return false;
}
}
}
// 不能出现连续数字3位及以上
Regex continuousNumbers = new Regex(@"\d{3,}");
bool isContinuousNumbers = !continuousNumbers.IsMatch(password);
return isContinuousNumbers;
}
return true;
}

View File

@@ -229,9 +229,14 @@ namespace BP.Sys
protected override bool beforeInsert()
{
/**
* 日志的标志
* 登录 退出 访问 删除
*/
//是否开启日志记录
string IsEnableUserLog = SystemConfig.IsEnableUserLog();
if (IsEnableUserLog.Equals("0") && !this.LogFlag.Equals("登录") && !this.LogFlag.Equals("退出") && !this.LogFlag.Contains("删除"))
if (IsEnableUserLog.Equals("0"))
{
return false;
}
@@ -244,57 +249,53 @@ namespace BP.Sys
this.IP=BP.Difference.Glo.GetIP;
}
if ( this.LogFlag.Equals("登录") || this.LogFlag.Equals("退出") || this.LogFlag.Equals("访问") || this.LogFlag.Contains("删除"))
if (DataType.IsNullOrEmpty(BP.Web.WebUser.No) == true)
{
if (DataType.IsNullOrEmpty(BP.Web.WebUser.No) == true)
this.EmpNo = "访客";
this.EmpName = "访客";
this.LogFlag = "访问";
}
else
{
this.Docs=WebUser.Token;
}
//退出时
// 1.宽泛模式根据toke 删除 port_token 对应数据
//2.严谨模式时根据no 修改 wf_emp 表的Atpara 字段 online=0
if (this.LogFlag.Equals("退出"))
{
//严谨模式,saas模式只有宽泛模式
if (SystemConfig.TokenModel == 1 && SystemConfig.CCBPMRunModel != CCBPMRunModel.SAAS)
{
this.EmpNo = "访客";
this.EmpName = "访客";
this.LogFlag = "访问";
string sql="select Atpara from wf_emp where No='"+ WebUser.No + "'";
string rdata= DBAccess.RunSQLReturnString(sql);
rdata = rdata.Replace("Online=1", "Online=0");
sql = "update wf_emp set Atpara='"+ rdata + "' where No='" + WebUser.No + "'";
DBAccess.RunSQL(sql);
}
else
{
this.Docs=WebUser.Token;
}
//退出时
// 1.宽泛模式根据toke 删除 port_token 对应数据
//2.严谨模式时根据no 修改 wf_emp 表的Atpara 字段 online=0
if (this.LogFlag.Equals("退出"))
{
//严谨模式,saas模式只有宽泛模式
if (SystemConfig.TokenModel == 1 && SystemConfig.CCBPMRunModel != CCBPMRunModel.SAAS)
{
string sql="select Atpara from wf_emp where No='"+ WebUser.No + "'";
string rdata= DBAccess.RunSQLReturnString(sql);
rdata = rdata.Replace("Online=1", "Online=0");
sql = "update wf_emp set Atpara='"+ rdata + "' where No='" + WebUser.No + "'";
DBAccess.RunSQL(sql);
}
else
{
String sql = "delete from port_token where mypk='" + WebUser.Token + "'";
DBAccess.RunSQL(sql);
}
}
else
{ //访客,登录 记录ip详情
try
{
string jsonString = SystemUtil.GetCityByIp();
// 将 JSON 字符串转换为对象
dynamic json = JsonConvert.DeserializeObject(jsonString);
this.IP = json.ip;
this.Locatinon = json.pro + " " + json.city;
this.Brower = SystemUtil.GetBrowser();
this.OS = SystemUtil.GetOperatingSystem();
}
catch (Exception E)
{
}
String sql = "delete from port_token where mypk='" + WebUser.Token + "'";
DBAccess.RunSQL(sql);
}
}
//访客,登录 记录ip详情
try
{
string jsonString = SystemUtil.GetCityByIp();
// 将 JSON 字符串转换为对象
dynamic json = JsonConvert.DeserializeObject(jsonString);
this.IP = json.ip;
this.Locatinon = json.pro + " " + json.city;
this.Brower = SystemUtil.GetBrowser();
this.OS = SystemUtil.GetOperatingSystem();
}
catch (Exception E)
{
}
return base.beforeInsert();
}

View File

@@ -3856,7 +3856,7 @@ namespace BP.WF
return DB_GenerWillReturnNodes_DealDT(dt, gwf.FlowNo);
}
WorkNode mywnP = wn.GetPreviousWorkNode();
WorkNode mywnP = wn.GetPreviousWorkNode("WorkReturn");
if (nd.TodolistModel == TodolistModel.Order)
@@ -5049,10 +5049,26 @@ namespace BP.WF
Token tk = new Token();
isExist = tk.IsExit("EmpNo", no);
}
if (!isExist)
//判断是否初始密码
Object type = SystemConfig.GetIsPasswordEncryptionType();
//初始密码
string yspass = "123";
string pass = DBAccess.RunSQLReturnString("select Pass from port_emp WHERE No='" + no + "'");
//BCrypt加密类型
if (type.ToString().Equals("2"))
{
yspass = BP.Tools.Cryptography.HashPassword(yspass);
}
//MD5加密类型
if (type.ToString().Equals("1"))
{
yspass = BP.Tools.Cryptography.MD5_Encrypt(yspass);
}
if (!isExist || pass.Equals(yspass))
{
WebUser.IsFirstLogin = true;
}
}
/**
* 判断是否需要强制改密码

View File

@@ -7912,13 +7912,13 @@ namespace BP.WF.HttpHandler
#region SQL转移处理
public string RunSQL_Init()
{
string sql = GetRequestVal("SQL");
DBAccess.RunSQLReturnTable(sql);
DataTable dt = new DataTable();
return BP.Tools.Json.ToJson(dt);
}
//public string RunSQL_Init()
//{
// string sql = GetRequestVal("SQL");
// DBAccess.RunSQLReturnTable(sql);
// DataTable dt = new DataTable();
// return BP.Tools.Json.ToJson(dt);
//}
#endregion

View File

@@ -5491,26 +5491,26 @@ namespace BP.WF.HttpHandler
#endregion
#region SQL转移处理
public string RunSQL_Init()
{
string sql = GetRequestVal("SQL");
string dbSrc = this.GetRequestVal("DBSrc");
DataTable dt = null;
if (DataType.IsNullOrEmpty(dbSrc) == false && dbSrc.Equals("local") == false)
{
SFDBSrc sfdb = new SFDBSrc(dbSrc);
dt = sfdb.RunSQLReturnTable(sql);
}
else
{
dt = DBAccess.RunSQLReturnTable(sql);
}
if (sql.ToUpper().Contains("PORT_EMP") == true && (dt.Columns.Contains("Pass") || dt.Columns.Contains("PASS") || dt.Columns.Contains("pass") || dt.Columns.Contains("PWS")))
{
return "";
}
return BP.Tools.Json.ToJson(dt);
}
//public string RunSQL_Init()
//{
// string sql = GetRequestVal("SQL");
// string dbSrc = this.GetRequestVal("DBSrc");
// DataTable dt = null;
// if (DataType.IsNullOrEmpty(dbSrc) == false && dbSrc.Equals("local") == false)
// {
// SFDBSrc sfdb = new SFDBSrc(dbSrc);
// dt = sfdb.RunSQLReturnTable(sql);
// }
// else
// {
// dt = DBAccess.RunSQLReturnTable(sql);
// }
// if (sql.ToUpper().Contains("PORT_EMP") == true && (dt.Columns.Contains("Pass") || dt.Columns.Contains("PASS") || dt.Columns.Contains("pass") || dt.Columns.Contains("PWS")))
// {
// return "";
// }
// return BP.Tools.Json.ToJson(dt);
//}
#endregion
// 您的应用ID

View File

@@ -2303,7 +2303,7 @@ namespace BP.WF.HttpHandler
if (i == 0)
return "该流程的工作已删除,请联系管理员.WorkID=" + this.WorkID;
if (gwf.IsOver == true)
return "该流程工作已经结束,不需要重复发送";
return "该流程工作已经结束";
Int64 workid = this.WorkID;
//如果包含subWorkID

View File

@@ -1148,21 +1148,21 @@ namespace BP.WF.HttpHandler
int currNodeID = gwf.NodeID;
//获取未来处理人的节点
Node nd = new Node(currNodeID);
GERpt rptGe = nd.HisFlow.HisGERpt;
rptGe.OID = this.WorkID;
rptGe.RetrieveFromDBSources();
if (nd.ItIsStartNode)
{
Work wk = nd.HisWork;
wk.OID=this.WorkID;
wk.Retrieve();
WorkNode wn = new WorkNode(wk, nd);
wn.rptGe = nd.HisFlow.HisGERpt;
wn.rptGe.OID=this.WorkID;
wn.rptGe = rptGe;
//执行计算未来处理人.
FullSA fsa = new FullSA();
fsa.DoIt2023(wn);
}
GERpt rptGe = nd.HisFlow.HisGERpt;
rptGe.OID = this.WorkID;
rptGe.RetrieveFromDBSources();
Node hisNode = nd;
//获取当前节点的抄送节点
nodeIDs += GetFutureCCNodes(nd, rptGe, nodeIDs);

View File

@@ -10229,7 +10229,7 @@ namespace BP.WF
/// 如果没有找到转向他的节点,就返回,当前的工作.
/// </summary>
/// <returns>得当他的上一步工作</returns>
public WorkNode GetPreviousWorkNode()
public WorkNode GetPreviousWorkNode(string workSource= "WorkUnSend")
{
// 如果没有找到转向他的节点,就返回,当前的工作.
if (this.HisNode.ItIsStartNode)
@@ -10247,16 +10247,16 @@ namespace BP.WF
//首先获取实际发送节点不存在时再使用from节点.
DataTable dt = DBAccess.RunSQLReturnTable(sql);
if (dt != null && dt.Rows.Count > 0)
foreach(DataRow dr in dt.Rows)
{
nodeid = int.Parse(dt.Rows[0]["NDFrom"].ToString());
if (dt.Rows[0]["Tag"] != null && dt.Rows[0]["Tag"].ToString().Contains("SendNode=") == true)
nodeid = int.Parse(dr["NDFrom"].ToString());
string tag = dr["Tag"] != null ? dr["Tag"].ToString() : "";
if (DataType.IsNullOrEmpty(tag) == false && tag.Contains("SendNode=") == true)
{
string tag = dt.Rows[0]["Tag"].ToString();
string[] strs = tag.Split('@');
foreach (string str in strs)
{
if (str == null || str.Equals("") || str.Contains("SendNode=") == false)
if (DataType.IsNullOrEmpty(str) || str.Contains("SendNode=") == false)
continue;
string[] mystr = str.Split('=');
if (mystr.Length == 2)
@@ -10265,9 +10265,15 @@ namespace BP.WF
if (string.IsNullOrEmpty(sendNode) == false && sendNode.Equals("0") == false)
{
nodeid = int.Parse(sendNode);
break;
}
}
}
if (workSource.Equals("WorkUnSend"))
break;
if (nodeid != this.HisNode.NodeID)
break;
nodeid = 0;
}
}

File diff suppressed because one or more lines are too long

BIN
dist.zip

Binary file not shown.