模块:少女前线立绘
来自OGAS数据中枢
更多操作
此模块的文档可以在Module:少女前线立绘/doc创建
local p = {}
local PIC_NAMES = { '普通', '重创', '和谐', '重创和谐' }
local STYLES_PAGE = 'User:弃权者/Template:少女前线信息/styles.css'
local WIDGET_NAME = 'GF立绘切换'
local function escape(s)
if not s then return '' end
return s:gsub('&','&'):gsub('<','<'):gsub('>','>'):gsub('"','"')
end
local function getArg(args, key)
local v = args[key]
if v and v ~= '' then return v end
return nil
end
local function parseGroups(args)
local groups = {}
for i = 1, 30 do
local tag = args['tag' .. i]
if not tag or tag == '' then
if i > 3 then
local allEmpty = true
for k = i, math.min(i + 2, 30) do
if args['tag' .. k] and args['tag' .. k] ~= '' then
allEmpty = false; break
end
end
if allEmpty then break end
end
else
local groupType = args['type' .. i] or 'pic'
local pics = {}
for j = 1, 20 do
local picFile = args['tag' .. i .. 'pic' .. j]
if picFile and picFile ~= '' then
local label
if groupType == 'pic' then
label = PIC_NAMES[j] or ('差分' .. j)
else
label = args['tag' .. i .. 'name' .. j]
if not label or label == '' then label = '差分' .. j end
end
table.insert(pics, { file = picFile, label = label })
end
end
table.insert(groups, { label = tag, groupType = groupType, pics = pics })
end
end
return groups
end
local function renderSwitcher(groups)
local parts = {}
table.insert(parts, '<div class="gf-switcher-overlay">')
table.insert(parts, '<div class="gf-switcher-toggle" title="展开/隐藏菜单"></div>')
table.insert(parts, '<div class="gf-switcher-list">')
for gi, group in ipairs(groups) do
local isFirst = gi == 1
table.insert(parts, string.format(
'<div class="gf-group-btn%s" data-group="%d">%s</div>',
isFirst and ' active' or '', gi, escape(group.label)
))
table.insert(parts, string.format(
'<div class="gf-variant-list%s" data-group="%d">',
isFirst and '' or ' collapsed', gi
))
for vi, pic in ipairs(group.pics) do
table.insert(parts, string.format(
'<div class="gf-switch-btn%s" data-group="%d" data-variant="%d" data-filename="%s">%s</div>',
(isFirst and vi == 1) and ' active' or '',
gi, vi, escape(pic.file), escape(pic.label)
))
end
table.insert(parts, '</div>')
end
table.insert(parts, '</div>')
table.insert(parts, '</div>')
return table.concat(parts, '\n')
end
local function renderImageContainer(groups)
local parts = {}
table.insert(parts, '<div class="gf-image-container">')
if groups[1] and groups[1].pics[1] then
table.insert(parts, string.format(
'<div class="gf-main-img">[[File:%s|400px|link=|class=gf-img-inner]]</div>',
groups[1].pics[1].file
))
end
table.insert(parts, '<div class="gf-controls">')
table.insert(parts, '<div class="gf-view-original" title="查看原图"></div>')
table.insert(parts, '</div>')
table.insert(parts, '</div>')
return table.concat(parts, '\n')
end
local function renderOverlay(args, frame)
local parts = {}
local argCV = getArg(args, '声优')
local argIllust = getArg(args, '人设')
local argRarity = getArg(args, '稀有度')
local argNo = getArg(args, '编号')
local argSubname = getArg(args, '本名')
local argTitle = getArg(args, '标题')
local argName = getArg(args, '名字')
local argType = getArg(args, '类型')
local argDept = getArg(args, '归属部门')
local argOrg = getArg(args, '归属组织')
local pageName = mw.title.getCurrentTitle().subpageText
table.insert(parts, '<div class="gf-info-overlay">')
if argCV or argIllust then
table.insert(parts, '<div class="gf-cv-block">')
if argCV then
table.insert(parts, string.format(
'<div class="gf-cv-row"><span class="gf-cv-label">CV</span><span class="gf-cv-value">%s</span></div>',
escape(argCV)
))
end
if argIllust then
table.insert(parts, string.format(
'<div class="gf-cv-row"><span class="gf-cv-label">Illustrator</span><span class="gf-cv-value">%s</span></div>',
escape(argIllust)
))
end
table.insert(parts, '</div>')
end
if argRarity then
local isMod = ''
if argNo then
isMod = frame:preprocess('{{#invoke:GfAvatarIndex|isMod|' .. argNo .. '}}')
end
local stars = frame:preprocess('{{User:弃权者/Template:少女前线稀有度|' .. argRarity .. '|' .. isMod .. '}}')
table.insert(parts, '<div class="gf-stars">' .. stars .. '</div>')
end
if argSubname then
table.insert(parts, '<div class="gf-subname">' .. escape(argSubname) .. '</div>')
end
local displayName = argTitle or argName or pageName
table.insert(parts, '<div class="gf-profile-wrap">')
table.insert(parts, '<div class="gf-name">' .. escape(displayName) .. '</div>')
table.insert(parts, '<div class="gf-profile-watermark">PROFILE</div>')
table.insert(parts, '</div>')
local typeMap = {
['突击步枪'] = 'AR', ['手枪'] = 'HG', ['步枪'] = 'RF',
['机枪'] = 'MG', ['霰弹枪'] = 'SG', ['冲锋枪'] = 'SMG'
}
if argType or argDept or argOrg then
table.insert(parts, '<div class="gf-bottom-info">')
if argType then
local rarity = argRarity or ''
local typeCode = typeMap[argType] or argType
local icon = frame:preprocess('{{GfTypeIcon|' .. typeCode .. '|' .. rarity .. '|60}}')
table.insert(parts, '<div class="gf-type-icon">' .. icon .. '</div>')
end
if argDept or argOrg then
table.insert(parts, '<div class="gf-affiliation">')
if argDept then
table.insert(parts, '<div class="gf-affil-row">' .. frame:preprocess(argDept) .. '</div>')
end
if argOrg then
table.insert(parts, '<div class="gf-affil-row">' .. frame:preprocess(argOrg) .. '</div>')
end
table.insert(parts, '</div>')
end
table.insert(parts, '</div>')
end
table.insert(parts, '</div>')
return table.concat(parts, '\n')
end
function p.main(frame)
local args = frame:getParent().args
local pageName = mw.title.getCurrentTitle().subpageText
local groups = parseGroups(args)
local boxId = 'gf-box-' .. mw.uri.encode(pageName, 'PATH')
local parts = {}
table.insert(parts, frame:extensionTag('templatestyles', '', { src = STYLES_PAGE }))
table.insert(parts, frame:preprocess('{{#widget:' .. WIDGET_NAME .. '}}'))
table.insert(parts, string.format('<div class="gf-infobox-new" id="%s">', escape(boxId)))
table.insert(parts, '<div class="gf-left-panel">')
if #groups > 0 then
table.insert(parts, renderImageContainer(groups))
table.insert(parts, renderSwitcher(groups))
end
table.insert(parts, renderOverlay(args, frame))
table.insert(parts, '</div>')
return table.concat(parts, '\n')
end
return p