Files
ft/Client/Assets/Scripts/Activity/Data/AEventDataManager.cs
2026-06-29 21:18:33 +08:00

236 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using Activity.Data;
using Activity.Services;
using asap.core;
using cfg;
using GameCore;
using UniRx;
using UnityEngine;
namespace Activity
{
public abstract class AEventDataManager
{
protected readonly CompositeDisposable CompositeDisposable = new();
private Tables _tables;
public Tables Tables => _tables ??= GContext.container.Resolve<Tables>();
public void Dispose()
{
CompositeDisposable?.Dispose();
}
#region
private IEventDataRepository _dataRepository;
private IEventTokenService _tokenService;
/// <summary>
/// 数据仓库 - 负责数据的持久化
/// </summary>
protected IEventDataRepository Repository =>
_dataRepository ??= GContext.container?.Resolve<IEventDataRepository>();
/// <summary>
/// 代币服务 - 负责代币的统一管理
/// </summary>
protected IEventTokenService TokenService =>
_tokenService ??= GContext.container?.Resolve<IEventTokenService>();
#endregion
#region
/// <summary>
/// 加载数据 - UI/Sentry 调用
/// </summary>
public virtual T LoadData<T>() where T : IEventData, new()
{
return Repository.Load<T>() ?? new T();
}
/// <summary>
/// 保存数据 - 显式保存
/// </summary>
public virtual void SaveData<T>(T data) where T : IEventData, new()
{
if (data == null) return;
Repository?.Save(data);
// 发布数据保存事件,通知订阅者刷新缓存
GContext.Publish(data);
}
/// <summary>
/// 刷新数据 - Sentry 调用,返回新创建或加载的数据
/// 基类实现:加载缓存数据,如不存在则创建新数据
/// </summary>
public virtual T RefreshData<T>(FishingEvent eventConfig) where T : IEventData, new()
{
var cachedData = Repository.Load<T>();
if (cachedData != null && cachedData.EventID == eventConfig.ID) return cachedData;
var newData = CreateData<T>(eventConfig);
OnDataInitialized(newData, eventConfig);
// 根据子类返回值决定是否自动保存
if (AutoSaveOnCreate(newData))
{
Repository.Save(newData);
}
return newData;
}
/// <summary>
/// 创建新数据实例 - 子类可重写
/// </summary>
protected virtual T CreateData<T>(FishingEvent eventConfig) where T : IEventData, new()
{
var playerData = GContext.container.Resolve<PlayerData>();
return new T
{
EventID = eventConfig.ID,
FishingEvent = eventConfig,
InflationRate = playerData.InflationRate,
VipLevel = playerData.PriceLv
};
}
/// <summary>
/// 数据初始化钩子 - 子类可重写
/// </summary>
protected virtual void OnDataInitialized(IEventData data, FishingEvent eventConfig)
{
}
/// <summary>
/// 是否在新数据创建后自动保存 - 子类可重写
/// </summary>
protected virtual bool AutoSaveOnCreate<T>(T data) where T : IEventData, new() => true;
#endregion
#region IEventTokenService
public virtual void AddToken<T>(T data, int count) where T : IEventData, new()
{
try
{
if (data == null || data.EventID <= 0) return;
TokenService?.AddToken(data.EventID, count);
}
catch (Exception e)
{
Debug.LogError($"[AEventDataManager] Failed to add token for {typeof(T).Name}: {e.Message}");
}
}
public virtual void RemoveToken<T>(T data, int count) where T : IEventData, new()
{
try
{
if (data == null || data.EventID <= 0) return;
TokenService?.RemoveToken(data.EventID, count);
}
catch (Exception e)
{
Debug.LogError($"[AEventDataManager] Failed to remove token for {typeof(T).Name}: {e.Message}");
}
}
public virtual int GetTokenCount<T>(T data) where T : IEventData, new()
{
try
{
if (data == null || data.EventID <= 0) return 0;
return TokenService?.GetTokenCount(data.EventID) ?? 0;
}
catch (Exception e)
{
Debug.LogError($"[AEventDataManager] Failed to get token count for {typeof(T).Name}: {e.Message}");
return 0;
}
}
#endregion
}
public abstract class AEventDataManager<T> : AEventDataManager where T : IEventData, new()
{
#region
/// <summary>
/// 加载数据 - 调用基类泛型方法
/// </summary>
public virtual T LoadData()
{
return base.LoadData<T>();
}
/// <summary>
/// 保存数据 - 调用基类泛型方法
/// </summary>
public virtual void SaveData(T data)
{
base.SaveData(data);
}
/// <summary>
/// 刷新数据 - 调用基类泛型方法
/// </summary>
public virtual T RefreshData(FishingEvent eventConfig)
{
var data = base.RefreshData<T>(eventConfig);
if (this is IActivityEventRedPoint<T> red)
red.SetRedPoint(data);
return data;
}
/// <summary>
/// 数据初始化钩子 - 重写
/// </summary>
protected override void OnDataInitialized(IEventData data, FishingEvent eventConfig)
{
base.OnDataInitialized(data, eventConfig);
}
/// <summary>
/// 泛型子类默认自动保存新创建的数据
/// </summary>
protected override bool AutoSaveOnCreate<TData>(TData data) => true;
#endregion
#region
public virtual void AddToken(T data, int count)
{
base.AddToken(data, count);
}
public virtual void RemoveToken(T data, int count)
{
base.RemoveToken(data, count);
}
public virtual int GetTokenCount(T data)
{
return base.GetTokenCount(data);
}
#endregion
}
/// <summary>
/// 活动入口红点:由具体 <see cref="AEventDataManager{T}"/> 实现。
/// Key、State、数量等规则放在实现类内部框架仅通过本接口调用 <see cref="SetRedPoint"/>(如 <see cref="AEventDataManager{T}.RefreshData"/>、代币 <see cref="ActivityEventTokenBalanceChanged"/> 转发)。
/// </summary>
public interface IActivityEventRedPoint<T> where T : IEventData, new()
{
void SetRedPoint(T data);
}
}