模块

装备:修订间差异

来自卡厄思梦境WIKI

律Rhyme留言 | 贡献
无编辑摘要
律Rhyme留言 | 贡献
无编辑摘要
第5行: 第5行:
local rarityMap = {
local rarityMap = {
     ["蓝"] = "蓝",
     ["蓝"] = "蓝",
     ["紫"] = "紫",  
     ["紫"] = "紫",
     ["金"] = "金"
     ["金"] = "金"
}
}


-- 生成装备卡片
-- 辅助函数:根据装备基础数据计算数值
local function calculateValue(rarity, itemType, level)
    local BASE_VALUES = {
        ["蓝"] = {
            ["武器"] = { values = {25, 41, 56, 67, 74} },
            ["装甲"] = { values = {9, 15, 21, 24, 28} },
            ["戒指"] = { values = {20, 37, 54, 66, 75} },
        },
        ["紫"] = {
            ["武器"] = { values = {28, 45, 62, 74, 82} },
            ["装甲"] = { values = {10, 17, 23, 27, 31} },
            ["戒指"] = { values = {22, 41, 60, 73, 83} },
        },
        ["金"] = {
            ["武器"] = { values = {31, 50, 68, 81, 90} },
            ["装甲"] = { values = {11, 19, 25, 30, 34} },
            ["戒指"] = { values = {24, 45, 66, 80, 91} },
        },
    }
   
    local levelNum = tonumber(level) or 1
    if BASE_VALUES[rarity] and BASE_VALUES[rarity][itemType] then
        return BASE_VALUES[rarity][itemType].values[levelNum]
    end
    return 0
end
 
-- 辅助函数:获取属性类型
local function getValueType(itemType)
    local typeMap = {
        ["武器"] = "攻击力",
        ["装甲"] = "防御力",
        ["戒指"] = "HP"
    }
    return typeMap[itemType] or ""
end
 
-- 生成装备卡片列表(用于筛选页面)
function p.generateCards(frame)
    local html = mw.html.create()
   
    -- 遍历所有装备,生成5星卡片
    for equipName, equipData in pairs(data) do
        -- 创建可筛选的卡片容器
        local cardWrapper = html:tag('div')
            :addClass('divsort equipment-wrapper')
            :attr('data-param1', equipData.rarity)  -- 稀有度
            :attr('data-param2', equipData.area or "")  -- 区域(如果有的话)
            :attr('data-param3', equipData.tag or "")  -- TAG(多个用逗号分隔)
            :cssText('display: inline-block; margin: 5px; position: relative;')
       
        -- 创建卡片和名称的容器
        local cardContainer = cardWrapper:tag('div')
            :cssText('display: flex; flex-direction: column; align-items: center;')
       
        -- 生成卡片内容
        local cardDiv = cardContainer:tag('div')
            :addClass('equipment-card')
            :attr('data-equipment', equipName)
            :attr('data-level', '5')
            :cssText('position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')
       
        -- 背景
        cardDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', equipData.rarity))
       
        -- 装备图片
        cardDiv:tag('div')
            :cssText('position: absolute; top: 43px; left: 13px;')
            :wikitext(string.format('[[File:%s|124px|link=]]', equipData.art))
       
        -- 底部背景
        cardDiv:tag('div')
            :cssText('position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
       
        -- 星级
        cardDiv:tag('div')
            :cssText('position: absolute; bottom: 10px; left: 20px;')
            :wikitext('[[File:icon_star_rating_5.png|link=]]')
       
        -- 顶层蒙版
        cardDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')
       
        -- 装备名称(可点击链接)
        local nameDiv = cardContainer:tag('div')
            :addClass('equipment-name-link')
            :cssText('text-align: center; width: 150px;')
       
        -- 根据稀有度设置名称颜色
        local nameColor = '#34638c'  -- 蓝色
        if equipData.rarity == '紫' then
            nameColor = '#b14fc5'  -- 紫色
        elseif equipData.rarity == '金' then
            nameColor = '#ff9500'  -- 金色
        end
       
        nameDiv:wikitext(string.format('[[%s|<span style="color:%s; font-size:14px; font-weight:bold;">%s</span>]]',
            equipName, nameColor, equipName))
       
        -- 生成对应的弹窗
        local popupDiv = cardWrapper:tag('div')
            :addClass('equipment-popup')
            :attr('id', 'equipment-popup-' .. mw.uri.encode(equipName))
            :cssText('position: fixed; display: none; width:368px; height: 335px; background-color: #343434; border-radius: 9px; z-index: 10000;')
       
        -- 弹窗背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', equipData.rarity))
       
        -- 弹窗装备图片
        popupDiv:tag('div')
            :cssText('position: absolute; top: 40px; left: 128px;')
            :wikitext(string.format('[[File:%s|124px|link=]]', equipData.art))
       
        -- 星级背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5);')
       
        -- 星级
        popupDiv:tag('div')
            :cssText('position: absolute; top: 173px; left: 128px;')
            :wikitext('[[File:icon_star_rating_5.png|link=]]')
       
        -- 类型图标
        popupDiv:tag('div')
            :cssText('position: absolute; top: 205px; left: 5px; color: white')
            :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', equipData.type, equipData.rarity))
       
        -- 装备名称
        popupDiv:tag('div')
            :cssText('position: absolute; top: 209px; left: 33px; color: white')
            :wikitext(equipName)
       
        -- 属性背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
       
        -- 属性类型
        local valueType = getValueType(equipData.type)
        popupDiv:tag('div')
            :cssText('position: absolute; top: 242px; left: 14px; color: white')
            :wikitext(valueType)
       
        -- 属性值
        local value = calculateValue(equipData.rarity, equipData.type, "5")
        popupDiv:tag('div')
            :cssText('position: absolute; top: 242px; right: 14px; color: white')
            :wikitext(value)
       
        -- 处理描述文本
        local desc = equipData.desc and equipData.desc[5] or ""
        desc = string.gsub(desc, "{{文本|橙|([^}]+)}}", '<span style="color:#ff9500;">%1</span>')
        desc = string.gsub(desc, "{{词典|([^}]+)}}", "[[%1]]")
       
        -- 描述
        popupDiv:tag('div')
            :cssText('position: absolute; top: 277px; left: 10px; right: 10px; color: white; font-size: 14px;')
            :wikitext(desc)
       
        -- 关闭按钮
        popupDiv:tag('div')
            :addClass('equipment-popup-close')
            :cssText('position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; cursor: pointer; color: white; font-size: 20px;')
            :wikitext('×')
    end
   
    return tostring(html)
end
 
-- 生成单个装备卡片
function p.card(frame)
function p.card(frame)
     local args = frame.args
     local args = frame.args
第20行: 第193行:
      
      
     local equip = data[name]
     local equip = data[name]
    local base = equip.base
    local levelData = equip[level]
   
    if not levelData then
        return "装备等级不存在: " .. level
    end
      
      
     -- 生成HTML
     -- 生成HTML
第37行: 第204行:
     html:tag('div')
     html:tag('div')
         :cssText('position: absolute; top: 0px; left: 0px;')
         :cssText('position: absolute; top: 0px; left: 0px;')
         :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', base.rarity))
         :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', equip.rarity))
      
      
     -- 装备图片
     -- 装备图片
     html:tag('div')
     html:tag('div')
         :cssText('position: absolute; top: 43px; left: 13px;')
         :cssText('position: absolute; top: 43px; left: 13px;')
         :wikitext(string.format('[[File:%s|124px|link=]]', base.art))
         :wikitext(string.format('[[File:%s|124px|link=]]', equip.art))
      
      
     -- 底部背景
     -- 底部背景
第59行: 第226行:
      
      
     return tostring(html)
     return tostring(html)
end
-- 生成装备详情弹窗
function p.popup(frame)
    local args = frame.args
    local name = args[1] or args.name
    local level = args[2] or args.level or "1"
   
    if not name or not data[name] then
        return "装备不存在: " .. (name or "未指定")
    end
   
    local equip = data[name]
    local base = equip.base
    local levelData = equip[level]
   
    if not levelData then
        return "装备等级不存在: " .. level
    end
   
    -- 处理描述文本
    local desc = levelData.desc_global
    desc = string.gsub(desc, "{{文本|橙|([^}]+)}}", '<span style="color:#ff9500;">%1</span>')
   
    -- 生成HTML
    local html = mw.html.create('div')
        :addClass('equipment-popup')
        :attr('id', 'equipment-popup-' .. mw.uri.encode(name))
        :cssText('position: relative; display: none; width:368px; height: 335px; background-color: #343434; border-radius: 9px')
   
    -- 背景
    html:tag('div')
        :cssText('position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', base.rarity))
   
    -- 装备图片
    html:tag('div')
        :cssText('position: absolute; top: 40px; left: 128px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', base.art))
   
    -- 星级背景
    html:tag('div')
        :cssText('position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5);')
   
    -- 星级
    html:tag('div')
        :cssText('position: absolute; top: 173px; left: 128px;')
        :wikitext(string.format('[[File:icon_star_rating_%s.png|link=]]', level))
   
    -- 类型图标
    html:tag('div')
        :cssText('position: absolute; top: 205px; left: 5px; color: white')
        :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', base.type, base.rarity))
   
    -- 装备名称
    html:tag('div')
        :cssText('position: absolute; top: 209px; left: 33px; color: white')
        :wikitext(name)
   
    -- 属性背景
    html:tag('div')
        :cssText('position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
   
    -- 属性类型
    html:tag('div')
        :cssText('position: absolute; top: 242px; left: 14px; color: white')
        :wikitext(base.value_type)
   
    -- 属性值
    html:tag('div')
        :cssText('position: absolute; top: 242px; right: 14px; color: white')
        :wikitext(levelData.value)
   
    -- 描述
    html:tag('div')
        :cssText('position: absolute; top: 277px; left: 10px; right: 10px; color: white; font-size: 14px;')
        :wikitext(desc)
   
    -- 关闭按钮
    html:tag('div')
        :addClass('equipment-popup-close')
        :cssText('position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; cursor: pointer; color: white; font-size: 20px;')
        :wikitext('×')
   
    return tostring(html)
end
-- 生成装备完整展示(卡片+弹窗)
function p.show(frame)
    local cardHtml = p.card(frame)
    local popupHtml = p.popup(frame)
   
    local wrapper = mw.html.create('div')
        :addClass('equipment-wrapper')
        :cssText('display: inline-block; position: relative;')
        :wikitext(cardHtml)
        :wikitext(popupHtml)
   
    return tostring(wrapper)
end
-- 生成装备卡片列表(用于筛选页面)
function p.generateCards(frame)
    local html = mw.html.create()
   
    -- 遍历所有装备,生成5星卡片
    for equipName, equipData in pairs(data) do
        local base = equipData.base
        local level5 = equipData["5"]
       
        if level5 then  -- 只显示有5星的装备
            -- 创建可筛选的卡片容器
            local cardWrapper = html:tag('div')
                :addClass('divsort equipment-wrapper')
                :attr('data-param1', rarityMap[base.rarity] or base.rarity)  -- 稀有度
                :attr('data-param2', base.area)  -- 区域
                :attr('data-param3', base.tag)  -- TAG(多个用逗号分隔)
                :cssText('display: inline-block; margin: 5px; position: relative;')
           
            -- 创建卡片和名称的容器
            local cardContainer = cardWrapper:tag('div')
                :cssText('display: flex; flex-direction: column; align-items: center;')
           
            -- 生成卡片内容
            local cardDiv = cardContainer:tag('div')
                :addClass('equipment-card')
                :attr('data-equipment', equipName)
                :attr('data-level', '5')
                :cssText('position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')
           
            -- 背景
            cardDiv:tag('div')
                :cssText('position: absolute; top: 0px; left: 0px;')
                :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', base.rarity))
           
            -- 装备图片
            cardDiv:tag('div')
                :cssText('position: absolute; top: 43px; left: 13px;')
                :wikitext(string.format('[[File:%s|124px|link=]]', base.art))
           
            -- 底部背景
            cardDiv:tag('div')
                :cssText('position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
           
            -- 星级
            cardDiv:tag('div')
                :cssText('position: absolute; bottom: 10px; left: 20px;')
                :wikitext('[[File:icon_star_rating_5.png|link=]]')
           
            -- 顶层蒙版
            cardDiv:tag('div')
                :cssText('position: absolute; top: 0px; left: 0px;')
                :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')
           
            -- 装备名称(可点击链接)
            local nameDiv = cardContainer:tag('div')
                :addClass('equipment-name-link')
                :cssText('text-align: center; width: 150px;')
           
            -- 根据稀有度设置名称颜色
            local nameColor = '#34638c'  -- 蓝色
            if base.rarity == '紫' then
                nameColor = '#b14fc5'  -- 紫色
            elseif base.rarity == '金' then
                nameColor = '#ff9500'  -- 金色
            end
           
            nameDiv:wikitext(string.format('[[%s|<span style="color:%s; font-size:14px; font-weight:bold;">%s</span>]]',
                equipName, nameColor, equipName))
           
            -- 生成对应的弹窗
            local popupDiv = cardWrapper:tag('div')
                :addClass('equipment-popup')
                :attr('id', 'equipment-popup-' .. mw.uri.encode(equipName))
                :cssText('position: fixed; display: none; width:368px; height: 335px; background-color: #343434; border-radius: 9px')
           
            -- 弹窗背景
            popupDiv:tag('div')
                :cssText('position: absolute; top: 0px; left: 0px;')
                :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', base.rarity))
           
            -- 弹窗装备图片
            popupDiv:tag('div')
                :cssText('position: absolute; top: 40px; left: 128px;')
                :wikitext(string.format('[[File:%s|124px|link=]]', base.art))
           
            -- 星级背景
            popupDiv:tag('div')
                :cssText('position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5);')
           
            -- 星级
            popupDiv:tag('div')
                :cssText('position: absolute; top: 173px; left: 128px;')
                :wikitext('[[File:icon_star_rating_5.png|link=]]')
           
            -- 类型图标
            popupDiv:tag('div')
                :cssText('position: absolute; top: 205px; left: 5px; color: white')
                :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', base.type, base.rarity))
           
            -- 装备名称
            popupDiv:tag('div')
                :cssText('position: absolute; top: 209px; left: 33px; color: white')
                :wikitext(equipName)
           
            -- 属性背景
            popupDiv:tag('div')
                :cssText('position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
           
            -- 属性类型
            popupDiv:tag('div')
                :cssText('position: absolute; top: 242px; left: 14px; color: white')
                :wikitext(base.value_type)
           
            -- 属性值
            popupDiv:tag('div')
                :cssText('position: absolute; top: 242px; right: 14px; color: white')
                :wikitext(level5.value)
           
            -- 处理描述文本
            local desc = level5.desc_global
            desc = string.gsub(desc, "{{文本|橙|([^}]+)}}", '<span style="color:#ff9500;">%1</span>')
           
            -- 描述
            popupDiv:tag('div')
                :cssText('position: absolute; top: 277px; left: 10px; right: 10px; color: white; font-size: 14px;')
                :wikitext(desc)
           
            -- 关闭按钮
            popupDiv:tag('div')
                :addClass('equipment-popup-close')
                :cssText('position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; cursor: pointer; color: white; font-size: 20px;')
                :wikitext('×')
        end
    end
   
    return tostring(html)
end
-- 直接显示弹窗内容(用于测试或独立展示)
function p.displayPopup(frame)
    local args = frame.args
    local name = args[1] or args.name
    local level = args[2] or args.level or "5"
   
    if not name or not data[name] then
        return "装备不存在: " .. (name or "未指定")
    end
   
    local equip = data[name]
    local base = equip.base
    local levelData = equip[level]
   
    if not levelData then
        return "装备等级不存在: " .. level
    end
   
    -- 处理描述文本
    local desc = levelData.desc_global
    desc = string.gsub(desc, "{{文本|橙|([^}]+)}}", '<span style="color:#ff9500;">%1</span>')
   
    -- 创建容器
    local container = mw.html.create('div')
        :cssText('display: inline-block; position: relative;')
   
    -- 生成弹窗HTML(直接显示,不隐藏)
    local popup = container:tag('div')
        :addClass('equipment-popup-display')
        :cssText('position: relative; display: block; width:368px; height: 335px; background-color: #343434; border-radius: 9px')
   
    -- 背景
    popup:tag('div')
        :cssText('position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', base.rarity))
   
    -- 装备图片
    popup:tag('div')
        :cssText('position: absolute; top: 40px; left: 128px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', base.art))
   
    -- 星级背景
    popup:tag('div')
        :cssText('position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5);')
   
    -- 星级
    popup:tag('div')
        :cssText('position: absolute; top: 173px; left: 128px;')
        :wikitext(string.format('[[File:icon_star_rating_%s.png|link=]]', level))
   
    -- 类型图标
    popup:tag('div')
        :cssText('position: absolute; top: 205px; left: 5px; color: white')
        :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', base.type, base.rarity))
   
    -- 装备名称
    popup:tag('div')
        :cssText('position: absolute; top: 209px; left: 33px; color: white; font-weight: bold;')
        :wikitext(name)
   
    -- 属性背景
    popup:tag('div')
        :cssText('position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
   
    -- 属性类型
    popup:tag('div')
        :cssText('position: absolute; top: 242px; left: 14px; color: white')
        :wikitext(base.value_type)
   
    -- 属性值
    popup:tag('div')
        :cssText('position: absolute; top: 242px; right: 14px; color: white; font-weight: bold;')
        :wikitext(levelData.value)
   
    -- 描述
    popup:tag('div')
        :cssText('position: absolute; top: 277px; left: 10px; right: 10px; color: white; font-size: 14px; line-height: 1.4;')
        :wikitext(desc)
   
    return tostring(container)
end
end


return p
return p

2025年10月17日 (五) 18:31的版本

此模块的文档可以在模块:装备/doc创建

local p = {}
local data = mw.loadData('模块:装备/data')

-- 获取装备稀有度对应的中文
local rarityMap = {
    ["蓝"] = "蓝",
    ["紫"] = "紫",
    ["金"] = "金"
}

-- 辅助函数:根据装备基础数据计算数值
local function calculateValue(rarity, itemType, level)
    local BASE_VALUES = {
        ["蓝"] = {
            ["武器"] = { values = {25, 41, 56, 67, 74} },
            ["装甲"] = { values = {9, 15, 21, 24, 28} },
            ["戒指"] = { values = {20, 37, 54, 66, 75} },
        },
        ["紫"] = {
            ["武器"] = { values = {28, 45, 62, 74, 82} },
            ["装甲"] = { values = {10, 17, 23, 27, 31} },
            ["戒指"] = { values = {22, 41, 60, 73, 83} },
        },
        ["金"] = {
            ["武器"] = { values = {31, 50, 68, 81, 90} },
            ["装甲"] = { values = {11, 19, 25, 30, 34} },
            ["戒指"] = { values = {24, 45, 66, 80, 91} },
        },
    }
    
    local levelNum = tonumber(level) or 1
    if BASE_VALUES[rarity] and BASE_VALUES[rarity][itemType] then
        return BASE_VALUES[rarity][itemType].values[levelNum]
    end
    return 0
end

-- 辅助函数:获取属性类型
local function getValueType(itemType)
    local typeMap = {
        ["武器"] = "攻击力",
        ["装甲"] = "防御力",
        ["戒指"] = "HP"
    }
    return typeMap[itemType] or ""
end

-- 生成装备卡片列表(用于筛选页面)
function p.generateCards(frame)
    local html = mw.html.create()
    
    -- 遍历所有装备,生成5星卡片
    for equipName, equipData in pairs(data) do
        -- 创建可筛选的卡片容器
        local cardWrapper = html:tag('div')
            :addClass('divsort equipment-wrapper')
            :attr('data-param1', equipData.rarity)  -- 稀有度
            :attr('data-param2', equipData.area or "")  -- 区域(如果有的话)
            :attr('data-param3', equipData.tag or "")  -- TAG(多个用逗号分隔)
            :cssText('display: inline-block; margin: 5px; position: relative;')
        
        -- 创建卡片和名称的容器
        local cardContainer = cardWrapper:tag('div')
            :cssText('display: flex; flex-direction: column; align-items: center;')
        
        -- 生成卡片内容
        local cardDiv = cardContainer:tag('div')
            :addClass('equipment-card')
            :attr('data-equipment', equipName)
            :attr('data-level', '5')
            :cssText('position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')
        
        -- 背景
        cardDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', equipData.rarity))
        
        -- 装备图片
        cardDiv:tag('div')
            :cssText('position: absolute; top: 43px; left: 13px;')
            :wikitext(string.format('[[File:%s|124px|link=]]', equipData.art))
        
        -- 底部背景
        cardDiv:tag('div')
            :cssText('position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
        
        -- 星级
        cardDiv:tag('div')
            :cssText('position: absolute; bottom: 10px; left: 20px;')
            :wikitext('[[File:icon_star_rating_5.png|link=]]')
        
        -- 顶层蒙版
        cardDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')
        
        -- 装备名称(可点击链接)
        local nameDiv = cardContainer:tag('div')
            :addClass('equipment-name-link')
            :cssText('text-align: center; width: 150px;')
        
        -- 根据稀有度设置名称颜色
        local nameColor = '#34638c'  -- 蓝色
        if equipData.rarity == '紫' then
            nameColor = '#b14fc5'  -- 紫色
        elseif equipData.rarity == '金' then
            nameColor = '#ff9500'  -- 金色
        end
        
        nameDiv:wikitext(string.format('[[%s|<span style="color:%s; font-size:14px; font-weight:bold;">%s</span>]]', 
            equipName, nameColor, equipName))
        
        -- 生成对应的弹窗
        local popupDiv = cardWrapper:tag('div')
            :addClass('equipment-popup')
            :attr('id', 'equipment-popup-' .. mw.uri.encode(equipName))
            :cssText('position: fixed; display: none; width:368px; height: 335px; background-color: #343434; border-radius: 9px; z-index: 10000;')
        
        -- 弹窗背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 0px; left: 0px;')
            :wikitext(string.format('[[File:bg_collection_rarity_%s.png|link=]]', equipData.rarity))
        
        -- 弹窗装备图片
        popupDiv:tag('div')
            :cssText('position: absolute; top: 40px; left: 128px;')
            :wikitext(string.format('[[File:%s|124px|link=]]', equipData.art))
        
        -- 星级背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 167px; left: 0px; width: 368px; height: 35px; background-color: rgba(0,0,0,0.5);')
        
        -- 星级
        popupDiv:tag('div')
            :cssText('position: absolute; top: 173px; left: 128px;')
            :wikitext('[[File:icon_star_rating_5.png|link=]]')
        
        -- 类型图标
        popupDiv:tag('div')
            :cssText('position: absolute; top: 205px; left: 5px; color: white')
            :wikitext(string.format('[[File:icon_equip_%s_%s.png|25px|link=]]', equipData.type, equipData.rarity))
        
        -- 装备名称
        popupDiv:tag('div')
            :cssText('position: absolute; top: 209px; left: 33px; color: white')
            :wikitext(equipName)
        
        -- 属性背景
        popupDiv:tag('div')
            :cssText('position: absolute; top: 235px; left: 9px; width: 350px; height: 35px; background-color: rgba(255,255,255,0.3); border-radius: 2px')
        
        -- 属性类型
        local valueType = getValueType(equipData.type)
        popupDiv:tag('div')
            :cssText('position: absolute; top: 242px; left: 14px; color: white')
            :wikitext(valueType)
        
        -- 属性值
        local value = calculateValue(equipData.rarity, equipData.type, "5")
        popupDiv:tag('div')
            :cssText('position: absolute; top: 242px; right: 14px; color: white')
            :wikitext(value)
        
        -- 处理描述文本
        local desc = equipData.desc and equipData.desc[5] or ""
        desc = string.gsub(desc, "{{文本|橙|([^}]+)}}", '<span style="color:#ff9500;">%1</span>')
        desc = string.gsub(desc, "{{词典|([^}]+)}}", "[[%1]]")
        
        -- 描述
        popupDiv:tag('div')
            :cssText('position: absolute; top: 277px; left: 10px; right: 10px; color: white; font-size: 14px;')
            :wikitext(desc)
        
        -- 关闭按钮
        popupDiv:tag('div')
            :addClass('equipment-popup-close')
            :cssText('position: absolute; top: 10px; right: 10px; width: 24px; height: 24px; cursor: pointer; color: white; font-size: 20px;')
            :wikitext('×')
    end
    
    return tostring(html)
end

-- 生成单个装备卡片
function p.card(frame)
    local args = frame.args
    local name = args[1] or args.name
    local level = args[2] or args.level or "1"
    
    if not name or not data[name] then
        return "装备不存在: " .. (name or "未指定")
    end
    
    local equip = data[name]
    
    -- 生成HTML
    local html = mw.html.create('div')
        :addClass('equipment-card')
        :attr('data-equipment', name)
        :attr('data-level', level)
        :cssText('position: relative; display: inline-block; width:150px; height: 230px; cursor: pointer;')
    
    -- 背景
    html:tag('div')
        :cssText('position: absolute; top: 0px; left: 0px;')
        :wikitext(string.format('[[File:bg_equipment_rarity_%s.png|150px|link=]]', equip.rarity))
    
    -- 装备图片
    html:tag('div')
        :cssText('position: absolute; top: 43px; left: 13px;')
        :wikitext(string.format('[[File:%s|124px|link=]]', equip.art))
    
    -- 底部背景
    html:tag('div')
        :cssText('position: absolute; bottom: 5px; left: 5px; width: 140px; height: 35px; background-color: rgba(0,0,0,0.5); border-radius: 0px 0px 8px 8px')
    
    -- 星级
    html:tag('div')
        :cssText('position: absolute; bottom: 10px; left: 20px;')
        :wikitext(string.format('[[File:icon_star_rating_%s.png|link=]]', level))
    
    -- 顶层蒙版
    html:tag('div')
        :cssText('position: absolute; top: 0px; left: 0px;')
        :wikitext('[[File:equipment_顶层蒙版.png|150px|link=]]')
    
    return tostring(html)
end

return p