yyl
2025-06-09 b9751b2f076ee050fe5b685e91ae4fc4469b1015
Main/System/Mail/MailManager.cs
@@ -3,332 +3,329 @@
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>();
        }
    }
}
}