模块:Db:修订间差异
MJ Hamster(留言 | 贡献) 小无编辑摘要 |
MJ Hamster(留言 | 贡献) 小无编辑摘要 |
||
| 第1行: | 第1行: | ||
local function GetValuesTable() | local function GetValuesTable() | ||
return mw.loadData('Module:db_song') | return mw.loadData('Module:db_song') | ||
end | end | ||
local function ValueFromValuesByKey(values, key) | local function ValueFromValuesByKey(values, key) | ||
if values and key then | if values and key then | ||
| 第69行: | 第10行: | ||
end | end | ||
-- | -- 格式化单个值的私有函数 (重点:确保此定义被包含) | ||
local | local function formatSingleValue(value, fieldType) | ||
-- | if value == nil then | ||
return i18n['none'] | |||
elseif type(value) == 'boolean' then | |||
return value and i18n['true'] or i18n['false'] | |||
-- 注意:这里调用了 p.valueMappingMethod,它在 p 被返回之前完成定义 | |||
elseif type(p.valueMappingMethod[fieldType]) == 'function' then | |||
return p.valueMappingMethod[fieldType](value) | |||
else | |||
return tostring(value) | |||
end | |||
end | |||
-- 4. 值格式化方法 (valueMappingMethod) | |||
p.valueMappingMethod = { | |||
['duration'] = (function (value) | ['duration'] = (function (value) | ||
if type(value) == 'number' then | if type(value) == 'number' then | ||
| 第80行: | 第34行: | ||
return value | return value | ||
end), | end), | ||
['artist'] = (function (value) | ['artist'] = (function (value) | ||
if type(value) == 'string' and value ~= '' then | if type(value) == 'string' and value ~= '' then | ||
| 第89行: | 第42行: | ||
} | } | ||
-- | -- [[------------------------------------------------------------------]] | ||
-- [[ 5. 外部调用函数 (p.*) ]] | |||
-- [[------------------------------------------------------------------]] | |||
-- p.value 函数体(调用 formatSingleValue) | |||
function p.value(f) | function p.value(f) | ||
local args = f | |||
local frame = mw.getCurrentFrame() | local frame = mw.getCurrentFrame() | ||
if f == frame then | if f == frame then | ||
| 第97行: | 第54行: | ||
end | end | ||
local argTargetName = mw.text.trim(args[1] or '' | local argTargetName = mw.text.trim(args[1] or '') | ||
local | local argTypeString = args.type | ||
local argNocat = args.nocat | local argNocat = args.nocat | ||
if not | if not argTypeString then | ||
return i18n['error_no_type'] | return i18n['error_no_type'] | ||
end | end | ||
local values = GetValuesTable() | local values = GetValuesTable() | ||
local songEntry = ValueFromValuesByKey(values, argTargetName) | local songEntry = ValueFromValuesByKey(values, argTargetName) | ||
if not songEntry then | if not songEntry then | ||
if not argNocat then | |||
local title = mw.title.getCurrentTitle() | |||
if title.namespace == 0 and not title.isSubpage then | |||
return '?' .. '[[Category:' .. string.format(i18n['category_missing_value'], '歌曲ID ' .. argTargetName) .. ']]' | |||
end | |||
end | |||
return i18n['none'] | return i18n['none'] | ||
end | end | ||
local fieldNames = mw.text.split(argTypeString, ',') | |||
local | local resultTable = {} | ||
for _, argType in ipairs(fieldNames) do | |||
argType = mw.text.trim(argType) | |||
local value = ValueFromValuesByKey(songEntry, argType) | |||
-- 调用本地函数 | |||
local formattedValue = formatSingleValue(value, argType) | |||
table.insert(resultTable, formattedValue) | |||
end | end | ||
return table.concat(resultTable, ' / ') | |||
end | end | ||
-- p.findKeysByValue 函数体 | |||
function p.findKeysByValue(f) | |||
local args = f | local args = f | ||
local frame = mw.getCurrentFrame() | local frame = mw.getCurrentFrame() | ||
| 第154行: | 第99行: | ||
local targetField = mw.text.trim(args.field or '') | local targetField = mw.text.trim(args.field or '') | ||
local targetValue = args.value | local targetValue = args.value | ||
if type(targetValue) == 'string' then | if type(targetValue) == 'string' then | ||
| 第160行: | 第104行: | ||
end | end | ||
if targetField == '' or targetValue == nil then | if targetField == '' or targetValue == nil then | ||
return i18n['error_find_keys_args'] | return i18n['error_find_keys_args'] | ||
end | end | ||
local songData = GetValuesTable() | local songData = GetValuesTable() | ||
local matchingKeys = {} | local matchingKeys = {} | ||
for songId, songEntry in pairs(songData) do | for songId, songEntry in pairs(songData) do | ||
local currentValue = ValueFromValuesByKey(songEntry, targetField) | local currentValue = ValueFromValuesByKey(songEntry, targetField) | ||
if currentValue == targetValue then | if currentValue == targetValue then | ||
table.insert(matchingKeys, songId) | table.insert(matchingKeys, songId) | ||
| 第180行: | 第119行: | ||
end | end | ||
table.sort(matchingKeys) | table.sort(matchingKeys) | ||
return table.concat(matchingKeys, ', ') | return table.concat(matchingKeys, ', ') | ||
end | end | ||
-- | -- p.generateListTable 函数体(调用 formatSingleValue) | ||
function p.generateListTable(f) | function p.generateListTable(f) | ||
local args = require('Module:ProcessArgs').merge(true) | local args = require('Module:ProcessArgs').merge(true) | ||
| 第242行: | 第179行: | ||
table.insert(output, '{| class="wikitable sortable"') | table.insert(output, '{| class="wikitable sortable"') | ||
table.insert(output, '|-') | table.insert(output, '|-') | ||
table.insert(output, '! ' .. (displayNames['id'] or 'ID')) | table.insert(output, '! ' .. (displayNames['id'] or 'ID')) | ||
for _, field in ipairs(displayFields) do | for _, field in ipairs(displayFields) do | ||
field = mw.text.trim(field) | field = mw.text.trim(field) | ||
table.insert(output, '! ' .. (displayNames[field] or field)) | table.insert(output, '! ' .. (displayNames[field] or field)) | ||
end | end | ||
| 第256行: | 第191行: | ||
table.insert(output, '|-') | table.insert(output, '|-') | ||
table.insert(output, '| ' .. songId) | table.insert(output, '| ' .. songId) | ||
for _, field in ipairs(displayFields) do | for _, field in ipairs(displayFields) do | ||
field = mw.text.trim(field) | field = mw.text.trim(field) | ||
local rawValue = ValueFromValuesByKey(songEntry, field) | local rawValue = ValueFromValuesByKey(songEntry, field) | ||
-- 调用本地函数 | |||
local formattedValue = formatSingleValue(rawValue, field) | local formattedValue = formatSingleValue(rawValue, field) | ||
table.insert(output, '| ' .. formattedValue) | table.insert(output, '| ' .. formattedValue) | ||
| 第268行: | 第202行: | ||
end | end | ||
table.insert(output, '|}') | table.insert(output, '|}') | ||
return table.concat(output, '\n') | return table.concat(output, '\n') | ||
end | end | ||
return p | return p | ||
2025年11月29日 (六) 09:17的版本
本模块为自动表核心功能程序,根据输入的信息自动筛选数据。
数据库储存在Module:db_song,通过Template:db可以调用数据库中的信息,也可以通过Template:songlist生成自动表格。
local function GetValuesTable()
return mw.loadData('Module:db_song')
end
local function ValueFromValuesByKey(values, key)
if values and key then
return values[key]
end
return nil
end
-- 格式化单个值的私有函数 (重点:确保此定义被包含)
local function formatSingleValue(value, fieldType)
if value == nil then
return i18n['none']
elseif type(value) == 'boolean' then
return value and i18n['true'] or i18n['false']
-- 注意:这里调用了 p.valueMappingMethod,它在 p 被返回之前完成定义
elseif type(p.valueMappingMethod[fieldType]) == 'function' then
return p.valueMappingMethod[fieldType](value)
else
return tostring(value)
end
end
-- 4. 值格式化方法 (valueMappingMethod)
p.valueMappingMethod = {
['duration'] = (function (value)
if type(value) == 'number' then
local minutes = math.floor(value / 60)
local seconds = value % 60
return string.format('%d:%02d', minutes, seconds)
end
return value
end),
['artist'] = (function (value)
if type(value) == 'string' and value ~= '' then
return '[[' .. value .. ']]'
end
return value
end),
}
-- [[------------------------------------------------------------------]]
-- [[ 5. 外部调用函数 (p.*) ]]
-- [[------------------------------------------------------------------]]
-- p.value 函数体(调用 formatSingleValue)
function p.value(f)
local args = f
local frame = mw.getCurrentFrame()
if f == frame then
args = require('Module:ProcessArgs').merge(true)
end
local argTargetName = mw.text.trim(args[1] or '')
local argTypeString = args.type
local argNocat = args.nocat
if not argTypeString then
return i18n['error_no_type']
end
local values = GetValuesTable()
local songEntry = ValueFromValuesByKey(values, argTargetName)
if not songEntry then
if not argNocat then
local title = mw.title.getCurrentTitle()
if title.namespace == 0 and not title.isSubpage then
return '?' .. '[[Category:' .. string.format(i18n['category_missing_value'], '歌曲ID ' .. argTargetName) .. ']]'
end
end
return i18n['none']
end
local fieldNames = mw.text.split(argTypeString, ',')
local resultTable = {}
for _, argType in ipairs(fieldNames) do
argType = mw.text.trim(argType)
local value = ValueFromValuesByKey(songEntry, argType)
-- 调用本地函数
local formattedValue = formatSingleValue(value, argType)
table.insert(resultTable, formattedValue)
end
return table.concat(resultTable, ' / ')
end
-- p.findKeysByValue 函数体
function p.findKeysByValue(f)
local args = f
local frame = mw.getCurrentFrame()
if f == frame then
args = require('Module:ProcessArgs').merge(true)
end
local targetField = mw.text.trim(args.field or '')
local targetValue = args.value
if type(targetValue) == 'string' then
targetValue = mw.text.trim(targetValue)
end
if targetField == '' or targetValue == nil then
return i18n['error_find_keys_args']
end
local songData = GetValuesTable()
local matchingKeys = {}
for songId, songEntry in pairs(songData) do
local currentValue = ValueFromValuesByKey(songEntry, targetField)
if currentValue == targetValue then
table.insert(matchingKeys, songId)
end
end
table.sort(matchingKeys)
return table.concat(matchingKeys, ', ')
end
-- p.generateListTable 函数体(调用 formatSingleValue)
function p.generateListTable(f)
local args = require('Module:ProcessArgs').merge(true)
local conditionField = mw.text.trim(args.field or '')
local conditionValue = args.value
local displayFieldsString = mw.text.trim(args.columns or '')
-- 优化:预处理 conditionValue 的类型
if type(conditionValue) == 'string' then
local trimmedValue = mw.text.trim(conditionValue)
local lowerValue = string.lower(trimmedValue)
if lowerValue == 'true' or trimmedValue == '是' then
conditionValue = true
elseif lowerValue == 'false' or trimmedValue == '否' then
conditionValue = false
else
local num = tonumber(trimmedValue)
if num ~= nil then
conditionValue = num
else
conditionValue = trimmedValue
end
end
end
if conditionField == '' or conditionValue == nil or displayFieldsString == '' then
return i18n['error_generate_table_args']
end
local songData = GetValuesTable()
local displayFields = mw.text.split(displayFieldsString, ',')
local matchingKeys = {}
-- 查找匹配的键
for songId, songEntry in pairs(songData) do
local currentValue = ValueFromValuesByKey(songEntry, conditionField)
if currentValue == conditionValue then
table.insert(matchingKeys, songId)
end
end
table.sort(matchingKeys)
if #matchingKeys == 0 then
return '未找到符合条件的歌曲。'
end
local output = {}
-- 构造表格头部
table.insert(output, '{| class="wikitable sortable"')
table.insert(output, '|-')
table.insert(output, '! ' .. (displayNames['id'] or 'ID'))
for _, field in ipairs(displayFields) do
field = mw.text.trim(field)
table.insert(output, '! ' .. (displayNames[field] or field))
end
-- 构造表格行
for _, songId in ipairs(matchingKeys) do
local songEntry = songData[songId]
table.insert(output, '|-')
table.insert(output, '| ' .. songId)
for _, field in ipairs(displayFields) do
field = mw.text.trim(field)
local rawValue = ValueFromValuesByKey(songEntry, field)
-- 调用本地函数
local formattedValue = formatSingleValue(rawValue, field)
table.insert(output, '| ' .. formattedValue)
end
end
table.insert(output, '|}')
return table.concat(output, '\n')
end
return p