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

This commit is contained in:
2025-12-17 10:13:31 +08:00
parent 40fa6ba2e8
commit 420e699b4c
5 changed files with 251 additions and 24 deletions

View File

@@ -112,8 +112,89 @@
</view>
</view>
<!-- 药店模式药品列表容器 -->
<view v-if="storeType === '1'" class="product-list-container">
<!-- 药店模式分类热销商品展示 -->
<view v-if="storeType === '1'" class="top-products-container">
<!-- OTC热销 -->
<view v-if="topProducts.otc && topProducts.otc.length > 0" class="category-section">
<view class="category-title">OTC非处方药</view>
<view class="product-list-container">
<view class="product-card-simple" @click="goProductDetail(item)" v-for="(item,index) in topProducts.otc" :key="item.drug.id">
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img"></image>
<view class="product-info-simple">
<view class="product-main">
<view class="product-name-row">
<text class="product-name">{{item.drug.drug_name}}</text>
<text class="otc-tag otc-green">OTC</text>
</view>
<text class="product-spec">{{item.drug.specification}}</text>
</view>
<view class="product-bottom">
<view class="price-box">
<text class="currency">¥</text>
<text class="price">{{item.price || (item.drug.drugStoreDrug ? item.drug.drugStoreDrug.price : '0.00')}}</text>
</view>
<view class="buy-btn" @click.stop="buyProduct(item)">购买</view>
</view>
</view>
</view>
</view>
</view>
<!-- 处方药热销 -->
<view v-if="topProducts.prescription && topProducts.prescription.length > 0" class="category-section">
<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>
<view class="product-info-simple">
<view class="product-main">
<view class="product-name-row">
<text class="product-name">{{item.drug.drug_name}}</text>
<text class="otc-tag otc-red">Rx</text>
</view>
<text class="product-spec">{{item.drug.specification}}</text>
</view>
<view class="product-bottom">
<view class="price-box">
<text class="currency">¥</text>
<text class="price">{{item.price || (item.drug.drugStoreDrug ? item.drug.drugStoreDrug.price : '0.00')}}</text>
</view>
<view class="buy-btn" @click.stop="buyProduct(item)">购买</view>
</view>
</view>
</view>
</view>
</view>
<!-- 保健食品热销 -->
<view v-if="topProducts.health_food && topProducts.health_food.length > 0" class="category-section">
<view class="category-title">保健食品</view>
<view class="product-list-container">
<view class="product-card-simple" @click="goProductDetail(item)" v-for="(item,index) in topProducts.health_food" :key="item.drug.id">
<image :src="item.drug.image || '/static/mine/avatar_1.png'" mode="aspectFill" class="product-img"></image>
<view class="product-info-simple">
<view class="product-main">
<view class="product-name-row">
<text class="product-name">{{item.drug.drug_name}}</text>
<text class="otc-tag" style="color: #FF9800; border-color: #FF9800;">保健</text>
</view>
<text class="product-spec">{{item.drug.specification}}</text>
</view>
<view class="product-bottom">
<view class="price-box">
<text class="currency">¥</text>
<text class="price">{{item.price || (item.drug.drugStoreDrug ? item.drug.drugStoreDrug.price : '0.00')}}</text>
</view>
<view class="buy-btn" @click.stop="buyProduct(item)">购买</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 药店模式药品列表容器保留原有逻辑作为备用 -->
<view v-if="storeType === '1' && (!topProducts.otc || topProducts.otc.length === 0)" class="product-list-container">
<!-- 药品卡片优化后的单卡片UI布局 -->
<view class="product-card-simple" @click="goProductDetail(item)" v-for="(item,index) in productList" :key="item.drug.id">
<!-- 左侧药品封面图 -->
@@ -170,7 +251,7 @@ import {
storeInfo,
storeList
} from '../../request/api/api'
import { getStoreDrugListBySalespersonApi } from "@/request/api/product";
import { getStoreDrugListBySalespersonApi, getHomeTopProductsApi } from "@/request/api/product";
export default {
data() {
@@ -180,6 +261,11 @@ export default {
storeinfo: [],
doctorList: [],
productList: [], // 存储药品列表数据
topProducts: {
otc: [],
prescription: [],
health_food: []
}, // 首页热销商品
show: true,
showed: false,
shopList: {},
@@ -442,6 +528,16 @@ export default {
}
})
},
// 获取首页热销商品
getHomeTopProducts() {
getHomeTopProductsApi({
store_id: uni.getStorageSync('store_id') || '11001',
}).then((res) => {
if (res.data.code == 0) {
this.topProducts = res.data.result;
}
})
},
// 跳转药品详情
goProductDetail(item) {
uni.navigateTo({
@@ -473,6 +569,7 @@ export default {
this.getStore();
this.getList();
this.getProductList(); // 每次显示页面刷新商品列表
this.getHomeTopProducts(); // 获取首页热销商品
},
}
</script>
@@ -663,6 +760,24 @@ export default {
.consult-btn { background: #4175EE; color: white; border-radius: 40rpx; padding: 10rpx 24rpx; font-size: 26rpx; display: flex; align-items: center; .iconfont { font-size: 24rpx; margin-right: 6rpx; } }
}
// 4. 药店模式 - 分类热销商品容器
.top-products-container {
padding: 0 20rpx;
.category-section {
margin-bottom: 40rpx;
.category-title {
font-size: 32rpx;
font-weight: bold;
color: #232323;
margin-bottom: 20rpx;
padding-left: 20rpx;
border-left: 6rpx solid #4175EE;
}
}
}
// 4. 药店模式 - 药品列表容器
.product-list-container {
padding: 0 20rpx;

View File

@@ -23,4 +23,20 @@ export async function getStoreDrugDetailApi(params) {
*/
export async function getOrderTextApi(params) {
return await get('/product/order-text', params, 3)
}
/**
* 获取首页热销商品各分类Top 5
* @param params
* @returns {Promise<*>}
*/
export async function getHomeTopProductsApi(params) {
return await get('/product/home-top-products', params, 3)
}
/**
* 更新商品介绍图
* @param params
* @returns {Promise<*>}
*/
export async function updateIntroductionImagesApi(params) {
return await post('/product/update-introduction-images', params, 3)
}

View File

@@ -3,6 +3,17 @@
<!-- 顶部搜索栏保持优化后的结构但背景色微调融入原风格 -->
<view class="search-sticky">
<view class="search-section">
<!-- 类目筛选下拉 -->
<view class="category-filter">
<u-dropdown>
<u-dropdown-item
v-model="selectedCategory"
title="类目筛选"
:options="categoryOptions"
@change="onCategoryChange">
</u-dropdown-item>
</u-dropdown>
</view>
<!-- 搜索组件配置 -->
<u-search
v-model="searchKeyword"
@@ -25,9 +36,9 @@
<!-- 商品列表区域 -->
<view class="list-section">
<!-- 列表项卡片遍历渲染 filteredProducts 数据 -->
<!-- 列表项卡片遍历渲染 products 数据 -->
<view
v-for="(item, index) in filteredProducts"
v-for="(item, index) in products"
:key="item.id"
class="list-item"
@click="handClickProduct(item)"
@@ -81,8 +92,8 @@
</view>
</view>
<!-- 空状态过滤后没有商品时显示 -->
<view v-if="filteredProducts.length === 0" class="empty-state">
<!-- 空状态当没有商品时显示 -->
<view v-if="products.length === 0" class="empty-state">
<u-empty text="暂无相关药品" mode="search"></u-empty>
</view>
</view>
@@ -151,9 +162,15 @@ import { getCartCountsApi, saveCartApi } from "@/request/api/cart";
export default {
data() {
return {
products: [], // 所有商品原始数据
filteredProducts: [], // 搜索过滤后的商品数据
products: [], // 商品数据(从后端获取)
searchKeyword: "", // 搜索关键词
selectedCategory: 'all', // 选中的类目
categoryOptions: [ // 类目选项
{ label: '全部', value: 'all' },
{ label: 'OTC', value: 'otc' },
{ label: '处方药', value: 'prescription' },
{ label: '保健食品', value: 'health_food' }
],
scrollViewHeight: 0, // 滚动区域高度(预留)
doctorId: 0, // 医生ID参数
r_type: 0, // 注册类型参数
@@ -186,29 +203,46 @@ export default {
methods: {
// 获取商品列表
getList() {
getStoreDrugListBySalespersonApi({
const params = {
store_id: uni.getStorageSync('store_id') || '11001',
page: 1,
limit: 100
}).then((res) => {
};
// 添加类目筛选
if (this.selectedCategory !== 'all') {
params.category = this.selectedCategory;
}
// 添加搜索关键字
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;
this.filteredProducts = [...this.products]; // 初始化时显示所有商品
this.products = res.data.result.records || [];
this.cartCount = res.data.result.cart_count || 0;
}
})
},
// 处理搜索:支持名称和拼音搜索
// 处理搜索:调用后端API
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()))
);
// 防抖处理,避免频繁请求
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.getList();
}, 500);
},
// 清空搜索
clearSearch() {
this.searchKeyword = "";
this.filteredProducts = [...this.products];
this.getList();
},
// 类目改变
onCategoryChange(value) {
this.selectedCategory = value;
this.getList();
},
// 计算可视区域高度
calculateScrollViewHeight() {
@@ -315,6 +349,12 @@ export default {
this.initCartPosition();
this.updateCartCount();
},
onUnload() {
// 清理定时器
if (this.searchTimer) {
clearTimeout(this.searchTimer);
}
},
onReady() {
uni.onWindowResize(() => {
this.calculateScrollViewHeight();
@@ -345,6 +385,17 @@ export default {
background: rgba(255, 255, 255, 0.95);
padding: 16rpx 24rpx;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.02);
.search-section {
display: flex;
align-items: center;
gap: 16rpx;
.category-filter {
flex-shrink: 0;
width: 160rpx;
}
}
}
.list-section {

View File

@@ -50,8 +50,8 @@
<text>{{ orderText }}</text>
</view>
<!-- 功效与用法 -->
<view class="detail-section">
<!-- 功效与用法保健食品不显示 -->
<view class="detail-section" v-if="productDetail.category_type !== 'health_food'">
<view class="section-title">
<text>功效主治</text>
</view>
@@ -89,6 +89,23 @@
</view>
</view>
<!-- 商品介绍图 -->
<view class="detail-section" v-if="introductionImages.length > 0">
<view class="section-title">
<text>商品介绍</text>
</view>
<view class="introduction-images">
<image
v-for="(img, idx) in introductionImages"
:key="idx"
class="introduction-image"
:src="img"
mode="widthFix"
@click="previewIntroductionImage(idx)"
/>
</view>
</view>
<!-- 购物车弹窗 -->
<u-popup
v-model="showCartPopup"
@@ -370,6 +387,7 @@ export default {
illnessOptions: [],
showIllnessPicker: false,
orderText: '本次商品物流配送,由萧康医药提供服务。',
introductionImages: [], // 商品介绍图数组
};
},
computed: {
@@ -435,6 +453,12 @@ export default {
if (!this.productDetail.indications && data.function) {
this.productDetail.indications = data.function;
}
// 设置商品介绍图
if (data.introduction_images && Array.isArray(data.introduction_images)) {
this.introductionImages = data.introduction_images;
} else {
this.introductionImages = [];
}
}
}).catch(error => {
console.error('加载商品详情失败:', error);
@@ -455,6 +479,15 @@ export default {
});
}
},
// 预览商品介绍图
previewIntroductionImage(index) {
if (this.introductionImages.length > 0) {
uni.previewImage({
current: index,
urls: this.introductionImages
});
}
},
updateCartCount() {
getCartCountsApi({
store_id: uni.getStorageSync('store_id') || '11001',
@@ -726,6 +759,18 @@ export default {
text { font-size: 28rpx; color: #999; }
}
}
.introduction-images {
display: flex;
flex-direction: column;
gap: 20rpx;
.introduction-image {
width: 100%;
border-radius: 12rpx;
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.05);
}
}
}
// 通用表单项间距

View File

@@ -6,8 +6,8 @@ export function checkDev(key = '') {
// 判断某些模块是否开启
switch (key) {
case 'dev':
return false;
// return true;
// return false;
return true;
case 'open-im':
return false;
default: