feat(sku):sku 合并

This commit is contained in:
Ankkaya 2024-06-07 18:34:58 +08:00
parent 900936db56
commit b10f8458af
4 changed files with 294 additions and 201 deletions

View File

@ -1,77 +1,84 @@
<template> <template>
<view class="property-detail"> <view class="property-detail">
<template v-for="item in goodsPropertyList" :key="item.id"> <template v-for="item in goodsPropertyList" :key="item.id">
<view class="property-item ss-p-40 ss-gap-40" v-if="item.checked"> <view class="property-item ss-p-40 ss-gap-40" v-if="item.checked">
<view class="property-name ss-flex ss-gap-40 ss-m-b-20"> <view class="property-name ss-flex ss-gap-40 ss-m-b-20">
<view class="property-name-text">规格名</view> <view class="property-name-text">规格名</view>
<view class="property-name-value">{{ item.name }}</view> <view class="property-name-value">{{ item.name }}</view>
</view> </view>
<view class="property-value ss-flex ss-gap-40"> <view class="property-value ss-flex ss-gap-40">
<view class="property-value-text">规格值</view> <view class="property-value-text">规格值</view>
<view class="property-value-value ss-flex ss-gap-10"> <view class="property-value-value ss-flex ss-gap-10">
<view v-for="sitem in item.propertyValues" @tap="chooseProperty(item)" <view
:class="['item', sitem.checked ? 'active' : '']">{{ sitem.name }}</view> v-for="sitem in item.propertyValues"
</view> @tap="chooseProperty(sitem)"
</view> :class="['item', sitem.checked ? 'active' : '']"
</view> >{{ sitem.name }}</view
</template> >
</view> </view>
</view>
</view>
</template>
</view>
</template> </template>
<script setup> <script setup>
import { defineProps, ref, computed } from 'vue' import { defineProps, defineEmits, ref, computed } from 'vue'
import { goodsPropertyList } from '../js/sku'; import { goodsPropertyList } from '../js/sku'
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
goodsPropertyList: { goodsPropertyList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
}) })
const emit = defineEmits(['changeSubProperty'])
function chooseProperty(item) { function chooseProperty(item) {
item.checked = !item.checked item.checked = !item.checked
emit('changeSubProperty')
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.property-detail { .property-detail {
.property-item { .property-item {
margin: 0 40rpx 20rpx; margin: 0 40rpx 20rpx;
background-color: #f9f9f9; background-color: #f9f9f9;
border-radius: 10px; border-radius: 10px;
.property-name { .property-name {
.property-name-text { .property-name-text {
color: #606266; color: #606266;
} }
}
.property-value {
.property-value-text {
color: #606266;
}
.property-value-value {
.item {
text-align: center;
line-height: 60rpx;
height: 60rpx;
padding: 0 10px;
border-radius: 10px;
background-color: var(--ui-BG-4);
} }
.active { .property-value {
color: #fff; .property-value-text {
background-color: var(--ui-BG-Main); color: #606266;
}
.property-value-value {
.item {
text-align: center;
line-height: 60rpx;
height: 60rpx;
padding: 0 10px;
border-radius: 10px;
background-color: var(--ui-BG-4);
}
.active {
color: #fff;
background-color: var(--ui-BG-Main);
}
}
} }
}
} }
}
} }
</style> </style>

View File

@ -1,101 +1,163 @@
import { ref, computed } from "vue"; import { ref, computed } from 'vue'
import { onLoad } from "@dcloudio/uni-app"; import { onLoad } from '@dcloudio/uni-app'
import peach from "@/peach"; import peach from '@/peach'
import GoodsApi from "@/peach/api/trade/goods"; import GoodsApi from '@/peach/api/trade/goods'
import { SPEC_TYPE } from "./config"; import { SPEC_TYPE } from './config'
const pickerRef = ref(null); const pickerRef = ref(null)
// 多属性商品 sku 列表 // 多属性商品 sku 列表
const skus = ref([]); const skus = ref([])
const propertyList = ref([]); const propertyList = ref([])
const goodsPropertyList = ref([]); const goodsPropertyList = ref([])
const propertyListRef = ref(null); const propertyListRef = ref(null)
const formData = ref({ const formData = ref({
specType: true, specType: true,
specText: SPEC_TYPE[0].label, specText: SPEC_TYPE[0].label,
}); })
async function showPropertyList() { async function showPropertyList() {
await getGoodsProperty(); await getGoodsProperty()
propertyListRef.value.onOpen(); propertyListRef.value.onOpen()
} }
function onRDPickerConfirm(e) { function onRDPickerConfirm(e) {
peach.$store("trade").specType = SPEC_TYPE[e.value[0]].value; peach.$store('trade').specType = SPEC_TYPE[e.value[0]].value
formData.value.specText = SPEC_TYPE[e.value[0]].label; formData.value.specText = SPEC_TYPE[e.value[0]].label
formData.value.specType = SPEC_TYPE[e.value[0]].value; formData.value.specType = SPEC_TYPE[e.value[0]].value
} }
function pickerProperty() { function pickerProperty() {
let index = specType.value ? 1 : 0; let index = specType.value ? 1 : 0
pickerRef.value.onOpen([index]); pickerRef.value.onOpen([index])
} }
async function onPropertyConfirm(e) { async function onPropertyConfirm(e) {
await getGoodsProperty(); await getGoodsProperty()
console.log(e); console.log(e)
} }
async function getGoodsProperty() { async function getGoodsProperty() {
let { data } = await GoodsApi.getHistoryProperty(); let { data } = await GoodsApi.getHistoryProperty()
// 把 propertyList 中 id 相同的属性合并,并去重 // 把 propertyList 中 id 相同的属性合并,并去重
propertyList.value = peach.$store("trade").selectedProperty; propertyList.value = peach.$store('trade').selectedProperty
console.log(propertyList.value); console.log(propertyList.value)
// 根据已经选择数据,设置默认选中 // 根据已经选择数据,设置默认选中
data.forEach((item) => { data.forEach((item) => {
// 判断属性是否已经选中 // 判断属性是否已经选中
let propertyParent = propertyList.value.find( let propertyParent = propertyList.value.find((sitem) => sitem?.id === item.id)
(sitem) => sitem?.id === item.id
);
item.checked = propertyParent ? true : false; item.checked = propertyParent ? true : false
// 如果属性已经选中,查询子类中是否有选中 // 如果属性已经选中,查询子类中是否有选中
if (item.checked) { if (item.checked) {
item.propertyValues.forEach((child) => { item.propertyValues.forEach((child) => {
let childResult = propertyParent?.children.some( let childResult = propertyParent?.children.some((schild) => schild === child.id)
(schild) => schild === child.id child.checked = childResult ? true : false
); })
console.log(childResult); }
child.checked = childResult ? true : false; })
});
}
});
goodsPropertyList.value = data; goodsPropertyList.value = data
console.log(goodsPropertyList.value)
} }
const specType = computed(() => peach.$store("trade").goodsInfo.specType); function changeSubProperty() {
// 修改子属性状态,需要同步更新 skus 的显示
console.log(goodsPropertyList.value)
// 过滤父属性 checked 选项,深拷贝避免后面循环改变元数据内容
let temp = JSON.parse(JSON.stringify(goodsPropertyList.value.filter((item) => item.checked)))
temp.forEach((item) => {
item.propertyValues = item.propertyValues.filter((child) => child.checked)
})
let result = temp.map((item) => {
return item.propertyValues.map((child) => ({
propertyId: item.id,
propertyName: item.name,
valueId: child.id,
valueName: child.name,
}))
})
let tempSkus = []
for (let item of reduceArr(result)) {
let obj = {
picUrl: '',
barCode: '',
price: 0,
marketPrice: 0,
costPrice: 0,
stock: 0,
weight: 0,
volume: 0,
properties: item,
}
tempSkus.push(obj)
}
skus.value = tempSkus
}
function reduceArr(arr) {
return arr.reduce((acc, cur) => {
let tempAcc = []
if (acc.length < 1) {
cur.forEach((item, index) => {
if (tempAcc[index]) {
tempAcc[index].push(item)
} else {
tempAcc[index] = [item]
}
})
} else {
acc.forEach((item, index) => {
cur.forEach((sitem, sindex) => {
tempAcc.push([...item, sitem])
})
})
if (cur.length < 1) {
tempAcc = acc
}
}
return tempAcc
}, [])
}
const specType = computed(() => peach.$store('trade').goodsInfo.specType)
function initial() { function initial() {
onLoad(() => { onLoad(() => {
formData.value.specType = specType.value ? true : false; formData.value.specType = specType.value ? true : false
formData.value.specText = SPEC_TYPE[specType.value ? 1 : 0].label; formData.value.specText = SPEC_TYPE[specType.value ? 1 : 0].label
skus.value = peach.$store("trade").skus; skus.value = peach.$store('trade').skus
if (specType.value) { if (specType.value) {
getGoodsProperty(); getGoodsProperty()
} }
}); })
} }
export { export {
initial, initial,
skus, skus,
pickerRef, pickerRef,
pickerProperty, pickerProperty,
propertyListRef, propertyListRef,
formData, formData,
onRDPickerConfirm, onRDPickerConfirm,
onPropertyConfirm, onPropertyConfirm,
propertyList, propertyList,
showPropertyList, showPropertyList,
goodsPropertyList, goodsPropertyList,
}; changeSubProperty,
}

View File

@ -1,34 +1,57 @@
<template> <template>
<pb-layout class="goods-property" title="商品属性" leftIcon="leftIcon" navbar="normal" :bgStyle="bgStyle" <pb-layout
opacityBgUi="bg-white" color="black"> class="goods-property"
<view class="property"> title="商品属性"
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160"> leftIcon="leftIcon"
<uni-forms-item label="商品规格" @tap="pickerProperty" name="specType" label-position="left" required> navbar="normal"
<uni-easyinput type="text" :clearable="false" :styles="selfStyles" placeholderStyle="color:#8a8a8a" :bgStyle="bgStyle"
:inputBorder="false" v-model="formData.specText" placeholder="请选择商品规格" disabled> opacityBgUi="bg-white"
<template v-slot:right> color="black"
<uni-icons type="right" /> >
</template> <view class="property">
</uni-easyinput> <uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
</uni-forms-item> <uni-forms-item label="商品规格" @tap="pickerProperty" name="specType" label-position="left" required>
</uni-forms> <uni-easyinput
</view> type="text"
<template v-if="formData.specType"> :clearable="false"
<button class="ss-reset-button add-property" @tap="showPropertyList">+添加规格</button> :styles="selfStyles"
<property-detail v-if="propertyList.length > 0" v-model="propertyList" placeholderStyle="color:#8a8a8a"
:goodsPropertyList="goodsPropertyList"></property-detail> :inputBorder="false"
<mutiple-sku :skus="skus"></mutiple-sku> v-model="formData.specText"
</template> placeholder="请选择商品规格"
disabled
>
<template v-slot:right>
<uni-icons type="right" />
</template>
</uni-easyinput>
</uni-forms-item>
</uni-forms>
</view>
<template v-if="formData.specType">
<button class="ss-reset-button add-property" @tap="showPropertyList">+添加规格</button>
<property-detail
v-if="propertyList.length > 0"
v-model="propertyList"
:goodsPropertyList="goodsPropertyList"
@changeSubProperty="changeSubProperty"
></property-detail>
<mutiple-sku :skus="skus"></mutiple-sku>
</template>
<template v-else> <template v-else>
<SkuItem :skus="skus" /> <SkuItem :skus="skus" />
</template> </template>
<p-picker ref="pickerRef" mode="single" :options-cols="SPEC_TYPE" @confirm="onRDPickerConfirm"></p-picker> <p-picker ref="pickerRef" mode="single" :options-cols="SPEC_TYPE" @confirm="onRDPickerConfirm"></p-picker>
<PropertyList ref="propertyListRef" v-model="propertyList" :goodsPropertyList="goodsPropertyList" <PropertyList
@confirm="onPropertyConfirm" /> ref="propertyListRef"
</pb-layout> v-model="propertyList"
:goodsPropertyList="goodsPropertyList"
@confirm="onPropertyConfirm"
/>
</pb-layout>
</template> </template>
<script setup> <script setup>
@ -38,23 +61,24 @@ import PropertyList from './components/propertyList'
import PropertyDetail from './components/propertyDetail' import PropertyDetail from './components/propertyDetail'
import { SPEC_TYPE } from './js/config' import { SPEC_TYPE } from './js/config'
import { import {
initial, initial,
pickerRef, pickerRef,
propertyListRef, propertyListRef,
onRDPickerConfirm, onRDPickerConfirm,
formData, formData,
propertyList, propertyList,
onPropertyConfirm, onPropertyConfirm,
showPropertyList, showPropertyList,
goodsPropertyList, goodsPropertyList,
pickerProperty, pickerProperty,
skus skus,
changeSubProperty,
} from './js/sku' } from './js/sku'
const bgStyle = { const bgStyle = {
backgroundImage: '', backgroundImage: '',
backgroundColor: '#fff', backgroundColor: '#fff',
description: '', description: '',
} }
initial() initial()
@ -62,49 +86,49 @@ initial()
<style lang="scss" scoped> <style lang="scss" scoped>
.goods-property { .goods-property {
.property { .property {
margin: 40rpx; margin: 40rpx;
:deep() { :deep() {
.uni-easyinput__content-input { .uni-easyinput__content-input {
font-size: 28rpx !important; font-size: 28rpx !important;
color: #333333 !important; color: #333333 !important;
line-height: normal !important; line-height: normal !important;
} }
.uni-easyinput__placeholder-class { .uni-easyinput__placeholder-class {
font-size: 14px; font-size: 14px;
} }
.is-direction-left { .is-direction-left {
.uni-forms-item__label { .uni-forms-item__label {
padding-left: 10px; padding-left: 10px;
background-color: #f9f9f9; background-color: #f9f9f9;
border-radius: 10px 0 0 10px; border-radius: 10px 0 0 10px;
}
uni-icons {
margin-right: 10px;
}
.uni-easyinput__content {
border-radius: 0 10px 10px 0;
}
}
.is-disabled {
color: #333333;
text-align: right;
}
} }
uni-icons {
margin-right: 10px;
}
.uni-easyinput__content {
border-radius: 0 10px 10px 0;
}
}
.is-disabled {
color: #333333;
text-align: right;
}
} }
}
.add-property { .add-property {
margin: 40rpx; margin: 40rpx;
border: 1px dotted var(--ui-BG-Main); border: 1px dotted var(--ui-BG-Main);
color: var(--ui-BG-Main); color: var(--ui-BG-Main);
border-radius: 10px; border-radius: 10px;
text-align: center; text-align: center;
} }
} }
</style> </style>

BIN
static/upload-camera.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB