打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:CardData:修订间差异

来自夜幕之下
Rin留言 | 贡献
无编辑摘要
标签已被回退
Rin留言 | 贡献
无编辑摘要
标签已被回退
第1行: 第1行:
-- Module:CardData
-- 用法:{{#invoke:CardData|render|复仇童谣}}
local p = {}
local p = {}


local function val(v, fallback)
local API = "https://data.saltedkiss.org/items/cards"
    if v == nil or v == "" then return fallback or "—" end
    return v
end
 
local function rarityStars(n)
    n = tonumber(n) or 0
    return string.rep("★", n)
end


-- 解析JSON
local function parseJson(str)
local function parseJson(str)
    if not str or str == "" then return nil end
     local ok, data = pcall(mw.text.jsonDecode, str)
     local ok, result = pcall(mw.text.jsonDecode, str)
     if ok then
     if ok then return result else return nil end
        return data
    end
    return nil
end
end


local function makeTitle(titleText, subtitleText, extraClass)
-- HTTP请求
     local div = mw.html.create("div")
local function request(url)
        :addClass("card_content-item-title")
     local res = mw.http.fetch(url)
        :addClass("card_content-item-title--mt")
     if res.status == 200 then
 
        return res.body
     if extraClass then div:addClass(extraClass) end
     end
 
     return nil
     div:wikitext(titleText)
    div:tag("span")
        :addClass("card_content-item-subtitle")
        :wikitext(subtitleText)
 
     return div
end
end


local function makeHr(extraClass)
function p.card(frame)
    local div = mw.html.create("div")
        :addClass("card_content-item-hr")


     if extraClass then div:addClass(extraClass) end
    local name = frame.args[1] or frame.args.name
     if not name then
        return "未提供角色名"
    end


     return div
     local fields = table.concat({
end
        "stylename",
 
        "stories.*",
local function makeStoryTimeline(stories, cardTitle)
        "stories.story.*"
 
    }, ",")
    local timeline = mw.html.create("div")
        :addClass("card_timeline card_content_story-timeline")


     timeline:tag("div")
     local url = API ..
         :addClass("card_timeline-line")
        "?fields=" .. mw.uri.encode(fields) ..
         "&filter[stylename][_eq]=" .. mw.uri.encode(name)


    -- 更安全获取 entry
     local raw = request(url)
     local entry
     if not raw then
     if type(stories) == "table" then
         return "API请求失败"
         for _,v in pairs(stories) do
            entry = v
            break
        end
     end
     end


     local chapters = entry and entry.story or {}
     local json = parseJson(raw)
 
     if not json or not json.data or not json.data[1] then
     if not chapters or type(chapters) ~= "table" then
         return "未获取到数据"
         chapters = {}
     end
     end


     if next(chapters) == nil then
     local card = json.data[1]
        timeline:tag("div")
            :addClass("card_timeline-item")
            :wikitext("(小传数据待补充)")
        return timeline
    end


     local romans = { "Ⅰ","Ⅱ","Ⅲ","Ⅳ","Ⅴ","Ⅵ","Ⅶ","Ⅷ" }
     local html = {}
    local unlockLevels = {
        "Lv.20 解锁",
        "Lv.40 解锁",
        "Lv.60 解锁",
        "Lv.80 解锁",
        "Lv.100 解锁"
    }


     local idx = 1
     table.insert(html, '<div class="card-story">')
    table.insert(html, '<h2>小传</h2>')


     for _, chapter in pairs(chapters) do
     if card.stories then


         local item = timeline:tag("div")
         for _,storyGroup in ipairs(card.stories) do
            :addClass("card_timeline-item")


        item:tag("div")
             if storyGroup.story then
             :addClass("card_timeline-dot")


        item:tag("div")
                for _,story in ipairs(storyGroup.story) do
            :addClass("card_timeline-unlock")
            :wikitext(unlockLevels[idx] or ("Lv."..(idx*20).." 解锁"))


        local titleDiv = item:tag("div")
                    if story.text then
            :addClass("card_timeline-title")


        titleDiv:tag("span")
                        local text = mw.text.nowiki(story.text)
            :addClass("card_timeline-numeral")
                        text = text:gsub("\n","<br>")
            :wikitext(romans[idx] or idx)


        titleDiv:tag("span")
                        table.insert(html,
            :addClass("card_timeline-chapter")
                            '<p class="story-text">' .. text .. '</p>'
            :wikitext(cardTitle or "")
                        )


        titleDiv:tag("span")
                    end
            :addClass("card_timeline-label")
            :wikitext("/ Story")


        local bodyDiv = item:tag("div")
            :addClass("card_timeline-body")
        local text = chapter.text or ""
        if text ~= "" then
            local lines = mw.text.split(text,"\n")
            for i,line in ipairs(lines) do
                if line ~= "" then
                    bodyDiv:wikitext(line)
                end
                if i < #lines then
                    bodyDiv:tag("br")
                 end
                 end


第135行: 第80行:
         end
         end


        idx = idx + 1
     else
 
        table.insert(html, "<p>未获取到数据</p>")
     end
 
    return timeline
end
 
 
function p.render(frame)
 
    local name = mw.text.trim(frame.args[1] or frame.args.name or "")
 
    if name == "" then
        return '<span class="error">错误:请提供卡片名称</span>'
     end
     end


    table.insert(html, '</div>')


     -- 关键:stories.story.*
     return table.concat(html,"\n")
    local fields = table.concat({
 
        "stylename",
        "rarity",
 
        "character.name",
        "profession.name",
        "desire.name",
 
        "skill_normal_attack.name",
        "skill_normal_attack.type",
        "skill_normal_attack.weapon",
        "skill_normal_attack.description",
        "skill_normal_attack.levels.*",
 
        "skill_passive.name",
        "skill_passive.type",
        "skill_passive.trigger_type",
        "skill_passive.trigger_value",
        "skill_passive.tags",
        "skill_passive.description",
        "skill_passive.levels.*",
 
        "skill_ultimate.name",
        "skill_ultimate.type",
        "skill_ultimate.desire_cost",
        "skill_ultimate.tags",
        "skill_ultimate.description",
        "skill_ultimate.levels.*",
 
        "feats.stages",
 
        -- 修复 stories
        "stories.*",
        "stories.story.*"
 
    },",")
 
 
    local encodedName = mw.uri.encode(name,"QUERY")
 
    local apiUrl =
        "https://data.saltedkiss.org/items/cards"
        .. "?fields=" .. mw.uri.encode(fields,"QUERY")
        .. "&filter[stylename][_eq]=" .. encodedName
 
 
    local rawResponse = frame:preprocess(
        '{{#get_web_data:url='..apiUrl
        ..'|format=text|data=responseText=__text}}'
        ..'{{#external_value:responseText}}'
    )
 
    rawResponse = mw.text.trim(rawResponse or "")
 
    local parsed = parseJson(rawResponse)
 
    local card =
        parsed
        and type(parsed.data) == "table"
        and parsed.data[1]
        or nil
 
    if not card then
        return '<span class="error">⚠ 无法加载卡片数据</span>'
    end
 
 
    local stories = card.stories or {}
 
    local root = mw.html.create("div")
        :addClass("ron-card")
 
    local rightCol = root:tag("div")
        :addClass("card_content_right")
 
 
    local storySection = rightCol:tag("div")
        :addClass("card_content_story")
 
    local storyHeader = storySection:tag("div")
        :addClass("card_content_story-header")
 
    local storyLeft = storyHeader:tag("div")
        :addClass("card_content_story-header-left")
 
    storyLeft:node(makeTitle("小传","Story"))
 
    storyLeft:node(makeHr("card_content-item-hr--mb12"))
 
    storyHeader:node(
        makeStoryTimeline(stories,card.stylename)
    )
 
 
    return tostring(root)


end
end


return p
return p

2026年3月11日 (三) 21:17的版本

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

local p = {}

local API = "https://data.saltedkiss.org/items/cards"

-- 解析JSON
local function parseJson(str)
    local ok, data = pcall(mw.text.jsonDecode, str)
    if ok then
        return data
    end
    return nil
end

-- HTTP请求
local function request(url)
    local res = mw.http.fetch(url)
    if res.status == 200 then
        return res.body
    end
    return nil
end

function p.card(frame)

    local name = frame.args[1] or frame.args.name
    if not name then
        return "未提供角色名"
    end

    local fields = table.concat({
        "stylename",
        "stories.*",
        "stories.story.*"
    }, ",")

    local url = API ..
        "?fields=" .. mw.uri.encode(fields) ..
        "&filter[stylename][_eq]=" .. mw.uri.encode(name)

    local raw = request(url)
    if not raw then
        return "API请求失败"
    end

    local json = parseJson(raw)
    if not json or not json.data or not json.data[1] then
        return "未获取到数据"
    end

    local card = json.data[1]

    local html = {}

    table.insert(html, '<div class="card-story">')
    table.insert(html, '<h2>小传</h2>')

    if card.stories then

        for _,storyGroup in ipairs(card.stories) do

            if storyGroup.story then

                for _,story in ipairs(storyGroup.story) do

                    if story.text then

                        local text = mw.text.nowiki(story.text)
                        text = text:gsub("\n","<br>")

                        table.insert(html,
                            '<p class="story-text">' .. text .. '</p>'
                        )

                    end

                end

            end

        end

    else
        table.insert(html, "<p>未获取到数据</p>")
    end

    table.insert(html, '</div>')

    return table.concat(html,"\n")

end

return p