local addonName, ZLAUTO= ...

local ZL = ZLAUTO.mainFrame
local REALM_SEPARATOR_LIST = {}
local cGetItemInfo = C_Item and C_Item.GetItemInfo or GetItemInfo
local cGetItemIcon = C_Item and C_Item.GetItemIconByID or GetItemIcon
local GetItemInfoInstant = C_Item and C_Item.GetItemInfoInstant or GetItemInfoInstant
ZL.GUI = LibStub('tdGUI-1.0')
-- 依赖库: AceAddon-3.0, AceComm-3.0, LibSerialize, LibDeflate
local MyAddon = LibStub("AceAddon-3.0"):GetAddon("AutoAuction", true)
if not MyAddon then
    MyAddon = LibStub("AceAddon-3.0"):NewAddon("AutoAuction", "AceComm-3.0")
end
ZL.MyAddon = MyAddon
for s in REALM_SEPARATORS:gmatch(".") do tinsert(REALM_SEPARATOR_LIST, s) end

ZL.colorList = {
    waiting = {1, 1, 1, 1},
    auctioning = {0, 0, 1, 1},
    success = {0, 1, 0, 1},
    failed = {1, 0, 0, 1},
    lgnore = {0.5, 0.5, 0.5, 1},
    other = {0.2, 0.2, 0.2, 1}
}


--将RGB转换为|caarrggbb|r格式
function ZL.RGBAToHex(r, g, b, a)
    a = a or 1
    r = math.max(0, math.min(255, r))
    g = math.max(0, math.min(255, g))
    b = math.max(0, math.min(255, b))
    a = math.max(0, math.min(255, a))
    return string.format("|c%02X%02X%02X%02X", a, r, g, b)
end
--背景，测试用
function ZL.background(frame)
    frame.background = frame:CreateTexture(nil, "BACKGROUND")
    frame.background:SetAllPoints(frame) -- 让纹理覆盖整个Frame
    frame.background:SetColorTexture(math.random(), math.random(), math.random()) -- 设置为随机颜色
end

--设置消息前缀为[AutoAuction]
function ZL.Prefix(...)
    local prefix = string.format("|cff87CEEB%s|r", "[AutoAuction]")
    return string.join(" ", prefix, tostringall(...))
end

function ZL.Print(msgStr, r, g, b, notScrollFrame, notChatFrame)
    r = r or 1
    g = g or 0.82
    b = b or 0
    if not notScrollFrame then
        ZL.ScrollingMessageFrame:AddMessage(msgStr, r, g, b)
    end
    if not notChatFrame then
        DEFAULT_CHAT_FRAME:AddMessage(ZL.Prefix(msgStr), r, g, b)
    end
end

--定义空元表
function ZL.emptytable(...)
    local logTableRequests = false
    local tables = {}
    local meta = {
        __index = {
            Release=function(t,noRecursion)
                if not noRecursion then
                    for key,val in pairs(t) do
                        if (type(val) == "table") and (getmetatable(val) == "TempTable") then
                            val:Release()
                        end
                    end
                end
                table.wipe(t)
                if not tContains(tables,t) then
                    tinsert(tables,t)
                end
            end,
        },
        __metatable = "TempTable",
    }
    if logTableRequests then
        TempTables_RequestLog = {}
    end
    local t = tremove(tables) or setmetatable({},meta)
    for i=1,select('#',...) do
        t[i] = (select(i,...))
    end
    if logTableRequests then
        local tostrT = tostring(t)
        TempTables_RequestLog[tostrT] = TempTables_RequestLog[tostrT] or {}
        tinsert(TempTables_RequestLog[tostrT],debugstack())
    end
    return t
end
-- 团队官员，非团长
function ZL.IsRaidOfficer()
	return IsInRaid(1) and UnitIsRaidOfficer("player")
end
--小队队长或团队团长
function ZL.IsRaidLeader()
	return IsInRaid(1) and UnitIsGroupLeader("player")
end
--是否拥有拾取权限(ML权限)，默认为玩家自己
function ZL.PlayerIsML(playerName)
    playerName = playerName or UnitName("player")
    playerName = ZL.ParseClassColorName(playerName)
    local lootMethod, partyMaster, raidMaster = GetLootMethod()
    if IsInRaid(1) then
        if lootMethod == "master" and (raidMaster == UnitInRaid(playerName)) then
            return true
        else
            return false
        end
    elseif IsInRaid(2) or IsInGroup() then
        return false
    else
        if ZL.opt.developerMode then
            if playerName ~= UnitName("player") then
                return false
            else
                return true
            end
        else
            return false
        end
    end
end

--获取ML的名字
function ZL.GetMLname()
    local _, masterlooterPartyID, masterlooterRaidID = GetLootMethod()
    local MLname
    if masterlooterRaidID then
        MLname = UnitName("raid" .. masterlooterRaidID)
    -- elseif masterlooterPartyID then
    --     if masterlooterPartyID == 0 then
    --         MLname= UnitName("player")
    --     else
    --         MLname = UnitName("party" .. masterlooterPartyID)
    --     end
    end
    if MLname == "未知目标" then MLname = nil end
    return MLname
end

--获取RL的名字
function ZL.GetRLname()
    if IsInRaid(1) then
        for i = 1, MAX_RAID_MEMBERS do
            local name, rank = GetRaidRosterInfo(i)
            if rank == 2 then
                return name
            end
        end
    end
    return nil
end
--战利品窗口槽是否为物品：0表示没有东西，1表示为物品，2表示为钱
function ZL.LootSlotIsItem(i)
	return (GetLootSlotType(i) == 1)
end

--拍卖倒计时，默认拍卖时间3600秒
function ZL.CountDown(index, endtime)
    local Frame1 = ZL.AuctionFrame.entries[index].Frame1
    if ZL.IsCandidate(index) then
        Frame1.statetext:SetText("拍卖中...")
        if Frame1:GetParent().maxAutoBid then
            Frame1.bidbox:Disable()
            Frame1.bidBtn:Disable()
            Frame1.lgnoreBtn:Disable()
        else
            Frame1.bidbox:Enable()
            Frame1.bidBtn:Enable()
            Frame1.lgnoreBtn:Enable()
        end
        Frame1.autobidBtn:Enable()
    else
        Frame1.statetext:SetText("你不是装备候选人，无法竞拍")
        Frame1.bidbox:Disable()
        Frame1.bidBtn:Disable()
        Frame1.autobidBtn:Disable()
        Frame1.lgnoreBtn:Enable()
    end
    Frame1.MLframe.PauseBtn:Enable()
    Frame1.MLframe.CancelBtn:SetText("取消")
    Frame1.MLframe.CountDownBtn:Enable()
    Frame1.MLframe.reverseBidBtn:Enable()
    Frame1.MLframe.delAuctionBtn:Disable()
    endtime = endtime or 3600
    Frame1.timer.updateframe:Show()
    Frame1.timer.oneMinuteWarn = false
    Frame1.timer:SetCooldown(GetTime(), endtime)
end
-- 如果GetUnitName不能解析名字为unitID，需我们自己的定义，手动解析
function ZL.localNameOnly(name)
	for _, s in ipairs(REALM_SEPARATOR_LIST) do
		local i = name:find(s, 1, true)
		if i then name = name:sub(1, i - 1) end
	end
	return name
end

--仅在团队中使用,自定义手动解析玩家名字
function ZL.pruneCrossRealm(name)
	return GetUnitName(name, true) or ZL.localNameOnly(name)
end
--创建默认按钮
function ZL.CreateButton(ButtonName, parent, ButtonText, point, relativeto, relativePoint, offsetX, offsetY, Width, Height, fontSize)
	offsetX = offsetX or 0
	offsetY = offsetY or 0
	Width = Width or 70
	Height = Height or 20
	fontSize = fontSize or 14
	local btn = CreateFrame("Button", ButtonName, parent) -- , "UIPanelButtonTemplate"
    ZL.CreateBorder(btn, 0.24, 0.25, 0.3, 1, "OVERLAY", 1)
	btn:SetText(ButtonText or " ")
	btn:SetSize(Width, Height)
    btn:SetPoint(point, relativeto, relativePoint, offsetX, offsetY)
    do
        local texture = btn:CreateTexture(nil,"BACKGROUND")
		texture:SetColorTexture(0,0,0,1)
		texture:SetPoint("TOPLEFT")
		texture:SetPoint("BOTTOMRIGHT")
        btn.Background = texture
    end
    do
        local texture = btn:CreateTexture()
        texture:SetColorTexture(0.9,0.9,0.9,.2)
        texture:SetPoint("TOPLEFT")
        texture:SetPoint("BOTTOMRIGHT")
        btn:SetHighlightTexture(texture)
    end
    -- do
    --     local texture = btn:CreateTexture()
    --     texture:SetColorTexture(.9,.8,.1,.3)
    --     texture:SetPoint("TOPLEFT")
    --     texture:SetPoint("BOTTOMRIGHT")
    --     btn:SetPushedTexture(texture)
    -- end
	btn:SetNormalFontObject("GameFontNormal")
	btn:SetHighlightFontObject("GameFontHighlight")
	btn:SetDisabledFontObject("GameFontDisable")
    local fontString = btn:GetFontString()
    if fontString then
	    fontString:SetFont(GameFontNormal:GetFont(), fontSize)
    end
	return btn
end

--创建标题按钮
function ZL.CreateHeaderButton(parent, width, height, size)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(width or 40, height or 21)

    -- 背景层
    local backgroundLeft = btn:CreateTexture("backgroundLeft", "BACKGROUND")
    backgroundLeft:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
    backgroundLeft:SetSize(8, height)
    backgroundLeft:SetPoint("TOPLEFT")
    -- backgroundLeft:SetColorTexture(0.25, 0.25, 0.25, 1)
    backgroundLeft:SetTexCoord(0.0625, 0.1875, 0.34375, 1)
    
    
    local backgroundRight = btn:CreateTexture("backgroundRight", "BACKGROUND")
    backgroundRight:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
    backgroundRight:SetSize(8, height)
    backgroundRight:SetPoint("TOPRIGHT")
    backgroundRight:SetTexCoord(0.8125, 0.9375, 0.34375, 1)
    -- backgroundRight:SetColorTexture(0.25, 0.25, 0.25, 1)
    
    local backgroundMid = btn:CreateTexture("backgroundMid", "BACKGROUND")
    backgroundMid:SetTexture("Interface\\ChatFrame\\ChatFrameTab")
    backgroundMid:SetSize(0, height)
    backgroundMid:SetPoint("TOPLEFT", 8, 0)
    backgroundMid:SetPoint("TOPRIGHT", -8, 0)
    backgroundMid:SetTexCoord(0.1875, 0.8125, 0.34375, 1)
    -- backgroundMid:SetColorTexture(0.25, 0.25, 0.25, 1)

    do
        local texture = btn:CreateTexture()
        texture:SetColorTexture(0, 0, 1, 0.2)
        texture:SetPoint("TOPLEFT")
        texture:SetPoint("BOTTOMRIGHT")
        btn:SetHighlightTexture(texture)
    end
    -- 按钮文本
    -- local customFont = CreateFont("CustomFont")
    -- customFont:SetFont(GameFontNormal:GetFont(), size or 14, "")  -- 字体路径、大小、字体样式
    -- customFont:SetTextColor(1, 1, 1)
	-- btn:SetNormalFontObject(customFont) --GameFontNormal
    btn:SetNormalFontObject("GameFontNormal")
	btn:SetHighlightFontObject("GameFontHighlight")
	btn:SetDisabledFontObject("GameFontDisable")
    -- local fontString = btn:GetFontString()
	-- fontString:SetFont(GameFontNormal:GetFont(), size)

    return btn
end
--创建边框
function ZL.CreateBorder(frame, r, g, b, a, drawLayer, size)
    drawLayer = drawLayer or "BACKGROUND"
    size = size or 1
    frame.BorderTop = frame.BorderTop or frame:CreateTexture(nil,drawLayer) --BACKGROUND  OVERLAY
    frame.BorderTop:SetColorTexture(r,g,b,a)
    -- frame.BorderTop:SetTexture([[Interface\Common\UI-TooltipDivider-Transparent]])
    frame.BorderTop:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
    frame.BorderTop:SetPoint("BOTTOMRIGHT",frame,"TOPRIGHT",0,-size)
    -- frame.BorderTop = frame.BorderTop or frame:CreateLine()
    -- frame.BorderTop:SetColorTexture(r,g,b,a)
    -- frame.BorderTop:SetStartPoint("TOPLEFT", 0, 0)
    -- frame.BorderTop:SetEndPoint("TOPRIGHT", 0, 0)
    -- frame.BorderTop:SetThickness(size)

    frame.BorderLeft = frame.BorderLeft or frame:CreateTexture(nil,drawLayer)
    frame.BorderLeft:SetColorTexture(r,g,b,a)
    frame.BorderLeft:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
    frame.BorderLeft:SetPoint("BOTTOMRIGHT",frame,"BOTTOMLEFT",size,0)
    -- frame.BorderLeft = frame.BorderLeft or frame:CreateLine()
    -- frame.BorderLeft:SetColorTexture(r,g,b,a)
    -- frame.BorderLeft:SetStartPoint("TOPLEFT", 0, 0)
    -- frame.BorderLeft:SetEndPoint("BOTTOMLEFT", 0, 0)
    -- frame.BorderLeft:SetThickness(size)


    frame.BorderBottom = frame.BorderBottom or frame:CreateTexture(nil,drawLayer)
    frame.BorderBottom:SetColorTexture(r,g,b,a)
    -- frame.BorderBottom:SetTexture([[Interface\Common\UI-TooltipDivider-Transparent]])
    frame.BorderBottom:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
    frame.BorderBottom:SetPoint("TOPRIGHT",frame,"BOTTOMRIGHT",0,size)
    -- frame.BorderBottom = frame.BorderBottom or frame:CreateLine()
    -- frame.BorderBottom:SetColorTexture(r,g,b,a)
    -- frame.BorderBottom:SetStartPoint("BOTTOMLEFT", 0, 0)
    -- frame.BorderBottom:SetEndPoint("BOTTOMRIGHT", 0, 0)
    -- frame.BorderBottom:SetThickness(size)

    frame.BorderRight = frame.BorderRight or frame:CreateTexture(nil,drawLayer)
    frame.BorderRight:SetColorTexture(r,g,b,a)
    frame.BorderRight:SetPoint("TOPLEFT",frame,"TOPRIGHT",0,0)
    frame.BorderRight:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-1,0)
    -- frame.BorderRight = frame.BorderRight or frame:CreateLine()
    -- frame.BorderRight:SetColorTexture(r,g,b,a)
    -- frame.BorderRight:SetStartPoint("TOPRIGHT", 0, 0)
    -- frame.BorderRight:SetEndPoint("BOTTOMRIGHT", 0, 0)
    -- frame.BorderRight:SetThickness(size)
end

--创建框架
function ZL.ZLCreateFrame(FrameName, parent, Width, Height, FrameStrata, ClampedToScreen, Movable, TitleText)
    local f = CreateFrame("Frame", FrameName, parent or ZL)
    ZL.CreateBorder(f, 1, 1, 1, 0.5, "OVERLAY", 1)
    f:SetSize(Width or 305, Height or 350)
    f:SetFrameStrata(FrameStrata or "DIALOG")
    f:SetClampedToScreen(ClampedToScreen and true or false)
    f:SetMovable(Movable and true or false)
    f:SetResizable(true)
    f:SetResizeBounds(305, 219, GetScreenWidth()-30, GetScreenHeight()-110) -- 设置最小尺寸，以避免框架被缩小到看不见
    ZL.CreateResizeButton(f)

    f.Background = f:CreateTexture(nil,"BACKGROUND")
    f.Background:SetColorTexture(0, 0, 0, .8)
    f.Background:SetPoint("TOPLEFT")
    f.Background:SetPoint("BOTTOMRIGHT")

    f.TitleBottom = f:CreateTexture(nil,"ARTWORK")
    f.TitleBottom:SetColorTexture(1, 1, 1, 0.5)
    f.TitleBottom:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -26)
    f.TitleBottom:SetPoint("BOTTOMRIGHT", f, "TOPRIGHT", 0, -27)

    f.Title = f:CreateFontString(nil, "OVERLAY")
    f.Title:SetFont(GameFontNormal:GetFont(), 15, "")
    f.Title:SetTextColor(1, 0.82, 0)
    f.Title:SetWordWrap(false)
    f.Title:SetJustifyH("CENTER")
    f.Title:SetJustifyV("MIDDLE")
    f.Title:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -1)
    f.Title:SetPoint("TOPRIGHT", f, "TOPRIGHT", -20, 0)
    f.Title:SetHeight(26)
    f.Title:SetText(TitleText or "")

    f.closeButton = CreateFrame("Button", nil, f, "UIPanelCloseButton")
    f.closeButton:SetPoint("LEFT", f.Title, "RIGHT", -5, 0)
    f.closeButton:SetSize(30, 30)

    -- f.closeButton = ZL.CreateButton(nil, f, "x", "TOPRIGHT", f, "TOPRIGHT", 0, 0, 20, 20, 18)
    -- f.closeButton.Background:SetColorTexture(1, 1, 1, 0)
    -- f.closeButton.BorderTop:SetColorTexture(1, 1, 1, 1)
    -- f.closeButton.BorderLeft:SetColorTexture(1, 1, 1, 1)
    -- f.closeButton.BorderBottom:SetColorTexture(1, 1, 1, 1)
    -- f.closeButton.BorderRight:SetColorTexture(1, 1, 1, 1)
    -- f.closeButton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Up")
    f.closeButton:SetScript("OnClick", function (self)
        f:Hide()
    end)
    f:SetScript("OnMouseUp", function (self)
        self:StopMovingOrSizing()
    end)
    f:SetScript("OnMouseDown", function (self)
        self:StartMoving()
    end)
    return f
end
--创建文本框
--parent, width, heigth, fontSize, justifyH, numeric, multiLine, r, g, b, a, name
function ZL.CreateEditBox(parent, width, heigth, fontSize, justifyH, numeric, multiLine, r, g, b, a, name)
    r = r or 0.24
    g = g or 0.25
    b = b or 0.3
    a = a or 1
    local editBox = CreateFrame("EditBox", name, parent, BackdropTemplateMixin and "BackdropTemplate")
    editBox:EnableMouse(true)
    ZL.CreateBorder(editBox, r, g, b, a, "OVERLAY", 1)

    editBox.Background = editBox:CreateTexture(nil,"BACKGROUND")
    editBox.Background:SetColorTexture(0,0,0,0.5)
    editBox.Background:SetPoint("TOPLEFT")
    editBox.Background:SetPoint("BOTTOMRIGHT")

    editBox:SetFontObject("ChatFontNormal")

    editBox:SetTextInsets(4, 4, 0, 0)
    editBox:SetSize(width or 60, heigth or 20)
    editBox:SetFont(GameFontNormal:GetFont(), fontSize or 14, "")
    editBox:SetMultiLine(multiLine)
    editBox:SetTextColor(0.95, 0.95, 0.95)
    editBox:SetAutoFocus(false)
    editBox:SetNumeric(numeric)
    editBox:SetJustifyH(justifyH or "CENTER")

    editBox:SetScript("OnEscapePressed",function (self)
        self:ClearFocus()
    end)
    editBox:SetScript("OnEnterPressed", function (self)
        self:ClearFocus()
    end)
    editBox:SetScript("OnEditFocusLost",function (self)
        self:HighlightText(0, 0)
    end)
    editBox:SetScript("OnEditFocusGained",function (self)
        self:HighlightText()
    end)

    return editBox
end

--创建拉升按钮
function ZL.CreateResizeButton(parent)
    -- 创建右下角的拉伸角标
    -- AuctionFrame.resizeButton = CreateFrame("Button", nil, AuctionFrame)
    local resizeButton = CreateFrame("Button", nil, parent)
    resizeButton:SetSize(16, 16)
    resizeButton:SetPoint("BOTTOMRIGHT")

    -- 设置拉伸角标的纹理，可以是默认的角标图案
    resizeButton.texture = resizeButton:CreateTexture(nil, "BACKGROUND")
    resizeButton.texture:SetAllPoints()
    resizeButton.texture:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up") -- 默认拉伸图标
    -- 鼠标悬停和点击效果
    resizeButton:SetHighlightTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
    resizeButton:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down")
    -- 设置鼠标按下时开始调整大小
    resizeButton:SetScript("OnMouseDown", function(self, button)
        if button == "LeftButton" then
            parent:StartSizing("BOTTOMRIGHT")
        end
    end)
    -- 鼠标松开时停止调整大小
    resizeButton:SetScript("OnMouseUp", function(self, button)
        parent:StopMovingOrSizing()
    end)
    parent.resizeButton = resizeButton
end

--重写滑动条鼠标滚动事件
function ZL.ScrollFrame_OnMouseWheel(self, delta)
    local newValue = self:GetVerticalScroll() - (delta * 20)
    if newValue < 0 then
        newValue = 0
    elseif newValue > self:GetVerticalScrollRange() then
        newValue = self:GetVerticalScrollRange()
    end
    self:SetVerticalScroll(newValue)
end

--更新拍卖主窗口
function ZL.UpdateAuctionFrame()
    local height = 0
    local content = ZL.AuctionFrame.scrollFrame.content
    for _, frame in ipairs(auctionFrames) do
        if frame:IsShown() then
            frame:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
            height = height + frame:GetHeight()
        end
    end
    content:SetHeight(height) --设置滚动放置区域高度
end

--根据值查询索引号,只能查询到第一个出现的
function ZL.tableIndex(myTable, targetValue)
    for i, value in ipairs(myTable) do
        if value == targetValue then
            return i
        end
    end
end
--根据itemId和itemindex获取数据库中是否已存在该拍卖物品
function ZL.FetchDataFromItemId(itemlink, itemindex)
    if ZL_CURRENT.auctionlist and #ZL_CURRENT.auctionlist > 0 then
        for index, data in ipairs(ZL_CURRENT.auctionlist) do
            if (data.itemlink == itemlink) and (data.itemindex == itemindex) then --注意匹配时数据类型是否一致
                return data, index
            end
        end
    end
    return nil, nil
end
--按钮点击间隔时间
function ZL.btnDelay(self)
    C_Timer.After(0.3, function() --ZL.opt.buttonReenableDelay
        self:Disable()
        C_Timer.After(1, function() --ZL.opt.buttonReenableDelay
            self:Enable()
        end)
    end)
end
--没被忽略情况下，拍卖状态的物品个数:拍卖中，等待拍卖，成功，流拍, 忽略
function ZL.auctionStateCount()
    local auctioningCount = 0
    local waitingCount = 0
    local successCount = 0
    local failedCount = 0
    local lgnoreCount = 0
    for _, frame in ipairs(ZL_CURRENT.auctionlist) do
        if frame.lgnore then
            lgnoreCount = lgnoreCount + 1
        else
            if frame.state == "auctioning" then
                auctioningCount = auctioningCount + 1
            elseif frame.state == "waiting" then
                waitingCount = waitingCount + 1
            elseif frame.state == "success" then
                successCount = successCount + 1
            elseif frame.state == "failed" then
                failedCount = failedCount + 1
            end
        end
    end
    return auctioningCount, waitingCount, successCount, failedCount, lgnoreCount
end
--通过itemId获取数组表的索引
function ZL.GetIndex(table, itemId)
    for index, data in ipairs(table) do
        if data.itemId == itemId then
            return index
        end
    end
    return nil
end

--获取起拍价和每次最低加价，优先顺序：独立的物品设置，按照物品等级设置，默认设置
function ZL.GetStartAndIncrementBid(itemId)
	local index = ZL.GetIndex(ZL_SETTING["itemIdSetting"], itemId)
    if index then
        return ZL_SETTING["itemIdSetting"][index].startbid, ZL_SETTING["itemIdSetting"][index].increment
    end
    --然后查询按照物品等级，如果存在，则按照物品等级设置返回
    --先判断物品类型
    if (ZL_SETTING["itemLevelSetting"] and #ZL_SETTING["itemLevelSetting"] > 0) then
        local itemType = nil
        local itemLevel = ZL.setsItemLevelData[tostring(itemId)] --查询是否为兑换套装物品
        if itemLevel then
            itemType = "套装"
        else
            local function linshi(itemlink)
            end
            ZL.LoadItemDataByID(itemId, linshi, ZL.AuctionFrame2)
            local _, _, _, _itemLevel, _, _itemType, _itemSubType, _, _itemEquipLoc, _, _, _, _, _, _, _setID = cGetItemInfo(itemId)
            if _setID then
                itemType = "套装"
            else
                if _itemType == "护甲" then
                    --装备槽位为13,14(饰品)，16,17,18(武器类)
                    if _itemEquipLoc == "INVTYPE_TRINKET" or _itemEquipLoc == "INVTYPE_SHIELD" or _itemEquipLoc == "INVTYPE_HOLDABLE" or
                    _itemEquipLoc == "INVTYPE_WEAPON" or _itemEquipLoc == "INVTYPE_RANGED" or _itemEquipLoc == "INVTYPE_2HWEAPON" or
                    _itemEquipLoc == "INVTYPE_WEAPONMAINHAND" or _itemEquipLoc == "INVTYPE_WEAPONOFFHAND" or
                    _itemEquipLoc == "INVTYPE_THROWN" or _itemEquipLoc == "INVTYPE_RANGEDRIGHT" then
                        itemType = "武器饰品"
                    else
                        itemType = "散件"
                    end
                elseif _itemType == "武器" then
                    itemType = "武器饰品"
                else
                    itemType = _itemType
                end
            end
            itemLevel = _itemLevel
        end
        if itemType then
            for _, d in ipairs(ZL_SETTING["itemLevelSetting"]) do
                if (d.minLevel <= itemLevel) and (d.maxLevel >= itemLevel) then
                    if itemType == "散件" and d.sanJianStartBid > 0  then
                        return d.sanJianStartBid, d.increment
                    elseif itemType == "套装" and d.taoZhuangStartBid > 0  then
                        return d.taoZhuangStartBid, d.increment
                    elseif itemType == "武器饰品" and d.wuQiStartBid > 0  then
                        return d.wuQiStartBid, d.increment
                    end
                end
            end
        end
    end
    return ZL.opt.startBid, ZL.opt.increment --全局默认值
end

--获取新的基础价，加价，目标价
function ZL.GetNewBidAmount(v)
    local fdata = ZL_CURRENT.auctionlist[v]
    local itemCount = fdata.itemCount
    local bidderlist = fdata.bidderlist
    local tarbidamount = 0
    local bidIncrement = 0
    local baseamount = 0
    local successBidderCount = 0
    local successIndex
    local successList = {}
    local bidCount = 0
    ZL.tableSort(bidderlist)
    for _successIndex, bidData in ipairs(bidderlist) do
        if successBidderCount < itemCount then
            local count = bidData["bidCount"] or 1
            if (successBidderCount + count) >= itemCount then
                count = itemCount - successBidderCount
                ZL_CURRENT.auctionlist[v].bidderlist[_successIndex].bidCount = count
            end
            --(出价，最大可竞拍数量，累计入围数量)
            tinsert(successList, {bidData.bidamount, itemCount-successBidderCount, successBidderCount + count})
            successIndex = _successIndex
            successBidderCount = successBidderCount + count
        else
            break
        end
    end
    --如果总的出价数量小于物品总数量，则按照起拍价
    if successBidderCount < itemCount then
        baseamount = fdata.startbidamount
    else
        baseamount = bidderlist[successIndex].bidamount
    end

    if ZL_CURRENT.globalConfig.intervalBidIncrement then
        if baseamount < ZL_CURRENT.globalConfig.baseAmount1 then
            bidIncrement = fdata.bidIncrement
        elseif baseamount < ZL_CURRENT.globalConfig.baseAmount2 then
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement1, fdata.bidIncrement)
        elseif baseamount < ZL_CURRENT.globalConfig.baseAmount3 then
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement2, fdata.bidIncrement)
        else
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement3, fdata.bidIncrement)
        end
    else
        bidIncrement = fdata.bidIncrement
    end

    if successBidderCount >= itemCount then
        tarbidamount = baseamount + bidIncrement
        for _, data in ipairs(successList) do
            if data[1] == baseamount then
                bidCount =data[2]
                break
            end
        end
    else
        tarbidamount = fdata.startbidamount
        bidCount = itemCount - successBidderCount
    end
    if tarbidamount >= bidIncrement then
        tarbidamount = tarbidamount - tarbidamount % bidIncrement
    end
    return baseamount, bidIncrement, tarbidamount, bidCount, successList
end
--获取新的基础价，加价，目标价2
function ZL.GetNewBidAmount2(v)
    local fdata = ZL_CURRENT.auctionlist[v]
    local bidderlist = fdata.bidderlist
    local tarbidamount = 0
    local bidIncrement = 0
    local baseamount = 0
    ZL.tableSort(bidderlist)
    if bidderlist[fdata.itemCount] then
        baseamount = bidderlist[fdata.itemCount].bidamount
    else
        baseamount = fdata.startbidamount
    end
    if ZL_CURRENT.globalConfig.intervalBidIncrement then
        if baseamount < ZL_CURRENT.globalConfig.baseAmount1 then
            bidIncrement = fdata.bidIncrement
        elseif baseamount < ZL_CURRENT.globalConfig.baseAmount2 then
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement1, fdata.bidIncrement)
        elseif baseamount < ZL_CURRENT.globalConfig.baseAmount3 then
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement2, fdata.bidIncrement)
        else
            bidIncrement = math.max(ZL_CURRENT.globalConfig.bidIncrement3, fdata.bidIncrement)
        end
    else
        bidIncrement = fdata.bidIncrement
    end
    if bidderlist and #bidderlist >= fdata.itemCount then
        tarbidamount = baseamount + bidIncrement
    else
        tarbidamount = baseamount
    end
    if tarbidamount >= bidIncrement then
        tarbidamount = tarbidamount - tarbidamount % bidIncrement
    end
    return baseamount, bidIncrement, tarbidamount
end

--返回开始拍卖语音文字
function ZL.GetAuctionSoundText(itemInfo)
    if itemInfo == "[打包拍卖]" then return "打包物品" end
    local itemName, itemLink, _, itemLevel, _, itemType, itemSubType, _, itemEquipLoc, _, _, _, _, bindType, _, setID = cGetItemInfo(itemInfo)
    local itemId = tonumber(itemLink:match("|Hitem:(%d+):"))
    local profession --职业
    local soundText = ""
    --获取职业限制信息
    if (not ZL.itemToolTip) then
        ZL.itemToolTip = CreateFrame("GameTooltip", "ZLitemToolTip", nil, "GameTooltipTemplate")
    end
    ZL.itemToolTip:SetOwner(UIParent, "ANCHOR_NONE")
    ZL.itemToolTip:ClearLines()
    ZL.itemToolTip:SetHyperlink(itemLink)
    for i = 1, ZL.itemToolTip:NumLines() do
        -- 遍历每一行并打印内容
        local leftLine = _G["ZLitemToolTipTextLeft"..i]
        -- local rightLine = _G["ZLitemToolTipTextRight"..i]
        if leftLine and leftLine:GetText() then
            local text = leftLine:GetText()
            profession = string.match(text, "^职业：(.+)")
            if profession then
                break
            end
        end
    end
    local _itemLevel = ZL.setsItemLevelData[tostring(itemId)] --查询是否为兑换套装物品
    if _itemLevel then
        soundText = soundText .. "套装：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(_itemLevel))
        if profession then
            soundText = soundText .. "，适合职业：" .. profession
        end
    else
        local socketCounts = 0 --插槽数量
        local statList = {}
        local stats = GetItemStats(itemLink)
        for key, value in pairs(stats) do
            if ZL.itemStats[key] then
                table.insert(statList, ZL.itemStats[key])
            elseif ZL.socketStats[key] then --插槽
                socketCounts = socketCounts + value
            end
        end
        if bindType == 2 then
            soundText = soundText .. "装绑"
        end
        if setID then
            soundText = soundText .. "套装"
        end

        if itemType == "护甲" then
            if itemSubType == "盾牌" or itemSubType == "圣契" or itemSubType == "神像" or itemSubType == "图腾" or itemSubType == "魔印" then
                soundText = soundText .. itemSubType .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
            elseif itemSubType == "布甲" or itemSubType == "皮甲" or itemSubType == "锁甲" or itemSubType == "板甲" then
                if itemEquipLoc == "INVTYPE_CLOAK" then --披风
                    soundText = soundText .. ZL.itemEquipLoc[itemEquipLoc] .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
                else
                    soundText = soundText .. itemSubType .. ZL.itemEquipLoc[itemEquipLoc] .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
                end
            else
                soundText = soundText .. ZL.itemEquipLoc[itemEquipLoc] .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
            end
        elseif itemType == "武器" then
            if itemSubType == "双手斧" or itemSubType == "双手剑" or itemSubType == "双手锤" or itemSubType == "投掷武器" or itemSubType == "弓" or itemSubType == "枪"
            or itemSubType == "弩" or itemSubType == "长柄武器" or itemSubType == "法杖" or itemSubType == "魔杖" or itemSubType == "鱼竿" then
                soundText = soundText .. itemSubType .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
            elseif itemSubType == "单手斧" or itemSubType == "单手剑" or itemSubType == "单手锤" or itemSubType == "拳套" or itemSubType == "匕首" then
                itemSubType = itemSubType:gsub("单手", "")
                soundText = soundText .. ZL.itemEquipLoc[itemEquipLoc] .. itemSubType .. "：" .. itemName .. "，装等：" .. ZL.convertToChineseNumber(tostring(itemLevel))
            else
                soundText = soundText .. "：" .. itemName
            end
        elseif itemType == "容器" or itemType == "箭袋" then
            soundText = soundText .. itemSubType .. "：" .. itemName
        elseif itemType == "配方" then
            if itemSubType == "附魔" then
                soundText = soundText .. itemName
            else
                soundText = soundText .. itemSubType .. itemName
            end
        else
            soundText = soundText .. "：" .. itemName
        end

        if profession then
            soundText = soundText .. "，适合职业：" .. profession
        end
        if socketCounts > 0 then
            soundText = soundText .. "，插槽：" .. socketCounts .. "个"
        end
        if #statList > 0 then
            soundText = soundText .. "，属性：" .. table.concat(statList)
        end
    end
    return soundText
end

--设置物品子拍卖窗口是显示还是隐藏
function ZL.ItemAuctionFrameIsShown(data)
    --打包拍卖物品都不显示
    local selectCharKey = ZL.GetClassColorName(UnitName("player")) .. " - " .. GetRealmName()
    local tabId = ZL.opt.ZLAuctionFrameTabId
    if (not data.isPackage) then
        if tabId == 0 then
            return true
        elseif tabId == 1 then
            if (not data.lgnore) and (data.state == "auctioning") then
                return true
            else
                return false
            end
        elseif tabId == 2 then
            if (not data.lgnore) and (data.state == "success") then
                return true
            else
                return false
            end
        elseif tabId == 3 then
            if (not data.lgnore) and (data.state == "failed") then
                return true
            else
                return false
            end
        elseif tabId == 4 then
            if data.lgnore then
                return true
            else
                return false
            end
        elseif tabId == 5 then
            if (not data.lgnore) and (data.state == "waiting") then
                return true
            else
                return false
            end
        elseif tabId == 6 then
            local itemId = data.itemId
            if ZL.opt.concernList and ZL.opt.concernList[selectCharKey]
            and ZL.opt.concernList[selectCharKey]["itemList"][itemId] then
                return true
            else
                return false
            end
        end
    else
        return false
    end
end

--获取正在拍卖的物品个数，如果有多个，则返回个数和最后1个拍卖物品的index，暂停拍卖的也不属于拍卖中
function ZL.GetAuctioningCount()
    local num = 0
    local index = nil
    if ZL_CURRENT.auctionlist and #ZL_CURRENT.auctionlist then
        for i, data in ipairs(ZL_CURRENT.auctionlist) do
            if data.state == "auctioning" and (not data.isPaused) then
                num = num + 1
                index = i
            end
        end
    end
    return num, index
end
-- 定义一个函数来判断一串数字是否由相同的数字组成
function ZL.isAllSameDigits(numberString)
    -- 获取字符串的第一个字符
    local firstChar = numberString:sub(1, 1)
    -- 使用模式匹配来检查字符串是否只包含这个字符
    local pattern = "^" .. firstChar .. "+$"
    return numberString:match(pattern) ~= nil
end

--将出价者列表按照出价金额从大到小排序，相同出价的按照出价先后排序
function ZL.tableSort(tab)
    if #tab > 1 then
        table.sort(tab, function (a, b)
            if a.bidamount > b.bidamount then
                return true
            elseif a.bidamount == b.bidamount then
                if a.time and b.time and a.time < b.time then
                    return true
                end
            end
            return false
        end)
    end
end
--当前拍卖清单排序
function ZL.AuctionListSort(changeSize)
   if ZL_CURRENT.auctionlist and  #ZL_CURRENT.auctionlist > 1 then
        table.sort(ZL_CURRENT.auctionlist, function (a, b)
            if ZL.opt.timeSort then
                if ZL.opt.timeSort == "up" then
                    if (a.createTime or 0) < (b.createTime or 0) then
                        return true
                    elseif (a.createTime or 0) == (b.createTime or 0) then
                        --如果创建时间相同按装等降序排序
                        if (a.itemLevel or 0) > (b.itemLevel or 0) then
                            return true
                        elseif (a.itemLevel or 0) == (b.itemLevel or 0) then
                            --如果装等一样，按照物品ID升序排序
                            if (a.itemId or 0) < (b.itemId or 0) then
                                return true
                            end
                        end
                    end
                else
                    if (a.createTime or 0) > (b.createTime or 0) then
                        return true
                    elseif (a.createTime or 0) == (b.createTime or 0) then
                        --如果创建时间相同按装等降序排序
                        if (a.itemLevel or 0) > (b.itemLevel or 0) then
                            return true
                        elseif (a.itemLevel or 0) == (b.itemLevel or 0) then
                            --如果装等一样，按照物品ID升序排序
                            if (a.itemId or 0) < (b.itemId or 0) then
                                return true
                            end
                        end
                    end
                end
            else
                if ZL.opt.levelSort == "up" then
                    if (a.itemLevel or 0) < (b.itemLevel or 0) then
                        return true
                    elseif (a.itemLevel or 0) == (b.itemLevel or 0) then
                        --如果装等相同，按照创建时间升序排列
                        if (a.createTime or 0) < (b.createTime or 0) then
                            return true
                        elseif (a.createTime or 0) == (b.createTime or 0) then
                            --如果创建时间一样，按照物品ID升序排序
                            if (a.itemId or 0) < (b.itemId or 0) then
                                return true
                            end
                        end
                    end
                else
                    if (a.itemLevel or 0) > (b.itemLevel or 0) then
                        return true
                    elseif (a.itemLevel or 0) == (b.itemLevel or 0) then
                        --如果装等相同，按照创建时间升序排列
                        if (a.createTime or 0) < (b.createTime or 0) then
                            return true
                        elseif (a.createTime or 0) == (b.createTime or 0) then
                            --如果创建时间一样，按照物品ID升序排序
                            if (a.itemId or 0) < (b.itemId or 0) then
                                return true
                            end
                        end
                    end
                end
            end
            return false
        end)
        -- for num, _ in ipairs(ZL_CURRENT.auctionlist) do
        --     local f = ZL.AuctionFrame2.entries[num]
        --     f:SetValues(num)
        -- end
   end
   ZL.AuctionFrame2:Update(changeSize)
end
--是否过滤物品
function ZL.isFilterItem(itemId)
    local filterItemId = ZL_SETTING["filterItemId"]
    for _, data in ipairs(filterItemId) do
        if data.itemId == itemId then
            return data.itemlink, data.auction, data.loot
        end
    end
    return nil, nil, nil
end
--字符串固定长度，如不够，自动在前面填充
function ZL.pad_left(str, length)
    return string.format("%" .. length .. "s", str)
  end

--自动出价
function ZL.autoBid(index, maxAutoBid, bidCount)
    local curAuctionList = ZL_CURRENT.auctionlist[index]
    if maxAutoBid and (not curAuctionList.isPaused) then
        local bidderlist = ZL_CURRENT.auctionlist[index].bidderlist
        local totalBidCount = 0
        local isSelf = false
        for _, bidData in ipairs(bidderlist) do
            if totalBidCount < curAuctionList.itemCount then
                local count = bidData["bidCount"] or 1
                local newTotalBidCount = totalBidCount + count
                if newTotalBidCount > curAuctionList.itemCount then
                    count = curAuctionList.itemCount - totalBidCount
                end
                totalBidCount = newTotalBidCount
                if ZL.ParseClassColorName(bidData.bidder) == UnitName("player") then
                    if bidData.bidCount >= bidCount then
                        isSelf = true
                    end
                    break
                end
            else
                break
            end
        end
        if (not isSelf) then
            local _, bidIncrement, newBid, _bidCount, successList = ZL.GetNewBidAmount(index)
            local msgStr = ""
            if bidCount > _bidCount and #successList > 0 then
                for i = #successList, 1, -1 do
                    if successList[i][2] >= bidCount then
                        newBid = successList[i][1] + bidIncrement
                        break
                    end
                end
            end
            if newBid <= maxAutoBid then
                if bidCount == 1 then
                    msgStr = tostring(newBid)
                else
                    msgStr = tostring(newBid) .. "x" .. bidCount
                end
                if ZL_CURRENT.globalConfig.auctionMode == "团队" then
                    if not ZL_CURRENT.globalConfig.allowMultipleAuctions then
                        SendChatMessage(msgStr, "RAID")
                    else
                        SendChatMessage(curAuctionList.itemlink .. msgStr, "RAID")
                    end
                else
                    MyAddon:TransmitAddonInfo2("AUTOAUC BID", curAuctionList.itemlink .. msgStr)
                end
            else
                local f = ZL.AuctionFrame2.entries[index]
                f.bidFrame.bidBtn:Click()
            end
        end
    end
end
--同步配置文件全局参数
function ZL.TransmitAddonInfo_Pro()
    --开始拍卖和修改这些配置的时候需要同步
    if ZL.PlayerIsML() then
        local data = {
            auctionTimerRefresh = ZL.opt.auctionTimerRefresh,--不需要单独同步，已包含在拍卖清单Table里
            auctionTimer = ZL.opt.auctionTimer,--不需要单独同步，已包含在拍卖清单Table里
            allowMultipleAuctions = ZL.opt.allowMultipleAuctions, --多拍模式：需要单独同步，属于全团共享变量
            intervalBidIncrement = ZL.opt.intervalBidIncrement, --是否区间加价幅度：需要单独同步，属于全团共享变量
            baseAmount1 = ZL.opt.baseAmount1, --区间目标价1：需要单独同步，属于全团共享变量
            baseAmount2 = ZL.opt.baseAmount2, --区间目标价2：需要单独同步，属于全团共享变量
            baseAmount3 = ZL.opt.baseAmount3, --区间目标价3：需要单独同步，属于全团共享变量
            bidIncrement1 = ZL.opt.bidIncrement1, --区间加价幅度1：需要单独同步，属于全团共享变量
            bidIncrement2 = ZL.opt.bidIncrement2, --区间加价幅度2：需要单独同步，属于全团共享变量
            bidIncrement3 = ZL.opt.bidIncrement3, --区间加价幅度3：需要单独同步，属于全团共享变量
            wagesGroupMembers = ZL.opt.wagesGroupMembers, --计算工资成员
            RLBuTieType = ZL.opt.RLBuTieType,
            raidLeaderTiCheng = ZL.opt.raidLeaderTiCheng,
            raidLeaderbutie = ZL.opt.raidLeaderbutie,
            Tbutie = ZL.opt.Tbutie,
            Nbutie = ZL.opt.Nbutie,
            DPSbutie = ZL.opt.DPSbutie,
            FOODbutie = ZL.opt.FOODbutie,
            xiuXingbutie = ZL.opt.xiuXingbutie,
            ANMUbutie = ZL.opt.ANMUbutie,
            YYSound = ZL.opt.YYSound,
            auctionMode = ZL.opt.auctionMode, --拍卖模式
        }
        MyAddon:TransmitAddonInfo("AUTOAUC PRO", data)
    end
end
--提示消息
function ZL.GameTooltipShow(self, point, relativePoint, offsetX, offsetY)
    offsetX = offsetX or 0
    offsetY = offsetY or 0
    GameTooltip:ClearAllPoints()
    GameTooltip:ClearLines()
    GameTooltip:SetOwner(self, "ANCHOR_NONE")
    GameTooltip:SetPoint(point, self, relativePoint, offsetX, offsetY)
end
--将秒转换成时间格式
function ZL.ConvertSecondsToTime(seconds)
    local hours = math.floor(seconds / 3600)
    local minutes = math.floor((seconds % 3600) / 60)
    local remainingSeconds = seconds % 60

    if hours > 0 then
        return string.format("%02d:%02d:%02d", hours, minutes, remainingSeconds)
    elseif hours == 0 and minutes > 0 then
        return string.format("%02d:%02d", minutes, remainingSeconds)
    else
        return string.format("%d", remainingSeconds)
    end
end
--获取装备交易剩余时间
function ZL.GetRemainingTradeTime(IsShow)
    if not ZL.PlayerIsML() then return end
    local RemainingTradeItems = {}
    local itemLocation
    local itemGuid, itemLink
    for bag = 0, NUM_BAG_SLOTS do
        for slot = 1, C_Container.GetContainerNumSlots(bag) do
            if not itemLocation then
                itemLocation = ItemLocation:CreateFromBagAndSlot(bag, slot)
            else
                itemLocation:SetBagAndSlot(bag, slot)
            end
            if C_Item.DoesItemExist(itemLocation) then
                itemLink = C_Container.GetContainerItemLink(bag, slot)
                itemGuid = C_Item.GetItemGUID(itemLocation)
                if ZL_CURRENT.itemGUIDUsed and ZL_CURRENT.itemGUIDUsed[itemGuid] and ((not ZL_CURRENT.SelfAuction) or (not ZL_CURRENT.SelfAuction[itemGuid])) then
                    if (not ZL.ToolTip) then
                        ZL.ToolTip = CreateFrame("GameTooltip", "TradeTimeRemainingTooltip", nil, "GameTooltipTemplate")
                    end
                    ZL.ToolTip:SetOwner(UIParent, "ANCHOR_NONE")
                    ZL.ToolTip:ClearLines()
                    ZL.ToolTip:SetBagItem(bag, slot)
                    for i = 1, ZL.ToolTip:NumLines() do
                        local text = _G["TradeTimeRemainingTooltipTextLeft"..i]:GetText()
                        if text then
                            local timeRemaining = text:match(BIND_TRADE_TIME_REMAINING:gsub("%%s", "(.+)"))
                            if timeRemaining then
                                local hour = tonumber(timeRemaining:match("(%d+)" .. "小时")) or 0
                                local min = tonumber(timeRemaining:match("(%d+)" .. "分钟")) or 0
                                table.insert(RemainingTradeItems, {
                                    itemLink=itemLink, timeRemaining=timeRemaining, hour=hour, min=min
                                })
                                break
                            end
                        end
                    end
                end
            end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid = nil
    itemLink = nil
    local text = ""
    if #RemainingTradeItems > 0 then
        table.sort(RemainingTradeItems, function (a, b)
            return (a.hour*60 + a.min) < (b.hour*60 + b.min)
        end)
        text = "|cffffd100交易剩余时间清单(前5)：|r\n"
    else
        text = "|cffffd100没有交易剩余时间的装备！|r\n"
    end
    
    local _IsVoiceReminder = false
    for _, data in ipairs(RemainingTradeItems) do
        local remainingTime = (data.hour*60 + data.min)
        if remainingTime <= ZL.opt.TradeRemainingTimer then _IsVoiceReminder = true end
        if remainingTime <= 30 then
            text = text .. data.itemLink .. ":|cffff0000" .. data.timeRemaining .. "|r\n"
        else
            text = text .. data.itemLink .. ":" .. data.timeRemaining .. "\n"
        end
    end
    ZL.ZLRemainingTradeTimeFrame.RemainingTradeTimeText:SetText(text)
    if ZL.opt.IsTradeRemainingVoiceReminder and _IsVoiceReminder and IsInInstance() and (select(2, IsInInstance()) == "raid") and
        ((not ZL.TradeRemainingReminderTime) or ((GetServerTime() - ZL.TradeRemainingReminderTime) >= (ZL.opt.TradeRemainingReminderPinlv * 60)))
        then
        ZL.TradeRemainingReminderTime = GetServerTime()
        PlaySoundFile("Interface\\AddOns\\" .. addonName .. "\\sound\\" .. ZL.SoundType .. "\\有装备快要过期了哦.mp3", "Master")
    end
    if IsShow then
        return RemainingTradeItems
    else
        RemainingTradeItems = nil
    end
end

--获取职业颜色名字
function ZL.GetClassColorName(name)
    if not name then return end
    if name:match("|c%x%x%x%x%x%x%x%x.-%|r") ~= nil then return name end --如有已经是带职业颜色名字则直接返回
    local classFilename = UnitClassBase(name)
    if classFilename then
        local color = select(4, GetClassColor(classFilename))
        return "|c" .. color .. name .. "|r"
    else
        return name
    end
end

--解析带职业颜色的名字
function ZL.ParseClassColorName(name)
    local cleanText = name and string.gsub(name, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1") --把颜色代码剔除掉
    return cleanText
end

--获取团队成员名
function ZL.GetCurrentRoster(IsSaveUnitGuid)
    local roster = {{},{},{},{},{},{},{},{}} --初始化8个小队
    for i = 1, MAX_RAID_MEMBERS do
        local name, _, subgroup, _, _, classFilename = GetRaidRosterInfo(i)
        local oldName = name
        if name then
            if classFilename then
                local color = select(4, GetClassColor(classFilename))
                name = "|c" .. color .. name .. "|r"
            end
            table.insert(roster[subgroup], name)
            if IsSaveUnitGuid then
                if not ZL_CURRENT.UnitGUID then ZL_CURRENT.UnitGUID = {} end
                ZL_CURRENT.UnitGUID[name] = UnitGUID(oldName)
            end
        end
    end
    return roster
end
--识别出价2
function ZL.padZeros2(num, tarbidamount, bidIncrement, baseamount)
    local numStr = tostring(num)
    local currentLength = #numStr-- 获取字符串长度
    local baselength = #tostring(baseamount)
    -- 如果当前长度已经大于或等于基础出价的长度，则直接返回原数字字符串
    -- 不能与目标价长度做对比，如：baseamount=9500，tarbidamount=10000，如有人出价9，则为识别为90000
    if currentLength >= baselength then
        return num
    end
    -- 计算需要添加的零的数量
    local zerosToAdd = baselength - currentLength
    -- 创建一个包含需要数量零的字符串
    local zeros = string.rep("0", zerosToAdd)
    -- 将零添加到数字字符串的后面
    local paddedNumStr = numStr .. zeros
    --添0后大于或等于基础出价时，直接返回
    if tonumber(paddedNumStr) >= baseamount then
        return tonumber(paddedNumStr)
    end
    local zeroCount = 0
    for i = currentLength, 1, -1 do  -- 从右往左遍历字符串
        if numStr:sub(i, i) == "0" then
            zeroCount = zeroCount + 1
        else
            break  -- 一旦遇到非零字符，就停止
        end
    end
    -- local step = tarbidamount <= 5000 and 1000 or 10000
    local step = 0
    if tarbidamount <= 2000 then
        step = 1000
    elseif tarbidamount <= 5000 then
        step = 5000
    elseif tarbidamount <= 80000 then
        step = 10000
    else
        step = 20000
    end
    --如果添加0后的数字小于目标价并且再加一个0的数字减去目标价小于step则再在后面加一个0
    if (tonumber(paddedNumStr) < tarbidamount) and  ((tonumber(paddedNumStr) + bidIncrement) ~= tarbidamount) and (tonumber(paddedNumStr .. "0") - tarbidamount <= step) then
        paddedNumStr = paddedNumStr .. "0"
    end
    return tonumber(paddedNumStr)
end
--识别出价
function ZL.padZeros(num, tarbidamount, bidIncrement, baseamount)
    local numStr = tostring(num)
    local currentLength = #numStr-- 获取字符串长度
    local baselength = #tostring(baseamount)
    -- 如果当前长度已经大于或等于基础出价的长度，则直接返回原数字字符串
    -- 不能与目标价长度做对比，如：baseamount=9500，tarbidamount=10000，如有人出价9，则为识别为90000
    if currentLength >= baselength then
        return num
    end
    -- 计算需要添加的零的数量
    local zerosToAdd = baselength - currentLength
    -- 创建一个包含需要数量零的字符串
    local zeros = string.rep("0", zerosToAdd)
    -- 将零添加到数字字符串的后面
    local paddedNumStr = numStr .. zeros
    --添0后大于或等于基础出价时，直接返回
    if tonumber(paddedNumStr) >= baseamount then
        return tonumber(paddedNumStr)
    end
    --计算原始出价从右往左数有几个连续的0，如果大于0个，则继续在第一次添加0后的数字加一个0
    local zeroCount = 0
    for i = currentLength, 1, -1 do  -- 从右往左遍历字符串
        if numStr:sub(i, i) == "0" then
            zeroCount = zeroCount + 1
        else
            break  -- 一旦遇到非零字符，就停止
        end
    end
    if zeroCount == 1 then
        paddedNumStr = paddedNumStr .. "0"
    elseif zeroCount == 0 then
        local firstChar = string.sub(numStr, 1, 1)
        if firstChar == "1" then
            if ((tarbidamount == baseamount) and (baseamount <= 10000 or (baseamount > 50000 and baseamount < 100000))) or
            ((tarbidamount > baseamount) and ((baseamount > 500 and baseamount < 1000) or (baseamount > 5000 and baseamount < 10000) or (baseamount > 50000 and baseamount < 100000))) then
                paddedNumStr = paddedNumStr .. "0"
            end
        elseif firstChar == "2" then
            if ((tarbidamount == baseamount) and ((baseamount <= 1000) or (baseamount > 5000 and baseamount < 10000))) or
            ((tarbidamount > baseamount) and ((baseamount > 500 and baseamount < 1000) or (baseamount > 5000 and baseamount < 10000))) then
                paddedNumStr = paddedNumStr .. "0"
            end
        end
    end
    return tonumber(paddedNumStr)
end
-- 自定义位与操作
function ZL.bit_and(a, b)
    local result = 0
    local bit = 1
    while a > 0 or b > 0 do
        if (a % 2 == 1) and (b % 2 == 1) then
            result = result + bit
        end
        a = math.floor(a / 2)
        b = math.floor(b / 2)
        bit = bit * 2
    end
    return result
end
-- 自定义位左移操作
function ZL.bit_lshift(num, shift)
    return num * (2 ^ shift)
end
-- 自定义位或操作
function ZL.bit_or(a, b)
    return a + b - ZL.bit_and(a, b)
end
function ZL.utf8_to_num(raw_string)
    local result = {}
    local pos = 1
    while pos <= #raw_string do
        local count_1_of_byte = ZL.get_continuous_1_count_of_byte(string.byte(raw_string, pos))
        local num = 0
        if count_1_of_byte < 1 then 
            num = string.byte(raw_string, pos)
            count_1_of_byte = 1
        else
            local boundary = 8
            local i = count_1_of_byte + 1
            while i < boundary * count_1_of_byte do
                if 0 == i % boundary then
                    i = i + 2
                end
                if ZL.bit_and(ZL.bit_lshift(1, boundary - i % boundary - 1), string.byte(raw_string, pos + math.floor(i / boundary))) ~= 0 then
                    num = ZL.bit_or(ZL.bit_lshift(num, 1), 1)
                else
                    num = ZL.bit_lshift(num, 1)
                end
                i = i + 1
            end
        end
        pos = pos + count_1_of_byte
        table.insert(result, num)
    end

    return result
end
--获取一个字节中，从最高位开始连续的1的个数
function ZL.get_continuous_1_count_of_byte(num)
    if nil == num then
        return -1
    end
    local count = 0
    while ZL.bit_and(num, 0x80) ~= 0 do
        count = count + 1
        num = ZL.bit_lshift(num, 1)
    end
    return count
end
--将全角转换成半角
function ZL.fullwidthToHalfwidth(raw_string)
    local new_string = {}
    local pos = 1
    while pos <= #raw_string do
        local count_1_of_byte = ZL.get_continuous_1_count_of_byte(string.byte(raw_string, pos))
        if 3 == count_1_of_byte then
            local char = string.sub(raw_string, pos, pos + 2)
            local num_of_char = ZL.utf8_to_num(char)[1]
            if num_of_char == 12288 then --全角空格
                num_of_char = 32
                table.insert(new_string, string.char(num_of_char))
            elseif num_of_char >= 65281 and num_of_char <= 65374 then --其他字符全角
                num_of_char = num_of_char - 65248
                table.insert(new_string, string.char(num_of_char))
            else --汉字默认为全角
                table.insert(new_string, char)
            end
            pos = pos + count_1_of_byte
        else
            table.insert(new_string, string.sub(raw_string, pos, pos))
            pos = pos + 1
        end
    end
    return table.concat(new_string)
end
--处理竞价消息
function ZL.msg_gsub(msg)
    local cmsg = msg:gsub("[!Pp%s]", "") --！
    cmsg = cmsg:gsub("%[T%]", "")
    cmsg = cmsg:gsub("。", ".")
    cmsg = cmsg:gsub("万", "w")
    cmsg = cmsg:gsub("千", "k")
    cmsg = cmsg:gsub("一", "1")
    cmsg = cmsg:gsub("二", "2")
    cmsg = cmsg:gsub("三", "3")
    cmsg = cmsg:gsub("四", "4")
    cmsg = cmsg:gsub("五", "5")
    cmsg = cmsg:gsub("六", "6")
    cmsg = cmsg:gsub("七", "7")
    cmsg = cmsg:gsub("八", "8")
    cmsg = cmsg:gsub("九", "9")
    cmsg = cmsg:gsub("两", "2")
    cmsg = cmsg:gsub("伍", "5")
    return cmsg
end

--获取玩家购买清单
function ZL.GetPlayerBuyList(bill)
    local buyList = {}
    bill = bill or ZL_CURRENT
    if bill then
        local IncomeList = bill.IncomeList
        if IncomeList and #IncomeList > 0 then
            for _, data in ipairs(IncomeList) do
                if data.player ~= "" then
                    local name = data.player
                    if not buyList[name] then buyList[name] = {["items"] = {},["totalAmount"] = 0} end
                    buyList[name].totalAmount = buyList[name].totalAmount + data.amount
                    if data.itemList and next(data.itemList, nil) then
                        for _itemlink, _data in pairs(data.itemList) do
                            table.insert(buyList[name]["items"], {
                                notes=_itemlink, isTraded=_data.isTraded, itemCount=_data.itemCount,
                                stackCount=_data.stackCount, itemGUID=_data.itemGUID,
                            })
                        end
                    end
                end
            end
        end
    end
    return buyList
end

--创建当前拍卖TABLE
function ZL.CreateAuctionList()
    if ZL_CURRENT and (not ZL_CURRENT.auctionlist) then --如果当前不存在拍卖记录，则创建
        local name, _, difficultyID, difficultyName, _, _, _, instanceID = GetInstanceInfo()
        ZL_CURRENT.auctionlist = {}
        difficultyName = difficultyName:gsub("人", ""):gsub("（", ""):gsub("）", "")
        ZL_CURRENT.name = difficultyName ~= "" and name .. "(" .. difficultyName .. ")" or name
        ZL_CURRENT.difficultyID = difficultyID
        ZL_CURRENT.instanceID = instanceID
        ZL_CURRENT.auctiondate =  date("%Y-%m-%d %H:%M:%S", time())
        ZL_CURRENT.totalincome = 0
        ZL_CURRENT.IncomeList = {}
        ZL_CURRENT.UnitGuid = UnitGUID(ZL.GetMLname())
        ZL_CURRENT.FactionGroup = select(2, UnitFactionGroup(ZL.GetMLname())) --阵营
        ZL_CURRENT.MLname = ZL.GetMLname()
        ZL_CURRENT.RealmName = GetRealmName()
    end
end

--获取掉落物品候选人
function ZL.GetMasterLootCandidates(slot)
    local candidates = {}
    for index = 1, MAX_RAID_MEMBERS do
        local candidate = GetMasterLootCandidate(slot, index)
        if candidate then
            candidates[ZL.GetClassColorName(candidate)] = true
        end
    end
    -- local index = 1
    -- while true do
    --     local candidate = GetMasterLootCandidate(slot, index)
    --     if not candidate then
    --         break
    --     end
    --     candidates[ZL.GetClassColorName(candidate)] = true
    --     index = index + 1
    -- end
    return candidates
end

--判断玩家是否拥有装备交易权限(装备候选人)
function ZL.IsCandidate(v, name)
    local bindType = ZL_CURRENT.auctionlist[v].bindType
    if bindType ~= 1 then return true end --只要不是拾取绑定的，都可以参与拍卖
    for _, value in pairs(ZL_CURRENT.auctionlist[v]["spawnUID"]) do
        if not value["candidates"] then
            return true
        else
            if not next(value["candidates"], nil) then
                return true
            else
                name = name or UnitName("player")
                name = ZL.GetClassColorName(name)
                if value["candidates"][name] == true then
                    return true
                end
            end
        end
    end
    return false
end
--加载物品信息获取itemlink
function ZL.LoadItemDataByID(itemId, func, relativeFrame)
    local itemExists = C_Item.DoesItemExistByID(itemId)
    if itemExists then
        local itemlink = select(2, cGetItemInfo(itemId))
        if (not itemlink) then
            ZL:RegisterEvent("ITEM_DATA_LOAD_RESULT")
            C_Item.RequestLoadItemDataByID(itemId)
            ZL:SetScript("OnEvent", function(self, event, ...)
                if event == "ITEM_DATA_LOAD_RESULT" then
                    local loadedItemId, success = ...
                    if loadedItemId == itemId then
                        if success then
                            itemlink = select(2, cGetItemInfo(itemId))
                            if func then
                                func(itemlink)
                            end
                        else
                            local msgStr = "物品ID：" .. itemId .. "信息加载失败，请重试！"
                            ZL.Print(msgStr)
                            if relativeFrame then
                                ZL.GameTooltipShow(relativeFrame, "BOTTOM", "TOP")
                                GameTooltip:AddLine(msgStr)
                                GameTooltip:Show()
                                C_Timer.After(5, function ()
                                    GameTooltip:Hide()
                                end)
                            end
                        end
                        -- 取消事件注册
                        self:UnregisterEvent("ITEM_DATA_LOAD_RESULT")
                    end
                end
            end)
        else
            func(itemlink)
        end
    else
        local msgStr = "物品ID：" .. itemId .. "不存在，请核实填写是否正确！"
        ZL.Print(msgStr)
        if relativeFrame then
            ZL.GameTooltipShow(relativeFrame, "BOTTOM", "TOP")
            GameTooltip:AddLine(msgStr)
            GameTooltip:Show()
            C_Timer.After(3, function ()
                GameTooltip:Hide()
            end)
        end
    end
end

--手动创建拍卖物品
function ZL.ManualCreateAuctionItem(itemLink, itemCount, itemGuid)
    local function linshi()
        if (not ZL_CURRENT.globalConfig) or (ZL_CURRENT.globalConfig.intervalBidIncrement == nil) then
            ZL.TransmitAddonInfo_Pro()
            C_Timer.After(1, linshi)
        else
            local _, _, _, itemLevel, _, _, itemSubType, stackCount, _, _, _, _, _, bindType = cGetItemInfo(itemLink)
            local itemindex
            local itemId = tonumber(itemLink:match("|Hitem:(%d+):"))
            if ZL_CURRENT.auctionlist and (#ZL_CURRENT.auctionlist > 0) then
                for _, fdata in ipairs(ZL_CURRENT.auctionlist) do
                    if (fdata.itemlink == itemLink) then
                        itemindex = fdata.itemindex
                    end
                end
            end
            itemindex = itemindex and (itemindex + 1) or 1
            local startbidamount, bidIncrement = ZL.GetStartAndIncrementBid(itemId)
            if startbidamount < 5000 then
                bidIncrement = bidIncrement
            elseif startbidamount < 10000 then
                bidIncrement = math.max(500, bidIncrement)
            else
                bidIncrement = math.max(1000, bidIncrement)
            end
            local spawnUIDkey
            local spawnUID = {}
            if stackCount == 1 then
                for i = 1, itemCount do
                    spawnUIDkey = itemId ..time() .. string.format("%02d", i)
                    spawnUID[spawnUIDkey] = {bossName="其他", itemGUID={}}
                end
            else
                spawnUIDkey = itemId ..time() .. "01"
                spawnUID[spawnUIDkey] = {bossName="其他", itemGUID={}}
            end
            local fdata = {
                ["type"] = "手动创建",
                ["itemId"] = itemId,
                ["itemlink"] = itemLink,
                ["itemindex"] = itemindex,
                ["itemCount"] = itemCount,
                ["itemLevel"] = itemLevel,
                ["itemSubType"] = itemSubType,
                ["bindType"] = bindType,
                ["startbidamount"] = startbidamount,
                ["bidIncrement"] = bidIncrement,
                ["state"] = "waiting",
                ["countdownremaining"] = 0,
                ["auctionTimerRefresh"] = (ZL_CURRENT.globalConfig and ZL_CURRENT.globalConfig["auctionTimerRefresh"]) and ZL_CURRENT.globalConfig["auctionTimerRefresh"] or ZL.opt.auctionTimerRefresh,
                ["isPaused"] = false,
                ["stackCount"] = stackCount,
                ["spawnUID"] = spawnUID,
                ["bidderlist"] = {},
                ["sourceGUID"] = {},
                ["lgnore"] = false,
                ["createTime"] = date("%Y-%m-%d %H:%M:%S", time()),
            }
            --ML自己创建，不参与插件同步创建
            ZL.CreateAuctionList()
            table.insert(ZL_CURRENT.auctionlist, fdata)
            ZL.GetLootItemGUID()
            local index2 = #ZL_CURRENT.auctionlist
            --开始同步给其他人
            local fdata2 = {
                ["type"] = "手动创建",
                ["data2"] = ZL_CURRENT.auctionlist[index2],
            }
            MyAddon:TransmitAddonInfo("AUTOAUC SYNC9", fdata2)
            ZL.AuctionListSort(true)
        end
    end
    linshi()
end
--信息发送频道
function ZL.MsgChannel()
    if IsInRaid(1) then
        if ZL.opt.announceRaidWarning and (UnitIsGroupLeader("player") or UnitIsRaidOfficer("player")) then
            return "RAID_WARNING"
        else
            return "RAID"
        end
    elseif IsInGroup(1) then
        return "PARTY"
    elseif IsInRaid(2) or IsInGroup(2) then
        return "INSTANCE_CHAT"
    else
        return "SAY"
    end

end
--获取需邮寄工资的人数
function ZL.GetNeedMailNums()
    local playerBuyList = ZL.GetPlayerBuyList()
    local nums = 0
    ZL.GetAveWages()
    if (not ZL_CURRENT["aveWages"]) then return nums end
    local mailPlayers = ZL_CURRENT.mailPlayers
    if mailPlayers and next(mailPlayers, nil) then
        for name, value in pairs(mailPlayers) do
            if value == false then
                local balanceAmount = 0
                local playerPayToMLamount = 0
                local biLi = (ZL_CURRENT.WagesBiLi and ZL_CURRENT.WagesBiLi[name] and ZL_CURRENT.WagesBiLi[name].biLi) and (ZL_CURRENT.WagesBiLi[name].biLi/100) or 1
                if ZL_CURRENT.playerPayToML and ZL_CURRENT.playerPayToML[name] then
                    playerPayToMLamount = ZL_CURRENT.playerPayToML[name]
                end
                local amount = playerPayToMLamount - (playerBuyList[name] and playerBuyList[name].totalAmount or 0)
                amount = amount > 0 and 0 or amount
                balanceAmount = (ZL_CURRENT["aveWages"] or 0) * biLi + amount
                if ZL.PlayerIsML(name) then
                    balanceAmount = 0
                end
                if balanceAmount > 0 then
                    nums = nums + 1
                end
            end
        end
    end
    return nums
end

--获取计算工资团队成员名单
function ZL.GetWagesGroupMembers(bill)
    local WagesGroupMembers
    local msg
    local ML, RL
    bill = bill or ZL_CURRENT
    local wagesGroupMembersIndex = (bill["globalConfig"] and bill["globalConfig"]["wagesGroupMembers"]) and bill["globalConfig"]["wagesGroupMembers"] or 0
    if wagesGroupMembersIndex then
        if wagesGroupMembersIndex == 0 then
            if IsInGroup() then
                WagesGroupMembers = ZL.GetCurrentRoster()
                msg = "|cffff0000当前成员|r"
                ML = ZL.GetClassColorName(ZL.GetMLname())
                RL = ZL.GetClassColorName(ZL.GetRLname())
            else
                if bill["GroupMembersList"] and #bill["GroupMembersList"] > 0 then
                    WagesGroupMembers = bill["GroupMembersList"][1]["list"]
                    msg = "|cffff0000历史1成员|r"
                    ML = bill["GroupMembersList"][1]["ML"]
                    RL = bill["GroupMembersList"][1]["RL"]
                end
            end
        else
            if bill["GroupMembersList"] and bill["GroupMembersList"][wagesGroupMembersIndex] then
                WagesGroupMembers = bill["GroupMembersList"][wagesGroupMembersIndex]["list"]
                msg = "|cffff0000历史" .. wagesGroupMembersIndex .. "成员|r"
                ML = bill["GroupMembersList"][wagesGroupMembersIndex]["ML"]
                RL = bill["GroupMembersList"][wagesGroupMembersIndex]["RL"]
            elseif IsInGroup() then
                WagesGroupMembers = ZL.GetCurrentRoster()
                msg = "|cffff0000当前成员|r"
                ZL.opt.wagesGroupMembers = 0
                ZL.TransmitAddonInfo_Pro()
                ML = ZL.GetClassColorName(ZL.GetMLname())
                RL = ZL.GetClassColorName(ZL.GetRLname())
            end
        end
    end
    return WagesGroupMembers, msg, ML, RL
end
--获取平均工资
function ZL.GetAveWages(bill)
    bill = bill or ZL_CURRENT
    local WagesGroupMembers, _, _, RL = ZL.GetWagesGroupMembers(bill)
    if (not WagesGroupMembers) then bill["aveWages"] = nil return end
    ZL_CURRENT.butie = {}
    local numGroupMembers = 0 --团队成员数-消费老板数
    local totalBiLi = 0
    local biLi = 0
    local RLBuTieType,raidLeaderTiCheng2,raidLeaderbutie,Tbutie,Nbutie,DPSbutie,FOODbutie,xiuXingbutie,ANMUbutie
    if bill["globalConfig"] then
        RLBuTieType = bill["globalConfig"].RLBuTieType
        raidLeaderTiCheng2 = bill["globalConfig"].raidLeaderTiCheng
        raidLeaderbutie = bill["globalConfig"].raidLeaderbutie
        Tbutie = bill["globalConfig"].Tbutie
        Nbutie = bill["globalConfig"].Nbutie
        DPSbutie = bill["globalConfig"].DPSbutie
        FOODbutie = bill["globalConfig"].FOODbutie
        xiuXingbutie = bill["globalConfig"].xiuXingbutie
        ANMUbutie = bill["globalConfig"].ANMUbutie
    else
        RLBuTieType = ZL.opt.RLBuTieType
        raidLeaderTiCheng2 = ZL.opt.raidLeaderTiCheng
        raidLeaderbutie = ZL.opt.raidLeaderbutie
        Tbutie = ZL.opt.Tbutie
        Nbutie = ZL.opt.Nbutie
        DPSbutie = ZL.opt.DPSbutie
        FOODbutie = ZL.opt.FOODbutie
        xiuXingbutie = ZL.opt.xiuXingbutie
        ANMUbutie = ZL.opt.ANMUbutie
    end
    for _, data in ipairs(WagesGroupMembers) do
        if #data > 0 then
            for _, name in ipairs(data) do
                if (not bill.WagesBiLi) or (not bill.WagesBiLi[name]) or (not bill.WagesBiLi[name]["biLi"]) or bill.WagesBiLi[name]["biLi"] >= 100 then
                    biLi = 100
                elseif bill.WagesBiLi[name]["biLi"] <= 0 then
                    biLi = 0
                else
                    biLi = bill.WagesBiLi[name]["biLi"]
                end
                if name == RL and RLBuTieType == 3 then  --RL双倍工资
                    biLi = biLi * 2
                end
                if biLi > 0 then
                    numGroupMembers = numGroupMembers + 1
                    totalBiLi = totalBiLi + biLi
                end
            end
        end
    end
    totalBiLi = totalBiLi / 100
    if numGroupMembers <= 0 then bill["aveWages"] = nil return end
    if RLBuTieType == 3 then --如果团双则计算工资人数+1
        numGroupMembers = numGroupMembers + 1
    end
    local totalamount = 0 --净收入
    local totalincome = 0 --总收入
    local totalpayout = 0 --总支出为负值
    local averageamount = 0 --平均工资
    local raidLeaderTiCheng = ((RLBuTieType == 4) and raidLeaderTiCheng2 and raidLeaderTiCheng2 > 0) and (raidLeaderTiCheng2/100) or 0 --RL提成点
    local RLBuTie = 0
    if bill.IncomeList and (#bill.IncomeList > 0) then
        for _, data in ipairs(bill.IncomeList) do
            if data.amount > 0 then
                totalincome = totalincome + data.amount
            else
                totalpayout = totalpayout + data.amount
            end
        end
    end
    if RLBuTieType == 2 and raidLeaderbutie and raidLeaderbutie > 0 then --RL固定补贴
        totalpayout = totalpayout - raidLeaderbutie
        RLBuTie = raidLeaderbutie
    end
    if Tbutie and Tbutie > 0 then
        totalpayout = totalpayout - Tbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="T补贴", amount=-Tbutie, isTraded=true})
    end
    if Nbutie and Nbutie > 0 then
        totalpayout = totalpayout - Nbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="奶补贴", amount=-Nbutie, isTraded=true})
    end
    if DPSbutie and DPSbutie > 0 then
        totalpayout = totalpayout - DPSbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="DPS补贴", amount=-DPSbutie, isTraded=true})
    end
    if FOODbutie and FOODbutie > 0 then
        totalpayout = totalpayout - FOODbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="食物补贴", amount=-FOODbutie, isTraded=true})
    end
    if xiuXingbutie and xiuXingbutie > 0 then
        totalpayout = totalpayout - xiuXingbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="修星补贴", amount=-xiuXingbutie, isTraded=true})
    end
    if ANMUbutie and ANMUbutie > 0 then
        totalpayout = totalpayout - ANMUbutie
        table.insert(ZL_CURRENT.butie, {player="", notes="工具人补贴", amount=-ANMUbutie, isTraded=true})
    end
    if bill == ZL_CURRENT and ZL.AuctionRecordFrame.playerBalanceFrame.wagesNumber:GetNumber() > 0 then
        numGroupMembers = ZL.AuctionRecordFrame.playerBalanceFrame.wagesNumber:GetNumber()
        averageamount = math.floor((totalincome+totalpayout)*(1-raidLeaderTiCheng)/numGroupMembers)
    else
        averageamount = math.floor((totalincome+totalpayout)*(1-raidLeaderTiCheng)/totalBiLi)
    end
    -- averageamount = math.floor((totalincome+totalpayout)*(1-raidLeaderTiCheng)/totalBiLi)
    totalamount = totalincome + totalpayout
    --如果团长按点提成，则在净收入上先剔除团长提成
    if (RLBuTieType == 4) and raidLeaderTiCheng2 and raidLeaderTiCheng2 > 0 then
        RLBuTie = math.floor(totalamount*raidLeaderTiCheng)
        totalpayout = totalpayout - RLBuTie
        totalamount = totalamount - RLBuTie
    end
    if RLBuTie and RLBuTie > 0 then
        table.insert(ZL_CURRENT.butie, {player="", notes="RL补贴", amount=-RLBuTie, isTraded=true})
    end
    bill["aveWages"] = averageamount
    return numGroupMembers, RLBuTie, totalincome, totalpayout, totalamount, averageamount
end

--发送物品链接到聊天窗口
function ZL.ChatEditInsertLink(itemlink)
    if ZL.focusEditBox then
        ZL.focusEditBox:Insert(itemlink)
    elseif _G["ChatFrameEditBox"] and _G["ChatFrameEditBox"]:IsVisible() then
        _G["ChatFrameEditBox"]:Insert(itemlink)
    else
        -- ChatEdit_ActivateChat(ChatEdit_ChooseBoxForSend())
        -- ChatEdit_InsertLink(itemlink)
    end
end
--判断物品是否可以拍卖
function ZL.IsCanAuction(data, senderColorName)
    local info
    if data.spawnUID then
        for _, value in pairs(data.spawnUID) do
            if (not value["candidates"]) or (not next(value["candidates"], nil)) or (not senderColorName) or value["candidates"][senderColorName] then
                if value["itemGUID"] and next(value["itemGUID"], nil) then
                    for itemGuid in pairs(value["itemGUID"]) do
                        local bagID, slotIndex = ZL.FindItemInBag(itemGuid)
                        if bagID and slotIndex then
                            info = C_Container.GetContainerItemInfo(bagID, slotIndex)
                            if info.isBound then
                                --如果是拾取绑定物品，检测是否还有剩余交易时间
                                if (not ZL.ToolTip) then
                                    ZL.ToolTip = CreateFrame("GameTooltip", "TradeTimeRemainingTooltip", nil, "GameTooltipTemplate")
                                end
                                ZL.ToolTip:SetOwner(UIParent, "ANCHOR_NONE")
                                ZL.ToolTip:ClearLines()
                                ZL.ToolTip:SetBagItem(bagID, slotIndex)
                                for i = 1, ZL.ToolTip:NumLines() do
                                    local text = _G["TradeTimeRemainingTooltipTextLeft"..i]:GetText()
                                    if text then
                                        local timeRemaining = text:match(BIND_TRADE_TIME_REMAINING:gsub("%%s", "(.+)"))
                                        if timeRemaining then
                                            return true
                                        end
                                    end
                                end
                            else
                                return true
                            end
                        end
                    end
                else
                    return true
                end
            end
        end
    end
    return false
end
--获取背包格子信息
function ZL.GetBagsInfo()
    local bags = {}
    local currentInfo
    for bagID = 0, NUM_BAG_SLOTS do
        if not bags[bagID] then bags[bagID] = {} end
        for slotIndex = 1, C_Container.GetContainerNumSlots(bagID) do
            -- 获取当前格子的物品信息
            currentInfo = C_Container.GetContainerItemInfo(bagID, slotIndex)
            if currentInfo then
                bags[bagID][slotIndex] = currentInfo
            end
        end
    end
    currentInfo = nil
    return bags
end

--获取背包物品GUID并保存
function ZL.GetBagsItemGUDI()
    local guidList = {}
    local itemLocation, itemGuid
    for bagID = 0, NUM_BAG_SLOTS do
        for slotIndex = 1, C_Container.GetContainerNumSlots(bagID) do
            if not itemLocation then
                itemLocation = ItemLocation:CreateFromBagAndSlot(bagID, slotIndex)
            else
                itemLocation:SetBagAndSlot(bagID, slotIndex)
            end
            if C_Item.DoesItemExist(itemLocation) then
                itemGuid = C_Item.GetItemGUID(itemLocation)
                table.insert(guidList, itemGuid)
            end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid = nil
    return guidList
end
--获取新拾取物品的GUID并匹配到拍卖物品中
local function findItemGUID(itemlink, index, needCount)
    local itemHasCount = 0
    local itemLocation, itemGuid
    for bagID = 0, NUM_BAG_SLOTS do
        for slotIndex = 1, C_Container.GetContainerNumSlots(bagID) do
            -- 获取当前格子的物品信息
            local currentInfo = C_Container.GetContainerItemInfo(bagID, slotIndex)
            if currentInfo and currentInfo.hyperlink == itemlink then
                if not itemLocation then
                    itemLocation = ItemLocation:CreateFromBagAndSlot(bagID, slotIndex)
                else
                    itemLocation:SetBagAndSlot(bagID, slotIndex)
                end
                itemGuid = C_Item.GetItemGUID(itemLocation)
                local itemID = currentInfo.itemID
                --这个物品的GUID没有被使用过
                if (not ZL_CURRENT["itemGUIDUsed"]) or (not ZL_CURRENT["itemGUIDUsed"][itemGuid]) then
                    local isTrue = false
                    if currentInfo.isBound then
                        --如果是拾取绑定物品，检测是否还有剩余交易时间
                        if (not ZL.ToolTip) then
                            ZL.ToolTip = CreateFrame("GameTooltip", "TradeTimeRemainingTooltip", nil, "GameTooltipTemplate")
                        end
                        ZL.ToolTip:SetOwner(UIParent, "ANCHOR_NONE")
                        ZL.ToolTip:ClearLines()
                        ZL.ToolTip:SetBagItem(bagID, slotIndex)
                        for i = 1, ZL.ToolTip:NumLines() do
                            local text = _G["TradeTimeRemainingTooltipTextLeft"..i]:GetText()
                            if text then
                                local timeRemaining = text:match(BIND_TRADE_TIME_REMAINING:gsub("%%s", "(.+)"))
                                if timeRemaining then
                                    isTrue = true
                                    break
                                end
                            end
                        end
                    else
                        isTrue = true
                    end
                    if isTrue then
                        local npcID
                        local data =ZL_CURRENT["auctionlist"][index]
                        if data["stackCount"] == 1 then
                            --新增测试内容↓↓↓↓↓↓
                            for _, spawnData in pairs(data.spawnUID) do
                                if spawnData["itemGUID"] and (not next(spawnData["itemGUID"], nil)) then
                                    if itemID == 47242 then
                                        npcID = "其他"
                                    else
                                        npcID = spawnData["bossName"]
                                    end
                                    spawnData["itemGUID"][itemGuid] = {}
                                    break
                                end
                            end
                            --新增测试内容↑↑↑↑↑↑
                        else
                            npcID = "其他"
                            --新增测试内容↓↓↓↓↓↓
                            if data.spawnUID then
                                for _, spawnData in pairs(data.spawnUID) do
                                    spawnData["itemGUID"][itemGuid] = {}
                                end
                            end
                            --新增测试内容↑↑↑↑↑↑
                        end
                        --将使用过的itemGUID添加到itemGUIDUsed表中
                        if not ZL_CURRENT["itemGUIDUsed"] then ZL_CURRENT["itemGUIDUsed"] = {} end
                        ZL_CURRENT["itemGUIDUsed"][itemGuid] = npcID
                        --如果是打包拍卖，则同步到打包拍卖里面
                        if data.isPackage then
                            local _, __index = ZL.FetchDataFromItemId("[打包拍卖]", 1)
                            if __index then
                                table.insert(ZL_CURRENT.auctionlist[__index]["itemList"][itemlink]["itemGUID"], itemGuid)
                                ZL.syncAuction(__index)
                            end
                        end
                        itemHasCount = itemHasCount + currentInfo.stackCount
                        if itemHasCount >= needCount then
                            return
                        end
                    end
                end
            end
            if type(currentInfo) == "table" then wipe(currentInfo) end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid = nil
end
--获取物品ItemGUID
function ZL.GetLootItemGUID()
    if not ZL.PlayerIsML() then return end
    local info, itemHasCount
    local itemBagCount = 0
    local itemNeedCount = 0
    -- local auctionlist = ZL_CURRENT["auctionlist"]
    if ZL_CURRENT["auctionlist"] and #ZL_CURRENT["auctionlist"] > 0 then
        ZL.AuctionFrame2.StateFrame.levelSortBtn:Disable()
        ZL.AuctionFrame2.StateFrame.timeSortBtn:Disable()
        for index, data in ipairs(ZL_CURRENT["auctionlist"]) do
            itemBagCount = GetItemCount(data.itemlink) --获取背包物品数量
            itemHasCount = 0
            if data["spawnUID"] then
                for _, value in pairs(data["spawnUID"]) do
                    if value["itemGUID"] then
                        for itemGUID, _ in pairs(value["itemGUID"]) do
                            local bagID, slotIndex = ZL.FindItemInBag(itemGUID)
                            if bagID and slotIndex then
                                info = C_Container.GetContainerItemInfo(bagID, slotIndex)
                                itemHasCount = itemHasCount + info.stackCount
                            end
                        end
                    end
                end
            end
            itemNeedCount = data.itemCount - itemHasCount
            if itemBagCount > 0 and itemNeedCount > 0 then
                findItemGUID(data.itemlink, index, itemNeedCount)
            end
        end
        ZL.AuctionFrame2.StateFrame.levelSortBtn:Enable()
        ZL.AuctionFrame2.StateFrame.timeSortBtn:Enable()
    end
    if info then info = nil end
end

--在IncomeList中查询tradeId的索引号，可能有多个
function ZL.FindTradeIdIncomeList(tradeId)
    local index = {}
    if ZL_CURRENT["IncomeList"] and #ZL_CURRENT["IncomeList"] > 0 then
        for _index, data in ipairs(ZL_CURRENT["IncomeList"]) do
            if data["tradeId"] == tradeId then
                table.insert(index, _index)
            end
        end
    end
    return index
end

--将物品放到指定背包
function ZL.PutAuctionItemInBag(itemGUID, targetBag, direction)
    targetBag = tonumber(targetBag) or 0
    local itemLocation, itemGuid, currentInfo, targetSlotIndex, _currentInfo, ___currentInfo
    if targetBag and C_Container.GetContainerNumFreeSlots(targetBag) > 0 then
        for bagID = 0, NUM_BAG_SLOTS do
            if bagID ~= targetBag then
                for slotIndex = 1, C_Container.GetContainerNumSlots(bagID) do
                    currentInfo = C_Container.GetContainerItemInfo(bagID, slotIndex)
                    if currentInfo and currentInfo.isBound then --拾取绑定的物品才移动位置
                        if not itemLocation then
                            itemLocation = ItemLocation:CreateFromBagAndSlot(bagID, slotIndex)
                        else
                            itemLocation:SetBagAndSlot(bagID, slotIndex)
                        end
                        itemGuid = C_Item.GetItemGUID(itemLocation)
                        if itemGuid == itemGUID then
                            for _targetSlotIndex = (direction and C_Container.GetContainerNumSlots(targetBag) or 1), (direction and 1 or C_Container.GetContainerNumSlots(targetBag)), (direction and -1 or 1) do
                                _currentInfo = C_Container.GetContainerItemID(targetBag, _targetSlotIndex)
                                if not _currentInfo then
                                    if ZL.opt.emptyOneSpace then
                                        --不同包之间空一格格子
                                        if _targetSlotIndex == C_Container.GetContainerNumSlots(targetBag) and targetBag < NUM_BAG_SLOTS then
                                            ___currentInfo = C_Container.GetContainerItemID(targetBag+1, 1)
                                            if not ___currentInfo then
                                                targetSlotIndex = _targetSlotIndex
                                                break
                                            end
                                        elseif _targetSlotIndex == 1 and targetBag > 0 then
                                            ___currentInfo = C_Container.GetContainerItemID(targetBag-1, C_Container.GetContainerNumSlots(targetBag-1))
                                            if not ___currentInfo then
                                                targetSlotIndex = _targetSlotIndex
                                                break
                                            end
                                        else
                                            targetSlotIndex = _targetSlotIndex
                                            break
                                        end
                                    else
                                        targetSlotIndex = _targetSlotIndex
                                        break
                                    end
                                end
                            end
                            if targetSlotIndex then
                                ClearCursor()
                                C_Container.PickupContainerItem(bagID, slotIndex)
                                C_Container.PickupContainerItem(targetBag, targetSlotIndex)
                                return
                            end
                        end
                    end
                end
            end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid = nil
end

--通过itemGUID查询物品在背包中的位置
function ZL.FindItemInBag(itemGUID)
    if not itemGUID then return nil, nil end
    local itemLocation, itemGuid
    for bagID = 0, NUM_BAG_SLOTS do
        for slotIndex = 1, C_Container.GetContainerNumSlots(bagID) do
            if not itemLocation then
                itemLocation = ItemLocation:CreateFromBagAndSlot(bagID, slotIndex)
            else
                itemLocation:SetBagAndSlot(bagID, slotIndex)
            end
            if C_Item.DoesItemExist(itemLocation) then
                itemGuid = C_Item.GetItemGUID(itemLocation)
                if itemGuid == itemGUID then
                    return bagID, slotIndex
                end
            end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid = nil
    return nil, nil
end
--将指定成员调整到队伍后面
function ZL.ChangePlayerGroup(memeberList)
    local index = 1
    local function changeGroup()
        if index <= #memeberList then
            local sender = memeberList[index]
            local senderIndex = nil
            local subgroup = nil
            --获取在团队中的位置和小队号
            for i = 1, MAX_RAID_MEMBERS do
                local name, _, _subgroup = GetRaidRosterInfo(i)
                if name and ZL.GetClassColorName(name) == sender then
                    senderIndex = i
                    subgroup = _subgroup
                    break
                end
            end
            if senderIndex then
                local currentRoster = ZL.GetCurrentRoster()
                --从最后一队开始循环遍历
                for i = 8, subgroup+1, -1 do
                    if subgroup == i then --如果是和要调换队伍的人队伍一样，则不调换
                        break
                    else
                        if #currentRoster[i] < 5 then --如果目标队伍人数小于5人，则直接放到该小队
                            SetRaidSubgroup(senderIndex, i)
                            break
                        else --如果目标队伍人数为5人，则判断队伍中的玩家是否为消费老板或者需要邮寄的人或者是ML，都不是则跟他调换队伍
                            for j = 1, #currentRoster[i] do
                                local name = currentRoster[i][j]
                                local biLi = (ZL_CURRENT.WagesBiLi and ZL_CURRENT.WagesBiLi[name] and ZL_CURRENT.WagesBiLi[name].biLi) and (ZL_CURRENT.WagesBiLi[name].biLi/100) or 1
                                if ZL.PlayerIsML(name) and (biLi > 0) and ((not ZL_CURRENT["mailPlayers"]) or (not ZL_CURRENT["mailPlayers"][name])) then
                                    --如果不是消费老板，也不是需要邮寄的人，也不是ML，则遍历整个团队，查找这个在团队中的位置，然后相互调换
                                    for k = 1, MAX_RAID_MEMBERS do
                                        local _name = GetRaidRosterInfo(k)
                                        if _name and ZL.GetClassColorName(_name) == name then
                                            SwapRaidSubgroup(senderIndex, k)
                                            break
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
                index = index + 1
                C_Timer.After(0.3, changeGroup)
            else
                index = index + 1
                C_Timer.After(0.001, changeGroup)
            end
        end
    end
    changeGroup()
end

--获取不同背包插件的itemGuid对应的背包按钮名字
function ZL.GetBagButtonName(hide)
    local itemGuidBtnList = {}
    local itemLocation, itemGuid, bagButton, bagID, slotIndex
    local function linshi()
        if not itemLocation then
            itemLocation = ItemLocation:CreateFromBagAndSlot(bagID, slotIndex)
        else
            itemLocation:SetBagAndSlot(bagID, slotIndex)
        end
        if C_Item.DoesItemExist(itemLocation) then
            itemGuid = C_Item.GetItemGUID(itemLocation)
            itemGuidBtnList[itemGuid] = bagButton
        end
        if bagButton.BorderTop and hide then
            bagButton.BorderTop:Hide()
            bagButton.BorderLeft:Hide()
            bagButton.BorderBottom:Hide()
            bagButton.BorderRight:Hide()
        end
    end
    if _G["BagnonContainerItem1"] then
        --Bagnon背包插件,网易有爱BagBrother
        local i = 1
        while _G["BagnonContainerItem" .. i] do
            bagButton = _G["BagnonContainerItem" .. i]
            bagID = bagButton:GetParent():GetID()
            slotIndex = bagButton:GetID()
            linshi()
            i = i + 1
        end
    elseif _G["CombuctorFrame1"] then
        --Combuctor背包插件
        local i = 1
        while _G["CombuctorItem" .. i] do
            bagButton = _G["CombuctorItem" .. i]
            bagID = bagButton:GetParent():GetID()
            slotIndex = bagButton:GetID()
            linshi()
            i = i + 1
        end
    elseif _G["NDui_BackpackSlot1"] then
        --NDui插件
        local i = 1
        while _G["NDui_BackpackSlot" .. i] do
            bagButton = _G["NDui_BackpackSlot" .. i]
            bagID = bagButton.bagId
            slotIndex = bagButton.slotId
            linshi()
            i = i + 1
        end
    elseif _G["ElvUI_ContainerFrame"] then
        --ElvUI插件
        for _bagID = -1, NUM_BAG_SLOTS-1 do
            for _slotIndex = 1, C_Container.GetContainerNumSlots(_bagID + 1) do
                bagButton = _G["ElvUI_ContainerFrameBag" .. _bagID .. "Slot" .. _slotIndex]
                bagID = bagButton.BagID
                slotIndex = bagButton.SlotID
                linshi()
            end
        end
    elseif _G["CombuctorInventoryFrame1"] then
        --网易有爱CombuctDep
        local totalSlots = 0
        local id, bag, slot
        for _bagID = 0, NUM_BAG_SLOTS do
            totalSlots = totalSlots + C_Container.GetContainerNumSlots(_bagID)
        end
        totalSlots = totalSlots + 32 --加上钥匙链
        for i = 1, totalSlots do
            id = i + 1
            bag = ceil(id / 36)
            slot = (id-1) % 36 + 1
            bagButton = _G[format('ContainerFrame%dItem%d', bag, slot)]
            if bagButton then
                bagID = bagButton:GetParent():GetID()
                slotIndex = bagButton:GetID()
                linshi()
            end
        end
        id, bag, slot = nil, nil, nil
    elseif _G["AdiBagsContainer1"] then
        --AdiBags

    elseif _G["ARKINV_Frame1"] then
        --ArkInventory
        for _bagID = 0, NUM_BAG_SLOTS do
            for _slotIndex = 1, C_Container.GetContainerNumSlots(_bagID) do
                bagButton = _G["ARKINV_Frame1ScrollContainerBag" .. (_bagID+1) .. "Item" .. _slotIndex]
                if bagButton then
                    bagID = bagButton:GetParent():GetID()
                    slotIndex = bagButton:GetID()
                    linshi()
                end
            end
        end
    else
        --暴雪原始背包
        for _bagID = 0, NUM_BAG_SLOTS do
            for _slotIndex = 1, C_Container.GetContainerNumSlots(_bagID) do
                bagButton = _G["ContainerFrame" .. (_bagID+1) .. "Item" .. (C_Container.GetContainerNumSlots(_bagID) - _slotIndex + 1)]
                bagID = bagButton:GetParent():GetID()
                slotIndex = bagButton:GetID()
                linshi()
            end
        end
    end
    if itemLocation then
        itemLocation:Clear()
    end
    itemGuid, bagButton, bagID, slotIndex = nil, nil, nil, nil
    return itemGuidBtnList
end

--创建动画闪烁
function ZL.CreateBagFlash(b)
    if not b then return end
    b.ZLFlashFind = b:CreateAnimationGroup()
    b.IconGlow = b:CreateTexture(nil, 'OVERLAY', nil, 7) --OVERLAY  HIGHLIGHT
	b.IconGlow:SetTexture('Interface/Buttons/UI-ActionButton-Border')
	b.IconGlow:SetBlendMode('ADD')
	b.IconGlow:SetPoint('CENTER')
    b.IconGlow:SetSize(67,67)
    -- b.IconGlow:SetAllPoints(b)
    b.IconGlow:Hide()
	
	for i = 1, 3 do
		local fade = b.ZLFlashFind:CreateAnimation('Alpha')
		fade:SetChildKey('flash')
		fade:SetOrder(i * 2)
		fade:SetDuration(.4)
		fade:SetFromAlpha(.1)
		fade:SetToAlpha(1)

		local fade = b.ZLFlashFind:CreateAnimation('Alpha')
		fade:SetChildKey('flash')
		fade:SetOrder(i * 2 + 1)
		fade:SetDuration(.4)
		fade:SetFromAlpha(1)
		fade:SetToAlpha(.1)
	end
    b.ZLFlashFind:SetToFinalAlpha(0)
end
--创建高亮图层
function ZL.CreateBagHighLightFrame(parent, edgeSize, state, frame, talbe, flash)
    parent = parent or UIParent
    local color = ZL.colorList[state] or {1, 0, 0, 1}
    local f
    if frame then
        --如果存在则重新设置父对象
        f = frame
        f:SetParent(parent)
    else
        f = CreateFrame("Frame", nil, parent, "BackdropTemplate")
        table.insert(talbe, f)
    end
    f:SetBackdrop({
        edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",  --ChatFrameBackground
        edgeSize = edgeSize or 4,
        tile = true,
        insets = { left = 1, right = 1, top = 1, bottom = 1 }, -- 内边距
    })
    f:SetBackdropBorderColor(unpack(color))
    f:ClearAllPoints()
    f:SetAllPoints(parent)
    f:SetFrameLevel(parent:GetFrameLevel() + 8)
    f:Show()
    if flash then
        if not f.ag then
            f.ag = f:CreateAnimationGroup()
            f.anim = f.ag:CreateAnimation("Alpha")
            local anim = f.anim
            anim:SetOrder(1)
            anim:SetFromAlpha(0.1)
            anim:SetToAlpha(1)
            anim:SetDuration(0.5)
            f.ag:SetToFinalAlpha(1)
            f.ag:SetLooping("REPEAT")
        end
        if f.ag:Play() then f.ag:Stop() end
        f.ag:Play()
        C_Timer.After(5, function ()
            f.ag:Stop()
            f:Hide()
        end)
    end
end
--创建背包高亮
function ZL.BagHighLight()
    if (not ZL.opt.waitingBagHighLight) and (not ZL.opt.auctioningBagHighLight) and (not ZL.opt.successBagHighLight)
    and (not ZL.opt.failedBagHighLight) and (not ZL.opt.lgnoreBagHighLight) then
        return
    end
    -- if not ZL.BagHighLightList then ZL.BagHighLightList = {} end
    -- if ZL.BagHighLightList and #ZL.BagHighLightList > 0 then
    --     for _, f in ipairs(ZL.BagHighLightList) do
    --         f:Hide()
    --     end
    -- end
    if ZL_CURRENT.auctionlist and #ZL_CURRENT.auctionlist > 0 then
        local itemGuidBtnList = ZL.GetBagButtonName(true)
        local r, g, b, a
        local state
        if not next(itemGuidBtnList, nil) then return end
        -- local index = 1
        for _, data in ipairs(ZL_CURRENT.auctionlist) do
            if data.spawnUID and next(data.spawnUID, nil) and ((data.state == "waiting" and ZL.opt.waitingBagHighLight)
                or (data.state == "auctioning" and ZL.opt.auctioningBagHighLight) or (data.state == "success" and ZL.opt.successBagHighLight)
                or (data.state == "failed" and ZL.opt.failedBagHighLight) or (data.lgnore and ZL.opt.lgnoreBagHighLight)
            ) then
                if data.lgnore and ZL.opt.lgnoreBagHighLight then
                    state = "lgnore"
                else
                    if data.state == "waiting" and ZL.opt.waitingBagHighLight then
                        state = "waiting"
                    elseif data.state == "auctioning" and ZL.opt.auctioningBagHighLight then
                        state = "auctioning"
                    elseif data.state == "success" and ZL.opt.successBagHighLight then
                        state = "success"
                    elseif data.state == "failed" and ZL.opt.failedBagHighLight then
                        state = "failed"
                    end
                end
                if state then
                    for _, value in pairs(data.spawnUID) do
                        if value["itemGUID"] and next(value["itemGUID"], nil) then
                            for key in pairs(value["itemGUID"]) do
                                if itemGuidBtnList[key] then
                                    r, g, b, a = unpack(ZL.colorList[state] or {1, 0, 0, 1})
                                    if not itemGuidBtnList[key].BorderTop then
                                        ZL.CreateBorder(itemGuidBtnList[key], r, g, b, a, "OVERLAY", 4)
                                    else
                                        itemGuidBtnList[key].BorderTop:SetColorTexture(r,g,b,a)
                                        itemGuidBtnList[key].BorderLeft:SetColorTexture(r,g,b,a)
                                        itemGuidBtnList[key].BorderBottom:SetColorTexture(r,g,b,a)
                                        itemGuidBtnList[key].BorderRight:SetColorTexture(r,g,b,a)
                                        itemGuidBtnList[key].BorderTop:Show()
                                        itemGuidBtnList[key].BorderLeft:Show()
                                        itemGuidBtnList[key].BorderBottom:Show()
                                        itemGuidBtnList[key].BorderRight:Show()
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
        if itemGuidBtnList then itemGuidBtnList = nil end
    end
end
function ZL.CreateBagHighLightFrame2(parent, edgeSize, state, frame, talbe, flash)
    parent = parent or UIParent
    local color = ZL.colorList[state] or {1, 0, 0, 1}
    local f
    if not frame then
        f = CreateFrame("Frame", nil, parent, "BackdropTemplate")
        f:SetBackdrop({
            edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",  --ChatFrameBackground
            edgeSize = edgeSize or 8,
            tile = true,
            insets = { left = 1, right = 1, top = 1, bottom = 1 }, -- 内边距
        })
        f:SetBackdropBorderColor(unpack(color))
        f:ClearAllPoints()
        f:SetAllPoints(parent)
        f:SetFrameLevel(parent:GetFrameLevel() + 8)
    end
    f:Show()
    if flash then
        if not f.ag then
            f.ag = f:CreateAnimationGroup()
            f.anim = f.ag:CreateAnimation("Alpha")
            local anim = f.anim
            anim:SetOrder(1)
            anim:SetFromAlpha(0.1)
            anim:SetToAlpha(1)
            anim:SetDuration(0.5)
            f.ag:SetToFinalAlpha(1)
            f.ag:SetLooping("REPEAT")
        end
        if f.ag:Play() then f.ag:Stop() end
        f.ag:Play()
        -- local cbObject = C_Timer.NewTimer
        C_Timer.After(5, function ()
            f.ag:Stop()
            f:Hide()
        end)
    end
    table.insert(talbe, f)
end
--创建鼠标移动到拍卖物品背包高亮加闪烁
function ZL.OnEnterBagHighLight(v)
    
    local itemGuidBtnList = ZL.GetBagButtonName()
    local data = ZL_CURRENT.auctionlist[v]
    if data["spawnUID"] and next(data["spawnUID"], nil) then
        for _, value in pairs(data["spawnUID"]) do
            if value["itemGUID"] and next(value["itemGUID"], nil) then
                for key, _ in pairs(value["itemGUID"]) do
                    if itemGuidBtnList[key] then
                        if not itemGuidBtnList[key].ZLFlashFind then
                            ZL.CreateBagFlash(itemGuidBtnList[key])
                        end
                        if itemGuidBtnList[key].ZLFlashFind then
                            itemGuidBtnList[key].ZLFlashFind:Stop()
                            itemGuidBtnList[key].ZLFlashFind:Play()
                        end
                    end
                end
            end
        end
    end
    itemGuidBtnList = nil
end
-- 函数：在鼠标位置显示框架
function ZL.ShowAtMouse(frame)
    local scale = frame:GetEffectiveScale()
    local x, y = GetCursorPosition()
    x = x / scale
    y = y / scale
    frame:ClearAllPoints()
    frame:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", x, y)
    frame:Show()
end

function ZL.utf8len(s)
    local len = 0
    local currentIndex = 1
    local bytes = string.len(s)
    while currentIndex <= bytes do
        local char = string.byte(s, currentIndex)
        if char > 0 and char <= 127 then
            currentIndex = currentIndex + 1
        elseif char >= 194 and char <= 223 then
            currentIndex = currentIndex + 2
        elseif char >= 224 and char <= 239 then
            currentIndex = currentIndex + 3
        elseif char >= 240 and char <= 244 then
            currentIndex = currentIndex + 4
        end
        len = len + 1
    end
    return len
end

--打开设置窗口并设置为横向不可拉升
function ZL.OpenAceConfigDialog(name, path, ...)
    local AceConfigDialog = LibStub("AceConfigDialog-3.0")
    AceConfigDialog:Open(name)
    local frame = AceConfigDialog.OpenFrames[name]
    if frame then
        local actualFrame = frame.frame
        -- 设置横向不可拉升
        actualFrame:SetResizeBounds(700, 500, 700, GetScreenHeight()-30)
    end
    if path then
        LibStub("AceConfigDialog-3.0"):SelectGroup(name, path, ...)
    end
end
-- 添加到打包拍卖
function ZL.AddToPackage(v)
    ZL_CURRENT.auctionlist[v].isPackage = true
    local currentAuctionList = ZL_CURRENT.auctionlist[v]
    local itemlink = currentAuctionList.itemlink
    local itemindex = currentAuctionList.itemindex
    local itemCount = currentAuctionList.itemCount
    local _, index = ZL.FetchDataFromItemId("[打包拍卖]", 1)
    if not index then
        local spawnKey = "0" .. time() .. "01"
        local fdata = {
            type = "自动创建",
            itemId = 0,
            itemlink = "[打包拍卖]",
            itemindex = 1,
            startbidamount = 300,
            bidIncrement = 100,
            state = "waiting",
            lgnore = false,
            countdownremaining = 0,
            isPaused = false,
            bidderlist = {},
            itemCount = 1,
            sourceGUID = {},
            spawnUID = {[spawnKey] = {bossName="打包拍卖", itemGUID={}}},
            stackCount = 1,
            bindType = 0,
            itemLevel = 0,
            itemSubType = "打包",
            createTime = date("%Y-%m-%d %H:%M:%S", time()),
            itemList = {},
        }
        --ML自己创建，不参与插件同步创建
        ZL.CreateAuctionList()
        table.insert(ZL_CURRENT.auctionlist, fdata)
        index = #ZL_CURRENT.auctionlist
    end
    if not ZL_CURRENT.auctionlist[index].itemList then ZL_CURRENT.auctionlist[index].itemList = {} end
    if not ZL_CURRENT.auctionlist[index].itemList[itemlink] then ZL_CURRENT.auctionlist[index].itemList[itemlink] = {} end
    if not ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemGUID"] then
        ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemGUID"] = {}
    end
    if not ZL_CURRENT.auctionlist[index].itemList[itemlink]["spawnUID"] then
        ZL_CURRENT.auctionlist[index].itemList[itemlink]["spawnUID"] = {}
    end
    if not ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemindex"] then
        ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemindex"] = {}
    end
    local _itemlink = ZL_CURRENT.auctionlist[index].itemList[itemlink]
    ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemCount"] = (_itemlink["itemCount"] or 0) + ZL_CURRENT.auctionlist[v].itemCount
    ZL_CURRENT.auctionlist[index].itemList[itemlink]["stackCount"] = ZL_CURRENT.auctionlist[v].stackCount
    table.insert(ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemindex"], ZL_CURRENT.auctionlist[v].itemindex)
    local curAuction = ZL_CURRENT.auctionlist[v]
    if curAuction["spawnUID"] then
        for key, value in pairs(curAuction["spawnUID"]) do
            ZL_CURRENT.auctionlist[index].itemList[itemlink]["spawnUID"][key] = {["bossName"]=value["bossName"]}
            if value["itemGUID"] and next(value["itemGUID"], nil) then
                for itemGUID_key in pairs(value["itemGUID"]) do
                    table.insert(ZL_CURRENT.auctionlist[index].itemList[itemlink]["itemGUID"], itemGUID_key)
                end
            end
        end
    end
    --开始同步的功能
    local fdata = {
        type = "打包拍卖",
        data1 = ZL_CURRENT.auctionlist[v],
        data2 = ZL_CURRENT.auctionlist[index]
    }
    MyAddon:TransmitAddonInfo("AUTOAUC SYNC14", fdata)
    ZL.AuctionListSort()
end

--数字转汉字
function ZL.convertToChineseNumber(number)
    local chineseNumber = ""
    number = tostring(number)
    -- 遍历每个字符并进行转换
    for i = 1, #number do
        local digit = number:sub(i, i)
        chineseNumber = chineseNumber .. ZL.numToChinese[digit]
    end
    return chineseNumber
end

--将汉字数字转换为数字
function ZL.convert_all_chinese_numbers(input_str)
    -- 创建一个映射表，将汉字数字转换为阿拉伯数字
    local chinese_numbers = {
        ["两"] = 2,
        ["零"] = 0,
        ["一"] = 1,
        ["二"] = 2,
        ["三"] = 3,
        ["四"] = 4,
        ["五"] = 5,
        ["六"] = 6,
        ["七"] = 7,
        ["八"] = 8,
        ["九"] = 9,
        ["十"] = 10,
        ["百"] = 100,
        ["千"] = 1000,
        ["万"] = 10000,
        ["亿"] = 100000000
    }
    -- 将汉字数字转换为阿拉伯数字
    local function chinese_to_arabic(chinese_str)
        local result = 0
        local temp_num = 0
        local last_unit = 1 -- 上一个单位
    
        for i = 1, #chinese_str-2, 3 do
            local char = chinese_str:sub(i, i+2)
            local num = chinese_numbers[char]
    
            if num < 10 then
                temp_num = num
            else
                if num > last_unit then
                    result = result + (temp_num == 0 and 1 or temp_num) * num
                else
                    result = result + temp_num * num
                end
                temp_num = 0
                last_unit = num
            end
        end
    
        -- 处理最后一个数字
        if temp_num ~= 0 then
            result = result + temp_num
        end
    
        return result
    end
    local pattern = "[两零一二三四五六七八九十百千万亿]+"
    local result = input_str:gsub(pattern, function(cn_num)
        if cn_num then
            return tostring(chinese_to_arabic(cn_num))
        end
    end)
    return result
end

--ML检测自己的WA是否存在或是否是最新版
function  ZL.CheckWaVersion(dataID)
    local texture = "Interface\\Buttons\\UI-OptionsButton.blp"
    local data
    local oldWaVer
    local sendVer
    local msgStr
    if _G["WeakAurasSaved"] then
        data = _G["WeakAurasSaved"].displays[dataID]
    end
    if not data then
        msgStr = "请先复制字符串导入到自己的WA中，然后再|cff00ff00Shift+右键|r点击|T" .. texture .. ":12|t发送字符串到聊天频道中！"
        return false, msgStr
    else
        if data["authorOptions"] and #data["authorOptions"] > 0 then
            local authorOption = data["authorOptions"][1]
            if authorOption["type"] == "description" and authorOption["text"] then
                oldWaVer = (authorOption["text"]):match("^|cff00ff00版本号：WA%-V(%d+%.%d+%.%d+)|r$")
                sendVer = oldWaVer
            end
        end
    end
    if oldWaVer then
        oldWaVer = gsub(oldWaVer, "%.", "")
        oldWaVer = tonumber(oldWaVer)
        local newWaVer
        newWaVer = gsub(ZL.WAVersion, "V", ""):gsub("%.", "")
        newWaVer = tonumber(newWaVer)
        if newWaVer > oldWaVer then
            msgStr = "你的拍卖端WA版本过低，请先删除历史版本，重新复制WA字符串导入！"
            data = nil
            return false, msgStr
        end
    else
        msgStr = "未检测到你拍卖端WA版本号，请先删除历史版本，重新复制WA字符串导入！"
        data = nil
        return false, msgStr
    end
    return sendVer, msgStr
end

--获取周几
function ZL.GetWeekDay(dateString)
    local weekdays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"}
    local currentDate
    if dateString and type(dateString) == "string" then
        local year, month, day = dateString:match("(%d+)-(%d+)-(%d+)")
        local timestamp = time({
            year = tonumber(year),
            month = tonumber(month),
            day = tonumber(day)
        })
        currentDate = date("*t", timestamp)
    else
        currentDate = date("*t")
    end
    return weekdays[currentDate.wday]
end

--将收入记录添加到统计数据库
function ZL.InportToStatistics(data)
    if data.IncomeList and #data.IncomeList > 0 then
        local RealmName, FactionGroup, UnitGuid, auctiondate, listkey
        auctiondate = data.auctiondate:match("^(%d+-%d+-%d+)")
        if not auctiondate then return end
        if not data.RealmName then
            RealmName = GetRealmName()
            data.RealmName = RealmName
        else
            RealmName = data.RealmName
        end
        if not data.FactionGroup then
            FactionGroup = select(2, UnitFactionGroup("player"))
            data.FactionGroup = FactionGroup
        else
            FactionGroup = data.FactionGroup
        end
        if not data.UnitGuid then
            return
        end
        UnitGuid = data.UnitGuid
        listkey = RealmName .. "|" .. FactionGroup .. "|" .. UnitGuid .. "|" .. data.auctiondate
        if not ZL_Statistics[listkey] then
            for _, incomedata in ipairs(data.IncomeList) do
                local itemlink = incomedata.notes
                local itemId = itemlink:match("|Hitem:(%d+):")
                if itemId then
                    if not ZL_Statistics[listkey] then ZL_Statistics[listkey] = {} end
                    ZL_Statistics[listkey]["RealmName"] = RealmName
                    ZL_Statistics[listkey]["FactionGroup"] = FactionGroup
                    ZL_Statistics[listkey]["UnitGuid"] = UnitGuid
                    ZL_Statistics[listkey]["auctiondate"] = auctiondate
                    if not ZL_Statistics[listkey]["IncomeList"] then ZL_Statistics[listkey]["IncomeList"] = {} end
                    tinsert(ZL_Statistics[listkey]["IncomeList"], {
                        ["player"] = incomedata["player"],
                        ["amount"] = incomedata["amount"],
                        ["itemCount"] = incomedata["itemCount"],
                        ["notes"] = incomedata["notes"],
                    })
                end
            end
        end
    end
end

--格式为：“2025-01-01”, endtime 默认为今天
function ZL.GetDiffTime(_startTime, _endTime)
    _endTime = _endTime or date("%Y-%m-%d", time())
    local agoYear, agoMonth, agoDay = _startTime:match("(%d+)-(%d+)-(%d+)")
    local startTime = time{year=agoYear, month=agoMonth, day=agoDay, hour=0, min=0, sec=0}

    local endyear, endmonth, endday = _endTime:match("(%d+)-(%d+)-(%d+)")
    local endTime = time{year=endyear, month=endmonth, day=endday, hour=0, min=0, sec=0} -- 当前时间
    return difftime(endTime, startTime)
end
--鼠标滚轮设置文本框数字
function ZL.EditOnMouseWheel(self, delta)
    if self:HasFocus() then
        local number = self:GetNumber()
        if delta > 0 then
            number = number + 100
        else
            number = number - 100
        end
        -- if delta > 0 then
        --     if number >= 10000 then
        --         number = number + 1000
        --     elseif number >= 1000 then
        --         number = number + 1000
        --     elseif number >= 100 then
        --         number = number + 100
        --     else
        --         number = number + 10
        --     end
        -- else
        --     if number < 200 then
        --         number = number - 10
        --     elseif number < 2000 then
        --         number = number - 100
        --     elseif number < 20000 then
        --         number = number - 1000
        --     else
        --         number = number - 10000
        --     end
        -- end
        -- number = number >= 10 and number or 10
        self:SetNumber(number)
    end
end

function ZL.AddFriendFilterFunc(self, event, text, player, l, cs, t, flag, channelId, ...)
    local _msg = ERR_FRIEND_ADDED_S:gsub("%%s", "(.+)")
    if strfind(text, _msg) or strfind(text, "(.+)上线了。") or strfind(text, ERR_FRIEND_NOT_FOUND) then
        return true
    end
    return false, text, player, l, cs, t, flag, channelId, ...
end

--通过添加好友方式判断玩家是否在线
--del表示新添加的查完信息后是否要删除好友
function ZL.IsOnline(target, del, yield, noadd)
    if target == UnitName("player") then return true end
    local info = C_FriendList.GetFriendInfo(target)
    if (not info) then
        if C_FriendList.GetNumFriends() >= 100 then
            local msgStr = "好友数量已满，无法判断【" .. target .. "】是否在线，请先删除部分好友后重试"
            ZL.Print(msgStr, 1, 0, 0)
            return false
        else
            if yield or (not noadd) then
                C_FriendList.AddFriend(target)
                C_FriendList.ShowFriends()
                if yield then
                    ZL.addNewPlayer[target] = true
                    ZL.IsOnlinePlayer = target
                    coroutine.yield()
                end
                info = C_FriendList.GetFriendInfo(target)
                if del then
                    C_Timer.After(1, function ()
                        C_FriendList.RemoveFriend(target)
                        C_FriendList.ShowFriends()
                    end)
                end
            end
        end
    end
    return info and info.connected or false
end

-- 创建一个动态表格函数
function ZL.CreateDynamicTable()
    local mt = {
        __index = function(t, k)
            if not rawget(t, k) then
                -- 动态创建一个新的行或列
                t[k] = setmetatable({}, mt)
            end
            return t[k]
        end
    }
    return setmetatable({}, mt)  -- 返回一个动态表格
end

--获取周长重置和剩余重置时间
function ZL.GetWeeklyResetTime()
    -- 获取当前服务器时间（秒）
    local currentTime = GetServerTime()
    local resetTime
    local midnightTime
    local dateTable = date("*t", currentTime)
    local currentDayOfhour = dateTable.hour
    dateTable.hour = 7
    dateTable.min = 0
    dateTable.sec = 0

    -- 计算当前是本周的第几天（1 = 周日，2 = 周一，...，7 = 周六）
    local currentDayOfWeek = dateTable.wday
    if currentDayOfWeek == 5 then
        if currentDayOfhour >= 7 then
            dateTable.day = dateTable.day + 7
        end
    elseif currentDayOfWeek > 5 then
        dateTable.day = 7 - (currentDayOfWeek - 5) + dateTable.day
    else
        dateTable.day = 5 - currentDayOfWeek + dateTable.day
    end
    resetTime = time(dateTable)
    -- 计算剩余时间（秒）
    local remainingTime = resetTime - currentTime

    -- 将剩余时间转换为天、小时、分钟和秒
    local days = floor(remainingTime / 86400)
    local hours = floor((remainingTime % 86400) / 3600)
    local minutes = floor((remainingTime % 3600) / 60)
    local seconds = remainingTime % 60
    local remainTime
    if days > 0 then
        remainTime = days .. "天" .. hours .. "时" .. minutes .. "分" .. seconds .. "秒"
    elseif hours > 0 then
        remainTime = hours .. "时" .. minutes .. "分" .. seconds .. "秒"
    elseif minutes > 0 then
        remainTime = minutes .. "分" .. seconds .. "秒"
    else
        remainTime = seconds .. "秒"
    end
    return resetTime, remainTime
end

--获取日常重置和剩余时间
function ZL.GetDailyResetTime()
    -- 获取当前服务器时间（秒）
    local currentTime = GetServerTime()

    -- 获取当前日期的0点时间（秒）
    local dateTable = date("*t", currentTime)
    dateTable.hour = 0
    dateTable.min = 0
    dateTable.sec = 0
    local midnightTime = time(dateTable)

    -- 计算下一次7点的时间（秒）
    local resetTime = midnightTime + 25200  -- 7点 = 7 * 3600秒
    if currentTime >= resetTime then
        resetTime = resetTime + 86400  -- 如果当前时间已经超过7点，重置时间为第二天的7点
    end

    -- 计算剩余时间（秒）
    local remainingTime = resetTime - currentTime

    -- 将剩余时间转换为小时、分钟和秒
    local hours = floor(remainingTime / 3600)
    local minutes = floor((remainingTime % 3600) / 60)
    local seconds = remainingTime % 60
    local remainTime
    if hours > 0 then
        remainTime = hours .. "时" .. minutes .. "分" .. seconds .. "秒"
    elseif minutes > 0 then
        remainTime = minutes .. "分" .. seconds .. "秒"
    else
        remainTime = seconds .. "秒"
    end
    return resetTime, remainTime
end

--获取专业技能CD重置时间和剩余时间
function ZL.GetCooldownTime(spellID)
    local start, duration, enabled = GetSpellCooldown(spellID)
    local resetTime, remainTime
    if enabled == 1 and start > 0 and duration > 0 then
        local serverTime, time = GetServerTime(), GetTime()
        start = start > time and (start - 2 ^ 32 / 1000) or start
        local cooldownTime = start + duration - time
        if cooldownTime > 0 then
            remainTime = cooldownTime
            resetTime = cooldownTime + serverTime
        end
    elseif start == 0 then
        resetTime = 0
        remainTime = 0
    end
    return resetTime, remainTime
end
--将秒转换成时间格式2
function ZL.ConvertSecondsToTimeString(remainingTime)
    -- 将剩余时间转换为天、小时、分钟和秒
    local days = floor(remainingTime / 86400)
    local hours = floor((remainingTime % 86400) / 3600)
    local minutes = floor((remainingTime % 3600) / 60)
    local seconds = remainingTime % 60
    local remainTime
    if days > 0 then
        remainTime = days .. "天" .. hours .. "时"
    elseif hours > 0 then
        remainTime = hours .. "时" .. minutes .. "分"
    elseif minutes > 0 then
        remainTime = minutes .. "分" .. seconds .. "秒"
    else
        remainTime = seconds .. "秒"
    end
    return remainTime
end
--只支持3天，7天周期副本，默认重置周期为3天
function ZL.GetNextInstanceReset(days)
    days = ((not days) or days == 3) and 3 or 7
    local lastResetTime
    if days == 3 then
        lastResetTime = time({year=2025, month=4, day=15, hour=7})
    else
        lastResetTime = time({year=2025, month=4, day=17, hour=7})
    end
    local currentTime = GetServerTime()
    local nextReset = lastResetTime
    while nextReset <= currentTime do
        nextReset = nextReset + days * 24 * 60 * 60
    end
    return nextReset - currentTime, date("%Y-%m-%d %H:%M", nextReset)
end

function ZL.PrintHelp()
    DEFAULT_CHAT_FRAME:AddMessage(ZL.Prefix(" 斜杠命令："))
    for _, key in ipairs(ZL.commandInfoKeyList) do
        local value = ZL.commandInfo[key]
        if value and value.label then
            if value.key == "" then
                DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00/aa|r - " .. value.label)
            else
                DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00/aa " .. value.key .. "|r - " .. value.label)
            end
        end
    end
end
function ZL.OnChatCommand(input)
    input = strtrim(input)
    local cmd, args = strmatch(input, "^([^ ]*) ?(.*)$")
    cmd = strlower(cmd)
    if ZL.commandInfo[cmd] then
        ZL.commandInfo[cmd].callback(args)
    else
        ZL.PrintHelp()
    end
end

function ZL.SaveDataRemind(reset)
    if ZL.PlayerIsML() then
        if ZL.UpdateReloadUI and reset then
            if not ZL.UpdateReloadUI:IsCancelled() then
                ZL.UpdateReloadUI:Cancel()
            end
            ZL.UpdateReloadUI = nil
        end
        if not ZL.UpdateReloadUI then
            ZL.UpdateReloadUI = C_Timer.NewTicker((ZL.opt.reloadUITimerJump or 600), function ()
                if (not InCombatLockdown()) and ZL.opt.isReloadUI and IsInInstance() and (select(2, IsInInstance()) == "raid") then
                    if not ZL.ReloadUIFrame then ZL:CreateReloadUIFrame() end
                    ZL.ReloadUIFrame:Show()
                    PlaySoundFile("Interface\\AddOns\\" .. addonName .. "\\sound\\" .. ZL.SoundType .. "\\保存数据.mp3", "Master")
                    C_Timer.After(5, function ()
                        ZL.ReloadUIFrame:Hide()
                        if ZL.opt.isSYNCAll and ZL.GetAuctioningCount() == 0 then
                            ZL.syncDada()
                        end
                    end)
                end
            end)
        end
    else
        if ZL.UpdateReloadUI then
            if not ZL.UpdateReloadUI:IsCancelled() then
                ZL.UpdateReloadUI:Cancel()
            end
            ZL.UpdateReloadUI = nil
        end
    end
end

function ZL.GroupMembersDropdownMenuTable()
    local menuTable = {}
    local currentRoster = ZL.GetWagesGroupMembers()
    if currentRoster then
        for i = 1, #currentRoster do
            if #currentRoster[i] > 0 then
                local group = {
                    text = "|cffffffff小队" .. tostring(i) .. "|r",
                    hasArrow = true,
                    isTitle = true,
                    menuTable = {},
                }
                for _, playerName in ipairs(currentRoster[i]) do
                    tinsert(group.menuTable, {text=playerName})
                end
                tinsert(menuTable, group)
                group = nil
            end
        end
    end
    return menuTable
end
--创建团队成员下拉框
function ZL.CreateGroupMembersDropdown()
    -- 创建按钮并绑定菜单
    ZL.GroupMembersDropdown = CreateFrame("Button", nil, ZL)
    local GroupMembersDropdown = ZL.GroupMembersDropdown
    GroupMembersDropdown:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
    GroupMembersDropdown:SetSize(200, 24)
    ZL.GUI:GetClass('Dropdown'):Bind(GroupMembersDropdown)
    GroupMembersDropdown:Hide()
end

--判断流拍物品是否可以分解
function ZL.IsDisenchantAble(itemId)
    local inventoryType = C_Item.GetItemInventoryTypeByID(itemId)
    --0表示不可以装备
    if (not inventoryType) or inventoryType == 0 or (not ZL.invTypeToSlotId[inventoryType]) or
    ZL.invTypeToSlotId[inventoryType] == 4 or ZL.invTypeToSlotId[inventoryType] == 19 then
        return
    end
    return true
end

--深度复制表seen:可选
function ZL.deepCopy(original, seen)
    seen = seen or {}  -- 避免循环引用导致的无限递归
    if seen[original] then
        return seen[original]
    end

    local copy = {}
    seen[original] = copy

    for key, value in pairs(original) do
        if type(value) == "table" then
            copy[key] = ZL.deepCopy(value, seen)  -- 递归复制子表
        else
            copy[key] = value
        end
    end
    return copy
end

--获取物品装备、背包、银行中的数量
function ZL.GetItemNumbers(itemId)
    if not type(itemId) == "number" or itemId <= 0 then return end
    local inventoryCount = 0
    for slot = 1, 19 do -- 遍历所有装备栏（1-19）
        local item = GetInventoryItemID("player", slot)
        if item == itemId then
            inventoryCount = inventoryCount + 1
        end
    end
    local itemBagCount = GetItemCount(itemId) --获取背包+角色装备物品数量
    local bagCount = itemBagCount - inventoryCount --背包数量
    local itemTotalCount = GetItemCount(itemId, true) --获取背包+角色装备+银行物品数量
    local itemBankCount = itemTotalCount - itemBagCount --银行物品数量
    return inventoryCount, bagCount, itemBankCount, itemTotalCount
end

--获取在线总团员数和已安装插件或拍卖WA字符串数
function ZL.GetGroupMembersAndHasAddon()
    local totalMembers = 0
    local hasAddon = 0
    if ZL_PLAYERLIST.GroupMembersVersion and next(ZL_PLAYERLIST.GroupMembersVersion) and IsInRaid(1) then
        for i = 1, MAX_RAID_MEMBERS do
            local name, _, _, _, _, _, _, online = GetRaidRosterInfo(i)
            if name and online then
                totalMembers = totalMembers + 1
                if ZL_PLAYERLIST.GroupMembersVersion[name] then
                    hasAddon = hasAddon + 1
                end
            end
        end
    end
    return totalMembers, hasAddon
end

function ZL.formatNumber(num)
    -- 处理小数和负数
    local sign = ""
    if num < 0 then
        sign = "-"
        num = math.abs(num)
    end

    -- 定义单位表
    local units = {
        {value = 100000000, unit = "亿"},  -- 1亿
        {value = 10000, unit = "万"},      -- 1万
    }
    
    -- 检查是否需要转换
    if num < 10000 then
        return tostring(num)
    end

    -- 遍历单位表找到合适的单位
    for _, v in ipairs(units) do
        if num >= v.value then
            local formatted = num / v.value
            -- 根据大小决定保留几位小数
            -- local decimals = (formatted >= 100) and 0 or ((formatted >= 10) and 1 or 2)
            -- 格式化输出
            return sign .. formatted .. v.unit
        end
    end
    -- 默认返回原始数字（理论上不会执行到这里）
    return tostring(num)
end

--出价弹出菜单
function ZL.bidMenuTable(index)
    local menuList = {{text="快速出价", isTitle=true}}
    local curAuctionList = ZL_CURRENT.auctionlist[index]
    local Frame1 = ZL.AuctionFrame2.entries[index]
    local itemCount = curAuctionList.itemCount
    local bidCount = Frame1.bidFrame.bidCounts:GetNumber()
    bidCount = bidCount > 0 and bidCount or 1
    bidCount = bidCount > itemCount and itemCount or bidCount
    local _, bidIncrement, tarbidamount, _bidCount, successList = ZL.GetNewBidAmount(index)
    if bidCount > _bidCount and #successList > 0 then
        for i = #successList, 1, -1 do
            if successList[i][2] >= bidCount then
                tarbidamount = successList[i][1] + bidIncrement
                break
            end
        end
    end
    bidIncrement = max(bidIncrement, ZL.opt.quickBidIncrement)
    tarbidamount = math.ceil(tarbidamount / bidIncrement) * bidIncrement
    for i = 1, 10 do
        local wantBid = tarbidamount + bidIncrement * (i-1)
        tinsert(menuList, {
            text = wantBid,
            func = function ()
                local bidderlist = curAuctionList.bidderlist
                ZL.tableSort(bidderlist)
                local isSelf = false
                local totalBidCount = 0
                bidCount = Frame1.bidFrame.bidCounts:GetNumber()
                bidCount = bidCount > 0 and bidCount or 1
                bidCount = bidCount > itemCount and itemCount or bidCount
                for _, bidData in ipairs(bidderlist) do
                    if totalBidCount < curAuctionList.itemCount then
                        local count = bidData["bidCount"] or 1
                        local newTotalBidCount = totalBidCount + count
                        if newTotalBidCount > curAuctionList.itemCount then
                            count = curAuctionList.itemCount - totalBidCount
                        end
                        totalBidCount = newTotalBidCount
                        if ZL.ParseClassColorName(bidData.bidder) == UnitName("player") then
                            if bidData.bidCount >= bidCount then
                                isSelf = true
                            end
                            break
                        end
                    else
                        break
                    end
                end
                if (not isSelf) then
                    local msgStr = ""
                    local _, _bidIncrement, newBid, __bidCount, _successList = ZL.GetNewBidAmount(index)
                    if bidCount > __bidCount and #_successList > 0 then
                        for j = #_successList, 1, -1 do
                            if _successList[j][2] >= bidCount then
                                newBid = _successList[j][1] + _bidIncrement
                                break
                            end
                        end
                    end
                    if wantBid >= newBid then
                        if bidCount == 1 then
                            msgStr = tostring(wantBid)
                        else
                            msgStr = tostring(wantBid) .. "x" .. bidCount
                        end
                        if ZL_CURRENT.globalConfig.auctionMode == "团队" then
                            if not ZL_CURRENT.globalConfig.allowMultipleAuctions then
                                SendChatMessage(msgStr, "RAID")
                            else
                                SendChatMessage(curAuctionList.itemlink .. msgStr, "RAID")
                            end
                        else
                            MyAddon:TransmitAddonInfo2("AUTOAUC BID", curAuctionList.itemlink .. msgStr)
                        end
                    else
                        msgStr = "出价过低，当前竞拍数量".. bidCount .. "至少出价：|cffffd100" .. newBid .."|rg"
                        ZL.Print(msgStr)
                    end
                else
                    local msgStr = "你已经是有效最高出价者，无需竞价！"
                    ZL.Print(msgStr)
                end
                Frame1.bidFrame.bidEditBox:ClearFocus()
                ZL.FloatAuctionFrame.bidFrame.bidEditBox:ClearFocus()
            end
        })
    end
    tinsert(menuList, {isSeparator = true})
    tinsert(menuList, {
        text = "设置幅度",
        func = function ()
            Frame1.bidFrame.bidEditBox:ClearFocus()
            StaticPopup_Show("ZL_QUICKBIDINCREMENT", nil, nil)
        end
    })
    tinsert(menuList, {isSeparator = true})
    tinsert(menuList, {text="取消", func = function ()
        ZL.GUI:CloseMenu()
        Frame1.bidFrame.bidEditBox:ClearFocus()
        ZL.FloatAuctionFrame.bidFrame.bidEditBox:ClearFocus()
    end})
    return menuList
end

