Skip to content

SelectSeat 选座 ​

平台兼容性 ​

App Web 微信小程序
√ √ √

说明 ​

影院 / 剧场 / 巴士等场景的图形化选座:座位平面以画布渲染,支持单指拖动平移、双指缩放、点按选中或取消座位;座位可声明禁用(已售)、空位(走道缺口)、图片座位、逐座位配色与图标。选中集合经 v-model 绑定({row, col} 数组,行列从 0 起),左侧行号条随视图平移缩放联动。

  • 无 seats 数据时按 rows × cols 自动生成满布座位
  • 双指缩放以触点中心为基准,范围 minScale ~ maxScale;平移范围受约束(内容边缘最多进入视图 20% 空白)
  • 拖动超过 10px 判定为视图调整,松手不再触发选座(防滚动浏览误选)
  • 手势轴向锁定:首段位移主方向判定(阈值 6px)——横向为主才平移座位平面,纵向为主判为页面滚动意图(本轮手势不平移、不选座)。页面内嵌画布时纵向滑动交还页面滚动(Web/App 端动态不阻断;微信端 catch 静态阻断页面滚动为平台限制,座位不再跟随跑动)
  • 禁用与空位不响应点选;选中态绘制顺序:座位图片 > 选中背景 + 图标

基本用法 ​

html
<template>
	<view>
		<n-select-seat
			v-model="picked"
			:rows="8"
			:cols="12"
			:seats="seatList"
			:width="343"
			:height="300"
			@seat-click="onSeatClick"
			@move="onMove"
		/>
	</view>
</template>

<script setup lang="uts">
	import { ref } from "vue";
	import { type NSelectSeatItem, type NSelectSeatValue, type NSelectSeatMoveDetail } from "@/uni_modules/new-ui/components/n-select-seat/props";

	const picked = ref<NSelectSeatValue[]>([{ row: 0, col: 3 } as NSelectSeatValue]);

	// 座位数据(示例:禁用 + 空位 + 情侣座图标)
	const seatList: NSelectSeatItem[] = [
		{ row: 1, col: 2, disabled: true } as NSelectSeatItem,
		{ row: 1, col: 3, empty: true } as NSelectSeatItem,
		{ row: 7, col: 5, icon: "heart-fill", color: "#f472b6" } as NSelectSeatItem
	];

	function onSeatClick(seat: NSelectSeatItem): void {
		console.log(`${seat.row + 1}排${seat.col + 1}座`);
	}

	function onMove(detail: NSelectSeatMoveDetail): void {
		// detail.screenTranslateX 可驱动银幕图等装饰层同步平移
		console.log(detail.scale);
	}
</script>

API ​

Properties ​

属性 类型 默认值 说明
modelValue NSelectSeatValue[] [] 选中座位集合({row, col} 数组,行列从 0 起);外部变化后画布按值重绘,组件点选后经 update:model-value 回写
rows number 0 行数(无 seats 数据时按 rows × cols 自动生成满布座位)
cols number 0 列数(无 seats 数据时按 rows × cols 自动生成满布座位)
seats NSelectSeatItem[] [] 座位数据(空数组时按 rows/cols 自动生成;每项含坐标与外观状态)
seat-gap number 8 座位间距 px
border-radius number 8 座位圆角 px
border-width number 1 座位描边宽度 px(0 = 无描边)
min-scale number 1 最小缩放倍数(双指缩放下限)
max-scale number 3 最大缩放倍数(双指缩放上限)
width number | string 300 画布宽度(数字 = px;字符串支持 px / rpx)
height number | string 300 画布高度(数字 = px;字符串支持 px / rpx)
color string #d4d4d4 未选中图标色(浅色主题);座位级 color 优先
dark-color string #737373 未选中图标色(深色主题);座位级 color 优先
bg-color string #ffffff 未选中背景色(浅色主题);座位级 bgColor 优先
dark-bg-color string #262626 未选中背景色(深色主题);座位级 bgColor 优先
border-color string #e5e6eb 未选中描边色(浅色主题);座位级 borderColor 优先
dark-border-color string #333333 未选中描边色(深色主题);座位级 borderColor 优先
selected-bg-color string #10b981 选中背景色;座位级 selectedBgColor 优先
selected-color string #ffffff 选中图标色
selected-icon string check 选中图标名(内置图标表名称;座位级 selectedIcon 优先;空串不绘制图标)
selected-image string "" 选中图片地址(优先于选中背景 + 图标绘制,按座位尺寸圆角裁剪)
image string "" 未选中图片地址(优先于背景 + 描边绘制,按座位尺寸圆角裁剪)
custom-class string "" 根节点类名(须为本组件样式表内定义的类)
custom-style string "" 根节点行内样式,尾拼可覆盖内部值(含尺寸)

座位数据项 NSelectSeatItem:{ row, col, disabled?, empty?, color?, bgColor?, borderColor?, selectedBgColor?, selectedColor?, selectedIcon?, selectedImage?, icon?, image? }(行列从 0 起;disabled 禁用不响应点选、empty 空位不绘制但保留位置;外观字段缺省回落组件级同名属性与主题自动色;icon / selectedIcon 为内置图标表名称)。

NSelectSeatStyle 为不含坐标的字段子集,用于 setSeat() 局部更新。

Event ​

事件名 参数 说明
update:modelValue NSelectSeatValue[] 选中集合变化(v-model),点选翻转时触发
seat-click NSelectSeatItem 座位被点击且选中状态翻转时触发,参数为座位数据项(禁用与空位不触发)
move NSelectSeatMoveDetail 拖动或缩放过程中触发,参数 {translateX, translateY, scale, screenTranslateX}(screenTranslateX 为内容未缩放坐标系下的横向视口偏移,可驱动银幕图等装饰层同步平移)
error string 画布通道失败 / 绘制异常时触发,参数为错误说明

Method ​

方法名 参数 说明
setSeat (row: number, col: number, patch: NSelectSeatStyle) 局部更新座位数据(合并字段)并重绘;坐标不存在时忽略
getSeats () 获取内部座位表(含自动生成的座位;引用即内部状态,修改后调 draw() 生效)
draw () 重新绘制(手动修改座位数据后调用)

Slot ​

无插槽。

实现说明(与参考实现的机制对照) ​

机制 参考实现 本库实现 理由
触摸绑定 手势三事件绑在 canvas 元素上 绑在组件根 view(画布铺满根,命中区一致) 各端 canvas 元素的事件转发行为不一致(点选与手势事件在部分端不回传);根 view 绑定为画布族验证过的可靠通道
图标绘制 组件图标字体运行时查表(名称 → 码点 + 字体名)后 fillText 同机制,查库内置图标表 + 库图标字体 fillText 图标资产与名称表随库发行;check-line 等参考侧图标名换成库内置表名称(勾 = check)
width / height 仅 number(页面量宽后传入) number 或 px / rpx 字符串(rpx 随窗口宽度换算) 与库内画布族(chart / qrcode / barcode)尺寸语义一致
error 事件 无(画布失败静默) 画布通道失败 / 绘制异常显式发 error 库内画布族一致约定:错误显式暴露,不静默吞错
toPng 导出 无 不收录 选座为交互组件,画布内容非保存 / 分享产物,导出无业务价值
setSeat 参数 UTSJSONObject + 运行时合并 类型化 NSelectSeatStyle(不含坐标的字段子集) 编译期字段校验,避免运行时字段名拼写静默失效
行号条触摸 无处理(条覆盖画布左缘可拦截触摸) 行号条 pointer-events: none 装饰条不应吃掉覆盖区域的座位点选
图片加载失败 静默跳过(缓存未命中回退背景形态) 同语义:失败不入缓存,绘制时回退背景 + 图标形态 座位图片是可选装饰,失败回退不阻断选座主功能
深浅主题 isDark 监听重绘(未选中三色换 dark 系) 同机制(useTheme 主题单例 isDark 重绘) 一致
导出图片缓存 模块级 Map 缓存(src → Image) 组件实例 Map,卸载时清空 避免跨实例残留与内存滞留

记录 · 思考 · 创作