BizLink · bizlinkbiz.com · 产品线解耦 V1.0

产品矩阵解耦 · 智能会议系统与 AI 中台

本件回答两个问题:这一大堆东西怎么切开,让每一块都能独立卖、独立交付、独立演进; 以及本轮新增的五项能力(分会场 / 3D 展位 / 物料裂变 / AI 中台 / 现场端侧)在已核实事实下该怎么定规格。 00 节先给出四项判断,其中一项是劝退;02 节是解耦的完整工程方案。

主文档补充件 · 第 12 号 2026-09-18 法律法规已核实原文 含 3 条新红线 成本核算为量级估算

00本轮判断:四项,其中一项是劝退

你这次给的约束条件(百人内小会场、礼品百元内)把上一份文档的抽奖合规结论整个改写了。 结论:那条最大的风险消失了,但换成了另外两条原本不起眼的风险。此外本轮新查出三条红线, 它们看似分散在三个毫不相干的领域,却全部发生在同一个技术环节——这是 07 节 AI 中台必须内置合规网关的直接依据。

00.1 四项判断一览

#判断依据与后果结论
1抽奖的风险等级整个降级,但风险换了位置 礼品 ≤100 元 vs 法定最高奖 5 万元上限 —— 相差 500 倍,第三项完全无压力。
但《反不正当竞争法》第十条还有第(一)项「有奖销售信息不明确」和第(二)项「谎称有奖或内定人员中奖」, 这两项恰恰是现场小奖最容易犯的。
系统要做的从「金额校验」变成「可审计」。
风险改位
2「学员发朋友圈换礼品」是广告行为,不是打卡 《互联网广告管理办法》第九条第三款:通过体验分享等形式推销商品或服务,并附加购物链接等购买方式的, 应当显著标明「广告」——你的物料恰恰都带链接。发布者是学员本人,学员即「广告发布者」(该办法第四条明列自然人适用)。 必须改造
3佣金必须单层,且要在代码里硬限制 「层级在三级以上 + 三十人以上」即可追究组织领导传销活动的刑事责任(2013 年公通字 37 号)。 以销售业绩为依据的单层佣金完全合法(马哥给的报名费 10% 就是这一形态);
一旦允许「下线业绩给上线提成」,性质立刻变成团队计酬——司法解释的问题 Giving 见 06.3。
硬编码约束
43D 展位不要做成「拍照重建」 3D 高斯泼溅的几何精度约 7.82cm 平均误差,做不了面积计量;而「准确面积」恰恰是你最重要的字段 (面积决定价格)。面积只能来自场馆的 CAD 平面图。
且空宴会厅每次布置都不同,重建一次复用价值有限。
方案调整

00.2 诚实交代:上一份文档有一条结论作废

作废:《智能会场执行》06 节「抽奖三颗雷」中的第一条

当时我把「最高奖不得超过 5 万元」列为抽奖的头号风险,并据此设计了系统的硬校验。 你补充「礼品都是 100 元以下」之后,这条退居次要 —— 100 元 vs 5 万元,差 500 倍,永远不会触碰。

替换上来的两条是:信息不明确(第十条第一项)与 内定中奖(第十条第二项)。 它们的处罚依同一法条(第二十二条,四万元以上二十万元以下罚款);
更重要的是这两条在系统上的答案完全不同——不是「校验一个数字」,而是「让抽奖过程可复现、可举证」。详见 04.4。

00.3 本轮核实依据

事项核实到的原文要点来源可信度
有奖销售 《反不正当竞争法》第十条:经营者进行有奖销售不得存在下列情形:(一) 所设奖的种类、兑奖条件、奖金金额或者奖品等有奖销售信息不明确,影响兑奖;(二) 采用谎称有奖或者故意让内定人员中奖的欺骗方式进行有奖销售;(三) 抽奖式的有奖销售,最高奖的金额超过五万元。 法律原文已核实
朋友圈分享 《互联网广告管理办法》第九条第三款 + 第四条(利用互联网为广告主发布广告的自然人适用广告发布者规定)+ 第十六条(平台经营者义务) 市场监管总局令第 72 号,中国政府网已核实
分销层级 2013 年《关于办理组织领导传销活动刑事案件适用法律若干问题的意见》:层级三级以上且人员三十人以上追究刑责;第五条:以销售业绩为计酬依据的单纯「团队计酬」不作为犯罪处理,但实质以发展人员数量为计酬依据的以组织领导传销活动罪论处 最高人民法院公报已核实
证书称谓 人社部函〔2022〕25 号:重点审核违规使用「中华人民共和国」「中国」「中华」「国家」「全国」「职业资格」「执业资格」「岗位合格(凭证)」「专业技术职务」「职业技能鉴定」「职业技能等级」等字样;禁用「包过」「上岗必须」「X 天拿证」「挂靠」「高薪入职」等宣传词 人社部官网已核实
3D 重建精度 高斯泼溅平均几何误差约 7.82cm;摄影测量配合控制点可达 1~3cm;两者定位「可视化 vs 测量」 第三方技术评测量级
3DGS 自采成本 国内公开测算:手机/微单采集 + 本地处理,单套综合成本约 ¥80~160,含 GPU 算力约 ¥16 公开技术博客测算仅参考

00.4 一个贯穿全件的观察

三条新红线指向同一个技术位置

广告标识义务、传销层级限制、证书禁用词 —— 分属三部完全不同的法规,看似互不相干。 但它们有一个共同点:全部作用在「内容被生成出来的那一刻」

物料是 AI 生成的;推广链接是系统按模板拼的;课程宣传语很可能也是 AI 写的。 也就是说,违规内容不是人写出来的,是系统产出的 —— 而你要的恰恰是让它自动批量产出。

这意味着合规不能靠「运营审核一遍」这种人工环节兜住 —— 产量一大必然漏。 唯一可行的位置是在生成/分发的管道上做一道强制拦截。这就是 07 节的「合规网关」。 它不是外挂的审核功能,是 AI 中台的出口闸门:内容不出网关,就不允许被发布。

01产品矩阵:先定义什么才算「能独立运作」

你说「会议系统、AI 中台都可以独立运作,也可以 OEM 给园区、会展中心、酒店」。 这句话成立与否,取决于一件事:「独立」能不能被验收。
如果它只是一个形容词,那么三个月后一定会变成「改一个抽奖字段要回归测试整套 CRM」。 所以先把标准定死 —— 下列五条,缺一条就不许宣称独立。

01.1 独立性的五个可验证条件

#条件可验收的定义为什么这条不能省
1数据自洽 该产品拥有的全部数据表,与其他产品的表之间没有外键约束。删除该产品的全部数据后,其余产品功能不受任何影响。 最常见也最难改。共享外键一上手就赢不了,后期只能靠数据迁移才能分开。
2部署独立 可以只对它发一次版:npm run deploy --pkg=booth,其余产品不停机、不重启、不需同步发布。 做不到全量发布,就永远不敢在会前一周改动 —— 而会场类产品恰恰最需要会前改动。
3依赖单向 允许依赖下层内核,禁止依赖兄弟产品。产品之间不认识对方的存在。这条在 CI 里用静态检查卡住(见 02.4)。 今天是 lateral 依赖,明天就是循环依赖。循环依赖出现之日就是单体退化之日。
4契约通信 跨产品只能通过「 API 调用」或「领域事件」两种形式,禁止跨库 JOIN、禁止 import 对方的内部类 这是把「物理拆分」推后也能保持逻辑解耦的唯一办法 —— 你可以先不拆服务,但必须先拆契约。
5账单可算 该产品能独立核算:独立定价、独立统计用量、独立算出毛利率。 算不出账的产品,被砍掉时无法判断得失 —— 结果就是什么都不敢砍,需求无限膨胀。
这五条的顺序不是随便排的

条件 1~3 是能不能拆,条件 4 是拆完之后会不会重新长回去,条件 5 是商业上值不值得拆
绝大多数听起来很美的「微服务」死在条件 4 —— 代码拆了,但彼此 import 对方的内部实现,改一处两边一起崩。

01.2 产品全景:三层结构

P2 交付形态(包装方式,不是产品) SaaS 多租户 私有化单实例 OEM 白标交付 API / SDK 独立小程序 正交组合 P1 产品层(可独立售卖、独立交付、独立演进) M1 智能会场 分会场·签到·抽奖·需求 M2 3D 展位招商 选位·定价·预订·装修 M3 裂变分发 物料·一键转发·回流 M4 AI 中台 生成·合规网关·知识库 M5 现场端侧 签到屏·求助·组网 M6 线索总线 授权·投递·CRM 对接 M7 保本测算 Cost Cover Gate M8 获客与客服 会话·报名转化·工单 其余(内容制作分发、露营养老、证书管理等)二期再说,位置预留但不先建房 P0 共享内核(不单独售卖,是所有产品的地基) IAM / 多租户 工作流引擎 事件总线 文件与媒体 计费与分账 审计与合规管道 单一数据库 Schema + 单一 ORM + 单一认证体系 —— 允许共享实例,但必须通过 Schema 隔离,禁止共享表
图 1 · 产品三层结构。 关键不在「分了几层」,而在箭头的方向:P1 只能向下依赖 P0,禁止横向依赖;P2 与 P1 正交,同一个产品可以有五种交付形态。 这条约束一旦被破坏,「独立运作」就只是一句 PPT。

01.3 独立性验收:当前八项的达标情况

产品①数据自洽②部署独立③依赖单向④契约通信⑤账单可算备注
M1 智能会场 天然独立,学员数据自成一域
M2 3D 展位 ④ 有风险:很容易直接读写 M1 的场次表
M3 裂变分发 ③ 有风险:天然想依赖 M2 的展商数据
M4 AI 中台 独立性最强,且是唯一可反向输出的
M5 现场端侧 离线数据同步是难点;建议单卖硬件+服务包
M6 线索总线 可做成完全独立的小服务
M7 保本测算 上一个文档已论证:独立性最好的切入点
M8 获客客服 基于开源件二次封装,注意许可证边界

◯ = 设计上可达 | △ = 需要在 02 节用手段强制 | ✕ = 需要重构。 当前八项全部可达 ◯,前提是把 02 节的两处薄弱点先补掉。

01.4 三条反模式(做到是指标,犯了是返工)

反模式一:用「共享这个类吧」代替契约

两个产品都需要「场次」,于是共用一个 Entity 类 —— 半年后给 A 加字段,B 崩了。 正确做法:各自存自己关心的那几个字段(往往是 id 和名称),靠事件同步。重复三行代码,换回十年不耦合。

反模式二:为 OEM 客户开分支

园区客户要求改个字段、改个流程 —— 一行 if (tenant == 'xxx'),就是最终长出几十个分支的开端。 正确做法:一切差异必须是配置或插件,内核只读。改不了内核,你就知道自己该拒绝这个需求,而不是接下一个外包项目。

反模式三:先拆服务,后拆数据

最热闹的失败方式:起了八个 Kubernetes 服务,但它们连同一个库同一个表 —— 于是获得了分布式的全部缺点,没得到任何解耦好处。 正确做法:数据先按 01.1 第 1 条切干净,服务怎么部署是后面再说的事。

02解耦架构:两个正交切面与四道强制手段

你这套系统里有两套隔离维度经常被混为一谈:多租户隔离,和产品边界隔离。 它们不是一回事,搞混是这类平台最常见的结构性错误。

02.1 先分清楚:垂直切与水平切

垂直切 —— 多租户(同一套功能,按客户隔离) 平安 A 企业的全部数据 示波器 B 主播的全部数据 某园区客户的全部数据 手段:tenant_id 列 + 数据库行级安全策略 问题:绝不能漏一次过滤,否则就是数据泄露事故 水平切 —— 产品边界(同一个客户,按功能隔离) 会场数据 展位数据 线索数据 AI 生成数据 账单数据 日志数据 手段:每个产品独立数据库 schema,禁止跨 schema 外键 问题:不能图方便写一 JOIN,写完就拆不开了 两者正交:最终数据单元 = 「某个产品的某个 schema 里,tenant_id 等于某个值的一行」 SELECT * FROM booth.slot WHERE tenant_id = $1 —— 产品由 schema 决定,租户由行决定,互不干扰
图 2 · 两套隔离维度。红色管的是「谁的数据」,蓝色管的是「哪个功能的数据」。 真正事故往往出在两者的组合错误:产品边界写对了,但忘了带 tenant_id —— 于是 A 主播看到了 B 企业的学员名单。

02.2 数据边界的四条硬规则

#规则具体定义违反的后果
1一个产品一个 schema P1 每个产品独占 PostgreSQL 一个 schema(venue / booth / viral / aihub ...),产品名称即 schema 名。 共享一个 schema,就等于把删除权交给了所有人
2禁止跨 schema 外键 表之间只能用「弱引用」—— 存对方 id(UUID),不加 FOREIGN KEY 约束。引用完整性由应用层保证,不做级联删除。 有了外键,删一条展位订单会连带级联删掉别的模块的记录
3禁止跨 schema JOIN 查询只能在本 schema 内进行。需要别的产品数据,要么调 API,要么订阅事件后冗余存储到自己库里(推荐后者)。 一次 JOIN 让两个产品的发布绑死在一起
4每个表必须有 tenant_id 除系统级字典表外,业务表一律带 tenant_id UUID NOT NULL,并启用行级安全策略。缺失该列的表,迁移脚本直接报错。 这是唯一一种「一次疏忽就是数据泄露」的错误

02.3 跨产品通信:只开放三种形式

形式什么时候用约束
查询 API需要即时读到对方的数据(如展位页要显示场次名称) 只读,且必须由被调用方提供稳定契约;调用方要把结果缓存或落地,避免强依赖可用性。
命令 API需要对方做事(如「冻结这个展位」) 幂等,必须带幂等键;失败可重试。
领域事件通知「某件事已发生」(如 attendee.checked_in 首选方式。单向广播,发布者不知道谁在听 —— 这是最松的耦合。采用事务发件箱模式保证不丢。
为什么领域事件是首选

它不是架构洁癖,是解耦力度不一样: 调用 API 时,A 知道 B 的存在,B 挂了 A 就得做降级;发事件时,A 根本不知道有没有人在听,B 挂了 A 完全不受影响。

具体到你的场景:学员签到是一个事件。AI 中台可以听(做人群画像)、线索总线可以听(给展商推通知)、 会场大屏可以听(更新到场率)——三个订阅方随时可以加,会场系统一行代码都不用改。 这就是「 _____ —— 这正是你要的「}}}
换成三个 await NotificationService.xxx() 调用,每加一个订阅方,签到服务就得改一次。

02.4 怎么让规则真的生效:四道 CI 强制手段

规则写在文档里等于没有。必须让它在 CI 里跑起来,违反就红。

① 依赖关系检查(阻断横向依赖)

用 dependency-cruiser 或自定义 ESLint 规则:P1 产品模块只能 import @core/*禁止 import 其他产品模块的内部文件

② SQL 静态扫描(阻断跨库 JOIN)

扫描迁移文件与查询语句,正则匹配 JOIN <其他schema>. 与缺 tenant_id 的建表语句,直接报错。

③ 契约版本检查(阻断静默破坏)

产品对外 API 与事件 schema 变更必须通过兼容性检查;不兼容变更需走「新版本号 → 双写过渡 → 下线旧版」三步。

④ 单产品部署演练(验证第 2 条独立性)

CI 里每周一次的流水线:只构建并部署某一个产品到测试环境,其余产品镜像不变。跑不通说明耦合了。

参考实现:依赖关系检查规则

// .dependency-cruiser.js —— 放进 CI,违反即构建失败
module.exports = {
  forbidden: [
    {
      name: 'no-cross-product-import',
      comment: 'P1 产品之间禁止互相引用内部实现,只能走 @core 或事件',
      from:   { path: '^src/products/([^/]+)/' },
      to:     {
        path: '^src/products/([^/]+)/',
        pathNot: '^src/products/$1/',
      },
    },
    {
      name: 'no-deep-import-into-core',
      comment: '只能通过 @core/xxx 的公开入口,禁止直接摸内核内部文件',
      from:   { path: '^src/products/' },
      to:     { path: '^src/core/(?!index|public)' },
    },
  ],
};

参考实现:按产品切分 schema 与租户列的数据库骨架

-- 每个产品一个 schema;禁止跨 schema 外键,只做弱引用
CREATE SCHEMA booth;

CREATE TABLE booth.slot (
  id            UUID PRIMARY KEY,
  tenant_id     UUID NOT NULL,          -- 垂直切:租户
  event_ref     UUID NOT NULL,          -- 弱引用 venue.session.id,无外键
  code          TEXT NOT NULL,
  area_sqm      NUMERIC(8,2) NOT NULL,   -- 来自场馆图纸,不是 3D 重建结果
  price_cny     NUMERIC(12,2) NOT NULL,
  geom          JSONB NOT NULL,          -- 摊位多边形顶点,业务图层的真相来源
  status        TEXT NOT NULL,          -- available / held / sold / blocked
  UNIQUE (tenant_id, event_ref, code)
);

-- 行级安全:漏写 tenant_id 过滤也不会越权
ALTER TABLE booth.slot ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON booth.slot
  USING (tenant_id = current_setting('app.tenant_id')::UUID);
一个反直觉的建议:现在不要拆微服务

你最终可能确实需要拆,但顺序不能错:先按上面的规则把数据和契约切干净, 将来某个产品真的需要独立扩容或被单独交付给 OEM 客户时,再把它抽出去单独部署 —— 那时的成本是改配置,不是重构。

反过来(先拆服务后拆数据)会得到分布式系统的全部缺点,却得不到解耦的任何好处。

03OEM 交付形态:五种买家,五套话术

同一套 booth.slot 表,卖给会展中心和卖给酒店,卖的不是同一个东西。 OEM 最常见的失败就是把「换 logo + 换域名」当成全部工作,结果客户问「这对我有什么用」时答不上来。

03.1 买家全景:同一个产品,不同的主语

买家他的真实痛点他要买的交付形态定价方式优先级
大型会展中心 场租单价被压、淡季空置、展后用完即走拿不到数据;展商年年流失 场地的数字化销售前台:把每一个厅、每一块区域变成可在线看位、选位、下单的商品 私有化 + 其域名下嵌 iframe 年费 + 成交额抽成(低) 首选
大型酒店(宴会厅) 宴会部靠电话和熟人;婚宴公司-会议品类的线上成交几乎没有;客人问「你们厅多大」要看 PDF 宴会厅的在线选位与预订,尤其是培训/会务这类非婚宴场景 SaaS 为主,PMS 对接 月费按门店数 首选
地方园区 / 政府机构 要给入驻企业做「增值服务」但手上没东西;需要数字化政绩 园区企业服务门户里的「活动与培训」板块 私有化,数据不出园区 项目制 + 年运维 跟进
行业主办方 / 主播 前面几份文档论证过:跑得动一场,跑不动第二场 整套办会操作系统(M1+M2+M3+M7) SaaS 多租户 按场次 / SaaS 订阅 自有为主战场
活动公司 / 承办方 接单靠关系,交付靠 Excel,和客户对账靠微信截图 给客户看的进度透明工具(这是他拿单的武器) SaaS,多项目隔离 低月费或免费,靠 GMV 反哺 渠道角色
一个很实在的选择:先做酒店,而不是先做会展中心

会展中心话语权强、决策链长、往往已有成熟系统和长期供应商; 而酒店的痛更具体、更没人管 —— 宴会部至今基本靠电话和微信。 更重要的是:酒店同时也是你自己的供给侧。 卖给酒店一套系统,顺带把这家酒店变成了你可以随时调用的会场资源 —— 卖出一个客户,同时解决一个供给。 这在别人那里是两件事,在你这里是一件事。这是你的结构性优势。

03.2 OEM 的三层可变项:哪些能改,哪些绝对不能改

层次可调整的内容实现方式目标覆盖率说明
品牌层名称、Logo、域名、主色、字体、邮件/短信签名、小程序名称 配置文件 + 主题变量100%必须全部可配,且不能改代码
业务层模块开关、字段是否必填、审批流节点、计价规则、角色权限模板 功能开关 + 流程模板80% 剩下的 20% 用插件接口,不改内核
数据层数据存在谁那里、是否能导出、留存多久 部署形态(SaaS / VPC / 本地)100% 每层必须有明确选项,不能口头承诺
内核层数据库结构、核心领域逻辑、认证与权限机制 不可协商
这一条决定了你是产品公司还是外包公司

内核一旦对某个客户开放修改,你就获得了一个客户和一份不可复用的代码。 判断标准依旧是那一条:新增一个客户的边际交付工时是否趋近于零。

实操建议:当客户提出一个必须改内核才能满足的需求时,先算账 —— 若这批需求可以沉淀成一个通用插件,且预估有 3 个以上客户会用,则做;否则明确告知「这条我们不做,但可以这样绕过去」。 拒绝一个需求,比接下一个项目更有价值。

03.3 OEM 的隐性成本:别重复踩版本碎片化的坑

前面《后端选型与供给侧引擎》里论证过给客户部署开源件的最大风险是版本碎片化。OEM 完全同理 —— 而且更贵,因为 OEM 客户是大客户,他会打电话。

手段做法不可妥协的程度
单一版本轨道所有 OEM 实例跑同一个版本号,不维护多个长期支持分支
自动升级OEM 实例默认开启自动升级,窗口可协商但不能无限推迟
遥测与健康回传版本、错误率、关键指标回传;写入合同的运维条款中(先谈清楚,避免事后争议)
集中管控台一侧能看见所有 OEM 实例健康状态,出问题比你先知道
升级前自动备份与回滚每次升级前快照,一键回滚
验收标准只有一句

做不到「一台服务器上一键安装 + 后台点一下升级」之前,不要卖 OEM。 否则你卖的不是产品,是一份没有出口的运维债务。

03.4 反向 OEM:AI 中台是你唯一能完全控制的资产

为什么它能反向输出

前几份文档查实过:Dify 的 Modified Apache 2.0 附加条款限制多租户供给;Chatwoot 的 SSO/白标/权限在企业版包里。 外购/外挂的 AI 能力,你无法给它任何许可证承诺。自建的部分反过来 —— 每一行代码都是你的。

它能卖给谁

OEM 客户买会场系统时,往往会顺带问「你们那个 AI 能不能也给我用」。 此刻 M4 就是一个完全独立的商品:知识库 + 问答 + 合规网关,不依赖任何会场功能。

这也是它必须满足 01.1 那五条独立性标准的第二个理由 —— 第一次是因为红线就压在它这里(架构上必须隔离),第二次是因为它自己就是一个独立商品(商业上独立核算)。

04M1 分会场子系统:八个二维码撑起的新场景

你说的那段现场观察里,最关键的判断是这句:「抽奖只在百人以内的小会场,大会场不做」。 这句话的产品含义远大于它看起来 —— 因为它意味着分会场不是主会场的附属品,它是一个独立的经营单元: 有自己的主题、自己的赞助商、自己的礼品预算、自己的学员名单。

04.1 分会场的功能清单与对应痛点

你的原话痛点对应功能载体说明
学员找不到自己的会场分会场导航页:全部分会场主题、时间、地点、导师、当前状态 小程序 + 蓝牙信标走到哪个区域页面自动切换(蓝牙信标方案已在上一份文档核实)
不知道主题会场具体内容和流程会程详情页:议题、发言单位、时间节点、讲义下载 H5发言单位就是赞助商,天然是招商位
不知道哪些学员进来了分会场扫码签到 二维码 + 小程序这是整套数据资产的源头
咨询互动场内提问墙:匿名提问、点赞排序、主持端投影 H5 + 大屏提问即需求采集,见 04.5
抽奖可审计抽奖 小程序见 04.4,重点变了
收集用户需求需求登记:勾选式需求标签 + 留资授权开关 H5勾选比开放填空填写率高得多
分摊礼品经费 / 给服务商做推广分会场招商位礼品认领 后台见 06 节与 09 节
结束后我们不知道谁进了哪个场分会场复盘报表 后台这是给赞助商看的交付物

04.2 一个分会场页面的信息架构

分会场入口 门口立牌 / 桌面卡二维码 扫码 → 我是谁 首次需授权登录 之后全场免扫码 蓝牙自动识别到场 关键:一次授权,全场通行。 每换一个会场都要扫一次, 填写率会断崖式下跌。 分会场主页(四段式,顺序固定) ① 我在这场 主题 · 时段 · 室号 · 当前发言单位 · 下一个环节倒计时 ② 议程与讲师 时间轴 · 发言单位 Logo(= 赞助位)· 讲义/PPT/资料下载 ③ 参与 提问墙 · 需求勾选 · 抽奖报名 · 资料领取授权开关 ④ 带走 多风格物料(端重/活泼/好玩)挑选 → 一键转发朋友圈 → 领礼品 ④ 是 06 节裂变分发的入口,也是合规风险最高的一屏 后台同步产出 实时在场人数(按人,不靠估算) 到场率 vs 报名数 提问与需求标签词云 抽奖审计记录(可举证) 转发曝光数与来源追溯 → 事件推送给 M4/M6 全部通过事件广播,M1 不认识下游
图 3 · 分会场页面结构。顺序不能乱 —— 学员打开后第一屏必须先确认「我来对了地方」, 否则后面所有转化都无从谈起。④的位置必须在最后:先让他获得内容价值,再请求传播。

04.3 数据模型(独立 schema:venue)

-- 分会场:一个独立经营单元,有自己的主题、场地容量、赞助归属
CREATE TABLE venue.sub_session (
  id            UUID PRIMARY KEY,
  tenant_id     UUID NOT NULL,
  event_ref     UUID NOT NULL,        -- 弱引用主会场
  topic         TEXT NOT NULL,
  room_label    TEXT,
  starts_at     TIMESTAMPTZ,
  capacity      INT,
  beacon_key    TEXT,                    -- 蓝牙信标标识,用于自动识别到场
  sponsor_ref   UUID,                    -- 弱引用该分会场的冠名赞助商
  status        TEXT NOT NULL
);

-- 签到记录:每条都要能回答「谁、几点、进的哪个场、授权的什么」
CREATE TABLE venue.sub_checkin (
  id            BIGSERIAL PRIMARY KEY,
  tenant_id     UUID NOT NULL,
  session_ref   UUID NOT NULL,
  attendee_ref  UUID NOT NULL,
  via           TEXT NOT NULL,        -- qr / beacon / manual
  checked_in_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (tenant_id, session_ref, attendee_ref)
);

-- 需求勾选:结构化,便于二次销售与课程设计
CREATE TABLE venue.demand_tag (
  id            BIGSERIAL PRIMARY KEY,
  tenant_id     UUID NOT NULL,
  session_ref   UUID NOT NULL,
  attendee_ref  UUID NOT NULL,
  tag_code      TEXT NOT NULL,
  lead_consent  BOOLEAN NOT NULL DEFAULT false,  -- 是否同意转给服务商
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

04.4 抽奖:从「校验金额」改为「全程可举证」

既然《反不正当竞争法》第十条第(三)项(最高奖 5 万元)对百元礼品不构成压力, 系统真正要防的是第(一)项「信息不明确」和第(二)项「内定中奖」

法定要求系统落地做法为什么这样做才有效
信息明确(种类、兑奖条件、奖品) 抽奖前展示规则卡:奖项名称、数量、奖品、参与条件、开奖时间、兑换方式。规则卡生成版本号,每次展示都可回溯到当时那一版。 纠纷发生时,你能拿出的不是「我们当时说了」,是一份带时间戳的规则快照
不得内定 开奖瞬间冻结名单快照(写哈希);随机数种子公开;抽奖结果 = f(快照哈希, 种子)。任何人可复核重算,得到同一批中奖者。 把「我们没作弊」从辩解变成可验算的数学
奖品来源可追 记录每件奖品的提供方(主办方 / 某服务商),并在规则卡上明示。 奖品由服务商提供时,明确谁是经营者,避免责任归属不清
// 抽奖结果必须可复现:同样的输入,任何时候重算都得到同一个人
async function draw(req) {
  // 1. 冻结名单并落哈希 —— 之后名单再变也不影响已开出的结果
  const pool   = await freezePool(req.sessionRef, req.ruleVersion);
  const poolHash = sha256(pool.attendeeIds.join(','));

  // 2. 种子:由规则版本号 + 冻结时间戳 + 可选的现场公证输入构成
  const seed = sha256(`${req.ruleVersion}:${pool.frozenAt}:${req.liveInput ?? ''}`);

  // 3. 确定性洗牌 —— 不用 Math.random(),它不可回放
  const rng   = makeSeededRandom(seed);
  const winners = await pickWithoutReplacement(pool, rng, req.prizeCount);

  // 4. 存证:这条记录就是日后用于举证的完整材料
  await saveEvidence({
    sessionRef: req.sessionRef, ruleVersion: req.ruleVersion,
    poolHash, seed, liveInput: req.liveInput ?? null,
    winners, operatorId: req.operatorId, drawnAt: new Date(),
  });

  return winners;   // 事后调用 verify(poolHash, seed) 可复算,结果必然一致
}
这一段代码的价值不在技术难度,在于它把举证责任从人转到了记录

对开发来说这只是几十行代码,价值在于它把举证责任从「人怎么说」转移到了「记录怎么算」: 学员质疑「是不是内定了」时,答复不再是道歉或口头保证,而是「这是当时的名单哈希、种子和算法,你可以自己重算」。

对主办方而言,这种可举证能力本身就是产品的一部分 —— 它是别家抽奖软件给不了的东西。

04.5 需求勾选:把「用户想要什么」变成可售资产

为什么用勾选而不是填空

开放填空题的填写率通常远低于勾选;而结构化标签才能汇总成商品。 「我想找储能项目甲方」和一段自由文本,前者能直接卖给服务商,后者不能。

留资开关必须与需求分离

勾需求是免费的;「同意把我的联系方式给相关服务商」必须是独立开关,默认关闭。 这是《个人信息保护法》下最稳妥的做法,也是后续能否变现的前提 —— 未经授权的线索一分钱都不值。

需求标签汇总后有三条变现路径:给主办方(下次办什么课)、给服务商(精准线索,按条或打包计费)、 给产品研发(哪些主题值得做)。第一条免费,第二三条收费,而它们的成本是同一份数据。

05M2 3D 展位子系统:拍照做成 3D,但摊位不能靠拍照定

本节有一项和你的设想不一致,我先说结论

你想的是「拍照实现 3D 效果 → 展位规划(准确 3D 位置、价格、面积)→ 线上预览 → 预定 → 线上装修」。 这条链里,第一步到第二步之间断开了: 拍照重建出来的东西做不了面积和尺寸的法定依据,而面积恰恰是定价的基础。

但 3D 拍照本身不是没用 —— 它在另一个场景里价值极高(见 05.5)。 结论不是放弃 3D,是把它放回正确的位置。

05.1 技术现实:两种重建方式的定位不同

维度3D 高斯泼溅(你设想的方向)摄影测量(Mesh)谁更适合
几何精度平均误差约 7.82cm配合控制点可达 1~3cm摄影测量
渲染速度浏览器实时 60fps需预处理高斯泼溅
复杂材质玻璃、反光、水表现优秀容易出网格瑕疵高斯泼溅
可编辑性有限(不能像 mesh 那样改特定的面)完全可编辑摄影测量
模型体积压缩后约 8~30MB,加载 3 秒内纹理图导致体积更大高斯泼溅
专业定位「可视化」对战「测量」 —— 这是两者的本质区别

来源:第三方评测机构 2026 年对比数据。说明:7.82cm 是平均几何误差,用于观看完全足够,用于「这个摊位 36.5㎡」则不可。

三个理由说明为什么不能用它来定面积
  1. 精度不够 —— 7.82cm 误差在同一个摊位上就是零点几平方米,而面积直接乘单价。
  2. 法律风险更现实 —— 一旦展商质疑「你们标的面积和实测不符」,你能拿出的应该是有盖章的场馆平面图纸,不是一份 AI 重建的点云。
  3. 根本用不上 —— 宴会厅的摊位绝大多数是规则矩形排布的,本来就不需要重建。用二维矢量多边形表达,精度是毫米级且可编辑。

05.2 正确的三层结构

第 1 层 · 视觉底图 拍照重建(高斯泼溅) · 一次扫描,长期复用 · 只看不做 —— 没有任何字段依赖它 · 作用:让人一眼看懂现场长什么样 · 它可以是空的,系统照样能用 · 成本:自采约 ¥80~160/套(公开测算,量级) 把它当成「装修效果图的底层」 第 2 层 · 矢量业务图层 场馆 CAD / 平面图 → 多边形 · 这才是真相来源: площадь 面积从这里来 · 摊位多边形、通道、柱子、门、电箱 · 可编辑:合并/拆分摊位随时改 · 精度取决于图纸,与拍照无关 · 判断遮挡多的情况的自由性 决定「能不能卖、卖多少钱」的是这一层 第 3 层 · 状态着色层 实时业务数据叠加显示 · 绿=可售 黄=已锁定 红=已售出 灰=不可售 · 悬停显示:编号 / 面积 / 单价 / 位置说明 · 「距离主入口 12 米」「在茶歇区主动线上」 · 这些描述比 3D 更能促成决策 · 相邻摊位是谁、是否有竞品的摊位 决定「他买不买」的信息在这一层
图 4 · 展位系统的三层真相。关键设计:第 1 层可以缺失,系统照样运行。 先看会不会因为 3D 没做完就整个不能上线 —— 把 3D 放在可以被跳过的那一层,它才是一个加分项而不是阻塞项。

05.3 「线上装修」到底要做什么:不要建模,要挂载

你提到「预定后线上装修成自己公司的宣传效果,上传可以分享给客户的公司网站、APP、方案文档」。 这一句里包含两种不同的东西,容易做成成本黑洞。

诉求❌ 过度设计的做法✅ 正确的做法理由
装修成宣传效果让展商在 3D 里拖拽搭建 3D 展台、换材质 上传背景图 + Logo + 主色,自动生成谈二维码页 展商的目的是「有人扫的时候有东西看」,不是玩 3D
上传公司网站、APP、方案文档做一个站内 CMS 让用户重新录入一遍 挂载外链 + 文件直传,学员扫码后一站式获取 重新录入的填写率极低,且立刻变成过时信息
能分享给客户复杂的私域系统 一个短链 + 一张带二维码的海报 展商真正会用的是扫码那一刻能不能顺畅拿到资料
由此得到一个更准的产品定义

这个子系统的价值不是「3D 展位图」,而是 「数字化展包」 —— 展商买了摊位,拿到的是一个能扫码带走资料的页面,而不是一块物理空间。

这也解释了为什么之前几份文档反复强调「数据和结构化 Ask 才是资产」: 物理摊位一天就拆了,数字展包能长期存在,而且能被统计访问量。它能按访问量向展商收费。

05.4 数据模型(独立 schema:booth)

-- 面积、价格来自第 2 层;3D 底图只是可选的可视化资源
ALTER TABLE booth.slot ADD COLUMN visual_ref   TEXT;    -- 3D 资源地址,可空
ALTER TABLE booth.slot ADD COLUMN walk_desc    TEXT;    -- 位置描述:距入口/主动线/邻近业态
ALTER TABLE booth.slot ADD COLUMN source      TEXT NOT NULL DEFAULT 'blueprint';

-- 数字展包:这才是展商真正购买并长期使用的东西
CREATE TABLE booth.digital_kit (
  id            UUID PRIMARY KEY,
  tenant_id     UUID NOT NULL,
  slot_ref      UUID NOT NULL,
  exhibitor_ref UUID NOT NULL,
  theme_json    JSONB,                    -- 背景/主色/Logo,而非 3D 模型
  links_json    JSONB,                    -- 外挂的官网/APP/文档链接
  docs_json     JSONB,                    -- 直传文件清单
  short_code    TEXT UNIQUE,              -- 摊位二维码指向的固定短码
  view_count    BIGINT NOT NULL DEFAULT 0     -- 可计量,可作为加价依据
);

05.5 同一项技术在两个场景里的价值差了 10 倍

场景3D 拍照的价值是否做说明
自己办的培训会
(临时布置的宴会厅)
低。每次布置都不同,重建一次只能用一场;而且是临时场地,没人看 不做 用第 2 层矢量图 + 几张现场照片足够
OEM 给会展中心
(固定场馆)
。一次扫描,承接的所有活动都能复用;本来就有「虚拟展馆」招标需求 分摊到几十场活动后,单场成本近乎为零
OEM 给酒店
(固定宴会厅)
中高。宴会厅布置变化不大,客户决策周期长多次查看 尤其适合婚宴之外的会议场景
这就是解耦带来的第二个具体收益

同一套代码,技术组件是可选安装的,而不是必须。 自用时关掉 3D 也能跑(节省 ¥80~160/场 × N 场); 卖给会展中心时打开它,它从「我自己用不上」变成对方的采购理由

这也再一次说明 01 节的判断:产品有多条不同的销售路径,才值得去谈迁移。只有一条用途的功能,做了就是浪费。