|
@@ -3,7 +3,7 @@
|
|
|
<cu-modalC :show.sync="value" custom="2">
|
|
|
<view style="height: 80vh;padding: 20upx;">
|
|
|
<!-- 详情 -->
|
|
|
- <view class="cu-header padding-bottom">
|
|
|
+ <view style="min-height: 240upx;" class="cu-header padding-bottom">
|
|
|
<!-- 图片 -->
|
|
|
<view @click="previewImage(goods.index)" v-if="goods.main" class="shop-img" :style="{ backgroundImage: 'url(' + goods.main + ')' }"></view>
|
|
|
<!-- 商品数据 -->
|
|
@@ -11,7 +11,7 @@
|
|
|
<!-- 价格 -->
|
|
|
<view class="price text-price text-red"><cu-price :value="goods.price" size="64" /></view>
|
|
|
<!-- 剩余 -->
|
|
|
- <view v-if="!goods.hide_stock" class="surplus text-gray margin-tb-xs">剩余{{ goods.stock_num }}件</view>
|
|
|
+ <view v-if="goods.hide_stock" class="surplus text-gray margin-tb-xs">剩余{{ goods.stock_num }}件</view>
|
|
|
<!-- 参数 -->
|
|
|
<view v-if="parameter.tip" class="parameter text-gray">{{ parameter.tip }}</view>
|
|
|
</view>
|
|
@@ -19,7 +19,7 @@
|
|
|
<!-- 参数 80vh-40upx-30upx-200upx-30upx-80upx -->
|
|
|
<scroll-view style="height:calc(80vh - 380upx)" scroll-y="true" class="cu-section">
|
|
|
<!-- 商品参数 -->
|
|
|
- <view v-for="(item, index) in options.tree" :key="index" class="parameter-item padding-tb">
|
|
|
+ <view v-for="(item, index) in options.tree" :key="index" class="parameter-item padding-tb border">
|
|
|
<view class="parameter-label text-xl">{{ item.k }}</view>
|
|
|
<view class="parameter-content flex flex-wrap align-center">
|
|
|
<!-- 放大版 -->
|
|
@@ -29,7 +29,11 @@
|
|
|
v-for="(v, vi) in item.v"
|
|
|
:key="vi"
|
|
|
class="parameter-content-item-one text-center margin-top-sm margin-right padding-sm light radius"
|
|
|
- :class="{'bg-grey':!collection_keys[item.k_s],'bg-red':v.id==collection_keys[item.k_s],}"
|
|
|
+ :class="{
|
|
|
+ 'bg-blue': collection_tree[item.k_s][v.id] && v.id != collection_keys[item.k_s],
|
|
|
+ 'bg-red': collection_tree[item.k_s][v.id] && v.id == collection_keys[item.k_s],
|
|
|
+ 'bg-gray': !collection_tree[item.k_s][v.id]
|
|
|
+ }"
|
|
|
>
|
|
|
<view class="parameter-content-item-img-one" v-if="item.largeImageMode" :style="{ backgroundImage: 'url(' + v.imgUrl + ')' }"></view>
|
|
|
<view class="margin-sm">{{ v.name }}</view>
|
|
@@ -38,11 +42,16 @@
|
|
|
</scroll-view>
|
|
|
<!-- 缩小版 -->
|
|
|
<view
|
|
|
- @click="handler(item, v)"
|
|
|
+ @click="handler(item, v)"
|
|
|
v-else
|
|
|
v-for="(v, vi) in item.v"
|
|
|
:key="vi"
|
|
|
- class="parameter-content-item flex align-center margin-tb-sm margin-right padding-sm bg-grey light radius"
|
|
|
+ class="parameter-content-item flex align-center margin-tb-sm margin-right padding-sm light radius"
|
|
|
+ :class="{
|
|
|
+ 'bg-blue': collection_tree[item.k_s][v.id] && v.id != collection_keys[item.k_s],
|
|
|
+ 'bg-red': collection_tree[item.k_s][v.id] && v.id == collection_keys[item.k_s],
|
|
|
+ 'bg-gray': !collection_tree[item.k_s][v.id]
|
|
|
+ }"
|
|
|
>
|
|
|
<view
|
|
|
class="parameter-content-item-img-two margin-right-sm"
|
|
@@ -53,15 +62,22 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <!-- 计步器 -->
|
|
|
+ <view class="flex justify-between align-center padding-tb border">
|
|
|
+ <view class="text-xl">购买数量</view>
|
|
|
+ <cu-stepper @change="val=>num=val" :value="num" min="1" :max="goods.stock_num"/>
|
|
|
+ </view>
|
|
|
<!-- 添加操作 -->
|
|
|
<view style="position: relative;"><slot /></view>
|
|
|
</scroll-view>
|
|
|
<!-- 按钮 -->
|
|
|
<view class="cu-footer padding-top flex">
|
|
|
- <view @click="$emit('addcart')" style="flex: 1;background:linear-gradient(to right, #ffd01e, #ff8917) ;" class="btns-left text-center text-white">
|
|
|
+ <view @click="addcart" style="flex: 1;background:linear-gradient(to right, #ffd01e, #ff8917) ;" class=" btns-left text-center text-white">
|
|
|
+ <text v-if="addcartLock" class="cuIcon-loading2 cuIconfont-spin "></text>
|
|
|
加入购物车
|
|
|
</view>
|
|
|
- <view @click="$emit('buyclicked')" style="flex: 1;background: linear-gradient(to right, #ff6034, #ee0a24);" class="btns-right text-center text-white">
|
|
|
+ <view @click="buyclicked" style="flex: 1;background: linear-gradient(to right, #ff6034, #ee0a24);" class="btns-right text-center text-white">
|
|
|
+ <text v-if="buyclickedLock" class="cuIcon-loading2 cuIconfont-spin "></text>
|
|
|
立即购买
|
|
|
</view>
|
|
|
</view>
|
|
@@ -73,10 +89,12 @@
|
|
|
<script>
|
|
|
import cuModalC from './cu-modalC.vue';
|
|
|
import cuPrice from './cu-price.vue';
|
|
|
+import cuStepper from "./cu-stepper.vue";
|
|
|
export default {
|
|
|
components: {
|
|
|
cuPrice,
|
|
|
- cuModalC
|
|
|
+ cuModalC,
|
|
|
+ cuStepper
|
|
|
},
|
|
|
props: {
|
|
|
show: { type: Boolean, default: true },
|
|
@@ -91,7 +109,6 @@ export default {
|
|
|
goods() {
|
|
|
var options = this.options,
|
|
|
_options = {};
|
|
|
- console.log(options);
|
|
|
// 默认使用的商品id this.collection_id > options.collection_id > options.list[0].id
|
|
|
var collection_id = this.collection_id
|
|
|
? this.collection_id
|
|
@@ -104,20 +121,30 @@ export default {
|
|
|
if (collection_id && options.list && options.list.length > 0 && options.tree && options.tree.length > 0) {
|
|
|
// 查找默认id库存位置
|
|
|
let listItem = options.list.find(item => item.id == collection_id);
|
|
|
- if (!listItem) return _options;
|
|
|
- let { id, price = 0, stock_num = 0, ...arg } = listItem;
|
|
|
- _options = { price, stock_num };
|
|
|
- // 查找图片所在位置
|
|
|
- let treeItem = options.tree.find(item => item.largeImageMode);
|
|
|
- if (!treeItem) return _options;
|
|
|
- let { k_s, v } = treeItem; //显示图片的key 以及 位置
|
|
|
- if (!(k_s && v && v.length > 0)) return _options;
|
|
|
- _options['main'] = treeItem.v[arg[k_s]].imgUrl;
|
|
|
- _options['index'] = arg[k_s]; //预览图片的坐标
|
|
|
- // 获取预览图片
|
|
|
- if (this.previewImgArray.length == 0) {
|
|
|
- var previewImgArray = treeItem.v.map(item => item.previewImgUrl || item.imgUrl);
|
|
|
- this.previewImgArray = previewImgArray;
|
|
|
+ if (Object.keys(listItem).length > 0) {
|
|
|
+ let { id, price = 0, stock_num = 0, ...arg } = listItem;
|
|
|
+ _options = { price, stock_num };
|
|
|
+ // 查找图片所在位置
|
|
|
+ let treeItem = options.tree.find(item => item.largeImageMode);
|
|
|
+ if (Object.keys(treeItem).length) {
|
|
|
+ let { k_s, v } = treeItem; //显示图片的key 以及 位置
|
|
|
+ if (k_s && v && v.length > 0) {
|
|
|
+ treeItem.v.some((item, index) => {
|
|
|
+ if (item.id == arg[k_s]) {
|
|
|
+ _options['main'] = item.previewImgUrl || item.imgUrl;
|
|
|
+ _options['index'] = index; //预览图片的坐标
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 获取预览图片
|
|
|
+ if (this.previewImgArray.length == 0) {
|
|
|
+ var previewImgArray = treeItem.v.map(item => item.previewImgUrl || item.imgUrl);
|
|
|
+ this.previewImgArray = previewImgArray;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
} else {
|
|
|
// 给的默认
|
|
@@ -130,29 +157,28 @@ export default {
|
|
|
// 获取预览图片
|
|
|
if (this.previewImgArray.length == 0 && options.main) {
|
|
|
var previewImgArray = [options.main];
|
|
|
- is.previewImgArray = previewImgArray;
|
|
|
+ this.previewImgArray = previewImgArray;
|
|
|
}
|
|
|
}
|
|
|
_options['hide_stock'] = options.hide_stock || false;
|
|
|
- if(options.tree && options.tree.length>0){
|
|
|
- let collection_tree={};
|
|
|
- options.tree.forEach(treeItem=>treeItem.v.forEach(vItem=>collection_tree[treeItem.k_s]={id:vItem.id,lock:false}));
|
|
|
- this.collection_tree=collection_tree;
|
|
|
- }
|
|
|
+ if (Object.keys(this.collection_tree).length == 0) this.collection_tree = this.filterTree();
|
|
|
return _options;
|
|
|
},
|
|
|
// 参数
|
|
|
parameter() {
|
|
|
var options = this.options,
|
|
|
- _options = {},collection_id=this.collection_id;
|
|
|
+ _options = {},
|
|
|
+ collection_id = this.collection_id,
|
|
|
+ collection_keys = this.collection_keys,
|
|
|
+ collection_keys_len = Object.keys(collection_keys).length;
|
|
|
// 当用户没有选 不允许默认的情况下
|
|
|
- if (!collection_id && !options.root && options.tree && options.tree.length > 0) {
|
|
|
+ if (collection_keys_len == 0 && !collection_id && !options.root && options.tree && options.tree.length > 0) {
|
|
|
let tip = '请选择 ';
|
|
|
options.tree.forEach(item => (tip += item.k + ' '));
|
|
|
_options['tip'] = tip;
|
|
|
}
|
|
|
// 当用户没有选 允许默认的情况下
|
|
|
- if (!collection_id && options.root && options.list && options.list.length > 0 && options.tree && options.tree.length > 0) {
|
|
|
+ if (collection_keys_len == 0 && !collection_id && options.root && options.list && options.list.length > 0 && options.tree && options.tree.length > 0) {
|
|
|
let tip = '';
|
|
|
// 默认选中的
|
|
|
let listItem = options.list.find(item => item.id == options.collection_id);
|
|
@@ -163,32 +189,97 @@ export default {
|
|
|
});
|
|
|
_options['tip'] = tip;
|
|
|
}
|
|
|
+ // 当用户尚在选取的情况下;
|
|
|
+ if (collection_keys_len > 0 && !collection_id && options.list && options.list.length > 0 && options.tree && options.tree.length > 0) {
|
|
|
+ let tip = '请选择 ';
|
|
|
+ options.tree.forEach(item => {
|
|
|
+ var treeItem = item['v'].find(v => v.id == collection_keys[item.k_s]);
|
|
|
+ if (!treeItem) tip += item['k'] + ' ';
|
|
|
+ });
|
|
|
+ _options['tip'] = tip;
|
|
|
+ }
|
|
|
+ if (collection_id && options.list && options.list.length > 0 && options.tree && options.tree.length > 0) {
|
|
|
+ let listItem = options.list.find(item => item.id == collection_id);
|
|
|
+ let tip = '';
|
|
|
+ let { id, price, stock_num, ...arg } = listItem;
|
|
|
+ options.tree.forEach(item => {
|
|
|
+ item['v'].find(v => v.id == arg[item.k_s]).name;
|
|
|
+ tip += item['v'].find(v => v.id == arg[item.k_s]).name + ' ';
|
|
|
+ });
|
|
|
+ _options['tip'] = tip;
|
|
|
+ }
|
|
|
return _options;
|
|
|
- },
|
|
|
+ }
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
value: true, //显示隐藏
|
|
|
// 商品
|
|
|
collection_id: '', //选中id
|
|
|
- collection_keys:{},//选中参数
|
|
|
+ num:1,//购买数量
|
|
|
+ collection_keys: {}, //选中参数
|
|
|
// 商品参数集
|
|
|
- collection_tree:{},
|
|
|
+ collection_tree: {},
|
|
|
// 预览数据
|
|
|
- previewImgArray: []
|
|
|
+ previewImgArray: [],
|
|
|
+ // 按钮执行
|
|
|
+ addcartLock: false,
|
|
|
+ buyclickedLock: false
|
|
|
};
|
|
|
},
|
|
|
methods: {
|
|
|
+ // 添加购物车
|
|
|
+ addcart() {
|
|
|
+ if (this.addcartLock) return false;
|
|
|
+ this.addcartLock = true;
|
|
|
+ var collection_id = this.collection_id;
|
|
|
+ if (this.options.root && collection_id === '') collection_id = this.options.collection_id;
|
|
|
+ this.$emit('addcart', {collection_id,number:this.num}, () => (this.addcartLock = false));
|
|
|
+ },
|
|
|
+ // 立即购买
|
|
|
+ buyclicked() {
|
|
|
+ if (this.buyclickedLock) return false;
|
|
|
+ this.buyclickedLock = true;
|
|
|
+ var collection_id = this.collection_id;
|
|
|
+ if (this.options.root && collection_id === '') collection_id = this.options.collection_id;
|
|
|
+ this.$emit('buyclicked', {collection_id,number:this.num}, () => (this.buyclickedLock = false));
|
|
|
+ },
|
|
|
+ // 去除没有库存的参数
|
|
|
+ filterTree() {
|
|
|
+ let options = this.options;
|
|
|
+ let collection_tree = {};
|
|
|
+ if (options.tree && options.tree.length > 0) {
|
|
|
+ // 全部转化 默认true // 去除仓库没有的商品参数
|
|
|
+ options.tree.forEach(treeItem => {
|
|
|
+ collection_tree[treeItem.k_s] = {};
|
|
|
+ treeItem.v.forEach(vItem => {
|
|
|
+ let status = options.list.some(listItem => listItem[treeItem.k_s] == vItem.id);
|
|
|
+ collection_tree[treeItem.k_s][vItem.id] = status;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return collection_tree;
|
|
|
+ },
|
|
|
// 挑选参数
|
|
|
handler(item, v) {
|
|
|
- let collection_keys=JSON.parse(JSON.stringify(this.collection_keys));
|
|
|
+ let collection_tree = this.collection_tree;
|
|
|
+ if (!collection_tree[item.k_s][v.id]) return false;
|
|
|
+ let collection_keys = JSON.parse(JSON.stringify(this.collection_keys));
|
|
|
// 双击取消
|
|
|
- if(collection_keys[item.k_s] && collection_keys[item.k_s]==v.id){
|
|
|
- collection_keys[item.k_s]=''
|
|
|
- }else{
|
|
|
- collection_keys[item.k_s]=v.id;
|
|
|
+ if (collection_keys[item.k_s] && collection_keys[item.k_s] == v.id) {
|
|
|
+ collection_keys[item.k_s] = '';
|
|
|
+ } else {
|
|
|
+ collection_keys[item.k_s] = v.id;
|
|
|
+ }
|
|
|
+ var _collection_keys = Object.keys(collection_keys);
|
|
|
+ this.collection_keys = collection_keys;
|
|
|
+ // 针对已选中的参数选中对应类别的id;
|
|
|
+ var listItem = this.options.list.find(it => _collection_keys.every(key => collection_keys[key] == it[key]));
|
|
|
+ if (_collection_keys.length == this.options.tree.length && listItem) {
|
|
|
+ this.collection_id = listItem.id;
|
|
|
+ } else {
|
|
|
+ this.collection_id = '';
|
|
|
}
|
|
|
- this.collection_keys=collection_keys;
|
|
|
},
|
|
|
// 图片预览
|
|
|
previewImage(index) {
|
|
@@ -199,6 +290,39 @@ export default {
|
|
|
indicator: 'number'
|
|
|
});
|
|
|
}
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ collection_keys: {
|
|
|
+ // 针对已选参数进行过滤筛选
|
|
|
+ handler(newVal, oldVal) {
|
|
|
+ if (newVal != oldVal) {
|
|
|
+ let collection_tree = this.filterTree();
|
|
|
+ let collection_tree_keys = [];
|
|
|
+ let newValArr = Object.entries(newVal);
|
|
|
+ let includeArr = [];
|
|
|
+ newValArr.forEach(items => (includeArr = includeArr.concat(this.options.list.filter(item => item[items[0]] == items[1]))));
|
|
|
+ // 去重
|
|
|
+ includeArr = includeArr.filter((item, index) => includeArr.findIndex(it => JSON.stringify(it) == JSON.stringify(item)) === index);
|
|
|
+ // 二重
|
|
|
+ if (includeArr.length != 0) {
|
|
|
+ collection_tree = Object.fromEntries(
|
|
|
+ Object.entries(collection_tree).map(it => {
|
|
|
+ it[1] = Object.fromEntries(
|
|
|
+ Object.entries(it[1]).map(em => {
|
|
|
+ let status = includeArr.some(item => item[it[0]] == em[0]);
|
|
|
+ em[1] = status;
|
|
|
+ return em;
|
|
|
+ })
|
|
|
+ );
|
|
|
+ return it;
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ this.collection_tree = collection_tree;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
}
|
|
|
};
|
|
|
</script>
|
|
@@ -261,6 +385,18 @@ export default {
|
|
|
background-size: cover;
|
|
|
}
|
|
|
}
|
|
|
+ .border {
|
|
|
+ position: relative;
|
|
|
+ &::after {
|
|
|
+ content: '';
|
|
|
+ border-bottom: 1upx solid #ccc;
|
|
|
+ position: absolute;
|
|
|
+ width: 100%;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ transform: scaleY(0.5);
|
|
|
+ }
|
|
|
+ }
|
|
|
.cu-footer {
|
|
|
.btns-left,
|
|
|
.btns-right {
|