修复了部分bug,优化了首页和商品列表、商品详情、购物车的UI

This commit is contained in:
2025-12-11 15:09:58 +08:00
parent 419c62cde7
commit 730e286eb5
5 changed files with 929 additions and 1552 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -284,11 +284,11 @@
}
}).then((res) => {
if (res.data.errcode == 0) {
uni.showToast({
title: '切换成功',
duration: 2000,
icon: "success"
});
// uni.showToast({
// title: '切换成功',
// duration: 2000,
// icon: "success"
// });
}
})
},
@@ -646,4 +646,4 @@
}
}
</style>
</style>

View File

@@ -1,63 +1,93 @@
<template>
<view class="container">
<!-- 顶部搜索栏 -->
<view class="search-section">
<u-search
v-model="searchKeyword"
placeholder="搜索药品名称"
:show-action="false"
bg-color="#ffffff"
shape="square"
height="70"
@input="handleSearch"
@search="handleSearch"
@clear="clearSearch"
:action-style="{ color: '#4A90E2' }"
>
<template v-slot:icon>
<u-icon name="search" color="#4A90E2" size="32"></u-icon>
</template>
</u-search>
<!-- 顶部搜索栏保持优化后的结构但背景色微调融入原风格 -->
<view class="search-sticky">
<view class="search-section">
<!-- 搜索组件配置 -->
<u-search
v-model="searchKeyword"
placeholder="搜索药品 / 症状 / 品牌"
:show-action="false"
bg-color="#F5F7FA"
placeholder-color="#9CA3AF"
shape="round"
height="72"
@input="handleSearch"
@search="handleSearch"
@clear="clearSearch"
>
<template v-slot:icon>
<u-icon name="search" color="#9CA3AF" size="32"></u-icon>
</template>
</u-search>
</view>
</view>
<!-- 商品列表 -->
<!-- 商品列表区域 -->
<view class="list-section">
<!-- 列表项卡片遍历渲染 filteredProducts 数据 -->
<view
v-for="(item, index) in filteredProducts"
:key="item.id"
class="list-item"
@click="handClickProduct(item)"
>
<image
class="item-image"
:src="item.drug.image"
mode="aspectFill"
lazy-load
/>
<!-- 左侧药品图片容器 -->
<view class="image-wrapper">
<image
class="item-image"
:src="item.drug.image"
mode="aspectFill"
lazy-load
/>
<!-- 预留缺货蒙层位置 -->
<!-- <view class="mask" v-if="!item.stock">缺货</view> -->
</view>
<!-- 右侧商品详细内容区 -->
<view class="item-content">
<view class="item-title">{{ item.drug.drug_name }}</view>
<view class="item-spec">
<text class="spec-label">功效</text>
<text class="spec-value">{{ item.drug.function }}</text>
</view>
<view class="item-spec">
<text class="spec-label">规格</text>
<text class="spec-value">{{ item.drug.specification }}</text>
</view>
<view class="item-bottom">
<view class="price-section">
<text class="price-tag">¥{{ item.price }}</text>
<text class="stock-tag">库存充足</text>
<!-- 上半部分基础信息名称标签主治 -->
<view class="top-info">
<!-- 药品名称加粗强调限制2行 -->
<view class="item-title">{{ item.drug.drug_name }}</view>
<!-- 标签行包含OTC标识和规格 -->
<view class="tags-row">
<!-- OTC/Rx 标签根据 is_otc 属性动态切换绿/红样式 -->
<text class="tag-otc" :class="item.drug.is_otc ? 'green' : 'red'">{{item.drug.is_otc ? 'OTC' : 'Rx'}}</text>
<!-- 规格文本灰色辅助信息 -->
<text class="tag-spec">{{ item.drug.specification }}</text>
</view>
<view class="cart-icon-btn" @click.stop="showCartPopup(item)">
<u-icon name="shopping-cart" color="#ffffff" size="40"></u-icon>
<!-- 主治功能灰色小字辅助决策 -->
<view class="item-function" v-if="item.drug.function">
主治{{ item.drug.function }}
</view>
</view>
<!-- 下半部分价格与操作按钮固定在底部 -->
<view class="item-bottom">
<!-- 价格区域红色强调 -->
<view class="price-section">
<text class="currency">¥</text>
<text class="price-val">{{ item.price }}</text>
</view>
<!-- 购物车按钮阻止冒泡(@click.stop)防止触发进入详情页 -->
<view class="cart-btn" @click.stop="showCartPopup(item)">
<u-icon name="plus" color="#ffffff" size="30"></u-icon>
</view>
</view>
</view>
</view>
<!-- 空状态当过滤后没有商品时显示 -->
<view v-if="filteredProducts.length === 0" class="empty-state">
<u-empty text="暂无相关药品" mode="search"></u-empty>
</view>
</view>
<!-- 购物车悬浮球 -->
<!-- 购物车悬浮球固定在页面右下角 -->
<view
class="cart-float"
:style="{ left: cartPosition.x + 'px', top: cartPosition.y + 'px' }"
@@ -66,50 +96,47 @@
@touchend="onTouchEnd"
@click="goToCart"
>
<u-badge :count="cartCount" :max="99" type="error" class="cart-badge" v-if="cartCount > 0"></u-badge>
<u-icon name="shopping-cart" color="#ffffff" size="36"></u-icon>
<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="20"
border-radius="24"
:closeable="true"
@close="closePopup"
>
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">选择购买数量</text>
</view>
<view class="product-info">
<image class="product-image" :src="getProductImage" mode="aspectFill"></image>
<view class="product-details">
<text class="product-name">{{ getProductName }}</text>
<text class="product-spec">{{ getProductSpec }}</text>
<view class="product-price">¥{{ currentProduct.price || '' }}</view>
<!-- 弹窗头部商品简要信息 -->
<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-selector">
<text class="quantity-label">购买数量</text>
<view class="quantity-controls">
<u-number-box
v-model="quantity"
:min="1"
:max="999"
integer
:step="1"
:disabled-input="false"
@change="quantityChange"
></u-number-box>
</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-actions">
<button class="cancel-btn" @click="closePopup">取消</button>
<button class="confirm-btn" @click="confirmAddToCart">加入购物车</button>
<!-- 底部确认按钮 -->
<view class="popup-footer">
<button class="action-btn add-cart" @click="confirmAddToCart">加入购物车</button>
</view>
</view>
</u-popup>
@@ -117,34 +144,31 @@
</template>
<script>
// 引入API接口
import { getStoreDrugListBySalespersonApi } from "@/request/api/product";
import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
export default {
data() {
return {
products: [],
filteredProducts: [],
searchKeyword: "",
scrollViewHeight: 0,
doctorId: 0,
r_type: 0,
cartCount: 0,
cartPosition: {
x: 0,
y: 0
},
cartMove: {
startX: 0,
startY: 0,
moving: false
},
showPopup: false,
currentProduct: {},
quantity: 1
products: [], // 所有商品原始数据
filteredProducts: [], // 搜索过滤后的商品数据
searchKeyword: "", // 搜索关键词
scrollViewHeight: 0, // 滚动区域高度(预留)
doctorId: 0, // 医生ID参数
r_type: 0, // 注册类型参数
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 : '';
},
@@ -160,6 +184,7 @@ export default {
this.r_type = e.register_type;
},
methods: {
// 获取商品列表
getList() {
getStoreDrugListBySalespersonApi({
store_id: uni.getStorageSync('store_id') || '11001',
@@ -169,29 +194,34 @@ export default {
if (res.data.code == 0) {
this.products = res.data.result.records;
this.cartCount = res.data.result.cart_count;
this.filteredProducts = [...this.products];
this.filteredProducts = [...this.products]; // 初始化时显示所有商品
}
})
},
// 处理搜索:支持名称和拼音搜索
handleSearch() {
this.filteredProducts = this.products.filter(item =>
item.drug.drug_name.includes(this.searchKeyword) ||
(item.drug.pinyin_simple && item.drug.pinyin_simple.includes(this.searchKeyword.toLowerCase()))
);
},
// 清空搜索
clearSearch() {
this.searchKeyword = "";
this.filteredProducts = [...this.products];
},
// 计算可视区域高度
calculateScrollViewHeight() {
const systemInfo = uni.getSystemInfoSync();
this.scrollViewHeight = systemInfo.windowHeight - 160;
},
// 点击商品进入详情页
handClickProduct(item) {
uni.navigateTo({
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}`
});
},
// 初始化悬浮球位置:右下角
initCartPosition() {
const systemInfo = uni.getSystemInfoSync();
this.cartPosition = {
@@ -199,70 +229,59 @@ export default {
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
};
this.cartPosition = { x: finalX, y: finalY };
},
// 跳转购物车页面
goToCart() {
uni.navigateTo({
url: '/subPackages/shop/shop-cate'
});
uni.navigateTo({ url: '/subPackages/shop/shop-cate' });
},
// 显示加购弹窗
showCartPopup(item) {
this.currentProduct = item;
this.quantity = 1;
this.showPopup = true;
},
// 关闭弹窗
closePopup() {
this.showPopup = false;
},
quantityChange(value) {
console.log('[v0] 数量变化:', value);
},
quantityChange(value) {},
// 确认加入购物车
confirmAddToCart() {
try {
let cart = uni.getStorageSync('cart') || [];
if (!Array.isArray(cart)) {
cart = [];
}
saveCartApi({
store_id: uni.getStorageSync('store_id') || '11001',
drug_id: this.currentProduct.drug.id,
@@ -270,23 +289,13 @@ export default {
}).then(() => {
this.updateCartCount();
this.closePopup();
uni.showToast({
title: `已加入${this.quantity}件商品`,
icon: 'success',
duration: 1500
});
uni.showToast({ title: `已加入购物车`, icon: 'success' });
})
} catch (error) {
console.error('[v0] 加入购物车失败:', error);
uni.showToast({
title: '加入购物车失败',
icon: 'none',
duration: 1000
});
uni.showToast({ title: '失败', icon: 'none' });
}
},
// 更新购物车数量
updateCartCount() {
let that = this;
getCartCountsApi({
@@ -319,295 +328,252 @@ export default {
</script>
<style lang="scss" scoped>
/* 页面主容器:保留原有品牌色(淡蓝渐变) */
.container {
padding: 20rpx;
background: linear-gradient(180deg, #f0f5ff 0%, #ffffff 100%);
min-height: 100vh;
box-sizing: border-box;
position: relative;
padding-bottom: 40rpx;
}
.search-section {
padding: 20rpx;
background: #ffffff;
border-radius: 20rpx;
box-shadow: 0 6rpx 24rpx rgba(74,144,226,0.15);
margin-bottom: 24rpx;
/* 顶部搜索栏:吸顶效果 */
.search-sticky {
position: sticky;
top: 0;
z-index: 100;
/* 使用高透明度白色背景,既保证文字可读,又透出底部渐变 */
background: rgba(255, 255, 255, 0.95);
padding: 16rpx 24rpx;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.02);
}
.list-section {
padding-top: 10rpx;
padding: 24rpx;
}
/* --- 核心优化:商品卡片样式 --- */
.list-item {
display: flex;
padding: 28rpx;
margin-bottom: 24rpx;
border-radius: 20rpx;
background: linear-gradient(135deg, #ffffff 0%, #f8fbff 100%);
box-shadow: 0 6rpx 20rpx rgba(65, 117, 238, 0.12);
transition: all 0.3s ease;
position: relative;
overflow: hidden;
display: flex; /* 使用 Flex 布局实现左图右文 */
background: #ffffff; /* 纯白背景突出商品 */
border-radius: 20rpx; /* 大圆角,增加亲和力 */
padding: 24rpx; /* 内边距,保持呼吸感 */
margin-bottom: 20rpx; /* 卡片间距 */
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4rpx;
background: linear-gradient(90deg, #4A90E2, #5B8FF9);
opacity: 0;
transition: opacity 0.3s ease;
}
/* 阴影优化:使用品牌蓝色的极淡阴影,清爽不脏 */
box-shadow: 0 4rpx 16rpx rgba(65, 117, 238, 0.08);
transition: transform 0.1s; /* 添加点击缩放动画 */
&:active {
transform: translateY(4rpx);
box-shadow: 0 3rpx 12rpx rgba(65, 117, 238, 0.18);
transform: scale(0.99); /* 点击时的微缩反馈 */
}
}
&::before {
opacity: 1;
/* 左侧图片容器 */
.image-wrapper {
position: relative;
margin-right: 24rpx; /* 图片与文字的间距 */
.item-image {
width: 200rpx; /* 固定宽度 */
height: 200rpx; /* 固定高度,正方形 */
border-radius: 12rpx;
background-color: #f8f8f8; /* 图片加载前的占位背景 */
}
}
/* 右侧内容区域 */
.item-content {
flex: 1; /* 占满剩余空间 */
display: flex;
flex-direction: column; /* 垂直排列 */
justify-content: space-between; /* 上下两端对齐:顶部是信息,底部是价格 */
overflow: hidden;
/* 上部信息区 */
.top-info {
.item-title {
font-size: 30rpx;
font-weight: 700; /* 标题加粗 */
color: #1F2937; /* 深黑灰,易读 */
margin-bottom: 10rpx;
line-height: 1.4;
/* 限制显示两行,超出省略 */
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* 标签行布局 */
.tags-row {
display: flex;
align-items: center;
margin-bottom: 10rpx;
/* OTC/Rx 标签样式 */
.tag-otc {
font-size: 20rpx;
padding: 0 8rpx;
border-radius: 4rpx;
margin-right: 10rpx;
border: 1px solid;
line-height: 28rpx;
/* 绿/红 配色方案 */
&.green { color: #10B981; border-color: #10B981; }
&.red { color: #EF4444; border-color: #EF4444; }
}
/* 规格文本样式 */
.tag-spec {
font-size: 24rpx;
color: #6B7280; /* 灰色 */
}
}
/* 主治功能描述 */
.item-function {
font-size: 22rpx;
color: #9CA3AF; /* 浅灰,弱化显示 */
/* 限制单行显示 */
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
}
}
/* 底部价格与按钮区 */
.item-bottom {
display: flex;
justify-content: space-between; /* 价格在左,按钮在右 */
align-items: flex-end; /* 底部对齐 */
margin-top: 10rpx;
/* 价格样式 */
.price-section {
color: #EF4444; /* 价格红 */
font-weight: bold;
.currency { font-size: 24rpx; margin-right: 2rpx; }
.price-val { font-size: 36rpx; } /* 数字放大 */
}
/* 购物车按钮样式 */
.cart-btn {
width: 56rpx;
height: 56rpx;
border-radius: 50%;
/* 按钮背景:保持品牌蓝色渐变 */
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
display: flex;
align-items: center;
justify-content: center;
/* 按钮投影 */
box-shadow: 0 4rpx 10rpx rgba(74, 144, 226, 0.3);
}
}
}
.item-image {
width: 200rpx;
height: 200rpx;
margin-right: 24rpx;
border-radius: 16rpx;
border: 3rpx solid #f0f5ff;
flex-shrink: 0;
}
.item-content {
flex: 1;
display: flex;
flex-direction: column;
}
.item-title {
font-size: 32rpx;
font-weight: 600;
color: #232323;
margin-bottom: 16rpx;
line-height: 1.4;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.item-spec {
display: flex;
align-items: flex-start;
margin-bottom: 10rpx;
font-size: 26rpx;
}
.spec-label {
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
color: #ffffff;
padding: 4rpx 12rpx;
border-radius: 6rpx;
margin-right: 12rpx;
flex-shrink: 0;
font-weight: 500;
}
.spec-value {
color: #666;
flex: 1;
line-height: 1.6;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.item-bottom {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 16rpx;
margin-top: auto;
border-top: 2rpx solid #f0f5ff;
}
.price-section {
display: flex;
flex-direction: column;
gap: 6rpx;
}
.price-tag {
font-size: 36rpx;
font-weight: 700;
color: #FF6B6B;
}
.stock-tag {
font-size: 24rpx;
color: #52C41A;
font-weight: 500;
}
.cart-icon-btn {
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 6rpx 20rpx rgba(74,144,226,0.3);
transition: all 0.3s ease;
&:active {
transform: scale(0.9);
box-shadow: 0 3rpx 12rpx rgba(74,144,226,0.4);
}
}
/* 购物车悬浮球样式 */
.cart-float {
position: fixed;
width: 110rpx;
height: 110rpx;
background: linear-gradient(135deg, #FF6B6B, #FF8E8E);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 8rpx 28rpx rgba(255, 107, 107, 0.4);
z-index: 999;
transition: all 0.3s ease;
&:active {
transform: scale(0.92);
.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;
}
}
}
.cart-badge {
position: absolute;
top: -8rpx;
right: -8rpx;
}
/* 弹窗内容样式 */
.popup-content {
padding: 40rpx;
padding-bottom: calc(60rpx + env(safe-area-inset-bottom));
}
padding: 30rpx 30rpx 60rpx;
background: #fff;
.popup-header {
margin-bottom: 40rpx;
text-align: center;
padding-bottom: 30rpx;
border-bottom: 2rpx solid #f0f5ff;
}
.product-header-row {
display: flex;
margin-bottom: 40rpx;
.popup-title {
font-size: 38rpx;
font-weight: 700;
color: #232323;
}
.popup-img {
width: 180rpx;
height: 180rpx;
border-radius: 12rpx;
margin-right: 24rpx;
background: #f8f8f8;
}
.product-info {
display: flex;
margin-bottom: 50rpx;
padding: 30rpx;
background: linear-gradient(135deg, #f8fbff, #ffffff);
border-radius: 20rpx;
border: 2rpx solid #f0f5ff;
}
.popup-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
.product-image {
width: 140rpx;
height: 140rpx;
border-radius: 16rpx;
margin-right: 24rpx;
border: 2rpx solid #f0f5ff;
}
.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; }
}
}
.product-details {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.quantity-section {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 60rpx;
.product-name {
font-size: 30rpx;
font-weight: 600;
color: #232323;
margin-bottom: 12rpx;
line-height: 1.4;
}
.label {
font-size: 30rpx;
color: #1F2937;
font-weight: 500;
}
}
.product-spec {
font-size: 26rpx;
color: #999;
margin-bottom: 16rpx;
}
.popup-footer {
.action-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
border-radius: 44rpx;
font-size: 32rpx;
font-weight: 600;
.product-price {
font-size: 36rpx;
font-weight: 700;
color: #FF6B6B;
}
&.add-cart {
background: linear-gradient(90deg, #4A90E2, #5B8FF9);
color: #fff;
}
.quantity-selector {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 60rpx;
padding: 35rpx 0;
border-top: 2rpx solid #f0f5ff;
border-bottom: 2rpx solid #f0f5ff;
}
.quantity-label {
font-size: 32rpx;
color: #232323;
font-weight: 600;
}
.popup-actions {
display: flex;
gap: 20rpx;
}
.cancel-btn {
flex: 1;
background: #f5f5f5;
color: #666;
border: none;
border-radius: 50rpx;
padding: 28rpx 0;
font-size: 32rpx;
font-weight: 600;
&:active {
background: #e8e8e8;
&:active { opacity: 0.9; }
}
}
}
.confirm-btn {
flex: 2;
background: linear-gradient(135deg, #4A90E2, #5B8FF9);
color: #ffffff;
border: none;
border-radius: 50rpx;
padding: 28rpx 0;
font-size: 32rpx;
font-weight: 600;
box-shadow: 0 6rpx 20rpx rgba(74,144,226,0.3);
&:active {
opacity: 0.85;
box-shadow: 0 3rpx 12rpx rgba(74,144,226,0.4);
}
.empty-state {
margin-top: 100rpx;
}
</style>

View File

@@ -8,7 +8,7 @@
autoplay
circular
indicator-color="rgba(255,255,255,0.6)"
indicator-active-color="#536DFE"
indicator-active-color="#4175EE"
>
<swiper-item v-for="(img, index) in productImages" :key="index">
<image
@@ -19,14 +19,6 @@
/>
</swiper-item>
</swiper>
<!-- 收藏按钮 -->
<view class="favorite-btn" @click="toggleFavorite">
<u-icon
:name="isFavorite ? 'heart-fill' : 'heart'"
:color="isFavorite ? '#FF5252' : '#fff'"
size="24"
/>
</view>
</view>
<!-- 商品基本信息 -->
@@ -36,11 +28,9 @@
<text class="original-price" v-if="productDetail.daijian_price">
¥{{ productDetail.daijian_price }}
</text>
<view class="sales-tag" v-if="productDetail.is_otc === 0">
<text>处方药</text>
</view>
<view class="sales-tag" v-else>
<text>非处方药</text>
<!-- 优化标签颜色使用医疗蓝或标准的警告色 -->
<view class="sales-tag" :class="productDetail.is_otc === 0 ? 'tag-rx' : 'tag-otc'">
<text>{{ productDetail.is_otc === 0 ? '处方药' : 'OTC 非处方药' }}</text>
</view>
</view>
@@ -49,7 +39,7 @@
<view class="meta-info">
<view class="meta-item">
<u-icon name="file-text" size="16" color="#999"></u-icon>
<u-icon name="file-text" size="28" color="#999"></u-icon>
<text>规格{{ productDetail.specification || '暂无' }}</text>
</view>
</view>
@@ -93,7 +83,7 @@
@click="previewInstruction"
/>
<view v-else class="no-instruction">
<u-icon name="file-text" size="48" color="#999"></u-icon>
<u-icon name="file-text" size="60" color="#999"></u-icon>
<text>暂无说明书详见产品内部的说明书</text>
</view>
</view>
@@ -103,11 +93,11 @@
<u-popup
v-model="showCartPopup"
mode="bottom"
border-radius="20"
border-radius="24"
:closeable="true"
@close="closeCartPopup"
>
<view class="cart-popup">
<view class="cart-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">选择购买数量</text>
</view>
@@ -150,11 +140,11 @@
<u-popup
v-model="showBuyPopup"
mode="bottom"
border-radius="20"
border-radius="24"
:closeable="true"
@close="closeBuyPopup"
>
<view class="cart-popup">
<view class="cart-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">选择购买数量</text>
</view>
@@ -197,11 +187,11 @@
<u-popup
v-model="showPrescriptionFormPopup"
mode="bottom"
border-radius="20"
border-radius="24"
:closeable="true"
@close="closePrescriptionFormPopup"
>
<view class="prescription-popup">
<view class="prescription-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">请填写用药信息</text>
</view>
@@ -234,27 +224,24 @@
</view>
<u-form :model="prescriptionFormData" ref="prescriptionForm">
<!-- 是否就诊过 -->
<view class="form-item-wrapper">
<u-form-item label="是否就诊过" prop="hasVisited" label-width="200">
<u-radio-group v-model="prescriptionFormData.hasVisited">
<u-radio name="1" style="margin-right: 60rpx;"></u-radio>
<u-radio name="0"></u-radio>
<u-radio name="1" active-color="#4175EE" style="margin-right: 60rpx;"></u-radio>
<u-radio name="0" active-color="#4175EE"></u-radio>
</u-radio-group>
</u-form-item>
</view>
<!-- 是否用过此药 -->
<view class="form-item-wrapper">
<u-form-item label="是否用过此药" prop="hasUsedDrug" label-width="200">
<u-radio-group v-model="prescriptionFormData.hasUsedDrug">
<u-radio name="1" style="margin-right: 60rpx;"></u-radio>
<u-radio name="0"></u-radio>
<u-radio name="1" active-color="#4175EE" style="margin-right: 60rpx;"></u-radio>
<u-radio name="0" active-color="#4175EE"></u-radio>
</u-radio-group>
</u-form-item>
</view>
<!-- 患病信息 -->
<view class="form-item-wrapper">
<u-form-item label="患病信息" prop="illnessInfo" label-width="200">
<u-input
@@ -275,7 +262,7 @@
</view>
</u-popup>
<!-- 患病信息选择器 - 需要放在最外层避免被弹窗遮挡 -->
<!-- 患病信息选择器 -->
<u-picker
v-model="showIllnessPicker"
mode="selector"
@@ -283,24 +270,43 @@
range-key="label"
@confirm="onIllnessConfirm"
:mask-close-able="true"
confirm-color="#4175EE"
></u-picker>
<!-- 底部操作栏 -->
<!-- 底部操作栏关键优化点 -->
<view class="footer">
<view class="footer-left">
<!-- 购物车入口增加徽标 Badge -->
<view class="action-item" @click="goToCart">
<u-icon name="shopping-cart" size="24" color="#666"></u-icon>
<view class="icon-wrap">
<u-icon name="shopping-cart" size="40" color="#666"></u-icon>
<!-- 修复购物车徽标位置使用绝对定位的u-badge或自定义样式 -->
<u-badge
:count="cartCount"
type="error"
size="mini"
:offset="[-8, -8]"
absolute
v-if="cartCount > 0"
></u-badge>
</view>
<text class="action-text">购物车</text>
</view>
<view class="action-item" @click="goBack">
<u-icon name="home" size="24" color="#666"></u-icon>
<view class="icon-wrap">
<u-icon name="home" size="40" color="#666"></u-icon>
</view>
<text class="action-text">首页</text>
</view>
</view>
<!-- 按钮组优化配色 -->
<view class="footer-right">
<!-- 加入购物车浅色/辅助色 -->
<button class="add-cart-btn" @click="showCartPopup = true">加入购物车</button>
<!-- 立即购买主品牌色 -->
<button class="buy-now-btn" @click="handleBuyNow">
{{ productDetail.is_otc === 0 ? '立即购买' : '立即下单' }}
{{ productDetail.is_otc === 0 ? '立即咨询' : '立即购买' }}
</button>
</view>
</view>
@@ -308,6 +314,7 @@
</template>
<script>
// 保持脚本逻辑不变仅确保API引用正确
import {getOrderTextApi, getStoreDrugDetailApi} from "@/request/api/product";
import { genOrderApi } from "@/request/api/order";
import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
@@ -349,16 +356,10 @@ export default {
isFavorite: false,
cartCount: 0,
submitted: false,
// 购物车弹窗数据
showCartPopup: false,
cartQuantity: 1,
// 立即购买弹窗数据(非处方药)
showBuyPopup: false,
buyQuantity: 1,
// 处方药表单弹窗数据
showPrescriptionFormPopup: false,
prescriptionQuantity: 1,
prescriptionFormData: {
@@ -366,14 +367,12 @@ export default {
hasUsedDrug: '1',
illnessInfo: '',
},
illnessOptions: [],
showIllnessPicker: false,
orderText: '本次商品物流配送,由萧康医药提供服务。',
};
},
computed: {
// 计算商品价格优先使用drug_store_drug.price
productPrice() {
if (this.productDetail.drug_store_drug && this.productDetail.drug_store_drug.price) {
return parseFloat(this.productDetail.drug_store_drug.price);
@@ -383,7 +382,6 @@ export default {
},
onLoad(options) {
if (options.id) {
// 从options中获取传递的参数
this.productDetail.id = options.id;
this.formData.id = options.id;
this.formData.type = options.type || '';
@@ -391,17 +389,11 @@ export default {
this.formData.price = parseFloat(options.price || 0);
this.formData.doctor_id = options.doctor_id || '';
this.formData.drug_name = options.drug_name || '';
// 设置productDetail的基本信息
this.productDetail.id = options.id;
this.productDetail.drug_name = options.drug_name || '';
this.productDetail.image = options.image || '';
this.productDetail.price = parseFloat(options.price || 0);
// 加载商品详情
this.getDetail();
} else {
// 如果没有id参数尝试从本地存储获取
const savedId = uni.getStorageSync('symptoms_id');
if (savedId) {
this.productDetail.id = savedId;
@@ -409,8 +401,6 @@ export default {
this.getDetail();
}
}
// 更新购物车数量
this.updateCartCount();
},
onShow() {
@@ -426,7 +416,6 @@ export default {
console.error('获取订单提示失败:', err);
})
},
// 获取商品详情 - 保留原有的getDetail方法
getDetail() {
let that = this;
this.getOrderText();
@@ -435,44 +424,22 @@ export default {
}).then((res) => {
if (res.data.code === 0) {
const data = res.data.result;
// 更新productDetail
Object.assign(this.productDetail, data);
// 处理商品图片
this.productImages = data.image ? [data.image] : [];
// 处理功效信息
if (data.indications_array && data.indications_array.length > 0) {
this.illnessOptions = data.indications_array.map(item => ({
value: item.label || item.value,
label: item.label || item.value
}));
}
// 如果没有功效信息使用function字段
if (!this.productDetail.indications && data.function) {
this.productDetail.indications = data.function;
}
console.log('商品详情加载成功:', this.productDetail);
console.log('商品价格:', this.productPrice);
}
}).catch(error => {
console.error('加载商品详情失败:', error);
uni.showToast({
title: '加载失败',
icon: 'none'
});
});
},
updateTotalPrice() {
// 保留原有的更新总价逻辑
return (this.productPrice * this.formData.number).toFixed(2);
},
// 图片预览
previewImage(index) {
if (this.productImages.length > 0) {
uni.previewImage({
@@ -481,8 +448,6 @@ export default {
});
}
},
// 说明书预览
previewInstruction() {
if (this.productDetail.instruction) {
uni.previewImage({
@@ -490,17 +455,6 @@ export default {
});
}
},
// 收藏功能
toggleFavorite() {
this.isFavorite = !this.isFavorite;
uni.showToast({
title: this.isFavorite ? '已收藏' : '已取消收藏',
icon: 'none'
});
},
// 更新购物车数量
updateCartCount() {
getCartCountsApi({
store_id: uni.getStorageSync('store_id') || '11001',
@@ -512,8 +466,6 @@ export default {
}
})
},
// 加入购物车
addToCart() {
saveCartApi({
store_id: uni.getStorageSync('store_id') || '11001',
@@ -522,33 +474,20 @@ export default {
}).then(() => {
this.updateCartCount();
this.closeCartPopup();
uni.showToast({
title: `已加入${this.cartQuantity}件商品`,
icon: 'success',
duration: 1500
});
}).catch(error => {
console.error('加入购物车失败:', error);
uni.showToast({
title: '加入购物车失败',
icon: 'none'
});
});
})
},
// 处理立即购买
handleBuyNow() {
if (this.productDetail.is_otc === 0) {
// 处方药:显示表单弹窗
this.showPrescriptionFormPopup = true;
} else {
// 非处方药:显示数量选择弹窗
this.showBuyPopup = true;
}
},
// 非处方药立即下单
buyNowConfirm() {
genOrderApi({
drug_id: this.productDetail.id,
@@ -559,105 +498,57 @@ export default {
uni.navigateTo({
url: `/subPackages/my/my-drug/drug-info?id=${resOrder.data.result.id}&order_type=${resOrder.data.result.order_type}`
});
}).catch(error => {
console.error('下单失败:', error);
uni.showToast({
title: '下单失败',
icon: 'none'
});
});
})
},
// 提交处方药表单
submitPrescriptionForm() {
// 验证表单
if (!this.prescriptionFormData.hasVisited) {
if (!this.prescriptionFormData.hasVisited || !this.prescriptionFormData.hasUsedDrug || !this.prescriptionFormData.illnessInfo) {
uni.showToast({
title: '请选择是否就诊过',
title: '请填写完整信息',
icon: 'none'
});
return;
}
if (!this.prescriptionFormData.hasUsedDrug) {
uni.showToast({
title: '请选择是否用过此药',
icon: 'none'
});
return;
}
if (!this.prescriptionFormData.illnessInfo) {
uni.showToast({
title: '请选择患病信息',
icon: 'none'
});
return;
}
// 设置submitted状态
this.submitted = true;
// 处方药流程
uni.showToast({
title: '信息提交成功',
icon: 'success'
});
// 关闭弹窗
this.closePrescriptionFormPopup();
// 准备跳转数据 - 包含购买数量
const rInfo = {
id: this.productDetail.id,
drug_name: this.productDetail.drug_name,
image: this.productDetail.image,
price: this.productPrice,
number: this.prescriptionQuantity, // 使用处方药弹窗中的购买数量
number: this.prescriptionQuantity,
hasVisited: this.prescriptionFormData.hasVisited,
hasUsedDrug: this.prescriptionFormData.hasUsedDrug,
illnessInfo: this.prescriptionFormData.illnessInfo,
doctor_id: this.formData.doctor_id,
type: this.formData.type
};
// 跳转到医生信息页
uni.navigateTo({
url: `/subPackages/doctor/doctor-userinfo?id=${this.formData.doctor_id}&r_info=${JSON.stringify(rInfo)}&r_type=${this.formData.type}`
});
},
// 跳转购物车
goToCart() {
uni.navigateTo({
url: '/subPackages/shop/shop-cate'
});
},
// 返回首页
goBack() {
uni.navigateBack({
delta: 1
});
},
// 患病信息选择
onIllnessConfirm(e) {
const index = e[0];
this.prescriptionFormData.illnessInfo = this.illnessOptions[index].value;
this.showIllnessPicker = false;
},
closeCartPopup() {
this.showCartPopup = false;
this.cartQuantity = 1;
},
closeBuyPopup() {
this.showBuyPopup = false;
this.buyQuantity = 1;
},
closePrescriptionFormPopup() {
this.showPrescriptionFormPopup = false;
this.prescriptionQuantity = 1;
@@ -675,7 +566,9 @@ export default {
.container {
background-color: #f5f8ff;
min-height: 100vh;
padding-bottom: 120rpx; // 底部操作栏留出空间
// 底部留白 = 固定操作栏高度 + 安全距离 + 额外间距
padding-bottom: calc(120rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}
// 轮播图区域
@@ -693,20 +586,6 @@ export default {
width: 100%;
height: 100%;
}
.favorite-btn {
position: absolute;
right: 30rpx;
top: 30rpx;
width: 60rpx;
height: 60rpx;
background: rgba(0, 0, 0, 0.3);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
z-index: 10;
}
}
// 基本信息区域
@@ -735,11 +614,21 @@ export default {
}
.sales-tag {
background: linear-gradient(135deg, #ff7875, #ff4d4f);
color: white;
padding: 6rpx 16rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
font-size: 22rpx;
&.tag-rx {
background: #ffe5e5;
color: #ff4d4f;
border: 1px solid #ff4d4f;
}
&.tag-otc {
background: #e6f7ff;
color: #00B578;
border: 1px solid #00B578;
}
}
}
@@ -761,27 +650,30 @@ export default {
.meta-item {
display: flex;
align-items: center;
font-size: 24rpx;
font-size: 26rpx;
color: #666;
margin-bottom: 8rpx;
background: #f9f9f9;
padding: 10rpx 20rpx;
border-radius: 8rpx;
display: inline-flex;
u-icon {
margin-right: 8rpx;
margin-right: 12rpx;
}
}
}
}
/* 新增:物流提示样式 */
// 物流提示
.order-text-tip {
background: #e6f3ff;
padding: 20rpx 30rpx;
margin: 0 20rpx 20rpx 20rpx;
border-radius: 8rpx;
border-radius: 12rpx;
font-size: 26rpx;
color: #1890ff;
line-height: 1.4;
border-left: 6rpx solid #1890ff;
color: #4175EE; // 统一为医疗蓝
line-height: 1.5;
border-left: 8rpx solid #4175EE;
}
// 详情区域
@@ -794,9 +686,9 @@ export default {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
margin-bottom: 24rpx;
position: relative;
padding-left: 20rpx;
padding-left: 24rpx;
&::before {
content: "";
@@ -804,106 +696,78 @@ export default {
left: 0;
top: 50%;
transform: translateY(-50%);
width: 6rpx;
height: 30rpx;
background: #536DFE;
border-radius: 3rpx;
width: 8rpx;
height: 32rpx;
background: #4175EE; // 统一颜色
border-radius: 4rpx;
}
}
.section-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
color: #555;
line-height: 1.8;
text-align: justify;
}
// 说明书区域
.instruction-content {
.instruction-image {
width: 100%;
border-radius: 12rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
}
.no-instruction {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60rpx 0;
u-icon {
margin-bottom: 20rpx;
}
text {
font-size: 28rpx;
color: #999;
text-align: center;
}
u-icon { margin-bottom: 20rpx; }
text { font-size: 28rpx; color: #999; }
}
}
}
// 表单区域
// 通用表单项间距
.form-item-wrapper {
margin-bottom: 30rpx;
&:last-child {
margin-bottom: 0;
}
}
// 购物车/购买弹窗
.cart-popup {
// 弹窗通用样式
.cart-popup, .prescription-popup {
padding: 40rpx;
padding-bottom: 20rpx; // 基础padding不含安全距离
// 弹窗底部增加安全距离
&.safe-area-bottom {
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
}
.popup-header {
margin-bottom: 40rpx;
text-align: center;
}
.popup-title {
font-size: 36rpx;
font-weight: 600;
color: #2c3e50;
.popup-title { font-size: 36rpx; font-weight: 600; color: #333; }
}
.product-info {
display: flex;
margin-bottom: 40rpx;
.product-image {
width: 120rpx;
height: 120rpx;
width: 140rpx;
height: 140rpx;
border-radius: 12rpx;
margin-right: 24rpx;
border: 1px solid #f0f0f0;
}
.product-details {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.product-name {
font-size: 30rpx;
font-weight: 500;
color: #2c3e50;
margin-bottom: 8rpx;
line-height: 1.4;
}
.product-spec {
font-size: 24rpx;
color: #95a5a6;
margin-bottom: 12rpx;
}
.product-price {
font-size: 32rpx;
font-weight: 600;
color: #ff4d4f;
}
.product-name { font-size: 30rpx; font-weight: bold; color: #333; margin-bottom: 8rpx; }
.product-spec { font-size: 24rpx; color: #999; margin-bottom: 12rpx; }
.product-price { font-size: 36rpx; font-weight: bold; color: #ff4d4f; }
}
}
@@ -912,205 +776,87 @@ export default {
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-top: 1rpx solid #f0f0f0;
border-bottom: 1rpx solid #f0f0f0;
.quantity-label {
font-size: 30rpx;
color: #2c3e50;
font-weight: 500;
}
border-top: 1rpx solid #f5f5f5;
border-bottom: 1rpx solid #f5f5f5;
.quantity-label { font-size: 30rpx; color: #333; font-weight: 500; }
}
.popup-actions {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
margin-top: 50rpx;
gap: 30rpx;
.cancel-btn {
flex: 1;
margin-right: 20rpx;
background-color: #f8f9fa;
color: #95a5a6;
border: none;
background-color: #f5f7fa;
color: #666;
border-radius: 50rpx;
padding: 24rpx 0;
font-size: 30rpx;
font-weight: 500;
&:active {
background-color: #e9ecef;
}
border: none;
}
.confirm-btn {
flex: 1;
margin-left: 20rpx;
background: linear-gradient(135deg, #4A90E2, #3A86FF);
// 统一使用医疗蓝渐变
background: linear-gradient(135deg, #4A90E2, #4175EE);
color: #ffffff;
border: none;
border-radius: 50rpx;
padding: 24rpx 0;
font-size: 30rpx;
font-weight: 500;
&:active {
opacity: 0.8;
}
border: none;
box-shadow: 0 6rpx 16rpx rgba(65, 117, 238, 0.3);
}
}
}
// 处方药表单弹窗
.prescription-popup {
padding: 40rpx;
max-height: 80vh;
overflow-y: auto;
.popup-header {
margin-bottom: 40rpx;
text-align: center;
}
.popup-title {
font-size: 36rpx;
font-weight: 600;
color: #2c3e50;
}
.product-info {
display: flex;
margin-bottom: 40rpx;
.product-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
margin-right: 24rpx;
}
.product-details {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.product-name {
font-size: 30rpx;
font-weight: 500;
color: #2c3e50;
margin-bottom: 8rpx;
line-height: 1.4;
}
.product-spec {
font-size: 24rpx;
color: #95a5a6;
margin-bottom: 12rpx;
}
.product-price {
font-size: 32rpx;
font-weight: 600;
color: #ff4d4f;
}
}
}
.quantity-selector {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-top: 1rpx solid #f0f0f0;
border-bottom: 1rpx solid #f0f0f0;
.quantity-label {
font-size: 30rpx;
color: #2c3e50;
font-weight: 500;
}
}
.popup-actions {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
.cancel-btn {
flex: 1;
margin-right: 20rpx;
background-color: #f8f9fa;
color: #95a5a6;
border: none;
border-radius: 50rpx;
padding: 24rpx 0;
font-size: 30rpx;
font-weight: 500;
&:active {
background-color: #e9ecef;
}
}
.confirm-btn {
flex: 1;
margin-left: 20rpx;
background: linear-gradient(135deg, #4A90E2, #3A86FF);
color: #ffffff;
border: none;
border-radius: 50rpx;
padding: 24rpx 0;
font-size: 30rpx;
font-weight: 500;
&:active {
opacity: 0.8;
}
}
}
}
// 底部操作栏
// 底部操作栏 - 固定 + 适配
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 100rpx;
// 高度 = 内容高度(110rpx) + 安全距离
height: calc(110rpx + constant(safe-area-inset-bottom));
height: calc(110rpx + env(safe-area-inset-bottom));
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
background: #fff;
display: flex;
align-items: center;
padding: 0 20rpx;
box-shadow: 0 -2rpx 20rpx rgba(0, 0, 0, 0.1);
padding-left: 30rpx;
padding-right: 30rpx;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
z-index: 1000;
box-sizing: border-box; // 关键包含padding在高度内
.footer-left {
display: flex;
align-items: center;
flex: 1;
flex: 0 0 auto;
margin-right: 30rpx;
.action-item {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
margin-right: 40rpx;
position: relative;
.icon-wrap {
position: relative; // 为 Badge 绝对定位提供基准
width: 48rpx;
height: 48rpx;
display: flex;
justify-content: center;
align-items: center;
}
.action-text {
font-size: 20rpx;
color: #666;
margin-top: 4rpx;
}
.cart-badge-container {
position: absolute;
top: -10rpx;
right: -10rpx;
}
.cart-badge {
position: relative;
margin-top: 6rpx;
}
}
}
@@ -1118,7 +864,8 @@ export default {
.footer-right {
display: flex;
align-items: center;
flex: 2;
flex: 1;
gap: 20rpx;
button {
flex: 1;
@@ -1126,24 +873,29 @@ export default {
line-height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
font-weight: 500;
font-weight: 600;
border: none;
padding: 0;
&.add-cart-btn {
background: linear-gradient(135deg, #FF9800, #FFB74D);
color: white;
margin-right: 20rpx;
// 加入购物车:浅色风格,避免视觉争抢
background: #EBF3FF;
color: #4175EE;
border: 2rpx solid #EBF3FF;
}
&.buy-now-btn {
background: linear-gradient(135deg, #536DFE, #6C8EFF);
// 立即购买:强烈的品牌色
background: linear-gradient(135deg, #4A90E2, #4175EE);
color: white;
box-shadow: 0 6rpx 16rpx rgba(65, 117, 238, 0.3);
}
&:active {
opacity: 0.8;
transform: scale(0.98);
opacity: 0.9;
}
}
}
}
</style>
</style>

View File

@@ -1,6 +1,6 @@
<template>
<view class="container safe-area-inset-bottom">
<!-- 清空购物车 -->
<!-- 头部区域显示数量和清空按钮 -->
<view class="head">
<view class="num">
购物车{{ totalCount }}件商品
@@ -11,28 +11,41 @@
</view>
</view>
<!-- 商品列表 -->
<!-- 商品列表卡片 -->
<view class="card">
<!-- 门店 -->
<!-- 门店名称 -->
<view class="store">
<text class="iconfont icon-mendian"></text>
{{ cartLists.store_name }}
</view>
<!-- 购物车列表循环 -->
<u-checkbox-group>
<view class="list" v-for="item in cartLists.data" :key="item.id">
<!-- 复选框 -->
<u-checkbox shape="circle" @change="checkboxChange(item)" v-model="item.checked">
</u-checkbox>
<view class="img" @click="checkboxChange(item)">
<image :src="item.drug.image" mode=""></image>
<!-- 商品图片点击跳转详情 (使用 .stop 阻止冒泡避免触发选中) -->
<view class="img" @click.stop="goProductDetail(item)">
<image :src="item.drug.image" mode="aspectFill"></image>
</view>
<!-- 商品信息区域点击空白处切换选中状态 -->
<view class="it" @click="checkboxChange(item)">
<view class="it_name">{{ item.drug.drug_name }}</view>
<!-- 商品名称点击跳转详情 (使用 .stop 阻止冒泡) -->
<view class="it_name" @click.stop="goProductDetail(item)">{{ item.drug.drug_name }}</view>
<!-- 规格/用法信息 -->
<view class="it_info">{{ item.drug.usage }}</view>
<!-- 价格与数量控制器 -->
<view class="it_price">
<text>{{ item.drug.drugstore_drug.price }}</text>
<!-- 显示价格 -->
<text>{{ item.drug.drugstore_drug ? item.drug.drugstore_drug.price : (item.drug.drug_store_relations ? item.drug.drug_store_relations.price : '0.00') }}</text>
<!-- 步进器点击阻止冒泡防止触发选中 -->
<view class="it_num" @click.stop>
<uni-number-box :min="1" @change="changeNum($event,item)" :value="item.qty">
</uni-number-box>
@@ -43,6 +56,7 @@
</u-checkbox-group>
</view>
<!-- 底部结算栏 -->
<view class="footer">
<view class="allselect-left" @click="checkedAll">
<u-checkbox-group>
@@ -61,12 +75,11 @@
</template>
<script>
// CartList
// 引入API接口
import {
CartList,
addCart,
clearAll
} from '../../request/api/api'
import {getCartListApi, saveCartApi} from "@/request/api/cart";
import {genOrderByCartApi} from "@/request/api/order";
@@ -74,7 +87,7 @@ import {genOrderByCartApi} from "@/request/api/order";
export default {
data() {
return {
checked: false,
checked: false, // 全选状态
allcheck: false,
value: 1,
numberValue: 0,
@@ -83,49 +96,52 @@ export default {
checked: false,
disabled: false
}],
selectList: [], //选中的数据
cartLists: {
selectList: [], // 选中的数据
cartLists: { // 购物车列表数据源
data: []
},
drug_ids: [],//药品id
cart_ids: [],//购物车id
drug_ids: [], // 药品id集合
cart_ids: [], // 购物车id集合
qty: '',
change_qty: '',
true_qty: ''
}
},
// onLoad() {
// this.getCartList()
// },
onShow() {
this.getCartList()
},
computed: {
//全部价格
// 计算选中商品的总价格
totalPrice: function() {
// 添加空值检查
// 空值检查,防止报错
if (!this.cartLists || !this.cartLists.data || this.cartLists.data.length === 0) {
return '0.00';
}
let totalPrice = 0;
// 过滤出已选中的商品,再计算总价
// 过滤出已选中的商品
const checkedItems = this.cartLists.data.filter(item => item.checked);
checkedItems.forEach(item => {
// 添加价格和数量的有效性检查
const price = item.drug?.drug_store_relations?.price || 0;
// 兼容不同字段结构获取价格
let price = 0;
if(item.drug && item.drug.drugstore_drug && item.drug.drugstore_drug.price) {
price = item.drug.drugstore_drug.price;
} else if (item.drug && item.drug.drug_store_relations && item.drug.drug_store_relations.price) {
price = item.drug.drug_store_relations.price;
}
const qty = item.qty || 0;
totalPrice += price * qty;
});
return totalPrice.toFixed(2);
},
//全部件数
// 计算购物车总件数
totalCount: function () {
if (!this.cartLists || !this.cartLists.data) return 0;
var totalCount = 0;
for (var i = 0; i < this.cartLists.data.length; i++) {
totalCount += this.cartLists.data[i].qty;
@@ -135,73 +151,57 @@ export default {
},
methods: {
//清空购物车
// 跳转商品详情页
goProductDetail(item) {
if (!item || !item.drug) return;
// 获取显示价格,逻辑与模板保持一致
let price = '0';
if (item.drug.drugstore_drug && item.drug.drugstore_drug.price) {
price = item.drug.drugstore_drug.price;
} else if (item.drug.drug_store_relations && item.drug.drug_store_relations.price) {
price = item.drug.drug_store_relations.price;
}
// 构建参数并跳转
uni.navigateTo({
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=${price}`
});
},
// 清空购物车
clearCart() {
// const list=this.cartLists.data.map(item=>item.drug_id)
// this.drug_id=list
// this.true_qty=0
// this.addToCart()
this.clearAll()
},
// 搜索
toSearch() {
// this.getList()
},
//加减法
// 步进器数量变化
changeNum(e, current) {
console.log(e, current);
this.cartLists.data.forEach(item => {
if (item.id == current.id) {
item.qty = e;
this.true_qty = e
// this.qty=e
this.drug_id = current.drug_id
this.addToCart()
}
})
},
// 选中某个复选框时由checkbox时触发
// 单个商品复选框状态改变
checkboxChange(item) {
console.log(item);
// this.drug_ids.push(item.drug_id)
// this.cart_ids.push(item.id)
item.checked = !item.checked
// 如果存在未选中的项,则取消全选状态
if (this.cartLists.data.filter(e => !e.checked).length) {
this.checked = false
} else {
this.checked = true
}
// console.log(item);
// item.checked = !item.checked
// if (!item.checked) {
// this.allChecked = false
// } else {
// // 判断每一个商品是否是被选择的状态
// const cartList = this.list.every(item => {
// return item.checked === true
// })
// if (cartList) {
// this.allChecked = true
// } else {
// this.allChecked = false
// }
// }
},
//// 更新购物车中商品的数量
// 选中任一checkbox时由checkbox-group触发
checkboxGroupChange(item) {
console.log(item, 7711117);
// console.log(e,c);
},
// 全选
// 全选/反
checkedAll() {
// 如果当前已经是全部选中状态,则全部取消
if (this.cartLists.data.filter(item => item.checked).length === this.cartLists.data.length) {
this.cartLists = {
...this.cartLists,
@@ -213,6 +213,7 @@ export default {
})
}
} else {
// 否则全部选中
this.cartLists = {
...this.cartLists,
data: this.cartLists.data.map(item => {
@@ -223,18 +224,26 @@ export default {
})
}
}
},
// 去结算
toPay() {
const list = this.cartLists.data.filter(item => item.checked).map(item => {
return {
drug_id: item.drug_id,
id: item.id,
numbers: item.qty
// numbers:item.qty,
}
})
if(list.length === 0) {
uni.showToast({
title: '请先选择商品',
icon: 'none'
});
return;
}
let cart_ids = list.map(item => item.id);
genOrderByCartApi({
store_id: uni.getStorageSync('store_id') || '11001',
@@ -246,67 +255,56 @@ export default {
})
}
})
// uni.navigateTo({
// url: `/subPackages/shop/shop-pay?list=${JSON.stringify(list)}`
// })
},
// 清空购物车
// 调用API清空购物车
clearAll() {
clearAll({
method: "post",
data: {
store_id: uni.getStorageSync('store_id') || '11001',
}
}).then((res) => {
// console.log(res, 'list');
if (res.data.code == 0) {
console.log(res);
// 提示成功清空购物车
uni.showToast({
title: '清空成功',
icon: 'success',
})
this.getCartList()
}
})
},
// 更新购物车数量到服务器
addToCart() {
saveCartApi({
store_id: uni.getStorageSync('store_id') || '11001',
drug_id: this.drug_id,
quantity: this.true_qty
// id:this.id
}).then((res) => {
// console.log(res, 'list');
if (res.data.code == 0) {
console.log(res);
console.log('数量更新成功');
}
})
},
//请求购物车列表数据
// 获取购物车列表数据
getCartList() {
getCartListApi({
store_id: uni.getStorageSync('store_id') || '11001',
}).then((res) => {
console.log(res, 'list');
if (res.data.code == 0) {
// this.drugLists=res.data.data
this.cartLists = {
...res.data.result,
data: res.data.result.data.map((item) => {
return {
...item,
checked: false
checked: false // 默认不选中
};
})
};
console.log(this.cartLists, 666);
// console.log(this.cartLists.data[0].drug);
}
})
},
}
@@ -369,7 +367,6 @@ export default {
vertical-align: middle;
margin-right: 10rpx;
}
}
.list {
@@ -435,7 +432,6 @@ export default {
}
}
}
}
.footer {
@@ -475,7 +471,6 @@ export default {
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
}
}
}