using System; using PhxhSDK; using Framework; using UnityEngine; using System.Linq; using Gameplay.Net; using cfg.RedPoint; using Newtonsoft.Json; using UnityEngine.Networking; using Cysharp.Threading.Tasks; using System.Collections.Generic; using System.Text.RegularExpressions; using Constants = Framework.Constants; public class NoticeDataForDisplay { public int ID; public string Title; public E_NoticeType Type; public int LinkType; public Sprite Bannersprite; public Sprite ContentSprite; public string Content; public bool Rotate; public string UpdateTime; public RedPointNodeNotice RedPointNodeNotice; } /// /// 公告类型 /// public enum E_NoticeType { None = 0, /// /// 系统 /// System = 1, /// /// 活动 /// Activity = 2, /// /// 通行证 /// BattlePass = 3, } public class NoticeManager : Singlenton, IInitable { private const string NoticePost = "notices"; private const int NoticeRedNod = 100; /// /// 公告请求结果 /// private class NoticeGetResult { public int code; public string message; public List data; } /// /// link_type: 1-内链, 2-外链(需点击跳转链接后红点才消失) /// is_swiper: 1-需轮播, 2-否 /// private class NoticeData { public int id; public string title; public int type; public int link_type; public int is_swiper; public string url; public string cover; public string content; public int application_id; public string created_at; public string update_at; } /// /// 真是公告数据 /// private List curNoticeData; /// /// 公告数据 UI /// private Dictionary activityNoticeDataForDisplays; /// /// 系统公告数据 UI /// private Dictionary systemNoticeDataForDisplays; /// /// 轮播公告数据 UI /// private List rotateNoticeDataForDisplays; /// /// 公告红点缓存数据 /// private NoticeRedStorage noticeRedStorage; /// /// 公告页签红点字典 /// private Dictionary redPointNodeNoticeTypes; public Dictionary ActivityNoticeDataForDisplays => activityNoticeDataForDisplays; public Dictionary SystemNoticeDataForDisplays => systemNoticeDataForDisplays; public List RotateNoticeDataForDisplays => rotateNoticeDataForDisplays; public Dictionary RedPointNodeNoticeTypes => redPointNodeNoticeTypes; public async void GetNotice() { var requestUrl = AppConfig.Instance.LoginURL + NoticePost; DebugUtil.Log("拉起公告请求地址: " + requestUrl); try { var headData = PostHeader.PostHeaderInfo(new Dictionary { { "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() } }); var request = new UnityWebRequest(requestUrl, UnityWebRequest.kHttpVerbGET) { downloadHandler = new DownloadHandlerBuffer(), }; request.SetRequestHeader("Content-Type", "application/json;charset=utf-8"); //为了保证客户端发送的json格式在后端能解析 request.SetRequestHeader("signature", headData["signature"]); request.SetRequestHeader("timestamp", headData["timestamp"]); request.SetRequestHeader("accessKey", headData["accessKey"]); // 异步等待请求完成 await request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { DebugUtil.LogError(request.downloadHandler.text); } else { Debug.Log("http消息请求成功!返回内容:\n" + request.downloadHandler.text); var result = JsonConvert.DeserializeObject(request.downloadHandler.text); if (result.code == 0) { curNoticeData = result.data; ConvertNotice(); } else { DebugUtil.LogError("获取公告失败"); } } } catch (UnityWebRequestException e) { DebugUtil.LogError(e); var pattern = @"\{.*\}"; var match = Regex.Match(e.Message, pattern); if (match.Success) { var json = match.Value; NoticeGetResult res = JsonConvert.DeserializeObject(json); DebugUtil.LogError("请求失败, 服务器有错误响应: " + res.message); } else { DebugUtil.LogError("请求失败!"); } } } private async void ConvertNotice() { var activityIndex = 0; var systemIndex = 0; foreach (var data in curNoticeData) { Debug.Log($"公告ID:{data.id}, Title:{data.title}"); Debug.Log($"公告内容:{data.content}"); var sprite = await DownLoadImg(data.cover); var noticeDataForDisplay = new NoticeDataForDisplay { ID = data.id, Content = data.content, Bannersprite = sprite, ContentSprite = sprite, Title = data.title, LinkType = data.link_type, UpdateTime = data.update_at, }; noticeDataForDisplay.Type = (E_NoticeType)data.type; // 红点 var param = new ValueTuple(NoticeRedType.Notice, data.id); noticeDataForDisplay.RedPointNodeNotice = RedPointManager.Instance.AddDynamicNode(NodeType.Notice, NoticeRedNod, param) as RedPointNodeNotice; if (data.type == 1) { systemNoticeDataForDisplays[systemIndex] = noticeDataForDisplay; systemIndex++; } else { activityNoticeDataForDisplays[activityIndex] = noticeDataForDisplay; activityIndex++; } if (data.is_swiper == 1) rotateNoticeDataForDisplays.Add(noticeDataForDisplay); } SortRotateNotice(); EventManager.Instance.Send(EventManager.EventName.RefreshNotice); } private async UniTask DownLoadImg(string url) { if (string.IsNullOrEmpty(url)) return null; Sprite sprite = null; try { using var request = UnityWebRequestTexture.GetTexture(url); var operation = request.SendWebRequest(); await operation.ToUniTask(); if (request.result == UnityWebRequest.Result.Success) { var texture = DownloadHandlerTexture.GetContent(request); if (texture != null) { sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f)); } } else { Debug.LogError($"公告图片下载失败: {request.error}"); } return sprite; } catch (Exception e) { DebugUtil.LogError("NoticeManager.DownLoadImg error: {0}", e); return sprite; } } private void SortRotateNotice() { // 如果解析失败,返回一个最小值,这样无效时间会排在最后 rotateNoticeDataForDisplays = rotateNoticeDataForDisplays .OrderByDescending(notice => DateTime.TryParse(notice.UpdateTime, out var time) ? time : DateTime.MinValue) .ToList(); } #region 红点 public bool GetNoticeTypeRedNode(int type) { switch (type) { case 1: { foreach (var notice in systemNoticeDataForDisplays.Values) { if (noticeRedStorage.CheckNotice(notice.ID)) return true; } break; } case 2: { foreach (var notice in activityNoticeDataForDisplays.Values) { if (noticeRedStorage.CheckNotice(notice.ID)) return true; } break; } } return false; } public bool GetNoticeRedNode(int id) { return noticeRedStorage.CheckNotice(id); } public void CloseRedNode(int id) { if (!noticeRedStorage.NoticeList.Contains(id)) noticeRedStorage.NoticeList.Add(id); StorageMgr.Instance.SyncForce = true; EventManager.Instance.Send(EventManager.EventName.RefreshNotice); } #endregion #region 初始化与释放 public void Init() { activityNoticeDataForDisplays = new Dictionary(); systemNoticeDataForDisplays = new Dictionary(); rotateNoticeDataForDisplays = new List(); redPointNodeNoticeTypes = new Dictionary(); noticeRedStorage = StorageMgr.Instance.GetStorage(Constants.Storage.NoticeRed); noticeRedStorage ??= new NoticeRedStorage(); // 公告类型红点 var systemParam = new ValueTuple(NoticeRedType.NoticeType, (int)E_NoticeType.System); var systemNode = RedPointManager.Instance.AddDynamicNode(NodeType.Notice, NoticeRedNod, systemParam) as RedPointNodeNotice; var activityParam = new ValueTuple(NoticeRedType.NoticeType, (int)E_NoticeType.Activity); var activityNode = RedPointManager.Instance.AddDynamicNode(NodeType.Notice, NoticeRedNod, activityParam) as RedPointNodeNotice; redPointNodeNoticeTypes.Add(E_NoticeType.System, systemNode); redPointNodeNoticeTypes.Add(E_NoticeType.Activity, activityNode); } public void Release() { foreach (var noticeData in activityNoticeDataForDisplays) { noticeData.Value.ContentSprite = null; noticeData.Value.Bannersprite = null; } foreach (var noticeData in activityNoticeDataForDisplays) { noticeData.Value.ContentSprite = null; noticeData.Value.Bannersprite = null; } foreach (var redPointNodeNotice in redPointNodeNoticeTypes) { if (redPointNodeNotice.Value != null) RedPointManager.Instance.RemoveDynamicNode(redPointNodeNotice.Value); } activityNoticeDataForDisplays = null; systemNoticeDataForDisplays = null; } #endregion }