Skip to content

聊天室 MD 格式完整教程(v3.8) ​

本教程详细讲解聊天室(Lobby)支持的 v3 扩展语法,包括标准 Markdown 和聊天室扩展组件。 所有示例均可直接复制到聊天室测试。 语法版本 v3.8(含 v4 宏系统):服务端 PHP 解析器 + 前端 JS 渲染双路径一致,所有组件由服务端解析为结构化 blocks,前端渲染。 v3.8 代码块保护:fenced 代码块(三反引号)与内联代码(单反引号)内的自定义语法只显示不解析(宏定义/触发写在代码块里同样不生效)。 v3.8 转义:\& → 字面 &(动作串内防拆分)、\| → 字面 |(参数值内)。 v3.7 内容换行:组件内容文本中 \n 转真实换行(\\n 转义保留字面);定时组件未绑定且 end 含 发送: 不自动启动。 v3.6 防刷屏:倒计时/计时器必须 绑定=1 启动;动作链未绑定且含 发送: 不自动启动。


目录 ​

  1. 标准 Markdown 语法
  2. 扩展语法基础结构
  3. 组件总览
  4. 展示组件
  5. 交互组件
  6. 数据与逻辑组件
  7. 媒体组件
  8. 时间组件
  9. 动作系统
  10. 条件动作与动作串
  11. 值引用与数学
  12. 通用参数
  13. 画板与动作链
  14. 宏系统(v4)
  15. 安全与限制
  16. 完整示例合集

一、标准 Markdown 语法 ​

聊天室使用 marked(GFM 模式)渲染标准 Markdown。

markdown
# 一级标题
**粗体文字** *斜体文字* ~~删除线文字~~
> 引用文字 `行内代码`
- 无序列表 1. 有序列表
- [x] 已完成 - [ ] 未完成
[点击访问](https://example.com)
| 列1 | 列2 |
|-----|-----|
| a   | b   |

⚠️ 消息内禁止图片(防流量攻击);图片仅在弹窗内容里允许(png/jpg/gif/webp/bmp/svg/ico)。 所有自定义语法写进 fenced 代码块或 ` 内联代码时只显示不解析(见第二章),宏也不会注册。

1.1 回复引用(聊天室通用) ​

回复消息时引用块自动处理:

  • 引用文本过长:超过 60 字自动截断 + 省略号(...)
  • 引用 MD/特殊格式消息:显示「特殊格式不支持预览」(不解析组件语法)
  • 引用表情消息:显示表情图片

二、扩展语法基础结构 ​

v3 所有扩展组件统一格式:

[!类型:内容|键=值|键=值|...]
部分说明必填
[!组件标记(普通 [...] 文本不解析)是
类型组件类型(中文,如 文本/按钮/投票/画板),[! 后紧跟,到 :/`/]`/空白为止
内容: 后的第一个无键段是
键=值命名参数,`分隔,顺序任意(键为小写字母/中文开头,含字母数字中文._-`)
无键段不含 = 的段按内容处理(如按钮附加文字、画板图形)否

组件格式规则(v3.8):

  • 嵌套:内容可含子组件,[] 深度感知闭合。如 [!按钮:开|发送:[!文本:你好]]
  • 未闭合(缺 ]):按普通文本显示并提示错误,不按组件渲染
  • | 是参数分隔符,参数值内的字面 | 用 \| 转义
  • 代码块保护:fenced 代码块与内联代码内所有自定义语法只显示不解析
  • 转义:\& → 字面 &、\| → 字面 |
  • 状态(输入/开关/变量)仅当前消息内有效
  • 单条消息长度上限 4000 字符
  • 所有展示文本自动 HTML 转义(防注入)
markdown
[!文本:你好]                        ← 最简
[!输入:占位符|id=name]              ← 带命名参数
[!按钮:开始|发送:开打!]             ← 动作按钮
[!倒计时:90|id=t|绑定=1|end=发送:时间到!]  ← 组合参数
[!按钮:开始倒计时|倒计时:t]
[!按钮:开启[!文本:你好]]             ← 嵌套子组件

三、组件总览 ​

#类型用途章节
1文本文本框4
2画板像素画板13
3表格数据表4
4音乐音乐播放7
5图集图片轮播7
6投票投票统计5
7进度进度条4
8倒计时倒计时8
9计时秒表8
10定时定时触发8
11按钮动作按钮5
12发送发送消息按钮5
13复制复制按钮5
14弹窗弹窗5
15确认确认按钮5
16输入输入框5
17显示变量值显示6
18开关多选切换5
19隐藏隐藏组件6
20变量变量赋值6
21条件条件分支6
22动作链多步编排13
23宏宏定义14
24触发宏宏触发14
25宏删宏删除14
26宏列表宏库列表14

通用参数(大部分组件可用):id=名(统一标识,动作链定位)、x=像素、y=像素(弹窗内位置偏移)、隐藏=1(初始隐藏)、颜色=#hex(前景色)。


四、展示组件 ​

组件语法说明
文本[!文本:内容|#f00|大|居中]彩色文本;大/小 显式档位;无显式按长度自适应(≤4字特大、≤12大、≤40中、>40小);标题=/t= 标题行、bg=色/-1 背景
进度[!进度:7/10|颜色=#f00|id=p1]进度条(内容 当前/上限 或 70%);支持 bar.set:/bar.add:/bar.sub: 实时更新
表格[!表格:列1/列2|数据...|标题=表名]单元格以 / 分隔,行以 | 分隔;支持 %值% 变量引用,自动换行
图集[!图集:标题|URL1|URL2|...|自动=秒|id=名]图集轮播弹窗;图片 URL 需 http(s)+扩展名白名单;自动= 秒数自动轮播,点击放大预览
音乐[!音乐:URL|标题=歌名|自动播放|id=名|状态=变量名]音乐播放器(带播放/暂停/进度条;房间点歌系统同步;状态= 输出播放/暂停/结束到变量)
投票[!投票:问题|选项1|选项2|多选=2|perm=@名|洗牌|id=名|mode=bar]投票(多选/权限/洗牌/实时统计条)
倒计时[!倒计时:90|id=名|绑定=1|end=动作|lock=组|bar=进度条id]倒计时(必须绑定启动(v3.6 防刷屏)/锁定按钮组/进度联动);动作 倒计时:名/倒计时:名|重置
计时[!计时:25分|id=名|绑定=1|end=动作|重复=1]正向计时器(必须绑定启动(v3.6 防刷屏)/到点动作/自动重复)
定时[!定时:09:00|动作|重复=1|绑定=1|id=名]定时到点执行动作(绑定=1 自动启动;未绑定且动作含 发送: 不自动启动(v3.7 防刷屏),需按钮 定时:名 手动启动)
markdown
[!文本:🎉 欢迎|#f00|大|居中]
[!进度:7/10|id=血条]
[!倒计时:5分|id=茶|绑定=1|end=发送:茶泡好了!]
[!按钮:泡茶|倒计时:茶]
[!投票:今晚吃什么|火锅|烧烤|日料|多选=2]
[!表格:商品/价格|苹果/5元|香蕉/3元|标题=小卖部]

五、交互组件 ​

组件语法说明
按钮[!按钮:文字|动作|颜色=#f00|perm=@小红|click=限制|sound=音效|anim=动画]动作按钮(动作见第九章);perm= 仅指定用户可点;click= 点击限制
发送[!发送:文字|内容]点击把内容填入输入框并发送
复制[!复制:文字|内容]点击复制到剪贴板
弹窗[!弹窗:按钮文字|弹窗内容|标题=标题]弹窗(内容可含组件/图片,弹窗内图片全放行;弹窗内组件可用 x=/y= 定位)
确认[!确认:提示语|要发送的内容]点击先弹确认框,确认后再执行动作
输入[!输入:占位符|id=名|ok=答案1/答案2|on=动作]输入框,值存入 {名};回车匹配 ok= 才执行 on=,不写 ok= 任意输入触发
显示[!显示:名|颜色=#f00]实时显示输入/开关/变量值(随变量刷新重绘)
开关[!开关:值1/值2|id=名|颜色=1|锁定=1|on=动作]点击循环切换值,当前值存入 {名} 并联动动作
隐藏[!隐藏:名]隐藏指定 id 组件(动作 隐藏:名 可再显示)
markdown
[!输入:输入昵称|id=昵称] [!显示:昵称]
[!开关:开/关|id=灯|on=发送:灯被切到{灯}]
[!确认:确定删除?|发送:已删除]
[!复制:copy码|INVITE-2026]
[!弹窗:📖 说明|**这是弹窗**,支持图片与嵌套按钮|标题=帮助]

六、数据与逻辑组件 ​

组件语法说明
变量[!变量:名=值]定义变量(隐藏,{名} 引用),值支持数学表达式;赋值后同消息内立即生效并刷新
条件[!条件:表达式|成立动作|否则动作]表达成立执行成立动作,否则执行否则动作(可省略)
动作链[!动作链:步骤/步骤|循环=N|id=名|绑定=1]隐形编排器(见第十三章)

条件表达式格式:

语法含义
{变量}非空即真
{变量}=值 / ==相等
!=不等
> >= < <=数值比较
{变量}~a/b/c列表包含
1恒真
markdown
[!变量:金币=100] 我的金币:[!显示:金币]
[!变量:血量=100-20] 血量:[!显示:血量]
[!条件:{金币}>50|💰 有钱人|发送:继续努力]
[!隐藏:标题]

七、媒体组件 ​

7.1 音乐 ​

[!音乐:音频URL|标题=歌名|自动播放|id=m1|状态=mus]
  • 音频 URL:mp3 等标准音频链接(白名单域名校验)
  • 自动播放 自动开始;状态= 初始状态(mus 表示播放 / 其他暂停)
  • 带播放/暂停/进度条控制;房间点歌系统同步
  • 动作:音乐:play / 音乐:stop

7.2 图集 ​

见第四章「图集」。


八、时间组件 ​

组件语法说明
倒计时[!倒计时:90|id=名|end=动作|绑定=1]内容为秒数或 1时30分15秒;end= 到时执行动作;绑定=1 隐藏本体仅作定时器;动作 倒计时:名 启动、倒计时:名|重置 重置
计时[!计时:id=sw1|开始=1]点击开始/暂停秒表;动作 计时:名 切换
定时[!定时:10|end=动作|id=名]到时间点执行 end=;未绑定且含 发送: 不自动启动(v3.7 防刷屏),需动作 定时:名 手动启动
markdown
[!倒计时:90|id=t1|绑定=1|end=发送:时间到!]
[!计时:id=sw1|开始=1]
[!定时:10|id=at1|绑定=1|end=发送:到点提醒!]
[!按钮:启动倒计时|倒计时:t1]

九、动作系统 ​

动作是按钮/开关/倒计时等组件的"执行体",统一 前缀:内容:

动作说明示例
发送:内容填入输入框并发送发送:大家好
复制:内容复制到剪贴板复制:https://...
弹窗:内容弹窗弹窗:说明文字
跳转:URL新标签打开跳转:https://x.com
开关:名切换开关组件开关:sw1
显示:名 / 隐藏:名显示/隐藏指定组件显示:板1
倒计时:名启动/重置倒计时倒计时:t1
计时:名启动/暂停秒表计时:sw1
定时:名手动启动定时器定时:at1
变量:名=值赋值变量变量:金币=100
循环:N循环标记循环:3
洗牌:名重排选项洗牌:v1
音乐:动作控制音乐音乐:play
随机:名=最小,最大随机整数写回随机:骰=1,6
等待:秒延时(支持小数)等待:1.5
分支:表达式条件分支分支:{金币}>=100
动作链:名启动/控制动作链动作链:c1

英文兼容(v2 历史消息):send: copy: show: hide: switch: timer.start: timer.stop: incr: decr: reset: close: set: for: bar.add: bar.set: bar.sub: embed: modal:。

markdown
[!按钮:掷骰子|随机:骰=1,6&发送:你掷出了 {骰} 点]
[!按钮:抽奖|洗牌:名单,取1&弹窗:🎁 中奖者|{名单}]
[!按钮:翻页|变量:页=取余({页}+1,10)]
[!按钮:行动|分支:{选择}=1→发送:⚔️ 攻击;2→发送:🛡️ 防御;其他→发送:无效]

十、条件动作与动作串 ​

任意动作可带条件后缀,满足才执行:

动作?条件
动作?条件:否则动作
  • ? 分隔动作与条件:? 后必须是 { 开头才视为条件(防 URL 误判);: 分隔否则动作
  • 条件支持:{名} 非空、= != > >= < <=、~(列表包含)
  • 成功/失败分支可嵌套条件动作(≤3 层)
  • & 连接多个动作顺序执行(动作串);\& 转义为字面 &(URL 参数内);URL 查询串中的 & 不拆分,& 后是动作前缀或新 URL 才拆分
markdown
[!开关:🦔|on=变量:分数={分数}+10?{洞1}=1:发送:打空了!]
[!按钮:签到|发送:签到成功&变量:天数={天数}+1?{已签}!=1:发送:今天已签过啦!]
[!按钮:攻击|随机:伤害=5,15&变量:血量={血量}-{伤害}?{血量}>10:发送:⚠️ 倒下了]
[!按钮:结算|变量:分数={分数}+10?{分数}>=100:变量:分数={分数}+5?{分数}>=60:发送:不及格]

十一、值引用与数学 ​

11.1 引用语法 ​

{名}         或   {名|默认值}
%名%          或   %名|默认值%
  • 变量名:中文/字母/数字/下划线/短横线
  • |默认值:变量为空时显示默认值
  • 组件内容、动作、表格单元格、条件表达式、画板参数中均可引用

列表值用 / 或 , 分隔,在列表型参数中自动展开:

markdown
[!变量:菜单=火锅,烧烤,日料]
[!投票:今晚吃什么|{菜单}]          ← 展开为 3 个选项
[!变量:图库=https://a.png,https://b.png]
[!图集:我的图库|{图库}]            ← 展开为 2 张图

11.2 数学表达式与函数 ​

+ - * / ( ) 四则运算
取余({a},{b})  取整({x})  绝对值({x})  最大({a},{b})  最小({a},{b})

白名单校验:仅数字 + - * / ( ) 空格 % 与上述函数可执行,防注入。

markdown
[!按钮:加5|变量:金币={金币}+5]
[!按钮:翻页|变量:页=取余({页}+1,10)]
[!按钮:保底|变量:伤害=最大(0,{攻击}-{防御})]

十二、通用参数 ​

12.1 颜色(裸色简写) ​

markdown
[!文本:你好|#f00]           ← 红色(3 位/6 位 hex 均可)
[!按钮:确定|#0f0]           ← 按钮也支持
[!文本:大号居中|#f00|大]

12.2 统一 ID ​

所有组件支持 id=名:渲染时注入 data-ui-id,供动作链目标、显示:/隐藏: 按 id 操作。同一消息内唯一。

markdown
[!文本:标题|id=标题]
[!动作链:目标=标题;颜色=#f00;延时=300|循环]

12.3 点击次数限制 click ​

写法含义
click=*1每人只能点 1 次
click=*5每人独立 5 次
click=1所有人合计只能点 1 次
click=@张三:2仅张三 2 次,其他人无限
click=5@张三:2全局 5 次 + 张三 2 次
markdown
[!按钮:签到|发送:签到成功|click=*1]     ← 每人只能签到一次
[!按钮:抢到|发送:我抢到了!|click=1]     ← 所有人只能抢一次

12.4 弹窗内定位(x/y) ​

组件支持 x=数字 / y=数字 偏移(px,可负值),相对自身流位置定位,手机/电脑显示位置一致:

markdown
[!按钮:🌟|id=星|x=10|y=5]

十三、画板与动作链 ​

13.1 画板 ​

[!画板[:尺寸]|图形序列|bg=色|grid=0|id=板1|text=..|modal=1|hide=1]
  • 尺寸:1~20(默认 20);bg= 背景色;grid=0 隐藏网格
  • text= 画板文字(tx/ty/ts/tc 定位/字号/颜色)
  • 图形代码:l线 p折线 c曲线 r矩形 o圆 d点 t三角 h心形 pt多边形 dl菱形 st星形 fr边框框 tx文字
  • 图形间以 ; 分隔;描边色 图形:坐标:#颜色、填充 |f#颜色、线宽 |wN
  • 坐标与画板尺寸同比例(0~尺寸-1),超界自动裁剪
  • 图形参数支持 {名} 引用,变量变时自动重绘;modal=1 折叠为按钮点击展开;hide=1 初始隐藏
markdown
[!画板:20|o:10,10,6|dl:10,10,5|st:10,10,3|id=卡牌]
[!画板:10|o:{圆x},5,2:{颜色}|grid=0]

13.2 动作链(隐形编排器) ​

[!动作链:步骤1/步骤2|循环=N|id=名|绑定=1]

步骤 = 目标=组件id;操作;延时=秒;条件=表达式;跳转=步骤号(步骤内 `;` 分隔)
  • 双 ID:目标=组件id 操作对象;id=链名 对外接口
  • 触发:省略 绑定= 自动;绑定=1 等外部触发;v3.6 防刷屏:未绑定且含 发送: 步骤的不自动启动,必须绑定
  • 操作集:移动x/y 缩放 旋转(累积增量) 透明 闪烁 颜色 文字 隐藏/显示 状态 变量 音效 更新(画板重绘)任意 v3 动作
  • 循环在消息可见时才跑,划出视口暂停;绑定=1 不自动启动,用动作 动作链:名 启动
  • 控制动作:开始 暂停 继续 停止 重播
markdown
[!动作链:目标=标题;闪烁=3;延时=200|id=开场|绑定=1]
[!倒计时:5|id=开打计时|绑定=1|end=动作链:开场,开始&发送:开打!]
[!按钮:开始|倒计时:开打计时]
[!按钮:⏸ 暂停|动作链:跳动,暂停]

13.2.1 动作链控制动作 ​

动作链:名,开始   动作链:名,暂停   动作链:名,继续   动作链:名,停止   动作链:名,重播

十四、宏系统(v4) ​

宏是玩家自定义的 MD 组件模板,聊天室房间级共享。每条宏有唯一 名称、可选的 昵称(触发别名)、参数列表 params 和 模板 template。同一消息内可以用 [!宏:...] 定义/[!宏删:...] 删除,用 [!触发宏:...] 展开调用;也可以在 BOT 面板 / 宏管理里通过 HTTP API 管理(见 HTTP 接口文档第 10 章)。

源码:宏解析与展开见 MarkdownMessageParser.php,存储见 MacroRepository.php。

14.1 定义宏 宏 ​

[!宏:名称|昵称(参数1,参数2)=模板内容]
  • 名称:必填,唯一,[A-Za-z0-9_中文] 1~20 字符,不能与内置组件重名
  • 昵称:可选,触发别名,全局唯一,[A-Za-z0-9_中文.-] 1~32 字符
  • 参数:可选,逗号分隔 ≤8 个,模板内用 {参数名} 占位
  • 模板:任意合法 MD 语法(组件/动作链/变量/嵌套宏),≤500 字符
  • 定义消息发送后注册到房间宏库(带创建者身份),并显示为宏卡片
  • 代码块内的 [!宏:...] 不注册(仅展示)
  • 每人最多注册 50 个宏;昵称唯一
markdown
[!宏:点歌卡|点歌(歌名,歌手)=[!音乐:{歌名}|标题={歌手}|自动播放]]
[!宏:早安|za(名)=[!文本:早上好,{名}!]]
[!宏:签到=[!文本:✅ 签到成功]&变量:签到次数={次数|0}+1]

14.2 触发宏 ​

[!触发宏:昵称]              ← 无参
[!触发宏:昵称:值1|值2]      ← 位置参数传值
  • 优先按昵称匹配,其次按名称匹配
  • 参数按声明顺序填入 {参数名};缺失用空串
  • 嵌套触发:模板内可内含 [!触发宏:],递归深度 ≤3(循环引用自动截断)
  • 未找到的宏:渲染为"宏不存在"提示
  • 消息总长保护:展开结果超限自动截断
markdown
[!触发宏:点歌卡:One Ok Rock|Al To You]

14.3 修改 / 删除 ​

[!宏:名称|新昵称(参数)=新模板]   ← 同名重定义即修改(仅创建者)
[!宏删:名称]                     ← 删除(仅创建者)

14.4 宏列表 ​

[!宏列表]

以列表卡片展示房间宏库(最近 50 个:昵称/名称/参数/模板/创建者)。


十五、安全与限制 ​

限制项值
消息最大长度4000 字符
解析节点数超限整条降级为纯文本
JSON 广播64KB 上限(超限自动降级纯文本)
宏模板≤500 字符,每人 ≤50 个,昵称唯一
宏展开深度≤3(防递归死循环)
图片域名消息内禁图片;弹窗内 http(s)+扩展名白名单
XSS前端 escapeHtml + DOMPurify(style 仅颜色属性)
动作串 URL仅拆分 & 后动作前缀/新 URL,参数内 & 保留
定时防刷屏定时组件未绑定且含发送不自动启动
代码块所有自定义语法在代码块内不解析不注册

十六、完整示例合集 ​

markdown
# 🎲 单骰
[!按钮:🎲 掷 1d6|随机:骰=1,6&发送:🎲 你掷出了 {骰} 点]

# 🎲 双骰(自动求和)
[!变量:总=0]
[!按钮:🎲 掷 2d6|随机:骰1=1,6&随机:骰2=1,6&变量:总={骰1}+{骰2}&发送:🎲 {骰1}+{骰2}={总}]

# ✂️ 猜拳(电脑随机)
[!按钮:✌️ 剪刀|随机:电脑=1,3&发送:👍 平局?{电脑}=1:发送:💔 你输了?{电脑}=2:发送:🎉 你赢了]

# 📢 每人只能点一次
[!按钮:签到|发送:✅ 签到成功!|click=*1]

# 🔒 所有人只能点一次
[!按钮:抢沙发|发送:🧨 我是第一个!|click=1]

# 🎁 游戏结算
[!变量:奖励=取整(随机(1,10))*10]
[!显示:奖励|颜色=#f59e0b]
[!进度:{血}/100|颜色=#22c55e|id=血条]
[!按钮:领取|变量:金币={金币|0}+{奖励}&发送:我获得了{金币}金币]

文档版本:v3.8(含 v4 宏系统)· 语法规范详见《MD扩展语法规范v3.md》(v3.8)。

最近更新