本WIKI由旅行者酒馆于2020年03月14日申请开通,内容按CC BY-NC-SA 4.0协议提供,编辑权限开放。感谢 大猫雷恩 对WIKI设计支持,期待更多能人异士加入原神WIKI。
免责声明 • 反馈留言 • 交流群:1018709157
原神WIKI五周年啦!
bugfix250107.1

全站通知:

模块:原神WIKI导航

来自原神WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

此模块的文档可以在模块:原神WIKI导航/doc创建

local p = {}

--------------------------------------------------
--	公开函数
--------------------------------------------------

p['生成导航栏'] = function(frame)
    local moshi = frame.args['模式'] or ''
    local currentPage = mw.title.getCurrentTitle().text

    -- 获取当前日期
    local currentDate = os.date('%Y年%m月%d日')

    -- 获取当前版本
    local currentVersion = frame.args['当前版本'] or ''

    -- 查询角色数据
    local roleData = callAskQuery('[[分类:角色]][[实装日期::<' .. currentDate .. ']]', {
        '?元素属性',
        '?角色显示名',
        '?稀有度',
        link = 'none',
        sort = '稀有度,实装日期,TAG',
        order = 'desc,desc,asc',
        headers = 'hide',
        format = 'table',
        named_args = 1,
        limit = 1000
    })

    -- 查询武器数据
    local weaponData = callAskQuery('[[分类:武器]][[实装版本::<' .. currentVersion .. ']]', {
        '?类型',
        '?稀有度',
        link = 'none',
        sort = '稀有度,实装版本,TAG',
        order = 'desc,desc,asc',
        headers = 'hide',
        format = 'table',
        named_args = 1,
        limit = 1000
    })

    -- 查询圣遗物数据
    local artifactData = callAskQuery('[[分类:圣遗物套装]][[实装版本::<' .. currentVersion .. ']]', {
        '?最高稀有度',
        link = 'none',
        sort = '最高稀有度,实装版本,名称',
        order = 'desc,desc,desc',
        headers = 'hide',
        format = 'table',
        named_args = 1,
        limit = 1000
    })

    -- 生成导航栏HTML
    local navHtml = generateNavHtml(roleData, weaponData, artifactData, currentPage, moshi)

    return navHtml
end

p['生成角色导航栏'] = function(frame)
    local moshi = frame.args['模式'] or ''
    local currentPage = mw.title.getCurrentTitle().text

    -- 获取当前日期
    local currentDate = os.date('%Y年%m月%d日')

    -- 查询角色数据
    local roleData = callAskQuery('[[分类:角色]][[实装日期::<' .. currentDate .. ']]', {
        '?元素属性',
        '?角色显示名',
        '?稀有度',
        link = 'none',
        sort = '稀有度,实装日期,TAG',
        order = 'desc,desc,asc',
        headers = 'hide',
        format = 'table',
        named_args = 1,
        limit = 1000
    })

    -- 生成角色导航栏HTML
    local navHtml = generateRoleNavHtml(roleData, currentPage, moshi)

    return navHtml
end

--------------------------------------------------
--	主要过程
--------------------------------------------------

-- 获取当前日期
--function getCurrentDate()
    --local year = os.date('%Y')  -- 获取当前年份
    --local month = os.date('%m') -- 获取当前月份
    --local day = os.date('%d')   -- 获取当前日期
    --return year .. '年' .. month .. '月' .. day .. '日'
--end

-- 生成导航栏HTML
function generateNavHtml(roleData, weaponData, artifactData, currentPage, moshi)
    local html = '<div id="ys-nav-frame">'
    html = html .. '<div class="ys-nav-title">原神WIKI导航</div>'
    html = html .. '<div class="main-line-wrap" style="width:100%">'
    html = html .. '<div class="resp-tabs" style="border-spacing: 0px;">'
    html = html .. '<ul class="resp-tabs-list clearfix" style="display:flex; flex-wrap:wrap;margin-left:0;margin-top:0px">'

    -- 生成角色选项卡
    local roleTypes = {'火', '水', '风', '雷', '草', '冰', '岩'}
    local isCurrentPageFound = false
    for _, type in ipairs(roleTypes) do
        local active = isActive(currentPage, roleData, type, '角色', moshi)
        if active then isCurrentPageFound = true end
        html = html .. generateTabItem('角色', type, active)
    end

    -- 生成武器选项卡
    local weaponTypes = {'单手剑', '双手剑', '长柄武器', '法器', '弓'}
    for _, type in ipairs(weaponTypes) do
        local active = isActive(currentPage, weaponData, type, '武器', moshi)
        if active then isCurrentPageFound = true end
        html = html .. generateTabItem('武器', type, active)
    end

    -- 生成圣遗物选项卡
    local active = isActive(currentPage, artifactData, nil, '圣遗物', moshi)
    if active then isCurrentPageFound = true end
    html = html .. generateTabItem('圣遗物', nil, active)

    html = html .. '</ul>'
    html = html .. '<div class="resp-tabs-container">'

    -- 生成角色内容
    for _, type in ipairs(roleTypes) do
        local active = isActive(currentPage, roleData, type, '角色', moshi)
        html = html .. generateTabContent(roleData, type, active, '角色', moshi)
    end

    -- 生成武器内容
    for _, type in ipairs(weaponTypes) do
        local active = isActive(currentPage, weaponData, type, '武器', moshi)
        html = html .. generateTabContent(weaponData, type, active, '武器', moshi)
    end

    -- 生成圣遗物内容
    local active = isActive(currentPage, artifactData, nil, '圣遗物', moshi)
    html = html .. generateTabContent(artifactData, nil, active, '圣遗物', moshi)

    html = html .. '</div></div></div></div>'

    -- 如果当前页面不在数据库中,默认激活第一个选项
    if not isCurrentPageFound then
        html = setDefaultActive(html)
    end

    return html
end

-- 生成角色导航栏HTML
function generateRoleNavHtml(roleData, currentPage, moshi)
    local html = '<div id="ys-nav-frame" class="navigation-not-searchable">'
    html = html .. '<div class="ys-nav-title">原神WIKI角色攻略导航</div>'
    html = html .. '<div class="main-line-wrap" style="width:100%">'
    html = html .. '<div class="resp-tabs" style="border-spacing: 0px;">'
    html = html .. '<ul class="resp-tabs-list clearfix" style="display:flex; flex-wrap:wrap;margin-left:0;margin-top:0px">'

    -- 生成角色选项卡
    local roleTypes = {'火', '水', '风', '雷', '草', '冰', '岩'}
    local isCurrentPageFound = false
    for _, type in ipairs(roleTypes) do
        local active = isActive(currentPage, roleData, type, '角色', moshi)
        if active then isCurrentPageFound = true end
        html = html .. generateTabItem('角色', type, active)
    end

    html = html .. '</ul>'
    html = html .. '<div class="resp-tabs-container">'

    -- 生成角色内容
    for _, type in ipairs(roleTypes) do
        local active = isActive(currentPage, roleData, type, '角色', moshi)
        html = html .. generateTabContent(roleData, type, active, '角色', moshi)
    end

    html = html .. '</div></div></div></div>'

    -- 如果当前页面不在数据库中,默认激活第一个选项
    if not isCurrentPageFound then
        html = setDefaultActive(html)
    end

    return html
end

-- 设置默认激活第一个选项
function setDefaultActive(html)
    -- 激活第一个选项卡
    html = html:gsub('(<li class="bili%-list%-style")', '<li class="bili-list-style active"', 1)
    -- 显示第一个内容区域
    html = html:gsub('(<div class="resp%-tab%-content")', '<div class="resp-tab-content" style="display:block;"', 1)
    return html
end

-- 生成选项卡项
function generateTabItem(category, type, active)
    local class = 'bili-list-style'
    if active then
        class = class .. ' active'
    end

    local tabContent
    if category == '角色' then
        tabContent = string.format(
            '[[文件:选项装饰1.png|9px|link=]] &nbsp; [[文件:元素%s.png|20px|link=]] %s &nbsp; [[文件:选项装饰1.png|9px|link=]]',
            type, type
        )
    elseif category == '武器' then
        tabContent = string.format(
            '[[文件:选项装饰1.png|9px|link=]] &nbsp; %s &nbsp; [[文件:选项装饰1.png|9px|link=]]',
            type
        )
    elseif category == '圣遗物' then
        tabContent = '[[文件:选项装饰1.png|9px|link=]] &nbsp; 圣遗物 &nbsp; [[文件:选项装饰1.png|9px|link=]]'
    end

    return string.format('<li class="%s"><span class="tab-panel">%s</span></li>', class, tabContent)
end

-- 生成选项卡内容
function generateTabContent(data, type, active, category, moshi)
    local style = active and 'style="display:block;"' or ''
    local content = string.format('<div class="resp-tab-content" %s><div class="resp-tab-case">', style)

    for _, item in ipairs(data) do
        local shouldAdd = false
        if category == '角色' and item['元素属性'] == type then
            shouldAdd = true
        elseif category == '武器' and item['类型'] == type then
            shouldAdd = true
        elseif category == '圣遗物' and item['最高稀有度'] then
            shouldAdd = true
        end

        if shouldAdd then
            content = content .. generateItemHtml(item, category, moshi)
        end
    end

    content = content .. '<i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div>'
    return content
end

-- 生成单个项目HTML
function generateItemHtml(item, category, moshi)
    local rarity = item['稀有度'] or item['最高稀有度']
    local name = (item['角色显示名'] and item['角色显示名'] ~= '') and item['角色显示名'] or item[1]
    local imageLink = item[1]  -- 默认使用 item[1]

    if category == '角色' and moshi ~= '' then
        imageLink = item[1] .. '/' .. moshi
    end

    local imageFile

    -- 根据类型生成图片路径
    if category == '角色' then
        imageFile = '无背景-角色-' .. item[1] .. '.png'
    elseif category == '圣遗物' then
        imageFile = item[1] .. '生之花.png'
    else
        imageFile = item[1] .. '.png'
    end

    return string.format('<div class="item r%s">[[文件:%s|link=%s]]<div class="title">%s</div></div>', rarity, imageFile, imageLink, name)
end

-- 判断是否激活
function isActive(currentPage, data, type, category, moshi)
    for _, item in ipairs(data) do
        local name = item[1] -- 使用参数1作为名称
        if category == '角色' and moshi ~= '' then
            currentPage = currentPage:gsub('/' .. moshi, '')
        end
        if category == '角色' and item['元素属性'] == type and name == currentPage then
            return true
        elseif category == '武器' and item['类型'] == type and name == currentPage then
            return true
        elseif category == '圣遗物' and name == currentPage then
            return true
        end
    end
    return false
end

-- 调用#ask语义查询,并将结果解析为table
function callAskQuery(title, args)
    local frame = mw.getCurrentFrame()
    args.format = 'table'
    local html = frame:callParserFunction('#ask:' .. title, args)

    -- 返回解析结果的key
    local keys = {}
    keys[1] = ''  -- #ask的参数#1是title
    for i, v in ipairs(args) do
        keys[i + 1] = mw.text.trim(v:sub(2))
    end

    local data = {}
    for tr in html:gmatch('<tr .-</tr>') do
        if tr:match('smwfooter') then break end

        local item = {}
        local i = 1  -- #1单元格是页面名称

        for td in tr:gmatch('<td.->(.-)</td>') do
            td = mw.text.trim(td)

            item[i] = td
            if keys[i] then item[keys[i]] = td end
            i = i + 1
        end

        table.insert(data, item)
    end

    return data
end

return p