using System; using System.Data; using System.Collections; using BP.DA; using BP.Web; using BP.En; using BP.Port; using BP.Sys; using System.Threading; using System.Collections.Generic; using BP.Difference; using System.Web; namespace BP.WF.Template { /// /// 推送的方式 /// public enum PushWay { /// /// 当前节点的接受人 /// CurrentWorkers, /// /// 指定节点的工作人员 /// NodeWorker, /// /// 指定的工作人员s /// SpecEmps, /// /// 指定的工作角色s /// SpecStations, /// /// 指定的部门人员 /// SpecDepts, /// /// 指定的SQL /// SpecSQL, /// /// 按照系统指定的字段 /// ByParas } /// /// 消息推送属性 /// public class PushMsgAttr { /// /// 流程编号 /// public const string FK_Flow = "FK_Flow"; /// /// 节点 /// public const string FK_Node = "FK_Node"; /// /// 事件 /// public const string FK_Event = "FK_Event"; /// /// 推送方式 /// public const string PushWay = "PushWay"; /// /// 推送处理内容 /// public const string PushDoc = "PushDoc"; /// /// 推送处理内容 tag. /// public const string Tag = "Tag"; #region 消息设置. /// /// 是否启用发送邮件 /// public const string MailEnable = "MailEnable"; /// /// 消息标题 /// public const string MailTitle = "MailTitle"; /// /// 消息内容模版 /// public const string MailDoc = "MailDoc"; /// /// 是否启用短信 /// public const string SMSEnable = "SMSEnable"; /// /// 短信内容模版 /// public const string SMSDoc = "SMSDoc"; /// /// 是否推送? /// public const string MobilePushEnable = "MobilePushEnable"; #endregion 消息设置. /// /// 短信字段 /// public const string SMSField = "SMSField"; /// /// 接受短信的节点. /// public const string SMSNodes = "SMSNodes"; /// /// 推送方式 /// public const string SMSPushWay = "SMSPushWay"; /// /// 短消息发送设置 /// public const string SMSPushModel = "SMSPushModel"; /// /// 邮件字段 /// public const string MailAddress = "MailAddress"; /// /// 邮件推送方式 /// public const string MailPushWay = "MailPushWay"; /// /// 推送邮件的节点s /// public const string MailNodes = "MailNodes"; /// /// 按照指定的SQL /// public const string BySQL = "BySQL"; /// /// 发送给指定的接受人 /// public const string ByEmps = "ByEmps"; } /// /// 消息推送 /// public class PushMsg : EntityMyPK { #region 基本属性 /// /// 流程编号 /// public string FK_Flow { get { return this.GetValStringByKey(PushMsgAttr.FK_Flow); } set { this.SetValByKey(PushMsgAttr.FK_Flow, value); } } /// /// 事件 /// public string FK_Event { get { return this.GetValStringByKey(PushMsgAttr.FK_Event); } set { this.SetValByKey(PushMsgAttr.FK_Event, value); } } /// /// 推送方式. /// public int PushWay { get { return this.GetValIntByKey(PushMsgAttr.PushWay); } set { this.SetValByKey(PushMsgAttr.PushWay, value); } } /// ///节点 /// public int FK_Node { get { return this.GetValIntByKey(PushMsgAttr.FK_Node); } set { this.SetValByKey(PushMsgAttr.FK_Node, value); } } public string PushDoc { get { string s = this.GetValStringByKey(PushMsgAttr.PushDoc); if (DataType.IsNullOrEmpty(s) == true) s = ""; return s; } set { this.SetValByKey(PushMsgAttr.PushDoc, value); } } public string Tag { get { string s = this.GetValStringByKey(PushMsgAttr.Tag); if (DataType.IsNullOrEmpty(s) == true) s = ""; return s; } set { this.SetValByKey(PushMsgAttr.Tag, value); } } #endregion #region 事件消息. /// /// 邮件推送方式 /// public int MailPushWay { get { return this.GetValIntByKey(PushMsgAttr.MailPushWay); } set { this.SetValByKey(PushMsgAttr.MailPushWay, value); } } /// /// 推送方式Name /// public string MailPushWayText { get { if (this.FK_Event == EventListNode.WorkArrive) { if (this.MailPushWay == 0) return "不发送"; if (this.MailPushWay == 1) return "发送给当前节点的所有处理人"; if (this.MailPushWay == 2) return "向指定的字段发送"; } if (this.FK_Event == EventListNode.SendSuccess) { if (this.MailPushWay == 0) return "不发送"; if (this.MailPushWay == 1) return "发送给下一个节点的所有接受人"; if (this.MailPushWay == 2) return "向指定的字段发送"; } if (this.FK_Event == EventListNode.ReturnAfter) { if (this.MailPushWay == 0) return "不发送"; if (this.MailPushWay == 1) return "发送给被退回的节点处理人"; if (this.MailPushWay == 2) return "向指定的字段发送"; } return "未知"; } } /// /// 邮件地址 /// public string MailAddress { get { return this.GetValStringByKey(PushMsgAttr.MailAddress); } set { this.SetValByKey(PushMsgAttr.MailAddress, value); } } /// /// 邮件标题. /// public string MailTitle { get { string str = this.GetValStrByKey(PushMsgAttr.MailTitle); if (DataType.IsNullOrEmpty(str) == false) return str; switch (this.FK_Event) { case EventListNode.WorkArrive: return "新工作{{Title}},发送人@WebUser.No,@WebUser.Name"; case EventListNode.SendSuccess: return "新工作{{Title}},发送人@WebUser.No,@WebUser.Name"; case EventListNode.ShitAfter: return "移交来的新工作{{Title}},移交人@WebUser.No,@WebUser.Name"; case EventListNode.ReturnAfter: return "被退回来{{Title}},退回人@WebUser.No,@WebUser.Name"; case EventListNode.UndoneAfter: return "工作被撤销{{Title}},发送人@WebUser.No,@WebUser.Name"; case EventListNode.AskerReAfter: return "加签新工作{{Title}},发送人@WebUser.No,@WebUser.Name"; case EventListFlow.FlowOverAfter: return "流程{{Title}}已经结束,处理人@WebUser.No,@WebUser.Name"; case EventListFlow.AfterFlowDel: return "流程{{Title}}已经删除,处理人@WebUser.No,@WebUser.Name"; default: throw new Exception("@该事件类型没有定义默认的消息模版:" + this.FK_Event); break; } return str; } } /// /// Email节点s /// public string MailNodes { get { return this.GetValStringByKey(PushMsgAttr.MailNodes); } set { this.SetValByKey(PushMsgAttr.MailNodes, value); } } /// /// 邮件标题 /// public string MailTitle_Real { get { string str = this.GetValStrByKey(PushMsgAttr.MailTitle); return str; } set { this.SetValByKey(PushMsgAttr.MailTitle, value); } } /// /// 邮件内容 /// public string MailDoc_Real { get { return this.GetValStrByKey(PushMsgAttr.MailDoc); } set { this.SetValByKey(PushMsgAttr.MailDoc, value); } } public string MailDoc { get { string str = this.GetValStrByKey(PushMsgAttr.MailDoc); if (DataType.IsNullOrEmpty(str) == false) return str; switch (this.FK_Event) { case EventListNode.WorkArrive: str += "\t\n您好:"; str += "\t\n 有新工作{{Title}}需要您处理, 点击这里打开工作报告{Url} ."; str += "\t\n "; str += "\t\n "; str += "\t\n致! "; str += "\t\n @WebUser.No, @WebUser.Name"; str += "\t\n @RDT"; break; case EventListNode.SendSuccess: str += "\t\nHi,您好您有新工作."; str += "\t\n 标题:{{Title}} ."; str += "\t\n 单号:{{BillNo}} ."; str += "\t\n 详细信息:请打开工作{Url} "; str += "\t\n "; str += "\t\n "; str += "\t\n 致!! "; str += "\t\n @WebUser.No, @WebUser.Name"; str += "\t\n @RDT"; break; case EventListNode.ReturnAfter: str += "\t\n您好:"; str += "\t\n 工作{{Title}}被退回来了, 点击这里打开工作报告{Url} ."; str += "\t\n 退回意见: \t\n "; str += "\t\n { @ReturnMsg }"; str += "\t\n "; str += "\t\n "; str += "\t\n "; str += "\t\n 致! "; str += "\t\n @WebUser.No,@WebUser.Name"; str += "\t\n @RDT"; break; case EventListNode.ShitAfter: str += "\t\n 您好:"; str += "\t\n 移交给您的工作{{Title}}, 点击这里打开工作{Url} ."; str += "\t\n 致! "; str += "\t\n "; str += "\t\n "; str += "\t\n "; str += "\t\n @WebUser.No,@WebUser.Name"; str += "\t\n @RDT"; break; case EventListNode.UndoneAfter: str += "\t\n您好:"; str += "\t\n 移交给您的工作{{Title}}, 点击这里打开工作报告{Url} ."; str += "\t\n "; str += "\t\n "; str += "\t\n "; str += "\t\n 致! "; str += "\t\n @WebUser.No,@WebUser.Name"; str += "\t\n @RDT"; break; case EventListNode.AskerReAfter: //加签. str += "\t\n您好:"; str += "\t\n 移交给您的工作{{Title}}, 点击这里打开报告{Url} ."; str += "\t\n "; str += "\t\n "; str += "\t\n "; str += "\t\n 致! "; str += "\t\n @WebUser.No,@WebUser.Name"; str += "\t\n @RDT"; break; case EventListFlow.FlowOverAfter: //流程结束后. str += "\t\n您好:"; str += "\t\n 工作{{Title}}已经结束, 点击这里打开工作报告{Url} ."; str += "\t\n 致! "; str += "\t\n @WebUser.No,@WebUser.Name"; str += "\t\n @RDT"; break; default: throw new Exception("@该事件类型没有定义默认的消息模版:" + this.FK_Event); break; } return str; } } /// /// 短信接收人字段 /// public string SMSField { get { return this.GetValStringByKey(PushMsgAttr.SMSField); } set { this.SetValByKey(PushMsgAttr.SMSField, value); } } public string SMSNodes { get { return this.GetValStringByKey(PushMsgAttr.SMSNodes); } set { this.SetValByKey(PushMsgAttr.SMSNodes, value); } } public string SMSPushModel { get { return this.GetValStringByKey(PushMsgAttr.SMSPushModel); } set { this.SetValByKey(PushMsgAttr.SMSPushModel, value); } } /// /// 短信提醒方式 /// public int SMSPushWay { get { return this.GetValIntByKey(PushMsgAttr.SMSPushWay); } set { this.SetValByKey(PushMsgAttr.SMSPushWay, value); } } /// /// 发送消息标签 /// public string SMSPushWayText { get { if (this.FK_Event == EventListNode.WorkArrive) { if (this.SMSPushWay == 0) return "不发送"; if (this.SMSPushWay == 1) return "发送给当前节点的所有处理人"; if (this.SMSPushWay == 2) return "向指定的字段发送"; } if (this.FK_Event == EventListNode.SendSuccess) { if (this.SMSPushWay == 0) return "不发送"; if (this.SMSPushWay == 1) return "发送给下一个节点的所有接受人"; if (this.SMSPushWay == 2) return "向指定的字段发送"; } if (this.FK_Event == EventListNode.ReturnAfter) { if (this.SMSPushWay == 0) return "不发送"; if (this.SMSPushWay == 1) return "发送给被退回的节点处理人"; if (this.SMSPushWay == 2) return "向指定的字段发送"; } if (this.FK_Event == EventListFlow.FlowOverAfter) { if (this.SMSPushWay == 0) return "不发送"; if (this.SMSPushWay == 1) return "发送给所有节点处理人"; if (this.SMSPushWay == 2) return "向指定的字段发送"; } return "未知"; } } /// /// 短信模版内容 /// public string SMSDoc_Real { get { string str = this.GetValStrByKey(PushMsgAttr.SMSDoc); return str; } set { this.SetValByKey(PushMsgAttr.SMSDoc, value); } } /// /// 短信模版内容 /// public string SMSDoc { get { string str = this.GetValStrByKey(PushMsgAttr.SMSDoc); if (DataType.IsNullOrEmpty(str) == false) return str; switch (this.FK_Event) { case EventListNode.WorkArrive: case EventListNode.SendSuccess: str = "有新工作{{Title}}需要您处理, 发送人:@WebUser.No, @WebUser.Name,打开{Url} ."; break; case EventListNode.ReturnAfter: str = "工作{{Title}}被退回,退回人:@WebUser.No, @WebUser.Name,打开{Url} ."; break; case EventListNode.ShitAfter: str = "移交工作{{Title}},移交人:@WebUser.No, @WebUser.Name,打开{Url} ."; break; case EventListNode.UndoneAfter: str = "工作撤销{{Title}},撤销人:@WebUser.No, @WebUser.Name,打开{Url}."; break; case EventListNode.AskerReAfter: //加签. str = "工作加签{{Title}},加签人:@WebUser.No, @WebUser.Name,打开{Url}."; break; case EventListFlow.FlowOverAfter: //加签. str = "流程{{Title}}已经结束,最后处理人:@WebUser.No, @WebUser.Name,打开{Url}."; break; default: throw new Exception("@该事件类型没有定义默认的消息模版:" + this.FK_Event); break; } return str; } set { this.SetValByKey(PushMsgAttr.SMSDoc, value); } } /// /// 按照指定的SQL /// public string BySQL { get { return this.GetValStrByKey(PushMsgAttr.BySQL); } set { this.SetValByKey(PushMsgAttr.BySQL, value); } } /// /// 发送给指定的人员,人员之间以逗号分割 /// public string ByEmps { get { return this.GetValStrByKey(PushMsgAttr.ByEmps); } set { this.SetValByKey(PushMsgAttr.ByEmps, value); } } #endregion #region 构造方法 /// /// 消息推送 /// public PushMsg() { } /// /// 重写基类方法 /// public override Map EnMap { get { if (this._enMap != null) return this._enMap; Map map = new Map("WF_PushMsg", "消息推送"); map.AddMyPK(); map.AddTBString(PushMsgAttr.FK_Flow, null, "流程", true, false, 0, 5, 10); map.AddTBInt(PushMsgAttr.FK_Node, 0, "节点", true, false); map.AddTBString(PushMsgAttr.FK_Event, null, "事件类型", true, false, 0, 20, 10); #region 将要删除. map.AddDDLSysEnum(PushMsgAttr.PushWay, 0, "推送方式", true, false, PushMsgAttr.PushWay, "@0=按照指定节点的工作人员@1=按照指定的工作人员@2=按照指定的工作角色@3=按照指定的部门@4=按照指定的SQL@5=按照系统指定的字段"); //设置内容. map.AddTBString(PushMsgAttr.PushDoc, null, "推送保存内容", true, false, 0, 3500, 10); map.AddTBString(PushMsgAttr.Tag, null, "Tag", true, false, 0, 500, 10); #endregion 将要删除. #region 短消息. map.AddTBInt(PushMsgAttr.SMSPushWay, 0, "短消息发送方式", true, true); map.AddTBString(PushMsgAttr.SMSField, null, "短消息字段", true, false, 0, 100, 10); map.AddTBStringDoc(PushMsgAttr.SMSDoc, null, "短消息内容模版", true, false, true); map.AddTBString(PushMsgAttr.SMSNodes, null, "SMS节点s", true, false, 0, 100, 10); // 邮件,站内消息,短信,钉钉,微信,WebServices. map.AddTBString(PushMsgAttr.SMSPushModel, "", "短消息发送设置", true, false, 0, 50, 10); #endregion 短消息. #region 邮件. map.AddTBInt(PushMsgAttr.MailPushWay, 0, "邮件发送方式", true, true); map.AddTBString(PushMsgAttr.MailAddress, null, "邮件字段", true, false, 0, 100, 10); map.AddTBString(PushMsgAttr.MailTitle, null, "邮件标题模版", true, false, 0, 200, 20, true); map.AddTBStringDoc(PushMsgAttr.MailDoc, null, "邮件内容模版", true, false, true); map.AddTBString(PushMsgAttr.MailNodes, null, "Mail节点s", true, false, 0, 100, 10); #endregion 邮件. map.AddTBString(PushMsgAttr.BySQL, null, "按照SQL计算", true, false, 0, 500, 10); map.AddTBString(PushMsgAttr.ByEmps, null, "发送给指定的人员", true, false, 0, 100, 10); map.AddTBAtParas(500); this._enMap = map; return this._enMap; } } #endregion /// /// 生成提示信息. /// /// private string generAlertMessage = null; /// /// 执行消息发送 /// /// 当前节点 /// 数据实体 /// 参数 /// 发送返回对象 /// 跳转到的节点 /// 跳转到的人员 /// 执行成功的消息 public string DoSendMessage(Node currNode, Entity en, string atPara, SendReturnObjs objs, Node jumpToNode = null, string jumpToEmps = null) { if (en == null) return ""; #region 处理参数. Row r = en.Row; try { //系统参数. r.Add("FK_MapData", en.ClassID); } catch { r["FK_MapData"] = en.ClassID; } if (atPara != null) { AtPara ap = new AtPara(atPara); foreach (string s in ap.HisHT.Keys) { try { r.Add(s, ap.GetValStrByKey(s)); } catch { r[s] = ap.GetValStrByKey(s); } } } //生成标题. Int64 workid = Int64.Parse(en.PKVal.ToString()); string title = "标题"; if (en.Row.ContainsKey("Title") == true) { title = en.GetValStringByKey("Title"); // 获得工作标题. if (DataType.IsNullOrEmpty(title)) title = DBAccess.RunSQLReturnStringIsNull("SELECT Title FROM WF_GenerWorkFlow WHERE WorkID=" + en.PKVal, "标题"); } else title = DBAccess.RunSQLReturnStringIsNull("SELECT Title FROM WF_GenerWorkFlow WHERE WorkID=" + en.PKVal, "标题"); //生成URL. string hostUrl = BP.WF.Glo.HostURL; string sid = DBAccess.GenerGUID() + "_" + workid + "_{EmpStr}_" + currNode.NodeID; string openWorkURl = ""; if (BP.Difference.SystemConfig.CCBPMRunModel == CCBPMRunModel.SAAS) { //openWorkURl = hostUrl + "/App/Portal/GuideWeiXin.aspx?DoType=OpenWork&WorkID=" + workid + "&FK_Flow=" + currNode.FK_Flow + "&GUID=" + WebUser.SID; openWorkURl = ""; } else openWorkURl = hostUrl + "WF/Do.htm?DoType=OF&Token=" + sid; openWorkURl = openWorkURl.Replace("//", "/"); openWorkURl = openWorkURl.Replace("http:/", "http://"); #endregion // 有可能是退回信息. 翻译. if (jumpToEmps == null) { if (atPara != null) { AtPara ap = new AtPara(atPara); jumpToEmps = ap.GetValStrByKey("SendToEmpIDs"); } } //发送消息 string msg = this.SendMessage(title, en, currNode, workid, jumpToEmps, openWorkURl, objs, r); return msg; } #region 多线程信号量 private static SemaphoreSlim _semaphore = new SemaphoreSlim(100); //限制最大并发数为100 #endregion /// /// 发送消息 /// /// 标题 /// 数据实体 /// 当前节点 /// 流程WorkId /// 下一个节点的接收人 /// 打开链接的URL /// 发送返回的对象 /// 表单数据HashTable /// private string SendMessage(string title, Entity en, Node currNode, Int64 workid, string jumpToEmps, string openUrl, SendReturnObjs objs, Row r) { //不启用消息. if (this.SMSPushWay == 0) return ""; string atParas = "@FK_Flow=" + currNode.FK_Flow + "@WorkID=" + workid + "@NodeID=" + currNode.NodeID + "@FK_Node=" + currNode.NodeID; string generAlertMessage = ""; //定义要返回的提示消息. string mailTitle = this.MailTitle;// 邮件标题. string smsDoc = this.SMSDoc;//消息模板. #region 邮件标题 mailTitle = this.MailTitle; mailTitle = mailTitle.Replace("{Title}", title); mailTitle = mailTitle.Replace("@WebUser.No", WebUser.No); mailTitle = mailTitle.Replace("@WebUser.Name", WebUser.Name); #endregion 邮件标题 #region 处理消息内容 smsDoc = smsDoc.Replace("{Title}", title); smsDoc = smsDoc.Replace("{Url}", openUrl); smsDoc = smsDoc.Replace("@WebUser.No", WebUser.No); smsDoc = smsDoc.Replace("@WebUser.Name", WebUser.Name); smsDoc = smsDoc.Replace("@WorkID", en.PKVal.ToString()); smsDoc = smsDoc.Replace("@OID", en.PKVal.ToString()); /*如果仍然有没有替换下来的变量.*/ if (smsDoc.Contains("@") == true) smsDoc = BP.WF.Glo.DealExp(smsDoc, en, null); #region 初始化线程池 HttpContext ctx = HttpContextHelper.Current; // 设置最大线程 ThreadPool.SetMaxThreads(100,100); // 设置最小线程 ThreadPool.SetMinThreads(8, 8); #endregion 初始化线程池 if (this.FK_Event == BP.Sys.EventListNode.ReturnAfter) { //获取退回原因 Paras ps = new Paras(); //ps.SQL = "SELECT BeiZhu,ReturnerName,IsBackTracking FROM WF_ReturnWork WHERE WorkID=" + BP.Difference.SystemConfig.AppCenterDBVarStr + "WorkID ORDER BY RDT DESC"; ps.SQL = "SELECT Msg,EmpFrom FROM ND"+Int32.Parse(this.FK_Flow)+"Track WHERE (ActionType=2 OR ActionType=201) AND WorkID=" + BP.Difference.SystemConfig.AppCenterDBVarStr + "WorkID ORDER BY RDT DESC"; ps.Add(ReturnWorkAttr.WorkID, Int64.Parse(en.PKVal.ToString())); DataTable retunWdt = DBAccess.RunSQLReturnTable(ps); if (retunWdt.Rows.Count != 0) { string returnMsg = retunWdt.Rows[0][0].ToString(); string returner = retunWdt.Rows[0][1].ToString(); smsDoc = smsDoc.Replace("ReturnMsg", returnMsg); } } #endregion 处理消息内容 string toEmpIDs = ""; #region 表单字段作为接受人 if (this.SMSPushWay == 2) { /*从字段里取数据. */ string toEmp = r[this.SMSField] as string; //修改内容 smsDoc = smsDoc.Replace("{EmpStr}", toEmp); openUrl = openUrl.Replace("{EmpStr}", toEmp); //发送消息 BP.WF.Dev2Interface.Port_SendMessage(toEmp, smsDoc, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); return "@已向:{" + toEmp + "}发送提醒信息."; } #endregion 表单字段作为接受人 #region 如果发送给指定的节点处理人,就计算出来直接退回,任何方式的处理人都是一致的. if (this.SMSPushWay == 3) { /*如果向指定的字段作为发送邮件的对象, 从字段里取数据. */ string[] nodes = this.SMSNodes.Split(','); string msg = ""; foreach (string nodeID in nodes) { if (DataType.IsNullOrEmpty(nodeID) == true) continue; string sql = "SELECT EmpFromT AS Name,EmpFrom AS No FROM ND" + int.Parse(this.FK_Flow) + "Track A WHERE A.ActionType=1 AND A.WorkID=" + workid + " AND A.NDFrom=" + nodeID; DataTable dt = DBAccess.RunSQLReturnTable(sql); if (dt.Rows.Count == 0) continue; CountdownEvent cdEvent = new CountdownEvent(dt.Rows.Count); foreach (DataRow dr in dt.Rows) { ThreadPool.QueueUserWorkItem(obj => { try { _semaphore.Wait(); HttpContext.Current = ctx; string empName = dr["Name"].ToString(); string empNo = dr["No"].ToString(); // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", empName); openUrl = openUrl.Replace("{EmpStr}", empNo); string paras = "@FK_Flow=" + this.FK_Flow + "@WorkID=" + workid + "@FK_Node=" + this.FK_Node + "_" + empNo; //发送消息. BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); //处理短消息. toEmpIDs += empName + ","; } catch (Exception ex) { BP.DA.Log.DebugWriteError("写入失败, 用户id [" + dr["No"].ToString() + "], " + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); } cdEvent.Wait(); } return "@已向:{" + toEmpIDs + "}发送了短消息提醒."; } #endregion 如果发送给指定的节点处理人, 就计算出来直接退回, 任何方式的处理人都是一致的. #region 按照SQL计算 if (this.SMSPushWay == 4) { string bySQL = this.BySQL; if (DataType.IsNullOrEmpty(BySQL) == true) return "按照指定的SQL发送消息,SQL数据不能为空"; bySQL = bySQL.Replace("~", "'"); //替换SQL中的参数 bySQL = bySQL.Replace("@WebUser.No", WebUser.No); bySQL = bySQL.Replace("@WebUser.Name", WebUser.Name); bySQL = bySQL.Replace("@WebUser.FK_DeptNameOfFull", WebUser.FK_DeptNameOfFull); bySQL = bySQL.Replace("@WebUser.FK_DeptName", WebUser.FK_DeptName); bySQL = bySQL.Replace("@WebUser.FK_Dept", WebUser.FK_Dept); /*如果仍然有没有替换下来的变量.*/ if (bySQL.Contains("@") == true) bySQL = BP.WF.Glo.DealExp(bySQL, en, null); DataTable dt = DBAccess.RunSQLReturnTable(bySQL); if (dt.Rows.Count == 0) return "没有要发送的对象"; CountdownEvent cdEvent = new CountdownEvent(dt.Rows.Count); foreach (DataRow dr in dt.Rows) { ThreadPool.QueueUserWorkItem(o => { _semaphore.Wait(); try { HttpContext.Current = ctx; string empName = dr["Name"].ToString(); string empNo = dr["No"].ToString(); // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", empName); openUrl = openUrl.Replace("{EmpStr}", empNo); string paras = "@FK_Flow=" + this.FK_Flow + "@WorkID=" + workid + "@FK_Node=" + this.FK_Node + "_" + empNo; //发送消息 BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); //处理短消息. toEmpIDs += empName + ","; } catch (Exception ex) { BP.DA.Log.DebugWriteError("写入失败, 用户id [" + dr["No"].ToString() + "], " + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); } cdEvent.Wait(); return "@已向:{" + toEmpIDs + "}发送了短消息提醒."; } #endregion 按照SQL计算 #region 发送给指定的接收人 if (this.SMSPushWay == 5) { if (DataType.IsNullOrEmpty(this.ByEmps) == true) return "发送给指定的人员,则人员集合不能为空。"; //以逗号分割开 string[] toEmps = this.ByEmps.Split(','); List empList = new List(); foreach (string empNo in toEmps) { if (DataType.IsNullOrEmpty(empNo) == true) continue; empList.Add(empNo); } if (empList.Count == 0) return "没有要发送的对象"; CountdownEvent cdEvent = new CountdownEvent(empList.Count); empList.ForEach(empStr => { string empNo = empStr; ThreadPool.QueueUserWorkItem(o => { _semaphore.Wait(); try { HttpContext.Current = ctx; BP.WF.Port.WFEmp emp = new BP.WF.Port.WFEmp(empNo); // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", emp.Name); openUrl = openUrl.Replace("{EmpStr}", emp.No); //发送消息 BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); //处理短消息. toEmpIDs += emp.Name + ","; } catch (Exception ex) { BP.DA.Log.DebugWriteError("发送给指定的人员[" + empNo + "]失败," + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); }); cdEvent.Wait(); return "@已向:{" + toEmpIDs + "}发送了短消息提醒."; } #endregion 发送给指定的接收人 #region 发送给流程发起人 if (this.SMSPushWay ==6) { GenerWorkFlow gwf = new GenerWorkFlow(workid); string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", gwf.StarterName); openUrl = openUrl.Replace("{EmpStr}", gwf.Starter); //发送消息 BP.WF.Dev2Interface.Port_SendMessage(gwf.Starter, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); //处理短消息. toEmpIDs += gwf.StarterName + ","; return "@已向:{" + toEmpIDs + "}发送了短消息提醒."; } #endregion 发送给流程发起人 #region 不同的消息事件,接收人不同的处理 if (this.SMSPushWay == 1) { #region 工作到达、退回、移交、撤销 if ((this.FK_Event == BP.Sys.EventListNode.WorkArrive || this.FK_Event == BP.Sys.EventListNode.ReturnAfter || this.FK_Event == BP.Sys.EventListNode.ShitAfter || this.FK_Event == BP.Sys.EventListNode.UndoneAfter) && DataType.IsNullOrEmpty(jumpToEmps) == false) { /*当前节点的处理人.*/ toEmpIDs = jumpToEmps; string[] myEmpStrs = toEmpIDs.Split(','); List empList = new List(); foreach (string empNo in myEmpStrs) { if (DataType.IsNullOrEmpty(empNo)) continue; empList.Add(empNo); } if (empList.Count == 0) return "没有要发送的对象"; CountdownEvent cdEvent = new CountdownEvent(empList.Count); empList.ForEach(empStr => { string empNo = empStr; ThreadPool.QueueUserWorkItem(obj => { _semaphore.Wait(); try { HttpContext.Current = ctx; // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", empNo); openUrl = openUrl.Replace("{EmpStr}", empNo); BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); } catch (Exception ex) { BP.DA.Log.DebugWriteError("发送消息给[" + empNo + "]失败" + ", 原因:" + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); }); cdEvent.Wait(); return "@已向:{" + toEmpIDs + "}发送提醒信息."; } #endregion 工作到达、退回、移交、撤销 #region 节点发送成功后 if (this.FK_Event == BP.Sys.EventListNode.SendSuccess && objs != null && objs.VarAcceptersID != null) { /*如果向接受人发送消息.*/ toEmpIDs = objs.VarAcceptersID; string toEmpNames = objs.VarAcceptersName; string[] myEmpStrs = toEmpIDs.Split(','); List empList = new List(); foreach (string empNo in myEmpStrs) { if (DataType.IsNullOrEmpty(empNo)) continue; empList.Add(empNo); } if (empList.Count == 0) return "没有要发送的对象"; CountdownEvent cdEvent = new CountdownEvent(empList.Count); empList.ForEach(emp => { string empNo = emp; ThreadPool.QueueUserWorkItem(o => { _semaphore.Wait(); try { HttpContext.Current = ctx; // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", empNo); openUrl = openUrl.Replace("{EmpStr}", empNo); BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDocReal, mailTitle, this.FK_Event, "WKAlt" + objs.VarToNodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); } catch (Exception ex) { BP.DA.Log.DebugWriteError("发送消息给[" + empNo + "]失败" + ", 原因:" + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); }); cdEvent.Wait(); return "@已向:{" + toEmpNames + "}发送提醒信息."; } #endregion 节点发送成功后 #region 流程结束后、流程删除后 if (this.FK_Event == BP.Sys.EventListFlow.FlowOverAfter || this.FK_Event == BP.Sys.EventListFlow.AfterFlowDel) { /*向所有参与人发送消息. */ DataTable dt = DBAccess.RunSQLReturnTable("SELECT Emps,TodoEmps FROM WF_GenerWorkFlow WHERE WorkID=" + workid); if (dt.Rows.Count == 0) return ""; string empsStrs = ""; foreach (DataRow dr in dt.Rows) { empsStrs += dr["Emps"]; string todoEmps = dr["TodoEmps"].ToString(); if (DataType.IsNullOrEmpty(todoEmps) == false) { string[] strs = todoEmps.Split(';'); todoEmps = ""; foreach (string str in strs) { if (DataType.IsNullOrEmpty(str) == true || empsStrs.Contains(str) == true) continue; empsStrs += str.Split(',')[0] + "@"; } } } string[] myEmpStrs = empsStrs.Split('@'); string empNo = ""; List empList = new List(); foreach (string str in myEmpStrs) { if (DataType.IsNullOrEmpty(str)) continue; empList.Add(str); } if (empList.Count == 0) return "没有要发送消息的对象"; CountdownEvent cdEvent = new CountdownEvent(empList.Count); empList.ForEach(emp => { string str = emp; ThreadPool.QueueUserWorkItem(o => { _semaphore.Wait(); try { HttpContext.Current = ctx; empNo = str; if (str.IndexOf(",") != -1) empNo = str.Split(',')[0]; // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDoccReal = smsDoc.Clone() as string; smsDoccReal = smsDoccReal.Replace("{EmpStr}", empNo); openUrl = openUrl.Replace("{EmpStr}", empNo); //发送消息 BP.WF.Dev2Interface.Port_SendMessage(empNo, smsDoccReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); } catch (Exception ex) { BP.DA.Log.DebugWriteError("发送消息给[" + empNo + "]失败" + ", 原因:" + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); }); cdEvent.Wait(); return "@已向:{" + empsStrs + "}发送提醒信息."; } #endregion 流程结束后、流程删除后 #region 节点预警、逾期 if (this.FK_Event == BP.Sys.EventListNode.NodeWarning || this.FK_Event == BP.Sys.EventListNode.NodeOverDue) { //获取当前节点的接收人 GenerWorkFlow gwf = new GenerWorkFlow(workid); string[] myEmpStrs = gwf.TodoEmps.Split(';'); List empList = new List(); foreach (string emp in myEmpStrs) { if (DataType.IsNullOrEmpty(emp)) continue; string[] empA = emp.Split(','); if (DataType.IsNullOrEmpty(empA[0]) == true || empA[0] == WebUser.No) continue; empList.Add(empA); } if (empList.Count == 0) return "没有需要发送的对象"; CountdownEvent cdEvent = new CountdownEvent(empList.Count); empList.ForEach(empNo => { string[] empA = empNo; ThreadPool.QueueUserWorkItem(o => { _semaphore.Wait(); try { HttpContext.Current = ctx; // 因为要发给不同的人,所有需要clone 一下,然后替换发送. string smsDocReal = smsDoc.Clone() as string; smsDocReal = smsDocReal.Replace("{EmpStr}", empA[0]); openUrl = openUrl.Replace("{EmpStr}", empA[0]); BP.WF.Dev2Interface.Port_SendMessage(empA[0], smsDocReal, mailTitle, this.FK_Event, "WKAlt" + currNode.NodeID + "_" + workid, BP.Web.WebUser.No, openUrl, this.SMSPushModel, workid, null, atParas); } catch (Exception ex) { BP.DA.Log.DebugWriteError("发送消息给[" + empA[0] + "]失败" + ", 原因:" + ex.Message); } finally { cdEvent.Signal(); _semaphore.Release(); } }); }); cdEvent.Wait(); return "@已向:{" + toEmpIDs + "}发送提醒信息."; } #endregion 节点预警、逾期 } #endregion 不同的消息事件,接收人不同的处理 return ""; } /// /// 发送短信到其它节点的处理人. /// private void SendShortMessageToSpecNodeWorks() { } protected override bool beforeUpdateInsertAction() { // this.setMyPK(this.FK_Event + "_" + this.FK_Node + "_" + this.PushWay; // string sql = "UPDATE WF_PushMsg SET FK_Flow=(SELECT FK_Flow FROM WF_Node WHERE NodeID= WF_PushMsg.FK_Node)"; // DBAccess.RunSQL(sql); return base.beforeUpdateInsertAction(); } } /// /// 消息推送 /// public class PushMsgs : EntitiesMyPK { /// /// 消息推送 /// public PushMsgs() { } /// /// 消息推送 /// /// 流程编号 public PushMsgs(string flowNo) { //this.RetrieveFromCash(PushMsgAttr.FK_Flow, flowNo); this.Retrieve(PushMsgAttr.FK_Flow, flowNo); } /// /// 消息推送 /// /// 节点ID public PushMsgs(int nodeid) { // this.RetrieveFromCash(PushMsgAttr.FK_Node, nodeid); this.Retrieve(PushMsgAttr.FK_Node, nodeid); } /// /// 得到它的 Entity /// public override Entity GetNewEntity { get { return new PushMsg(); } } #region 为了适应自动翻译成java的需要,把实体转换成List. /// /// 转化成 java list,C#不能调用. /// /// List public System.Collections.Generic.IList ToJavaList() { return (System.Collections.Generic.IList)this; } /// /// 转化成list /// /// List public System.Collections.Generic.List Tolist() { System.Collections.Generic.List list = new System.Collections.Generic.List(); for (int i = 0; i < this.Count; i++) { list.Add((PushMsg)this[i]); } return list; } #endregion 为了适应自动翻译成java的需要,把实体转换成List. } }