少年修仙传客户端代码仓库
Client_PangDeRong
2018-10-12 63eba1a8a153a39724b86e60a66090a225251291
4074  【前端】限时抢购开发
10个文件已修改
600 ■■■■ 已修改文件
Core/NetworkPackage/ClientPack/ClientToMapServer/CAA SaleActivity/CAA05_tagCMFlashSaleAppointment.cs 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA003_tagUniversalGameRecInfo.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA18_tagMCFlashSaleAppointmentInfo.cs 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/FlashRushToBuyCoolDown.cs 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/FlashRushToBuyModel.cs 160 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/FlashRushToBuyWin.cs 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/FlashSaleItemCell.cs 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/FlashSaleTimeCell.cs 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
System/OpenServerActivity/OperationFlashRushToBuy.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Utility/GlobalTimeEvent.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Core/NetworkPackage/ClientPack/ClientToMapServer/CAA SaleActivity/CAA05_tagCMFlashSaleAppointment.cs
@@ -4,7 +4,8 @@
// AA 05 限时抢购预约 #tagCMFlashSaleAppointment
public class CAA05_tagCMFlashSaleAppointment : GameNetPackBasic {
    public uint GoodsID;    // 商城表的商品ID
    public uint GoodsID;    // 抢购商品标识
    public byte State;    // 1-预约 0-取消
    public CAA05_tagCMFlashSaleAppointment () {
        combineCmd = (ushort)0x03FE;
@@ -13,6 +14,7 @@
    public override void WriteToBytes () {
        WriteBytes (GoodsID, NetDataType.DWORD);
        WriteBytes (State, NetDataType.BYTE);
    }
}
Core/NetworkPackage/DTCFile/ServerPack/HA0_Sys/DTCA003_tagUniversalGameRecInfo.cs
@@ -18,12 +18,11 @@
    {
        base.Done(vNetPack);
        var data = vNetPack as HA003_tagUniversalGameRecInfo;
        heavenModel.RefreshBattleInfo(data);
        if (onGetUniversalGameInfo != null)
        {
            onGetUniversalGameInfo(data);
        }
        heavenModel.RefreshBattleInfo(data);
    }
}
Core/NetworkPackage/ServerPack/HAA_SaleActivity/HAA18_tagMCFlashSaleAppointmentInfo.cs
@@ -4,26 +4,16 @@
// AA 18 限时抢购活动玩家预约信息 #tagMCFlashSaleAppointmentInfo
public class HAA18_tagMCFlashSaleAppointmentInfo : GameNetPackBasic {
    public ushort GiftItemCount;    // 礼包数
    public  tagMCFlashSaleItemYY[] ItemInfo;    // 物品信息
    public ushort GoodsCount;    // 商品数
    public  uint[] GoodsList;    // 预约的商品
    public HAA18_tagMCFlashSaleAppointmentInfo () {
        _cmd = (ushort)0xAA18;
    }
    public override void ReadFromBytes (byte[] vBytes) {
        TransBytes (out GiftItemCount, vBytes, NetDataType.WORD);
        ItemInfo = new tagMCFlashSaleItemYY[GiftItemCount];
        for (int i = 0; i < GiftItemCount; i ++) {
            ItemInfo[i] = new tagMCFlashSaleItemYY();
            TransBytes (out ItemInfo[i].GiftID, vBytes, NetDataType.DWORD);
            TransBytes (out ItemInfo[i].IsAppointment, vBytes, NetDataType.BYTE);
        }
    }
    public struct tagMCFlashSaleItemYY {
        public uint GiftID;        //商城表的ID
        public byte IsAppointment;        //是否预约
        TransBytes (out GoodsCount, vBytes, NetDataType.WORD);
        TransBytes (out GoodsList, vBytes, NetDataType.DWORD, GoodsCount);
    }
}
System/OpenServerActivity/FlashRushToBuyCoolDown.cs
@@ -8,88 +8,76 @@
{
    public class FlashRushToBuyCoolDown : MonoBehaviour
    {
        [SerializeField] TimerBehaviour m_Time;
        [SerializeField] RectTransform m_ContainerAdvance;
        [SerializeField] Text m_AdvanceTime;
        [SerializeField] Text timeText;
        FlashRushToBuyModel rushToBuyModel { get { return ModelCenter.Instance.GetModel<FlashRushToBuyModel>(); } }
        bool isReplace = false;
        bool isStartReplace = false;
        private void Awake()
        {
            GlobalTimeEvent.Instance.halfMinuteEvent += UpdateHalfMinute;
        }
        private void OnEnable()
        {
            SecondEvent();
            GlobalTimeEvent.Instance.secondEvent -= SecondEvent;
            GlobalTimeEvent.Instance.secondEvent += SecondEvent;
            OperationTimeHepler.Instance.dayResetEvent -= DayResetEvent;
            OperationTimeHepler.Instance.dayResetEvent += DayResetEvent;
        }
        private void DayResetEvent(int resetType)
        {
            SecondEvent();
        }
        private void SecondEvent()
        {
            OperationBase operationBase;
            if (OperationTimeHepler.Instance.TryGetOperationTime(Operation.FlashRushToBuy, out operationBase))
            {
                var operation = (operationBase as OperationFlashRushToBuy);
                bool inAdvance = false;
                var seconds = 0;
                if (operation.InAdvanceTime(TimeUtility.ServerNow))
                {
                    inAdvance = true;
                    seconds = operation.GetSecondsBeforeStart(TimeUtility.ServerNow);
                }
                else
                {
                    seconds = operation.GetResetSurplusTime();
                }
                m_ContainerAdvance.gameObject.SetActive(inAdvance);
                if (inAdvance)
                {
                    if (m_Time.gameObject.activeSelf)
                    {
                        DisplayTime(0);
                    }
                    DisplayAdvance(seconds);
                }
                else
                {
                    if (seconds * TimeSpan.TicksPerSecond >= TimeSpan.TicksPerDay || seconds <= 0)
                    {
                        if (m_Time.gameObject.activeSelf)
                        {
                            DisplayTime(0);
                        }
                    }
                    else
                    {
                        m_Time.timeShow.color = seconds > 3600 ? UIHelper.GetUIColor(TextColType.Green) : UIHelper.GetUIColor(TextColType.Red);
                        if (!m_Time.gameObject.activeSelf)
                        {
                            DisplayTime(seconds);
                        }
                    }
                }
            }
        }
        private void OnDisable()
        {
            GlobalTimeEvent.Instance.secondEvent -= SecondEvent;
            OperationTimeHepler.Instance.dayResetEvent -= DayResetEvent;
            m_Time.gameObject.SetActive(false);
        }
        void DisplayTime(int seconds)
        private void UpdateHalfMinute()
        {
            m_Time.timeShow.color = seconds > 3600 ? UIHelper.GetUIColor(TextColType.Green) : UIHelper.GetUIColor(TextColType.Red);
            m_Time.Begin(seconds);
            if (!isStartReplace) return;
            isReplace = !isReplace;
        }
        void DisplayAdvance(int seconds)
        private void SecondEvent()
        {
            m_AdvanceTime.text = Language.Get("OperationAdvanceOpen", TimeUtility.SecondsToHMS(seconds));
            DisplayTime();
        }
        void DisplayTime()
        {
            var operation = rushToBuyModel.GetOperationFlashRushToBuy();
            if (operation == null) return;
            int seconds = 0;
            OperationTime operationTime;
            FlashRushToBuyModel.FlashRushToBuySate flashState = rushToBuyModel.GetActivityState(out seconds,out operationTime);
            isStartReplace = false;
            switch (flashState)
            {
                case FlashRushToBuyModel.FlashRushToBuySate.NoOpen:
                    break;
                case FlashRushToBuyModel.FlashRushToBuySate.InAdvance:
                    if(seconds <= 3600)
                    {
                        isStartReplace = true;
                        if(!isReplace)
                        {
                            timeText.text = TimeUtility.SecondsToHMS(seconds);
                        }
                        else
                        {
                            timeText.text = operation.ToDisplayBuyTime(operationTime.startHour, operationTime.startMinute);
                        }
                    }
                    else
                    {
                        timeText.text = operation.ToDisplayBuyTime(operationTime.startHour, operationTime.startMinute);
                    }
                    break;
                case FlashRushToBuyModel.FlashRushToBuySate.Begining:
                    timeText.text = "秒杀中";
                    break;
                case FlashRushToBuyModel.FlashRushToBuySate.End:
                    timeText.text = "活动已结束";
                    break;
            }
        }
    }
}
System/OpenServerActivity/FlashRushToBuyModel.cs
@@ -8,6 +8,8 @@
    public class FlashRushToBuyModel : Model,IBeforePlayerDataInitialize,IPlayerLoginOk,IOpenServerActivity
    {
        StoreModel storeModel { get { return ModelCenter.Instance.GetModel<StoreModel>(); } }
        HeavenBattleModel battleModel { get { return ModelCenter.Instance.GetModel<HeavenBattleModel>(); } }
        public override void Init()
        {
            OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
@@ -58,8 +60,46 @@
            }
        }
        public void SetDefaultSelectSaleTime()
        {
            OperationFlashRushToBuy operation = GetOperationFlashRushToBuy();
            if (!presentFlashShop.Equals(default(OperationFlashRushToBuy.FlashSaleShop)))
            {
                int seconds = 0;
                int buyState = operation.GetBuyTimeState(TimeUtility.ServerNow,presentFlashShop.dayIndex,presentFlashShop.timeIndex, out seconds);
                if(buyState != 1)
                {
                    return;
                }
            }
            for (int i = 0; i < operation.flashShops.Count; i++)
            {
                int days = operation.totalDays;
                int dayIndex = i / (operation.flashShops.Count / days);
                int timeIndex = i % (operation.flashShops.Count / days);
                int seconds = 0;
                OperationTime operationTime = operation.times[timeIndex];
                var date = operation.startDate;
                int buyState = operation.GetBuyTimeState(TimeUtility.ServerNow, dayIndex, timeIndex, out seconds);
                switch(buyState)
                {
                    case -1:
                    case 0:
                        UpdateSelectFlashSaleTime(dayIndex,timeIndex);
                        return;
                }
            }
        }
        public void ResetFlashShop()
        {
            presentFlashShop = default(OperationFlashRushToBuy.FlashSaleShop);
        }
        #region 本地数据处理
        public OperationFlashRushToBuy.FlashSaleShop presentFlashShop { get; private set; }
        public event Action UpdateSelectSaleTimeEvent;
        public void UpdateSelectFlashSaleTime(int dayIndex,int timeIndex)
        {
            presentFlashShop = default(OperationFlashRushToBuy.FlashSaleShop);
@@ -69,6 +109,10 @@
                OperationFlashRushToBuy.FlashSaleShop flashShop;
                operation.TryGetFlashShop(dayIndex, timeIndex, out flashShop);
                presentFlashShop = flashShop;
                if(UpdateSelectSaleTimeEvent != null)
                {
                    UpdateSelectSaleTimeEvent();
                }
            }
        }
@@ -82,43 +126,102 @@
            return null;
        }
        #endregion
        public FlashRushToBuySate GetActivityState(out int seconds)
        #region 协议
        public event Action UpdateAppointmentEvent;
        public void UpdateFlashSaleAppointmentInfo(HAA18_tagMCFlashSaleAppointmentInfo appointmentInfo)
        {
            OperationBase operationBase;
            OperationTimeHepler.Instance.TryGetOperationTime(Operation.FlashRushToBuy, out operationBase);
            var operation = GetOperationFlashRushToBuy();
            if (operation == null) return;
            for(int i = 0; i < appointmentInfo.GoodsCount; i++)
            {
               for(int j = 0; j < operation.flashShops.Count; j++)
                {
                    var saleItems = operation.flashShops[j].items;
                    for (int k = 0; k < saleItems.Length; k++)
                    {
                       if(saleItems[k].shopGuid == appointmentInfo.GoodsList[i])
                        {
                            saleItems[k].isAppointment = 1;
                        }
                    }
                }
            }
            if(UpdateAppointmentEvent != null)
            {
                UpdateAppointmentEvent();
            }
        }
        /// <summary>
        /// Value1  商品ID  Value2 全服购买次数
        /// </summary>
        /// <returns></returns>
        public GameRecInfo GetFullServerInfo()
        {
            var infolist = battleModel.GetBatterInfoListByType(8);
            if(infolist != null && infolist.Count > 0)
            {
                return infolist[0];
            }
            return null;
        }
        /// <summary>
        ///  限时抢购预约
        /// </summary>
        public void SendFlashSaleAppointment(int shopGuid,int state)
        {
            CAA05_tagCMFlashSaleAppointment appointment = new CAA05_tagCMFlashSaleAppointment();
            appointment.GoodsID = (uint)shopGuid;
            appointment.State = (byte)state;
            GameNetSystem.Instance.SendInfo(appointment);
        }
        #endregion
        /// <summary>
        /// 获得限时抢购活动状态
        /// </summary>
        /// <param name="seconds"></param>
        /// <returns></returns>
        public FlashRushToBuySate GetActivityState(out int seconds,out OperationTime operationTime)
        {
            seconds = 0;
            FlashRushToBuySate rushToBuySate = FlashRushToBuySate.InAdvance;
            var inAdvance = false;
            if (operationBase != null)
            operationTime = default(OperationTime);
            var operation = GetOperationFlashRushToBuy();
            if (!IsOpen || operation == null) return FlashRushToBuySate.NoOpen;
            int openState = 0;
            int endState = 0;
            int openSeconds = 0;
            int endSeconds = 0;
            if(operation.flashShops.Count > 0)
            {
                if (operationBase.InAdvanceTime(TimeUtility.ServerNow))
                {
                    inAdvance = true;
                    seconds = operationBase.GetSecondsBeforeStart(TimeUtility.ServerNow);
                }
                else
                {
                    OperationFlashSale operation = operationBase as OperationFlashSale;
                    seconds = operation.GetResetSurplusTime();
                }
                OperationFlashRushToBuy.FlashSaleShop openSaleShop = operation.flashShops[0];
                operationTime = operation.times[openSaleShop.timeIndex];
                openState = operation.GetBuyTimeState(TimeUtility.ServerNow, openSaleShop.dayIndex, openSaleShop.timeIndex,out openSeconds);
                OperationFlashRushToBuy.FlashSaleShop endSaleShop = operation.flashShops[operation.flashShops.Count - 1];
                endState = operation.GetBuyTimeState(TimeUtility.ServerNow, endSaleShop.dayIndex, endSaleShop.timeIndex, out endSeconds);
            }
            if (seconds > 0)
            switch(openState)
            {
                if (inAdvance)
                {
                    rushToBuySate = FlashRushToBuySate.InAdvance;
                }
                else
                {
                    rushToBuySate = FlashRushToBuySate.Begining;
                }
                case -1:
                    seconds = openSeconds;
                    return FlashRushToBuySate.InAdvance;
            }
            else
            switch(endState)
            {
                rushToBuySate = FlashRushToBuySate.End;
                case -1:
                    return FlashRushToBuySate.Begining;
                case 0:
                    return FlashRushToBuySate.Begining;
                case 1:
                    return FlashRushToBuySate.End;
                default:
                    return FlashRushToBuySate.NoOpen;
            }
            return rushToBuySate;
        }
        private void OperationEndEvent(Operation type, int state)
@@ -289,6 +392,7 @@
        public enum FlashRushToBuySate
        {
            NoOpen, //活动未开启
            InAdvance,//提前
            Begining, //活动中
            End, //结束
System/OpenServerActivity/FlashRushToBuyWin.cs
@@ -1,4 +1,5 @@
using UnityEngine;
using System;
using UnityEngine;
using UnityEngine.UI;
namespace Snxxz.UI
@@ -25,11 +26,11 @@
        protected override void OnPreOpen()
        {
            SetDisplayModel();
            TimeMgr.Instance.OnDayEvent += OnDayEvent;
            rushToBuyModel.SetDefaultSelectSaleTime();
            OperationTimeHepler.Instance.operationStartEvent += OperationStartEvent;
            storeModel.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
            OperationTimeHepler.Instance.operationTimeUpdateEvent += OperationTimeUpdateEvent;
            rushToBuyModel.UpdateSelectSaleTimeEvent += UpdateSelectSaleTime;
            SetDisplayModel();
            Display();
        }
@@ -40,10 +41,10 @@
        protected override void OnPreClose()
        {
            TimeMgr.Instance.OnDayEvent -= OnDayEvent;
            rushToBuyModel.UpdateSelectSaleTimeEvent -= UpdateSelectSaleTime;
            OperationTimeHepler.Instance.operationStartEvent -= OperationStartEvent;
            storeModel.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
            OperationTimeHepler.Instance.operationTimeUpdateEvent -= OperationTimeUpdateEvent;
            rushToBuyModel.ResetFlashShop();
        }
        protected override void OnAfterClose()
@@ -77,6 +78,12 @@
            CreateSaleItem();
        }
        private void UpdateSelectSaleTime()
        {
            CreateSaleItem();
        }
        private void CreateOperationTimes()
        {
            if (operation == null) return;
@@ -102,29 +109,18 @@
        private void OperationTimeUpdateEvent(Operation type)
        {
            if (type == Operation.FlashSale)
            if (type == Operation.FlashRushToBuy)
            {
                Display();
            }
        }
        private void RefreshBuyShopLimitEvent()
        {
            Display();
        }
        private void OperationStartEvent(Operation type, int state)
        {
            if (type == Operation.FlashRushToBuy && state == 0)
            {
                Display();
            }
        }
        private void OnDayEvent()
        {
            Display();
        }
    }
}
System/OpenServerActivity/FlashSaleItemCell.cs
@@ -1,6 +1,8 @@
using UnityEngine;
using UnityEngine.UI;
using EnhancedUI.EnhancedScroller;
using TableConfig;
using System;
namespace Snxxz.UI
{
@@ -15,27 +17,143 @@
        [SerializeField] Button flashSaleBtn;
        [SerializeField] Text btnStateText;
        public const int RefreshFullServerBuyType = 8;
        FlashRushToBuyModel rushToBuyModel { get { return ModelCenter.Instance.GetModel<FlashRushToBuyModel>(); } }
        StoreModel storeModel { get { return ModelCenter.Instance.GetModel<StoreModel>(); } }
        HeavenBattleModel battleModel { get { return ModelCenter.Instance.GetModel<HeavenBattleModel>(); } }
        ItemTipsModel tipsModel { get { return ModelCenter.Instance.GetModel<ItemTipsModel>(); } }
        OperationFlashRushToBuy.FlashSaleItem saleItem;
        private void OnEnable()
        {
            battleModel.RefreshGameRecInfoAct += UpdateFullServerBuy;
            storeModel.RefreshBuyShopLimitEvent += RefreshBuyShopLimitEvent;
            rushToBuyModel.UpdateAppointmentEvent += UpdateAppointmentInfo;
        }
        private void OnDisable()
        {
            storeModel.RefreshBuyShopLimitEvent -= RefreshBuyShopLimitEvent;
            battleModel.RefreshGameRecInfoAct -= UpdateFullServerBuy;
            rushToBuyModel.UpdateAppointmentEvent -= UpdateAppointmentInfo;
        }
        public override void Refresh(CellView cell)
        {
            if (rushToBuyModel.presentFlashShop.Equals(default(OperationFlashRushToBuy.FlashSaleShop))) return;
            var saleItem = rushToBuyModel.presentFlashShop.items[cell.index];
            saleItem = rushToBuyModel.presentFlashShop.items[cell.index];
            ItemCellModel cellModel = new ItemCellModel(saleItem.itemId,true,(ulong)saleItem.itemCount,saleItem.isBind);
            itemBaisc.Init(cellModel);
            itemBaisc.cellBtn.RemoveAllListeners();
            itemBaisc.cellBtn.AddListener(()=>
            {
                ItemAttrData attrData = new ItemAttrData(saleItem.itemId,true, (ulong)saleItem.itemCount, -1,saleItem.isBind);
                tipsModel.SetItemTipsModel(attrData);
            });
            originalMoneyIcon.SetIconWithMoneyType(saleItem.moneyType);
            presentMoneyIcon.SetIconWithMoneyType(saleItem.moneyType);
            originalPrice.text = saleItem.moneyOriginal.ToString();
            presentPrice.text = saleItem.moneyNumber.ToString();
            UpdateSaleItem();
            UpdateSaleItemSellState();
        }
        private void RefreshBuyShopLimitEvent()
        {
            UpdateSaleItemSellState();
        }
        private void UpdateFullServerBuy(int type)
        {
            if (type != RefreshFullServerBuyType) return;
            UpdateSaleItemSellState();
        }
        private void UpdateAppointmentInfo()
        {
            UpdateSaleItem();
        }
        private void UpdateSaleItem()
        {
            if (rushToBuyModel.presentFlashShop.Equals(default(OperationFlashRushToBuy.FlashSaleShop))) return;
            StoreConfig storeConfig = Config.Instance.Get<StoreConfig>(saleItem.shopId);
            flashSaleBtn.RemoveAllListeners();
            var operation = rushToBuyModel.GetOperationFlashRushToBuy();
            int seconds = 0;
            int buyState = operation.GetBuyTimeState(TimeUtility.ServerNow,rushToBuyModel.presentFlashShop.dayIndex,
                rushToBuyModel.presentFlashShop.timeIndex,out seconds);
            switch(buyState)
            {
                case -1:
                    if(saleItem.isAppointment == 0)
                    {
                        btnStateText.text = "预约";
                        flashSaleBtn.AddListener(() => { rushToBuyModel.SendFlashSaleAppointment(saleItem.shopGuid, 1); });
                    }
                    else
                    {
                        btnStateText.text = "取消预约";
                        flashSaleBtn.AddListener(() => { rushToBuyModel.SendFlashSaleAppointment(saleItem.shopGuid, 0); });
                    }
                    break;
                case 0:
                    btnStateText.text = "秒杀";
                    flashSaleBtn.AddListener(() => { storeModel.SendBuyShopItem(storeConfig,saleItem.itemCount); });
                    break;
            }
        }
        private void UpdateSaleItemSellState()
        {
            int sellState = GetSellSate();
            switch (sellState)
            {
                case 0:
                    stateImg.gameObject.SetActive(false);
                    flashSaleBtn.gameObject.SetActive(true);
                    break;
                case 1:
                    stateImg.gameObject.SetActive(true);
                    flashSaleBtn.gameObject.SetActive(false);
                    break;
                case 2:
                    stateImg.gameObject.SetActive(true);
                    flashSaleBtn.gameObject.SetActive(false);
                    break;
            }
        }
        /// <summary>
        /// 0 秒杀 1 已买到 2 已抢光
        /// </summary>
        /// <returns></returns>
        private int GetSellSate()
        {
            var buyInfo = storeModel.GetBuyShopLimit((uint)saleItem.shopId);
            var buyCount = 0;
            if (buyInfo != null)
            {
                buyCount = buyInfo.BuyCnt;
            }
            stateImg.gameObject.SetActive(buyCount >= saleItem.limitNum);
            flashSaleBtn.gameObject.SetActive(buyCount < saleItem.limitNum);
            if(buyCount >= saleItem.limitNum)
            {
                return 1;
            }
            var fullServerInfo = rushToBuyModel.GetFullServerInfo();
            if(fullServerInfo != null && fullServerInfo.Value1 == saleItem.shopId
                && fullServerInfo.Value2 >= saleItem.fullServerLimitNum)
            {
                return 2;
            }
            return 0;
        }
    }
}
System/OpenServerActivity/FlashSaleTimeCell.cs
@@ -1,22 +1,84 @@
using UnityEngine;
using UnityEngine.UI;
using EnhancedUI.EnhancedScroller;
using System;
namespace Snxxz.UI
{
    public class FlashSaleTimeCell : ScrollerUI
    {
        [SerializeField] Text remainText;
        FlashRushToBuyModel rushToBuyModel { get { return ModelCenter.Instance.GetModel<FlashRushToBuyModel>(); } }
        [SerializeField] Button saleTimeBtn;
        [SerializeField] GameObject unSelectImg;
        [SerializeField] GameObject selectImg;
        FlashRushToBuyModel rushToBuyModel { get { return ModelCenter.Instance.GetModel<FlashRushToBuyModel>(); } }
        OperationFlashRushToBuy operation;
        int dayIndex = -1;
        int timeIndex = -1;
        private void Awake()
        {
            saleTimeBtn.AddListener(() =>
            {
                rushToBuyModel.UpdateSelectFlashSaleTime(dayIndex, timeIndex);
            });
        }
        private void OnEnable()
        {
            GlobalTimeEvent.Instance.secondEvent += UpdateBuyState;
        }
        private void OnDisable()
        {
            GlobalTimeEvent.Instance.secondEvent -= UpdateBuyState;
        }
        public override void Refresh(CellView cell)
        {
            var operation = rushToBuyModel.GetOperationFlashRushToBuy();
            operation = rushToBuyModel.GetOperationFlashRushToBuy();
            dayIndex = -1;
            timeIndex = -1;
            if (operation == null) return;
            int days = operation.totalDays;
            dayIndex = cell.index/(operation.flashShops.Count / days);
            timeIndex = cell.index % (operation.flashShops.Count / days);
            if(dayIndex == rushToBuyModel.presentFlashShop.dayIndex
                && timeIndex == rushToBuyModel.presentFlashShop.timeIndex)
            {
                selectImg.SetActive(true);
                unSelectImg.SetActive(false);
            }
            else
            {
                selectImg.SetActive(false);
                unSelectImg.SetActive(true);
            }
            UpdateBuyState();
        }
        public void UpdateBuyState()
        {
            if (operation == null) return;
            int seconds = 0;
            OperationTime operationTime = operation.times[timeIndex];
            var date = operation.startDate;
            int buyState = operation.GetBuyTimeState(TimeUtility.ServerNow, dayIndex, timeIndex, out seconds);
            switch (buyState)
            {
                case -1:
                    this.gameObject.SetActive(true);
                    string timeStr = operation.ToDisplayBuyTime(date.month, dayIndex + date.day, operationTime.startHour, operationTime.startMinute);
                    remainText.text = StringUtility.Contact(timeStr, "开抢");
                    break;
                case 0:
                    this.gameObject.SetActive(true);
                    remainText.text = StringUtility.Contact("秒杀进行中", TimeUtility.SecondsToHMS(seconds));
                    break;
                case 1:
                    this.gameObject.SetActive(false);
                    rushToBuyModel.UpdateSelectFlashSaleTime(dayIndex, timeIndex);
                    break;
            }
        }
    }
}
System/OpenServerActivity/OperationFlashRushToBuy.cs
@@ -23,6 +23,47 @@
            return false;
        }
        /// <summary>
        ///-1 未开始 0 开始 1结束
        /// </summary>
        /// <param name="time"></param>
        /// <param name="dayIndex"></param>
        /// <param name="timeIndex"></param>
        /// <returns></returns>
        public int GetBuyTimeState(DateTime time,int dayIndex,int timeIndex,out int seconds)
        {
            seconds = 0;
            int day = startDate.day + dayIndex;
            OperationTime operationTime = times[timeIndex];
            var startTime = new DateTime(startDate.year, startDate.month,day, operationTime.startHour, operationTime.startMinute,0);
            var endTime = new DateTime(startDate.year, startDate.month,day, operationTime.endHour, operationTime.endHour, 0);
            int advanceSec = Mathf.CeilToInt((float)(startTime - time).TotalSeconds);
            int endSec = Mathf.CeilToInt((float)(endTime - time).TotalSeconds);
            if (seconds > 0)
            {
                return -1;
            }
            else if(endSec <= 0)
            {
                return 1;
            }
            else
            {
                seconds = endSec;
                return 0;
            }
        }
        public string ToDisplayBuyTime(int month,int day,int startHour,int startMinute)
        {
            return StringUtility.Contact(month, Language.Get("Month"), day, Language.Get("Day"), startHour.ToString("D2"), ":", startMinute.ToString("D2"));
        }
        public string ToDisplayBuyTime(int startHour, int startMinute)
        {
            return StringUtility.Contact(startHour.ToString("D2"), ":", startMinute.ToString("D2"));
        }
        public override bool SatisfyOpenCondition()
        {
            return PlayerDatas.Instance.baseData.LV >= limitLv;
@@ -61,6 +102,7 @@
                    var item = new FlashSaleItem();
                    var saleItem = shop.GiftbagInfo[k];
                    item.shopId = (int)saleItem.GiftID;
                    item.shopGuid = shop.DayIndex*1000 + shop.TimeIndex*100 + k;
                    item.limitNum = saleItem.BuyCountLimit;
                    item.fullServerLimitNum = saleItem.ServerBuyCountLimit;
                    item.moneyType = saleItem.MoneyType;
@@ -69,6 +111,7 @@
                    item.itemId = (int)saleItem.ItemID;
                    item.itemCount = saleItem.ItemCount;
                    item.isBind = saleItem.IsBind;
                    item.isAppointment = 0;
                    gift.items[k] = item;
                }
                flashShops.Add(gift);
@@ -86,6 +129,7 @@
        public struct FlashSaleItem
        {
            public int shopId;
            public int shopGuid;
            public int limitNum;//个人限购数量
            public int fullServerLimitNum; //个人限购数量
            public int moneyType;
@@ -94,6 +138,7 @@
            public int itemId;
            public int itemCount;
            public int isBind;
            public int isAppointment; //是否预约
        }
    }
}
Utility/GlobalTimeEvent.cs
@@ -11,6 +11,7 @@
    public event Action tenMinuteEvent;
    public event Action halfHourEvent;
    public event Action hourEvent;
    public event Action halfMinuteEvent;
    int secondBuf = -1;
    int minuteBuf = -1;
@@ -18,6 +19,7 @@
    int tenMinuteBuf = -1;
    int halfHourBuf = -1;
    int hourBuf = -1;
    int halfMinuteBuf = -1;
    public void Begin()
    {
@@ -57,6 +59,26 @@
            }
        }
        var thirtySeconds = second / 30;
        if (halfMinuteBuf != thirtySeconds)
        {
            try
            {
                if (halfMinuteEvent != null)
                {
                    halfMinuteEvent();
                }
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
            }
            finally
            {
                halfMinuteBuf = thirtySeconds;
            }
        }
        var fiveMinute = minute / 5;
        if (fiveMinuteBuf != fiveMinute)
        {