feat(商品属性)
This commit is contained in:
parent
50e03907e7
commit
c188d92c11
|
@ -1,78 +1,77 @@
|
||||||
<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
|
<view v-for="sitem in item.propertyValues" @tap="chooseProperty(item)"
|
||||||
v-for="sitem in item.propertyValues"
|
:class="['item', sitem.checked ? 'active' : '']">{{ sitem.name }}</view>
|
||||||
@tap="chooseProperty(item)"
|
</view>
|
||||||
:class="['item', item.checked ? 'active' : '']"
|
</view>
|
||||||
>{{ sitem.name }}</view
|
</view>
|
||||||
>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, ref, computed } from 'vue'
|
import { defineProps, ref, computed } from 'vue'
|
||||||
|
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: () => [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function chooseProperty(item) {
|
function chooseProperty(item) {
|
||||||
item.checked = !item.checked
|
item.checked = !item.checked
|
||||||
}
|
}
|
||||||
</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 {
|
|
||||||
color: #fff;
|
|
||||||
background-color: var(--ui-BG-Main);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
|
color: #fff;
|
||||||
|
background-color: var(--ui-BG-Main);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,122 +1,129 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="property-list">
|
<view class="property-list">
|
||||||
<uni-popup type="bottom" ref="propertyListPopupRef" background-color="#fff">
|
<uni-popup type="bottom" ref="propertyListPopupRef" background-color="#fff">
|
||||||
<view class="popup-header">
|
<view class="popup-header">
|
||||||
<view class="button-cancel" @click="onClosePopup">取消</view>
|
<view class="button-cancel" @click="onClosePopup">取消</view>
|
||||||
<view class="button-link" @click="onConfirmPopup">确定</view>
|
<view class="button-link" @click="onConfirmPopup">确定</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="popup-content">
|
<view class="popup-content">
|
||||||
<view
|
<view v-for="item in nowGoodsPropertyList" :key="item.id"
|
||||||
v-for="item in goodsPropertyList"
|
:class="['property-item', item.checked ? 'active' : '']" @tap="chooseProperty(item)">
|
||||||
:key="item.id"
|
{{ item.name }}
|
||||||
:class="['property-item', item.checked ? 'active' : '']"
|
</view>
|
||||||
@tap="chooseProperty(item)"
|
</view>
|
||||||
>
|
</uni-popup>
|
||||||
{{ item.name }}
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, defineEmits, defineProps, defineExpose } from 'vue'
|
import { ref, computed, defineEmits, defineProps, defineExpose } from 'vue'
|
||||||
import peach from '@/peach'
|
import peach from '@/peach'
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* todo 底部高度配置
|
* todo 底部高度配置
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
default: () => [],
|
default: () => [],
|
||||||
required: true,
|
required: true,
|
||||||
type: Array,
|
type: Array,
|
||||||
},
|
},
|
||||||
goodsPropertyList: {
|
goodsPropertyList: {
|
||||||
default: () => [],
|
default: () => [],
|
||||||
required: true,
|
required: true,
|
||||||
type: Array,
|
type: Array,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const nowGoodsPropertyList = ref([])
|
||||||
|
|
||||||
|
const emit = defineEmits(['update:modelValue', 'confirm'])
|
||||||
|
|
||||||
const propertyListPopupRef = ref()
|
const propertyListPopupRef = ref()
|
||||||
|
|
||||||
const onClosePopup = () => {
|
const onClosePopup = () => {
|
||||||
propertyListPopupRef.value.close()
|
propertyListPopupRef.value.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
function chooseProperty(item) {
|
function chooseProperty(item) {
|
||||||
item.checked = !item.checked
|
item.checked = !item.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
function onConfirmPopup() {
|
function onConfirmPopup() {
|
||||||
let resut = props.goodsPropertyList
|
|
||||||
.filter((item) => {
|
|
||||||
if (item.checked) {
|
|
||||||
return item.propertyValues.filter((sitem) => sitem.checked)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map((item) => {
|
|
||||||
let children = item.propertyValues.filter((sitem) => sitem.checked).map((titem) => titem.id)
|
|
||||||
return {
|
|
||||||
id: item.id,
|
|
||||||
children: children,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log(resut)
|
let result = nowGoodsPropertyList.value
|
||||||
// emit('update:modelValue', props.goodsPropertyList.filter((item) => item.checked).map((item) => item.id) ?? [])
|
.filter((item) => {
|
||||||
onClosePopup()
|
if (item.checked) {
|
||||||
|
return item.propertyValues.filter((sitem) => sitem.checked)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map((item) => {
|
||||||
|
let children = item.propertyValues.filter((sitem) => sitem.checked).map((titem) => titem.id)
|
||||||
|
return {
|
||||||
|
id: item.id,
|
||||||
|
children: children,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
peach.$store('trade').selectedProperty = result
|
||||||
|
emit('confirm')
|
||||||
|
emit('update:modelValue', result)
|
||||||
|
onClosePopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onOpen() {
|
function onOpen() {
|
||||||
propertyListPopupRef.value.open('bottom')
|
nowGoodsPropertyList.value = cloneDeep(props.goodsPropertyList)
|
||||||
|
propertyListPopupRef.value.open('bottom')
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
onOpen,
|
onOpen,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.property-list {
|
.property-list {
|
||||||
.popup-content {
|
.popup-content {
|
||||||
height: 500rpx;
|
height: 500rpx;
|
||||||
padding: 40rpx;
|
padding: 40rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 20rpx;
|
gap: 20rpx;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
.property-item {
|
|
||||||
text-align: center;
|
.property-item {
|
||||||
line-height: 60rpx;
|
text-align: center;
|
||||||
height: 60rpx;
|
line-height: 60rpx;
|
||||||
padding: 0 10px;
|
height: 60rpx;
|
||||||
border-radius: 10px;
|
padding: 0 10px;
|
||||||
background-color: var(--ui-BG-4);
|
border-radius: 10px;
|
||||||
}
|
background-color: var(--ui-BG-4);
|
||||||
.active {
|
|
||||||
color: #fff;
|
|
||||||
background-color: var(--ui-BG-Main);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-link {
|
.active {
|
||||||
color: #1892ea;
|
color: #fff;
|
||||||
font-size: 28rpx;
|
background-color: var(--ui-BG-Main);
|
||||||
}
|
|
||||||
.button-cancel {
|
|
||||||
color: #888;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
|
||||||
.popup-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 24rpx 38rpx 0;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-link {
|
||||||
|
color: #1892ea;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-cancel {
|
||||||
|
color: #888;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 24rpx 38rpx 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,89 +1,93 @@
|
||||||
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);
|
||||||
|
|
||||||
const propertyList = ref([
|
const propertyList = ref([]);
|
||||||
{
|
|
||||||
id: 36,
|
|
||||||
children: [68],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 37,
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
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 ? 1 : 0
|
let index = specType ? 1 : 0;
|
||||||
pickerRef.value.onOpen([index])
|
pickerRef.value.onOpen([index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPropertyConfirm(e) {
|
function onPropertyConfirm(e) {
|
||||||
console.log(e)
|
getGoodsProperty();
|
||||||
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getGoodsProperty() {
|
async function getGoodsProperty() {
|
||||||
let { data } = await GoodsApi.getHistoryProperty()
|
let { data } = await GoodsApi.getHistoryProperty();
|
||||||
// 根据已经选择数据,设置默认选中
|
propertyList.value = [];
|
||||||
data.forEach((item) => {
|
|
||||||
// 判断属性是否已经选中
|
|
||||||
let propertyParent = propertyList.value.find((sitem) => sitem?.id === item.id)
|
|
||||||
|
|
||||||
item.checked = propertyParent ? true : false
|
// 把 propertyList 中 id 相同的属性合并,并去重
|
||||||
|
propertyList.value = peach.$store("trade").selectedProperty;
|
||||||
|
|
||||||
// 如果属性已经选中,查询子类中是否有选中
|
// 根据已经选择数据,设置默认选中
|
||||||
if (item.checked) {
|
data.forEach((item) => {
|
||||||
item.propertyValues.forEach((child) => {
|
// 判断属性是否已经选中
|
||||||
let childResult = propertyParent?.children.some((schild) => schild?.id === child.id)
|
let propertyParent = propertyList.value.find(
|
||||||
child.checked = childResult ? true : false
|
(sitem) => sitem?.id === item.id
|
||||||
})
|
);
|
||||||
}
|
|
||||||
})
|
item.checked = propertyParent ? true : false;
|
||||||
goodsPropertyList.value = data
|
|
||||||
|
// 如果属性已经选中,查询子类中是否有选中
|
||||||
|
if (item.checked) {
|
||||||
|
item.propertyValues.forEach((child) => {
|
||||||
|
let childResult = propertyParent?.children.some(
|
||||||
|
(schild) => schild?.id === child.id
|
||||||
|
);
|
||||||
|
console.log(childResult);
|
||||||
|
child.checked = childResult ? true : false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
goodsPropertyList.value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const specType = computed(() => peach.$store('trade').specType)
|
const specType = computed(() => peach.$store("trade").specType);
|
||||||
|
|
||||||
function initial() {
|
function initial() {
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
formData.value.specType = specType ? true : false
|
formData.value.specType = specType ? true : false;
|
||||||
formData.value.specText = SPEC_TYPE[specType ? 1 : 0].label
|
formData.value.specText = SPEC_TYPE[specType ? 1 : 0].label;
|
||||||
})
|
getGoodsProperty();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
initial,
|
initial,
|
||||||
pickerRef,
|
pickerRef,
|
||||||
pickerProperty,
|
pickerProperty,
|
||||||
propertyListRef,
|
propertyListRef,
|
||||||
formData,
|
formData,
|
||||||
onRDPickerConfirm,
|
onRDPickerConfirm,
|
||||||
onPropertyConfirm,
|
onPropertyConfirm,
|
||||||
propertyList,
|
propertyList,
|
||||||
showPropertyList,
|
showPropertyList,
|
||||||
goodsPropertyList,
|
goodsPropertyList,
|
||||||
}
|
};
|
||||||
|
|
|
@ -1,129 +1,61 @@
|
||||||
<template>
|
<template>
|
||||||
<pb-layout
|
<pb-layout class="manage-goods" title="发布商品" leftIcon="leftIcon" navbar="normal" :bgStyle="bgStyle"
|
||||||
class="manage-goods"
|
opacityBgUi="bg-white" color="black">
|
||||||
title="发布商品"
|
<view class="goods-form">
|
||||||
leftIcon="leftIcon"
|
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
|
||||||
navbar="normal"
|
<uni-forms-item label="商品封面图" name="picUrl" required>
|
||||||
:bgStyle="bgStyle"
|
<p-uploader v-model:url="formData.picUrl" fileMediatype="image" limit="1" mode="grid"
|
||||||
opacityBgUi="bg-white"
|
:imageStyles="{ width: '168rpx', height: '168rpx' }" />
|
||||||
color="black"
|
</uni-forms-item>
|
||||||
>
|
<uni-forms-item label="商品轮播图" name="sliderPicUrls" required>
|
||||||
<view class="goods-form">
|
<p-uploader v-model:url="formData.sliderPicUrls" fileMediatype="image" limit="6" mode="grid"
|
||||||
<uni-forms ref="formRef" v-model="formData" :rules="rules" label-position="top" label-width="160">
|
:imageStyles="{ width: '168rpx', height: '168rpx' }" />
|
||||||
<uni-forms-item label="商品封面图" name="picUrl" required>
|
</uni-forms-item>
|
||||||
<p-uploader
|
<uni-forms-item label="商品名称" name="name" required>
|
||||||
v-model:url="formData.picUrl"
|
<uni-easyinput type="text" trim="all" v-model="formData.name" placeholder="请输入商品名称" />
|
||||||
fileMediatype="image"
|
</uni-forms-item>
|
||||||
limit="1"
|
<uni-forms-item label="商品分类" @tap="openPicker('category', 'multiple')" name="categoryId" label-position="left"
|
||||||
mode="grid"
|
required>
|
||||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
<uni-easyinput type="text" v-model="formData.categoryText" :styles="selfStyles"
|
||||||
/>
|
placeholderStyle="color:#8a8a8a" :clearable="false" :inputBorder="false" placeholder="请选择商品分类" disabled>
|
||||||
</uni-forms-item>
|
<template v-slot:right>
|
||||||
<uni-forms-item label="商品轮播图" name="sliderPicUrls" required>
|
<uni-icons type="right" />
|
||||||
<p-uploader
|
</template>
|
||||||
v-model:url="formData.sliderPicUrls"
|
</uni-easyinput>
|
||||||
fileMediatype="image"
|
</uni-forms-item>
|
||||||
limit="6"
|
<uni-forms-item label="商品品牌" name="brandId" label-position="left" required @tap="openPicker('brand', 'single')">
|
||||||
mode="grid"
|
<uni-easyinput type="text" v-model="formData.brandText" :styles="selfStyles" placeholderStyle="color:#8a8a8a"
|
||||||
:imageStyles="{ width: '168rpx', height: '168rpx' }"
|
:clearable="false" :inputBorder="false" placeholder="请选择商品品牌" disabled>
|
||||||
/>
|
<template v-slot:right>
|
||||||
</uni-forms-item>
|
<uni-icons type="right" />
|
||||||
<uni-forms-item label="商品名称" name="name" required>
|
</template>
|
||||||
<uni-easyinput type="text" trim="all" v-model="formData.name" placeholder="请输入商品名称" />
|
</uni-easyinput>
|
||||||
</uni-forms-item>
|
</uni-forms-item>
|
||||||
<uni-forms-item
|
<uni-forms-item label="商品规格" name="skus" required label-position="left">
|
||||||
label="商品分类"
|
<view class="btn-group">
|
||||||
@tap="openPicker('category', 'multiple')"
|
<button class="ss-reset-button ss-set-property" @tap="clickSetProperty">规格设置</button>
|
||||||
name="categoryId"
|
</view>
|
||||||
label-position="left"
|
</uni-forms-item>
|
||||||
required
|
<uni-forms-item label="商品关键词" name="keyword" required>
|
||||||
>
|
<uni-easyinput type="text" v-model="formData.keyword" placeholder="请输入商品关键词" />
|
||||||
<uni-easyinput
|
</uni-forms-item>
|
||||||
type="text"
|
<uni-forms-item label="商品简介" name="introduction" required>
|
||||||
v-model="formData.categoryText"
|
<uni-easyinput type="textarea" trim="all" autoHeight v-model="formData.introduction" placeholder="请输入商品简介" />
|
||||||
:styles="selfStyles"
|
</uni-forms-item>
|
||||||
placeholderStyle="color:#8a8a8a"
|
<uni-forms-item label="物流设置" @tap="openPicker('delivery', 'single')" name="deliveryTypes" label-position="left"
|
||||||
:clearable="false"
|
required>
|
||||||
:inputBorder="false"
|
<uni-easyinput type="text" :clearable="false" :styles="selfStyles" placeholderStyle="color:#8a8a8a"
|
||||||
placeholder="请选择商品分类"
|
:inputBorder="false" v-model="formData.deliveryText" placeholder="请选择配送方式" disabled>
|
||||||
disabled
|
<template v-slot:right>
|
||||||
>
|
<uni-icons type="right" />
|
||||||
<template v-slot:right>
|
</template>
|
||||||
<uni-icons type="right" />
|
</uni-easyinput>
|
||||||
</template>
|
</uni-forms-item>
|
||||||
</uni-easyinput>
|
</uni-forms>
|
||||||
</uni-forms-item>
|
</view>
|
||||||
<uni-forms-item
|
|
||||||
label="商品品牌"
|
|
||||||
name="brandId"
|
|
||||||
label-position="left"
|
|
||||||
required
|
|
||||||
@tap="openPicker('brand', 'single')"
|
|
||||||
>
|
|
||||||
<uni-easyinput
|
|
||||||
type="text"
|
|
||||||
v-model="formData.brandText"
|
|
||||||
:styles="selfStyles"
|
|
||||||
placeholderStyle="color:#8a8a8a"
|
|
||||||
:clearable="false"
|
|
||||||
:inputBorder="false"
|
|
||||||
placeholder="请选择商品品牌"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
<template v-slot:right>
|
|
||||||
<uni-icons type="right" />
|
|
||||||
</template>
|
|
||||||
</uni-easyinput>
|
|
||||||
</uni-forms-item>
|
|
||||||
<uni-forms-item label="商品规格" name="skus" required label-position="left">
|
|
||||||
<view class="btn-group">
|
|
||||||
<button class="ss-reset-button ss-set-property" @tap="clickSetProperty">规格设置</button>
|
|
||||||
</view>
|
|
||||||
</uni-forms-item>
|
|
||||||
<uni-forms-item label="商品关键词" name="keyword" required>
|
|
||||||
<uni-easyinput type="text" v-model="formData.keyword" placeholder="请输入商品关键词" />
|
|
||||||
</uni-forms-item>
|
|
||||||
<uni-forms-item label="商品简介" name="introduction" required>
|
|
||||||
<uni-easyinput
|
|
||||||
type="textarea"
|
|
||||||
trim="all"
|
|
||||||
autoHeight
|
|
||||||
v-model="formData.introduction"
|
|
||||||
placeholder="请输入商品简介"
|
|
||||||
/>
|
|
||||||
</uni-forms-item>
|
|
||||||
<uni-forms-item
|
|
||||||
label="物流设置"
|
|
||||||
@tap="openPicker('delivery', 'single')"
|
|
||||||
name="deliveryTypes"
|
|
||||||
label-position="left"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<uni-easyinput
|
|
||||||
type="text"
|
|
||||||
:clearable="false"
|
|
||||||
:styles="selfStyles"
|
|
||||||
placeholderStyle="color:#8a8a8a"
|
|
||||||
:inputBorder="false"
|
|
||||||
v-model="formData.deliveryText"
|
|
||||||
placeholder="请选择配送方式"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
<template v-slot:right>
|
|
||||||
<uni-icons type="right" />
|
|
||||||
</template>
|
|
||||||
</uni-easyinput>
|
|
||||||
</uni-forms-item>
|
|
||||||
</uni-forms>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<p-picker
|
<p-picker ref="pickerRef" :mode="pickerMode" :options-cols="optionsCols" @confirm="onRDPickerConfirm"></p-picker>
|
||||||
ref="pickerRef"
|
</pb-layout>
|
||||||
:mode="pickerMode"
|
|
||||||
:options-cols="optionsCols"
|
|
||||||
@confirm="onRDPickerConfirm"
|
|
||||||
></p-picker>
|
|
||||||
</pb-layout>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -135,117 +67,117 @@ import GoodsApi from '@/peach/api/trade/goods'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
const bgStyle = {
|
const bgStyle = {
|
||||||
backgroundImage: '',
|
backgroundImage: '',
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
description: '',
|
description: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
const DELIVERY_TYPES = [
|
const DELIVERY_TYPES = [
|
||||||
{
|
{
|
||||||
value: 3,
|
value: 3,
|
||||||
label: '到店核销',
|
label: '到店核销',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 4,
|
value: 4,
|
||||||
label: '商家配送',
|
label: '商家配送',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const selfStyles = {
|
const selfStyles = {
|
||||||
backgroundColor: '#f9f9f9',
|
backgroundColor: '#f9f9f9',
|
||||||
}
|
}
|
||||||
|
|
||||||
const pickerRef = ref()
|
const pickerRef = ref()
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
picUrl: 'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
picUrl: 'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
||||||
sliderPicUrls: [
|
sliderPicUrls: [
|
||||||
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
||||||
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
||||||
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
'http://101.43.181.163:9001/mall-backend/8f11e372520501531d06bfce15ea97bbecead41c5e4a36d15d7e40af85729ff3.png',
|
||||||
],
|
],
|
||||||
name: '测试商品',
|
name: '测试商品',
|
||||||
categoryId: [],
|
categoryId: [],
|
||||||
categoryText: '',
|
categoryText: '',
|
||||||
brandId: '',
|
brandId: '',
|
||||||
keyword: '香酥鸭,但家',
|
keyword: '香酥鸭,但家',
|
||||||
deliveryTypes: [],
|
deliveryTypes: [],
|
||||||
deliveryText: '',
|
deliveryText: '',
|
||||||
introduction: '但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭',
|
introduction: '但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭但家贵阳香酥鸭现榨香酥鸭无任何添加剂香酥鸭',
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
name: {
|
name: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请输入商品名称',
|
errorMessage: '请输入商品名称',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
picUrl: {
|
picUrl: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请上传商品封面图',
|
errorMessage: '请上传商品封面图',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
sliderPicUrls: {
|
sliderPicUrls: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请上传商品轮播图',
|
errorMessage: '请上传商品轮播图',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
categoryId: {
|
categoryId: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请选择商品分类',
|
errorMessage: '请选择商品分类',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
brandId: {
|
brandId: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请选择商品品牌',
|
errorMessage: '请选择商品品牌',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
skus: {
|
skus: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请选择商品规格',
|
errorMessage: '请选择商品规格',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
keyword: {
|
keyword: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请输入商品关键字',
|
errorMessage: '请输入商品关键字',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
introduction: {
|
introduction: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请输入商品简介',
|
errorMessage: '请输入商品简介',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
deliveryTypes: {
|
deliveryTypes: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
errorMessage: '请选择商品物流',
|
errorMessage: '请选择商品物流',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRef = ref(null)
|
const formRef = ref(null)
|
||||||
|
@ -256,175 +188,197 @@ const brandList = ref([])
|
||||||
const optionsCols = ref([])
|
const optionsCols = ref([])
|
||||||
|
|
||||||
function openPicker(mark, mode) {
|
function openPicker(mark, mode) {
|
||||||
pickerMode.value = mode
|
pickerMode.value = mode
|
||||||
popMark.value = mark
|
popMark.value = mark
|
||||||
if (mark === 'delivery') {
|
if (mark === 'delivery') {
|
||||||
optionsCols.value = DELIVERY_TYPES
|
optionsCols.value = DELIVERY_TYPES
|
||||||
pickerRef.value.onOpen([0])
|
pickerRef.value.onOpen([0])
|
||||||
} else if (mark === 'category') {
|
} else if (mark === 'category') {
|
||||||
optionsCols.value = categoryList.value
|
optionsCols.value = categoryList.value
|
||||||
pickerRef.value.onOpen([0, 0])
|
pickerRef.value.onOpen([0, 0])
|
||||||
} else if (mark === 'brand') {
|
} else if (mark === 'brand') {
|
||||||
optionsCols.value = brandList.value
|
optionsCols.value = brandList.value
|
||||||
pickerRef.value.onOpen([0])
|
pickerRef.value.onOpen([0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRDPickerConfirm(e) {
|
function onRDPickerConfirm(e) {
|
||||||
if (popMark.value === 'delivery') {
|
if (popMark.value === 'delivery') {
|
||||||
formData.value.deliveryTypes = []
|
formData.value.deliveryTypes = []
|
||||||
formData.value.deliveryText = DELIVERY_TYPES[e.value[0]].label
|
formData.value.deliveryText = DELIVERY_TYPES[e.value[0]].label
|
||||||
formData.value.deliveryTypes.push(DELIVERY_TYPES[e.value[0]].value)
|
formData.value.deliveryTypes.push(DELIVERY_TYPES[e.value[0]].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popMark.value === 'category') {
|
if (popMark.value === 'category') {
|
||||||
formData.value.categoryId = categoryList.value[e.value[0]].children[e.value[1]].id
|
formData.value.categoryId = categoryList.value[e.value[0]].children[e.value[1]].id
|
||||||
formData.value.categoryText =
|
formData.value.categoryText =
|
||||||
categoryList.value[e.value[0]].name + '/' + categoryList.value[e.value[0]].children[e.value[1]].name
|
categoryList.value[e.value[0]].name + '/' + categoryList.value[e.value[0]].children[e.value[1]].name
|
||||||
}
|
}
|
||||||
|
|
||||||
if (popMark.value === 'brand') {
|
if (popMark.value === 'brand') {
|
||||||
formData.value.brandId = brandList.value[e.value[0]].id
|
formData.value.brandId = brandList.value[e.value[0]].id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickSetProperty() {
|
function clickSetProperty() {
|
||||||
peach.$store('trade').$patch({
|
// 如果是多规格,处理格式问题,合并属性
|
||||||
selectedProperty: formData.value.skus,
|
let temp = formData.value.skus.map((item) => {
|
||||||
goodsInfo: formData.value,
|
return item.properties.map((sitem) => ({
|
||||||
})
|
id: sitem.propertyId,
|
||||||
peach.$router.go('/pages/product/sku')
|
children: [sitem.valueId],
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
.flat(1);
|
||||||
|
|
||||||
|
// 去除重复数据
|
||||||
|
let result = temp.reduce((pre, cur) => {
|
||||||
|
let index = pre.findIndex((item) => item.id === cur.id);
|
||||||
|
if (index !== -1) {
|
||||||
|
pre[index].children.push(...new Set(cur.children));
|
||||||
|
} else {
|
||||||
|
pre.push(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pre;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
peach.$store('trade').$patch({
|
||||||
|
selectedProperty: result,
|
||||||
|
goodsInfo: formData.value,
|
||||||
|
})
|
||||||
|
peach.$router.go('/pages/product/sku')
|
||||||
}
|
}
|
||||||
|
|
||||||
function getProduct(id) {
|
function getProduct(id) {
|
||||||
GoodsApi.getProduct({ id }).then((res) => {
|
GoodsApi.getProduct({ id }).then((res) => {
|
||||||
formData.value = res.data
|
formData.value = res.data
|
||||||
|
|
||||||
// 循环遍历 categoryList,从二级分类找出和 formData.value.categoryId 相等的
|
// 循环遍历 categoryList,从二级分类找出和 formData.value.categoryId 相等的
|
||||||
let tempCategory = categoryList.value.find((item) => {
|
let tempCategory = categoryList.value.find((item) => {
|
||||||
return item.children.find((child) => {
|
return item.children.find((child) => {
|
||||||
return child.id === formData.value.categoryId
|
return child.id === formData.value.categoryId
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
formData.value.categoryText =
|
|
||||||
tempCategory.name +
|
|
||||||
'/' +
|
|
||||||
tempCategory.children.find((item) => {
|
|
||||||
return item.id === formData.value.categoryId
|
|
||||||
}).name
|
|
||||||
|
|
||||||
// 循环遍历 brandList, 从一级分类找出和 formData.value.brandId 相等的
|
|
||||||
let tempBrand = brandList.value.find((item) => {
|
|
||||||
return item.id === formData.value.brandId
|
|
||||||
})
|
|
||||||
|
|
||||||
formData.value.brandText = tempBrand.name
|
|
||||||
|
|
||||||
// 从 DELIVERY_TYPES 找出和 formData.value.deliveryTypes 相等的
|
|
||||||
formData.value.deliveryText = DELIVERY_TYPES.find((item) => {
|
|
||||||
return item.value === formData.value.deliveryTypes[0]
|
|
||||||
}).label
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
formData.value.categoryText =
|
||||||
|
tempCategory.name +
|
||||||
|
'/' +
|
||||||
|
tempCategory.children.find((item) => {
|
||||||
|
return item.id === formData.value.categoryId
|
||||||
|
}).name
|
||||||
|
|
||||||
|
// 循环遍历 brandList, 从一级分类找出和 formData.value.brandId 相等的
|
||||||
|
let tempBrand = brandList.value.find((item) => {
|
||||||
|
return item.id === formData.value.brandId
|
||||||
|
})
|
||||||
|
|
||||||
|
formData.value.brandText = tempBrand.name
|
||||||
|
|
||||||
|
// 从 DELIVERY_TYPES 找出和 formData.value.deliveryTypes 相等的
|
||||||
|
formData.value.deliveryText = DELIVERY_TYPES.find((item) => {
|
||||||
|
return item.value === formData.value.deliveryTypes[0]
|
||||||
|
}).label
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
console.log('res', formData.value)
|
console.log('res', formData.value)
|
||||||
|
|
||||||
formRef.value
|
formRef.value
|
||||||
.validate()
|
.validate()
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
let tempObj = { ...res }
|
let tempObj = { ...res }
|
||||||
|
|
||||||
if (formData.value.id) {
|
if (formData.value.id) {
|
||||||
tempObj.id = formData.value.id
|
tempObj.id = formData.value.id
|
||||||
await GoodsApi.editProduct(tempObj)
|
await GoodsApi.editProduct(tempObj)
|
||||||
} else {
|
} else {
|
||||||
await GoodsApi.addProduct(tempObj)
|
await GoodsApi.addProduct(tempObj)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log('err', err)
|
console.log('err', err)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得商品分类
|
// 获得商品分类
|
||||||
async function getCategoryList() {
|
async function getCategoryList() {
|
||||||
let { data } = await GoodsApi.getGoodsCategory()
|
let { data } = await GoodsApi.getGoodsCategory()
|
||||||
categoryList.value = handleTree(data)
|
categoryList.value = handleTree(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得商品品牌
|
// 获得商品品牌
|
||||||
async function getBrandList() {
|
async function getBrandList() {
|
||||||
let { data } = await GoodsApi.getBrand()
|
let { data } = await GoodsApi.getBrand()
|
||||||
brandList.value = data
|
brandList.value = data
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
await getCategoryList()
|
await getCategoryList()
|
||||||
await getBrandList()
|
await getBrandList()
|
||||||
if (options.id) {
|
if (options.id) {
|
||||||
getProduct(options.id)
|
getProduct(options.id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.manage-goods {
|
.manage-goods {
|
||||||
.goods-form {
|
.goods-form {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.btn-group {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
border-radius: 0 10px 10px 0;
|
|
||||||
|
|
||||||
.ss-set-property {
|
uni-icons {
|
||||||
width: 80px;
|
margin-right: 10px;
|
||||||
height: 60rpx;
|
|
||||||
line-height: normal;
|
|
||||||
background: var(--ui-BG-Main);
|
|
||||||
border-radius: 28rpx;
|
|
||||||
font-size: 26rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.uni-easyinput__content {
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-disabled {
|
||||||
|
color: #333333;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
|
||||||
|
.ss-set-property {
|
||||||
|
width: 80px;
|
||||||
|
height: 60rpx;
|
||||||
|
line-height: normal;
|
||||||
|
background: var(--ui-BG-Main);
|
||||||
|
border-radius: 28rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue