red-bag-detail.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. <!-- 红包码详情列表 -->
  2. <template>
  3. <div class="red-bag-detail">
  4. <!-- 统计卡片 -->
  5. <div class="stats-row">
  6. <div class="stat-item">
  7. <div class="stat-label">扫码领取用户数</div>
  8. <div class="stat-value">{{ stats.scanDrawSumUserNum || 0 }}</div>
  9. </div>
  10. <div class="stat-item">
  11. <div class="stat-label">领取总用户数</div>
  12. <div class="stat-value">{{ stats.drawSumUserNum || 0 }}</div>
  13. </div>
  14. <div class="stat-item">
  15. <div class="stat-label">扫码总次数</div>
  16. <div class="stat-value">{{ stats.scanSumNum || 0 }}</div>
  17. </div>
  18. <div class="stat-item">
  19. <div class="stat-label">A 分享红包数量</div>
  20. <div class="stat-value">{{ stats.shareUserNum || 0 }}</div>
  21. </div>
  22. <div class="stat-item">
  23. <div class="stat-label">B 被分享红包数量</div>
  24. <div class="stat-value">{{ stats.sharedUserNum || 0 }}</div>
  25. </div>
  26. <div class="stat-item">
  27. <div class="stat-label">扫码领取小程序红包金额</div>
  28. <div class="stat-value">{{ stats.scanMiniProgramPrice || 0 }}</div>
  29. </div>
  30. <div class="stat-item">
  31. <div class="stat-label">扫码领取现金红包金额</div>
  32. <div class="stat-value">{{ stats.scanRedCashPrice || 0 }}</div>
  33. </div>
  34. <div class="stat-item">
  35. <div class="stat-label">A 分享得金额</div>
  36. <div class="stat-value">{{ stats.shareUserPrice || 0 }}</div>
  37. </div>
  38. <div class="stat-item">
  39. <div class="stat-label">B 被分享得金额</div>
  40. <div class="stat-value">{{ stats.sharedUserPrice || 0 }}</div>
  41. </div>
  42. </div>
  43. <!-- 搜索栏 -->
  44. <div style="display: flex; gap: 10px; align-items: center">
  45. <el-input v-model="searchForm.userName" placeholder="用户名" style="width: 200px" clearable />
  46. <el-select v-model="searchForm.redType" placeholder="红包类型" clearable style="width: 150px">
  47. <el-option label="无门槛" :value="0" />
  48. <el-option label="现金" :value="1" />
  49. </el-select>
  50. <el-select v-model="searchForm.drawStatus" placeholder="领取状态" clearable style="width: 150px">
  51. <el-option label="未领取" :value="0" />
  52. <el-option label="已领取" :value="1" />
  53. </el-select>
  54. <el-button type="primary" @click="reload()">查询</el-button>
  55. <el-button type="primary" plain @click="resetSearch">重置</el-button>
  56. </div>
  57. <!-- 表格 -->
  58. <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns" :tools="false" :body-style="{ padding: '0' }">
  59. <template #redType="{ row }">
  60. <el-tag :type="row.redType === 1 ? 'success' : 'primary'">
  61. {{ row.redType === 1 ? '现金' : '无门槛' }}
  62. </el-tag>
  63. </template>
  64. <template #drawStatus="{ row }">
  65. <el-tag :type="row.drawStatus === 1 ? 'success' : 'info'">
  66. {{ row.drawStatus === 1 ? '已领取' : '未领取' }}
  67. </el-tag>
  68. </template>
  69. <template #action="{ row }">
  70. <el-button link type="primary" v-permission="'marketing:redBag:shareDetail'"
  71. @click="handleShareDetail(row)">
  72. [分享信息]
  73. </el-button>
  74. </template>
  75. </common-table>
  76. <!-- 分享信息弹窗 -->
  77. <el-dialog v-model="shareDialogVisible" title="分享信息" width="800px" :close-on-click-modal="false">
  78. <red-bag-share :red-id="currentRedId" />
  79. </el-dialog>
  80. </div>
  81. </template>
  82. <script setup>
  83. import { ref, reactive, watch } from 'vue';
  84. import CommonTable from '@/components/CommonPage/CommonTable.vue';
  85. import RedBagShare from './red-bag-share.vue';
  86. import request from '@/utils/request';
  87. const props = defineProps({
  88. activityId: {
  89. type: Number,
  90. required: true
  91. }
  92. });
  93. // 统计数据
  94. const stats = ref({});
  95. // 搜索表单
  96. const searchForm = ref({
  97. userName: '',
  98. redType: undefined,
  99. drawStatus: undefined
  100. });
  101. const resetSearch = () => {
  102. searchForm.value = {
  103. userName: '',
  104. redType: undefined,
  105. drawStatus: undefined
  106. };
  107. reload();
  108. };
  109. // 表格列配置
  110. const columns = ref([
  111. {
  112. label: '红包 ID',
  113. prop: 'id',
  114. align: 'center',
  115. width: 120
  116. },
  117. {
  118. label: '红包链接',
  119. prop: 'redLink',
  120. align: 'center',
  121. minWidth: 200,
  122. showOverflowTooltip: true
  123. },
  124. {
  125. label: '用户名',
  126. prop: 'userName',
  127. align: 'center',
  128. minWidth: 120,
  129. showOverflowTooltip: true
  130. },
  131. {
  132. label: '红包类型',
  133. prop: 'redType',
  134. align: 'center',
  135. slot: 'redType',
  136. width: 100
  137. },
  138. {
  139. label: '红包金额',
  140. prop: 'redPrice',
  141. align: 'center',
  142. width: 100
  143. },
  144. {
  145. label: '生成时间',
  146. prop: 'createTime',
  147. align: 'center',
  148. width: 160
  149. },
  150. {
  151. label: '领取时间',
  152. prop: 'drawTime',
  153. align: 'center',
  154. width: 160
  155. },
  156. {
  157. label: '领取状态',
  158. prop: 'drawStatus',
  159. align: 'center',
  160. slot: 'drawStatus',
  161. width: 100
  162. },
  163. {
  164. label: '分享人数',
  165. prop: 'shareUserNum',
  166. align: 'center',
  167. minWidth: 90
  168. },
  169. {
  170. label: '扫码次数',
  171. prop: 'scanNum',
  172. align: 'center',
  173. minWidth: 110
  174. },
  175. {
  176. columnKey: 'action',
  177. label: '操作',
  178. width: 120,
  179. align: 'center',
  180. slot: 'action',
  181. fixed: 'right'
  182. }
  183. ]);
  184. // 页面配置
  185. const pageRef = ref(null);
  186. const pageConfig = reactive({
  187. pageUrl: '/activity/red/bag/detail/activity/redBag/detail/pagelist',
  188. fileName: '红包码详情',
  189. cacheKey: 'redBagDetailTable'
  190. });
  191. // 刷新表格
  192. function reload() {
  193. pageRef.value?.reload({
  194. activityId: props.activityId,
  195. ...searchForm.value
  196. });
  197. }
  198. // 加载统计数据
  199. const loadStats = () => {
  200. request
  201. .get('/activity/red/bag/detail/activity/redBag/detail/sum', {
  202. params: { activityId: props.activityId }
  203. })
  204. .then((res) => {
  205. if (res.data.code === 200) {
  206. stats.value = res.data.data || {};
  207. }
  208. });
  209. };
  210. // 监听 activityId 变化
  211. watch(
  212. () => props.activityId,
  213. (newVal) => {
  214. if (newVal) {
  215. loadStats();
  216. reload();
  217. }
  218. },
  219. { immediate: true }
  220. );
  221. // 分享信息相关
  222. const shareDialogVisible = ref(false);
  223. const currentRedId = ref(null);
  224. const handleShareDetail = (row) => {
  225. currentRedId.value = row.id;
  226. shareDialogVisible.value = true;
  227. };
  228. </script>
  229. <style lang="scss" scoped>
  230. .red-bag-detail {
  231. .stats-row {
  232. display: flex;
  233. flex-wrap: wrap;
  234. gap: 20px;
  235. margin-bottom: 20px;
  236. .stat-item {
  237. display: flex;
  238. flex-direction: column;
  239. align-items: center;
  240. min-width: 110px;
  241. flex: 0 0 auto;
  242. .stat-label {
  243. font-size: 13px;
  244. color: #666;
  245. margin-bottom: 10px;
  246. text-align: center;
  247. line-height: 1.4;
  248. min-height: 36px;
  249. display: flex;
  250. align-items: center;
  251. justify-content: center;
  252. }
  253. .stat-value {
  254. font-size: 26px;
  255. font-weight: bold;
  256. color: #409eff;
  257. line-height: 1.2;
  258. }
  259. }
  260. }
  261. // 表格样式优化
  262. :deep(.ele-pro-table) {
  263. .el-table .cell.el-tooltip {
  264. width: 200px;
  265. white-space: nowrap;
  266. }
  267. }
  268. }
  269. </style>