如何用无代码实现一个不会被重复抢的选座系统?

0 阅读5分钟

电影院选座,是一个非常经典但实现难度并不低的交互场景。

它不仅需要:

动态展示座位布局

实时更新座位状态

区分“自己已购买”和“别人已占用”

更关键的是:必须解决并发问题。

例如:

两个用户同时点击同一个座位时, 系统必须保证:

最终只有一个人下单成功。

很多系统会尝试通过前端刷新解决, 但实际上真正可靠的方案, 一定来自数据库底层约束。

本文将带你使用 Zion:

通过 “嵌套列表 + 条件式容器 + 联合唯一约束”

搭建一个真正具备防冲突能力的选座系统。

如何在 Zion 中构建

数据模型设计

我们需要五张表来管理用户、场次、物理布局和交易记录。

数据库表结构

1. 帐户表系统自带,记录用户信息。

2. 场次表用于区分不同时间段的占用情况。

3. 排表外层列表数据源,定义座位的纵向层级。

4. 座位表内层列表数据源,定义具体的物理坐标。

5. 订单表业务核心表,通过“唯一约束”实现防冲突。

配置唯一约束

为了防止物理重叠和重复预订,需要配置两项约束:

物理空间约束:在“座位表”中添加名为 uk_row_seat 的联合唯一约束,选择字段 排_id + 序号。确保同一排下不会出现重复位置。

业务逻辑约束:在“订单表”中添加名为 uk_session_seat 的联合唯一约束,选择字段 场次_id + 座位_id。确保同一场次下,一个座位只能产生一笔订单。

使用 Zion 的“导入”功能,通过 Excel/CSV 文件可以快速填充行和座位数据。

点击文末【阅读原文】获取

[排数据样例.xlsx]

[座位数据样例.xlsx]

UI搭建与交互配置

外层列表:排

在画布中添加一个列表组件。

在右侧“数据”面板:

数据源:选择“远程数据”。

数据表:选择“排”。

排序:添加按“序号”升序排列。

在列表项内添加一个文本组件,内容绑定为 [当前项].[名称]。

内层列表:座位

在“列表”的列表项内部嵌套第二个列表组件。

在“设计”面板将布局设置为横向排列

在右侧“数据”面板:

数据表:选择“座位”。

数据筛选:添加条件 排_id等于[外层列表.当前项].[id]。这是实现嵌套显示的核心。

排序:按“序号”升序排列。

交互逻辑配置

在内层“列表 座位”中放入一个条件式容器,根据座位的不同状态显示对应的 UI。

1. 无 (走廊/空位) 分支

条件:[当前项].[类型]等于none。

UI:保持空白或隐藏,作为走廊。

2. 已购买 (当前用户) 分支

条件:查询“订单表”,筛选 座位_id 等于当前项 ID,场次_id 等于当前场次,且 用户_id 等于 [当前用户].[id]。若数量等于 1,则当前用户拥有此座。

UI:显示蓝色勾选图标。

3. 已占用 (其他用户) 分支

条件:查询“订单表”,筛选 座位_id 等于当前项 ID,场次_id 等于当前场次,且 用户_id不等于[当前用户].[id]。若数量不等于 0,则他人已占。

UI:显示灰色图标。

4. 可选 (默认) 分支

作为默认分支,无需条件。显示空座位图标。

行为流 (Actionflow) 建设

针对不同状态的点击事件,配置以下逻辑:

取消订单 (已购买状态)

显示弹窗:确认是否取消。

删除 订单:筛选条件为 用户_id 等于当前用户且 座位_id 等于当前座位。

切换视图条件:切回“可选”状态。

占座拦截 (已占用状态)

显示提示:显示“当前座位已被预定”。

提交下单 (可选状态)

显示弹窗:确认选座。

添加 订单:映射 用户_id、场次_id 和 座位_id。

关键步骤:在冲突行为中选择 uk_session_seat,行为类型选“无”。

条件分支

下单成功:判断 [添加动作].[id] 是否非空。若是,显示成功提示并切换视图至“已购买”。

下单失败:若 ID 为空(触发了数据库唯一约束),显示“座位已被抢占”并切换视图至“已占用”。

验证

第一步:初始预订 (用户 1)

以用户 1 身份登录,选择 A 排 2 座,确认预订。

座位图标立即变为蓝色(已购买状态)。

第二步:并发会话 (用户 2)

开启无痕窗口以用户 2 身份登录。

观察到 A 排 2 座已显示为灰色(已占用),证明条件式容器生效。

用户 2 成功预订 B 排 3 座。

第三步:冲突拦截 (用户 1)

回到用户 1 的窗口(页面未刷新),B 排 3 座仍显示为黑色(可选)。

用户 1 尝试点击并确认预订 B 排 3 座。

点击确认后,数据库拦截器介入:

uk_session_seat 约束阻止了插入。

行为流检测到 ID 为空,触发失败分支

弹出提示:“该座位已被预定”。

状态回滚:座位图标无需刷新即刻由黑变灰。

第四步:释放资源

用户 1 取消其 A 排 2 座的订单。

唯一约束释放,该座位对所有用户恢复为“可选”状态。

动手尝试并深入学习

嵌套列表非常适合二维布局

条件式容器适合复杂状态 UI

联合唯一约束是防冲突核心

页面状态不能替代数据库约束

数据一致性必须由数据库保证

示例项目

go.functorz.com/7iRTWQyz