

电影院选座,是一个非常经典但实现难度并不低的交互场景。
它不仅需要:
动态展示座位布局
实时更新座位状态
区分“自己已购买”和“别人已占用”
更关键的是:必须解决并发问题。
例如:
两个用户同时点击同一个座位时, 系统必须保证:
最终只有一个人下单成功。
很多系统会尝试通过前端刷新解决, 但实际上真正可靠的方案, 一定来自数据库底层约束。
本文将带你使用 Zion:
通过“嵌套列表 + 条件式容器 + 联合唯一约束”,
搭建一个真正具备防冲突能力的选座系统。
我们需要五张表来管理用户、场次、物理布局和交易记录。
1. 帐户表系统自带,记录用户信息。
2. 场次表用于区分不同时间段的占用情况。
3. 排表外层列表数据源,定义座位的纵向层级。
4. 座位表内层列表数据源,定义具体的物理坐标。
5. 订单表业务核心表,通过“唯一约束”实现防冲突。
为了防止物理重叠和重复预订,需要配置两项约束:
物理空间约束:在“座位表”中添加名为 uk_row_seat 的联合唯一约束,选择字段 排_id + 序号。确保同一排下不会出现重复位置。
业务逻辑约束:在“订单表”中添加名为 uk_session_seat 的联合唯一约束,选择字段 场次_id + 座位_id。确保同一场次下,一个座位只能产生一笔订单。
使用 Zion 的“导入”功能,通过 Excel/CSV 文件可以快速填充行和座位数据。
点击文末【阅读原文】获取
[排数据样例.xlsx]
[座位数据样例.xlsx]
在画布中添加一个列表组件。
在右侧“数据”面板:
数据源:选择“远程数据”。
数据表:选择“排”。
排序:添加按“序号”升序排列。
在列表项内添加一个文本组件,内容绑定为 [当前项].[名称]。
在“列表”的列表项内部嵌套第二个列表组件。
在“设计”面板将布局设置为横向排列。
在右侧“数据”面板:
数据表:选择“座位”。
数据筛选:添加条件 排_id等于[外层列表.当前项].[id]。这是实现嵌套显示的核心。
排序:按“序号”升序排列。
在内层“列表 座位”中放入一个条件式容器,根据座位的不同状态显示对应的 UI。
条件:[当前项].[类型]等于none。
UI:保持空白或隐藏,作为走廊。
条件:查询“订单表”,筛选 座位_id 等于当前项 ID,场次_id 等于当前场次,且 用户_id 等于 [当前用户].[id]。若数量等于 1,则当前用户拥有此座。
UI:显示蓝色勾选图标。
条件:查询“订单表”,筛选 座位_id 等于当前项 ID,场次_id 等于当前场次,且 用户_id不等于[当前用户].[id]。若数量不等于 0,则他人已占。
UI:显示灰色图标。
作为默认分支,无需条件。显示空座位图标。
针对不同状态的点击事件,配置以下逻辑:
显示弹窗:确认是否取消。
删除 订单:筛选条件为 用户_id 等于当前用户且 座位_id 等于当前座位。
切换视图条件:切回“可选”状态。
显示提示:显示“当前座位已被预定”。
显示弹窗:确认选座。
添加 订单:映射 用户_id、场次_id 和 座位_id。
关键步骤:在冲突行为中选择 uk_session_seat,行为类型选“无”。
条件分支:
下单成功:判断 [添加动作].[id] 是否非空。若是,显示成功提示并切换视图至“已购买”。
下单失败:若 ID 为空(触发了数据库唯一约束),显示“座位已被抢占”并切换视图至“已占用”。
以用户 1 身份登录,选择 A 排 2 座,确认预订。
座位图标立即变为蓝色(已购买状态)。
开启无痕窗口以用户 2 身份登录。
观察到 A 排 2 座已显示为灰色(已占用),证明条件式容器生效。
用户 2 成功预订 B 排 3 座。
回到用户 1 的窗口(页面未刷新),B 排 3 座仍显示为黑色(可选)。
用户 1 尝试点击并确认预订 B 排 3 座。
点击确认后,数据库拦截器介入:
uk_session_seat 约束阻止了插入。
行为流检测到 ID 为空,触发失败分支。
弹出提示:“该座位已被预定”。
状态回滚:座位图标无需刷新即刻由黑变灰。
用户 1 取消其 A 排 2 座的订单。
唯一约束释放,该座位对所有用户恢复为“可选”状态。
嵌套列表非常适合二维布局
条件式容器适合复杂状态 UI
联合唯一约束是防冲突核心
页面状态不能替代数据库约束
数据一致性必须由数据库保证
https://go.functorz.com/7iRTWQyz
选座系统核心难点:并发冲突与数据一致性
数据模型设计:5张表构建选座底层逻辑
关键配置:数据库联合唯一约束(防抢座核心)
零代码UI搭建:嵌套列表实现座位布局智能
状态展示:条件式容器自动切换座位状态
交互逻辑:行为流实现选座/取消/拦截全流程
实战验证:并发抢座测试与效果演示

