commit
a6fc5f775a
|
@ -47,17 +47,13 @@ export interface Spu {
|
||||||
recommendBest?: boolean // 是否精品
|
recommendBest?: boolean // 是否精品
|
||||||
recommendNew?: boolean // 是否新品
|
recommendNew?: boolean // 是否新品
|
||||||
recommendGood?: boolean // 是否优品
|
recommendGood?: boolean // 是否优品
|
||||||
}
|
price?: number // 商品价格
|
||||||
|
salesCount?: number // 商品销量
|
||||||
// TODO @puhui999: SpuRespVO 合并到 SPU 里?前端少点 VO 类哈;
|
marketPrice?: number // 市场价
|
||||||
export interface SpuRespVO extends Spu {
|
costPrice?: number // 成本价
|
||||||
price: number
|
stock?: number // 商品库存
|
||||||
salesCount: number
|
createTime?: Date // 商品创建时间
|
||||||
marketPrice: number
|
status?: number // 商品状态
|
||||||
costPrice: number
|
|
||||||
stock: number
|
|
||||||
createTime: Date
|
|
||||||
status: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得 Spu 列表
|
// 获得 Spu 列表
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import request from '@/config/axios'
|
import request from '@/config/axios'
|
||||||
import { Sku, SpuRespVO } from '@/api/mall/product/spu'
|
import { Sku, Spu } from '@/api/mall/product/spu'
|
||||||
|
|
||||||
export interface SeckillActivityVO {
|
export interface SeckillActivityVO {
|
||||||
id: number
|
id: number
|
||||||
|
@ -21,6 +21,7 @@ export interface SeckillActivityVO {
|
||||||
products: SeckillProductVO[]
|
products: SeckillProductVO[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 秒杀活动所需属性
|
||||||
export interface SeckillProductVO {
|
export interface SeckillProductVO {
|
||||||
spuId: number
|
spuId: number
|
||||||
skuId: number
|
skuId: number
|
||||||
|
@ -28,11 +29,12 @@ export interface SeckillProductVO {
|
||||||
stock: number
|
stock: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 扩展 Sku 配置
|
||||||
type SkuExtension = Sku & {
|
type SkuExtension = Sku & {
|
||||||
productConfig: SeckillProductVO
|
productConfig: SeckillProductVO
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SpuExtension extends SpuRespVO {
|
export interface SpuExtension extends Spu {
|
||||||
skus: SkuExtension[] // 重写类型
|
skus: SkuExtension[] // 重写类型
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,9 +55,9 @@ 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<ComponentRef<typeof BasicInfoForm>>() // 商品信息Ref
|
const basicInfoRef = ref() // 商品信息Ref
|
||||||
const descriptionRef = ref<ComponentRef<typeof DescriptionForm>>() // 商品详情Ref
|
const descriptionRef = ref() // 商品详情Ref
|
||||||
const otherSettingsRef = ref<ComponentRef<typeof OtherSettingsForm>>() // 其他设置Ref
|
const otherSettingsRef = ref() // 其他设置Ref
|
||||||
// spu 表单数据
|
// spu 表单数据
|
||||||
const formData = ref<ProductSpuApi.Spu>({
|
const formData = ref<ProductSpuApi.Spu>({
|
||||||
name: '', // 商品名称
|
name: '', // 商品名称
|
||||||
|
@ -98,7 +98,7 @@ const formData = ref<ProductSpuApi.Spu>({
|
||||||
|
|
||||||
/** 获得详情 */
|
/** 获得详情 */
|
||||||
const getDetail = async () => {
|
const getDetail = async () => {
|
||||||
if ('productSpuDetail' === name) {
|
if ('ProductSpuDetail' === name) {
|
||||||
isDetail.value = true
|
isDetail.value = true
|
||||||
}
|
}
|
||||||
const id = params.spuId as number
|
const id = params.spuId as number
|
||||||
|
|
|
@ -176,7 +176,7 @@ import { checkSelectedNode, defaultProps, handleTree, treeToString } from '@/uti
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
import { UploadImg, UploadImgs } from '@/components/UploadFile'
|
import { UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||||
import { ProductAttributes, ProductPropertyAddForm, SkuList } from './index'
|
import { getPropertyList, ProductAttributes, ProductPropertyAddForm, SkuList } from './index'
|
||||||
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'
|
||||||
|
@ -242,7 +242,7 @@ const rules = reactive({
|
||||||
introduction: [required],
|
introduction: [required],
|
||||||
picUrl: [required],
|
picUrl: [required],
|
||||||
sliderPicUrls: [required],
|
sliderPicUrls: [required],
|
||||||
// deliveryTemplateId: [required],
|
deliveryTemplateId: [required],
|
||||||
brandId: [required],
|
brandId: [required],
|
||||||
specType: [required],
|
specType: [required],
|
||||||
subCommissionType: [required]
|
subCommissionType: [required]
|
||||||
|
@ -261,26 +261,7 @@ watch(
|
||||||
formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({
|
formData.sliderPicUrls = data['sliderPicUrls']?.map((item) => ({
|
||||||
url: item
|
url: item
|
||||||
}))
|
}))
|
||||||
// 只有是多规格才处理
|
propertyList.value = getPropertyList(data)
|
||||||
if (!formData.specType) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 直接拿返回的 skus 属性逆向生成出 propertyList
|
|
||||||
const properties = []
|
|
||||||
formData.skus?.forEach((sku) => {
|
|
||||||
sku.properties?.forEach(({ propertyId, propertyName, valueId, valueName }) => {
|
|
||||||
// 添加属性
|
|
||||||
if (!properties?.some((item) => item.id === propertyId)) {
|
|
||||||
properties.push({ id: propertyId, name: propertyName, values: [] })
|
|
||||||
}
|
|
||||||
// 添加属性值
|
|
||||||
const index = properties?.findIndex((item) => item.id === propertyId)
|
|
||||||
if (!properties[index].values?.some((value) => value.id === valueId)) {
|
|
||||||
properties[index].values?.push({ id: valueId, name: valueName })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
propertyList.value = properties
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true
|
immediate: true
|
||||||
|
@ -293,10 +274,7 @@ watch(
|
||||||
const emit = defineEmits(['update:activeName'])
|
const emit = defineEmits(['update:activeName'])
|
||||||
const validate = async () => {
|
const validate = async () => {
|
||||||
// 校验 sku
|
// 校验 sku
|
||||||
if (!skuListRef.value.validateSku()) {
|
skuListRef.value.validateSku()
|
||||||
message.warning('商品相关价格不能低于 0.01 元!!')
|
|
||||||
throw new Error('商品相关价格不能低于 0.01 元!!')
|
|
||||||
}
|
|
||||||
// 校验表单
|
// 校验表单
|
||||||
if (!productSpuBasicInfoRef) return
|
if (!productSpuBasicInfoRef) return
|
||||||
return await unref(productSpuBasicInfoRef).validate((valid) => {
|
return await unref(productSpuBasicInfoRef).validate((valid) => {
|
||||||
|
|
|
@ -259,8 +259,10 @@ import { UploadImg } from '@/components/UploadFile'
|
||||||
import type { Property, Sku, Spu } from '@/api/mall/product/spu'
|
import type { Property, Sku, Spu } from '@/api/mall/product/spu'
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
import { RuleConfig } from '@/views/mall/product/spu/components/index'
|
import { RuleConfig } from '@/views/mall/product/spu/components/index'
|
||||||
|
import { Properties } from './index'
|
||||||
|
|
||||||
defineOptions({ name: 'SkuList' })
|
defineOptions({ name: 'SkuList' })
|
||||||
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
propFormData: {
|
propFormData: {
|
||||||
|
@ -268,7 +270,7 @@ const props = defineProps({
|
||||||
default: () => {}
|
default: () => {}
|
||||||
},
|
},
|
||||||
propertyList: {
|
propertyList: {
|
||||||
type: Array,
|
type: Array as PropType<Properties[]>,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
ruleConfig: {
|
ruleConfig: {
|
||||||
|
@ -323,26 +325,47 @@ const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表
|
||||||
/**
|
/**
|
||||||
* 保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。
|
* 保存时,每个商品规格的表单要校验下。例如说,销售金额最低是 0.01 这种。
|
||||||
*/
|
*/
|
||||||
const validateSku = (): boolean => {
|
const validateSku = () => {
|
||||||
const checks = ['price', 'marketPrice', 'costPrice']
|
const checks = ['price', 'marketPrice', 'costPrice']
|
||||||
|
let warningInfo = '请检查商品各行相关属性配置,'
|
||||||
let validate = true // 默认通过
|
let validate = true // 默认通过
|
||||||
for (const sku of formData.value!.skus) {
|
for (const sku of formData.value!.skus!) {
|
||||||
// 作为活动组件的校验
|
// 作为活动组件的校验
|
||||||
if (props.isActivityComponent) {
|
if (props.isActivityComponent) {
|
||||||
for (const rule of props.ruleConfig) {
|
for (const rule of props.ruleConfig) {
|
||||||
if (sku[rule.name] < rule.geValue) {
|
const arg = getValue(sku, rule.name)
|
||||||
|
if (!rule.rule(arg)) {
|
||||||
validate = false // 只要有一个不通过则直接不通过
|
validate = false // 只要有一个不通过则直接不通过
|
||||||
|
warningInfo += rule.message
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (checks.some((check) => sku[check] < 0.01)) {
|
if (checks.some((check) => sku[check] < 0.01)) {
|
||||||
validate = false // 只要有一个不通过则直接不通过
|
validate = false // 只要有一个不通过则直接不通过
|
||||||
|
warningInfo = '商品相关价格不能低于 0.01 元!!'
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 只要有一个不通过则结束后续的校验
|
||||||
|
if (!validate) {
|
||||||
|
message.warning(warningInfo)
|
||||||
|
throw new Error(warningInfo)
|
||||||
}
|
}
|
||||||
return validate
|
}
|
||||||
|
}
|
||||||
|
const getValue = (obj, arg) => {
|
||||||
|
const keys = arg.split('.')
|
||||||
|
let value = obj
|
||||||
|
for (const key of keys) {
|
||||||
|
if (value && typeof value === 'object' && key in value) {
|
||||||
|
value = value[key]
|
||||||
|
} else {
|
||||||
|
value = undefined
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
|
@ -417,13 +440,13 @@ const generateTableData = (propertyList: any[]) => {
|
||||||
* 生成 skus 前置校验
|
* 生成 skus 前置校验
|
||||||
*/
|
*/
|
||||||
const validateData = (propertyList: any[]) => {
|
const validateData = (propertyList: any[]) => {
|
||||||
const skuPropertyIds = []
|
const skuPropertyIds: number[] = []
|
||||||
formData.value!.skus!.forEach((sku) =>
|
formData.value!.skus!.forEach((sku) =>
|
||||||
sku.properties
|
sku.properties
|
||||||
?.map((property) => property.propertyId)
|
?.map((property) => property.propertyId)
|
||||||
.forEach((propertyId) => {
|
?.forEach((propertyId) => {
|
||||||
if (skuPropertyIds.indexOf(propertyId) === -1) {
|
if (skuPropertyIds.indexOf(propertyId!) === -1) {
|
||||||
skuPropertyIds.push(propertyId)
|
skuPropertyIds.push(propertyId!)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -457,7 +480,7 @@ const build = (propertyValuesList: Property[][]) => {
|
||||||
/** 监听属性列表,生成相关参数和表头 */
|
/** 监听属性列表,生成相关参数和表头 */
|
||||||
watch(
|
watch(
|
||||||
() => props.propertyList,
|
() => props.propertyList,
|
||||||
(propertyList) => {
|
(propertyList: Properties[]) => {
|
||||||
// 如果不是多规格则结束
|
// 如果不是多规格则结束
|
||||||
if (!formData.value!.specType) {
|
if (!formData.value!.specType) {
|
||||||
return
|
return
|
||||||
|
@ -497,7 +520,7 @@ watch(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 添加新属性没有属性值也不做处理
|
// 添加新属性没有属性值也不做处理
|
||||||
if (propertyList.some((item) => item.values.length === 0)) {
|
if (propertyList.some((item) => item.values!.length === 0)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 生成 table 数据,即 sku 列表
|
// 生成 table 数据,即 sku 列表
|
||||||
|
|
|
@ -14,8 +14,19 @@ interface Properties {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RuleConfig {
|
interface RuleConfig {
|
||||||
name: string // 需要校验的字段
|
// 需要校验的字段
|
||||||
geValue: number // TODO 暂定大于一个数字
|
// 例:name: 'name' 则表示校验 sku.name 的值
|
||||||
|
// 例:name: 'productConfig.stock' 则表示校验 sku.productConfig.name 的值,此处 productConfig 表示我在 Sku 上扩展的属性
|
||||||
|
name: string
|
||||||
|
// 校验规格为一个毁掉函数,其中 arg 为需要校验的字段的值。
|
||||||
|
// 例:需要校验价格必须大于0.01
|
||||||
|
// {
|
||||||
|
// name:'price',
|
||||||
|
// rule:(arg) => arg > 0.01
|
||||||
|
// }
|
||||||
|
rule: (arg: any) => boolean
|
||||||
|
// 校验不通过时的消息提示
|
||||||
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-table :data="spuData">
|
<el-table :data="spuData" :default-expand-all="true">
|
||||||
<el-table-column type="expand" width="30">
|
<el-table-column type="expand" width="30">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<SkuList
|
<SkuList
|
||||||
|
@ -46,87 +46,39 @@
|
||||||
<el-table-column align="center" label="库存" min-width="90" prop="stock" />
|
<el-table-column align="center" label="库存" min-width="90" prop="stock" />
|
||||||
</el-table>
|
</el-table>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" name="SpuAndSkuList" setup>
|
<script generic="T extends Spu" lang="ts" setup>
|
||||||
// TODO 后续计划重新封装作为活动商品配置通用组件;可以等其他活动做到的时候,在统一处理 SPU 选择组件哈
|
// TODO 后续计划重新封装作为活动商品配置通用组件;可以等其他活动做到的时候,在统一处理 SPU 选择组件哈
|
||||||
import { formatToFraction } from '@/utils'
|
import { formatToFraction } from '@/utils'
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
import * as ProductSpuApi from '@/api/mall/product/spu'
|
import { Spu } from '@/api/mall/product/spu'
|
||||||
import { SpuRespVO } from '@/api/mall/product/spu'
|
import { RuleConfig, SkuList } from '@/views/mall/product/spu/components'
|
||||||
import {
|
import { SeckillProductVO } from '@/api/mall/promotion/seckill/seckillActivity'
|
||||||
getPropertyList,
|
import { SpuProperty } from '@/views/mall/promotion/components/index'
|
||||||
Properties,
|
|
||||||
RuleConfig,
|
|
||||||
SkuList
|
|
||||||
} from '@/views/mall/product/spu/components'
|
|
||||||
import { SeckillProductVO, SpuExtension } from '@/api/mall/promotion/seckill/seckillActivity'
|
|
||||||
const message = useMessage() // 消息弹窗
|
|
||||||
|
|
||||||
// TODO @puhui999:是不是改成传递一个 spu 就好啦?
|
defineOptions({ name: 'PromotionSpuAndSkuList' })
|
||||||
const props = defineProps({
|
|
||||||
spuList: {
|
// TODO @puhui999:是不是改成传递一个 spu 就好啦? 因为活动商品可以多选所以展示编辑的时候需要展示多个
|
||||||
type: Array,
|
const props = defineProps<{
|
||||||
default: () => []
|
spuList: T[]
|
||||||
}
|
ruleConfig: RuleConfig[]
|
||||||
})
|
spuPropertyListP: SpuProperty<T>[]
|
||||||
const spuData = ref<SpuRespVO[]>([]) // spu 详情数据列表
|
}>()
|
||||||
|
|
||||||
|
const spuData = ref<Spu[]>([]) // spu 详情数据列表
|
||||||
const skuListRef = ref() // 商品属性列表Ref
|
const skuListRef = ref() // 商品属性列表Ref
|
||||||
interface spuProperty {
|
|
||||||
spuId: number
|
|
||||||
spuDetail: SpuExtension
|
|
||||||
propertyList: Properties[]
|
|
||||||
} // TODO @puhui999:类名首字母大写哈
|
|
||||||
|
|
||||||
const spuPropertyList = ref<spuProperty[]>([]) // spuId 对应的 sku 的属性列表
|
const spuPropertyList = ref<SpuProperty<T>[]>([]) // spuId 对应的 sku 的属性列表
|
||||||
/**
|
|
||||||
* 获取 SPU 详情
|
|
||||||
* @param spuIds
|
|
||||||
*/
|
|
||||||
const getSpuDetails = async (spuIds: number[]) => {
|
|
||||||
const spuProperties: spuProperty[] = []
|
|
||||||
// TODO puhui999: 考虑后端添加通过 spuIds 批量获取
|
|
||||||
for (const spuId of spuIds) {
|
|
||||||
// 获取 SPU 详情
|
|
||||||
const res = (await ProductSpuApi.getSpu(spuId)) as SpuExtension
|
|
||||||
if (!res) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 初始化每个 sku 秒杀配置
|
|
||||||
res.skus?.forEach((sku) => {
|
|
||||||
const config: SeckillProductVO = {
|
|
||||||
spuId,
|
|
||||||
skuId: sku.id!,
|
|
||||||
stock: 0,
|
|
||||||
seckillPrice: 0
|
|
||||||
}
|
|
||||||
sku.productConfig = config
|
|
||||||
})
|
|
||||||
spuProperties.push({ spuId, spuDetail: res, propertyList: getPropertyList(res) })
|
|
||||||
}
|
|
||||||
spuPropertyList.value = spuProperties
|
|
||||||
}
|
|
||||||
const ruleConfig: RuleConfig[] = [
|
|
||||||
{
|
|
||||||
name: 'stock',
|
|
||||||
geValue: 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'seckillPrice',
|
|
||||||
geValue: 0.01
|
|
||||||
}
|
|
||||||
]
|
|
||||||
/**
|
/**
|
||||||
* 获取所有 sku 秒杀配置
|
* 获取所有 sku 秒杀配置
|
||||||
|
* @param extendedAttribute 在 sku 上扩展的属性,例:秒杀活动 sku 扩展属性 productConfig 请参考 seckillActivity.ts
|
||||||
*/
|
*/
|
||||||
const getSkuConfigs = (): SeckillProductVO[] => {
|
const getSkuConfigs: <V>(extendedAttribute: string) => V[] = (extendedAttribute: string) => {
|
||||||
if (!skuListRef.value.validateSku()) {
|
skuListRef.value.validateSku()
|
||||||
// TODO 作为通用组件是需要进一步完善
|
|
||||||
message.warning('请检查商品相关属性配置!!')
|
|
||||||
throw new Error('请检查商品相关属性配置!!')
|
|
||||||
}
|
|
||||||
const seckillProducts: SeckillProductVO[] = []
|
const seckillProducts: SeckillProductVO[] = []
|
||||||
spuPropertyList.value.forEach((item) => {
|
spuPropertyList.value.forEach((item) => {
|
||||||
item.spuDetail.skus.forEach((sku) => {
|
item.spuDetail.skus.forEach((sku) => {
|
||||||
seckillProducts.push(sku.productConfig)
|
seckillProducts.push(sku[extendedAttribute])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return seckillProducts
|
return seckillProducts
|
||||||
|
@ -149,8 +101,21 @@ watch(
|
||||||
() => props.spuList,
|
() => props.spuList,
|
||||||
(data) => {
|
(data) => {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
spuData.value = data as SpuRespVO[]
|
spuData.value = data as Spu[]
|
||||||
getSpuDetails(spuData.value.map((spu) => spu.id!))
|
},
|
||||||
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* 将传进来的值赋值给 skuList
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.spuPropertyListP,
|
||||||
|
(data) => {
|
||||||
|
if (!data) return
|
||||||
|
spuPropertyList.value = data as SpuProperty<T>[]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
|
@ -20,7 +20,6 @@
|
||||||
class="w-1/1"
|
class="w-1/1"
|
||||||
node-key="id"
|
node-key="id"
|
||||||
placeholder="请选择商品分类"
|
placeholder="请选择商品分类"
|
||||||
@change="nodeClick"
|
|
||||||
/>
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
|
@ -110,18 +109,20 @@
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" name="SeckillActivitySpuAndSkuSelect" setup>
|
<script lang="ts" setup>
|
||||||
import { getPropertyList, Properties, SkuList } from '@/views/mall/product/spu/components'
|
import { getPropertyList, Properties, SkuList } from '@/views/mall/product/spu/components'
|
||||||
import { ElTable } from 'element-plus'
|
import { ElTable } from 'element-plus'
|
||||||
import { dateFormatter } from '@/utils/formatTime'
|
import { dateFormatter } from '@/utils/formatTime'
|
||||||
import { createImageViewer } from '@/components/ImageViewer'
|
import { createImageViewer } from '@/components/ImageViewer'
|
||||||
import { formatToFraction } from '@/utils'
|
import { formatToFraction } from '@/utils'
|
||||||
import { checkSelectedNode, defaultProps, handleTree } from '@/utils/tree'
|
import { defaultProps, handleTree } from '@/utils/tree'
|
||||||
|
|
||||||
import * as ProductCategoryApi from '@/api/mall/product/category'
|
import * as ProductCategoryApi from '@/api/mall/product/category'
|
||||||
import * as ProductSpuApi from '@/api/mall/product/spu'
|
import * as ProductSpuApi from '@/api/mall/product/spu'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
|
||||||
|
defineOptions({ name: 'PromotionSpuSelect' })
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// 默认不需要(不需要的情况下只返回 spu,需要的情况下返回 选中的 spu 和 sku 列表)
|
// 默认不需要(不需要的情况下只返回 spu,需要的情况下返回 选中的 spu 和 sku 列表)
|
||||||
// 其它活动需要选择商品和商品属性导入此组件即可,需添加组件属性 :isSelectSku='true'
|
// 其它活动需要选择商品和商品属性导入此组件即可,需添加组件属性 :isSelectSku='true'
|
||||||
|
@ -159,7 +160,7 @@ const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 获取 SPU 详情
|
// 获取 SPU 详情
|
||||||
const res = (await ProductSpuApi.getSpu(row.id as number)) as ProductSpuApi.SpuRespVO
|
const res = (await ProductSpuApi.getSpu(row.id as number)) as ProductSpuApi.Spu
|
||||||
propertyList.value = getPropertyList(res)
|
propertyList.value = getPropertyList(res)
|
||||||
spuData.value = res
|
spuData.value = res
|
||||||
isExpand.value = true
|
isExpand.value = true
|
||||||
|
@ -167,53 +168,50 @@ const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.
|
||||||
}
|
}
|
||||||
|
|
||||||
//============ 商品选择相关 ============
|
//============ 商品选择相关 ============
|
||||||
const selectedSpu = ref<ProductSpuApi.Spu>() // 选中的商品 spu 只能选择一个
|
const selectedSpuIds = ref<number[]>([]) // 选中的商品 spuIds
|
||||||
const selectedSku = ref<ProductSpuApi.Sku[]>() // 选中的商品 sku
|
const selectedSkuIds = ref<number[]>([]) // 选中的商品 skuIds
|
||||||
const selectSku = (val: ProductSpuApi.Sku[]) => {
|
const selectSku = (val: ProductSpuApi.Sku[]) => {
|
||||||
selectedSku.value = val
|
selectedSkuIds.value = val.map((sku) => sku.id!)
|
||||||
}
|
}
|
||||||
const selectSpu = (val: ProductSpuApi.Spu[]) => {
|
const selectSpu = (val: ProductSpuApi.Spu[]) => {
|
||||||
// 只选择一个
|
selectedSpuIds.value = val.map((spu) => spu.id!)
|
||||||
selectedSpu.value = val[0]
|
// // 只选择一个
|
||||||
// 如果大于1个
|
// selectedSpu.value = val[0]
|
||||||
if (val.length > 1) {
|
// // 如果大于1个
|
||||||
// 清空选择
|
// if (val.length > 1) {
|
||||||
spuListRef.value.clearSelection()
|
// // 清空选择
|
||||||
// 变更为最后一次选择的
|
// spuListRef.value.clearSelection()
|
||||||
spuListRef.value.toggleRowSelection(val.pop(), true)
|
// // 变更为最后一次选择的
|
||||||
}
|
// spuListRef.value.toggleRowSelection(val.pop(), true)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
// 确认选择时的触发事件
|
// 确认选择时的触发事件
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
(e: 'confirm', value: ProductSpuApi.Spu, value1?: ProductSpuApi.Sku[]): void
|
(e: 'confirm', spuIds: number[], skuIds?: number[]): void
|
||||||
}>()
|
}>()
|
||||||
/**
|
/**
|
||||||
* 确认选择返回选中的 spu 和 sku (如果需要选择sku的话)
|
* 确认选择返回选中的 spu 和 sku (如果需要选择sku的话)
|
||||||
*/
|
*/
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
if (typeof selectedSpu.value === 'undefined') {
|
if (selectedSpuIds.value.length === 0) {
|
||||||
message.warning('没有选择任何商品')
|
message.warning('没有选择任何商品')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (props.isSelectSku && selectedSkuIds.value.length === 0) {
|
||||||
(props.isSelectSku && typeof selectedSku.value === 'undefined') ||
|
|
||||||
selectedSku.value?.length === 0
|
|
||||||
) {
|
|
||||||
message.warning('没有选择任何商品属性')
|
message.warning('没有选择任何商品属性')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO 返回选择 sku 没测试过,后续测试完善
|
// 返回各自 id 列表
|
||||||
props.isSelectSku
|
props.isSelectSku
|
||||||
? emits('confirm', selectedSpu.value!, selectedSku.value!)
|
? emits('confirm', selectedSpuIds.value, selectedSkuIds.value)
|
||||||
: emits('confirm', selectedSpu.value!)
|
: emits('confirm', selectedSpuIds.value)
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:直接叫商品选择;不用外部传入标题;
|
/** 打开弹窗 */
|
||||||
/** 打开弹窗 TODO 没做国际化 */
|
const open = () => {
|
||||||
const open = (title: string) => {
|
dialogTitle.value = '商品选择'
|
||||||
dialogTitle.value = title
|
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
@ -259,15 +257,6 @@ const imagePreview = (imgUrl: string) => {
|
||||||
const categoryList = ref() // 分类树
|
const categoryList = ref() // 分类树
|
||||||
|
|
||||||
// TODO @puhui999:商品搜索的时候,可以通过一级搜二级;所以这个校验可以去掉哈;也就是说,只允许挂在二级,但是一级可搜索到
|
// TODO @puhui999:商品搜索的时候,可以通过一级搜二级;所以这个校验可以去掉哈;也就是说,只允许挂在二级,但是一级可搜索到
|
||||||
/**
|
|
||||||
* 校验所选是否为二级及以下节点
|
|
||||||
*/
|
|
||||||
const nodeClick = () => {
|
|
||||||
if (!checkSelectedNode(categoryList.value, queryParams.value.categoryId)) {
|
|
||||||
queryParams.value.categoryId = null
|
|
||||||
message.warning('必须选择二级及以下节点!!')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getList()
|
await getList()
|
|
@ -0,0 +1,13 @@
|
||||||
|
import SpuSelect from './SpuSelect.vue'
|
||||||
|
import SpuAndSkuList from './SpuAndSkuList.vue'
|
||||||
|
import { Properties } from '@/views/mall/product/spu/components'
|
||||||
|
|
||||||
|
type SpuProperty<T> = {
|
||||||
|
spuId: number
|
||||||
|
spuDetail: T
|
||||||
|
propertyList: Properties[]
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 提供商品活动商品选择通用组件
|
||||||
|
*/
|
||||||
|
export { SpuSelect, SpuAndSkuList, SpuProperty }
|
|
@ -8,10 +8,14 @@
|
||||||
:schema="allSchemas.formSchema"
|
:schema="allSchemas.formSchema"
|
||||||
>
|
>
|
||||||
<!-- 先选择 -->
|
<!-- 先选择 -->
|
||||||
<template #spuId>
|
<template #spuIds>
|
||||||
<el-button @click="spuAndSkuSelectForm.open('秒杀商品选择')">选择商品</el-button>
|
<el-button @click="spuSelectRef.open()">选择商品</el-button>
|
||||||
<!-- TODO @puhui999:默认展开 SKU 哈,毕竟 SKU 是主角,SPU 是配角 -->
|
<SpuAndSkuList
|
||||||
<SpuAndSkuList ref="spuAndSkuListRef" :spu-list="spuList" />
|
ref="spuAndSkuListRef"
|
||||||
|
:rule-config="ruleConfig"
|
||||||
|
:spu-list="spuList"
|
||||||
|
:spu-property-list-p="spuPropertyList"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</Form>
|
</Form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
@ -19,15 +23,17 @@
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<!-- TODO @puhui999:这个组件是不是 SpuSelect,不需要带 sku 或者 Form 呀 -->
|
<SpuSelect ref="spuSelectRef" @confirm="selectSpu" />
|
||||||
<SpuAndSkuSelectForm ref="spuAndSkuSelectForm" @confirm="selectSpu" />
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" name="PromotionSeckillActivityForm" setup>
|
<script lang="ts" setup>
|
||||||
import { SpuAndSkuList, SpuAndSkuSelectForm } from './components'
|
import { SpuAndSkuList, SpuProperty, SpuSelect } from '../../components'
|
||||||
import { allSchemas, rules } from './seckillActivity.data'
|
import { allSchemas, rules } from './seckillActivity.data'
|
||||||
import { Spu } from '@/api/mall/product/spu'
|
|
||||||
|
|
||||||
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
||||||
|
import { getPropertyList, RuleConfig } from '@/views/mall/product/spu/components'
|
||||||
|
import * as ProductSpuApi from '@/api/mall/product/spu'
|
||||||
|
|
||||||
|
defineOptions({ name: 'PromotionSeckillActivityForm' })
|
||||||
|
|
||||||
const { t } = useI18n() // 国际化
|
const { t } = useI18n() // 国际化
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
|
@ -37,14 +43,26 @@ const dialogTitle = ref('') // 弹窗的标题
|
||||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
const spuAndSkuSelectForm = ref() // 商品和属性选择 Ref
|
const spuSelectRef = ref() // 商品和属性选择 Ref
|
||||||
const spuAndSkuListRef = ref() // sku 秒杀配置组件Ref
|
const spuAndSkuListRef = ref() // sku 秒杀配置组件Ref
|
||||||
|
const ruleConfig: RuleConfig[] = [
|
||||||
|
{
|
||||||
|
name: 'productConfig.stock',
|
||||||
|
rule: (arg) => arg > 1,
|
||||||
|
message: '商品秒杀库存必须大于 1 !!!'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'productConfig.seckillPrice',
|
||||||
|
rule: (arg) => arg > 0.01,
|
||||||
|
message: '商品秒杀价格必须大于 0.01 !!!'
|
||||||
|
}
|
||||||
|
]
|
||||||
/** 打开弹窗 */
|
/** 打开弹窗 */
|
||||||
const open = async (type: string, id?: number) => {
|
const open = async (type: string, id?: number) => {
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = t('action.' + type)
|
dialogTitle.value = t('action.' + type)
|
||||||
formType.value = type
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
// 修改时,设置数据 TODO 没测试估计有问题
|
// 修改时,设置数据 TODO 没测试估计有问题
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
|
@ -58,12 +76,49 @@ const open = async (type: string, id?: number) => {
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
const spuList = ref<Spu[]>([]) // 选择的 spu
|
const spuList = ref<SeckillActivityApi.SpuExtension[]>([]) // 选择的 spu
|
||||||
const selectSpu = (val: Spu) => {
|
const spuPropertyList = ref<SpuProperty<SeckillActivityApi.SpuExtension>[]>([])
|
||||||
formRef.value.setValues({ spuId: val.id })
|
const selectSpu = (spuIds: number[]) => {
|
||||||
spuList.value = [val]
|
formRef.value.setValues({ spuIds })
|
||||||
|
getSpuDetails(spuIds)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取 SPU 详情
|
||||||
|
* TODO 获取 SPU 详情,放到各自活动表单来做,让 SpuAndSkuList 职责单一点
|
||||||
|
* @param spuIds
|
||||||
|
*/
|
||||||
|
const getSpuDetails = async (spuIds: number[]) => {
|
||||||
|
const spuProperties: SpuProperty<SeckillActivityApi.SpuExtension>[] = []
|
||||||
|
spuList.value = []
|
||||||
|
// TODO puhui999: 考虑后端添加通过 spuIds 批量获取
|
||||||
|
for (const spuId of spuIds) {
|
||||||
|
// 获取 SPU 详情
|
||||||
|
const res = (await ProductSpuApi.getSpu(spuId)) as SeckillActivityApi.SpuExtension
|
||||||
|
if (!res) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
spuList.value.push(res)
|
||||||
|
// 初始化每个 sku 秒杀配置
|
||||||
|
res.skus?.forEach((sku) => {
|
||||||
|
const config: SeckillActivityApi.SeckillProductVO = {
|
||||||
|
spuId,
|
||||||
|
skuId: sku.id!,
|
||||||
|
stock: 0,
|
||||||
|
seckillPrice: 0
|
||||||
|
}
|
||||||
|
sku.productConfig = config
|
||||||
|
})
|
||||||
|
spuProperties.push({ spuId, spuDetail: res, propertyList: getPropertyList(res) })
|
||||||
|
}
|
||||||
|
spuPropertyList.value = spuProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 重置表单 */
|
||||||
|
const resetForm = () => {
|
||||||
|
spuList.value = []
|
||||||
|
spuPropertyList.value = []
|
||||||
|
formRef.value.getElFormRef().resetFields()
|
||||||
|
}
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
|
@ -76,7 +131,7 @@ const submitForm = async () => {
|
||||||
try {
|
try {
|
||||||
const data = formRef.value.formModel as SeckillActivityApi.SeckillActivityVO
|
const data = formRef.value.formModel as SeckillActivityApi.SeckillActivityVO
|
||||||
data.spuIds = spuList.value.map((spu) => spu.id!)
|
data.spuIds = spuList.value.map((spu) => spu.id!)
|
||||||
data.products = spuAndSkuListRef.value.getSkuConfigs()
|
data.products = spuAndSkuListRef.value.getSkuConfigs('productConfig')
|
||||||
if (formType.value === 'create') {
|
if (formType.value === 'create') {
|
||||||
await SeckillActivityApi.createSeckillActivity(data)
|
await SeckillActivityApi.createSeckillActivity(data)
|
||||||
message.success(t('common.createSuccess'))
|
message.success(t('common.createSuccess'))
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
import SpuAndSkuSelectForm from './SpuAndSkuSelectForm.vue'
|
|
||||||
import SpuAndSkuList from './SpuAndSkuList.vue'
|
|
||||||
|
|
||||||
export { SpuAndSkuSelectForm, SpuAndSkuList }
|
|
|
@ -24,11 +24,19 @@
|
||||||
v-model:pageSize="tableObject.pageSize"
|
v-model:pageSize="tableObject.pageSize"
|
||||||
:columns="allSchemas.tableColumns"
|
:columns="allSchemas.tableColumns"
|
||||||
:data="tableObject.tableList"
|
:data="tableObject.tableList"
|
||||||
|
:expand="true"
|
||||||
:loading="tableObject.loading"
|
:loading="tableObject.loading"
|
||||||
:pagination="{
|
:pagination="{
|
||||||
total: tableObject.total
|
total: tableObject.total
|
||||||
}"
|
}"
|
||||||
|
@expand-change="expandChange"
|
||||||
>
|
>
|
||||||
|
<template #expand> 展示活动商品和商品相关属性活动配置</template>
|
||||||
|
<template #configIds="{ row }">
|
||||||
|
<el-tag v-for="(name, index) in convertSeckillConfigNames(row)" :key="index" class="mr-5px">
|
||||||
|
{{ name }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
<template #action="{ row }">
|
<template #action="{ row }">
|
||||||
<el-button
|
<el-button
|
||||||
v-hasPermi="['promotion:seckill-activity:update']"
|
v-hasPermi="['promotion:seckill-activity:update']"
|
||||||
|
@ -53,11 +61,14 @@
|
||||||
<!-- 表单弹窗:添加/修改 -->
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
<SeckillActivityForm ref="formRef" @success="getList" />
|
<SeckillActivityForm ref="formRef" @success="getList" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" name="PromotionSeckillActivity" setup>
|
<script lang="ts" setup>
|
||||||
import { allSchemas } from './seckillActivity.data'
|
import { allSchemas } from './seckillActivity.data'
|
||||||
|
import { getListAllSimple } from '@/api/mall/promotion/seckill/seckillConfig'
|
||||||
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
||||||
import SeckillActivityForm from './SeckillActivityForm.vue'
|
import SeckillActivityForm from './SeckillActivityForm.vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'PromotionSeckillActivity' })
|
||||||
|
|
||||||
// tableObject:表格的属性对象,可获得分页大小、条数等属性
|
// tableObject:表格的属性对象,可获得分页大小、条数等属性
|
||||||
// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作
|
// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作
|
||||||
// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/
|
// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/
|
||||||
|
@ -78,9 +89,21 @@ const openForm = (type: string, id?: number) => {
|
||||||
const handleDelete = (id: number) => {
|
const handleDelete = (id: number) => {
|
||||||
tableMethods.delList(id, false)
|
tableMethods.delList(id, false)
|
||||||
}
|
}
|
||||||
|
const seckillConfigAllSimple = ref([]) // 时段配置精简列表
|
||||||
|
const convertSeckillConfigNames = computed(
|
||||||
|
() => (row) =>
|
||||||
|
seckillConfigAllSimple.value
|
||||||
|
?.filter((item) => row.configIds.includes(item.id))
|
||||||
|
?.map((config) => config.name)
|
||||||
|
)
|
||||||
|
const expandChange = (row, expandedRows) => {
|
||||||
|
// TODO puhui:等 CRUD 完事后弄
|
||||||
|
console.log(row, expandedRows)
|
||||||
|
}
|
||||||
|
|
||||||
/** 初始化 **/
|
/** 初始化 **/
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
getList()
|
await getList()
|
||||||
|
seckillConfigAllSimple.value = await getListAllSimple()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -16,7 +16,6 @@ export const rules = reactive({
|
||||||
})
|
})
|
||||||
|
|
||||||
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
|
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
|
||||||
// TODO @puhui999:table 宽度调整下,有点太长啦;部分字段可以隐藏哈,根据需求;
|
|
||||||
const crudSchemas = reactive<CrudSchema[]>([
|
const crudSchemas = reactive<CrudSchema[]>([
|
||||||
{
|
{
|
||||||
label: '秒杀活动名称',
|
label: '秒杀活动名称',
|
||||||
|
@ -40,8 +39,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
type: 'daterange',
|
type: 'daterange'
|
||||||
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
|
@ -52,7 +50,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -64,8 +62,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
component: 'DatePicker',
|
component: 'DatePicker',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
valueFormat: 'YYYY-MM-DD',
|
valueFormat: 'YYYY-MM-DD',
|
||||||
type: 'daterange',
|
type: 'daterange'
|
||||||
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
|
@ -76,11 +73,11 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '秒杀时段', // todo @PUHUI999: 在列表界面,格式化不对
|
label: '秒杀时段',
|
||||||
field: 'configIds',
|
field: 'configIds',
|
||||||
form: {
|
form: {
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
|
@ -106,7 +103,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -118,7 +115,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -130,7 +127,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -141,7 +138,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -152,7 +149,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -164,7 +161,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -175,12 +172,14 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '秒杀活动商品', // TODO @puhui999:格式化的商品不对;
|
label: '秒杀活动商品',
|
||||||
field: 'spuId',
|
field: 'spuIds',
|
||||||
|
isTable: false,
|
||||||
|
isSearch: false,
|
||||||
form: {
|
form: {
|
||||||
colProps: {
|
colProps: {
|
||||||
span: 24
|
span: 24
|
||||||
|
@ -204,7 +203,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
},
|
},
|
||||||
isForm: false,
|
isForm: false,
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 120
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -215,12 +214,12 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
value: 0
|
value: 0
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
width: 300
|
width: 80
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '状态',
|
label: '状态',
|
||||||
field: 'status', // TODO @puhui999:状态在 table 格式化不对;
|
field: 'status', // TODO @puhui999:状态在 table 格式化不对;建表插入的数据状态值不对,改为 0 或 1 就好了
|
||||||
dictType: DICT_TYPE.COMMON_STATUS,
|
dictType: DICT_TYPE.COMMON_STATUS,
|
||||||
dictClass: 'number',
|
dictClass: 'number',
|
||||||
isForm: false,
|
isForm: false,
|
||||||
|
@ -235,6 +234,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
||||||
{
|
{
|
||||||
label: '备注',
|
label: '备注',
|
||||||
field: 'remark',
|
field: 'remark',
|
||||||
|
isSearch: false,
|
||||||
form: {
|
form: {
|
||||||
component: 'Input',
|
component: 'Input',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
|
|
Loading…
Reference in New Issue