bug:订单详情问题修复
This commit is contained in:
parent
bb958ce2fe
commit
c4f85aa9dc
@ -1,46 +1,72 @@
|
||||
export type PrDetailType = {
|
||||
adminCategoryId1: 146
|
||||
adminCategoryId2: 147
|
||||
appCategoryId1: 48
|
||||
appCategoryId2: 56
|
||||
createTime: 1762760434000
|
||||
defaultSort: 0
|
||||
frontPage: 1
|
||||
id: 73
|
||||
isDelete: 0
|
||||
isFlash: 0
|
||||
isNew: 1
|
||||
isTest: 0
|
||||
mainImageUrl: 'https://heyuimage.ihzhy.com/prd/202511/9a77567562f87caf.jpg?key=xxxxxxx'
|
||||
modifyTime: 1762760434000
|
||||
realSaleCount: 0
|
||||
showPromotionPrice: 0
|
||||
showSaleCount: 0
|
||||
showSalePrice: 0
|
||||
status: 'online'
|
||||
title: 'Akoya双珠海水戒指'
|
||||
export type ProductDetailType = {
|
||||
adminCategoryId1: number
|
||||
adminCategoryId2: number
|
||||
appCategoryId1: number
|
||||
appCategoryId2: number
|
||||
createTime: number
|
||||
defaultSort: number
|
||||
frontPage: number
|
||||
id: number
|
||||
isDelete: number
|
||||
isFlash: number
|
||||
isNew: number
|
||||
isTest: number
|
||||
mainImageUrl: string
|
||||
modifyTime: number
|
||||
realSaleCount: number
|
||||
showPromotionPrice: number
|
||||
showSaleCount: number
|
||||
showSalePrice: number
|
||||
status: string
|
||||
title: string
|
||||
vvSkuList: SkuType[]
|
||||
vvProductDetailList: []
|
||||
vvProductPropertyList: []
|
||||
vvProductDetailList: ProductDetailImagesType[]
|
||||
vvProductPropertyList: ProudictProductPropertyType[]
|
||||
}
|
||||
|
||||
export type SkuType = {
|
||||
createTime: number
|
||||
id: 364
|
||||
isDelete: 0
|
||||
modifyTime: 1762760434000
|
||||
productId: 73
|
||||
promotionPrice: 0
|
||||
showSaleCount: 0
|
||||
stock: 0
|
||||
id: number
|
||||
isDelete: number
|
||||
modifyTime: number
|
||||
productId: number
|
||||
promotionPrice: number
|
||||
showSaleCount: number
|
||||
stock: number
|
||||
imageUrl: string
|
||||
salePrice: number
|
||||
vvSkuPropertyValueList: SkuPropretyType[]
|
||||
}
|
||||
|
||||
export type SkuPropretyType = {
|
||||
createTime: number
|
||||
id: number
|
||||
isDelete: number
|
||||
modifyTime: number
|
||||
productId: number
|
||||
productPropertyName: string
|
||||
productPropertyValue: string
|
||||
skuId: number
|
||||
}
|
||||
|
||||
export type ProductDetailImagesType = {
|
||||
createTime: 1762760434000
|
||||
detail: 'https://heyuimage.ihzhy.com/prd/202511/304182481ebfc9ab.jpg?key=xxxxxxx'
|
||||
id: 187
|
||||
isDelete: 0
|
||||
modifyTime: 1762760434000
|
||||
productId: 73
|
||||
type: 1
|
||||
createTime: number
|
||||
detail: string
|
||||
id: number
|
||||
isDelete: number
|
||||
modifyTime: number
|
||||
productId: number
|
||||
type: number
|
||||
}
|
||||
|
||||
export type ProudictProductPropertyType = {
|
||||
createTime: number
|
||||
defaultSort: number
|
||||
id: number
|
||||
isDelete: number
|
||||
modifyTime: number
|
||||
productId: number
|
||||
productPropertyName: string
|
||||
vvProductPropertyList?: ProudictProductPropertyType[] // 如需树状结构可用此字段
|
||||
vvProductPropertyValueList: ProudictProductPropertyType[] // 按你原写法保持不变
|
||||
}
|
||||
|
||||
@ -15,8 +15,8 @@ const service: AxiosInstance = axios.create({
|
||||
timeout: 150000, // 请求超时时间
|
||||
})
|
||||
|
||||
const noEncryptWhiteList = ['/common/protocol/content', '/portal/common/protocol/content', '/bl-log/web/log/add']
|
||||
const noConsoleWhiteList = ['bl-log/web/log/add']
|
||||
// const noEncryptWhiteList = ['/common/protocol/content', '/portal/common/protocol/content', '/bl-log/web/log/add']
|
||||
// const noConsoleWhiteList = ['bl-log/web/log/add']
|
||||
|
||||
// request拦截器
|
||||
service.interceptors.request.use(
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<div class="cart-wrap">
|
||||
<p class="flex justify-between" @click="showAddressList = true">
|
||||
<van-icon name="location-o" class="mr-1" /><span class="max-w-12 mr-1">{{ curAddressData?.buyerName }}</span>
|
||||
<b class="font- flex-1">{{ (curAddressData?.province ?? '') + (curAddressData?.city ?? '') + (curAddressData?.district ?? '') + (curAddressData?.detail?? '') }}</b
|
||||
<b class="font- flex-1">{{ (curAddressData?.province ?? '') + (curAddressData?.city ?? '') + (curAddressData?.district ?? '') + (curAddressData?.detail ?? '') }}</b
|
||||
><van-icon name="arrow" />
|
||||
</p>
|
||||
</div>
|
||||
@ -19,6 +19,13 @@
|
||||
</p>
|
||||
<p>
|
||||
<van-stepper v-model="formData.num" input-width=".4rem" button-size=".2rem" min="1" :max="curPageData.num" />
|
||||
<span class="text-[10px] text-hex-cccccc ml-[5px]">
|
||||
(最大可购买{{ curPageData?.num }})
|
||||
</span>
|
||||
|
||||
<span class="text-[10px] text-hex-cccccc ml-[3px]">
|
||||
{{ curPageData?.num > 0 ? "有货" : "缺货"}}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -28,11 +35,11 @@
|
||||
<div class="cagetory">
|
||||
<p
|
||||
v-for="v in arr"
|
||||
:key="v.propertyId"
|
||||
:class="{ 'theme-border-color theme-color': v.propertyId === curPropertyIds.find((it) => it.productPropertyName === key).id }"
|
||||
@click="onChooseProperty(v, key)"
|
||||
:key="v.sid"
|
||||
:class="[{ 'theme-border-color theme-color': v.label === curSelection[key] }, { disabled: v.disabled }]"
|
||||
@click="!v.disabled && onChooseProperty(v, key)"
|
||||
>
|
||||
{{ v?.label }}
|
||||
{{ v.label }} {{ v.num }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
@ -49,59 +56,109 @@
|
||||
<script lang="ts" setup>
|
||||
import api from '@/api'
|
||||
import { requestPayment } from '@/utils/wx-minprogram'
|
||||
|
||||
import type { SkuType } from '@/api/types/shop'
|
||||
const model = defineModel<boolean>()
|
||||
const showAddressList = defineModel<boolean>('showAddressList')
|
||||
const props = defineProps<{ list: Array<any>; curAddressData: Recordable<any>; scene: 'order' | 'cart' }>()
|
||||
const skuData = ref<any>({}) // sku分类,key为属性的类目,value为属性的分类{ 颜色: [{ '黄色'}]}
|
||||
const commodityData = ref<any>({}) // 商品对象, value为每种商品的skuId,图片,销售价,成交价,库存(key为属性id的集合)
|
||||
const curPropertyIds = ref<any>([]) // 当前选中的属性id的集合[{ id: 1, name: '颜色'},{id: 2, name: '重量'}] name是用来赋值的
|
||||
const curPageData = ref<any>({ price: '', imageUrl: '', num: 0 }) // 当前商品页面数据
|
||||
const formData = ref<any>({ skuId: NaN, num: 1 })
|
||||
type SkuOption = { sid: string; label: string; num: number; disabled?: boolean }
|
||||
const skuData = ref<Record<string, SkuOption[]>>({}) // sku分类,key为属性的类目
|
||||
const commodityData = ref<Record<string, { id: number; imageUrl?: string; salePrice?: number; price?: number; num: number }>>({}) // 商品对象,每种组合的 sku 信息
|
||||
const categoryOrder = ref<string[]>([]) // 类目
|
||||
const curSelection = ref<Record<string, string>>({})
|
||||
const curPageData = ref({ price: 0, imageUrl: '', num: 0 })
|
||||
const formData = ref({ skuId: NaN, num: 1 })
|
||||
|
||||
// 设置pathset
|
||||
const buildSignature = (order: string[], selection: Record<string, string>) => order.map((name) => `${name}:${selection[name] ?? ''}`).join('|')
|
||||
|
||||
// 设置唯一id
|
||||
const buildOptionSid = (vv: SkuType['vvSkuPropertyValueList'][number]) => `${vv.productPropertyName}:${vv.productPropertyValue}`
|
||||
|
||||
watch(model, (val) => {
|
||||
if (val) {
|
||||
const { result, commodityMap, firstShopIds } = handleGetSkuList(props.list)
|
||||
skuData.value = result
|
||||
commodityData.value = commodityMap
|
||||
curPropertyIds.value = firstShopIds
|
||||
const { pageData, skuId } = handleGetPageData(commodityData.value, curPropertyIds.value)
|
||||
curPageData.value = pageData
|
||||
formData.value = { skuId, num: 1 }
|
||||
}
|
||||
if (!val) return
|
||||
const { result, commodityMap, firstSelection } = handleGetSkuList(props.list)
|
||||
skuData.value = result
|
||||
commodityData.value = commodityMap
|
||||
curSelection.value = firstSelection
|
||||
syncCurrentSku()
|
||||
updateOptionDisabled()
|
||||
})
|
||||
|
||||
const handleGetSkuList = (list: any[]) => {
|
||||
const result = {} as any // sku分类
|
||||
const commodityMap = {} //
|
||||
let firstShopIds = []
|
||||
list.forEach((item, i) => {
|
||||
const commodityValue = { id: item.id, imageUrl: item.imageUrl, salePrice: item.salePrice, price: item.promotionPrice, num: item.stock }
|
||||
let commodityPropertyId = ''
|
||||
if (i === 0) {
|
||||
firstShopIds = item.vvSkuPropertyValueList.map((child) => ({ id: child.id, productPropertyName: child.productPropertyName }))
|
||||
}
|
||||
item.vvSkuPropertyValueList.forEach((item2, index) => {
|
||||
commodityPropertyId += item2.id + (index < item.vvSkuPropertyValueList.length - 1 ? '_' : '')
|
||||
if (!result[item2.productPropertyName]) result[item2.productPropertyName] = []
|
||||
if (result[item2.productPropertyName].some((child) => child.propertyId === item2.id)) return
|
||||
result[item2.productPropertyName].push({ propertyId: item2.id, label: item2.productPropertyValue })
|
||||
// 更新
|
||||
const updateOptionDisabled = () => {
|
||||
Object.entries(skuData.value).forEach(([categoryName, options]) => {
|
||||
options.forEach((opt) => {
|
||||
const trialSelection = { ...curSelection.value, [categoryName]: opt.label }
|
||||
const match = commodityData.value[buildSignature(categoryOrder.value, trialSelection)]
|
||||
opt.disabled = !match || (match.num ?? 0) <= 0
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleGetSkuList = (list: SkuType[]) => {
|
||||
const result: Record<string, SkuOption[]> = {}
|
||||
const commodityMap: Record<string, { id: number; imageUrl?: string; salePrice?: number; price?: number; num: number }> = {}
|
||||
// 提取类目
|
||||
const order = list[0]?.vvSkuPropertyValueList?.map((vv) => vv.productPropertyName) || []
|
||||
categoryOrder.value = order
|
||||
let firstSelection: Record<string, string> = {}
|
||||
|
||||
list.forEach((sku, index) => {
|
||||
// 第一次默认选择
|
||||
if (index === 0) {
|
||||
firstSelection = Object.fromEntries(sku.vvSkuPropertyValueList.map((vv) => [vv.productPropertyName, vv.productPropertyValue]))
|
||||
}
|
||||
|
||||
// 提取 类目对应值
|
||||
const selection = Object.fromEntries(sku.vvSkuPropertyValueList.map((vv) => [vv.productPropertyName, vv.productPropertyValue]))
|
||||
|
||||
// 类目生成 唯一值 设置属性 一位数组
|
||||
const comboKey = buildSignature(order, selection)
|
||||
|
||||
commodityMap[comboKey] = {
|
||||
id: sku.id,
|
||||
imageUrl: sku.imageUrl,
|
||||
salePrice: sku.salePrice,
|
||||
price: sku.promotionPrice,
|
||||
num: sku.stock,
|
||||
}
|
||||
|
||||
// 生成展示的数组
|
||||
sku.vvSkuPropertyValueList.forEach((vv, idx) => {
|
||||
if (!result[vv.productPropertyName]) result[vv.productPropertyName] = []
|
||||
const bucket = result[vv.productPropertyName]
|
||||
const sid = buildOptionSid(vv)
|
||||
const existing = bucket.find((item) => item.sid === sid)
|
||||
const isLeafProperty = idx === order.length - 1
|
||||
if (existing) {
|
||||
// 非叶子类目需要展示该类目下所有 SKU 的累计库存;叶子类目保持当前 SKU 库存
|
||||
existing.num = isLeafProperty ? sku.stock : existing.num + sku.stock
|
||||
} else {
|
||||
bucket.push({
|
||||
sid,
|
||||
label: vv.productPropertyValue,
|
||||
num: sku.stock,
|
||||
disabled: isLeafProperty ? sku.stock <= 0 : false,
|
||||
})
|
||||
}
|
||||
})
|
||||
commodityMap[commodityPropertyId] = commodityValue
|
||||
})
|
||||
|
||||
return { result, commodityMap, firstShopIds }
|
||||
return { result, commodityMap, firstSelection }
|
||||
}
|
||||
|
||||
const onChooseProperty = (v, categoryName) => {
|
||||
curPropertyIds.value.find((it) => it.productPropertyName === categoryName).id = v.propertyId
|
||||
const { pageData, skuId } = handleGetPageData(commodityData.value, curPropertyIds.value)
|
||||
curPageData.value = pageData
|
||||
formData.value = { skuId, num: 1 }
|
||||
if (v.disabled) return
|
||||
|
||||
curSelection.value[categoryName] = v.label
|
||||
syncCurrentSku()
|
||||
updateOptionDisabled()
|
||||
}
|
||||
const handleGetPageData = (commodityData, curPropertyIds) => {
|
||||
const data = commodityData[curPropertyIds.map((item) => item.id).join('_')]
|
||||
return { pageData: { price: data?.price, imageUrl: data?.imageUrl, num: data?.num }, skuId: data?.id }
|
||||
|
||||
const syncCurrentSku = () => {
|
||||
const data = commodityData.value[buildSignature(categoryOrder.value, curSelection.value)]
|
||||
curPageData.value = { price: data?.price ?? 0, imageUrl: data?.imageUrl ?? '', num: data?.num ?? 0 }
|
||||
formData.value = { skuId: data?.id ?? NaN, num: 1 }
|
||||
}
|
||||
|
||||
const onSubmit = async () => {
|
||||
@ -125,15 +182,18 @@ const onSubmit = async () => {
|
||||
border-radius: 0.04rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cart-cagetory-wrap {
|
||||
h4 {
|
||||
font-weight: bold;
|
||||
margin-top: 0.16rem;
|
||||
margin-bottom: 0.12rem;
|
||||
}
|
||||
|
||||
.cagetory {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > p {
|
||||
border: 1px solid #f2f2f2;
|
||||
box-sizing: border-box;
|
||||
@ -146,14 +206,24 @@ const onSubmit = async () => {
|
||||
border-radius: 0.04rem;
|
||||
margin-right: 0.08rem;
|
||||
margin-bottom: 0.08rem;
|
||||
|
||||
&.theme-border-color {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background: #eee;
|
||||
color: #bbb;
|
||||
border-color: #eee;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.van-popup--bottom.van-popup--round {
|
||||
border-radius: 0.08rem 0.08rem 0 0;
|
||||
|
||||
:deep(.van-popup__close-icon) {
|
||||
top: 0.06rem;
|
||||
font-size: 0.2rem;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user