Files
xk-client-wx/subPackages/product/symptoms.vue

902 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="container">
<!-- 商品图片轮播 -->
<view class="swiper-section">
<swiper
class="swiper"
indicator-dots
autoplay
circular
indicator-color="rgba(255,255,255,0.6)"
indicator-active-color="#4175EE"
>
<swiper-item v-for="(img, index) in productImages" :key="index">
<image
class="swiper-image"
:src="img"
mode="aspectFill"
@click="previewImage(index)"
/>
</swiper-item>
</swiper>
</view>
<!-- 商品基本信息 -->
<view class="basic-info">
<view class="price-section">
<text class="current-price">¥{{ productPrice }}</text>
<text class="original-price" v-if="productDetail.daijian_price">
¥{{ productDetail.daijian_price }}
</text>
<!-- 优化标签颜色:使用医疗蓝或标准的警告色 -->
<view class="sales-tag" :class="productDetail.is_otc === 0 ? 'tag-rx' : 'tag-otc'">
<text>{{ productDetail.is_otc === 0 ? '处方药' : 'OTC 非处方药' }}</text>
</view>
</view>
<view class="product-name">{{ productDetail.drug_name }}</view>
<view class="product-subtitle">{{ productDetail.drug_alias || productDetail.drug_name }}</view>
<view class="meta-info">
<view class="meta-item">
<u-icon name="file-text" size="28" color="#999"></u-icon>
<text>规格:{{ productDetail.specification || '暂无' }}</text>
</view>
</view>
</view>
<!-- 物流提示信息 -->
<view class="order-text-tip" v-if="orderText">
<text>{{ orderText }}</text>
</view>
<!-- 功效与用法 -->
<view class="detail-section">
<view class="section-title">
<text>功效主治</text>
</view>
<view class="section-content">
{{ productDetail.function || productDetail.indications || '暂无相关信息' }}
</view>
</view>
<view class="detail-section">
<view class="section-title">
<text>用法用量</text>
</view>
<view class="section-content">
{{ productDetail.usage || '暂无相关信息' }}
</view>
</view>
<!-- 说明书 -->
<view class="detail-section">
<view class="section-title">
<text>说明书</text>
</view>
<view class="instruction-content">
<image
v-if="productDetail.instruction"
class="instruction-image"
:src="productDetail.instruction"
mode="widthFix"
@click="previewInstruction"
/>
<view v-else class="no-instruction">
<u-icon name="file-text" size="60" color="#999"></u-icon>
<text>暂无说明书,详见产品内部的说明书</text>
</view>
</view>
</view>
<!-- 购物车弹窗 -->
<u-popup
v-model="showCartPopup"
mode="bottom"
border-radius="24"
:closeable="true"
@close="closeCartPopup"
>
<view class="cart-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">选择购买数量</text>
</view>
<view class="product-info">
<image
class="product-image"
:src="productDetail.image"
mode="aspectFill"
></image>
<view class="product-details">
<text class="product-name">{{ productDetail.drug_name }}</text>
<text class="product-spec">{{ productDetail.specification || '暂无规格' }}</text>
<view class="product-price">¥{{ productPrice }}</view>
</view>
</view>
<view class="quantity-selector">
<text class="quantity-label">购买数量</text>
<view class="quantity-controls">
<u-number-box
v-model="cartQuantity"
:min="1"
:max="999"
integer
:step="1"
:disabled-input="false"
></u-number-box>
</view>
</view>
<view class="popup-actions">
<button class="cancel-btn" @click="closeCartPopup">取消</button>
<button class="confirm-btn" @click="addToCart">加入购物车</button>
</view>
</view>
</u-popup>
<!-- 立即购买弹窗(非处方药) -->
<u-popup
v-model="showBuyPopup"
mode="bottom"
border-radius="24"
:closeable="true"
@close="closeBuyPopup"
>
<view class="cart-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">选择购买数量</text>
</view>
<view class="product-info">
<image
class="product-image"
:src="productDetail.image"
mode="aspectFill"
></image>
<view class="product-details">
<text class="product-name">{{ productDetail.drug_name }}</text>
<text class="product-spec">{{ productDetail.specification || '暂无规格' }}</text>
<view class="product-price">¥{{ productPrice }}</view>
</view>
</view>
<view class="quantity-selector">
<text class="quantity-label">购买数量</text>
<view class="quantity-controls">
<u-number-box
v-model="buyQuantity"
:min="1"
:max="999"
integer
:step="1"
:disabled-input="false"
></u-number-box>
</view>
</view>
<view class="popup-actions">
<button class="cancel-btn" @click="closeBuyPopup">取消</button>
<button class="confirm-btn" @click="buyNowConfirm">立即下单</button>
</view>
</view>
</u-popup>
<!-- 处方药购买表单弹窗 -->
<u-popup
v-model="showPrescriptionFormPopup"
mode="bottom"
border-radius="24"
:closeable="true"
@close="closePrescriptionFormPopup"
>
<view class="prescription-popup safe-area-bottom">
<view class="popup-header">
<text class="popup-title">请填写用药信息</text>
</view>
<view class="product-info">
<image
class="product-image"
:src="productDetail.image"
mode="aspectFill"
></image>
<view class="product-details">
<text class="product-name">{{ productDetail.drug_name }}</text>
<text class="product-spec">{{ productDetail.specification || '暂无规格' }}</text>
<view class="product-price">¥{{ productPrice }}</view>
</view>
</view>
<view class="quantity-selector">
<text class="quantity-label">购买数量</text>
<view class="quantity-controls">
<u-number-box
v-model="prescriptionQuantity"
:min="1"
:max="999"
integer
:step="1"
:disabled-input="false"
></u-number-box>
</view>
</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" 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" 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
v-model="prescriptionFormData.illnessInfo"
type="select"
placeholder="请选择患病信息"
@click="showIllnessPicker = true"
disabled
/>
</u-form-item>
</view>
</u-form>
<view class="popup-actions">
<button class="cancel-btn" @click="closePrescriptionFormPopup">取消</button>
<button class="confirm-btn" @click="submitPrescriptionForm">提交信息</button>
</view>
</view>
</u-popup>
<!-- 患病信息选择器 -->
<u-picker
v-model="showIllnessPicker"
mode="selector"
:range="illnessOptions"
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">
<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">
<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 ? '立即咨询' : '立即购买' }}
</button>
</view>
</view>
</view>
</template>
<script>
// 保持脚本逻辑不变,仅确保API引用正确
import {getOrderTextApi, getStoreDrugDetailApi} from "@/request/api/product";
import { genOrderApi } from "@/request/api/order";
import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
export default {
data() {
return {
productDetail: {
id: '',
drug_name: '',
drug_alias: '',
image: '',
price: 0,
drug_store_drug: { price: 0 },
daijian_price: null,
specification: '',
function: '',
usage: '',
instruction: '',
is_otc: 1,
guozi_no: '',
bar_code: '',
indications: '',
indications_array: []
},
formData: {
id: '',
hasVisited: '1',
hasUsedDrug: '1',
number: 1,
illnessInfo: '',
doctor_id: '',
type: '',
drug_name: '',
image: '',
price: 0
},
productImages: [],
isFavorite: false,
cartCount: 0,
submitted: false,
showCartPopup: false,
cartQuantity: 1,
showBuyPopup: false,
buyQuantity: 1,
showPrescriptionFormPopup: false,
prescriptionQuantity: 1,
prescriptionFormData: {
hasVisited: '1',
hasUsedDrug: '1',
illnessInfo: '',
},
illnessOptions: [],
showIllnessPicker: false,
orderText: '本次商品物流配送,由萧康医药提供服务。',
};
},
computed: {
productPrice() {
if (this.productDetail.drug_store_drug && this.productDetail.drug_store_drug.price) {
return parseFloat(this.productDetail.drug_store_drug.price);
}
return parseFloat(this.productDetail.price || 0);
}
},
onLoad(options) {
if (options.id) {
this.productDetail.id = options.id;
this.formData.id = options.id;
this.formData.type = options.type || '';
this.formData.image = options.image || '';
this.formData.price = parseFloat(options.price || 0);
this.formData.doctor_id = options.doctor_id || '';
this.formData.drug_name = options.drug_name || '';
this.productDetail.drug_name = options.drug_name || '';
this.productDetail.image = options.image || '';
this.productDetail.price = parseFloat(options.price || 0);
this.getDetail();
} else {
const savedId = uni.getStorageSync('symptoms_id');
if (savedId) {
this.productDetail.id = savedId;
this.formData.id = savedId;
this.getDetail();
}
}
this.updateCartCount();
},
onShow() {
this.updateCartCount();
},
methods: {
getOrderText() {
getOrderTextApi().then((res) => {
if (res.data && res.data.result) {
this.orderText = res.data.result;
}
}).catch(err => {
console.error('获取订单提示失败:', err);
})
},
getDetail() {
let that = this;
this.getOrderText();
getStoreDrugDetailApi({
id: this.productDetail.id,
}).then((res) => {
if (res.data.code === 0) {
const data = res.data.result;
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
}));
}
if (!this.productDetail.indications && data.function) {
this.productDetail.indications = data.function;
}
}
}).catch(error => {
console.error('加载商品详情失败:', error);
});
},
previewImage(index) {
if (this.productImages.length > 0) {
uni.previewImage({
current: index,
urls: this.productImages
});
}
},
previewInstruction() {
if (this.productDetail.instruction) {
uni.previewImage({
urls: [this.productDetail.instruction]
});
}
},
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;
}
})
},
addToCart() {
saveCartApi({
store_id: uni.getStorageSync('store_id') || '11001',
drug_id: this.productDetail.id,
quantity: this.cartQuantity
}).then(() => {
this.updateCartCount();
this.closeCartPopup();
uni.showToast({
title: `已加入${this.cartQuantity}件商品`,
icon: 'success',
duration: 1500
});
})
},
handleBuyNow() {
if (this.productDetail.is_otc === 0) {
this.showPrescriptionFormPopup = true;
} else {
this.showBuyPopup = true;
}
},
buyNowConfirm() {
genOrderApi({
drug_id: this.productDetail.id,
number: this.buyQuantity,
store_id: uni.getStorageSync('store_id') || '11001',
}).then((resOrder) => {
this.closeBuyPopup();
uni.navigateTo({
url: `/subPackages/my/my-drug/drug-info?id=${resOrder.data.result.id}&order_type=${resOrder.data.result.order_type}`
});
})
},
submitPrescriptionForm() {
if (!this.prescriptionFormData.hasVisited || !this.prescriptionFormData.hasUsedDrug || !this.prescriptionFormData.illnessInfo) {
uni.showToast({
title: '请填写完整信息',
icon: 'none'
});
return;
}
this.submitted = true;
this.closePrescriptionFormPopup();
const rInfo = {
id: this.productDetail.id,
drug_name: this.productDetail.drug_name,
image: this.productDetail.image,
price: this.productPrice,
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;
this.prescriptionFormData = {
hasVisited: '1',
hasUsedDrug: '1',
illnessInfo: '',
};
}
}
}
</script>
<style lang="scss" scoped>
.container {
background-color: #f5f8ff;
min-height: 100vh;
// 底部留白 = 固定操作栏高度 + 安全距离 + 额外间距
padding-bottom: calc(120rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
}
// 轮播图区域
.swiper-section {
position: relative;
height: 500rpx;
overflow: hidden;
.swiper {
width: 100%;
height: 100%;
}
.swiper-image {
width: 100%;
height: 100%;
}
}
// 基本信息区域
.basic-info {
background: #fff;
padding: 30rpx;
margin-bottom: 20rpx;
.price-section {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.current-price {
font-size: 48rpx;
font-weight: bold;
color: #ff4d4f;
margin-right: 20rpx;
}
.original-price {
font-size: 28rpx;
color: #999;
text-decoration: line-through;
margin-right: 20rpx;
}
.sales-tag {
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;
}
}
}
.product-name {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
line-height: 1.4;
}
.product-subtitle {
font-size: 28rpx;
color: #666;
margin-bottom: 20rpx;
}
.meta-info {
.meta-item {
display: flex;
align-items: center;
font-size: 26rpx;
color: #666;
background: #f9f9f9;
padding: 10rpx 20rpx;
border-radius: 8rpx;
display: inline-flex;
u-icon {
margin-right: 12rpx;
}
}
}
}
// 物流提示
.order-text-tip {
background: #e6f3ff;
padding: 20rpx 30rpx;
margin: 0 20rpx 20rpx 20rpx;
border-radius: 12rpx;
font-size: 26rpx;
color: #4175EE; // 统一为医疗蓝
line-height: 1.5;
border-left: 8rpx solid #4175EE;
}
// 详情区域
.detail-section {
background: #fff;
padding: 30rpx;
margin-bottom: 20rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 24rpx;
position: relative;
padding-left: 24rpx;
&::before {
content: "";
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 8rpx;
height: 32rpx;
background: #4175EE; // 统一颜色
border-radius: 4rpx;
}
}
.section-content {
font-size: 28rpx;
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; }
}
}
}
// 通用表单项间距
.form-item-wrapper {
margin-bottom: 30rpx;
}
// 弹窗通用样式
.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: #333; }
}
.product-info {
display: flex;
margin-bottom: 40rpx;
.product-image {
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: 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; }
}
}
.quantity-selector {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
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: 50rpx;
gap: 30rpx;
.cancel-btn {
flex: 1;
background-color: #f5f7fa;
color: #666;
border-radius: 50rpx;
font-size: 30rpx;
font-weight: 500;
border: none;
}
.confirm-btn {
flex: 1;
// 统一使用医疗蓝渐变
background: linear-gradient(135deg, #4A90E2, #4175EE);
color: #ffffff;
border-radius: 50rpx;
font-size: 30rpx;
font-weight: 500;
border: none;
box-shadow: 0 6rpx 16rpx rgba(65, 117, 238, 0.3);
}
}
}
// 底部操作栏 - 固定 + 适配
.footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
// 高度 = 内容高度(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-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: 0 0 auto;
margin-right: 30rpx;
.action-item {
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: 6rpx;
}
}
}
.footer-right {
display: flex;
align-items: center;
flex: 1;
gap: 20rpx;
button {
flex: 1;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
font-weight: 600;
border: none;
padding: 0;
&.add-cart-btn {
// 加入购物车:浅色风格,避免视觉争抢
background: #EBF3FF;
color: #4175EE;
border: 2rpx solid #EBF3FF;
}
&.buy-now-btn {
// 立即购买:强烈的品牌色
background: linear-gradient(135deg, #4A90E2, #4175EE);
color: white;
box-shadow: 0 6rpx 16rpx rgba(65, 117, 238, 0.3);
}
&:active {
transform: scale(0.98);
opacity: 0.9;
}
}
}
}
</style>