跳转到内容
打开/关闭菜单
  • 451 条目
  • 798 文件
  • 22 用户
  • 8955 编辑
Blockland Wiki
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:QQ聊天记录

来自Blockland Wiki
KK​(留言 | 贡献)2026年8月13日 (四) 10:58的版本 (创建页面,内容为“local p = {} local function escapeHtml(s) return mw.text.nowiki(s or '') end local function formatMessage(text) if not text or text == '' then return '<span class="qqchat-empty">(无文字消息)</span>' end text = escapeHtml(text) -- 高亮 @用户名 text = text:gsub('(@[^%s@]+)', '<span class="qqchat-mention">%1</span>') -- 简单支持换行 text = text:gsub('\n', '<br>') return text end function p.main(frame) local args = frame:getPa…”)
(差异) ←上一版本 | 最后版本 (差异) | 下一版本→ (差异)

此模块的文档可以在模块:QQ聊天记录/doc创建

local p = {}

local function escapeHtml(s)
	return mw.text.nowiki(s or '')
end

local function formatMessage(text)
	if not text or text == '' then
		return '<span class="qqchat-empty">(无文字消息)</span>'
	end

	text = escapeHtml(text)

	-- 高亮 @用户名
	text = text:gsub('(@[^%s@]+)', '<span class="qqchat-mention">%1</span>')

	-- 简单支持换行
	text = text:gsub('\n', '<br>')

	return text
end

function p.main(frame)
	local args = frame:getParent().args

	local title = args['标题'] or args['title'] or 'QQ聊天记录'
	local content = args['内容'] or args['content'] or ''
	local collapsed = args['折叠'] or args['collapsed'] or 'yes'
	local note = args['说明'] or args['note']

	-- 去除首尾空白
	content = mw.text.trim(content)

	local messages = {}

	-- 按行解析
	for line in content:gmatch('[^\r\n]+') do
		line = mw.text.trim(line)

		if line ~= '' then
			-- 格式:
			-- 用户名: 2025-03-15 20:45:03 消息
			local username, date, time, message =
				line:match('^(.-):%s*(%d%d%d%d%-%d%d%-%d%d)%s+(%d%d:%d%d:%d%d)%s*(.*)$')

			if username and date and time then
				table.insert(messages, {
					username = mw.text.trim(username),
					datetime = date .. ' ' .. time,
					message = message or ''
				})
			else
				-- 无法识别的行附加到上一条消息
				if #messages > 0 then
					local old = messages[#messages].message or ''
					if old ~= '' then
						old = old .. '\n'
					end
					messages[#messages].message = old .. line
				else
					table.insert(messages, {
						username = '',
						datetime = '',
						message = line,
						unparsed = true
					})
				end
			end
		end
	end

	local root = mw.html.create('div')
	root:addClass('qqchat')

	if collapsed ~= 'no' and collapsed ~= '否' and collapsed ~= 'false' then
		root:addClass('mw-collapsible')
		root:addClass('mw-collapsed')
	else
		root:addClass('mw-collapsible')
	end

	-- 标题栏
	local header = root:tag('div')
	header:addClass('qqchat-header')

	header:tag('span')
		:addClass('qqchat-icon')
		:wikitext('💬')

	header:tag('span')
		:addClass('qqchat-title')
		:wikitext(escapeHtml(title))

	header:tag('span')
		:addClass('qqchat-count')
		:wikitext('共 ' .. tostring(#messages) .. ' 条消息')

	-- 内容区域
	local body = root:tag('div')
	body:addClass('qqchat-body')
	body:addClass('mw-collapsible-content')

	if note and mw.text.trim(note) ~= '' then
		body:tag('div')
			:addClass('qqchat-note')
			:wikitext(escapeHtml(note))
	end

	for i, item in ipairs(messages) do
		local row = body:tag('div')
		row:addClass('qqchat-message')

		if item.unparsed then
			row:addClass('qqchat-unparsed')
		end

		local meta = row:tag('div')
		meta:addClass('qqchat-meta')

		meta:tag('span')
			:addClass('qqchat-user')
			:wikitext(escapeHtml(item.username))

		if item.datetime ~= '' then
			meta:tag('span')
				:addClass('qqchat-time')
				:wikitext(escapeHtml(item.datetime))
		end

		row:tag('div')
			:addClass('qqchat-text')
			:wikitext(formatMessage(item.message))
	end

	return tostring(root)
end

return p