缺氧 wiki 编辑团队提示:注册账号并登录后体验更佳,且可通过参数设置定制优化您的浏览体验!

该站点为镜像站点,如果你想帮助这个由玩家志愿编辑的 wiki 站点,请前往原站点参与编辑,
同时欢迎加入编辑讨论群 851803695 与其他编辑者一起参与建设!

全站通知:

模块:建筑信息框

来自缺氧WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

用于模板:Template:建筑信息框。 视图模块:Module:信息框/建筑。 数据模块:Module:Data/Buildings



-- Module:建筑信息框
local p = {}
local utils = require([[Module:Utils]])
local rcputils = require([[Module:Utils/Recipes]]).infobox
local po = require([[Module:Po]]).po
local getArgs = require('Module:Dev/Arguments').getArgs
local fstr = mw.ustring.format -- shortcut for formattig a string
local infobox = require([[Module:信息框/建筑]])

local i18ndc = require([[Module:I18n]]).loadMessages([[Module:i18n/Codex]])
local i18nde = require([[Module:I18n]]).loadMessages([[Module:i18n/Elements]])
local i18ndi = require([[Module:I18n]]).loadMessages([[Module:i18n/Items]])
local i18ndr = require([[Module:I18n]]).loadMessages([[Module:i18n/Research]])
local i18ndu = require([[Module:I18n]]).loadMessages([[Module:i18n/Ui]])
local i18ndm = require([[Module:I18n]]).loadMessages([[Module:i18n/Misc]])
local i18ndb = require([[Module:I18n]]).loadMessages([[Module:i18n/Buildings]])
local _c = function(...) return i18ndc:msg(...) end
local _e = function(...) return i18nde:msg(...) end
local _i = function(...) return i18ndi:msg(...) end
local _r = function(...) return i18ndr:msg(...) end
local _u = function(...) return i18ndu:msg(...) end
local _m = function(...) return i18ndm:msg(...) end
local _b = function(...) return i18ndb:msg(...) end
local buData = mw.loadData([[Module:Data/Buildings]])
local mModifier = require([[Module:Data/MaterialModifier]])
local k0 = utils.K0
local epsilon = 1e-7
local ROTATIONS = {
    [0] = "不可旋转",
    [1] = "90度旋转",
    [2] = "360度旋转",
    [3] = "水平翻转",
    [4] = "垂直翻转"
}

local function effectCode(id) return fstr("STRINGS.BUILDINGS.PREFABS.%s.EFFECT", string.upper(id)) end
local function descCode(id) return fstr("STRINGS.BUILDINGS.PREFABS.%s.DESC", string.upper(id)) end
local function isDefaultT(s, t) return ("<" .. s .. ">") == t end

local function cleanLoc(str) return (string.gsub(str,"<br/>","")) end

-- return {buCode}
local function getBuCode(pagename)
    local buCode = i18ndb:msgRev({
        key = pagename,
        args = {
            prefix = "STRINGS.BUILDINGS.PREFABS."
        }
    } or "")
    if buCode == nil or isDefaultT(pagename, buCode) then
        error(fstr("找不到建筑物 '%s',请使用参数1或检查 [[%s]]。",pagename, [[Module:Data/Buildings]]))
    else
        return buCode
    end
    return nil
end

local function getItemLink(items, sep)
    -- 返回物品短链
    local links = {}
    local shortcut = {
        ["BuildingFiber"] = "BasicFabric", -- 纤维 => 芦苇纤维
        ["BuildingWood"] = "Wood", -- 木材(分类) => 木材
    }
    for item in items:gmatch("[^%&]+") do
        item = shortcut[item] or item
        local locStr, isCat = utils.getEntry(item)
        locStr = cleanLoc(locStr)
        local link = isCat and fstr("[[:category:%s|%s]]", locStr, locStr) or fstr("[[%s]]", locStr)
        table.insert(links, link)
    end
    return table.concat(links, sep or "/")
end

local function logicMsg(s)
    local ret = _u(s)
    if isDefaultT(s, ret) then
        ret = _b(s)
    end
    return ret
end

function p._main(bu, buCode, args)
    local out = {}
    local pageCats = {}
    local elemData = nil
    out["ID"] = fstr("<code>%s</code>", bu.id)
    out["名称"] = _b(buCode)
    out["图片"] = args.img or fstr("%s.png", out["名称"])
    out["图片说明"] = _b(descCode(bu.id))
    out["图片说明"] = not isDefaultT(descCode(bu.id), out["图片说明"]) and out["图片说明"] or nil
    out["描述"] = _b(effectCode(bu.id))
    out["描述"] = not isDefaultT(effectCode(bu.id), out["描述"]) and out["描述"] or nil

    out['弃用'] = bu.Deprecated ~= nil and bu.Deprecated == true and "已弃用" or nil
    out["尺寸"] = fstr("宽 %s 高 %s", bu.WidthInCells, bu.HeightInCells)
    out["旋转"] = bu.PermittedRotations and ROTATIONS[bu.PermittedRotations] or "不可旋转"
    out["淹没"] = bu.Floodable and "淹没时无法运作" or "淹没时可正常工作"
    out["掩埋"] = bu.Entombable and "掩埋时无法运作" or "掩埋时可正常工作"
    out["基础建造时间"] = bu.ConstructionTime and fstr("%d 秒", bu.ConstructionTime) or nil
    out['建筑血量'] = bu.Invincible == true and "无敌" or utils.float2str(bu.HitPoints)
    out['可被蓄意破坏'] = bu.Breakable == true and bu.Invincible == false and "✔" or "✖"
    out['导热系数'] = bu.ThermalConductivity ~= nil and utils.float2str(bu.ThermalConductivity) or nil
    out['火箭限制'] = bu.rocketUsageRestrictionDef ~= nil and "✔" or nil

    out['电力'] = {}
    if bu.GeneratorWattageRating and bu.GeneratorWattageRating > 0 then
        local power = fstr("发电 %d 瓦", utils.float2str(bu.GeneratorWattageRating))
        table.insert(out['电力'], power)
    end
    if bu.EnergyConsumptionWhenActive and bu.EnergyConsumptionWhenActive > 0 then
        local power = fstr("消耗 %d 瓦", utils.float2str(bu.EnergyConsumptionWhenActive))
        table.insert(out['电力'], power)
    end
    out['电力'] = #out["电力"] ~= 0 and table.concat(out["电力"], "<br/>") or nil
    local heatGenerate = 0
    heatGenerate = heatGenerate + ( bu.ExhaustKilowattsWhenActive or 0 )
    heatGenerate = heatGenerate + ( bu.SelfHeatKilowattsWhenActive or 0 )
    if math.abs(heatGenerate) > 0.5 then
        out["产热"] = fstr("%d 千复制热/秒",
                            utils.float2str(heatGenerate, nil, true))
    elseif heatGenerate ~= 0 then
        out["产热"] = fstr("%d 复制热/秒",
                            utils.float2str(heatGenerate * 1000, nil, true))
    end
    if bu.battery ~= nil then
        out['电力容量'] = fstr("%s 千焦", utils.float2str(bu.battery.capacity/1000))
        out['电力泄露'] = fstr("%s 焦/[[周期]]", utils.float2str(bu.battery.joulesLostPerSecond*600))
    end
    if bu.tech ~= nil then
        local tech = _r("STRINGS.RESEARCH.TECHS."..bu.tech:upper()..".NAME")
        tech = cleanLoc(tech)
        out["科技"] = fstr("[[技术/%s|%s]]", tech, tech)
    end
    if bu.category ~= nil then
        out["类别"] = cleanLoc(_u(bu.category))
        if bu.subCategory ~= nil then
            out["类别"] = fstr("%s > %s", out["类别"], cleanLoc(_u(bu.subCategory)))
            table.insert(pageCats, fstr("[[category:%s]]", cleanLoc(_u(bu.subCategory))))
        end
    end
    if bu.roomRequireTags ~= nil then
        --- 房间需求类型
        out['类型'] = {}
        for _, tag in ipairs(bu.roomRequireTags) do
            local tagName = cleanLoc(po("STRINGS.ROOMS.CRITERIA."..tag:upper()..".NAME"))
            table.insert(out['类型'],fstr(
                "[[category:%s]]",
                tagName
            ))
            table.insert(pageCats, fstr("[[category:%s]]", tagName))
        end
        out['类型'] = #out["类型"] ~= 0 and table.concat(out["类型"], " ") or nil
    end
    if bu.effects ~= nil then
        local function getAttributeDesc(attribute)
            if attribute.formatter == nil then
                return utils.float2str(attribute.Value)
            end
            local unitClass = attribute.formatter['unitClass']
            local deltaTimeSlice = attribute.formatter['DeltaTimeSlice']
            local plusChar = attribute['IsMultiplier'] == true and "x" or true
            local timeSlice = deltaTimeSlice == "PerCycle" and 600 or 1
            if unitClass == "Percent" then
                return fstr("%s%%", utils.float2str(attribute.Value * timeSlice * 100, nil, plusChar))
            elseif unitClass == "SimpleFloat" then
                return utils.float2str(attribute.Value * timeSlice, 2, plusChar)
            elseif unitClass == "SimpleInteger" then
                return utils.float2str(attribute.Value * timeSlice, nil, plusChar)
            else
                return utils.float2str(attribute.Value * timeSlice, nil, plusChar)
            end
        end
        out['使用效果'] = {}
        for _, effect in ipairs(bu.effects) do
            table.insert(out['使用效果'],fstr(
                "%s(%s周期):",
                po("STRINGS.DUPLICANTS.MODIFIERS."..effect.Id:upper()..".NAME"),
                utils.float2str(effect.duration/600)
            ))
            if effect.SelfModifiers ~= nil then
                for _, attribute in ipairs(effect.SelfModifiers) do
                    table.insert(out['使用效果'],fstr(
                        "* %s: %s",
                        po("STRINGS.DUPLICANTS.ATTRIBUTES."..attribute.AttributeId:upper()..".NAME"),
                        getAttributeDesc(attribute)
                    ))
                end
            end
        end
        out['使用效果'] = #out["使用效果"] ~= 0 and table.concat(out["使用效果"], "\n") or nil
    end
    if bu.roomTracker ~= nil and bu.roomTracker.requiredRoomName ~= nil then
        out['房间类型'] = fstr("[[%s]]",cleanLoc(po(bu.roomTracker.requiredRoomName)))
    end
    -- out['操作'] = bu.AlwaysOperational == true and "复制人操作" or "无人值守"
    if bu.requiredGrantSkill == true then
        local skill = po(bu.requiredGrantSkill)
        local skillredir = {
        	["高级研究"] = "高级研究(技能)",
        	["应用科学研究"] = "应用科学研究(技能)"
        }
        if skillredir[skill] ~= nil then
            out['操作'] = fstr("%s(技能:[[%s|%s]])", out['操作'], cleanLoc(skillredir[skill]), cleanLoc(skill))
        else
            out['操作'] = fstr("%s(技能:[[%s]])", out['操作'], cleanLoc(skill))
        end
    end

    out["建筑材料"] = {}
    for _, ingredient in ipairs(bu.ingredients) do
        local material = ingredient.name
        if material == "BuildingFiber" then
            table.insert(out["建筑材料"], fstr("%s %s 单位", getItemLink(material), tostring(ingredient.amount)))
        else
            table.insert(out["建筑材料"], fstr("%s %s", getItemLink(material), utils.kg2str(ingredient.amount)))
        end
    end
    out["建筑材料"] = #out["建筑材料"] > 0 and table.concat(out["建筑材料"], "<br />") or nil
    if bu.Overheatable == true then
        out["过热"] = utils.float2str(bu.OverheatTemperature + k0) .. "°C"
        if out['过热'] ~= nil then
            local perMat = {}
            local elemRead = {}
            -- 读取元素数据
            if elemData == nil then
                elemData = mw.loadData([[Module:Data/Elements]])
            end
            -- 添加元素过热加成
            local function addEle(elem)
                local eId = elem.elementId
                if elemRead[eId] == nil then
                    local mod = mModifier[eId] and mModifier[eId].overheatMod ~= nil and mModifier[eId].overheatMod or 0
                    table.insert(perMat, {
                        elem.localizationID,
                        elem.buildMenuSort,
                        utils.float2str(bu.OverheatTemperature + mod + k0),
                        mod
                    })
                    elemRead[eId] = true
                end
            end

            local tagPrefix = "STRINGS.ELEMENTS."
            for i, ingredient in ipairs(bu.ingredients) do
                local m = ingredient.name
                local name, isCate , msgctxt, cate = utils.getEntry(m)
                if isCate or msgctxt:sub(1, #tagPrefix) ~= tagPrefix then
                    -- 获取标签下所有的元素
                    for _, elem in pairs(elemData) do
                        if elem.state == "Solid" and elem.isDisabled ~= true then
                            if elem.materialCategory ~= nil and elem.materialCategory:upper() == m:upper() then
                                addEle(elem)
                            elseif elem.tags ~= nil then
                                for _, t in ipairs(elem.tags) do
                                    if t:upper() == m:upper() then
                                        addEle(elem)
                                    end
                                end
                            end
                        end
                    end
                else
                    -- 元素
                    if mModifier[m] and mModifier[m].overheatMod then
                        local elem = elemData[m]
                        if elem ~= nil then
                            addEle(elem)
                        end
                    end
                end
            end

            -- 组装过热加成
            if #perMat > 0 then
                table.sort(perMat, function(a, b) return a[2] < b[2] end) -- 排序
                out['各材料过热'] = {}
                for _, mat in ipairs(perMat) do
                    local info = fstr(
                        "{{物品|%s}}<div></div><div>:</div><div style='text-align: right'>%s°C</div><div style='text-align: right'>(%+d°C)</div>",
                        _e(mat[1]), mat[3], mat[4])
                    table.insert(out['各材料过热'], info)
                end
                out['各材料过热'] = #out["各材料过热"] ~= 0 and table.concat(out["各材料过热"], "\n") or nil
            end
        end
    else
        out["过热"] = "✖"
    end
    if bu.BaseDecor and bu.BaseDecor ~= 0 and bu.BaseDecorRadius then
        out["装饰"] = fstr("%s(范围:%s 格)", tostring(bu.BaseDecor), tostring(bu.BaseDecorRadius))
        if out['装饰'] ~= nil then
            local perMat = {}
            local elemRead = {}
            -- 读取元素数据
            if elemData == nil then
                elemData = mw.loadData([[Module:Data/Elements]])
            end
            -- 添加元素装饰加成
            local function addEle(elem)
                local eId = elem.elementId
                if elemRead[eId] == nil then
                    local mod = mModifier[eId] and mModifier[eId].decor ~= nil and mModifier[eId].decor or 0
                    table.insert(perMat, {
                        elem.localizationID,
                        elem.buildMenuSort,
                        utils.float2str(bu.BaseDecor + math.abs(bu.BaseDecor) * mod, nil, true),
                        mod * 100
                    })
                    elemRead[eId] = true
                end
            end

            local tagPrefix = "STRINGS.ELEMENTS."
            for i, ingredient in ipairs(bu.ingredients) do
                local m = ingredient.name
                local name, isCate , msgctxt, cate = utils.getEntry(m)
                if isCate or msgctxt:sub(1, #tagPrefix) ~= tagPrefix then
                    -- 获取标签下所有的元素
                    for _, elem in pairs(elemData) do
                        if elem.state == "Solid" and elem.isDisabled ~= true then
                            if elem.materialCategory ~= nil and elem.materialCategory:upper() == m:upper() then
                                addEle(elem)
                            elseif elem.tags ~= nil then
                                for _, t in ipairs(elem.tags) do
                                    if t:upper() == m:upper() then
                                        addEle(elem)
                                    end
                                end
                            end
                        end
                    end
                else
                    -- 元素
                    if mModifier[m] and mModifier[m].decor then
                        local elem = elemData[m]
                        if elem ~= nil then
                            addEle(elem)
                        end
                    end
                end
            end

            -- 组装装饰加成
            if #perMat > 0 then
                table.sort(perMat, function(a, b) return a[2] < b[2] end) -- 排序
                out['各材料装饰'] = {}
                for _, mat in ipairs(perMat) do
                    local info = fstr(
                        "{{物品|%s}}<div></div><div>:</div><div style='text-align: right'>%s</div><div style='text-align: right'>(%+d%%)</div>",
                        _e(mat[1]), mat[3], mat[4])
                    table.insert(out['各材料装饰'], info)
                end
                out['各材料装饰'] = #out["各材料装饰"] ~= 0 and table.concat(out["各材料装饰"], "\n") or nil
            end
        end
    end
    if bu.storage ~= nil then
        if bu.storage.showInUI == true then
            out['机械臂运送'] = bu.storage.useGunForDelivery == true and "✔" or "✖"
            if bu.storage.storageFilters ~= nil and #bu.storage.storageFilters > 0 then
                out['允许清空库存'] = bu.storage.allowItemRemoval == true and "✔" or "✖"
                out['库存容量'] = utils.kg2str(bu.storage.capacityKg)
                out['库存'] = {}
                for _, tag in ipairs(bu.storage.storageFilters) do
                    local name = utils.getEntry(tag)
                    if name ~= nil then
                        table.insert(out['库存'], fstr("{{物品|%s}}}", name))
                    end
                end
            end
        else
            out['机械臂运送'] = bu.storage.useGunForDelivery == true and "✔" or nil
        end
    end
    if bu.LogicInputPorts ~= nil then
        out['自动化输入'] = {}
        for _, logicPort in ipairs(bu.LogicInputPorts) do
            table.insert(out['自动化输入'], fstr(logicMsg(logicPort.description)))
            table.insert(out['自动化输入'], fstr(
                "[[File:自动化输入绿色.png|16px|link=|alt=自动化输入绿色信号]] %s",
                logicMsg(logicPort.activeDescription)
            ))
            table.insert(out['自动化输入'], fstr(
                "[[File:自动化输入红色.png|16px|link=|alt=自动化输入红色信号]] %s",
                logicMsg(logicPort.inactiveDescription)
            ))
        end
        out["自动化输入"] = #out["自动化输入"] > 0 and table.concat(out["自动化输入"], "<br/>") or nil
    end
    if bu.LogicOutputPorts ~= nil then
        out['自动化输出'] = {}
        for _, logicPort in ipairs(bu.LogicOutputPorts) do
            table.insert(out['自动化输出'], fstr(logicMsg(logicPort.description)))
            table.insert(out['自动化输出'], fstr(
                "[[File:自动化输出绿色.png|16px|link=|alt=自动化输出绿色信号]] %s",
                logicMsg(logicPort.activeDescription)
            ))
            table.insert(out['自动化输出'], fstr(
                "[[File:自动化输出红色.png|16px|link=|alt=自动化输出红色信号]] %s",
                logicMsg(logicPort.inactiveDescription)
            ))
        end
        out["自动化输出"] = #out["自动化输出"] > 0 and table.concat(out["自动化输出"], "<br />") or nil
    end

    -- 眼冒金星火箭舱块
    if bu.rocketModule ~= nil then
        out["舱块负担"] = bu.rocketModule.burden
        out["引擎功率"] = bu.rocketModule.enginePower > 0 and bu.rocketModule.enginePower or nil
        if bu.rocketEngineCluster ~= nil then
            out["最大高度"] = bu.rocketEngineCluster.maxHeight
            if bu.rocketEngineCluster.requireOxidizer ~= nil then
                out["需要氧化剂"] = bu.rocketEngineCluster.requireOxidizer and "是" or "否"
            end
            -- 燃料
            if bu.rocketEngineCluster.fuelTag ~= nil then
                local fuelTag = fstr("{{物品|%s}}", utils.getEntry(bu.rocketEngineCluster.fuelTag))
                -- global::CraftModuleInterface.FuelPerHex.get()
                if fuelTag == "HighEnergyParticle" then
                    out["燃料"] = fstr("%s:%s单位/格", fuelTag, utils.float2str(bu.rocketModule.fuelKilogramPerDistance * 600))
                else
                    out["燃料"] = fstr("%s:%s/格", fuelTag, utils.kg2str(bu.rocketModule.fuelKilogramPerDistance * 600))
                end
            end
            -- 废气
            if bu.rocketEngineCluster.exhaustElement ~= nil then
                out["废气"] = fstr(
                    "%s:%s/秒\n(最高 %s°C)", 
                    fstr("{{物品|%s}}", utils.getEntry(bu.rocketEngineCluster.exhaustElement)),
                    utils.kg2str(bu.rocketEngineCluster.exhaustEmitRate),
                    utils.float2str(bu.rocketEngineCluster.exhaustTemperature + k0)
                )
            end
        end
    elseif bu.rocketEngine ~= nil then
        if bu.rocketEngine.requireOxidizer ~= nil then
            out["需要氧化剂"] = bu.rocketEngine.requireOxidizer and "是" or "否"
        end
        -- 燃料
        if bu.rocketEngine.fuelTag ~= nil then
            out["燃料"] = fstr("{{物品|%s}}", utils.getEntry(bu.rocketEngine.fuelTag))
        end
        -- 废气
        if bu.rocketEngine.exhaustElement ~= nil then
            out["废气"] = fstr(
                "%s:%s/秒\n(最高 %s°C)", 
                fstr("{{物品|%s}}", utils.getEntry(bu.rocketEngine.exhaustElement)),
                utils.kg2str(bu.rocketEngine.exhaustEmitRate),
                utils.float2str(bu.rocketEngine.exhaustTemperature + k0)
            )
        end
    end
    
    -- 配方
    if bu.recipes then
    	out["配方"] = rcputils(bu.recipes)
    end

    -- 添加页面分类
    if bu.category ~= nil then
        if utils.startswith(bu.category, "STRINGS.UI.BUILDCATEGORIES.") then
            table.insert(pageCats, fstr("[[category:%s建筑]]", cleanLoc(_u(bu.category))))
        elseif utils.startswith(bu.category, "STRINGS.UI.") then
            table.insert(pageCats, fstr("[[category:%s]]", cleanLoc(_u(bu.category))))
        else
            table.insert(pageCats, fstr("[[category:%s]]", cleanLoc(_m(bu.category))))
        end
    end

    if (args.namespace or args.nocat) then pageCats = {} end
    if (args.debug) then mw.logObject(out) end
    return out, pageCats
end

-- test by: = p.main(require("Module:debug").frame({},{debug=1, "AirConditioner"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, "Tile"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="温度调节器"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="电解器"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="藻类箱"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="反熵热量中和器"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="塑料梯子"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="自动卸物箱"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="变温板"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="浓缩咖啡机"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="榨汁机"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="丰碑中段"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="肖像画布"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="冰箱"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="花盆"}))
--[[ test by:
= p.main(require("Module:debug").frame({},{
    pagename='虚拟天象仪'
}))
]]
-- test by: = p.main(require("Module:debug").frame({},{debug=1, pagename="辐射粒子引擎"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, "KeroseneEngineCluster" ,pagename="辐射粒子引擎"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, "SteamEngineCluster"}))
-- test by: = p.main(require("Module:debug").frame({},{debug=1, multipage="PropSurfaceSatellite1,PropSurfaceSatellite2,PropSurfaceSatellite3"}))
--[[ test by:
= p.main(require("Module:debug").frame({},{
    main,
    debug=1,
    multipage=,
}))
]]
function p.main(frame)
    local args = getArgs(frame)
    local builds = {}
    if args.debug then mw.logObject(args, "args") end
    
    if args[1] ~= nil or args.multipage ~= nil then
        local pagename_array = {}
        pagename_array = args[1] ~= nil and {args[1]} or nil
        if pagename_array == nil then
            pagename_array = args.multipage ~= nil and mw.text.split(args.multipage, ",") or {}
        end
        for _, buId in ipairs(pagename_array) do
            local _, _, buCode = utils.getEntry(buId)
            if buCode ~= nil then
                -- 使用id
                table.insert(builds, {
                    id = buId,
                    code = buCode
                })
            else
                -- 使用pagename
                buCode = getBuCode(buId)
                local mId = buCode:match("([%u%d]+).NAME$")
                table.insert(builds, {
                    id = mId,
                    code = buCode
                })
            end
        end
    else
        local buCode = getBuCode(args.pagename)
        local buId = buCode:match("([%u%d]+).NAME$")
        table.insert(builds, {
            id = buId,
            code = buCode
        })
    end

    -- 组装信息
    local pageCats = {}
    local infos = {}
    for _, building in ipairs(builds) do
        for k, v in pairs(buData) do
            if k:upper() == building.id:upper() then
                local curr, cats = p._main(v, building.code, args)
                table.insert(infos, {
                    label = curr['名称'],
                    data = curr
                })
                if cats ~= nil then
                    for _, c in ipairs(cats) do
                        if c ~= nil then
                            table.insert(pageCats, c)
                        end
                    end
                end
            end
        end
    end

    if args.debug then mw.logObject(infos, "infos") end
    if args.debug then mw.logObject(pageCats, "pageCats") end

    local infoboxTitle = #infos == 1 and infos[1].label or args.pagename
    return infobox.main(infoboxTitle, infos) .. table.concat(pageCats, "")
end

return p