bugfix20250107.1
全站通知:

模块:角色

来自卡拉彼丘WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

此模块的文档可以在模块:角色/doc创建

local p = {}

local stringUtil = require("模块:StringUtil")
local acandy = require("模块:ACandy")
local a, Raw, Fragment = acandy.a, acandy.Raw, acandy.Fragment
local tr, th, td = a.tr, a.th, a.td

local skillData = mw.loadData("模块:角色/SkillData")
local skinData = mw.loadData("模块:角色/SkinData")

local function nonEmpty(str)
	return str and str ~= ""
end

local function strFallback(str, fallbackStr)
	return str ~= "" and str or fallbackStr
end

local qualityColor = {
	["私服"] = "#F78653",
	["传说"] = "#F85555",
	["完美"] = "#FFC555",
	["卓越"] = "#F285FF",
	["精致"] = "#60A3F7",
	["初始"] = "#ECECEC",
}

-- 角色评论标题映射
local roleCommentsTitle = {
	["令"] = "令的手工俱乐部",
	["香奈美"] = "香奈美的粉丝团",
	["芙拉薇娅"] = "芙拉薇娅的围棋室",
	["加拉蒂亚·利里"] = "加拉蒂亚的魔术团",
	["玛德蕾娜·利里"] = "玛德蕾娜的绘梦室",
	["米雪儿·李"] = "米雪儿的猫猫军团",
	["绯莎"] = "绯莎的秘训基地",
	["伊薇特"] = "伊薇特的小熊团",
	["信"] = "信的侦探推理社",
	["奥黛丽·格罗夫"] = "奥黛丽的执事团",
	["明"] = "明的暗影刺客团",
	["梅瑞狄斯"] = "梅瑞狄斯科考团",
	["星绘"] = "星绘的疗愈小屋",
	["拉薇"] = "拉薇的茗香茶社",
	["艾卡"] = "艾卡的吉他室",
	["心夏"] = "心夏的无人机小队",
	["白墨"] = "白墨的涂鸦社",
	["珐格兰丝"] = "珐格兰丝的植物园",
	["忧雾"] = "忧雾的图书角",
	["蕾欧娜"] = "蕾欧娜的工程部",
	["玛拉"] = "玛拉的特训场",
	["千代"] = "千代的弓道部",
}

-- 获取当前页面标题
local function getPageTitle()
	return mw.title.getCurrentTitle().text
end

----角色页角色技能模板----
function p.roleSkill (frame)
	local role =  getPageTitle()
	local skillTypeToNum = {
		["主动"] = 1,  -- 主动技能
		["被动"] = 2,  -- 被动技能
		["终极"] = 3,  -- 终极技能
		["战术"] = 4,  -- 战术技能
	}
	local skills = {}
	
	-- 技能详情创建函数
	local function SkillDetail(skillType)
		local num = skillTypeToNum[skillType]
		local skill = skills[num]

		local roleskill = skillData[role]
		assert(roleskill, "角色名称错误: "..(role or "未知"))
		local RoleSkillType1 = skillType.."技能"
		local RoleSkillType = roleskill[RoleSkillType1]
		assert(RoleSkillType, "技能类型错误: "..(RoleSkillType1 or "未知"))
		local skillinfo = RoleSkillType[1]
		assert(skillinfo, RoleSkillType1.." 中没有技能")

		return {
			tr / th { colspan = "2", class = "text-center", style = "font-size: 18px;", skillType, "技能" },
			tr {
				td { class = "text-center", style = "font-weight:bold;font-size: 20px;padding: 0;width: 120px;min-height: 240px;", "[[文件:", role, "技能", num, ".png|120px]]", a.br, skillinfo['Name'] },
				td { style = "font-size: 16px;min-height: 240px;", skillinfo['Intro'] },
			},
		}
	end

	-- 创建角色技能表格
	local Roleskilltable = a.table { class = "klbqtable", style = "width: 100%;",
		SkillDetail("主动"),  -- 主动技能
		SkillDetail("被动"),  -- 被动技能
		SkillDetail("终极"),  -- 终极技能
		SkillDetail("战术"),  -- 战术技能
	}
	return Roleskilltable
end

----角色页角色时装----
local function createSkinTab(frame, characterName, skinName, skinQuality)
	local BorderColor = qualityColor[skinQuality]  -- 获取品质颜色
	local skinTabNav, skinTabContent = "", ""

	if skinQuality ~= "卓越" then
		skinTabNav = a.li { style = "display: inline;border-radius:5px;margin:0 3px;padding:5px;", frame:callParserFunction('#tag:a', { '立绘', href = '#'..skinName..'立绘', ['data-toggle'] = 'tab' }) }
		skinTabContent = a.div { class = "tab-pane", id = skinName.."立绘", "[[文件:"..characterName.."-"..skinName.."立绘.png]]" }
	end

	-- 返回时装标签和内容
	return a.li { class = "bili-list-style",
			a.span { class = "tab-panel radius5", style = "width:100%;border:3px solid "..BorderColor..";",
				skinName,
			},
		},
		a.div { class = "resp-tab-content",
			a.div { class = "tab skinImgTab", style = "display: flex;width: 100%;flex-direction: row-reverse;",
				a.ul { class = "tab-nav", style = "margin: 0 0 0 0.5em;writing-mode: vertical-rl;",
					a.li { class = "active", style = "display: inline;border-radius:5px;margin:0 3px;padding:5px;", frame:callParserFunction('#tag:a', { '模型正面', href = '#'..skinName..'模型正面', ['data-toggle'] = 'tab' }) },
					a.li { style = "display: inline;border-radius:5px;margin:0 3px;padding:5px;", frame:callParserFunction('#tag:a', { '模型背面', href = '#'..skinName..'模型背面', ['data-toggle'] = 'tab' }) },
					skinTabNav,
				},
				a.div { class = "tab-content",
					a.div { class = "tab-pane active", id = skinName.."模型正面", "[[文件:"..characterName.."时装-"..skinName..".jpg|class=radius5|link=]]" },
					a.div { class = "tab-pane", id = skinName.."模型背面", "[[文件:"..characterName.."时装-"..skinName.."_背面.jpg|class=radius5|link=]]" },
					skinTabContent,
				},
			},
		}
end

p["角色时装"] = function (frame)
    local roleName = getPageTitle()
    local skinsByQuality = { ["初始"] = {}, ["私服"] = {}, ["传说"] = {}, ["完美"] = {}, ["卓越"] = {} }

    local roleSkinData = skinData[roleName]
    if not roleSkinData then return "未找到角色数据" end

    -- 根据品质分类角色皮肤
    for skinName, skin in pairs(roleSkinData) do
        local rarity = skin['稀有度']
        local skinsOfThisQuality = skinsByQuality[rarity]
        if skinsOfThisQuality then
            skinsOfThisQuality[#skinsOfThisQuality + 1] = skinName
        end
    end

    local tabLabels, tabBodies = {}, {}
    -- 按顺序生成皮肤标签
    for _, quality in ipairs({ "初始", "私服", "传说", "完美", "卓越" }) do
        local len = #tabLabels
        for i, skinName in ipairs(skinsByQuality[quality]) do
            local label, body = createSkinTab(frame, roleName, skinName, quality)
            tabLabels[len + i] = label
            tabBodies[len + i] = body
        end
    end

    if tabLabels[1] then
        tabLabels[1].class = (tabLabels[1].class or "") .. " active"
        tabBodies[1].style = "display:block"
    end
    
    -- 修改评论区标题
	local commentsTitle = roleCommentsTitle[roleName]
	local css = frame:callParserFunction('#css', '.comments-title { max-width: 0; white-space: nowrap; }'..
		'.comments-title::before { position: absolute; content: "'..commentsTitle..'"; }')

    return a.div { class = "resp-tabs roleSkinTab", style = "border-spacing:0",
        a.ul { class = "resp-tabs-list clearfix", tabLabels },
        a.div { class = "resp-tabs-container", style = "margin-bottom: 5px;", tabBodies },
    }, a.br, css
end


local function flattenSkinData(data)
    local flatData = {}
    for roleName, skins in pairs(data) do
        for skinName, skin in pairs(skins) do
            table.insert(flatData, {
                id = skin.id,
                ["角色"] = roleName,
                ["时装名称"] = skinName,
                ["稀有度"] = skin["稀有度"],
                ['获得方式'] = skin['获得方式'],
                ["巴布洛晶核"] = skin["巴布洛晶核"] or "",
                ["基弦"] = skin["基弦"] or "",
                ["简介"] = skin["简介"],
                ["备注"] = skin["备注"] or "",
            })
        end
    end
    return flatData
end

local function renderSkinImage(skin)
	local rarityPopupSet = { ["卓越"] = true, ["完美"] = true, ["传说"] = true, ["私服"] = true }
    local file = "角色时装图鉴_" .. skin.id .. ".png"
    local role = skin['角色']
    local skinName = skin['时装名称']

    if rarityPopupSet[skin['稀有度']] then
        return '<span class="popup"><span style="display: table-cell;"><div style="position:relative;">[[File:'
            .. file .. '|200px|link=]]<br>' .. role .. ':' .. skinName
            .. '</div></span><span style="display:none;">[[file:'
            .. role .. '时装-' .. skinName .. '.jpg|200px]]</span></span>'
    end

    return '[[文件:' .. file .. '|200px|link=]]<br>' .. role .. ':' .. skinName
end


local function renderRarityTag(frame, skin)
	return frame:expandTemplate { title = '稀有度标签', args = { skin['稀有度'] } }
end

local function renderAcquireMethod(ways)
    if type(ways) ~= "table" then return "" end
    local parts = {}
    for _, part in ipairs(ways) do
        if part and part ~= "" then
            parts[#parts + 1] =
                '<span class="badge bg-primary" style="margin: 2px 0; font-size: 13px; white-space: nowrap;">'
                .. part .. '</span>'
        end
    end
    return table.concat(parts, "<br>")
end

p["角色时装筛选"] = function (frame)
    local flatData = flattenSkinData(skinData)

    local formatter = stringUtil.Formatter [=[
|- class="divsort" data-param1="{角色}" data-param2="{稀有度}" data-param3="{获得方式数据}" data-param4="{巴布洛晶核数据}" data-param5="{基弦数据}"
| style="padding: 2px;font-size: 16px;font-weight: 700;"|{时装}
| style="padding: 2px;"|{稀有度标签}
| style="width: 10%;padding: 2px"|{获得方式}
| style="width: 7%;padding: 2px"|{巴布洛晶核}
| style="width: 7%;padding: 2px"|{基弦}
| style="width: 40%;padding: 2px"|{简介}
| style="width: 15%;padding: 2px"|{备注}
]=]

    local result = {}

    for _, skin in ipairs(flatData) do
        if skin["稀有度"] ~= "初始" then
            local ways = skin["获得方式"] or {}
			local acquire_str = ""
			for i, v in ipairs(ways) do
    			if v and v ~= "" then
        			acquire_str = acquire_str .. (acquire_str ~= "" and "," or "") .. v
    			end
			end

            table.insert(result, formatter({
            	["角色"] = skin["角色"],
                ["稀有度"] = skin["稀有度"],
                ["时装"] = renderSkinImage(skin),
                ["稀有度标签"] = renderRarityTag(frame, skin),
                ["获得方式数据"] = acquire_str,
                ["巴布洛晶核数据"] = strFallback(skin["巴布洛晶核"], "无"),
                ["基弦数据"] = strFallback(skin["基弦"], "无"),
                ["巴布洛晶核"] = nonEmpty(skin["巴布洛晶核"]) and (skin["巴布洛晶核"] .. "[[文件:图标-小巴布洛晶核.png|15px|link=]]") or "",
                ["基弦"] = nonEmpty(skin["基弦"]) and (skin["基弦"] .. "[[文件:图标-小基弦.png|15px|link=]]") or "",
                ["获得方式"] = renderAcquireMethod(ways),
                ["简介"] = skin["简介"] or "",
                ["备注"] = skin["备注"] or "",
            }))
        end
    end

    return table.concat(result)
end


p["意识重构时装筛选"] = function (frame)
    local skinGet = frame.args[1]

    -- 内部函数:检查获得方式
    local function matchGetWay(ways, needle)
        if not needle or needle == "" then
            return true
        end
        if type(ways) == "table" then
            for _, w in ipairs(ways) do
                if string.find(w, needle, 1, true) then
                    return true
                end
            end
            return false
        end
        return false
    end

    local formatter = stringUtil.Formatter [=[
|-
| style="padding: 2px;font-size: 16px;font-weight: 700;"|{时装}
| style="padding: 2px;"|{稀有度标签}
| style="width: 70%"|{简介}
]=]

    local result = {}

    -- 遍历所有角色及其时装
    for roleName, skins in pairs(skinData) do
        for skinName, skin in pairs(skins) do
            if matchGetWay(skin['获得方式'], skinGet) then
                table.insert(result, formatter({
                    ['时装'] = renderSkinImage({
                        ['id'] = skin.id,
                        ['角色'] = roleName,
                        ['时装名称'] = skinName,
                        ['稀有度'] = skin['稀有度']
                    }),
                    ['稀有度标签'] = renderRarityTag(frame, skin),
                    ['简介'] = skin['简介'] or "",
                }, ''))
            end
        end
    end

    return table.concat(result)
end


return p