当前位置: 首页 > news >正文

建设主管部门门户网站制造做网站

建设主管部门门户网站,制造做网站,哪里有响应式网站企业,网站内容页显示不出来拖动代码 /*** 获取点击或触摸事件对应的座位位置* 通过事件对象获取座位的行列信息* param {Event|TouchEvent} event - 点击或触摸事件对象* returns {Object} 返回座位位置对象#xff0c;包含行(row)和列(col)信息#xff0c;若未找到有效位置则返回 {row: -1, col: -1}*…拖动代码 /*** 获取点击或触摸事件对应的座位位置* 通过事件对象获取座位的行列信息* param {Event|TouchEvent} event - 点击或触摸事件对象* returns {Object} 返回座位位置对象包含行(row)和列(col)信息若未找到有效位置则返回 {row: -1, col: -1}*/getSeatPosition(event) {// 统一处理触摸事件和点击事件// 触摸事件时从 touches 数组获取第一个触摸点// 点击事件时直接使用事件对象const touch event.touches ? event.touches[0] : event;// 获取触摸/点击的坐标位置// clientX/Y 用于标准事件x/y 用于某些特殊环境const x touch.clientX || touch.x;const y touch.clientY || touch.y;// 创建查询对象用于获取 DOM 信息当前未使用const query uni.createSelectorQuery();// 从事件目标的数据集中获取座位信息// 使用 HTML5 data-* 属性存储的行列信息if (event.target event.target.dataset) {const dataset event.target.dataset;// 检查数据集中是否包含有效的行列信息if (dataset.row ! undefined dataset.col ! undefined) {// 返回解析后的座位位置// parseInt 确保返回数值类型return {row: parseInt(dataset.row),col: parseInt(dataset.col)};}}// 如果无法获取有效的座位信息// 返回表示无效位置的对象return { row: -1, col: -1 };},/*** 处理触摸开始事件* 用于初始化拖拽和缩放的起始状态* param {TouchEvent} event - 触摸事件对象包含触摸点信息*/onTouchStart(event) {// 记录触摸开始的时间戳用于后续判断是点击还是拖动this.touchStartTime Date.now();// 重置移动标志初始状态下未发生移动this.isMoved false;// 单指触摸 - 处理拖动初始化if (event.touches.length 1) {const touch event.touches[0];// 记录当前触摸点作为上一次触摸位置用于计算移动距离this.lastTouch { x: touch.clientX, y: touch.clientY };// 记录触摸起始位置用于计算总移动距离this.touchStartPos { x: touch.clientX, y: touch.clientY };}// 双指触摸 - 处理缩放初始化else if (event.touches.length 2) {// 计算两个触摸点之间的初始距离用于后续计算缩放比例this.startDistance this.getDistance(event.touches[0], event.touches[1]);}},// 处理触摸移动事件onTouchMove(event) {// 标记已经发生移动用于区分点击和拖动this.isMoved true;// 单指触摸 - 处理拖动if (event.touches.length 1) {const touch event.touches[0];// 计算相对于上一次触摸位置的偏移量const deltaX touch.clientX - this.lastTouch.x;const deltaY touch.clientY - this.lastTouch.y;// 根据当前缩放比例调整位移距离// 缩放比例越大移动距离越小保证移动体验一致this.position.x deltaX / this.scale;this.position.y deltaY / this.scale;// 更新最后一次触摸位置this.lastTouch { x: touch.clientX, y: touch.clientY };}// 双指触摸 - 处理缩放else if (event.touches.length 2) {// 计算当前两个触摸点之间的距离const currentDistance this.getDistance(event.touches[0], event.touches[1]);// 根据距离变化计算新的缩放比例let newScale this.scale * (currentDistance / this.startDistance);// 限制缩放范围在 minScale 和 maxScale 之间newScale Math.max(this.minScale, Math.min(this.maxScale, newScale));this.scale newScale;// 更新起始距离用于下一次计算this.startDistance currentDistance;}// 检查并限制移动边界防止内容移出可视区域this.checkBoundaries();},// 处理手势结束onTouchEnd() {// 可以在这里处理手势结束后的逻辑},/*** 计算两个触摸点之间的距离* param {Object} touch1 - 第一个触摸点包含 clientX 和 clientY 坐标* param {Object} touch2 - 第二个触摸点包含 clientX 和 clientY 坐标* returns {number} 两点之间的欧几里得距离*/getDistance(touch1, touch2) {// 计算 X 轴方向的距离差const dx touch1.clientX - touch2.clientX;// 计算 Y 轴方向的距离差const dy touch1.clientY - touch2.clientY;// 使用勾股定理计算两点之间的直线距离// distance √(dx² dy²)return Math.sqrt(dx * dx dy * dy);},/*** 检查并限制座位区域的移动边界* 防止用户将座位区域拖动到视图之外*/checkBoundaries() {// 定义最大可移动距离像素const maxX 200; // X轴最大移动距离可根据实际座位区域大小调整const maxY 200; // Y轴最大移动距离可根据实际座位区域大小调整// 限制X轴移动范围[-maxX, maxX]// Math.min 确保不会超过右边界// Math.max 确保不会超过左边界this.position.x Math.max(-maxX, Math.min(maxX, this.position.x));// 限制Y轴移动范围[-maxY, maxY]// Math.min 确保不会超过下边界// Math.max 确保不会超过上边界this.position.y Math.max(-maxY, Math.min(maxY, this.position.y));}, 计算总价代码 /*** 获取指定座位在所有已选座位中的序号* param {number} row - 要查询的座位行号* param {number} col - 要查询的座位列号* returns {number} 返回该座位是第几个被选中的座位从1开始计数* * 使用场景* 1. 用于确定座位的选中顺序* 2. 可用于显示座位的选中序号* 3. 帮助用户了解座位的选择顺序*/getSelectedIndex(row, col) {// 初始化计数器从1开始计数let count 1;// 遍历所有座位for (let i 0; i this.seatMap.length; i) {for (let j 0; j this.seatMap[i].length; j) {// 检查当前遍历到的座位是否被选中if (this.seatMap[i][j].selected) {// 如果找到目标座位返回当前计数if (i row j col) return count;// 如果不是目标座位计数器加1count;}}}return count;},// 获取已选座位列表getSelectedSeats() {const selectedSeats [];this.seatMap.forEach((row, rowIndex) {row.forEach((seat, colIndex) {if (seat.selected) {selectedSeats.push({row: rowIndex,col: colIndex,type: seat.type});}});});return selectedSeats;},/*** 计算所有已选座位的总价* returns {string} 返回格式化后的总价字符串保留两位小数* * 使用场景* 1. 显示确认选座按钮上的总价* 2. 提交订单时计算支付金额* 3. 更新用户选座时实时显示价格*/getTotalPrice() {// 定义不同类型座位的价格映射const prices {pink: 40, // 粉色座位VIP座价格orange: 38, // 橙色座位情侣座价格blue: 35 // 蓝色座位普通座价格};// 使用 reduce 方法计算总价// 1. 获取所有已选座位列表// 2. 根据每个座位的类型获取对应价格// 3. 累加所有座位的价格return this.getSelectedSeats().reduce((total, seat) {// total: 累计总价// seat: 当前座位信息包含 type 属性return total prices[seat.type];}, 0).toFixed(2); // 初始值为0结果保留两位小数},/*** 获取指定类型座位的单价* param {string} type - 座位类型pink|orange|blue* returns {string} 返回格式化后的价格字符串保留两位小数* * 使用场景* 1. 显示单个座位的价格* 2. 在已选座位列表中显示每个座位的单价*/getSeatPrice(type) {// 定义不同类型座位的价格映射const prices {pink: 40, // 粉色座位VIP座价格orange: 38, // 橙色座位情侣座价格blue: 35 // 蓝色座位普通座价格};// 返回格式化后的价格保留两位小数return prices[type].toFixed(2);},/*** 处理确认选座操作* 验证选座状态并进行后续处理* * 使用场景* 1. 用户点击确认选座按钮时触发* 2. 验证是否已选择座位* 3. 进行下一步订单处理*/confirmSeats() {// 检查是否有选中的座位if (this.selectedSeatsCount 0) {// 如果没有选择座位显示提示信息uni.showToast({title: 请先选择座位,icon: none});return;}// TODO: 处理确认选座逻辑// 可以添加以下操作// 1. 获取选中的座位信息// 2. 调用后端API锁定座位// 3. 跳转到订单确认页面// 4. 处理支付流程等console.log(确认选座, this.getSelectedSeats());} 完整代码 templateview classchooseSeat!-- 价格说明 --view classprice-infoview classprice-itemview classprice-box pink/viewtext¥40.00/text/viewview classprice-itemview classprice-box orange/viewtext¥38.00/text/viewview classprice-itemview classprice-box blue/viewtext¥35.00/text/view/view!-- 银幕 --view classscreenimage classscreen-image srchttps://s.xitupt.com/tsimgs/949558333604714792/20250318/h5_mng_1742302489261modeaspectFit/image!-- view classscreen-texttextIMAX/texttext4DX/text/view --/view!-- 座位区域 --view classseat-container!-- 修改行号部分让它和座位区域一起缩放移动 --view classseat-area-wrapper :style{transform: scale(${scale}) translate(${position.x}px, ${position.y}px),transformOrigin: 0 0} touchstartonTouchStart touchmoveonTouchMove touchendonTouchEnd!-- 行号 --view classrow-numbersview v-fori in 6 :keyi classrow-number{{ i }}/view/view!-- 座位图 --view classseats-areaview v-for(row, rowIndex) in seatMap :keyrowIndex classseat-rowview v-for(seat, colIndex) in row :keycolIndex classseat :class[seat.type,{selected: seat.selected,sold: seat.sold}] :data-rowrowIndex :data-colcolIndex tap.stopselectSeat(rowIndex, colIndex)image v-ifseat.selected classseat-selected-imagesrchttps://s.xitupt.com/tsimgs/949558333604714792/20250318/h5_mng_1742303462702 modeaspectFit/image/view/view/view/view/view!-- 底部固定区域 --view classbottom-fixed!-- 卡片部分 --view classinfo-cardview classmovie-infoview classmovie-titletext classtitle初步举证/text/viewview classmovie-timetext classtoday今天/texttext classtime14:10-16:25/text/view!-- 已选座位区域 --view classselected-seats v-ifselectedSeatsCount 0!-- 已选标签和数量 --view classselected-headertext classselected-label已选/texttext classselected-count{{ selectedSeatsCount }}个座位/text/view!-- 座位详情列表 --scroll-view classseats-scroll scroll-x show-scrollbarfalseview classseats-containerview classseat-tag v-for(seat, index) in getSelectedSeats() :keyindexview classseat-infoview classseat-position{{ ${seat.row 1}排${seat.col 1}座 }}/viewview classseat-price¥{{ getSeatPrice(seat.type) }}/view/viewtext classclose tap.stopselectSeat(seat.row, seat.col)×/text/view/view/scroll-view/view/view/view!-- 按钮部分 --view classbutton-wrapperview classconfirm-button :class{ disabled: selectedSeatsCount 0 } tapconfirmSeatstext¥{{ getTotalPrice() }} 确认选座/text/view/view/view/view /templatescript export default {data() {return {seatMap: [], // 座位数据isDragging: false, // 是否正在拖动中dragAction: false, // 拖动动作(true:选择, false:取消选择)lastDragPosition: { row: -1, col: -1 }, // 上一次拖动的位置scale: 1, // 当前缩放比例startDistance: 0, // 开始的手势距离position: { x: 0, y: 0 }, // 添加位置信息lastTouch: { x: 0, y: 0 }, // 记录上次触摸位置minScale: 0.5, // 最小缩放比例maxScale: 2, // 最大缩放比例maxSelectedSeats: 40, // 最多可选座位数selectedSeatsCount: 0, // 当前已选座位数touchStartTime: 0, // 触摸开始的时间戳用于区分点击和拖动touchStartPos: { x: 0, y: 0 }, // 触摸开始的位置用于计算移动距离isMoved: false, // 是否发生了移动用于区分点击和拖动事件}},created() {this.initSeatMap()},methods: {/*** 初始化座位图数据* 创建一个二维数组来表示影院座位布局*/initSeatMap() {// 定义座位图的尺寸const rows 6 // 总行数const cols 8 // 每行座位数// 创建二维数组并初始化每个座位的属性this.seatMap Array(rows).fill().map((_, rowIndex) Array(cols).fill().map((_, colIndex) ({// 根据位置确定座位类型粉色/橙色/蓝色type: this.getSeatType(rowIndex, colIndex),// 初始状态为未选中selected: false,// 随机设置座位是否已售出sold: this.getRandomSoldStatus(rowIndex, colIndex)})))},getSeatType(row, col) {// 第一列和第二列、倒数第二列、倒数第一列是蓝色if (col 2 || col 5) {return blue}// 第三列和倒数第三列是橙色if (col 2 || col 5) {return orange}// 第一行的第四第五列是橙色if (row 0 (col 3 || col 4)) {return orange}// 第五行的第四第五列是橙色if (row 5 (col 3 || col 4)) {return orange}// 第四第五列的第二到第四行是粉色if ((col 3 || col 4) (row 1 row 4)) {return pink}return blue // 默认蓝色},/*** 处理座位选择事件* 用于切换座位的选中状态并管理已选座位数量* param {number} row - 座位所在行号* param {number} col - 座位所在列号*/selectSeat(row, col) {// 防止拖动操作触发选座// 当用户拖动查看座位时不应触发选座操作if (this.isMoved) return;// 检查座位是否可选// 验证座位是否存在且未售出if (!this.isSeatSelectable(row, col)) return;// 获取目标座位对象const seat this.seatMap[row][col];// 检查是否超出最大可选座位数// 仅在要选中新座位时进行检查if (!seat.selected this.selectedSeatsCount this.maxSelectedSeats) {// 显示提示信息uni.showToast({title: 最多只能选择${this.maxSelectedSeats}个座位,icon: none});return;}// 切换座位选中状态seat.selected !seat.selected;// 更新已选座位计数// 选中时 1取消选中时 -1this.selectedSeatsCount seat.selected ? 1 : -1;},// 随机设置部分座位为已售getRandomSoldStatus(row, col) {// 约20%的概率将座位标记为已售return Math.random() 0.2;},// 检查座位是否可选择isSeatSelectable(row, col) {// 确保座位存在且未售出return this.seatMap[row] this.seatMap[row][col] !this.seatMap[row][col].sold;},/*** 获取点击或触摸事件对应的座位位置* 通过事件对象获取座位的行列信息* param {Event|TouchEvent} event - 点击或触摸事件对象* returns {Object} 返回座位位置对象包含行(row)和列(col)信息若未找到有效位置则返回 {row: -1, col: -1}*/getSeatPosition(event) {// 统一处理触摸事件和点击事件// 触摸事件时从 touches 数组获取第一个触摸点// 点击事件时直接使用事件对象const touch event.touches ? event.touches[0] : event;// 获取触摸/点击的坐标位置// clientX/Y 用于标准事件x/y 用于某些特殊环境const x touch.clientX || touch.x;const y touch.clientY || touch.y;// 创建查询对象用于获取 DOM 信息当前未使用const query uni.createSelectorQuery();// 从事件目标的数据集中获取座位信息// 使用 HTML5 data-* 属性存储的行列信息if (event.target event.target.dataset) {const dataset event.target.dataset;// 检查数据集中是否包含有效的行列信息if (dataset.row ! undefined dataset.col ! undefined) {// 返回解析后的座位位置// parseInt 确保返回数值类型return {row: parseInt(dataset.row),col: parseInt(dataset.col)};}}// 如果无法获取有效的座位信息// 返回表示无效位置的对象return { row: -1, col: -1 };},/*** 处理触摸开始事件* 用于初始化拖拽和缩放的起始状态* param {TouchEvent} event - 触摸事件对象包含触摸点信息*/onTouchStart(event) {// 记录触摸开始的时间戳用于后续判断是点击还是拖动this.touchStartTime Date.now();// 重置移动标志初始状态下未发生移动this.isMoved false;// 单指触摸 - 处理拖动初始化if (event.touches.length 1) {const touch event.touches[0];// 记录当前触摸点作为上一次触摸位置用于计算移动距离this.lastTouch { x: touch.clientX, y: touch.clientY };// 记录触摸起始位置用于计算总移动距离this.touchStartPos { x: touch.clientX, y: touch.clientY };}// 双指触摸 - 处理缩放初始化else if (event.touches.length 2) {// 计算两个触摸点之间的初始距离用于后续计算缩放比例this.startDistance this.getDistance(event.touches[0], event.touches[1]);}},// 处理触摸移动事件onTouchMove(event) {// 标记已经发生移动用于区分点击和拖动this.isMoved true;// 单指触摸 - 处理拖动if (event.touches.length 1) {const touch event.touches[0];// 计算相对于上一次触摸位置的偏移量const deltaX touch.clientX - this.lastTouch.x;const deltaY touch.clientY - this.lastTouch.y;// 根据当前缩放比例调整位移距离// 缩放比例越大移动距离越小保证移动体验一致this.position.x deltaX / this.scale;this.position.y deltaY / this.scale;// 更新最后一次触摸位置this.lastTouch { x: touch.clientX, y: touch.clientY };}// 双指触摸 - 处理缩放else if (event.touches.length 2) {// 计算当前两个触摸点之间的距离const currentDistance this.getDistance(event.touches[0], event.touches[1]);// 根据距离变化计算新的缩放比例let newScale this.scale * (currentDistance / this.startDistance);// 限制缩放范围在 minScale 和 maxScale 之间newScale Math.max(this.minScale, Math.min(this.maxScale, newScale));this.scale newScale;// 更新起始距离用于下一次计算this.startDistance currentDistance;}// 检查并限制移动边界防止内容移出可视区域this.checkBoundaries();},// 处理手势结束onTouchEnd() {// 可以在这里处理手势结束后的逻辑},/*** 计算两个触摸点之间的距离* param {Object} touch1 - 第一个触摸点包含 clientX 和 clientY 坐标* param {Object} touch2 - 第二个触摸点包含 clientX 和 clientY 坐标* returns {number} 两点之间的欧几里得距离*/getDistance(touch1, touch2) {// 计算 X 轴方向的距离差const dx touch1.clientX - touch2.clientX;// 计算 Y 轴方向的距离差const dy touch1.clientY - touch2.clientY;// 使用勾股定理计算两点之间的直线距离// distance √(dx² dy²)return Math.sqrt(dx * dx dy * dy);},/*** 检查并限制座位区域的移动边界* 防止用户将座位区域拖动到视图之外*/checkBoundaries() {// 定义最大可移动距离像素const maxX 200; // X轴最大移动距离可根据实际座位区域大小调整const maxY 200; // Y轴最大移动距离可根据实际座位区域大小调整// 限制X轴移动范围[-maxX, maxX]// Math.min 确保不会超过右边界// Math.max 确保不会超过左边界this.position.x Math.max(-maxX, Math.min(maxX, this.position.x));// 限制Y轴移动范围[-maxY, maxY]// Math.min 确保不会超过下边界// Math.max 确保不会超过上边界this.position.y Math.max(-maxY, Math.min(maxY, this.position.y));},/*** 获取指定座位在所有已选座位中的序号* param {number} row - 要查询的座位行号* param {number} col - 要查询的座位列号* returns {number} 返回该座位是第几个被选中的座位从1开始计数* * 使用场景* 1. 用于确定座位的选中顺序* 2. 可用于显示座位的选中序号* 3. 帮助用户了解座位的选择顺序*/getSelectedIndex(row, col) {// 初始化计数器从1开始计数let count 1;// 遍历所有座位for (let i 0; i this.seatMap.length; i) {for (let j 0; j this.seatMap[i].length; j) {// 检查当前遍历到的座位是否被选中if (this.seatMap[i][j].selected) {// 如果找到目标座位返回当前计数if (i row j col) return count;// 如果不是目标座位计数器加1count;}}}return count;},// 获取已选座位列表getSelectedSeats() {const selectedSeats [];this.seatMap.forEach((row, rowIndex) {row.forEach((seat, colIndex) {if (seat.selected) {selectedSeats.push({row: rowIndex,col: colIndex,type: seat.type});}});});return selectedSeats;},/*** 计算所有已选座位的总价* returns {string} 返回格式化后的总价字符串保留两位小数* * 使用场景* 1. 显示确认选座按钮上的总价* 2. 提交订单时计算支付金额* 3. 更新用户选座时实时显示价格*/getTotalPrice() {// 定义不同类型座位的价格映射const prices {pink: 40, // 粉色座位VIP座价格orange: 38, // 橙色座位情侣座价格blue: 35 // 蓝色座位普通座价格};// 使用 reduce 方法计算总价// 1. 获取所有已选座位列表// 2. 根据每个座位的类型获取对应价格// 3. 累加所有座位的价格return this.getSelectedSeats().reduce((total, seat) {// total: 累计总价// seat: 当前座位信息包含 type 属性return total prices[seat.type];}, 0).toFixed(2); // 初始值为0结果保留两位小数},/*** 获取指定类型座位的单价* param {string} type - 座位类型pink|orange|blue* returns {string} 返回格式化后的价格字符串保留两位小数* * 使用场景* 1. 显示单个座位的价格* 2. 在已选座位列表中显示每个座位的单价*/getSeatPrice(type) {// 定义不同类型座位的价格映射const prices {pink: 40, // 粉色座位VIP座价格orange: 38, // 橙色座位情侣座价格blue: 35 // 蓝色座位普通座价格};// 返回格式化后的价格保留两位小数return prices[type].toFixed(2);},/*** 处理确认选座操作* 验证选座状态并进行后续处理* * 使用场景* 1. 用户点击确认选座按钮时触发* 2. 验证是否已选择座位* 3. 进行下一步订单处理*/confirmSeats() {// 检查是否有选中的座位if (this.selectedSeatsCount 0) {// 如果没有选择座位显示提示信息uni.showToast({title: 请先选择座位,icon: none});return;}// TODO: 处理确认选座逻辑// 可以添加以下操作// 1. 获取选中的座位信息// 2. 调用后端API锁定座位// 3. 跳转到订单确认页面// 4. 处理支付流程等console.log(确认选座, this.getSelectedSeats());}} } /scriptstyle scoped .chooseSeat {width: 100%;min-height: 100vh;padding: 20rpx;box-sizing: border-box; }.chooseSeat-header {padding: 20rpx 0;text-align: center;font-size: 32rpx;font-weight: bold; }.price-info {display: flex;justify-content: space-around;margin: 20rpx 0; }.price-item {display: flex;align-items: center; }.price-box {width: 30rpx;height: 30rpx;margin-right: 10rpx;border-radius: 4rpx; }.price-box.pink {background-color: #FF3162; }.price-box.orange {background-color: #F6BB7F; }.price-box.blue {background-color: #8BBFF0; }.screen {margin: 40rpx 0;text-align: center; }.screen-image {width: 90%;height: 60rpx;margin: 0 auto 10rpx; }.seat-container {width: 100%;height: 100%;display: flex;margin-top: 40rpx;user-select: none;touch-action: none;/* overflow: hidden; *//* 防止缩放时溢出 */ }/* 新增包装器样式 */ .seat-area-wrapper {display: flex;will-change: transform;touch-action: none; }/* 修改行号样式 */ .row-numbers {width: 35rpx;margin-right: 75rpx;background: rgba(0, 0, 0, 0.3);border-radius: 36rpx;display: flex;flex-direction: column; }.row-number {height: 50rpx;/* 与座位高度一致 */line-height: 50rpx;text-align: center;font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #FFFFFF;margin-bottom: 20rpx;/* 与座位间距一致 */ }.row-number:last-child {margin-bottom: 0;/* 最后一个行号不需要底部间距 */ }.seat-row {display: flex;justify-content: space-between;margin-bottom: 20rpx;/* 修改座位行间距为20rpx */ }.seat-row:last-child {margin-bottom: 0;/* 最后一行不需要底部间距 */ }.seat {width: 50rpx;height: 50rpx;margin-right: 20rpx;background-color: #fff;border-radius: 8rpx;position: relative;transition: transform 0.3s ease;/* 添加过渡效果 */ }.seat:last-child {margin-right: 0;/* 最后一个座位不需要右边距 */ }.seats-area {flex: 1;will-change: transform;touch-action: none;padding: 0;/* 移除内边距 */ }/* 修改选中状态的样式 */ .seat.selected {transform: scale(1.05);/* 恢复放大效果 */ }/* 选中图片样式 */ .seat-selected-image {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1;pointer-events: none; }/* 修改选中状态的边框样式 */ .seat.selected.pink {border: 2rpx solid #FF3162; }.seat.selected.orange {border: 2rpx solid #F6BB7F; }.seat.selected.blue {border: 2rpx solid #8BBFF0; }/* 未选中状态样式 */ .seat.pink {border: 2rpx solid #FF3162; }.seat.orange {border: 2rpx solid #F6BB7F; }.seat.blue {border: 2rpx solid #8BBFF0; }/* 已售出座位的样式 */ .seat.sold {background-color: #F5F5F5;border-color: #E0E0E0;opacity: 0.6;cursor: not-allowed;transition: all 0.2s ease;filter: grayscale(100%); }.seat.sold::after {content: ×;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);font-size: 24rpx;color: #999; }/* 添加hover效果 */ .seat:active:not(.sold) {opacity: 0.8;transform: scale(0.95); }/* 底部固定区域 */ .bottom-fixed {position: fixed;left: 0;bottom: 0;width: 100%;z-index: 100;display: flex;flex-direction: column; }/* 卡片样式 */ .info-card {margin: 20rpx;padding: 20rpx;background-color: #fff;border-radius: 16rpx;box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); }.movie-title {margin-bottom: 16rpx; }.movie-title .title {font-size: 32rpx;font-weight: bold;margin-right: 20rpx; }.movie-time {display: flex;align-items: center;margin-bottom: 16rpx; }.movie-time .today {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #FF3162;margin-right: 8rpx; }.movie-time .time {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #666666; }.selected-seats {display: flex;flex-direction: column;gap: 16rpx; }.selected-header {display: flex;align-items: center; }.selected-label {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #666666; }.selected-count {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #FF3162;margin-left: 8rpx; }/* 滚动区域样式 */ .seats-scroll {width: 100%;white-space: nowrap;overflow: hidden; }/* 座位容器样式 */ .seats-container {display: inline-flex;align-items: center; }.seat-tag {width: 147rpx;height: 64rpx;background: #F4F5F7;border-radius: 10rpx;display: inline-flex;align-items: center;justify-content: space-between;padding: 0 16rpx;margin-right: 10rpx;flex-shrink: 0; }.seat-info {display: flex;flex-direction: column;align-items: flex-start; }.seat-position {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 24rpx;color: #666666; }.seat-price {font-family: PingFang SC, PingFang SC;font-weight: 400;font-size: 20rpx;color: #FF3162; }.seat-tag .close {color: #999;font-size: 28rpx; }.seat-tag:last-child {margin-right: 0; }/* 按钮容器 */ .button-wrapper {padding: 20rpx;background-color: #fff; }/* 确认按钮样式 */ .confirm-button {width: 100%;height: 88rpx;background: linear-gradient(to right, #ff3162, #ff6c89);border-radius: 44rpx;display: flex;justify-content: center;align-items: center;color: #fff;font-size: 32rpx;font-weight: 500;margin-bottom: constant(safe-area-inset-bottom);/* iOS 11.2 */margin-bottom: env(safe-area-inset-bottom);/* iOS 11.2 */ }.confirm-button.disabled {background: #ccc;opacity: 0.8; } /style
http://www.zqtcl.cn/news/729478/

相关文章:

  • 重庆智能网站建设价格毕业设计做系统跟做网站哪个容易
  • 淘宝美工做兼职的网站多多返利网站建设
  • 如何承接设计网站建设电商平台开发流程
  • 安康做网站简洁高端的wordpress个人博客
  • 酒店网站建设协议手机怎么做销售网站
  • 屏蔽网站接口js广告seminar
  • 谁有手机网站啊介绍一下wordpress 流量插件
  • 杭州网站公司google网站建设
  • 莱芜住房和城乡建设厅网站网站头部设计
  • 织梦响应式茶叶网站模板邯郸最新通告今天
  • 深圳公司网站改版通知做网站分类链接
  • 电子商务网站建设答案网络运营与维护
  • 网站登陆怎么做网站app的区别
  • 获取网站缩略图工信部2017网站备案
  • 有哪些网站可以做ps挣钱自己制作游戏
  • 旅游网站开发团队四川住房和城乡建设网站
  • 网站框架设计商城网站制作需要多少费用
  • 网站建设哪个公司个人网站做哪种能赚钱
  • 福建建设人才与科技发展中心seo导航站
  • 修文县生态文明建设局网站郑州制作网站哪家好
  • 泉州网站优化排名东莞长安做网站公司
  • 网站制作公司 顺的有口碑的赣州网站建设
  • 成都网站设计制作苏州新闻
  • 黑色网站设计iis 网站 红
  • 专业做家居的网站佛山做网站永网
  • 医疗网站建设讯息企业门户网站建设思路
  • 四川建设安全监督管理局网站网站传送门怎么做
  • 哪家网站做推广好优化师和运营区别
  • 鹰潭网站建设公司南宁行业平台开发公司
  • 织梦如何仿手机网站源码奉贤区专业建网站