暂时去掉登录时候client参数,会引发account唯一索引错误

This commit is contained in:
2025-05-13 14:44:56 +08:00
parent a079f9d9fe
commit 1b6971407d
34 changed files with 1980 additions and 207 deletions

View File

@ -0,0 +1,228 @@
<template>
<view class="order-goods bg-white">
<view v-for="(item, index) in list" :key="index" class="item-wrap">
<view class="item row" @tap="toGoods(item.goods_id)">
<view class="goods-img">
<u-image :src="item.image_str || item.image"
:width="imageWidth"
:height="imageHeight"
:border-radius="imageRadius"
lazy-load/>
</view>
<view class="goods-info ml20 flex1">
<view class="goods-name line2 mb10">
<u-tag
class="mr10"
v-if="team.need"
:text="team.need + '人团'"
size="mini"
type="primary"
mode="plain"
/>
{{ item.goods_name || item.name }}</view
>
<view class="goods-spec xs muted mb20">{{
item.spec_value_str || item.spec_value
}}</view>
<view class="row-between">
<view class="goods-price row">
<view class="primary">
<price-format
v-if="!item.is_member && order_type === 0"
:weight="500"
:subscript-size="24"
:first-size="34"
:second-size="24"
:price="item.original_price || item.goods_price"
></price-format>
</view>
<view class="vip-price row" v-if="item.is_member && order_type === 0">
<view class="price-name xxs">会员价</view>
<view style="padding: 0 10rpx">
<price-format
:price="item.goods_price"
:first-size="22"
:second-size="22"
:subscript-size="22"
:weight="500"
color="#7B3200"
></price-format>
</view>
</view>
<view
class="vip-price row"
v-if="order_type === 1 || order_type === 2 || order_type === 3"
>
<view class="price-name xxs" style="background-color: #e74346">
<text v-if="order_type === 1">秒杀价</text>
<text v-if="order_type === 2">拼团价</text>
<text v-if="order_type === 3">砍价</text>
</view>
<view style="padding: 0 10rpx">
<price-format
:price="item.goods_price"
:first-size="22"
:second-size="22"
:subscript-size="22"
:weight="500"
color="#7B3200"
></price-format>
</view>
</view>
</view>
<view class="goods-num sm">x{{ item.goods_num }}</view>
</view>
</view>
</view>
<template v-if="mode === 'comfirm'">
<view class="delivery" v-if="delivery === 1 && !item.is_express"
>该商品不支持快递配送</view
>
<view class="delivery" v-if="delivery === 2 && !item.is_selffetch"
>该商品不支持门店自提</view
>
</template>
<view class="goods-footer row" v-if="link">
<view style="flex: 1"></view>
<navigator
class="mr20"
hover-class="none"
:url="'/bundle/pages/goods_reviews/goods_reviews?id=' + item.id"
v-if="item.comment_btn"
>
<button size="xs" class="plain br60" hover-class="none">评价晒图</button>
</navigator>
<navigator
v-if="item.refund_btn"
hover-class="none"
:url="
'/bundle/pages/apply_refund/apply_refund?order_id=' +
item.order_id +
'&item_id=' +
item.item_id
"
>
<button size="xs" class="plain br60" hover-class="none">申请退款</button>
</navigator>
<view v-if="item.after_status_desc" style="color: orange">
{{ item.after_status_desc }}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {}
},
components: {},
props: {
list: {
type: Array,
default: () => []
},
link: {
type: Boolean,
default: false
},
team: {
type: [Object, Array],
default: () => ({})
},
delivery: {
type: Number,
default: 1
},
// order | comfirm
mode: {
type: String,
default: 'order'
},
order_type: {
type: Number,
default: 0
},
imageWidth: {
type: Number,
default: 180
},
imageHeight: {
type: Number,
default: 180
},
imageRadius: {
type: Number,
default: 0
}
},
methods: {
toGoods(id) {
if (!this.link) return
uni.navigateTo({
url: `/pages/goods_details/goods_details?id=${id}`
})
}
}
}
</script>
<style lang="scss">
.order-goods {
.item {
padding: 20rpx 24rpx;
.vip-price {
// margin: 0 10rpx;
background-color: #ffe9ba;
line-height: 30rpx;
border-radius: 6rpx;
overflow: hidden;
.price-name {
background-color: #101010;
padding: 3rpx 10rpx;
color: #ffd4b7;
position: relative;
overflow: hidden;
&::after {
content: '';
display: block;
width: 20rpx;
height: 20rpx;
position: absolute;
right: -15rpx;
background-color: #ffe9ba;
border-radius: 50%;
top: 50%;
transform: translateY(-50%);
box-sizing: border-box;
}
}
}
}
.goods-footer {
height: 70rpx;
align-items: flex-start;
padding: 0 24rpx;
.plain {
border: 1px solid #999;
height: 52rpx;
line-height: 52rpx;
font-size: 26rpx;
}
}
.delivery {
display: inline-block;
margin-left: calc(180rpx + 20rpx * 2);
padding: 4rpx 15rpx;
border-radius: 60px;
font-size: 20rpx;
background-color: #f4f4f4;
color: #999999;
}
}
</style>

View File

@ -5,15 +5,15 @@
<view class="shop-title bold-600 u-p-l-40 u-p-r-40 w-full u-line-1">{{ name }}</view>
<scroll-view scroll-y="true" scroll-with-animation="true" style="height: 480rpx;">
<view class="u-m-l-40">
<view v-for="(item, index1) in specBck" :key="index1">
<view v-for="(item, index) in specList" :key="index">
<view class="attr nr u-m-t-20 u-m-b-20 ">{{ item.name }}</view>
<view class="row wrap">
<view
v-for="(attr, index2) in item.spec_value" :key="index2"
@click="chooseSpec(item, index1, index2, attr)"
:class="item.spec_value[index2].is_select ? 'attr-list active' : 'attr-list'"
v-for="(specitem, index2) in item.spec_value" :key="index2"
@click="chooseSpec(index, index2)"
:class="checkedGoods.spec_value_ids_arr[index] == specitem.id ? 'attr-list active' : 'attr-list'"
>
{{ attr.value }}
{{ specitem.value }}
</view>
</view>
</view>
@ -21,12 +21,20 @@
</scroll-view>
<view class="mt20">
<view class="u-m-l-40 u-flex u-flex-wrap">已选规格
<view v-for="(item, index) in selectedSpec" :key="index" class="current">
{{ item.name }}
<view class="u-flex u-m-l-40 u-m-r-40">
<view class="u-flex u-flex-wrap">
{{ specValueText }}
<!-- <view v-for="(item, index) in selectedSpec" :key="index" class="current">
{{ item.name }}
</view> -->
</view>
<view class="flex1 u-text-right">
<u-number-box v-model="goodsNum" :min="1" :max="checkedGoods.stock"
:disabled="disabledNumberBox"></u-number-box>
</view>
</view>
<view class="row u-row-center mt20 u-p-b-20">
<view class="row u-row-center mt20 u-p-b-20" :class="specValueText.indexOf('请选择') != -1 || checkedGoods.stock == 0 ? 'disabled' : ''">
<view class="w-40 mr10">
<u-button @click="close" hover-class="none" :customStyle="{color: themeColor, border: '1px solid ' + themeColor, padding: '16rpx 0'}" :plain="true" :hair-line="false" shape="circle">取消</u-button>
</view>
@ -48,12 +56,13 @@
type: Boolean,
required: true
},
spec: {
type: [Array, Object],
default: () => [{}]
goods: {
type: [Object, Array],
},
disabledNumberBox: {
type: Boolean,
default: false,
},
name: {
type: String,
default: ''
@ -64,6 +73,13 @@
mobile: '',
specBck: [],
selectedSpec: [],
checkedGoods: {
stock: 0,
}, //选中的
outOfStock: [], //缺货的
specList: [], //规格
disable: [], //不可选择的
goodsNum: 1,
};
},
methods: {
@ -73,53 +89,129 @@
this.$emit('close')
},
// 选择规格
chooseSpec(item, index1, index2, attr) {
if (item.name == '辣度') {
// 规格-单选
item.spec_value.map((i, k) => {
if(k === index2) {
if (item.spec_value[index2].is_select) {
this.$set(i, 'is_select', false)
this.selectedSpec = this.selectedSpec.filter(it => it.id !== item.spec_value[index2].id)
} else {
this.$set(i, 'is_select', true)
this.selectedSpec.push({
id: item.spec_value[index2].id,
name: item.spec_value[index2].value
})
}
} else {
this.$set(i, 'is_select', false)
this.selectedSpec.map((se, index) => {
if (se.id == i.id) {
this.selectedSpec.splice(index, 1)
}
})
}
})
} else {
// 规格-复选
if (item.spec_value[index2].is_select) {
this.$set(item.spec_value[index2], 'is_select', false)
this.selectedSpec = this.selectedSpec.filter(i => i.id !== item.spec_value[index2].id)
} else {
// 选中
this.$set(item.spec_value[index2], 'is_select', true)
this.selectedSpec.push({
id: item.spec_value[index2].id,
name: item.spec_value[index2].value
})
// 过滤出需要进行禁用的规格
getOutOfStockArr(arr, arr1, result = []) {
arr.forEach((el) => {
if (el.num >= arr1.length - 1) {
result.push(...el.different);
}
}
});
return result;
},
// 匹配出缺货库存和已选中对比结果
getArrIdentical(arr1, arr2, arr = [], num = 0) {
arr1.forEach((el) => {
arr2.forEach((el2) => {
if (el == el2) {
num += 1;
arr.push(el);
}
});
});
return {
num, //n个相同的
different: this.getArrDifference(
[...new Set(arr)].map(Number),
arr2.map(Number)
),
identical: [...new Set(arr)],
};
},
// 匹配出已选择和缺库存的
getArrResult(arr, outOfStock, result = []) {
outOfStock.forEach((item) => {
const res = this.getArrIdentical(arr, item.spec_value_ids.split(","));
if (res != undefined && res.length != 0) {
result.push(res);
}
});
return result;
},
// 找出两个数组中参数不同的
getArrDifference(arr1, arr2) {
return arr1.concat(arr2).filter(function (v, i, arr) {
return arr.indexOf(v) == arr.lastIndexOf(v);
});
},
chooseSpec(index, index2) {
const id = this.specList[index].spec_value[index2].id;
// 无法选择
const disable = this.disable.filter((item) => item == id);
if (disable.length != 0) return;
let idsArr = this.checkedGoods.spec_value_ids_arr;
if (id == idsArr[index]) idsArr[index] = "";
else idsArr[index] = id;
//保存已选规格
this.checkedGoods.spec_value_ids_arr = idsArr;
this.checkedGoods.spec_value_ids = idsArr.join(",");
// 重新渲染页面
this.specList = [...this.specList]
console.log("this.checkedGoods>>>", this.checkedGoods);
},
// 选择规格
// chooseSpec(item, index1, index2, attr) {
// if (item.name == '辣度') {
// // 规格-单选
// item.spec_value.map((i, k) => {
// if(k === index2) {
// if (item.spec_value[index2].is_select) {
// this.$set(i, 'is_select', false)
// this.selectedSpec = this.selectedSpec.filter(it => it.id !== item.spec_value[index2].id)
// } else {
// this.$set(i, 'is_select', true)
// this.selectedSpec.push({
// id: item.spec_value[index2].id,
// name: item.spec_value[index2].value
// })
// }
// } else {
// this.$set(i, 'is_select', false)
// this.selectedSpec.map((se, index) => {
// if (se.id == i.id) {
// this.selectedSpec.splice(index, 1)
// }
// })
// }
// })
// } else {
// // 规格-复选
// if (item.spec_value[index2].is_select) {
// this.$set(item.spec_value[index2], 'is_select', false)
// this.selectedSpec = this.selectedSpec.filter(i => i.id !== item.spec_value[index2].id)
// } else {
// // 选中
// this.$set(item.spec_value[index2], 'is_select', true)
// this.selectedSpec.push({
// id: item.spec_value[index2].id,
// name: item.spec_value[index2].value
// })
// }
// }
// },
// 确认选择的规格
confirm() {
this.showPop = false
this.$emit('confirm', {
spec: this.selectedSpec
})
let { checkedGoods, goodsNum } = this;
if (this.specValueText.indexOf("请选择") != -1)
return this.$toast({
title: this.specValueText,
});
if (checkedGoods.stock == 0)
return this.$toast({
title: "当前选择库存不足",
});
checkedGoods.goodsNum = goodsNum;
this.$emit('buynow', {
detail: checkedGoods,
});
}
},
computed: {
@ -130,13 +222,70 @@
set(val) {
this.$emit('input', val)
}
}
},
specValueText() {
let arr = this.checkedGoods.spec_value_ids?.split(",");
let spec_str = "";
if (arr)
arr.forEach((item, index) => {
if (item == "") spec_str += this.specList[index].name + ",";
});
if (this.checkedGoods?.stock != 0 && spec_str == "")
return `已选规格:${this.checkedGoods.spec_value_str} ${this.goodsNum}`;
else return `请选择 ${spec_str.slice(0, spec_str.length - 1)}`;
},
},
watch: {
spec(val) {
goods(value) {
// 创建副本
this.specBck = val
}
this.specList = value.goods_spec || []
let goodsItem = value.goods_item || []
this.outOfStock = goodsItem.filter((item) => item.stock == 0)
// 找出库存不为0的
const resultArr = goodsItem.filter((item) => item.stock != 0)
if (resultArr.length != 0) {
resultArr[0].spec_value_ids_arr =
resultArr[0].spec_value_ids.split(",");
this.checkedGoods = resultArr[0];
} else {
// 无法选择
goodsItem[0].spec_value_ids_arr = [];
this.disable = goodsItem.map((item) => item.spec_value_ids.split(","));
this.checkedGoods = goodsItem[0];
}
},
specList(value) {
if (this.checkedGoods.stock == 0) return;
const res = this.goods.goods_item.filter((item) => {
return this.checkedGoods.spec_value_ids === item.spec_value_ids;
});
// 库存为0的规格
const idsArr = this.checkedGoods.spec_value_ids_arr;
const outOfStock = this.outOfStock;
// 找出规格相同和规格不相同的余数
const getArrGather = this.getArrResult(idsArr, outOfStock);
// 计算出缺货的规格项
this.disable = this.getOutOfStockArr(getArrGather, idsArr);
if (res.length != 0) {
console.log(res, "-----");
let result = JSON.parse(JSON.stringify(res[0]));
result.spec_value_ids_arr = result.spec_value_ids.split(",");
if (this.goodsNum > result.stock) {
this.goodsNum = result.stock;
}
this.checkedGoods = result;
// 同步到父组件
this.$emit("change", {
detail: this.checkedGoods,
});
}
},
}
};
</script>
@ -186,5 +335,10 @@
border: 2rpx solid #F6F6F7;
padding: 20rpx;
}
// 底部按钮无法选择
.disabled {
opacity: 0.4;
}
}
</style>