parent
9e7fe34ae8
commit
d35ac547ac
@ -37,7 +37,7 @@ export interface Spu {
|
||||
brandId?: number | null // 商品品牌编号
|
||||
specType?: boolean // 商品规格
|
||||
subCommissionType?: boolean // 分销类型
|
||||
skus: Sku[] // sku数组
|
||||
skus?: Sku[] // sku数组
|
||||
description?: string // 商品详情
|
||||
sort?: number // 商品排序
|
||||
giveIntegral?: number // 赠送积分
|
||||
|
@ -379,6 +379,19 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
||||
title: '编辑商品',
|
||||
activeMenu: '/product/product-spu'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'productSpuDetail/:spuId(\\d+)',
|
||||
component: () => import('@/views/mall/product/spu/addForm.vue'),
|
||||
name: 'productSpuDetail',
|
||||
meta: {
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
icon: 'ep:view',
|
||||
title: '商品详情',
|
||||
activeMenu: '/product/product-spu'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -310,26 +310,30 @@ export const handleTree2 = (data, id, parentId, children, rootId) => {
|
||||
* @param nodeId 需要判断在什么层级的数据
|
||||
* @param level 检查的级别, 默认检查到二级
|
||||
*/
|
||||
export const checkSelectedNode = (tree: any[], nodeId, level = 2) => {
|
||||
export const checkSelectedNode = (tree: any[], nodeId: any, level = 2): boolean => {
|
||||
if (typeof tree === 'undefined' || !Array.isArray(tree) || tree.length === 0) {
|
||||
console.warn('tree must be an array')
|
||||
return false
|
||||
}
|
||||
|
||||
// 校验是否是一级节点
|
||||
if (tree.some((item) => item.id === nodeId)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 递归计数
|
||||
let count = 1
|
||||
|
||||
// 深层次校验
|
||||
function performAThoroughValidation(arr) {
|
||||
function performAThoroughValidation(arr: any[]): boolean {
|
||||
count += 1
|
||||
for (const item of arr) {
|
||||
if (item.id === nodeId) {
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
performAThoroughValidation(item.children)
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
@ -339,11 +343,15 @@ export const checkSelectedNode = (tree: any[], nodeId, level = 2) => {
|
||||
count = 1
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
// 找到后对比是否是期望的层级
|
||||
if (count >= level) return true
|
||||
if (count >= level) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取节点的完整结构
|
||||
* @param tree 树数据
|
||||
@ -367,7 +375,10 @@ export const treeToString = (tree: any[], nodeId) => {
|
||||
str += `/${item.name}`
|
||||
return true
|
||||
} else if (typeof item.children !== 'undefined' && item.children.length !== 0) {
|
||||
performAThoroughValidation(item.children)
|
||||
str += `/${item.name}`
|
||||
if (performAThoroughValidation(item.children)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -5,6 +5,7 @@
|
||||
<BasicInfoForm
|
||||
ref="basicInfoRef"
|
||||
v-model:activeName="activeName"
|
||||
:is-detail="isDetail"
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@ -12,6 +13,7 @@
|
||||
<DescriptionForm
|
||||
ref="descriptionRef"
|
||||
v-model:activeName="activeName"
|
||||
:is-detail="isDetail"
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@ -19,6 +21,7 @@
|
||||
<OtherSettingsForm
|
||||
ref="otherSettingsRef"
|
||||
v-model:activeName="activeName"
|
||||
:is-detail="isDetail"
|
||||
:propFormData="formData"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@ -42,11 +45,12 @@ import { convertToInteger, formatToFraction } from '@/utils'
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { push, currentRoute } = useRouter() // 路由
|
||||
const { params } = useRoute() // 查询参数
|
||||
const { params, name } = useRoute() // 查询参数
|
||||
const { delView } = useTagsViewStore() // 视图操作
|
||||
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const activeName = ref('basicInfo') // Tag 激活的窗口
|
||||
const isDetail = ref(false) // 是否查看详情
|
||||
const basicInfoRef = ref<ComponentRef<typeof BasicInfoForm>>() // 商品信息Ref
|
||||
const descriptionRef = ref<ComponentRef<typeof DescriptionForm>>() // 商品详情Ref
|
||||
const otherSettingsRef = ref<ComponentRef<typeof OtherSettingsForm>>() // 其他设置Ref
|
||||
@ -90,12 +94,13 @@ const formData = ref<ProductSpuApi.Spu>({
|
||||
|
||||
/** 获得详情 */
|
||||
const getDetail = async () => {
|
||||
console.log(name)
|
||||
const id = params.spuId as number
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const res = (await ProductSpuApi.getSpu(id)) as ProductSpuApi.Spu
|
||||
res.skus.forEach((item) => {
|
||||
res.skus!.forEach((item) => {
|
||||
// 回显价格分转元
|
||||
item.price = formatToFraction(item.price)
|
||||
item.marketPrice = formatToFraction(item.marketPrice)
|
||||
@ -123,7 +128,7 @@ const submitForm = async () => {
|
||||
// 深拷贝一份, 这样最终 server 端不满足,不需要恢复,
|
||||
const deepCopyFormData = cloneDeep(unref(formData.value))
|
||||
// 兜底处理 sku 空数据
|
||||
formData.value.skus.forEach((sku) => {
|
||||
formData.value.skus!.forEach((sku) => {
|
||||
// 因为是空数据这里判断一下商品条码是否为空就行
|
||||
if (sku.barCode === '') {
|
||||
const index = deepCopyFormData.skus.findIndex(
|
||||
@ -171,7 +176,6 @@ const close = () => {
|
||||
delView(unref(currentRoute))
|
||||
push('/product/product-spu')
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getDetail()
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<el-form ref="productSpuBasicInfoRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form
|
||||
v-if="!isDetail"
|
||||
ref="productSpuBasicInfoRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
@ -115,18 +121,72 @@
|
||||
</el-row>
|
||||
</el-form>
|
||||
<ProductAttributesAddForm ref="attributesAddFormRef" :propertyList="propertyList" />
|
||||
<!-- 详情跟表单放在一块可以共用已有功能,再抽离成组件有点过度封装的感觉 -->
|
||||
<Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema">
|
||||
<template #categoryId="{ row }"> {{ categoryString(row.categoryId) }}</template>
|
||||
<template #brandId="{ row }">
|
||||
{{ brandList.find((item) => item.id === row.brandId)?.name }}
|
||||
</template>
|
||||
<template #specType="{ row }">
|
||||
{{ row.specType ? '多规格' : '单规格' }}
|
||||
</template>
|
||||
<template #subCommissionType="{ row }">
|
||||
{{ row.subCommissionType ? '自行设置' : '默认设置' }}
|
||||
</template>
|
||||
<template #picUrl="{ row }">
|
||||
<el-image :src="row.picUrl" class="w-60px h-60px" @click="imagePreview(row.picUrl)" />
|
||||
</template>
|
||||
<template #sliderPicUrls="{ row }">
|
||||
<el-image
|
||||
v-for="(item, index) in row.sliderPicUrls"
|
||||
:key="index"
|
||||
:src="item.url"
|
||||
class="w-60px h-60px mr-10px"
|
||||
@click="imagePreview(row.sliderPicUrls)"
|
||||
/>
|
||||
</template>
|
||||
<template #skus>
|
||||
<SkuList
|
||||
ref="skuDetailListRef"
|
||||
:is-detail="isDetail"
|
||||
:prop-form-data="formData"
|
||||
:propertyList="propertyList"
|
||||
/>
|
||||
</template>
|
||||
</Descriptions>
|
||||
</template>
|
||||
<script lang="ts" name="ProductSpuBasicInfoForm" setup>
|
||||
import { PropType } from 'vue'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { checkSelectedNode, defaultProps, handleTree } from '@/utils/tree'
|
||||
import { checkSelectedNode, defaultProps, handleTree, treeToString } from '@/utils/tree'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import type { Spu } from '@/api/mall/product/spu'
|
||||
import { UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||
import { ProductAttributes, ProductAttributesAddForm, SkuList } from './index'
|
||||
import { basicInfoSchema } from './spu.data'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
import * as ProductCategoryApi from '@/api/mall/product/category'
|
||||
import { getSimpleBrandList } from '@/api/mall/product/brand'
|
||||
import { isArray } from '@/utils/is'
|
||||
|
||||
// ====== 商品详情相关操作 ======
|
||||
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() // 消息弹窗
|
||||
|
||||
@ -135,7 +195,8 @@ const props = defineProps({
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
activeName: propTypes.string.def('')
|
||||
activeName: propTypes.string.def(''),
|
||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||
})
|
||||
const attributesAddFormRef = ref() // 添加商品属性表单
|
||||
const productSpuBasicInfoRef = ref() // 表单 Ref
|
||||
@ -149,11 +210,11 @@ const formData = reactive<Spu>({
|
||||
name: '', // 商品名称
|
||||
categoryId: null, // 商品分类
|
||||
keyword: '', // 关键字
|
||||
unit: '', // 单位
|
||||
unit: null, // 单位
|
||||
picUrl: '', // 商品封面图
|
||||
sliderPicUrls: [], // 商品轮播图
|
||||
introduction: '', // 商品简介
|
||||
deliveryTemplateId: 1, // 运费模版
|
||||
deliveryTemplateId: null, // 运费模版
|
||||
brandId: null, // 商品品牌
|
||||
specType: false, // 商品规格
|
||||
subCommissionType: false, // 分销类型
|
||||
@ -273,9 +334,16 @@ const categoryList = ref([]) // 分类树
|
||||
const nodeClick = () => {
|
||||
if (!checkSelectedNode(categoryList.value, formData.categoryId)) {
|
||||
formData.categoryId = null
|
||||
message.warning('必须选择二级节点!!')
|
||||
message.warning('必须选择二级及以下节点!!')
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取分类的节点的完整结构
|
||||
* @param categoryId 分类id
|
||||
*/
|
||||
const categoryString = (categoryId) => {
|
||||
return treeToString(categoryList.value, categoryId)
|
||||
}
|
||||
const brandList = ref([]) // 精简商品品牌列表
|
||||
onMounted(async () => {
|
||||
// 获得分类树
|
||||
|
@ -1,10 +1,27 @@
|
||||
<template>
|
||||
<el-form ref="descriptionFormRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form
|
||||
v-if="!isDetail"
|
||||
ref="descriptionFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<!--富文本编辑器组件-->
|
||||
<el-form-item label="商品详情" prop="description">
|
||||
<Editor v-model:modelValue="formData.description" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<Descriptions
|
||||
v-if="isDetail"
|
||||
:data="formData"
|
||||
:schema="allSchemas.detailSchema"
|
||||
class="descriptionFormDescriptions"
|
||||
>
|
||||
<!-- 展示 HTML 内容 -->
|
||||
<template #description="{ row }">
|
||||
<div style="width: 600px" v-html="row.description"></div>
|
||||
</template>
|
||||
</Descriptions>
|
||||
</template>
|
||||
<script lang="ts" name="DescriptionForm" setup>
|
||||
import type { Spu } from '@/api/mall/product/spu'
|
||||
@ -12,6 +29,9 @@ import { Editor } from '@/components/Editor'
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { descriptionSchema } from './spu.data'
|
||||
|
||||
const { allSchemas } = useCrudSchemas(descriptionSchema)
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const props = defineProps({
|
||||
@ -19,7 +39,8 @@ const props = defineProps({
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
activeName: propTypes.string.def('')
|
||||
activeName: propTypes.string.def(''),
|
||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||
})
|
||||
const descriptionFormRef = ref() // 表单Ref
|
||||
const formData = ref<Spu>({
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<el-form ref="otherSettingsFormRef" :model="formData" :rules="rules" label-width="120px">
|
||||
<el-form
|
||||
v-if="!isDetail"
|
||||
ref="otherSettingsFormRef"
|
||||
:model="formData"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-row :gutter="20">
|
||||
@ -50,12 +56,38 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<Descriptions v-if="isDetail" :data="formData" :schema="allSchemas.detailSchema">
|
||||
<template #recommendHot="{ row }">
|
||||
{{ row.recommendHot ? '是' : '否' }}
|
||||
</template>
|
||||
<template #recommendBenefit="{ row }">
|
||||
{{ row.recommendBenefit ? '是' : '否' }}
|
||||
</template>
|
||||
<template #recommendBest="{ row }">
|
||||
{{ row.recommendBest ? '是' : '否' }}
|
||||
</template>
|
||||
<template #recommendNew="{ row }">
|
||||
{{ row.recommendNew ? '是' : '否' }}
|
||||
</template>
|
||||
<template #recommendGood="{ row }">
|
||||
{{ row.recommendGood ? '是' : '否' }}
|
||||
</template>
|
||||
<template #activityOrders>
|
||||
<el-tag>默认</el-tag>
|
||||
<el-tag class="ml-2" type="success">秒杀</el-tag>
|
||||
<el-tag class="ml-2" type="info">砍价</el-tag>
|
||||
<el-tag class="ml-2" type="warning">拼团</el-tag>
|
||||
</template>
|
||||
</Descriptions>
|
||||
</template>
|
||||
<script lang="ts" name="OtherSettingsForm" setup>
|
||||
import type { Spu } from '@/api/mall/product/spu'
|
||||
import { PropType } from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { copyValueToTarget } from '@/utils'
|
||||
import { otherSettingsSchema } from './spu.data'
|
||||
|
||||
const { allSchemas } = useCrudSchemas(otherSettingsSchema)
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
@ -64,7 +96,8 @@ const props = defineProps({
|
||||
type: Object as PropType<Spu>,
|
||||
default: () => {}
|
||||
},
|
||||
activeName: propTypes.string.def('')
|
||||
activeName: propTypes.string.def(''),
|
||||
isDetail: propTypes.bool.def(false) // 是否作为详情组件
|
||||
})
|
||||
|
||||
const otherSettingsFormRef = ref() // 表单Ref
|
||||
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<el-table
|
||||
v-if="!isDetail"
|
||||
:data="isBatch ? skuList : formData!.skus"
|
||||
border
|
||||
class="tabNumWidth"
|
||||
@ -21,8 +22,8 @@
|
||||
min-width="120"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<!-- TODO puhui999:展示成蓝色,有点区分度哈 fix: 字体加粗,颜色使用 #99a9bf 蓝色有点不好看哈哈-->
|
||||
<span style="font-weight: bold; color: #99a9bf">
|
||||
<!-- TODO puhui999:展示成蓝色,有点区分度哈 fix-->
|
||||
<span style="font-weight: bold; color: #40aaff">
|
||||
{{ row.properties[index]?.valueName }}
|
||||
</span>
|
||||
</template>
|
||||
@ -108,6 +109,84 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-table
|
||||
v-if="isDetail"
|
||||
:data="formData!.skus"
|
||||
border
|
||||
max-height="500"
|
||||
size="small"
|
||||
style="width: 99%"
|
||||
>
|
||||
<el-table-column align="center" label="图片" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-image :src="row.picUrl" class="w-60px h-60px" @click="imagePreview(row.picUrl)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="formData!.specType && !isBatch">
|
||||
<!-- 根据商品属性动态添加 -->
|
||||
<el-table-column
|
||||
v-for="(item, index) in tableHeaders"
|
||||
:key="index"
|
||||
:label="item.label"
|
||||
align="center"
|
||||
min-width="80"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<!-- TODO puhui999:展示成蓝色,有点区分度哈 fix-->
|
||||
<span style="font-weight: bold; color: #40aaff">
|
||||
{{ row.properties[index]?.valueName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column align="center" label="商品条码" min-width="100">
|
||||
<template #default="{ row }">
|
||||
{{ row.barCode }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="销售价(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.price }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="市场价(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.marketPrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="成本价(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.costPrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="库存" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.stock }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="重量(kg)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.weight }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="体积(m^3)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.volume }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-if="formData!.subCommissionType">
|
||||
<el-table-column align="center" label="一级返佣(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.subCommissionFirstPrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="二级返佣(元)" min-width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.subCommissionSecondPrice }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table>
|
||||
</template>
|
||||
<script lang="ts" name="SkuList" setup>
|
||||
import { PropType, Ref } from 'vue'
|
||||
@ -115,6 +194,7 @@ import { copyValueToTarget } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { UploadImg } from '@/components/UploadFile'
|
||||
import type { Property, Sku, Spu } from '@/api/mall/product/spu'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
|
||||
const props = defineProps({
|
||||
propFormData: {
|
||||
@ -125,7 +205,8 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
isBatch: propTypes.bool.def(false) // 是否作为批量操作组件
|
||||
isBatch: propTypes.bool.def(false), // 是否作为批量操作组件
|
||||
isDetail: propTypes.bool.def(false) // 是否作为 sku 详情组件
|
||||
})
|
||||
const formData: Ref<Spu | undefined> = ref<Spu>() // 表单数据
|
||||
const skuList = ref<Sku[]>([
|
||||
@ -143,20 +224,27 @@ const skuList = ref<Sku[]>([
|
||||
}
|
||||
]) // 批量添加时的临时数据
|
||||
|
||||
/** 商品图预览 */
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/** 批量添加 */
|
||||
const batchAdd = () => {
|
||||
formData.value!.skus.forEach((item) => {
|
||||
formData.value!.skus!.forEach((item) => {
|
||||
copyValueToTarget(item, skuList.value[0])
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除 sku */
|
||||
const deleteSku = (row) => {
|
||||
const index = formData.value!.skus.findIndex(
|
||||
const index = formData.value!.skus!.findIndex(
|
||||
// 直接把列表转成字符串比较
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
formData.value!.skus.splice(index, 1)
|
||||
formData.value!.skus!.splice(index, 1)
|
||||
}
|
||||
const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表头
|
||||
/**
|
||||
@ -221,13 +309,13 @@ const generateTableData = (propertyList: any[]) => {
|
||||
subCommissionSecondPrice: 0
|
||||
}
|
||||
// 如果存在属性相同的 sku 则不做处理
|
||||
const index = formData.value!.skus.findIndex(
|
||||
const index = formData.value!.skus!.findIndex(
|
||||
(sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
|
||||
)
|
||||
if (index !== -1) {
|
||||
continue
|
||||
}
|
||||
formData.value!.skus.push(row)
|
||||
formData.value!.skus!.push(row)
|
||||
}
|
||||
}
|
||||
|
||||
@ -236,7 +324,7 @@ const generateTableData = (propertyList: any[]) => {
|
||||
*/
|
||||
const validateData = (propertyList: any[]) => {
|
||||
const skuPropertyIds = []
|
||||
formData.value!.skus.forEach((sku) =>
|
||||
formData.value!.skus!.forEach((sku) =>
|
||||
sku.properties
|
||||
?.map((property) => property.propertyId)
|
||||
.forEach((propertyId) => {
|
||||
|
105
src/views/mall/product/spu/components/spu.data.ts
Normal file
105
src/views/mall/product/spu/components/spu.data.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
|
||||
export const basicInfoSchema = reactive<CrudSchema[]>([
|
||||
{
|
||||
label: '商品名称',
|
||||
field: 'name'
|
||||
},
|
||||
{
|
||||
label: '关键字',
|
||||
field: 'keyword'
|
||||
},
|
||||
{
|
||||
label: '商品简介',
|
||||
field: 'introduction'
|
||||
},
|
||||
{
|
||||
label: '商品分类',
|
||||
field: 'categoryId'
|
||||
},
|
||||
{
|
||||
label: '商品品牌',
|
||||
field: 'brandId'
|
||||
},
|
||||
{
|
||||
label: '商品封面图',
|
||||
field: 'picUrl'
|
||||
},
|
||||
{
|
||||
label: '商品轮播图',
|
||||
field: 'sliderPicUrls'
|
||||
},
|
||||
{
|
||||
label: '商品视频',
|
||||
field: 'videoUrl'
|
||||
},
|
||||
{
|
||||
label: '单位',
|
||||
field: 'unit',
|
||||
dictType: DICT_TYPE.PRODUCT_UNIT
|
||||
},
|
||||
{
|
||||
label: '规格类型',
|
||||
field: 'specType'
|
||||
},
|
||||
{
|
||||
label: '分销类型',
|
||||
field: 'subCommissionType'
|
||||
},
|
||||
{
|
||||
label: '物流模版',
|
||||
field: 'deliveryTemplateId'
|
||||
},
|
||||
{
|
||||
label: '商品属性列表',
|
||||
field: 'skus'
|
||||
}
|
||||
])
|
||||
export const descriptionSchema = reactive<CrudSchema[]>([
|
||||
{
|
||||
label: '商品详情',
|
||||
field: 'description'
|
||||
}
|
||||
])
|
||||
export const otherSettingsSchema = reactive<CrudSchema[]>([
|
||||
{
|
||||
label: '商品排序',
|
||||
field: 'sort'
|
||||
},
|
||||
{
|
||||
label: '赠送积分',
|
||||
field: 'giveIntegral'
|
||||
},
|
||||
{
|
||||
label: '虚拟销量',
|
||||
field: 'virtualSalesCount'
|
||||
},
|
||||
{
|
||||
label: '是否热卖推荐',
|
||||
field: 'recommendHot'
|
||||
},
|
||||
{
|
||||
label: '是否优惠推荐',
|
||||
field: 'recommendBenefit'
|
||||
},
|
||||
{
|
||||
label: '是否精品推荐',
|
||||
field: 'recommendBest'
|
||||
},
|
||||
{
|
||||
label: '是否新品推荐',
|
||||
field: 'recommendNew'
|
||||
},
|
||||
{
|
||||
label: '是否优品推荐',
|
||||
field: 'recommendGood'
|
||||
},
|
||||
{
|
||||
label: '赠送的优惠劵',
|
||||
field: 'giveCouponTemplateIds'
|
||||
},
|
||||
{
|
||||
label: '活动显示排序',
|
||||
field: 'activityOrders'
|
||||
}
|
||||
])
|
@ -171,8 +171,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<!-- TODO @puhui999:【详情】,可以后面点做哈 -->
|
||||
<el-button v-hasPermi="['product:spu:update']" link type="primary" @click="openDetail">
|
||||
<!-- TODO @puhui999:【详情】,可以后面点做哈 fix-->
|
||||
<el-button
|
||||
v-hasPermi="['product:spu:update']"
|
||||
link
|
||||
type="primary"
|
||||
@click="openDetail(row.id)"
|
||||
>
|
||||
详情
|
||||
</el-button>
|
||||
<template v-if="queryParams.tabType === 4">
|
||||
@ -284,12 +289,14 @@ const getTabsCount = async () => {
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
tabType: 0
|
||||
tabType: 0,
|
||||
name: '',
|
||||
categoryId: null
|
||||
}) // 查询参数
|
||||
const queryFormRef = ref() // 搜索的表单Ref
|
||||
|
||||
const handleTabClick = (tab: TabsPaneContext) => {
|
||||
queryParams.value.tabType = tab.paneName
|
||||
queryParams.value.tabType = tab.paneName as number
|
||||
getList()
|
||||
}
|
||||
|
||||
@ -400,8 +407,8 @@ const openForm = (id?: number) => {
|
||||
/**
|
||||
* 查看商品详情
|
||||
*/
|
||||
const openDetail = () => {
|
||||
message.alert('查看详情未完善!!!')
|
||||
const openDetail = (id?: number) => {
|
||||
push('/product/productSpuDetail' + id)
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
@ -436,12 +443,12 @@ const categoryString = (categoryId) => {
|
||||
return treeToString(categoryList.value, categoryId)
|
||||
}
|
||||
/**
|
||||
* 校验所选是否为二级节点
|
||||
* 校验所选是否为二级及以下节点
|
||||
*/
|
||||
const nodeClick = () => {
|
||||
if (!checkSelectedNode(categoryList.value, queryParams.value.categoryId)) {
|
||||
queryParams.value.categoryId = null
|
||||
message.warning('必须选择二级节点!!')
|
||||
message.warning('必须选择二级及以下节点!!')
|
||||
}
|
||||
}
|
||||
/** 初始化 **/
|
||||
|
Loading…
Reference in New Issue
Block a user