fix: 商品详情UI优化、提示增强

This commit is contained in:
2025-12-18 15:12:26 +08:00
parent 4ce856562f
commit cf0e974fa1
9 changed files with 503 additions and 9 deletions

View File

@@ -74,6 +74,12 @@
}
// "needLogin": true
},
{
"path": "pages/index/platform-info",
"style": {
"navigationBarTitleText": "平台信息"
}
},
{
"path": "pages/index/order-info",
"style": {

View File

@@ -39,7 +39,7 @@
<view class="list" v-for="(item,index) in drugLists" @click="toDetail(item.id)">
<text class="cf">{{item.is_otc=='0'?'处方药':'非处方药'}}</text>
<view class="img">
<image :src="item.image" mode=""></image>
<image :src="item.image" mode="" :class="{ 'prescription-blur': item.is_otc === '0' || item.is_otc === 0 }"></image>
</view>
<view class="it">
<view class="it_name">{{item.drug_name}}</view>
@@ -475,6 +475,12 @@
width: 100%;
height: 100%;
border-radius: 8rpx;
// 处方药图片模糊处理
&.prescription-blur {
filter: blur(10px);
-webkit-filter: blur(10px);
}
}
}

View File

@@ -145,7 +145,7 @@
<view class="category-title">处方药</view>
<view class="product-list-container">
<view class="product-card-simple" @click="goProductDetail(item)" v-for="(item,index) in topProducts.prescription" :key="item.drug.id">
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img"></image>
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img prescription-blur"></image>
<view class="product-info-simple">
<view class="product-main">
<view class="product-name-row">
@@ -198,7 +198,7 @@
<!-- 药品卡片优化后的单卡片UI布局 -->
<view class="product-card-simple" @click="goProductDetail(item)" v-for="(item,index) in productList" :key="item.drug.id">
<!-- 左侧药品封面图 -->
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img"></image>
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img" :class="{ 'prescription-blur': item.drug.is_otc === 0 || item.drug.is_otc === '0' }"></image>
<!-- 右侧药品详情信息 -->
<view class="product-info-simple">
@@ -233,6 +233,20 @@
</view>
</view>
<!-- 首页资质公示区域 -->
<view v-if="storeType === '1'" class="qualifications-section">
<view class="qualifications-title">
平台资质
<text class="more-link" @click.stop="goPlatformInfo">更多 ></text>
</view>
<view class="qualifications-grid">
<view class="qualification-item" v-for="(item, index) in qualifications" :key="index" @click="previewQualification(item)">
<image :src="item.image" mode="aspectFit" class="qualification-img"></image>
<text class="qualification-name">{{ item.name }}</text>
</view>
</view>
</view>
<!-- 全局遮罩层 -->
<view class="bg-" v-if="bgShow" @click="bgShow=false">
<image src="/static/home/bg.png" mode=""></image>
@@ -251,6 +265,7 @@ import {
storeInfo,
storeList
} from '../../request/api/api'
import { getPlatformQualificationsApi } from '../../request/api/platform'
import { getStoreDrugListBySalespersonApi, getHomeTopProductsApi } from "@/request/api/product";
export default {
@@ -266,6 +281,7 @@ export default {
prescription: [],
health_food: []
}, // 首页热销商品
qualifications: [], // 资质证明列表
show: true,
showed: false,
shopList: {},
@@ -538,6 +554,25 @@ export default {
}
})
},
// 获取平台资质证明
getPlatformQualifications() {
getPlatformQualificationsApi({
store_id: uni.getStorageSync('store_id') || '11001',
}).then((res) => {
if (res.data.code == 0 || res.data.errcode == 0) {
this.qualifications = res.data.data || res.data.result || [];
}
}).catch(() => {
// 如果接口不存在,使用默认数据
this.qualifications = [
{ name: '药品经营许可证', image: '', type: 1 },
{ name: '营业执照', image: '', type: 2 },
{ name: '医疗器械经营许可证', image: '', type: 3 },
{ name: '食品经营许可证', image: '', type: 4 },
{ name: '药师资格证', image: '', type: 5 }
];
})
},
// 跳转药品详情
goProductDetail(item) {
uni.navigateTo({
@@ -549,6 +584,21 @@ export default {
uni.navigateTo({
url: `/subPackages/product/product?doctor_id=39&register_type=3`
});
},
// 预览资质证明
previewQualification(item) {
if (item.image) {
uni.previewImage({
urls: [item.image],
current: item.image
});
}
},
// 跳转平台信息页面
goPlatformInfo() {
uni.navigateTo({
url: '/pages/index/platform-info'
});
}
},
mounted() {
@@ -570,6 +620,7 @@ export default {
this.getList();
this.getProductList(); // 每次显示页面刷新商品列表
this.getHomeTopProducts(); // 获取首页热销商品
this.getPlatformQualifications(); // 获取平台资质证明
},
}
</script>
@@ -801,6 +852,12 @@ export default {
border-radius: 12rpx;
margin-right: 24rpx;
background: #f8f8f8;
// 处方药图片模糊处理
&.prescription-blur {
filter: blur(10px);
-webkit-filter: blur(10px);
}
}
// 右侧信息区域布局
@@ -886,5 +943,59 @@ export default {
}
}
}
// 资质公示区域
.qualifications-section {
padding: 40rpx 20rpx;
margin-top: 40rpx;
background: #fff;
.qualifications-title {
font-size: 32rpx;
font-weight: bold;
color: #232323;
margin-bottom: 24rpx;
padding: 0 20rpx;
display: flex;
justify-content: space-between;
align-items: center;
.more-link {
font-size: 24rpx;
color: #4175EE;
font-weight: normal;
}
}
.qualifications-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20rpx;
padding: 0 20rpx;
.qualification-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx;
background: #F7F8FA;
border-radius: 12rpx;
.qualification-img {
width: 120rpx;
height: 120rpx;
margin-bottom: 12rpx;
border-radius: 8rpx;
}
.qualification-name {
font-size: 24rpx;
color: #666;
text-align: center;
line-height: 1.4;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,250 @@
<template>
<view class="content safe-area-inset-bottom">
<!-- 平台资质证明 -->
<view class="section">
<view class="section-title">平台资质证明</view>
<view class="qualifications-list">
<view class="qualification-item" v-for="(item, index) in qualifications" :key="index" @click="previewImage(item.image)">
<view class="qualification-content">
<text class="qualification-name">{{ item.name }}</text>
<image :src="item.image || '/static/mine/avatar_1.png'" mode="aspectFit" class="qualification-img"></image>
</view>
</view>
</view>
</view>
<!-- 联系方式 - 暂时隐藏 -->
<!-- <view class="section" v-if="contactInfo">
<view class="section-title">联系方式</view>
<view class="info-card">
<view class="info-item" v-if="contactInfo.phone">
<text class="label">客服电话</text>
<text class="value" @click="makeCall(contactInfo.phone)">{{ contactInfo.phone }}</text>
</view>
<view class="info-item" v-if="contactInfo.email">
<text class="label">邮箱</text>
<text class="value">{{ contactInfo.email }}</text>
</view>
<view class="info-item" v-if="contactInfo.address">
<text class="label">地址</text>
<text class="value">{{ contactInfo.address }}</text>
</view>
</view>
</view> -->
<!-- 投诉举报方式 - 暂时隐藏 -->
<!-- <view class="section" v-if="complaintInfo">
<view class="section-title">投诉举报方式</view>
<view class="info-card">
<view class="info-item" v-if="complaintInfo.phone">
<text class="label">投诉电话</text>
<text class="value" @click="makeCall(complaintInfo.phone)">{{ complaintInfo.phone }}</text>
</view>
<view class="info-item" v-if="complaintInfo.email">
<text class="label">投诉邮箱</text>
<text class="value">{{ complaintInfo.email }}</text>
</view>
<view class="info-item" v-if="complaintInfo.address">
<text class="label">投诉地址</text>
<text class="value">{{ complaintInfo.address }}</text>
</view>
</view>
</view> -->
</view>
</template>
<script>
import { getPlatformQualificationsApi, getPlatformInfoApi } from '../../request/api/platform'
export default {
data() {
return {
qualifications: [],
contactInfo: {
phone: '',
email: '',
address: ''
},
complaintInfo: {
phone: '',
email: '',
address: ''
}
}
},
onLoad() {
this.getQualifications();
this.getPlatformInfoData();
},
methods: {
// 获取平台资质证明
getQualifications() {
getPlatformQualificationsApi({
store_id: uni.getStorageSync('store_id') || '11001',
}).then((res) => {
if (res.data.code == 0 || res.data.errcode == 0) {
this.qualifications = res.data.data || res.data.result || [];
}
}).catch(() => {
// 如果接口不存在,使用默认数据
this.qualifications = [
{ name: '药品经营许可证', image: '', type: 1 },
{ name: '营业执照', image: '', type: 2 },
{ name: '医疗器械经营许可证', image: '', type: 3 },
{ name: '食品经营许可证', image: '', type: 4 },
{ name: '药师资格证', image: '', type: 5 }
];
})
},
// 获取平台信息
getPlatformInfoData() {
getPlatformInfoApi({
store_id: uni.getStorageSync('store_id') || '11001',
}).then((res) => {
if (res.data.code == 0 || res.data.errcode == 0) {
const data = res.data.data || res.data.result || {};
if (data.contact) {
this.contactInfo = data.contact;
}
if (data.complaint) {
this.complaintInfo = data.complaint;
}
}
}).catch(() => {
// 接口不存在时使用空数据
})
},
// 预览资质图片
previewImage(image) {
if (image) {
uni.previewImage({
urls: [image],
current: image
});
}
},
// 拨打电话
makeCall(phone) {
if (phone) {
uni.makePhoneCall({
phoneNumber: phone,
fail: (err) => {
console.error('拨打电话失败:', err);
}
});
}
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 750rpx;
min-height: 100vh;
padding-bottom: env(safe-area-inset-bottom);
background: #F5F5F5;
padding: 20rpx;
.section {
background: #fff;
border-radius: 24rpx;
padding: 40rpx 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
.section-title {
font-size: 40rpx;
font-weight: bold;
color: #232323;
margin-bottom: 32rpx;
padding-bottom: 24rpx;
border-bottom: 2rpx solid #F0F0F0;
position: relative;
&::after {
content: '';
position: absolute;
left: 0;
bottom: -2rpx;
width: 80rpx;
height: 2rpx;
background: linear-gradient(90deg, #4175EE 0%, #6B9EFF 100%);
border-radius: 2rpx;
}
}
.qualifications-list {
display: flex;
flex-direction: column;
gap: 24rpx;
.qualification-item {
background: #fff;
border-radius: 20rpx;
overflow: hidden;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
}
.qualification-content {
display: flex;
flex-direction: column;
padding: 32rpx;
}
.qualification-name {
font-size: 36rpx;
font-weight: bold;
color: #232323;
margin-bottom: 24rpx;
line-height: 1.5;
letter-spacing: 1rpx;
}
.qualification-img {
width: 100%;
height: 500rpx;
border-radius: 16rpx;
background: #F7F8FA;
}
}
}
.info-card {
.info-item {
display: flex;
align-items: flex-start;
padding: 20rpx 0;
border-bottom: 1rpx solid #F0F0F0;
&:last-child {
border-bottom: none;
}
.label {
font-size: 28rpx;
color: #666;
width: 160rpx;
flex-shrink: 0;
}
.value {
font-size: 28rpx;
color: #232323;
flex: 1;
word-break: break-all;
&:active {
opacity: 0.7;
}
}
}
}
}
}
</style>

View File

@@ -446,6 +446,7 @@ export async function getOrdDetail(params) {
}
// 申请退款原因 https://app.xiaokang88.com/member/v1/product-order/refund-reason
export async function getRefundReson(params) {
let data = await http('/oldApi/v1/product-order/refund-reason', params)
@@ -492,3 +493,4 @@ export async function getVersion(params) {
return data
}

19
request/api/platform.js Normal file
View File

@@ -0,0 +1,19 @@
import {get} from './http'
/**
* 获取平台资质证明列表
* @param params
* @returns {Promise<*>}
*/
export async function getPlatformQualificationsApi(params) {
return await get('/platform/qualifications', params, 3)
}
/**
* 获取平台信息(联系方式、投诉举报方式等)
* @param params
* @returns {Promise<*>}
*/
export async function getPlatformInfoApi(params) {
return await get('/platform/info', params, 3)
}

View File

@@ -78,6 +78,10 @@
<view class="it_info">
{{item.drug.usage}}
</view>
<!-- 添加查看说明书按钮 -->
<view class="instruction-btn" v-if="prescriptionStatus && item.drug && item.drug.instruction" @click="previewInstruction(item.drug.instruction)">
<text>查看说明书</text>
</view>
<view class="it_price">
<text>{{item.price}}</text>
<view class="it_num">
@@ -172,6 +176,8 @@ import {
// 导入 getOrderTextApi 接口方法
import { getOrderTextApi } from '../../../request/api/product'
// 导入订单相关接口
import { getPrescriptionStatusApi } from '../../../request/api/order'
export default {
data() {
@@ -235,6 +241,8 @@ export default {
fontWeight: '540',
fontSize: '33rpx'
},
// 处方状态
prescriptionStatus: null,
}
},
onLoad(e) {
@@ -375,6 +383,9 @@ export default {
this.isshowed = false
this.isshow = true
}
// 查询处方状态
this.getPrescriptionStatus()
}
})
},
@@ -521,6 +532,34 @@ export default {
})
}
},
// 查询处方状态
getPrescriptionStatus() {
if (!this.order_id) {
return;
}
getPrescriptionStatusApi({
order_id: this.order_id
}).then((res) => {
if (res.data && (res.data.code == 0 || res.data.errcode == 0)) {
const data = res.data.data || res.data.result || {};
// 假设 status = 2 表示审核通过
this.prescriptionStatus = data.status === true || data.status === 2 || data.status == 2;
} else {
this.prescriptionStatus = false;
}
}).catch(() => {
this.prescriptionStatus = false;
});
},
// 预览说明书
previewInstruction(instructionImage) {
if (instructionImage) {
uni.previewImage({
urls: [instructionImage],
current: instructionImage
});
}
}
},
mounted() {
@@ -538,6 +577,8 @@ export default {
onShow() {
this.getInfo()
this.getList()
// 查询处方状态
this.getPrescriptionStatus()
},
onUnload() {
uni.removeStorageSync('userWay_order_id')
@@ -791,6 +832,26 @@ export default {
margin-bottom: 20rpx;
}
.instruction-btn {
margin-top: 16rpx;
margin-bottom: 16rpx;
padding: 12rpx 24rpx;
background: #ECF5FF;
border-radius: 8rpx;
display: inline-flex;
align-items: center;
justify-content: center;
text {
font-size: 26rpx;
color: #2B85E4;
}
&:active {
opacity: 0.7;
}
}
.it_price {
display: flex;
align-items: center;

View File

@@ -68,6 +68,7 @@
<view class="image-wrapper">
<image
class="item-image"
:class="{ 'prescription-blur': item.drug.is_otc === 0 || item.drug.is_otc === '0' }"
:src="item.drug.image || '/static/mine/avatar_1.png'"
mode="aspectFill"
lazy-load
@@ -494,6 +495,12 @@ export default {
height: 200rpx;
border-radius: 12rpx;
background-color: #f8f8f8;
// 处方药图片模糊处理
&.prescription-blur {
filter: blur(10px);
-webkit-filter: blur(10px);
}
}
}

View File

@@ -41,6 +41,12 @@
</view>
</view>
<!-- 合规提示 - 移动到商品名称上方 -->
<view class="compliance-tip-card" v-if="complianceTip">
<u-icon name="info-circle" color="#FF4D4F" size="32" style="margin-right: 12rpx;"></u-icon>
<text class="tip-text">{{ complianceTip }}</text>
</view>
<view class="title">{{ productDetail.drug_name }}</view>
<view class="sub-title" v-if="productDetail.drug_alias">{{ productDetail.drug_alias }}</view>
@@ -63,6 +69,7 @@
<text>{{ orderText }}</text>
</view>
<!-- 4. 功效与用法 (卡片式布局 + 优化标题) -->
<view class="info-card" v-if="productDetail.category_type !== 'health_food'">
<!-- 优化点医疗风格标题 -->
@@ -75,7 +82,8 @@
</view>
</view>
<view class="info-card">
<!-- 保健食品不展示用法用量 -->
<view class="info-card" v-if="productDetail.type != 3">
<view class="section-title-modern">
<view class="indicator"></view>
<text>用法用量</text>
@@ -85,8 +93,8 @@
</view>
</view>
<!-- 说明书入口 -->
<view class="info-card">
<!-- 说明书入口 - 处方药不展示 -->
<view class="info-card" v-if="!(productDetail.is_otc == 0 && productDetail.type == 2)">
<view class="section-title-modern">
<view class="indicator"></view>
<text>说明书</text>
@@ -119,7 +127,6 @@
:src="img"
mode="widthFix"
lazy-load
@click="previewIntroductionImage(idx)"
/>
</view>
</view>
@@ -315,7 +322,8 @@ export default {
guozi_no: '',
bar_code: '',
indications: '',
indications_array: []
indications_array: [],
compliance_tip: '' // 合规提示文案,由后端返回
},
formData: {
id: '',
@@ -356,6 +364,10 @@ export default {
return parseFloat(this.productDetail.drug_store_drug.price);
}
return parseFloat(this.productDetail.price || 0);
},
// 合规提示文案 - 从后端返回的 compliance_tip 字段获取
complianceTip() {
return this.productDetail.compliance_tip || '';
}
},
onLoad(options) {
@@ -690,6 +702,23 @@ export default {
}
}
/* 合规提示卡片 - 与物流提示UI一致 */
.compliance-tip-card {
background: #FFF1F0;
padding: 24rpx 30rpx;
margin: 0 -30rpx 20rpx -30rpx;
display: flex;
align-items: center;
font-size: 26rpx;
color: #FF4D4F;
.tip-text {
font-weight: 600;
line-height: 1.6;
flex: 1;
}
}
/* 5. 详情图区域 */
.detail-images-wrapper {
background: #fff;
@@ -723,7 +752,10 @@ export default {
}
/* 6. 底部操作栏 */
.footer-placeholder { height: 120rpx; }
.footer-placeholder {
height: calc(110rpx + env(safe-area-inset-bottom));
min-height: 140rpx; /* 确保最小高度,避免在小屏设备上被遮挡 */
}
.footer-bar {
position: fixed;