review 营销活动
parent
fa71d3e7dd
commit
5d613e69b3
|
@ -49,6 +49,7 @@ export interface Spu {
|
|||
recommendGood?: boolean // 是否优品
|
||||
}
|
||||
|
||||
// TODO @puhui999: SpuRespVO 合并到 SPU 里?前端少点 VO 类哈;
|
||||
export interface SpuRespVO extends Spu {
|
||||
price: number
|
||||
salesCount: number
|
||||
|
|
|
@ -60,8 +60,3 @@ export const updateSeckillActivity = async (data: SeckillActivityVO) => {
|
|||
export const deleteSeckillActivity = async (id: number) => {
|
||||
return await request.delete({ url: '/promotion/seckill-activity/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出秒杀活动 Excel
|
||||
export const exportSeckillActivityApi = async (params) => {
|
||||
return await request.download({ url: '/promotion/seckill-activity/export-excel', params })
|
||||
}
|
||||
|
|
|
@ -47,8 +47,3 @@ export const updateSeckillConfigStatus = (id: number, status: number) => {
|
|||
export const deleteSeckillConfig = async (id: number) => {
|
||||
return await request.delete({ url: '/promotion/seckill-config/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 导出秒杀时段配置 Excel
|
||||
export const exportSeckillConfigApi = async (params) => {
|
||||
return await request.download({ url: '/promotion/seckill-config/export-excel', params })
|
||||
}
|
||||
|
|
|
@ -149,6 +149,21 @@ export const dateFormatter = (row, column, cellValue) => {
|
|||
return formatDate(cellValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* element plus 的时间 Formatter 实现,使用 YYYY-MM-DD 格式
|
||||
*
|
||||
* @param row 行数据
|
||||
* @param column 字段
|
||||
* @param cellValue 字段值
|
||||
*/
|
||||
// @ts-ignore
|
||||
export const dateFormatter2 = (row, column, cellValue) => {
|
||||
if (!cellValue) {
|
||||
return
|
||||
}
|
||||
return formatDate(cellValue, 'YYYY-MM-DD')
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置起始日期,时间为00:00:00
|
||||
* @param param 传入日期
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
>
|
||||
<!-- 先选择 -->
|
||||
<template #spuId>
|
||||
<el-button @click="spuAndSkuSelectForm.open('秒杀商品选择')">添加商品</el-button>
|
||||
<el-button @click="spuAndSkuSelectForm.open('秒杀商品选择')">选择商品</el-button>
|
||||
<!-- TODO @puhui999:默认展开 SKU 哈,毕竟 SKU 是主角,SPU 是配角 -->
|
||||
<SpuAndSkuList ref="spuAndSkuListRef" :spu-list="spuList" />
|
||||
</template>
|
||||
</Form>
|
||||
|
@ -18,6 +19,7 @@
|
|||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
<!-- TODO @puhui999:这个组件是不是 SpuSelect,不需要带 sku 或者 Form 呀 -->
|
||||
<SpuAndSkuSelectForm ref="spuAndSkuSelectForm" @confirm="selectSpu" />
|
||||
</template>
|
||||
<script lang="ts" name="PromotionSeckillActivityForm" setup>
|
||||
|
@ -37,6 +39,7 @@ const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
|||
const formRef = ref() // 表单 Ref
|
||||
const spuAndSkuSelectForm = ref() // 商品和属性选择 Ref
|
||||
const spuAndSkuListRef = ref() // sku 秒杀配置组件Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
</el-table>
|
||||
</template>
|
||||
<script lang="ts" name="SpuAndSkuList" setup>
|
||||
// TODO 后续计划重新封装作为活动商品配置通用组件
|
||||
// TODO 后续计划重新封装作为活动商品配置通用组件;可以等其他活动做到的时候,在统一处理 SPU 选择组件哈
|
||||
import { formatToFraction } from '@/utils'
|
||||
import { createImageViewer } from '@/components/ImageViewer'
|
||||
import * as ProductSpuApi from '@/api/mall/product/spu'
|
||||
|
@ -59,7 +59,9 @@ import {
|
|||
SkuList
|
||||
} from '@/views/mall/product/spu/components'
|
||||
import { SeckillProductVO, SpuExtension } from '@/api/mall/promotion/seckill/seckillActivity'
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
// TODO @puhui999:是不是改成传递一个 spu 就好啦?
|
||||
const props = defineProps({
|
||||
spuList: {
|
||||
type: Array,
|
||||
|
@ -72,7 +74,7 @@ interface spuProperty {
|
|||
spuId: number
|
||||
spuDetail: SpuExtension
|
||||
propertyList: Properties[]
|
||||
}
|
||||
} // TODO @puhui999:类名首字母大写哈
|
||||
|
||||
const spuPropertyList = ref<spuProperty[]>([]) // spuId 对应的 sku 的属性列表
|
||||
/**
|
||||
|
@ -112,7 +114,6 @@ const ruleConfig: RuleConfig[] = [
|
|||
geValue: 0.01
|
||||
}
|
||||
]
|
||||
const message = useMessage() // 消息弹窗
|
||||
/**
|
||||
* 获取所有 sku 秒杀配置
|
||||
*/
|
||||
|
@ -132,6 +133,7 @@ const getSkuConfigs = (): SeckillProductVO[] => {
|
|||
}
|
||||
// 暴露出给表单提交时使用
|
||||
defineExpose({ getSkuConfigs })
|
||||
|
||||
/** 商品图预览 */
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
|
@ -139,6 +141,7 @@ const imagePreview = (imgUrl: string) => {
|
|||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将传进来的值赋值给 skuList
|
||||
*/
|
||||
|
|
|
@ -147,6 +147,7 @@ const spuListRef = ref<InstanceType<typeof ElTable>>()
|
|||
const spuData = ref<ProductSpuApi.Spu | {}>() // 商品详情
|
||||
const isExpand = ref(false) // 控制 SKU 列表显示
|
||||
const expandRowKeys = ref<number[]>() // 控制展开行需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。
|
||||
|
||||
// 计算商品属性
|
||||
const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.Spu[]) => {
|
||||
spuData.value = {}
|
||||
|
@ -208,6 +209,8 @@ const confirm = () => {
|
|||
// 关闭弹窗
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
// TODO @puhui999:直接叫商品选择;不用外部传入标题;
|
||||
/** 打开弹窗 TODO 没做国际化 */
|
||||
const open = (title: string) => {
|
||||
dialogTitle.value = title
|
||||
|
@ -226,6 +229,7 @@ const getList = async () => {
|
|||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
getList()
|
||||
|
@ -243,6 +247,7 @@ const resetQuery = () => {
|
|||
}
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 商品图预览 */
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
|
@ -253,6 +258,7 @@ const imagePreview = (imgUrl: string) => {
|
|||
|
||||
const categoryList = ref() // 分类树
|
||||
|
||||
// TODO @puhui999:商品搜索的时候,可以通过一级搜二级;所以这个校验可以去掉哈;也就是说,只允许挂在二级,但是一级可搜索到
|
||||
/**
|
||||
* 校验所选是否为二级及以下节点
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
|
||||
import { getListAllSimple } from '@/api/mall/promotion/seckill/seckillConfig'
|
||||
|
||||
// 表单校验
|
||||
|
@ -16,6 +16,7 @@ export const rules = reactive({
|
|||
})
|
||||
|
||||
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
|
||||
// TODO @puhui999:table 宽度调整下,有点太长啦;部分字段可以隐藏哈,根据需求;
|
||||
const crudSchemas = reactive<CrudSchema[]>([
|
||||
{
|
||||
label: '秒杀活动名称',
|
||||
|
@ -33,12 +34,12 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||
{
|
||||
label: '活动开始时间',
|
||||
field: 'startTime',
|
||||
formatter: dateFormatter,
|
||||
formatter: dateFormatter2,
|
||||
isSearch: true,
|
||||
search: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
type: 'daterange',
|
||||
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
|
||||
}
|
||||
|
@ -57,12 +58,12 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||
{
|
||||
label: '活动结束时间',
|
||||
field: 'endTime',
|
||||
formatter: dateFormatter,
|
||||
formatter: dateFormatter2,
|
||||
isSearch: true,
|
||||
search: {
|
||||
component: 'DatePicker',
|
||||
componentProps: {
|
||||
valueFormat: 'YYYY-MM-DD HH:mm:ss',
|
||||
valueFormat: 'YYYY-MM-DD',
|
||||
type: 'daterange',
|
||||
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||
}
|
||||
},
|
||||
{
|
||||
label: '秒杀时段',
|
||||
label: '秒杀时段', // todo @PUHUI999: 在列表界面,格式化不对
|
||||
field: 'configIds',
|
||||
form: {
|
||||
component: 'Select',
|
||||
|
@ -178,7 +179,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||
}
|
||||
},
|
||||
{
|
||||
label: '秒杀活动商品',
|
||||
label: '秒杀活动商品', // TODO @puhui999:格式化的商品不对;
|
||||
field: 'spuId',
|
||||
form: {
|
||||
colProps: {
|
||||
|
@ -219,7 +220,7 @@ const crudSchemas = reactive<CrudSchema[]>([
|
|||
},
|
||||
{
|
||||
label: '状态',
|
||||
field: 'status',
|
||||
field: 'status', // TODO @puhui999:状态在 table 格式化不对;
|
||||
dictType: DICT_TYPE.COMMON_STATUS,
|
||||
dictClass: 'number',
|
||||
isForm: false,
|
||||
|
|
|
@ -64,7 +64,7 @@
|
|||
<!-- 表单弹窗:添加/修改 -->
|
||||
<SeckillConfigForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
<script lang="ts" name="SeckillConfig" setup>
|
||||
<script lang="ts" name="PromotionSeckillConfig" setup>
|
||||
import { allSchemas } from './seckillConfig.data'
|
||||
import * as SeckillConfigApi from '@/api/mall/promotion/seckill/seckillConfig'
|
||||
import SeckillConfigForm from './SeckillConfigForm.vue'
|
||||
|
@ -81,12 +81,14 @@ const { tableObject, tableMethods } = useTable({
|
|||
})
|
||||
// 获得表格的各种操作
|
||||
const { getList, setSearchParams } = tableMethods
|
||||
|
||||
/** 商品图预览 */
|
||||
const imagePreview = (imgUrl: string) => {
|
||||
createImageViewer({
|
||||
urlList: [imgUrl]
|
||||
})
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
|
@ -97,6 +99,7 @@ const openForm = (type: string, id?: number) => {
|
|||
const handleDelete = (id: number) => {
|
||||
tableMethods.delList(id, false)
|
||||
}
|
||||
|
||||
/** 修改用户状态 */
|
||||
const handleStatusChange = async (row: SeckillConfigApi.SeckillConfigVO) => {
|
||||
try {
|
||||
|
|
Loading…
Reference in New Issue