模块:少女前线信息
来自OGAS数据中枢
更多操作
此模块的文档可以在Module:少女前线信息/doc创建
local p = {}
local PIC_NAMES = { '普通', '重创', '和谐', '重创和谐' }
local INFO_FIELDS = {
{ 'tagline', '标题' },
{ '本名', '本名' },
{ '发色', '发色' },
{ '瞳色', '瞳色' },
{ '声优', '声优' },
{ '人设', '人设' },
{ '类型', '类型' },
{ '稀有度', '稀有度' },
{ '归属部门', '归属部门' },
{ '归属组织', '归属组织' },
{ '个人状态', '个人状态' },
}
-- 底部额外字段
local BOTTOM_FIELDS = {
{ '别名', '别名' },
{ '萌点', '萌点' },
{ '相关人士', '亲属/相关人士' },
}
-- HTML转义
local function escape(s)
if not s then return '' end
return s:gsub('&','&'):gsub('<','<'):gsub('>','>'):gsub('"','"')
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 html = {}
table.insert(html, '<div class="gf-switcher-overlay">')
table.insert(html, '<div class="gf-switcher-toggle" title="展开/隐藏菜单"></div>')
table.insert(html, '<div class="gf-switcher-list">')
for gi, group in ipairs(groups) do
local isFirst = gi == 1
table.insert(html, string.format(
'<div class="gf-group-btn%s" data-group="%d">%s</div>',
isFirst and ' active' or '',
gi,
escape(group.label)
))
table.insert(html, string.format(
'<div class="gf-variant-list%s" data-group="%d">',
isFirst and '' or ' collapsed',
gi
))
for vi, pic in ipairs(group.pics) do
local isFirstPic = vi == 1
table.insert(html, string.format(
'<div class="gf-switch-btn%s" data-group="%d" data-variant="%d" data-filename="%s">%s</div>',
isFirst and isFirstPic and ' active' or '',
gi,
vi,
escape(pic.file),
escape(pic.label)
))
end
table.insert(html, '</div>') -- gf-variant-list
end
table.insert(html, '</div>') -- gf-switcher-list
table.insert(html, '</div>') -- gf-switcher-overlay
return table.concat(html, '\n')
end
local function renderImageContainer(groups)
local html = {}
table.insert(html, '<div class="gf-image-container">')
local defaultFile = ''
if groups[1] and groups[1].pics[1] then
defaultFile = groups[1].pics[1].file
end
if defaultFile ~= '' then
table.insert(html, string.format(
'<div class="gf-main-img">[[File:%s|link=]]</div>',
defaultFile
))
end
table.insert(html, '<div class="gf-view-original" title="查看原图"></div>')
table.insert(html, '</div>') -- gf-image-container
return table.concat(html, '\n')
end
local function renderInfoTable(args, pageName, frame)
local html = {}
local title = args['名字'] or args['tagline'] or pageName or ''
table.insert(html, '<div class="gf-right-panel">')
table.insert(html, '<table class="gf-info-table">')
table.insert(html, string.format(
'<tr><th colspan="2" class="gf-header-row">%s</th></tr>',
escape(title)
))
for _, field in ipairs(INFO_FIELDS) do
local val = args[field[1]]
if val and val ~= '' then
table.insert(html, string.format(
'<tr><td class="gf-label">%s</td><td>%s</td></tr>',
escape(field[2]),
frame:preprocess(val)
))
end
end
table.insert(html, '</table>')
table.insert(html, '</div>') -- gf-right-panel
return table.concat(html, '\n')
end
local function renderBottomSection(args, frame)
local rows = {}
for _, field in ipairs(BOTTOM_FIELDS) do
local val = args[field[1]]
if val and val ~= '' then
table.insert(rows, string.format(
'<tr><td class="gf-label">%s</td><td>%s</td></tr>',
escape(field[2]),
frame:preprocess(val)
))
end
end
if #rows == 0 then return '' end
local html = {}
table.insert(html, '<div class="gf-bottom-section">')
table.insert(html, '<table class="gf-bottom-table">')
for _, row in ipairs(rows) do
table.insert(html, row)
end
table.insert(html, '</table>')
table.insert(html, '</div>')
return table.concat(html, '\n')
end
-- Cargo存储(如需启用,取消注释并补充表名/字段)
--[[
local function storeCargo(frame, args)
-- 示例:
-- frame:callParserFunction('#cargo_store', {
-- _table = 'GF_Characters',
-- 名字 = args['名字'] or '',
-- 声优 = args['声优'] or '',
-- 类型 = args['类型'] or '',
-- })
end
]]
local STYLES_PAGE = 'User:弃权者/Template:少女前线信息/styles.css'
local WIDGET_NAME = 'GF立绘切换'
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') .. '-' .. tostring(os.clock()):gsub('%.','')
local html = {}
table.insert(html, frame:extensionTag('templatestyles', '', { src = STYLES_PAGE }))
table.insert(html, frame:preprocess('{{#widget:' .. WIDGET_NAME .. '}}'))
table.insert(html, string.format('<div class="gf-infobox-new" id="%s">', escape(boxId)))
table.insert(html, '<div class="gf-left-panel">')
if #groups > 0 then
table.insert(html, renderSwitcher(groups))
table.insert(html, renderImageContainer(groups))
end
table.insert(html, '</div>') -- gf-left-panel
table.insert(html, renderInfoTable(args, pageName, frame))
table.insert(html, '</div>') -- gf-infobox-new
table.insert(html, renderBottomSection(args, frame))
-- storeCargo(frame, args)
return table.concat(html, '\n')
end
return p