📖 MALL:商品编辑的简化
This commit is contained in:
parent
a5d6d18b6a
commit
f1c858b9af
@ -57,7 +57,6 @@
|
|||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"qs": "^6.11.2",
|
"qs": "^6.11.2",
|
||||||
"sortablejs": "^1.15.0",
|
|
||||||
"steady-xml": "^0.1.0",
|
"steady-xml": "^0.1.0",
|
||||||
"url": "^0.11.3",
|
"url": "^0.11.3",
|
||||||
"video.js": "^7.21.5",
|
"video.js": "^7.21.5",
|
||||||
@ -81,7 +80,6 @@
|
|||||||
"@types/nprogress": "^0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/qrcode": "^1.5.5",
|
"@types/qrcode": "^1.5.5",
|
||||||
"@types/qs": "^6.9.10",
|
"@types/qs": "^6.9.10",
|
||||||
"@types/sortablejs": "^1.15.5",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||||
"@typescript-eslint/parser": "^6.11.0",
|
"@typescript-eslint/parser": "^6.11.0",
|
||||||
"@unocss/transformer-variant-group": "^0.57.4",
|
"@unocss/transformer-variant-group": "^0.57.4",
|
||||||
|
@ -48,11 +48,6 @@ export interface Spu {
|
|||||||
sort?: number // 商品排序
|
sort?: number // 商品排序
|
||||||
giveIntegral?: number // 赠送积分
|
giveIntegral?: number // 赠送积分
|
||||||
virtualSalesCount?: number // 虚拟销量
|
virtualSalesCount?: number // 虚拟销量
|
||||||
recommendHot?: boolean // 是否热卖
|
|
||||||
recommendBenefit?: boolean // 是否优惠
|
|
||||||
recommendBest?: boolean // 是否精品
|
|
||||||
recommendNew?: boolean // 是否新品
|
|
||||||
recommendGood?: boolean // 是否优品
|
|
||||||
price?: number // 商品价格
|
price?: number // 商品价格
|
||||||
salesCount?: number // 商品销量
|
salesCount?: number // 商品销量
|
||||||
marketPrice?: number // 市场价
|
marketPrice?: number // 市场价
|
||||||
@ -60,7 +55,6 @@ export interface Spu {
|
|||||||
stock?: number // 商品库存
|
stock?: number // 商品库存
|
||||||
createTime?: Date // 商品创建时间
|
createTime?: Date // 商品创建时间
|
||||||
status?: number // 商品状态
|
status?: number // 商品状态
|
||||||
activityOrders: number[] // 活动排序
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得 Spu 列表
|
// 获得 Spu 列表
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="elTagWrappingRef">
|
|
||||||
<template v-if="activityOrders && activityOrders.length > 0">
|
|
||||||
<el-tag
|
|
||||||
v-for="activityType in activityOrders"
|
|
||||||
:key="activityType"
|
|
||||||
:type="promotionTypes.find((item) => item.value === activityType)?.colorType"
|
|
||||||
class="mr-[10px]"
|
|
||||||
>
|
|
||||||
{{ promotionTypes.find((item) => item.value === activityType)?.label }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-tag
|
|
||||||
v-for="type in promotionTypes"
|
|
||||||
:key="type.value as number"
|
|
||||||
:type="type.colorType"
|
|
||||||
class="mr-[10px]"
|
|
||||||
>
|
|
||||||
{{ type.label }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import Sortable from 'sortablejs'
|
|
||||||
import type { DictDataType } from '@/utils/dict'
|
|
||||||
|
|
||||||
defineOptions({ name: 'ActivityOrdersSort' })
|
|
||||||
const props = defineProps<{
|
|
||||||
promotionTypes: DictDataType[]
|
|
||||||
activityOrders: number[]
|
|
||||||
}>()
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:activityOrders', v: number[])
|
|
||||||
}>()
|
|
||||||
const elTagWrappingRef = ref() // elTag 容器 Ref
|
|
||||||
|
|
||||||
const initSortable = () => {
|
|
||||||
new Sortable(elTagWrappingRef.value, {
|
|
||||||
swapThreshold: 1,
|
|
||||||
animation: 150,
|
|
||||||
onEnd: (el) => {
|
|
||||||
const innerText = el.to.innerText
|
|
||||||
// 将字符串按换行符分割成数组
|
|
||||||
const activityOrder = innerText.split('\n')
|
|
||||||
// 根据字符串中的顺序重新排序数组
|
|
||||||
const sortedActivityOrder = activityOrder.map((activityName) => {
|
|
||||||
return props.promotionTypes.find((item) => item.label === activityName)?.value
|
|
||||||
})
|
|
||||||
emit('update:activityOrders', sortedActivityOrder as number[])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onMounted(async () => {
|
|
||||||
await nextTick()
|
|
||||||
// 如果活动排序为空也就是新增的时候加入活动
|
|
||||||
if (props.activityOrders && props.activityOrders.length === 0) {
|
|
||||||
emit(
|
|
||||||
'update:activityOrders',
|
|
||||||
props.promotionTypes.map((item) => item.value as number)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
initSortable()
|
|
||||||
})
|
|
||||||
</script>
|
|
@ -7,13 +7,18 @@
|
|||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-width="120px"
|
label-width="120px"
|
||||||
>
|
>
|
||||||
<el-row>
|
<!-- TODO 芋艿:宽度!! -->
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品名称" prop="name">
|
<el-form-item label="商品名称" prop="name">
|
||||||
<el-input v-model="formData.name" placeholder="请输入商品名称" />
|
<el-input
|
||||||
|
v-model="formData.name"
|
||||||
|
placeholder="请输入商品名称"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 2, maxRows: 2 }"
|
||||||
|
maxlength="64"
|
||||||
|
:show-word-limit="true"
|
||||||
|
:clearable="true"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品分类" prop="categoryId">
|
<el-form-item label="商品分类" prop="categoryId">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
v-model="formData.categoryId"
|
v-model="formData.categoryId"
|
||||||
@ -25,25 +30,9 @@
|
|||||||
filterable
|
filterable
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品关键字" prop="keyword">
|
<el-form-item label="商品关键字" prop="keyword">
|
||||||
<el-input v-model="formData.keyword" placeholder="请输入商品关键字" />
|
<el-input v-model="formData.keyword" placeholder="请输入商品关键字" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="单位" prop="unit">
|
|
||||||
<el-select v-model="formData.unit" class="w-1/1" placeholder="请选择单位">
|
|
||||||
<el-option
|
|
||||||
v-for="dict in getIntDictOptions(DICT_TYPE.PRODUCT_UNIT)"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品简介" prop="introduction">
|
<el-form-item label="商品简介" prop="introduction">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.introduction"
|
v-model="formData.introduction"
|
||||||
@ -52,18 +41,13 @@
|
|||||||
type="textarea"
|
type="textarea"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品封面图" prop="picUrl">
|
<el-form-item label="商品封面图" prop="picUrl">
|
||||||
<UploadImg v-model="formData.picUrl" height="80px" />
|
<UploadImg v-model="formData.picUrl" height="80px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="商品轮播图" prop="sliderPicUrls">
|
<el-form-item label="商品轮播图" prop="sliderPicUrls">
|
||||||
<UploadImgs v-model:modelValue="formData.sliderPicUrls" />
|
<UploadImgs v-model:modelValue="formData.sliderPicUrls" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
<!-- TODO 芋艿:这里要挪出去 -->
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="运费模板" prop="deliveryTemplateId">
|
<el-form-item label="运费模板" prop="deliveryTemplateId">
|
||||||
<el-select v-model="formData.deliveryTemplateId" placeholder="请选择">
|
<el-select v-model="formData.deliveryTemplateId" placeholder="请选择">
|
||||||
<el-option
|
<el-option
|
||||||
@ -74,64 +58,11 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="品牌" prop="brandId">
|
<el-form-item label="品牌" prop="brandId">
|
||||||
<el-select v-model="formData.brandId" placeholder="请选择">
|
<el-select v-model="formData.brandId" placeholder="请选择">
|
||||||
<el-option
|
<el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
v-for="item in brandList"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
:value="item.id"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="商品规格" props="specType">
|
|
||||||
<el-radio-group v-model="formData.specType" @change="onChangeSpec">
|
|
||||||
<el-radio :label="false" class="radio">单规格</el-radio>
|
|
||||||
<el-radio :label="true">多规格</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="分销类型" props="subCommissionType">
|
|
||||||
<el-radio-group v-model="formData.subCommissionType" @change="changeSubCommissionType">
|
|
||||||
<el-radio :label="false">默认设置</el-radio>
|
|
||||||
<el-radio :label="true" class="radio">单独设置</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<!-- 多规格添加-->
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item v-if="!formData.specType">
|
|
||||||
<SkuList
|
|
||||||
ref="skuListRef"
|
|
||||||
:prop-form-data="formData"
|
|
||||||
:propertyList="propertyList"
|
|
||||||
:rule-config="ruleConfig"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item v-if="formData.specType" label="商品属性">
|
|
||||||
<el-button class="mb-10px mr-15px" @click="attributesAddFormRef.open">添加属性</el-button>
|
|
||||||
<ProductAttributes :propertyList="propertyList" @success="generateSkus" />
|
|
||||||
</el-form-item>
|
|
||||||
<template v-if="formData.specType && propertyList.length > 0">
|
|
||||||
<el-form-item label="批量设置">
|
|
||||||
<SkuList :is-batch="true" :prop-form-data="formData" :propertyList="propertyList" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="属性列表">
|
|
||||||
<SkuList
|
|
||||||
ref="skuListRef"
|
|
||||||
:prop-form-data="formData"
|
|
||||||
:propertyList="propertyList"
|
|
||||||
:rule-config="ruleConfig"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</template>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<!-- 情况二:详情 -->
|
<!-- 情况二:详情 -->
|
||||||
@ -161,30 +92,15 @@
|
|||||||
@click="imagePreview(row.sliderPicUrls)"
|
@click="imagePreview(row.sliderPicUrls)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #skus>
|
|
||||||
<SkuList
|
|
||||||
ref="skuDetailListRef"
|
|
||||||
:is-detail="isDetail"
|
|
||||||
:prop-form-data="formData"
|
|
||||||
:propertyList="propertyList"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
|
|
||||||
<!-- 商品属性添加 Form 表单 -->
|
|
||||||
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PropType } from 'vue'
|
import { PropType } from 'vue'
|
||||||
import { isArray } from '@/utils/is'
|
import { isArray } from '@/utils/is'
|
||||||
import { copyValueToTarget } from '@/utils'
|
import { copyValueToTarget } from '@/utils'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { checkSelectedNode, defaultProps, handleTree, treeToString } from '@/utils/tree'
|
import { defaultProps, handleTree, treeToString } from '@/utils/tree'
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
|
||||||
import { getPropertyList, RuleConfig, SkuList } from '@/views/mall/product/spu/components/index.ts'
|
|
||||||
import ProductAttributes from './ProductAttributes.vue'
|
|
||||||
import ProductPropertyAddForm from './ProductPropertyAddForm.vue'
|
|
||||||
import { basicInfoSchema } from './spu.data'
|
import { basicInfoSchema } from './spu.data'
|
||||||
import type { Spu } from '@/api/mall/product/spu'
|
import type { Spu } from '@/api/mall/product/spu'
|
||||||
import * as ProductCategoryApi from '@/api/mall/product/category'
|
import * as ProductCategoryApi from '@/api/mall/product/category'
|
||||||
@ -193,30 +109,6 @@ import * as ExpressTemplateApi from '@/api/mall/trade/delivery/expressTemplate'
|
|||||||
|
|
||||||
defineOptions({ name: 'ProductSpuBasicInfoForm' })
|
defineOptions({ name: 'ProductSpuBasicInfoForm' })
|
||||||
|
|
||||||
// sku 相关属性校验规则
|
|
||||||
const ruleConfig: RuleConfig[] = [
|
|
||||||
{
|
|
||||||
name: 'stock',
|
|
||||||
rule: (arg) => arg >= 0,
|
|
||||||
message: '商品库存必须大于等于 1 !!!'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'price',
|
|
||||||
rule: (arg) => arg >= 0.01,
|
|
||||||
message: '商品销售价格必须大于等于 0.01 元!!!'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'marketPrice',
|
|
||||||
rule: (arg) => arg >= 0.01,
|
|
||||||
message: '商品市场价格必须大于等于 0.01 元!!!'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'costPrice',
|
|
||||||
rule: (arg) => arg >= 0.01,
|
|
||||||
message: '商品成本价格必须大于等于 0.00 元!!!'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
// ====== 商品详情相关操作 ======
|
// ====== 商品详情相关操作 ======
|
||||||
const { allSchemas } = useCrudSchemas(basicInfoSchema)
|
const { allSchemas } = useCrudSchemas(basicInfoSchema)
|
||||||
/** 商品图预览 */
|
/** 商品图预览 */
|
||||||
@ -246,40 +138,26 @@ const props = defineProps({
|
|||||||
activeName: propTypes.string.def(''),
|
activeName: propTypes.string.def(''),
|
||||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||||
})
|
})
|
||||||
const attributesAddFormRef = ref() // 添加商品属性表单
|
|
||||||
const productSpuBasicInfoRef = ref() // 表单 Ref
|
const productSpuBasicInfoRef = ref() // 表单 Ref
|
||||||
const propertyList = ref([]) // 商品属性列表
|
|
||||||
const skuListRef = ref() // 商品属性列表Ref
|
|
||||||
/** 调用 SkuList generateTableData 方法*/
|
|
||||||
const generateSkus = (propertyList) => {
|
|
||||||
skuListRef.value.generateTableData(propertyList)
|
|
||||||
}
|
|
||||||
const formData = reactive<Spu>({
|
const formData = reactive<Spu>({
|
||||||
name: '', // 商品名称
|
name: '', // 商品名称
|
||||||
categoryId: null, // 商品分类
|
categoryId: null, // 商品分类
|
||||||
keyword: '', // 关键字
|
keyword: '', // 关键字
|
||||||
unit: null, // 单位
|
|
||||||
picUrl: '', // 商品封面图
|
picUrl: '', // 商品封面图
|
||||||
sliderPicUrls: [], // 商品轮播图
|
sliderPicUrls: [], // 商品轮播图
|
||||||
introduction: '', // 商品简介
|
introduction: '', // 商品简介
|
||||||
deliveryTemplateId: null, // 运费模版
|
deliveryTemplateId: null, // 运费模版
|
||||||
brandId: null, // 商品品牌
|
brandId: null // 商品品牌
|
||||||
specType: false, // 商品规格
|
|
||||||
subCommissionType: false, // 分销类型
|
|
||||||
skus: []
|
|
||||||
})
|
})
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
name: [required],
|
name: [required],
|
||||||
categoryId: [required],
|
categoryId: [required],
|
||||||
keyword: [required],
|
keyword: [required],
|
||||||
unit: [required],
|
|
||||||
introduction: [required],
|
introduction: [required],
|
||||||
picUrl: [required],
|
picUrl: [required],
|
||||||
sliderPicUrls: [required],
|
sliderPicUrls: [required],
|
||||||
deliveryTemplateId: [required],
|
deliveryTemplateId: [required],
|
||||||
brandId: [required],
|
brandId: [required]
|
||||||
specType: [required],
|
|
||||||
subCommissionType: [required]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,7 +173,6 @@ watch(
|
|||||||
formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({
|
formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({
|
||||||
url: item
|
url: item
|
||||||
}))
|
}))
|
||||||
propertyList.value = getPropertyList(data)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true
|
immediate: true
|
||||||
@ -307,8 +184,6 @@ watch(
|
|||||||
*/
|
*/
|
||||||
const emit = defineEmits(['update:activeName'])
|
const emit = defineEmits(['update:activeName'])
|
||||||
const validate = async () => {
|
const validate = async () => {
|
||||||
// 校验 sku
|
|
||||||
skuListRef.value.validateSku()
|
|
||||||
// 校验表单
|
// 校验表单
|
||||||
if (!productSpuBasicInfoRef) return
|
if (!productSpuBasicInfoRef) return
|
||||||
return await unref(productSpuBasicInfoRef).validate((valid) => {
|
return await unref(productSpuBasicInfoRef).validate((valid) => {
|
||||||
@ -325,39 +200,9 @@ const validate = async () => {
|
|||||||
}
|
}
|
||||||
defineExpose({ validate })
|
defineExpose({ validate })
|
||||||
|
|
||||||
/** 分销类型 */
|
|
||||||
const changeSubCommissionType = () => {
|
|
||||||
// 默认为零,类型切换后也要重置为零
|
|
||||||
for (const item of formData.skus) {
|
|
||||||
item.firstBrokeragePrice = 0
|
|
||||||
item.secondBrokeragePrice = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 选择规格 */
|
|
||||||
const onChangeSpec = () => {
|
|
||||||
// 重置商品属性列表
|
|
||||||
propertyList.value = []
|
|
||||||
// 重置sku列表
|
|
||||||
formData.skus = [
|
|
||||||
{
|
|
||||||
price: 0,
|
|
||||||
marketPrice: 0,
|
|
||||||
costPrice: 0,
|
|
||||||
barCode: '',
|
|
||||||
picUrl: '',
|
|
||||||
stock: 0,
|
|
||||||
weight: 0,
|
|
||||||
volume: 0,
|
|
||||||
firstBrokeragePrice: 0,
|
|
||||||
secondBrokeragePrice: 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
const categoryList = ref([]) // 分类树
|
|
||||||
/** 获取分类的节点的完整结构 */
|
/** 获取分类的节点的完整结构 */
|
||||||
const formatCategoryName = (categoryId) => {
|
const categoryList = ref<any[]>([]) // 分类树
|
||||||
|
const formatCategoryName = (categoryId: number) => {
|
||||||
return treeToString(categoryList.value, categoryId)
|
return treeToString(categoryList.value, categoryId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,78 +7,19 @@
|
|||||||
:rules="rules"
|
:rules="rules"
|
||||||
label-width="120px"
|
label-width="120px"
|
||||||
>
|
>
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="商品排序" prop="sort">
|
<el-form-item label="商品排序" prop="sort">
|
||||||
<el-input-number v-model="formData.sort" :min="0" />
|
<el-input-number v-model="formData.sort" :min="0" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="赠送积分" prop="giveIntegral">
|
<el-form-item label="赠送积分" prop="giveIntegral">
|
||||||
<el-input-number v-model="formData.giveIntegral" :min="0" />
|
<el-input-number v-model="formData.giveIntegral" :min="0" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="虚拟销量" prop="virtualSalesCount">
|
<el-form-item label="虚拟销量" prop="virtualSalesCount">
|
||||||
<el-input-number
|
<el-input-number v-model="formData.virtualSalesCount" :min="0" placeholder="请输入虚拟销量" />
|
||||||
v-model="formData.virtualSalesCount"
|
|
||||||
:min="0"
|
|
||||||
placeholder="请输入虚拟销量"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="商品推荐">
|
|
||||||
<el-checkbox-group v-model="checkboxGroup" @change="onChangeGroup">
|
|
||||||
<el-checkbox v-for="(item, index) in recommendOptions" :key="index" :label="item.value">
|
|
||||||
{{ item.name }}
|
|
||||||
</el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="活动优先级">
|
|
||||||
<ActivityOrdersSort
|
|
||||||
v-model:activity-orders="formData.activityOrders"
|
|
||||||
:promotion-types="promotionTypes"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<!-- 情况二:详情 -->
|
<!-- 情况二:详情 -->
|
||||||
<Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema">
|
<Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema" />
|
||||||
<template #recommendHot="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.recommendHot" />
|
|
||||||
</template>
|
|
||||||
<template #recommendBenefit="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.recommendBenefit" />
|
|
||||||
</template>
|
|
||||||
<template #recommendBest="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.recommendBest" />
|
|
||||||
</template>
|
|
||||||
<template #recommendNew="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.recommendNew" />
|
|
||||||
</template>
|
|
||||||
<template #recommendGood="{ row }">
|
|
||||||
<dict-tag :type="DICT_TYPE.INFRA_BOOLEAN_STRING" :value="row.recommendGood" />
|
|
||||||
</template>
|
|
||||||
<template #activityOrders="{ row }">
|
|
||||||
<el-tag
|
|
||||||
v-for="activityType in row.activityOrders"
|
|
||||||
:key="activityType"
|
|
||||||
:type="promotionTypes.find((item) => item.value === activityType)?.colorType"
|
|
||||||
class="mr-[10px]"
|
|
||||||
>
|
|
||||||
{{ promotionTypes.find((item) => item.value === activityType)?.label }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</Descriptions>
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Spu } from '@/api/mall/product/spu'
|
import type { Spu } from '@/api/mall/product/spu'
|
||||||
@ -86,8 +27,6 @@ import { PropType } from 'vue'
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { copyValueToTarget } from '@/utils'
|
import { copyValueToTarget } from '@/utils'
|
||||||
import { otherSettingsSchema } from './spu.data'
|
import { otherSettingsSchema } from './spu.data'
|
||||||
import { DICT_TYPE, DictDataType } from '@/utils/dict'
|
|
||||||
import ActivityOrdersSort from './ActivityOrdersSort.vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'OtherSettingsForm' })
|
defineOptions({ name: 'OtherSettingsForm' })
|
||||||
|
|
||||||
@ -104,44 +43,12 @@ const props = defineProps({
|
|||||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO @puhui999:这个目前先写死;主要是,这个优惠类型不好用 promotion_type_enum;因为优惠劵、会员折扣都算
|
|
||||||
// 活动优先级处理
|
|
||||||
const promotionTypes = ref<DictDataType[]>([
|
|
||||||
{
|
|
||||||
dictType: 'promotionTypes',
|
|
||||||
label: '秒杀',
|
|
||||||
value: 1,
|
|
||||||
colorType: 'warning',
|
|
||||||
cssClass: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dictType: 'promotionTypes',
|
|
||||||
label: '砍价',
|
|
||||||
value: 2,
|
|
||||||
colorType: 'warning',
|
|
||||||
cssClass: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dictType: 'promotionTypes',
|
|
||||||
label: '拼团',
|
|
||||||
value: 3,
|
|
||||||
colorType: 'warning',
|
|
||||||
cssClass: ''
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const otherSettingsFormRef = ref() // 表单Ref
|
const otherSettingsFormRef = ref() // 表单Ref
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = ref<Spu>({
|
const formData = ref<Spu>({
|
||||||
sort: 1, // 商品排序
|
sort: 1, // 商品排序
|
||||||
giveIntegral: 1, // 赠送积分
|
giveIntegral: 1, // 赠送积分
|
||||||
virtualSalesCount: 1, // 虚拟销量
|
virtualSalesCount: 1 // 虚拟销量
|
||||||
recommendHot: false, // 是否热卖
|
|
||||||
recommendBenefit: false, // 是否优惠
|
|
||||||
recommendBest: false, // 是否精品
|
|
||||||
recommendNew: false, // 是否新品
|
|
||||||
recommendGood: false, // 是否优品
|
|
||||||
activityOrders: [] // 活动排序
|
|
||||||
})
|
})
|
||||||
// 表单规则
|
// 表单规则
|
||||||
const rules = reactive({
|
const rules = reactive({
|
||||||
@ -149,21 +56,6 @@ const rules = reactive({
|
|||||||
giveIntegral: [required],
|
giveIntegral: [required],
|
||||||
virtualSalesCount: [required]
|
virtualSalesCount: [required]
|
||||||
})
|
})
|
||||||
const recommendOptions = [
|
|
||||||
{ name: '是否热卖', value: 'recommendHot' },
|
|
||||||
{ name: '是否优惠', value: 'recommendBenefit' },
|
|
||||||
{ name: '是否精品', value: 'recommendBest' },
|
|
||||||
{ name: '是否新品', value: 'recommendNew' },
|
|
||||||
{ name: '是否优品', value: 'recommendGood' }
|
|
||||||
] // 商品推荐选项
|
|
||||||
const checkboxGroup = ref<string[]>([]) // 选中的推荐选项
|
|
||||||
|
|
||||||
/** 选择商品后赋值 */
|
|
||||||
const onChangeGroup = () => {
|
|
||||||
recommendOptions.forEach(({ value }) => {
|
|
||||||
formData.value[value] = checkboxGroup.value.includes(value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将传进来的值赋值给formData
|
* 将传进来的值赋值给formData
|
||||||
@ -175,11 +67,6 @@ watch(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
copyValueToTarget(formData.value, data)
|
copyValueToTarget(formData.value, data)
|
||||||
recommendOptions.forEach(({ value }) => {
|
|
||||||
if (formData.value[value] && !checkboxGroup.value.includes(value)) {
|
|
||||||
checkboxGroup.value.push(value)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true
|
immediate: true
|
||||||
|
240
src/views/mall/product/spu/form/SkuForm.vue
Normal file
240
src/views/mall/product/spu/form/SkuForm.vue
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
<template>
|
||||||
|
<!-- 情况一:添加/修改 -->
|
||||||
|
<el-form
|
||||||
|
v-if="!isDetail"
|
||||||
|
ref="productSpuSkuRef"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="120px"
|
||||||
|
>
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="商品规格" props="specType">
|
||||||
|
<el-radio-group v-model="formData.specType" @change="onChangeSpec">
|
||||||
|
<el-radio :label="false" class="radio">单规格</el-radio>
|
||||||
|
<el-radio :label="true">多规格</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="分销类型" props="subCommissionType">
|
||||||
|
<el-radio-group v-model="formData.subCommissionType" @change="changeSubCommissionType">
|
||||||
|
<el-radio :label="false">默认设置</el-radio>
|
||||||
|
<el-radio :label="true" class="radio">单独设置</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<!-- 多规格添加-->
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-form-item v-if="!formData.specType">
|
||||||
|
<SkuList
|
||||||
|
ref="skuListRef"
|
||||||
|
:prop-form-data="formData"
|
||||||
|
:propertyList="propertyList"
|
||||||
|
:rule-config="ruleConfig"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="formData.specType" label="商品属性">
|
||||||
|
<el-button class="mb-10px mr-15px" @click="attributesAddFormRef.open">添加属性</el-button>
|
||||||
|
<ProductAttributes :propertyList="propertyList" @success="generateSkus" />
|
||||||
|
</el-form-item>
|
||||||
|
<template v-if="formData.specType && propertyList.length > 0">
|
||||||
|
<el-form-item label="批量设置">
|
||||||
|
<SkuList :is-batch="true" :prop-form-data="formData" :propertyList="propertyList" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="属性列表">
|
||||||
|
<SkuList
|
||||||
|
ref="skuListRef"
|
||||||
|
:prop-form-data="formData"
|
||||||
|
:propertyList="propertyList"
|
||||||
|
:rule-config="ruleConfig"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 情况二:详情 -->
|
||||||
|
<Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema">
|
||||||
|
<template #specType="{ row }">
|
||||||
|
{{ row.specType ? '多规格' : '单规格' }}
|
||||||
|
</template>
|
||||||
|
<template #subCommissionType="{ row }">
|
||||||
|
{{ row.subCommissionType ? '单独设置' : '默认设置' }}
|
||||||
|
</template>
|
||||||
|
<template #sliderPicUrls="{ row }">
|
||||||
|
<el-image
|
||||||
|
v-for="(item, index) in row.sliderPicUrls"
|
||||||
|
:key="index"
|
||||||
|
:src="item.url"
|
||||||
|
class="mr-10px h-60px w-60px"
|
||||||
|
@click="imagePreview(row.sliderPicUrls)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #skus>
|
||||||
|
<SkuList
|
||||||
|
ref="skuDetailListRef"
|
||||||
|
:is-detail="isDetail"
|
||||||
|
:prop-form-data="formData"
|
||||||
|
:propertyList="propertyList"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Descriptions>
|
||||||
|
|
||||||
|
<!-- 商品属性添加 Form 表单 -->
|
||||||
|
<ProductPropertyAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { PropType } from 'vue'
|
||||||
|
import { isArray } from '@/utils/is'
|
||||||
|
import { copyValueToTarget } from '@/utils'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
|
import { getPropertyList, RuleConfig, SkuList } from '@/views/mall/product/spu/components/index.ts'
|
||||||
|
import ProductAttributes from './ProductAttributes.vue'
|
||||||
|
import ProductPropertyAddForm from './ProductPropertyAddForm.vue'
|
||||||
|
import { basicInfoSchema } from './spu.data'
|
||||||
|
import type { Spu } from '@/api/mall/product/spu'
|
||||||
|
|
||||||
|
defineOptions({ name: 'ProductSpuSkuForm' })
|
||||||
|
|
||||||
|
// sku 相关属性校验规则
|
||||||
|
const ruleConfig: RuleConfig[] = [
|
||||||
|
{
|
||||||
|
name: 'stock',
|
||||||
|
rule: (arg) => arg >= 0,
|
||||||
|
message: '商品库存必须大于等于 1 !!!'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'price',
|
||||||
|
rule: (arg) => arg >= 0.01,
|
||||||
|
message: '商品销售价格必须大于等于 0.01 元!!!'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'marketPrice',
|
||||||
|
rule: (arg) => arg >= 0.01,
|
||||||
|
message: '商品市场价格必须大于等于 0.01 元!!!'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'costPrice',
|
||||||
|
rule: (arg) => arg >= 0.01,
|
||||||
|
message: '商品成本价格必须大于等于 0.00 元!!!'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// ====== 商品详情相关操作 ======
|
||||||
|
const { allSchemas } = useCrudSchemas(basicInfoSchema)
|
||||||
|
/** 商品图预览 */
|
||||||
|
const imagePreview = (args) => {
|
||||||
|
const urlList = []
|
||||||
|
if (isArray(args)) {
|
||||||
|
args.forEach((item) => {
|
||||||
|
urlList.push(item.url)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
urlList.push(args)
|
||||||
|
}
|
||||||
|
createImageViewer({
|
||||||
|
urlList
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====== end ======
|
||||||
|
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
propFormData: {
|
||||||
|
type: Object as PropType<Spu>,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
activeName: propTypes.string.def(''),
|
||||||
|
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||||
|
})
|
||||||
|
const attributesAddFormRef = ref() // 添加商品属性表单
|
||||||
|
const productSpuSkuRef = ref() // 表单 Ref
|
||||||
|
const propertyList = ref([]) // 商品属性列表
|
||||||
|
const skuListRef = ref() // 商品属性列表Ref
|
||||||
|
/** 调用 SkuList generateTableData 方法*/
|
||||||
|
const generateSkus = (propertyList) => {
|
||||||
|
skuListRef.value.generateTableData(propertyList)
|
||||||
|
}
|
||||||
|
const formData = reactive<Spu>({
|
||||||
|
specType: false, // 商品规格
|
||||||
|
subCommissionType: false, // 分销类型
|
||||||
|
skus: []
|
||||||
|
})
|
||||||
|
const rules = reactive({
|
||||||
|
specType: [required],
|
||||||
|
subCommissionType: [required]
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将传进来的值赋值给 formData
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.propFormData,
|
||||||
|
(data) => {
|
||||||
|
if (!data) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
copyValueToTarget(formData, data)
|
||||||
|
propertyList.value = getPropertyList(data)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
/** 表单校验 */
|
||||||
|
const emit = defineEmits(['update:activeName'])
|
||||||
|
const validate = async () => {
|
||||||
|
// 校验 sku
|
||||||
|
skuListRef.value.validateSku()
|
||||||
|
// 校验表单
|
||||||
|
if (!productSpuSkuRef) return
|
||||||
|
return await unref(productSpuSkuRef).validate((valid) => {
|
||||||
|
if (!valid) {
|
||||||
|
message.warning('商品信息未完善!!')
|
||||||
|
emit('update:activeName', 'sku')
|
||||||
|
// 目的截断之后的校验
|
||||||
|
throw new Error('商品信息未完善!!')
|
||||||
|
} else {
|
||||||
|
// 校验通过更新数据
|
||||||
|
Object.assign(props.propFormData, formData)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({ validate })
|
||||||
|
|
||||||
|
/** 分销类型 */
|
||||||
|
const changeSubCommissionType = () => {
|
||||||
|
// 默认为零,类型切换后也要重置为零
|
||||||
|
for (const item of formData.skus) {
|
||||||
|
item.firstBrokeragePrice = 0
|
||||||
|
item.secondBrokeragePrice = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选择规格 */
|
||||||
|
const onChangeSpec = () => {
|
||||||
|
// 重置商品属性列表
|
||||||
|
propertyList.value = []
|
||||||
|
// 重置sku列表
|
||||||
|
formData.skus = [
|
||||||
|
{
|
||||||
|
price: 0,
|
||||||
|
marketPrice: 0,
|
||||||
|
costPrice: 0,
|
||||||
|
barCode: '',
|
||||||
|
picUrl: '',
|
||||||
|
stock: 0,
|
||||||
|
weight: 0,
|
||||||
|
volume: 0,
|
||||||
|
firstBrokeragePrice: 0,
|
||||||
|
secondBrokeragePrice: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<ContentWrap v-loading="formLoading">
|
<ContentWrap v-loading="formLoading">
|
||||||
<el-tabs v-model="activeName">
|
<el-tabs v-model="activeName">
|
||||||
<el-tab-pane label="商品信息" name="basicInfo">
|
<el-tab-pane label="基础信息" name="basicInfo">
|
||||||
<BasicInfoForm
|
<BasicInfoForm
|
||||||
ref="basicInfoRef"
|
ref="basicInfoRef"
|
||||||
v-model:activeName="activeName"
|
v-model:activeName="activeName"
|
||||||
@ -9,6 +9,14 @@
|
|||||||
:propFormData="formData"
|
:propFormData="formData"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="价格库存" name="sku">
|
||||||
|
<SkuForm
|
||||||
|
ref="skuRef"
|
||||||
|
v-model:activeName="activeName"
|
||||||
|
:is-detail="isDetail"
|
||||||
|
:propFormData="formData"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
<el-tab-pane label="商品详情" name="description">
|
<el-tab-pane label="商品详情" name="description">
|
||||||
<DescriptionForm
|
<DescriptionForm
|
||||||
ref="descriptionRef"
|
ref="descriptionRef"
|
||||||
@ -17,6 +25,7 @@
|
|||||||
:propFormData="formData"
|
:propFormData="formData"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
<!-- TODO 芋艿:物流设置 -->
|
||||||
<el-tab-pane label="其他设置" name="otherSettings">
|
<el-tab-pane label="其他设置" name="otherSettings">
|
||||||
<OtherSettingsForm
|
<OtherSettingsForm
|
||||||
ref="otherSettingsRef"
|
ref="otherSettingsRef"
|
||||||
@ -43,6 +52,7 @@ import * as ProductSpuApi from '@/api/mall/product/spu'
|
|||||||
import BasicInfoForm from './BasicInfoForm.vue'
|
import BasicInfoForm from './BasicInfoForm.vue'
|
||||||
import DescriptionForm from './DescriptionForm.vue'
|
import DescriptionForm from './DescriptionForm.vue'
|
||||||
import OtherSettingsForm from './OtherSettingsForm.vue'
|
import OtherSettingsForm from './OtherSettingsForm.vue'
|
||||||
|
import SkuForm from './SkuForm.vue'
|
||||||
import { convertToInteger, floatToFixed2, formatToFraction } from '@/utils'
|
import { convertToInteger, floatToFixed2, formatToFraction } from '@/utils'
|
||||||
|
|
||||||
defineOptions({ name: 'ProductSpuForm' })
|
defineOptions({ name: 'ProductSpuForm' })
|
||||||
@ -56,15 +66,15 @@ const { delView } = useTagsViewStore() // 视图操作
|
|||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
const activeName = ref('basicInfo') // Tag 激活的窗口
|
const activeName = ref('basicInfo') // Tag 激活的窗口
|
||||||
const isDetail = ref(false) // 是否查看详情
|
const isDetail = ref(false) // 是否查看详情
|
||||||
const basicInfoRef = ref() // 商品信息Ref
|
const basicInfoRef = ref() // 商品信息 Ref
|
||||||
const descriptionRef = ref() // 商品详情Ref
|
const skuRef = ref() // 商品规格 Ref
|
||||||
const otherSettingsRef = ref() // 其他设置Ref
|
const descriptionRef = ref() // 商品详情 Ref
|
||||||
|
const otherSettingsRef = ref() // 其他设置 Ref
|
||||||
// spu 表单数据
|
// spu 表单数据
|
||||||
const formData = ref<ProductSpuApi.Spu>({
|
const formData = ref<ProductSpuApi.Spu>({
|
||||||
name: '', // 商品名称
|
name: '', // 商品名称
|
||||||
categoryId: undefined, // 商品分类
|
categoryId: undefined, // 商品分类
|
||||||
keyword: '', // 关键字
|
keyword: '', // 关键字
|
||||||
unit: undefined, // 单位
|
|
||||||
picUrl: '', // 商品封面图
|
picUrl: '', // 商品封面图
|
||||||
sliderPicUrls: [], // 商品轮播图
|
sliderPicUrls: [], // 商品轮播图
|
||||||
introduction: '', // 商品简介
|
introduction: '', // 商品简介
|
||||||
@ -89,13 +99,7 @@ const formData = ref<ProductSpuApi.Spu>({
|
|||||||
description: '', // 商品详情
|
description: '', // 商品详情
|
||||||
sort: 0, // 商品排序
|
sort: 0, // 商品排序
|
||||||
giveIntegral: 0, // 赠送积分
|
giveIntegral: 0, // 赠送积分
|
||||||
virtualSalesCount: 0, // 虚拟销量
|
virtualSalesCount: 0 // 虚拟销量
|
||||||
recommendHot: false, // 是否热卖
|
|
||||||
recommendBenefit: false, // 是否优惠
|
|
||||||
recommendBest: false, // 是否精品
|
|
||||||
recommendNew: false, // 是否新品
|
|
||||||
recommendGood: false, // 是否优品
|
|
||||||
activityOrders: [] // 活动排序
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 获得详情 */
|
/** 获得详情 */
|
||||||
@ -139,6 +143,7 @@ const submitForm = async () => {
|
|||||||
// 校验各表单
|
// 校验各表单
|
||||||
try {
|
try {
|
||||||
await unref(basicInfoRef)?.validate()
|
await unref(basicInfoRef)?.validate()
|
||||||
|
await unref(skuRef)?.validate()
|
||||||
await unref(descriptionRef)?.validate()
|
await unref(descriptionRef)?.validate()
|
||||||
await unref(otherSettingsRef)?.validate()
|
await unref(otherSettingsRef)?.validate()
|
||||||
// 深拷贝一份, 这样最终 server 端不满足,不需要恢复,
|
// 深拷贝一份, 这样最终 server 端不满足,不需要恢复,
|
||||||
@ -181,6 +186,7 @@ const close = () => {
|
|||||||
delView(unref(currentRoute))
|
delView(unref(currentRoute))
|
||||||
push({ name: 'ProductSpu' })
|
push({ name: 'ProductSpu' })
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getDetail()
|
await getDetail()
|
||||||
|
@ -33,11 +33,6 @@ export const basicInfoSchema = reactive<CrudSchema[]>([
|
|||||||
label: '商品视频',
|
label: '商品视频',
|
||||||
field: 'videoUrl'
|
field: 'videoUrl'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: '单位',
|
|
||||||
field: 'unit',
|
|
||||||
dictType: DICT_TYPE.PRODUCT_UNIT
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: '规格类型',
|
label: '规格类型',
|
||||||
field: 'specType'
|
field: 'specType'
|
||||||
@ -73,29 +68,5 @@ export const otherSettingsSchema = reactive<CrudSchema[]>([
|
|||||||
{
|
{
|
||||||
label: '虚拟销量',
|
label: '虚拟销量',
|
||||||
field: 'virtualSalesCount'
|
field: 'virtualSalesCount'
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '是否热卖推荐',
|
|
||||||
field: 'recommendHot'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '是否优惠推荐',
|
|
||||||
field: 'recommendBenefit'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '是否精品推荐',
|
|
||||||
field: 'recommendBest'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '是否新品推荐',
|
|
||||||
field: 'recommendNew'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '是否优品推荐',
|
|
||||||
field: 'recommendGood'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '活动显示排序',
|
|
||||||
field: 'activityOrders'
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
Loading…
Reference in New Issue
Block a user