diff --git a/app.json b/app.json index 21cb189..ce8a09d 100644 --- a/app.json +++ b/app.json @@ -8,7 +8,8 @@ "pages/seller/index", "pages/profile/index", "pages/notopen/index", - "pages/create-supply/index" + "pages/create-supply/index", + "pages/goods-detail/goods-detail" ], "subpackages": [ { diff --git a/pages/buyer/index.js b/pages/buyer/index.js index ca2c941..540d5e4 100644 --- a/pages/buyer/index.js +++ b/pages/buyer/index.js @@ -1642,7 +1642,7 @@ Page({ }); }, - // 显示商品详情 + // 跳转到商品详情页面 showGoodsDetail: function (e) { // 检查用户是否登录 const openid = wx.getStorageSync('openid'); @@ -1664,17 +1664,11 @@ Page({ } const goodsItem = e.currentTarget.dataset.item; - this.setData({ - currentGoodsDetail: goodsItem, - showGoodsDetail: true + // 跳转到商品详情页面,并传递商品数据,使用encodeURIComponent编码JSON字符串 + wx.navigateTo({ + url: '/pages/goods-detail/goods-detail?goodsData=' + encodeURIComponent(JSON.stringify(goodsItem)) }); - // 隐藏底部导航栏 - 通过更新全局数据 - const app = getApp(); - if (app && app.globalData) { - app.globalData.showTabBar = false; - } - // 同时尝试直接更新tabBar的选中状态 if (typeof this.getTabBar === 'function' && this.getTabBar()) { const tabBar = this.getTabBar(); @@ -1693,36 +1687,7 @@ Page({ ); }, - // 关闭商品详情 - closeGoodsDetail: function () { - this.setData({ - showGoodsDetail: false, - currentGoodsDetail: {} - }); - - // 显示底部导航栏 - 通过更新全局数据 - const app = getApp(); - if (app && app.globalData) { - app.globalData.showTabBar = true; - } - - // 同时尝试直接更新tabBar的选中状态 - if (typeof this.getTabBar === 'function' && this.getTabBar()) { - const tabBar = this.getTabBar(); - if (tabBar.setData) { - tabBar.setData({ show: true }); - } - } - }, - // 在详情弹窗中点击"我想要"按钮 - onClickWantInDetail: function (e) { - const goodsId = e.currentTarget.dataset.id; - // 先关闭详情弹窗 - this.closeGoodsDetail(); - // 然后调用原来的"我想要"方法 - this.onClickWant({ currentTarget: { dataset: { id: goodsId } } }); - }, // 获取手机号并登录 onGetPhoneNumber: function (e) { diff --git a/pages/buyer/index.wxml b/pages/buyer/index.wxml index e801e27..e0aec79 100644 --- a/pages/buyer/index.wxml +++ b/pages/buyer/index.wxml @@ -189,103 +189,7 @@ - - - - - - 商品详情 - × - - - - - - - - - - - - - - - - - - {{currentGoodsDetail.name}} - 价格: {{currentGoodsDetail.price || '暂无'}} - - - - - 地区 - {{currentGoodsDetail.region}} - - - 规格 - {{currentGoodsDetail.spec || '无'}} - - - 蛋黄 - {{currentGoodsDetail.yolk || '无'}} - - - 斤重 - {{currentGoodsDetail.displayGrossWeight}} - - - 件数 - {{currentGoodsDetail.minOrder}}件 - - - 关注人数 - {{currentGoodsDetail.reservedCount || 0}}人 - - - - - - 联系信息 - - 👤 - 联系人: {{currentGoodsDetail.product_contact || '暂无'}} - - - 📞 - 联系电话: {{currentGoodsDetail.contact_phone || '暂无'}} - - - - - - - - - - - - - + diff --git a/pages/goods-detail/goods-detail.js b/pages/goods-detail/goods-detail.js new file mode 100644 index 0000000..6845cf0 --- /dev/null +++ b/pages/goods-detail/goods-detail.js @@ -0,0 +1,440 @@ +// pages/goods-detail/goods-detail.js +const API = require('../../utils/api.js') + +// 格式化毛重显示的辅助函数 +function formatGrossWeight(grossWeight, weight) { + console.log('===== formatGrossWeight 函数调用 ====='); + console.log('输入参数:'); + console.log('- grossWeight:', grossWeight, '(类型:', typeof grossWeight, ')'); + console.log('- weight:', weight, '(类型:', typeof weight, ')'); + + // 1. 优先使用grossWeight,只要它不是null、不是undefined、不是空字符串 + if (grossWeight !== null && grossWeight !== undefined && grossWeight !== '') { + console.log('使用grossWeight参数'); + return grossWeight; + } + // 如果grossWeight无效,尝试使用weight字段 + if (weight !== null && weight !== undefined && weight !== '') { + console.log('使用weight参数'); + return weight; + } + + // 3. 新增逻辑:如果grossWeight和weight都无效,返回空字符串以支持文字输入 + console.log('两个参数都无效,返回空字符串'); + return ""; +} + +Page({ + data: { + goodsDetail: {}, // 当前商品详情 + showImagePreview: false, // 控制图片预览弹窗显示 + previewImageUrls: [], // 预览的图片URL列表 + previewImageIndex: 0, // 当前预览图片的索引 + // 图片缩放相关状态 + scale: 1, // 当前缩放比例 + lastScale: 1, // 上一次缩放比例 + startDistance: 0, // 双指起始距离 + doubleTapTimer: null, // 双击计时器 + lastTapTime: 0, // 上一次单击时间 + isScaling: false, // 是否正在缩放中 + offsetX: 0, // X轴偏移量 + offsetY: 0, // Y轴偏移量 + initialTouch: null, // 初始触摸点 + }, + + onLoad(options) { + console.log('商品详情页面加载,参数:', options); + + // 支持两种参数传递方式:直接传递商品数据或仅传递商品ID + if (options.goodsData) { + try { + // 解析JSON字符串为商品对象 + const goodsData = JSON.parse(decodeURIComponent(options.goodsData)); + console.log('解析后的商品数据:', goodsData); + + // 设置商品详情数据 + this.setData({ + goodsDetail: goodsData + }); + } catch (error) { + console.error('解析商品数据失败:', error); + wx.showToast({ + title: '数据解析错误', + icon: 'none', + duration: 2000 + }); + // 2秒后返回上一页 + setTimeout(() => { + wx.navigateBack(); + }, 2000); + } + } else if (options.id) { + // 如果只传递了商品ID,则从服务器加载商品详情 + this.loadGoodsDetail(options.id); + } else { + wx.showToast({ + title: '参数错误', + icon: 'none', + duration: 2000 + }); + // 2秒后返回上一页 + setTimeout(() => { + wx.navigateBack(); + }, 2000); + } + }, + + // 加载商品详情 + loadGoodsDetail(goodsId) { + wx.showLoading({ + title: '加载中', + }); + + API.getProductDetail({ productId: goodsId }) + .then(res => { + console.log('获取商品详情成功:', res); + if (res && res.code === 200 && res.data) { + // 从本地存储获取已预约商品ID列表 + const reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || []; + const product = res.data; + + // 确保商品ID的一致性 + const productIdStr = String(product.productId || product.id); + + // 增强的预约人数计算逻辑 + const selectedValue = product.selected; + const reservedCountValue = product.reservedCount; + const reservationCountValue = product.reservationCount; + + const finalReservationCount = selectedValue !== undefined && selectedValue !== null ? selectedValue : + (reservedCountValue !== undefined && reservedCountValue !== null ? reservedCountValue : + (reservationCountValue || 0)); + + // 处理grossWeight为null或无效的情况,返回空字符串以支持文字输入 + const grossWeightValue = product.grossWeight !== null && product.grossWeight !== undefined ? product.grossWeight : ''; + + // 转换商品数据格式 + const formattedGoods = { + id: productIdStr, + productId: productIdStr, + name: product.productName, + price: product.price, + minOrder: product.quantity, + yolk: product.yolk, + spec: product.specification, + region: product.region, + contact_phone: product.contactPhone, + product_contact: product.contactName, + imageUrls: product.images || [], + displayGrossWeight: formatGrossWeight(grossWeightValue, product.weight), + isReserved: reservedGoodsIds.some(itemId => String(itemId) === productIdStr), + reservedCount: finalReservationCount, + created_at: product.createdAt, + updated_at: product.updatedAt + }; + + this.setData({ + goodsDetail: formattedGoods + }); + } else { + wx.showToast({ + title: '获取商品详情失败', + icon: 'none', + duration: 2000 + }); + } + }) + .catch(err => { + console.error('获取商品详情失败:', err); + wx.showToast({ + title: '获取商品详情失败', + icon: 'none', + duration: 2000 + }); + }) + .finally(() => { + wx.hideLoading(); + }); + }, + + // 预览图片 + previewImage(e) { + console.log('预览图片事件:', e); + const { urls, index } = e.currentTarget.dataset; + if (!urls || urls.length === 0) { + wx.showToast({ + title: '没有图片可预览', + icon: 'none' + }); + return; + } + + this.setData({ + showImagePreview: true, + previewImageUrls: urls, + previewImageIndex: index || 0, + // 重置图片缩放状态 + scale: 1, + offsetX: 0, + offsetY: 0, + isScaling: false + }); + }, + + // 关闭图片预览 + closeImagePreview() { + this.setData({ + showImagePreview: false, + // 重置图片缩放状态 + scale: 1, + offsetX: 0, + offsetY: 0, + isScaling: false + }); + }, + + // 图片预览切换 + onPreviewImageChange(e) { + console.log('图片预览切换:', e); + this.setData({ + previewImageIndex: e.detail.current, + // 重置当前图片的缩放状态 + scale: 1, + offsetX: 0, + offsetY: 0, + isScaling: false + }); + }, + + // 处理图片点击事件(双击放大/缩小) + handleImageTap(e) { + console.log('图片点击事件:', e); + const now = Date.now(); + const DOUBLE_TAP_DELAY = 300; + + // 检查是否为双击 + if (now - this.lastTapTime < DOUBLE_TAP_DELAY) { + // 双击事件 + if (this.doubleTapTimer) { + clearTimeout(this.doubleTapTimer); + } + + // 切换缩放状态 + const newScale = this.data.scale === 1 ? 2 : 1; + this.setData({ + scale: newScale, + isScaling: false + }); + } else { + // 单击事件,设置双击计时器 + if (this.doubleTapTimer) { + clearTimeout(this.doubleTapTimer); + } + + this.doubleTapTimer = setTimeout(() => { + // 单击后300毫秒内没有第二次点击,视为单击 + // 可以在这里添加单击事件的处理逻辑 + }, DOUBLE_TAP_DELAY); + } + + this.lastTapTime = now; + }, + + // 计算两点之间的距离 + getDistance(point1, point2) { + const dx = point2.clientX - point1.clientX; + const dy = point2.clientY - point1.clientY; + return Math.sqrt(dx * dx + dy * dy); + }, + + // 处理触摸开始事件 + handleTouchStart(e) { + console.log('触摸开始事件:', e); + if (e.touches.length === 2) { + // 双指触摸,计算初始距离 + this.setData({ + startDistance: this.getDistance(e.touches[0], e.touches[1]), + lastScale: this.data.scale, + isScaling: true + }); + } else if (e.touches.length === 1) { + // 单指触摸,记录初始位置 + this.setData({ + initialTouch: { + x: e.touches[0].clientX, + y: e.touches[0].clientY + } + }); + } + }, + + // 处理触摸移动事件 + handleTouchMove(e) { + console.log('触摸移动事件:', e); + const touches = e.touches; + + if (touches.length === 1 && this.data.initialTouch && this.data.scale !== 1) { + // 单指拖动(只有在缩放状态下才允许拖动) + const deltaX = touches[0].clientX - this.data.initialTouch.x; + const deltaY = touches[0].clientY - this.data.initialTouch.y; + + // 计算新的偏移量 + let newOffsetX = this.data.offsetX + deltaX; + let newOffsetY = this.data.offsetY + deltaY; + + // 边界限制 + const windowWidth = wx.getSystemInfoSync().windowWidth; + const windowHeight = wx.getSystemInfoSync().windowHeight; + const maxOffsetX = (windowWidth * (this.data.scale - 1)) / 2; + const maxOffsetY = (windowHeight * (this.data.scale - 1)) / 2; + + newOffsetX = Math.max(-maxOffsetX, Math.min(maxOffsetX, newOffsetX)); + newOffsetY = Math.max(-maxOffsetY, Math.min(maxOffsetY, newOffsetY)); + + this.setData({ + offsetX: newOffsetX, + offsetY: newOffsetY, + initialTouch: { + x: touches[0].clientX, + y: touches[0].clientY + } + }); + } else if (touches.length === 2) { + // 双指缩放 + const currentDistance = this.getDistance(touches[0], touches[1]); + const scale = (currentDistance / this.data.startDistance) * this.data.lastScale; + + // 限制缩放范围在0.5倍到3倍之间 + const newScale = Math.max(0.5, Math.min(3, scale)); + + this.setData({ + scale: newScale, + isScaling: true + }); + } + }, + + // 处理触摸结束事件 + handleTouchEnd(e) { + console.log('触摸结束事件:', e); + if (e.touches.length === 0) { + // 触摸结束,更新最后缩放比例 + this.setData({ + lastScale: this.data.scale, + isScaling: false, + initialTouch: null + }); + } else if (e.touches.length === 1) { + // 单指触摸结束,保留初始触摸点 + this.setData({ + initialTouch: { + x: e.touches[0].clientX, + y: e.touches[0].clientY + } + }); + } + }, + + // 拨打电话 + makePhoneCall(e) { + console.log('拨打电话事件:', e); + const phoneNumber = e.currentTarget.dataset.phone; + if (phoneNumber) { + wx.showModal({ + title: '联系人电话', + content: phoneNumber, + showCancel: true, + cancelText: '取消', + confirmText: '拨打', + success: (res) => { + if (res.confirm) { + wx.makePhoneCall({ + phoneNumber: phoneNumber, + success: () => { + console.log('拨打电话成功'); + }, + fail: (err) => { + console.error('拨打电话失败', err); + wx.showToast({ + title: '拨打电话失败', + icon: 'none' + }); + } + }); + } + } + }); + } + }, + + // 我想要(预约) + onClickWantInDetail(e) { + console.log('我想要事件:', e); + const { id } = e.currentTarget.dataset; + if (!id) return; + + // 从本地存储获取openid + const openid = wx.getStorageSync('openid'); + console.log('openid:', openid); + + // 检查是否已登录 + if (!openid) { + // 如果未登录,显示授权登录弹窗 + this.setData({ showAuthModal: true }); + return; + } + + // 获取已预约商品ID列表 + let reservedGoodsIds = wx.getStorageSync('reservedGoodsIds') || []; + + // 检查是否已经预约过 + if (reservedGoodsIds.some(itemId => String(itemId) === String(id))) { + wx.showToast({ + title: '您已经预约过该商品', + icon: 'none', + duration: 1500 + }); + return; + } + + // 添加到已预约列表 + reservedGoodsIds.push(id); + wx.setStorageSync('reservedGoodsIds', reservedGoodsIds); + + // 更新页面状态 + this.setData({ + 'goodsDetail.isReserved': true + }); + + // 调用API记录预约 + API.reserveProduct({ id: id }) + .then(res => { + console.log('预约成功:', res); + wx.showToast({ + title: '预约成功', + icon: 'success', + duration: 1500 + }); + }) + .catch(err => { + console.error('预约失败:', err); + // 如果API调用失败,从本地列表中移除 + reservedGoodsIds = reservedGoodsIds.filter(itemId => String(itemId) !== String(id)); + wx.setStorageSync('reservedGoodsIds', reservedGoodsIds); + // 更新页面状态 + this.setData({ + 'goodsDetail.isReserved': false + }); + wx.showToast({ + title: '预约失败,请重试', + icon: 'none', + duration: 1500 + }); + }); + }, + + // 返回上一页 + goBack() { + wx.navigateBack(); + } +}); \ No newline at end of file diff --git a/pages/goods-detail/goods-detail.json b/pages/goods-detail/goods-detail.json new file mode 100644 index 0000000..7d505f9 --- /dev/null +++ b/pages/goods-detail/goods-detail.json @@ -0,0 +1,4 @@ +{ + "navigationBarTitleText": "商品详情", + "enablePullDownRefresh": false +} \ No newline at end of file diff --git a/pages/goods-detail/goods-detail.wxml b/pages/goods-detail/goods-detail.wxml new file mode 100644 index 0000000..ca26da4 --- /dev/null +++ b/pages/goods-detail/goods-detail.wxml @@ -0,0 +1,175 @@ + + + + + + + 商品详情 + + + × + + + + + + + + + + + + + + + + + + + {{goodsDetail.name}} + + 价格: + {{goodsDetail.price}} + + + + + + + + + 地区 + + + {{goodsDetail.region || '暂无'}} + + + + + 规格 + + + {{goodsDetail.spec || '暂无'}} + + + + + + + 蛋黄 + + + {{goodsDetail.yolk || '暂无'}} + + + + + 斤重 + + + {{goodsDetail.displayGrossWeight || '暂无'}} + + + + + + + 件数 + + + {{goodsDetail.minOrder || '暂无'}} + + + + + 关注人数 + + + {{goodsDetail.reservedCount || '0'}} + + + + + + + + 联系信息 + + + 👤 + 联系人: + {{goodsDetail.product_contact || '暂无'}} + + + 📞 + + 联系电话: + {{goodsDetail.contact_phone || '暂无'}} + + + + + + + + + + + + + + + + + × + + + {{previewImageIndex + 1}} / {{previewImageUrls.length}} + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/goods-detail/goods-detail.wxss b/pages/goods-detail/goods-detail.wxss new file mode 100644 index 0000000..cdf13cf --- /dev/null +++ b/pages/goods-detail/goods-detail.wxss @@ -0,0 +1,514 @@ +/* pages/goods-detail/goods-detail.wxss */ + +/* 页面容器 */ +.goods-detail-page { + min-height: 100vh; + background-color: #f5f7fa; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif; +} + +/* 页面头部 */ +.page-header { + display: flex; + align-items: center; + justify-content: space-between; + height: 44px; + background: #ffffff; + padding: 0 16px; + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 100; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); +} + +.header-left { + width: 40px; +} + +.header-center { + flex: 1; + text-align: center; +} + +.header-title { + font-size: 17px; + font-weight: 600; + color: #000000; + letter-spacing: 0.5px; +} + +.header-right { + width: 40px; + text-align: right; +} + +.close-icon { + font-size: 28px; + color: #000000; + font-weight: 300; + line-height: 1; +} + +/* 商品详情内容区域 */ +.goods-detail-content { + padding-top: 44px; + padding-bottom: 100px; +} + +/* 商品图片轮播 */ +.goods-image-slider { + width: 100%; + height: 280px; + background: linear-gradient(135deg, #f0f4ff 0%, #d9e4ff 100%); + overflow: hidden; + position: relative; +} + +.goods-image-slider::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 1px; + background: linear-gradient(90deg, transparent, rgba(0,0,0,0.05), transparent); +} + +.goods-image-slider swiper { + width: 100%; + height: 100%; + margin: 0; + padding: 0; +} + +.goods-image-slider swiper-item { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + box-sizing: border-box; +} + +.slider-image { + width: 100%; + height: 100%; + object-fit: contain; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + transition: transform 0.3s ease; +} + +.slider-image:active { + transform: scale(0.98); +} + +/* 商品基本信息 */ +.goods-info { + background-color: #ffffff; + padding: 20px 16px 16px; + position: relative; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); +} + +.goods-info::after { + content: ''; + position: absolute; + bottom: 0; + left: 16px; + right: 16px; + height: 1px; + background: linear-gradient(90deg, transparent, #f0f0f0, transparent); +} + +.goods-name { + display: block; + font-size: 20px; + font-weight: 700; + color: #262626; + margin-bottom: 12px; + line-height: 1.4; + letter-spacing: -0.2px; +} + +.goods-price { + display: flex; + align-items: baseline; + margin-bottom: 4px; +} + +.price-symbol { + font-size: 15px; + color: #666; + margin-right: 4px; + font-weight: 500; +} + +.price-value { + font-size: 28px; + color: #ff4d4f; + font-weight: 700; + letter-spacing: -0.5px; +} + +.price-value::before { + content: '¥'; + font-size: 20px; + margin-right: 2px; +} + +/* 商品详细信息网格 */ +.info-grid { + background-color: #ffffff; + margin: 12px 0; + padding: 16px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); +} + +.info-row { + display: flex; + flex-wrap: wrap; + margin-bottom: 16px; + background: #f0f5ff; + border-radius: 10px; + overflow: hidden; + border: 1px solid #d6e4ff; +} + +.info-row:last-child { + margin-bottom: 0; +} + +.info-item { + flex: 0 0 50%; + display: flex; + flex-direction: column; + padding: 14px 16px; + box-sizing: border-box; + position: relative; +} + +.info-item:nth-child(odd)::after { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 1px; + background: linear-gradient(180deg, transparent, #e8e8e8, transparent); +} + +.info-label-container { + margin-bottom: 6px; +} + +.info-label { + font-size: 13px; + color: #8c8c8c; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.3px; +} + +.info-value-container { + min-height: 24px; +} + +.info-value { + font-size: 16px; + color: #000000d9; + font-weight: 600; + line-height: 1.3; +} + +/* 联系信息 */ +.contact-info { + margin: 16px; + padding: 16px; + border-radius: 12px; + background: #ffffff; + border: 1px solid #d6e4ff; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.contact-label { + display: block; + font-size: 16px; + font-weight: 600; + color: #2f54eb; + margin-bottom: 16px; + text-align: center; +} + +.contact-content { + display: flex; + flex-direction: column; + gap: 12px; +} + +.contact-item { + display: flex; + align-items: center; + padding: 8px 0; +} + +.phone-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 0; +} + +.contact-icon { + font-size: 16px; + margin-right: 10px; + flex-shrink: 0; + width: 20px; + text-align: center; + color: #2f54eb; +} + +.user-icon { + font-size: 18px; +} + +.phone-icon { + font-size: 18px; +} + +.contact-label-text { + font-size: 14px; + color: #595959; + margin-right: 8px; + white-space: nowrap; + flex-shrink: 0; +} + +.contact-text { + font-size: 14px; + color: #262626; + flex-shrink: 0; + margin-right: 16px; +} + +.phone-info { + display: flex; + flex-direction: row; + flex: 1; + align-items: center; +} + +.phone-info .contact-label-text { + margin-bottom: 0; +} + +.call-button { + padding: 0 24px; + height: 36px; + line-height: 36px; + font-size: 14px; + color: #ffffff; + background-color: #2f54eb; + border: 1px solid #2f54eb; + border-radius: 4px; + flex-shrink: 0; + box-shadow: 0 2px 8px rgba(47, 84, 235, 0.2); +} + +.call-button:active { + background-color: #4066ff; + border-color: #4066ff; + box-shadow: 0 4px 12px rgba(47, 84, 235, 0.3); +} + +.call-button:active { + background-color: #1d39c4; + transform: scale(0.98); +} + +/* 操作按钮区域 */ +.action-buttons { + position: fixed; + bottom: 0; + left: 0; + right: 0; + padding: 16px; + background-color: #ffffff; + border-top: 1px solid #f0f0f0; + box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.06); + z-index: 99; + display: flex; + gap: 12px; +} + +.bottom-button { + flex: 1; + height: 52px; + border-radius: 26px; + font-size: 18px; + font-weight: 700; + display: flex; + justify-content: center; + align-items: center; + border: none; + outline: none; + transition: all 0.3s ease; +} + +.call-button.bottom-button { + background-color: #ffffff; + color: #2f54eb; + border: 2px solid #2f54eb; + box-shadow: none; +} + +.want-button.bottom-button { + background: linear-gradient(135deg, #2f54eb 0%, #1d39c4 100%); + color: #ffffff; + box-shadow: 0 4px 12px rgba(47, 84, 235, 0.2); +} + +.call-button.bottom-button:active { + background-color: #f0f4ff; + transform: scale(0.98); +} + +.want-button.bottom-button:active { + transform: translateY(2px) scale(0.98); + box-shadow: 0 2px 6px rgba(47, 84, 235, 0.15); +} + +.want-button.bottom-button[disabled] { + background: linear-gradient(135deg, #52c41a 0%, #389e0d 100%); + color: #ffffff !important; + border: none; + box-shadow: 0 4px 12px rgba(82, 196, 26, 0.2); + opacity: 1; +} + +.want-button.bottom-button[disabled]:active { + transform: none; + box-shadow: 0 4px 12px rgba(82, 196, 26, 0.3); +} + +/* 图片预览弹窗 */ +.image-preview-container { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #000000; + z-index: 1000; + display: flex; + flex-direction: column; +} + +.preview-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 16px; + color: #ffffff; + z-index: 10; + background: rgba(0, 0, 0, 0.5); + backdrop-filter: blur(10px); +} + +.preview-close { + width: 44px; + height: 44px; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.1); + border-radius: 22px; + transition: all 0.2s ease; +} + +.preview-close:active { + background: rgba(255, 255, 255, 0.2); + transform: scale(0.95); +} + +.close-icon { + font-size: 24px; + color: #ffffff; + font-weight: 300; +} + +.preview-indicator { + font-size: 15px; + color: #ffffff; + font-weight: 500; + opacity: 0.8; +} + +.preview-swiper { + flex: 1; + width: 100%; +} + +.preview-image-wrapper { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + position: relative; + padding: 20px; + box-sizing: border-box; +} + +.preview-image { + width: 100%; + height: 100%; + max-width: 100%; + max-height: 100%; + object-fit: contain; + border-radius: 8px; +} + +/* 添加一些微动画效果 */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.goods-info, +.info-grid, +.contact-info { + animation: fadeIn 0.4s ease-out; +} + +.info-grid { + animation-delay: 0.1s; +} + +.contact-info { + animation-delay: 0.2s; +} + +/* 响应式调整 */ +@media (min-height: 800px) { + .goods-image-slider { + height: 320px; + } + + .goods-name { + font-size: 22px; + } + + .price-value { + font-size: 32px; + } +} \ No newline at end of file