829 lines
22 KiB
Vue
829 lines
22 KiB
Vue
<template>
|
||
<view class="container">
|
||
<MessageNotification />
|
||
<!-- 1. 顶部搜索栏 -->
|
||
<view class="header-section">
|
||
<view class="search-box">
|
||
<u-search
|
||
v-model="searchKeyword"
|
||
placeholder="搜索药品/症状"
|
||
:show-action="true"
|
||
action-text="搜索"
|
||
bg-color="#F5F7FA"
|
||
placeholder-color="#9CA3AF"
|
||
shape="round"
|
||
height="64"
|
||
:input-style="{fontSize: '26rpx'}"
|
||
@custom="handleSearch"
|
||
@search="handleSearch"
|
||
@clear="clearSearch"
|
||
></u-search>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 2. 顶部专区Tab -->
|
||
<view class="zone-tabs-wrapper">
|
||
<scroll-view scroll-x class="zone-tabs-scroll">
|
||
<view class="zone-tabs">
|
||
<view
|
||
v-for="(zone, index) in homeZones"
|
||
:key="index"
|
||
class="zone-tab-item"
|
||
:class="{ active: selectedZoneIndex === index }"
|
||
@click="onZoneChange(index)"
|
||
>
|
||
<text>{{ zone.title }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<!-- 3. 主体内容区:左侧分类 + 右侧商品 -->
|
||
<view
|
||
class="main-content"
|
||
@touchstart="onZoneTouchStart"
|
||
@touchend="onZoneTouchEnd"
|
||
>
|
||
<!-- 左侧分类栏 -->
|
||
<view class="category-sidebar">
|
||
<scroll-view scroll-y class="category-scroll">
|
||
<view
|
||
class="category-item"
|
||
:class="{ active: selectedCategoryId === 0 }"
|
||
@click="selectCategory(0)"
|
||
>
|
||
<text>全部</text>
|
||
</view>
|
||
<view
|
||
v-for="cat in categoryList"
|
||
:key="cat.id"
|
||
class="category-item"
|
||
:class="{ active: selectedCategoryId === cat.id }"
|
||
@click="selectCategory(cat.id)"
|
||
>
|
||
<text class="u-line-1">{{ cat.category_name }}</text>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<!-- 右侧商品列表区 -->
|
||
<view class="product-area">
|
||
<scroll-view scroll-y class="product-scroll" @scrolltolower="loadMore">
|
||
<!-- 商品列表 - 两列布局 -->
|
||
<view class="product-grid" v-if="products.length > 0">
|
||
<view
|
||
v-for="(item, index) in products"
|
||
:key="item.id"
|
||
class="product-card"
|
||
@click="handClickProduct(item)"
|
||
>
|
||
<!-- 商品图片 -->
|
||
<view class="product-img-box">
|
||
<image
|
||
class="product-img"
|
||
:class="{ 'prescription-blur': item.drug && item.drug.is_otc === 0 && item.drug.type == 2 }"
|
||
:src="(item.drug && item.drug.image) ? item.drug.image : 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png'"
|
||
mode="aspectFill"
|
||
lazy-load
|
||
/>
|
||
</view>
|
||
|
||
<!-- 商品信息 -->
|
||
<view class="product-info">
|
||
<view class="product-title u-line-2">{{ item.drug ? item.drug.drug_name : '' }}</view>
|
||
<view class="product-tags" v-if="item.drug.type == 2">
|
||
<text
|
||
class="tag-label"
|
||
:class="getProductTag(item.drug).className"
|
||
>
|
||
{{ getProductTag(item.drug).label }}
|
||
</text>
|
||
<text class="tag-spec u-line-1">{{ (item.drug && item.drug.specification) ? item.drug.specification : '标准规格' }}</text>
|
||
</view>
|
||
<view class="product-bottom">
|
||
<view class="price-box">
|
||
<text class="price-symbol">¥</text>
|
||
<text class="price-val">{{ item.price }}</text>
|
||
</view>
|
||
<view class="cart-btn" @click.stop="showCartPopup(item)">
|
||
<u-icon name="plus" color="#ffffff" size="26"></u-icon>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 空状态 -->
|
||
<view v-if="products.length === 0" class="empty-state">
|
||
<u-empty text="暂无相关药品" mode="search" margin-top="100"></u-empty>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 购物车悬浮球 -->
|
||
<view
|
||
class="cart-float"
|
||
:style="{ left: cartPosition.x + 'px', top: cartPosition.y + 'px' }"
|
||
@touchstart="onTouchStart"
|
||
@touchmove="onTouchMove"
|
||
@touchend="onTouchEnd"
|
||
@click="goToCart"
|
||
>
|
||
<view class="cart-icon-inner">
|
||
<u-icon name="shopping-cart" color="#ffffff" size="44"></u-icon>
|
||
<view class="badge" v-if="cartCount > 0">{{ cartCount > 99 ? '99+' : cartCount }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 购物车弹窗 -->
|
||
<u-popup
|
||
v-model="showPopup"
|
||
mode="bottom"
|
||
border-radius="24"
|
||
:closeable="true"
|
||
@close="closePopup"
|
||
>
|
||
<view class="popup-content safe-area-inset-bottom">
|
||
<view class="product-header-row">
|
||
<image class="popup-img" :src="getProductImage" mode="aspectFill"></image>
|
||
<view class="popup-info">
|
||
<view class="price-row">¥<text class="big">{{ currentProduct.price || '' }}</text></view>
|
||
<view class="stock-row">库存充足</view>
|
||
<view class="selected-spec">已选: {{ getProductSpec }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="quantity-section">
|
||
<text class="label">购买数量</text>
|
||
<u-number-box
|
||
v-model="quantity"
|
||
:min="1"
|
||
:max="999"
|
||
integer
|
||
@change="quantityChange"
|
||
></u-number-box>
|
||
</view>
|
||
|
||
<view class="popup-footer">
|
||
<button class="action-btn add-cart" @click="confirmAddToCart">加入购物车</button>
|
||
</view>
|
||
</view>
|
||
</u-popup>
|
||
|
||
<u-toast ref="uToast" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getStoreDrugListBySalespersonApi, getHomeZonesApi, getDrugCategoriesApi } from "@/request/api/product";
|
||
import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
products: [],
|
||
searchKeyword: "",
|
||
|
||
// 专区相关
|
||
homeZones: [],
|
||
selectedZoneIndex: 0,
|
||
selectedZoneType: 'otc',
|
||
zoneTouch: { startX: 0, startY: 0 },
|
||
|
||
// 分类相关
|
||
categoryList: [],
|
||
selectedCategoryId: 0,
|
||
|
||
doctorId: 0,
|
||
r_type: 0,
|
||
delegateStoreId: '',
|
||
cartCount: 0,
|
||
cartPosition: { x: 0, y: 0 },
|
||
cartMove: { startX: 0, startY: 0, moving: false },
|
||
showPopup: false,
|
||
currentProduct: {},
|
||
quantity: 1
|
||
};
|
||
},
|
||
computed: {
|
||
getProductImage() {
|
||
return (this.currentProduct.drug && this.currentProduct.drug.image) ? this.currentProduct.drug.image : 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/mine/avatar_1.png';
|
||
},
|
||
getProductName() {
|
||
return (this.currentProduct.drug && this.currentProduct.drug.drug_name) ? this.currentProduct.drug.drug_name : '';
|
||
},
|
||
getProductSpec() {
|
||
return (this.currentProduct.drug && this.currentProduct.drug.specification) ? this.currentProduct.drug.specification : '标准规格';
|
||
}
|
||
},
|
||
onLoad(e) {
|
||
this.doctorId = e.doctor_id;
|
||
this.r_type = e.register_type;
|
||
this.delegateStoreId = e.delegate_store_id || '';
|
||
|
||
// 根据首页传入的专区类型初始化
|
||
if (e.zone_type) {
|
||
this.selectedZoneType = e.zone_type;
|
||
} else {
|
||
this.selectedZoneType = 'otc';
|
||
}
|
||
|
||
// 获取专区列表
|
||
this.getHomeZones();
|
||
},
|
||
methods: {
|
||
// 获取专区列表
|
||
getHomeZones() {
|
||
getHomeZonesApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
}).then((res) => {
|
||
if (res.data.code == 0) {
|
||
this.homeZones = res.data.result || res.data.data || [];
|
||
|
||
// 根据传入的zone_type找到对应的索引
|
||
if (this.homeZones.length > 0) {
|
||
const index = this.homeZones.findIndex(z => z.type === this.selectedZoneType);
|
||
this.selectedZoneIndex = index >= 0 ? index : 0;
|
||
this.selectedZoneType = this.homeZones[this.selectedZoneIndex]?.type || 'otc';
|
||
}
|
||
|
||
// 获取分类列表
|
||
this.getCategoryList();
|
||
}
|
||
}).catch(() => {
|
||
// 使用默认专区
|
||
this.homeZones = [
|
||
{ id: 1, title: 'OTC', type: 'otc' },
|
||
{ id: 2, title: '保健食品', type: 'health_food' }
|
||
];
|
||
this.getCategoryList();
|
||
});
|
||
},
|
||
|
||
// 获取分类列表
|
||
getCategoryList() {
|
||
getDrugCategoriesApi({
|
||
zone_type: this.selectedZoneType
|
||
}).then((res) => {
|
||
if (res.data.code == 0) {
|
||
// 将树形结构扁平化为一级分类列表
|
||
const categories = res.data.result || [];
|
||
this.categoryList = this.flattenCategories(categories);
|
||
}
|
||
}).catch(() => {
|
||
this.categoryList = [];
|
||
}).finally(() => {
|
||
// 重置分类选择并获取商品列表
|
||
this.selectedCategoryId = 0;
|
||
this.getList();
|
||
});
|
||
},
|
||
|
||
// 扁平化分类树(只取一级分类,或展开所有层级)
|
||
flattenCategories(categories, result = []) {
|
||
for (const cat of categories) {
|
||
result.push({
|
||
id: cat.id,
|
||
category_name: cat.category_name,
|
||
level: cat.level,
|
||
parent_id: cat.parent_id
|
||
});
|
||
if (cat.children && cat.children.length > 0) {
|
||
this.flattenCategories(cat.children, result);
|
||
}
|
||
}
|
||
return result;
|
||
},
|
||
|
||
// 专区切换
|
||
onZoneChange(index) {
|
||
this.selectedZoneIndex = index;
|
||
this.selectedZoneType = this.homeZones[index]?.type || 'otc';
|
||
this.selectedCategoryId = 0;
|
||
this.getCategoryList();
|
||
},
|
||
|
||
onZoneTouchStart(e) {
|
||
const touch = e.touches[0] || e.changedTouches[0];
|
||
if (!touch) return;
|
||
this.zoneTouch.startX = touch.clientX;
|
||
this.zoneTouch.startY = touch.clientY;
|
||
},
|
||
|
||
onZoneTouchEnd(e) {
|
||
const dx = e.changedTouches[0].clientX - this.zoneTouch.startX;
|
||
const dy = e.changedTouches[0].clientY - this.zoneTouch.startY;
|
||
if (Math.abs(dx) < 60 || Math.abs(dx) < Math.abs(dy)) return;
|
||
const next = dx < 0 ? this.selectedZoneIndex + 1 : this.selectedZoneIndex - 1;
|
||
if (next < 0 || next >= this.homeZones.length) return;
|
||
this.onZoneChange(next);
|
||
},
|
||
|
||
// 分类选择
|
||
selectCategory(categoryId) {
|
||
this.selectedCategoryId = categoryId;
|
||
this.getList();
|
||
},
|
||
|
||
// 核心标签判断逻辑
|
||
getProductTag(drug) {
|
||
if (!drug) return { label: 'OTC', className: 'tag-green' };
|
||
if (drug.type === 3) {
|
||
return { label: '保健食品', className: 'tag-orange' };
|
||
}
|
||
if (drug.type == 2) {
|
||
if (drug.is_otc) {
|
||
return { label: 'OTC', className: 'tag-green' };
|
||
} else {
|
||
return { label: 'Rx', className: 'tag-red' };
|
||
}
|
||
}
|
||
},
|
||
|
||
getList() {
|
||
const params = {
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
page: 1,
|
||
limit: 100,
|
||
category: this.selectedZoneType
|
||
};
|
||
|
||
if (this.selectedCategoryId > 0) {
|
||
params.category_id = this.selectedCategoryId;
|
||
}
|
||
|
||
if (this.searchKeyword) {
|
||
params.keyword = this.searchKeyword;
|
||
}
|
||
|
||
getStoreDrugListBySalespersonApi(params).then((res) => {
|
||
if (res.data.code == 0) {
|
||
this.products = res.data.result.records || [];
|
||
this.cartCount = res.data.result.cart_count || 0;
|
||
}
|
||
});
|
||
},
|
||
|
||
handleSearch() {
|
||
this.getList();
|
||
},
|
||
|
||
clearSearch() {
|
||
this.searchKeyword = "";
|
||
this.getList();
|
||
},
|
||
|
||
handClickProduct(item) {
|
||
let url = `/subPackages/product/symptoms?id=${item.drug.id}&drug_name=${item.drug.drug_name}&is_otc=${item.drug.is_otc}&image=${item.drug.image}&price=${item.price}`;
|
||
if (this.delegateStoreId) {
|
||
url += `&delegate_store_id=${this.delegateStoreId}`;
|
||
}
|
||
uni.navigateTo({ url });
|
||
},
|
||
|
||
// 悬浮球逻辑
|
||
initCartPosition() {
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
this.cartPosition = {
|
||
x: systemInfo.windowWidth - 80,
|
||
y: systemInfo.windowHeight - 200
|
||
};
|
||
},
|
||
onTouchStart(e) {
|
||
this.cartMove.startX = e.touches[0].clientX;
|
||
this.cartMove.startY = e.touches[0].clientY;
|
||
this.cartMove.moving = false;
|
||
},
|
||
onTouchMove(e) {
|
||
this.cartMove.moving = true;
|
||
const moveX = e.touches[0].clientX - this.cartMove.startX;
|
||
const moveY = e.touches[0].clientY - this.cartMove.startY;
|
||
this.cartPosition.x += moveX;
|
||
this.cartPosition.y += moveY;
|
||
this.cartMove.startX = e.touches[0].clientX;
|
||
this.cartMove.startY = e.touches[0].clientY;
|
||
},
|
||
onTouchEnd() {
|
||
if (!this.cartMove.moving) return;
|
||
const systemInfo = uni.getSystemInfoSync();
|
||
const screenWidth = systemInfo.windowWidth;
|
||
const screenHeight = systemInfo.windowHeight;
|
||
let finalX = this.cartPosition.x;
|
||
let finalY = this.cartPosition.y;
|
||
finalX = Math.max(10, Math.min(finalX, screenWidth - 70));
|
||
finalY = Math.max(10, Math.min(finalY, screenHeight - 70));
|
||
if (finalX < screenWidth / 2) {
|
||
finalX = 20;
|
||
} else {
|
||
finalX = screenWidth - 70;
|
||
}
|
||
this.cartPosition = { x: finalX, y: finalY };
|
||
},
|
||
goToCart() {
|
||
uni.navigateTo({ url: '/subPackages/shop/shop-cate' });
|
||
},
|
||
showCartPopup(item) {
|
||
this.currentProduct = item;
|
||
this.quantity = 1;
|
||
this.showPopup = true;
|
||
},
|
||
closePopup() {
|
||
this.showPopup = false;
|
||
},
|
||
quantityChange(value) {},
|
||
confirmAddToCart() {
|
||
// 检查是否为处方药:is_otc === 0 && type == 2
|
||
if (this.currentProduct.drug && this.currentProduct.drug.is_otc === 0 && this.currentProduct.drug.type == 2) {
|
||
uni.showToast({
|
||
title: '处方药不能加入购物车,请通过提交预定购买',
|
||
icon: 'none',
|
||
duration: 2000
|
||
});
|
||
return;
|
||
}
|
||
|
||
saveCartApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
drug_id: this.currentProduct.drug.id,
|
||
quantity: this.quantity
|
||
}).then(() => {
|
||
this.updateCartCount();
|
||
this.closePopup();
|
||
this.$refs.uToast.show({ title: '已加入购物车', type: 'success' });
|
||
});
|
||
},
|
||
updateCartCount() {
|
||
getCartCountsApi({
|
||
store_id: uni.getStorageSync('store_id') || '11001',
|
||
page: 1,
|
||
limit: 100
|
||
}).then((res) => {
|
||
if (res.data.code == 0) {
|
||
this.cartCount = res.data.result.cart_count;
|
||
}
|
||
});
|
||
},
|
||
loadMore() {
|
||
// 可扩展加载更多功能
|
||
}
|
||
},
|
||
onShow() {
|
||
if (this.homeZones.length === 0) {
|
||
this.getHomeZones();
|
||
} else {
|
||
this.getList();
|
||
}
|
||
this.initCartPosition();
|
||
this.updateCartCount();
|
||
},
|
||
onReady() {
|
||
uni.onWindowResize(() => {
|
||
this.initCartPosition();
|
||
});
|
||
},
|
||
mounted() {
|
||
this.updateCartCount();
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.container {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 100vh;
|
||
background: #F5F7FA;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 1. 顶部搜索栏 */
|
||
.header-section {
|
||
background: #fff;
|
||
padding: 16rpx 24rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03);
|
||
|
||
.search-box {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
/* 2. 顶部专区Tab */
|
||
.zone-tabs-wrapper {
|
||
background: #fff;
|
||
border-bottom: 2rpx solid #f0f0f0;
|
||
|
||
.zone-tabs-scroll {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.zone-tabs {
|
||
display: inline-flex;
|
||
padding: 0 24rpx;
|
||
|
||
.zone-tab-item {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 24rpx 32rpx;
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
position: relative;
|
||
transition: all 0.2s;
|
||
|
||
&.active {
|
||
color: #2B85E4;
|
||
font-weight: bold;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
bottom: 0;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
width: 48rpx;
|
||
height: 6rpx;
|
||
background: linear-gradient(90deg, #5CADFF, #2B85E4);
|
||
border-radius: 3rpx;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 3. 主体内容区 */
|
||
.main-content {
|
||
flex: 1;
|
||
display: flex;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 左侧分类栏 */
|
||
.category-sidebar {
|
||
width: 180rpx;
|
||
background: #fff;
|
||
flex-shrink: 0;
|
||
|
||
.category-scroll {
|
||
height: 100%;
|
||
}
|
||
|
||
.category-item {
|
||
height: 100rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
position: relative;
|
||
padding: 0 12rpx;
|
||
|
||
text {
|
||
text-align: center;
|
||
max-width: 100%;
|
||
}
|
||
|
||
&.active {
|
||
background: #F5F7FA;
|
||
color: #2B85E4;
|
||
font-weight: bold;
|
||
|
||
&::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 0;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 6rpx;
|
||
height: 48rpx;
|
||
background: #2B85E4;
|
||
border-radius: 0 3rpx 3rpx 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 右侧商品区域 */
|
||
.product-area {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
|
||
.product-scroll {
|
||
height: 100%;
|
||
padding: 16rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
}
|
||
|
||
/* 商品网格 - 两列布局 */
|
||
.product-grid {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.product-card {
|
||
width: calc((100% - 16rpx) / 2);
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.04);
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
.product-img-box {
|
||
width: 100%;
|
||
height: 240rpx;
|
||
background: #f8f8f8;
|
||
|
||
.product-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
&.prescription-blur {
|
||
/* 暂时禁用模糊
|
||
filter: blur(8px);
|
||
-webkit-filter: blur(8px);
|
||
*/
|
||
}
|
||
}
|
||
}
|
||
|
||
.product-info {
|
||
padding: 16rpx;
|
||
|
||
.product-title {
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
line-height: 1.4;
|
||
height: 72rpx;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.product-tags {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
gap: 8rpx;
|
||
|
||
.tag-label {
|
||
font-size: 18rpx;
|
||
padding: 2rpx 8rpx;
|
||
border-radius: 4rpx;
|
||
font-weight: 500;
|
||
border: 1px solid;
|
||
flex-shrink: 0;
|
||
|
||
&.tag-green { color: #10B981; border-color: #10B981; background: #ECFDF5; }
|
||
&.tag-red { color: #EF4444; border-color: #EF4444; background: #FEF2F2; }
|
||
&.tag-orange { color: #F59E0B; border-color: #F59E0B; background: #FFFBEB; }
|
||
}
|
||
|
||
.tag-spec {
|
||
font-size: 20rpx;
|
||
color: #999;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
}
|
||
|
||
.product-bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.price-box {
|
||
color: #EF4444;
|
||
font-weight: bold;
|
||
|
||
.price-symbol { font-size: 22rpx; }
|
||
.price-val { font-size: 32rpx; font-family: 'DIN Alternate', sans-serif; }
|
||
}
|
||
|
||
.cart-btn {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 4rpx 8rpx rgba(74, 144, 226, 0.3);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 购物车悬浮球 */
|
||
.cart-float {
|
||
position: fixed;
|
||
z-index: 999;
|
||
|
||
.cart-icon-inner {
|
||
width: 100rpx;
|
||
height: 100rpx;
|
||
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 8rpx 20rpx rgba(74, 144, 226, 0.4);
|
||
position: relative;
|
||
|
||
.badge {
|
||
position: absolute;
|
||
top: -6rpx;
|
||
right: -6rpx;
|
||
background: #EF4444;
|
||
color: #fff;
|
||
font-size: 20rpx;
|
||
padding: 2rpx 10rpx;
|
||
border-radius: 20rpx;
|
||
border: 2rpx solid #fff;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* 弹窗内容 */
|
||
.popup-content {
|
||
padding: 30rpx 30rpx 40rpx;
|
||
background: #fff;
|
||
padding-bottom: calc(40rpx + env(safe-area-inset-bottom));
|
||
|
||
.product-header-row {
|
||
display: flex;
|
||
margin-bottom: 40rpx;
|
||
|
||
.popup-img {
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
border-radius: 12rpx;
|
||
margin-right: 24rpx;
|
||
background: #f8f8f8;
|
||
}
|
||
|
||
.popup-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: flex-end;
|
||
|
||
.price-row {
|
||
color: #EF4444;
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
.big { font-size: 44rpx; margin-left: 4rpx; }
|
||
}
|
||
.stock-row { font-size: 22rpx; color: #6B7280; margin: 8rpx 0; }
|
||
.selected-spec { font-size: 24rpx; color: #374151; }
|
||
}
|
||
}
|
||
|
||
.quantity-section {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 60rpx;
|
||
.label { font-size: 30rpx; color: #1F2937; font-weight: 500; }
|
||
}
|
||
|
||
.popup-footer {
|
||
.action-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
line-height: 88rpx;
|
||
text-align: center;
|
||
border-radius: 44rpx;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
|
||
&.add-cart {
|
||
background: linear-gradient(90deg, #4A90E2, #5B8FF9);
|
||
color: #fff;
|
||
}
|
||
&:active { opacity: 0.9; }
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-state {
|
||
margin-top: 100rpx;
|
||
}
|
||
|
||
.u-line-1 {
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.u-line-2 {
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
</style>
|