--[[
    背包系统主模块
    主要功能:
    - 管理背包界面布局
    - 处理多页签切换
    - 物品格子初始化
    - 货币数量更新
    平台适配说明:
    - 支持Win32和移动端双平台不同布局
    - 通过isWin32参数区分平台配置
]]

Bag = {}

function Bag.Init(isWin32)
    -- 平台相关布局配置参数
    -- _ScrollHeight: 滚动容器总高度
    -- _PWidth/_PHeight: 容器可见区域尺寸
    -- _IWidth/_IHeight: 单个物品格子尺寸
    -- _Row/_Col: 行列数(Win32采用12x10布局,移动端8x5布局)
    Bag._ScrollHeight = isWin32 and 214 or 320
    Bag._PWidth       = isWin32 and 338 or 500
    Bag._PHeight      = isWin32 and 214 or 320
    Bag._IWidth       = isWin32 and 30 or 62.5
    Bag._IHeight      = isWin32 and 30 or 64
    Bag._Row          = isWin32 and 10 or 5
    Bag._Col          = isWin32 and 12 or 8
    Bag._PerPageNum   = isWin32 and 120 or 40  -- 每页容量 = 行数 x 列数
    Bag._defaultNum   = isWin32 and 120 or 40  -- 默认每页格子数
    Bag._MaxPage      = isWin32 and 1 or 3     -- 最大支持页数
    Bag._codeInitGrid = false  -- 是否用代码生成格子(当UI预制件中无格子时启用)

    -- 状态控制变量
    Bag._changeStoreMode = false  -- 切换存储模式标志
    Bag._bagPage    = isWin32 and 1 or 3  -- 当前开放的页数
    Bag._selPage    = 0  -- 当前选中页签索引
    Bag._openNum    = 126  -- 当前开放的格子总数(从服务器获取)

    -- 资源路径配置
    Bag._lockImg   = isWin32 and "res/image/bag_ui/pc/lock.png" or "res/image/bag_ui/mobile/lock.png"
    Bag._baiTanImg = isWin32 and "res/public/word_bqzy_09_1.png" or "res/public/word_bqzy_09.png"
    Bag._bagPageBtns = {}  -- 页签按钮缓存表
end

--[[
    主入口函数
    @param page: 初始显示页数(可选)
]]
function Bag.main(page)
    local parent = GUI:Attach_Parent()
    local isWin32 = SL:GetMetaValue("WINPLAYMODE")
    -- 加载平台对应的UI预制件
    GUI:LoadExport(parent, isWin32 and "bag/bag_panel_win32" or "bag/bag_panel")

    -- 初始化UI引用和代理
    Bag._ui = GUI:ui_delegate(parent)
    Bag._UI_ScrollView = Bag._ui["ScrollView_items"]

    Bag.Init(isWin32)  -- 初始化配置参数

    -- 界面定位适配
    GUI:setPositionY(Bag._ui["Panel_1"], isWin32 and SL:GetMetaValue("PC_POS_Y") or SL:GetMetaValue("SCREEN_HEIGHT") / 2)

    -- 设置界面拖动和浮起功能
    GUI:Win_SetDrag(parent, Bag._ui["Image_bg"])
    GUI:Win_SetZPanel(parent, Bag._ui["Image_bg"])

    -- 关闭按钮事件
    GUI:addOnClickEvent(Bag._ui["Button_close"], function()
        SL:CloseBagUI()
    end)

    -- 存入英雄背包按钮逻辑
    local Button_store_hero_bag = Bag._ui["Button_store_hero_bag"]
    GUI:addOnClickEvent(Button_store_hero_bag, function()
        local changeStoreMode = not Bag._changeStoreMode
        -- 切换前验证英雄状态
        if changeStoreMode then
            if not SL:GetMetaValue("HERO_IS_ACTIVE") then
                return SL:ShowSystemTips("英雄还未激活")
            end
            if not SL:GetMetaValue("HERO_IS_ALIVE") then
                return SL:ShowSystemTips("英雄还未召唤")
            end
        end
        Bag._changeStoreMode = changeStoreMode
        GUI:Button_setGrey(Button_store_hero_bag, changeStoreMode)
    end)
    GUI:setVisible(Button_store_hero_bag, SL:GetMetaValue("USEHERO"))

    Bag.InitPage()    -- 初始化页签
    Bag.PageTo(page or 1)  -- 跳转到指定页
    Bag.OnUpdateGold()  -- 初始化货币显示
    Bag.RegisterEvent() -- 注册事件监听

    -- 设置页签层级
    GUI:setLocalZOrder(Bag._ui.Button_page1, 4)
    GUI:setLocalZOrder(Bag._ui.Button_page2, 3)
    GUI:setLocalZOrder(Bag._ui.Button_page3, 2)
end

--[[
    初始化页签按钮
    根据开放页数动态显示/隐藏页签按钮
]]
function Bag.InitPage()
    -- 计算实际需要显示的页数
    Bag._bagPage = math.ceil(Bag._openNum / Bag._PerPageNum)
    Bag._bagPage = math.max(Bag._bagPage, 1)
    Bag._bagPage = math.min(Bag._bagPage, Bag._MaxPage)

    -- 遍历初始化所有页签按钮
    for i = 1, Bag._MaxPage do
        local pageBtn = Bag._ui["Button_page" .. i]
        GUI:setVisible(pageBtn, false)
        if Bag._bagPage ~= 1 and i <= Bag._bagPage then
            GUI:setVisible(pageBtn, true)
            GUI:setTag(pageBtn, i)  -- 用tag存储页索引
            Bag._bagPageBtns[i] = pageBtn
            -- 页签点击事件
            GUI:addOnClickEvent(GUI:getChildByName(pageBtn, "TouchSize"), function()
                if Bag._selPage == i then return end
                Bag.PageTo(i)
                if Bag.UpdateItems then
                    Bag.UpdateItems()  -- 刷新物品显示
                end
            end)
        end
    end
end

--[[
    跳转到指定页签
    @param page: 目标页数(1-based)
]]
function Bag.PageTo(page)
    if Bag._selPage == page then return end
    SL:SetMetaValue("BAG_PAGE_CUR", page)
    Bag._selPage = page
    Bag.SetPageBtnStatus()  -- 更新按钮状态
end

-- 更新页签按钮的选中状态
function Bag.SetPageBtnStatus()
    for i = 1, Bag._bagPage do
        local btnPage = Bag._bagPageBtns[i]
        if btnPage then
            local isPress = i == Bag._selPage
            -- 通过ZOrder和纹理切换实现选中效果
            GUI:setLocalZOrder(btnPage, isPress and Bag._bagPage + 1 or GUI:getTag(btnPage))
            GUI:Button_loadTextureNormal(btnPage, 
                isPress and "res/image/bag_ui/mobile/p" .. i .. "_light.png" 
                       or "res/image/bag_ui/mobile/p" .. i .. "_gray.png")
        end
    end
end

-- 初始化背包格子线(当_codeInitGrid为true时调用)
function Bag.InitGird()
    local index = 0
    -- 绘制垂直和水平格子线
    for i = 1, Bag._Row + 1 do
        for j = 1, Bag._Col + 1 do
            local x = (j-1) * Bag._IWidth
            local y = Bag._ScrollHeight - (i-1) * Bag._IHeight

            -- 绘制垂直线(旋转90度的图片)
            if i <= Bag._Row then
                local pGird1 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_1_" .. index, x, y, "res/public/bag_gezi.png")
                GUI:setAnchorPoint(pGird1, 0, j == 1 and 0 or 1)  -- 首列底部对齐,其他顶部对齐
                GUI:setRotation(pGird1, 90)
                index = index + 1
            end

            -- 绘制水平线
            if j <= Bag._Col then
                local pGird2 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_2_" .. index, x, y, "res/public/bag_gezi.png")
                GUI:setAnchorPoint(pGird2, 0, i == 1 and 1 or 0)  -- 首行顶部对齐,其他底部对齐
                index = index + 1
            end
        end
    end
end

--[[
    重置初始化参数(根据游戏数据动态调整)
    从GAME_DATA.bag_row_col获取行列配置,格式:"列数|行数"
]]
function Bag.ResetInitData()
    local isWinMode = SL:GetMetaValue("WINPLAYMODE")
    local bag_row_col = SL:GetMetaValue("GAME_DATA", "bag_row_col_max")
    if isWinMode and bag_row_col then 
        local slices = string.split(bag_row_col, "|") 
        -- 覆盖默认行列配置
        Bag._Row = tonumber(slices[2]) or 5
        Bag._Col = tonumber(slices[1]) or 8
        Bag._PerPageNum = Bag._Row * Bag._Col

        -- 当自定义容量大于默认时隐藏页签
        if Bag._PerPageNum > Bag._defaultNum then 
            for i = 1, Bag._MaxPage do
                GUI:setVisible(Bag._ui["Button_page"..i], false)
            end
        end 
    end 

    -- 重新计算容器尺寸
    local pSize = GUI:getContentSize(Bag._UI_ScrollView)
    GUI:ScrollView_setInnerContainerSize(Bag._UI_ScrollView, pSize)
    Bag._ScrollHeight = pSize.height
    Bag._PWidth = pSize.width
    Bag._PHeight = pSize.height
    Bag._IWidth = Bag._PWidth / Bag._Col  -- 重新计算格子宽度
    Bag._IHeight = Bag._PHeight / Bag._Row -- 重新计算格子高度

    -- 按需生成格子线
    if Bag._codeInitGrid then
        Bag.InitGird()
    end
end

--[[
    货币更新处理
    @param data: 事件数据(可选),当指定时只更新对应货币
]]
function Bag.OnUpdateGold(data)
    -- 货币类型配置表
    local currencyTypes = {
        {id = 1, uiKey = "Text_goldNum"},       -- 金币
        {id = 2, uiKey = "Text_gamegoldNum"},   -- 元宝
        {id = 4, uiKey = "Text_b_gamegoldNum"}, -- 绑定元宝
        {id = 7, uiKey = "Text_gamegirdNum"},   -- 代币
        {id = 8, uiKey = "Text_b_gamegirdNum"}, -- 绑定代币
    }

    local function updateCurrency(id, uiElement)
        local amount = SL:GetMetaValue("ITEM_COUNT", id) or 0
        if Bag._ui[uiElement] then
            GUI:Text_setString(Bag._ui[uiElement], amount)
        end
    end

    if not data then
        -- 全量更新所有货币
        for _, currency in ipairs(currencyTypes) do
            updateCurrency(currency.id, currency.uiKey)
        end
    else
        -- 增量更新指定货币
        for _, currency in ipairs(currencyTypes) do
            if data.id == currency.id then
                updateCurrency(currency.id, currency.uiKey)
                break
            end
        end
    end
end

-- 事件拦截函数(供业务层扩展)
function Bag.IsCanSingle(data) return true end  -- 是否允许单击
function Bag.IsCanDouble(data) return true end  -- 是否允许双击

-- 关闭事件处理
function Bag.OnClose(winID)
    if winID == "BagLayerGUI" then
        Bag.UnRegisterEvent()
    end
end

-- 事件注册/注销
function Bag.RegisterEvent()
    SL:RegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag", Bag.OnUpdateGold)
    SL:RegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag", Bag.OnClose)
end

function Bag.UnRegisterEvent()
    SL:UnRegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag")
    SL:UnRegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag")
end
    撰写回复...