Skip to Content
最佳实践嵌套列表选座功能

嵌套列表选座功能

项目访问链接

https://zion.functorz.com/tool/nwLdKMXK0yg/WEB?code=c8sKlFmEB1qY2&ref=5316313

场景与目标

  • 目标:实现具备防冲突能力的选座功能,利用嵌套列表展示布局,并通过数据库唯一约束拦截重复下单。
  • 适用场景:电影选座、场馆预约、餐厅订座或任何基于网格的资源分配场景。
  • 核心逻辑:使用“嵌套列表”(排 -> 座位)实现布局。利用数据库的“联合唯一约束”在底层确保数据一致性,从根本上杜绝同一座位被多人同时预订。

实现步骤

数据模型设计

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

数据库表结构

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

字段名称类型说明
id长整数用户唯一标识

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

字段名称类型说明
id长整数区分不同场次

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

字段名称类型说明
名称文本如:A排、1排
序号长整数决定排在界面上的显示先后顺序

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

字段名称类型说明
序号长整数决定该排内座位的横向排列顺序
类型文本seat (座位) 或 none (走廊/空位)
排_id长整数关联关系:多对一关联至“排表”

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

字段名称类型说明
用户_id长整数关联至“帐户表”,记录购买者
场次_id长整数关联至“场次表”,锁定特定场次
座位_id长整数关联至“座位表”,锁定特定座位

配置唯一约束

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

  1. 物理空间约束:在“座位表”中添加名为 uk_row_seat 的联合唯一约束,选择字段 排_id + 序号。确保同一排下不会出现重复位置。
  2. 业务逻辑约束:在“订单表”中添加名为 uk_session_seat 的联合唯一约束,选择字段 场次_id + 座位_id。确保同一场次下,一个座位只能产生一笔订单。

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


UI搭建与交互配置

外层列表:排

  1. 在画布中添加一个列表组件。
  2. 在右侧“数据”面板:
    • 数据源:选择“远程数据”。
    • 数据表:选择“排”。
    • 排序:添加按“序号”升序排列。
  3. 在列表项内添加一个文本组件,内容绑定为 [当前项].[名称]

内层列表:座位

  1. 在“列表”的列表项内部嵌套第二个列表组件。
  2. 在“设计”面板将布局设置为横向排列
  3. 在右侧“数据”面板:
    • 数据表:选择“座位”。
    • 数据筛选:添加条件 排_id 等于 [外层列表.当前项].[id]。这是实现嵌套显示的核心。
    • 排序:按“序号”升序排列。


交互逻辑配置

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

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

  • 条件[当前项].[类型] 等于 none
  • UI:保持空白或隐藏,作为走廊。

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

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

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

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

4. 可选 (默认) 分支

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

行为流 (Actionflow) 建设

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

取消订单 (已购买状态)

  1. 显示弹窗:确认是否取消。
  2. 删除 订单:筛选条件为 用户_id 等于当前用户且 座位_id 等于当前座位。
  3. 切换视图条件:切回“可选”状态。

占座拦截 (已占用状态)

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

提交下单 (可选状态)

  1. 显示弹窗:确认选座。
  2. 添加 订单:映射 用户_id场次_id座位_id
    • ⚠️
      关键步骤:在冲突行为中选择 uk_session_seat,行为类型选“无”。
  3. 条件分支
    • 下单成功:判断 [添加动作].[id] 是否非空。若是,显示成功提示并切换视图至“已购买”。
    • 下单失败:若 ID 为空(触发了数据库唯一约束),显示“座位已被抢占”并切换视图至“已占用”。


验证

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

  1. 以用户 1 身份登录,选择 A 排 2 座,确认预订。
  2. 座位图标立即变为蓝色(已购买状态)。

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

  1. 开启无痕窗口以用户 2 身份登录。
  2. 观察到 A 排 2 座已显示为灰色(已占用),证明条件式容器生效。
  3. 用户 2 成功预订 B 排 3 座。

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

  1. 回到用户 1 的窗口(页面未刷新),B 排 3 座仍显示为黑色(可选)。
  2. 用户 1 尝试点击并确认预订 B 排 3 座。
  3. 点击确认后,数据库拦截器介入:
    • uk_session_seat 约束阻止了插入。
    • 行为流检测到 ID 为空,触发​失败分支​。
    • 弹出提示:“该座位已被预定”。
    • 状态回滚​:座位图标无需刷新即刻由黑变灰。

第四步:释放资源

  1. 用户 1 取消其 A 排 2 座的订单。
  2. 唯一约束释放,该座位对所有用户恢复为“可选”状态。

Last updated on