打开/关闭搜索
搜索
打开/关闭菜单
5
6
1
403
夜幕之下
导航
首页
最近更改
随机页面
MediaWiki帮助
特殊页面
上传文件
打开/关闭外观设置菜单
通知
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。
user-interface-preferences
个人工具
创建账号
登录
查看“︁模块:CardData”︁的源代码
来自夜幕之下
查看
阅读
查看源代码
查看历史
associated-pages
模块
讨论
更多操作
←
模块:CardData
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
管理员
您可以查看和复制此页面的源代码。
-- Module:CardData -- 用法:{{#invoke:CardData|render|复仇童谣}} local p = {} local function val(v, fallback) 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 local function parseJson(str) if not str or str == "" then return nil end local ok, result = pcall(mw.text.jsonDecode, str) if ok then return result else return nil end end local function makeTitle(titleText, subtitleText, extraClass) local div = mw.html.create("div") :addClass("card_content-item-title") :addClass("card_content-item-title--mt") if extraClass then div:addClass(extraClass) end div:wikitext(titleText) div:tag("span"):addClass("card_content-item-subtitle"):wikitext(subtitleText) return div end local function makeHr(extraClass) local div = mw.html.create("div"):addClass("card_content-item-hr") if extraClass then div:addClass(extraClass) end return div end -- 单条属性行:图标 + 标签 + 值 local function makeAttrRow(label, value) local item = mw.html.create("div"):addClass("card_content_attribute-item") local titleDiv = item:tag("div"):addClass("card_content_attribute-title") titleDiv:tag("div"):addClass("card_content_attribute-icon") titleDiv:tag("div"):wikitext(" " .. label) item:tag("div"):wikitext(value or "—") return item end -- 信息栏:稀有度 + 四维 local function makeInfoSection(intel, supply, execute, strategy, rarity) local infoDiv = mw.html.create("div"):addClass("card_content_info") local rarityItem = infoDiv:tag("div"):addClass("card_content_info-item") rarityItem:tag("div"):wikitext("稀有度") rarityItem:tag("div"):wikitext(rarityStars(rarity)) local dims = { { label = "情报", value = intel }, { label = "物资", value = supply }, { label = "执行", value = execute }, { label = "策略", value = strategy }, } for _, dim in ipairs(dims) do local item = infoDiv:tag("div"):addClass("card_content_info-item") item:tag("div"):wikitext(dim.label) local n = tonumber(dim.value) item:tag("div"):wikitext(n and ("※" .. n) or "—") end return infoDiv end local function makeTriggerLabel(triggerType, triggerValue) local span = mw.html.create("span"):addClass("card_content_skill-meta-val") if triggerType == "normal_attack" then span:wikitext("每进行") span:tag("span"):addClass("card_accent"):wikitext(tostring(triggerValue or "?")) span:wikitext("次普攻") else span:wikitext(val(triggerType)) end return span end local function makeTagsRow(tagsJson) local div = mw.html.create("div"):addClass("card_content_skill-tags") local tags = parseJson(tagsJson) if tags and type(tags) == "table" then for _, tag in ipairs(tags) do div:tag("div"):addClass("card_content_skill-tag"):wikitext(tag) end end return div end local function makeUpgradeTable(levelsJson) local wrap = mw.html.create("div"):addClass("card_content_skill-upgrade") local rows = parseJson(levelsJson) if not rows or type(rows) ~= "table" or #rows == 0 then return wrap end local maxCols = 0 for _, row in ipairs(rows) do if type(row.levels) == "table" and #row.levels > maxCols then maxCols = #row.levels end end local DATA_COLS, gridClass if maxCols > 8 then DATA_COLS = 9 gridClass = "card_content_skill-upgrade-grid card_content_skill-upgrade-grid--10" else DATA_COLS = 8 gridClass = "card_content_skill-upgrade-grid" end local grid = wrap:tag("div"):addClass(gridClass) grid:tag("div") for i = 2, DATA_COLS + 1 do grid:tag("div"):addClass("card_content_skill-upgrade-lv"):wikitext(tostring(i)) end for idx, row in ipairs(rows) do local labelCell = grid:tag("div"):addClass("card_content_skill-upgrade-row-label") labelCell:tag("span"):addClass("card_content_skill-upgrade-badge"):wikitext(tostring(idx)) labelCell:tag("span"):addClass("card_content_skill-upgrade-badge-text"):wikitext(val(row.name, "")) labelCell:tag("span"):addClass("card_content_skill-upgrade-arrow"):wikitext("→") local levels = (type(row.levels) == "table") and row.levels or {} for col = 1, DATA_COLS do local v = levels[col] local cell = grid:tag("div"):addClass("card_content_skill-upgrade-val") if v == nil or v == "" then cell:addClass("card_content_skill-upgrade-val--null"):wikitext("—") else cell:addClass("card_accent"):wikitext(tostring(v)) end end end return wrap end local function makeSkillCard(skillData, skillType) local card = mw.html.create("div"):addClass("card_content_skill-card") local left = card:tag("div"):addClass("card_content_skill-left") local titleRow = left:tag("div"):addClass("card_content_skill-title") titleRow:tag("div"):addClass("card_content_skill-icon") local titleText = titleRow:tag("div"):addClass("card_content_skill-title-text") local nameRow = titleText:tag("div") nameRow:tag("span"):addClass("card_content_skill-name"):wikitext(val(skillData.name)) nameRow:tag("span"):addClass("card_content_skill-type card_accent--type") :wikitext("「" .. val(skillData.type) .. "」") local metaRow = titleText:tag("div"):addClass("card_content_skill-meta") if skillType == "normal_attack" then metaRow:wikitext("使用武器 ") metaRow:tag("span"):addClass("card_content_skill-meta-val card_accent"):wikitext(val(skillData.weapon)) elseif skillType == "passive" then metaRow:wikitext("触发条件 ") metaRow:node(makeTriggerLabel(skillData.trigger_type, skillData.trigger_value)) elseif skillType == "ultimate" then metaRow:wikitext("欲火消耗 ") metaRow:tag("span"):addClass("card_content_skill-meta-val") :tag("span"):addClass("card_accent"):wikitext(val(skillData.desire_cost)) end if skillType == "passive" or skillType == "ultimate" then left:node(makeTagsRow(skillData.tags)) end left:tag("div"):addClass("card_content_skill_effect"):wikitext(val(skillData.description)) card:node(makeUpgradeTable(skillData.levels)) return card end local function makeFeatList(stagesJson) local ul = mw.html.create("ul"):addClass("card_content_feat-ul") local stages = parseJson(stagesJson) if not stages or type(stages) ~= "table" then ul:tag("li"):wikitext("—") return ul end for _, stage in ipairs(stages) do local li = ul:tag("li"):addClass("card_content_feat-list") local row = li:tag("div"):addClass("card_content_feat-row") local sw = row:tag("div"):addClass("card_content_feat-stage-wrap") sw:tag("p"):tag("span"):addClass("card_content_feat-stage"):wikitext("STAGE") sw:tag("div"):addClass("card_content_feat-number") :wikitext(string.format("%02d", stage.stage or 0)) local rd = row:tag("div") if stage.value and type(stage.value) == "table" then for _, v in ipairs(stage.value) do if v.description then rd:tag("span"):addClass("card_accent"):wikitext(v.description) rd:tag("br") end end end if stage.stat_boosts and type(stage.stat_boosts) == "table" then for _, boost in ipairs(stage.stat_boosts) do rd:wikitext((boost.type or "") .. "提升" .. (boost.value or "")) end end if stage.extra_name then rd:tag("span"):addClass("card_content_feat-stage-cn") :wikitext("「" .. stage.extra_name .. "」") end end return ul end local function makeStoryTimeline(stories, cardTitle) local timeline = mw.html.create("div") :addClass("card_timeline card_content_story-timeline") timeline:tag("div"):addClass("card_timeline-line") if not stories or type(stories) ~= "table" or #stories == 0 then timeline:tag("div"):addClass("card_timeline-item"):wikitext("(小传数据待补充)") return timeline end local romans = { "Ⅰ", "Ⅱ", "Ⅲ", "Ⅳ", "Ⅴ" } local unlockLevels = { "Lv.20 解锁", "Lv.40 解锁", "Lv.60 解锁", "Lv.80 解锁", "Lv.100 解锁" } for idx, chapter in ipairs(stories) do local item = timeline:tag("div"):addClass("card_timeline-item") if idx == #stories then item:addClass("card_timeline-item--last") end item:tag("div"):addClass("card_timeline-dot") item:tag("div"):addClass("card_timeline-unlock") :wikitext(unlockLevels[idx] or ("Lv." .. (idx * 20) .. " 解锁")) local titleDiv = item:tag("div"):addClass("card_timeline-title") titleDiv:tag("span"):addClass("card_timeline-numeral"):wikitext(romans[idx] or tostring(idx)) titleDiv:tag("span"):addClass("card_timeline-chapter"):wikitext(cardTitle or "") titleDiv:tag("span"):addClass("card_timeline-label"):wikitext("/ Story") local bodyDiv = item:tag("div"):addClass("card_timeline-body") local text = chapter.text or "" if text ~= "" then text = text:gsub("\r\n", "\n") local paragraphs = mw.text.split(text, "\n+") for _, para in ipairs(paragraphs) do para = mw.text.trim(para) if para ~= "" then bodyDiv:tag("p"):wikitext(para) end end end 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">错误:请提供卡片名称,例如 {{#invoke:CardData|render|复仇童谣}}</span>' end local encodedName = mw.uri.encode(name, "QUERY") local apiUrl = "https://data.saltedkiss.org/items/cards" .. "?fields=stylename,rarity,character.name,profession.name,desire.name" .. ",intel,supply,execute,strategy" .. ",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.text" .. "&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">⚠ 无法加载卡片数据:' .. mw.text.nowiki(name) .. '(response=' .. mw.text.nowiki(rawResponse) .. ')</span>' end local charData = card.character or {} local profData = card.profession or {} local desireData = card.desire or {} local skillNA = card.skill_normal_attack or {} local skillPA = card.skill_passive or {} local skillUL = card.skill_ultimate or {} local stories = card.stories or {} local featsStagesJson = "[]" if card.feats and type(card.feats) == "table" and card.feats[1] then local sr = card.feats[1].stages featsStagesJson = type(sr) == "table" and mw.text.jsonEncode(sr) or type(sr) == "string" and sr or "[]" end local function levelsToJson(skill) if not skill.levels then return "[]" end if type(skill.levels) == "string" then return skill.levels end if type(skill.levels) == "table" then return mw.text.jsonEncode(skill.levels) end return "[]" end skillNA.levels = levelsToJson(skillNA) skillPA.levels = levelsToJson(skillPA) skillUL.levels = levelsToJson(skillUL) local function tagsToJson(skill) if not skill.tags then return "[]" end if type(skill.tags) == "string" then return skill.tags end if type(skill.tags) == "table" then return mw.text.jsonEncode(skill.tags) end return "[]" end skillPA.tags = tagsToJson(skillPA) skillUL.tags = tagsToJson(skillUL) local rarity = tonumber(card.rarity) or 0 local stylename = val(card.stylename) local charName = val(charData.name) local profName = val(profData.name) local desName = val(desireData.name) local root = mw.html.create("div") :addClass("ron-card ron-card--rarity-" .. rarity) :attr("data-rarity", rarity) -- 全屏背景图,文件命名规则:卡面_卡面名.png root:tag("div"):addClass("card_fullscreen-img") :wikitext("[[文件:卡面_" .. stylename .. ".png]]") root:tag("div"):addClass("card_hero"):css("height", "100vh") local layout = root:tag("div"):addClass("card_content-container") :tag("div"):addClass("card_content-background") :tag("div"):addClass("card_content-inner") :tag("div"):addClass("card_content card_content--layout") -- 左栏 local leftCol = layout:tag("div"):addClass("card_content_left") -- 卡名 local nc = leftCol:tag("div"):addClass("card_content_name-container") local nr = nc:tag("div"):addClass("card_content_name-row") nr:tag("div"):addClass("card_content_name-icon") nr:tag("div"):addClass("card_content_name-classtext"):wikitext(profName) nr:tag("div"):addClass("card_content_name-icon card_content_name-icon--ml") nr:tag("div"):addClass("card_content_name-classtext"):wikitext(desName) local nt = nc:tag("div"):addClass("card_content_name-text") nt:wikitext(stylename .. " ") nt:tag("span"):addClass("card_accent"):wikitext("·") nt:wikitext(" " .. charName) -- 信息(稀有度 + 四维) leftCol:node(makeTitle("信息", "Info")) leftCol:node(makeHr()) leftCol:node(makeInfoSection(card.intel, card.supply, card.execute, card.strategy, rarity)) -- 等级 100 属性 leftCol:node(makeTitle("等级 100", "Lv. Max")) leftCol:node(makeHr()) leftCol:node(makeAttrRow("生命", "—")) leftCol:node(makeAttrRow("攻击", "—")) leftCol:node(makeAttrRow("防御", "—")) leftCol:node(makeAttrRow("暴击率", "—")) leftCol:node(makeAttrRow("暴击伤害", "—")) -- 映像 leftCol:node(makeTitle("映像", "Reflection")) leftCol:node(makeHr()) leftCol:node(makeAttrRow("固定攻击", "—")) leftCol:node(makeAttrRow("固定生命", "—")) leftCol:node(makeAttrRow("伤害加成", "—")) -- 认知 leftCol:node(makeTitle("认知", "Cognition")) leftCol:node(makeHr()) leftCol:tag("div"):addClass("card_content_attribute-item"):wikitext("(数据待补充)") -- 右栏 local rightCol = layout:tag("div"):addClass("card_content_right") rightCol:node(makeTitle("战斗技能", "Tactical")) rightCol:node(makeHr("card_content-item-hr--mb12")) rightCol:node(makeSkillCard(skillNA, "normal_attack")) rightCol:tag("div"):addClass("card_content_skill-gap") rightCol:node(makeSkillCard(skillPA, "passive")) rightCol:tag("div"):addClass("card_content_skill-gap") rightCol:node(makeSkillCard(skillUL, "ultimate")) rightCol:node(makeTitle("觉醒", "Feat")) rightCol:node(makeHr("card_content-item-hr--mb12")) rightCol:node(makeFeatList(featsStagesJson)) -- 小传 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")) storyLeft:tag("div"):addClass("card_content_story-toggle") :attr("data-collapsed", "false") :tag("span"):addClass("story-toggle-text"):wikitext("收起"):done() :tag("span"):addClass("story-toggle-icon"):wikitext("-") storyHeader:tag("div"):addClass("card_content_story-header-spacer") storyHeader:node(makeStoryTimeline(stories, stylename)) -- 邀约 rightCol:tag("div"):css("height", "12px"):css("width", "100%") rightCol:node(makeTitle("邀约", "Date")) rightCol:node(makeHr("card_content-item-hr--mb12")) rightCol:tag("div"):addClass("card_content_date") :tag("div"):addClass("card_content_date-track") :tag("ul"):addClass("card_content_date-list") :tag("li"):addClass("card_content_date-item"):wikitext("(邀约数据待补充)") return tostring(root) end return p
该页面嵌入的页面:
模块:CardData/doc
(
查看源代码
)
返回
模块:CardData
。
查看“︁模块:CardData”︁的源代码
来自夜幕之下