using BreakpointTransmission.Client; using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Configuration; using System.Data; using System.IO; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using Transmission.SDK.ThreadPool; using TransmissionClient.Model; namespace TransmissionClient { /// /// MainWindow.xaml 的交互逻辑 /// 注:修改上传/下发的内容:在本页对应配置方法中修改 /// 修改上传/下发需要传输的表及传输类型、传输表时间间隔比例【分钟】、 /// 查询服务区本地数据表SQL语句、初始化传输时间字段、初始化表信息、 /// 定义表传输状态字段、单次最大传输数量:在ConfigThread.cs类中修改 /// 修改传输方法:在Transmission.SDK中ClientThread.cs类中修改 /// OpenTopThreads、OpenDownThreads、DownLoadDataByServerpaertCode、IsStartDownData方法 /// public partial class MainWindow : Window { #region Config参数 //protected string _TransferType = ConfigurationManager.AppSettings["TransferType"].ToString(); protected string _OracleConnStr = ConfigurationManager.AppSettings["OracleConnStr"].ToString(); //protected string _HostIP = ConfigurationManager.AppSettings["HostIP"].ToString(); //protected string _HostPort = ConfigurationManager.AppSettings["HostPort"].ToString(); //protected string _ToolListen = ConfigurationManager.AppSettings["ToolListen"].ToString(); //protected string _StartApp = ConfigurationManager.AppSettings["StartApp"].ToString(); //protected string _Connectport = ConfigurationManager.AppSettings["Connectport"].ToString(); //protected string _DownloadConnString = ConfigurationManager.AppSettings["DownloadConnString"].ToString(); //protected string _ScanUpdateURL = ConfigurationManager.AppSettings["ScanUpdateURL"].ToString(); protected string _TimerInterval = ConfigurationManager.AppSettings["Interval"].ToString(); #endregion #region 参数定义 /// /// 运行状态上报时间 /// DateTime StateUploadTime; /// /// 运行状态上报线程 /// Thread StateUploadThread { get; set; } /// /// 当天已采集统计数量 /// int TodayCount = 0; /// /// 十分钟数据统计线程 /// Thread CreateDataCollectionThread { get; set; } /// /// 客单时段区段统计线程 /// Thread CreateSalesIntervalAnalysisThread { get; set; } /// /// 在线订单线程 /// Thread OnlineOrderThread { get; set; } /// /// 在线订单线程 /// Thread OldSystemExceptionThread { get; set; } /// /// 压缩文件上传线程 /// Thread FileUploadThread { get; set; } /// /// 内部会员数据传输线程 /// ClientThread MemberClientThread = new ClientThread(); /// /// 内部会员数据传输配置 /// ConfigThread MemberConfigThread = null; //配置类 /// /// 大数据上传线程 /// ClientThread StateClientThread = new ClientThread(); /// /// 大数据上传配置 /// ConfigThread StateConfigThread = null; //配置类 /// /// 移动支付相关数据上传线程 /// ClientThread MobilePayClientThread = new ClientThread(); /// /// 移动支付相关数据上传配置 /// ConfigThread MobilePayConfigThread = null; /// /// 日结营收数据上传线程 /// ClientThread BusinessClientThread = new ClientThread(); /// /// 日结营收数据上传配置 /// ConfigThread BusinessConfigThread = null; /// /// 服务区数据下载线程 /// ClientThread ServerPartClientThread = new ClientThread(); /// /// 服务区数据下载配置 /// ConfigThread ServerPartConfigThread = null; /// /// 传输客户端定时器 /// DispatcherTimer CilentTimer = new DispatcherTimer(); /// /// 在线订单传输定时器 /// DispatcherTimer OnlineOrderTimer = new DispatcherTimer(); /// /// 公共数据库连接类 /// Transmission.SDK.OracleHelper LocalOracle; /// /// 运行日志记录 /// DataTable TransResultTable; /// /// 服务区信息缓存表 /// DataTable ServerPartTable; /// /// 服务区信息缓存有效期 /// DateTime ServerPartCacheTime; /// /// 多链路配置信息 /// List TransLinkConfigList { get; set; } /// /// 多链路传输参数库配置 /// ConcurrentDictionary MulLinkConfigThreadList { get; set; } /// /// 多链路传输线程库配置 /// ConcurrentDictionary MulLinkCilentThreadList { get; set; } List TransferErrorNotify { get; set; } bool IsFirstRun = true; bool IsReplaceColumn = false; string ServerPartCode { get; set; } #endregion #region 文件传输Socket客户端 private SuperSocketClient SocketClient { get; set; } private string SocketServerpartCode { get; set; } #endregion #region 方法 -> 主窗体事件 public MainWindow() { InitializeComponent(); } /// /// 主窗体加载事件 /// /// /// private void Window_Loaded(object sender, RoutedEventArgs e) { #region 程序启动初始化 if (LocalOracle == null || !LocalOracle.ConnTest()) { LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4], _OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]); } //DataSet dataSet = LocalOracle.ExcuteSqlGetDataSet(@"select * from highway_exchange.T_COMMODITYSALE "); //绑定大数据上传回调事件 StateClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent); //绑定移动支付数据上传回调事件 MobilePayClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent); //绑定日结营收数据上传回调事件 BusinessClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent); //绑定服务区基础数据下载回调事件 ServerPartClientThread.DownloadStringEvent += new ClientThread.OutputResultsDownArg(ClientThread_DownloadStringEvent); //绑定内部会员数据上传回调事件(暂无上传) MemberClientThread.UploadStringEvent += new ClientThread.OutputResultsUploadArg(ClientThread_UploadStringEvent); //绑定内部会员数据下载回调事件 MemberClientThread.DownloadStringEvent += new ClientThread.OutputResultsDownArg(ClientThread_DownloadStringEvent); //初始化数据传输计时器 CilentTimer.Tick += CilentTimer_Tick; double timeInterval = 0; try { if (!double.TryParse(_TimerInterval, out timeInterval) || timeInterval < 1 || timeInterval > 10) { timeInterval = 5; } } catch { timeInterval = 5; } timeInterval = timeInterval * 60 * 1000; CilentTimer.Interval = TimeSpan.FromMilliseconds(timeInterval); CilentTimer.Start(); //初始化在线订单传输定时器 OnlineOrderTimer.Tick += OnlineOrderTimer_Tick; OnlineOrderTimer.Interval = TimeSpan.FromSeconds(3); OnlineOrderTimer.Start(); BtnTimerState.Content = "停止"; Title = "服务区数据传输工具 TCv" + System.Windows.Forms.Application.ProductVersion; int _FileCount = 0; string[] _masks = { ".log" }; try { //清理过期日志文件 Transmission.SDK.LogHelper.DeleteFiles( AppDomain.CurrentDomain.BaseDirectory + "\\log", new string[] { ".log" }, false, false, ref _FileCount); } catch { } #endregion } #endregion #region 方法 -> 在线订单传输定时器事件 /// /// 在线订单传输定时器事件 /// /// /// private void OnlineOrderTimer_Tick(object sender, EventArgs e) { try { string _OnlineService; try { _OnlineService = ConfigurationManager.AppSettings["OnlineService"]; } catch { _OnlineService = ""; } if (string.IsNullOrWhiteSpace(_OnlineService)) { TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。"); OnlineOrderTimer.Stop(); return; } if (LocalOracle == null || !LocalOracle.ConnTest()) { //初始化Oracle数据库连接字符串 LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4], _OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]); } //启动线上订单线程 if (OnlineOrderThread == null || !OnlineOrderThread.IsAlive) { OnlineOrderThread = new Thread(() => OnlineOrder(LocalOracle)) { IsBackground = true }; OnlineOrderThread.Start(); } } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "在线订单传输启动失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("在线订单传输启动失败:" + ex.Message); } } #endregion #region 事件 -> 主窗体按钮事件 /// /// 主窗体按钮事件 /// /// /// private void Button_Click(object sender, RoutedEventArgs e) { Button _Button = (Button)sender; switch (_Button.Name) { case "BtnTimerState": if (CilentTimer != null) { if (CilentTimer.IsEnabled) { CilentTimer.Stop(); _Button.Content = "启动"; TransResultBeginInvoke(DateTime.Now, "数据传输定时器已停止"); } else { CilentTimer.Start(); _Button.Content = "停止"; TransResultBeginInvoke(DateTime.Now, "数据传输定时器已启动"); } } else { TransResultBeginInvoke(DateTime.Now, "数据传输定时器初始化失败,请重启程序!"); } break; case "BtnClosed": if (CilentTimer != null && CilentTimer.IsEnabled) { CilentTimer.Stop(); } Close(); break; } } #endregion #region 事件 -> 主线程定时器 /// /// 主线程定时器 /// /// /// private void CilentTimer_Tick(object sender, EventArgs e) { try { #region 初始化参数 //初始化数据库连接实例 if (LocalOracle == null || !LocalOracle.ConnTest()) { LocalOracle = new Transmission.SDK.OracleHelper(_OracleConnStr.Split(',')[0], _OracleConnStr.Split(',')[4], _OracleConnStr.Split(',')[1], _OracleConnStr.Split(',')[2], _OracleConnStr.Split(',')[3]); } #endregion #region 检查服务区编码参数,未设置时,从数据库中获取 //检查服务区编码参数,未设置时,从数据库中获取 if (string.IsNullOrWhiteSpace(ServerPartCode)) { try { //从数据库中读取服务区编码信息 var _ServerPartList = from t in LocalOracle.ExcuteSqlGetDataSet( "SELECT SERVERPARTCODE FROM HIGHWAY_EXCHANGE.T_SYSCODE").Tables[0].AsEnumerable() group t by new { t1 = t.Field("SERVERPARTCODE") } into m select new { serverPartCode = m.Key.t1 }; //判断数据库中是否已读取到服务区信息 if (_ServerPartList.ToList().Count() > 0) { //多个服务区编码信息用英文逗号( , )拼接在一起,并保存到服务区信息参数属性中 ServerPartCode = string.Join(",", _ServerPartList.Select(p => p.serverPartCode)); } } catch { } } #endregion #region 启动传输链路 TransResultBeginInvoke(DateTime.Now, "正在预启动上传子线程......"); //初始化门店日结营收数据上传线程配置 if (BusinessConfigThreadConfigure()) { //启动门店日结营收数据上传线程 if (BusinessClientThread.onState(LocalOracle)) { TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动成功"); } else { TransResultBeginInvoke(DateTime.Now, "日结营收上传线程预启动失败"); } } //初始化服务区基础数据下载线程配置 if (ServerPartConfigThreadConfigure()) { //启动服务区基础数据下载线程 if (ServerPartClientThread.onState(LocalOracle)) { TransResultBeginInvoke(DateTime.Now, "服务区数据下载线程预启动成功"); } else { TransResultBeginInvoke(DateTime.Now, "服务区数据下载线程预启动失败"); } } #endregion } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "传输启动失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("传输启动失败:" + ex.Message); } } #endregion #region 事件 -> Socket客户端消息通知事件 /// /// Socket客户端消息通知事件 /// /// /// private void SocketClient_NotifyEvent(object sender, Transmission.SDK.Model.Common.NotifyEventArgs e) { string DirectoryName = AppDomain.CurrentDomain.BaseDirectory + "/SocketLog"; //记录文本日志 Transmission.SDK.LogHelper.WriteLog(e.NotifyLoggerMessage, "", DirectoryName); #region 调用云端【/WebSocket/RecordLogToOracle】接口上报Socket消息通知执行结果到云端 try { Transmission.SDK.LogHelper.WriteServiceLog($"是否调用日志上传接口:" + e.NotifyUploadState); //只有通知上传状态为True的消息才上传到云端 if (e.NotifyUploadState) { //文件上传耗时记录 string str_HttpURL = "http://pos.eshangtech.com:7198/webApi_publish/WebSocket/RecordLogToOracle"; string str_PostData = $"ServerpartCode={SocketServerpartCode}&ShopCode=000000&" + $"MachineCode=0000&LogCentent={e.NotifyLoggerMessage}&TableName={(int)e.NotifyLoggerType}" + $"&OperateTime={e.NotifyLoggerTime.ToString("yyyyMMddHHmmss")}"; string Result = Transmission.SDK.HttpDataHelper.OnPost($"{str_HttpURL}?{str_PostData}", str_PostData); Transmission.SDK.LogHelper.WriteServiceLog($"开始上传日志【{str_PostData}】,上传结果:" + Result); } } catch (Exception ex) { Transmission.SDK.LogHelper.WriteLog($"{ e.NotifyLoggerType }执行结果上报失败。原因:{ex.Message}", "", DirectoryName); } #endregion //界面显示消息内容 TransResultBeginInvoke(e.NotifyLoggerTime, e.NotifyLoggerMessage); } #endregion #region 事件 -> 检测本地数据表字段 /// /// 检测本地数据表字段 /// /// 本地数据库链接 private void CheckTableColumn(Transmission.SDK.OracleHelper localOracle) { DataBaseUpdate _DataBaseUpdate = new DataBaseUpdate(localOracle); //收银状态反馈表更新 _DataBaseUpdate.AlterTableColumn("T_STATEFEEDBACK"); //智能稽查任务表更新 _DataBaseUpdate.AlterTableColumn("T_AUDITTASKS"); //移动支付记录表更新 _DataBaseUpdate.AlterTableColumn("T_MOBILE_PAY"); //新日结营收表更新 _DataBaseUpdate.AlterTableColumn("T_ENDACCOUNT_NEW"); //旧日结营收表更新 _DataBaseUpdate.AlterTableColumn("T_ENDACCOUNT"); //门店信息表更新 _DataBaseUpdate.AlterTableColumn("T_SHOPMESSAGE_EX"); #region 表字段检测 try { localOracle.ExcuteSql("SELECT TRANSFER_STATE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE 1 = 0"); } catch { try { localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA ADD TRANSFER_STATE NUMBER(4,0)"); } catch { } } try { //修正T_BUSINESSCONFIG【业态收银配置表】主键值字段名 localOracle.ExcuteSql("SELECT USINESSCONFIG_ID FROM HIGHWAY_EXCHANGE.T_BUSINESSCONFIG WHERE 1=0"); localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_BUSINESSCONFIG RENAME COLUMN USINESSCONFIG_ID TO BUSINESSCONFIG_ID"); } catch { } try { localOracle.ExcuteSql("SELECT MEMBERSHIP_COMPANY FROM HIGHWAY_EXCHANGE.T_MEMBERSHIP WHERE 1 = 0"); } catch { try { //会员信息表增加字段所属单位【MEMBERSHIP_COMPANY】 localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_MEMBERSHIP ADD MEMBERSHIP_COMPANY NUMBER(9,0)"); } catch { } } try { localOracle.ExcuteSql("SELECT EXTERNALMEMBER_ID FROM HIGHWAY_EXCHANGE.T_MEMBERSHIP WHERE 1 = 0"); } catch { try { //会员信息表增加字段外部会员内码【EXTERNALMEMBER_ID】 localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_MEMBERSHIP ADD EXTERNALMEMBER_ID NUMBER(9,0)"); } catch { } } //自定义类别表增加数据来源字段 if (LocalOracle.ExcuteSqlGetDataSet("SELECT COLUMN_NAME FROM SYS.ALL_TAB_COLUMNS WHERE OWNER = 'HIGHWAY_EXCHANGE' AND " + "TABLE_NAME = 'T_USERDEFINEDTYPE' AND COLUMN_NAME IN ('DATA_SOURCE')").Tables[0].Rows.Count == 0) { localOracle.ExcuteSql("ALTER TABLE HIGHWAY_EXCHANGE.T_USERDEFINEDTYPE ADD (DATA_SOURCE NUMBER(1,0) DEFAULT 0)"); } #endregion } #endregion #region 事件 -> 大数据线程回传事件 private void BigData_ResultEvent(DateTime triggerTime, string resultMessage) { TransResultBeginInvoke(triggerTime, resultMessage); } #endregion #region 方法 -> 校验并更新数据库表结构 /// /// 校验并更新数据库表结构 /// /// /// private void CheckOracleTable(Transmission.SDK.OracleHelper localOracle, Dictionary checkList) { DataBaseUpdate _DataBaseUpdate = new DataBaseUpdate(localOracle); foreach (string _Key in checkList.Keys) { if (string.IsNullOrWhiteSpace(checkList[_Key])) { _DataBaseUpdate.CreateTable(_Key); } else { try { if (LocalOracle.ExcuteSqlGetDataSet("SELECT 1 FROM SYS.DBA_ALL_TABLES WHERE TABLE_NAME = '" + _Key + "' AND OWNER = 'HIGHWAY_EXCHANGE'").Tables[0].Rows.Count == 0) { if (_DataBaseUpdate.CreateTable(_Key)) { TransResultBeginInvoke(DateTime.Now, $"{checkList[_Key]}创建成功。"); } else { TransResultBeginInvoke(DateTime.Now, $"{checkList[_Key]}创建失败。"); } } } catch (Exception ex) { Transmission.SDK.LogHelper.WriteServiceLog("校验并更新数据库表结构失败:" + ex.Message); } } } } #endregion #region 方法 -> APP运行状态上报 /// /// APP运行状态上报 /// /// 数据库连接类 private void AppStateUpload(Transmission.SDK.OracleHelper localOracle) { try { if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now) { //重置服务区信息缓存表 ServerPartTable = localOracle.ExcuteSqlGetDataSet( @"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0]; if (ServerPartTable.Rows.Count == 0) { ServerPartCacheTime = DateTime.Now.AddMinutes(5); } else { ServerPartCacheTime = DateTime.Now.AddHours(1); } } //定义APP运行状态上报传输地址 string _UploadRuningStateUrl = ConfigurationManager.AppSettings["UploadRuningStateUrl"]; if (string.IsNullOrWhiteSpace(_UploadRuningStateUrl)) { TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因:参数[UploadRuningStateUrl]未配置。"); return; } foreach (DataRow ServerPartRow in ServerPartTable.Rows) { Hashtable hashtable = new Hashtable { //省份编码 { "provinceCode", ServerPartRow["PROVINCE_CODE"].ToString() }, //省份名称 { "provinceName", "" }, //服务区编码 { "serverPartCode", ServerPartRow["SERVERPART_CODE"].ToString() }, //服务区名称 { "serverPartName", ServerPartRow["SERVERPART_NAME"].ToString() }, //运行工具名称 { "appName", System.Windows.Forms.Application.ProductName }, //运行工具版本号 { "appVersion", $"TCv{System.Windows.Forms.Application.ProductVersion}" } }; //上传运行工具状态信息 Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString( $"{_UploadRuningStateUrl}/Service.asmx", "UploadTransClientState", hashtable); } } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, $"APP运行状态上报失败。原因:{ex.Message}"); } } #endregion #region 方法 -> 线上订单传输 /// /// 线上订单传输 /// /// 数据库连接类 private void OnlineOrder(Transmission.SDK.OracleHelper localOracle) { TransResultBeginInvoke(DateTime.Now, $"正在启动线上订单数据同步线程......"); try { //定义线上订单数据同步地址 string _OnlineService; try { _OnlineService = ConfigurationManager.AppSettings["OnlineService"]; } catch { _OnlineService = ""; } if (string.IsNullOrWhiteSpace(_OnlineService)) { TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:参数[OnlineService]未配置。"); return; } if (ServerPartTable == null || ServerPartCacheTime < DateTime.Now) { //重置服务区信息缓存表 ServerPartTable = localOracle.ExcuteSqlGetDataSet( @"SELECT SERVERPART_CODE,PROVINCE_CODE,SERVERPART_NAME FROM HIGHWAY_EXCHANGE.T_SERVERPART").Tables[0]; if (ServerPartTable.Rows.Count == 0) { ServerPartCacheTime = DateTime.Now.AddMinutes(5); } else { ServerPartCacheTime = DateTime.Now.AddHours(1); } } OrderOnline.OnlineTransferResult transferResult; foreach (DataRow ServerPartRow in ServerPartTable.Rows) { //分服务区下载已付款线上订单 TransResultBeginInvoke(DateTime.Now, $"正在下载[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单数据......"); transferResult = OrderOnline.OrderBillDown(localOracle, _OnlineService, ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString()); TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单下载完成;" + $"\n本次订单获取总数:{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" + $"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。"); //分服务区上传已完成、已制作订单结果 TransResultBeginInvoke(DateTime.Now, $"正在上传[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据......"); transferResult = OrderOnline.OrderBillUpload(localOracle, _OnlineService, ServerPartRow["SERVERPART_CODE"].ToString(), ServerPartRow["PROVINCE_CODE"].ToString()); TransResultBeginInvoke(DateTime.Now, $"[{ServerPartRow["SERVERPART_NAME"].ToString()}]线上订单接收结果数据上传完成;" + $"\n本次订单结果上传总数:{transferResult.TotalCount}条;成功:{transferResult.SuccessCount}条;" + $"失败:{transferResult.FailCount}条;过滤:{transferResult.FilterCount}条;耗时:{transferResult.TotalSeconds.ToString("F2")}秒。"); } } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, $"线上订单数据同步线程启动失败。原因:{ex.Message}"); } } #endregion #region 方法 -> 数据库历史数据迁移清理 /// /// 数据库历史数据迁移清理 /// /// 数据库连接 private void ClearHistoryData(Transmission.SDK.OracleHelper localOracle) { try { //删除不完整的账期记录 localOracle.ExecuteSqlTran("DELETE FROM HIGHWAY_EXCHANGE.T_ENDACCOUNT_NEW WHERE ENDDATE IS NULL"); //删除不完整的工班记录 localOracle.ExecuteSqlTran("DELETE FROM HIGHWAY_EXCHANGE.T_PERSONSELL_NEW WHERE ENDDATE IS NULL"); //迁移30天以上的移动支付记录到历史表 localOracle.ExecuteSqlTran( @"INSERT INTO HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA_HIS (SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE, SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE, SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG, SELLDATA_EXTRA_DESC,TRANSFER_STATE) SELECT SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE, SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE, SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG, SELLDATA_EXTRA_DESC,TRANSFER_STATE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 30 "); localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 30 "); //迁移15天以上并已上传的移动支付记录到历史表 localOracle.ExecuteSqlTran( @"INSERT INTO HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA_HIS (SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE, SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE, SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG, SELLDATA_EXTRA_DESC,TRANSFER_STATE) SELECT SELLDATA_ID,SELLDATA_TYPE,SELLDATA_DATE,SERVERPARTCODE, SHOPCODE,MACHINECODE,TICKETCODE,WORKERCODE,COMMODITY_CODE, SELLCOUNT,SELLPRICE,OFFPRICE,FACTAMOUNT,LINENUM,FLAG, SELLDATA_EXTRA_DESC,TRANSFER_STATE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 15 AND NVL(TRANSFER_STATE,0) = 9"); localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SELLDATA_EXTRA WHERE SELLDATA_DATE < TRUNC(SYSDATE) - 15 AND NVL(TRANSFER_STATE,0) = 9"); TransResultBeginInvoke(DateTime.Now, $"数据库移动支付历史数据迁移清理完成。"); //删除重复商品促销记录 localOracle.ExecuteSqlTran(@"DELETE FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE B WHERE (B.SERVERPARTCODE,B.SHOPCODE,B.PROMOTION_ID,B.COMMODITY_CODE) IN (SELECT A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE A GROUP BY A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE HAVING COUNT(1) > 1) AND B.SALESPROMOTE_ID NOT IN (SELECT MAX(A.SALESPROMOTE_ID) FROM HIGHWAY_EXCHANGE.T_SALESPROMOTE A GROUP BY A.SERVERPARTCODE,A.SHOPCODE,A.PROMOTION_ID,A.COMMODITY_CODE HAVING COUNT(1) > 1)"); TransResultBeginInvoke(DateTime.Now, $"重复商品促销记录清理完成。"); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, $"历史数据迁移清理失败。原因:{ex.Message}"); } } #endregion #region 方法 -> 十分钟数据采集统计 /// /// 十分钟数据采集统计 /// /// 数据库连接类 private void CreateDataCollection(Transmission.SDK.OracleHelper localOracle) { try { TransResultBeginInvoke(DateTime.Now, "正在生成今日实时采集统计数据......"); //查询已固化的每十分钟营收数据 DataTable _DataCollectionTable = localOracle.ExcuteSqlGetDataSet( @"SELECT A.SERVERPARTCODE,A.DATACOLLECTION_DATE FROM HIGHWAY_EXCHANGE.T_DATACOLLECTION A,HIGHWAY_EXCHANGE.T_SYSCODE B WHERE TRUNC(A.DATACOLLECTION_DATE) = TRUNC(SYSDATE) AND A.DATACOLLECTION_TYPE = 3000 AND A.SERVERPARTCODE = B.SERVERPARTCODE").Tables[0]; //计算已统计的服务区 int _ServerPartCount = _DataCollectionTable.DefaultView.ToTable(true, new string[] { "SERVERPARTCODE" }).Rows.Count; //获取截止当前时间,今日每个服务区应统计的条数 int _TotalCount = (int)(DateTime.Now - DateTime.Today).TotalMinutes / 10; TransResultBeginInvoke(DateTime.Now, string.Format("本次统计截止:{0}", DateTime.Today.AddMinutes((double)_TotalCount * 10).ToString())); //判断是否有未统计的营收数据 if (_DataCollectionTable.Rows.Count == 0 || _DataCollectionTable.Rows.Count < _ServerPartCount * _TotalCount) { //从T_DATACOLLECTION统计每十分钟营收数据 List _DataCollectionList = (List)Transmission.SDK.DataTableHelper.DataTableToIList( localOracle.ExcuteSqlGetDataSet(string.Format( @"SELECT A.SERVERPARTCODE,3000 AS DATACOLLECTION_TYPE, (CASE FLOOR((TO_CHAR(A.DATACOLLECTION_DATE, 'MI')) /10) WHEN 0 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((00+10) * 60-1)/86400 WHEN 1 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((10+10) * 60-1)/86400 WHEN 2 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((20+10) * 60-1)/86400 WHEN 3 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((30+10) * 60-1)/86400 WHEN 4 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((40+10) * 60-1)/86400 WHEN 5 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((50+10) * 60-1)/86400 END) AS DATACOLLECTION_DATE, NVL(SUM(A.TOTAL_COUNT),0) AS TOTAL_COUNT,NVL(SUM(A.TOTALSELL_AMOUNT),0) AS TOTALSELL_AMOUNT, NVL(SUM(A.TICKET_COUNT),0) AS TICKET_COUNT FROM HIGHWAY_EXCHANGE.T_DATACOLLECTION A,HIGHWAY_EXCHANGE.T_SYSCODE B WHERE A.DATACOLLECTION_DATE BETWEEN TRUNC(SYSDATE) AND TO_DATE('{0}','YYYY/MM/DD HH24:MI:SS') AND A.DATACOLLECTION_TYPE IN (1000,2000) AND A.SERVERPARTCODE = B.SERVERPARTCODE GROUP BY A.SERVERPARTCODE, CASE FLOOR((TO_CHAR(A.DATACOLLECTION_DATE, 'MI')) /10) WHEN 0 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((00+10) * 60-1)/86400 WHEN 1 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((10+10) * 60-1)/86400 WHEN 2 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((20+10) * 60-1)/86400 WHEN 3 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((30+10) * 60-1)/86400 WHEN 4 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((40+10) * 60-1)/86400 WHEN 5 THEN TO_DATE(TO_CHAR(A.DATACOLLECTION_DATE, 'YYYY/MM/DD HH24'), 'YYYY/MM/DD HH24:MI:SS') + ((50+10) * 60-1)/86400 END ORDER BY DATACOLLECTION_DATE", DateTime.Today.AddMinutes((double)_TotalCount * 10).ToString())).Tables[0]); //var _MaxDate = _DataCollectionList.Max(p => p.DATACOLLECTION_DATE); List _InsertList = new List(); foreach (DATACOLLECTION _DATACOLLECTION in _DataCollectionList) { //过滤已插入数据库的每十分钟营收数据 if (_DataCollectionTable.Select(string.Format("SERVERPARTCODE = '{0}' AND DATACOLLECTION_DATE = '{1}'", _DATACOLLECTION.SERVERPARTCODE, _DATACOLLECTION.DATACOLLECTION_DATE)).Count() == 0) { _InsertList.Add(_DATACOLLECTION); } } if (_InsertList.Count > 0) { Transmission.SDK.OperationDataHelper.InsertTableData(localOracle, _InsertList, "HIGHWAY_EXCHANGE.T_DATACOLLECTION", true, "DATACOLLECTION_ID", "HIGHWAY_EXCHANGE.SEQ_DATACOLLECTION.NEXTVAL"); } TransResultBeginInvoke(DateTime.Now, string.Format("今日实时采集数据统计完成:总数:{0};新增:{1}", _DataCollectionList.Count, _InsertList.Count)); TodayCount = _TotalCount; } } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "今日实时采集数据统计失败:" + ex.Message); } try { TransResultBeginInvoke(DateTime.Now, "正在清理过期实时采集数据......"); int _DeleteCount = localOracle.ExcuteSql("DELETE FROM HIGHWAY_EXCHANGE.T_DATACOLLECTION WHERE DATACOLLECTION_DATE < SYSDATE - 15"); TransResultBeginInvoke(DateTime.Now, string.Format("过期实时采集数据清理完成:本次清理{0}条。", _DeleteCount)); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "过期实时采集数据清理失败:" + ex.Message); } } #endregion #region 方法 -> 收银数据压缩文件上传 /// /// 文件上传 /// /// 上传地址 /// private void UploadDataZipFile(string uploadURL) { try { string str_BaseDirectory = Transmission.SDK.IISWorkerHelper.GetPhysicPath("PosDataUpload"); if (string.IsNullOrWhiteSpace(str_BaseDirectory)) { //区服不存在文件接收站点 TransResultBeginInvoke(DateTime.Now, $"文件接收站点【PosDataUpload】不存在。"); return; } //压缩文件保存的路径 string str_ZipFileDir = Path.Combine(str_BaseDirectory, "Upload"); if (!Directory.Exists(str_ZipFileDir)) { //压缩文件不存在,直接结束 TransResultBeginInvoke(DateTime.Now, $"无未上传的数据文件。"); return; } BreakpointUploader DataBreakpointUploader = new BreakpointUploader(1024 * 1024 * 1, UploadType.Append); DataBreakpointUploader.OnUploading += Uploader_OnUploading; //读取压缩文件存储目录下全部压缩文件 FileInfo[] file_DataFileList = new DirectoryInfo(str_ZipFileDir).GetFiles("*.zip", SearchOption.AllDirectories); foreach (FileInfo file_DataFile in file_DataFileList) { //判断压缩文件是否已上传,未上传的有效压缩文件才进行上传 if (file_DataFile.Length > 0) { TransResultBeginInvoke(DateTime.Now, $"正在上传数据文件:{file_DataFile.Name}"); Internal.Header.M_Headers = new KeyValuePair( "x-app-name", System.Web.HttpUtility.UrlEncode("TransmissionClient")); UploadStatus status = DataBreakpointUploader.Upload(file_DataFile.Directory.Name,file_DataFile.FullName, uploadURL); if (status == UploadStatus.Completed) { //等待1秒,用于释放被传输占用的文件资源 Thread.Sleep(1000); if (!Directory.Exists(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name))) { Directory.CreateDirectory(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name)); } if (File.Exists(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name, file_DataFile.Name))) { //删除已经存在的文件 File.Delete(Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name, file_DataFile.Name)); //暂停300毫秒,等待资源释放 Thread.Sleep(300); } //移动已上传的文件到备份文件夹 File.Move(file_DataFile.FullName, Path.Combine(str_BaseDirectory, "Zip", file_DataFile.Directory.Name, file_DataFile.Name)); TransResultBeginInvoke(DateTime.Now, $"数据文件:【{file_DataFile.Name}】上传成功。"); } } } } catch (Exception ex) { Transmission.SDK.LogHelper.WriteServiceLog("数据文件压缩包上传失败:" + ex.Message); } } /// /// 文件传输进度处理事件 /// /// /// private void Uploader_OnUploading(object sender, UploadEventArgs e) { TransResultBeginInvoke(DateTime.Now, $"正在上传数据文件:【{e.FileName}】已上传:{e.Position}。"); } #endregion #region 方法 -> 内部会员相关数据传输配置 private bool MemberConfigThreadConfigure() { //定义内部会员数据传输地址 string _MemberUrl; try { _MemberUrl = ConfigurationManager.AppSettings["MemberUrl"]; } catch { _MemberUrl = ""; } if (string.IsNullOrWhiteSpace(_MemberUrl)) { TransResultBeginInvoke(DateTime.Now, $"内部会员数据传输线程启动失败。原因:参数[MemberUrl]未配置。"); return false; } //初始化内部会员相关数据传输配置 if (MemberConfigThread == null) { MemberConfigThread = new ConfigThread(""); } //上传数据配置 MemberClientThread.IsUpload(true, new List { "T_RECHARGERECORD" //消费记录表【离线支付交易记录】 }); //下载数据配置 MemberClientThread.IsDownload(true, new List { "T_MEMBERSHIP", //内部会员钱包表 "T_ICCARDINFO", //IC卡信息表 "T_COMPANYAUTHORIZE" //内部会员禁止消费门店表 }); try { MemberClientThread.setConfiguration($"{_MemberUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 2); MemberClientThread.setConfigThread(MemberConfigThread); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "内部会员数据传输配置失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("内部会员数据传输配置失败:" + ex.Message); } return true; } #endregion #region 方法 -> 大数据平台相关信息上传配置 /// /// 大数据平台相关信息上传配置 /// private bool StateConfigThreadConfigure() { //初始化大数据传输地址 string _BigDataUrl; try { _BigDataUrl = ConfigurationManager.AppSettings["BigDataUrl"]; } catch { _BigDataUrl = ""; } if (string.IsNullOrWhiteSpace(_BigDataUrl)) { TransResultBeginInvoke(DateTime.Now, $"大数据平台上传线程启动失败。原因:参数[BigDataUrl]未配置。"); return false; } //初始化大数据平台相关信息上传配置 if (StateConfigThread == null) { StateConfigThread = new ConfigThread(""); } //定义上传表内容 StateClientThread.IsUpload(true, new List { //"T_DATACOLLECTION", //十分钟营收数据表 //"T_CUSTOMERINFO", //客群消费信息表 //"T_SATISFACTIONFLOW", //满意度统计表 //"T_PASSENGERFLOW", //客流统计表 //"T_VEHICLEFLOW", //车流统计表 //"T_CONNECTPOINT", //旧状态反馈表 //"T_STATEFEEDBACK", //新状态反馈表 //"T_COMMODITYANALYSIS", //单品排行统计表(前后10位)【自然日】 //"T_CUSTOMERANALYSIS", //客群分析汇总表【自然日】 //"T_SALESANALYSIS", //客单金额段统计分析表【自然日】 //"T_SALESINTERVALANALYSIS" //客单金额时段统计分析表【自然日】 }); StateClientThread.IsDownload(false); try { //设置配置参数 StateClientThread.setConfiguration($"{_BigDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 2); //配置线程参数 StateClientThread.setConfigThread(StateConfigThread); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "大数据平台上传配置失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("大数据平台上传配置失败:" + ex.Message); } return true; } #endregion #region 方法 -> 移动支付、稽核上传配置 /// /// 移动支付、稽核数据上传线程配置 /// private bool MobilePayConfigThreadConfigure() { //初始化移动支付、稽核上传地址 string _MobilePayDataUrl; try { _MobilePayDataUrl = ConfigurationManager.AppSettings["MobilePayDataUrl"]; } catch { _MobilePayDataUrl = ""; } if (string.IsNullOrWhiteSpace(_MobilePayDataUrl)) { TransResultBeginInvoke(DateTime.Now, $"移动支付数据上传线程启动失败。原因:参数[MobilePayDataUrl]未配置。"); return false; } //初始化移动支付、稽核数据上传线程配置 if (MobilePayConfigThread == null) { MobilePayConfigThread = new ConfigThread(""); } //定义上传表内容 MobilePayClientThread.IsUpload(true, new List { //"T_MOBILE_PAY", //收银前端异常支付数据表 //"T_EXCEPTION", //旧异常稽核数据表 //"T_CONSUMPTIONRECORD", //促销明细流水表 //"T_PROMOTIONRECORD", //促销明细流水表【新】--2021.04 //"T_ABNOEMALITYANALYSIS", //异常稽核汇总报表【新】 //"T_ABNORMALITY", //异常稽核主表【新】 //"T_ABNORMALITYDETAIL", //异常稽核明细表【新】 //"T_COMMODITYSALE_EX" //三方系统单品表(湖北) }); MobilePayClientThread.IsDownload(false); try { //设置配置参数 MobilePayClientThread.setConfiguration($"{_MobilePayDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 50, 2); //配置线程参数 MobilePayClientThread.setConfigThread(MobilePayConfigThread); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "移动支付、稽核数据上传配置失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("移动支付、稽核数据上传配置失败:" + ex.Message); } return true; } #endregion #region 方法 -> 日结营收上传配置 /// /// 日结营收数据上传线程配置 /// private bool BusinessConfigThreadConfigure() { //初始化日结营收数据上传地址 string _SalesDataUrl; try { _SalesDataUrl = ConfigurationManager.AppSettings["SalesDataUrl"]; } catch { _SalesDataUrl = ""; } if (string.IsNullOrWhiteSpace(_SalesDataUrl)) { TransResultBeginInvoke(DateTime.Now, $"日结营收数据上传线程启动失败。原因:参数[SalesDataUrl]未配置。"); return false; } //初始化日结营收数据上传线程配置 if (BusinessConfigThread == null) { BusinessConfigThread = new ConfigThread("", IsReplaceColumn); } //定义上传表内容 BusinessClientThread.IsUpload(true, new List { "T_ENDACCOUNT_NEW", //日结账期表【新】 "T_ENDACCOUNT", //日结账期表【旧】 "T_PERSONSELL_NEW", //收银员交班表【新】 "T_PERSONSELL", //收银员交班表【旧】 //"T_TRANSFER_SALE", //单品集合表 //"T_COMMODITYSALE", //PB老系统单品明细表 //"T_COMMODITYSALE_NEW", //新系统单品明细表 //"T_COMMODITYSALE_EXTAR" //特殊单品报表 }); BusinessClientThread.IsDownload(false); try { //设置配置参数 BusinessClientThread.setConfiguration($"{_SalesDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 20, 1); //配置线程参数 BusinessClientThread.setConfigThread(BusinessConfigThread); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "日结营收数据上传配置失败:" + ex.Message); Transmission.SDK.LogHelper.WriteServiceLog("日结营收数据上传配置失败:" + ex.Message); } return true; } #endregion #region 方法 -> 基础数据下载配置 /// /// 基础数据下载配置 /// /// private bool ServerPartConfigThreadConfigure() { string _MasterDataUrl; //设置基础数据下载配置传输地址 try { _MasterDataUrl = ConfigurationManager.AppSettings["MasterDataUrl"]; } catch { _MasterDataUrl = ""; } //运行日志委托处理事件 if (string.IsNullOrWhiteSpace(_MasterDataUrl)) { TransResultBeginInvoke(DateTime.Now, $"基础数据下载线程启动失败。原因:参数[MasterDataUrl]未配置。"); return false; } //初始化基础数据下载配置对象 if (ServerPartConfigThread == null) { ServerPartConfigThread = new ConfigThread(ServerPartCode); } //设置传输模式为下载 ServerPartClientThread.IsUpload(false); //设置需要下载的表信息 ServerPartClientThread.IsDownload(true, new List { "T_SERVERPART", //服务区 "T_SHOPMESSAGE_EX", //门店 "T_SELLWORKER_UNIT", //业主管理收银员数据 "T_SELLWORKER_CLOUD", //商户管理收银员数据 "T_COMMODITYEX_UNIT", //业主审批商品数据 "T_COMMODITYEX_CLOUD", //商户审批商品数据 "T_USERDEFINEDTYPE_UNIT", //业主管理自定义类 "T_USERDEFINEDTYPE_CLOUD", //商户管理自定义类 "T_SALESPROMOTE_EX", //促销数据表 //"T_PROMOTION", //新促销数据表 "T_MOBILEPAYCODE", //移动支付配置表【待优化】 "T_MACHINEINFO", //机器信息表 "T_CONFIGURATION", //收银系统参数配置表 "T_AUDITTASKS" //智能稽核任务表【待优化】 }); try { //设置配置参数 ServerPartClientThread.setConfiguration($"{_MasterDataUrl}/Service.asmx", "", ServerPartCode, "", "", "", "", 100, 3); //配置线程参数 ServerPartClientThread.setConfigThread(ServerPartConfigThread); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, "服务区数据下载配置失败:" + ex.Message); } return true; } #endregion #region 方法 -> 多链路传输配置 /// /// 多链路传输配置 /// /// private bool MulLinkConfigThreadConfigure() { //定义多链路传输配置获取服务地址 string str_MulLinkTransConfigUrl; try { //默认读取Config文件中设置的传输链路配置地址; str_MulLinkTransConfigUrl = ConfigurationManager.AppSettings["MulLinkTransConfigUrl"]; } catch { str_MulLinkTransConfigUrl = ""; } if (string.IsNullOrWhiteSpace(str_MulLinkTransConfigUrl)) { //未配置多链路传输配置服务地址时,使用默认地址 str_MulLinkTransConfigUrl = "http://user.eshangtech.com:7088"; //TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:参数[MulLinkTransConfigUrl]未配置。"); //return false; } if (TransLinkConfigList == null) { //当启动程序时,调用服务获取多链路传输配置 TransLinkConfigList = OnTransLinkConfig(ServerPartCode, $"{str_MulLinkTransConfigUrl}/Service.asmx"); } if (TransLinkConfigList == null || TransLinkConfigList.Count == 0) { //当云端未配置当前服务区多链路传输时,不继续初始化线程配置 TransResultBeginInvoke(DateTime.Now, $"多链路传输配置失败。原因:当前服务区云端未配置多链路传输。"); return false; } //遍历循环多链路配置列表,初始化每个链路的传输线程配置 foreach (var tlcm_TransLinkConfig in TransLinkConfigList) { //初始化链路传输数据类型,每个链路初始化一次 if (!MulLinkConfigThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID)) { MulLinkConfigThread mulLinkConfig = new MulLinkConfigThread(tlcm_TransLinkConfig.TableConfig, ServerPartCode); MulLinkConfigThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkConfig, (TransLinkID, MulLinkConfig) => mulLinkConfig); } //检查当前传输链路是否实例化传输线程配置 if (!MulLinkCilentThreadList.ContainsKey(tlcm_TransLinkConfig.TransLinkID)) { //添加当前线程配置至线程列表 MulLinkCilentThread mulLinkCilent = new MulLinkCilentThread(); //绑定多链路线程上传回调事件 mulLinkCilent.UploadStringEvent += new MulLinkCilentThread.OutputResultsUploadArg(ClientThread_UploadStringEvent); //绑定多链路线程下载回调事件 mulLinkCilent.DownloadStringEvent += new MulLinkCilentThread.OutputResultsDownArg(ClientThread_DownloadStringEvent); MulLinkCilentThreadList.AddOrUpdate(tlcm_TransLinkConfig.TransLinkID, mulLinkCilent, (TransLinkID, MulLinkCilent) => mulLinkCilent); } //根据云端链路配置,设置需要启动传输的数据类型 List _TransTableList = new List(); foreach (var tc_TableConfig in tlcm_TransLinkConfig.TableConfig) { string[] str_TableName = tc_TableConfig.TableName.Split('.'); if (str_TableName.Length > 1) { _TransTableList.Add(str_TableName[1]); //如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上:区服数据版本上传表类型【T_SERVERPARTFEEDBACK】 if (str_TableName[1] == "T_STATEFEEDBACK") { _TransTableList.Add("T_SERVERPARTFEEDBACK"); } } else { _TransTableList.Add(str_TableName[0]); //如多链路传输的数据上次给类型为状态反馈【T_STATEFEEDBACK】时需加上:区服数据版本上传表类型【T_SERVERPARTFEEDBACK】 if (str_TableName[0] == "T_STATEFEEDBACK") { _TransTableList.Add("T_SERVERPARTFEEDBACK"); } } } try { //设置上传启动的表 MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsUpload(true, _TransTableList); //设置下发启动的表 MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].IsDownload(true, _TransTableList); //设置数据传输的链路地址 MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfiguration(tlcm_TransLinkConfig.TransLinkURL, "", ServerPartCode, "", "", "", "", 20, 1); //设置数据传输线程参数 MulLinkCilentThreadList[tlcm_TransLinkConfig.TransLinkID].setConfigThread(MulLinkConfigThreadList[tlcm_TransLinkConfig.TransLinkID]); } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, $"链路[{tlcm_TransLinkConfig.TransLinkURL}]传输配置失败:" + ex.Message); } } return true; } #endregion #region 方法 -> 获取服务区多链路传输配置信息 /// /// 获取服务区多链路传输配置信息 /// /// 服务区编码,多个使用英文逗号【,】隔开,如:888888,888889 /// 多链路传输配置获取服务地址,格式:http://127.0.0.1:7080/service.asmx /// private List OnTransLinkConfig(string serverpartCode, string serviceUrl) { List tlcm_TransLinkConfigList = new List(); try { //调用云端多链路配置服务接口,获取当前服务区多链路配置信息 string str_MulLinkTransConfig = Transmission.SDK.SoapWSHelper.QuerySoapWebServiceString( serviceUrl, "GetMulLinkTransConfig", new Hashtable() { { "serverpartCodes", serverpartCode } }); if (string.IsNullOrWhiteSpace(str_MulLinkTransConfig)) { //云端接口无返回值时,返回空白配置信息 return tlcm_TransLinkConfigList; } //反序列化返回值为JSon对象 JObject jObject_MulLinkTransConfig = JObject.Parse(str_MulLinkTransConfig); if (jObject_MulLinkTransConfig.Property("IsSuccess") == null || jObject_MulLinkTransConfig.Property("IsSuccess").Value.ToString() != "1") { //当接口返回值:IsSuccess不等于1时,代表接口不成功,返回空白配置信息 return tlcm_TransLinkConfigList; } //解析多链路配置为List实体 List mlcm_MulLinkConfigModelList = jObject_MulLinkTransConfig.Property("Obj").Value.ToObject>(); //var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress, p.ServerPartCode }).Distinct().ToList(); //多链路传输地址去重 var tmp_MulLinkConfigList = mlcm_MulLinkConfigModelList.Select(p => new { p.MulLinkConfig_ID, p.InterfaceAddress }).Distinct().ToList(); //遍历循环获取到的多链路信息,转化为本地多链路配置实体属性 foreach (var _MulLinkConfig in tmp_MulLinkConfigList) { TransLinkConfigModel temp_TransLinkConfig = new TransLinkConfigModel(); //设置链路唯一标识,用于多链路线程配置识别 temp_TransLinkConfig.TransLinkID = (int)_MulLinkConfig.MulLinkConfig_ID; //设置链路传输真实服务地址 temp_TransLinkConfig.TransLinkURL = $"{_MulLinkConfig.InterfaceAddress}/Service.asmx"; //temp_TransLinkConfig.ServerPartCode = _MulLinkConfig.ServerPartCode; //设置链路传输服务区编码 temp_TransLinkConfig.ServerPartCode = serverpartCode; //设置链路传输启动的表数据类型 temp_TransLinkConfig.TableConfig = new List(); List temp_TransTable = mlcm_MulLinkConfigModelList.FindAll(p => { return p.MulLinkConfig_ID == _MulLinkConfig.MulLinkConfig_ID;//&& p.ServerPartCode == _MulLinkConfig.ServerPartCode; }); //循环添加需要启动传输的数据表类型至配置列表 for (int i = 0; i < temp_TransTable.Count; i++) { TransTableConfigModel temp_TransTableConfig = new TransTableConfigModel(); if (temp_TransTable[i].TransFrequence != null) { temp_TransTableConfig.TransFrequence = (int)temp_TransTable[i].TransFrequence.Value; } temp_TransTableConfig.TableName = temp_TransTable[i].TableName; temp_TransTableConfig.HistoryCallbackDate = temp_TransTable[i].HistoryCallBackDate; temp_TransTableConfig.HistoryCallbackDays = (int)temp_TransTable[i].HistoryCallBackDays; temp_TransTableConfig.StartTime = (int)temp_TransTable[i].StartTime; temp_TransTableConfig.EndTime = (int)temp_TransTable[i].EndTime; temp_TransLinkConfig.TableConfig.Add(temp_TransTableConfig); } tlcm_TransLinkConfigList.Add(temp_TransLinkConfig); } } catch (Exception ex) { TransResultBeginInvoke(DateTime.Now, $"多链路传输配置获取异常。原因:{ex.Message}"); } return tlcm_TransLinkConfigList; } #endregion #region 事件 -> 上传回调事件 /// /// 上传回调事件 /// /// /// private void ClientThread_UploadStringEvent(UploadResultInfo uploadResultInfo, string resultString) { if (uploadResultInfo.StartToEnd) { TransResultBeginInvoke(DateTime.Now, resultString); } else { //于窗体中显示上传结果 TransResultBeginInvoke(DateTime.Now, string.Format("上传完成:[{0}]\n     总数:{1};成功:{2};过滤:{3};失败:{5};耗时:{4}{6}", uploadResultInfo.TableName, uploadResultInfo.TotalNumber, uploadResultInfo.SuccessNumber, uploadResultInfo.FilterNumber, uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒", uploadResultInfo.TotalNumber - uploadResultInfo.SuccessNumber - uploadResultInfo.FilterNumber, (string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) ? "" : (";\n     接口错误:" + uploadResultInfo.InterfaceError)) + (string.IsNullOrWhiteSpace(uploadResultInfo.Error) ? "" : (";\n     本地错误:" + uploadResultInfo.Error)))); //若上传出现异常,则记录日志文本文件 if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(uploadResultInfo.Error)) { //接口报错,记录异常变量,延迟重试传输 if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError)) { CheckTransferErrorNotify(uploadResultInfo.TableName, uploadResultInfo.ServiceURL); } //记录接口错误信息到文本日志中,供后续排查 if (!string.IsNullOrWhiteSpace(uploadResultInfo.InterfaceError)) { Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + uploadResultInfo.InterfaceError + $"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒"}"); } //记录本地错误信息到文本日志中,供后续排查 if (!string.IsNullOrWhiteSpace(uploadResultInfo.Error)) { Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + uploadResultInfo.Error + $"\n{uploadResultInfo.TableDesc}数据上传错误:[{uploadResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{uploadResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒"}"); } } else { if (TransferErrorNotify != null) { TransferErrorNotify.RemoveAll(p => p.ServiceURL == uploadResultInfo.ServiceURL); } } } } #endregion #region 事件 -> 下载回调事件 /// /// 下载回调事件 /// /// /// private void ClientThread_DownloadStringEvent(DownResultInfo downResultInfo, string resultString) { if (downResultInfo.StartToEnd) { TransResultBeginInvoke(DateTime.Now, resultString); } else { //于窗体中显示下载结果 TransResultBeginInvoke(DateTime.Now, string.Format("下载完成:[{0}]\n     总数:{1};新增:{2};更新:{3};过滤:{4};耗时:{5}{6}", downResultInfo.TableName, downResultInfo.TotalNumber, downResultInfo.AddNumber, downResultInfo.UpNumber, downResultInfo.FilterNumber, downResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒", (string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) ? "" : (";\n     接口错误:" + downResultInfo.InterfaceError)) + (string.IsNullOrWhiteSpace(downResultInfo.Error) ? "" : (";\n     本地错误:" + downResultInfo.Error)))); //若下载出现异常,则记录日志文本文件 if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError) || !string.IsNullOrWhiteSpace(downResultInfo.Error)) { //接口报错,记录异常变量,延迟重试传输 if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError)) { CheckTransferErrorNotify(downResultInfo.TableName, downResultInfo.ServiceURL); } //记录接口错误信息到文本日志中,供后续排查 if (!string.IsNullOrWhiteSpace(downResultInfo.InterfaceError)) { Transmission.SDK.LogHelper.WriteServiceLog("接口错误:" + downResultInfo.InterfaceError + $"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒"}"); } //记录本地错误信息到文本日志中,供后续排查 if (!string.IsNullOrWhiteSpace(downResultInfo.Error)) { Transmission.SDK.LogHelper.WriteServiceLog("本地错误:" + downResultInfo.Error + $"\n{downResultInfo.TableDesc}数据获取错误:[{downResultInfo.TableName.Replace("HIGHWAY_EXCHANGE.", "")}];耗时:{downResultInfo.Elapsed.TotalSeconds.ToString("F2") + "秒"}"); } } else { if (TransferErrorNotify != null) { TransferErrorNotify.RemoveAll(p => p.ServiceURL == downResultInfo.ServiceURL); } } } } /// /// 接口异常记录缓存 /// /// 传输表名 /// 传输接口地址 private void CheckTransferErrorNotify(string tableName, string serviceURL) { //初始化缓存变量 if (TransferErrorNotify == null) { TransferErrorNotify = new List(); } //读取缓存的对应数据表传输异常变量 TransferErrorNotifyModel tenm_TransferErrorNotify = TransferErrorNotify.Find(p => p.ServiceURL == serviceURL); // if (tenm_TransferErrorNotify == null) { tenm_TransferErrorNotify = new TransferErrorNotifyModel(); //tenm_TransferErrorNotify.TableName = tableName; tenm_TransferErrorNotify.ServiceURL = serviceURL; TransferErrorNotify.Add(tenm_TransferErrorNotify); } //记录接口报错重试次数 if (tenm_TransferErrorNotify.ErrorCount < 10) { tenm_TransferErrorNotify.ErrorCount += 1; } tenm_TransferErrorNotify.LastErrorTime = DateTime.Now; if (tenm_TransferErrorNotify.ErrorCount >= 3) { tenm_TransferErrorNotify.RestartTime = DateTime.Now.AddMinutes(5); } } #endregion #region 委托 -> 运行日志委托处理事件 private delegate void DelegateTransResult(DateTime triggerTime, string resultMessage); private void TransResultBeginInvoke(DateTime triggerTime, string resultMessage) { Dispatcher.BeginInvoke(new DelegateTransResult(TransResult), new object[] { triggerTime, resultMessage }); } /// /// 运行日志呈现 /// /// 日志时间 /// 日志内容 private void TransResult(DateTime triggerTime, string resultMessage) { if (TransResultTable == null) { TransResultTable = ResultTable(); } foreach (DataRow _RowTemp in TransResultTable.Select(string.Format("TransDate < '{0}'", DateTime.Now.AddHours(-1)))) { TransResultTable.Rows.Remove(_RowTemp); } TransResultTable.AcceptChanges(); DataRow _DataRow = TransResultTable.NewRow(); _DataRow["TransDate"] = triggerTime; _DataRow["TransResult"] = resultMessage; TransResultTable.Rows.InsertAt(_DataRow, 0); DataTransResult.AutoGenerateColumns = false; DataTransResult.SelectionMode = DataGridSelectionMode.Single; DataTransResult.ItemsSource = TransResultTable.DefaultView; } /// /// 运行日志记录表结构 /// /// private DataTable ResultTable() { DataTable _DataTable = new DataTable(); _DataTable.Columns.Add("TransDate", typeof(DateTime)); _DataTable.Columns.Add("TransResult", typeof(string)); return _DataTable; } #endregion #region 方法 -> 比较两集合值是否需要更新 /// /// 方法 -> 比较两集合值 /// /// 集合 /// 集合 /// 是否区分大小写 private bool IsListCompare(List listOne, List listTwo, bool isCase = false) { if (listOne == null && listTwo == null) { return true; } if (listOne != null && listTwo != null) { if (listOne.Count == listTwo.Count) { foreach (string tempOne in listOne) { foreach (string tempTwo in listTwo) { if (isCase) { if (!tempOne.Equals(tempTwo)) { return false; } } else { if (!tempOne.ToUpper().Equals(tempTwo.ToUpper())) { return false; } } } } return true; } } return false; } #endregion } }