You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
540 lines
12 KiB
Vue
540 lines
12 KiB
Vue
<template>
|
|
<uni-popup v-if="(goods.goods_sku && goods.goods_sku.length > 1) || (goods.small_goods && goods.small_goods.length > 0)"
|
|
style="z-index: 1004;" z-index="1004" ref="popup" closeable type="bottom">
|
|
<view class="goodsPop">
|
|
<view @click="$refs.popup.close()" class="close">
|
|
<u-icon size="14" color="#9b9b9b" name="close"></u-icon>
|
|
</view>
|
|
<view class="info">
|
|
<view class="img">
|
|
<u-image radius="10" class="img" :src="getGoodsInfo.pic_url ? getGoodsInfo.pic_url : goods.pic_url"
|
|
width="200rpx" height="200rpx"></u-image>
|
|
</view>
|
|
<view class="txt">
|
|
<view class="subTitle"> {{ goods.name || "" }}</view>
|
|
<view class="g-price">
|
|
<view>¥</view>
|
|
<view class="fwb">{{ getPrice(getGoodsInfo.price_max)[0] }}</view>
|
|
<view>.{{ getPrice(getGoodsInfo.price_max)[1] }}</view>
|
|
</view>
|
|
<view class="current" v-if="getGoodsInfo.attr_name">{{
|
|
getGoodsInfo.attr_name
|
|
}}</view>
|
|
</view>
|
|
</view>
|
|
<scroll-view scroll-y class="scroll">
|
|
<view v-for="(item, index) of skuPopData.new_sku_group" :key="item.id">
|
|
<view class="m-tit">{{ item.name }}</view>
|
|
<view class="skuList">
|
|
<view @click="checked(item, index, e, i)" :class="[
|
|
'item',
|
|
e.disabled ? 'disabled' : '',
|
|
skuPopData.subIndex[index] == i ? 'checked' : '',
|
|
!e.isShow ? 'disabled' : '',
|
|
]" v-for="(e, i) of item.group_item" :key="e.id">{{ e.name }}</view>
|
|
</view>
|
|
</view>
|
|
<smallMaterial ref="smallMaterial" :smallPrice.sync="smallPrice" :small_goods="goods.small_goods"></smallMaterial>
|
|
</scroll-view>
|
|
<view class="number">
|
|
<view class="m-tit">数量</view>
|
|
<view class="number-rig">
|
|
<u-number-box v-model="skuPopData.num" :min="1" :max="getGoodsInfo.stock"></u-number-box>
|
|
</view>
|
|
</view>
|
|
<view class="btn">
|
|
<view @click="submit">确定</view>
|
|
</view>
|
|
</view>
|
|
</uni-popup>
|
|
</template>
|
|
|
|
<script>
|
|
import smallMaterial from "./smallMaterial";
|
|
export default {
|
|
components: { smallMaterial },
|
|
props: {
|
|
goods: {
|
|
type: Object,
|
|
required: true,
|
|
default: {
|
|
goods: {},
|
|
goods_sku: {}
|
|
},
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
skuPopData: {
|
|
num: 1,
|
|
type: 1, // 1.加入购物车 0.立即购买
|
|
showPop: false,
|
|
skuId: "", //规格id
|
|
// attr: [],
|
|
shopItemInfo: {}, //存放要和选中的值进行匹配的数据
|
|
subIndex: [], //是否选中 因为不确定是多规格还是单规格,所以这里定义数组来判断
|
|
selectArr: [], //存放被选中的值
|
|
activeGoodsInfo: null, // 当前选中的规格
|
|
new_sku_group: [],
|
|
},
|
|
smallPrice: 0
|
|
}
|
|
},
|
|
watch: {
|
|
'goods': {
|
|
handler(newvalue) {
|
|
if (newvalue) this.init(newvalue);
|
|
},
|
|
deep: true,
|
|
immediate: true,
|
|
},
|
|
|
|
"getGoodsInfo.stock"() {
|
|
if (this.getGoodsInfo.stock < this.skuPopData.num) {
|
|
this.skuPopData.num = 1
|
|
}
|
|
},
|
|
|
|
"getGoodsInfo.price_max": {
|
|
handler(newVal) {
|
|
try {
|
|
this.$emit("changeCoupon", Number(newVal) + Number(this.smallPrice))
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
},
|
|
},
|
|
smallPrice(newVal) {
|
|
try {
|
|
this.$nextTick(() => {
|
|
this.$emit("changeCoupon", Number(this.getGoodsInfo.price_max) + Number(newVal))
|
|
})
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
},
|
|
"skuPopData.showPop"(newVal) {
|
|
if (newVal) {
|
|
try {
|
|
this.$nextTick(() => {
|
|
this.$emit("changeCoupon", Number(this.getGoodsInfo.price_max) + Number(this.smallPrice))
|
|
})
|
|
} catch (error) {
|
|
console.log(error);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
getPrice: {
|
|
get() {
|
|
return (price = "0.00") => {
|
|
return String((Number(price) + this.smallPrice).toFixed(2)).split(".");
|
|
};
|
|
},
|
|
},
|
|
getGoodsInfo: {
|
|
get() {
|
|
try {
|
|
// 如果是
|
|
if (this.goods && !this.skuPopData.activeGoodsInfo) {
|
|
let {
|
|
stock,
|
|
price_max,
|
|
price_min,
|
|
use_sku,
|
|
name,
|
|
pic_url
|
|
} =
|
|
this.goods;
|
|
return {
|
|
stock,
|
|
price_max,
|
|
price_min,
|
|
use_sku,
|
|
pic_url: pic_url[0].pic_url,
|
|
};
|
|
}
|
|
let {
|
|
stock,
|
|
attr_list = [],
|
|
pic_url,
|
|
price
|
|
} = this.skuPopData.activeGoodsInfo;
|
|
return {
|
|
stock,
|
|
price_max: price,
|
|
price_min: price,
|
|
use_sku: 1,
|
|
pic_url,
|
|
attr_name: attr_list.map((el) => el.name).join("-"),
|
|
};
|
|
} catch (e) {
|
|
return {
|
|
stock: 0,
|
|
price_max: "0.00",
|
|
price_min: "0.00",
|
|
use_sku: 0,
|
|
name: "",
|
|
pic_url: "",
|
|
};
|
|
}
|
|
},
|
|
},
|
|
},
|
|
methods: {
|
|
getInfo(item) {
|
|
const checked = item.join("_");
|
|
if (this.skuPopData.shopItemInfo[checked]) {
|
|
this.skuPopData.skuId = this.skuPopData.shopItemInfo?.[checked]?.attr_list;
|
|
} else {
|
|
this.skuPopData.skuId = "";
|
|
}
|
|
|
|
if (this.skuPopData.skuId) {
|
|
const sku_no = this.skuPopData.skuId.map((el) => el.attr_id).join("_");
|
|
this.skuPopData.activeGoodsInfo = this.skuPopData.shopItemInfo[sku_no];
|
|
}
|
|
},
|
|
isMay(result) {
|
|
for (let i in result) {
|
|
if (result[i] == "") {
|
|
return true;
|
|
}
|
|
}
|
|
result = result.join("_");
|
|
if (!this.skuPopData.shopItemInfo[result]) {
|
|
return false;
|
|
}
|
|
|
|
// console.log(result);
|
|
// console.log(this.skuPopData.shopItemInfo);
|
|
return this.skuPopData.shopItemInfo[result].stock == 0 ? false : true;
|
|
},
|
|
checkItem() {
|
|
const option = JSON.parse(JSON.stringify(this.goods.sku_group));
|
|
const result = []; // define an array to store selected values
|
|
for (let i = 0; i < option.length; i++) {
|
|
result[i] = this.skuPopData.selectArr[i] ? this.skuPopData.selectArr[i] : "";
|
|
}
|
|
for (let i = 0; i < option.length; i++) {
|
|
const last = result[i];
|
|
for (let k = 0; k < option[i].group_item.length; k++) {
|
|
result[i] = option[i].group_item[k].id;
|
|
option[i].group_item[k].isShow = this.isMay(result);
|
|
}
|
|
result[i] = last;
|
|
}
|
|
this.skuPopData.new_sku_group = [];
|
|
// assign the original array
|
|
this.skuPopData.new_sku_group = option;
|
|
this.getInfo(this.skuPopData.selectArr);
|
|
},
|
|
pushData(id, pindex, index, disable, pname, attr_group_id, attr_name) {
|
|
if (!disable) {
|
|
return "";
|
|
}
|
|
if (this.skuPopData.selectArr[pindex] !== id) {
|
|
this.$set(this.skuPopData.selectArr, pindex, id);
|
|
this.$set(this.skuPopData.subIndex, pindex, index);
|
|
// this.$set(this.skuPopData.attr, pindex, {
|
|
// attr_id: id,
|
|
// attr_group_id: attr_group_id,
|
|
// attr_name: attr_name,
|
|
// attr_group_name: pname,
|
|
// });
|
|
}
|
|
this.checkItem();
|
|
},
|
|
checked(pItem, pindex, item, index) {
|
|
let { id: attr_group_id, name: group_name } = pItem;
|
|
let { id, isShow: disable, name: attr_name } = item;
|
|
|
|
this.pushData(id, pindex, index, disable, group_name, attr_group_id, attr_name);
|
|
|
|
this.goods.goods_sku.forEach((d) => {
|
|
if (d.id === attr_group_id) {
|
|
this.$set(d, 'select_name', attr_name);
|
|
}
|
|
});
|
|
},
|
|
async init(newvalue = { goods_sku: [] }) {
|
|
this.skuPopData.skuId = "";
|
|
this.skuPopData.attr = [];
|
|
this.skuPopData.shopItemInfo = {};
|
|
this.skuPopData.subIndex = [];
|
|
this.skuPopData.selectArr = [];
|
|
this.skuPopData.activeGoodsInfo = null;
|
|
if (!newvalue.goods_sku) {
|
|
return
|
|
}
|
|
// 初始化规格数据
|
|
for (let i of newvalue.goods_sku) {
|
|
let sp = "";
|
|
for (let j of i.attr_list) {
|
|
sp += j.attr_id + "_";
|
|
}
|
|
if (sp.length > 0) {
|
|
sp = sp.substr(0, sp.length - 1);
|
|
}
|
|
this.skuPopData.shopItemInfo[sp] = i;
|
|
}
|
|
|
|
if (newvalue.sku_group && newvalue.sku_group.length) {
|
|
this.skuPopData.selectArr.length = newvalue.sku_group.length;
|
|
this.skuPopData.subIndex.length = newvalue.sku_group.length;
|
|
for (let i = 0; i < newvalue.goods_sku.length; i++) {
|
|
let group = newvalue.goods_sku[i];
|
|
if (group.stock > 0) {
|
|
let attrList = group.attr_list;
|
|
let skuGroup = newvalue.sku_group;
|
|
for (let attr of attrList) {
|
|
for (let groups of skuGroup) {
|
|
if (attr.attr_group_id === groups.id) {
|
|
let groupItem = groups.group_item.find((item) => item.id === attr.attr_id);
|
|
let groupItemIndex = groups.group_item.findIndex((item) => item.id === attr.attr_id);
|
|
if (groupItem) {
|
|
let groupIndex = skuGroup.indexOf(groups);
|
|
groupItem.isShow = true
|
|
this.checked(groups, groupIndex, groupItem, groupItemIndex, 1)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this.checkItem();
|
|
await this.$nextTick()
|
|
if (this.goods.goods_sku && this.goods.goods_sku.length == 1 && (!this.goods.small_goods || this.goods.small_goods.length == 0)) {
|
|
this.submit(1)
|
|
}
|
|
},
|
|
changeNum(num) {
|
|
let count = 0;
|
|
if (num <= this.getGoodsInfo.stock) {
|
|
if (num <= 0) {
|
|
count = 1;
|
|
} else {
|
|
count = num;
|
|
}
|
|
} else {
|
|
count = this.getGoodsInfo.stock;
|
|
}
|
|
|
|
this.skuPopData.num = count;
|
|
},
|
|
async addCart(params) {
|
|
uni.showLoading({
|
|
title: "请稍等",
|
|
mask: true,
|
|
});
|
|
|
|
try {
|
|
const res = await this.$api.goods.cartEdit(params);
|
|
uni.hideLoading();
|
|
if (res.code) return uni.$u.toast(res.message);
|
|
uni.$u.toast("操作成功!");
|
|
this.skuPopData.showPop = false;
|
|
this.$refs.popup.close()
|
|
} catch (e) {
|
|
uni.hideLoading();
|
|
throw new Error(e);
|
|
}
|
|
},
|
|
submit(is_auto = 0) {
|
|
let {
|
|
num,
|
|
activeGoodsInfo,
|
|
type
|
|
} = this.skuPopData;
|
|
if (!activeGoodsInfo) return uni.$u.toast("请完善规格!");
|
|
const [result, judge] = this.$refs?.smallMaterial?.check() || [[], true]
|
|
if (!judge) {
|
|
return
|
|
}
|
|
let {
|
|
id: goods_sku_id
|
|
} = activeGoodsInfo,
|
|
params = {
|
|
goods_sku_id,
|
|
num,
|
|
goods_id: this.goods.id,
|
|
small_goods: result,
|
|
small_goods_json: JSON.stringify(result)
|
|
};
|
|
this.skuPopData.small_goods = result
|
|
this.skuPopData.small_goods_json = JSON.stringify(result)
|
|
type = 2
|
|
switch (type) {
|
|
case 0:
|
|
uni.navigateTo({
|
|
url: "/subPackages/order/preview/index?submit=" +
|
|
JSON.stringify([{
|
|
mch_id: this.goods?.mch_id,
|
|
good_list: [{
|
|
...params,
|
|
cart_id: 0
|
|
}],
|
|
},]),
|
|
});
|
|
break;
|
|
case 1:
|
|
this.addCart(params);
|
|
break;
|
|
case 2:
|
|
this.skuPopData.showPop = false;
|
|
this.$refs.popup?.close()
|
|
this.skuPopData.goods_sku_id = goods_sku_id;
|
|
this.skuPopData.goods = this.goods;
|
|
this.skuPopData.activeGoodsInfo.totalPrice = (Number(this.skuPopData.activeGoodsInfo.price) + this.smallPrice).toFixed(2)
|
|
this.$emit('skuPopData', this.skuPopData);
|
|
break;
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.goodsPop {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 36rpx 36rpx 0;
|
|
max-height: 90vh;
|
|
background-color: white;
|
|
border-radius: 26rpx 26rpx 0 0;
|
|
position: relative;
|
|
|
|
.close {
|
|
position: absolute;
|
|
right: 28rpx;
|
|
top: 28rpx;
|
|
background-color: #eaeaea;
|
|
padding: 6rpx;
|
|
border-radius: 100px;
|
|
}
|
|
|
|
.info {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
|
|
.txt {
|
|
flex: 1;
|
|
padding-left: 20rpx;
|
|
overflow: hidden;
|
|
color: #f0250e;
|
|
}
|
|
|
|
.stock {
|
|
font-size: 22rpx;
|
|
color: #f0250e;
|
|
}
|
|
|
|
.current {
|
|
font-size: 22rpx;
|
|
color: #8c8c8c;
|
|
}
|
|
}
|
|
}
|
|
|
|
.g-price {
|
|
line-height: 1;
|
|
}
|
|
|
|
.scroll {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.m-tit {
|
|
padding: 30rpx 0 0;
|
|
font-size: 26rpx;
|
|
font-weight: bold;
|
|
color: #262626;
|
|
}
|
|
|
|
.btn {
|
|
display: flex;
|
|
margin: 10rpx -11rpx;
|
|
|
|
view {
|
|
overflow: hidden;
|
|
flex: 1;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 11rpx;
|
|
height: 76rpx;
|
|
font-size: 26rpx;
|
|
color: #fff;
|
|
font-weight: bold;
|
|
border-radius: 32px;
|
|
background: linear-gradient(90deg, #f22407 0%, #f84d17 100%);
|
|
}
|
|
}
|
|
|
|
.skuList {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
|
|
.item {
|
|
position: relative;
|
|
margin: 24rpx 24rpx 0 0;
|
|
padding: 14rpx 28rpx;
|
|
border-radius: 32px;
|
|
background: #f2f1f2;
|
|
color: #262626;
|
|
|
|
font-size: 14px;
|
|
}
|
|
|
|
.disabled {
|
|
color: #8c8c8c;
|
|
|
|
&:after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 20rpx;
|
|
top: 50%;
|
|
right: 20rpx;
|
|
height: 1px;
|
|
background: #8c8c8c;
|
|
}
|
|
}
|
|
|
|
.checked {
|
|
background: #fbeceb;
|
|
color: #f0250e;
|
|
}
|
|
}
|
|
|
|
.subTitle {
|
|
font-size: 28rpx;
|
|
color: #262626;
|
|
margin-bottom: 20rpx;
|
|
margin-right: 50rpx;
|
|
}
|
|
|
|
.number {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 40rpx 0;
|
|
|
|
.m-tit {
|
|
flex: 1;
|
|
overflow: hidden;
|
|
padding: 0;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<style>
|
|
uni-toast {
|
|
z-index: 999999999999 !important;
|
|
}
|
|
</style> |