|
1 | 1 | <template>
|
2 |
| - <doc-alert title="功能开启" url="https://doc.iocoder.cn/mall/build/" /> |
3 |
| - |
4 |
| - <!-- 搜索工作栏 --> |
5 | 2 | <ContentWrap>
|
6 |
| - <Search :schema="allSchemas.searchSchema" @reset="setSearchParams" @search="setSearchParams"> |
7 |
| - <!-- 新增等操作按钮 --> |
8 |
| - <template #actionMore> |
| 3 | + <!-- 搜索工作栏 --> |
| 4 | + <el-form |
| 5 | + class="-mb-15px" |
| 6 | + :model="queryParams" |
| 7 | + ref="queryFormRef" |
| 8 | + :inline="true" |
| 9 | + label-width="68px" |
| 10 | + > |
| 11 | + <el-form-item label="活动名称" prop="name"> |
| 12 | + <el-input |
| 13 | + v-model="queryParams.name" |
| 14 | + placeholder="请输入活动名称" |
| 15 | + clearable |
| 16 | + @keyup.enter="handleQuery" |
| 17 | + class="!w-240px" |
| 18 | + /> |
| 19 | + </el-form-item> |
| 20 | + <el-form-item label="活动状态" prop="status"> |
| 21 | + <el-select |
| 22 | + v-model="queryParams.status" |
| 23 | + placeholder="请选择活动状态" |
| 24 | + clearable |
| 25 | + class="!w-240px" |
| 26 | + > |
| 27 | + <el-option |
| 28 | + v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" |
| 29 | + :key="dict.value" |
| 30 | + :label="dict.label" |
| 31 | + :value="dict.value" |
| 32 | + /> |
| 33 | + </el-select> |
| 34 | + </el-form-item> |
| 35 | + <el-form-item> |
| 36 | + <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> |
| 37 | + <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> |
9 | 38 | <el-button
|
10 |
| - v-hasPermi="['promotion:seckill-activity:create']" |
11 |
| - plain |
12 | 39 | type="primary"
|
| 40 | + plain |
13 | 41 | @click="openForm('create')"
|
| 42 | + v-hasPermi="['promotion:seckill-activity:create']" |
14 | 43 | >
|
15 |
| - <Icon class="mr-5px" icon="ep:plus" /> 新增 |
| 44 | + <Icon icon="ep:plus" class="mr-5px" /> 新增 |
16 | 45 | </el-button>
|
17 |
| - </template> |
18 |
| - </Search> |
| 46 | + </el-form-item> |
| 47 | + </el-form> |
19 | 48 | </ContentWrap>
|
20 | 49 |
|
21 | 50 | <!-- 列表 -->
|
22 | 51 | <ContentWrap>
|
23 |
| - <Table |
24 |
| - v-model:currentPage="tableObject.currentPage" |
25 |
| - v-model:pageSize="tableObject.pageSize" |
26 |
| - :columns="allSchemas.tableColumns" |
27 |
| - :data="tableObject.tableList" |
28 |
| - :expand="true" |
29 |
| - :loading="tableObject.loading" |
30 |
| - :pagination="{ |
31 |
| - total: tableObject.total |
32 |
| - }" |
33 |
| - @expand-change="expandChange" |
34 |
| - > |
35 |
| - <template #expand> 展示活动商品和商品相关属性活动配置</template> |
36 |
| - <template #spuId="{ row }"> |
37 |
| - <el-image |
38 |
| - :src="row.picUrl" |
39 |
| - class="mr-5px h-30px w-30px align-middle" |
40 |
| - @click="imagePreview(row.picUrl)" |
41 |
| - /> |
42 |
| - <span class="align-middle">{{ row.spuName }}</span> |
43 |
| - </template> |
44 |
| - <template #configIds="{ row }"> |
45 |
| - <el-tag v-for="(name, index) in convertSeckillConfigNames(row)" :key="index" class="mr-5px"> |
46 |
| - {{ name }} |
47 |
| - </el-tag> |
48 |
| - </template> |
49 |
| - <template #action="{ row }"> |
50 |
| - <el-button |
51 |
| - v-hasPermi="['promotion:seckill-activity:update']" |
52 |
| - link |
53 |
| - type="primary" |
54 |
| - @click="openForm('update', row.id)" |
55 |
| - > |
56 |
| - 编辑 |
57 |
| - </el-button> |
58 |
| - <el-button |
59 |
| - v-hasPermi="['promotion:seckill-activity:delete']" |
60 |
| - link |
61 |
| - type="danger" |
62 |
| - @click="handleDelete(row.id)" |
63 |
| - > |
64 |
| - 删除 |
65 |
| - </el-button> |
66 |
| - </template> |
67 |
| - </Table> |
| 52 | + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> |
| 53 | + <el-table-column label="活动编号" prop="id" min-width="80" /> |
| 54 | + <el-table-column label="活动名称" prop="name" min-width="140" /> |
| 55 | + <el-table-column |
| 56 | + label="秒杀时段" |
| 57 | + prop="configIds" |
| 58 | + width="220px" |
| 59 | + :show-overflow-tooltip="false" |
| 60 | + > |
| 61 | + <template #default="scope"> |
| 62 | + <el-tag v-for="(configId, index) in scope.row.configIds" :key="index" class="mr-5px"> |
| 63 | + {{ formatConfigNames(configId) }} |
| 64 | + </el-tag> |
| 65 | + </template> |
| 66 | + </el-table-column> |
| 67 | + <el-table-column label="活动时间" min-width="210"> |
| 68 | + <template #default="scope"> |
| 69 | + {{ formatDate(scope.row.startTime, 'YYYY-MM-DD') }} |
| 70 | + ~ {{ formatDate(scope.row.endTime, 'YYYY-MM-DD') }} |
| 71 | + </template> |
| 72 | + </el-table-column> |
| 73 | + <el-table-column label="商品图片" prop="spuName" min-width="80"> |
| 74 | + <template #default="scope"> |
| 75 | + <el-image |
| 76 | + :src="scope.row.picUrl" |
| 77 | + class="h-40px w-40px" |
| 78 | + :preview-src-list="[scope.row.picUrl]" |
| 79 | + preview-teleported |
| 80 | + /> |
| 81 | + </template> |
| 82 | + </el-table-column> |
| 83 | + <el-table-column label="商品标题" prop="spuName" min-width="300" /> |
| 84 | + <el-table-column |
| 85 | + label="原价" |
| 86 | + prop="marketPrice" |
| 87 | + min-width="100" |
| 88 | + :formatter="fenToYuanFormat" |
| 89 | + /> |
| 90 | + <el-table-column label="秒杀价" prop="marketPrice" min-width="100"> |
| 91 | + <template #default="scope"> |
| 92 | + {{ formatSeckillPrice(scope.row.products) }} |
| 93 | + </template> |
| 94 | + </el-table-column> |
| 95 | + <el-table-column label="活动状态" align="center" prop="status" min-width="100"> |
| 96 | + <template #default="scope"> |
| 97 | + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> |
| 98 | + </template> |
| 99 | + </el-table-column> |
| 100 | + <el-table-column label="库存" align="center" prop="stock" min-width="80" /> |
| 101 | + <el-table-column label="总库存" align="center" prop="totalStock" min-width="80" /> |
| 102 | + <el-table-column |
| 103 | + label="创建时间" |
| 104 | + align="center" |
| 105 | + prop="createTime" |
| 106 | + :formatter="dateFormatter" |
| 107 | + width="180px" |
| 108 | + /> |
| 109 | + <el-table-column label="操作" align="center" width="150px"> |
| 110 | + <template #default="scope"> |
| 111 | + <el-button |
| 112 | + link |
| 113 | + type="primary" |
| 114 | + @click="openForm('update', scope.row.id)" |
| 115 | + v-hasPermi="['promotion:seckill-activity:update']" |
| 116 | + > |
| 117 | + 编辑 |
| 118 | + </el-button> |
| 119 | + <el-button |
| 120 | + link |
| 121 | + type="danger" |
| 122 | + @click="handleClose(scope.row.id)" |
| 123 | + v-if="scope.row.status === 0" |
| 124 | + v-hasPermi="['promotion:seckill-activity:close']" |
| 125 | + > |
| 126 | + 关闭 |
| 127 | + </el-button> |
| 128 | + <el-button |
| 129 | + link |
| 130 | + type="danger" |
| 131 | + @click="handleDelete(scope.row.id)" |
| 132 | + v-else |
| 133 | + v-hasPermi="['promotion:seckill-activity:delete']" |
| 134 | + > |
| 135 | + 删除 |
| 136 | + </el-button> |
| 137 | + </template> |
| 138 | + </el-table-column> |
| 139 | + </el-table> |
| 140 | + <!-- 分页 --> |
| 141 | + <Pagination |
| 142 | + :total="total" |
| 143 | + v-model:page="queryParams.pageNo" |
| 144 | + v-model:limit="queryParams.pageSize" |
| 145 | + @pagination="getList" |
| 146 | + /> |
68 | 147 | </ContentWrap>
|
69 | 148 |
|
70 | 149 | <!-- 表单弹窗:添加/修改 -->
|
71 | 150 | <SeckillActivityForm ref="formRef" @success="getList" />
|
72 | 151 | </template>
|
73 |
| -<script lang="ts" setup> |
74 |
| -import { allSchemas } from './seckillActivity.data' |
75 |
| -import { getSimpleSeckillConfigList } from '@/api/mall/promotion/seckill/seckillConfig' |
| 152 | + |
| 153 | +<script setup lang="ts"> |
| 154 | +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' |
| 155 | +import { dateFormatter } from '@/utils/formatTime' |
76 | 156 | import * as SeckillActivityApi from '@/api/mall/promotion/seckill/seckillActivity'
|
| 157 | +import * as SeckillConfigApi from '@/api/mall/promotion/seckill/seckillConfig' |
77 | 158 | import SeckillActivityForm from './SeckillActivityForm.vue'
|
78 |
| -import { createImageViewer } from '@/components/ImageViewer' |
79 |
| -import { sortTableColumns } from '@/hooks/web/useCrudSchemas' |
| 159 | +import { formatDate } from '@/utils/formatTime' |
| 160 | +import { fenToYuanFormat } from '@/utils/formatter' |
| 161 | +import { fenToYuan } from '@/utils' |
80 | 162 |
|
81 |
| -defineOptions({ name: 'PromotionSeckillActivity' }) |
| 163 | +defineOptions({ name: 'SeckillActivity' }) |
82 | 164 |
|
83 |
| -// tableObject:表格的属性对象,可获得分页大小、条数等属性 |
84 |
| -// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作 |
85 |
| -// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/ |
86 |
| -const { tableObject, tableMethods } = useTable({ |
87 |
| - getListApi: SeckillActivityApi.getSeckillActivityPage, // 分页接口 |
88 |
| - delListApi: SeckillActivityApi.deleteSeckillActivity // 删除接口 |
| 165 | +const message = useMessage() // 消息弹窗 |
| 166 | +const { t } = useI18n() // 国际化 |
| 167 | +
|
| 168 | +const loading = ref(true) // 列表的加载中 |
| 169 | +const total = ref(0) // 列表的总页数 |
| 170 | +const list = ref([]) // 列表的数据 |
| 171 | +const queryParams = reactive({ |
| 172 | + pageNo: 1, |
| 173 | + pageSize: 10, |
| 174 | + name: null, |
| 175 | + status: null |
89 | 176 | })
|
90 |
| -// 获得表格的各种操作 |
91 |
| -const { getList, setSearchParams } = tableMethods |
| 177 | +const queryFormRef = ref() // 搜索的表单 |
| 178 | +const exportLoading = ref(false) // 导出的加载中 |
| 179 | +
|
| 180 | +/** 查询列表 */ |
| 181 | +const getList = async () => { |
| 182 | + loading.value = true |
| 183 | + try { |
| 184 | + const data = await SeckillActivityApi.getSeckillActivityPage(queryParams) |
| 185 | + list.value = data.list |
| 186 | + total.value = data.total |
| 187 | + } finally { |
| 188 | + loading.value = false |
| 189 | + } |
| 190 | +} |
| 191 | +
|
| 192 | +/** 搜索按钮操作 */ |
| 193 | +const handleQuery = () => { |
| 194 | + queryParams.pageNo = 1 |
| 195 | + getList() |
| 196 | +} |
| 197 | +
|
| 198 | +/** 重置按钮操作 */ |
| 199 | +const resetQuery = () => { |
| 200 | + queryFormRef.value.resetFields() |
| 201 | + handleQuery() |
| 202 | +} |
92 | 203 |
|
93 | 204 | /** 添加/修改操作 */
|
94 | 205 | const formRef = ref()
|
95 | 206 | const openForm = (type: string, id?: number) => {
|
96 | 207 | formRef.value.open(type, id)
|
97 | 208 | }
|
98 | 209 |
|
99 |
| -/** 删除按钮操作 */ |
100 |
| -const handleDelete = (id: number) => { |
101 |
| - tableMethods.delList(id, false) |
| 210 | +/** 关闭按钮操作 */ |
| 211 | +const handleClose = async (id: number) => { |
| 212 | + try { |
| 213 | + // 关闭的二次确认 |
| 214 | + await message.confirm('确认关闭该秒杀活动吗?') |
| 215 | + // 发起关闭 |
| 216 | + await SeckillActivityApi.closeSeckillActivity(id) |
| 217 | + message.success('关闭成功') |
| 218 | + // 刷新列表 |
| 219 | + await getList() |
| 220 | + } catch {} |
102 | 221 | }
|
103 | 222 |
|
104 |
| -/** 商品图预览 */ |
105 |
| -const imagePreview = (imgUrl: string) => { |
106 |
| - createImageViewer({ |
107 |
| - urlList: [imgUrl] |
108 |
| - }) |
| 223 | +/** 删除按钮操作 */ |
| 224 | +const handleDelete = async (id: number) => { |
| 225 | + try { |
| 226 | + // 删除的二次确认 |
| 227 | + await message.delConfirm() |
| 228 | + // 发起删除 |
| 229 | + await SeckillActivityApi.deleteSeckillActivity(id) |
| 230 | + message.success(t('common.delSuccess')) |
| 231 | + // 刷新列表 |
| 232 | + await getList() |
| 233 | + } catch {} |
109 | 234 | }
|
110 | 235 |
|
111 | 236 | const configList = ref([]) // 时段配置精简列表
|
112 |
| -const convertSeckillConfigNames = computed( |
113 |
| - () => (row) => |
114 |
| - configList.value |
115 |
| - ?.filter((item) => row.configIds.includes(item.id)) |
116 |
| - ?.map((config) => config.name) |
117 |
| -) |
| 237 | +const formatConfigNames = (configId) => { |
| 238 | + const config = configList.value.find((item) => item.id === configId) |
| 239 | + return config != null ? `${config.name}[${config.startTime} ~ ${config.endTime}]` : '' |
| 240 | +} |
118 | 241 |
|
119 |
| -const expandChange = (row, expandedRows) => { |
120 |
| - // TODO puhui:等 CRUD 完事后弄 |
121 |
| - console.log(row, expandedRows) |
| 242 | +const formatSeckillPrice = (products) => { |
| 243 | + const seckillPrice = Math.min(...products.map((item) => item.seckillPrice)) |
| 244 | + return `¥${fenToYuan(seckillPrice)}` |
122 | 245 | }
|
123 | 246 |
|
124 | 247 | /** 初始化 **/
|
125 | 248 | onMounted(async () => {
|
126 |
| - // 获得活动列表 |
127 |
| - sortTableColumns(allSchemas.tableColumns, 'spuId') |
128 | 249 | await getList()
|
129 | 250 | // 获得秒杀时间段
|
130 |
| - configList.value = await getSimpleSeckillConfigList() |
| 251 | + configList.value = await SeckillConfigApi.getSimpleSeckillConfigList() |
131 | 252 | })
|
132 | 253 | </script>
|
0 commit comments