feat(商品属性): 多 sku
This commit is contained in:
parent
c188d92c11
commit
900936db56
|
@ -1,48 +1,72 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sku-item">
|
<div class="sku-item">
|
||||||
<uni-forms label-width="160" label-position="top">
|
<uni-forms label-width="176rpx" label-position="left">
|
||||||
<uni-forms-item label="商品封面图" name="picUrl">
|
|
||||||
<p-uploader
|
<template v-if="specType">
|
||||||
v-model:url="formData.picUrl"
|
<template v-for="item in formData.properties">
|
||||||
fileMediatype="image"
|
<uni-forms-item :label="item.propertyName">
|
||||||
limit="1"
|
<uni-easyinput type="text" :value="item.valueName" disabled />
|
||||||
mode="grid"
|
</uni-forms-item>
|
||||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
</template>
|
||||||
/>
|
</template>
|
||||||
</uni-forms-item>
|
|
||||||
<uni-forms-item label="商品条码" name="barCode">
|
<uni-forms-item label="商品封面图" name="picUrl" label-position="top">
|
||||||
<uni-easyinput type="text" trim="all" v-model="formData.barCode" placeholder="请输入商品条码" />
|
<p-uploader v-model:url="formData.picUrl" fileMediatype="image" limit="1" mode="grid"
|
||||||
</uni-forms-item>
|
:imageStyles="{ width: '168rpx', height: '168rpx' }" />
|
||||||
<uni-forms-item label="销售价" name="price">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.price" placeholder="请输入商品销售价" />
|
<uni-forms-item label="商品条码" name="barCode">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="text" trim="all" v-model="formData.barCode" placeholder="请输入商品条码" />
|
||||||
<uni-forms-item label="市场价" name="marketPrice">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.marketPrice" placeholder="请输入商品销售价" />
|
<uni-forms-item label="销售价" name="price">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="number" trim="all" v-model="formData.price" placeholder="请输入商品销售价" />
|
||||||
<uni-forms-item label="成本价" name="costPrice">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.costPrice" placeholder="请输入商品销售价" />
|
<uni-forms-item label="市场价" name="marketPrice">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="number" trim="all" v-model="formData.marketPrice" placeholder="请输入商品销售价" />
|
||||||
<uni-forms-item label="库存" name="stock">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.stock" placeholder="请输入商品库存" />
|
<uni-forms-item label="成本价" name="costPrice">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="number" trim="all" v-model="formData.costPrice" placeholder="请输入商品销售价" />
|
||||||
<uni-forms-item label="重量(kg)" name="weight">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.weight" placeholder="请输入商品重量" />
|
<uni-forms-item label="库存" name="stock">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="number" trim="all" v-model="formData.stock" placeholder="请输入商品库存" />
|
||||||
<uni-forms-item label="体积(m³)" name="volume">
|
</uni-forms-item>
|
||||||
<uni-easyinput type="number" trim="all" v-model="formData.volume" placeholder="请输入商品体积" />
|
<uni-forms-item label="重量(kg)" name="weight">
|
||||||
</uni-forms-item>
|
<uni-easyinput type="number" trim="all" v-model="formData.weight" placeholder="请输入商品重量" />
|
||||||
</uni-forms>
|
</uni-forms-item>
|
||||||
</div>
|
<uni-forms-item label="体积(m³)" name="volume">
|
||||||
|
<uni-easyinput type="number" trim="all" v-model="formData.volume" placeholder="请输入商品体积" />
|
||||||
|
</uni-forms-item>
|
||||||
|
</uni-forms>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref, watch, computed, defineProps } from 'vue'
|
||||||
|
import peach from '@/peach'
|
||||||
|
const props = defineProps({
|
||||||
|
skus: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
const formData = ref({})
|
const formData = ref({})
|
||||||
|
const specType = computed(() => peach.$store("trade").goodsInfo.specType);
|
||||||
|
|
||||||
|
watch(() => props.skus, (newVal) => {
|
||||||
|
console.log(newVal)
|
||||||
|
formData.value = newVal ?? {}
|
||||||
|
}, { immediate: true })
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.sku-item {
|
.sku-item {
|
||||||
margin: 40rpx;
|
margin: 40rpx;
|
||||||
|
padding-top: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sku-item:first-child {
|
||||||
|
border-top: 1px solid var(--ui-BG-Main);
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<template>
|
||||||
|
<view class="mutiple-sku">
|
||||||
|
<template v-for="item in props.skus">
|
||||||
|
<sku-item :skus="item">
|
||||||
|
|
||||||
|
</sku-item>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import SkuItem from './item'
|
||||||
|
import { defineProps } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
skus: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
|
@ -6,6 +6,9 @@ import { SPEC_TYPE } from "./config";
|
||||||
|
|
||||||
const pickerRef = ref(null);
|
const pickerRef = ref(null);
|
||||||
|
|
||||||
|
// 多属性商品 sku 列表
|
||||||
|
const skus = ref([]);
|
||||||
|
|
||||||
const propertyList = ref([]);
|
const propertyList = ref([]);
|
||||||
|
|
||||||
const goodsPropertyList = ref([]);
|
const goodsPropertyList = ref([]);
|
||||||
|
@ -29,22 +32,23 @@ function onRDPickerConfirm(e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pickerProperty() {
|
function pickerProperty() {
|
||||||
let index = specType ? 1 : 0;
|
let index = specType.value ? 1 : 0;
|
||||||
pickerRef.value.onOpen([index]);
|
pickerRef.value.onOpen([index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPropertyConfirm(e) {
|
async function onPropertyConfirm(e) {
|
||||||
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.value = [];
|
|
||||||
|
|
||||||
// 把 propertyList 中 id 相同的属性合并,并去重
|
// 把 propertyList 中 id 相同的属性合并,并去重
|
||||||
propertyList.value = peach.$store("trade").selectedProperty;
|
propertyList.value = peach.$store("trade").selectedProperty;
|
||||||
|
|
||||||
|
console.log(propertyList.value);
|
||||||
|
|
||||||
// 根据已经选择数据,设置默认选中
|
// 根据已经选择数据,设置默认选中
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
// 判断属性是否已经选中
|
// 判断属性是否已经选中
|
||||||
|
@ -58,7 +62,7 @@ async function getGoodsProperty() {
|
||||||
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?.id === child.id
|
(schild) => schild === child.id
|
||||||
);
|
);
|
||||||
console.log(childResult);
|
console.log(childResult);
|
||||||
child.checked = childResult ? true : false;
|
child.checked = childResult ? true : false;
|
||||||
|
@ -69,18 +73,22 @@ async function getGoodsProperty() {
|
||||||
goodsPropertyList.value = data;
|
goodsPropertyList.value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const specType = computed(() => peach.$store("trade").specType);
|
const specType = computed(() => peach.$store("trade").goodsInfo.specType);
|
||||||
|
|
||||||
function initial() {
|
function initial() {
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
formData.value.specType = specType ? true : false;
|
formData.value.specType = specType.value ? true : false;
|
||||||
formData.value.specText = SPEC_TYPE[specType ? 1 : 0].label;
|
formData.value.specText = SPEC_TYPE[specType.value ? 1 : 0].label;
|
||||||
getGoodsProperty();
|
skus.value = peach.$store("trade").skus;
|
||||||
|
if (specType.value) {
|
||||||
|
getGoodsProperty();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
initial,
|
initial,
|
||||||
|
skus,
|
||||||
pickerRef,
|
pickerRef,
|
||||||
pickerProperty,
|
pickerProperty,
|
||||||
propertyListRef,
|
propertyListRef,
|
||||||
|
|
|
@ -245,6 +245,7 @@ function clickSetProperty() {
|
||||||
peach.$store('trade').$patch({
|
peach.$store('trade').$patch({
|
||||||
selectedProperty: result,
|
selectedProperty: result,
|
||||||
goodsInfo: formData.value,
|
goodsInfo: formData.value,
|
||||||
|
skus: formData.value.skus
|
||||||
})
|
})
|
||||||
peach.$router.go('/pages/product/sku')
|
peach.$router.go('/pages/product/sku')
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +1,60 @@
|
||||||
<template>
|
<template>
|
||||||
<pb-layout
|
<pb-layout class="goods-property" title="商品属性" leftIcon="leftIcon" navbar="normal" :bgStyle="bgStyle"
|
||||||
class="goods-property"
|
opacityBgUi="bg-white" color="black">
|
||||||
title="商品属性"
|
<view class="property">
|
||||||
leftIcon="leftIcon"
|
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
|
||||||
navbar="normal"
|
<uni-forms-item label="商品规格" @tap="pickerProperty" name="specType" label-position="left" required>
|
||||||
:bgStyle="bgStyle"
|
<uni-easyinput type="text" :clearable="false" :styles="selfStyles" placeholderStyle="color:#8a8a8a"
|
||||||
opacityBgUi="bg-white"
|
:inputBorder="false" v-model="formData.specText" placeholder="请选择商品规格" disabled>
|
||||||
color="black"
|
<template v-slot:right>
|
||||||
>
|
<uni-icons type="right" />
|
||||||
<view class="property">
|
</template>
|
||||||
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
|
</uni-easyinput>
|
||||||
<uni-forms-item label="商品规格" @tap="pickerProperty" name="specType" label-position="left" required>
|
</uni-forms-item>
|
||||||
<uni-easyinput
|
</uni-forms>
|
||||||
type="text"
|
</view>
|
||||||
:clearable="false"
|
<template v-if="formData.specType">
|
||||||
:styles="selfStyles"
|
<button class="ss-reset-button add-property" @tap="showPropertyList">+添加规格</button>
|
||||||
placeholderStyle="color:#8a8a8a"
|
<property-detail v-if="propertyList.length > 0" v-model="propertyList"
|
||||||
:inputBorder="false"
|
:goodsPropertyList="goodsPropertyList"></property-detail>
|
||||||
v-model="formData.specText"
|
<mutiple-sku :skus="skus"></mutiple-sku>
|
||||||
placeholder="请选择商品规格"
|
</template>
|
||||||
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"
|
|
||||||
></property-detail>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<SkuItem />
|
<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
|
<PropertyList ref="propertyListRef" v-model="propertyList" :goodsPropertyList="goodsPropertyList"
|
||||||
ref="propertyListRef"
|
@confirm="onPropertyConfirm" />
|
||||||
v-model="propertyList"
|
</pb-layout>
|
||||||
:goodsPropertyList="goodsPropertyList"
|
|
||||||
@confirm="onPropertyConfirm"
|
|
||||||
/>
|
|
||||||
</pb-layout>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import SkuItem from './components/item'
|
import SkuItem from './components/item'
|
||||||
|
import MutipleSku from './components/mutipleSku'
|
||||||
import PropertyList from './components/propertyList'
|
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
|
||||||
} from './js/sku'
|
} from './js/sku'
|
||||||
|
|
||||||
const bgStyle = {
|
const bgStyle = {
|
||||||
backgroundImage: '',
|
backgroundImage: '',
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
description: '',
|
description: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
initial()
|
initial()
|
||||||
|
@ -81,49 +62,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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.add-property {
|
uni-icons {
|
||||||
margin: 40rpx;
|
margin-right: 10px;
|
||||||
border: 1px dotted var(--ui-BG-Main);
|
}
|
||||||
color: var(--ui-BG-Main);
|
|
||||||
border-radius: 10px;
|
.uni-easyinput__content {
|
||||||
text-align: center;
|
border-radius: 0 10px 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-disabled {
|
||||||
|
color: #333333;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-property {
|
||||||
|
margin: 40rpx;
|
||||||
|
border: 1px dotted var(--ui-BG-Main);
|
||||||
|
color: var(--ui-BG-Main);
|
||||||
|
border-radius: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
import { ref } from 'vue'
|
import { ref } from "vue";
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
const useTradeStore = defineStore('trade', () => {
|
const useTradeStore = defineStore("trade", () => {
|
||||||
// 已选择规格类型
|
// 已选择规格类型
|
||||||
const selectedProperty = ref(null)
|
const selectedProperty = ref(null);
|
||||||
|
|
||||||
// 商品信息
|
// 商品信息
|
||||||
const goodsInfo = ref(null)
|
const goodsInfo = ref(null);
|
||||||
|
|
||||||
return {
|
// 商品属性
|
||||||
selectedProperty,
|
const skus = ref(null);
|
||||||
goodsInfo,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default useTradeStore
|
return {
|
||||||
|
selectedProperty,
|
||||||
|
goodsInfo,
|
||||||
|
skus,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export default useTradeStore;
|
||||||
|
|
BIN
static/point.png
BIN
static/point.png
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
Before Width: | Height: | Size: 7.5 KiB |
Loading…
Reference in New Issue