<template>
|
|
<!-- 商品款式选择弹窗 -->
|
|
<view v-if="showStylePopup" class="style-popup-mask">
|
|
<view class="style-popup">
|
|
<view class="style-popup-header">
|
|
<text class="style-popup-close" @click="close">关闭</text>
|
|
<text class="style-popup-title">选择回收款式</text>
|
|
</view>
|
|
<view class="style-popup-brand-info">
|
|
<view class="brand-info-center">
|
|
<image :src="brandInfo.logo" class="brand-logo" mode="aspectFit" />
|
|
<text class="brand-name">{{ brandInfo.name }}</text>
|
|
<button class="brand-switch-btn" @click="switchBrand">
|
|
切换
|
|
</button>
|
|
</view>
|
|
</view>
|
|
<scroll-view class="style-popup-list" scroll-y>
|
|
<view class="style-grid">
|
|
<view v-for="(item, index) in styleList" :key="item.id" class="style-item" @click="selectStyle(item, index)">
|
|
<view class="style-item-content">
|
|
<view class="image-container">
|
|
<image :src="item.image" class="style-image" mode="aspectFit" />
|
|
<view class="style-quantity">
|
|
<button class="btn-minus" @click.stop="updateQuantity(index, -1)">-</button>
|
|
<text class="quantity">{{ item.quantity || 0 }}</text>
|
|
<button class="btn-plus" @click.stop="updateQuantity(index, 1)">+</button>
|
|
</view>
|
|
</view>
|
|
<text class="style-name">{{ item.name }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
<view class="style-popup-footer">
|
|
<button class="next-btn" @click="nextStep" :disabled="!hasSelectedItems">下一步</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
name: 'ProductStyleSelector',
|
|
data() {
|
|
return {
|
|
showStylePopup: false,
|
|
brandInfo: {
|
|
id: '',
|
|
name: '',
|
|
logo: ''
|
|
},
|
|
styleList: [],
|
|
currentProductId: null,
|
|
existingQuantities: {}
|
|
}
|
|
},
|
|
computed: {
|
|
hasSelectedItems() {
|
|
return this.styleList.some(item => (item.quantity || 0) > 0)
|
|
}
|
|
},
|
|
methods: {
|
|
// 打开款式选择弹窗
|
|
open(brandInfo, productId, existingQuantities = {}) {
|
|
if (!brandInfo || !productId) {
|
|
console.error('brandInfo and productId are required')
|
|
return
|
|
}
|
|
this.brandInfo = brandInfo
|
|
this.currentProductId = productId
|
|
this.existingQuantities = existingQuantities
|
|
this.getProductStyles(brandInfo.id, productId)
|
|
this.showStylePopup = true
|
|
},
|
|
|
|
// 关闭弹窗
|
|
close() {
|
|
this.showStylePopup = false
|
|
this.styleList = []
|
|
this.brandInfo = { id: '', name: '', logo: '' }
|
|
this.currentProductId = null
|
|
this.existingQuantities = {}
|
|
this.$emit('close')
|
|
},
|
|
|
|
// 选择款式
|
|
selectStyle(item, index) {
|
|
// 点击款式项时的处理逻辑
|
|
console.log('Selected style:', item)
|
|
},
|
|
|
|
// 更新数量
|
|
updateQuantity(index, delta) {
|
|
const item = this.styleList[index]
|
|
if (!item) return
|
|
|
|
let newQuantity = (item.quantity || 0) + delta
|
|
if (newQuantity < 0) newQuantity = 0
|
|
|
|
this.$set(item, 'quantity', newQuantity)
|
|
},
|
|
|
|
// 获取商品款式列表
|
|
getProductStyles(brandId, productId) {
|
|
const params = {
|
|
brandId: brandId,
|
|
productId: productId
|
|
}
|
|
|
|
this.$api('getGoodsBrandProduct', params, res => {
|
|
if (res && res.success && res.result && res.result) {
|
|
this.styleList = res.result.map(item => {
|
|
const uniqueKey = `${brandId}_${item.id}`
|
|
const existingQty = this.existingQuantities[uniqueKey] || 0
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
image: item.image || '/static/default-product.png',
|
|
minPrice: item.minPrice,
|
|
maxPrice: item.maxPrice,
|
|
brandId: item.brandId,
|
|
shopId: item.shopId,
|
|
quantity: existingQty,
|
|
...item
|
|
}
|
|
})
|
|
} else {
|
|
this.styleList = []
|
|
}
|
|
})
|
|
},
|
|
|
|
// 切换品牌
|
|
switchBrand() {
|
|
this.close()
|
|
},
|
|
|
|
// 下一步
|
|
nextStep() {
|
|
const selectedItems = this.styleList.filter(item => (item.quantity || 0) > 0)
|
|
|
|
if (selectedItems.length === 0) {
|
|
uni.showToast({
|
|
title: '请选择至少一个款式',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
|
|
this.$emit('style-confirm', {
|
|
brandInfo: this.brandInfo,
|
|
selectedStyles: selectedItems
|
|
})
|
|
this.close()
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.style-popup-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
background: rgba(0,0,0,0.35);
|
|
z-index: 3000;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
justify-content: center;
|
|
}
|
|
|
|
.style-popup {
|
|
position: relative;
|
|
width: 100%;
|
|
max-width: 750px;
|
|
background: #fff;
|
|
border-radius: 32rpx 32rpx 0 0;
|
|
box-shadow: 0 -4rpx 24rpx rgba(0,0,0,0.08);
|
|
height: 94vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.style-popup-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 32rpx 24rpx 0 24rpx;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
position: relative;
|
|
}
|
|
|
|
.style-popup-close {
|
|
position: absolute;
|
|
left: 24rpx;
|
|
font-size: 28rpx;
|
|
color: #888;
|
|
}
|
|
|
|
.style-popup-title {
|
|
font-size: 32rpx;
|
|
color: #222;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.style-popup-brand-info {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
padding: 20rpx 24rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.brand-info-center {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12rpx;
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 60rpx;
|
|
height: 60rpx;
|
|
border-radius: 8rpx;
|
|
background: #f8f8f8;
|
|
}
|
|
|
|
.brand-name {
|
|
font-size: 28rpx;
|
|
color: #222;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.brand-switch-btn {
|
|
padding: 4rpx 8rpx;
|
|
background: #eee;
|
|
color: #777;
|
|
font-size: 24rpx;
|
|
border-radius: 40rpx;
|
|
border: none;
|
|
margin: 0;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.style-popup-list {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 0 24rpx;
|
|
box-sizing: border-box;
|
|
scrollbar-width: none;
|
|
-ms-overflow-style: none;
|
|
&::-webkit-scrollbar {
|
|
width: 0 !important;
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
.style-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 20rpx;
|
|
padding: 20rpx 0;
|
|
}
|
|
|
|
.style-item {
|
|
width: calc((100% - 40rpx) / 3);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
border-radius: 16rpx;
|
|
background: #fff;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.style-item-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
width: 100%;
|
|
}
|
|
|
|
.image-container {
|
|
position: relative;
|
|
width: 100%;
|
|
height: 200rpx;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
|
|
.style-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 12rpx;
|
|
background: #f8f8f8;
|
|
}
|
|
|
|
.style-name {
|
|
font-size: 24rpx;
|
|
color: #222;
|
|
font-weight: 500;
|
|
text-align: center;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
width: 100%;
|
|
}
|
|
|
|
.style-quantity {
|
|
position: absolute;
|
|
bottom: 8rpx;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(255, 255, 255, 0.9);
|
|
border-radius: 24rpx;
|
|
padding: 4rpx 8rpx;
|
|
}
|
|
|
|
.btn-minus, .btn-plus {
|
|
width: 40rpx;
|
|
height: 40rpx;
|
|
border-radius: 50%;
|
|
background: #fff;
|
|
border: 1px solid #ddd;
|
|
color: #333;
|
|
font-size: 20rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0;
|
|
padding: 0;
|
|
box-shadow: 0 2rpx 4rpx rgba(0,0,0,0.1);
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:active {
|
|
background: #f0f0f0;
|
|
}
|
|
}
|
|
|
|
.quantity {
|
|
width: 32rpx;
|
|
text-align: center;
|
|
font-size: 20rpx;
|
|
color: #333;
|
|
margin: 0 8rpx;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.style-popup-footer {
|
|
padding: 20rpx 24rpx;
|
|
border-top: 1px solid #f0f0f0;
|
|
background: #fff;
|
|
}
|
|
|
|
.next-btn {
|
|
width: 100%;
|
|
height: 88rpx;
|
|
background: linear-gradient(to right, #ffd01e, #ff8917);
|
|
border-radius: 44rpx;
|
|
color: #fff;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
border: none;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&:disabled {
|
|
background: #ccc;
|
|
color: #999;
|
|
}
|
|
|
|
&:active:not(:disabled) {
|
|
opacity: 0.9;
|
|
}
|
|
}
|
|
</style>
|