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.

547 lines
12 KiB
Vue

<template>
<uni-popup v-if="goods.goods_sku && goods.goods_sku.length > 1" 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.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>