621 lines
17 KiB
C#
621 lines
17 KiB
C#
using TMPro;
|
||
using System;
|
||
using PhxhSDK;
|
||
using Gameplay;
|
||
using UnityEngine;
|
||
using UnityEngine.UI;
|
||
using System.Globalization;
|
||
using Cysharp.Threading.Tasks;
|
||
using System.Collections.Generic;
|
||
|
||
/// <summary>
|
||
/// 公告UI
|
||
/// </summary>
|
||
public class UI_NoticeController : UIWindow
|
||
{
|
||
/// <summary>
|
||
/// 打开公告界面
|
||
/// </summary>
|
||
public static async UniTask<UIWindow> Open(int id = -1, E_NoticeType type = E_NoticeType.Activity)
|
||
{
|
||
CommonUtils.CaptureScreenshot();
|
||
|
||
InputData inputData = new()
|
||
{
|
||
OpenType = type,
|
||
Idx = id,
|
||
};
|
||
|
||
return await UIManager.Instance.CreateAndOpenWindow(UINameConst.UI_Notice, inputData);
|
||
}
|
||
|
||
private struct InputData
|
||
{
|
||
public E_NoticeType OpenType;
|
||
public int Idx;
|
||
}
|
||
|
||
#region 类
|
||
|
||
/// <summary>
|
||
/// 公告类型
|
||
/// </summary>
|
||
private class NoticeTypeTab : UIGameObjectWrapper
|
||
{
|
||
#region UI
|
||
|
||
/// <summary>
|
||
/// 选中按钮
|
||
/// </summary>
|
||
private Button buttonChoose;
|
||
|
||
/// <summary>
|
||
/// 未选中按钮
|
||
/// </summary>
|
||
private Button buttonNormal;
|
||
|
||
/// <summary>
|
||
/// 公告类型
|
||
/// </summary>
|
||
private readonly E_NoticeType noticeType;
|
||
|
||
/// <summary>
|
||
/// 公告索引
|
||
/// </summary>
|
||
private readonly int index;
|
||
|
||
/// <summary>
|
||
/// 点击回调
|
||
/// </summary>
|
||
private readonly Action<E_NoticeType> clickAction;
|
||
|
||
/// <summary>
|
||
/// 选中红点
|
||
/// </summary>
|
||
private RedPointUIController redPointChoose;
|
||
|
||
/// <summary>
|
||
/// 未选中红点
|
||
/// </summary>
|
||
private RedPointUIController redPointNormal;
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// 是否选中
|
||
/// </summary>
|
||
public bool IsSelect
|
||
{
|
||
set
|
||
{
|
||
buttonChoose.gameObject.IsScaleShow(value);
|
||
buttonNormal.gameObject.IsScaleShow(!value);
|
||
}
|
||
}
|
||
|
||
public NoticeTypeTab(GameObject root, E_NoticeType noticeType, Action<E_NoticeType> click) : base(root, true)
|
||
{
|
||
this.noticeType = noticeType;
|
||
clickAction = click;
|
||
|
||
buttonChoose = GetComponent<Button>("ButtonChoose");
|
||
buttonNormal = GetComponent<Button>("ButtonNormal");
|
||
redPointChoose = GetComponent<RedPointUIController>("ButtonChoose/UI_RedPoint");
|
||
redPointNormal = GetComponent<RedPointUIController>("ButtonNormal/UI_RedPoint");
|
||
|
||
if (NoticeManager.Instance.RedPointNodeNoticeTypes.TryGetValue(noticeType, out var redPointNodeNotice) &&
|
||
redPointNodeNotice != null)
|
||
{
|
||
redPointChoose.NodeID = redPointNodeNotice.ID;
|
||
redPointNormal.NodeID = redPointNodeNotice.ID;
|
||
}
|
||
|
||
IsSelect = false;
|
||
|
||
CommonUtils.BindButton(buttonChoose, OnClick);
|
||
CommonUtils.BindButton(buttonNormal, OnClick);
|
||
}
|
||
|
||
private void OnClick()
|
||
{
|
||
clickAction?.Invoke(noticeType);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 公告页签
|
||
/// </summary>
|
||
private class NoticeTab : UIGameObjectWrapper
|
||
{
|
||
#region UI
|
||
|
||
/// <summary>
|
||
/// 选中状态按钮
|
||
/// </summary>
|
||
private Button buttonChoose;
|
||
|
||
/// <summary>
|
||
/// 非选中状态按钮
|
||
/// </summary>
|
||
private Button buttonNormal;
|
||
|
||
/// <summary>
|
||
/// 选中状态标题
|
||
/// </summary>
|
||
private TMP_Text textSelectTitle;
|
||
|
||
/// <summary>
|
||
/// 选中状态日
|
||
/// </summary>
|
||
private TMP_Text textSelectDay;
|
||
|
||
/// <summary>
|
||
/// 选中状态月
|
||
/// </summary>
|
||
private TMP_Text textSelectWeek;
|
||
|
||
/// <summary>
|
||
/// 选中状态星期
|
||
/// </summary>
|
||
private TMP_Text textSelectMonth;
|
||
|
||
/// <summary>
|
||
/// 未选中状态标题
|
||
/// </summary>
|
||
private TMP_Text textTitle;
|
||
|
||
/// <summary>
|
||
/// 未选中状态日
|
||
/// </summary>
|
||
private TMP_Text textDay;
|
||
|
||
/// <summary>
|
||
/// 未选中状态月
|
||
/// </summary>
|
||
private TMP_Text textWeek;
|
||
|
||
/// <summary>
|
||
/// 未选中状态星期
|
||
/// </summary>
|
||
private TMP_Text textMonth;
|
||
|
||
/// <summary>
|
||
/// 选中红点
|
||
/// </summary>
|
||
private RedPointUIController redPointChoose;
|
||
|
||
/// <summary>
|
||
/// 未选中红点
|
||
/// </summary>
|
||
private RedPointUIController redPointNormal;
|
||
|
||
#endregion
|
||
|
||
public int ID;
|
||
|
||
/// <summary>
|
||
/// 选中回调
|
||
/// </summary>
|
||
private readonly Action<NoticeTab> selectAction;
|
||
|
||
/// <summary>
|
||
/// 公告数据
|
||
/// </summary>
|
||
private NoticeDataForDisplay noticeInfo;
|
||
|
||
/// <summary>
|
||
/// 是否选中
|
||
/// </summary>
|
||
public bool IsSelect
|
||
{
|
||
set
|
||
{
|
||
buttonChoose.gameObject.IsScaleShow(value);
|
||
buttonNormal.gameObject.IsScaleShow(!value);
|
||
}
|
||
}
|
||
|
||
public NoticeDataForDisplay NoticeInfo => noticeInfo;
|
||
|
||
public NoticeTab(GameObject root, Action<NoticeTab> select) : base(root)
|
||
{
|
||
selectAction = select;
|
||
|
||
buttonChoose = GetComponent<Button>("ButtonChoose");
|
||
buttonNormal = GetComponent<Button>("ButtonNormal");
|
||
textSelectTitle = GetComponent<TMP_Text>("ButtonChoose/TextTitle");
|
||
textSelectDay = GetComponent<TMP_Text>("ButtonChoose/TextDay");
|
||
textSelectWeek = GetComponent<TMP_Text>("ButtonChoose/TextWeek");
|
||
textSelectMonth = GetComponent<TMP_Text>("ButtonChoose/TextMonth");
|
||
textTitle = GetComponent<TMP_Text>("ButtonNormal/TextTitle");
|
||
textDay = GetComponent<TMP_Text>("ButtonNormal/TextDay");
|
||
textWeek = GetComponent<TMP_Text>("ButtonNormal/TextWeek");
|
||
textMonth = GetComponent<TMP_Text>("ButtonNormal/TextMonth");
|
||
|
||
redPointChoose = GetComponent<RedPointUIController>("ButtonChoose/UI_RedPoint");
|
||
redPointNormal = GetComponent<RedPointUIController>("ButtonNormal/UI_RedPoint");
|
||
|
||
IsSelect = false;
|
||
|
||
CommonUtils.BindButton(buttonChoose, OnClick);
|
||
CommonUtils.BindButton(buttonNormal, OnClick);
|
||
}
|
||
|
||
public void SetInfo(NoticeDataForDisplay notice)
|
||
{
|
||
if (notice == null)
|
||
{
|
||
IsScaleShow = false;
|
||
return;
|
||
}
|
||
|
||
noticeInfo = notice;
|
||
ID = notice.ID;
|
||
textSelectTitle.text = notice.Title;
|
||
textTitle.text = notice.Title;
|
||
ConvertTime();
|
||
|
||
if (notice.RedPointNodeNotice != null)
|
||
{
|
||
redPointChoose.NodeID = notice.RedPointNodeNotice.ID;
|
||
redPointNormal.NodeID = notice.RedPointNodeNotice.ID;
|
||
}
|
||
|
||
IsScaleShow = true;
|
||
}
|
||
|
||
private void OnClick()
|
||
{
|
||
selectAction?.Invoke(this);
|
||
}
|
||
|
||
private void ConvertTime()
|
||
{
|
||
try
|
||
{
|
||
// 解析时间字符串为 DateTime 对象
|
||
if (DateTime.TryParseExact(noticeInfo.UpdateTime, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture,
|
||
DateTimeStyles.None, out var dateTime))
|
||
{
|
||
var day = dateTime.Day.ToString(); // 日期(1-31)
|
||
var month = dateTime.Month.ToString();
|
||
var weekDayAbbreviation = dateTime.ToString("ddd", CultureInfo.InvariantCulture);
|
||
|
||
textSelectDay.text = day;
|
||
textDay.text = day;
|
||
textMonth.text = month + "/";
|
||
textSelectMonth.text = month + "/";
|
||
textWeek.text = weekDayAbbreviation;
|
||
textSelectWeek.text = weekDayAbbreviation;
|
||
|
||
/*// 输出结果
|
||
DebugUtil.LogError($"Day: {day}");
|
||
DebugUtil.LogError($"Month: {month}");
|
||
DebugUtil.LogError($"Weekday Abbreviation: {weekDayAbbreviation}");*/
|
||
}
|
||
else
|
||
{
|
||
DebugUtil.LogError("公告时间转换错误:{0}", noticeInfo.UpdateTime);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
DebugUtil.LogError("公告时间转换异常:{0}, Error:{1}", noticeInfo.UpdateTime, e);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 公告内容
|
||
/// </summary>
|
||
private class NoticeContent : UIGameObjectWrapper
|
||
{
|
||
/// <summary>
|
||
/// 活动名
|
||
/// </summary>
|
||
private TMP_Text textActivityName;
|
||
|
||
/// <summary>
|
||
/// 横幅
|
||
/// </summary>
|
||
private Image imageBanner;
|
||
|
||
/// <summary>
|
||
/// 内置浏览器
|
||
/// </summary>
|
||
private UniWebView webView;
|
||
|
||
/// <summary>
|
||
/// 当前公告ID
|
||
/// </summary>
|
||
private int noticeID;
|
||
|
||
public NoticeContent(GameObject root) : base(root)
|
||
{
|
||
textActivityName = GetComponent<TMP_Text>("ImageTitle/TextActivityName");
|
||
imageBanner = GetComponent<Image>("ImageBanner");
|
||
webView = GetComponent<UniWebView>("TextContent");
|
||
}
|
||
|
||
public void SetInfo(NoticeDataForDisplay noticeInfo)
|
||
{
|
||
if (noticeInfo == null)
|
||
{
|
||
IsScaleShow = false;
|
||
return;
|
||
}
|
||
|
||
noticeID = noticeInfo.ID;
|
||
|
||
if (webView != null)
|
||
{
|
||
webView.LoadHTMLString(noticeInfo.Content, null, false);
|
||
webView.SetZoomEnabled(false); // 禁止缩放
|
||
webView.EmbeddedToolbar.Hide();
|
||
webView.Show();
|
||
webView.OnMessageReceived += HandleMessageReceived;
|
||
}
|
||
|
||
textActivityName.text = noticeInfo.Title;
|
||
IsScaleShow = true;
|
||
|
||
/*
|
||
if (noticeInfo.Bannersprite != null)
|
||
{
|
||
imageBanner.sprite = noticeInfo.ContentSprite;
|
||
}*/
|
||
}
|
||
|
||
public override void Dispose()
|
||
{
|
||
base.Dispose();
|
||
if (webView != null)
|
||
webView.OnMessageReceived -= HandleMessageReceived;
|
||
webView = null;
|
||
}
|
||
|
||
private void HandleMessageReceived(UniWebView web, UniWebViewMessage message)
|
||
{
|
||
DebugUtil.Log("Message received: " + message.RawMessage);
|
||
if (!message.Path.Equals("open")) return;
|
||
var openUrl = message.Args["url"];
|
||
DebugUtil.Log($"公告跳转链接是: {openUrl}");
|
||
if (!string.IsNullOrEmpty(openUrl))
|
||
{
|
||
Application.OpenURL(openUrl);
|
||
NoticeManager.Instance.CloseRedNode(noticeID);
|
||
}
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region UI
|
||
|
||
/// <summary>
|
||
/// 关闭按钮
|
||
/// </summary>
|
||
private Button buttonClose;
|
||
|
||
/// <summary>
|
||
/// 页签循环列表
|
||
/// </summary>
|
||
private RecycleView tabRecycleView;
|
||
|
||
/// <summary>
|
||
/// 高斯模糊遮罩
|
||
/// </summary>
|
||
private RawImage rawImageGaussianBlurMask;
|
||
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// 公告类型页签字典
|
||
/// </summary>
|
||
private readonly Dictionary<E_NoticeType, NoticeTypeTab> dicNoticeTypeTab = new();
|
||
|
||
/// <summary>
|
||
/// 页签字典
|
||
/// </summary>
|
||
private readonly Dictionary<int, NoticeTab> dicNoticeTap = new();
|
||
|
||
/// <summary>
|
||
/// 页签内容
|
||
/// </summary>
|
||
private NoticeContent noticeContent;
|
||
|
||
/// <summary>
|
||
/// 当前选中的公告类型
|
||
/// </summary>
|
||
private E_NoticeType curSelectNoticeType = E_NoticeType.None;
|
||
|
||
/// <summary>
|
||
/// 当前选择的页签
|
||
/// </summary>
|
||
private NoticeTab curSelectTab;
|
||
|
||
private ScrollRect contentScrollRect;
|
||
|
||
private InputData inputData;
|
||
|
||
|
||
public override void OnInit()
|
||
{
|
||
buttonClose = GetComponent<Button>("Image_NoticeBG/Button_Close");
|
||
tabRecycleView = GetComponent<RecycleView>("Image_NoticeBG/Tabs");
|
||
rawImageGaussianBlurMask = GetComponent<RawImage>("GaussianBlurMask");
|
||
|
||
dicNoticeTypeTab.Add(E_NoticeType.Activity,
|
||
new NoticeTypeTab(FindObj("Image_NoticeBG/Notices/ActivityNotice"), E_NoticeType.Activity,
|
||
OnNoticeTypeTab));
|
||
dicNoticeTypeTab.Add(E_NoticeType.System,
|
||
new NoticeTypeTab(FindObj("Image_NoticeBG/Notices/SystemNotice"), E_NoticeType.System, OnNoticeTypeTab));
|
||
|
||
noticeContent = new(FindObj("Image_NoticeBG/ContentRoot/Viewport/Content"));
|
||
contentScrollRect = GetComponent<ScrollRect>("Image_NoticeBG/ContentRoot");
|
||
|
||
rawImageGaussianBlurMask.texture = CommonUtils.GetScreenTexture2D();
|
||
tabRecycleView.Init(OnRefreshTab);
|
||
|
||
BindButton(buttonClose, OnClose);
|
||
}
|
||
|
||
protected override void OnShowWindow(object data)
|
||
{
|
||
if (data == null) return;
|
||
inputData = (InputData)data;
|
||
OnNoticeTypeTab(inputData.OpenType);
|
||
}
|
||
|
||
public override void OnRelease()
|
||
{
|
||
noticeContent.Dispose();
|
||
noticeContent = null;
|
||
|
||
base.OnRelease();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取要显示的页签数量
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private int GetShowTabCount()
|
||
{
|
||
return curSelectNoticeType switch
|
||
{
|
||
E_NoticeType.Activity => NoticeManager.Instance.ActivityNoticeDataForDisplays.Count,
|
||
E_NoticeType.System => NoticeManager.Instance.SystemNoticeDataForDisplays.Count,
|
||
_ => 0,
|
||
};
|
||
}
|
||
|
||
#region 回调方法
|
||
|
||
/// <summary>
|
||
/// 刷新页签
|
||
/// </summary>
|
||
private void OnRefreshTab(GameObject cell, int index)
|
||
{
|
||
if (!dicNoticeTap.TryGetValue(cell.GetInstanceID(), out NoticeTab noticeTab))
|
||
{
|
||
noticeTab = new NoticeTab(cell, OnNoticeTab);
|
||
dicNoticeTap[cell.GetInstanceID()] = noticeTab;
|
||
}
|
||
|
||
switch (curSelectNoticeType)
|
||
{
|
||
case E_NoticeType.Activity:
|
||
{
|
||
if (NoticeManager.Instance.ActivityNoticeDataForDisplays.Count < 0 ||
|
||
index >= NoticeManager.Instance.ActivityNoticeDataForDisplays.Count)
|
||
{
|
||
DebugUtil.LogWarning("索引错误");
|
||
return;
|
||
}
|
||
|
||
if (!NoticeManager.Instance.ActivityNoticeDataForDisplays.TryGetValue(index, out var noticeInfo))
|
||
{
|
||
DebugUtil.LogError("没有索引为{0}的公告", index);
|
||
}
|
||
|
||
noticeTab.SetInfo(noticeInfo);
|
||
if ((inputData.Idx == -1 && curSelectTab == null) || inputData.Idx == noticeTab.ID)
|
||
{
|
||
curSelectTab = noticeTab;
|
||
OnNoticeTab(noticeTab);
|
||
}
|
||
else
|
||
{
|
||
noticeTab.IsSelect = false;
|
||
}
|
||
}
|
||
break;
|
||
case E_NoticeType.System:
|
||
{
|
||
if (NoticeManager.Instance.SystemNoticeDataForDisplays.Count < 0 ||
|
||
index >= NoticeManager.Instance.SystemNoticeDataForDisplays.Count)
|
||
{
|
||
DebugUtil.LogWarning("索引错误");
|
||
return;
|
||
}
|
||
|
||
if (!NoticeManager.Instance.SystemNoticeDataForDisplays.TryGetValue(index, out var noticeInfo))
|
||
{
|
||
DebugUtil.LogError("没有索引为{0}的系统公告", index);
|
||
}
|
||
|
||
noticeTab.SetInfo(noticeInfo);
|
||
|
||
if ((inputData.Idx == -1 && curSelectTab == null) || inputData.Idx == noticeTab.ID)
|
||
{
|
||
curSelectTab = noticeTab;
|
||
OnNoticeTab(noticeTab);
|
||
}
|
||
else
|
||
{
|
||
noticeTab.IsSelect = false;
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
{
|
||
noticeTab.IsSelect = false;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 关闭
|
||
/// </summary>
|
||
private void OnClose()
|
||
{
|
||
CloseWindow();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 公告类型切换
|
||
/// </summary>
|
||
private void OnNoticeTypeTab(E_NoticeType noticeType)
|
||
{
|
||
if (curSelectNoticeType == noticeType)
|
||
return;
|
||
|
||
if (dicNoticeTypeTab.TryGetValue(curSelectNoticeType, out NoticeTypeTab tab))
|
||
tab.IsSelect = false;
|
||
|
||
curSelectNoticeType = noticeType;
|
||
|
||
if (inputData.Idx != -1 && curSelectTab != null)
|
||
inputData.Idx = -1;
|
||
|
||
curSelectTab = null;
|
||
|
||
if (dicNoticeTypeTab.TryGetValue(curSelectNoticeType, out tab))
|
||
tab.IsSelect = true;
|
||
|
||
tabRecycleView.ShowList(GetShowTabCount());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 公告页签
|
||
/// </summary>
|
||
private void OnNoticeTab(NoticeTab tab)
|
||
{
|
||
if (curSelectTab != null)
|
||
{
|
||
curSelectTab.IsSelect = false;
|
||
}
|
||
|
||
curSelectTab = tab;
|
||
curSelectTab.IsSelect = true;
|
||
contentScrollRect.verticalNormalizedPosition = 1f;
|
||
|
||
noticeContent.SetInfo(curSelectTab.NoticeInfo);
|
||
if (tab.NoticeInfo.LinkType != 2)
|
||
NoticeManager.Instance.CloseRedNode(tab.ID);
|
||
}
|
||
|
||
#endregion
|
||
} |