local p = {}
local color_map = {
["0"]="b3b3b3", ["1"]="b3b3b3", ["2"]="38c8ff", ["3"]="9a6cf1",
["4"]="ffce3b", ["5"]="f7c1cf", ["6"]="c90", ["7"]="ffd4e0",
["13"]="3e0000",["14"]="36244f"
}
local bg_map = {
["0"]="linear-gradient(-45deg,#d0d0d0,#D3D3D3,#A9A9A9)",
["2"]="linear-gradient(-45deg,#4169E1,#aae6fd,#00BFFF)",
["3"]="linear-gradient(-45deg,#9932CC,#B399FF,#9932CC)",
["4"]="linear-gradient(-45deg,#E6B800,#FFD700,#E6B800)",
["5"]="linear-gradient(-45deg,#fd99dc,#c5a2f5,#a2bef5,#a2e0f5,#93f2ff,#a1ffe2,#a4ffb1)",
["6"]="linear-gradient(-45deg,#9a4720,#d3aa4f,#f7ec85,#d3aa4f,#9a4720)",
["7"]="linear-gradient(-45deg,#ffd4e0,#f3d0ff,#b2cbff,#c3fdff,#b9f7e7)",
["13"]="linear-gradient(-45deg,#372654,#a676fc,#9c73fc,#9c73fc,#a676fc,#372654)",
["14"]="linear-gradient(-45deg,#372654,#9e5c22,#E6B800,#E6B800,#9e5c22,#372654)"
}
local function safe(v) return tostring(v or "") end
-- 解析 size(支持 number、"75"、"75px"、" 75 px " 等)
local function parse_size(raw)
if not raw then return 75 end
if type(raw) == "number" then
return raw
end
local s = tostring(raw)
s = s:match("^%s*(.-)%s*$") or s
local numstr = s:match("([%d]+%.?%d*)")
local n = tonumber(numstr)
if n then return n end
return 75
end
-- 从模板展开得到纯文本(尽量去除首尾空白)
local function expand_and_sanitize(frame, title, args_table)
local expanded = frame:expandTemplate{ title = title, args = args_table }
if not expanded then return "" end
-- 去掉首尾空白并把内部换行/多空白压缩为单个空格,再去空格(文件名一般不需要空格)
expanded = tostring(expanded)
expanded = expanded:match("^%s*(.-)%s*$") or expanded
-- 将所有空白(空格、换行、制表)压缩为单个空格
expanded = expanded:gsub("[%s]+", " ")
-- 移除空格以防文件名里出现空白(符合原模板文件拼音通常没有空格)
expanded = expanded:gsub(" ", "")
return expanded
end
-- 主渲染函数(每次调用都会重新生成 wikitext)
function p.render(frame)
frame = frame or mw.getCurrentFrame()
local args = frame.args or {}
-- 参数解析(保持与原模板签名兼容)
local name = safe(args[1] or args.name)
local fileArg = args.file and args.file ~= "" and args.file or nil
local rarity = ""
local size_raw = args.size or args["大小"] or nil
local size = parse_size(size_raw) -- number
local num = args.num or ""
local dt = args.dt or ""
local isnav = args.isnav or ""
local css = args.css or ""
local suffix = args["后缀"] or args.suffix or "" -- 后缀原样接收
local skin = args.skin or args["序号"] or ""
local linkParam = args.link or ""
-- 安全取得当前页面标题的文本(避免对字符串调用 :text() 导致错误)
local cur = mw.title.getCurrentTitle()
local curText
if type(cur) == "table" then
if type(cur.text) == "string" then
curText = cur.text
else
curText = cur:text()
end
else
curText = tostring(cur)
end
-- 文件名决定逻辑(优先 file 参数,否则按老逻辑组装)
local fileName = fileArg
if not fileName or fileName == "" then
-- 先取得拼音(调用模板:碧蓝航线文件拼音)
-- 传参:第一个位置参数为中文名(即模板原来写法:{{碧蓝航线文件拼音|{{{1}}}}})
local pinyin = ""
if name and name ~= "" then
pinyin = expand_and_sanitize(frame, "碧蓝航线文件拼音", { [1] = tostring(name) })
end
if pinyin == "" then
-- 回退到页面名的文本(已做过类型检查)
pinyin = expand_and_sanitize(frame, "碧蓝航线文件拼音", { [1] = tostring(curText) })
-- 如果上面也为空,就直接用 curText 但去除空格
if pinyin == "" then
pinyin = tostring(curText):gsub("%s+", "")
end
end
-- 后缀处理(尽量遵循原模板:若有后缀则默认在前加下划线)
local suffix_part = ""
if suffix and suffix ~= "" then
-- 如果你需要对特定后缀(如 'younv'、'idol')做特殊处理(原模板把它们归类),
-- 可以在这里加入判断;当前实现统一附加下划线前缀(与原模板的 #default 行一致)。
suffix_part = "_" .. tostring(suffix)
end
local skinSuffix = (skin and skin ~= "") and ("_" .. skin) or ""
local iconType = (name == "指挥官") and "Qicon" or "Icon"
fileName = string.format("BLHX_%s_%s%s%s.png", iconType, pinyin, suffix_part, skinSuffix)
end
-- link 目标
local linkTarget = ""
if linkParam and linkParam ~= "" then
linkTarget = "碧蓝航线:" .. linkParam
else
linkTarget = "碧蓝航线:" .. (name ~= "" and name or "")
end
-- 颜色/背景
if name ~= "指挥官" then
rarity = frame:expandTemplate{ title = "碧蓝航线稀有度", args = { [1] = name } }
else
rarity = "0"
end
local border = color_map[rarity] or "fff"
local bg = bg_map[rarity] or "#fff"
-- 开始构造 wikitext(保持与原模板外观一致)
local parts = {}
-- 外层 span(保留 css 参数)
if css and css ~= "" then
table.insert(parts, string.format('<span class="Azur-RoundIcon" style="%s">', mw.text.nowiki(css)))
else
table.insert(parts, '<span class="Azur-RoundIcon">')
end
-- 外围容器(azur-item-outer)—— 使用 math.floor(size) 确保整数 px
local outer_style = string.format("width:%dpx;height:%dpx;border-color:#%s;background-image:%s",
math.floor(size), math.floor(size), border, bg)
table.insert(parts, string.format('<span class="azur-item-outer" style="%s">', outer_style))
-- 使用 frame:expandTemplate 调用 FileLink 模板(正确形式)
local filelink = frame:expandTemplate{
title = "FileLink",
args = {
check = tostring(isnav or ""),
[1] = tostring(fileName or ""),
size = tostring(math.floor(size)) .. "px",
link = tostring(linkTarget or ""),
desc = tostring(name or "")
}
}
table.insert(parts, filelink)
table.insert(parts, '</span>') -- 关闭 azur-item-outer
-- 数量角标
if num and num ~= "" then
local bottom = math.floor(size * 0.04)
local font = math.floor(size * 16 / 75)
local count_w = string.format(
'<span class="azur-item-count" style="bottom:%dpx;right:%dpx;font-size:%dpx">%s</span>',
bottom, bottom, font, mw.text.nowiki(num)
)
table.insert(parts, count_w)
end
-- dt 标签:使用 frame:expandTemplate 展开碧蓝航线标签模板
if dt and dt ~= "" then
local dt_expanded = frame:expandTemplate{
title = "碧蓝航线标签",
args = { [1] = tostring(dt) }
}
local dt_w = string.format(
'<span style="position:absolute;top:-3px;white-space:nowrap;color:#000!important;font-weight:bold;font-size:small;left:0;right:0;text-align:center">%s</span>',
dt_expanded
)
table.insert(parts, dt_w)
end
table.insert(parts, '</span>') -- 关闭 Azur-RoundIcon
return table.concat(parts)
end
return p