| | |
| | | using System.Linq; |
| | | using UnityEngine; |
| | | |
| | | namespace vnxbqy.UI |
| | | public class MailManager : GameSystemManager<MailManager> |
| | | { |
| | | public class MailManager : GameSystemManager<MailManager> |
| | | /// <summary> |
| | | /// 邮件数据字典,存储所有邮件详情 |
| | | /// Key: 邮件GUID(唯一标识) |
| | | /// Value: 邮件详细数据(MailData结构体) |
| | | /// </summary> |
| | | Dictionary<string, MailData> mailDataDict = new Dictionary<string, MailData>(); |
| | | public MailCategory nowMailCategory = MailCategory.Personal; |
| | | public Redpoint parentRedpoint = new Redpoint(MainRedDot.MailRepoint); |
| | | public Redpoint tabRedpoint0; |
| | | public Redpoint tabRedpoint1; |
| | | public event Action OnUpdateMailListEvent;// 更新邮件列表数据 |
| | | public event Action OnUpdateMailStateChangeEvent;// 更新邮件状态变更 |
| | | public readonly string dateFormat = "yyyy-MM-dd"; |
| | | public string nowUuid = string.Empty; |
| | | public override void Init() |
| | | { |
| | | /// <summary> |
| | | /// 邮件数据字典,存储所有邮件详情 |
| | | /// Key: 邮件GUID(唯一标识) |
| | | /// Value: 邮件详细数据(MailData结构体) |
| | | /// </summary> |
| | | Dictionary<string, MailData> mailDataDict = new Dictionary<string, MailData>(); |
| | | public MailCategory nowMailCategory = MailCategory.Personal; |
| | | public Redpoint parentRedpoint = new Redpoint(MainRedDot.MailRepoint); |
| | | public Redpoint tabRedpoint0; |
| | | public Redpoint tabRedpoint1; |
| | | public event Action OnUpdateMailListEvent;// 更新邮件列表数据 |
| | | public event Action OnUpdateMailStateChangeEvent;// 更新邮件状态变更 |
| | | public readonly string dateFormat = "yyyy-MM-dd"; |
| | | public string nowUuid = string.Empty; |
| | | public override void Init() |
| | | { |
| | | tabRedpoint0 = new Redpoint(MainRedDot.MailRepoint, GetTabRedpointId(MailCategory.Personal)); |
| | | tabRedpoint1 = new Redpoint(MainRedDot.MailRepoint, GetTabRedpointId(MailCategory.Global)); |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent; |
| | | } |
| | | tabRedpoint0 = new Redpoint(MainRedDot.MailRepoint, GetTabRedpointId(MailCategory.Personal)); |
| | | tabRedpoint1 = new Redpoint(MainRedDot.MailRepoint, GetTabRedpointId(MailCategory.Global)); |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent; |
| | | } |
| | | |
| | | public override void Release() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent; |
| | | } |
| | | public override void Release() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent; |
| | | } |
| | | |
| | | public void OnBeforePlayerDataInitializeEvent() |
| | | { |
| | | mailDataDict.Clear(); |
| | | } |
| | | public void OnBeforePlayerDataInitializeEvent() |
| | | { |
| | | mailDataDict.Clear(); |
| | | } |
| | | |
| | | public bool HasNoReadMail(MailCategory category) |
| | | { |
| | | var list = GetMailList(category); |
| | | if (list.IsNullOrEmpty()) |
| | | return false; |
| | | |
| | | foreach (var guid in list) |
| | | { |
| | | if (mailDataDict.TryGetValue(guid, out var mailData) && mailData.MailState == 1) |
| | | return true; |
| | | } |
| | | public bool HasNoReadMail(MailCategory category) |
| | | { |
| | | var list = GetMailList(category); |
| | | if (list.IsNullOrEmpty()) |
| | | return false; |
| | | } |
| | | |
| | | public int GetTabRedpointId(MailCategory type) |
| | | foreach (var guid in list) |
| | | { |
| | | return MainRedDot.MailRepoint * 10 + (int)type; |
| | | if (mailDataDict.TryGetValue(guid, out var mailData) && mailData.MailState == 1) |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | public void UpdatePersonalRedPoint() |
| | | public int GetTabRedpointId(MailCategory type) |
| | | { |
| | | return MainRedDot.MailRepoint * 10 + (int)type; |
| | | } |
| | | |
| | | public void UpdatePersonalRedPoint() |
| | | { |
| | | if (tabRedpoint0 == null) |
| | | return; |
| | | tabRedpoint0.state = RedPointState.None; |
| | | if (HasNoReadMail(MailCategory.Personal)) |
| | | { |
| | | if (tabRedpoint0 == null) |
| | | return; |
| | | tabRedpoint0.state = RedPointState.None; |
| | | if (HasNoReadMail(MailCategory.Personal)) |
| | | tabRedpoint0.state = RedPointState.Simple; |
| | | } |
| | | } |
| | | |
| | | public void UpdateGlobalRedPoint() |
| | | { |
| | | if (tabRedpoint1 == null) return; |
| | | tabRedpoint1.state = RedPointState.None; |
| | | if (HasNoReadMail(MailCategory.Global)) |
| | | { |
| | | tabRedpoint1.state = RedPointState.Simple; |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新邮件红点提示状态 |
| | | /// </summary> |
| | | public void UpdateRedPoint() |
| | | { |
| | | UpdatePersonalRedPoint(); |
| | | UpdateGlobalRedPoint(); |
| | | } |
| | | |
| | | public bool TryGetMailData(string uuid, out MailData mailData) |
| | | { |
| | | return mailDataDict.TryGetValue(uuid, out mailData); |
| | | } |
| | | public string FormatCreateMailTime(DateTime createDateTime) |
| | | { |
| | | TimeSpan diff = TimeUtility.ServerNow - createDateTime; |
| | | if (diff.TotalHours <= 24) |
| | | { |
| | | int hours = (int)Math.Floor(diff.TotalHours); |
| | | return Language.Get("Mail05", hours); |
| | | } |
| | | else |
| | | { |
| | | return createDateTime.ToString(dateFormat); |
| | | } |
| | | } |
| | | |
| | | //返回有效期天数(正数=已过期天数,负数=剩余天数) |
| | | public int GetMailExpiryDays(DateTime createDateTime, int limitDays) |
| | | { |
| | | DateTime expiryDate = createDateTime.AddDays(limitDays); |
| | | return (int)(TimeUtility.ServerNow - expiryDate).TotalDays; |
| | | } |
| | | |
| | | |
| | | public List<string> GetMailList(MailCategory mailCategory) |
| | | { |
| | | var result = new List<string>(); |
| | | foreach (var kvp in mailDataDict) |
| | | { |
| | | if (kvp.Value.Category == mailCategory) |
| | | { |
| | | tabRedpoint0.state = RedPointState.Simple; |
| | | result.Add(kvp.Key); |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public void UpdateGlobalRedPoint() |
| | | public List<string> GetSortMailScrList(MailCategory mailCategory) |
| | | { |
| | | List<string> resList = GetMailList(mailCategory); |
| | | return resList.OrderByDescending(guid => mailDataDict[guid].CreateDateTime).ToList(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新邮件列表数据 |
| | | /// </summary> |
| | | /// <param name="vNetData">从服务器接收的邮件列表数据包</param> |
| | | public void UpdateMailList(HA362_tagMCMailList vNetData) |
| | | { |
| | | if (vNetData == null) return; |
| | | |
| | | // 更新邮件数据字典 |
| | | foreach (var mail in vNetData.MailList) |
| | | { |
| | | if (tabRedpoint1 == null) return; |
| | | tabRedpoint1.state = RedPointState.None; |
| | | if (HasNoReadMail(MailCategory.Global)) |
| | | var category = vNetData.IsServerMail == 1 ? MailCategory.Global : MailCategory.Personal; |
| | | var mailData = new MailData(); |
| | | |
| | | mailData.Category = category; |
| | | mailData.GUID = mail.GUID; |
| | | mailData.Type = mail.Type; |
| | | mailData.CreateTime = mail.CreateTime; |
| | | mailData.CreateDateTime = Convert.ToDateTime(UIHelper.GetTime(mail.CreateTime)); |
| | | mailData.LimitDays = mail.LimitDays; |
| | | mailData.Title = mail.Title; |
| | | mailData.Text = mail.Text; |
| | | mailData.MailState = mail.MailState; |
| | | |
| | | mailData.Items = mail.Items?.Select(i => new MailItemData |
| | | { |
| | | tabRedpoint1.state = RedPointState.Simple; |
| | | } |
| | | ItemID = i.ItemID, |
| | | Count = i.Count, |
| | | IsBind = i.IsBind, |
| | | UserData = i.UserData |
| | | }).ToList(); |
| | | mailDataDict[mail.GUID] = mailData; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新邮件红点提示状态 |
| | | /// </summary> |
| | | public void UpdateRedPoint() |
| | | { |
| | | UpdatePersonalRedPoint(); |
| | | UpdateGlobalRedPoint(); |
| | | } |
| | | UpdateRedPoint(); |
| | | OnUpdateMailListEvent?.Invoke(); |
| | | } |
| | | |
| | | public bool TryGetMailData(string uuid, out MailData mailData) |
| | | /// <summary> |
| | | /// 更新邮件状态变更 |
| | | /// </summary> |
| | | /// <param name="vNetData">从服务器接收的邮件状态变更数据包</param> |
| | | public void UpdateMailStateChange(HA363_tagMCMailStateChange vNetData) |
| | | { |
| | | if (vNetData == null || vNetData.MailList == null) return; |
| | | |
| | | foreach (var stateChange in vNetData.MailList) |
| | | { |
| | | return mailDataDict.TryGetValue(uuid, out mailData); |
| | | } |
| | | public string FormatCreateMailTime(DateTime createDateTime) |
| | | { |
| | | TimeSpan diff = TimeUtility.ServerNow - createDateTime; |
| | | if (diff.TotalHours <= 24) |
| | | if (mailDataDict.TryGetValue(stateChange.GUID, out var mailData)) |
| | | { |
| | | int hours = (int)Math.Floor(diff.TotalHours); |
| | | return Language.Get("Mail05", hours); |
| | | } |
| | | else |
| | | { |
| | | return createDateTime.ToString(dateFormat); |
| | | } |
| | | } |
| | | |
| | | //返回有效期天数(正数=已过期天数,负数=剩余天数) |
| | | public int GetMailExpiryDays(DateTime createDateTime, int limitDays) |
| | | { |
| | | DateTime expiryDate = createDateTime.AddDays(limitDays); |
| | | return (int)(TimeUtility.ServerNow - expiryDate).TotalDays; |
| | | } |
| | | |
| | | |
| | | public List<string> GetMailList(MailCategory mailCategory) |
| | | { |
| | | var result = new List<string>(); |
| | | foreach (var kvp in mailDataDict) |
| | | { |
| | | if (kvp.Value.Category == mailCategory) |
| | | if (stateChange.MailState == 4) |
| | | { |
| | | result.Add(kvp.Key); |
| | | mailDataDict.Remove(stateChange.GUID); |
| | | continue; |
| | | } |
| | | mailData.MailState = stateChange.MailState; |
| | | mailDataDict[stateChange.GUID] = mailData; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | public List<string> GetSortMailScrList(MailCategory mailCategory) |
| | | UpdateRedPoint(); |
| | | OnUpdateMailStateChangeEvent?.Invoke(); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 阅读邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID</param> |
| | | public void ReadMail(string GUID) |
| | | { |
| | | if (string.IsNullOrEmpty(GUID)) |
| | | { |
| | | List<string> resList = GetMailList(mailCategory); |
| | | return resList.OrderByDescending(guid => mailDataDict[guid].CreateDateTime).ToList(); |
| | | Debug.LogError("阅读邮件GUID不能为空"); |
| | | return; |
| | | } |
| | | SendRequestMail(GUID, 0); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新邮件列表数据 |
| | | /// </summary> |
| | | /// <param name="vNetData">从服务器接收的邮件列表数据包</param> |
| | | public void UpdateMailList(HA362_tagMCMailList vNetData) |
| | | { |
| | | if (vNetData == null) return; |
| | | /// <summary> |
| | | /// 领取邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID,为空时批量领取所有邮件</param> |
| | | public void ClaimMail(string GUID = null) |
| | | { |
| | | SendRequestMail(GUID, 1); |
| | | } |
| | | |
| | | // 更新邮件数据字典 |
| | | foreach (var mail in vNetData.MailList) |
| | | { |
| | | var category = vNetData.IsServerMail == 1 ? MailCategory.Global : MailCategory.Personal; |
| | | var mailData = new MailData(); |
| | | /// <summary> |
| | | /// 删除邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID,为空时批量删除已领取或无物品的已读邮件</param> |
| | | public void DeleteMail(string GUID = null) |
| | | { |
| | | SendRequestMail(GUID, 2); |
| | | } |
| | | |
| | | mailData.Category = category; |
| | | mailData.GUID = mail.GUID; |
| | | mailData.Type = mail.Type; |
| | | mailData.CreateTime = mail.CreateTime; |
| | | mailData.CreateDateTime = Convert.ToDateTime(UIHelper.GetTime(mail.CreateTime)); |
| | | mailData.LimitDays = mail.LimitDays; |
| | | mailData.Title = mail.Title; |
| | | mailData.Text = mail.Text; |
| | | mailData.MailState = mail.MailState; |
| | | |
| | | mailData.Items = mail.Items?.Select(i => new MailItemData |
| | | { |
| | | ItemID = i.ItemID, |
| | | Count = i.Count, |
| | | IsBind = i.IsBind, |
| | | UserData = i.UserData |
| | | }).ToList(); |
| | | mailDataDict[mail.GUID] = mailData; |
| | | } |
| | | |
| | | UpdateRedPoint(); |
| | | OnUpdateMailListEvent?.Invoke(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 更新邮件状态变更 |
| | | /// </summary> |
| | | /// <param name="vNetData">从服务器接收的邮件状态变更数据包</param> |
| | | public void UpdateMailStateChange(HA363_tagMCMailStateChange vNetData) |
| | | { |
| | | if (vNetData == null || vNetData.MailList == null) return; |
| | | |
| | | foreach (var stateChange in vNetData.MailList) |
| | | { |
| | | if (mailDataDict.TryGetValue(stateChange.GUID, out var mailData)) |
| | | { |
| | | if (stateChange.MailState == 4) |
| | | { |
| | | mailDataDict.Remove(stateChange.GUID); |
| | | continue; |
| | | } |
| | | mailData.MailState = stateChange.MailState; |
| | | mailDataDict[stateChange.GUID] = mailData; |
| | | } |
| | | } |
| | | |
| | | UpdateRedPoint(); |
| | | OnUpdateMailStateChangeEvent?.Invoke(); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 阅读邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID</param> |
| | | public void ReadMail(string GUID) |
| | | { |
| | | if (string.IsNullOrEmpty(GUID)) |
| | | { |
| | | Debug.LogError("阅读邮件GUID不能为空"); |
| | | return; |
| | | } |
| | | SendRequestMail(GUID, 0); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 领取邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID,为空时批量领取所有邮件</param> |
| | | public void ClaimMail(string GUID = null) |
| | | { |
| | | SendRequestMail(GUID, 1); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 删除邮件 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID,为空时批量删除已领取或无物品的已读邮件</param> |
| | | public void DeleteMail(string GUID = null) |
| | | { |
| | | SendRequestMail(GUID, 2); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 发送邮件请求到服务器 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID</param> |
| | | /// <param name="ReqType">请求类型 0-设置已读,1-领取邮件,2-删除邮件</param> |
| | | public void SendRequestMail(string GUID, byte ReqType) |
| | | { |
| | | CA537_tagCMRequestMail pack = new CA537_tagCMRequestMail(); |
| | | pack.GUID = GUID; |
| | | pack.ReqType = ReqType; |
| | | GameNetSystem.Instance.SendInfo(pack); |
| | | } |
| | | /// <summary> |
| | | /// 发送邮件请求到服务器 |
| | | /// </summary> |
| | | /// <param name="GUID">邮件GUID</param> |
| | | /// <param name="ReqType">请求类型 0-设置已读,1-领取邮件,2-删除邮件</param> |
| | | public void SendRequestMail(string GUID, byte ReqType) |
| | | { |
| | | CA537_tagCMRequestMail pack = new CA537_tagCMRequestMail(); |
| | | pack.GUID = GUID; |
| | | pack.ReqType = ReqType; |
| | | GameNetSystem.Instance.SendInfo(pack); |
| | | } |
| | | |
| | | //没有一个可领取的个人邮件 |
| | | public bool IsCanHaveMail() |
| | | { |
| | | var personalMails = GetMailList(MailCategory.Personal); |
| | | return personalMails.Any(guid => |
| | | mailDataDict.TryGetValue(guid, out var mail) && |
| | | mail.MailState != 3 && |
| | | mail.Items != null && |
| | | mail.Items.Count > 0 |
| | | ); |
| | | } |
| | | } |
| | | |
| | | public enum MailCategory |
| | | //没有一个可领取的个人邮件 |
| | | public bool IsCanHaveMail() |
| | | { |
| | | Personal = 0, // 个人邮件 |
| | | Global = 1 // 全服邮件 |
| | | var personalMails = GetMailList(MailCategory.Personal); |
| | | return personalMails.Any(guid => |
| | | mailDataDict.TryGetValue(guid, out var mail) && |
| | | mail.MailState != 3 && |
| | | mail.Items != null && |
| | | mail.Items.Count > 0 |
| | | ); |
| | | } |
| | | } |
| | | |
| | | public class MailItemData |
| | | public enum MailCategory |
| | | { |
| | | Personal = 0, // 个人邮件 |
| | | Global = 1 // 全服邮件 |
| | | } |
| | | |
| | | public class MailItemData |
| | | { |
| | | public uint ItemID; //物品ID |
| | | public uint Count; //数量 |
| | | public byte IsBind; //是否绑定 |
| | | public string UserData; //自定义数据 |
| | | } |
| | | |
| | | public class MailData |
| | | { |
| | | public MailCategory Category; |
| | | public string GUID; //邮件GUID |
| | | public byte Type; //邮件类型,暂时默认0 |
| | | public string CreateTime; //创建时间 |
| | | public DateTime CreateDateTime; |
| | | public byte LimitDays; //有效天数 |
| | | public string Title; //标题 |
| | | public string Text; //内容 |
| | | public byte MailState; //邮件状态: 0-未知;1-未读;2-已读;3-已领; |
| | | public List<MailItemData> Items; //物品信息 |
| | | |
| | | /// <summary> |
| | | /// 判断是否为模板类型邮件 |
| | | /// </summary> |
| | | /// <returns>true-模板邮件, false-普通邮件</returns> |
| | | public bool IsTemplateMail() |
| | | { |
| | | public uint ItemID; //物品ID |
| | | public uint Count; //数量 |
| | | public byte IsBind; //是否绑定 |
| | | public string UserData; //自定义数据 |
| | | if (string.IsNullOrEmpty(Title)) |
| | | return false; |
| | | |
| | | return Title.StartsWith("<T>") && Title.EndsWith("</T>"); |
| | | } |
| | | |
| | | public class MailData |
| | | /// <summary> |
| | | /// 获取模板邮件的模板key |
| | | /// </summary> |
| | | /// <returns>模板key,如果不是模板邮件返回空字符串</returns> |
| | | public string GetTemplateKey() |
| | | { |
| | | public MailCategory Category; |
| | | public string GUID; //邮件GUID |
| | | public byte Type; //邮件类型,暂时默认0 |
| | | public string CreateTime; //创建时间 |
| | | public DateTime CreateDateTime; |
| | | public byte LimitDays; //有效天数 |
| | | public string Title; //标题 |
| | | public string Text; //内容 |
| | | public byte MailState; //邮件状态: 0-未知;1-未读;2-已读;3-已领; |
| | | public List<MailItemData> Items; //物品信息 |
| | | if (!IsTemplateMail()) |
| | | return string.Empty; |
| | | |
| | | /// <summary> |
| | | /// 判断是否为模板类型邮件 |
| | | /// </summary> |
| | | /// <returns>true-模板邮件, false-普通邮件</returns> |
| | | public bool IsTemplateMail() |
| | | // 模板格式: <T>key</T> |
| | | // 跳过开头的"<T>" (3字符) |
| | | // 取中间部分,总长度减去"<T>"和"</T>"共7字符 |
| | | const int prefixLength = 3; // "<T>"长度 |
| | | const int suffixLength = 4; // "</T>"长度 |
| | | return Title.Substring(prefixLength, Title.Length - (prefixLength + suffixLength)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取模板邮件的参数列表 |
| | | /// </summary> |
| | | /// <returns>参数列表,如果不是模板邮件或参数为空则返回空列表</returns> |
| | | public List<string> GetTemplateParams() |
| | | { |
| | | if (!IsTemplateMail() || string.IsNullOrEmpty(Text)) |
| | | return new List<string>(); |
| | | |
| | | try |
| | | { |
| | | if (string.IsNullOrEmpty(Title)) |
| | | return false; |
| | | |
| | | return Title.StartsWith("<T>") && Title.EndsWith("</T>"); |
| | | // 参数格式为JSON数组:[参数1, 参数2, ...] |
| | | return JsonUtility.FromJson<List<string>>(Text); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取模板邮件的模板key |
| | | /// </summary> |
| | | /// <returns>模板key,如果不是模板邮件返回空字符串</returns> |
| | | public string GetTemplateKey() |
| | | catch |
| | | { |
| | | if (!IsTemplateMail()) |
| | | return string.Empty; |
| | | |
| | | // 模板格式: <T>key</T> |
| | | // 跳过开头的"<T>" (3字符) |
| | | // 取中间部分,总长度减去"<T>"和"</T>"共7字符 |
| | | const int prefixLength = 3; // "<T>"长度 |
| | | const int suffixLength = 4; // "</T>"长度 |
| | | return Title.Substring(prefixLength, Title.Length - (prefixLength + suffixLength)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取模板邮件的参数列表 |
| | | /// </summary> |
| | | /// <returns>参数列表,如果不是模板邮件或参数为空则返回空列表</returns> |
| | | public List<string> GetTemplateParams() |
| | | { |
| | | if (!IsTemplateMail() || string.IsNullOrEmpty(Text)) |
| | | return new List<string>(); |
| | | |
| | | try |
| | | { |
| | | // 参数格式为JSON数组:[参数1, 参数2, ...] |
| | | return JsonUtility.FromJson<List<string>>(Text); |
| | | } |
| | | catch |
| | | { |
| | | return new List<string>(); |
| | | } |
| | | return new List<string>(); |
| | | } |
| | | } |
| | | } |
| | | } |