review 营销活动

pull/176/MERGE
YunaiV 2023-06-24 18:53:57 +08:00
parent fa71d3e7dd
commit 5d613e69b3
9 changed files with 45 additions and 23 deletions

View File

@ -49,6 +49,7 @@ export interface Spu {
recommendGood?: boolean // 是否优品 recommendGood?: boolean // 是否优品
} }
// TODO @puhui999: SpuRespVO 合并到 SPU 里?前端少点 VO 类哈;
export interface SpuRespVO extends Spu { export interface SpuRespVO extends Spu {
price: number price: number
salesCount: number salesCount: number

View File

@ -60,8 +60,3 @@ export const updateSeckillActivity = async (data: SeckillActivityVO) => {
export const deleteSeckillActivity = async (id: number) => { export const deleteSeckillActivity = async (id: number) => {
return await request.delete({ url: '/promotion/seckill-activity/delete?id=' + id }) 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 })
}

View File

@ -47,8 +47,3 @@ export const updateSeckillConfigStatus = (id: number, status: number) => {
export const deleteSeckillConfig = async (id: number) => { export const deleteSeckillConfig = async (id: number) => {
return await request.delete({ url: '/promotion/seckill-config/delete?id=' + id }) 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 })
}

View File

@ -149,6 +149,21 @@ export const dateFormatter = (row, column, cellValue) => {
return formatDate(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 * 00:00:00
* @param param * @param param

View File

@ -9,7 +9,8 @@
> >
<!-- 先选择 --> <!-- 先选择 -->
<template #spuId> <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" /> <SpuAndSkuList ref="spuAndSkuListRef" :spu-list="spuList" />
</template> </template>
</Form> </Form>
@ -18,6 +19,7 @@
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
</template> </template>
</Dialog> </Dialog>
<!-- TODO @puhui999这个组件是不是 SpuSelect不需要带 sku 或者 Form -->
<SpuAndSkuSelectForm ref="spuAndSkuSelectForm" @confirm="selectSpu" /> <SpuAndSkuSelectForm ref="spuAndSkuSelectForm" @confirm="selectSpu" />
</template> </template>
<script lang="ts" name="PromotionSeckillActivityForm" setup> <script lang="ts" name="PromotionSeckillActivityForm" setup>
@ -37,6 +39,7 @@ const formType = ref('') // 表单的类型create - 新增update - 修改
const formRef = ref() // Ref const formRef = ref() // Ref
const spuAndSkuSelectForm = ref() // Ref const spuAndSkuSelectForm = ref() // Ref
const spuAndSkuListRef = ref() // sku Ref const spuAndSkuListRef = ref() // sku Ref
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
dialogVisible.value = true dialogVisible.value = true

View File

@ -47,7 +47,7 @@
</el-table> </el-table>
</template> </template>
<script lang="ts" name="SpuAndSkuList" setup> <script lang="ts" name="SpuAndSkuList" setup>
// TODO // 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 * as ProductSpuApi from '@/api/mall/product/spu'
@ -59,7 +59,9 @@ import {
SkuList SkuList
} from '@/views/mall/product/spu/components' } from '@/views/mall/product/spu/components'
import { SeckillProductVO, SpuExtension } from '@/api/mall/promotion/seckill/seckillActivity' import { SeckillProductVO, SpuExtension } from '@/api/mall/promotion/seckill/seckillActivity'
const message = useMessage() //
// TODO @puhui999 spu
const props = defineProps({ const props = defineProps({
spuList: { spuList: {
type: Array, type: Array,
@ -72,7 +74,7 @@ interface spuProperty {
spuId: number spuId: number
spuDetail: SpuExtension spuDetail: SpuExtension
propertyList: Properties[] propertyList: Properties[]
} } // TODO @puhui999
const spuPropertyList = ref<spuProperty[]>([]) // spuId sku const spuPropertyList = ref<spuProperty[]>([]) // spuId sku
/** /**
@ -112,7 +114,6 @@ const ruleConfig: RuleConfig[] = [
geValue: 0.01 geValue: 0.01
} }
] ]
const message = useMessage() //
/** /**
* 获取所有 sku 秒杀配置 * 获取所有 sku 秒杀配置
*/ */
@ -132,6 +133,7 @@ const getSkuConfigs = (): SeckillProductVO[] => {
} }
// 使 // 使
defineExpose({ getSkuConfigs }) defineExpose({ getSkuConfigs })
/** 商品图预览 */ /** 商品图预览 */
const imagePreview = (imgUrl: string) => { const imagePreview = (imgUrl: string) => {
createImageViewer({ createImageViewer({
@ -139,6 +141,7 @@ const imagePreview = (imgUrl: string) => {
urlList: [imgUrl] urlList: [imgUrl]
}) })
} }
/** /**
* 将传进来的值赋值给 skuList * 将传进来的值赋值给 skuList
*/ */

View File

@ -147,6 +147,7 @@ const spuListRef = ref<InstanceType<typeof ElTable>>()
const spuData = ref<ProductSpuApi.Spu | {}>() // const spuData = ref<ProductSpuApi.Spu | {}>() //
const isExpand = ref(false) // SKU const isExpand = ref(false) // SKU
const expandRowKeys = ref<number[]>() // row-key 使 keys const expandRowKeys = ref<number[]>() // row-key 使 keys
// //
const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.Spu[]) => { const expandChange = async (row: ProductSpuApi.Spu, expandedRows: ProductSpuApi.Spu[]) => {
spuData.value = {} spuData.value = {}
@ -208,6 +209,8 @@ const confirm = () => {
// //
dialogVisible.value = false dialogVisible.value = false
} }
// TODO @puhui999
/** 打开弹窗 TODO 没做国际化 */ /** 打开弹窗 TODO 没做国际化 */
const open = (title: string) => { const open = (title: string) => {
dialogTitle.value = title dialogTitle.value = title
@ -226,6 +229,7 @@ const getList = async () => {
loading.value = false loading.value = false
} }
} }
/** 搜索按钮操作 */ /** 搜索按钮操作 */
const handleQuery = () => { const handleQuery = () => {
getList() getList()
@ -243,6 +247,7 @@ const resetQuery = () => {
} }
getList() getList()
} }
/** 商品图预览 */ /** 商品图预览 */
const imagePreview = (imgUrl: string) => { const imagePreview = (imgUrl: string) => {
createImageViewer({ createImageViewer({
@ -253,6 +258,7 @@ const imagePreview = (imgUrl: string) => {
const categoryList = ref() // const categoryList = ref() //
// TODO @puhui999
/** /**
* 校验所选是否为二级及以下节点 * 校验所选是否为二级及以下节点
*/ */

View File

@ -1,5 +1,5 @@
import type { CrudSchema } from '@/hooks/web/useCrudSchemas' 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' import { getListAllSimple } from '@/api/mall/promotion/seckill/seckillConfig'
// 表单校验 // 表单校验
@ -16,6 +16,7 @@ export const rules = reactive({
}) })
// CrudSchema https://doc.iocoder.cn/vue3/crud-schema/ // CrudSchema https://doc.iocoder.cn/vue3/crud-schema/
// TODO @puhui999table 宽度调整下,有点太长啦;部分字段可以隐藏哈,根据需求;
const crudSchemas = reactive<CrudSchema[]>([ const crudSchemas = reactive<CrudSchema[]>([
{ {
label: '秒杀活动名称', label: '秒杀活动名称',
@ -33,12 +34,12 @@ const crudSchemas = reactive<CrudSchema[]>([
{ {
label: '活动开始时间', label: '活动开始时间',
field: 'startTime', field: 'startTime',
formatter: dateFormatter, formatter: dateFormatter2,
isSearch: true, isSearch: true,
search: { search: {
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
valueFormat: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD',
type: 'daterange', type: 'daterange',
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')]
} }
@ -57,12 +58,12 @@ const crudSchemas = reactive<CrudSchema[]>([
{ {
label: '活动结束时间', label: '活动结束时间',
field: 'endTime', field: 'endTime',
formatter: dateFormatter, formatter: dateFormatter2,
isSearch: true, isSearch: true,
search: { search: {
component: 'DatePicker', component: 'DatePicker',
componentProps: { componentProps: {
valueFormat: 'YYYY-MM-DD HH:mm:ss', valueFormat: 'YYYY-MM-DD',
type: 'daterange', type: 'daterange',
defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')] 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', field: 'configIds',
form: { form: {
component: 'Select', component: 'Select',
@ -178,7 +179,7 @@ const crudSchemas = reactive<CrudSchema[]>([
} }
}, },
{ {
label: '秒杀活动商品', label: '秒杀活动商品', // TODO @puhui999格式化的商品不对
field: 'spuId', field: 'spuId',
form: { form: {
colProps: { colProps: {
@ -219,7 +220,7 @@ const crudSchemas = reactive<CrudSchema[]>([
}, },
{ {
label: '状态', label: '状态',
field: 'status', field: 'status', // TODO @puhui999状态在 table 格式化不对;
dictType: DICT_TYPE.COMMON_STATUS, dictType: DICT_TYPE.COMMON_STATUS,
dictClass: 'number', dictClass: 'number',
isForm: false, isForm: false,

View File

@ -64,7 +64,7 @@
<!-- 表单弹窗添加/修改 --> <!-- 表单弹窗添加/修改 -->
<SeckillConfigForm ref="formRef" @success="getList" /> <SeckillConfigForm ref="formRef" @success="getList" />
</template> </template>
<script lang="ts" name="SeckillConfig" setup> <script lang="ts" name="PromotionSeckillConfig" setup>
import { allSchemas } from './seckillConfig.data' import { allSchemas } from './seckillConfig.data'
import * as SeckillConfigApi from '@/api/mall/promotion/seckill/seckillConfig' import * as SeckillConfigApi from '@/api/mall/promotion/seckill/seckillConfig'
import SeckillConfigForm from './SeckillConfigForm.vue' import SeckillConfigForm from './SeckillConfigForm.vue'
@ -81,12 +81,14 @@ const { tableObject, tableMethods } = useTable({
}) })
// //
const { getList, setSearchParams } = tableMethods const { getList, setSearchParams } = tableMethods
/** 商品图预览 */ /** 商品图预览 */
const imagePreview = (imgUrl: string) => { const imagePreview = (imgUrl: string) => {
createImageViewer({ createImageViewer({
urlList: [imgUrl] urlList: [imgUrl]
}) })
} }
/** 添加/修改操作 */ /** 添加/修改操作 */
const formRef = ref() const formRef = ref()
const openForm = (type: string, id?: number) => { const openForm = (type: string, id?: number) => {
@ -97,6 +99,7 @@ const openForm = (type: string, id?: number) => {
const handleDelete = (id: number) => { const handleDelete = (id: number) => {
tableMethods.delList(id, false) tableMethods.delList(id, false)
} }
/** 修改用户状态 */ /** 修改用户状态 */
const handleStatusChange = async (row: SeckillConfigApi.SeckillConfigVO) => { const handleStatusChange = async (row: SeckillConfigApi.SeckillConfigVO) => {
try { try {