59 子 【常规】邮件系统 / 【常规】邮件系统-客户端 MailModel改MailManager
1 文件已重命名
2个文件已修改
1个文件已删除
1个文件已添加
597 ■■■■■ 已修改文件
Main/Mail/MailModel.cs 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/GameSystemManager/MailManager.cs 331 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Manager/GameSystemManager/MailManager.cs.meta 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA362_tagMCMailList.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA363_tagMCMailStateChange.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/Mail/MailModel.cs
File was deleted
Main/Manager/GameSystemManager/MailManager.cs
New file
@@ -0,0 +1,331 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace vnxbqy.UI
{
    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()
        {
            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 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;
            }
            return false;
        }
        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))
            {
                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)
                {
                    result.Add(kvp.Key);
                }
            }
            return result;
        }
        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)
            {
                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
                {
                    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);
        }
        //没有一个可领取的邮件
        public bool IsCanHaveMail()
        {
            return mailDataDict.Values.Any(mail =>
                mail.MailState != 3 &&
                mail.Items != null &&
                mail.Items.Count > 0
            );
        }
    }
    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()
        {
            if (string.IsNullOrEmpty(Title))
                return false;
            return Title.StartsWith("<T>") && Title.EndsWith("</T>");
        }
        /// <summary>
        /// 获取模板邮件的模板key
        /// </summary>
        /// <returns>模板key,如果不是模板邮件返回空字符串</returns>
        public string GetTemplateKey()
        {
            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>();
            }
        }
    }
}
Main/Manager/GameSystemManager/MailManager.cs.meta
Main/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA362_tagMCMailList.cs
@@ -1,10 +1,12 @@
// A3 62 邮件列表 #tagMCMailList
using vnxbqy.UI;
public class DTCA362_tagMCMailList : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA362_tagMCMailList vNetData = vNetPack as HA362_tagMCMailList;
        MailModel.Instance.UpdateMailList(vNetData);
        MailManager.Instance.UpdateMailList(vNetData);
    }
}
Main/NetworkPackage/DTCFile/ServerPack/HA3_Function/DTCA363_tagMCMailStateChange.cs
@@ -1,10 +1,12 @@
// A3 63 邮件状态变更 #tagMCMailStateChange
using vnxbqy.UI;
public class DTCA363_tagMCMailStateChange : DtcBasic
{
    public override void Done(GameNetPackBasic vNetPack)
    {
        base.Done(vNetPack);
        HA363_tagMCMailStateChange vNetData = vNetPack as HA363_tagMCMailStateChange;
        MailModel.Instance.UpdateMailStateChange(vNetData);
        MailManager.Instance.UpdateMailStateChange(vNetData);
    }
}