bugfix250107.1
通过 SULFUR.WIKI 可快速访问本维基!
全站通知:

模块:Data

来自火湖WIKI_BWIKI_哔哩哔哩
跳到导航 跳到搜索

JSON数据获取模块

⚠️模块尚处于测试阶段⚠️

待实现功能

  • 函数
    • (🚧)过滤:filter
    • (🚧)范围:limit
    • (🚧)格式:format
  • 其他
    • (🚧)属性设置

模块说明

这是一个通用的JSON数据获取模块,支持以下数据结构:

  • 对象(Object)
  • 数组(Array)
  • 嵌套结构(对象和数组的任意组合)

基本用法

[err] > type(data): TYPE IS[string]

参数说明

参数 必填 说明
数据页面名 要查询的主数据页面名称
路径 使用!分隔的多级路径

使用示例

示例1:获取数据页所有键

{{#invoke:Data|main|武器}}

输出:

.22 一枪一个,.308 洛库亚,.357 巴尔萨泽,.38 警枪,1889 马里奥,80 号台风,D4RT,M11A2 菲斯克,M182 皮埃尔燧发枪,M3 白蚁枪,P38 德克手枪,“校内高管”百连发,一次性手机,仲裁者 2 号,低温手榴弹,因帕拉格拉维塔,大杀器,奥古斯塔,守墓者,弗雷德号,怀亚特脉冲,攻坚 8 号,敢为人先,无名,星视双枪,木柄手榴弹,杜哈,极速线圈 X,死星 PG,毒药罐,沙罗曼隐蛇,波洛伊卡紧凑型,海豚 99,海豹突击 9 号,漂流木 9 号,灰马鬃剪,炸药,烈马 89 号,燃烧瓶,爱心罐,硫磺手榴弹,神经核心 F22,群攻 76,胁差,莫斯曼,菠萝手榴弹,裁缝精英 MKII,贝克 8 号,近炸地雷,闪曳,雪球,飞刀

示例2:获取特定对象键

{{#invoke:Data|main|武器|沙罗曼隐蛇}}

输出:

扩散,射速,弹速,后坐,名称,耐久,品质,子弹类型,尺寸,类型,重量,价格,伤害,弹匣容量,描述

示例3:获取嵌套值

{{#invoke:Data|main|武器|沙罗曼隐蛇!描述}}

输出:

将不同颜色的部件混搭在一起,虽然这一设计的初衷是为了美观,但沙罗曼隐蛇因绝佳的隐匿性,被多次偷偷带入高度戒备的地点而饱受秘密机构的青睐。

错误处理

错误情况 示例 输出
未提供数据页 [err] > data_page_name: NOT PROVIDED[nil] [err] > data_page_name: NOT PROVIDED[nil]
数据页不存在 [err] > type(data): TYPE IS[string] [err] > data_page_list: NOT FOUND[不存在的页面]
路径不存在 nil

数据结构要求

主数据页(如"数据:首页")格式:

{
    "武器": "数据:武器",
    "配件": "数据:配件",
}

数据:武器数据页格式:

{
"沙罗曼隐蛇": {
        "名称": {
            "中": "沙罗曼隐蛇",
            "英": "Salamander"
        },
        "描述": "将不同颜色的部件混搭在一起,虽然这一设计的初衷是为了美观,但沙罗曼隐蛇因绝佳的隐匿性,被多次偷偷带入高度戒备的地点而饱受秘密机构的青睐。",
        "品质": "Rare",
        "类型": "手枪",
        "子弹类型": "7.62mm",
        "伤害": 120,
        "射速": 170,
        "弹匣容量": 8,
        "扩散": 2,
        "弹速": 750,
        "后坐": 15,
        "重量": 5,
        "耐久": 1600,
        "尺寸": [
            3,
            2
        ],
        "价格": 5000
    }
}

注意事项

  • 数组索引从1开始
  • ?_开头的键会被自动过滤
  • 模块使用缓存优化,适合处理大型数据(易脚本超时,待优化)
  • 路径区分大小写

local getArgs = require('Module:Arguments').getArgs
local p = {}
local cache = require 'mw.ext.LuaCache'

-- 缓存配置
local CACHE_PREFIX = "Cache:"  -- 缓存键前缀
local CACHE_EXPIRE = 3600  -- 默认缓存时间(秒,1小时)

function p.main(frame)
    local args = getArgs(frame)
    return p._main(args)
end

function p._main(args)
    local DATAPAGE = "数据:首页"
    
    local data_page_name = args[1]
    if not data_page_name or data_page_name == "" then
        return "[err] > data_page_name: NOT PROVIDED[" ..tostring(data_page_name).. "]"
    end
    
    -- 尝试从缓存获取数据
    local cacheKey = CACHE_PREFIX .. data_page_name
    local data = cache.get(cacheKey)
    
    if data == nil then
        -- 缓存未命中,从原始数据源获取
        data = p.getDataPage(data_page_name, DATAPAGE)
        if type(data) == "string" then
            return "[err] > type(data): TYPE IS[string]"
        end
        -- 将数据存入缓存
        cache.set(cacheKey, data, CACHE_EXPIRE)
    end
    
    local data_key_name = args[2]
    if data_key_name then
        local data_key_name = mw.text.split(data_key_name, "!")
        
        -- 为嵌套数据查询创建缓存键
        local nestedCacheKey = cacheKey .. ":" .. table.concat(data_key_name, "!")
        local data_values = cache.get(nestedCacheKey)
        
        if data_values == nil then
            data_values = p.getDataValues(data, data_key_name)
            if data_values ~= nil then
                cache.set(nestedCacheKey, data_values, CACHE_EXPIRE)
            end
        end
        
        if type(data_values) == "table" then
            local keys = ""
            for key, _ in pairs(data_values) do
                if not tostring(key):match("^%?_") then
                    keys = keys..key..","
                end
            end
            return keys:sub(1, -2)
        end
        return data_values
    else
        -- 缓存键列表
        local keysCacheKey = cacheKey .. ":keys"
        local data_keys = cache.get(keysCacheKey)
        
        if data_keys == nil then
            data_keys = p.getDataKeys(data)
            if type(data_keys) == "table" then
                cache.set(keysCacheKey, data_keys, CACHE_EXPIRE)
            end
        end
        
        if type(data_keys) == "table" then
            return table.concat(data_keys, ",")
        end
        return mw.text.jsonEncode(data_keys)
    end
    
    -- 以下功能暂未实现
    -- local funcFilter = args["filter"]
    -- local funcFormat = args["format"]
    -- local funcLimit = args["limit"]
end

function p.getDataPage(data_page_name, DATAPAGE)
    -- 缓存数据页列表
    local listCacheKey = CACHE_PREFIX .. "data_page_list"
    local data_page_list = cache.get(listCacheKey)
    
    if data_page_list == nil then
        data_page_list = mw.text.jsonDecode(mw.title.new(DATAPAGE):getContent())
        if not data_page_list then
            return "[err] > data_page_list"
        end
        cache.set(listCacheKey, data_page_list, CACHE_EXPIRE)
    end
    
    local data_page = data_page_list[data_page_name]
    if not data_page then
        return "[err] > data_page_list: NOT FOUND[" ..tostring(data_page_name).. "]"
    end
    
    -- 缓存单个数据页内容
    local pageCacheKey = CACHE_PREFIX .. "page:" .. data_page
    local data = cache.get(pageCacheKey)
    
    if data == nil then
        data = mw.text.jsonDecode(mw.title.new(data_page):getContent())
        if not data then
            return "[err] > data_page"
        end
        cache.set(pageCacheKey, data, CACHE_EXPIRE)
    end
    
    return data
end

function p.getDataKeys(data)
    local keys = {}
    for key, _ in pairs(data) do
        if not tostring(key):match("^%?_") then
            table.insert(keys, key)
        end
    end
    
    table.sort(keys)
    
    return keys
end

function p.getDataValues(data, data_keys)
    local values = data
    for _, key in ipairs(data_keys) do
        if tonumber(key) then
            key = tonumber(key)
        end
        if type(values) == "table" and values[key] then
            values = values[key]
        else
            return nil
        end
    end

    if type(values) == "table" and #values > 0 then
        if type(values[1]) == "table" then
            return #values
        else
            return table.concat(values, ",")
        end
    end
    
    return values
end

function p.getDataLimit(data, limit)
    -- 待实现
end

return p