基于 SpacetimeDB 的实时聊天应用消息转发(Message Forwarding)功能规格与实现指南
2026/9/15 7:54:48 网站建设 项目流程

基于 SpacetimeDB 的实时聊天应用消息转发(Message Forwarding)功能规格与实现指南

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

本文围绕 SpacetimeDB 仓库中tools/llm-oneshot/apps/chat-app/prompts/composed/17_forwarding.md这一 LLM 基准测试提示词规格展开,系统解读"实时聊天应用 + 消息转发"的完整功能需求、UI 契约、UI/样式规范,并结合仓库内的提示词模块化体系、TypeScript SDK 数据同步模型与自动化评测机制,为开发者提供一份可直接指导实现与验收的实战指南。

一、文档定位:LLM 基准测试中的"组合式提示词"

在 SpacetimeDB 仓库的 tools/llm-oneshot 目录下,维护着一套用于对比 SpacetimeDB 与 PostgreSQL 在不同功能集下 LLM 生成代码能力的基准测试工程。其聊天应用(chat-app)的提示词按"模块化 + 组合式(composed)"设计:

  • prompts/features/ 存放单一功能积木,每个文件只描述一个功能,如 17_forwarding.md 单独描述消息转发;
  • prompts/composed/ 存放累积式组合提示词,编号越大功能越全,例如17_forwarding.md表示"基础聊天 + 前述全部功能 + 消息转发";
  • prompts/language/ 存放语言/后端特定约束(如typescript-spacetime.mdrust-spacetime.mdcsharp-spacetime.md)。

根据 prompts/README.md 的说明,这套结构的核心动机是 DRY(Don't Repeat Yourself):功能描述只维护一份,再与语言文件拼接即可生成面向不同技术栈的完整提示词。组合方式为"语言文件在前、组合提示词在后",例如:

@language/typescript-spacetime.md @composed/17_forwarding.md execute

值得注意的是,composed/ 目录实际已扩展到19_polls.md(慢速模式、投票),说明该提示词系统在 README 中标注的 12 级基础上仍在持续演进。

二、UI 与样式规范:完整继承的界面基线

关联文档在开头约三分之一篇幅定义了与功能无关的通用 UI 基线,这是所有组合提示词共享的部分,任何实现都必须遵守。

2.1 布局(Layout)

  • 侧边栏(左侧,固定约 220px):应用标题/品牌、带状态的用户信息、房间列表、在线用户;
  • 主区域(右侧,flex):房间头部栏、可滚动消息列表、固定在底部的输入栏;
  • 面板(右侧滑入或浮层):话题(threads)、置顶消息(pinned messages)、用户资料(profiles)、设置(settings)。

2.2 视觉设计(Visual Design)

采用深色主题,并使用语言文件中的品牌色(见第七节)。核心规则:

维度要求
背景最深的色阶用于主背景,侧边栏与卡片用略亮色阶
文字深底浅字,时间戳与次要信息使用弱化色
边框1px 细边框,与背景低对比
间距统一使用 8/12/16/24px 刻度
字体系统字体栈,层级清晰(标题加粗、正文常规、元数据弱化小字)
圆角输入框、按钮、卡片、消息容器均圆角

2.3 组件规范(Components)

  • 消息:发送者姓名(彩色)+ 时间戳(弱化)+ 文本;同一发送者的连续消息分组显示;操作按钮仅悬停时出现(具体按钮取决于启用的功能);
  • 输入框:全宽、圆角、细边框、占位文本、聚焦环使用主色;
  • 按钮:主操作填充主色,次级操作用描边/幽灵样式,需有清晰的 hover 与 active 状态;
  • 徽章:小药丸形、带计数、对比色(如房间未读数);
  • 模态/面板:右侧滑入 + 柔和背景遮罩,或下拉浮层;
  • 状态指示:小圆点(绿=在线、黄=离开、红=请勿打扰、灰=离线);
  • 房间列表:房间名带可选图标前缀(#),当前房间高亮,未读徽章。

2.4 交互与体验(Interaction & UX)

  • 后端连接期间显示加载/连接中状态(spinner 或骨架屏),不得出现白屏
  • 空状态需给出有帮助的文案(如 "Create a room to get started");
  • 错误反馈:行内错误或 toast 通知,绝不静默失败
  • 平滑过渡:面板、模态、状态变化使用淡入淡出/滑动;
  • 悬停揭示:消息操作按钮、表情回应 tooltip、用户资料卡片;
  • 键盘支持:Enter 发送消息,Escape 关闭模态/面板;
  • 自动滚动到最新消息,向上滚动时出现"回到底部"按钮。

三、功能规格总览:20 项能力的累积式集合

关联文档的核心是"Important"声明:每个功能都附带一个 "UI contract" 小节,规定自动化测试所依赖的元素属性——它们定义了用户可见的接口。而架构、状态管理、后端设计则完全交给实现者自主决定。这意味着该文档刻意做到"接口契约与实现解耦",方便用统一脚本对不同实现做黑盒验收。

整个组合提示词(01–16 + Forwarding)包含以下功能族:

编号功能核心要点
1基础聊天设置昵称、创建/加入/离开房间、向已加入房间发消息、在线用户展示、合理校验(防刷屏、长度限制)
2打字指示同一房间内广播"正在输入",数秒无活动自动过期,支持单/多人文案
3已读回执追踪谁看过哪些消息,展示"Seen by X, Y, Z",实时更新,不包含发送者本人
4未读计数房间列表未读徽章,按用户×房间记录最后读取位置,实时增减
5定时消息定时发送、作者可取消的待发列表、到点出现在房间
6阅后即焚设定时长后从数据库永久删除,UI 显示倒计时/消失提示
7消息表情回应emoji 回应、计数实时更新、可切换自身回应、悬停显示回应者
8编辑与历史编辑自己的消息、"(edited)" 标记、他人可查看编辑历史、实时同步
9实时权限房间创建者为管理员,可踢/封禁,可晋升管理员,变更即时生效无需重连
10丰富在线状态online/away/DND/invisible 四态、离线显示"Last active X minutes ago"、自动置为 away
11消息话题(线程)回复特定消息形成线程、父消息显示回复数与预览、线程视图、实时同步
12私密房间与私聊邀请制私密房(不进公开列表)、按用户名邀请、双人 DM、仅成员可见
13房间活跃度5 分钟内有 1+ 消息标 "Active"(绿),2 分钟内有 5+ 消息标 "Hot"(橙),实时变化
14草稿同步自动保存草稿、跨设备实时同步、每房间独立草稿、发送后清除
15匿名到注册迁移无账号可聊天、匿名身份跨会话保留、注册后身份与消息历史完整保留、房间成员关系转移
16置顶消息管理员与作者可置顶/取消、消息列表与"置顶面板"双入口、实时同步
17用户资料昵称/bio/头像可编辑、点击用户名弹出资料卡、修改后全局实时生效
18@提及与通知@username 高亮、生成通知、铃铛未读计数、通知面板可标记已读、点击跳转到源消息
19收藏/已存消息悬停收藏、侧边栏"Saved"面板、展示消息内容/发送者/频道/时间、个人私有、实时反映编辑
20消息转发(Forwarding)悬停出现 Forward 按钮 → 频道选择器 → 目标频道出现带来源归属的副本,原消息不变,目标频道成员实时可见

四、逐功能 UI 契约详解(自动化验收接口)

由于组合提示词具有累积性(每个级别包含其前所有功能),下面按原文逐项保留各功能的 UI contract 关键元素。实现时必须确保这些可被自动化测试识别的属性存在。

4.1 基础聊天

  • 姓名输入框:placeholder包含 "name"(不区分大小写);
  • 姓名提交:文本为 "Join"、"Register"、"Set Name" 的button,或type="submit"
  • 创建房间:文本含 "Create"、"New" 或 "+" 的button
  • 房间名输入:placeholder含 "room" 或 "name";
  • 消息输入:placeholder含 "message";
  • 发送:在消息输入框按 Enter 发送;
  • 房间列表:侧边栏/列表中房间名可见且可点击;
  • 加入房间:点击房间名进入,或文本为 "Join" 的button
  • 离开房间:文本为 "Leave" 的button
  • 在线用户:可见用户列表/成员面板中以文本形式展示用户名。

4.2 打字指示

  • 打字文本:他人输入时,可见文本包含 "typing";
  • 自动过期:无活动 6 秒内指示文本消失。

4.3 已读回执

  • 回执文本:他人查看后,消息附近出现含 "seen" 或 "read" 的文本;
  • 读者姓名:回执文本包含查看者的显示名。

4.4 未读计数

  • 徽章:侧边栏房间名旁出现数字徽章(如 "3");
  • 清空:打开/进入房间后徽章消失。

4.5 定时消息

  • 定时按钮:文本为 "Schedule"、aria-label含 "schedule",或title含 "schedule" 的图标按钮;
  • 时间选择器:input[type="datetime-local"]input[type="time"]input[type="number"]
  • 待发列表:查看定时消息时可见 "Scheduled" 或 "Pending" 文本;
  • 取消:待发消息旁有文本为 "Cancel" 的button

4.6 阅后即焚

  • 开关:文本/标签含 "ephemeral"、"disappear" 或 "expire" 的select/button/input
  • 时长选项:可选项如 30s、1m、5m;
  • 指示:消息上可见倒计时、"expires" 或 "disappearing" 文本;
  • 删除:时长到期后消息文本从 DOM 中移除。

4.7 表情回应

  • 触发:悬停时出现 emoji 文本按钮(👍 ❤️ 😂 😮 😢)或文本 "React" /aria-label含 "react" 的按钮;
  • 展示:消息下方或旁边显示 emoji + 计数(如 "👍 2");
  • 切换:再次点击同一 emoji 移除自己的回应;
  • 悬停信息:回应元素的title属性包含回应者姓名。

4.8 编辑与历史

  • 编辑按钮:悬停在自己消息上出现文本为 "Edit" 的button
  • 编辑表单:编辑期间用行内input/textarea替换消息内容,并有 "Save"button
  • 编辑标记:已编辑消息可见 "(edited)";
  • 历史:点击 "(edited)" 打开查看历史版本的视图。

4.9 实时权限

  • 管理员指示:成员列表中管理员显示 "Admin"/"ADMIN";
  • 成员面板:房间头部有文本为 "Members" 或 "Manage" 的button
  • 踢出:非管理员成员旁有文本为 "Kick" 的button
  • 晋升:非管理员成员旁有文本为 "Promote" 的button
  • 被踢反馈:被踢用户看到含 "kicked" 的文本或被重定向离开房间。

4.10 丰富在线状态

  • 状态选择器:文本为 "Online"、"Away"、"Do Not Disturb"/"DND"、"Invisible" 的select或按钮组;
  • 状态指示:用户名旁彩色圆点(绿=online、黄=away、红=DND、灰=invisible);
  • 最后活跃:离线/离开用户显示含 "Last active" 或 "ago" 的文本。

4.11 话题线程

  • 回复按钮:悬停时出现文本 "Reply" 或 "💬" 的button
  • 回复数:有回复的消息显示 "N replies" 或 "💬 N";
  • 线程面板:点击回复按钮/计数打开包含父消息与全部回复的面板;
  • 线程输入:面板内placeholder含 "reply" 的input/textarea

4.12 私密房间与私聊

  • 私密开关:创建房间时input[type="checkbox"]或文本/标签含 "Private" 的button
  • 私密指示:侧边栏私密房间显示 "private" 文本或锁图标 🔒;
  • 邀请按钮:房间头部或成员面板中文本为 "Invite" 的button
  • 邀请 UI:被邀请用户看到含房间名的 "Accept" 与 "Decline"button
  • DM 按钮:用户列表中用户名旁文本为 "DM" 或 "💬" 的button

4.13 活跃度指示

  • Active 徽章:最近 5 分钟内有 1+ 消息的房间显示绿色 "Active"/"ACTIVE";
  • Hot 徽章:最近 2 分钟内有 5+ 消息的房间显示橙色 "Hot"/"🔥";
  • 出现位置:侧边栏房间名旁。

4.14 草稿同步

  • 自动保存:输入即自动保存(无需保存按钮);
  • 持久化:切换房间再切回,输入框恢复草稿文本;
  • 跨会话:刷新页面后草稿仍恢复;
  • 发送即清空:发送消息后清空该房间草稿。

4.15 匿名迁移

  • 游客入口:文本为 "Guest"/"Anonymous"/"Join as Guest" 的button,或自动分配 "Guest-XXXXX"/"Anon-XXXXX" 式名称;
  • 游客指示:匿名用户名旁显示 "guest"/"anon" 徽章/标签;
  • 注册按钮:游客可见文本为 "Register" 或 "Sign Up" 的button
  • 注册表单:placeholder含 "name" 或 "username" 的input
  • 迁移:注册后此前所有消息显示新显示名。

4.16 置顶消息

  • 置顶按钮:悬停时文本 "Pin" 或aria-label含 "pin" 的button
  • 置顶指示:置顶消息显示 "pinned" 文本或 📌 图标;
  • 置顶面板:频道头部有 "Pinned"/"Pins"button,打开后列出全部置顶消息;
  • 取消置顶:置顶消息上有 "Unpin"button(面板内或悬停时)。

4.17 用户资料

  • 资料编辑:侧边栏可访问文本 "Edit Profile"/"Profile" 或齿轮图标按钮;
  • Bio 输入:placeholder含 "bio" 或 "status" 的input/textarea
  • 资料卡:点击用户名弹出显示姓名、bio、头像的 popover/模态;
  • 姓名传播:修改显示名后所有消息归属实时更新。

4.18 @提及与通知

  • 提及高亮:消息中的@username视觉区分(加粗、着色或包裹进带样式的span);
  • 通知铃铛:侧边栏/头部有文本 "🔔" 或aria-label含 "notification" 的button
  • 未读数:铃铛旁数字徽章;
  • 通知面板:点击铃铛显示含消息文本与频道名的通知列表;
  • 标记已读:"Mark Read"/"Mark All Read"button

4.19 收藏/已存消息

  • 收藏按钮:悬停时文本 "Bookmark"/"Save" 或aria-label含 "bookmark"/"save" 的button
  • 已存面板:侧边栏 "Saved"/"Bookmarks"button打开面板;
  • 条目:每条已存消息显示消息文本与来源频道/发送者;
  • 移除:面板内 "Remove"/"Unsave"button

五、消息转发(Forwarding)深度剖析

这是本关联文档的编号主题与新增核心功能,对应独立积木文件 features/17_forwarding.md。

5.1 功能需求(原文完整继承)

  • 用户可以将一条消息转发到其作为成员的其他频道
  • 消息悬停时出现"Forward" 按钮,点击打开频道选择器(channel picker)
  • 转发后,消息出现在目标频道,并带有"Forwarded from #原频道 by @用户"的归属标注;
  • 原消息不被修改——转发创建的是副本(copy),而非移动或引用
  • 转发消息对目标频道全体成员实时可见

5.2 UI 契约(原文完整继承)

契约项自动化测试要求
转发按钮消息悬停时出现文本为 "Forward" 或aria-label含 "forward" 的button
频道选择器列出用户可转发目标频道的列表或下拉框
归属标注转发消息显示含 "Forwarded" 或 "forwarded from" 的文本
原消息不变源消息上没有任何 "forwarded" 指示

5.3 基于 SpacetimeDB 数据模型的实现思路

结合仓库中 SpacetimeDB 的架构可以推断出一套与"副本 + 实时同步"语义天然契合的实现方案:

后端(reducer 层面):消息表增加forwarded_from(源频道名或 ID)与forwarded_by(转发者身份)两个字段。新增一个转发 reducer,例如forward_message(msg_id, target_room)

  • 校验调用者是源房间与目标房间的成员;
  • 读取源消息内容,在目标房间的消息表中插入一条新行(副本),并写入来源归属字段;
  • 源房间中的消息行不做任何修改——这正符合"原消息不变、转发创建副本"的契约。

实时同步(subscription 层面):SpacetimeDB 的客户端通过订阅(subscription)与后端建立实时同步,目标频道成员订阅了该房间消息表后,新插入的转发副本会自动推送到所有订阅者,无需任何额外广播代码。这一机制在仓库的 TypeScript SDK 中有直接支撑:订阅通过ConnectionManagersubscribe与查询构建器完成,参见 sdks/typescript/src/react/SpacetimeDBProvider.ts 与 sdks/typescript/src/lib/query.ts(其中tables.user.where(...)这类带过滤条件的订阅示例也出现在 Angular 注入器中)。

客户端(React 组件层面):消息项组件悬停时渲染 "Forward" 按钮,点击后弹出频道选择器(仅列出当前用户已加入且非当前房间的频道);提交后调用转发 reducer;渲染时根据forwarded_from字段决定是否显示 "Forwarded from #xx by @xx" 归属行。

从数据流看,该功能在 SpacetimeDB 上只需要"一张表 + 一个 reducer + 一条订阅"即可闭环,这也是 prompts/README.md 中"转发/同步类功能对 SpacetimeDB 而言是 trivial 级别"结论的体现。

六、技术栈约束与品牌规范

关联文档的落地必须与语言文件组合使用。以 TypeScript 技术栈为例,language/typescript-spacetime.md 规定了如下硬约束:

  • 架构:后端为 SpacetimeDB TypeScript 模块,客户端为 React + Vite + TypeScript;
  • 模块名chat-app
  • 目录约束:所有代码只能写在.../backend/spacetimedb/(服务端)与.../client/src/(客户端)下,且必须位于带时间戳的文件夹chat-app-YYYYMMDD-HHMMSS/内,保持最小化与可读性;
  • 输出约束:只返回带文件头的代码块(见 output_instructions.md)。

同时 base_spacetime.md 规定应用使用 SpacetimeDB 品牌深色主题,官方品牌色取自语言文件:

用途色值
Primary(主色/成功色)#4cf490(SpacetimeDB 绿)
Primary hover#4cf490bf(绿 75% 透明度)
Secondary#a880ff(SpacetimeDB 紫)
Background(shade2)#0d0d0e(近黑)
Surface(shade1)#141416(略亮)
Border(n6)#202126
Text(n1)#e6e9f0(浅灰)
Text muted(n4)#6f7987
Accent#02befa(SpacetimeDB 蓝)
Warning#fbdc8e(黄)
Danger#ff4c4c(红)
可选头部渐变linear-gradient(266deg, #4cf490 0%, #8a38f5 100%)(绿到紫)

应用标题统一为"SpacetimeDB Chat"

七、自动化评测:如何验证"转发"是否达标

提示词系统配套了完整的评分机制(grading_rubric.md 与 grading_checklist.md),其核心方法论对转发功能同样适用:

7.1 评分规则

  • 每个功能按0–3 分打分:0 = 未实现或完全损坏;1 = 部分实现且缺失核心功能;2 = 大体可用但有次要缺陷;3 = 完全符合规格;N/A = 未包含在提示词中;
  • Prompt Level 到评分范围的映射:每个组合提示词级别只对"包含的功能"计分(如01_basic对应功能 1–4、满分 12;级别越高覆盖越多);
  • UI 契约是评分的硬依据:评分强调"实际测试胜于代码分析","代码存在 ≠ 功能可用"。

7.2 针对转发的可执行验收清单(依据 UI 契约推导)

结合 grading_rubric.md 中"每功能独立测试"的方法学,转发功能可按以下步骤验证:

  1. 用户 A 在 #general 发送一条消息;
  2. 悬停该消息,确认出现文本 "Forward"(或aria-label含 "forward")的按钮;
  3. 点击后出现频道选择器,且只列出 A 已加入的频道
  4. 选择 #design,确认 #design 中实时出现该消息副本,并带 "Forwarded from #general by @A" 归属文本;
  5. 回到 #general,确认源消息没有任何转发指示(原消息未被修改);
  6. 打开另一浏览器以用户 B(#design 成员)登录,确认 B 能实时收到转发副本;若 B 不是 #general 成员,则其看不到源消息;
  7. 验证转发者非目标频道成员时操作被拒绝(合理校验)。

这些用例恰好可以直接映射到"评分标准 3 分"的要求:转发入口可达、目标频道实时可见、归属标注正确、原消息不变。

7.3 真实评测样例

仓库中保留了真实生成的评测记录,例如 chat-app-20260102-162918/GRADING_RESULTS.md:该实例针对09_spacetime_private_rooms.md级别(功能 1–12)评分,后端 1008 行、前端约 1500 行、共 26 个文件,外部依赖仅spacetimedbreactreact-domvitetypescript,总分 34/36(94.4%),0 次重提示(reprompt)。这份记录同时印证了生成项目的典型结构:

chat-app-<时间戳>/ ├── backend/spacetimedb/ │ └── src/ │ ├── schema.ts # 表结构定义 │ └── index.ts # reducer 逻辑 └── client/ ├── src/ │ ├── App.tsx / main.tsx / styles.css │ ├── module_bindings/ # 生成绑定 │ └── components/ # 14 个组件 └── index.html

它也为"转发功能"的实际落地提供了范本:schema 定义消息表结构,index.ts 定义 reducer,客户端组件负责悬停按钮、频道选择器与归属渲染。

八、结语

17_forwarding.md不仅是一份功能规格,更是一套**"契约先行、实现自决"**的工程化验收范式:通过把用户可见的 UI 契约从实现细节中剥离出来,它让同一个功能定义可以跨技术栈(SpacetimeDB 的 TypeScript/Rust/C#、PostgreSQL 的多种组合)统一评测。对于开发者而言,本文所梳理的完整功能族、转发功能的数据模型映射,以及可执行的验收清单,可以直接复用于:

  • 基于 SpacetimeDB 构建包含转发能力的实时聊天应用(参考 sdks/typescript 的订阅/查询模型);
  • 理解 LLM 生成代码的基准测试方法(参考 tools/llm-oneshot 整套提示词与评分体系);
  • 以"UI 契约 + 黑盒测试"方式为自己开发的实时应用建立可自动化的验收标准。

转发这一看似简单的功能,在 SpacetimeDB 的"表 + reducer + 订阅"模型下,恰好是理解"副本语义 + 实时数据同步"的最佳最小示例:一次插入、一次订阅,其余全部交给数据库内置的实时同步机制完成。

【免费下载链接】SpacetimeDBDevelopment at the speed of light项目地址: https://gitcode.com/GitHub_Trending/sp/SpacetimeDB

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询