Files
RBMESAPICore/Controllers/Cloud/HostService/PushMesInterface.cs
yuyubohh e8494ba988 qqq
2025-09-09 22:41:29 +08:00

526 lines
26 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Microsoft.EntityFrameworkCore;
using Nancy.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RB_MES_API.Context;
using RB_MES_API.Controllers;
using RB_MES_API.Controllers.Cloud;
using RB_MES_API.Models;
using RB_MES_API.Models.Cloud;
using RB_MES_API.Models.Pangu;
using RB_MES_APICore.Models.Pangu;
using RB_MES_APICore.Models;
using System.Data;
using System.Net;
using System.Reflection;
using System.Text;
namespace RB_MES_API.HostService
{
/// <summary>
/// 定时推送服务
/// </summary>
public class PushMesInterface : IPushMesInterface,IDisposable
{
private List<Timer> _timer = new List<Timer>();
private readonly RBContext _context;
private readonly IConfiguration _config;
private readonly IShareController _shareController;
private readonly IKDCloudHttpClient _KdhttpClient;
private readonly IKDSqlHelper _kdsqlhelper;
/// <summary>
///
/// </summary>
/// <param name="context">注入的数据库连接</param>
/// <param name="shareController">共享方法</param>
/// <param name="httpClient">金蝶API</param>
/// <param name="configuration"></param>
/// <param name="kdsqlhelper"></param>
public PushMesInterface(RBContext context, IConfiguration configuration, IShareController shareController
, IKDCloudHttpClient httpClient, IKDSqlHelper kdsqlhelper)
{
_context = context;
_config = configuration;
_shareController = shareController;
_KdhttpClient = httpClient;
_kdsqlhelper = kdsqlhelper;
}
/// <inheritdoc/>
public void Dispose()
{
foreach (Timer timer in _timer)
{
timer?.Dispose();
}
}
private void DoWork(object state)
{
// 定时任务逻辑
try
{
List<CloudBillQuery> queryJsons = _shareController.GetAPIList<CloudBillQuery>().Result;
var clouds = queryJsons.Where(s => s.GetFormID.FDocType == state.ToString()).ToList();
if (clouds.Count > 0)
{
new TaskFactory().StartNew(async () =>
{
CloudBillQuery query = clouds.FirstOrDefault();
//启动新线程执行推送业务
Type type = this.GetType();
MethodInfo? methodInfo = type.GetMethod(query.GetFormID.FActionName);
if (methodInfo != null)
{
object[] para = new object[] { query.GetFormID.FID, query.GetFormID.functions.FUrl };
methodInfo.Invoke(this, para);
}
});
}
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService的BackgroundServiceWork发生错误{0}", ex.Message));
}
}
public async void DoTimerWorkAsyn()
{
await Task.Run(() => LoadLocalStaticRequest());
try
{
string v = LocalStaticRequest.GetSystemProfile(1, "AutoPushTask");
int at = 0;
int.TryParse(v, out at);
if (at > 0)
{
//只要FTimer > 0的接口都有一个属于自己的定时器
List<ApiHostService> systimeds = _shareController.GetAPIList<ApiHostService>().Result;
if (systimeds.Count == 0) { return; }
var sys = from a in systimeds
select new
{
worktime = a.FTimer,
name = a.FDocType
};
foreach (var item in sys)
{
_timer.Add(new Timer(DoWork, item.name, TimeSpan.Zero, TimeSpan.FromMinutes(item.worktime)));
}
}
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService的StartAsync发生错误{0}", ex.Message));
}
return;
}
/// <summary>
/// 优先加载系统必须的静态数据
/// </summary>
private void LoadLocalStaticRequest()
{
try
{
//如果缓存中不存在,就从数据库里取出来再放进缓存
List<SystemProfile> sys = CacheHelper.GetCache<List<SystemProfile>>("sys");
if (sys == null)
{
//先初始化全局变量
sys = _context.r_SystemProfiles!.AsNoTracking().ToList();
if (sys.Any())
{
CacheHelper.Set_AbsluteExpire("sys", sys);
}
}
LocalStaticRequest.sysprofile = sys; //定时刷新
}
catch (Exception ex)
{
//如果金蝶Cloud登录失败就会发生异常可能导致程序崩溃...
string msg = ex.Message;
LogHelper.WriteLog(string.Format("TimedHostedService的LoadHostFunctionAsync发生错误{0}", msg));
}
//将计量单位加入缓存
Thread uthread = new Thread(AddUnitCache);
uthread.Start();
//无论是否推送,静态全局设置应该首先加载
string orgid = LocalStaticRequest.GetSystemProfile(2, "DefaultORGID");
string orgno = LocalStaticRequest.GetSystemProfile(2, "DefaultORG");
LocalStaticRequest.DefaultOrgID = string.IsNullOrEmpty(orgid) ? 1 : int.Parse(orgid);
LocalStaticRequest.DefaultOrg = string.IsNullOrEmpty(orgno) ? "100" : orgno;
}
private void AddUnitCache()
{
try
{
List<BD_UNIT> units = new List<BD_UNIT>();
string messstr = string.Empty;
string fileds = "FUNITID,FNumber,FName,FIsBaseUnit,FPrecision,FDocumentStatus,FForbidStatus,FConvertDenominator,FConvertNumerator,FRoundType";
//从云星空中把所有计量单位获取过来
BillQuery queryJson = new BillQuery()
{
FieldKeys = fileds,
FormId = "BD_UNIT",
FilterString = "FDOCUMENTSTATUS='C' AND FFORBIDSTATUS='A'"
};
if (!LocalStaticRequest.Islogin)
{
if (!_KdhttpClient.LoginErp().Result)
{
return;
}
}
//从云星空查询
string jsonstr = JsonConvert.SerializeObject(queryJson);
List<object> Parameters = new List<object>();
Parameters.Add(jsonstr);
string content = JsonConvert.SerializeObject(Parameters);
string url = LocalStaticRequest.GetSystemProfile(4, "TokenUrl");
string myurl = url + "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.ExecuteBillQuery.common.kdsvc";
//string result = _KdhttpClient.AsyncRequest();
string result = _KdhttpClient.AsyncRequest(myurl, content);
//如果访问正常
if (_KdhttpClient.CloudExecuteQueryStatus(result, ref messstr))
{
//将获取到的结果转为List<BD_UNIT>
units = _shareController.GetNewObjForChild<BD_UNIT>(fileds, result, ref messstr);
CacheHelper.Set_AbsluteExpire("BD_UNIT", units);
}
}
catch (Exception e)
{
LogHelper.WriteLog(string.Format("TimedHostedService的AddUnitCache发生错误{0}", e.Message));
}
}
/// <summary>
/// 将自定义SQL查询结果推送给MES
/// </summary>
/// <param name="formtypeid"></param>
/// <param name="url"></param>
public void GetSelfDBbaseAsync(int formtypeid, string url)
{
string result = GetCustomRequestTBAsync(formtypeid);
List<CloudBillQuery> query = _shareController.GetAPIList<CloudBillQuery>().Result;
if (query.Count == 0) return;
string doctype = query.Find(s => s.FFormIDTypeID == formtypeid).GetFormID.FDocType;
if (string.IsNullOrEmpty(result)) { return; }
try
{
//可以将datatable直接转为JSON但这里约定的格式用不上
//new JsonSerializer().Deserialize(new JsonTextReader(new StringReader(result)));
JArray array = (JArray)JsonConvert.DeserializeObject(result);
if (array == null || array.Count == 0) { return; }
PanguPostBill mes = new PanguPostBill()
{
DocType = doctype,
DataSet = _shareController.GetClassList(array)
};
string json = JsonConvert.SerializeObject(mes);
////推送给MES
//PanguBreakJson mesjson = PushMesData(json).Result;
//if (mesjson.Status)
//{
// LogHelper.WriteLog(string.Format("推送【{0}】成功:{1}", doctype, json), doctype);
//}
//else
//{
// LogHelper.WriteLog(string.Format("TimedHostedService的GetSelfDBbaseAsync方法推送【{0}】失败:{1}\n原始数据{2}", doctype, mesjson.Message, json), doctype);
//}
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService推送【{0}】动态GetSelfDBbaseAsync方法出错{1}", doctype, ex.Message), doctype);
}
}
/// <summary>
/// 查询Cloud表单。注意基础资料表单查询有多用途FFieldKeys中必须有Key。同理...
/// </summary>
/// <param name="formtypeid"></param>
/// <param name="url"></param>
public async void GetBDbase(int formtypeid, string url) //动态引用
{
string reason = string.Empty;
List<CloudBillQuery> queryJsons = await _shareController.GetAPIList<CloudBillQuery>();
if (queryJsons.Count == 0)
{
LogHelper.WriteLog("TimedHostedService的GetBDbase方法_shareController.GetAPIList<CloudBillQuery>()缓存过期");
return;
}
else
{
var formtype = queryJsons.Where(s => s.GetFormID.FID == formtypeid).FirstOrDefault()!.GetFormID;
int fid = formtype.FFunctionID;
string doctype = formtype.FDocType;
var queryJson = from a in queryJsons.Where(s => s.GetFormID.FID == formtypeid)
select new BillQuery
{
FieldKeys = a.FFieldKeys.Replace("@defaultorgid", LocalStaticRequest.DefaultOrgID.ToString()).Replace("@defaultorgno", LocalStaticRequest.DefaultOrg),
FormId = a.GetFormID.FDBName,
FilterString = a.FFiledString.Replace("GETDATE", DateTime.Now.ToShortDateString()).Replace("@defaultorgid", LocalStaticRequest.DefaultOrgID.ToString()).Replace("@defaultorgno", LocalStaticRequest.DefaultOrg),
Limit = a.FLimit,
OrderString = a.FOrderString,
StartRow = a.FStartRow,
SubSystemId = a.FSubSystemID,
TopRowCount = a.FTopRowCount
};
if (queryJson.Any())
{
try
{
if (!LocalStaticRequest.Islogin)
{
await _KdhttpClient.LoginErp();
}
if (!LocalStaticRequest.Islogin)
{
reason = "KdhttpClient登录失败";
goto EBread;
}
string jsonstr = JsonConvert.SerializeObject(queryJson.FirstOrDefault());
List<object> Parameters = new List<object>() { jsonstr };
string content = JsonConvert.SerializeObject(Parameters);
//string result = _KdhttpClient.AsyncRequest();
string result = _KdhttpClient.AsyncRequest(url, content);
if (_KdhttpClient.CloudExecuteQueryStatus(result, ref reason)) //查询表单数据接口使用
{
if (!string.IsNullOrEmpty(reason)) { goto EBread; }
JArray jArray = (JArray)JsonConvert.DeserializeObject(result.ToString()!)!; //特别注意!!!
//为dt添加数据
if (jArray != null && jArray.Count > 0)
{
string fileds = queryJson.FirstOrDefault()!.FieldKeys!;
//根据字段对应关系分配字段
DataTable dt = _shareController.JsonConvertDatatable(fileds, result, ref reason);
if (!string.IsNullOrEmpty(reason)) { goto EBread; }
//DataTable dt = CreateFFieldKeys(fileds);
//由于jArray没有字段名只能先装填DataTable
//LoadDatatable(jArray, ref dt);
if (dt.Rows.Count > 0)
{
List<Dictionary<string, object>> dic = GetClassList(fid, doctype, dt);
if (dic.Any())
{
//json = JsonConvert.SerializeObject(dic);
PanguPostBill mes = new PanguPostBill()
{
DocType = doctype,
DataSet = dic
};
string json = JsonConvert.SerializeObject(mes);
////推送给MES
//PanguBreakJson mesjson = await PushMesData(json);
//if (mesjson.Status)
//{
// reason = string.Format("推送【{0}】成功:{1}", doctype, json);
//}
//else
//{
// reason = string.Format("TimedHostedService的GetBDbase方法推送【{0}】失败:{1}\r原始数据{2}", doctype, mesjson.Message, json);
//}
}
else
{
reason = string.Format("TimedHostedService的GetBDbase方法推送【{0}】失败:!GetClassList(fid, doctype, dt)Any(){1}}", doctype, result);
}
}
}
}
else
{
//将message写入错误日志
reason = string.Format("TimedHostedService的GetBDbase方法推送【{0}】返回结果:{1}", doctype, result.ToString());
}
}
catch (Exception ex)
{
reason = string.Format("TimedHostedService的GetBDbase方法推送【{0}】过程中发生错误:{1}", doctype, ex.Message);
}
}
EBread:
if (!string.IsNullOrEmpty(reason)) { LogHelper.WriteLog(reason, doctype); }
}
}
/// <summary>
/// 向第三方系统推送数据
/// </summary>
/// <param name="inputdata">推送的JSON文本</param>
/// <returns></returns>
private async Task<PanguBreakJson> PushMesData(string inputdata)
{
PanguBreakJson breadJson = new PanguBreakJson() { Status = false };
string mesurl = _config.GetConnectionString("MesUrl");
mesurl += mesurl.Substring(mesurl.Length - 1, 1) == "/" ? "" : "/"; //如果最后一个字符不是"/"就添加上去
mesurl += "updateimsdata";
HttpWebRequest reqest = (HttpWebRequest)WebRequest.Create(mesurl);
reqest.Timeout = 20 * 60 * 1000;
reqest.Method = "POST";
reqest.ContentType = "application/json";
try
{
byte[] bytes = Encoding.UTF8.GetBytes(inputdata);
reqest.ContentLength = bytes.Length;
string result = string.Empty;
reqest.GetRequestStream().Write(bytes, 0, bytes.Length);
HttpWebResponse webResponse = (HttpWebResponse)await reqest.GetResponseAsync();
//读取返回数据
StreamReader streamReader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8);
result = streamReader.ReadToEnd();
streamReader.Dispose();
webResponse.Dispose();
breadJson = JsonConvert.DeserializeObject<PanguBreakJson>(result);
}
catch (Exception ex)
{
breadJson.Message = ex.Message;
}
return breadJson;
}
/// <summary>
/// 根据字段转换的目标名称从table获取数据生成新的键值对集合。
/// 适用于定时推送任务或其他不需要存储的动态对象。与接口_shareController中同名方法有异曲同工之处
/// </summary>
/// <param name="fid">FFunctionID</param>
/// <param name="decname">目标表名</param>
/// <param name="table">需要转换的表,没有字段名</param>
/// <returns></returns>
private List<Dictionary<string, object>> GetClassList(int fid, string decname, DataTable table)
{
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
//先检查是否需要作字段转换
List<SelectClumnConvert> scc = _shareController.GetAPIList<SelectClumnConvert>().Result;
scc = scc.Where(s => s.FFunctionID == fid && s.FDesTableName.Equals(decname)).ToList();
if (scc.Any())
{
foreach (DataRow row in table.Rows)
{
Dictionary<string, object> keyValuePairs = new Dictionary<string, object>();
foreach (SelectClumnConvert clumnConvert in scc)
{
string oldname = clumnConvert.FSourceName;
if (table.Columns.Contains(oldname))
{
string newname = clumnConvert.FDesName;
keyValuePairs.Add(newname, row[oldname].ToString()!);
}
}
list.Add(keyValuePairs);
}
}
return list;
}
/// <summary>
/// 来源于接口_ChiledSelect但由于本地服务启动与依赖性注入底层冲突而不能直接调用接口
/// </summary>
/// <param name="formtypeid"></param>
/// <returns></returns>
private string GetCustomRequestTBAsync(int formtypeid)
{
//throw new NotImplementedException();
string tbjson = string.Empty;
try
{
List<CloudBillQuery> queryJsons = _shareController.GetAPIList<CloudBillQuery>().Result;
var query = queryJsons.Where(s => s.FFormIDTypeID == formtypeid).FirstOrDefault();
//查询脚本
string sql = query.FFieldKeys.Replace("@defaultorgid", LocalStaticRequest.DefaultOrgID.ToString());
if (string.IsNullOrEmpty(sql)) { return tbjson; }
//这个方法无法携带参数,只能先写在查询语句里,然后替换之...
string param = query.FFiledString.Replace("@defaultorgid", LocalStaticRequest.DefaultOrgID.ToString()).Replace("@defaultorgno", LocalStaticRequest.DefaultOrg);
if (!string.IsNullOrEmpty(param))
{
string[] strings = param.Split(',');
foreach (string s in strings)
{
string[] cs = s.Split('=');
string key = cs[0];
string value = cs[1].Replace("GETDATE", DateTime.Now.ToShortDateString()).Replace("@defaultorgid", LocalStaticRequest.DefaultOrgID.ToString());
sql = sql.Replace(key, value);
}
}
string doctype = query.GetFormID.FDocType;
string costomsql = _config.GetValue<string>("CustomRequestRemoteSql");
if (costomsql.ToUpper() == "Y")
{
string result = GetCustomReaderAsync(sql, "ExecuteDataSet");
//string errmess = string.Empty;
try
{
if (string.IsNullOrWhiteSpace(result)) { return tbjson; }
//先将返回数据格式化
JObject jobj = (JObject)JsonConvert.DeserializeObject(result);
tbjson = JsonConvert.SerializeObject(jobj["Table"]);
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService的BackgroundServiceWork({0})本地查询{1}发生错误:{2}", formtypeid, doctype, ex.Message));
}
}
else
{
string mess = string.Empty;
//实施本地化查询
DataSet dataSet = _kdsqlhelper.GetDataSet(CommandType.Text, sql, null, ref mess, true);
if (mess != null || dataSet == null)
{
LogHelper.WriteLog(string.Format("TimedHostedService的BackgroundServiceWork({0})网络查询{1}发生错误:{2}", formtypeid, doctype, mess));
}
else if (dataSet.Tables.Count != 0)
{
DataTable dataTable = dataSet.Tables[0];
tbjson = JsonConvert.SerializeObject(dataTable);
}
}
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService的BackgroundServiceWork({0})发生错误:{1}", formtypeid, ex.Message));
}
return tbjson;
}
/// <summary>
/// 来源于接口_ChiledSelect但由于本地服务启动与依赖性注入底层冲突而不能直接调用接口
/// </summary>
/// <param name="sql"></param>
/// <param name="servicesstubname"></param>
/// <returns></returns>
private string GetCustomReaderAsync(string sql, string servicesstubname)
{
string tbjson = string.Empty;
try
{
//获取自定义查询的服务器端插件地址...
string apiid = LocalStaticRequest.GetSystemProfile(1, "APIGrouID");
var sv = _context.r_CustomServices.Where(s => s.FApiGroupID == int.Parse(apiid) && s.FActionName == servicesstubname);
if (!sv.Any()) { return tbjson; }
CustomService customservice = sv.FirstOrDefault();
if (customservice == null) { return tbjson; }
//查询前必须先登录...
if (!LocalStaticRequest.Islogin) { _KdhttpClient.LoginErp(); }
if (!LocalStaticRequest.Islogin) { return tbjson; }
string url = LocalStaticRequest.GetSystemProfile(4, "TokenUrl");
url += url.Substring(url.Length - 1, 1) == "/" ? "" : "/"; //如果最后一个字符不是"/"就添加上去
url += customservice.FNamespace + "." + customservice.FClassName + "." + customservice.FActionName + "," + customservice.FAppComponents;
List<object> Parameters = new List<object>
{
sql//服务中可添加参数SqlParam[],但要引用金蝶组件!
};
string content = JsonConvert.SerializeObject(Parameters);
tbjson = _KdhttpClient.AsyncRequest(url, content);
}
catch (Exception ex)
{
LogHelper.WriteLog(string.Format("TimedHostedService的BackgroundServiceWork({0},{1})发生错误:{1}", sql, servicesstubname, ex.Message));
}
return tbjson;
//throw new NotImplementedException();
}
}
}