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(); public void Dispose() { CompositeDisposable?.Dispose(); } #region 依赖注入 private IEventDataRepository _dataRepository; private IEventTokenService _tokenService; /// /// 数据仓库 - 负责数据的持久化 /// protected IEventDataRepository Repository => _dataRepository ??= GContext.container?.Resolve(); /// /// 代币服务 - 负责代币的统一管理 /// protected IEventTokenService TokenService => _tokenService ??= GContext.container?.Resolve(); #endregion #region 数据操作(无状态接口) /// /// 加载数据 - UI/Sentry 调用 /// public virtual T LoadData() where T : IEventData, new() { return Repository.Load() ?? new T(); } /// /// 保存数据 - 显式保存 /// public virtual void SaveData(T data) where T : IEventData, new() { if (data == null) return; Repository?.Save(data); // 发布数据保存事件,通知订阅者刷新缓存 GContext.Publish(data); } /// /// 刷新数据 - Sentry 调用,返回新创建或加载的数据 /// 基类实现:加载缓存数据,如不存在则创建新数据 /// public virtual T RefreshData(FishingEvent eventConfig) where T : IEventData, new() { var cachedData = Repository.Load(); if (cachedData != null && cachedData.EventID == eventConfig.ID) return cachedData; var newData = CreateData(eventConfig); OnDataInitialized(newData, eventConfig); // 根据子类返回值决定是否自动保存 if (AutoSaveOnCreate(newData)) { Repository.Save(newData); } return newData; } /// /// 创建新数据实例 - 子类可重写 /// protected virtual T CreateData(FishingEvent eventConfig) where T : IEventData, new() { var playerData = GContext.container.Resolve(); return new T { EventID = eventConfig.ID, FishingEvent = eventConfig, InflationRate = playerData.InflationRate, VipLevel = playerData.PriceLv }; } /// /// 数据初始化钩子 - 子类可重写 /// protected virtual void OnDataInitialized(IEventData data, FishingEvent eventConfig) { } /// /// 是否在新数据创建后自动保存 - 子类可重写 /// protected virtual bool AutoSaveOnCreate(T data) where T : IEventData, new() => true; #endregion #region 代币操作(委托给 IEventTokenService) public virtual void AddToken(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 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 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 : AEventDataManager where T : IEventData, new() { #region 数据操作(调用基类泛型方法) /// /// 加载数据 - 调用基类泛型方法 /// public virtual T LoadData() { return base.LoadData(); } /// /// 保存数据 - 调用基类泛型方法 /// public virtual void SaveData(T data) { base.SaveData(data); } /// /// 刷新数据 - 调用基类泛型方法 /// public virtual T RefreshData(FishingEvent eventConfig) { var data = base.RefreshData(eventConfig); if (this is IActivityEventRedPoint red) red.SetRedPoint(data); return data; } /// /// 数据初始化钩子 - 重写 /// protected override void OnDataInitialized(IEventData data, FishingEvent eventConfig) { base.OnDataInitialized(data, eventConfig); } /// /// 泛型子类默认自动保存新创建的数据 /// protected override bool AutoSaveOnCreate(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 } /// /// 活动入口红点:由具体 实现。 /// Key、State、数量等规则放在实现类内部;框架仅通过本接口调用 (如 、代币 转发)。 /// public interface IActivityEventRedPoint where T : IEventData, new() { void SetRedPoint(T data); } }