mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-10-31 18:28:44 +08:00 
			
		
		
		
	review 营销活动
This commit is contained in:
		| @@ -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 | ||||||
|   | |||||||
| @@ -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 }) |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -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 }) |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -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 传入日期 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -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:商品搜索的时候,可以通过一级搜二级;所以这个校验可以去掉哈;也就是说,只允许挂在二级,但是一级可搜索到 | ||||||
| /** | /** | ||||||
|  * 校验所选是否为二级及以下节点 |  * 校验所选是否为二级及以下节点 | ||||||
|  */ |  */ | ||||||
|   | |||||||
| @@ -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 @puhui999:table 宽度调整下,有点太长啦;部分字段可以隐藏哈,根据需求; | ||||||
| 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, | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV